#!/bin/csh
# generate random online searches
# gros [-sv][-t X]
# options: -s = silent, -v = verbose, -t X = maximum delay between searches
# This script generates random searches on poular search engines.
# A possible motivation is the generation of noise in one's user profile
# Beware - the search engine operator might be not amused and blacklist 
# your IP address
#
# for the script to work, we need dd, echo, od, wc, ping, and curl.
#
# drz 20090618
# drz 20160617 one script to search all (bing, google, yahoo)
#set verbose

# building blocks of query URL
# google
set gspr='http://www.go'
set efix='ogle.com/search?hl='
set gs_pref="${gspr}""${efix}"
set gs_query="&q=%22"

# bing
set bspre='http://www.bi'
set fix='ng.com/search?mkt='
set bs_pref="${bspre}""${fix}"
set bs_query="&q=%22"

# yahoo
# this one was somewhat tricky
set ysp='https://'
set refix='search.yahoo.com/search;_ylt=0;_ylc=0?'
set ys_query="&p=%22"

set rs_post="%22"

# we are multilingual
set rs_langs=`echo en jp cn ca fr de ru es no da fi ko pt sv zh-cn ar-ma lv is eu rm sa ta uz-uz sw ur yi el`
# the yahoo language list is poorer
set ys_langs=`echo ar ca nl fi fr de hu id it jp lv lt no pl pt ro ru es sv th tr`

# create dummy array for user agent strings
set ua=`echo a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1`
# populate array - must'nt do more entries than the dummy array has
set ua[1]='AmigaVoyager/3.4.4 (MorphOS/PPC native)' 
set ua[2]='Opera/9.60 (J2ME/MIDP; Opera Mini/4.1.11320/608; U; en) Presto/2.2.0'
set ua[3]='Mozilla/4.7 (compatible; OffByOne; Windows 2000)'
set ua[4]='Mozilla/4.08 (Charon; Inferno)'
set ua[5]='NetSurf/0.0 (RISC OS; armv5l)'
set ua[6]='Mozilla/3.0 (compatible; NetPositive/2.2.1; BeOS)'
set ua[7]='LGE-MX380/1.0 UP.Browser/6.2.3.9 (GUI) MMP/2.0'
set ua[8]='Mozilla/1.22 (compatible; MSIE 2.0; Windows 95)'
set ua[9]='Mozilla/4.0 (PS2; PlayStation BB Navigator 1.0) NetFront/3.0'
set ua[10]='Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20070606'
set ua[11]='PATHWORKS Mosaic/1.0 libwww/2.15_Spyglass'
set ua[12]='Lynx/2.8.5dev.16 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.6b'
set ua[13]='Mozilla/5.0(Windows;N;Win98;m18)Gecko/20010124'
set ua[14]='EPOC32-WTL/2.0 (VGA) STNC-WTL/2.0(230)'
set ua[15]='Mozilla/4.5 (compatible; iCab 2.7.1; Macintosh; I; PPC)'
set ua[16]='Opera/9.00 (Nintendo Wii; U; ; 1309-9; en)'
set ua[17]='IBrowse/2.4 (AmigaOS 3.9; 68K)'
set ua[18]='Mozilla/5.0 (X11; U; Linux i686) Gecko/20030422 Galeon/1.3.4'
set ua[19]='W3CLineMode/5.4.0 libwww/5.4.0'
set ua[20]='retawq/0.1.6 [en] (text)'
set ua[21]='Mozilla/1.22 (compatible; MSIE 5.01; PalmOS 3.0) EudoraWeb 2.1'
set ua[22]='amaya/9.51 libwww/5.4.0'
set ua[23]='xChaos_Arachne/5.1.89;GPL,386+'
set ua[24]='Mozilla/6.0; (Spoofed by Amiga-AWeb/3.5.07 beta)'
set ua[25]='Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Avant Browser [avantbrowser.com]; Hotbar 4.4.5.0)'
set ua[26]='Mozilla/5.0 (compatible; Konqueror/3.5; Darwin) KHTML/3.5.6 (like Gecko)'
set ua[27]='Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:0.9.6) Gecko/20011128'
set ua[28]='Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en; rv:1.8.1.14) Gecko/20080409 Camino/1.6 (like Firefox/2.0.0.14)'

# silent prevents all output
set silent = 0;
# chatty shows all diagnostic messages of curl
set very = 0
set chatty = 0;
# if neither chatty nor silent, gros writes a dot for each curl (progress bar)
# max_timo sets the maximum delay between consecutive curls; default is 60 s
@ max_timo = 60

set args = `getopt svt: $*`
@ narg = $#args
@ iarg = 1
set errcode = $?
# get arguments
while ( $iarg < $narg )
  if ( "$args[$iarg]" =~ *v ) then
    set chatty = 1
  endif
  if ( "$args[$iarg]" =~ *V ) then
    set very = 1
    set chatty = 1
  endif
  if ( "$args[$iarg]" =~ *s ) then
    set silent = 1
  endif
  if ( "$args[$iarg]" =~ *t ) then
    @ iarg++
    @ max_timo = $args[$iarg]
  endif
  @ iarg++
end

if ( ( $chatty == 0 ) && ( $silent == 0 ) ) then
  echo -n `date +%H:%M:%S`
endif

