diff options
author | Eudyptula <eitan@mosenkis.net> | 2009-06-18 18:34:16 -0400 |
---|---|---|
committer | Eudyptula <eitan@mosenkis.net> | 2009-06-18 18:34:16 -0400 |
commit | 7cc564052c31f96897a2087e890372d425cc7670 (patch) | |
tree | 6b6aa7b76f157d9ccf5f4a8c74e92d35403bb600 | |
parent | Plugged in sql_build to backend and frontend log viewer (diff) | |
download | ingenue-7cc564052c31f96897a2087e890372d425cc7670.tar.gz ingenue-7cc564052c31f96897a2087e890372d425cc7670.tar.bz2 ingenue-7cc564052c31f96897a2087e890372d425cc7670.zip |
Moved newclass utility into a cli script, created first-time setup script replacing the reset function from the frontend
-rw-r--r-- | backend/functions/build.php | 1 | ||||
-rw-r--r-- | frontend/pages/hardreset.php | 26 | ||||
-rw-r--r-- | frontend/pages/newclass.php | 17 | ||||
-rw-r--r-- | frontend/routing.csv | 2 | ||||
-rwxr-xr-x | newclass.php | 79 | ||||
-rwxr-xr-x | setup.php | 69 | ||||
-rw-r--r-- | shared/classes/0sql_row_obj.php | 16 | ||||
-rw-r--r-- | shared/classes/user.php | 36 | ||||
-rw-r--r-- | shared/config.php | 1 | ||||
-rw-r--r-- | shared/functions/validate.php | 52 | ||||
-rw-r--r-- | shared/include/includes.php | 5 | ||||
-rw-r--r-- | steps | 1 |
12 files changed, 252 insertions, 53 deletions
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 @@ -<?php -function init_hardreset() { - global $S; - $S['title']='DELETE EVERYTHING'; -} -function body_hardreset() { - global $S, $request; - if (isset($_POST['confirm']) && stripslashes($_POST['confirm']) == "I'm stupid.") { - echo '<h2>Deleting EVERYTHING</h2><h3>(We warned you)</h3>'; - foreach (get_declared_classes() as $class) { - if (is_subclass_of($class, 'sql_row_obj')) { - $obj=new $class(); - echo 'Class '.$class.':<br/>'."\n"; - foreach (array($obj->drop_table(), $obj->create_table()) as $q) { - echo '<pre><code>'.$q.'</code></pre>'."\n"; - $S['pdo']->query($q); - } -// } else { -// echo 'Ignoring class '.$class.'.<br/>'."\n"; - } - } - } else { - echo '<h2>This is a stupid thing to do.</h2><form action="'.url('hardreset').'" method="post"><input type="submit" name="confirm" value="I\'m stupid." /></form>'; - } -} -?> 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 @@ -<?php -function init_newclass() { - return array('title' => '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 '<pre>'.str_replace(str_repeat(' ', 4), "\t", highlight_string('<?php'."\n".$o->to_php().'?>', true)),'</pre>'; - } else { - echo '<form action="'.url('newclass').'">Class name: <input name="class" /><br/>Table name: <input name="table" /><br/><input type="submit" value="Submit" /></form>'; - } -} -?> 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 +<?php +require_once(dirname(__FILE__).'/shared/include/includes.php'); // USE __DIR__ in 5.3.0 +require_once(SHARED.'/config.php'); +require_once(SHARED.'/include/dbinit.php'); +function prompt_bool($prompt, $default=true) { + $yes=$default?'Y':'y'; + $no=$default?'n':'N'; + while (true) { + echo trim($prompt)." [$yes/$no] "; + $answer=trim(fgets(STDIN)); + if (strlen($answer) == 0) { + return $default; + } + if (strtolower(substr($answer, 0, 1)) == 'y') { + return true; + } elseif (strtolower(substr($answer, 0, 1)) == 'n') { + return false; + } else { + echo "Please respond yes or no.\n"; + } + } +} +function prompt_string($prompt, $default=null) { + echo $prompt.' '.($default?"[$default] ":''); + $answer=trim(fgets(STDIN)); + if (strlen($answer) == 0) { + if ($default) { + return $default; + } + } + return $answer; +} +$pdo=&$S['pdo']; +$r=$pdo->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, "<?php\n"); + eval ("class fake_class_for_newclass extends sql_row_obj {\nprotected \$table='$table';\t}"); + $obj=new fake_class_for_newclass(); + fputs($file, str_replace('fake_class_for_newclass', $class, $obj->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 +<?php +require_once(dirname(__FILE__).'/shared/include/includes.php'); // USE __DIR__ in 5.3.0 +require_once(SHARED.'/config.php'); +function echo_and_query($q) { + global $pdo; + echo $q."\n"; + return $pdo->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 @@ +<?php +class sql_user extends sql_row_obj { + protected $table='users', $primary_key='id', $columns=array( + 'id' => 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 @@ +<?php +class Validate { + // Email validation credit: http://www.linuxjournal.com/article/9585 + public static function email($email) { + $isValid = true; + $atIndex = strrpos($email, "@"); + if (is_bool($atIndex) && !$atIndex) { + $isValid = false; + } else { + $domain = substr($email, $atIndex+1); + $local = substr($email, 0, $atIndex); + $localLen = strlen($local); + $domainLen = strlen($domain); + if ($localLen < 1 || $localLen > 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 @@ <?php require_once(dirname(__FILE__).'/paths.php'); // USE __dir__ in 5.3.0 // Load functions and classes from the shared directory and either foreground or background -$dir=realpath($_SERVER['PHP_SELF']) == BACKEND.'/backend.php'?BACKEND:FRONTEND; foreach (array('functions', 'classes') as $type) { - foreach (array(SHARED, $dir) as $dir) { + foreach (array(SHARED, ($_SERVER['DOCUMENT_ROOT']?FRONTEND:BACKEND)) as $dir) { foreach (glob("$dir/$type/*.php") as $file) { require_once($file); } } } -unset($dir); +unset($dir, $file, $type); ?> @@ -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? |