![]() |
Xataface 2.0
Xataface Application Framework
|
00001 <?php 00002 /*------------------------------------------------------------------------------- 00003 * Xataface Web Application Framework 00004 * Copyright (C) 2005-2007 Steve Hannah (shannah@sfu.ca) 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 *------------------------------------------------------------------------------- 00020 */ 00032 class dataface_actions_register { 00033 00038 var $form; 00039 var $params; 00040 var $ontology; 00041 00042 00043 function handle(&$params){ 00044 $this->params =& $params['action']; 00045 unset($params); 00046 $params =& $this->params; 00047 00048 Dataface_PermissionsTool::getInstance()->setDelegate(new dataface_actions_register_permissions_delegate()); 00049 00050 00051 $app =& Dataface_Application::getInstance(); 00052 $auth =& Dataface_AuthenticationTool::getInstance(); 00053 00054 00055 import('Dataface/Ontology.php'); 00056 Dataface_Ontology::registerType('Person', 'Dataface/Ontology/Person.php', 'Dataface_Ontology_Person'); 00057 $this->ontology =& Dataface_Ontology::newOntology('Person', $app->_conf['_auth']['users_table']); 00058 00059 $atts =& $this->ontology->getAttributes(); 00060 00061 $query =& $app->getQuery(); 00062 if ( !is_array(@$app->_conf['_auth']) ){ 00063 return PEAR::raiseError("Cannot register when authentication is not enabled.", DATAFACE_E_ERROR); 00064 } 00065 00066 if ( isset($app->_conf['_auth']['email_column']) ){ 00067 00068 00069 $atts['email'] =& $this->ontology->table->getField( $app->_conf['_auth']['email_column'] ); 00070 $this->fieldnames['email'] = $app->_conf['_auth']['email_column']; 00071 } 00072 00073 00074 if ( $auth->isLoggedIn() ){ 00075 return Dataface_Error::permissionDenied("Sorry you cannot register once you are logged in. If you want to register, you must first log out."); 00076 } 00077 00078 00079 00080 if ( !@$app->_conf['_auth']['allow_register'] ){ 00081 return PEAR::raiseError("Sorry, registration is not allowed. Please contact the administrator for an account.", DATAFACE_E_ERROR); 00082 } 00083 00084 00085 $pt =& Dataface_PermissionsTool::getInstance(); 00086 00087 00088 // Create a new record form on the users table 00089 $this->form =& df_create_new_record_form($app->_conf['_auth']['users_table']); 00090 00091 // add the -action element so that the form will direct us back here. 00092 $this->form->addElement('hidden','-action'); 00093 $this->form->setDefaults(array('-action'=>$query['-action'])); 00094 00095 // Check to make sure that there isn't another user with the same 00096 // username already. 00097 $validationResults = $this->validateRegistrationForm($_POST); 00098 if ( count($_POST) > 0 and PEAR::isError($validationResults) ){ 00099 $app->addMessage($validationResults->getMessage()); 00100 $this->form->_errors[$app->_conf['_auth']['username_column']] = $validationResults->getMessage(); 00101 } 00102 if ( !PEAR::isError($validationResults) and $this->form->validate() ){ 00103 // The form input seems OK. Let's process the form 00104 00105 // Since we will be using our own form processing for this action, 00106 // we need to manually push the field inputs into the Dataface_Record 00107 // object. 00108 $this->form->push(); 00109 00110 // Now we obtain the Dataface_Record object that is to be added. 00111 $rec =& $this->form->_record; 00112 $delegate =& $rec->_table->getDelegate(); 00113 00114 00115 // Give the delegate classes an opportunity to have some fun 00116 if ( isset($delegate) and method_exists($delegate, 'beforeRegister') ){ 00117 $res = $delegate->beforeRegister($rec); 00118 if ( PEAR::isError($res) ){ 00119 return $res; 00120 } 00121 } 00122 00123 $appdel = & $app->getDelegate(); 00124 if ( isset($appdel) and method_exists($appdel, 'beforeRegister') ){ 00125 $res = $appdel->beforeRegister($rec); 00126 if ( PEAR::isError($res) ) return $res; 00127 } 00128 00129 // This is where we actually do the processing. This passes control 00130 // to the processRegistrationForm method in this class. 00131 $res = $this->form->process(array(&$this, 'processRegistrationForm'), true); 00132 00133 // If there was an error in processing mark the error, and show the 00134 // form again. Otherwise we just redirect to the next page and 00135 // let the user know that he was successful. 00136 if ( PEAR::isError($res) ){ 00137 $app->addError($res); 00138 00139 } else { 00140 00141 // Let the delegate classes perform their victory lap.. 00142 if ( isset($delegate) and method_exists($delegate, 'afterRegister') ){ 00143 $res = $delegate->afterRegister($rec); 00144 if ( PEAR::isError($res) ) return $res; 00145 } 00146 00147 if ( isset($appdel) and method_exists($appdel, 'afterRegister') ){ 00148 $res = $appdel->afterRegister($rec); 00149 if ( PEAR::isError($res) ) return $res; 00150 } 00151 00152 00153 // We accept --redirect markers to specify which page to redirect 00154 // to after we're done. This will usually be the page that the 00155 // user was on before they went to the login page. 00156 if ( isset($_SESSION['--redirect']) ) $url = $_SESSION['--redirect']; 00157 else if ( isset($_SESSION['-redirect']) ) $url = $_SESSION['-redirect']; 00158 else if ( isset($_REQUEST['--redirect']) ) $url = $_REQUEST['--redirect']; 00159 else if ( isset($_REQUEST['-redirect']) ) $url = $_REQUEST['-redirect']; 00160 else $url = $app->url('-action='.$app->_conf['default_action']); 00161 00162 if ( @$params['email_validation'] ){ 00163 $individual = $this->ontology->newIndividual($this->form->_record); 00164 $msg = df_translate('actions.register.MESSAGE_THANKYOU_PLEASE_VALIDATE', 00165 'Thank you. An email has been sent to '.$individual->strval('email').' with instructions on how to complete the registration process.', 00166 array('email'=>$individual->strval('email')) 00167 ); 00168 } else { 00169 // To save the user from having to log in after he has just filled 00170 // in the registration form, we will just log him in right here. 00171 $_SESSION['UserName'] = $this->form->exportValue($app->_conf['_auth']['username_column']); 00172 $msg = df_translate('actions.register.MESSAGE_REGISTRATION_SUCCESSFUL', 00173 "Registration successful. You are now logged in." 00174 ); 00175 } 00176 // Now we actually forward to the success page along with a success message 00177 if ( strpos($url, '?') === false ) $url .= '?'; 00178 $app->redirect($url.'&--msg='.urlencode($msg)); 00179 } 00180 } 00181 00182 // We want to display the form, but not yet so we will use an output buffer 00183 // to store the form HTML in a variable and pass it to our template. 00184 ob_start(); 00185 $this->form->display(); 00186 $out = ob_get_contents(); 00187 ob_end_clean(); 00188 00189 $context = array('registration_form'=>$out); 00190 00191 // We don't want to keep the registration page in history, because we want to 00192 // be able to redirect the user back to where he came from before registering. 00193 $app->prefs['no_history'] = true; 00194 df_display($context, 'Dataface_Registration.html'); 00195 00196 } 00197 00201 function createRegistrationTable(){ 00202 if ( !Dataface_Table::tableExists('dataface__registrations', false) ){ 00203 $sql = "create table `dataface__registrations` ( 00204 registration_code varchar(32) not null, 00205 registration_date timestamp(11) not null, 00206 registration_data longtext not null, 00207 primary key (registration_code))"; 00208 // registration_code stores an md5 code used to identify the registration 00209 // registration_date is the date that the registration was made 00210 // registration_data is a serialized array of the data from getValues() 00211 // on the record. 00212 00213 00214 $res = mysql_query($sql, df_db()); 00215 if ( !$res ) throw new Exception(mysql_error(df_db()), E_USER_ERROR); 00216 } 00217 return true; 00218 00219 } 00220 00227 function validateRegistrationForm($values){ 00228 00229 $app =& Dataface_Application::getInstance(); 00230 $del =& $app->getDelegate(); 00231 if ( $del and method_exists($del,'validateRegistrationForm') ){ 00232 $res = $del->validateRegistrationForm($values); 00233 if ( PEAR::isError($res) ) return $res; 00234 else if ( is_int($res) and $res === 2 ) return true; 00235 } 00236 $conf =& $app->_conf['_auth']; 00237 00238 // Make sure username is supplied 00239 if ( !@$values[$conf['username_column']] ) 00240 return PEAR::raiseError( 00241 df_translate('actions.register.MESSAGE_USERNAME_REQUIRED', 'Please enter a username') 00242 ); 00243 00244 00245 // Check for a duplicate username 00246 $res = mysql_query("select count(*) from `".$conf['users_table']."` where `".$conf['username_column']."` = '".addslashes($values[$conf['username_column']])."'", df_db()); 00247 if ( !$res ) throw new Exception(mysql_error(df_db()), E_USER_ERROR); 00248 00249 list($num) = mysql_fetch_row($res); 00250 if ( $num>0 ){ 00251 return PEAR::raiseError( 00252 df_translate('actions.register.MESSAGE_USERNAME_ALREADY_TAKEN', 'Sorry, that username is already in use by another user.') 00253 ); 00254 } 00255 00256 // Make sure that the user supplied a password 00257 if ( !@$values[$conf['password_column']] ) 00258 return PEAR::raiseError( 00259 df_translate('actions.register.MESSAGE_PASSWORD_REQUIRED', 'Please enter a password') 00260 ); 00261 00262 // Make sure that the user supplied an email address - and that the email address is valid 00263 $emailField = $this->ontology->getFieldname('email'); 00264 if ( !@$values[$emailField] or !$this->ontology->validate('email', @$values[$emailField], false /*No blanks*/)) 00265 return PEAR::raiseError( 00266 df_translate('actions.register.MESSAGE_EMAIL_REQUIRED', 'Please enter a valid email address in order to register. A valid email address is required because an email will be sent to the address with information on how to activate this account.') 00267 ); 00268 00269 return true; 00270 } 00271 00272 00273 function _fireDelegateMethod($name, &$record, $params=null){ 00274 $app =& Dataface_Application::getInstance(); 00275 $table = & Dataface_Table::loadTable($app->_conf['_auth']['users_table']); 00276 00277 $appdel =& $app->getDelegate(); 00278 $tdel =& $table->getDelegate(); 00279 00280 if ( isset($tdel) and method_exists($tdel, $name) ){ 00281 $res = $tdel->$name($record, $params); 00282 if ( !PEAR::isError($res) or ($res->getCode() != DATAFACE_E_REQUEST_NOT_HANDLED) ){ 00283 return $res; 00284 } 00285 } 00286 00287 if ( isset($appdel) and method_exists($appdel, $name) ){ 00288 $res = $appdel->$name($record, $params); 00289 if ( !PEAR::isError($res) or ($res->getCode() != DATAFACE_E_REQUEST_NOT_HANDLED) ){ 00290 return $res; 00291 } 00292 } 00293 return PEAR::raiseError("No delegate method found named '$name'.", DATAFACE_E_REQUEST_NOT_HANDLED); 00294 } 00295 00296 00297 00298 function processRegistrationForm($values){ 00299 00300 $app =& Dataface_Application::getInstance(); 00301 $conf =& $app->_conf['_auth']; 00302 $appConf =& $app->conf(); 00303 $table =& Dataface_Table::loadTable($conf['users_table']); 00304 00305 if ( @$this->params['email_validation'] ){ 00306 00307 // Let's try to create the registration table if it doesn't already 00308 // exist 00309 $this->createRegistrationTable(); 00310 00311 // Now we will store the registration attempt 00312 00313 // A unique code to be used as an id 00314 $code = null; 00315 do { 00316 $code = md5(rand()); 00317 } while ( 00318 mysql_num_rows( 00319 mysql_query( 00320 "select registration_code 00321 from dataface__registrations 00322 where registration_code='".addslashes($code)."'", 00323 df_db() 00324 ) 00325 ) 00326 ); 00327 00328 // Now that we have a unique id, we can insert the value 00329 00330 $sql = "insert into dataface__registrations 00331 (registration_code, registration_data) values 00332 ('".addslashes($code)."', 00333 '".addslashes( 00334 serialize( 00335 $this->form->_record->getValues() 00336 ) 00337 )."')"; 00338 $res = mysql_query($sql, df_db()); 00339 if ( !$res ) throw new Exception(mysql_error(df_db()), E_USER_ERROR); 00340 00341 $activation_url = $_SERVER['HOST_URI'].DATAFACE_SITE_HREF.'?-action=activate&code='.urlencode($code); 00342 00343 // Now that the registration information has been inserted, we need 00344 // to send the confirmation email 00345 // Let's try to send the email if possible. 00346 $res = $this->_fireDelegateMethod('sendRegistrationActivationEmail', $this->form->_record, $activation_url ); 00347 if ( !PEAR::isError($res) or ( $res->getCode() != DATAFACE_E_REQUEST_NOT_HANDLED) ){ 00348 return $res; 00349 } 00350 00351 // If we got this far, that means that we haven't sent the email yet... Rather 00352 // let's send it outselves. 00353 // We use the Person Ontology to work with the users table record in a more 00354 // generic way. 00355 $registrant =& $this->ontology->newIndividual($this->form->_record); 00356 // We now have the user's email address 00357 $email = $registrant->strval('email'); 00358 00359 // Let's get the email info. This will return an associative array 00360 // of the parameters involved in the registration email. The keys 00361 // are: 00362 // 1. subject 00363 // 2. message 00364 // 3. headers 00365 // 4. parameters 00366 // These are such that they can be passed directly to the mail function 00367 $info = $this->_fireDelegateMethod('getRegistrationActivationEmailInfo', $this->form->_record, $activation_url); 00368 if ( PEAR::isError($info) ) $info = array(); 00369 $info['to'] = $email; 00370 00371 // Override specific parts of the message if delegate class wants it. 00372 $subject = $this->_fireDelegateMethod('getRegistrationActivationEmailSubject', $this->form->_record, $activation_url); 00373 if ( !PEAR::isError($subject) ) $info['subject'] = $subject; 00374 00375 00376 $message = $this->_fireDelegateMethod('getRegistrationActivationEmailMessage', $this->form->_record, $activation_url); 00377 if ( !PEAR::isError($message) ) $info['message'] = $message; 00378 00379 $parameters = $this->_fireDelegateMethod('getRegistrationActivationEmailParameters', $this->form->_record, $activation_url); 00380 if ( !PEAR::isError($parameters) ) $info['parameters'] = $parameters; 00381 00382 $headers = $this->_fireDelegateMethod('getRegistrationActivationEmailHeaders', $this->form->_record, $activation_url); 00383 if ( !PEAR::isError($headers) ) $info['headers'] = $headers; 00384 00385 00386 // Now we fill in the missing information with defaults 00387 if ( !@$info['subject'] ) 00388 $info['subject'] = df_translate( 00389 'actions.register.MESSAGE_REGISTRATION_ACTIVATION_EMAIL_SUBJECT', 00390 $app->getSiteTitle().': Activate your account', 00391 array('site_title'=>$app->getSiteTitle()) 00392 ); 00393 00394 if ( !@$info['message'] ){ 00395 $site_title = $app->getSiteTitle(); 00396 if ( isset($appConf['abuse_email']) ){ 00397 $admin_email = $appConf['abuse_email']; 00398 } else if ( isset($appConf['admin_email']) ){ 00399 $admin_email = $appConf['admin_email']; 00400 } else { 00401 $admin_email = $_SERVER['SERVER_ADMIN']; 00402 } 00403 00404 if ( isset( $appConf['application_name'] ) ){ 00405 $application_name = $appConf['application_name']; 00406 } else { 00407 $application_name = df_translate('actions.register.LABEL_A_DATAFACE_APPLICATION','a Dataface Application'); 00408 } 00409 00410 if ( file_exists('version.txt') ){ 00411 $application_version = trim(file_get_contents('version.txt')); 00412 } else { 00413 $application_version = '0.1'; 00414 } 00415 00416 if ( file_exists(DATAFACE_PATH.'/version.txt') ){ 00417 $dataface_version = trim(file_get_contents(DATAFACE_PATH.'/version.txt')); 00418 } else { 00419 $dataface_version = 'unknown'; 00420 } 00421 00422 00423 00424 00425 $msg = <<<END 00426 Thank you for registering for an account on $site_title . In order to complete your registration, 00427 please visit $activation_url . 00428 00429 If you have not registered for an account on this web site and believe that you have received 00430 this email eroneously, please report this to $admin_email . 00431 ----------------------------------------------------------- 00432 This message was sent by $site_title which is powered by $application_name version $application_version 00433 $application_name built using Dataface version $dataface_version (http://fas.sfu.ca/dataface). 00434 END; 00435 00436 $info['message'] = df_translate( 00437 'actions.register.MESSAGE_REGISTRATION_ACTIVATION_EMAIL_MESSAGE', 00438 $msg, 00439 array( 00440 'site_title'=>$site_title, 00441 'activation_url'=>$activation_url, 00442 'admin_email'=>$admin_email, 00443 'application_name'=>$application_name, 00444 'application_version'=>$application_version, 00445 'dataface_version'=>$dataface_version 00446 ) 00447 ); 00448 00449 00450 } 00451 00452 // Now that we have all of the information ready to send. Let's send 00453 // the email message. 00454 00455 if ( @$conf['_mail']['func'] ) $func = $conf['_mail']['func']; 00456 else $func = 'mail'; 00457 $res = $func($info['to'], 00458 $info['subject'], 00459 $info['message'], 00460 @$info['headers'], 00461 @$info['parameters']); 00462 if ( !$res ){ 00463 return PEAR::raiseError('Failed to send activation email. Please try again later.', DATAFACE_E_ERROR); 00464 } else { 00465 return true; 00466 } 00467 00468 } else { 00469 // We aren't using email validation.. let's just pass it to the 00470 // form's standard processing function. 00471 return $this->form->process(array(&$this->form, 'save'), true); 00472 } 00473 00474 } 00475 } 00476 00477 class dataface_actions_register_permissions_delegate { 00478 function filterPermissions(&$obj, &$perms){ 00479 if ( @$perms['register'] ) $perms['new'] = 1; 00480 } 00481 } 00482 00483 ?>