1*906afcb8SAndy Fiddaman#!/usr/bin/ksh93 2*906afcb8SAndy Fiddaman 3*906afcb8SAndy Fiddaman# 4*906afcb8SAndy Fiddaman# CDDL HEADER START 5*906afcb8SAndy Fiddaman# 6*906afcb8SAndy Fiddaman# The contents of this file are subject to the terms of the 7*906afcb8SAndy Fiddaman# Common Development and Distribution License (the "License"). 8*906afcb8SAndy Fiddaman# You may not use this file except in compliance with the License. 9*906afcb8SAndy Fiddaman# 10*906afcb8SAndy Fiddaman# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11*906afcb8SAndy Fiddaman# or http://www.opensolaris.org/os/licensing. 12*906afcb8SAndy Fiddaman# See the License for the specific language governing permissions 13*906afcb8SAndy Fiddaman# and limitations under the License. 14*906afcb8SAndy Fiddaman# 15*906afcb8SAndy Fiddaman# When distributing Covered Code, include this CDDL HEADER in each 16*906afcb8SAndy Fiddaman# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17*906afcb8SAndy Fiddaman# If applicable, add the following below this CDDL HEADER, with the 18*906afcb8SAndy Fiddaman# fields enclosed by brackets "[]" replaced with your own identifying 19*906afcb8SAndy Fiddaman# information: Portions Copyright [yyyy] [name of copyright owner] 20*906afcb8SAndy Fiddaman# 21*906afcb8SAndy Fiddaman# CDDL HEADER END 22*906afcb8SAndy Fiddaman# 23*906afcb8SAndy Fiddaman 24*906afcb8SAndy Fiddaman# 25*906afcb8SAndy Fiddaman# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 26*906afcb8SAndy Fiddaman# 27*906afcb8SAndy Fiddaman 28*906afcb8SAndy Fiddaman# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant 29*906afcb8SAndy Fiddamanexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin 30*906afcb8SAndy Fiddaman 31*906afcb8SAndy Fiddaman# Make sure all math stuff runs in the "C" locale to avoid problems 32*906afcb8SAndy Fiddaman# with alternative # radix point representations (e.g. ',' instead of 33*906afcb8SAndy Fiddaman# '.' in de_DE.*-locales). This needs to be set _before_ any 34*906afcb8SAndy Fiddaman# floating-point constants are defined in this script). 35*906afcb8SAndy Fiddamanif [[ "${LC_ALL}" != "" ]] ; then 36*906afcb8SAndy Fiddaman export \ 37*906afcb8SAndy Fiddaman LC_MONETARY="${LC_ALL}" \ 38*906afcb8SAndy Fiddaman LC_MESSAGES="${LC_ALL}" \ 39*906afcb8SAndy Fiddaman LC_COLLATE="${LC_ALL}" \ 40*906afcb8SAndy Fiddaman LC_CTYPE="${LC_ALL}" 41*906afcb8SAndy Fiddaman unset LC_ALL 42*906afcb8SAndy Fiddamanfi 43*906afcb8SAndy Fiddamanexport LC_NUMERIC=C 44*906afcb8SAndy Fiddaman 45*906afcb8SAndy Fiddamanfunction fatal_error 46*906afcb8SAndy Fiddaman{ 47*906afcb8SAndy Fiddaman print -u2 "${progname}: $*" 48*906afcb8SAndy Fiddaman exit 1 49*906afcb8SAndy Fiddaman} 50*906afcb8SAndy Fiddaman 51*906afcb8SAndy Fiddaman# parse HTTP return code, cookies etc. 52*906afcb8SAndy Fiddamanfunction parse_http_response 53*906afcb8SAndy Fiddaman{ 54*906afcb8SAndy Fiddaman nameref response="$1" 55*906afcb8SAndy Fiddaman typeset h statuscode statusmsg i 56*906afcb8SAndy Fiddaman 57*906afcb8SAndy Fiddaman # we use '\r' as additional IFS to filter the final '\r' 58*906afcb8SAndy Fiddaman IFS=$' \t\r' read -r h statuscode statusmsg # read HTTP/1.[01] <code> 59*906afcb8SAndy Fiddaman [[ "$h" != ~(Eil)HTTP/.* ]] && { print -u2 -f $"%s: HTTP/ header missing\n" "$0" ; return 1 ; } 60*906afcb8SAndy Fiddaman [[ "$statuscode" != ~(Elr)[0-9]* ]] && { print -u2 -f $"%s: invalid status code\n" "$0" ; return 1 ; } 61*906afcb8SAndy Fiddaman response.statuscode="$statuscode" 62*906afcb8SAndy Fiddaman response.statusmsg="$statusmsg" 63*906afcb8SAndy Fiddaman 64*906afcb8SAndy Fiddaman # skip remaining headers 65*906afcb8SAndy Fiddaman while IFS='' read -r i ; do 66*906afcb8SAndy Fiddaman [[ "$i" == $'\r' ]] && break 67*906afcb8SAndy Fiddaman 68*906afcb8SAndy Fiddaman # strip '\r' at the end 69*906afcb8SAndy Fiddaman i="${i/~(Er)$'\r'/}" 70*906afcb8SAndy Fiddaman 71*906afcb8SAndy Fiddaman case "$i" in 72*906afcb8SAndy Fiddaman ~(Eli)Content-Type:.*) 73*906afcb8SAndy Fiddaman response.content_type="${i/~(El).*:[[:blank:]]*/}" 74*906afcb8SAndy Fiddaman ;; 75*906afcb8SAndy Fiddaman ~(Eli)Content-Length:[[:blank:]]*[0-9]*) 76*906afcb8SAndy Fiddaman integer response.content_length="${i/~(El).*:[[:blank:]]*/}" 77*906afcb8SAndy Fiddaman ;; 78*906afcb8SAndy Fiddaman ~(Eli)Transfer-Encoding:.*) 79*906afcb8SAndy Fiddaman response.transfer_encoding="${i/~(El).*:[[:blank:]]*/}" 80*906afcb8SAndy Fiddaman ;; 81*906afcb8SAndy Fiddaman esac 82*906afcb8SAndy Fiddaman done 83*906afcb8SAndy Fiddaman 84*906afcb8SAndy Fiddaman return 0 85*906afcb8SAndy Fiddaman} 86*906afcb8SAndy Fiddaman 87*906afcb8SAndy Fiddamanfunction cat_http_body 88*906afcb8SAndy Fiddaman{ 89*906afcb8SAndy Fiddaman typeset emode="$1" 90*906afcb8SAndy Fiddaman typeset hexchunksize="0" 91*906afcb8SAndy Fiddaman integer chunksize=0 92*906afcb8SAndy Fiddaman 93*906afcb8SAndy Fiddaman if [[ "${emode}" == "chunked" ]] ; then 94*906afcb8SAndy Fiddaman while IFS=$'\r' read hexchunksize && 95*906afcb8SAndy Fiddaman [[ "${hexchunksize}" == ~(Elri)[0-9abcdef]+ ]] && 96*906afcb8SAndy Fiddaman (( chunksize=$( printf "16#%s\n" "${hexchunksize}" ) )) && (( chunksize > 0 )) ; do 97*906afcb8SAndy Fiddaman dd bs=1 count="${chunksize}" 2>/dev/null 98*906afcb8SAndy Fiddaman done 99*906afcb8SAndy Fiddaman else 100*906afcb8SAndy Fiddaman cat 101*906afcb8SAndy Fiddaman fi 102*906afcb8SAndy Fiddaman 103*906afcb8SAndy Fiddaman return 0 104*906afcb8SAndy Fiddaman} 105*906afcb8SAndy Fiddaman 106*906afcb8SAndy Fiddamanfunction request_tinyurl 107*906afcb8SAndy Fiddaman{ 108*906afcb8SAndy Fiddaman # site setup 109*906afcb8SAndy Fiddaman typeset url_host="tinyurl.com" 110*906afcb8SAndy Fiddaman typeset url_path="/api-create.php" 111*906afcb8SAndy Fiddaman typeset url="http://${url_host}${url_path}" 112*906afcb8SAndy Fiddaman integer netfd # http stream number 113*906afcb8SAndy Fiddaman typeset inputurl="$1" 114*906afcb8SAndy Fiddaman compound httpresponse # http response 115*906afcb8SAndy Fiddaman typeset request="" 116*906afcb8SAndy Fiddaman 117*906afcb8SAndy Fiddaman # we assume "inputurl" is a correctly encoded URL which doesn't 118*906afcb8SAndy Fiddaman # require any further mangling 119*906afcb8SAndy Fiddaman url_path+="?url=${inputurl}" 120*906afcb8SAndy Fiddaman 121*906afcb8SAndy Fiddaman request="GET ${url_path} HTTP/1.1\r\n" 122*906afcb8SAndy Fiddaman request+="Host: ${url_host}\r\n" 123*906afcb8SAndy Fiddaman request+="User-Agent: ${http_user_agent}\r\n" 124*906afcb8SAndy Fiddaman request+="Connection: close\r\n" 125*906afcb8SAndy Fiddaman 126*906afcb8SAndy Fiddaman redirect {netfd}<> "/dev/tcp/${url_host}/80" 127*906afcb8SAndy Fiddaman (( $? != 0 )) && { print -u2 -f $"%s: Could not open connection to %s.\n" "$0" "${url_host}" ; return 1 ; } 128*906afcb8SAndy Fiddaman 129*906afcb8SAndy Fiddaman # send http post 130*906afcb8SAndy Fiddaman { 131*906afcb8SAndy Fiddaman print -n -- "${request}\r\n" 132*906afcb8SAndy Fiddaman } >&${netfd} 133*906afcb8SAndy Fiddaman 134*906afcb8SAndy Fiddaman # process reply 135*906afcb8SAndy Fiddaman parse_http_response httpresponse <&${netfd} 136*906afcb8SAndy Fiddaman response="${ cat_http_body "${httpresponse.transfer_encoding}" <&${netfd} ; }" 137*906afcb8SAndy Fiddaman 138*906afcb8SAndy Fiddaman # close connection 139*906afcb8SAndy Fiddaman redirect {netfd}<&- 140*906afcb8SAndy Fiddaman 141*906afcb8SAndy Fiddaman if (( httpresponse.statuscode >= 200 && httpresponse.statuscode <= 299 )) ; then 142*906afcb8SAndy Fiddaman print -r -- "${response}" 143*906afcb8SAndy Fiddaman return 0 144*906afcb8SAndy Fiddaman else 145*906afcb8SAndy Fiddaman print -u2 -f $"tinyurl response was (%s,%s):\n%s\n" "${httpresponse.statuscode}" "${httpresponse.statusmsg}" "${response}" 146*906afcb8SAndy Fiddaman return 1 147*906afcb8SAndy Fiddaman fi 148*906afcb8SAndy Fiddaman 149*906afcb8SAndy Fiddaman # not reached 150*906afcb8SAndy Fiddaman} 151*906afcb8SAndy Fiddaman 152*906afcb8SAndy Fiddamanfunction request_trimurl 153*906afcb8SAndy Fiddaman{ 154*906afcb8SAndy Fiddaman # site setup 155*906afcb8SAndy Fiddaman typeset url_host="api.tr.im" 156*906afcb8SAndy Fiddaman typeset url_path="/api/trim_url.xml" 157*906afcb8SAndy Fiddaman typeset url="http://${url_host}${url_path}" 158*906afcb8SAndy Fiddaman integer netfd # http stream number 159*906afcb8SAndy Fiddaman typeset inputurl="$1" 160*906afcb8SAndy Fiddaman compound httpresponse # http response 161*906afcb8SAndy Fiddaman typeset request="" 162*906afcb8SAndy Fiddaman 163*906afcb8SAndy Fiddaman # we assume "inputurl" is a correctly encoded URL which doesn't 164*906afcb8SAndy Fiddaman # require any further mangling 165*906afcb8SAndy Fiddaman url_path+="?url=${inputurl}" 166*906afcb8SAndy Fiddaman 167*906afcb8SAndy Fiddaman request="GET ${url_path} HTTP/1.1\r\n" 168*906afcb8SAndy Fiddaman request+="Host: ${url_host}\r\n" 169*906afcb8SAndy Fiddaman request+="User-Agent: ${http_user_agent}\r\n" 170*906afcb8SAndy Fiddaman request+="Connection: close\r\n" 171*906afcb8SAndy Fiddaman 172*906afcb8SAndy Fiddaman redirect {netfd}<> "/dev/tcp/${url_host}/80" 173*906afcb8SAndy Fiddaman (( $? != 0 )) && { print -u2 -f $"%s: Could not open connection to %s.\n" "$0" "${url_host}" ; return 1 ; } 174*906afcb8SAndy Fiddaman 175*906afcb8SAndy Fiddaman # send http post 176*906afcb8SAndy Fiddaman { 177*906afcb8SAndy Fiddaman print -n -- "${request}\r\n" 178*906afcb8SAndy Fiddaman } >&${netfd} 179*906afcb8SAndy Fiddaman 180*906afcb8SAndy Fiddaman # process reply 181*906afcb8SAndy Fiddaman parse_http_response httpresponse <&${netfd} 182*906afcb8SAndy Fiddaman response="${ cat_http_body "${httpresponse.transfer_encoding}" <&${netfd} ; }" 183*906afcb8SAndy Fiddaman 184*906afcb8SAndy Fiddaman # close connection 185*906afcb8SAndy Fiddaman redirect {netfd}<&- 186*906afcb8SAndy Fiddaman 187*906afcb8SAndy Fiddaman if (( httpresponse.statuscode >= 200 && httpresponse.statuscode <= 299 )) ; then 188*906afcb8SAndy Fiddaman # the statement below should really parse the XML... 189*906afcb8SAndy Fiddaman print -r -- "${response/~(Elr).*(\<url\>)(.*)(\<\/url\>).*/\2}" 190*906afcb8SAndy Fiddaman return 0 191*906afcb8SAndy Fiddaman else 192*906afcb8SAndy Fiddaman print -u2 -f $"tr.im response was (%s,%s):\n%s\n" "${httpresponse.statuscode}" "${httpresponse.statusmsg}" "${response}" 193*906afcb8SAndy Fiddaman return 1 194*906afcb8SAndy Fiddaman fi 195*906afcb8SAndy Fiddaman 196*906afcb8SAndy Fiddaman # not reached 197*906afcb8SAndy Fiddaman} 198*906afcb8SAndy Fiddaman 199*906afcb8SAndy Fiddamanfunction usage 200*906afcb8SAndy Fiddaman{ 201*906afcb8SAndy Fiddaman OPTIND=0 202*906afcb8SAndy Fiddaman getopts -a "${progname}" "${shtinyurl_usage}" OPT '-?' 203*906afcb8SAndy Fiddaman exit 2 204*906afcb8SAndy Fiddaman} 205*906afcb8SAndy Fiddaman 206*906afcb8SAndy Fiddaman# program start 207*906afcb8SAndy Fiddamanbuiltin basename 208*906afcb8SAndy Fiddamanbuiltin cat 209*906afcb8SAndy Fiddamanbuiltin date 210*906afcb8SAndy Fiddamanbuiltin uname 211*906afcb8SAndy Fiddaman 212*906afcb8SAndy Fiddamantypeset progname="${ basename "${0}" ; }" 213*906afcb8SAndy Fiddaman 214*906afcb8SAndy Fiddaman# HTTP protocol client identifer 215*906afcb8SAndy Fiddamantypeset -r http_user_agent="shtinyurl/ksh93 (2010-03-27; ${ uname -s -r -p ; })" 216*906afcb8SAndy Fiddaman 217*906afcb8SAndy Fiddamantypeset -r shtinyurl_usage=$'+ 218*906afcb8SAndy Fiddaman[-?\n@(#)\$Id: shtinyurl (Roland Mainz) 2010-03-27 \$\n] 219*906afcb8SAndy Fiddaman[-author?Roland Mainz <roland.mainz@nrubsig.org>] 220*906afcb8SAndy Fiddaman[+NAME?shtinyurl - create short alias URL from long URL] 221*906afcb8SAndy Fiddaman[+DESCRIPTION?\bshtinyurl\b is a small utility which passes a given URL 222*906afcb8SAndy Fiddaman to internet service which creates short aliases in the 223*906afcb8SAndy Fiddaman form of http://<servicename>/XXXXXXXX to redirect long URLs.] 224*906afcb8SAndy Fiddaman[+?The first arg \burl\b describes a long URL which is transformed into 225*906afcb8SAndy Fiddaman a tinyurl.com short alias.] 226*906afcb8SAndy Fiddaman[P:provider?Service provider (either \'tinyurl.com\' or \'tr.im\').]:[mode] 227*906afcb8SAndy Fiddaman 228*906afcb8SAndy Fiddamanurl 229*906afcb8SAndy Fiddaman 230*906afcb8SAndy Fiddaman[+SEE ALSO?\bksh93\b(1), \brssread\b(1), \bshtwitter\b(1), http://www.tinyurl.com, http://tr.im] 231*906afcb8SAndy Fiddaman' 232*906afcb8SAndy Fiddaman 233*906afcb8SAndy Fiddamantypeset service_provider="tr.im" 234*906afcb8SAndy Fiddaman 235*906afcb8SAndy Fiddamanwhile getopts -a "${progname}" "${shtinyurl_usage}" OPT ; do 236*906afcb8SAndy Fiddaman# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|" 237*906afcb8SAndy Fiddaman case ${OPT} in 238*906afcb8SAndy Fiddaman P) service_provider="${OPTARG}" ;; 239*906afcb8SAndy Fiddaman *) usage ;; 240*906afcb8SAndy Fiddaman esac 241*906afcb8SAndy Fiddamandone 242*906afcb8SAndy Fiddamanshift $((OPTIND-1)) 243*906afcb8SAndy Fiddaman 244*906afcb8SAndy Fiddaman# expecting at least one more argument 245*906afcb8SAndy Fiddaman(( $# >= 1 )) || usage 246*906afcb8SAndy Fiddaman 247*906afcb8SAndy Fiddamantypeset url="$1" 248*906afcb8SAndy Fiddamanshift 249*906afcb8SAndy Fiddaman 250*906afcb8SAndy Fiddamancase "${service_provider}" in 251*906afcb8SAndy Fiddaman "tinyurl.com") 252*906afcb8SAndy Fiddaman request_tinyurl "${url}" 253*906afcb8SAndy Fiddaman exit $? 254*906afcb8SAndy Fiddaman ;; 255*906afcb8SAndy Fiddaman "tr.im") 256*906afcb8SAndy Fiddaman request_trimurl "${url}" 257*906afcb8SAndy Fiddaman exit $? 258*906afcb8SAndy Fiddaman ;; 259*906afcb8SAndy Fiddaman *) 260*906afcb8SAndy Fiddaman fatal_error "Unsupported service provider." 261*906afcb8SAndy Fiddamanesac 262*906afcb8SAndy Fiddaman 263*906afcb8SAndy Fiddaman# not reached 264*906afcb8SAndy Fiddaman 265*906afcb8SAndy Fiddaman# EOF. 266