urn-scheme.tcl

Go to the documentation of this file.
00001 /*  urn-scheme.tcl - Copyright (C) 2001 Pat Thoyts <patthoyts@users.sf.net>*/
00002 /* */
00003 /*  extend the uri package to deal with URN (RFC 2141)*/
00004 /*  see http://www.normos.org/ietf/rfc/rfc2141.txt*/
00005 /* */
00006 /*  Released under the tcllib license.*/
00007 /* */
00008 /*  $Id: urn-scheme.tcl,v 1.11 2005/09/28 04:51:24 andreas_kupries Exp $*/
00009 /*  -------------------------------------------------------------------------*/
00010 
00011 package require uri      1.1.2
00012 
00013 namespace ::uri {}
00014 namespace ::uri::urn {
00015     variable version 1.0.2
00016 }
00017 
00018 /*  -------------------------------------------------------------------------*/
00019 
00020 /*  Description:*/
00021 /*    Called by uri::split with a url to split into its parts.*/
00022 /* */
00023 ret  ::uri::SplitUrn (type uri) {
00024     #@c Split the given uri into then URN component parts
00025     #@a uri: the URI to split without it's scheme part.
00026     #@r List of the component parts suitable for 'array set'
00027 
00028     upvar \#0 [namespace current]::urn::URNpart pattern
00029     array set parts {nid {} nss {}}
00030     if {[regexp -- ^$pattern $uri -> parts(nid) parts(nss)]} {
00031         return [array get parts]
00032     } else {
00033         error "invalid urn syntax: \"$uri\" could not be parsed"
00034     }
00035 }
00036 
00037 
00038 /*  -------------------------------------------------------------------------*/
00039 
00040 ret  ::uri::JoinUrn args (
00041     #@type c , type Join , type the , type parts , type of , type a , type URN , type scheme , type URI
00042     #@, type a , type list , type of , type nid , type value , type nss , type value
00043     #@, type r , type a , type valid , type string , type representation , type for , type your , type URI
00044     , type variable , type urn::, type NIDpart
00045 
00046     , type array , type set , type parts [, type list , type nid , optional  , type nss , optional ]
00047     , type array , type set , type parts $, type args
00048     , type if , optional ! =[regexp -- =^$NIDpart$ $parts(nid)] , optional 
00049         error ="invalid urn: =nid is =invalid"
00050     
00051     , type set , type url ", type urn:$, type parts(, type nid):[, type urn::, type quote $, type parts(, type nss)]"
00052     , type return $, type url
00053 )
00054 
00055 # -------------------------------------------------------------------------
00056 
00057 # Quote the disallowed characters according to the RFC for URN scheme.
00058 # ref: RFC2141 sec2.2
00059 proc ::uri::urn::quote {url} {
00060     variable trans
00061     
00062      ndx =  0
00063      result =  ""
00064     while {[regexp -indices -- "\[^$trans\]" $url r]} {
00065          ndx =  [lindex $r 0]
00066         scan [string index $url $ndx] %c chr
00067          rep =  %[format %.2X $chr]
00068         if {[string match $rep %00]} {
00069             error "invalid character: character $chr is not allowed"
00070         }
00071         
00072         incr ndx -1
00073         append result [string range $url 0 $ndx] $rep
00074         incr ndx 2
00075          url =  [string range $url $ndx end]
00076     }
00077     append result $url
00078     return $result
00079 }
00080 
00081 /*  -------------------------------------------------------------------------*/
00082 /*  Perform the reverse of urn::quote.*/
00083 
00084 if { [package vcompare [package provide Tcl] 8.3] < 0 } {
00085     /*  Before Tcl 8.3 we do not have 'regexp -start'. We simulate it by*/
00086     /*  using 'string range' and adjusting the match results.*/
00087 
00088     ret  ::uri::urn::unquote (type url) {
00089         set result ""
00090         set start 0
00091         while {[regexp -indices {%[0-9a-fA-F]{2}} [string range $url $start end] match]} {
00092             foreach {first last} $match break
00093             incr first $start ; # Make the indices relative to the true string.
00094             incr last  $start ; # I.e. undo the effect of the 'string range' on match results.
00095             append result [string range $url $start [expr {$first - 1}]]
00096             append result [format %c 0x[string range $url [incr first] $last]]
00097             set start [incr last]
00098         }
00099         append result [string range $url $start end]
00100         return $result
00101     }
00102 } else {
00103     ret  ::uri::urn::unquote (type url) {
00104         set result ""
00105         set start 0
00106         while {[regexp -start $start -indices {%[0-9a-fA-F]{2}} $url match]} {
00107             foreach {first last} $match break
00108             append result [string range $url $start [expr {$first - 1}]]
00109             append result [format %c 0x[string range $url [incr first] $last]]
00110             set start [incr last]
00111         }
00112         append result [string range $url $start end]
00113         return $result
00114     }
00115 }
00116 
00117 /*  -------------------------------------------------------------------------*/
00118 
00119 ::uri::register {urn URN} {
00120     variable NIDpart {[a-zA-Z0-9][a-zA-Z0-9-]{0,31}}
00121         variable esc {%[0-9a-fA-F]{2}}
00122         variable trans {a-zA-Z0-9$_.+!*'(,):=@;-}
00123         variable NSSpart "($esc|\[$trans\])+"
00124         variable URNpart "($NIDpart):($NSSpart)"
00125         variable schemepart $URNpart
00126     variable url "urn:$NIDpart:$NSSpart"
00127 }
00128 
00129 /*  -------------------------------------------------------------------------*/
00130 
00131 package provide uri::urn $::uri::urn::version
00132 
00133 /*  -------------------------------------------------------------------------*/
00134 /*  Local Variables:*/
00135 /*    indent-tabs-mode: nil*/
00136 /*  End:*/
00137 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1