summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEudyptula <eitan@mosenkis.net>2009-06-18 18:34:16 -0400
committerEudyptula <eitan@mosenkis.net>2009-06-18 18:34:16 -0400
commit7cc564052c31f96897a2087e890372d425cc7670 (patch)
tree6b6aa7b76f157d9ccf5f4a8c74e92d35403bb600
parentPlugged in sql_build to backend and frontend log viewer (diff)
downloadingenue-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.php1
-rw-r--r--frontend/pages/hardreset.php26
-rw-r--r--frontend/pages/newclass.php17
-rw-r--r--frontend/routing.csv2
-rwxr-xr-xnewclass.php79
-rwxr-xr-xsetup.php69
-rw-r--r--shared/classes/0sql_row_obj.php16
-rw-r--r--shared/classes/user.php36
-rw-r--r--shared/config.php1
-rw-r--r--shared/functions/validate.php52
-rw-r--r--shared/include/includes.php5
-rw-r--r--steps1
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('&nbsp;', 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);
?>
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?