diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2016-10-27 19:39:39 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2016-10-27 19:39:39 (GMT) |
commit | ea28451286d3ea4a772fa174483f9a7a66bb1ab3 (patch) | |
tree | 6ee9d8a7848333a7ceeee3b13d492e40225f8b86 /tcllib/examples/nntp/postmsg | |
parent | b5ca09bae0d6a1edce939eea03594dd56383f2c8 (diff) | |
parent | 7c621da28f07e449ad90c387344f07a453927569 (diff) | |
download | blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.zip blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.tar.gz blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.tar.bz2 |
Merge commit '7c621da28f07e449ad90c387344f07a453927569' as 'tcllib'
Diffstat (limited to 'tcllib/examples/nntp/postmsg')
-rwxr-xr-x | tcllib/examples/nntp/postmsg | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/tcllib/examples/nntp/postmsg b/tcllib/examples/nntp/postmsg new file mode 100755 index 0000000..c9f9c9c --- /dev/null +++ b/tcllib/examples/nntp/postmsg @@ -0,0 +1,192 @@ +#!/usr/bin/env tclsh +## -*- tcl -*- + +package require Tcl 8.5 +package require nntp +package require fileutil + +# This application, derived from its sibling 'postnews', takes a +# message file and directly posts it to a given server, and group. All +# other information, like destination group, subject, sender, etc. are +# expected to be in the message itself. This means that the message +# file is expected to have the proper format for a mail/news posting. +# +# Using "-" for the message file causes the command to read the +# message from stdin. + +proc main {} { + if {![cmdline]} usage + checkmessage + postmessage +} + +proc cmdline {} { + global argv newsserver message user password + + if {[lindex $argv 0] eq "-via"} { + if {[llength $argv] != 4} {return 0} + set argv [lassign $argv _ accountfile] + + lassign [split [validatefile {account file} $accountfile] \n] user password + } + + if {[llength $argv] != 2} {return 0} + + # Retrieve arguments + + lassign $argv newsserver messagefile + + # Validate messagefile + if {$messagefile eq "-"} { + set message [read stdin] + } else { + set message [validatefile {message file} $messagefile] + } + return 1 +} + +proc validatefile {which path} { + if {![file exists $path]} { stop "$which does not exist: $path" } + if {![file isfile $path]} { stop "$which not a file: $path" } + if {![file readable $path]} { stop "$which not readable: $path" } + return [fileutil::cat $path] +} + +proc usage {} { + global argv0 + puts stderr "$argv0: wrong # args, should be \"$argv0 ?-via accountfile? server messagefile\"" + exit 1 +} + +proc stop {text} { + global argv0 + puts stderr "$argv0: $text" + exit 1 +} + +proc checkmessage {} { + processmessage + need Newsgroups + need Subject + need From + + add "X-Posting-Engine" "Tcllib nntp/postmsg on Tcl [info patchlevel]" + # Some news-servers handle the adding of the Lines: header itself + #add Lines [llength $body] + add "Content-Type" "text/plain; charset=iso-8859-1" + + regenerate + return +} + +proc processmessage {} { + global message head body + + array set head {} + set body {} + set inBody 0 + set lastheader {} + + foreach line [split $message "\n"] { + if {$inBody} { + lappend body $line + } elseif {[string length $line] == 0} { + set inBody 1 + } elseif {[regexp {^([^ :]+): +(.*)} $line => header value]} { + set header [string tolower $header] + set value [string trim $value] + if {[string length $value]} { + set head($header) "$value " + } + set lastheader $header + } else { + append head($lastheader) "[string trim $line] " + } + } + + return +} + +proc need {header} { + global head + if {[info exist head([string tolower $header])]} return + stop "Required header \"${header}:\" is missing" +} + +# Add the given header to the message to be posted, if not already present. +proc add {header value} { + global head + set header [string tolower $header] + if {[info exist head($header)]} return + set head($header) $value + return +} + +proc regenerate {} { + global message head body + + foreach {header value} [array get head] { + lappend lines "[capitalise $header]: [string trim $value]" + } + lappend lines {} + lappend lines $body + + set message [join $lines \n] + return +} + +proc capitalise {string} { + set result {} + foreach word [split $string "-"] {lappend result [capitalise1 $word]} + join $result "-" +} + +proc capitalise1 {word} { + set c0 [string index $word 0] + set cr [string range $word 1 end] + return [string toupper $c0][string tolower $cr] +} + +proc postmessage {} { + global newsserver message user password + + nntp_cmd 1 {open } {set news [nntp::nntp $newsserver]} + nntp_cmd 1 {mode reader} {$news mode_reader} + + if {[info exists user]} { + nntp_cmd 1 {authinfo } {$news authinfo $user $password} + } + + puts stdout "post [llength [split $message \n]] lines" + + nntp_cmd 0 {post } {$news post $message} + nntp_cmd 1 {quit } {$news quit} + return +} + +proc nntp_cmd {exit title cmd {oktitle {}}} { + global argv0 + + puts -nonewline stdout $title + flush stdout + if {[catch { + set res [uplevel 1 $cmd] + } msg]} { + puts stdout " error: $msg" + #puts stderr "$argv0: nntp error: $msg" + if {$exit} { + exit 1 + } + return 0 + } else { + if {$oktitle != {}} { + puts stdout " $res $oktitle" + } else { + puts stdout " $res" + } + return 1 + } +} + +main +exit |