* Protect all calls to mail_elt in pith/ and alpine/ code. Protect means
[alpine.git] / web / config / alpine.tcl
blob531dafaf1765f7ea8a5df3ecd93654c70872482b
1 # Web Alpine Config options
2 # $Id: alpine.tcl 1266 2009-07-14 18:39:12Z hubert@u.washington.edu $
3 # ========================================================================
4 # Copyright 2006-2008 University of Washington
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # ========================================================================
14 encoding system "utf-8"
16 set _wp(appname) Alpine
17 set _wp(admin) admin@sample-domain.edu
18 set _wp(helpdesk) admin@sample-domain.edu
19 set _wp(comments) help@sample-domain.edu
21 # List of userid's allowed to request the monitor script output
22 set _wp(monitors) {}
24 # directory prefix web server uses for web alpine page requests
25 # Note: set to {} if DocumentRoot set to the root of web alpine cgi scripts
26 set _wp(urlprefix) webmail
28 # file system path to CGI application files
29 # directory containing web alpine application scripts and supporting tools
30 set _wp(fileroot) /usr/local/libexec/alpine
32 set _wp(tmpdir) /tmp
34 # NOTE: Make SURE tclsh and alpine.tcl symlinks in this directory
35 set _wp(cgipath) [file join $_wp(fileroot) cgi]
37 # CGI scripts implementing U/I, session cookie scope
38 set _wp(appdir) alpine
40 # UI versions
41 set _wp(ui1dir) 1.0
42 set _wp(ui2dir) 2.0
44 # place for CGI scripts not requiring session-key
45 set _wp(pubdir) pub
47 # place for binaries referenced by the CGI scripts
48 set _wp(bin) [file join $_wp(fileroot) bin]
49 set _wp(servlet) alpined
50 set _wp(pc_servlet) pc_alpined
51 set _wp(pldap) alpineldap
53 # place for config files referenced by the CGI scripts
54 set _wp(confdir) [file join $_wp(fileroot) config]
55 set _wp(conffile) pine.conf
56 set _wp(defconf) $_wp(conffile)
58 # place for library files used by CGI scripts
59 set _wp(lib) [file join $_wp(fileroot) lib]
61 # directory used temporarily to stage attatched and detached files
62 set _wp(detachpath) [file join $_wp(fileroot) detach]
64 set _wp(imagepath) [file join / $_wp(urlprefix) images]
66 set _wp(buttonpath) [file join $_wp(imagepath) buttons silver]
68 set _wp(staticondir) env
70 set _wp(servername) [info hostname]
72 # MUST specify SSL/TLS connection
73 set _wp(serverport) {}
74 set _wp(serverpath) https://[file join [join [eval list $_wp(servername) $_wp(serverport)] :] $_wp(urlprefix)]
76 # MAY specify a plaintext connection (comment out if plain support undesired)
77 set _wp(plainport) {}
78 set _wp(plainservpath) http://[file join [join [eval list $_wp(servername) $_wp(plainport)] :] $_wp(urlprefix)]
80 # url of faq page(s) available from initial greeting page
81 #set _wp(faq) "http://www.yourserver/faqs/alpine.html"
83 # url of informational page accessible from initial greeting page
84 set _wp(releaseblurb) "$_wp(plainservpath)/alpine/help/release.html"
86 # url of previous version server to be accessible from initial greeting page
87 #set _wp(oldserverpath) "https://previous.version.server.edu:444/"
89 # session id length: make sure the integer count below matches what's built
90 # into the pubcookie: "src/pubcookie/wp_uidmapper_lib.h:#define WP_KEY_LEN 6"
91 set _wp(sessidlen) 6
93 # Where and what format the alpined comm socket should take
94 set _wp(sockdir) $_wp(tmpdir)
95 set _wp(sockpat) wp%s
97 # skin settings
98 set _wp(bordercolor) #FEFAC9
99 set _wp(menucolor) #3E2E6D
100 set _wp(dialogcolor) #FEFAC9
101 set _wp(titlecolor) #000000
102 set _wp(logodir) alpine
104 # various timerouts, dimensions and feature settings
105 set _wp(refresh) 600
106 set _wp(timeout) 900
107 set _wp(autodraft) 300
108 set _wp(logoutpause) 60
109 set _wp(indexlines) 20
110 set _wp(indexlinesmax) 50
111 set _wp(indexheight) 24
112 set _wp(navheight) 28
113 set _wp(width) 80
114 set _wp(titleheight) 34
115 set _wp(titlesep) 4
116 set _wp(config) remote_pinerc
117 set _wp(motd) motd
118 set _wp(save_cache_max) 6
119 set _wp(fldr_cache_max) 20
120 set _wp(fldr_cache_def) 3
121 set _wp(statushelp) 0
122 set _wp(imgbuttons) 0
123 set _wp(keybindings) 1
124 set _wp(dictionary) 0
125 set _wp(debug) 0
126 set _wp(cmdtime) 0
127 set _wp(evaltime) 0
128 set _wp(menuargs) {width="112" nowrap valign=top}
129 set _wp(ispell) /usr/local/bin/ispell
131 # Yahoo! User Interface Library location
132 #set _wp(yui) $_wp(serverpath)/$_wp(appdir)/$_wp(ui2dir)/lib/yui
133 set _wp(yui) "http://yui.yahooapis.com/2.7.0"
135 # usage reporter - input: username as first command line argument
136 # output: space separated integers usage and total
137 #set _wp(usage) $_wp(bin)/usage.tcl
138 #set _wp(usage_link) "https://uwnetid.washington.edu/disk/"
140 # limit uploads to 1 file at a time, maximum 20MB.
141 set _wp(uplim_files) 1
142 set _wp(uplim_bytes) 20000000
144 # verify sessid from consistent REMOTE_ADDR (set to 0 for proxying clusters)
145 set _wp(hostcheck) 0
147 # set to list of domains for which ssl is NOT required
148 #set _wp(ssl_safe_domains) {}
150 # set to list of address blocks or ranges for which ssl is NOT required
151 #set _wp(ssl_safe_addrs) {}
153 # set this value to zero to turn OFF ssl by default
154 set _wp(ssl_default) 1
156 # allow connecting user to specify imap server on greeting page
157 set _wp(flexserver) 1
159 # make sure tmp files and such are ours alone to read/write
160 catch {exec umask 044}
162 #fix up indexheight so it isn't too high or too low
163 set _wp(indexheight) [expr {$_wp(indexheight) <= 20 ? 20 : $_wp(indexheight) >= 30 ? 30 : $_wp(indexheight)}]
165 # SPAM reporting facility, if set "Report Spam" button appears at top of View Page
166 #set _wp(spamaddr) spamaddr@sample-domain.edu
167 #set _wp(spamfolder) junk-mail
168 #set _wp(spamsubj) "ATTACHED SPAM"
170 # external mail filter config link
171 #set _wp(filter_link) http://delivery-filter.sample-domain.edu/filter/config
173 # external vacation config link
174 #set _wp(vacation_link) http://vacation.sample-domain.edu/vacation/config
177 # Nickname server bindings. If not present, prompt for the
178 # destination of the default pinerc location.
180 set _wp(hosts) {
182 Deskmail
183 $User.deskmail.washington.edu/ssl
184 $_wp(confdir)/conf.deskmail
188 # Everybody inherits the cgi, comm packages
189 lappend auto_path $_wp(lib)
191 package require cgi
192 package require WPComm
194 # Recipient of bad news bubbling up from cgi.tcl...
195 cgi_admin_mail_addr $_wp(admin)
197 cgi_sendmail {}
199 #cgi_mail_relay localhost
200 cgi_mail_relay smtpserver.sample-domain.edu
202 # set permissions for owner-only handling
203 cgi_tmpfile_permissions 0640
205 #set upload limits
206 cgi_file_limit $_wp(uplim_files) $_wp(uplim_bytes)
208 # universal body tag parameters
209 cgi_body_args link=#0000FF vlink=#000080 alink=#FF0000 marginwidth=0 marginheight=0 topmargin=0 leftmargin=0
211 # Common Images Image definitions
212 cgi_imglink logo [file join $_wp(imagepath) logo $_wp(logodir) big.gif] border=0 "alt=Web Alpine"
213 cgi_imglink smalllogo [file join $_wp(imagepath) logo $_wp(logodir) small.gif] border=0 "alt=About Web Alpine"
214 cgi_imglink background [file join $_wp(imagepath) logo $_wp(logodir) back.gif] border=0 align=top
215 cgi_imglink dot [file join $_wp(imagepath) dot2.gif] border=0 align=top
216 cgi_imglink increas [file join $_wp(imagepath) increas4.gif] border=0 align=absmiddle
217 cgi_imglink decreas [file join $_wp(imagepath) decreas4.gif] border=0 align=absmiddle
218 cgi_imglink expand [file join $_wp(imagepath) b_plus.gif] border=0 "alt=Expand" height=9 width=9
219 cgi_imglink contract [file join $_wp(imagepath) b_minus.gif] border=0 "alt=Collapse" height=9 width=9
220 cgi_imglink fullhdr [file join $_wp(imagepath) hdr.gif] border=0 "alt=Full Header"
221 cgi_imglink nofullhdr [file join $_wp(imagepath) hdrnon.gif] border=0 "alt=Digested Header"
222 cgi_imglink bang [file join $_wp(imagepath) caution.gif] border=0 "alt=!"
223 cgi_imglink postmark [file join $_wp(imagepath) postmark.gif] border=0 "alt=New Mail"
224 cgi_imglink gtab [file join $_wp(imagepath) tabs gtab.gif] border=0 align=top
225 cgi_imglink gdtab [file join $_wp(imagepath) tabs gdtab.gif] border=0 align=top
226 cgi_imglink abtab [file join $_wp(imagepath) tabs abtab.gif] border=0 align=top
227 cgi_imglink abdtab [file join $_wp(imagepath) tabs abdtab.gif] border=0 align=top
228 cgi_imglink ctab [file join $_wp(imagepath) tabs ctab.gif] border=0 align=top
229 cgi_imglink cdtab [file join $_wp(imagepath) tabs cdtab.gif] border=0 align=top
230 cgi_imglink ftab [file join $_wp(imagepath) tabs ftab.gif] border=0 align=top
231 cgi_imglink fdtab [file join $_wp(imagepath) tabs fdtab.gif] border=0 align=top
232 cgi_imglink mltab [file join $_wp(imagepath) tabs mltab.gif] border=0 align=top
233 cgi_imglink mldtab [file join $_wp(imagepath) tabs mldtab.gif] border=0 align=top
234 cgi_imglink mvtab [file join $_wp(imagepath) tabs mvtab.gif] border=0 align=top
235 cgi_imglink mvdtab [file join $_wp(imagepath) tabs mvdtab.gif] border=0 align=top
236 cgi_imglink rtab [file join $_wp(imagepath) tabs rtab.gif] border=0 align=top
237 cgi_imglink rdtab [file join $_wp(imagepath) tabs rdtab.gif] border=0 align=top
240 # Link definitions
241 cgi_link Admin "Web Alpine Administrator" "mailto:$_wp(admin)"
242 cgi_link Start "Web Alpine Home Page" "$_wp(serverpath)/session/greeting.tcl" target=_top
244 # Internally referenced CGI directory root
245 cgi_root $_wp(serverpath)
246 cgi_suffix .tcl
248 # have cgi.tcl convert eols in muiltipart/form-data
249 set _cgi(no_binary_upload) 1
251 proc WPSocketName {sessid} {
252 global _wp
254 return [file join $_wp(sockdir) [format $_wp(sockpat) $sessid]]
257 proc WPValidId {{sessid {}}} {
258 global _wp env
260 if {[string length $sessid] == 0} {
261 set created 1
263 # Session Handle: a bit reasonably random number. the format
264 # is convenient for pubcookie auth'd support
265 set rnum {}
266 set rsrc /dev/urandom
267 set idbytelength [expr {$_wp(sessidlen) * 4}]
268 if {[file readable $rsrc] && [catch {open $rsrc r} fp] == 0} {
269 while {1} {
270 for {set i 0} {$i < $idbytelength} {incr i} {
271 if {$i && ($i % 4) == 0} {
272 append rnum "."
275 if {[catch {read $fp 1} n] == 0} {
276 binary scan $n c x
277 set x [expr ($x & 0xff)]
278 append rnum [format {%02x} $x]
279 } else {
280 set rnum {}
281 break
285 if {[file exists [WPSocketName $rnum]]} {
286 set rnum {}
287 } else {
288 break
292 close $fp
295 # second choice for random numbers
296 if {[string length $rnum] == 0} {
297 expr srand([clock seconds])
298 for {set i 0} {$i < $idbytelength} {incr i 4} {
299 if {$i && ($i % 4) == 0} {
300 append rnum "."
303 append rnum [format {%08x} [expr int((100000000 * rand()))]]
307 # generate a session ID
308 set _wp(sessid) $rnum
309 } else {
310 set sessidparts [split $sessid {@}]
311 switch [llength $sessidparts] {
313 set _wp(sessid) $sessid
316 if {[string compare [string tolower [lindex $sessidparts 1]] [string tolower [info hostname]]]} {
317 regexp {^([a-zA-Z]*://).*} [cgi_root] match proto
318 error [list redirect "${proto}[lindex $sessidparts 1]:$env(SERVER_PORT)?$env(QUERY_STRING)"]
319 } else {
320 set _wp(sessid) [lindex $sessidparts 0]
323 default {
324 error "Malformed Session ID: $sessid"
329 set _wp(sockname) [WPSocketName $_wp(sessid)]
331 if {[info exists _wp(cumulative)]} {
332 rename WPCmd WPCmd.orig
333 rename WPCmdTimed WPCmd
336 if {[info exists _wp(hostcheck)] && $_wp(hostcheck) == 1 && ![info exists created]
337 && [catch {WPCmd set wp_client} client] == 0
338 && (([info exists env(REMOTE_ADDR)] && [string length $env(REMOTE_ADDR)] && [string compare $client $env(REMOTE_ADDR)])
339 || ([info exists env(REMOTE_HOST)] && [string length $env(REMOTE_HOST)] && [string compare $client $env(REMOTE_HOST)]))} {
340 error "Request from unrecognized client"
344 proc WPAbort {} {
345 WPCleanup
346 cgi_exit
349 proc WPCleanup {} {
350 global _wp
352 if {[info exists _wp(cleanup)]} {
353 foreach item $_wp(cleanup) {
354 catch {eval $item}
359 proc WPEval {vars cmd} {
360 global _wp
362 if {$_wp(cmdtime) || $_wp(evaltime)} {
363 set _wp(cumulative) 0
366 set _wp(cmd) $cmd
367 set _wp(vars) [linsert $vars 0 [list sessid "Missing Session ID"]]
369 uplevel 1 {
370 cgi_eval {
371 if {$_wp(debug) > 1} {
372 cgi_debug -on
375 # Session id?
376 if {[catch {WPGetInputAndID sessid}]} {
377 return
380 foreach item $_wp(vars) {
381 if {[catch {eval WPImport $item} errstr]} {
382 WPInfoPage "Web Alpine Error" [font size=+2 $errstr] "Please close this window."
383 return
387 # evaluate the given script
388 if {[catch {cgi_buffer $_wp(cmd)} result]} {
390 reset_cgi_state
392 if {[string index $result 0] == "_"} {
393 switch -- [lindex $result 0] {
394 _info {
395 WPInfoPage [lindex $result 1] [font size=+2 [lindex $result 2]] [lindex $result 3]
397 _action {
398 switch -regexp -- [lindex $result 2] {
399 "[Ii]nactive [Ss]ession" {
400 WPInactivePage
402 default {
403 if {[string length [lindex $result 3]]} {
404 set remedy [lindex $result 3]
405 } else {
406 set remedy " Click your browser's Back button to return to previous page."
408 WPInfoPage "[lindex $result 1] Error" [font size=+2 [lindex $result 2]] \
409 "Please report this to the [cgi_link Admin].$remedy"
413 _redirect {
414 cgi_http_head {
415 cgi_redirect [lindex $result 1]
418 cgi_html { cgi_body {} }
420 _close {
421 if {[string length [lindex $result 1]] == 0} {
422 set result "Indeterminate error"
425 WPInfoPage "Web Alpine Error" [font size=+2 [lindex $result 1]] "Please close this window."
427 default {
428 if {[string length $result]} {
429 WPInfoPage "Web Alpine Error" [font size=+2 "Eval Error: $result"] \
430 "Please complain to the [cgi_link Admin]. Click Back button to return to previous page."
431 } else {
432 WPInfoPage "Web Alpine Error" [font size=+2 "Indeterminate error response"] \
433 "Please complain to the [cgi_link Admin] and click Back button to return to previous page."
437 } else {
438 if {[regexp {[Ii]nactive [Ss]ession} $result]} {
439 WPInactivePage
440 } else {
441 WPInfoPage "Web Alpine Error" [font size=+2 "Error: $result"] \
442 "Please report this to the [cgi_link Admin]. Try clicking your browser's Back button to return to a working page."
445 } else {
446 catch {cgi_puts $result}
451 # cleanup here
452 WPCleanup
454 if {[info exists _wp(cumulative)]} {
455 WPdebug "Cumulative Eval: $_wp(cumulative)"
456 unset _wp(cumulative)
460 proc WPGetInputAndID {_sessid} {
461 global _wp
462 upvar $_sessid sessid
464 # Import data and validate it
465 if {[catch {cgi_input "sessid=8543949466398&"} result]} {
466 WPInfoPage "Web Alpine Error" [font size=+2 $result] "Please close this window."
467 error "Cannot get CGI Input"
470 if {[catch {WPImport sessid "Missing Session ID"} errstr]} {
471 if {[regexp {.*sessid.*no such.*} $errstr]} {
472 WPInactivePage [list "Your browser may have failed to send the necessary <i>cookie</i> information. Please verify your browser configuration has cookies enabled."]
473 } else {
474 WPInfoPage "Web Alpine Error" [font size=+2 $errstr] "Please close this window."
477 error "Session ID Failure"
478 } else {
479 # initialization here
480 if {[catch {WPValidId $sessid} result]} {
481 if {[string compare [lindex $result 0] redirect]} {
482 WPInfoPage "Web Alpine Error" [font size=+2 "$result"] \
483 "Please complain to the [cgi_link Admin] and visit the [cgi_link Start] later."
484 } else {
485 cgi_http_head {
486 cgi_redirect [lindex $result 1]
490 error "Unrecoverable Error"
491 } elseif {$_wp(sessid) == 0} {
492 WPInactivePage
493 error "Inactive Session"
496 if {[catch {WPCmd set serverroot} serverroot] == 0} {
497 cgi_root $serverroot
502 proc WPCmdEval {args} {
503 return [eval $args]
506 proc WPCmd {args} {
507 global _wp
509 return [WPSend $_wp(sockname) $args]
512 proc WPCmdTimed {args} {
513 global _wp
515 set t [lindex [time {set r [WPSend $_wp(sockname) $args]}] 0]
516 incr _wp(cumulative) $t
518 if {$_wp(cmdtime)} {
519 WPdebug "time $t : $args"
522 return $r
525 proc WPLoadCGIVar {_var} {
526 upvar $_var var
528 if {[catch {cgi_import_as $_var var} result]
529 && [catch {WPCmd set $_var} var]
530 && [catch {cgi_import_cookie_as $_var var} result]} {
531 error [list _action "Import Cookie $_var" $result]
535 proc WPLoadCGIVarAs {_var _varas} {
536 upvar $_varas varas
538 if {[catch {cgi_import_as $_var varas} result]
539 && [catch {WPCmd set $_var} varas]
540 && [catch {cgi_import_cookie_as $_var varas} result]} {
541 set varas ""
545 proc WPImport {valname {errstring ""} {default 0}} {
546 upvar $valname val
548 if {[catch {cgi_import_as $valname val} result]} {
549 if {[catch {WPCmd set $valname} val]} {
550 if {[catch {cgi_import_cookie_as $valname val} result]} {
551 if {[string length $errstring] > 0} {
552 error "$errstring: $result"
553 } else {
554 set val $default
562 proc WPExportCookie {name value {scope ""}} {
563 global _wp
565 cgi_cookie_set $name=$value "path=[file join / $_wp(urlprefix) $scope]"
569 # handle dynamic sizing of images showing thread relationships
570 proc WPThreadImageLink {t h} {
571 global _wp
573 return "<img src=\"[file join $_wp(imagepath) ${t}.gif]\" border=0 align=top height=${h} width=14>"
577 proc WPInactivePage {{reasons ""}} {
578 set l {}
579 foreach r $reasons {
580 append l "<li>$r"
583 WPInfoPage "Inactive Session" \
584 "[font size=+2 "Web Alpine Session No Longer Active"]" \
585 "There are several reasons why a session might become inactive.<ul><li>A bookmarked reference to a Web Alpine page.<li>Failed periodic page reload due to browser/system suspension associated with power saving mode, etc.${l}</ul><p>Please visit the [cgi_link Start] to start a new session."
588 proc WPInfoPage {title exp1 {exp2 ""} {imgurl {}} {exp3 ""}} {
589 global _wp
591 catch {
593 cgi_html {
594 cgi_head {
595 cgi_title $title
596 cgi_stylesheet [file join / $_wp(urlprefix) $_wp(pubdir) standard.css]
599 cgi_body {
600 cgi_table height="20%" {
601 cgi_table_row {
602 cgi_table_data {
603 cgi_puts [cgi_nbspace]
608 cgi_center {
609 cgi_table border=0 width=500 cellpadding=3 {
610 cgi_table_row {
611 cgi_table_data align=center rowspan=3 {
612 if {[string length $imgurl]} {
613 cgi_put [cgi_url [cgi_imglink logo] $imgurl]
614 } else {
615 cgi_put [cgi_imglink logo]
619 cgi_table_data rowspan=3 {
620 cgi_put [nbspace]
621 cgi_put [nbspace]
624 cgi_table_data {
625 cgi_puts $exp1
630 if {[string length $exp3]} {
631 cgi_table_row {
632 cgi_table_data "style=\"border: 1px solid red; background-color: pink\"" {
633 cgi_puts $exp3
638 if {[string length $exp2]} {
639 cgi_table_row {
640 cgi_table_data {
641 cgi_puts $exp2
652 proc WPimg {image {extension gif}} {
653 global _wp
655 return [file join $_wp(imagepath) ${image}.${extension}]
658 proc WPCharValue {c} {
659 scan "$c" %c n
660 return $n
663 proc WPPercentQuote {arg {exclude {}}} {
664 set t "\[^0-9a-zA-Z_${exclude}\]"
665 if {[regsub -all $t $arg {[format "%%%.2X" [WPCharValue "\\&"]]} subarg]} {
666 set x [subst $subarg]
667 return $x
668 } else {
669 return $arg
673 proc WPJSQuote {l} {
674 regsub -all {([\\'])} $l {\\\1} l
675 return $l
678 proc WPurl {cmd cmdargs text explanation args} {
679 global _wp
681 lappend urlargs $text
682 lappend urlargs $cmd
683 if {[regexp "^java*" $cmd] == 0 && [string first . $cmd] < 0} {
684 append urlargs ".tcl"
687 if {[string length $cmdargs]} {
688 if {[set i [string first "?" $cmdargs]] >= 0} {
689 append urlargs "[cgi_quote_url [string range $cmdargs 0 [expr {$i - 1}]]]?[cgi_quote_url [string range $cmdargs [incr i] end]]"
690 } else {
691 append urlargs "?[cgi_quote_url $cmdargs]"
695 if {$_wp(statushelp)} {
696 lappend urlargs [WPmouseover $explanation]
697 lappend urlargs "onMouseOut=window.status=''"
700 return [eval "cgi_url $urlargs $args"]
703 proc WPMenuURL {cmd cmdargs text explanation args} {
704 return [WPurl $cmd $cmdargs $text $explanation class=menubar [join $args]]
707 proc WPGetTDFontSize {{ih 24}} {
708 if {$ih <= 20 } {return 12}
709 if {$ih >= 30 } {return 24}
710 return [expr {$ih - 8}]
713 proc WPGetviewFontSize {{ih 24}} {
714 if {$ih <= 20 } {return 8}
715 if {$ih >= 30 } {return 13}
716 return [expr {($ih / 2) - 2}]
719 proc WPIndexLineHeight {{ih 0}} {
720 global _wp
722 set ih [WPCmd PEInfo indexheight]
723 if {[string length $ih] == 0 || $ih <= 0} {
724 set ih $_wp(indexheight)
727 return [expr {($ih < 20) ? 20 : $ih}]
730 proc WPStyleSheets {{ih 0}} {
731 global _wp
733 cgi_stylesheet [file join / $_wp(urlprefix) $_wp(pubdir) standard.css]
735 if {$ih <= 0} {
736 set ih [WPIndexLineHeight]
739 cgi_puts "<style type='text/css'>\nTD { font-size: [WPGetTDFontSize $ih]px }\n.view {font-size: [WPGetviewFontSize $ih]pt }\n</style>"
740 return $ih
743 proc WPStdScripts {{ih 0}} {
744 global _wp
746 set ih [WPStyleSheets $ih]
748 cgi_script language="JavaScript" src="[file join / $_wp(urlprefix) $_wp(pubdir) standard.js]" {}
749 cgi_script language="JavaScript1.3" {cgi_put "js_version = '1.3';"}
750 cgi_javascript {
751 cgi_puts "function getIndexHeight(){return $ih}"
755 proc WPStdHttpHdrs {{ctype {}} {expires 0}} {
756 global _wp
758 # set date and expires headers the same to prevent caching
759 # Date: Tue, 15 Nov 1994 08:12:31 GMT
760 set doctime [clock seconds]
762 if {[string length $ctype]} {
763 cgi_content_type $ctype
764 } else {
765 cgi_content_type
768 cgi_puts "Date: [clock format $doctime -gmt true -format "%a, %d %b %Y %H:%M:%S GMT"]"
769 if {$expires == 0} {
770 set _wp(nocache) 1
771 cgi_puts "Cache-Control: no-cache"
772 cgi_puts "Expires: [clock format [expr {$doctime - 31536000}] -gmt true -format "%a, %d %b %Y %H:%M:%S GMT"]"
773 } elseif {$expires > 0} {
774 cgi_puts "Expires: [clock format [expr {$doctime + ($expires * 60)}] -gmt true -format "%a, %d %b %Y %H:%M:%S GMT"]"
778 proc WPStdHtmlHdr {pagetitle {pagescript ""} {newmail 0}} {
779 global _wp
781 if {0 && $newmail} {
782 set nm "* "
783 } else {
784 set nm ""
787 cgi_title "${nm}Web Alpine - $pagetitle"
788 # cgi_base "href=$_wp(serverpath)/"
789 if {[info exists _wp(nocache)]} {
790 cgi_http_equiv Pragma no-cache
793 # cgi_http_equiv Expires $_wp(docdate)
794 cgi_meta "name=Web Alpine" content=[clock format [file mtime [info script]] -format "%y%m%d/%H%M"]
795 if {[catch {WPCmd set nojs} nojs] || $nojs != 1} {
796 cgi_script type="text/javascript" language="JavaScript" {
797 cgi_puts "if(self != top) top.location.href = location.href;"
798 cgi_puts "js_version = '1.0';"
802 cgi_put "<link rel=\"icon\" href=\"[cgi_root]/favicon.ico\" type=\"image/x-icon\">"
803 cgi_put "<link rel=\"shortcut icon\" href=\"[cgi_root]/favicon.ico\" type=\"image/x-icon\"> "
806 proc WPHtmlHdrReload {pagescript} {
807 global _wp
809 if {[regexp {\?} $pagescript]} {
810 set c "&"
811 } else {
812 set c "?"
815 cgi_http_equiv Refresh "$_wp(refresh); url=[cgi_root]/${pagescript}${c}reload=1"
818 proc WPNewMail {reload {viewpage msgview.tcl}} {
820 if {[catch {WPCmd PEMailbox newmail $reload} newmail]} {
821 return -code error $newmail
824 set newref ""
826 if {[set msgsnew [lindex $newmail 0]] > 0} {
827 if {[string length $viewpage]} {
828 if {[string first {?} $viewpage] < 0} {
829 set delim ?
830 } else {
831 set delim &
834 set newurl "${viewpage}${delim}uid=[lindex $newmail 1]"
835 } else {
836 set newurl [lindex $newmail 1]
839 set newicon "postmark"
840 set newtext [cgi_quote_html [WPCmd PEMailbox newmailstatmsg]]
842 if {[WPCmd PEInfo feature enable-newmail-sound]} {
843 #set audio sounds/mail_msg.wav
844 set audio /sounds/ding.wav
845 if {[isIE]} {
846 set newsound "<bgsound src=\"$audio\" loop=\"1\" volume=\"100\">"
847 } else {
848 set newsound "<embed src=\"$audio\" autostart=\"true\" hidden width=0 height=0 loop=\"false\"><noembed><bgsound src=\"$audio\" loop=\"1\"></noembed>"
850 } else {
851 set newsound {}
854 if {0 == [string length $newtext]} {
855 set newtext "You have $msgsnew new message[WPplural $msgsnew]"
858 lappend newref [list $newtext $newicon $newurl $newsound]
861 if {[set deleted [lindex $newmail 2]] > 0} {
862 set newtext "$deleted Message[WPplural $deleted] removed from folder"
863 lappend newref [list $newtext "" ""]
866 foreach statmsg [WPStatusMsgs] {
867 lappend newref [list $statmsg "" ""]
868 WPCmd PEInfo statmsg ""
871 if {!$reload} {
872 WPCmd PEMailbox newmailreset
875 return $newref
878 proc WPStatusMsgs {} {
879 set retmsgs ""
880 set lastmsg ""
881 if {[catch {WPCmd PEInfo statmsgs} statmsgs] == 0} {
882 foreach statmsg $statmsgs {
883 if {[string length $statmsg] > 0 && [string compare $statmsg $lastmsg]} {
884 if {[regexp "^Pinerc \(.+\) NOT saved$" $statmsg]} {
885 lappend retmsgs "Another Pine/WebPine session may be running. Settings cannot be saved."
886 } else {
887 lappend retmsgs $statmsg
890 set lastmsg $statmsg
895 return $retmsgs
898 proc WPStatusIcon {uid {extension gif} {statbits ""}} {
899 global _wp
901 if {[string length $statbits] == 0} {
902 set statbits [WPCmd PEMessage $uid statusbits]
905 if {[string index $statbits 0]} {
906 append sicon "new"
907 set alt " N"
908 set fullalt "New "
909 } else {
910 append sicon "read"
911 set alt " "
912 set fullalt "Viewed "
915 if {[string index $statbits 3]} {
916 append sicon "imp"
917 set alt "*[string range $alt 1 end]"
918 set fullaltend ", important message"
919 } elseif {([string index $statbits 4] || [string index $statbits 5])} {
920 append sicon "you"
921 set alt "+[string range $alt 1 end]"
922 set fullaltend " message to you"
925 if {[string index $statbits 2]} {
926 append sicon "ans"
927 set alt "[string range $alt 0 0]A"
928 append fullalt ", answered"
931 if {[string index $statbits 1]} {
932 append sicon "del"
933 set alt "[string range $alt 0 0]D"
934 append fullalt ", deleted"
937 if {[info exists fullaltend]} {
938 append fullalt $fullaltend
939 } else {
940 append fullalt message
943 regsub -all { } $alt {\&nbsp;} alt
945 return [list [file join $_wp(imagepath) $_wp(staticondir) ${sicon}.${extension}] i_${uid} $alt $fullalt]
948 proc WPStatusLabel {uid} {
949 global _wp
951 set statbits [WPCmd PEMessage $uid statusbits]
953 if {[string index $statbits 0]} {
954 set sl new
955 } else {
956 set sl read
959 if {[string index $statbits 3]} {
960 set sl important
963 if {[string index $statbits 1]} {
964 set sl deleted
967 if {[string index $statbits 2]} {
968 set sl answered
971 return $sl
974 proc WPStatusImg {uid} {
975 set sicon [WPStatusIcon $uid]
976 return [cgi_img [lindex $sicon 0] name=[lindex $sicon 1] id=[lindex $sicon 1] height=16 width=42 border=0 alt=[lindex $sicon 3]]
979 proc WPSessionState {args} {
980 switch [llength $args] {
983 if {[catch {WPCmd PEInfo alpinestate} state_list] == 0} {
984 array set state_array $state_list
985 if {[llength $args] == 1} {
986 return $state_array([lindex $args 0])
987 } else {
988 set state_array([lindex $args 0]) [lindex $args 1]
989 set state_list [array get state_array]
990 if {[catch {WPCmd PEInfo alpinestate $state_list} result]} {
991 error "Can't set session state : $result"
994 } else {
995 error "Can't read session state"
998 default {
999 error "Unknown SessionState Parameters: $args"
1004 proc WPScriptVersion {tag {inc 0}} {
1005 if {[catch {WPCmd set wp_script_version} sv]} {
1006 set versions($tag) [expr int((1000 * rand()))]
1007 set sv [array get versions]
1008 catch {WPCmd set wp_script_version $sv}
1009 } else {
1010 array set versions $sv
1012 if {![info exists versions($tag)]} {
1013 set versions($tag) [expr int((1000 * rand()))]
1014 set sv [array get versions]
1015 catch {WPCmd set wp_script_version $sv}
1016 } elseif {$inc} {
1017 incr versions($tag) $inc
1018 set sv [array get versions]
1019 catch {WPCmd set wp_script_version $sv}
1023 return $versions($tag)
1026 proc WPplural {count} {
1027 if {$count > 1} {
1028 return "s"
1031 return ""
1034 proc WPcomma {number {dot ,}} {
1035 set x ""
1037 while {[set n [string length $number]] > 3} {
1038 set x "${dot}[string range $number [incr n -3] end]$x"
1039 set number [string range $number 0 [incr n -1]]
1042 return "$number$x"
1045 proc isIE {} {
1046 global env
1048 return [expr {[info exists env(HTTP_USER_AGENT)] == 1 && [string first MSIE $env(HTTP_USER_AGENT)] >= 0}]
1051 proc isW3C {} {
1052 global env
1054 return [expr {[info exists env(HTTP_USER_AGENT)] && (([regexp {^Mozilla/([0-9]).[0-9]+} $env(HTTP_USER_AGENT) match majorversion] && $majorversion > 4) || ([regexp {Opera ([0-9])\.[0-9]+} $env(HTTP_USER_AGENT) match majorversion] && $majorversion > 5))}]
1057 proc WPdebug {args} {
1058 global _wp
1060 switch [lindex $args 0] {
1061 level {
1062 if {[regexp {^([0-9])+$} [lindex $args 1]]} {
1063 WPSend $_wp(sockname) [subst {PEDebug level [lindex $args 1]}]
1066 imap {
1067 switch [lindex $args 1] {
1068 on {
1069 WPSend $_wp(sockname) [subst {ePEDebug imap 4}]
1071 off {
1072 WPSend $_wp(sockname) [subst {PEDebug imap 0}]
1076 default {
1077 WPSend $_wp(sockname) "PEDebug write [list [list [file tail [info script]]: [lrange $args 0 end]]]"
1082 proc WPdebugstack {} {
1083 set stack {}
1085 for {set n [expr {[info level] - 1}]} {$n > 0} {incr n -1} {
1086 append stack "$n) [info level $n]\n"
1088 return $stack
1092 ##############################################################
1093 # routines to improve integration with cgi.tcl
1094 ##############################################################
1096 # routine exposing some of cgi.tcl's innards.
1097 # Should be exported by cgi.tcl package.
1098 proc reset_cgi_state {} {
1099 global _cgi
1101 catch {unset _cgi(http_head_in_progress)}
1102 catch {unset _cgi(http_head_done)}
1103 catch {unset _cgi(http_status_done)}
1104 catch {unset _cgi(html_in_progress)}
1105 catch {unset _cgi(head_in_progress)}
1106 catch {unset _cgi(head_done)}
1107 catch {unset _cgi(html_done)}
1108 catch {unset _cgi(head_suppress_tag)}
1109 catch {unset _cgi(body_in_progress)}
1110 catch {unset _cgi(tag_in_progress)}
1111 catch {unset _cgi(form_in_progress)}
1112 catch {unset _cgi(close_proc)}
1114 if {[info exists _cgi(returnIndex)]} {
1115 while {[set _cgi(returnIndex)] > 0} {
1116 incr _cgi(returnIndex) -1
1117 rename cgi_puts ""
1118 rename cgi_puts$_cgi(returnIndex) cgi_puts
1123 ###############################################################
1124 # routines to process (and be called in) html template files
1125 ###############################################################
1127 proc html_readfile {file} {
1128 set x [open $file "r"]
1129 set result [read $x]
1130 close $x
1131 return $result
1134 proc html_eval {_vars_ _this_} {
1135 foreach {_i_ _j_} $_vars_ {
1136 if {$_i_ == "global"} {global $_j_} {set $_i_ $_j_}
1138 unset _vars_ _i_ _j_
1139 return [subst $_this_]
1142 proc html_loop {varslist text} {
1143 set result ""
1144 foreach {vars} $varslist {
1145 append result [html_eval $vars $text]
1147 return $result