#!/usr/local/bin/tclsh8.6 package require sqlite3 set dbfile ./paste.db sqlite3 db $dbfile namespace eval scgi { proc listen {host port} { socket -server [namespace code connect] -myaddr $host $port } proc connect {sock ip port} { fconfigure $sock -blocking 0 -translation {binary binary} fileevent $sock readable [namespace code [list read_length $sock {}]] } proc read_length {sock data} { append data [read $sock] if {[eof $sock]} { close $sock return } set colonIdx [string first : $data] if {$colonIdx == -1} { # we don't have the headers length yet fileevent $sock readable [namespace code [list read_length $sock $data]] return } else { set length [string range $data 0 $colonIdx-1] set data [string range $data $colonIdx+1 end] read_headers $sock $length $data } } proc read_headers {sock length data} { append data [read $sock] if {[string length $data] < $length+1} { # we don't have the complete headers yet, wait for more fileevent $sock readable [namespace code [list read_headers $sock $length $data]] return } else { set headers [string range $data 0 $length-1] set headers [lrange [split $headers \0] 0 end-1] set body [string range $data $length+1 end] set content_length [dict get $headers CONTENT_LENGTH] read_body $sock $headers $content_length $body } } proc read_body {sock headers content_length body} { append body [read $sock] if {[string length $body] < $content_length} { # we don't have the complete body yet, wait for more fileevent $sock readable [namespace code [list read_body $sock $headers $content_length $body]] return } else { handle_request $sock $headers $body } } } proc handle_request {sock headers body} { array set Headers $headers set request $Headers(REQUEST_URI) switch -- $request { / {pastie_root $sock; return} /stats {pastie_stats $sock; return} } if {[regexp {^/([0-9]+)$} $request -> paste]} { db eval {select value from paste where rowid = :paste} v {} if {[info exists v(value)]} { puts $sock "Status: 200 OK\r" puts $sock "Content-Type: text/plain\r" puts $sock "Content-Length: [string length $v(value)]\r" puts $sock "\r" puts -nonewline $sock $v(value) } else { puts $sock "Status: 404 Paste Not Found\r" puts $sock "Content-Type: text/plain\r" puts $sock "\r" puts $sock "Paste Not Found\r" } } else { puts $sock "Status: 400 Bad Request Syntax\r" puts $sock "Content-Type: text/plain\r" puts $sock "\r" puts $sock "Bad Request Syntax\r" } close $sock } proc pastie_root {sock} { puts $sock \ "Status: 200 OK\r Content-Type: text/html\r \r
paste.wooledge.org Submissions are read on TCP port 9999 and stored for one week. Size limit is 32 kilobytes. Examples: $ nc paste.wooledge.org 9999 < myfile $ some unix command 2>&1 | nc paste.wooledge.org 9999" close $sock } proc pastie_stats {sock} { db eval {select count(*) as count from paste} v {} set html "
Paste | Length | " append html "Submitted | Expires |
---|---|---|---|
$v(rowid) | " append html "$v(length) | " append html "[clock format $submit -format {%Y-%m-%d %H:%M:%S}]" append html " | " append html "[clock format $v(expire) -format {%Y-%m-%d %H:%M:%S}]" append html " |
There are $v(count) pastes currently stored. Here are the 10 most recent:
$html " close $sock } scgi::listen localhost 9997 vwait forever