tcl-http.tcl
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:12k
源码类别:

通讯编程

开发平台:

Visual C++

  1. #
  2. # Copyright (c) 1998 Regents of the University of California.
  3. # All rights reserved.
  4. #
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions
  7. # are met:
  8. # 1. Redistributions of source code must retain the above copyright
  9. #    notice, this list of conditions and the following disclaimer.
  10. # 2. Redistributions in binary form must reproduce the above copyright
  11. #    notice, this list of conditions and the following disclaimer in the
  12. #    documentation and/or other materials provided with the distribution.
  13. # 3. All advertising materials mentioning features or use of this software
  14. #    must display the following acknowledgement:
  15. #       This product includes software developed by the Computer Systems
  16. #       Engineering Group at Lawrence Berkeley Laboratory.
  17. # 4. Neither the name of the University nor of the Laboratory may be used
  18. #    to endorse or promote products derived from this software without
  19. #    specific prior written permission.
  20. #
  21. # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. # SUCH DAMAGE.
  32. #
  33. # ------------
  34. #
  35. # Filename: tcl-http.tcl
  36. #   -- Created on Sun May 31 1998
  37. #   -- Author: Cynthia Romer <cromer@cs.berkeley.edu>
  38. #
  39. #  @(#) $Header: /cvsroot/otcl-tclcl/tclcl/tcl-http.tcl,v 1.4 1998/11/17 18:37:58 yatin Exp $
  40. #
  41. #
  42. # Copyright (c) 1998 Regents of the University of California.
  43. # All rights reserved.
  44. #
  45. # Redistribution and use in source and binary forms, with or without
  46. # modification, are permitted provided that the following conditions
  47. # are met:
  48. # 1. Redistributions of source code must retain the above copyright
  49. #    notice, this list of conditions and the following disclaimer.
  50. # 2. Redistributions in binary form must reproduce the above copyright
  51. #    notice, this list of conditions and the following disclaimer in the
  52. #    documentation and/or other materials provided with the distribution.
  53. # 3. All advertising materials mentioning features or use of this software
  54. #    must display the following acknowledgement:
  55. #       This product includes software developed by the Computer Systems
  56. #       Engineering Group at Lawrence Berkeley Laboratory.
  57. # 4. Neither the name of the University nor of the Laboratory may be used
  58. #    to endorse or promote products derived from this software without
  59. #    specific prior written permission.
  60. #
  61. # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  62. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  63. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  64. # ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  65. # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  66. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  67. # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  68. # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  69. # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  70. # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  71. # SUCH DAMAGE.
  72. #
  73. # ------------
  74. #
  75. # Filename: tcl-http.tcl
  76. #   -- Created on Sat May 30 1998
  77. #   -- Author: Yatin Chawathe <yatin@cs.berkeley.edu>
  78. #
  79. # Description:
  80. #
  81. #
  82. #  @(#) $Header: /cvsroot/otcl-tclcl/tclcl/tcl-http.tcl,v 1.4 1998/11/17 18:37:58 yatin Exp $
  83. #
  84. Class HTTP
  85. HTTP public init { } {
  86. $self next
  87. # enable the user interface by default only if we are using Tk
  88. if { [lsearch -exact [package names] Tk] != -1 } {
  89. $self set enable_output_ 1
  90. } else {
  91. $self set enable_output_ 0
  92. }
  93. $self set token_count_ 0
  94. }
  95. #
  96. # temporary helper function until Cindy converts the serial geturl requests
  97. # to a sequence of parallel requests
  98. #
  99. HTTP public geturl { url } {
  100. set token [$self start_fetch $url]
  101. $self wait
  102. return $token
  103. }
  104. HTTP public geturls { args } {
  105. set tokens [eval "$self start_fetch $args"] 
  106. $self wait
  107. return $tokens
  108. }
  109. #
  110. # args can be a list of urls
  111. #
  112. HTTP public start_fetch { args } {
  113. $self instvar token_count_ urls_
  114. set urls_ $args
  115. foreach url $args {
  116. lappend tokens [::http::geturl $url 
  117. -progress  "$self progress_callback" 
  118. -command "$self fetch_done"]
  119. incr token_count_
  120. }
  121. if { [llength $tokens] == 1 } {
  122. return [lindex $tokens 0]
  123. } else {
  124. return $tokens
  125. }
  126. }
  127. HTTP public wait { } {
  128. $self tkvar vwait_
  129. if { ![info exists vwait_] } {
  130. $self start_ping_pong
  131. # start_ping_pong did an update (during which, the vwait_
  132. # variable might have been set), so check for existence of
  133. # vwait_ again
  134. if { ![info exists vwait_] } { vwait [$self tkvarname vwait_] }
  135. $self stop_ping_pong
  136. }
  137. unset vwait_
  138. }
  139. HTTP private fetch_done { token } {
  140. $self instvar token_count_
  141. $self tkvar vwait_
  142. incr token_count_ -1
  143. if { $token_count_ <= 0 } {
  144. set vwait_ 1
  145. set token_count_ 0
  146. $self instvar total_bytes_ current_bytes_ per_token_
  147. unset total_bytes_ current_bytes_ per_token_
  148. }
  149. }
  150. HTTP private progress_callback { token total_bytes current_bytes } {
  151. $self instvar total_bytes_ current_bytes_ per_token_
  152. if { ![info exists total_bytes_] } {
  153. set total_bytes_ 0
  154. set current_bytes_ 0
  155. }
  156. if { ![info exists per_token_($token)] } {
  157. set per_token_($token) $current_bytes
  158. incr total_bytes_ $total_bytes
  159. incr current_bytes_ $current_bytes
  160. } else {
  161. set current_bytes_ [expr $current_bytes_ - 
  162. $per_token_($token) + $current_bytes]
  163. set per_token_($token) $current_bytes
  164. }
  165. $self instvar urls_
  166. $self print_status "Fetching $urls_ ... (rcvd $current_bytes_ bytes)"
  167. }
  168. HTTP private build_widget { } {
  169. $self instvar frame_ rect_
  170. if { ![info exists frame_] } {
  171. set cnt 0
  172. while [winfo exists .http_$cnt] { incr $cnt }
  173. set frame_ .http_$cnt
  174. toplevel $frame_
  175. wm withdraw $frame_
  176. wm transient $frame_ .
  177. wm title $frame_ "HTTP Status"
  178. set new_toplevel 1
  179. }
  180. set textheight [font metric http_font -linespace]
  181. label $frame_.label -font http_font -width 100 
  182. -justify left -anchor w -text ""
  183. canvas $frame_.canvas -height $textheight 
  184. -width 50 -bd 1 -relief sunken
  185. pack $frame_.canvas -side right
  186. pack $frame_.label -expand 1 -fill x -side left
  187. set rect_ [$frame_.canvas create rectangle 1 2 10 $textheight 
  188. -fill blue -outline blue]
  189. $frame_.canvas move $rect_ -1000 0
  190. if [info exists new_toplevel] {
  191. # center the window
  192. update idletasks
  193. update
  194. set x [expr [winfo screenwidth $frame_]/2 
  195. - [winfo reqwidth $frame_]/2 
  196. - [winfo vrootx [winfo parent $frame_]]]
  197. set y [expr [winfo screenheight $frame_]/2 
  198. - [winfo reqheight $frame_]/2 
  199. - [winfo vrooty [winfo parent $frame_]]]
  200. wm geom $frame_ +$x+$y
  201. }       
  202. }
  203. HTTP private start_ping_pong { } {
  204. if { ![$self set enable_output_] } return
  205. $self instvar frame_ rect_ after_id_ hide_id_ dir_ pos_
  206. if { [lsearch -exact [package names] Tk] != -1 } {
  207. # found Tk; display a UI
  208. if { ![info exists frame_] } {
  209. $self build_widget
  210. }
  211. if { [wm state [winfo toplevel $frame_]] == "withdrawn" } {
  212. wm deiconify $frame_
  213. }
  214. if { ![info exists dir_] } {
  215. set dir_ 2
  216. set pos_ 1
  217. }
  218. set coords [$frame_.canvas coords $rect_]
  219. set x1 [lindex $coords 0]
  220. set y1 [lindex $coords 1]
  221. set x2 [lindex $coords 2]
  222. set y2 [lindex $coords 3]
  223. $frame_.canvas coords $rect_ $pos_ $y1 [expr $pos_-$x1+$x2] $y2
  224. } else {
  225. $self set ping_cnt_ 0
  226. puts -nonewline stderr "Fetching URL "
  227. }
  228. set after_id_ [after 100 "$self do_ping_pong"]
  229. if [info exists hide_id_] { after cancel $hide_id_ }
  230. $self instvar urls_
  231. $self print_status "Fetching $urls_ ..."
  232. }
  233. HTTP private stop_ping_pong { } {
  234. if { ![$self set enable_output_] } return
  235. $self instvar after_id_ hide_id_ frame_ rect_
  236. if [info exists after_id_] {
  237. after cancel $after_id_
  238. unset after_id_
  239. if { [lsearch -exact [package names] Tk] != -1 } {
  240. set hide_id_ [after idle "$self hide"]
  241. } else {
  242. puts stderr ""
  243. }
  244. }
  245. }
  246. HTTP private hide { } {
  247. $self instvar frame_ rect_ pos_ dir_
  248. set pos_ 1
  249. set dir_ 2
  250. $self print_status ""
  251. $frame_.canvas move $rect_ -1000 0
  252. if { [winfo toplevel $frame_] == $frame_ } {
  253. wm withdraw $frame_
  254. }
  255. }
  256. HTTP private do_ping_pong { } {
  257. if { ![$self set enable_output_] } return
  258. $self instvar frame_ rect_ dir_ pos_ after_id_
  259. if { [lsearch -exact [package names] Tk] != -1 } {      
  260. incr pos_ $dir_
  261. $frame_.canvas move $rect_ $dir_ 0
  262. if { $pos_ <= 1 || $pos_ >= 42 } {
  263. set dir_ [expr 0 - $dir_]
  264. }
  265. } else {
  266. $self instvar ping_cnt_
  267. incr ping_cnt_
  268. if { $ping_cnt_ >= 10 } {
  269. puts -nonewline stderr "."
  270. set ping_cnt_ 0
  271. }
  272. }
  273. set after_id_ [after 100 "$self do_ping_pong"]
  274. }
  275. HTTP private print_status { status } {
  276. if { ![$self set enable_output_] } return
  277. if { [lsearch -exact [package names] Tk] != -1 } {
  278. $self instvar frame_
  279. if [info exists frame_] {
  280. $frame_.label configure -text $status
  281. }
  282. }
  283. }
  284. HTTP public set_frame { frame } {
  285. if { [lsearch -exact [package names] Tk] != -1 } {
  286. $self instvar frame_
  287. if [info exists frame_] {
  288. destroy $frame_
  289. }
  290. set frame_ $frame
  291. $self build_widget
  292. }
  293. }
  294. HTTP public enable_output { { yes 1 } } {
  295. $self set enable_output_ $yes
  296. }
  297. HTTP proc.invoke { } {
  298. if { [lsearch -exact [package names] Tk] != -1 } {
  299. font create http_font -family helvetica -size 10
  300. }
  301. }
  302. Class HTTPCache
  303. HTTPCache public init { {dir ~/.mash/cache/} } {
  304. $self next
  305. $self instvar dir_ index_ index_filename_
  306. $self create_dir $dir
  307. set dir_ [glob $dir]
  308. set index_filename_ [file join $dir_ index.db]
  309. if {! [catch {set f [open $index_filename_]}] } {
  310. while 1 {
  311. set line [gets $f]
  312. if [eof $f] {
  313. close $f
  314. break
  315. }
  316. set index_([lindex $line 0]) [lindex $line 1]
  317. }
  318. }
  319. }
  320. HTTPCache public get { url {last_modified {}} } {
  321. $self instvar index_
  322. if [info exists index_($url)] {
  323. if { $last_modified != {} } {
  324. if [catch {set mtime [file mtime $index_($url)]}] 
  325. { return "" }
  326. if { $last_modified==-1 || $mtime < $last_modified } 
  327. { return "" }
  328. }
  329. if [catch {set f [open $index_($url)]}] { return "" }
  330. fconfigure $f -translation binary
  331. set buffer ""
  332. while { ![eof $f] } {
  333. append buffer [read $f 4096]
  334. }
  335. close $f
  336. return $buffer
  337. } else {
  338. return ""
  339. }
  340. }
  341. HTTPCache public put { url buffer } {
  342. $self instvar index_ dir_ index_filename_
  343. if { ![info exists index_($url)] } {
  344. set update_index_file 1
  345. }
  346. set name cache[clock clicks]
  347. set index_($url) [file join $dir_ $name[file extension $url]]
  348. set f [open $index_($url) w 0644]
  349. fconfigure $f -translation binary
  350. puts -nonewline $f $buffer
  351. close $f
  352. # write the index file
  353. if [catch {set f [open $index_filename_ a]}] {
  354. set f [open $index_filename_ w 0644]
  355. }
  356. puts $f [list $url $index_($url)]
  357. close $f
  358. }
  359. HTTPCache public flush { } {
  360. $self instvar index_ dir_
  361. file delete -force -- [glob -nocomplain [file join $dir_ *]]
  362. catch {unset index_}
  363. }
  364. HTTPCache private create_dir { path } {
  365. if { ![file isdirectory $path] } {
  366. set dir ""
  367. foreach split [file split $path] {
  368. set dir [file join $dir $split]
  369. if { ![file exists $dir] } {
  370. # this command will cause an error
  371. # if it is not possible to create the dir
  372. file mkdir $dir
  373. }
  374. }
  375. }
  376. }
  377. # create an HTTP object
  378. HTTP Http