| 1 |
1 |
dpavlin |
#!/bin/sh |
| 2 |
|
|
# |
| 3 |
|
|
# This script is based on work of mendel from |
| 4 |
|
|
# http://www.lafferty.ca/software/webshots/webshot |
| 5 |
|
|
# webshot: hackish thing to take a picture of a whole webpage. |
| 6 |
|
|
# |
| 7 |
|
|
# idea from sippey (http://www.sippey.com/2004/blog-snaps/) |
| 8 |
|
|
# inspiration from bradfitz |
| 9 |
|
|
# |
| 10 |
|
|
# usage: webshot url filename |
| 11 |
|
|
# |
| 12 |
|
|
# JPEG seems to be the best format. |
| 13 |
|
|
# |
| 14 |
|
|
# Modified by Dobrica Pavlinusic 2004-07-25 |
| 15 |
|
|
# - include signal grabbing |
| 16 |
|
|
# - dynamic vncserver display |
| 17 |
|
|
# - correct WindowID parsing |
| 18 |
|
|
# - wait for browser to load full page (useful on slow links) |
| 19 |
|
|
# |
| 20 |
|
|
# It will need follwing external utilities: |
| 21 |
|
|
# vncserver |
| 22 |
|
|
# mozilla-firefox |
| 23 |
|
|
# HEAD (part or LWP perl library, it can be commented out) |
| 24 |
|
|
# nc (netcat, to simulate web server) |
| 25 |
|
|
# xwininfo (standard part of X-clients) |
| 26 |
|
|
# import (part of ImageMagick package) |
| 27 |
62 |
dpavlin |
# xdotool (much more useful than xwit for this purpose) |
| 28 |
1 |
dpavlin |
# |
| 29 |
|
|
# It will create snapshot of following size |
| 30 |
2 |
dpavlin |
W=1024 |
| 31 |
|
|
H=768 |
| 32 |
65 |
dpavlin |
D=24 |
| 33 |
1 |
dpavlin |
|
| 34 |
2 |
dpavlin |
# and then resize it to (comment out to disable) |
| 35 |
|
|
#RESIZE=200x |
| 36 |
1 |
dpavlin |
|
| 37 |
64 |
dpavlin |
# turn locally visible server to watch progress |
| 38 |
61 |
dpavlin |
DEBUG=0 |
| 39 |
65 |
dpavlin |
if [ ! -z "$3" ] ; then |
| 40 |
|
|
echo "DEBUG turned on" |
| 41 |
|
|
DEBUG=1 |
| 42 |
|
|
D=8 |
| 43 |
|
|
fi |
| 44 |
61 |
dpavlin |
|
| 45 |
|
|
# wait for $WAIT seconds for page to load |
| 46 |
|
|
WAIT=30 |
| 47 |
|
|
|
| 48 |
1 |
dpavlin |
# some configurable paths |
| 49 |
|
|
BROWSER=mozilla-firefox |
| 50 |
60 |
dpavlin |
XSERVER=Xvfb |
| 51 |
1 |
dpavlin |
URL=$1 |
| 52 |
|
|
FILE=${2:-screenshot.jpg} |
| 53 |
|
|
|
| 54 |
|
|
FRAMESET="`mktemp`.html" |
| 55 |
60 |
dpavlin |
PROFILE_DIR=`mktemp -d` |
| 56 |
1 |
dpavlin |
PORT=8888 |
| 57 |
|
|
|
| 58 |
61 |
dpavlin |
LOCAL_DISPLAY=$DISPLAY |
| 59 |
|
|
|
| 60 |
2 |
dpavlin |
if [ -z "$URL" ] ; then |
| 61 |
|
|
echo "usage: $0 http://url.to.capture [screenshot.jpg]" |
| 62 |
|
|
exit 1 |
| 63 |
|
|
fi |
| 64 |
|
|
|
| 65 |
62 |
dpavlin |
if [ -z "`which xdotool`" ] ; then |
| 66 |
|
|
echo "$0 need xdotool from http://www.semicomplete.com/blog/projects/xdotool/" |
| 67 |
2 |
dpavlin |
exit 1 |
| 68 |
|
|
fi |
| 69 |
|
|
|
| 70 |
60 |
dpavlin |
if [ -z "`which $XSERVER`" ] ; then |
| 71 |
|
|
echo "$0 really need $XSERVER to operate. please install it." |
| 72 |
|
|
exit 1 |
| 73 |
|
|
fi |
| 74 |
|
|
|
| 75 |
61 |
dpavlin |
while netstat -ln | grep ":$PORT " >/dev/null ; do |
| 76 |
|
|
PORT=`expr $PORT + 1` |
| 77 |
|
|
done |
| 78 |
|
|
|
| 79 |
|
|
echo "### using port $PORT" |
| 80 |
|
|
|
| 81 |
1 |
dpavlin |
echo -n "testing URL $URL " |
| 82 |
|
|
if HEAD $URL >/dev/null ; then |
| 83 |
|
|
echo "ok" |
| 84 |
|
|
else |
| 85 |
|
|
echo "FAILED" |
| 86 |
|
|
exit 1 |
| 87 |
|
|
fi |
| 88 |
|
|
|
| 89 |
64 |
dpavlin |
DISPLAY_PORT=6042 |
| 90 |
1 |
dpavlin |
|
| 91 |
64 |
dpavlin |
while netstat -ln | grep ":$DISPLAY_PORT " >/dev/null ; do |
| 92 |
|
|
DISPLAY_PORT=`expr $DISPLAY_PORT + 1` |
| 93 |
|
|
done |
| 94 |
1 |
dpavlin |
|
| 95 |
64 |
dpavlin |
DISPLAY=:`expr $DISPLAY_PORT - 6000` |
| 96 |
60 |
dpavlin |
|
| 97 |
64 |
dpavlin |
echo "using DISPLAY=$DISPLAY" |
| 98 |
|
|
|
| 99 |
61 |
dpavlin |
if [ "$DEBUG" == 1 ] ; then |
| 100 |
62 |
dpavlin |
echo "using locally visible debug server on $LOCAL_DISPLAY" |
| 101 |
65 |
dpavlin |
DISPLAY=$LOCAL_DISPLAY Xephyr -ac -screen ${W}x${H}x${D} $DISPLAY 2>/dev/null & |
| 102 |
61 |
dpavlin |
else |
| 103 |
62 |
dpavlin |
echo "starting $XSERVER" |
| 104 |
65 |
dpavlin |
$XSERVER -ac -screen 0 ${W}x${H}x${D} $DISPLAY 2>/dev/null & |
| 105 |
61 |
dpavlin |
fi |
| 106 |
|
|
|
| 107 |
64 |
dpavlin |
if [ -z "$!" ] ; then |
| 108 |
|
|
echo "ABORT: can't start X server!" |
| 109 |
|
|
exit |
| 110 |
|
|
fi |
| 111 |
60 |
dpavlin |
XSERVER_PID=$! |
| 112 |
64 |
dpavlin |
|
| 113 |
62 |
dpavlin |
echo "X server pid $XSERVER_PID" |
| 114 |
60 |
dpavlin |
|
| 115 |
|
|
function kill_x_server() { |
| 116 |
61 |
dpavlin |
echo "Killing server $XSERVER_PID" |
| 117 |
60 |
dpavlin |
kill $XSERVER_PID |
| 118 |
1 |
dpavlin |
rm -f $FRAMESET |
| 119 |
60 |
dpavlin |
rm -fr $PROFILE_DIR |
| 120 |
62 |
dpavlin |
trap '' EXIT |
| 121 |
61 |
dpavlin |
exit 1 |
| 122 |
1 |
dpavlin |
} |
| 123 |
61 |
dpavlin |
trap 'kill_x_server' INT QUIT TERM SEGV EXIT |
| 124 |
1 |
dpavlin |
|
| 125 |
|
|
# create frameset to load site and after site is loaded trigger this script |
| 126 |
|
|
cat > $FRAMESET <<END_OF_FRAMESET |
| 127 |
|
|
<html> |
| 128 |
|
|
<head> |
| 129 |
|
|
<frameset rows="0,*" border=0 frameborder=no framespacing=0 onload="window.frames['trigger_frame'].window.location.replace('http://localhost:$PORT');"> |
| 130 |
|
|
<frame src="about:blank" name="trigger_frame" scrolling=no marginwidth=0 marginheight=0> |
| 131 |
|
|
<frame src="$URL" name="page_frame" scrolling=no> |
| 132 |
|
|
</frameset> |
| 133 |
|
|
</head> |
| 134 |
|
|
</html> |
| 135 |
|
|
END_OF_FRAMESET |
| 136 |
|
|
|
| 137 |
|
|
echo "Using frameset html $FRAMESET" |
| 138 |
|
|
|
| 139 |
60 |
dpavlin |
echo "preview available with: xwd -display $DISPLAY -root | xwud" |
| 140 |
1 |
dpavlin |
|
| 141 |
60 |
dpavlin |
echo "making 'Screenshot' profile in $PROFILE_DIR" |
| 142 |
61 |
dpavlin |
$BROWSER -CreateProfile "Screenshot $PROFILE_DIR" 2>/dev/null | grep Success |
| 143 |
1 |
dpavlin |
|
| 144 |
|
|
echo "launching browser $BROWSER with $URL" |
| 145 |
62 |
dpavlin |
$BROWSER -P Screenshot -width $W -height $H -safemode $FRAMESET 2>/dev/null & |
| 146 |
60 |
dpavlin |
BROWSER_PID=$! |
| 147 |
1 |
dpavlin |
|
| 148 |
61 |
dpavlin |
function kill_browser() { |
| 149 |
|
|
echo "Killing browser $BROWSER_PID" |
| 150 |
|
|
kill $BROWSER_PID |
| 151 |
|
|
echo "Killing server $XSERVER_PID" |
| 152 |
|
|
kill $XSERVER_PID |
| 153 |
|
|
rm -f $FRAMESET |
| 154 |
|
|
rm -fr $PROFILE_DIR |
| 155 |
62 |
dpavlin |
trap '' EXIT |
| 156 |
61 |
dpavlin |
exit 1 |
| 157 |
|
|
} |
| 158 |
|
|
trap 'kill_browser' INT QUIT TERM SEGV EXIT |
| 159 |
1 |
dpavlin |
|
| 160 |
62 |
dpavlin |
function ping_browser() { |
| 161 |
|
|
echo -n "ping browser" |
| 162 |
|
|
while ! ( $BROWSER -remote "ping();" 2>&1 ) >/dev/null ; do |
| 163 |
|
|
RID=`xdotool search Restore 2>/dev/null` |
| 164 |
|
|
if [ ! -z "$RID" ] ; then |
| 165 |
|
|
echo -n "Esc" |
| 166 |
|
|
xdotool focus $RID |
| 167 |
|
|
xdotool key Escape |
| 168 |
|
|
sleep 1 |
| 169 |
|
|
fi |
| 170 |
|
|
echo -n "." |
| 171 |
|
|
sleep 1 |
| 172 |
|
|
done |
| 173 |
|
|
echo " OK" |
| 174 |
|
|
} |
| 175 |
|
|
|
| 176 |
|
|
ping_browser |
| 177 |
|
|
|
| 178 |
1 |
dpavlin |
# get Mozilla Firefox window id (for resize) |
| 179 |
60 |
dpavlin |
WINDOW_ID=`xwininfo -display $DISPLAY -root -tree | grep gecko | cut -d\" -f1 | sort -n | head -1` |
| 180 |
1 |
dpavlin |
|
| 181 |
|
|
if [ -z "$WINDOW_ID" ] ; then |
| 182 |
|
|
echo "can't find window with name 'Mozilla Firefox'" |
| 183 |
|
|
exit 1 |
| 184 |
62 |
dpavlin |
else |
| 185 |
|
|
echo "working on firefox window $WINDOW_ID" |
| 186 |
1 |
dpavlin |
fi |
| 187 |
|
|
|
| 188 |
62 |
dpavlin |
xdotool search firefox |
| 189 |
1 |
dpavlin |
|
| 190 |
62 |
dpavlin |
xdotool focus $WINDOW_ID |
| 191 |
|
|
xdotool key F11 |
| 192 |
1 |
dpavlin |
|
| 193 |
62 |
dpavlin |
ping_browser |
| 194 |
1 |
dpavlin |
|
| 195 |
65 |
dpavlin |
$BROWSER -remote "openURL($FRAMESET)" 2>/dev/null |
| 196 |
|
|
|
| 197 |
|
|
echo "waiting for on_load event from browser $BROWSER_PID for ${WAIT}s" |
| 198 |
|
|
|
| 199 |
|
|
# there is hard-coded limit here: |
| 200 |
|
|
# we will wait $WAIT sec for page to load and render |
| 201 |
|
|
|
| 202 |
|
|
echo -e "HTTP/1.0 304 Not modified\r\n\r\n" | nc -l -w $WAIT -p $PORT >/dev/null || echo "Timeout after $WAIT sec!" |
| 203 |
|
|
|
| 204 |
1 |
dpavlin |
# try to deduce inside area of window |
| 205 |
|
|
|
| 206 |
|
|
DUMP_ID=`xwininfo -display $DISPLAY -id $WINDOW_ID -tree | grep 0x | grep -v ${W}x${H} | grep ${W}x | head -1 | sed 's/^ *//' | cut -d' ' -f1` |
| 207 |
|
|
|
| 208 |
|
|
if [ -z "$DUMP_ID" ] ; then |
| 209 |
|
|
echo "can't find inside area of window. Using whole browser!" |
| 210 |
|
|
DUMP_ID=$WINDOW_ID |
| 211 |
|
|
fi |
| 212 |
|
|
|
| 213 |
|
|
echo "saving window $DUMP_ID to $FILE" |
| 214 |
2 |
dpavlin |
if [ ! -z "$RESIZE" ] ; then |
| 215 |
|
|
RESIZE="-geometry $RESIZE" |
| 216 |
|
|
fi |
| 217 |
60 |
dpavlin |
|
| 218 |
2 |
dpavlin |
import -window $DUMP_ID $RESIZE $FILE |
| 219 |
1 |
dpavlin |
|
| 220 |
62 |
dpavlin |
if [ "$DEBUG" == 1 ] ; then |
| 221 |
|
|
echo -n "press enter to exit! " |
| 222 |
|
|
read |
| 223 |
|
|
fi |