1#!./tclsh 2# $Id: cmdfunc.tcl 1204 2009-02-02 19:54:23Z hubert@u.washington.edu $ 3# ======================================================================== 4# Copyright 2006 University of Washington 5# 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 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# ======================================================================== 13 14# cmdfunc.tcl 15# 16# Purpose: CGI script to serve as single location for menu/command 17# function definitions 18# 19# OPTIMIZE: have servlet interpreter grok/exec these? 20# 21# Input: 22 23# Output: 24# 25 26proc WPTFTitle {{context {some page}} {newmail {}} {nologo 0} {aboutcancel {}}} { 27 global _wp 28 29 cgi_table border=0 cellspacing=0 cellpadding=0 width="100%" class=title { 30 cgi_table_row { 31 if {!$nologo} { 32 cgi_table_data valign=top align=left height=$_wp(titleheight) { 33 34 if {[string length $aboutcancel]} { 35 cgi_put [cgi_url [cgi_imglink smalllogo] wp.tcl?page=help&topic=about&oncancel=$aboutcancel class=navbar target=_top] 36 } else { 37 cgi_put [cgi_imglink smalllogo] 38 } 39 } 40 } 41 42 # work in new mail here 43 if {[llength $newmail]} { 44 cgi_table_data align=center { 45 WPTFStatusTable $newmail 46 } 47 } 48 49 cgi_table_data align=right valign=middle height=$_wp(titleheight) { 50 cgi_put [cgi_span "style=margin-right: 8; color: $_wp(titlecolor)" "$context"] 51 } 52 } 53 } 54} 55 56proc WPTFStatusTable {msgs {iconlink {0}} {style {}}} { 57 global _wp 58 59 cgi_table width=100% border=0 cellpadding=0 cellspacing=0 $style { 60 cgi_table_row align=right { 61 62 if {[info exists _wp(statusicons)] && $_wp(statusicons)} { 63 set img [cgi_imglink bang] 64 set snd "" 65 foreach m $msgs { 66 if {[string length [lindex $m 1]]} { 67 set img [cgi_imglink [lindex $m 1]] 68 if {$iconlink && [string length [lindex $m 2]]} { 69 set img [cgi_url $img wp.tcl?page=view&uid=[lindex $m 2] target=body] 70 } 71 72 set snd [lindex $m 3] 73 break 74 } 75 } 76 77 cgi_table_data { 78 cgi_puts ${img}${snd} 79 } 80 } 81 82 cgi_table_data align=center class="statustext" { 83 set i 0 84 85 foreach m $msgs { 86 87 if {[array exists lastmsg] && [info exists lastmsg([lindex $m 0])]} { 88 incr lastmsg([lindex $m 0]) 89 continue 90 } 91 92 if {0 == [string compare [string range [lindex $m 0] 0 20] "Alert received while "]} { 93 set style "style=border: 1px solid red ; background-color: pink; padding: 2; width: 80%;" 94 } elseif {!([info exists _wp(statusicons)] && $_wp(statusicons))} { 95 set style "style=color: white ; background-color: $_wp(menucolor); padding-left:8px; padding-right:8px; white-space: nowrap;" 96 } else { 97 set style 98 } 99 100 if {$iconlink && [string length [lindex $m 2]] && !([info exists _wp(statusicons)] && $_wp(statusicons))} { 101 set txt [cgi_url [lindex $m 0] wp.tcl?page=fr_view&uid=[lindex $m 2] target=body "style=text-decoration: none; color: white"] 102 } else { 103 set txt [lindex $m 0] 104 } 105 106 cgi_division "style=\"padding-bottom: 1px\"" { 107 cgi_puts [cgi_span $style $txt] 108 } 109 110 set lastmsg([lindex $m 0]) 1 111 } 112 } 113 114 if {[info exists _wp(statusicons)] && $_wp(statusicons)} { 115 cgi_table_data align=left { 116 cgi_puts $img 117 } 118 } 119 } 120 } 121} 122 123 124proc WPTFImageButton {args} { 125 return [cgi_buffer {eval cgi_image_button $args border=0}] 126} 127 128proc WPTFCommandMenu {s_menu c_menu} { 129 global _wp 130 131 set clist {} 132 if {[string length $s_menu]} { 133 upvar $s_menu specificmenu 134 if {[llength $specificmenu]} { 135 lappend clist $specificmenu 136 } 137 } 138 139 if {[string length $c_menu]} { 140 upvar $c_menu commonmenu 141 if {[llength $commonmenu]} { 142 if {[llength $clist]} { 143 lappend clist {} 144 } 145 lappend clist $commonmenu 146 } 147 } 148 149 cgi_table border=0 bgcolor=$_wp(menucolor) cellpadding=0 cellspacing=0 width=112 "style=\"padding: 8 0 8 4\"" { 150 foreach menulist $clist { 151 switch [llength $menulist] { 152 0 { 153 cgi_table_row { 154 cgi_table_data { 155 cgi_hr "width=75%" 156 } 157 } 158 } 159 default { 160 foreach item $menulist { 161 if {[llength $item] == 0} { 162 cgi_table_row { 163 cgi_table_data { 164 cgi_hr "width=75%" 165 } 166 } 167 continue 168 } 169 if {[llength $item] == 1} { 170 cgi_table_row { 171 cgi_table_data { 172 eval [lindex $item 0] 173 } 174 } 175 continue 176 } 177 if {[string length [lindex $item 0]]} { 178 if {[uplevel [lindex $item 0]] == 0} { 179 continue 180 } 181 } 182 183 cgi_table_row { 184 foreach l [lindex $item 1] { 185 cgi_table_data align=left valign=middle class=navbar { 186 uplevel $l 187 } 188 } 189 } 190 } 191 } 192 } 193 } 194 } 195} 196 197proc WPTFScript {scrpt {dflt ""}} { 198 global _wp 199 200 switch -- $scrpt { 201 main { 202 set src main.tcl 203 } 204 index { 205 set src index.tcl 206 WPCmd PEInfo set wp_body_script $src 207 } 208 view { 209 set src view.tcl 210 WPCmd PEInfo set wp_body_script $src 211 } 212 body { 213 if {[catch {WPCmd PEInfo set wp_body_script} src]} { 214 set src index.tcl 215 catch {WPCmd PEInfo set wp_body_script $src} 216 } 217 } 218 fr_view { 219 set src do_view.tcl 220 } 221 quit { 222 set src fr_queryquit.tcl 223 } 224 folders { 225 set src folders.tcl 226 } 227 fldrbrowse { 228 set src fldrbrowse.tcl 229 } 230 fldrsavenew { 231 set src fldrsavenew.tcl 232 } 233 fldrdel { 234 set src fr_querydelfldr.tcl 235 } 236 compose { 237 set src fr_compose.tcl 238 } 239 addrbrowse { 240 set src fr_addrbrowse.tcl 241 } 242 savebrowse { 243 set src fr_fldrbrowse.tcl 244 } 245 savecreate { 246 set src fr_fldrsavenew.tcl 247 } 248 take { 249 set src fr_take.tcl 250 } 251 takeedit { 252 set src fr_takeedit.tcl 253 } 254 takesame { 255 set src fr_takesame.tcl 256 } 257 ldapbrowse { 258 set src fr_ldapbrowse.tcl 259 } 260 addrbook { 261 set src addrbook.tcl 262 } 263 tconfig { 264 set src tconfig.tcl 265 } 266 cledit { 267 set src cledit.tcl 268 } 269 filtedit { 270 set src filtedit.tcl 271 } 272 conf_process { 273 set src conf_process.tcl 274 } 275 resume { 276 set src fr_resume.tcl 277 } 278 spell { 279 set src fr_spellcheck.tcl 280 } 281 auth { 282 set src fr_queryauth.tcl 283 } 284 expunge { 285 set src fr_queryexpunge.tcl 286 } 287 askattach { 288 set src fr_queryattach.tcl 289 } 290 ldapquery { 291 set src fr_ldapquery.tcl 292 } 293 querycreate { 294 set src fr_querycreate.tcl 295 } 296 queryprune { 297 set src fr_queryprune.tcl 298 } 299 attach { 300 set src attach.tcl 301 } 302 dosend { 303 set src dosend.tcl 304 } 305 docancel { 306 set src docancel.tcl 307 } 308 help { 309 set src fr_help.tcl 310 } 311 split { 312 set src fr_split.tcl 313 } 314 default { 315 if {[regexp {.*\.tcl$} $scrpt s]} { 316 set src $scrpt 317 } elseif {[string length $dflt]} { 318 set src $dflt 319 } else { 320 error "Unrecognized script abbreviation: $scrpt" 321 } 322 } 323 } 324 325 return [file join $_wp(cgipath) $_wp(appdir) $_wp(ui1dir) $src] 326} 327 328proc WPTFSaveDefault {{uid 0}} { 329 # "size" rather than "number" to work around temporary alpined bug 330 if {$uid == 0 331 || [catch {WPCmd PEMessage $uid size} n] 332 || $n == 0 333 || [catch {WPCmd PEMessage $uid savedefault} savedefault]} { 334 if {[WPCmd PEFolder isincoming 0]} { 335 set colid 1 336 } else { 337 set colid 0 338 } 339 340 return [list $colid "saved-messages"] 341 } 342 343 return $savedefault 344} 345 346if {$_wp(keybindings)} { 347 proc WPTFKeyEquiv {kl {exclusions {}} {frame window}} { 348 if {[llength $kl] > 0} { 349 WPStdScripts 350 351 append js "function bindListener(o,f)\{" 352 if {[isW3C]} { 353 append js "o.addEventListener('keypress',f, false);\n" 354 set cancelkeystroke "e.preventDefault(); return false;" 355 } elseif {[isIE]} { 356 append js "o.onkeydown = f;\n" 357 set cancelkeystroke "return false;" 358 } else { 359 append js "o.onkeydown = f;" 360 append js "o.captureEvents(Event.KEYDOWN);\n" 361 set cancelkeystroke "return false;" 362 } 363 append js "\}\n" 364 365 append js "function nobubble(e)\{" 366 if {[isW3C]} { 367 append js " e.stopPropagation();" 368 } elseif {[isIE]} { 369 append js " event.cancelBubble = true;" 370 } 371 append js "\}\n" 372 373 append js "function keyed(e)\{" 374 if {[isW3C] && [llength $exclusions]} { 375 set ex "" 376 foreach o $exclusions { 377 if {[string length $ex]} { 378 append ex " || " 379 } 380 381 append ex "e.target == $o" 382 } 383 append js "if (e.target && ($ex)) return true;" 384 } 385 append js " var c = getKeyStr(e);" 386 append js " if(getControlKey(e))\{" 387 append js " switch(c)\{" 388 append js " case 'n' : window.status = 'New window creation disabled in WebPine.' ; $cancelkeystroke" 389 append js " \}" 390 append js " \}" 391 append js " else" 392 append js " switch(c)\{" 393 foreach kb $kl { 394 append js " case '[lindex $kb 0]' : ${frame}.webpinelink = 1; [lindex $kb 1] ; $cancelkeystroke" 395 } 396 397 append js " \}\}\n" 398 399 set onload "bindListener(document,keyed);" 400 401 if {![isW3C]} { 402 foreach o $exclusions { 403 append onload "bindListener($o,nobubble);" 404 } 405 } 406 407 cgi_javascript { 408 cgi_puts $js 409 } 410 411 return $onload 412 } 413 } 414} 415 416# add given folder name to the cache of saved-to folders 417proc WPTFAddSaveCache {f_name} { 418 global _wp 419 420 if {[catch {WPSessionState save_cache} flist] == 0} { 421 if {[set i [lsearch -exact $flist $f_name]] < 0} { 422 set flist [lrange $flist 0 [expr {$_wp(save_cache_max) - 2}]] 423 } else { 424 set flist [lreplace $flist $i $i] 425 } 426 427 set flist [linsert $flist 0 $f_name] 428 } else { 429 set flist [list $f_name] 430 } 431 432 catch {WPSessionState save_cache $flist} 433} 434 435# return the list of cached saved-to folders and make sure given 436# default is somewhere in the list 437proc WPTFGetSaveCache {{def_name ""}} { 438 439 if {![string length $def_name]} { 440 set savedef [WPTFSaveDefault 0] 441 set def_name [lindex $savedef 1] 442 } 443 444 set seen "" 445 446 if {[catch {WPSessionState save_cache} flist] == 0} { 447 foreach f $flist { 448 if {[string compare $def_name $f] == 0} { 449 set def_listed 1 450 } 451 452 if {[string length $f] && [lsearch -exact $seen $f] < 0} { 453 lappend options $f 454 lappend options $f 455 lappend seen $f 456 } 457 } 458 } 459 460 if {!([info exists options] && [info exists def_listed])} { 461 lappend options $def_name 462 lappend options $def_name 463 } 464 465 if {[catch {WPCmd set wp_cache_folder} wp_cache_folder] 466 || [string compare $wp_cache_folder [WPCmd PEMailbox mailboxname]]} { 467 # move default to top on new folder 468 switch -- [set x [lsearch -exact $options $def_name]] { 469 0 { } 470 default { 471 if {$x > 0} { 472 set options [lreplace $options $x [expr {$x + 1}]] 473 } 474 475 set options [linsert $options 0 $def_name] 476 set options [linsert $options 0 $def_name] 477 } 478 } 479 480 catch {WPCmd set wp_cache_folder [WPCmd PEMailbox mailboxname]} 481 } 482 483 lappend options "\[ folder I type in \]" 484 lappend options "__folder__prompt__" 485 486 lappend options "\[ folder in my folder list \]" 487 lappend options "__folder__list__" 488 489 return $options 490} 491 492# add given folder name to the visited folder cache 493proc WPTFAddFolderCache {f_col f_name} { 494 global _wp 495 496 if {$f_col != 0 || [string compare [string tolower $f_name] inbox]} { 497 if {0 == [catch {WPSessionState folder_cache} flist]} { 498 499 if {[catch {WPSessionState left_column_folders} fln]} { 500 set fln $_wp(fldr_cache_def) 501 } 502 503 for {set i 0} {$i < [llength $flist]} {incr i} { 504 set f [lindex $flist $i] 505 if {$f_col == [lindex $f 0] && 0 == [string compare [lindex $f 1] $f_name]} { 506 break 507 } 508 } 509 510 if {$i >= [llength $flist]} { 511 set flist [lrange $flist 0 $fln] 512 } else { 513 set flist [lreplace $flist $i $i] 514 } 515 516 set flist [linsert $flist 0 [list $f_col $f_name]] 517 # let users of data know it's changed (cheaper than hash) 518 WPScriptVersion common 1 519 } else { 520 catch {unset flist} 521 lappend flist [list $f_col $f_name] [list [WPTFSaveDefault 0]] 522 # ditto 523 WPScriptVersion common 1 524 } 525 526 catch {WPSessionState folder_cache $flist} 527 } 528} 529 530# return the list of cached visited folders and make sure given 531# default is somewhere in the list 532proc WPTFGetFolderCache {} { 533 if {[catch {WPSessionState folder_cache} flist]} { 534 catch {unset flist} 535 lappend flist [WPTFSaveDefault 0] 536 catch {WPSessionState folder_cache $flist} 537 } 538 539 return $flist 540} 541 542proc WPExitOnClose {{frame window}} { 543 global _wp 544 545 cgi_script type="text/javascript" language="JavaScript" { 546 cgi_put "function wpLink(){" 547 cgi_put " ${frame}.webpinelink = 1;" 548 cgi_put " return true;" 549 cgi_puts "}" 550 cgi_put "function wpLoad(){" 551 cgi_put " ${frame}.webpinelink = 0;" 552 cgi_puts "}" 553 cgi_put "function wpUnLoad(){" 554 cgi_put " if(!${frame}.webpinelink){" 555 cgi_put " window.open('[cgi_root]/$_wp(appdir)/$_wp(ui1dir)/ripcord.tcl?t=10&cid=[WPCmd PEInfo key]','Depart','width=350,height=200');" 556 cgi_put " }" 557 cgi_puts "}" 558 } 559 560 uplevel 1 { 561 562 # tweak some cgi_* procs for global effect 563 if {0 == [catch {rename cgi_url _wp_orig_cgi_url}]} { 564 proc cgi_url {args} { 565 lappend newargs [lindex $args 0] 566 foreach a [lrange $args 1 end] { 567 if {[regexp "^(onClick)=(.*)" $a dummy attr str]} { 568 set onclicked 1 569 lappend newargs "${attr}=wpLink();${str}" 570 } else { 571 lappend newargs $a 572 } 573 } 574 575 if {![info exists onclicked]} { 576 lappend newargs "onClick=wpLink();" 577 } 578 579 return [eval "_wp_orig_cgi_url $newargs"] 580 } 581 } 582 583 if {0 == [catch {rename cgi_area _wp_orig_cgi_area}]} { 584 proc cgi_area {args} { 585 lappend newargs [lindex $args 0] 586 foreach a [lrange $args 1 end] { 587 if {[regexp "^(onClick)=(.*)" $a dummy attr str]} { 588 set onclicked 1 589 lappend newargs "${attr}=\"wpLink();${str}\"" 590 } else { 591 lappend newargs $a 592 } 593 } 594 595 if {![info exists onclicked]} { 596 lappend newargs "onClick=\"return wpLink();\"" 597 } 598 599 return [eval "_wp_orig_cgi_area $newargs"] 600 } 601 } 602 603 if {0 == [catch {rename cgi_form _wp_orig_cgi_form}]} { 604 proc cgi_form {args} { 605 foreach a [lrange $args 0 [expr [llength $args]-2]] { 606 if {[regexp "^onSubmit=(.*)" $a dummy str]} { 607 set onsubmitted 1 608 lappend newargs "onSubmit=wpLink(); ${str}" 609 } else { 610 lappend newargs $a 611 } 612 } 613 614 if {![info exists onsubmitted]} { 615 lappend newargs "onSubmit=return wpLink();" 616 } 617 618 lappend newargs [lindex $args end] 619 620 uplevel 1 "_wp_orig_cgi_form $newargs" 621 } 622 } 623 } 624} 625 626proc WPTFIndexWidthRatio {fields field} { 627 # should be formula based on total fields 628 # and number of "wider" fields 629 switch [string toupper $field] { 630 TO - 631 FROM - 632 FROMORTO - 633 FROMORTONOTNEWS - 634 RECIPS - 635 SENDER - 636 SUBJECT { return 1.25 } 637 default { return 1 } 638 } 639} 640