okapi r608

This commit is contained in:
following
2013-03-30 18:13:59 +01:00
parent 3988af84a9
commit 45b90b03a5
10 changed files with 180 additions and 51 deletions

View File

@ -778,7 +778,7 @@ class Okapi
{
public static $data_store;
public static $server;
public static $revision = 594; # This gets replaced in automatically deployed packages
public static $revision = 608; # This gets replaced in automatically deployed packages
private static $okapi_vars = null;
/** Get a variable stored in okapi_vars. If variable not found, return $default. */

View File

@ -13,6 +13,7 @@ use okapi\OkapiAccessToken;
use okapi\InvalidParam;
use okapi\services\caches\search\SearchAssistant;
use okapi\OkapiInternalConsumer;
use okapi\Db;
class WebService
{
@ -137,12 +138,41 @@ class WebService
$vars['caches'] = OkapiServiceRunner::call('services/caches/geocaches', new OkapiInternalRequest(
$request->consumer, $request->token, array('cache_codes' => $cache_codes,
'langpref' => $langpref, 'fields' => $fields, 'lpc' => $lpc, 'user_uuid' => $user_uuid)));
'langpref' => $langpref, 'fields' => $fields, 'lpc' => $lpc, 'user_uuid' => $user_uuid,
'log_fields' => 'uuid|date|user|type|comment|internal_id|was_recommended')));
$vars['installation'] = OkapiServiceRunner::call('services/apisrv/installation', new OkapiInternalRequest(
new OkapiInternalConsumer(), null, array()));
$vars['cache_GPX_types'] = self::$cache_GPX_types;
$vars['cache_GPX_sizes'] = self::$cache_GPX_sizes;
/* OC sites always used internal user_ids in their generated GPX files.
* This might be considered an error in itself (groundspeak's XML namespace
* doesn't allow that), but it very common (Garmin's OpenCaching.COM
* also does that). Therefore, for backward-compatibility reasons, OKAPI
* will do it the same way. See issue 174.
*
* Currently, the caches method does not expose "owner.internal_id" and
* "latest_logs.user.internal_id" fields, we will read them manually
* from the database here. */
$dict = array();
foreach ($vars['caches'] as &$cache_ref)
{
$dict[$cache_ref['owner']['uuid']] = true;
if (isset($cache_ref['latest_logs']))
foreach ($cache_ref['latest_logs'] as &$log_ref)
$dict[$log_ref['user']['uuid']] = true;
}
$rs = Db::query("
select uuid, user_id
from user
where uuid in ('".implode("','", array_map('mysql_real_escape_string', array_keys($dict)))."')
");
while ($row = mysql_fetch_assoc($rs))
$dict[$row['uuid']] = $row['user_id'];
$vars['user_uuid_to_internal_id'] = &$dict;
unset($dict);
$response = new OkapiHttpResponse();
$response->content_type = "text/xml; charset=utf-8";
$response->content_disposition = 'attachment; filename="results.gpx"';

View File

@ -37,7 +37,7 @@ http://www.gsak.net/xmlv1/5 http://www.gsak.net/xmlv1/5/gsak.xsd
<groundspeak:cache archived="<?= ($c['status'] == 'Archived') ? "True" : "False" ?>" available="<?= ($c['status'] == 'Available') ? "True" : "False" ?>" id="<?= $c['internal_id'] ?>" xmlns:groundspeak="http://www.groundspeak.com/cache/1/0/1">
<groundspeak:name><?= Okapi::xmlescape($c['name']) ?></groundspeak:name>
<groundspeak:placed_by><?= Okapi::xmlescape($c['owner']['username']) ?></groundspeak:placed_by>
<groundspeak:owner id="<?= $c['owner']['uuid'] ?>"><?= Okapi::xmlescape($c['owner']['username']) ?></groundspeak:owner>
<groundspeak:owner id="<?= $vars['user_uuid_to_internal_id'][$c['owner']['uuid']] ?>"><?= Okapi::xmlescape($c['owner']['username']) ?></groundspeak:owner>
<groundspeak:type><?= $vars['cache_GPX_types'][$c['type']] ?></groundspeak:type>
<groundspeak:container><?= $vars['cache_GPX_sizes'][$c['size2']] ?></groundspeak:container>
<groundspeak:difficulty><?= $c['difficulty'] ?></groundspeak:difficulty>
@ -108,11 +108,11 @@ http://www.gsak.net/xmlv1/5 http://www.gsak.net/xmlv1/5/gsak.xsd
<? if ($vars['latest_logs']) { /* Does user want us to include latest log entries? */ ?>
<groundspeak:logs>
<? foreach ($c['latest_logs'] as $log) { ?>
<groundspeak:log id="<?= $log['uuid'] ?>">
<groundspeak:log id="<?= $log['internal_id'] ?>">
<groundspeak:date><?= $log['date'] ?></groundspeak:date>
<groundspeak:type><?= $log['type'] ?></groundspeak:type>
<groundspeak:finder id="<?= $log['user']['uuid'] ?>"><?= Okapi::xmlescape($log['user']['username']) ?></groundspeak:finder>
<groundspeak:text encoded="False"><?= Okapi::xmlescape($log['comment']) ?></groundspeak:text>
<groundspeak:finder id="<?= $vars['user_uuid_to_internal_id'][$log['user']['uuid']] ?>"><?= Okapi::xmlescape($log['user']['username']) ?></groundspeak:finder>
<groundspeak:text encoded="False"><?= $log['was_recommended'] ? "(*) ": "" ?><?= Okapi::xmlescape($log['comment']) ?></groundspeak:text>
</groundspeak:log>
<? } ?>
</groundspeak:logs>

View File

@ -63,6 +63,11 @@ class WebService
if (!in_array($field, self::$valid_field_names))
throw new InvalidParam('fields', "'$field' is not a valid field code.");
# Currently, the "owner" field needs to be included whenever the "description" field is.
# That's a little ugly. Grep for "issue 178" below for more insight on this.
if ((in_array('description', $fields) || in_array('descriptions', $fields)) && !in_array('owner', $fields))
$fields[] = "owner";
$log_fields = $request->get_parameter('log_fields');
if (!$log_fields) $log_fields = "uuid|date|user|type|comment"; // validation is done on call
@ -424,8 +429,19 @@ class WebService
$cache_code = $cacheid2wptcode[$row['cache_id']];
// strtolower - ISO 639-1 codes are lowercase
if ($row['desc'])
$results[$cache_code]['descriptions'][strtolower($row['language'])] = $row['desc'].
"\n".self::get_cache_attribution_note($row['cache_id'], strtolower($row['language']), $langpref);
{
/* Regarding the attribution note - please note, that the "owner" field
* is automatically included, whenever the cache description is included.
* This is because we may need it for the attribution note - see issue 178. */
$results[$cache_code]['descriptions'][strtolower($row['language'])] = (
$row['desc']."\n".
self::get_cache_attribution_note(
$row['cache_id'], strtolower($row['language']), $langpref,
$results[$cache_code]['owner']
)
);
}
if ($row['hint'])
$results[$cache_code]['hints'][strtolower($row['language'])] = $row['hint'];
}
@ -738,7 +754,7 @@ class WebService
{
# OCDE uses 'coordinates' table (with type=1) to store additional waypoints.
# All waypoints are are public.
$waypoints = Db::select_all("
select
cache_id,
@ -871,14 +887,24 @@ class WebService
/**
* Return attribution note to be included in the cache description.
*
* The $lang parameter identifies the language of the cache description
* (one cache may have descriptions in multiple languages!). Whereas
* the $langpref parameter is *an array* of language preferences
* extracted from the langpref parameter passed to the method. Both
* values ($lang and $langpref) will be taken into account ($lang
* has the higher priority).
* to which the attribution note will be appended to (one cache may
* have descriptions in multiple languages!).
*
* The $langpref parameter is *an array* of language preferences
* extracted from the langpref parameter passed to the method by the
* OKAPI Consumer.
*
* Both values ($lang and $langpref) will be taken into account when
* generating the attribution note, but $lang will have a higher
* priority than $langpref (we don't want to mix the languages in the
* descriptions if we don't have to).
*
* $owner is in object describing the user, it has the same format as
* defined in "geocache" method specs (see the "owner" field).
*/
public static function get_cache_attribution_note($cache_id, $lang, array $langpref)
public static function get_cache_attribution_note($cache_id, $lang, array $langpref, $owner)
{
$site_url = Settings::get('SITE_URL');
$site_name = Okapi::get_normalized_site_name();
@ -886,10 +912,24 @@ class WebService
Okapi::gettext_domain_init(array_merge(array($lang), $langpref));
$note = "<p>";
$note .= sprintf(
_("This <a href='%s'>geocache</a> description comes from the <a href='%s'>%s</a> site."),
$cache_url, $site_url, $site_name
);
if (Settings::get('OC_BRANCH') == 'oc.de')
{
$note .= sprintf(
_(
"<em>&copy; <a href='%s'>%s</a>, <a href='%s'>%s</a>, ".
"<a href='http://creativecommons.org/licenses/by-nc-nd/3.0/en/'>CC-BY-NC-ND</a>, ".
"as of Jan 15, 2013; all log entries &copy; their authors</em>"
),
$owner['profile_url'], $owner['username'], $site_url, $site_name
);
}
else
{
$note .= sprintf(
_("This <a href='%s'>geocache</a> description comes from the <a href='%s'>%s</a> site."),
$cache_url, $site_url, $site_name
);
}
$note .= "</p>";
Okapi::gettext_domain_restore();

View File

@ -184,35 +184,38 @@ class ReplicateListener
and y = '".mysql_real_escape_string($y)."'
)";
}
Db::execute("
replace into okapi_tile_caches (
z, x, y, cache_id, z21x, z21y, status, type, rating, flags
)
select
z, x, y,
'".mysql_real_escape_string($row[0])."',
'".mysql_real_escape_string($row[1])."',
'".mysql_real_escape_string($row[2])."',
'".mysql_real_escape_string($row[3])."',
'".mysql_real_escape_string($row[4])."',
".(($row[5] === null) ? "null" : $row[5]).",
'".mysql_real_escape_string($row[6])."'
from okapi_tile_status
where
(".implode(" or ", $alternatives).")
and status in (1,2)
");
if (count($alternatives) > 0)
{
Db::execute("
replace into okapi_tile_caches (
z, x, y, cache_id, z21x, z21y, status, type, rating, flags
)
select
z, x, y,
'".mysql_real_escape_string($row[0])."',
'".mysql_real_escape_string($row[1])."',
'".mysql_real_escape_string($row[2])."',
'".mysql_real_escape_string($row[3])."',
'".mysql_real_escape_string($row[4])."',
".(($row[5] === null) ? "null" : $row[5]).",
'".mysql_real_escape_string($row[6])."'
from okapi_tile_status
where
(".implode(" or ", $alternatives).")
and status in (1,2)
");
# We might have just filled some empty tiles (status 1) with data.
# We need to update their status to 2.
# We might have just filled some empty tiles (status 1) with data.
# We need to update their status to 2.
Db::execute("
update okapi_tile_status
set status=2
where
(".implode(" or ", $alternatives).")
and status=1
");
Db::execute("
update okapi_tile_status
set status=2
where
(".implode(" or ", $alternatives).")
and status=1
");
}
# And that's all. That should do the trick.
}

View File

@ -9,6 +9,7 @@ use okapi\OkapiServiceRunner;
use okapi\OkapiRequest;
use okapi\ParamMissing;
use okapi\InvalidParam;
use okapi\BadRequest;
class WebService
{
@ -49,6 +50,9 @@ class WebService
if (!is_array($retr_params))
throw new InvalidParam('retr_params', "Should be a JSON-encoded dictionary");
self::map_values_to_strings($search_params);
self::map_values_to_strings($retr_params);
# Wrapped?
$wrap = $request->get_parameter('wrap');
if ($wrap == null) throw new ParamMissing('wrap');
@ -102,4 +106,16 @@ class WebService
return Okapi::formatted_response($request, $retr_result);
}
}
private static function map_values_to_strings(&$dict)
{
foreach (array_keys($dict) as $key)
{
$val = $dict[$key];
if (is_numeric($val) || is_string($val))
$dict[$key] = (string)$val;
else
throw new BadRequest("Invalid value format for key: ".$key);
}
}
}

View File

@ -46,12 +46,22 @@ class WebService
$cache_code = $request->get_parameter('cache_code');
if (!$cache_code) throw new ParamMissing('cache_code');
$logtype = $request->get_parameter('logtype');
if (!$logtype) throw new ParamMissing('logtype');
if (!in_array($logtype, array('Found it', "Didn't find it", 'Comment')))
throw new InvalidParam('logtype', "'$logtype' in not a valid logtype code.");
$comment = $request->get_parameter('comment');
if (!$comment) $comment = "";
$comment_format = $request->get_parameter('comment_format');
if ($comment_format)
{
if (!in_array($comment_format, array('html', 'plaintext')))
throw new InvalidParam('comment_format', $comment_format);
}
$tmp = $request->get_parameter('when');
if ($tmp)
{
@ -64,10 +74,12 @@ class WebService
}
else
$when = time();
$on_duplicate = $request->get_parameter('on_duplicate');
if (!$on_duplicate) $on_duplicate = "silent_success";
if (!in_array($on_duplicate, array('silent_success', 'user_error', 'continue')))
throw new InvalidParam('on_duplicate', "Unknown option: '$on_duplicate'.");
$rating = $request->get_parameter('rating');
if ($rating !== null && (!in_array($rating, array(1,2,3,4,5))))
throw new InvalidParam('rating', "If present, it must be an integer in the 1..5 scale.");
@ -83,6 +95,7 @@ class WebService
Okapi::get_normalized_site_name());
$rating = null;
}
$recommend = $request->get_parameter('recommend');
if (!$recommend) $recommend = 'false';
if (!in_array($recommend, array('true', 'false')))
@ -90,6 +103,7 @@ class WebService
$recommend = ($recommend == 'true');
if ($recommend && $logtype != 'Found it')
throw new BadRequest(_("Recommending is allowed only for 'Found it' logtypes."));
$needs_maintenance = $request->get_parameter('needs_maintenance');
if (!$needs_maintenance) $needs_maintenance = 'false';
if (!in_array($needs_maintenance, array('true', 'false')))

View File

@ -14,10 +14,13 @@
log types which are used for Event Caches (we are planning to add this).</p>
</req>
<opt name='comment'>
<p>Text to be submitted with the log entry. Plain-text (no HTML).</p>
<p><b>Note:</b> Due to <a href='http://code.google.com/p/opencaching-api/issues/detail?id=124'>some issues</a>
(which we cannot currently fix), you MAY be allowed to use some basic HTML tags (on some OC installations).
However, you should not (this may stop working at any time).</p>
<p>Text to be submitted with the log entry.</p>
</opt>
<opt name='comment_format' default='(unspecified!)'>
<p>Indicates the format of your <b>comment</b>. Two values allowed: <b>html</b> or <b>plaintext</b>.</p>
<p><b>Important note:</b> Due to <a href='http://code.google.com/p/opencaching-api/issues/detail?id=124'>some issues</a>,
this switch is currently completelly ignored (!). However, we still advise you to use it,
for future-compatibility.</p>
</opt>
<opt name='when'>
<p>A date and time string. This should be in ISO 8601 format (currently any

View File

@ -121,7 +121,7 @@ class View
if ($_POST['authorization_result'] == 'granted')
{
Db::execute("
insert into okapi_authorizations (consumer_key, user_id)
insert ignore into okapi_authorizations (consumer_key, user_id)
values (
'".mysql_real_escape_string($token['consumer_key'])."',
'".mysql_real_escape_string($OC_user_id)."'

View File

@ -60,6 +60,29 @@ class View
}
public static function call()
{
# First, let's acquire a lock to make sure the update isn't already running.
# We will use one of the existing lock handles, because we don't want to use
# to many of them. See issue 141.
$lock = OkapiLock::get('cronjobs-cron-5');
$lock->acquire();
try
{
self::_call();
$lock->release();
}
catch (Exception $e)
{
# Error occured. Make sure the lock is released and rethrow.
$lock->release();
throw $e;
}
}
private static function _call()
{
ignore_user_abort(true);
set_time_limit(0);