7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#!/usr/bin/ksh93
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# CDDL HEADER START
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# The contents of this file are subject to the terms of the
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# Common Development and Distribution License (the "License").
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# You may not use this file except in compliance with the License.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# or http://www.opensolaris.org/os/licensing.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# See the License for the specific language governing permissions
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# and limitations under the License.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# When distributing Covered Code, include this CDDL HEADER in each
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# If applicable, add the following below this CDDL HEADER, with the
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# fields enclosed by brackets "[]" replaced with your own identifying
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# information: Portions Copyright [yyyy] [name of copyright owner]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# CDDL HEADER END
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# Make sure all math stuff runs in the "C" locale to avoid problems
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# with alternative # radix point representations (e.g. ',' instead of
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# '.' in de_DE.*-locales). This needs to be set _before_ any
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# floating-point constants are defined in this script).
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinif [[ "${LC_ALL}" != "" ]] ; then
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin export \
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin LC_MONETARY="${LC_ALL}" \
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin LC_MESSAGES="${LC_ALL}" \
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin LC_COLLATE="${LC_ALL}" \
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin LC_CTYPE="${LC_ALL}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin unset LC_ALL
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinfi
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinexport LC_NUMERIC=C
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinfunction fatal_error
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin print -u2 "${progname}: $*"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin exit 1
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinfunction encode_multipart_form_data
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nameref formdata="$1"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nameref content="formdata.content"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin integer numformelements=${#formdata.form[*]}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin integer i
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset tmp
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin content=""
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # todo: add support to upload files
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for (( i=0 ; i < numformelements ; i++ )) ; do
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nameref element="formdata.form[${i}]"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin content+="--${formdata.boundary}\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin content+="Content-Disposition: form-data; name=\"${element.name}\"\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin content+="\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # make sure we quote the '\' properly since we pass these data to one instance of
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # "print" when putting the content on the wire.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin content+="${element.data//\\/\\\\}\n" # fixme: may need encoding for non-ASCII data
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin done
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # we have to de-quote the content before we can count the real numer of bytes in the payload
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin tmp="$(print -- "${content}")"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin formdata.content_length=${#tmp}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # add content tail (which MUST not be added to the content length)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin content+="--${formdata.boundary}--\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return 0
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# parse HTTP return code, cookies etc.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinfunction parse_http_response
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nameref response="$1"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset h statuscode statusmsg i
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # we use '\r' as additional IFS to filter the final '\r'
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin IFS=$' \t\r' read -r h statuscode statusmsg # read HTTP/1.[01] <code>
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin [[ "$h" != ~(Eil)HTTP/.* ]] && { print -u2 -f $"%s: HTTP/ header missing\n" "$0" ; return 1 ; }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin [[ "$statuscode" != ~(Elr)[0-9]* ]] && { print -u2 -f $"%s: invalid status code\n" "$0" ; return 1 ; }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin response.statuscode="$statuscode"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin response.statusmsg="$statusmsg"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # skip remaining headers
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin while IFS='' read -r i ; do
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin [[ "$i" == $'\r' ]] && break
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # strip '\r' at the end
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin i="${i/~(Er)$'\r'/}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin case "$i" in
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ~(Eli)Content-Type:.*)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin response.content_type="${i/~(El).*:[[:blank:]]*/}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ;;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ~(Eli)Content-Length:[[:blank:]]*[0-9]*)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin integer response.content_length="${i/~(El).*:[[:blank:]]*/}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ;;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ~(Eli)Transfer-Encoding:.*)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin response.transfer_encoding="${i/~(El).*:[[:blank:]]*/}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ;;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin esac
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin done
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return 0
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinfunction cat_http_body
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset emode="$1"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset hexchunksize="0"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin integer chunksize=0
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if [[ "${emode}" == "chunked" ]] ; then
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin while IFS=$'\r' read hexchunksize &&
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner [[ "${hexchunksize}" == ~(Elri)[0-9abcdef]+ ]] &&
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner (( chunksize=$( printf "16#%s\n" "${hexchunksize}" ) )) && (( chunksize > 0 )) ; do
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin dd bs=1 count="${chunksize}" 2>/dev/null
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin done
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin cat
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin fi
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return 0
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinfunction history_write_record
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # rec: history record:
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # rec.title
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # rec.description
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # rec.provider
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # rec.providertoken
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # rec.url
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin nameref rec="$1"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin integer histfd
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mkdir -p "${HOME}/.shnote"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # write a single-line record which can be read
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # as a compound variable back into the shell
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin printf "title=%q description=%q date=%q provider=%q providertoken=%q url=%q\n" \
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "${rec.title}" \
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "${rec.description}" \
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "$(date)" \
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "${rec.provider}" \
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "${rec.providertoken}" \
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "${rec.url}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin } >>"${history_file}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return $?
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinfunction print_history
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin integer histfd # http stream number
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset line
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin (( $# != 0 && $# != 1 )) && { print -u2 -f $"%s: Wrong number of arguments.\n" "$0" ; return 1 ; }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # default output format is:
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # <access url>/<title> <date> <access url>
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin [[ "$1" == "-l" ]] || printf "# %s\t\t\t\t\t%s\t%s\n" "<url>" "<title>" "<date>"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # no history file ?
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if [[ ! -f "${history_file}" ]] ; then
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return 0
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin fi
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # open history file
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz redirect {histfd}<> "${history_file}"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( $? != 0 )) && { print -u2 "Could not open history file." ; return 1 ; }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin while read -u${histfd} line ; do
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz compound rec
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin printf "( %s )\n" "${line}" | read -C rec
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if [[ "$1" == "-l" ]] ; then
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin print -- "${rec}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin printf "%q\t%q\t%q\n" "${rec.url}" "${rec.title}" "${rec.date}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin fi
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin unset rec
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin done
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # close history file
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin redirect {histfd}<&-
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return 0
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinfunction put_note_pastebin_ca
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # key to autheticate this script against pastebin.ca
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset -r pastebin_ca_key="9CFXFyeNC3iga/vthok75kTBu5kSSLPD"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # site setup
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset url_host="opensolaris.pastebin.ca"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset url_path="/quiet-paste.php?api=${pastebin_ca_key}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset url="http://${url_host}${url_path}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin integer netfd # http stream number
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz compound httpresponse
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin (( $# != 1 )) && { print -u2 -f $"%s: Wrong number of arguments.\n" "$0" ; return 1 ; }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin (( ${#1} == 0 )) && { print -u2 -f $"%s: No data.\n" "$0" ; return 1 ; }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # argument for "encode_multipart_form_data"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz compound mimeform=(
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # input
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset boundary
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset -a form
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # output
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset content
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin integer content_length
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin )
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset request=""
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset content=""
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset -r boundary="--------shnote_${RANDOM}_Xfish_${RANDOM}_Yeats_${RANDOM}_Zchicken_${RANDOM}monster_--------"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mimeform.boundary="${boundary}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin mimeform.form=( # we use explicit index numbers since we rely on them below when filling the history
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin [0]=( name="name" data="${LOGNAME}" )
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin [1]=( name="expiry" data="Never" )
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin [2]=( name="type" data="1" )
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin [3]=( name="description" data="logname=${LOGNAME};hostname=$(hostname);date=$(date)" )
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin [4]=( name="content" data="$1" )
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin )
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin encode_multipart_form_data mimeform
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin content="${mimeform.content}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin request="POST ${url_path} HTTP/1.1\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin request+="Host: ${url_host}\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin request+="User-Agent: ${http_user_agent}\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin request+="Connection: close\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin request+="Content-Type: multipart/form-data; boundary=${boundary}\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin request+="Content-Length: $(( mimeform.content_length ))\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz redirect {netfd}<> "/dev/tcp/${url_host}/80"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( $? != 0 )) && { print -u2 -f $"%s: Could not open connection to %s.\n" "$0" "${url_host}" ; return 1 ; }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # send http post
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin print -n -- "${request}\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin print -n -- "${content}\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin } >&${netfd}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # process reply
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin parse_http_response httpresponse <&${netfd}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin response="$(cat_http_body "${httpresponse.transfer_encoding}" <&${netfd})"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # close connection
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin redirect {netfd}<&-
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if [[ "${response}" == ~(E).*SUCCESS.* ]] ; then
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset response_token="${response/~(E).*SUCCESS:/}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin printf "SUCCESS: http://opensolaris.pastebin.ca/%s\n" "${response_token}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # write history entry
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz compound histrec=(
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin title="${mimeform.form[0].data}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin description="${mimeform.form[3].data}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin providertoken="${response_token}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin provider="opensolaris.pastebin.ca"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin url="http://opensolaris.pastebin.ca/${response_token}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin )
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin history_write_record histrec
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return 0
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin printf "ERROR: %s\n" "${response}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return 1
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin fi
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # not reached
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinfunction get_note_pastebin_ca
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset recordname="$1"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin integer netfd # http stream number
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin (( $# != 1 )) && { print -u2 -f $"%s: No key or key URL.\n" "$0" ; return 1 ; }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin case "${recordname}" in
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ~(Elr)[0-9][0-9]*)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # pass-through
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ;;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ~(Elr)http://opensolaris.pastebin.ca/raw/[0-9]*)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin recordname="${recordname/~(El)http:\/\/opensolaris.pastebin.ca\/raw\//}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ;;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ~(Elr)http://opensolaris.pastebin.ca/[0-9]*)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin recordname="${recordname/~(El)http:\/\/opensolaris.pastebin.ca\//}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin ;;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin *)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin fatal_error $"Unsupported record name ${recordname}."
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin esac
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin print -u2 -f "# Record name is '%s'\n" "${recordname}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset url_host="opensolaris.pastebin.ca"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset url_path="/raw/${recordname}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin typeset url="http://${url_host}${url_path}"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # I hereby curse Solaris for not having an entry for "http" in /etc/services
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # open TCP channel
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz redirect {netfd}<> "/dev/tcp/${url_host}/80"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz (( $? != 0 )) && { print -u2 -f $"%s: Could not open connection to %s.\n" "$0" "${url_host}" ; return 1 ; }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # send HTTP request
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin request="GET ${url_path} HTTP/1.1\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin request+="Host: ${url_host}\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin request+="User-Agent: ${http_user_agent}\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin request+="Connection: close\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin print -u${netfd} -- "${request}\r\n"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # collect response and send it to stdout
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin parse_http_response httpresponse <&${netfd}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin cat_http_body "${httpresponse.transfer_encoding}" <&${netfd}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin # close connection
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin redirect {netfd}<&-
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin print # add newline
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return 0
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinfunction usage
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin{
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin OPTIND=0
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin getopts -a "${progname}" "${USAGE}" OPT '-?'
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin exit 2
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin}
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# program start
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinbuiltin basename
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinbuiltin cat
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinbuiltin date
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinbuiltin uname
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chintypeset progname="${ basename "${0}" ; }"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# HTTP protocol client identifer
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulknertypeset -r http_user_agent="shnote/ksh93 (2010-03-27; $(uname -s -r -p))"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# name of history log (the number after "history" is some kind of version
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# counter to handle incompatible changes to the history file format)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chintypeset -r history_file="${HOME}/.shnote/history0.txt"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chintypeset -r shnote_usage=$'+
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner[-?\n@(#)\$Id: shnote (Roland Mainz) 2010-03-27 \$\n]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin[-author?Roland Mainz <roland.mainz@nrubsig.org>]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin[+NAME?shnote - read/write text data to internet clipboards]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin[+DESCRIPTION?\bshnote\b is a small utilty which can read and write text
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin data to internet "clipboards" such as opensolaris.pastebin.ca.]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin[+?The first arg \bmethod\b describes one of the methods, "put" saves a string
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin to the internet clipboard, returning an identifer and the full URL
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin where the data are stored. The method "get" retrives the raw
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin information using the identifer from the previous "put" action.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin The method "hist" prints a history of transactions created with the
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin "put" method and the keys to retrive them again using the "get" method.]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin[+?The second arg \bstring\b contains either the string data which should be
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin stored on the clipboard using the "put" method, the "get" method uses
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin this information as identifer to retrive the raw data from the
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin clipboard.]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinmethod [ string ]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin[+SEE ALSO?\bksh93\b(1), \brssread\b(1), \bshtwitter\b(1), \bshtinyurl\b(1), http://opensolaris.pastebin.ca]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin'
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinwhile getopts -a "${progname}" "${shnote_usage}" OPT ; do
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin case ${OPT} in
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin *) usage ;;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin esac
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chindone
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinshift $((OPTIND-1))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# expecting at least one more argument, the single method below will do
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# the checks for more arguments if needed ("put" and "get" methods need
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# at least one extra argument, "hist" none).
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin(($# >= 1)) || usage
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chintypeset method="$1"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinshift
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chincase "${method}" in
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin put) put_note_pastebin_ca "$@" ; exit $? ;;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin get) get_note_pastebin_ca "$@" ; exit $? ;;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin hist) print_history "$@" ; exit $? ;;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin *) usage ;;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinesac
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinfatal_error $"not reached."
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin# EOF.