addGrantType(new OAuth2_GrantType_ClientCredentials($storage)); // or any grant type you like! $request = OAuth2_Request::createFromGlobals(); $response = new OAuth2_Response(); $server->handleTokenRequest($request, $response)->send(); // save vipamdin logged-in user pass-thru for future API filtering //debug("Request=" . print_r($_REQUEST, TRUE)); $tmp = $response->getParameters(); //debug("Request=" . print_r($_REQUEST, TRUE)); //debug("OAuth returns=" . print_r($tmp,TRUE)); strip_numeric_keys($tmp); //debug("stripped=" . print_r($tmp,TRUE)); if (array_key_exists('access_token',$tmp) && Request('client_id')=='vipadminapiuser@contradovip.com' && Request('session_user_id')!='') { // save local UserID in new oauth_vipadmin_session.api_session_user_id field - the end-user /vipadmin/ session is not the same and variables do not automagically get copied $sql = "INSERT INTO oauth_vipadmin_session SET access_token='" . addslashes($tmp['access_token']) . "', api_session_user_id=" . (int)Request('session_user_id'); //debug("sql=" . $sql . "\r\n"); $db = DB::dbh(); $stmt = $db->prepare($sql); $stmt->execute(); } if ($format=='xml') $tmp2 = xml_encode($tmp); else $tmp2 = json_encode($tmp); //echo $tmp2; //debug("tmp2=" . $tmp2 . "\r\n"); } else { //debug("validating AUTH TOKEN (" . Request('access_token','') . ")\r\n"); // verify caller supplied a valid authtoken with the request if (!$server->verifyResourceRequest(OAuth2_Request::createFromGlobals(), new OAuth2_Response())) { $server->getResponse()->send(); //outputs on screen or returned via stream die(-1); //debug("INVALID AUTH TOKEN (" . Request('access_token','') . ")\r\n"); //die("INVALID AUTH TOKEN (" . print_r($_REQUEST,TRUE) . ")"); } //debug("IS VALID\r\n"); // get oauth_client and corresponding User from token - revalidates access token on every API call $db = DB::dbh(); if (defined('DB_API_REQUIRES_COLLATE') && DB_API_REQUIRES_COLLATE=="TRUE") $collate = " COLLATE utf8_general_ci"; else $collate = ""; $headers = getAuthorizationHeader(); $sql = "SELECT User.*, oauth_vipadmin_session.api_session_user_id , GROUP_CONCAT(DISTINCT `Client`.ClientID) AS ClientID , GROUP_CONCAT(DISTINCT `Client`.ClientDisplayName) AS ClientDisplayName , GROUP_CONCAT(IF(UserProjectPermissions.Access=1,UserProjectPermissions.ProjectID,NULL)) AS PermsAccess , GROUP_CONCAT(IF(UserProjectPermissions.Notification=1,UserProjectPermissions.ProjectID,NULL)) AS PermsNotifications , UserType.UserTypeID, UserType.UserTypeCode , IF(ClientPromoEndDate IS NOT NULL AND ClientPromoEndDate>CURDATE() AND ClientPromoLevel!='Disabled', ClientPromoLevel, ClientSubscriptionLevel) AS ClientSubscriptionLevel FROM oauth_access_tokens INNER JOIN oauth_clients ON oauth_clients.client_id=oauth_access_tokens.client_id " . $collate . " LEFT JOIN oauth_vipadmin_session ON oauth_vipadmin_session.access_token=oauth_access_tokens.access_token " . $collate . " INNER JOIN User ON User.UserEmail=oauth_clients.client_id " . $collate . " INNER JOIN UserType ON UserType.UserTypeID=User.UserTypeID LEFT JOIN UserProjectPermissions ON UserProjectPermissions.UserID=User.UserID LEFT JOIN ClientUser ON ClientUser.UserID=User.UserID LEFT JOIN `Client` ON ClientUser.ClientID=Client.ClientID WHERE oauth_access_tokens.access_token='" . addslashes(str_ireplace("Bearer ", "", $headers)) . "' GROUP BY User.UserID"; // NOTE 'COLLATE utf8_general_ci' required after 'oauth_clients.client_id ' above on some servers //echo "sql=" . $sql . "\r\n"; if (DB::fetchAll($users, $sql, array()) === 0) { if (count($users) === 1) { $user = $users[0]; if ($user['UserTypeCode']=='superadmin' || $user['UserTypeCode']=='admin' || $user['UserTypeCode']=='manager') $user['ClientSubscriptionLevel']='Platinum'; } else { // user can get an access_token not tied to ANY oauth_client by providing EMPTY username and password params in authorization request (!) // however, this could also happen if we have oauth_client records that are not properly linked to a User record (via email address). die('Your access token is valid but it is not linked to any account. Please contact Contrado API support.'); } } else { die('Failed fetching user information. Please contact Contrado API support.'); } //debug("user=" . print_r($user,TRUE)); //debug("Session User ID: " . $user['api_session_user_id'] ."\r\n"); // effect the pass-thru of /vipadmin/ logged-in user by overwriting the internal vipadminapiuser@contradovip.com user account variables if ((int)$user['api_session_user_id']!=0) { $_SESSION['User_UserID'] = $user['api_session_user_id']; // _SESSIONS are not maintained with curl calls so we have to restore from DB every time $sql = "SELECT User.*, Client.ClientID , GROUP_CONCAT(DISTINCT Client.ClientID) AS ClientID , GROUP_CONCAT(DISTINCT Client.ClientDisplayName) AS ClientName , GROUP_CONCAT(IF(UserProjectPermissions.Access=1,UserProjectPermissions.ProjectID,NULL)) AS PermsAccess , GROUP_CONCAT(IF(UserProjectPermissions.Notification=1,UserProjectPermissions.ProjectID,NULL)) AS PermsNotifications , UserType.UserTypeID, UserType.UserTypeCode , IF(ClientPromoEndDate IS NOT NULL AND ClientPromoEndDate>CURDATE() AND ClientPromoLevel!='Disabled', ClientPromoLevel, ClientSubscriptionLevel) AS ClientSubscriptionLevel FROM User INNER JOIN UserType ON UserType.UserTypeID=User.UserTypeID LEFT JOIN UserProjectPermissions ON UserProjectPermissions.UserID=User.UserID LEFT JOIN ClientUser ON ClientUser.UserID=User.UserID LEFT JOIN Client ON ClientUser.ClientID=Client.ClientID WHERE User.UserID='" . $_SESSION['User_UserID'] . "' GROUP BY User.UserID "; //debug("sql=" . $sql . "\r\n"); } $client_id = 0; if (DB::fetchAll($users, $sql, array()) === 0) { if (count($users) === 1) { $user = $users[0]; $client_id = $user['ClientID']; } } $ClientCredentials = AdminUtil::GetClientCredentials((int)$client_id, "SiteOption", 'contradovip'); if (array_key_exists("ErrorEncountered", $ClientCredentials)) return $ClientCredentials; $fieldname_map = $ClientCredentials['FieldnameMap']; $sql = "SELECT * FROM Client WHERE ClientID IN(" . $client_id . ")"; //echo "sql=". $sql; if (DB::fetchAll($recs, $sql, array()) === 0) { if (count($recs)>=1) { $ClientRec = $recs[0]; } } //debug("user=" . print_r($user,TRUE)); if ($user['PermsAccess']=='' && $user['UserTypeCode']=='client') { $user['PermsAccess'] = '0'; // SQL syntax fixer } if ($user['PermsNotifications']=='' && $user['UserTypeCode']=='client') { $user['PermsNotifications'] = '0'; // SQL syntax fixer } debug("_REQUEST=" . print_r($_REQUEST,TRUE) . "\r\n"); // SIMILAR PROGRAMMING TO SITEPLAN_STATUS_IMPORT.PHP ONLY INGESTING JSON DATA (IGNORING POSSIBLE PSV) AND ADDING SOMETHING FOR LAST TOUCHED TIMESTAMP FIELD $fileContent = file_get_contents('php://input'); $is_json = FALSE; $json = json_decode($fileContent, TRUE); $output = array(); $rowcount = 0; // setup default fieldname mapping $mapped_fieldname = array('SitePlanID'=>'sitePlanId' ,'ProjectBuilderName'=>'projectId' ,'LotNum'=>'lotNumId' ,'StatusID'=>'statusId' ,'SelectedPlanBuilderName'=>'selectedPlanId' ,'SelectedElevationBuilderName'=>'selectedElev' ,'SelectedOrientation'=>'selectedOrientation' ,'LotPremium'=>'lotPremium' ,'SalesPrice'=>'salesPrice' ,'Notes'=>'notes' ,'DisplayName'=>'lotDesc' ,'OptionTitle1'=>'subhead' ,'AvailablePlans'=>'availablePlans' ); // parse client specific fieldname map if it exists if (trim($fieldname_map)!="") { $map = explode('|',$fieldname_map); $mapped_fieldname = array(); // replace mapped fieldnames into array if (count($map)>0) foreach($map AS $k=>$v) { $tmp = explode('=',$v); $key = trim($tmp[0]); $value = trim($tmp[1]); if (array_key_exists($key, $mapped_fieldname)) $mapped_fieldname[$key] = $value; } } if (json_last_error()==JSON_ERROR_NONE) { // parse json and reformat into array as PSV would be $is_json = TRUE; $archive_extension = ".json"; foreach($json AS $option) { //echo "option=
" . print_r($option, TRUE) . "
"; $output[$rowcount] = array(); if (isset($option[$mapped_fieldname['SitePlanID']])) $output[$rowcount]['SitePlanID']=$option[$mapped_fieldname['SitePlanID']]; if (isset($option[$mapped_fieldname['ProjectBuilderName']])) $output[$rowcount]['ProjectBuilderName']=$option[$mapped_fieldname['ProjectBuilderName']]; if (isset($option[$mapped_fieldname['LotNum']])) $output[$rowcount]['LotNum']=$option[$mapped_fieldname['LotNum']]; if (isset($option[$mapped_fieldname['StatusID']])) $output[$rowcount]['StatusID']=$option[$mapped_fieldname['StatusID']]; if (isset($option[$mapped_fieldname['SelectedPlanBuilderName']])) $output[$rowcount]['SelectedPlanBuilderName']=$option[$mapped_fieldname['SelectedPlanBuilderName']]; if (isset($option[$mapped_fieldname['SelectedElevationBuilderName']])) $output[$rowcount]['SelectedElevationBuilderName']=$option[$mapped_fieldname['SelectedElevationBuilderName']]; if (isset($option[$mapped_fieldname['SelectedOrientation']])) $output[$rowcount]['SelectedOrientation']=$option[$mapped_fieldname['SelectedOrientation']]; if (isset($option[$mapped_fieldname['LotPremium']])) $output[$rowcount]['LotPremium']= str_replace(array('$',','),array("",""),$option[$mapped_fieldname['LotPremium']]); if (isset($option[$mapped_fieldname['SalesPrice']])) $output[$rowcount]['SalesPrice']= str_replace(array('$',','),array("",""),$option[$mapped_fieldname['SalesPrice']]); if (isset($option[$mapped_fieldname['Notes']])) $output[$rowcount]['OptionTexNotest1']=$option[$mapped_fieldname['Notes']]; if (isset($option[$mapped_fieldname['DisplayName']])) $output[$rowcount]['DisplayName']=$option[$mapped_fieldname['DisplayName']]; if (isset($option[$mapped_fieldname['OptionTitle1']])) $output[$rowcount]['OptionTitle1']=$option[$mapped_fieldname['OptionTitle1']]; if (isset($option[$mapped_fieldname['AvailablePlans']])) $output[$rowcount]['OptionAvailablePlaAvailablePlansns']=$option[$mapped_fieldname['AvailablePlans']]; $rowcount++; } //echo "output=
" . print_r($output, TRUE) . "
"; } else { // error: not json errorOutput("screen", "{\"status\": \"JSON error or incorrectly formatted JSON\"}"); die(); } //echo "sites=
" . print_r($SiteRecs, TRUE) . "
"; /* $api_params = array('access_token'=>$_SESSION['admintoken']); if ($selected_client_id!='') $api_params['client_id'] = (int)$selected_client_id; $api_params['json'] = urlencode(json_encode($output)); //echo "Calling API.."; $ret = call_api('import_plan_option_pricing', $api_params); */ // parse and import data locally instead of via the API for easier fieldmapping, reporting of exceptions, and handling of ignored exceptions $recs = $output; process_siteoption_recs($client_id, $recs, "email", $is_json); // archive the uploaded data in case there were warnings and we need to manually re-import after fixing the unmatched site/option names $target_dir = realpath($_SERVER["DOCUMENT_ROOT"]); $epos = strrpos($target_dir,'/'); $target_dir = substr($target_dir, 0, $epos) . "/client_uploads"; if (!file_exists($target_dir)) mkdir($target_dir, 0777, TRUE); $target_dir .= "/"; //echo "target_dir=" . $target_dir; /* $target_dir = $ClientRec['ClientPath']; if ($target_dir=='' || stripos($target_dir, "clients/")===FALSE) $target_dir = "/clients/" . strtolower(str_replace(" ","_",$ClientRec['ClientDisplayName'])) . "/"; $target_dir = str_replace("..","", $target_dir); // safety measure // create client path if it doesn't exist if (!file_exists($_SERVER["DOCUMENT_ROOT"].$target_dir)) mkdir($_SERVER["DOCUMENT_ROOT"].$target_dir); // add trailing slash to make it easier to append filenames below $target_dir = realpath($_SERVER["DOCUMENT_ROOT"].$target_dir) . "/"; */ // archve uploaded PSV/JSON data $errmsg = ""; $archived_filename = $target_dir . strtolower(str_replace(" ","_",$ClientRec['ClientDisplayName'])) . "_" . 'SiteplanStatusUpdate' . date('m-d-Y-hia') . $archive_extension; if (!file_put_contents($archived_filename, $fileContent)) $errmsg = 'Error! Error archiving import file (' . $archived_filename . ').'; if ($errmsg!="") die($errmsg); $ret['Status'] = 'SUCCESS'; //echo "base_plan_updated=
" . print_r($sites_updated,TRUE) . "
"; if (isset($ret['Status'])) { errorOutput("screen", "{\"status\": \"" . $ret['Status'] . "\"}"); } else { errorOutput("screen", "\"status\": \"JSON error or incorrectly formatted JSON\"}>"); die(); } if ($output_mode=="email") { $util = new Util(); // emailSend($sender, $recipients, $bcc_recipients, $subject, $body, $purpose = 0, $attachments = false) $util->emailSend('donotreply@thecontradogroup.com', 'craig.hall@thecontradogroup.com, gregorylee@contractweb.net', "", $ClientRec['ClientDisplayName'] . " siteplan status update results", "" . $log_output . "", 2, false); // also output/return error messages to the caller //echo $log_output; } // NOTE THAT SITEPLAN_STATUS_IMPORT.PHP ALSO INCLUDES inc.siteoption_import.lib.php AND CALLS process_siteoption_recs(); to actually process the data (REFORMATTED INTO ARRAYS) // THIS IS ALSO VERY SIMILAR TO WHAT INC.GOODLESHEETSAPI.PHP DOES using process_siteoption_recs to process the data } // helper function gets _REQUEST var if it exists, else default function Request($fieldname, $default=NULL) { if (array_key_exists($fieldname,$_REQUEST)) return $_REQUEST[$fieldname]; else return $default; } function getAuthorizationHeader() { $headers = null; if (isset($_SERVER['Authorization'])) { $headers = trim($_SERVER["Authorization"]); } elseif (isset($_SERVER['HTTP_AUTHORIZATION'])) { // Nginx or FastCGI $headers = trim($_SERVER["HTTP_AUTHORIZATION"]); } elseif (function_exists('apache_request_headers')) { $requestHeaders = apache_request_headers(); // Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization) $requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders)); if (isset($requestHeaders['Authorization'])) { $headers = trim($requestHeaders['Authorization']); } } return $headers; } // helper function strips out numeric field indexes from within each record function strip_numeric_keys(&$recs) { if (is_array($recs)) foreach($recs AS $count => $rec) { if (is_array($rec)) foreach($rec AS $k => $v) if (is_numeric($k)) unset($recs[$count][$k]); } } // helper function to generate xml string from array function xml_encode($arr) { // create instance of SimpleXMLElement $xml_result = new SimpleXMLElement(""); // convert array to xml array_to_xml($arr,$xml_result); // return generated xml as a string return $xml_result->asXML(); } // function defination to convert array to xml function array_to_xml($arr, &$xml_result) { foreach($arr as $key => $value) { if (is_array($value)) { if (!is_numeric($key)) { $subnode = $xml_result->addChild("$key"); array_to_xml($value, $subnode); } else { $subnode = $xml_result->addChild("item$key"); array_to_xml($value, $subnode); } } else { $xml_result->addChild("$key",htmlspecialchars("$value")); } } } // debug helper function pdo_sql_debug($sql,$placeholders) { foreach($placeholders as $k => $v){ $sql = preg_replace('/:'.$k.'/',"'".$v."'",$sql); } return $sql; } $escapedbh = NULL; // DB lib replacement without deprecated mysql library calls. function escapeString($theString, $host = NULL, $user = NULL, $password = NULL, $port=NULL) { global $escapedbh; // this function is problematic with return addslashes($theString); if (!isset($host) && isset($_SESSION['DB_HOST'])) $host = $_SESSION['DB_HOST']; if (!isset($host) && defined('DB_HOST')) $host = DB_HOST; if (!isset($host)) throw new Exception('No database host defined.'); if (!isset($user) && isset($_SESSION['DB_USER'])) $user = $_SESSION['DB_USER']; if (!isset($user) && defined('DB_USER')) $user = DB_USER; if (!isset($user)) throw new Exception('No database user defined.'); if (!isset($password) && isset($_SESSION['DB_PASSWORD'])) $password = $_SESSION['DB_PASSWORD']; if (!isset($password) && defined('DB_PASSWORD')) $password = DB_PASSWORD; if (!isset($password)) throw new Exception('No database password defined.'); if (!isset($port) && isset($_SESSION['DB_PORT'])) $port = $_SESSION['DB_PORT']; if (!isset($port) && defined('DB_PORT')) $port = DB_PORT; if (is_null($escapedbh)) $escapedbh = mysqli_connect($host, $user, $password, NULL, $port) ; return mysqli_real_escape_string($escapedbh, $theString); }