Oracle Virtual DirectoryのHTTPリスナーは、HTMLベースのゲートウェイを提供します。これは、Webゲートウェイと呼ばれ、DSMLおよびXSLTによりレンダリングされるディレクトリ・レポートを提供します。WebゲートウェイのDSML機能は、OracleのURLベースの問合せゲートウェイに基づきます。これは、URLベースの操作に基づいてDSML形式のXMLの結果を戻します。DSMLv2サービスは、HTTPリスナーのDSML V2サービスを通じて別に提供されます。
この付録では、HTTPリスナーのWebゲートウェイについて説明します。この項の内容は次のとおりです。
DSMLおよびXSLTによりレンダリングされるディレクトリ・レポートに加え、Webゲートウェイには、静的なWebコンテンツを処理する機能があり、複雑なディレクトリ・ホワイト・ページ、委任管理およびセルフサービス機能を作成できます。次に、Webゲートウェイの機能をリストします。
Oracle Virtual Directoryのディレクトリ・サービスとの動的な統合
認証および認可が可能なLDAP統合を使用したApacheに類似のセキュリティ
XHTML、DSML、WMLまたは任意のXML派生形式で出力内容がレンダリングされる動的XSLT変換
一般的なHTMLファイルなどの静的コンテンツのサポート
追加、変更、削除など、すべてのLDAP操作がサポートされるフォームベース入力の拡張サポート
jpegphotoまたはusercertificateなどのバイナリ属性を取得するための拡張サポート
Oracle Virtual DirectoryのDoS保護メカニズムの統合サポート
Oracle Virtual Directoryでは、XSLTリスナーのXMLサービスの機能を説明するデモンストレーション・ディレクトリ・ブラウザがhtdocsディレクトリに用意されています。このデモンストレーション・ディレクトリ・ブラウザは、本番環境向けの高度なツールとしては設計されていませんが、開発者が確認や特定の目的での拡張を行うためのサンプル・コードとして提供されています。
注意: Oracle Virtual Directoryに関するコーディング・レベルのサポートは行っていません。ただし、開発支援を行うためのコンサルティング・サービス・プログラムを介して支援を行うことができます。 |
Webゲートウェイは、広く普及しているオープン・ソースのApache AXISおよびTomcatサーバーで使用されるJettyサーバーに基づいています。Jettyサーバーは、特別な目的の製品に埋め込むために設計された拡張可能なサーバーです。次に、Webゲートウェイ・アーキテクチャのコンポーネントを説明します。
DSMLサーブレットではリクエストを受信すると、Oracle Virtual Directoryの内部APIがコールされるため、リクエストはリスナーからのものであるように処理されます。次に示すように、適切な問合せを伴う/dsml接頭辞を使用して、ディレクトリに標準のDSMLコンテンツに関する問合せを実行できます。
http://localhost:8080/dsml/directory?base=o=myorg.com&scope=base&filter=objectclass=*
リスナーがURLを受信すると、問合せはHTTPセッションのコンテキストで処理されます。ユーザー・セキュリティ・プリンシパルが存在しない場合、問合せは匿名の問合せとして扱われます。問合せが処理されると、結果は、DSML標準形式でHTTPクライアントに戻されます。
directoryをサーバー・ディレクトリ・コンテキストに置き換えることで、セキュリティ・コンテキストを確立できます。DSMLのセキュリティ・コンテキストは、htdocsの適切なサブディレクトリに.htaccessファイルを作成することで確立できます。たとえば、限定した問合せドメインを設定するには、.htaccessファイルを/htdocs/dsml/administratorsディレクトリに配置します。これにより、http://localhost:8080/dsml/administratorsに対する問合せは、/htdocs/dsml/administrators/.htaccessaccessファイルに指定されたアクセス要件を満たします。
XSLTサーブレットを使用すると、HTMLの表示方法を制御できます。サーブレットには、ディレクトリにコンテンツを問い合せ、指定されたXSLT変換ファイルに応じてコンテンツを変換する機能があります。
XSLTサーブレットでは、ディレクトリ問合せと、特殊な処理を可能にする特別なコマンドの両方がサポートされています。次に例を示します。
http://localhost:8080/search/results.xsl?params=...
.xslファイル接尾辞はXSLTサーブレットであることを示します。/search/results.xslは、結果のレンダリングに使用されるXSL変換ファイルを指定し、/htdocs/search/results.xslに自動的にマップされます。
DoSハンドラ: すべてのリクエストが、(vde.propで定義されている)DoSマネージャの割当て全体に対して、サブジェクト名とIPアドレスで追跡されます。割当て制限を超えるイベントの間、サーバーは原因であるクライアントに反応しなくなります。これにより、過剰にアクティブなクライアントまたはDoS攻撃からWebサービスが保護されます。
LDAPUserRealm: LDAPUserRealmはHTAccessHandlerと連携して、Webゲートウェイをディレクトリ・サービス(Oracle Virtual Directory)と統合します。LDAPUserRealmは、ディレクトリに対するユーザー認証を実行し、識別名マッピングに対するUIDの提供などの他の操作のユーザー・コンテキストを追跡します。
HTAccessHandler: このハンドラは、ApacheのようなWebサーバー・アクセス制御を提供します。HTAccessHandlerはリクエストされた各リソースを確認し、リソース・ディレクトリまたは親ディレクトリで.htaccessファイルを検索します。.htaccessファイルが見つからない場合は、/conf/htaccess.propで指定されているデフォルトのアクセス制御を使用します。現行ユーザーのコンテキストが現行のリソースの参照を認可されていない場合には、HTAccessHandlerによりHTTPクライアントにアクセスが拒否されたというレスポンスが戻されます。ブラウザがユーザーIDおよびパスワードを使用して応答すると、LDAPUserRealmサービスにより、認証目的でのHTAccessHandlerによる参照が可能なLDAPユーザー・プリンシパルが自動的に作成されます。
詳細は、「セキュリティ・コンテキスト」を参照してください。
サーブレット・ハンドラ: サーブレット・ハンドラは.xslで終わるURLリクエストをWebゲートウェイ・サーブレットに送り、/dsmlで始まるURLリクエストをDSMLサーブレットに送ります。Webゲートウェイ・サーブレットではXSLT書式の結果を提供し、ディレクトリ問合せおよびエントリ変更操作の両方をサポートしています。DSMLサーブレットには、単純なディレクトリ問合せ機能およびDSML書式のレスポンス機能があります。
リソース・ハンドラ: その他すべてのリクエストは、ドキュメント・リソース・リクエストとして扱われます。リソースがサーバーのhtdocsドキュメント・ルートに配置されている場合、ドキュメントはHTTPクライアントに戻されます。htmlやgifファイルなどの静的コンテンツは、標準的なWebサービスと同じように、リソース・ハンドラ経由でWebゲートウェイが処理します。静的コンテンツのアクセス制御は、ドキュメント・ディレクトリまたは親ディレクトリの.htaccessセキュリティ構成ファイルの存在に基づいて実行されます。Oracle Virtual Directoryインストールのhtdocsディレクトリにある静的ドキュメントは、直接メイン・サーバー・ルートにマップされます。たとえば、/htdocs/index.htmlはhttp://localhost:8080/index.htmlにマップします。
Webゲートウェイでは、次に示すDSMLおよびXSLT LDAP問合せパラメータがサポートされています。
検索が開始されるベースの識別名です。空の場合はNULLとみなされます。
LDAP標準の検索フィルタ。空の場合は、"(objectclass=*)"とみなされます。
検索の有効範囲。baseは、baseに指定したエントリのみを検索することを指定します(エントリを直接指定する場合に便利です)。onelevel
は、検索でベースDNのすぐ下の子エントリのみを確認することを指定します。サブツリーは、ベースDNのすべての子が検索されることを指定します。デフォルトでは、有効範囲はbaseに設定されています。
検索の実行基準となるユーザー識別名。空の場合は、デフォルトで匿名とみなされます。
binddnアカウントと関連付けられたパスワード。通常このパラメータは、binddnとともに指定されます。
このパラメータは、XSLTサーブレットにのみ適用され、DSMLサーブレットでは無視されます。指定されている場合、Oracle Virtual Directoryのルート・インストール・ディレクトリに関連するファイルが参照されます。HTMLファイルはhtdocsディレクトリに関連します。空の場合、デフォルト値はconf/html.xslです。
XSLTサーブレットは、ユーザーが指定するその他のパラメータを受け入れます。コンテキスト情報(parentname="Home"
など)を指定するために、XSLスタイルシートにパラメータを渡す場合に便利です。
Webゲートウェイ・コマンドは、バイナリ属性の取得、フォームベースの検索やフォームベースのエントリ操作などの追加機能を提供します。次に、各Webゲートウェイ・コマンドを説明します。
getcertおよびgetphotoコマンドは、DSMLでエンコードされるのとは対照的に、バイナリ属性をネイティブのバイナリ形式で取得する際に使用されます。getcertのコールからは、MIMEタイプがapplication/x-x509-email-certのhttpコンテンツが戻されます。同様にgetphotoのコールからは、MIMEタイプがimage/jpegのコンテンツが戻されます。
dnおよびattrパラメータによって指定されている証明書を取得します。次に例を示します。
http://localhost:8080/xslt/search/?cmd=getcert&dn=uid=jsmith,ou=people,o=airius.com&attr=usercertificate
dnおよびattrパラメータによって指定されているjpegphotoを取得します。
エントリの識別名を指定します。通常は、コマンド・パラメータとともに使用します。
getcertまたはgetphotoコマンドに関して属性名を指定します。
LDAPのようなXSLT/DSML形式の検索を実行することは可能ですが、cmd=search
オプションを使用するとわかりやすい検索フォームをより柔軟にサポートできます。このコマンドは、フォーム値を受け取って、コンテンツを標準のディレクトリ問合せに変換します。
関連するパラメータ、base、scope、kind、searchvalueおよびfilterattrsを使用するフォームベース検索をサポートします。このコマンドは、フォーム・パラメータから検索フィルタが自動的に作成される検索フォームのプログラミングをより簡単にするよう設計されていることを除き、XSLT問合せフォームに類似の機能を提供します。次に例を示します。
http://localhost:8080/xslt/search/results.xsl?cmd=search&base=o=airius.com&scope= sub&kind=all&filterattrs=cn,sn,givenname&searchvalue=smith
フォームベース検索コマンドの検索ベースを指定します。
検索の有効範囲を指定します。有効な値は、base、one、subです。
特定の属性と、filterattrsパラメータに指定されているすべての属性のどちらに基づいて検索フィルタを作成するかを指定します。
検索する属性のリスト。
ユーザーが検索文字列値として入力した値。
検索フォームのアクションは、GETまたはPOSTとして作成されます。次に、検索フォームによって生成されたGETリクエストの例を示します。
http://localhost:8080/xslt/search/results.xsl?cmd=search&base=o=airius.com&scope= sub&kind=all&filterattrs=cn,sn,givenname&searchvalue=smith
このコマンドはサーバーによって解釈され、次の内容と同等のものとして処理されます。
http://localhost:8080/xslt/search/results.xsl?base=o=airius.com&scope=sub&filter= (|(cn=*smith*)(sn=*smith*)(givename=*smith*))
問合せの処理後、XSLファイル/xslt/search/results.xslを使用して結果が変換されます。
変更コマンドを使用すると、ディレクトリ・エントリの変更に使用可能なhtmlフォームを作成できます。このコマンドには、実際にLDAPディレクトリ・エントリを追加、削除または変更する機能があります。
attrs
、changetype
、objectclass
などの一部のフォーム・パラメータは、非表示フィールドとして提供される場合があります。新規エントリの追加時には、必ずobjectclass属性(通常は非表示フィールドとして提供)を指定してください。
注意: 以降の項で使用されているattrx は、任意の有効なLDAP属性を表します。 |
クライアントがディレクトリ・エントリの変更をリクエストしたことを示します。変更のタイプは、changetype
フィールドで指定します。
ディレクトリ・エントリで実行する操作(追加、変更または削除)を指定します。操作で変更できるディレクトリ・エントリは1つのみです。
changetype=add
を使用して新規エントリを追加するときは、attrx_modify=[value]
値のみが処理されます。エントリの削除時には、すべてのattrx
パラメータが無視されます。dn
フォーム値を複数指定すると、複数のLDAPエントリを削除できます。
追加、編集または削除されるエントリの識別名。
フォームから処理される属性のリスト。このリストは、フォーム上のその他すべての属性パラメータ(attr1_type、attr1_action、attr1_new、attr1_confirmなど)の検索に使用されます。
処理エラーが発生した場合にエラーを送るxslファイルを指定します。エラーが発生すると、XSLフォームは、指定されているすべてのフォーム・パラメータと、result
およびmessage
パラメータを渡します。これらは、エンド・ユーザーに表示する適切なエラー・メッセージを決定するために、error.xslで解析されます。
attrxで表される属性のタイプを定義します。singleの場合は、attrx
の最初の値のみが受け入れられます。certまたはphotoの場合は、マルチパート・フォームの一部としてバイナリ値が配置されます。一度に追加できる値は1つです。
trueに設定すると、attrx
に値が指定されていることがプロセッサにより検証されます。
attrx
から削除する値です。1つ以上の値を指定できます。空の値は無視されます。
attrx
属性の変更に使用する値です。attrx_action
の値に応じて、この値がattrx
に追加されるか、attrx
のすべての値を置き換えます。
attrx_modify
の値をattrx
に追加するか、既存の値をすべて置き換えるかを指定します。changetype=add
の場合、attrx_action
は強制的にadd
になります。
add
操作では、dn
は親エントリとみなされ、rdn_attr
はrdn
値として使用する属性をプロセッサに伝えます。
HTTP POSTは、HTTP GETのかわりに使用できます。DoS攻撃またはバッファ・オーバーフロー攻撃を防ぐため、Listeners.propファイルには最大入力ファイル・サイズを設定できます。バイナリ属性(jpegphotosおよびcertificatesなど)をアップロードするときは、RFC 1867に従ってマルチパート・フォームを使用します。
HTTP GET操作を使用する時は、すべてのパラメータがURLとして渡され、URLにブックマークを付けることができます。ただし、binddn
などの機密情報がURLで入手できるようになります。そのため、匿名以外の問合せにはHTTP POSTを使用します。
GETを使用するときは、アンパサンド(&)および空白を適切にエスケープしてURL要件に準拠する必要があります。これにはjavaScriptを追加して、発行前のフィールド・パラメータを変更する必要があります。一般的に、アンパサンド(&)は&
に置き換える必要があります。
HTAccessHandlerを使用すると、サーバー内にセキュリティ・コンテキストを定義できます。セキュリティ・コンテキストでは、サーバー上の特定のリソース・ディレクトリへのアクセスを許可するIPアドレス、サブジェクトまたはグループを定義します。セキュリティ・コンテキストは、htdocsディレクトリまたは任意のサブディレクトリに.htaccessセキュリティ構成ファイルを作成することで作成できます。各.htaccessファイルは、ファイルが存在するディレクトリおよびその下の子ディレクトリに適用されます。直下のディレクトリまたは最も近い親の.htaccessファイルは、任意のリソースに適用されるファイルです。デフォルトのセキュリティ・コンテキストは、/conf/htaccess.propファイルを編集して定義できます。
次の項で、セキュリティ・コンテキストをより詳細に説明します。
次に示すのは.htaccessファイルの要件の一覧です。
.htaccessファイルはプレーン・テキスト・ファイルであることが必要です。
有効なディレクティブではないコンテンツには接頭辞としてコメント(#)文字が必要です。
.htaccessファイルのディレクティブは現行ディレクトリまたは子ディレクトリにのみ適用されます。
サブディレクトリまたは子ディレクトリに.htaccessファイルが含まれる場合は、親ディレクトリの.htaccessファイルが上書きされます。
次に示すのは、.htaccessファイルでサポートされているディレクティブです。
CRYPTハッシュで暗号化されたユーザーとパスワードのリストを含むテキスト・ファイルを使用して、ユーザーを認証することを示します。例については、例C-2を参照してください。
ユーザーがOracle Virtual Directoryサーバーから認証されることを示します。baseは、認証されるユーザーの検索ベースの識別名を指定します。
ユーザーがfilenameによって指定されているグループ・ファイルのメンバーであることが必要なことを示します。例については、例C-3を参照してください。
認証レルムの名前を設定します。ディレクトリ・ブラウザなど、ユーザーへのチャレンジで表示されるテキストです。
[restrictions]
詳細は、「リソースの制限」を参照してください。
リソース制限ブロックを定義します。制限は、トークン<Limit>と</Limit>の間に配置されます。
リース制限は、<Limit>文の間に配置します。次の制限がサポートされています。
すべてまたはいずれかの要件を満たす必要があるかどうかを指定します。
ユーザーが次のいずれかのメンバーであることが必要なことを示します。
user: AuthUserFileまたはAuthUserLDAPのメンバー
valid-user: 任意の検証済のユーザー
group: AuthUserGroupのメンバー
ldapgroup: ldapグループのメンバー
entitiesは、丸カッコ()で囲まれているldapgroupか、ユーザー名またはグループの明示的なリストを指定します。
次のように、ルールを許可および拒否するためのルールの優先順位を指定します。
allow,deny: denyリストではなくallowリストに存在する必要があることを意味します。
deny,allowまたはmutual-failure: denyリストに存在しない場合、またはallowリストに存在する場合に許可します。
リクエストを許可するための、空白で区切られたIPアドレスのリストを指定します。
リクエストを拒否するための、空白で区切られたIPアドレスのリストを指定します。
ここでは、セキュリティ・コンテキスト・ファイルの例を示します。例C-1は、.htaccessファイルの例です。
例C-1 .htaccessファイルの例
# HTAccess example. # AuthName "Airius Directory Browser" AuthType Basic #AuthUserFile /etc/htpasswd AuthUserLDAP ou=People,o=Airius.com AuthGroupFile /etc/htgroup <Limit> satisfy any require ldapgroup (cn=a group,ou=groups,o=Airius.com) require ldapgroup (cn=alternate group,ou=groups,o=Airius.com) order deny,allow deny from 192.168.0.3 192.168.0.4 </Limit>
例C-2はhtpasswdファイルの例です。
例C-2 htpasswdファイルの例
# <PRE> # HTPassword example. # # Passwords must be in CRYPT format # admin: adpexzg3FUZAk tom: tofn8Rh1L.xhQ dick: diF1tp4K2rvw. harry: haVyKPUXAHTjA
例C-3はhtgroupファイルの例です。
ここでは、XSLスタイルシート・テンプレートの使用方法を説明します。
XSLT問合せをスタイルシートと組み合せて使用し、クライアント用の編集フォームを作成できます。次に例を示します。
http://localhost:8080/manage/edit.xsl?base=ou=Atlanta,o=myorg.com&scope=base&filter=objectclass=*&mode=edit
このURLにより、サーバーはディレクトリ・エントリou=Atlanta,o=myorg.com
を取得し、それを/manage/edit.xsl
のxslフォームに渡します。
xslフォームの内部でmode
パラメータを探して、結果のレンダリング方法を決定します。この場合、edit
は、問合せによって戻されるオブジェクトを編集できるようにフォームをレンダリングする必要があることを意味します。addchild
モードは、組織への子エントリの追加に使用できるフォームを準備するために使用されます。
新しいmode
パラメータを作成できます。XSLの場合、mode
は、様々なレンダリング・サブルーチンに対して異なるロジックを存在させるために、テンプレートで頻繁に使用される特別なパラメータです。デフォルトの出荷デモンストレーション・アプリケーションでは、htdocs/xslt/secure/admin.xsl
の1つのスタイルシート内に複数モードの編集(表示、追加、変更、削除)が用意されています。
Oracle Virtual DirectoryのXSLTサーブレットのプロセッサは、document()
コマンドをサポートします。完全なドキュメントURLまたはファイル仕様を指定できます。ディレクトリまたはドキュメントのみを指定すると、htdocsドキュメント・ルートの場所に対する相対位置とみなされます。
たとえば、vdexsl.xmlファイルを使用して、LDAP属性名をよりわかりやすい名前に変換するとします。
<xsl:variable name="lname" select="translate(@name,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')"/> <xsl:variable name="prettyname" select="document('xslt/vdexsl.xml')/vdexsl:vdexsl/vdexsl:fields/vdexsl:attr[@name=$lname]/vdexsl: displayname"/>
document()
コマンドを使用して取得されたファイルは、パフォーマンスのために自動的にキャッシュされます。同様に、xsl:import
およびxsl:include
コマンドもサポートされ、グローバル・サブルーチンをXSLテンプレートにインポートするために使用できます。document()
コマンドと同様に、任意のURLまたはファイルを参照できます。デフォルトで、ファイル参照はhtdocsドキュメント・ルートの場所が基準になります。次に2つの例を示します。
<xsl:import href="http://192.168.0.2:8050/lib/globals.xslt"/>
<xsl:import href="lib/globals.xslt"/>
注意: httpを使用してOracle Virtual Directoryからスタイルシートを取得する場合、.xslファイル接尾辞を使用すると、XSLTサーブレットが干渉し、問合せの一部であるかのようにxslファイルをレンダリングします。別のOracle Virtual Directoryから未処理のXSLファイルを取得する場合は、接尾辞名が.xsl以外であることが必要です。前の例では、かわりに.xsltディレクトリが使用されています。 |
XSLTサーブレットは、渡されたすべてのパラメータをXSLスタイルシートで使用できるようにします。これにより、DSML検索結果には存在しないコンテキスト情報をXSLスタイルシートで受信できるようになります。パラメータは、有効な検索パラメータの一部またはこの目的で定義されたパラメータです。次のコード例では、parentname
およびbase
パラメータが取得されて、XSLコード内で変数として使用できるようになっています。
… <xml:output method="html" indent="yes"/> <xsl:param name="parentname" select="'Root'"/> <xsl:param name="base" select="'base'"/> <xsl:template match="/"> <html> …
xsl:param
文のselect部分は、存在しない場合にはデフォルト値を表します。
次に示す例C-4は、ディレクトリ・ナビゲーション・バーを作成するように設計されています。XSLプログラミングの詳細は、XSLTのガイドを参照してください。例C-4では、コンテキストを確立するために2つのパラメータが使用されています。parentname
およびbase
パラメータは、ツリー内を上下に移動できるようにするための、親エントリ名の記録に使用されます。親の親DNは、現行のbase
問合せパラメータからRDNを削除することで推測できます。
例C-4 XSLの例
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/TR/REC-html40" xmlns:dsml="http://www.dsml.org/DSML"> <xml:output method="html" indent="yes"/> <xsl:param name="parentname" select="'parentname'"/> <xsl:param name="base" select="'base'"/> <xsl:template match="/"> <html> <head> <title>Oracle Browser Navigation Bar</title> </head> <body bgcolor="#99CCCC"> <xsl:choose> <xsl:when test="$base = 'base'"> <xsl:variable name="rdn" select="'root'"/> <xsl:variable name="rvalue" select="'Root'"/> <xsl:variable name="parentdn" select="'base=&scope=base'"/> <FONT FACE="Verdana,Arial" size="-1">Root</FONT> </xsl:when> <xsl:when test="$base = ''"> <xsl:variable name="rdn" select="'root'"/> <xsl:variable name="rvalue" select="'Root'"/> <xsl:variable name="parentdn" select="'base=&scope=base'"/> <FONT FACE="Verdana,Arial" size="-1">Root</FONT> </xsl:when> <xsl:otherwise> <xsl:variable name="rdn"> <xsl:choose> <xsl:when test="contains($base,',') = 'true'"> <xsl:value-of select="substring-before($base,',')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$base"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="rvalue" select="substring-after($rdn,'=')"/> <xsl:variable name="parentdn"> <xsl:choose> <xsl:when test="contains($base,',') = 'true'">base=<xsl:value-of select="substring-after($base,',')"/>&scope=onelevel</xsl:when> <xsl:otherwise>base=&scope=base</xsl:otherwise> </xsl:choose> </xsl:variable> <a href="/xslt?{$parentdn}&filter=(objectclass=*)&parentname={$parentdn}& xsl=htdocs/Browser-navbar.xsl" target="leftFrame"> <FONT FACE="Verdana,Arial" size="-1"><xsl:value-of select="$rvalue"/></FONT></a> </xsl:otherwise> </xsl:choose> <table border="0" cellpadding="0" cellspacing="0"> <xsl:apply-templates select="dsml:dsml/dsml:directory-entries/dsml:entry"/> </table> </body> </html> </xsl:template> <xsl:template match="dsml:entry"> <xsl:variable name="edn" select="@dn"/> <xsl:variable name="evalue"> <xsl:choose> <xsl:when test="contains(@dn,',') = 'true'"> <xsl:value-of select="substring-after(substring-before(@dn,','),'=')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="substring-after(@dn,'=')"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:if test="@dn = ''"> <xsl:for-each select="dsml:attr[@name='namingContexts']/dsml:value"> <tr><td><li><a href="/xslt?base={.}&scope=onelevel&filter=(objectclass=*)&parentname ={.}&xsl=htdocs/Browser-navbar.xsl" target="leftFrame"><FONT FACE="Verdana,Arial" size="-1"><xsl:value-of select="."/></FONT></a> <FONT FACE="Verdana,Arial" size="-1">[<a href="/xslt?base={.}&scope=base&filter=(objectclass=*)&xsl=htdocs/res ults.xsl" target="mainFrame">-></a>]</FONT></li> </td></tr> </xsl:for-each> </xsl:if> <xsl:if test="@dn > ''"> <tr><td><li><a href="/xslt?base={@dn}&scope=onelevel&filter=(objectclass=*)&parentna me={$evalue}&xsl=htdocs/Browser-navbar.xsl" target="leftFrame"><FONT FACE="Verdana,Arial" size="-1"><xsl:value-of select="$evalue"/></FONT></a> <FONT FACE="Verdana,Arial" size="-1">[<a href="/xslt?base={@dn}&scope=base&filter=(objectclass=*)&xsl=htdocs/r esults.xsl" target="mainFrame">-></a>]</FONT></li> </td></tr> </xsl:if> </xsl:template>