X-Git-Url: http://pileus.org/git/?p=vpaste;a=blobdiff_plain;f=index.cgi;h=09e5c985d394b6307e4dc22c5c8350195e3aa603;hp=f1b8b15c0a99533fa6fcc59dde43912448c9f1ed;hb=HEAD;hpb=48424c1f3911da6d417e3190623d68ee041daba7 diff --git a/index.cgi b/index.cgi index f1b8b15..09e5c98 100755 --- a/index.cgi +++ b/index.cgi @@ -1,12 +1,12 @@ #!/bin/bash -# Copyright (C) 2009-2011 Andy Spencer -# +# Copyright (C) 2009-2013 Andy Spencer +# # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU Affero General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. -# +# # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more @@ -14,16 +14,17 @@ # Remove url codings from stdin function get_modeline { - modeline=$( - echo "$QUERY_STRING" | - sed -e 's/%\([0-9A-F][0-9A-F]\)/\\\\\x\1/g; s/[,&]/ /g' | - xargs echo -e - ) - echo "vim: $modeline" + echo "$QUERY_STRING" | + sed -e 's/%\([0-9A-F][0-9A-F]\)/\\\\\x\1/g' \ + -e 's/[^a-zA-Z0-9.:=_\-]/ /g' | + xargs echo -e +} +function get_param { + get_modeline | awk -v "key=$1" 'BEGIN{RS=" "; FS="="}; $1 ~ key {print $2}' } # Extract an uploaded file from standard input -# $2 is the name of the input to extract +# $1 is the name of the input to extract function cut_file { bnd="${CONTENT_TYPE/*boundary\=/}" awk -v "want=$1" -v "bnd=$bnd" ' @@ -44,28 +45,142 @@ function cut_file { ' | head -c $((128*1024)) # Limit size to 128K } -# Print out a generic header -function header { - echo "Content-Type: $1; charset=UTF-8" +# Respond to a request +function respond { + local allow ctype heads files texts gzip h f + while [ "$1" ]; do + case $1 in + -y) allow="true"; ;; + -c) ctype="$2"; shift ;; + -h) heads=("${heads[@]}" "$2"); shift ;; + -f) files=("${files[@]}" "$2"); shift ;; + *) texts=("${texts[@]}" "$1"); ;; + esac + shift + done + + # Check if the browser supports gzip + if [[ "$HTTP_ACCEPT_ENCODING" == *'gzip'* ]]; then + gzip=true + fi + + # Output header + if [ "$ctype" ]; then + echo "Content-Type: $ctype; charset=UTF-8" + else + echo "Content-Type: text/plain; charset=UTF-8" + fi + if [ "$gzip" ]; then + echo "Content-Encoding: gzip" + fi + if [ "$allow" ]; then + echo "Access-Control-Allow-Origin: *" + echo "Access-Control-Allow-Headers: Content-Type" + fi + for h in "${heads[@]}"; do + echo "$h" + done echo + + # Output text messages + if [ "$texts" ]; then + if [ "$gzip" ]; then + echo "${texts[@]}" | gzip + else + echo "${texts[@]}" + fi + exit + fi + + # Output body files + if [ "$files" ]; then + for f in "${files[@]}"; do + if [[ "$gzip" && "$f" != *'.gz' ]]; then + gzip < "$f" + elif [[ ! "$gzip" && "$f" == *'.gz' ]]; then + zcat < "$f" + else + cat "$f" + fi + done + exit + fi + + # Gzip remaining stream + if [ "$gzip" ]; then + exec 1> >(gzip) + fi +} + +# Format and output a file +function format { + # Create a temp file with the provided modeline + tmp="$(mktemp)" + sed -e "1ivim: $(get_modeline)" \ + -e "\$avim: $(get_modeline)" "$1" > "$tmp" + + # Determine cache name + md5="$(cat index.cgi vimrc "$tmp" /usr/bin/ex | md5sum -b)" + out="cache/${md5% *}.htm" + zip="$out.gz" + + # Cache the file, if needed + if [ ! -f "$zip" ]; then + # - I have some plugins in ~/.vim + # - Run ex in pty to trick it into thinking that it + # has a real terminal, note that we also have to set + # term=xterm-256color in vimrc + HOME=/home/andy \ + /home/vpaste/bin/pty \ + /usr/bin/ex -nXZ -i NONE -u vimrc \ + '+sil! set fde= fdt= fex= inde= inex= key= pa= pexpr=' \ + '+sil! set iconstring= ruf= stl= tal=' \ + "+sil! set titlestring=$1\ -\ vpaste.net" \ + '+sil! set noml' \ + '+sil! 1d|$d|'$2 \ + '+sil! %s/\r//g' \ + '+sil! TOhtml' \ + "+sav! $out" \ + '+qall!' \ + "$tmp" >/dev/null 2>&1 + gzip "$out" + fi + rm "$tmp" + + # Output the file + respond -y -c "text/html" -f "$zip" } # List previous pastes function do_cmd { -header text/plain -case "$1" in -head) - for i in $(ls -t db/*); do - basename $i - basename $i | sed 's/./-/g' - sed '1,/^$/d; /^\s*$/d' $i | sed -n '1,5s/\(.\{0,60\}\).*/\1/p' - echo - done - ;; -ls) - ls -t db | column - ;; -esac + respond + case "$1" in + ls) + ls -t db | column + ;; + head) + awk -v 'rows=4' -v 'cols=60' ' + FNR==1 { gsub(/.*\//, "", FILENAME); + print FILENAME + print "-----" } + FNR==1,/^$/ { next } + /\S/ { i++; printf "%."cols"s\n", $0 } + i>=rows { nextfile } + ENDFILE { i=0; print "" } + ' $(ls -t db/*) + ;; + stat) + ls -l --time-style='+%Y %m' db | + awk -v 'hdr=Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec' ' + BEGIN { printf "%64s\n", hdr } + NR>1 { cnt[$6+0][$7+0]++ } + END { for (y in cnt) { + printf "%4d", y + for (m=1; m<=12; m++) + printf "%5s", cnt[y][m] + printf "\n" } }' + ;; + esac } # Format a file for viewing @@ -76,204 +191,276 @@ function do_print { input="db/$1" trim='1,/^$/d' # sed command to remove cruft else - echo "Status: 404 Not Found" - header text/plain - echo "File '$1' not found" - return + respond -h 'Status: 404 Not Found' \ + "File '$1' not found" fi + # Check for javascript + if [[ "$input" == 'embed.js' && + "$HTTP_ACCEPT" != *'html'* ]]; then + respond -c text/javascript -f "$input" + fi - if [[ "$REQUEST_URI" == *'?'* ]]; then - # Create a temp file with the provided modeline - output="$(mktemp)" - tmp="$(mktemp)" - sed "\$a$(get_modeline)" "$input" > "$tmp" - - # - I have some plugins in ~/.vim - # - Run ex in screen to trick it into thinking that it - # has a real terminal, note that we also have to set - # term=xterm-256color in vimrc - HOME=/home/andy \ - screen -D -m ex -nXZ -i NONE -u vimrc \ - '+sil! set fde= fdt= fex= inde= inex= key= pa= pexpr=' \ - '+sil! set iconstring= ruf= stl= tal=' \ - "+sil! set titlestring=$1\ -\ vpaste.net" \ - '+sil! set noml' \ - '+sil! $d|'$trim \ - '+sil! %s/\r//g' \ - '+sil! TOhtml' \ - "+sav! $output" \ - '+qall!' \ - "$tmp" - - header text/html - cat "$output" - rm "$tmp" "$output" - else - header text/plain + # Check for raw paste + if [[ "$QUERY_STRING" == 'raw'* || + "$REQUEST_URI" != *'?'* && + ( "$input" != 'db/'* || + "$HTTP_ACCEPT" != *'html'* ) ]]; then + respond sed "$trim" "$input" + exit fi + + # Output the file + format "$input" "$trim" } +# Format a file for viewing +function do_view { + format - +} # Upload handler function do_upload { body=$(cat -) spam=$(echo -n "$body" | cut_file "ignoreme") text=$(echo -n "$body" | cut_file "(text|x)") - if [ ! -z "$spam" ]; then - header text/plain - echo "Spam check.." - exit - fi - if [ -z "$text" ]; then - header text/plain - echo "No text pasted" - exit - fi + bans=$(echo -n "$REMOTE_ADDR" | grep -f blacklist) + + [ ! -z "$spam" ] && respond -h "Status: 403 Forbidden" "Spam check.." + [ ! -z "$bans" ] && respond -h "Status: 403 Forbidden" "You have been banned" + [ -z "$text" ] && respond "No text pasted" + + # Format and save message output="$(mktemp db/XXXXX)" - uri="$url$(basename "$output")${QUERY_STRING:+"?"}" - - # Format, spam check, and save message - ( - get_modeline - echo "Date: $(date -R)" - echo "From: $REMOTE_ADDR" - echo - echo "$text" - ) | HOME=/home/vpaste spamc -E > "$output" - - # Test for spam - if [ "$?" -ne 0 ]; then - # Report spam - header text/plain - echo "Your post has been marked as spam!" - echo "Spam test results are as folllows.. " - echo - cat "$output" - mv "$output" spam - else - # Redirect user - echo "Status: 302 Found" - echo "Location: $uri" - header text/plain - echo "$uri" - fi + cat >"$output" <<-EOF + vim: $(get_modeline) + Date: $(date -R) + From: $REMOTE_ADDR + User-Agent: $HTTP_USER_AGENT + + $text + EOF + + # Redirect user + uri="$url$(basename "$output")" + respond -h 'Status: 302 Found' \ + -h "Location: $uri" \ + "$uri" } # Default index page function do_help { -filetypes=$( - ls /usr/share/vim/vim*/syntax/ /home/andy/.vim/syntax/ | - sed -n '/^\(syntax\|manual\|synload\|2html\|colortest\|hitest\).vim$/d; s/.vim$//p' | - sort | uniq -) -uploads=$(ls -t db | head -n 5) - -header text/html -cat - < - - - vpaste.net - Vim based pastebin - - - - - - -
-
- - - - -
-
- -

