/** * Queries the database with the given sql query. * This currently passes the query straight through to * xf_db_query, but it will be modified in the future to * automatically filter out blobs (because normally we don't want to * retrieve blob columns. */ function query($sql, $db = null, $lang = null, $as_array = false, $enumerated = false) { $app =& Dataface_Application::getInstance(); $refreshModTimes = false; if ($as_array and $isSelect = strpos(strtolower(trim($sql)), 'select ') === 0) { if ($results = $this->memcache_get($sql, $lang) or is_array($results)) { if (@$this->app->_conf['cache_queries_log']) { $fp = fopen('/tmp/querylog.log', 'a'); fwrite($fp, "\n[" . date('Y-m-d H:i:s') . "] Cached: " . $sql); fclose($fp); } $this->cache_hits++; return $results; } else { if (@$this->app->_conf['cache_queries_log']) { $fp = fopen('/tmp/querylog.log', 'a'); fwrite($fp, "\n[" . date('Y-m-d H:i:s') . "] Failed cached: " . $sql); fclose($fp); } $this->cache_fails++; $orig_sql = $sql; // save the original sql before it is translated } } else { if (@$app->_conf['cache_queries']) { $refreshModTimes = true; } } //$fp = fopen('/tmp/querylog.log', 'a'); //fwrite($fp, "\n[".date('Y-m-d H:i:s')."] Uncached: ".$sql); //fclose($fp); $this->count++; if ($this->app->_conf['multilingual_content']) { if (@$app->_conf['debug_sql']) { error_log("Before translation: " . $sql); } $sql = $this->translate_query($sql, $lang); if (PEAR::isError($sql)) { return $sql; } if (@$app->_conf['debug_sql']) { if (is_array($sql)) { foreach ($sql as $sqli) { error_log("After translation: " . $sqli); } } else { error_log("After translation: " . $sql); } } } if (!isset($db)) { $db = $this->app->db(); } $update_insert_id = true; if (is_array($sql)) { $loopctr = 0; foreach ($sql as $q) { if ($loopctr++ > 0 and xf_db_insert_id($db)) { $this->_insert_id = xf_db_insert_id($db); $update_insert_id = false; $q = str_replace("'%%%%%__MYSQL_INSERT_ID__%%%%%'", xf_db_insert_id($db), $q); } if (defined('DATAFACE_DEBUG_DB') or @$app->_conf['debug_sql']) { echo "Performing query: '{$q}' <br>"; } $res = xf_db_query($q, $db); } } else { if (defined('DATAFACE_DEBUG_DB') or @$app->_conf['debug_sql']) { echo "Performing query: '{$sql}' <br>"; } $this->db_hits++; $res = xf_db_query($sql, $db); } if ($update_insert_id) { $this->_insert_id = xf_db_insert_id($db); } if ($res and $refreshModTimes) { Dataface_Table::getTableModificationTimes(true); } if ($as_array and $isSelect) { if (!$res) { return $res; } // We want to return this as an array rather than a resource $out = array(); while ($row = $enumerated ? xf_db_fetch_row($res) : xf_db_fetch_assoc($res)) { $out[] = $row; } $this->memcache_set($orig_sql, $lang, $out); @xf_db_free_result($res); return $out; } return $res; }
/** * Backs up a record to the history table. This will automatically happen * when using Dataface_IO::save() if the [history] section exists in the * conf.ini file. * * @param Dataface_Record &$record The record that is being backed up. * @param string $comments Comments about this version to be stored. * @param string $lang The 2-digit language code of which language * to use to back up this record. If none is specified * then the current language of the system will be used. * @param integer $state Unused as yet. Was intended to store state/workflow * information.. but .. * @returns integer The history id of the resulting history record. */ function logRecord(&$record, $comments = '', $lang = null, $state = null) { $app =& Dataface_Application::getInstance(); if (!isset($lang)) { $lang = $app->_conf['lang']; } if (!isset($state)) { $state = 0; } $fieldnames = array_keys($record->_table->fields()); $sql = 'select `' . implode('`,`', $fieldnames) . '` from `' . $record->_table->tablename . '` where'; $keynames = array_keys($record->_table->keys()); $where_clauses = array(); foreach ($keynames as $keyname) { $where_clauses[] = '`' . $keyname . '`=\'' . addslashes($record->strval($keyname)) . '\''; } $sql .= ' ' . implode(' and ', $where_clauses); if (@$app->_conf['multilingual_content']) { $db =& Dataface_DB::getInstance(); $sql = $db->translate_query($sql, $lang); $sql = $sql[0]; } $auth =& Dataface_AuthenticationTool::getInstance(); $userRecord =& $auth->getLoggedInUser(); if (!isset($userRecord)) { $user = null; } else { $user = $auth->getLoggedInUsername(); } $insertsql = "insert into `" . $this->logTableName($record->_table->tablename) . "` \n\t\t\t(`" . implode('`,`', $fieldnames) . "`, `history__language`,`history__comments`,`history__user`,`history__state`,`history__modified`) \n\t\t\tselect *, '" . addslashes($lang) . "','" . addslashes($comments) . "','" . addslashes($user) . "','" . addslashes($state) . "', NOW() \n\t\t\tfrom (" . $sql . ") as t"; $res = xf_db_query($insertsql, $app->db()); if (!$res) { $this->updateHistoryTable($record->_table->tablename); $res = xf_db_query($insertsql, $app->db()); } if (!$res) { echo $insertsql; trigger_error(xf_db_error($app->db()), E_USER_ERROR); } // Now for the individual fields $hid = xf_db_insert_id($app->db()); foreach ($fieldnames as $fieldname) { $this->logField($record, $fieldname, $hid); } return $hid; }
/** * Sends the reset email to a particular user. * * @param Dataface_Record $user The user record. * @return true on success * * @throws Exception code: self::$EX_NO_USERNAME_FOR_USER If username is blank * @throws Exception code: self::$EX_NO_EMAIL_COLUMN_FOUND No email column was found in the users table. * @throws Exception code: self::$EX_NO_USERS_FOUND_WITH_EMAIL If the user record doesn't have an email address. */ public function send_reset_email_for_user(Dataface_Record $user) { $app = Dataface_Application::getInstance(); $auth = Dataface_AuthenticationTool::getInstance(); $emailCol = $auth->getEmailColumn(); $usernameCol = $auth->usernameColumn; if (!$emailCol) { throw new Exception(df_translate('actions.forgot_password.no_email_column_found', "No Email Column found in the users table. Please specify one using the email_column directive in the [_auth] section of the conf.ini file."), self::$EX_NO_EMAIL_COLUMN_FOUND); } if (!$usernameCol) { throw new Exception(df_translate('actions.forgot_password.no_username_column_found', "No username column found in the users table. Please specify one using the username_column directive in the [_auth] section of the conf.ini file."), self::$EX_NO_USERNAME_COLUMN_FOUND); } if (!$user) { throw new Exception(df_translate('actions.forgot_password.null_user', "Cannot send email for null user"), self::$EX_NO_USERS_FOUND_WITH_EMAIL); } $username = $user->val($usernameCol); if (!$username) { throw new Exception(df_translate('actions.forgot_password.user_without_name', "Cannot reset password for user without a username"), self::$EX_NO_USERNAME_FOR_USER); } $email = $user->val($emailCol); if (!$email) { throw new Exception(df_translate('actions.forgot_password.user_without_email', "User has not email address on file"), $EX_NO_EMAIL_FOR_USER); } $ip = null; $val = ip2long($_SERVER['REMOTE_ADDR']); if ($val !== false) { $ip = sprintf('%u', $val); } else { $ip = 0; //If IP is empty MySQL throws Incorrect Integer value on insert } $expire_seconds = 600; if (@$app->_conf['reset_password_expiry']) { $expire_seconds = intval($app->_conf['reset_password_expiry']); } // Insert the entry $this->create_reset_password_table(); $table = self::$TABLE_RESET_PASSWORD; $sql = "insert into `{$table}`\n\t\t\t(`request_uuid`, `username`, `request_ip`, `date_created`, `expires`)\n\t\t\tvalues\n\t\t\t(UUID(),'" . addslashes($username) . "','" . addslashes($ip) . "', NOW(), " . (time() + $expire_seconds) . ")"; $res = xf_db_query($sql, df_db()); if (!$res) { throw new Exception(xf_db_error(df_db())); } $id = xf_db_insert_id(df_db()); $res = xf_db_query("select * from `{$table}` where request_id='" . addslashes($id) . "'", df_db()); if (!$res) { throw new Exception(xf_db_error(df_db())); } $row = xf_db_fetch_assoc($res); if (!$row) { throw new Exception(df_translate('actions.forgot_password.failed_fetch_password_row', "Failed to fetch reset password request row from database after it has been inserted. This should never happen ... must be a bug")); } $uuid = $row['request_uuid']; if (!$uuid) { throw new Exception(df_translate('actions.forgot_password.blank_uuid_for_reset_request', "Blank uuid for the reset request. This should never happen. Must be a bug.")); } $url = df_absolute_url(DATAFACE_SITE_HREF . '?-action=forgot_password&--uuid=' . $uuid); $site_url = df_absolute_url(DATAFACE_SITE_URL); $msg = df_translate('actions.forgot_password.reset_password_request_email_body', <<<END You have requested to reset the password for the user '{$username}'. Please go to the URL below in order to proceed with resetting your password: <{$url}> If you did not make this request, please disregard this email. END , array('username' => $username, 'url' => $url)); $subject = df_translate('actions.forgot_password.password_reset', "Password Reset"); $del = $app->getDelegate(); $info = array(); if (isset($del) and method_exists($del, 'getResetPasswordEmailInfo')) { $info = $del->getResetPasswordEmailInfo($user, $url); } if (isset($info['subject'])) { $subject = $info['subject']; } if (isset($info['message'])) { $msg = $info['message']; } $parameters = null; if (isset($info['parameters'])) { $parameters = $info['parameters']; } $site_title = $app->getSiteTitle(); $support_email = $_SERVER['SERVER_ADMIN']; if (isset($app->_conf['admin_email'])) { $support_email = $app->_conf['admin_email']; } if (isset($app->_conf['support_email'])) { $support_email = $app->_conf['support_email']; } $from_email = $support_email; if (strpos($support_email, '>') === false) { $from_email = $site_title . ' <' . $support_email . '>'; } $headers = 'From: ' . $from_email . "\r\nReply-to: " . $from_email . "\r\nContent-type: text/plain; charset=" . $app->_conf['oe']; if (isset($info['headers'])) { $headers = $info['headers']; } //echo "Subject: $subject \nEmail: $email \n$msg \nHeaders: $headers";exit; if (@$app->_conf['_mail']['func']) { $func = $app->_conf['_mail']['func']; } else { $func = 'mail'; } $res = $func($email, $subject, $msg, $headers, $parameters); if (!$res) { throw new Exception(df_translate('actions.forgot_password.failed_send_activation', "Failed to send activation email. Please try again later."), DATAFACE_E_ERROR); } else { //echo "Successfully sent mail to $email";exit; return true; } }
/** * Returns the next free id in a sequence * * @param string $seq_name name of the sequence * @param boolean $ondemand when true, the seqence is automatically * created if it does not exist * * @return int the next id number in the sequence. * A DB_Error object on failure. * * @see DB_common::nextID(), DB_common::getSequenceName(), * DB_mysql::createSequence(), DB_mysql::dropSequence() */ function nextId($seq_name, $ondemand = true) { $seqname = $this->getSequenceName($seq_name); do { $repeat = 0; $this->pushErrorHandling(PEAR_ERROR_RETURN); $result = $this->query("UPDATE {$seqname} " . 'SET id=LAST_INSERT_ID(id+1)'); $this->popErrorHandling(); if ($result === DB_OK) { // COMMON CASE $id = @xf_db_insert_id($this->connection); if ($id != 0) { return $id; } // EMPTY SEQ TABLE // Sequence table must be empty for some reason, so fill // it and return 1 and obtain a user-level lock $result = $this->getOne("SELECT GET_LOCK('{$seqname}_lock',10)"); if (DB::isError($result)) { return $this->raiseError($result); } if ($result == 0) { // Failed to get the lock return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); } // add the default value $result = $this->query("REPLACE INTO {$seqname} (id) VALUES (0)"); if (DB::isError($result)) { return $this->raiseError($result); } // Release the lock $result = $this->getOne('SELECT RELEASE_LOCK(' . "'{$seqname}_lock')"); if (DB::isError($result)) { return $this->raiseError($result); } // We know what the result will be, so no need to try again return 1; } elseif ($ondemand && DB::isError($result) && $result->getCode() == DB_ERROR_NOSUCHTABLE) { // ONDEMAND TABLE CREATION $result = $this->createSequence($seq_name); if (DB::isError($result)) { return $this->raiseError($result); } else { $repeat = 1; } } elseif (DB::isError($result) && $result->getCode() == DB_ERROR_ALREADY_EXISTS) { // BACKWARDS COMPAT // see _BCsequence() comment $result = $this->_BCsequence($seqname); if (DB::isError($result)) { return $this->raiseError($result); } $repeat = 1; } } while ($repeat); return $this->raiseError($result); }
public function getInsertId() { return xf_db_insert_id($this->db()); }
function getTranslationId(&$record, $language) { $app = Dataface_Application::getInstance(); $sql = "select `id` from `dataface__translations` where `record_id`='" . addslashes($this->getRecordId($record)) . "' and `table`='" . addslashes($record->_table->tablename) . "' and `language`='" . addslashes($language) . "' limit 1"; $res = xf_db_query($sql, $app->db()); if (!$res) { $this->updateTranslationsTable(); $res = xf_db_query($sql, $app->db()); if (!$res) { throw new Exception(xf_db_error($app->db()), E_USER_ERROR); } } if (xf_db_num_rows($res) === 0) { @xf_db_free_result($res); $sql = "insert into `dataface__translations` (`record_id`,`language`,`table`,`last_modified`) VALUES (\n\t\t\t\t\t'" . addslashes($this->getRecordId($record)) . "',\n\t\t\t\t\t'" . addslashes($language) . "',\n\t\t\t\t\t'" . addslashes($record->_table->tablename) . "',\n\t\t\t\t\tNOW()\n\t\t\t\t\t)"; $res = xf_db_query($sql, $app->db()); if (!$res) { $this->updateTranslationsTable(); $res = xf_db_query($sql, $app->db()); if (!$res) { throw new Exception(xf_db_error($app->db()), E_USER_ERROR); } } $id = xf_db_insert_id($app->db()); } else { list($id) = xf_db_fetch_row($res); @xf_db_free_result($res); } return $id; }
function post($token = null, $comment, $uploaded_image_path) { $db = new Database(df_db()); global $error_message; $user = get_user($token); if (!$user) { $error_message = "Not logged in"; return false; } $filename = null; if (@$uploaded_image_path) { $imagesDir = 'uploads'; @mkdir($imagesDir); $imagesDir = 'uploads/' . sha1($user); @mkdir($imagesDir); $filename = time() . basename($uploaded_image_path) . '.png'; if (!move_uploaded_file($uploaded_image_path, $imagesDir . '/' . $filename)) { $error_message = "Failed to upload file"; return false; } } try { $res = $db->insertObject("posts", (object) array('username' => $user, 'date_posted' => time(), 'photo' => $filename, 'comment' => $comment)); return xf_db_insert_id(df_db()); } catch (Exception $ex) { $error_message = $ex->getMessage(); return false; } }
public function buildRecord(xatacard_layout_Schema $schema, Dataface_Record $rec) { //Now we populate the record $out = new xatacard_layout_Record(); $out->setSchema($schema); $out->setDataSource($this); $recordCache = array(); $recordCache[$rec->getId()] = $rec; $recordData = array('records' => array(), 'fields' => array()); $recordIdToIndex = array(); foreach ($schema->getFields() as $key => $value) { if (strpos($key, '/') !== false) { // this is a first class property of the record so we can just get it. $index = count($recordData['records']); $recordData['records'][$index] = array('id' => $rec->getId(), 'version' => $rec->getVersion()); $recordIdToIndex[$rec->getId()] = $index; $recordData['fields'][$key] = $recordIdToIndex[$rec->getId()]; $out->setValue($key, $rec->getValue($key)); } else { // this is a related record's property that we need to get from the related // records. $path = explode('/', $key); $crec = $rec; // As we're going to be going through related records // we need to mark the current record we are dealing /// with $fieldName = array_pop($path); // A flag to indicate if we should break the outer loop // after the inner loop finishes $shouldSkip = false; foreach ($path as $part) { $index = 0; if (preg_match('/^(.*)\\[(\\d+\\)]$/', $part, $matches)) { $index = intval($matches[2]); $part = $matches[1]; } $related = $crec->getRelatedRecord($part, $index); if (PEAR::isError($related)) { throw new Exception(sprintf("MySQL datasource failed to load record because there was an error retrieving a column from a related record. The field '%s' could not be retrieved because the following error: %s", $key, $related->getMessage())); } if (!$related) { // No related record could be found to satisfy this path. // This doesn't constitute an error. It just means that the // value should be blank. $out->setValue($key, null); $shouldSkip = true; break; } unset($crec); if (@$this->recordCache[$related->getId()]) { $crec = $this->recordCache[$related->getId()]; } else { $crec = $related->toRecord(); $this->recordCache[$related->getId()] = $crec; $index = count($recordData['records']); $recordData['records'][$index] = array('id' => $crec->getId(), 'version' => $rec->getVersion()); $recordIdToIndex[$crec->getId()] = $index; } unset($related); } if ($shouldSkip) { // Something occurred in the inner loop to // complete this step so we should skip the rest // of this stuff. continue; } if (!$crec) { // This should never happen throw new Exception(sprintf("MySQL datasource failed to load record because there was an error retrieving a related record required for one of the fields. The field '%s' could not be retrieved.", $key)); } $recordData['fields'][$key] = $recordIdToIndex[$crec->getId()]; $out->setValue($key, $crec->val($fieldName)); } } $cacheKeys = array_keys($recordCache); sort($cacheKeys); $versionstring = array(); foreach ($cacheKeys as $k) { $versionstring[] = $k . ':' . $recordCache[$k]->getVersion(); } $versionstring = implode(' ', $versionstring); $versionhash = md5($versionstring); $res = $this->query(sprintf("select `id` from `%s` where \n\t\t\t\tschema_id=%d and \n\t\t\t\tbase_record_id_hash='%s' and \n\t\t\t\tversion_hash='%s' and\n\t\t\t\t`lang`='%s'", str_replace('`', '', self::$RECORDS_TABLE), intval($schema->getId()), addslashes(md5($rec->getId())), addslashes($versionhash), addslashes($rec->lang))); if (xf_db_num_rows($res) >= 0) { $row = xf_db_fetch_row($res); $out->setId($row[0]); } else { $res = $this->query(sprintf("insert into `%s` (schema_id, base_record_id_hash, base_record_id, version_hash, `lang`, `record_data`)\n\t\t\t\tvalues (\n\t\t\t\t\t%d, '%s', '%s', '%s', '%s'\n\t\t\t\t)", intval($schema->getId()), addslashes(md5($rec->getId())), addslashes($rec->getid()), addslashes($versionhash), addslashes($rec->lang), addslashes(json_encode($recordData)))); $out->setId(xf_db_insert_id(df_db())); } $out->clearSnapshot(); return $out; }