Fix a crash
[framework/location/libdecarta.git] / decarta / decarta_xml_route.c
1 /*
2  * libdecarta
3  *
4  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
7  *          Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #include <glib.h>
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include "decarta_log.h"
27 #include "xml_wrapper.h"
28 #include "decarta_xml.h"
29 #include "decarta_xml_internal.h"
30
31 static char*
32 get_route_pref (DecartaRoutePreference pref)
33 {
34         char *ret = NULL;
35         if (pref == DECARTA_ROUTE_PREF_FASTEST) ret = g_strdup ("fastest");
36         else if (pref == DECARTA_ROUTE_PREF_SHORTEST) ret = g_strdup ("shortest");
37         else if (pref == DECARTA_ROUTE_PREF_PEDESTRIAN) ret = g_strdup ("pedestrian");
38         else if (pref == DECARTA_ROUTE_PREF_AVOID_FREEWAYS) ret = g_strdup ("AvoidFreeways");
39         else if (pref == DECARTA_ROUTE_PREF_NO_FREEWAYS) ret = g_strdup ("NoFreeways");
40         else if (pref == DECARTA_ROUTE_PREF_MORE_FREEWAYS) ret = g_strdup ("MoreFreeways");
41         else if (pref == DECARTA_ROUTE_PREF_IGNORE_PIPES) ret = g_strdup ("IgnorePipes");
42         else if (pref == DECARTA_ROUTE_PREF_EASY) ret = g_strdup ("easy");
43         return ret;
44 }
45
46 static unsigned int
47 get_time_from_string (const char* str)
48 {
49         if (!str) return 0;
50         unsigned int time = 0;
51
52         gchar **part = g_strsplit_set (str, "S", 2);
53         g_free (part[1]);
54
55         gchar **part_s = g_strsplit_set (part[0], "M", 2);
56         g_free (part[0]);
57         time += g_ascii_strtoull (part_s[1], NULL, 10);
58         g_free (part_s[1]);
59
60         gchar **part_m = g_strsplit_set (part_s[0], "H", 2);
61         g_free (part_s[0]);
62         time += (g_ascii_strtoull (part_m[1], NULL, 10)*60);
63         g_free (part_m[1]);
64
65         gchar **part_h = g_strsplit_set (part_m[0], "DT", 2);
66         g_free (part_m[0]);
67         time += (g_ascii_strtoull (part_h[1], NULL, 10)*3600);
68         g_free (part_h[1]);
69
70         gchar **part_d = g_strsplit_set (part_h[0], "P", 2);
71         g_free (part_h[0]);
72         time += (g_ascii_strtoull (part_d [1], NULL, 10)*3600*24);
73         g_free (part_d [1]);
74         g_free (part_d [0]);
75         return time;
76 }
77
78 static gboolean
79 make_xml_waypoint_list (XmlWriterHandler handle,
80         const DecartaRouteRequest *request)
81 {
82         if (!handle || !request || !request->start || !request->end) return FALSE;
83
84         if (!xml_writer_all_start(handle, NS_XLS":WayPointList", NULL, NULL)) return FALSE;
85         if (!make_xml_point (handle, NS_XLS":StartPoint", request->start)) return FALSE;
86         if (!xml_writer_end(handle)) return FALSE;
87
88         if (request->via_geocode_list) {
89                 const DecartaGeocode *via = NULL;
90                 GList *via_geocode_list = decarta_geocode_list_next (request->via_geocode_list, &via);
91                 while (via) {
92                         if (!make_xml_point(handle, NS_XLS":ViaPoint", via)) return FALSE;
93                         if (!xml_writer_end(handle)) return FALSE;
94                         if (!via_geocode_list) break;
95                         via_geocode_list = decarta_geocode_list_next(via_geocode_list, &via);
96                 }
97         }
98         if (!make_xml_point (handle, NS_XLS":EndPoint", request->end)) return FALSE;
99         if (!xml_writer_end(handle)) return FALSE;
100         if (!xml_writer_end(handle)) return FALSE;
101         return TRUE;
102 }
103
104 gboolean
105 xml_route_request_get (const DecartaRouteRequest *request,
106         char **xml_request,
107         unsigned int *size)
108 {
109         if (!request || !xml_request || !size) {
110                 DECARTA_LOGW ("request or xml_request or size is NULL");
111                 return FALSE;
112         }
113         gboolean ret = FALSE;
114         XmlWriterHandler handle = xml_writer_open("UTF-8");
115         char *pref_str = get_route_pref (request->pref);
116         if (!handle) {
117                 g_free(pref_str);
118                 return FALSE;
119         }
120         if (make_xml_header (handle, "DetermineRouteRequest", NULL, NULL) &&
121                 xml_writer_all_start (handle, NS_XLS":DetermineRouteRequest", NULL, "provideRouteHandle", "false", "distanceUnit", request->dist_unit, NULL) &&
122                 xml_writer_all_start (handle, NS_XLS":RoutePlan", NULL, NULL) &&
123                 xml_writer_all_start (handle, NS_XLS":RoutePreference", pref_str, NULL) &&
124                 xml_writer_end(handle) &&
125                 make_xml_waypoint_list (handle, request) &&
126                 xml_writer_end(handle)) {
127                 ret = TRUE;
128                 if (request->instructions_map_needed) {
129                         if (!xml_writer_all_start (handle, NS_XLS":RouteInstructionsRequest", NULL, "rules", request->rules, NULL) ||
130                                 !xml_writer_end(handle)) ret = FALSE;
131                 }
132                 if (request->pos_needed) {
133                         if (request->resolution_needed && request->VR_needed) {
134                                 char resolution_str[32];
135                                 if (g_snprintf (resolution_str, 32, "%f", request->resolution) < 0) ret = FALSE;
136                                 if (!xml_writer_all_start (handle, NS_XLS":RouteGeometryRequest", NULL, "resolution", resolution_str, "routeGeometryFormat", "VR", NULL)) ret = FALSE;
137                         } else if (request->resolution_needed && (request->VR_needed == FALSE)) {
138                                 char resolution_str[32];
139                                 if (g_snprintf (resolution_str, 32, "%f", request->resolution) < 0) ret = FALSE;
140                                 if (!xml_writer_all_start (handle, NS_XLS":RouteGeometryRequest", NULL, "resolution", resolution_str, NULL)) ret = FALSE;
141                         } else if ((request->resolution_needed == FALSE) && request->VR_needed) {
142                                 if (!xml_writer_all_start (handle, NS_XLS":RouteGeometryRequest", NULL, "routeGeometryFormat", "VR", NULL)) ret = FALSE;
143                         } else {
144                                 if (!xml_writer_all_start (handle, NS_XLS":RouteGeometryRequest", NULL, NULL)) ret = FALSE;
145                         }
146                         if (request->bbox_needed) {
147                                 if (!xml_writer_all_start (handle, NS_XLS":BoundingBox", NULL, NULL)) ret = FALSE;
148                                 if (!make_xml_position(handle, request->bbox_pos1)) ret = FALSE;
149                                 if (!make_xml_position(handle, request->bbox_pos2)) ret = FALSE;
150                                 if (!xml_writer_end(handle)) ret = FALSE;
151                         }
152                         if (!xml_writer_end(handle)) ret = FALSE;
153                 }
154                 if (request->instructions_map_needed) {
155                         if (!xml_writer_all_start (handle, NS_XLS":RouteMapRequest", NULL, NULL) ||
156                                 !xml_writer_all_start (handle, NS_XLS":Output", NULL, "width", "500", "height", "500", "style", "Overview", "format", IMG_FORMAT, NULL) ||
157                                 !xml_writer_end(handle) ||
158                                 !xml_writer_all_start (handle, NS_XLS":Output", NULL, "width", TILE_SIZE, "height", TILE_SIZE, "style", "Maneuver", "format", IMG_FORMAT, NULL) ||
159                                 !xml_writer_end(handle) ||
160                                 !xml_writer_end(handle)) ret = FALSE;
161                 }
162         } else ret = FALSE;
163         if (!xml_writer_close(handle, xml_request, size)) ret = FALSE;
164         g_free (pref_str);
165         return ret;
166 }
167
168 static void __route_geo_addr_list_free_cb (gpointer data)
169 {
170         g_return_if_fail (data);
171
172         decarta_geo_addr_s *addr_item = (decarta_geo_addr_s *)data;
173         if (addr_item->building_num) {
174                 g_free(addr_item->building_num);
175         }
176         if (addr_item->country_2_subdivision) {
177                 g_free(addr_item->country_2_subdivision);
178         }
179         if (addr_item->country_code) {
180                 g_free(addr_item->country_code);
181         }
182         if (addr_item->country_subdivision) {
183                 g_free(addr_item->country_subdivision);
184         }
185         if (addr_item->freeform_addr) {
186                 g_free(addr_item->freeform_addr);
187         }
188         if (addr_item->landmark_name) {
189                 g_free(addr_item->landmark_name);
190         }
191         if (addr_item->landmark_type) {
192                 g_free(addr_item->landmark_type);
193         }
194         if (addr_item->lang_code) {
195                 g_free(addr_item->lang_code);
196         }
197         if (addr_item->municipality) {
198                 g_free(addr_item->municipality);
199         }
200         if (addr_item->municipality_subdivision) {
201                 g_free(addr_item->municipality_subdivision);
202         }
203         if (addr_item->pos) {
204                 g_free(addr_item->pos);
205         }
206         if (addr_item->postcode) {
207                 g_free(addr_item->postcode);
208         }
209         if (addr_item->street) {
210                 g_free(addr_item->street);
211         }
212 }
213
214 static void __route_instruction_list_free_cb (gpointer data)
215 {
216         g_return_if_fail (data);
217
218         decarta_route_inst_str_s *inst_item = (decarta_route_inst_str_s *)data;
219         if (inst_item->duration) {
220                 g_free(inst_item->duration);
221         }
222         if (inst_item->distance) {
223                 g_free(inst_item->distance);
224         }
225         if (inst_item->tour) {
226                 g_free(inst_item->tour);
227         }
228         if (inst_item->instruction) {
229                 g_free(inst_item->instruction);
230         }
231         if (inst_item->description) {
232                 g_free(inst_item->description);
233         }
234 }
235
236 static void __route_map_list_free_cb (gpointer data)
237 {
238         g_return_if_fail (data);
239
240         decarta_route_map_str_s *map_item = (decarta_route_map_str_s *)data;
241         if (map_item->url) {
242                 g_free(map_item->url);
243         }
244         if (map_item->description) {
245                 g_free(map_item->description);
246         }
247         if (map_item->pos1) {
248                 g_free(map_item->pos1);
249         }
250         if (map_item->pos2) {
251                 g_free(map_item->pos2);
252         }
253 }
254
255 static void __sax_parse_route(void *user_data, DecartaRoute **route)
256 {
257         DECARTA_LOGD("_sax_parse_route enter ");
258
259         if (!user_data || !route) {
260                 DECARTA_LOGW ("user_data or route is NULL");
261                 return;
262         }
263
264         *route = NULL;
265         GList *start_geo_list = NULL;
266         GList *end_geo_list = NULL;
267         unsigned int total_time = 0;
268         double total_distance = 0;
269         DecartaPosition *box_corner1 = NULL;
270         DecartaPosition *box_corner2 = NULL;
271         GList *line_pos_list = NULL;
272         GList *instructions_list = NULL;
273         DecartaMap *overview_map = NULL;
274
275         /** geometry list*/
276         sax_route_data_s *route_data = (sax_route_data_s *)user_data;
277         if (route_data->route_geometry_str) {
278                 gchar **part = g_strsplit_set(route_data->route_geometry_str, ",", 0);
279                 int n_route_geomoetry = 0;
280                 GArray *garray = NULL;
281                 garray = g_array_new(FALSE, FALSE, sizeof(long));
282                 if (garray) {
283                         while (part[n_route_geomoetry]) {
284                                 long tmp_long = g_ascii_strtoll(part[n_route_geomoetry], NULL, 10);
285                                 g_array_append_val(garray, tmp_long);
286                                 n_route_geomoetry++;
287                         }
288                         g_strfreev(part);
289
290                         DECARTA_LOGD("verify the array:---------number[%d]----------\n", n_route_geomoetry);
291                         int i = 0;
292                         long prev_lat_l = 0;
293                         long prev_lon_l = 0;
294                         DecartaPosition *pos = NULL;
295                         for (i = 0; i < n_route_geomoetry; i++) {
296                                 DECARTA_LOGD("No. [%d]", i);
297                                 if (i == 0) {
298                                         // save the geometry locations number
299                                         int n_geometry = g_array_index(garray, long, i);
300                                         DECARTA_LOGD(" the summary number of route geometry is [%d]\n", n_geometry);
301                                 } else if (i == 2) {
302                                         long lat_l = g_array_index(garray, long, i - 1);
303                                         long lon_l = g_array_index(garray, long, i);
304                                         prev_lat_l = lat_l;
305                                         prev_lon_l = lon_l;
306                                         double lat_d = ((double)lat_l) / 100000;
307                                         double lon_d = ((double)lon_l) / 100000;
308                                         DECARTA_LOGD("first lat [%.5f], lon [%.5f]\n", lat_d, lon_d);
309
310                                         pos = decarta_position_new(lat_d, lon_d);
311                                         line_pos_list = decarta_position_list_append(line_pos_list, pos);
312                                 } else if ((i % 2) == 0) {
313                                         long lat_diff_l = g_array_index(garray, long, i - 1);
314                                         long lon_diff_l = g_array_index(garray, long, i);
315                                         DECARTA_LOGD("lat_diff_l [%ld], lon_diff_l [%ld]\n", lat_diff_l, lon_diff_l);
316                                         long lat_l = lat_diff_l + prev_lat_l;
317                                         long lon_l = lon_diff_l + prev_lon_l;
318                                         prev_lat_l = lat_l;
319                                         prev_lon_l = lon_l;
320                                         double lat_d = ((double)lat_l) / 100000;
321                                         double lon_d = ((double)lon_l) / 100000;
322                                         DECARTA_LOGD("lat [%.5f], lon [%.5f]\n", lat_d, lon_d);
323
324                                         pos = decarta_position_new(lat_d, lon_d);
325                                         line_pos_list = decarta_position_list_append(line_pos_list, pos);
326                                 }
327                         }
328
329                         g_array_free(garray, TRUE);
330                 }
331                 g_free(route_data->route_geometry_str);
332                 route_data->route_geometry_str = NULL;
333         }
334
335         /** total time*/
336         if (route_data->route_totaltime_str) {
337                 total_time = get_time_from_string(route_data->route_totaltime_str);
338                 g_free(route_data->route_totaltime_str);
339         }
340
341         /** total distance*/
342         if (route_data->route_totaldist_str) {
343                 total_distance = g_ascii_strtod(route_data->route_totaldist_str, NULL);
344                 g_free(route_data->route_totaldist_str);
345         }
346
347         /** box*/
348         if (route_data->route_bbox_pos1_str) {
349                 box_corner1 = get_position_from_string (route_data->route_bbox_pos1_str);
350                 g_free (route_data->route_bbox_pos1_str);
351         }
352         if (route_data->route_bbox_pos2_str) {
353                 box_corner2 = get_position_from_string (route_data->route_bbox_pos2_str);
354                 g_free (route_data->route_bbox_pos2_str);
355         }
356
357         /** StartAddressCandidates*/
358         DecartaPosition *pos = NULL;
359         DecartaAddress *addr = NULL;
360         DecartaFormedAddress *formed_addr = NULL;
361         gboolean is_freeformed = FALSE;
362         GList *start_addr_list = g_list_first(route_data->route_start_addr_list);
363         while (start_addr_list) {
364                 decarta_geo_addr_s *start_item = (decarta_geo_addr_s *)start_addr_list->data;
365                 if (!start_item) {
366                         DECARTA_LOGD("start_item NULL, break the start list loop\n");
367                         break;
368                 }
369                 if (start_item->pos) {
370                         DECARTA_LOGD("start pos [%s]\n", start_item->pos);
371                         pos = get_position_from_string(start_item->pos);
372                 }
373                 if (start_item->is_freeform) {
374                         DECARTA_LOGD("start freeform address [%s]\n", start_item->freeform_addr);
375                         is_freeformed = TRUE;
376                 } else {
377                         formed_addr = decarta_formed_address_new(start_item->building_num, start_item->street, start_item->country_subdivision,
378                                 start_item->country_2_subdivision, start_item->municipality, start_item->municipality_subdivision,
379                                 start_item->postcode, start_item->landmark_type, start_item->landmark_name);
380                 }
381                 addr = decarta_address_new(start_item->country_code, start_item->lang_code, is_freeformed, start_item->freeform_addr, formed_addr);
382                 if (formed_addr) {
383                         decarta_formed_address_free(formed_addr);
384                 }
385                 /** create the start address list */
386                 start_geo_list = decarta_geocode_list_append(start_geo_list, decarta_geocode_new(pos, addr));
387                 if (pos) {
388                         decarta_position_free(pos);
389                 }
390                 if (addr) {
391                         decarta_address_free(addr);
392                 }
393                 start_addr_list = g_list_next(start_addr_list);
394         }
395
396         if (route_data->route_start_addr_list) {
397                 g_list_free_full(route_data->route_start_addr_list, __route_geo_addr_list_free_cb);
398                 route_data->route_start_addr_list = NULL;
399         }
400
401         /** EndAddressCandidates*/
402         pos = NULL;
403         addr = NULL;
404         formed_addr = NULL;
405         is_freeformed = FALSE;
406         GList *end_addr_list = g_list_first(route_data->route_end_addr_list);
407         while (end_addr_list) {
408                 decarta_geo_addr_s *end_item = (decarta_geo_addr_s *)end_addr_list->data;
409                 if (!end_item) {
410                         DECARTA_LOGD("start_item NULL, break the end list loop\n");
411                         break;
412                 }
413                 if (end_item->pos) {
414                         DECARTA_LOGD("end pos [%s]\n", end_item->pos);
415                         pos = get_position_from_string(end_item->pos);
416                 }
417                 if (end_item->is_freeform) {
418                         DECARTA_LOGD("end freeform address [%s]\n", end_item->freeform_addr);
419                         is_freeformed = TRUE;
420                 } else {
421                         formed_addr = decarta_formed_address_new(end_item->building_num, end_item->street, end_item->country_subdivision,
422                                 end_item->country_2_subdivision, end_item->municipality, end_item->municipality_subdivision,
423                                 end_item->postcode, end_item->landmark_type, end_item->landmark_name);
424                 }
425                 addr = decarta_address_new(end_item->country_code, end_item->lang_code, is_freeformed, end_item->freeform_addr, formed_addr);
426                 if (formed_addr) {
427                         decarta_formed_address_free(formed_addr);
428                 }
429                 /** create the start address list */
430                 end_geo_list = decarta_geocode_list_append(end_geo_list, decarta_geocode_new (pos, addr));
431                 if (pos) {
432                         decarta_position_free(pos);
433                 }
434                 if (addr) {
435                         decarta_address_free(addr);
436                 }
437                 end_addr_list = g_list_next(end_addr_list);
438         }
439
440         if (route_data->route_end_addr_list) {
441                 g_list_free_full(route_data->route_end_addr_list, __route_geo_addr_list_free_cb);
442                 route_data->route_end_addr_list = NULL;
443         }
444
445         /** route overview*/
446         DecartaPosition *box_corner1_02 = get_position_from_string(route_data->route_ov_pos1_str);
447         DecartaPosition *box_corner2_02 = get_position_from_string(route_data->route_ov_pos2_str);
448         overview_map = decarta_map_new(NULL, box_corner1_02, box_corner2_02, route_data->route_ov_tile_url_str, 0);
449         if (box_corner1_02) {
450                 decarta_position_free (box_corner1_02);
451         }
452         if (box_corner2_02) {
453                 decarta_position_free (box_corner2_02);
454         }
455         if (route_data->route_ov_tile_url_str) {
456                 g_free(route_data->route_ov_tile_url_str);
457         }
458
459         /** instruction*/
460         unsigned int duration= 0;
461         double distance = 0;
462         DecartaMap *map = NULL;
463         GList *inst_list = g_list_first(route_data->route_inst_str_list);
464         while (inst_list) {
465                 decarta_route_inst_str_s *inst_item = (decarta_route_inst_str_s *)inst_list->data;
466                 if (!inst_item) {
467                         DECARTA_LOGD("inst_item NULL, break the inst list loop\n");
468                         break;
469                 }
470                 if (inst_item->instruction) {
471                         DECARTA_LOGD("instruction [%s]\n", inst_item->instruction);
472                 }
473
474                 if (inst_item->duration) {
475                         duration = get_time_from_string(inst_item->duration);
476                 }
477                 if (inst_item->distance) {
478                         distance = g_ascii_strtod(inst_item->distance, NULL);
479                 }
480
481                 /** find the description matched map item */
482                 GList *map_list = g_list_first(route_data->route_map_str_list);
483                 while (map_list) {
484                         decarta_route_map_str_s *map_item = (decarta_route_map_str_s *)map_list->data;
485                         if (map_item) {
486                                 if (!g_strcmp0(inst_item->description, map_item->description)) {
487                                         DECARTA_LOGD("---------inst & map description matched---------\n");
488                                         DecartaPosition *box_corner1_03 = get_position_from_string(map_item->pos1);
489                                         DecartaPosition *box_corner2_03 = get_position_from_string(map_item->pos2);
490                                         map = decarta_map_new(NULL, box_corner1_03, box_corner2_03, map_item->url, 0);
491                                         if (box_corner1_03) {
492                                                 decarta_position_free (box_corner1_03);
493                                         }
494                                         if (box_corner2_03) {
495                                                 decarta_position_free (box_corner2_03);
496                                         }
497                                         /** break when matched map_item found */
498                                         break;
499                                 }
500                         }else {
501                                 DECARTA_LOGD("map_item NULL \n");
502                         }
503                         map_list = g_list_next(map_list);
504                 }
505
506                 /** create the instruction list */
507                 instructions_list = decarta_route_instructions_list_append(instructions_list, decarta_route_instructions_new(inst_item->tour, duration, distance, inst_item->instruction, map));
508                 inst_list = g_list_next(inst_list);
509         }
510
511         if (route_data->route_inst_str_list) {
512                 g_list_free_full(route_data->route_inst_str_list, __route_instruction_list_free_cb);
513                 route_data->route_inst_str_list = NULL;
514         }
515
516         if (route_data->route_map_str_list) {
517                 g_list_free_full(route_data->route_map_str_list, __route_map_list_free_cb);
518                 route_data->route_map_str_list = NULL;
519         }
520
521         /** decarta route*/
522         *route = decarta_route_new(start_geo_list, end_geo_list, total_time, total_distance, box_corner1, box_corner2, overview_map, line_pos_list, instructions_list);
523 }
524
525 gboolean
526 xml_route_parse (const char* xml_response,
527         DecartaRoute **route,
528         char **req_id,
529         char **error_code,
530         char **message)
531 {
532         DECARTA_LOGD ("xml_route_parse");
533         if (!xml_response || !route) {
534                 DECARTA_LOGW ("xml_response or route is NULL");
535                 return FALSE;
536         }
537
538         sax_route_data_s *route_data = g_new0(sax_route_data_s, 1);
539         if (route_data) {
540                 _xml_sax_read(xml_response, route_data);
541
542                 /** check the error code & DetermineRouteResponse */
543                 if (route_data->has_error) {
544                         *error_code = g_strdup(route_data->error_code_str);
545                         *message = g_strdup(route_data->error_message_str);
546
547                         g_free(route_data->error_code_str);
548                         g_free(route_data->error_message_str);
549                         g_free(route_data->error_severity_str);
550                         g_free(route_data);
551                         return FALSE;
552                 }
553                 if (!route_data->has_route_resp) {
554                         g_free(route_data);
555                         return FALSE;
556                 }
557                 __sax_parse_route(route_data, route);
558                 g_free(route_data);
559         }
560
561         if (*route == NULL) {
562                 DECARTA_LOGW("[ERROR]xml_route_parse: route is NULL");
563                 return FALSE;
564         }
565
566         return TRUE;
567 }
568