1## dbhelper.sh -- shell program helpers for HotCRP database access 2## Copyright (c) 2006-2018 Eddie Kohler; see LICENSE. 3 4echo_n () { 5 # suns can't echo -n, and Mac OS X can't echo "x\c" 6 echo "$@" | tr -d ' 7' 8} 9 10findoptions () { 11 if test -n "$options_file" -a \( -r "$options_file" -o -n "$1" \); then echo "$options_file" 12 elif test -n "$options_file"; then echo /dev/null; return 1 13 elif test -r "${CONFDIR}options.php" -o -n "$1"; then echo "${CONFDIR}options.php" 14 elif test -r "${CONFDIR}options.inc"; then echo "${CONFDIR}options.inc" 15 elif test -r "${OLDCONFDIR}options.inc"; then echo "${OLDCONFDIR}options.inc" 16 else echo /dev/null; return 1; fi 17} 18 19getdbopt () { 20 (cd $MAINDIR && perl -e 'my(%Opt); 21my($Confname) = "'"$CONFNAME"'"; 22 23sub unslash ($) { 24 my($a) = @_; 25 my($b) = ""; 26 while ($a ne "") { 27 if ($a =~ m|\A\\|) { 28 if ($a =~ m|\A\\([0-7]{1,3})(.*)\z|s) { 29 $b .= chr(oct($1)); 30 $a = $2; 31 } elsif ($a =~ m|\A\\([nrftvb])(.*)\z|s) { 32 $b .= eval("\"\\$1\""); 33 $a = $2; 34 } else { 35 $b .= substr($a, 1, 1); 36 $a = substr($a, 2); 37 } 38 } else { 39 $b .= substr($a, 0, 1); 40 $a = substr($a, 1); 41 } 42 } 43 $b; 44} 45 46sub process ($) { 47 my($t) = @_; 48 49 $t =~ s|/\*.*?\*/||gs; 50 $t =~ s|//.*$||gm; 51 52 while ($t =~ m&\$Opt\[['"'"'"](.*?)['"'"'"]\]\s*=\s*\"((?:[^\"\\]|\\.)*)\"&g) { 53 $Opt{$1} = unslash($2); 54 } 55 while ($t =~ m&\$Opt\[['"'"'"](.*?)['"'"'"]\]\s*=\s*'"'"'([^'"'"']*)'"'"'&g) { 56 $Opt{$1} = $2; 57 } 58 while ($t =~ m&\$Opt\[['"'"'"](.*?)['"'"'"]\]\s*=\s*([\d.]+|true)&g) { 59 $Opt{$1} = $2; 60 } 61 while ($t =~ m&\$Opt\[['"'"'"](.*?)['"'"'"]\]\s*=\s*(?:array\(|\[)(.*)[\)\]]\s*;\s*$&gm) { 62 my($n, $x, $a) = ($1, $2, []); 63 while (1) { 64 if ($x =~ m&\A[\s,]*\"((?:[^\"\\]|\\.)*)\"(.*)\z&) { 65 push @$a, unslash($1); 66 $x = $2; 67 } elsif ($x =~ m&\A[\s,]*'"'"'([^'"'"']*)'"'"'(.*)\z&) { 68 push @$a, $1; 69 $x = $2; 70 } else { 71 last; 72 } 73 } 74 $Opt{$n} = $a; 75 } 76} 77 78undef $/; 79process(<STDIN>); 80if (exists($Opt{"include"})) { 81 $Opt{"include"} = [$Opt{"include"}] if !ref $Opt{"include"}; 82 my($confname, @flist) = $Confname ? $Confname : $Opt{"dbName"}; 83 foreach my $f (@{$Opt{"include"}}) { 84 $f =~ s,\$\{conf(?:id|name)\}|\$conf(?:id|name)\b,$confname,g; 85 @flist = ($f =~ m,[\[\]\*\?], ? glob($f) : $f); 86 foreach my $ff (@flist) { 87 if (open(F, "<", $ff)) { 88 process(<F>); 89 close(F); 90 } else { 91 print STDERR "$ff: $!\n"; 92 } 93 } 94 } 95} 96 97sub fixshell ($) { 98 my($a) = @_; 99 $a =~ s|'"'"'|'"'"'"'"'"'"'"'"'|g; 100 $a; 101} 102 103if ($Opt{"multiconference"} && $Confname ne "") { 104 foreach my $i ("dbName", "dbUser", "dbPassword", 105 "sessionName", "downloadPrefix", "conferenceSite") { 106 $Opt{$i} =~ s,\*|\*\{conf(?:id|name)\}|\$conf(?:id|name)\b,$Confname,g if exists($Opt{$i}); 107 } 108} 109 110if ("'$1'" =~ /^db/ 111 && (($Opt{"multiconference"} && $Confname eq "") 112 || exists($Opt{"dsn"}) 113 || !exists($Opt{"dbName"}))) { 114 print ""; 115} else { 116 $Opt{"dbUser"} = $Opt{"dbName"} if !exists($Opt{"dbUser"}) && exists($Opt{"dbName"}); 117 $Opt{"dbPassword"} = $Opt{"dbName"} if !exists($Opt{"dbPassword"}) && exists($Opt{"dbName"}); 118 print "'"'"'", fixshell($Opt{"'$1'"}), "'"'"'"; 119}') < "`findoptions`" 120} 121 122sql_quote () { 123 sed -e 's,\([\\"'"'"']\),\\\1,g' | sed -e 's,,\\Z,g' 124} 125 126json_quote () { 127 echo_n '"' 128 perl -pe 's{([\\\"])}{\\$1}g;s{([\000-\017])}{sprintf("\\%03o", ord($1))}eg' 129 # sed -e 's,\([\\"]\),\\\1,g' | tr -d '\n' 130 echo_n '"' 131} 132 133check_mysqlish () { 134 local m="`eval echo '$'$1`" 135 if test -n "$m"; then :; 136 elif $2 --version >/dev/null 2>&1; then m=$2; 137 elif ${2}5 --version >/dev/null 2>&1; then m=${2}5; 138 else m=$2; 139 fi 140 141 if $m --version >/dev/null 2>&1; then :; else 142 echo "I can't find a working $m program." 1>&2 143 echo "Install MySQL, or set the $1 environment variable and try again." 1>&2 144 exit 1 145 fi 146 eval ${1}="$m" 147} 148 149set_myargs () { 150 myargs="" 151 if test -n "$1"; then myargs=" -u$1"; fi 152 local password="$2" 153 if expr "$2" : "'" >/dev/null 2>&1; then :; else password="'$password'"; fi 154 if test "$password" = "''"; then 155 myargs_redacted="$myargs" 156 else 157 myargs_redacted="$myargs -p<REDACTED>" 158 if test "$no_password_file" = true; then 159 PASSWORDFILE= 160 else 161 PASSWORDFILE="`mktemp -q /tmp/hotcrptmp.XXXXXX`" 162 fi 163 if test -n "$PASSWORDFILE"; then 164 echo "[client]" > "$PASSWORDFILE" 165 chmod 600 "$PASSWORDFILE" # should be redundant 166 echo "password=$password" >> "$PASSWORDFILE" 167 myargs=" --defaults-extra-file=$PASSWORDFILE$myargs" 168 trap "rm -f $PASSWORDFILE" EXIT 2>/dev/null 169 else 170 PASSWORDFILE="" 171 myargs="$myargs -p$password" 172 fi 173 fi 174 if test -n "$dbhost" -a "$dbhost" != "''"; then 175 if expr "$dbhost" : "'" >/dev/null 2>&1; then 176 myargs="$myargs -h$dbhost" 177 else 178 myargs="$myargs -h'$dbhost'" 179 fi 180 fi 181} 182 183generate_random_ints () { 184 random="`head -c 48 /dev/urandom 2>/dev/null | tr -d '\000'`" 185 test -z "$random" && random="`head -c 48 /dev/random 2>/dev/null | tr -d '\000'`" 186 test -z "$random" && random="`openssl rand 48 2>/dev/null | tr -d '\000'`" 187 echo "$random" | awk ' 188BEGIN { for (i = 0; i < 256; ++i) { ord[sprintf("%c", i)] = i; } } 189{ for (i = 1; i <= length($0); ++i) { printf("%d\n", ord[substr($0, i, 1)]); } }' 190 # generate some very low-quality random bytes in case all the 191 # higher-quality mechanisms fail 192 awk 'BEGIN { srand(); for (i = 0; i < 256; ++i) { printf("%d\n", rand() * 256); } }' < /dev/null 193} 194 195generate_password () { 196 awk 'BEGIN { 197 npwchars = split("a e i o u y a e i o u y a e i o u y a e i o u y a e i o u y b c d g h j k l m n p r s t u v w tr cr br fr th dr ch ph wr st sp sw pr sl cl 2 3 4 5 6 7 8 9 - @ _ + =", pwchars, " "); 198 pw = ""; nvow = 0; 199} 200{ x = ($0 % npwchars); if (x < 30) ++nvow; 201 pw = pw pwchars[x + 1]; 202 if (length(pw) >= '"$1"' + nvow / 3) exit; 203} 204END { printf("%s\n", pw); }' 205} 206 207parse_common_argument () { 208 case "$1" in 209 -c|--co|--con|--conf|--confi|--config) 210 test "$#" -gt 1 -a -z "$options_file" || usage 211 options_file="$2"; shift=2;; 212 -c*) 213 test -z "$options_file" || usage 214 options_file="`echo "$1" | sed 's/^-c//'`"; shift=1;; 215 --co=*|--con=*|--conf=*|--confi=*|--config=*) 216 test -z "$options_file" || usage 217 options_file="`echo "$1" | sed 's/^[^=]*=//'`"; shift=1;; 218 -n|--n|--na|--nam|--name) 219 test "$#" -gt 1 -a -z "$CONFNAME" || usage 220 CONFNAME="$2"; shift=2;; 221 -n*) 222 test -z "$CONFNAME" || usage 223 CONFNAME="`echo "$1" | sed 's/^-n//'`"; shift=1;; 224 --n=*|--na=*|--nam=*|--name=*) 225 test -z "$CONFNAME" || usage 226 CONFNAME="`echo "$1" | sed 's/^-n//'`"; shift=1;; 227 --no-password-f|--no-password-fi|--no-password-fil|--no-password-file) 228 no_password_file=true; shift=1;; 229 *) 230 shift=0;; 231 esac 232} 233 234get_dboptions () { 235 dbname="`getdbopt dbName 2>/dev/null`" 236 dbuser="`getdbopt dbUser 2>/dev/null`" 237 dbpass="`getdbopt dbPassword 2>/dev/null`" 238 dbhost="`getdbopt dbHost 2>/dev/null`" 239 if test -z "$dbname" -o -z "$dbuser" -o -z "$dbpass"; then 240 echo "$1: Can't extract database options from `findoptions`!" 1>&2 241 if test "`getdbopt multiconference 2>/dev/null`" '!=' "''"; then 242 echo "This is a multiconference installation; check your '-n CONFNAME' option." 1>&2 243 fi 244 exit 1 245 fi 246} 247 248# slash-terminate LIBDIR 249expr "$LIBDIR" : '.*[^/]$' >/dev/null && LIBDIR="$LIBDIR/" 250# remove '/./' components 251LIBDIR="`echo "$LIBDIR" | sed ':a 252s,/\./,/,g 253ta'`" 254# set MAINDIR from LIBDIR 255if test "$LIBDIR" = ./; then 256 MAINDIR=../ 257elif expr "$LIBDIR" : '[^/]*[/]$' >/dev/null; then 258 MAINDIR=./ 259elif ! expr "$LIBDIR" : '.*\.\.' >/dev/null; then 260 MAINDIR="`echo "$LIBDIR" | sed 's,\(.*/\)[^/]*/$,\1,'`" 261else 262 MAINDIR="${LIBDIR}../" 263fi 264# set CONFDIR and SRCDIR from MAINDIR 265CONFDIR="`echo "${MAINDIR}conf/" | sed 's,^\./\(.\),\1,'`" 266OLDCONFDIR="`echo "${MAINDIR}Code/" | sed 's,^\./\(.\),\1,'`" 267SRCDIR="`echo "${MAINDIR}src/" | sed 's,^\./\(.\),\1,'`" 268export MAINDIR LIBDIR CONFDIR OLDCONFDIR SRCDIR 269