From 7cc564052c31f96897a2087e890372d425cc7670 Mon Sep 17 00:00:00 2001 From: Eudyptula Date: Thu, 18 Jun 2009 18:34:16 -0400 Subject: Moved newclass utility into a cli script, created first-time setup script replacing the reset function from the frontend --- backend/functions/build.php | 1 + frontend/pages/hardreset.php | 26 -------------- frontend/pages/newclass.php | 17 --------- frontend/routing.csv | 2 -- newclass.php | 79 +++++++++++++++++++++++++++++++++++++++++ setup.php | 69 +++++++++++++++++++++++++++++++++++ shared/classes/0sql_row_obj.php | 16 ++++++--- shared/classes/user.php | 36 +++++++++++++++++++ shared/config.php | 1 + shared/functions/validate.php | 52 +++++++++++++++++++++++++++ shared/include/includes.php | 5 ++- steps | 1 + 12 files changed, 252 insertions(+), 53 deletions(-) delete mode 100644 frontend/pages/hardreset.php delete mode 100644 frontend/pages/newclass.php create mode 100755 newclass.php create mode 100755 setup.php create mode 100644 shared/classes/user.php create mode 100644 shared/functions/validate.php diff --git a/backend/functions/build.php b/backend/functions/build.php index 39f2c48..13bacbb 100644 --- a/backend/functions/build.php +++ b/backend/functions/build.php @@ -5,6 +5,7 @@ $conf['pkgdir']='/home/eitan/soc/tinderbox/default-linux-amd64'; // $conf['cxxflags']='$CFLAGS'; // Not needed in a binary install $conf['chost']='x86_64-pc-linux-gnu'; $conf['port_logdir']='$W/log'; +$conf['emerge_log_dir']=$conf['port_logdir']; $conf['emerge_default_opts']='-t -K --color=n'; $conf['portage_tmpdir']='$W/tmp'; $profile='/etc/make.profile'; diff --git a/frontend/pages/hardreset.php b/frontend/pages/hardreset.php deleted file mode 100644 index d044da8..0000000 --- a/frontend/pages/hardreset.php +++ /dev/null @@ -1,26 +0,0 @@ -Deleting EVERYTHING

(We warned you)

'; - foreach (get_declared_classes() as $class) { - if (is_subclass_of($class, 'sql_row_obj')) { - $obj=new $class(); - echo 'Class '.$class.':
'."\n"; - foreach (array($obj->drop_table(), $obj->create_table()) as $q) { - echo '
'.$q.'
'."\n"; - $S['pdo']->query($q); - } -// } else { -// echo 'Ignoring class '.$class.'.
'."\n"; - } - } - } else { - echo '

This is a stupid thing to do.

