~ubuntu-branches/ubuntu/utopic/critcl/utopic

« back to all changes in this revision

Viewing changes to lib/wikit/web.tcl

  • Committer: Package Import Robot
  • Author(s): Andrew Shadura
  • Date: 2013-05-11 00:08:06 UTC
  • Revision ID: package-import@ubuntu.com-20130511000806-7hq1zc3fnn0gat79
Tags: upstream-3.1.9
ImportĀ upstreamĀ versionĀ 3.1.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# These routines are used when WiKit is called from CGI
 
2
 
 
3
package provide Web 1.0
 
4
 
 
5
package require cgi
 
6
package require Wikit::Db
 
7
package require Wikit::Search
 
8
 
 
9
# dump CGI env to file for debugging purposes
 
10
if {[catch {
 
11
  set logfd [open $env(WIKIT_DUMP) a]
 
12
  fconfigure $logfd -buffering line
 
13
  proc tclLog {msg} { puts $::logfd $msg }
 
14
  tclLog "#############################"
 
15
  foreach x [lsort [array names env]] {
 
16
    tclLog "\$$x = $env($x)"
 
17
  }
 
18
}]} {
 
19
  proc tclLog {msg} { }
 
20
}
 
21
 
 
22
tclLog ==============================
 
23
 
 
24
# 1-5-2001: new logic to work with a cache for *much* higher performance
 
25
 
26
# To make this work, create a "main" dir, reachable from the web, and store
 
27
# a special ".htaccess" file in it, (adjust as needed):
 
28
#       DirectoryIndex /home/jcw/wikit.cgi/0
 
29
#       ErrorDocument 404 /home/jcw/wikit.cgi
 
30
#
 
31
# Then config this wikit to maintain pages in that cache:
 
32
#       WIKI_CACHE=/home/jcw/www/tcl ./wikit.tkd 
 
33
#
 
34
# Operation without this new env var, or with the CGI url remains unaffected.
 
35
 
 
36
if {[info exists env(WIKIT_CACHE)] && $env(WIKIT_CACHE) != ""} {
 
37
  set htmlcache $env(WIKIT_CACHE)
 
38
  tclLog "htmlcache = $htmlcache"
 
39
}
 
40
 
 
41
set EditInstructions {}
 
42
set ProtectedPages {}
 
43
 
 
44
# 3-5-2001: force graceful cleanup
 
45
proc cgi_mail_start {args} {
 
46
  catch {
 
47
    global _cgi env appname
 
48
    file delete $appname.lock
 
49
    set fd [open errors.txt a]
 
50
    puts $fd {=================================================================}
 
51
    puts $fd [clock format [clock seconds]]
 
52
    puts $fd $_cgi(errorInfo)
 
53
    puts $fd $env(PATH_INFO)
 
54
    close $fd
 
55
  }
 
56
  exit
 
57
}
 
58
 
 
59
rename puts jcw_puts
 
60
proc puts {args} {
 
61
  # 3-5-2001: make sure broken pipes won't abort
 
62
  catch {eval jcw_puts $args}
 
63
  if {[info exists ::htmlcopy]} {
 
64
    lassign $args a0 a1
 
65
    if {[llength $args] == 1} {
 
66
      append ::htmlcopy $a0 \n
 
67
    } elseif {[llength $args] == 2 && $a0 == "-nonewline"} {
 
68
      append ::htmlcopy $a1
 
69
    }
 
70
  }
 
71
  return
 
72
}
 
73
 
 
74
proc Wikit::stylesheet {} {
 
75
  global env
 
76
  if {[info exists env(WIKIT_CSS)]} {
 
77
    cgi_relationship stylesheet $env(WIKIT_CSS) type=text/css
 
78
  }
 
79
}
 
