preview_image - This is either null or a dictionary describing - an image, which has been marked by the owner as preview image. You are - encouraged to display it as a 'teaser' for this cache. - The structure of the dictionary is the same as in the images field above.
-The preview image is no additional image but one of those which - are included in the images list.
+preview_image - On some installations, owners may select one of the images + (see above) as a preview image. You are encouraged to display it as a 'teaser' + for this cache. On other installations this functionality is disabled and you + will always get the null value here.
+ +The value of preview_image is either null or a dictionary describing + an image. The structure of this dictionary is the same as of a single entry on + the images list described above.
attrnames - list of names of attributes of the cache; the language will diff --git a/htdocs/okapi/services/caches/geocaches.php b/htdocs/okapi/services/caches/geocaches.php index 010f7405..6f467b70 100644 --- a/htdocs/okapi/services/caches/geocaches.php +++ b/htdocs/okapi/services/caches/geocaches.php @@ -179,8 +179,8 @@ class WebService # PL branch: # - Caches have ratings. # - Total numbers of found and notfounds are kept in the "caches" table. - # - search_time is round trip and way_length one way; both can be null; - # 0 or null = not specified + # - search_time is round trip and way_length one way or both ways (this is different on OCDE!); + # both can be null; 0 or null = not specified $rs = Db::query(" select @@ -188,7 +188,7 @@ class WebService c.date_created, c.type, c.status, c.date_hidden, c.size, c.difficulty, c.terrain, c.wp_oc, c.logpw, c.user_id, if(c.search_time=0, null, c.search_time) as trip_time, - if(c.way_length=0, null, 2*c.way_length) as trip_distance, + if(c.way_length=0, null, c.way_length) as trip_distance, c.topratings, c.founds, @@ -850,17 +850,13 @@ class WebService # Country and/or state. - if (Settings::get('OC_BRANCH') == 'oc.de') - $cache_location_state = 'adm2'; - else - $cache_location_state = 'adm3'; if (in_array('country', $fields) || in_array('state', $fields)) { $rs = Db::query(" select c.wp_oc as cache_code, cl.adm1 as country, - cl.".$cache_location_state." as state + cl.".((Settings::get('OC_BRANCH') == 'oc.de') ? 'adm2' : 'adm3')." as state from caches c, cache_location cl @@ -1016,6 +1012,8 @@ class WebService } else { + # OC.de wants the tld in lowercase here + $site_name = ucfirst(strtolower($site_name)); if ($type == 'full') { $note = sprintf( diff --git a/htdocs/okapi/services/caches/map/replicate_listener.inc.php b/htdocs/okapi/services/caches/map/replicate_listener.inc.php index 11b85ab8..6e4fb9f7 100644 --- a/htdocs/okapi/services/caches/map/replicate_listener.inc.php +++ b/htdocs/okapi/services/caches/map/replicate_listener.inc.php @@ -174,17 +174,17 @@ class ReplicateListener # Most of these tiles aren't cached at all. We need to update # only the cached ones. - $alternatives = array(); + $alternatives_escaped = array(); foreach ($tiles_to_update as $coords) { list($z, $x, $y) = $coords; - $alternatives[] = "( + $alternatives_escaped[] = "( z = '".mysql_real_escape_string($z)."' and x = '".mysql_real_escape_string($x)."' and y = '".mysql_real_escape_string($y)."' )"; } - if (count($alternatives) > 0) + if (count($alternatives_escaped) > 0) { Db::execute(" replace into okapi_tile_caches ( @@ -197,11 +197,11 @@ class ReplicateListener '".mysql_real_escape_string($row[2])."', '".mysql_real_escape_string($row[3])."', '".mysql_real_escape_string($row[4])."', - ".(($row[5] === null) ? "null" : $row[5]).", + ".(($row[5] === null) ? "null" : "'".mysql_real_escape_string($row[5])."'").", '".mysql_real_escape_string($row[6])."' from okapi_tile_status where - (".implode(" or ", $alternatives).") + (".implode(" or ", $alternatives_escaped).") and status in (1,2) "); @@ -212,7 +212,7 @@ class ReplicateListener update okapi_tile_status set status=2 where - (".implode(" or ", $alternatives).") + (".implode(" or ", $alternatives_escaped).") and status=1 "); } @@ -231,7 +231,7 @@ class ReplicateListener set status = '".mysql_real_escape_string($row[3])."', type = '".mysql_real_escape_string($row[4])."', - rating = ".(($row[5] === null) ? "null" : $row[5]).", + rating = ".(($row[5] === null) ? "null" : "'".mysql_real_escape_string($row[5])."'").", flags = '".mysql_real_escape_string($row[6])."' where cache_id = '".mysql_real_escape_string($row[0])."' diff --git a/htdocs/okapi/services/caches/map/tiletree.inc.php b/htdocs/okapi/services/caches/map/tiletree.inc.php index 3ad7c8c8..4cac67d6 100644 --- a/htdocs/okapi/services/caches/map/tiletree.inc.php +++ b/htdocs/okapi/services/caches/map/tiletree.inc.php @@ -83,27 +83,30 @@ class TileTree $tile_upper_x = $x << 8; $tile_leftmost_y = $y << 8; + $zoom_escaped = "'".mysql_real_escape_string($zoom)."'"; + $tile_upper_x_escaped = "'".mysql_real_escape_string($tile_upper_x)."'"; + $tile_leftmost_y_escaped = "'".mysql_real_escape_string($tile_leftmost_y)."'"; return Db::query(" select otc.cache_id, - cast(otc.z21x >> (21 - $zoom) as signed) - $tile_upper_x as px, - cast(otc.z21y >> (21 - $zoom) as signed) - $tile_leftmost_y as py, + cast(otc.z21x >> (21 - $zoom_escaped) as signed) - $tile_upper_x_escaped as px, + cast(otc.z21y >> (21 - $zoom_escaped) as signed) - $tile_leftmost_y_escaped as py, otc.status, otc.type, otc.rating, otc.flags, count(*) from okapi_tile_caches otc, okapi_search_results osr where - z = '".mysql_real_escape_string($zoom)."' + z = $zoom_escaped and x = '".mysql_real_escape_string($x)."' and y = '".mysql_real_escape_string($y)."' and otc.cache_id = osr.cache_id and osr.set_id = '".mysql_real_escape_string($set_id)."' group by - z21x >> (3 + (21 - $zoom)), - z21y >> (3 + (21 - $zoom)) + z21x >> (3 + (21 - $zoom_escaped)), + z21y >> (3 + (21 - $zoom_escaped)) order by - z21y >> (3 + (21 - $zoom)), - z21x >> (3 + (21 - $zoom)) + z21y >> (3 + (21 - $zoom_escaped)), + z21x >> (3 + (21 - $zoom_escaped)) "); } @@ -161,7 +164,7 @@ class TileTree '".mysql_real_escape_string($row[2])."', '".mysql_real_escape_string($row[3])."', '".mysql_real_escape_string($row[4])."', - ".(($row[5] === null) ? "null" : $row[5]).", + ".(($row[5] === null) ? "null" : "'".mysql_real_escape_string($row[5])."'").", '".mysql_real_escape_string($row[6])."' ); "); diff --git a/htdocs/okapi/services/caches/search/save.php b/htdocs/okapi/services/caches/search/save.php index d1bf53ae..e51f25d8 100644 --- a/htdocs/okapi/services/caches/search/save.php +++ b/htdocs/okapi/services/caches/search/save.php @@ -80,6 +80,10 @@ class WebService return Okapi::formatted_response($request, $result); } + /** + * Important: YOU HAVE TO make sure $tables and $where_conds don't contain + * unescaped user-supplied data! + */ public static function get_set($tables, $where_conds, $min_store, $ref_max_age) { # Compute the "params hash". diff --git a/htdocs/okapi/services/caches/search/searching.inc.php b/htdocs/okapi/services/caches/search/searching.inc.php index 43ada092..4f3726d1 100644 --- a/htdocs/okapi/services/caches/search/searching.inc.php +++ b/htdocs/okapi/services/caches/search/searching.inc.php @@ -570,6 +570,9 @@ class SearchAssistant * the query, * - order_by - list or SQL clauses to be used with ORDER BY, * - limit - maximum number of cache codes to be returned. + * + * Important: YOU HAVE TO make sure that all options are properly sanitized + * for SQL queries! I.e. they cannot contain unescaped user-supplied data. */ public static function get_common_search_result($options) { diff --git a/htdocs/okapi/services/logs/entry.xml b/htdocs/okapi/services/logs/entry.xml index d9d9835c..cc7bfe29 100644 --- a/htdocs/okapi/services/logs/entry.xml +++ b/htdocs/okapi/services/logs/entry.xml @@ -14,8 +14,10 @@
date - date and time (ISO 8601) when the log entry was submitted.
-Note, that some Opencaching servers don't store the exact times along - with the log entries.
+Please note that log entries often contain dates only (with the times + truncated to midnight, as in the local timezone). In such cases, you may + want to avoid displaying the time. You may assume that if the date + value contains the "00:00:00" string, then it is date-only.
user - a dictionary:
diff --git a/htdocs/okapi/services/logs/submit.php b/htdocs/okapi/services/logs/submit.php index 0cc85baf..9b9439c9 100644 --- a/htdocs/okapi/services/logs/submit.php +++ b/htdocs/okapi/services/logs/submit.php @@ -100,7 +100,7 @@ class WebService throw new InvalidParam('recommend', "Unknown option: '$recommend'."); $recommend = ($recommend == 'true'); if ($recommend && $logtype != 'Found it') - throw new BadRequest(_("Recommending is allowed only for 'Found it' logtypes.")); + throw new BadRequest("Recommending is allowed only for 'Found it' logtypes."); $needs_maintenance = $request->get_parameter('needs_maintenance'); if (!$needs_maintenance) $needs_maintenance = 'false'; @@ -165,10 +165,6 @@ class WebService if ($comment_format == 'plaintext') { - # If we would like to be compatible with old OCDE/OC.nl installation, - # "$comment_format == 'auto'" should go here, too. But we must choose - # to resemble either old OCDE or OCPL behaviour and opt for OCPL compatibility. - $formatted_comment = htmlspecialchars($comment, ENT_QUOTES); $formatted_comment = nl2br($formatted_comment); $value_for_text_html_field = 0; @@ -177,9 +173,9 @@ class WebService { if ($comment_format == 'auto') { - # This does not make sense on HTML comments, but it resembles the - # OCPL implementation and is needed for full compatibility with existing - # OKAPI clients. + # 'Auto' is for backward compatibility. Before the "comment_format" + # was introduced, OKAPI used a weird format in between (it allowed + # HTML, but applied nl2br too). $formatted_comment = nl2br($comment); } diff --git a/htdocs/okapi/services/logs/submit.xml b/htdocs/okapi/services/logs/submit.xml index 29d0f3c6..fdf41867 100644 --- a/htdocs/okapi/services/logs/submit.xml +++ b/htdocs/okapi/services/logs/submit.xml @@ -18,7 +18,7 @@Indicates the format of your comment. Three values allowed: - auto, html or plaintext. Usually, you should not + auto, html or plaintext. Usually, you should not use the auto option, because its exact behavior is unspecified and may depend on the installation (more info).
diff --git a/htdocs/okapi/services/logs/userlogs.xml b/htdocs/okapi/services/logs/userlogs.xml index 7e00c565..3ad4d62f 100644 --- a/htdocs/okapi/services/logs/userlogs.xml +++ b/htdocs/okapi/services/logs/userlogs.xml @@ -23,8 +23,10 @@date - date and time (ISO 8601) when the log entry was submitted.
-Note, that some Opencaching servers don't store the exact times along - with the log entries.
+Please note that log entries often contain dates only (with the times + truncated to midnight, as in the local timezone). In such cases, you may + want to avoid displaying the time. You may assume that if the date + value contains the "00:00:00" string, then it is date-only.