'; - } -} -?> diff --git a/frontend/pages/newclass.php b/frontend/pages/newclass.php deleted file mode 100644 index f56fa9c..0000000 --- a/frontend/pages/newclass.php +++ /dev/null @@ -1,17 +0,0 @@ - 'New class'); -} -function body_newclass() { - global $request; - if (isset($request['class']) && isset($request['table'])) { - $class=$request['class']; - $table=$request['table']; - eval("class $class extends sql_row_obj {\nvar \$table='$table';\n}\n"); - $o=new $class(); - echo '
'.str_replace(str_repeat(' ', 4), "\t", highlight_string('to_php().'?>', true)),'
'; - } else { - echo '
Class name:
Table name:
'; - } -} -?> diff --git a/frontend/routing.csv b/frontend/routing.csv index c8426f1..f203e10 100644 --- a/frontend/routing.csv +++ b/frontend/routing.csv @@ -14,8 +14,6 @@ ^logs$ logview ^logs/build([a-z0-9]{6})$ logview build ^logs/task([0-9]+)$ logview task -^hardreset$ hardreset -^newclass$ newclass # Session ^login$ login ^logout$ logout diff --git a/newclass.php b/newclass.php new file mode 100755 index 0000000..f942416 --- /dev/null +++ b/newclass.php @@ -0,0 +1,79 @@ +#!/usr/bin/php +query('SHOW TABLES'); +$tables=$r->fetchAll(PDO::FETCH_COLUMN); +foreach ($tables as $i => $table) { + if (sql_row_obj::table_to_class($table)) { + unset($tables[$i]); + } +} +if ($tables) { + echo 'Found table(s) without corresponding class: '.implode(', ', $tables)."\n"; + if (!prompt_bool('Generate classes for these tables?')) { + unset($tables); + } +} else { + echo "No tables found without corresponding classes.\n"; +} +if (!$tables) { + echo 'Which tables should we generate classes for? (space-separated) '; + $tables=explode(' ', trim(fgets(STDIN))); + if ($tables[0] == '') { + echo "Exiting.\n"; + exit; + } +} +echo 'Generating classes for table(s): '.implode(', ', $tables)."\n"; +foreach ($tables as $table) { + $default=rtrim($table, 's'); + $class=prompt_string('Class name for table '.$table.':', $default); + $file=SHARED.'/classes/'.prompt_string('Filename for class '.$class.': '.SHARED.'/classes/', $class.'.php'); + if (is_file($file)) { + if (!prompt_bool($file.' exists. Overwrite?', false)) { + echo 'Skipping table '.$table."\n"; + continue; + } + } + echo 'Writing '.$file.'...'; + $file=fopen($file, 'w'); + fputs($file, "to_php())); + fputs($file, "?>\n"); + fclose($file); + echo "done\n"; +} +?> diff --git a/setup.php b/setup.php new file mode 100755 index 0000000..e65cc91 --- /dev/null +++ b/setup.php @@ -0,0 +1,69 @@ +#!/usr/bin/php +query($q); +} +$interactive=posix_isatty(STDIN); +$opts=getopt('R'); +$pdo=new PDO('mysql:host='.$conf['sqlhost'], $conf['sqluser'], $conf['sqlpass']); +if (isset($opts['R'])) { + echo_and_query('DROP DATABASE IF EXISTS `'.$conf['sqldb'].'`'); +} +echo_and_query('CREATE DATABASE IF NOT EXISTS `'.$conf['sqldb'].'`'); // We can add charset and collate here if we want +echo_and_query('USE `'.$conf['sqldb'].'`'); +sql_row_obj::set_pdo_obj($pdo); +foreach (get_declared_classes() as $class) { + if (!is_subclass_of($class, 'sql_row_obj')) { + continue; + } + $o=new $class(); // TODO this will be static once 5.3.0 is out + if (isset($opts['R'])) { + echo_and_query($o->drop_table()); + } + echo_and_query($o->create_table()); +} +do { + if ($user->email) { + echo 'Invalid entry: '.$user->email."\n"; + } + echo 'Admin email address: '; + $user=new sql_user(); + $user->email=trim(fgets(STDIN)); + if (!$interactive) { + echo "\n"; + } +} while (!Validate::email($user->email)); +do { + if ($user->name) { + echo 'Invalid entry: '.$user->name."\n"; + } + echo 'Admin display name: '; + $user->name=trim(fgets(STDIN)); + if (!$interactive) { + echo "\n"; + } +} while (!Validate::username($user->name)); +if ($interactive) { + system('stty -echo'); +} +do { + if ($pass && $passconfirm) { + echo "Entered passwords did not match. Try again.\n"; + } + echo 'Admin password: '; + $pass=trim(fgets(STDIN)); + echo "\nRepeat password: "; + $passconfirm=trim(fgets(STDIN)); + echo "\n"; +} while (!$pass || $pass != $passconfirm); +if ($interactive) { + system('stty echo'); +} +$user->passhash=sha1($pass); +$user->flags='a'; +$user->write(); +?> diff --git a/shared/classes/0sql_row_obj.php b/shared/classes/0sql_row_obj.php index edafa4d..cf82e4b 100644 --- a/shared/classes/0sql_row_obj.php +++ b/shared/classes/0sql_row_obj.php @@ -38,15 +38,20 @@ abstract class sql_row_obj { // If the name of this class changes, it must be up $obj->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); self::$pdo=$obj; } - // Makes an SQL query using $sql and returns the resulting object - private static function sql_query($q) { + // Checks if set_pdo_obj has been called yet and complains if it hasn't + private static function check_pdo_obj() { if (!is_object(self::$pdo)) { - throw new Exception('sql_row_obj::sql_query was called, but sql_row_obj::set_pdo_obj() has not been called to set the PDO object to use for queries.'); + throw new Exception('sql_row_obj::set_pdo_obj() has not been called to set the PDO object to use for queries.'); } + } + // Makes an SQL query using $sql and returns the resulting object + private static function sql_query($q) { + self::check_pdo_obj(); // echo $q."\n"; return self::$pdo->query($q); } public static function sql_quote_string($s) { + self::check_pdo_obj(); $r=self::$pdo->quote($s); // We're not supposed to use this because PDO::ODBC doesn't support it return $r===false?"'".str_replace("'", "''", $s)."'":$r; # If the PDO call failed, at least fix single quotes } @@ -495,7 +500,7 @@ abstract class sql_row_obj { // If the name of this class changes, it must be up } // Returns an instance of whichever class extends sql_row_obj for the given table, or null if none found // TODO this shouldn't have to instantiate every class, we need 5.3.0 so this can be fully static - public static function table_to_obj($table) { + public static function &table_to_obj($table) { if (isset(self::$table_cache[$table])) { return new self::$table_cache[$table]; } @@ -512,7 +517,8 @@ abstract class sql_row_obj { // If the name of this class changes, it must be up } // Same as table_to_class, but returns the name of the class, not an instance public static function table_to_class($table) { - return get_class(self::table_to_obj($table)); + $obj=self::table_to_obj($table); + return $obj===null?null:get_class($obj); } } // This class represents a column in an SQL table definition diff --git a/shared/classes/user.php b/shared/classes/user.php new file mode 100644 index 0000000..2f604b5 --- /dev/null +++ b/shared/classes/user.php @@ -0,0 +1,36 @@ + array ( + 'type' => 'INT', + 'length' => 10, + 'unsigned' => true, + 'not_null' => true, + 'auto_increment' => true + ), + 'email' => array ( + 'type' => 'VARCHAR', + 'length' => 255, + 'not_null' => true, + 'unique' => true + ), + 'name' => array ( + 'type' => 'VARCHAR', + 'length' => 255, + 'not_null' => true + ), + 'passhash' => array ( + 'type' => 'CHAR', + 'length' => 40, + 'not_null' => true, + 'comment' => 'sha1' + ), + 'flags' => array ( + 'type' => 'VARCHAR', + 'length' => 255, + 'not_null' => true + ) + + ); +} +?> diff --git a/shared/config.php b/shared/config.php index 6a0ec38..12298ec 100644 --- a/shared/config.php +++ b/shared/config.php @@ -10,4 +10,5 @@ $conf['cookiename']='ingenueid'; // Name of the cookie to send for keeping sessi $conf['sessionlength']=1814400; // Time in seconds before sessions are purged $conf['timezone']=10800; // Time difference in seconds between UTC and the default timezone $conf['mod_rewrite']=true; // Use mod_rewrite for pretty URLs +$conf['check_email_dns']=true; // Use DNS to check the domain of submitted emails for validity ?> diff --git a/shared/functions/validate.php b/shared/functions/validate.php new file mode 100644 index 0000000..c409db4 --- /dev/null +++ b/shared/functions/validate.php @@ -0,0 +1,52 @@ + 64) { + // local part length exceeded + $isValid = false; + } else if ($domainLen < 1 || $domainLen > 255) { + // domain part length exceeded + $isValid = false; + } else if ($local[0] == '.' || $local[$localLen-1] == '.') { + // local part starts or ends with '.' + $isValid = false; + } else if (preg_match('/\\.\\./', $local)) { + // local part has two consecutive dots + $isValid = false; + } else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) { + // character not valid in domain part + $isValid = false; + } else if (preg_match('/\\.\\./', $domain)) { + // domain part has two consecutive dots + $isValid = false; + } else if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local))) { + // character not valid in local part unless + // local part is quoted + if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local))) { + $isValid = false; + } + } + // Checking DNS to make sure the domain is real is total overkill + global $conf; + if ($conf['check_email_dns'] && $isValid && !(checkdnsrr($domain,"MX") || checkdnsrr($domain,"A"))) { + // domain not found in DNS + $isValid = false; + } + } + return $isValid; + } + public static function username($name) { + return preg_match('/^[a-zA-Z0-9. _-]{2,}$/', $name); + } +} +?> diff --git a/shared/include/includes.php b/shared/include/includes.php index 40e68b6..b3ff5a3 100644 --- a/shared/include/includes.php +++ b/shared/include/includes.php @@ -1,13 +1,12 @@ diff --git a/steps b/steps index 8b74d34..17330e7 100644 --- a/steps +++ b/steps @@ -8,6 +8,7 @@ generate a fake CONF_ROOT with /etc/make.profile (linked based on target arch) a CXXFLAGS=? CHOST=... MAKEOPTS=? + EMERGE_LOG_DIR=... (same as PORT_LOGDIR) PORT_LOGDIR=... (create me) PORT_TMPDIR=... (create me) FEATURES=ccache? -- cgit v1.2.3-65-gdbad