NAME

-

vpaste: Vim based pastebin

- -

SYNOPSIS

-
-
 vpaste file [option=value,..]
-
 <command> | vpaste [option=value,..]
-
-
 <command> | curl -F 'text=<-' $url[?option=value,..]
-
-
 :map vp :exec "w !vpaste ft=".&ft<CR>
-
 :vmap vp <ESC>:exec "'<,'>w !vpaste ft=".&ft<CR>
-
- -

DESCRIPTION

-

Add ?[option[=value],..] to make your text a rainbow.

-

Options specified when uploading are used as defaults.

- -

OPTIONS

-
-
ft, filetype={filetype}
-
A filetype to use for highlighting, see above menu for supported types
-
bg, background={light|dark}
-
Background color to use for the page
-
et, expandtab
-
Expand tabs to spaces
-
ts, tabstop=[N]
-
Number of spaces to use for tabs when et is set
-
...
-
See :help modeline for more information
-
- -

BUGS

- - -

SOURCE

- - -

LATEST UPLOADS

- -

list all

-

sample all

- - -EOF + filetypes=$( + ls /usr/share/vim/vim*/syntax/ /home/andy/.vim/syntax/ | + sed -n '/^\(syntax\|manual\|synload\|2html\|colortest\|hitest\).vim$/d; s/.vim$//p' | + sort | uniq + ) + uploads=$(ls -t db 2>/dev/null | head -n 5) + filetype=$(get_param '^(ft|filet(y(pe?)?)?)$') + vpaste='vpaste' + pileus='http://pileus.org/tools/vpaste' + gitweb='http://pileus.org/git/?p=vpaste' + mailman='http://pileus.org/mailman/listinfo/dev' + repo='git://pileus.org/vpaste' + + respond -c text/html + cat <<-EOF + + + + vpaste.net - Vim based pastebin + + + + + + + + + + + + +
+
+ + +
+
+ + +
+ +
+ +
+

