]> git.street.me.uk Git - andy/viking.git/blame - src/vikwebtool_datasource.c
Remove not very helpful debug message since it can generate large volumes of messages.
[andy/viking.git] / src / vikwebtool_datasource.c
CommitLineData
82993cc7
RN
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2/*
3 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 *
5 * Copyright (C) 2013, Rob Norris <rw_norris@hotmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "vikwebtool_datasource.h"
3c304fd0 28#include <ctype.h>
82993cc7
RN
29#include <string.h>
30
31#include <glib.h>
32#include <glib/gi18n.h>
33
34#include "globals.h"
35#include "acquire.h"
3957ef85 36#include "maputils.h"
9449ccf9 37#include "dialog.h"
82993cc7
RN
38
39static GObjectClass *parent_class;
290fa6d7 40static GHashTable *last_user_strings = NULL;
82993cc7
RN
41
42static void webtool_datasource_finalize ( GObject *gob );
43
44static gchar *webtool_datasource_get_url ( VikWebtool *self, VikWindow *vw );
45
1a8f3840 46static gboolean webtool_needs_user_string ( VikWebtool *self );
e16e573b 47
82993cc7
RN
48typedef struct _VikWebtoolDatasourcePrivate VikWebtoolDatasourcePrivate;
49
50struct _VikWebtoolDatasourcePrivate
51{
52 gchar *url;
53 gchar *url_format_code;
54 gchar *file_type;
19d749d8 55 gchar *babel_filter_args;
1a8f3840
MH
56 gchar *input_label;
57 gchar *user_string;
82993cc7
RN
58};
59
60#define WEBTOOL_DATASOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
61 VIK_WEBTOOL_DATASOURCE_TYPE, \
62 VikWebtoolDatasourcePrivate))
63
64G_DEFINE_TYPE (VikWebtoolDatasource, vik_webtool_datasource, VIK_WEBTOOL_TYPE)
65
66enum
67{
68 PROP_0,
69 PROP_URL,
70 PROP_URL_FORMAT_CODE,
71 PROP_FILE_TYPE,
1a8f3840
MH
72 PROP_BABEL_FILTER_ARGS,
73 PROP_INPUT_LABEL
82993cc7
RN
74};
75
76static void webtool_datasource_set_property (GObject *object,
77 guint property_id,
78 const GValue *value,
79 GParamSpec *pspec)
80{
81 VikWebtoolDatasource *self = VIK_WEBTOOL_DATASOURCE ( object );
82 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
83
84 switch ( property_id ) {
290fa6d7
MH
85
86 case PROP_URL:
82993cc7
RN
87 g_free ( priv->url );
88 priv->url = g_value_dup_string ( value );
89 g_debug ( "VikWebtoolDatasource.url: %s", priv->url );
90 break;
91
92 case PROP_URL_FORMAT_CODE:
93 g_free ( priv->url_format_code );
94 priv->url_format_code = g_value_dup_string ( value );
95 g_debug ( "VikWebtoolDatasource.url_format_code: %s", priv->url_format_code );
96 break;
97
98 case PROP_FILE_TYPE:
99 g_free ( priv->file_type );
100 priv->file_type = g_value_dup_string ( value );
101 g_debug ( "VikWebtoolDatasource.file_type: %s", priv->url_format_code );
102 break;
103
19d749d8
MH
104 case PROP_BABEL_FILTER_ARGS:
105 g_free ( priv->babel_filter_args );
106 priv->babel_filter_args = g_value_dup_string ( value );
107 g_debug ( "VikWebtoolDatasource.babel_filter_args: %s", priv->babel_filter_args );
108 break;
109
1a8f3840
MH
110 case PROP_INPUT_LABEL:
111 g_free ( priv->input_label );
112 priv->input_label = g_value_dup_string ( value );
113 g_debug ( "VikWebtoolDatasource.input_label: %s", priv->input_label );
114 break;
115
82993cc7
RN
116 default:
117 /* We don't have any other property... */
118 G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, property_id, pspec );
119 break;
19d749d8 120 }
82993cc7
RN
121}
122
123static void webtool_datasource_get_property (GObject *object,
124 guint property_id,
125 GValue *value,
126 GParamSpec *pspec)
127{
128 VikWebtoolDatasource *self = VIK_WEBTOOL_DATASOURCE ( object );
129 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
130
131 switch ( property_id ) {
132
19d749d8
MH
133 case PROP_URL: g_value_set_string ( value, priv->url ); break;
134 case PROP_URL_FORMAT_CODE: g_value_set_string ( value, priv->url_format_code ); break;
135 case PROP_FILE_TYPE: g_value_set_string ( value, priv->url ); break;
136 case PROP_BABEL_FILTER_ARGS: g_value_set_string ( value, priv->babel_filter_args ); break;
1a8f3840 137 case PROP_INPUT_LABEL: g_value_set_string ( value, priv->input_label ); break;
82993cc7
RN
138
139 default:
140 /* We don't have any other property... */
141 G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, property_id, pspec );
142 break;
19d749d8 143 }
82993cc7
RN
144}
145
146typedef struct {
147 VikExtTool *self;
148 VikWindow *vw;
149 VikViewport *vvp;
1a8f3840 150 GtkWidget *user_string;
82993cc7
RN
151} datasource_t;
152
290fa6d7
MH
153
154static void ensure_last_user_strings_hash() {
155 if ( last_user_strings == NULL ) {
156 last_user_strings = g_hash_table_new_full ( g_str_hash,
157 g_str_equal,
158 g_free,
159 g_free );
160 }
161}
162
163
164static gchar *get_last_user_string ( const datasource_t *source ) {
165 ensure_last_user_strings_hash();
166 gchar *label = vik_ext_tool_get_label ( source->self );
167 gchar *last_str = g_hash_table_lookup ( last_user_strings, label );
168 g_free( label );
169 return last_str;
170}
171
172
173static void set_last_user_string ( const datasource_t *source, const gchar *s ) {
174 ensure_last_user_strings_hash();
175 g_hash_table_insert ( last_user_strings,
176 vik_ext_tool_get_label ( source->self ),
177 g_strdup ( s ) );
178}
179
82993cc7
RN
180static gpointer datasource_init ( acq_vik_t *avt )
181{
182 datasource_t *data = g_malloc(sizeof(*data));
183 data->self = avt->userdata;
184 data->vw = avt->vw;
185 data->vvp = avt->vvp;
1a8f3840 186 data->user_string = NULL;
82993cc7
RN
187 return data;
188}
189
e16e573b
MH
190static void datasource_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
191{
192 datasource_t *widgets = (datasource_t *)user_data;
1a8f3840
MH
193 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( widgets->self );
194 GtkWidget *user_string_label;
195 gchar *label = g_strdup_printf( "%s:", priv->input_label );
196 user_string_label = gtk_label_new ( label );
197 widgets->user_string = gtk_entry_new ( );
198
290fa6d7
MH
199 gchar *last_str = get_last_user_string ( widgets );
200 if ( last_str )
201 gtk_entry_set_text( GTK_ENTRY( widgets->user_string ), last_str );
e16e573b 202
9449ccf9
RN
203 // 'ok' when press return in the entry
204 g_signal_connect_swapped (widgets->user_string, "activate", G_CALLBACK(a_dialog_response_accept), dialog);
205
e16e573b
MH
206 /* Packing all widgets */
207 GtkBox *box = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
1a8f3840
MH
208 gtk_box_pack_start ( box, user_string_label, FALSE, FALSE, 5 );
209 gtk_box_pack_start ( box, widgets->user_string, FALSE, FALSE, 5 );
210 gtk_widget_show_all ( dialog );
9449ccf9
RN
211 gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
212 // NB presently the focus is overridden later on by the acquire.c code.
213 gtk_widget_grab_focus ( widgets->user_string );
1a8f3840 214
1a8f3840 215 g_free ( label );
e16e573b
MH
216}
217
218
219
82993cc7
RN
220static void datasource_get_cmd_string ( gpointer user_data, gchar **cmd, gchar **extra, DownloadMapOptions *options )
221{
222 datasource_t *data = (datasource_t*) user_data;
223
224 VikWebtool *vwd = VIK_WEBTOOL ( data->self );
e16e573b
MH
225 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( data->self );
226
1a8f3840
MH
227 if ( webtool_needs_user_string ( vwd ) ) {
228 priv->user_string = g_strdup ( gtk_entry_get_text ( GTK_ENTRY ( data->user_string ) ) );
229
230 if ( priv->user_string[0] != '\0' ) {
290fa6d7 231 set_last_user_string ( data, priv->user_string );
1a8f3840
MH
232 }
233 }
e16e573b 234
82993cc7
RN
235 gchar *url = vik_webtool_get_url ( vwd, data->vw );
236 g_debug ("%s: %s", __FUNCTION__, url );
237
1aefc7eb 238 *cmd = g_strdup ( url );
82993cc7
RN
239
240 // Only use first section of the file_type string
241 // One can't use values like 'kml -x transform,rte=wpt' in order to do fancy things
242 // since it won't be in the right order for the overall GPSBabel command
243 // So prevent any potentially dangerous behaviour
82993cc7
RN
244 gchar **parts = NULL;
245 if ( priv->file_type )
246 parts = g_strsplit ( priv->file_type, " ", 0);
247 if ( parts )
248 *extra = g_strdup ( parts[0] );
249 else
250 *extra = NULL;
251 g_strfreev ( parts );
252
253 options = NULL;
254}
255
256static gboolean datasource_process ( VikTrwLayer *vtl, const gchar *cmd, const gchar *extra, BabelStatusFunc status_cb, acq_dialog_widgets_t *adw, DownloadMapOptions *options )
257{
19d749d8
MH
258 datasource_t *data = (datasource_t *)adw->user_data;
259 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( data->self );
82993cc7
RN
260 // Dependent on the ExtTool / what extra has been set to...
261 // When extra is NULL - then it interprets results as a GPX
19d749d8 262 gboolean result = a_babel_convert_from_url_filter ( vtl, cmd, extra, priv->babel_filter_args, status_cb, adw, options);
82993cc7
RN
263 return result;
264}
265
266static void cleanup ( gpointer data )
267{
268 g_free ( data );
269}
270
271static void webtool_datasource_open ( VikExtTool *self, VikWindow *vw )
272{
1a8f3840 273 gboolean search = webtool_needs_user_string ( VIK_WEBTOOL ( self ) );
e16e573b 274
82993cc7
RN
275 // Use VikDataSourceInterface to give thready goodness controls of downloading stuff (i.e. can cancel the request)
276
277 // Can now create a 'VikDataSourceInterface' on the fly...
278 VikDataSourceInterface *vik_datasource_interface = g_malloc(sizeof(VikDataSourceInterface));
279
280 // An 'easy' way of assigning values
281 VikDataSourceInterface data = {
282 vik_ext_tool_get_label (self),
283 vik_ext_tool_get_label (self),
284 VIK_DATASOURCE_ADDTOLAYER,
285 VIK_DATASOURCE_INPUTTYPE_NONE,
286 FALSE, // Maintain current view - rather than setting it to the acquired points
287 TRUE,
288 TRUE,
289 (VikDataSourceInitFunc) datasource_init,
290 (VikDataSourceCheckExistenceFunc) NULL,
e16e573b 291 (VikDataSourceAddSetupWidgetsFunc) (search ? datasource_add_setup_widgets : NULL),
82993cc7
RN
292 (VikDataSourceGetCmdStringFunc) datasource_get_cmd_string,
293 (VikDataSourceProcessFunc) datasource_process,
294 (VikDataSourceProgressFunc) NULL,
295 (VikDataSourceAddProgressWidgetsFunc) NULL,
296 (VikDataSourceCleanupFunc) cleanup,
297 (VikDataSourceOffFunc) NULL,
298 NULL,
299 0,
300 NULL,
301 NULL,
302 0
303 };
304 memcpy ( vik_datasource_interface, &data, sizeof(VikDataSourceInterface) );
305
9cc13848 306 a_acquire ( vw, vik_window_layers_panel(vw), vik_window_viewport (vw), data.mode, vik_datasource_interface, self, cleanup );
82993cc7
RN
307}
308
309static void vik_webtool_datasource_class_init ( VikWebtoolDatasourceClass *klass )
310{
311 GObjectClass *gobject_class;
312 VikWebtoolClass *base_class;
313 GParamSpec *pspec;
314
315 gobject_class = G_OBJECT_CLASS (klass);
316
317 gobject_class->finalize = webtool_datasource_finalize;
318 gobject_class->set_property = webtool_datasource_set_property;
319 gobject_class->get_property = webtool_datasource_get_property;
320
321 pspec = g_param_spec_string ("url",
322 "Template URL",
323 "Set the template URL",
324 VIKING_URL /* default value */,
325 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
326 g_object_class_install_property (gobject_class,
327 PROP_URL,
328 pspec);
329
330 pspec = g_param_spec_string ("url_format_code",
331 "Template URL Format Code",
332 "Set the template URL format code",
333 "LRBT", // default value
334 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
335 g_object_class_install_property (gobject_class,
336 PROP_URL_FORMAT_CODE,
337 pspec);
338
339 pspec = g_param_spec_string ("file_type",
340 "The file type expected",
341 "Set the file type",
342 NULL, // default value ~ equates to internal GPX reading
343 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
344 g_object_class_install_property (gobject_class,
345 PROP_FILE_TYPE,
346 pspec);
347
19d749d8
MH
348 pspec = g_param_spec_string ("babel_filter_args",
349 "The command line filter options to pass to gpsbabel",
350 "Set the command line filter options for gpsbabel",
1a8f3840 351 NULL, // default value
19d749d8
MH
352 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
353 g_object_class_install_property (gobject_class,
354 PROP_BABEL_FILTER_ARGS,
355 pspec);
356
1a8f3840
MH
357 pspec = g_param_spec_string ("input_label",
358 "The label for the user input box if input is required.",
359 "Set the label to be shown next to the user input box if an input term is required",
9449ccf9 360 _("Search Term"),
1a8f3840
MH
361 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
362 g_object_class_install_property (gobject_class,
363 PROP_INPUT_LABEL,
364 pspec);
19d749d8 365
82993cc7
RN
366 parent_class = g_type_class_peek_parent (klass);
367
368 base_class = VIK_WEBTOOL_CLASS ( klass );
369 base_class->get_url = webtool_datasource_get_url;
370
371 // Override default open function here:
372 VikExtToolClass *ext_tool_class = VIK_EXT_TOOL_CLASS ( klass );
373 ext_tool_class->open = webtool_datasource_open;
374
375 g_type_class_add_private (klass, sizeof (VikWebtoolDatasourcePrivate));
376}
377
378VikWebtoolDatasource *vik_webtool_datasource_new ()
379{
380 return VIK_WEBTOOL_DATASOURCE ( g_object_new ( VIK_WEBTOOL_DATASOURCE_TYPE, NULL ) );
381}
382
383VikWebtoolDatasource *vik_webtool_datasource_new_with_members ( const gchar *label,
384 const gchar *url,
385 const gchar *url_format_code,
19d749d8 386 const gchar *file_type,
1a8f3840
MH
387 const gchar *babel_filter_args,
388 const gchar *input_label )
82993cc7
RN
389{
390 VikWebtoolDatasource *result = VIK_WEBTOOL_DATASOURCE ( g_object_new ( VIK_WEBTOOL_DATASOURCE_TYPE,
391 "label", label,
392 "url", url,
393 "url_format_code", url_format_code,
394 "file_type", file_type,
19d749d8 395 "babel_filter_args", babel_filter_args,
1a8f3840 396 "input_label", input_label,
82993cc7
RN
397 NULL ) );
398
399 return result;
400}
401
402static void vik_webtool_datasource_init ( VikWebtoolDatasource *self )
403{
404 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE (self);
405 priv->url = NULL;
406 priv->url_format_code = NULL;
407 priv->file_type = NULL;
19d749d8 408 priv->babel_filter_args = NULL;
1a8f3840
MH
409 priv->input_label = NULL;
410 priv->user_string = NULL;
82993cc7
RN
411}
412
413static void webtool_datasource_finalize ( GObject *gob )
414{
415 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( gob );
416 g_free ( priv->url ); priv->url = NULL;
417 g_free ( priv->url_format_code ); priv->url_format_code = NULL;
418 g_free ( priv->file_type ); priv->file_type = NULL;
1a8f3840
MH
419 g_free ( priv->babel_filter_args ); priv->babel_filter_args = NULL;
420 g_free ( priv->input_label ); priv->input_label = NULL;
421 g_free ( priv->user_string); priv->user_string = NULL;
82993cc7
RN
422 G_OBJECT_CLASS(parent_class)->finalize(gob);
423}
424
425#define MAX_NUMBER_CODES 7
426
427/**
428 * Calculate individual elements (similarly to the VikWebtool Bounds & Center) for *all* potential values
429 * Then only values specified by the URL format are used in parameterizing the URL
430 */
431static gchar *webtool_datasource_get_url ( VikWebtool *self, VikWindow *vw )
432{
433 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
434 VikViewport *viewport = vik_window_viewport ( vw );
435
436 // Get top left and bottom right lat/lon pairs from the viewport
437 gdouble min_lat, max_lat, min_lon, max_lon;
438 gchar sminlon[G_ASCII_DTOSTR_BUF_SIZE];
439 gchar smaxlon[G_ASCII_DTOSTR_BUF_SIZE];
440 gchar sminlat[G_ASCII_DTOSTR_BUF_SIZE];
441 gchar smaxlat[G_ASCII_DTOSTR_BUF_SIZE];
442 vik_viewport_get_min_max_lat_lon ( viewport, &min_lat, &max_lat, &min_lon, &max_lon );
443
444 // Cannot simply use g_strdup_printf and gdouble due to locale.
445 // As we compute an URL, we have to think in C locale.
446 g_ascii_dtostr (sminlon, G_ASCII_DTOSTR_BUF_SIZE, min_lon);
447 g_ascii_dtostr (smaxlon, G_ASCII_DTOSTR_BUF_SIZE, max_lon);
448 g_ascii_dtostr (sminlat, G_ASCII_DTOSTR_BUF_SIZE, min_lat);
449 g_ascii_dtostr (smaxlat, G_ASCII_DTOSTR_BUF_SIZE, max_lat);
450
451 // Center values
452 const VikCoord *coord = vik_viewport_get_center ( viewport );
453 struct LatLon ll;
454 vik_coord_to_latlon ( coord, &ll );
455
456 gchar scenterlat[G_ASCII_DTOSTR_BUF_SIZE];
457 gchar scenterlon[G_ASCII_DTOSTR_BUF_SIZE];
458 g_ascii_dtostr (scenterlat, G_ASCII_DTOSTR_BUF_SIZE, ll.lat);
459 g_ascii_dtostr (scenterlon, G_ASCII_DTOSTR_BUF_SIZE, ll.lon);
460
461 guint8 zoom = 17; // A zoomed in default
462 // zoom - ideally x & y factors need to be the same otherwise use the default
463 if ( vik_viewport_get_xmpp ( viewport ) == vik_viewport_get_ympp ( viewport ) )
3957ef85 464 zoom = map_utils_mpp_to_zoom_level ( vik_viewport_get_zoom ( viewport ) );
82993cc7
RN
465
466 gchar szoom[G_ASCII_DTOSTR_BUF_SIZE];
467 g_snprintf ( szoom, G_ASCII_DTOSTR_BUF_SIZE, "%d", zoom );
468
469 gint len = 0;
470 if ( priv->url_format_code )
471 len = strlen ( priv->url_format_code );
472 if ( len > MAX_NUMBER_CODES )
473 len = MAX_NUMBER_CODES;
474
475 gchar* values[MAX_NUMBER_CODES];
476 int i;
477 for ( i = 0; i < MAX_NUMBER_CODES; i++ ) {
644eea0e 478 values[i] = '\0';
82993cc7
RN
479 }
480
481 for ( i = 0; i < len; i++ ) {
482 switch ( g_ascii_toupper ( priv->url_format_code[i] ) ) {
483 case 'L': values[i] = g_strdup ( sminlon ); break;
484 case 'R': values[i] = g_strdup ( smaxlon ); break;
485 case 'B': values[i] = g_strdup ( sminlat ); break;
486 case 'T': values[i] = g_strdup ( smaxlat ); break;
487 case 'A': values[i] = g_strdup ( scenterlat ); break;
488 case 'O': values[i] = g_strdup ( scenterlon ); break;
489 case 'Z': values[i] = g_strdup ( szoom ); break;
1a8f3840 490 case 'S': values[i] = g_strdup ( priv->user_string ); break;
82993cc7
RN
491 default: break;
492 }
493 }
494
495 gchar *url = g_strdup_printf ( priv->url, values[0], values[1], values[2], values[3], values[4], values[5], values[6] );
496
497 for ( i = 0; i < MAX_NUMBER_CODES; i++ ) {
644eea0e
RN
498 if ( values[i] != '\0' )
499 g_free ( values[i] );
82993cc7
RN
500 }
501
502 return url;
503}
e16e573b 504
3c304fd0
RN
505// NB Only works for ascii strings
506char* strcasestr2(const char *dst, const char *src)
507{
508 if ( !dst || !src )
509 return NULL;
510
511 if(src[0] == '\0')
512 return (char*)dst;
513
514 int len = strlen(src) - 1;
515 char sc = tolower(src[0]);
516 for(char dc = *dst; (dc = *dst); dst++) {
517 dc = tolower(dc);
518 if(sc == dc && (len == 0 || !strncasecmp(dst+1, src+1, len)))
519 return (char*)dst;
520 }
521
522 return NULL;
523}
524
e16e573b
MH
525/**
526 * Returns true if the URL format contains 'S' -- that is, a search term entry
527 * box needs to be displayed
528 */
1a8f3840 529static gboolean webtool_needs_user_string ( VikWebtool *self )
e16e573b
MH
530{
531 VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
3c304fd0
RN
532 // For some reason (my) Windows build gets built with -D_GNU_SOURCE
533#if (_GNU_SOURCE && !WINDOWS)
e16e573b 534 return (strcasestr(priv->url_format_code, "S") != NULL);
3c304fd0
RN
535#else
536 return (strcasestr2(priv->url_format_code, "S") != NULL);
537#endif
e16e573b 538}