00001
00002
00003
00004
00005
00006
00007
00008
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
00021
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
00083
00084 if { [package vcompare [package provide Tcl] 8.3] < 0 } {
00085
00086
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