Pasting

+
+
From a shell
+
$vpaste file [option=value,..]
+
<command> | $vpaste [option=value,..]
+ +
From Vim
+
:map vp :exec "w !vpaste ft=".&ft<CR>
+
:vmap vp <ESC>:exec "'<,'>w !vpaste ft=".&ft<CR>
+ +
With curl
+
<command> | curl -F 'text=<-' $url[?option=value,..]
+
+ +

Options

+

Add ?option[=value],.. to make your text a rainbow.

+

Options specified when uploading are saved as defaults.

+ +
+
bg, background={light|dark}
+
Background color to use for the page
+
et, expandtab
+
Expand tabs to spaces
+
fdm, foldmethod=(syntax|indent)
+
Turn on dynamic code folding
+
ft, filetype={filetype}
+
A filetype to use for highlighting, see above menu for supported types
+
nu, number
+
Add line numbers
+
ts, tabstop=[N]
+
Number of spaces to use for tabs when et is set
+
...
+
See :help modeline for more information
+
+
+ +
+

License

+

Copyright © 2009-2013 + Andy Spencer <andy753421@gmail.com>

+

See individual files for licenses

+ +

Source code

+
+
Client
+
vpaste + embed.js
+
Server
+
index.cgi + vimrc + htaccess + robots.txt + sitemap.xml + blacklist
+
Patches
+
2html.patch
+
Development
+
homepage + gitweb
+ git clone $repo
+
+ +

Bugs

+ +
+ +
+

Recent Uploads

+ +

list all

+

sample all

+

statistics

+
+ + + EOF } # Main +PATH=/bin:/usr/bin url="http://$HTTP_HOST${REQUEST_URI/\?*}" pathinfo="${REQUEST_URI/*\/}" pathinfo="${pathinfo/\?*}" @@ -282,6 +469,10 @@ if [ "$pathinfo" = ls ]; then do_cmd ls elif [ "$pathinfo" = head ]; then do_cmd head +elif [ "$pathinfo" = stat ]; then + do_cmd stat +elif [ "$pathinfo" = view ]; then + do_view elif [ "$pathinfo" ]; then do_print "$pathinfo" elif [ "$CONTENT_TYPE" ]; then