80
 
 
81
proc Wikit::ProcessCGI {} {
 
82
  variable readonly
 
83
  global htmlcopy htmlcache env roflag
 
84
 
 
85
  if {[info exists env(WIKIT_EMAIL)]} {
 
86
    admin_mail_addr $env(WIKIT_EMAIL)
 
87
  } else {
 
88
    admin_mail_addr nowhere@to.go
 
89
  }
 
90
  #debug -on
 
91
  
 
92
  # 2002-06-17: moved to app-wikit/start.tcl
 
93
  #input "n=1"
 
94
  suffix ""
 
95
  
 
96
  # support AOLserver, fix by Pascal Scheffers from http://mini.net/tcl/4416
 
97
  if { [string first "AOLserver/3" $env(SERVER_SOFTWARE)] > -1 } {
 
98
    #Aolserver does not provide a correct SCRIPT_NAME
 
99
    #fix this by parsing the WIKIT_BASE (which is mandatory anyway)
 
100
    catch {
 
101
      regexp -nocase {^http://[^/]+(/.+)/$} $env(WIKIT_BASE) - env(SCRIPT_NAME)
 
102
    }
 
103
  }
 
104
 
 
105
  set ::script_name $::env(SCRIPT_NAME)
 
106
 
 
107
  # fix embedded wikithttpd server script name
 
108
  if { [string first "WikitHttpd" $env(SERVER_SOFTWARE)] > -1 } {
 
109
      if { $::script_name == "/" } {
 
110
          set ::script_name ""
 
111
      }
 
112
  }
 
113
 
 
114
  # this code added 1-5-2001 to handle ErrorDocument redirection/caching
 
115
  if {[info exists ::env(REDIRECT_URL)]} {
 
116
 
 
117
    set r $env(REDIRECT_URL)
 
118
    if {[info exists env(PATH_INFO)]} { # DirectoryIndex case
 
119
      append r [string range $env(PATH_INFO) 1 end]
 
120
    } else {        # ErrorDocument case
 
121
      set env(PATH_INFO) /[file tail $r]
 
122
    }
 
123
    set env(SCRIPT_NAME) [file dirname $r]
 
124
 
 
125
      catch {set env(QUERY_STRING) $env(REDIRECT_QUERY_STRING)}
 
126
 
 
127
    if {[info exists htmlcache] && [regexp {\d+(\.html)?$} $r - x]} {
 
128
      tclLog "setting up cache copy - $r"
 
129
      set htmlcopy ""
 
130
 
 
131
      proc saveCopy {N} {
 
132
        global htmlcopy htmlcache env
 
133
        if {[info exists env(WIKIT_SAVE)] && $env(WIKIT_SAVE) eq "0"} return
 
134
        regsub ".*?\n\n" $htmlcopy "" htmlcopy
 
135
        if {$N == 2 || $htmlcopy == ""} return
 
136
        catch {
 
137
          set fd [open [file join $htmlcache $N.html] w]
 
138
          puts -nonewline $fd $htmlcopy
 
139
          close $fd
 
140
        }
 
141
      }
 
142
    }
 
143
  }
 
144
  # end of new code
 
145
 
 
146
  cgi_eval {
 
147
    set host $::env(REMOTE_ADDR)
 
148
    #catch {set host $::env(REMOTE_HOST)}
 
149
 
 
150
    # this adds user name, if it is known (thx Shane McDonald, wiki page 19)
 
151
    catch {set host "$::env(REMOTE_USER)@$host"}
 
152
 
 
153
    set path ""
 
154
    catch {set path $::env(PATH_INFO)}
 
155
    
 
156
    set query ""
 
157
    catch {set query $::env(QUERY_STRING)}
 
158
    regsub {^Q=} $query {} query
 
159
    regsub {&.*} $query {} query
 
160
    
 
161
    set cmd ""
 
162
    set section ""
 
163
      # Updated 3Mar03, edit and references are now subdirs to allow
 
164
      # for site indexing. 
 
165
      if {![regexp {^/(edit/|references/)?([0-9]+)(.*)$} $path x section N cmd] || $N >= [mk::view size wdb.pages]} {
 
166
      set N 0
 
167
    
 
168
        # try to locate a page by name, using various search heuristics
 
169
      if {[regexp {^/(.*)} $path x arg] && $arg != "" && $query == ""} {
 
170
        set N [mk::select wdb.pages name $arg -min date 1]
 
171
        switch [llength $N] {
 
172
          0 { # no match, try alternative approach
 
173
            # do a glob search, where AbCdEf -> *[Aa]b*[Cc]d*[Ee]f*
 
174
              # skip this if the search has brackets
 
175
            if {[string first \[ $arg] < 0} {
 
176
              regsub -all {[A-Z]} $arg \
 
177
                {*\\[&[string tolower &]\]} temp
 
178
              set temp "[subst -novariable $temp]*"
 
179
              set N [mk::select wdb.pages -glob name $temp -min date 1]
 
180
            }
 
181
            if {[llength $N] != 1} {
 
182
              set N 0
 
183
              set query $arg ;# turn it into a keyword search
 
184
            }
 
185
          }
 
186
          1 { # uniquely identified, done
 
187
          }
 
188
          default { # ambiguous, turn it into a keyword search
 
189
            set query $arg
 
190
          }
 
191
        }
 
192
      }
 
193
    }
 
194
    #tclLog "path $path query $query N $N"
 
195
 
 
196
    # prevent DoS via way too large integers
 
197
    if {$query eq "" && [string length $N] > 9} { set query $N }
 
198
 
 
199
    if {$query != ""} {
 
200
      set N 2
 
201
      variable searchKey 
 
202
      variable searchLong
 
203
      set searchKey [unquote_input $query]
 
204
      set searchLong [regexp {^(.*)\*$} $searchKey x searchKey]
 
205
      set query "?$query"
 
206
    }
 
207
    
 
208
    pagevars $N name date who
 
209
    set origtag [list $date $who]
 
210
    set refs [mk::select wdb.refs to $N]
 
211
    
 
212
    # added 2004-05-17 wru cookie identification
 
213
    catch {source $::env(WIKIT_WRU)}
 
214
 
 
215
    # if there is new page content, save it now
 
216
    if {$N != "" && [lsearch -exact $::ProtectedPages $N] < 0} {
 
217
      if {$roflag < 0 && ![catch {import C}] && [import C] != ""} {
 
218
        # added 2002-06-13 - edit conflict detection
 
219
        if {![catch {import O}] && $O != $origtag} {
 
220
          tclLog "conflict, want $O, stored $origtag"
 
221
          http_head {
 
222
            content_type
 
223
            pragma no-cache
 
224
          }
 
225
          head {
 
226
            cgi_http_equiv Content-type "text/html; charset=utf-8"
 
227
            title $name
 
228
            cgi_http_equiv Pragma no-cache
 
229
            cgi_http_equiv Expire "Mon, 04 Dec 1999 21:29:02 GMT"
 
230
            stylesheet
 
231
          }
 
232
          body {
 
233
            h2 "Edit conflict on page $N - [Wiki $name $N]"
 
234
            p "[bold {Your changes have NOT been saved}], because
 
235
               someone (at IP address [lindex $origtag 1]) saved
 
236
               a change to this page while you were editing."
 
237
            p [italic {Please restart a new edit and merge your
 
238
               version, which is shown in full below.}]
 
239
            hr size=1
 
240
            p "<pre>[quote_html $C]</pre>" 
 
241
            hr size=1
 
242
            p
 
243
          }
 
244
          return
 
245
        }
 
246
        # thx Alistair Grant, see http://mini.net/tcl/9747
 
247
        #SavePage $N $C $host $name
 
248
        cgi_import_as Action editAction
 
249
        # Only actually save the page if the user selected "Save"
 
250
        if {[string trim $editAction] == "Save" && \
 
251
            (![info exists ::env(WIKIT_WRU_REQ)] || [info exists wru_nick])} {
 
252
          # this cache flushing is not perfect - for one, it fails to be run
 
253
          # when running the same wiki in local mode as well, the solution is
 
254
          # to move this code to the modify layer, not just the cgi script use
 
255
          if {[info exists htmlcache]} {
 
256
            file delete $htmlcache/4.html
 
257
            file delete $htmlcache/$N.html
 
258
            # remove all referencing pages, if this page did not exist before
 
259
            # this makes sure that cache entries point to a filled-in page
 
260
            # from now on, instead of a "[...]" link to a first-time edit page
 
261
            if {$date == 0} {
 
262
              foreach r $refs {
 
263
                set r1 [mk::get wdb.refs!$r from]
 
264
                file delete $htmlcache/$r1.html
 
265
              }
 
266
            }
 
267
          }
 
268
          SavePage $N $C $host $name
 
269
          # end of change, 03-09-2003
 
270
          mk::file commit wdb
 
271
          set saved "saved"
 
272
        } else {
 
273
          set saved "not saved"
 
274
        }
 
275
        # a general improvement: redirect through a fetch again
 
276
        if {![catch {import Z}]} {
 
277
          tclLog "redirect $Z"
 
278
          http_head {
 
279
            content_type
 
280
            pragma no-cache
 
281
            #redirect $Z
 
282
            #refresh 1 $Z
 
283
          }
 
284
          head {
 
285
            title $name
 
286
            http_equiv Refresh 1\;URL=$Z
 
287
            stylesheet
 
288
          }
 
289
          body {
 
290
            puts "Page $saved... [link - [Wikit::Format::quote $name] $Z]"
 
291
          }
 
292
          return
 
293
        }
 
294
        # end of changes
 
295
      }
 
296
    }
 
297
    
 
298
    # set up a few standard URLs an strings
 
299
    
 
300
    switch [llength $refs] {
 
301
      0 {
 
302
        set backRef ""
 
303
        set Refs ""
 
304
        set Title [Wikit::Format::quote $name]
 
305
      }
 
306
      1 {
 
307
        # 03-06-2003 generate page with back ref request, so cached
 
308
        # copy stays valid when more page references are added later
 
309
        #set backRef [mk::get wdb.refs!$refs from]
 
310
        set backRef references/$N!
 
311
        set Refs "[Wiki Reference $backRef] - " 
 
312
        set Title [Wiki $name $backRef]
 
313
      }
 
314
      default {
 
315
        set backRef references/$N!
 
316
        set Refs "[llength $refs] [Wiki References $backRef] - "
 
317
        set Title [Wiki $name $backRef]
 
318
      }
 
319
    }
 
320
    
 
321
    set Edit "Edit [Wiki - edit/$N@]"
 
322
 
 
323
    if { $section eq "" } {
 
324
        set Home "Go to [Wiki - 0]"
 
325
        set About "About [Wiki - 1] - "
 
326
        set Search "[Wiki - 2] - "
 
327
        set Changes "[Wiki - 4] - "
 
328
        set Help " - [Wiki - 3]"
 
329
    } else {
 
330
        # either edit/ or references/ is in the URL. That means all
 
331
        # links must point to ../, to avoid confusion (it would still
 
332
        # work, though).
 
333
        set Home "Go to [Wiki - ../0]"
 
334
        set About "About [Wiki - ../1] - "
 
335
        set Search "[Wiki - ../2] - "
 
336
        set Changes "[Wiki - ../4] - "
 
337
        set Help " - [Wiki - ../3]"
 
338
    }
 
339
 
 
340
    if {$N == 1} { set About "" }
 
341
    if {$N == 2} { set Search "" }
 
342
    if {$N == 3} { set Help "" }
 
343
    if {$N == 4} { set Changes "" }
 
344
    
 
345
    if {$date != 0} {
 
346
      set date [clock format $date -gmt 1 -format {%e %b %Y, %R GMT}]
 
347
    }
 
348
    
 
349
    set updated "Updated [cgi_font size=-1 $date]"
 
350
 
 
351
    # added 2004-05-17
 
352
    if {[regexp {^(.+)[,@]} $who - who_nick] && $who_nick ne ""} {
 
353
      append updated " by $who_nick"
 
354
    }
 
355
 
 
356
    if {[lsearch -exact $::ProtectedPages $N] >= 0} {
 
357
      set menu ""
 
358
    } elseif {$roflag >= 0 || $readonly} {
 
359
      set menu "$updated[nl]"
 
360
    } else {
 
361
      set menu "$updated [nbspace]-[nbspace] $Edit"
 
362
      # 2004-05-29 add optional link to history
 
363
      if {[info exists ::env(WIKIT_REVS)] && $::env(WIKIT_REVS) ne ""} {
 
364
      append menu " [nbspace]-[nbspace]\
 
365
        [link - Revisions $::env(WIKIT_REVS)/$N]"
 
366
      }
 
367
      append menu [nl]
 
368
    }
 
369
    
 
370
    append menu "$Search$Changes$Refs$About$Home$Help"
 
371
    
 
372
    cgi_http_head {
 
373
      cgi_content_type
 
374
      pragma no-cache
 
375
    }
 
376
 
 
377
    # now dispatch on the type of request
 
378
    
 
379
    cgi_html {
 
380
 
 
381
      switch -- $cmd {
 
382
 
 
383
        @ { # called to generate an edit page
 
384
          cgi_head {
 
385
            cgi_http_equiv Content-type "text/html; charset=utf-8"
 
386
            cgi_title "Edit $name"
 
387
            cgi_meta name=robots content=noindex,nofollow
 
388
            cgi_http_equiv Pragma no-cache
 
389
            cgi_http_equiv Expire "Mon, 04 Dec 1999 21:29:02 GMT"
 
390
            stylesheet
 
391
            if {$N != "2" && [info exists ::env(WIKIT_BASE)]} {
 
392
              cgi_base href=$::env(WIKIT_BASE)edit/
 
393
            }
 
394
          }
 
395
          
 
396
          cgi_body bgcolor=#ffffff {
 
397
            cgi_h2 [Wiki - ../$N]
 
398
            
 
399
            cgi_form $::script_name/$N {
 
400
              cgi_export O=$origtag
 
401
              catch {
 
402
                set z "http://$::env(HTTP_HOST)$::env(REDIRECT_URL)"
 
403
                regsub {@$} $z {} z
 
404
                regsub /edit/ $z / z
 
405
                cgi_export Z=$z
 
406
              }
 
407
              textarea C=[GetPage $N] rows=30 cols=72 wrap=virtual \
 
408
                style=width:100%
 
409
              p
 
410
              # thx Alistair Grant, see http://mini.net/tcl/9747
 
411
              #submit_button "=  Save  "
 
412
              # Create Save and Cancel buttons
 
413
              submit_button "Action=Save" \
 
414
                  [expr {[info exists ::env(WIKIT_WRU_REQ)] && \
 
415
                  ![info exists wru_nick] ? "disabled" : ""}]
 
416
              cgi_puts " [nbspace] "
 
417
              submit_button "Action=Cancel"
 
418
              # end of change, 03-09-2003
 
419
              # 2004-05-17 added some sugar to show wru identities
 
420
              if {$date != 0} {
 
421
                cgi_puts " [nbspace] [nbspace] [nbspace] "
 
422
                cgi_puts [italic "Last saved on [bold $date]"]
 
423
                if {[info exists who_nick] && $who_nick ne ""} {
 
424
                  cgi_puts [italic " by [bold $who_nick]"]
 
425
                }
 
426
              }
 
427
              if {[info exists wru_nick]} {
 
428
                cgi_puts " [nbspace] (you are: [bold $wru_nick])"
 
429
              } elseif {[info exists ::env(WIKIT_WRU_REQ)]} {
 
430
                cgi_puts " [nbspace] ([bold [url Register $::env(WIKIT_WRU_REQ)]] to enable saving)"
 
431
              }
 
432
              p
 
433
              cgi_puts $::EditInstructions
 
434
            }
 
435
          }
 
436
        }
 
437
              
 
438
        ! { # called to generate a page with references
 
439
          cgi_head {
 
440
            cgi_http_equiv Content-type "text/html; charset=utf-8"
 
441
            cgi_title "References to $name"
 
442
            cgi_meta name=robots content=noindex,nofollow
 
443
            cgi_http_equiv Pragma no-cache
 
444
            cgi_http_equiv Expire "Mon, 04 Dec 1999 21:29:02 GMT"
 
445
            stylesheet
 
446
            if {$N != "2" && [info exists ::env(WIKIT_BASE)]} {
 
447
              cgi_base href=$::env(WIKIT_BASE)references/
 
448
            }
 
449
          }
 
450
 
 
451
          cgi_body bgcolor=#ffffff {
 
452
            cgi_h2 "References to [Wiki - ../$N]"
 
453
        
 
454
            set refList ""
 
455
            foreach r $refs {
 
456
              set r [mk::get wdb.refs!$r from]
 
457
              pagevars $r name
 
458
              lappend refList [list $name $r]
 
459
            }
 
460
            
 
461
            bullet_list {
 
462
              # the items are a list, if we would just sort on them, then all
 
463
              # single-item entries come first (the rest has {}'s around it)
 
464
              # the following sorts again on 1st word, knowing sorts are stable
 
465
              foreach x [lsort -dict -index 0 [lsort -dict $refList]] {
 
466
                lassign $x name r
 
467
                pagevars $r who date
 
468
                li "[GetTimeStamp $date] . . . [Wiki - ../$r] . . . $who"
 
469
              }
 
470
            }
 
471
            
 
472
            hr noshade      
 
473
            cgi_puts [cgi_font size=-1 "$Search - $Changes - $About - $Home"]
 
474
          }
 
475
        }
 
476
 
 
477
        default { # display one page, also handles expanded pages
 
478
          cgi_head {
 
479
            cgi_http_equiv Content-type "text/html; charset=utf-8"
 
480
            #if {$N == 4} { cgi_http_equiv refresh 300 }
 
481
            cgi_title $name
 
482
            cgi_http_equiv Pragma no-cache
 
483
            cgi_http_equiv Expire "Mon, 04 Dec 1999 21:29:02 GMT"
 
484
            stylesheet
 
485
            if {$N != "2" && [info exists ::env(WIKIT_BASE)]} {
 
486
              cgi_base href=$::env(WIKIT_BASE)
 
487
            }
 
488
          }
 
489
          cgi_body bgcolor=#ffffff {
 
490
            set C [GetPage $N]
 
491
            set U ""
 
492
            foreach {C U} [Expand_HTML $C] break
 
493
            set noTitle [regsub {^<p>(<img src=".*?")>} $C \
 
494
                                        [link - {\1 border=0>} $backRef] C]
 
495
            if {!$noTitle} { h2 $Title }
 
496
        
 
497
            if {$N == 2} {
 
498
              # thx Alistair Grant, see http://mini.net/tcl/9748
 
499
              isindex "prompt=Enter the search phrase. \
 
500
                Append an asterisk (*) to search page contents as well: "
 
501
            }
 
502
            
 
503
            p $C
 
504
          
 
505
            hr noshade
 
506
            #cgi_puts $menu
 
507
            cgi_puts "<p id='footer'>$menu</p>"
 
508
          }
 
509
        }
 
510
      }
 
511
    }
 
512
        
 
513
    if {[info exists ::htmlcopy]} { saveCopy $N }
 
514
  }
 
515
}