function strbool($bool) { // returns the string of a boolean as 'true' or 'false'. if (is_string($bool)) { $bool = boolstr($bool); } // if a string is passed, convert it to a bool if (is_bool($bool)) { return $bool ? 'true' : 'false'; } else { return false; } }
$openid->required = array('username' => 'contact/email', 'name' => 'namePerson', 'dname' => 'namePerson/friendly', 'zip' => 'contact/postalCode/home'); } else { $openid->required = array('username' => 'contact/email'); $openid->optional = array('name' => 'namePerson', 'dname' => 'namePerson/friendly', 'zip' => 'contact/postalCode/home'); } } $openid->returnURL = $returnurl; header('Location: ' . $openid->authUrl()); } $buffer .= "\n<form action='' method='post'>\n <label for='openid_url'>OpenID: </label><input type='text' name='openid_url' required='required' /> <button>Submit</button>\n</form>"; } else { if ($openid->mode == 'cancel') { $buffer .= 'User has canceled authentication!'; // handle the rejection } else { $ok = boolstr($openid->validate()); if ($ok) { $data = $openid->getAttributes(); if ($signin_type != 'new') { // Do a user lookup for login // identity provider --> password // the [contact/email] field is their user id. // If it fails, offer to create a new user // if so, change $signin_type so it triggers the subsequent code block ... } if ($signin_type == 'new') { // Create a user require 'modular/login_functions.php'; $res = createUser($data['contact/email'], $provider, $data['namePerson'], $data['namePerson/friendly'], $data['contact/postalCode/home']); // handle the user creation // Direct to profile editor
function registerApp($appInformation) { /*** * * * @param bool new_user flag to create a new user * * These keys are for all new device registrations, including new * user creation * @key email username * @key string password a URL-encoded password * @key phone_verify (when asked) * @key string key the encryption key * * These keys are only for new user creation * @key string first_name * @key string last_name * @key int phone * @key string handle the display username ***/ $username = $appInformation['username']; $device = $appInformation['device']; $newUser = boolstr($appInformation['new_user']); $return_data = array(); $validuser_data = array(); $u = new UserFunctions(); $password = urldecode($appInformation['password']); $encryption_key = $appInformation['key']; if (isNull($password) || isNull($username) || isNull($device) || isNull($encryption_key)) { return array('status' => false, 'error' => 'Required parameters missing', 'have_username' => !isNull($username), 'have_password' => !isNull($password), 'have_device' => !isNull($device), 'have_encryption_key' => !isNull($encryption_key)); } if ($newUser) { # Start the new user creation process # The application should have verified password correctness $name = array($appInformation['first_name'], $appInformation['last_name']); $handle = $appInformation['handle']; $phone = $appInformation['phone']; if (isNull($appInformation['first_name']) || isNull($appInformation['last_name']) || isNull($phone) || isNull($handle)) { return array('status' => false, 'error' => 'Required parameters missing', 'have_name' => !isNull($name), 'have_phone' => !isNull($phone), 'have_handle' => !isNull($handle)); } $result = $u->createUser($username, $password, $name, $handle, $phone); if ($result['status'] != true) { if (empty($r['human_error'])) { $result['human_error'] = $result['error']; $result['app_error_code'] = 999; } return $result; } $return_data['dblink'] = $result['dblink']; $validuser_data['dblink'] = $result['dblink']; $validuser_data['secret'] = $result['raw_secret']; $validuser_data['hash'] = $result['raw_auth']; } else { # Verify the user # Set up equivalent variables to finish registering the app $totp = isset($appInformation['totp']) ? $appInformation['totp'] : false; $result = $u->lookupUser($username, $password, true, $totp); if ($result['status'] === false && $result['totp'] === true) { $u->sendTOTPText(); return array('status' => false, 'human_error' => $result['human_error'], 'error' => $result['error'], 'app_error_code' => 109); } # Get the cookie tokens we'll use to validate in registerApp() $cookies = $u->createCookieTokens($result['data']); $return_data['dblink'] = $result['data']['dblink']; $validuser_data['dblink'] = $result['data']['dblink']; $validuser_data['secret'] = $cookies['raw_secret']; $validuser_data['hash'] = $cookies['raw_auth']; } # Get the data we need $phone_verify_code = $appInformation['phone_verify']; $r = $u->registerApp($validuser_data, $encryption_key, $device, $phone_verify_code); if ($r['status'] === false) { # Phone needs validation. Return the dblink and request # validation. Upon validation, re-ping this same target if ($r['app_error_code'] == 111) { return array_merge($r, array($return_data)); } if (empty($r['human_error'])) { $r['human_error'] = $r['error']; $r['app_error_code'] = 999; } # $r["cookies"] = $cookies; # $r["lookup_data"] = $result; return $r; } $return_data['secret'] = $r['secret']; $return_data = array_merge(array('status' => true, 'message' => "Successful registration of device '{$device}'", 'details' => $r), $return_data); return $return_data; }
switch ($do) { case 'parse': $validatedPath = dirname(__FILE__).'/'.$_REQUEST['path']; if (!file_exists($validatedPath)) { returnAjax(array( 'status' => false, 'error' => "Non-existant file '".$validatedPath."'", 'paths' => array( 'requested_path' => $_REQUEST['path'], 'validated_path' => $validatedPath, ), 'human_error' => 'There was a problem validating your file. Please try again.', )); } $header = isset($_REQUEST['has_header']) ? boolstr($_REQUEST['has_header']) : true; $sheets = $_REQUEST['sheets']; $sheets_arr = explode(',', $sheets); if (sizeof($sheets_arr) > 1) { # PHPExcel only wants array for many sheets $sheets = $sheets_arr; } try { returnAjax(array( 'status' => true, 'data' => excelToArray($validatedPath, $header, $sheets), 'path' => array( 'requested_path' => $_REQUEST['path'], 'validated_path' => $validatedPath, ), ));
function saveToUser($get) { /*** * These are OK to pass with plaintext, they'll change with a different device anyway (non-persistent). * Worst-case scenario it only exposes public function calls. Sensitive things will need explicit revalidation. ***/ $conf = $get['hash']; $s = $get['secret']; $id = $get['dblink']; $replace = boolstr($get['replace']); /*** * These fields can only be written to from directly inside of a script, rather than an AJAX call. ***/ $protected_fields = array('username', 'password', 'admin_flag', 'su_flag', 'private_key', 'public_key', 'creation', 'dblink', 'secret', 'emergency_code'); if (!empty($conf) && !empty($s) && !empty($id) && !empty($get['data']) && !empty($get['col'])) { $u = new UserFunctions(); if ($u->validateUser($id, $conf, $s)) { // Yes, writeToUser looks up the validation again, but it is a more robust feedback like this // Could pass in $get for validation data, but let's be more limited $val = array('dblink' => $id, 'hash' => $conf, 'secret' => $s); $data = decode64($get['data']); $col = decode64($get['col']); if (empty($data) || empty($col)) { return array('status' => false, 'error' => 'Invalid data format (required valid base64 data)'); } // User safety if (in_array($col, $protected_fields, true)) { return array('status' => false, 'error' => 'Cannot write to $col : protected field'); } return $u->writeToUser($data, $col, $val); } else { return array('status' => false, 'error' => 'Invalid user'); } } return array('status' => false, 'error' => 'One or more required fields were left blank'); }
function toBool($str) { return boolstr($str); }
function doCartoSqlApiPush($get) { global $cartodb_username, $cartodb_api_key, $db, $udb, $login_status; // error_reporting(E_ALL); // ini_set('display_errors', 1); // error_log('Login is running in debug mode!'); $sqlQuery = decode64($get['sql_query'], true); if (empty($sqlQuery)) { $sqlQuery = base64_decode(urldecode($get["sql_query"])); } $originalQuery = $sqlQuery; # If it's a "SELECT" style statement, make sure the accessing user # has permissions to read this dataset $searchSql = strtolower($sqlQuery); $queryPattern = '/(?i)([a-zA-Z]+(?: +INTO)?) +.*(?:FROM)?[ `]*(t[0-9a-f]{10,}[_]?[0-9a-f]*)[ `]*.*[;]?/m'; $statements = explode(');', $sqlQuery); $checkedTablePermissions = array(); $pidList = array(); foreach ($statements as $k => $statement) { if (empty($statement)) { unset($statements[$k]); continue; } $sqlAction = preg_replace($queryPattern, '$1', $statement); $sqlAction = strtolower(str_replace(" ", "", $sqlAction)); $restrictedActions = array("select" => "READ", "delete" => "EDIT", "insert" => "EDIT", "insertinto" => "EDIT", "update" => "EDIT"); $unrestrictedActions = array("create" => true); # Looking up the columns is a safe action if (preg_match('/\\A(?i)SELECT +\\* +(?:FROM)?[ `]*(t[0-9a-f]{10,}[_]?[0-9a-f]*)[ `]* +(WHERE FALSE)[;]?\\Z/m', $statement)) { # Successful match unset($restrictedActions["select"]); $unrestrictedActions["select"] = true; } if (isset($restrictedActions[$sqlAction])) { # Check the user # If bad, kick the access out $cartoTable = preg_replace($queryPattern, '$2', $statement); $checkedTablePermissions[] = $cartoTable; $cartoTableJson = str_replace('_', '_', $cartoTable); $accessListLookupQuery = 'SELECT `project_id`, `author`, `access_data`, `public` FROM `' . $db->getTable() . "` WHERE `carto_id` LIKE '%" . $cartoTableJson . "%' OR `carto_id` LIKE '%" . $cartoTable . "%'"; $l = $db->openDB(); $r = mysqli_query($l, $accessListLookupQuery); $row = mysqli_fetch_assoc($r); $pid = $row["project_id"]; $pidList[$cartoTable] = $pid; # Non-existant projects are fair game if (!empty($pid)) { $requestedPermission = $restrictedActions[$sqlAction]; $pArr = explode(",", $row["access_data"]); $permissions = array(); foreach ($pArr as $access) { $up = explode(":", $access); $permissions[$up[0]] = $up[1]; } # End loop $csvString = preg_replace('/(:(EDIT|READ))/m', '', $row['access_data']); $users = explode(',', $csvString); $users[] = $row['author']; $isPublic = boolstr($row['public']); $suFlag = $login_status['detail']['userdata']['su_flag']; $isSu = boolstr($suFlag); # Get current user ID if ($login_status['status'] !== true && !$isPublic) { $response = array('status' => false, 'error' => 'NOT_LOGGED_IN', 'human_error' => 'Attempted to access private project without being logged in', 'args_provided' => $get, "project_id" => $pid, "query_type" => $sqlAction, 'is_public_dataset' => $isPublic, "statement_parsed" => $statement); returnAjax($response); } # End login check $uid = $login_status['detail']['uid']; if (!in_array($uid, $users) && !$isPublic && $isSu !== true) { $response = array('status' => false, 'error' => 'UNAUTHORIZED_USER', 'human_error' => "User {$uid} isn't authorized to access this dataset", 'args_provided' => $get, "project_id" => $pid, 'is_public_dataset' => $isPublic, "statement_parsed" => $statement); returnAjax($response); } # End authorized user check if ($requestedPermission == "EDIT") { # Editing has an extra filter $hasPermission = $permissions[$uid]; if ($hasPermission !== $requestedPermission && $isSu !== true) { $response = array('status' => false, 'error' => 'UNAUTHORIZED_USER', 'human_error' => "User '{$uid}' isn't authorized to edit this dataset", 'args_provided' => $get, "project_id" => $pid, "query_type" => $sqlAction, "user_permissions" => $hasPermission, "statement_parsed" => $statement); returnAjax($response); } # End edit permission check } # End edit permission case } # End project existence check } else { if (!isset($unrestrictedActions[$sqlAction])) { # Unrecognized query type returnAjax(array("status" => false, "error" => "UNAUTHORIZED_QUERY_TYPE", "query_type" => $sqlAction, "args_provided" => $get, "statement_parsed" => $statement)); } } if (empty($statement)) { returnAjax(array('status' => false, 'error' => 'Invalid Query', 'args_provided' => $get)); } } $cartoPostUrl = 'https://' . $cartodb_username . '.cartodb.com/api/v2/sql'; $cartoArgSuffix = '&api_key=' . $cartodb_api_key; $l = sizeof($statements); $lastIndex = $l - 1; foreach ($statements as $k => $statement) { # Re-append the closing parens if (substr_count($statement, "(") === substr_count($statement, ")") + 1) { $statements[$k] = $statement . ")"; } } $responses = array(); $parsed_responses = array(); $urls = array(); ini_set('allow_url_fopen', true); try { set_time_limit(0); } catch (Exception $e) { $length = 30 * sizeof($statements); set_time_limit($length); } if (!boolstr($get['blobby'])) { foreach ($statements as $statement) { $statement = trim($statement); if (empty($statement)) { continue; } $cartoArgs = 'q=' . urlencode($statement) . $cartoArgSuffix; # Fetch a table $cartoTable = preg_replace($queryPattern, '$2', $statement); $sqlAction = preg_replace($queryPattern, '$1', $statement); $cartoFullUrl = $cartoPostUrl . '?' . $cartoArgs; $urls[] = $cartoFullUrl; if (boolstr($get['alt'])) { $responses[] = json_decode(do_post_request($cartoPostUrl, $cartoArgs, 'GET'), true); } else { # Default $opts = array('http' => array('method' => 'GET', 'ignore_errors' => true, 'timeout' => 3.5)); $context = stream_context_create($opts); $response = file_get_contents($cartoFullUrl, false, $context); $responses[] = $response; $decoded = json_decode($response, true); $decoded["query"] = $statement; $decoded["encoded_query"] = urlencode($statement); $decoded["table"] = $cartoTable; $decoded["project_id"] = $pidList[$cartoTable]; $decoded["blobby"] = false; $decoded["sql_action"] = $sqlAction; $parsed_responses[] = $decoded; } } } else { $cartoArgs = 'q=' . $sqlQuery . $cartoArgSuffix; $cartoFullUrl = $cartoPostUrl . '?' . $cartoArgs; $opts = array('http' => array('method' => 'GET', 'request_fulluri' => true, 'timeout' => 3.5)); $context = stream_context_create($opts); $response = file_get_contents($cartoFullUrl, false, $context); $responses[] = $response; $decoded = json_decode($response, true); $decoded["query"] = $sqlQuery; $decoded["blobby"] = true; $parsed_responses[] = $decoded; } try { $response = array('status' => true, 'sql_statements' => $statements, 'post_response' => $responses, 'parsed_responses' => $parsed_responses, 'blobby' => boolstr($get['blobby']), "query_type" => $sqlAction, "parsed_query" => $originalQuery, "checked_tables" => $checkedTablePermissions); if (boolstr($get['blobby'])) { $response["project_id"] = $pid; $response["query_type"] = $sqlAction; } returnAjax($response); } catch (Exception $e) { returnAjax(array('status' => false, 'error' => $e->getMessage(), 'human_error' => 'There was a problem uploading to the CartoDB server.', 'blobby' => boolstr($get['blobby']), "query_type" => $sqlAction, "project_id" => $pid)); } }
function strbool($bool) { /*** * Get the string value of a boolean value. * Therefore, (bool) true returns "true" * * @param boolean $bool * @return string ***/ if (is_string($bool)) { $bool = boolstr($bool); } // if a string is passed, convert it to a bool if (is_bool($bool)) { return $bool ? 'true' : 'false'; } else { return 'non_bool'; } }
'public', 'bounding_box_n', 'bounding_box_e', 'bounding_box_w', 'bounding_box_s', 'lat', 'lng', ); foreach ($limitedProjectCols as $col) { $limitedProject[$col] = $project[$col]; } $limitedProject['carto_id'] = $cartoLimited; $jsonDataLimited = json_encode($limitedProject); $jsonData = json_encode($project); if (boolstr($project['public']) === true) { # Public project, base renders ?> <script type="text/javascript"> renderMapWithData(<?php echo $jsonData; ?>); </script> <?php } else { # Set the most limited public data possible. After correct user # validation, it'll render a simple map ?> <script type="text/javascript"> setPublicData(<?php echo $jsonDataLimited;
public function verifyUserAuth($encoded_key, $token, $target_user) { /*** * If a user needs to be authorized before being allowed access, * check the authorization token here and update the flag * Note that the user calling this themselves must be an * administrator, or the function will fail. * ***/ $ret = array(); try { $thisUserStatus = $this->validateUser(true); $thisUserdata = $thisUserStatus['userdata']; $thisUserEmail = $thisUserdata[$this->usercol]; if ($thisUserStatus['status'] !== true) { throw new Exception("You're not logged in as a valid user."); } if (boolstr($thisUserdata['admin_flag']) !== true) { throw new Exception("You must be logged in with an administrative user account to authorize a new user (logged in as '" . $thisUserEmail . "' )."); } } catch (Exception $e) { $cookielink = $this->domain . '_link'; $altcookielink = str_replace('.', '_', $this->domain) . '_link'; $ucookielink = empty($_COOKIE[$cookielink]) ? $altcookielink : $cookielink; return array('status' => false, 'error' => $e->getMessage(), 'message' => 'Please log in before attempting to authenticate a user: '******'cookie' => $ucookielink, 'value' => $_COOKIE[$ucookielink], 'userdata' => $thisUserdata, 'userstatus' => $thisUserStatus); } $thisUserEmail = $thisUserdata[$this->userColumn]; $target_user = array($this->linkColumn => $target_user); try { $userdata = $this->getUser($target_user); } catch (Exception $e) { return array('status' => false, 'error' => $e->getMessage(), 'message' => 'Bad target user', 'target' => $target_user); } # Is the user already authorized? if ($userdata['flag']) { $ret['status'] = true; $ret['message'] = 'Already authenticated'; return $ret; } $working_key = base64_decode(urldecode($encoded_key)); $key = self::decryptThis($thisUserdata[$this->linkColumn], $working_key, $this->getIV()); $components = $this->getAuthTokens($target_user, $key); $primary_token = $components['auth']; if ($primary_token != $token) { $ret['status'] = false; $ret['message'] = 'Bad token'; $ret['provided_token'] = $token; /* $ret['encoded_key'] = urldecode($encoded_key); */ /* $ret['key_to_decrypt'] = $working_key; */ /* $ret['decryption_user'] = $userdata[$this->linkColumn]; */ /* $ret['decrypted_key'] = $key; */ $ret['components'] = $components; return $ret; } $l = $this->openDB(); $query = 'UPDATE `' . $this->getTable() . '` SET `flag`=TRUE WHERE `' . $this->linkColumn . "`='" . $target_user[$this->linkColumn] . "'"; $r = mysqli_query($l, $query); if ($r === false) { $ret['status'] = false; $ret['message'] = 'MySQL error'; $ret['error'] = 'MySQL error: ' . mysqli_error($l); } else { $ret['status'] = true; } $mail = $this->getMailObject(); # Let the user know $mail->Subject = 'Authorization granted to ' . $this->getDomain(); $mail->Body = '<p>Your access to ' . $this->getDomain() . " as been enabled. <a href='" . $this->getQualifiedDomain() . "'>Click here to visit the site</a>."; $userMail = $mail; $userMail->addAddress($userdata[$this->userColumn]); $user = $userMail->send(); if ($user) { $ret['user_confirm_sent'] = true; } else { $ret['user_confirm_sent'] = false; $ret['error'] .= ' User: '******'ve been authorized. $query = 'SELECT `' . $this->userColumn . '` FROM ' . $this->getTable() . ' WHERE `admin_flag`=TRUE'; $r = mysqli_query($l, $query); $mail = $this->getMailObject(); $mail->Subject = '[' . $this->getDomain() . '] New User Authenticated'; $mail->Body = '<p>' . $userdata[$this->userColumn] . ' was granted access to ' . $this->getDomain() . ' by ' . $thisUserEmail . '.</p><p>No further action is required, and you can disregard emails asking to grant this user access.</p><p><strong>If you believe this to be in error, immediately take steps to take your site offline</strong></p>'; while ($row = mysqli_fetch_row($r)) { $to = $row[0]; $mail->addAddress($to); } if ($mail->send()) { $ret['admin_confirm_sent'] = true; } else { $ret['admin_confirm_sent'] = false; $ret['error'] .= ' Admin: ' . $mail->ErrorInfo; } return $ret; }
function superuserEditUser($get) { /*** * * $get is the $_REQUEST superglobal. * Expects keys: * * @param string user -> The dblink/hardlink of the target user * @param string change_type -> The type of change to * enact. Available: delete | reset * ***/ global $login_status, $default_user_database, $default_sql_user, $default_sql_password, $sql_url, $default_user_table, $db_cols; $udb = new DBHelper($default_user_database, $default_sql_user, $default_sql_password, $sql_url, $default_user_table, $db_cols); $uid = $login_status['detail']['uid']; # is caller an SU or admin? $suFlag = $login_status['detail']['userdata']['su_flag']; $isSu = boolstr($suFlag); $adminFlag = $login_status['detail']['userdata']['admin_flag']; $isAdmin = boolstr($adminFlag); if (!($isSu || $isAdmin)) { return array("status" => false, "error" => "INVALID_USER_PERMISSIONS", "human_error" => "You do not have enough permission to perform this action"); } # Check the target $target = $get["user"]; if (empty($target)) { return array("status" => false, "error" => "INVALID_TARGET_NO_USER_PROVIDED", "human_error" => "You must provide argument 'user'"); } # Do they exist? if (!$udb->isEntry($target, 'dblink')) { return array("status" => false, "error" => "INVALID_TARGET_DOES_NOT_EXIST", "human_error" => "The requested user does not exist"); } $uf = new UserFunctions($target, "dblink"); $userData = $uf->getUser($target); try { # Is the target an SU or admin? $suFlag = $userData['userdata']['su_flag']; $targetIsSu = boolstr($suFlag); if ($targetIsSu) { return array("status" => false, "error" => "INVALID_TARGET_IS_SU", "human_error" => "You can not edit Superusers through this interface. Please contact your system administrator"); } $adminFlag = $userData['userdata']['admin_flag']; $targetIsAdmin = boolstr($adminFlag); if ($targetIsAdmin && !$isSu) { return array("status" => false, "error" => "INVALID_TARGET_ADMIN_VS_ADMIN", "human_error" => "Sorry, only Superusers can edit adminstrators"); } # Permission check complete. $editAction = strtolower($get["change_type"]); if (empty($editAction)) { return array("status" => false, "error" => "INVALID_CHANGE_TYPE_EMPTY", "human_error" => "You must provide an argument 'change_type'"); } switch ($editAction) { case "delete": $dryRun = $uf->forceDeleteCurrentUser(); $targetUid = $dryRun["target_user"]; if ($targetUid != $target) { # Should never happen return array("status" => false, "error" => "MISMATCHED_TARGETS", "human_error" => "The system encountered an error confirming target for deletion", "obj_target" => $targetUid, "post_target" => $target); } return $uf->forceDeleteCurrentUser(true); break; case "reset": return array("status" => false, "error" => "Incomplete"); break; default: return array("status" => false, "error" => "INVALID_CHANGE_TYPE", "human_error" => "We didn't recognize this change type", "change_type_provided" => $editAction); } } catch (Exception $e) { return array("status" => false, "error" => $e->getMessage(), "human_error" => "Application error", "args" => $get); } }