static function call(OkapiRequest $request) { require_once 'log_images_common.inc.php'; list($image_uuid, $log_internal_id) = LogImagesCommon::validate_image_uuid($request); $image_uuid_escaped = Db::escape_string($image_uuid); Db::execute('start transaction'); $image_row = Db::select_row("\n select id, node, url, local\n from pictures\n where uuid = '" . $image_uuid_escaped . "'\n "); Db::execute("\n delete from pictures where uuid = '" . $image_uuid_escaped . "'\n "); # Remember that OCPL picture sequence numbers are always 1, and # OCDE sequence numbers may have gaps. So we do not need to adjust # any numbers after deleting from table 'pictures'. if (Settings::get('OC_BRANCH') == 'oc.de') { # OCDE does all the housekeeping by triggers } else { Db::execute("\n INSERT INTO removed_objects (\n localID, uuid, type, removed_date, node\n )\n VALUES (\n " . $image_row['id'] . "\n '" . $image_uuid_escaped . "',\n 6,\n NOW(),\n " . $image_row['node'] . "\n )\n "); # This will also update cache_logs.okapi_syncbase, so that replication # can output the updated log entry with one image less. For OCDE # that's done by DB trigges. Db::execute("\n update cache_logs\n set\n picturescount = greatest(0, picturescount - 1),\n last_modified = NOW()\n where id = '" . Db::escape_string($log_internal_id) . "'\n "); } Db::execute('commit'); if ($image_row['local']) { $filename = basename($image_row['url']); unlink(Settings::get('IMAGES_DIR') . '/' . $filename); } $result = array('success' => true); return Okapi::formatted_response($request, $result); }
public function new_access_token($token, $consumer, $verifier = null) { if ($token->consumer_key != $consumer->key) { throw new BadRequest("Request Token given is not associated with the Consumer who signed the request."); } if (!$token->authorized_by_user_id) { throw new BadRequest("Request Token given has not been authorized."); } if ($token->verifier != $verifier) { throw new BadRequest("Invalid verifier."); } # Invalidate the Request Token. Db::execute("\n delete from okapi_tokens\n where `key` = '" . Db::escape_string($token->key) . "'\n "); # In OKAPI, all Access Tokens are long lived. Therefore, we don't want # to generate a new one every time a Consumer wants it. We will check # if there is already an Access Token generated for this (Consumer, User) # pair and return it if there is. $row = Db::select_row("\n select `key`, secret\n from okapi_tokens\n where\n token_type = 'access'\n and user_id = '" . Db::escape_string($token->authorized_by_user_id) . "'\n and consumer_key = '" . Db::escape_string($consumer->key) . "'\n "); if ($row) { # Use existing Access Token $access_token = new OkapiAccessToken($row['key'], $row['secret'], $consumer->key, $token->authorized_by_user_id); } else { # Generate a new Access Token. $access_token = new OkapiAccessToken(Okapi::generate_key(20), Okapi::generate_key(40), $consumer->key, $token->authorized_by_user_id); Db::execute("\n insert into okapi_tokens\n (`key`, secret, token_type, timestamp, user_id, consumer_key)\n values (\n '" . Db::escape_string($access_token->key) . "',\n '" . Db::escape_string($access_token->secret) . "',\n 'access',\n unix_timestamp(),\n '" . Db::escape_string($access_token->user_id) . "',\n '" . Db::escape_string($consumer->key) . "'\n );\n "); } return $access_token; }
/** * Get [set_id, date_created, expires] for the given params_hash * (or [null, null, null] if not found). */ private static function find_param_set($params_hash, $ref_max_age) { $tmp = Db::select_row("\n select\n id as id,\n unix_timestamp(date_created) as date_created,\n unix_timestamp(expires) as expires\n from okapi_search_sets\n where\n params_hash = '" . mysql_real_escape_string($params_hash) . "'\n and date_add(date_created, interval '" . mysql_real_escape_string($ref_max_age) . "' second) > now()\n order by id desc\n limit 1\n "); if ($tmp === null) { return array(null, null, null); } return array($tmp['id'], $tmp['date_created'], $tmp['expires']); }
public static function call() { # By default, this view is turned off in the urls.php file. # This view is for debugging TileMap performace only! set_time_limit(0); header("Content-Type: text/plain; charset=utf-8"); $user_id = $_GET['u']; self::out("Yo. I'm {$user_id}.\n\n"); while (true) { srand(floor(time() / 10)); $mode2 = rand(0, 9) <= 7; if ($mode2) { $row = Db::select_row("\n select z, x, y\n from okapi_tile_status\n where status = 2 and z < 20\n order by rand()\n limit 1;\n "); $z = $row['z'] + 1; $x = $row['x'] << 1; $y = $row['y'] << 1; $x += rand(0, 1); $y += rand(0, 1); } else { $z = rand(5, 21); $x = rand(0, (1 << $z) - 1); $y = rand(0, (1 << $z) - 1); } $tiles = array(); for ($xx = $x; $xx < $x + 4; $xx++) { for ($yy = $y; $yy < $y + 4; $yy++) { $tiles[] = array($xx, $yy); } } srand(); shuffle($tiles); foreach ($tiles as $tile) { list($x, $y) = $tile; self::out("Loading " . str_pad("({$z}, {$x}, {$y})... ", 30)); $time_started = microtime(true); try { $response = OkapiServiceRunner::call('services/caches/map/tile', new OkapiInternalRequest(new OkapiInternalConsumer(), new OkapiInternalAccessToken($user_id), array('z' => "{$z}", 'x' => "{$x}", 'y' => "{$y}"))); $runtime = microtime(true) - $time_started; $ds = floor($runtime * 100); self::out(str_repeat("#", $ds) . " "); $b = floor(strlen($response->get_body()) / 256); self::out(str_repeat("@", $b) . "\n"); } catch (Exception $e) { self::out("\n\n" . OkapiExceptionHandler::get_exception_info($e)); die; } } } }
public static function call() { $token_key = isset($_GET['oauth_token']) ? $_GET['oauth_token'] : ''; $verifier = isset($_GET['oauth_verifier']) ? $_GET['oauth_verifier'] : ''; $langpref = isset($_GET['langpref']) ? $_GET['langpref'] : Settings::get('SITELANG'); $langprefs = explode("|", $langpref); $token = Db::select_row("\n select\n c.`key` as consumer_key,\n c.name as consumer_name,\n c.url as consumer_url,\n t.verifier\n from\n okapi_consumers c,\n okapi_tokens t\n where\n t.`key` = '" . mysql_real_escape_string($token_key) . "'\n and t.consumer_key = c.`key`\n "); if (!$token) { # Probably Request Token has expired or it was already used. We'll # just redirect to the Opencaching main page. return new OkapiRedirectResponse(Settings::get('SITE_URL')); } $vars = array('okapi_base_url' => Settings::get('SITE_URL') . "okapi/", 'token' => $token, 'verifier' => $verifier, 'site_name' => Okapi::get_normalized_site_name(), 'site_url' => Settings::get('SITE_URL'), 'site_logo' => Settings::get('SITE_LOGO')); $response = new OkapiHttpResponse(); $response->content_type = "text/html; charset=utf-8"; ob_start(); Okapi::gettext_domain_init($langprefs); include 'authorized.tpl.php'; $response->body = ob_get_clean(); Okapi::gettext_domain_restore(); return $response; }
public function execute() { ob_start(); $apisrv_stats = OkapiServiceRunner::call('services/apisrv/stats', new OkapiInternalRequest(new OkapiInternalConsumer(), null, array())); $active_apps_count = Db::select_value("\n select count(distinct s.consumer_key)\n from\n okapi_stats_hourly s,\n okapi_consumers c\n where\n s.consumer_key = c.`key`\n and s.period_start > date_add(now(), interval -7 day)\n "); $weekly_stats = Db::select_row("\n select\n sum(s.http_calls) as total_http_calls,\n sum(s.http_runtime) as total_http_runtime\n from okapi_stats_hourly s\n where\n s.consumer_key != 'internal' -- we don't want to exclude 'anonymous' nor 'facade'\n and s.period_start > date_add(now(), interval -7 day)\n "); print "Hello! This is your weekly summary of OKAPI usage.\n\n"; print "Apps active this week: " . $active_apps_count . " out of " . $apisrv_stats['apps_count'] . ".\n"; print "Total of " . $weekly_stats['total_http_calls'] . " requests were made (" . sprintf("%01.1f", $weekly_stats['total_http_runtime']) . " seconds).\n\n"; $consumers = Db::select_all("\n select\n s.consumer_key,\n c.name,\n sum(s.http_calls) as http_calls,\n sum(s.http_runtime) as http_runtime\n from\n okapi_stats_hourly s\n left join okapi_consumers c\n on s.consumer_key = c.`key`\n where s.period_start > date_add(now(), interval -7 day)\n group by s.consumer_key\n having sum(s.http_calls) > 0\n order by sum(s.http_calls) desc\n "); print "== Consumers ==\n\n"; print "Consumer name Calls Runtime\n"; print "----------------------------------- ------- -----------\n"; foreach ($consumers as $row) { $name = $row['name']; if ($row['consumer_key'] == 'anonymous') { $name = "Anonymous (Level 0 Authentication)"; } elseif ($row['consumer_key'] == 'facade') { $name = "Internal usage via Facade"; } if (mb_strlen($name) > 35) { $name = mb_substr($name, 0, 32) . "..."; } print self::mb_str_pad($name, 35, " ", STR_PAD_RIGHT); print str_pad($row['http_calls'], 8, " ", STR_PAD_LEFT); print str_pad(sprintf("%01.2f", $row['http_runtime']), 11, " ", STR_PAD_LEFT) . "s\n"; } print "\n"; $methods = Db::select_all("\n select\n s.service_name,\n sum(s.http_calls) as http_calls,\n sum(s.http_runtime) as http_runtime\n from okapi_stats_hourly s\n where s.period_start > date_add(now(), interval -7 day)\n group by s.service_name\n having sum(s.http_calls) > 0\n order by sum(s.http_calls) desc\n "); print "== Methods ==\n\n"; print "Service name Calls Runtime Avg\n"; print "----------------------------------- ------- ----------- --------\n"; foreach ($methods as $row) { $name = $row['service_name']; if (mb_strlen($name) > 35) { $name = mb_substr($name, 0, 32) . "..."; } print self::mb_str_pad($name, 35, " ", STR_PAD_RIGHT); print str_pad($row['http_calls'], 8, " ", STR_PAD_LEFT); print str_pad(sprintf("%01.2f", $row['http_runtime']), 11, " ", STR_PAD_LEFT) . "s"; print str_pad(sprintf("%01.4f", $row['http_calls'] > 0 ? $row['http_runtime'] / $row['http_calls'] : 0), 8, " ", STR_PAD_LEFT) . "s\n"; } print "\n"; $oauth_users = Db::select_all("\n select\n c.name,\n count(*) as users\n from\n okapi_authorizations a,\n okapi_consumers c\n where a.consumer_key = c.`key`\n group by a.consumer_key\n having count(*) >= 5\n order by count(*) desc;\n "); print "== Current OAuth usage by Consumers with at least 5 users ==\n\n"; print "Consumer name Users\n"; print "----------------------------------- -------\n"; foreach ($oauth_users as $row) { $name = $row['name']; if (mb_strlen($name) > 35) { $name = mb_substr($name, 0, 32) . "..."; } print self::mb_str_pad($name, 35, " ", STR_PAD_RIGHT); print str_pad($row['users'], 8, " ", STR_PAD_LEFT) . "\n"; } print "\n"; print "This report includes requests from external consumers and those made via\n"; print "Facade class (used by OC code). It does not include methods used by OKAPI\n"; print "internally (i.e. while running cronjobs). Runtimes do not include HTTP\n"; print "request handling overhead.\n"; $message = ob_get_clean(); Okapi::mail_admins("Weekly OKAPI usage report", $message); }
public static function call() { $token_key = isset($_GET['oauth_token']) ? $_GET['oauth_token'] : ''; $langpref = isset($_GET['langpref']) ? $_GET['langpref'] : Settings::get('SITELANG'); $langprefs = explode("|", $langpref); $locales = array(); foreach (Locales::$languages as $lang => $attrs) { $locales[$attrs['locale']] = $attrs; } # Current implementation of the "interactivity" parameter is: If developer # wants to "confirm_user", then just log out the current user before we # continue. $force_relogin = isset($_GET['interactivity']) && $_GET['interactivity'] == 'confirm_user'; $token = Db::select_row("\n select\n t.`key` as `key`,\n c.`key` as consumer_key,\n c.name as consumer_name,\n c.url as consumer_url,\n t.callback,\n t.verifier\n from\n okapi_consumers c,\n okapi_tokens t\n where\n t.`key` = '" . Db::escape_string($token_key) . "'\n and t.consumer_key = c.`key`\n and t.user_id is null\n "); $callback_concat_char = strpos($token['callback'], '?') === false ? "?" : "&"; if (!$token) { # Probably Request Token has expired. This will be usually viewed # by the user, who knows nothing on tokens and OAuth. Let's be nice then! $vars = array('okapi_base_url' => Settings::get('SITE_URL') . "okapi/", 'token' => $token, 'token_expired' => true, 'site_name' => Okapi::get_normalized_site_name(), 'site_url' => Settings::get('SITE_URL'), 'site_logo' => Settings::get('SITE_LOGO'), 'locales' => $locales); $response = new OkapiHttpResponse(); $response->content_type = "text/html; charset=utf-8"; ob_start(); $vars['locale_displayed'] = Okapi::gettext_domain_init($langprefs); include 'authorize.tpl.php'; $response->body = ob_get_clean(); Okapi::gettext_domain_restore(); return $response; } # Determine which user is logged in to OC. require_once $GLOBALS['rootpath'] . "okapi/lib/oc_session.php"; $OC_user_id = OCSession::get_user_id(); # Ensure a user is logged in (or force re-login). if ($force_relogin || $OC_user_id == null) { # TODO: confirm_user should first ask the user if he's "the proper one", # and then offer to sign in as a different user. $login_page = 'login.php?'; if ($OC_user_id !== null) { if (Settings::get('OC_BRANCH') == 'oc.de') { # OCDE login.php?action=logout&target=... will NOT logout and # then redirect to the target, but it will log out, prompt for # login and then redirect to the target after logging in - # that's exactly the relogin that we want. $login_page .= 'action=logout&'; } else { # OCPL uses REAL MAGIC for session handling. I don't get ANY of it. # The logout.php DOES NOT support the "target" parameter, so we # can't just call it. The only thing that comes to mind is... # Try to destroy EVERYTHING. (This still won't necessarilly work, # because OC may store cookies in separate paths, but hopefully # they won't). if (isset($_SERVER['HTTP_COOKIE'])) { $cookies = explode(';', $_SERVER['HTTP_COOKIE']); foreach ($cookies as $cookie) { $parts = explode('=', $cookie); $name = trim($parts[0]); setcookie($name, '', time() - 1000); setcookie($name, '', time() - 1000, '/'); foreach (self::getPossibleCookieDomains() as $domain) { setcookie($name, '', time() - 1000, '/', $domain); } } } # We should be logged out now. Let's login again. } } $after_login = "******" . ($langpref != Settings::get('SITELANG') ? "&langpref=" . $langpref : ""); $login_url = Settings::get('SITE_URL') . $login_page . "target=" . urlencode($after_login) . "&langpref=" . $langpref; return new OkapiRedirectResponse($login_url); } # Check if this user has already authorized this Consumer. If he did, # then we will automatically authorize all subsequent Request Tokens # from this Consumer. $authorized = Db::select_value("\n select 1\n from okapi_authorizations\n where\n user_id = '" . Db::escape_string($OC_user_id) . "'\n and consumer_key = '" . Db::escape_string($token['consumer_key']) . "'\n ", 0); if (!$authorized) { if (isset($_POST['authorization_result'])) { # Not yet authorized, but user have just submitted the authorization form. # WRTODO: CSRF protection if ($_POST['authorization_result'] == 'granted') { Db::execute("\n insert ignore into okapi_authorizations (consumer_key, user_id)\n values (\n '" . Db::escape_string($token['consumer_key']) . "',\n '" . Db::escape_string($OC_user_id) . "'\n );\n "); $authorized = true; } else { # User denied access. Nothing sensible to do now. Will try to report # back to the Consumer application with an error. if ($token['callback']) { return new OkapiRedirectResponse($token['callback'] . $callback_concat_char . "error=access_denied" . "&oauth_token=" . $token['key']); } else { # Consumer did not provide a callback URL (oauth_callback=oob). # We'll have to redirect to the Opencaching main page then... return new OkapiRedirectResponse(Settings::get('SITE_URL') . "index.php"); } } } else { # Not yet authorized. Display an authorization request. $vars = array('okapi_base_url' => Settings::get('SITE_URL') . "okapi/", 'token' => $token, 'site_name' => Okapi::get_normalized_site_name(), 'site_url' => Settings::get('SITE_URL'), 'site_logo' => Settings::get('SITE_LOGO'), 'locales' => $locales); $response = new OkapiHttpResponse(); $response->content_type = "text/html; charset=utf-8"; ob_start(); $vars['locale_displayed'] = Okapi::gettext_domain_init($langprefs); include 'authorize.tpl.php'; $response->body = ob_get_clean(); Okapi::gettext_domain_restore(); return $response; } } # User granted access. Now we can authorize the Request Token. Db::execute("\n update okapi_tokens\n set user_id = '" . Db::escape_string($OC_user_id) . "'\n where `key` = '" . Db::escape_string($token_key) . "';\n "); # Redirect to the callback_url. if ($token['callback']) { return new OkapiRedirectResponse($token['callback'] . $callback_concat_char . "oauth_token=" . $token_key . "&oauth_verifier=" . $token['verifier']); } else { # Consumer did not provide a callback URL (probably the user is using a desktop # or mobile application). We'll just have to display the verifier to the user. return new OkapiRedirectResponse(Settings::get('SITE_URL') . "okapi/apps/authorized?oauth_token=" . $token_key . "&oauth_verifier=" . $token['verifier'] . "&langpref=" . $langpref); } }
private static function ver60() { # Turns out there can be only one valid TIMESTAMP field in one table! # Fields added ver53-ver59 don't work properly *if* ver51-ver52 had been run. # # We'll check if ver51-ver52 had been run and try to withdraw it AND # *rerun* missing ver53-ver59 updates. # $row = Db::select_row("show create table cache_logs"); $stmt = $row["Create Table"]; if (strpos($stmt, "timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'") > 0) { Db::execute("alter table cache_logs modify column last_modified datetime not null;"); Db::execute("alter table cache_logs modify column okapi_syncbase timestamp not null;"); Db::execute("update cache_logs set okapi_syncbase=now() where okapi_syncbase='0000-00-00 00:00:00';"); if (Settings::get('OC_BRANCH') == 'oc.de') { Db::execute("alter table cache_logs_archived modify column last_modified datetime not null;"); Db::execute("alter table cache_logs_archived modify column okapi_syncbase timestamp not null;"); Db::execute("update cache_logs_archived set okapi_syncbase=now() where okapi_syncbase='0000-00-00 00:00:00';"); } } }