# for the search string and progress bar
set dot="."
set ast="*"
set hxc=( + 0 1 2 3 4 5 6 7 8 9 + a b c d e f g h i j k l m n o p q r s t u v w x y z + A B C D E F G H I J K L M N O P Q R S T U V W X Y Z + )
set hxl=${#hxc}
set lnl=`tput cols`; @ lnl -= 8; set lml=$lnl; @ lml--;
@ i = 0
@ j = 0
@ k = 1

# what we do is this: generate a random alphanumeric string of random length

set nb_in_long = 4
# number of bytes we read from /dev/random
# scratch file name
set dot_junk = ".junk"

# do forever
while 1
# retrieve 8 bytes from random device and write into a scratch file
  dd if=/dev/random of=$dot_junk ibs=$nb_in_long count=1 >& /dev/null
# have od convert them to a decimal	
  set num_of_bytes = `od -D $dot_junk`
# first one is file offset - skip
  shift num_of_bytes

# how many are left? we need at least one 
  # max string length
  @ lx = 14
  if ( $#num_of_bytes > 0 ) then
    @ ix = ( $num_of_bytes[1] % $lx )
    if ( $ix < 0 ) then
      @ ix = - $ix
    endif
    @ ix = $ix + 3

    dd if=/dev/random of=$dot_junk ibs=$ix count=1 >& /dev/null
    set the_bytes = `od -t u1 $dot_junk`
    shift the_bytes


    @ lng = 0
    @ csl = $#hxc
    set the_string = ""
    set old_char = '-'
    while 1
      if ( $#the_bytes > 1 ) then
	set the_byte = $the_bytes[1]
	@ lng++
	if ( $the_byte !~ "0*" ) then
	  @ cix = ( $the_byte % $csl ) + 1 
	  set the_char = $hxc[$cix]
	  while ( $the_char == + )
	    if ( ( $lng < 3 ) || ( $lng > ( $ix - 2 ) ) || \
		 ( $old_char == + ) ) then
	      @ cix = ( ( $the_byte + $cix + $ix ) % $csl ) + 1 
	      set the_char = $hxc[$cix]
	    else
	      break
	    endif
	  end
	  set the_string = ${the_string}$the_char
	  set old_char = $the_char
	endif
      else
	break
      endif
      shift the_bytes
    end

# throw dice for...
    dd if=/dev/random of=$dot_junk ibs=$nb_in_long count=2 >& /dev/null
# have od convert them to a decimal	
    set the_bytes = `od -t u2 $dot_junk`
# first one is file offset - skip
    shift the_bytes
    #echo $the_bytes

# ...a language...
    @ lang_idx = ( $the_bytes[1] % $#rs_langs ) + 1
    @ yang_idx = ( $the_bytes[1] % ($#ys_langs + 1) )
    shift the_bytes

# ...a user agent...
    @ ua_idx = ( $the_bytes[1] % $#ua ) + 1
    set rs_usag = "$ua[$ua_idx]"
    shift the_bytes

# ...and, while we're at it, a delay
    @ rs_timo = ( $the_bytes[1] % $max_timo )

# now we have a random string, go ahead and google or bing it:
    @ rs_flip = ( $the_bytes[1] % 3 )
#   @ rs_flip = 2

    if ( $rs_flip == 0 ) then
      set rs_lang = $rs_langs[$lang_idx]
      set rs_url = "${gs_pref}${rs_lang}${gs_query}${the_string}${rs_post}"
      if ( $chatty != 0 ) then
	echo -n googl
      endif
    else 
      if ( $rs_flip == 1 ) then
	set rs_lang = $rs_langs[$lang_idx]
	set rs_url = "${bs_pref}${rs_lang}${bs_query}${the_string}${rs_post}"
	if ( $chatty != 0 ) then
	  echo -n bing
	endif
      else
# yahoo handles languages by host names
	if ( $yang_idx == 0 ) then
	  set rs_lang = ""
	  set yost = $rs_lang
	else
	  set rs_lang = "$ys_langs[$yang_idx]"
	  set yost = "${rs_lang}."
	endif
	set rs_url = "${ysp}${yost}${refix}${ys_query}${the_string}${rs_post}"
	if ( $chatty != 0 ) then
	  echo -n yahoo
	endif
      endif
    endif
      
    if ( $chatty != 0 ) then
      echo ing for "$the_string", language=${rs_lang}
    endif
    if ( $chatty != 0 ) then
      echo posing as "$rs_usag"
    endif
    if ( $chatty != 0 ) then
      echo "$rs_url"
    endif
#
#
#	have URL, will travel
#
#
# note: since we know which hosts we access, curl may 
# forego SSL certificate authorization checking: option -k
    if ( $chatty != 0 ) then
      curl -k -f -A "$rs_usag" --connect-timeout 5 -m 30 -o /dev/null "${rs_url}"
      set cstat = $status
    else
      ( curl -k -f -A "$rs_usag" --connect-timeout 10 -m 30 -o /dev/null "${rs_url}" > /dev/null ) | & grep 'curl:' > gros.log
      set cstat = 0
#     set cstat = $status
    endif
    
# everything below is just eye candy
# init progress bar
    if ( ( $chatty == 0 ) && ( $silent == 0 ) ) then
      @ i++
      @ j++
# make the lines distinct
      if ( $i < $lml ) then
# almost always
	if ( $cstat == 0 ) then
	  set chr=$dot
	else
	  set chr="$ast"
	endif
      else
# where does the tag go?
	@ i = 0
	if ( $k > $hxl ) then
	  @ k = 1
	endif
	set chr="${hxc[$k]}"
      endif
      if ( $j < $lnl ) then
# continue the line
	echo -n "$chr"
      else
	@ j = 0
	set lnl=`tput cols`; @ lnl -= 8; set lml=$lnl; @ lml--
# when 80 lines are written, increment tag character
	if ( $i == 0 ) then
	  @ k++
	  set chr="${hxc[$k]}"
	endif
# new line
	echo $chr
	echo -n `date +%H:%M:%S`
      endif
      unset chr
    endif
  endif
  sleep $rs_timo
end

exit
