/[zanavi_public1]/navit/navit/map/binfile/binfile.c
ZANavi

Contents of /navit/navit/map/binfile/binfile.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (show annotations) (download)
Tue Aug 11 18:50:37 2015 UTC (5 years, 1 month ago) by zoff99
File MIME type: text/plain
File size: 77684 byte(s)
many fixes, and new features
1 /**
2 * ZANavi, Zoff Android Navigation system.
3 * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * Navit, a modular navigation system.
22 * Copyright (C) 2005-2008 Navit Team
23 *
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * version 2 as published by the Free Software Foundation.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the
35 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36 * Boston, MA 02110-1301, USA.
37 */
38
39 #include <stdlib.h>
40 #include <glib.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <math.h>
44 #include "config.h"
45 #include "debug.h"
46 #include "plugin.h"
47 #include "projection.h"
48 #include "item.h"
49 #include "map.h"
50 #include "maptype.h"
51 #include "attr.h"
52 #include "coord.h"
53 #include "transform.h"
54 #include "file.h"
55 #include "zipfile.h"
56 #include "linguistics.h"
57 #include "endianess.h"
58 #include "callback.h"
59 #include "types.h"
60 #include "navit.h"
61
62 static int map_id;
63
64 struct tile
65 {
66 int *start;
67 int *end;
68 int *pos;
69 int *pos_coord_start;
70 int *pos_coord;
71 int *pos_attr_start;
72 int *pos_attr;
73 int *pos_next;
74 struct file *fi;
75 int zipfile_num;
76 int mode;
77 };
78
79 struct map_download
80 {
81 int state;
82 struct map_priv *m;
83 struct map_rect_priv *mr;
84 struct file *http, *file;
85 int zipfile, toffset, tlength, progress, read, dl_size;
86 long long offset, start_offset, cd1offset, size;
87 struct zip64_eoc *zip64_eoc;
88 struct zip64_eocl *zip64_eocl;
89 struct zip_eoc *zip_eoc;
90 struct zip_cd *cd_copy, *cd;
91 };
92
93 struct map_priv
94 {
95 int id;
96 char *filename;
97 char *cachedir;
98 struct file *fi, *http;
99 struct file **fis;
100 struct zip_cd *index_cd;
101 int index_offset;
102 int cde_size;
103 struct zip_eoc *eoc;
104 struct zip64_eoc *eoc64;
105 int zip_members;
106 unsigned char *search_data;
107 int search_offset;
108 int search_size;
109 int version;
110 int check_version;
111 int map_version;
112 GHashTable *changes;
113 char *passwd;
114 char *map_release;
115 int flags;
116 char *url;
117 int update_available;
118 char *progress;
119 struct callback_list *cbl;
120 struct map_download *download;
121 int redirect;
122 long download_enabled;
123 };
124
125 struct map_rect_priv
126 {
127 int *start;
128 int *end;
129 enum attr_type attr_last;
130 int label;
131 int *label_attr[5];
132 struct map_selection *sel;
133 struct map_priv *m;
134 struct item item;
135 int tile_depth;
136 struct tile tiles[8];
137 struct tile *t;
138 int country_id;
139 char *url;
140 struct attr attrs[8];
141 int status;
142 #ifdef DEBUG_SIZE
143 int size;
144 #endif
145 };
146
147 struct map_search_priv
148 {
149 struct map_priv *map;
150 struct map_rect_priv *mr;
151 struct map_rect_priv *mr_item;
152 struct item *item;
153 struct attr *search;
154 struct map_selection ms;
155 int partial;
156 int mode;
157 GHashTable *search_results;
158 char *str;
159 };
160
161 static void push_tile(struct map_rect_priv *mr, struct tile *t, int offset, int length);
162 static void setup_pos(struct map_rect_priv *mr);
163 static void map_binfile_close(struct map_priv *m);
164 static int map_binfile_open(struct map_priv *m);
165 static void map_binfile_destroy(struct map_priv *m);
166
167 static void lfh_to_cpu(struct zip_lfh *lfh)
168 {
169 dbg_assert(lfh != NULL);
170 if (lfh->ziplocsig != zip_lfh_sig)
171 {
172 // dbg(0,"_endian 3\n");
173 lfh->ziplocsig = le32_to_cpu(lfh->ziplocsig);
174 lfh->zipver = le16_to_cpu(lfh->zipver);
175 lfh->zipgenfld = le16_to_cpu(lfh->zipgenfld);
176 lfh->zipmthd = le16_to_cpu(lfh->zipmthd);
177 lfh->ziptime = le16_to_cpu(lfh->ziptime);
178 lfh->zipdate = le16_to_cpu(lfh->zipdate);
179 lfh->zipcrc = le32_to_cpu(lfh->zipcrc);
180 lfh->zipsize = le32_to_cpu(lfh->zipsize);
181 lfh->zipuncmp = le32_to_cpu(lfh->zipuncmp);
182 lfh->zipfnln = le16_to_cpu(lfh->zipfnln);
183 lfh->zipxtraln = le16_to_cpu(lfh->zipxtraln);
184 }
185 }
186
187 static void cd_to_cpu(struct zip_cd *zcd)
188 {
189 dbg_assert(zcd != NULL);
190 if (zcd->zipcensig != zip_cd_sig)
191 {
192 // dbg(0,"_endian 1\n");
193 zcd->zipcensig = le32_to_cpu(zcd->zipcensig);
194 zcd->zipccrc = le32_to_cpu(zcd->zipccrc);
195 zcd->zipcsiz = le32_to_cpu(zcd->zipcsiz);
196 zcd->zipcunc = le32_to_cpu(zcd->zipcunc);
197 zcd->zipcfnl = le16_to_cpu(zcd->zipcfnl);
198 zcd->zipcxtl = le16_to_cpu(zcd->zipcxtl);
199 zcd->zipccml = le16_to_cpu(zcd->zipccml);
200 zcd->zipdsk = le16_to_cpu(zcd->zipdsk);
201 zcd->zipint = le16_to_cpu(zcd->zipint);
202 zcd->zipext = le32_to_cpu(zcd->zipext);
203 zcd->zipofst = le32_to_cpu(zcd->zipofst);
204 }
205 }
206
207 static void eoc_to_cpu(struct zip_eoc *eoc)
208 {
209 dbg_assert(eoc != NULL);
210 if (eoc->zipesig != zip_eoc_sig)
211 {
212 // dbg(0,"_endian 2\n");
213 eoc->zipesig = le32_to_cpu(eoc->zipesig);
214 eoc->zipedsk = le16_to_cpu(eoc->zipedsk);
215 eoc->zipecen = le16_to_cpu(eoc->zipecen);
216 eoc->zipenum = le16_to_cpu(eoc->zipenum);
217 eoc->zipecenn = le16_to_cpu(eoc->zipecenn);
218 eoc->zipecsz = le32_to_cpu(eoc->zipecsz);
219 eoc->zipeofst = le32_to_cpu(eoc->zipeofst);
220 eoc->zipecoml = le16_to_cpu(eoc->zipecoml);
221 }
222 }
223
224 static void binfile_check_version(struct map_priv *m);
225
226 static struct zip_eoc *
227 binfile_read_eoc(struct file *fi)
228 {
229 struct zip_eoc *eoc;
230 eoc = (struct zip_eoc *) file_data_read(fi, fi->size - sizeof(struct zip_eoc), sizeof(struct zip_eoc));
231 if (eoc)
232 {
233 eoc_to_cpu(eoc);
234 // dbg(0, "sig 0x%x\n", eoc->zipesig);
235 if (eoc->zipesig != zip_eoc_sig)
236 {
237 file_data_free(fi, (unsigned char *) eoc);
238 eoc = NULL;
239 }
240 }
241 return eoc;
242 }
243
244 static struct zip64_eoc *
245 binfile_read_eoc64(struct file *fi)
246 {
247 struct zip64_eocl *eocl;
248 struct zip64_eoc *eoc;
249 eocl = (struct zip64_eocl *) file_data_read(fi, fi->size - sizeof(struct zip_eoc) - sizeof(struct zip64_eocl), sizeof(struct zip64_eocl));
250 if (!eocl)
251 {
252 return NULL;
253 }
254 //dbg(0, "sig 0x%x\n", eocl->zip64lsig);
255 if (eocl->zip64lsig != zip64_eocl_sig)
256 {
257 file_data_free(fi, (unsigned char *) eocl);
258 //dbg(0, "eocl wrong\n");
259 return NULL;
260 }
261 eoc = (struct zip64_eoc *) file_data_read(fi, eocl->zip64lofst, sizeof(struct zip64_eoc));
262 if (eoc)
263 {
264 if (eoc->zip64esig != zip64_eoc_sig)
265 {
266 file_data_free(fi, (unsigned char *) eoc);
267 //dbg(0, "eoc wrong\n");
268 eoc = NULL;
269 }
270 //dbg(0, "eoc64 ok 0x%Lx 0x%Lx\n", eoc->zip64eofst, eoc->zip64ecsz);
271 }
272 file_data_free(fi, (unsigned char *) eocl);
273 return eoc;
274 }
275
276 static int binfile_cd_extra(struct zip_cd *cd)
277 {
278 return cd->zipcfnl + cd->zipcxtl;
279 }
280
281 static struct zip_cd *
282 binfile_read_cd(struct map_priv *m, int offset, int len)
283 {
284 //dbg(0,"_enter\n");
285 struct zip_cd *cd;
286 long long cdoffset = m->eoc64 ? m->eoc64->zip64eofst : m->eoc->zipeofst;
287 //dbg(0,"_cdoffset="LONGLONG_FMT"\n", cdoffset);
288
289 if (len == -1)
290 {
291 //dbg(0,"_len = -1\n");
292 cd = (struct zip_cd *) file_data_read(m->fi, cdoffset + offset, sizeof(*cd));
293 cd_to_cpu(cd);
294 len = binfile_cd_extra(cd);
295 //dbg(0,"_len = %d\n", len);
296 file_data_free(m->fi, (unsigned char *) cd);
297 }
298
299 cd = (struct zip_cd *) file_data_read(m->fi, cdoffset + offset, sizeof(*cd) + len);
300
301 if (cd)
302 {
303 //dbg(0,"cd at "LONGLONG_FMT" %d bytes\n",cdoffset+offset, sizeof(*cd)+len);
304 cd_to_cpu(cd);
305 //dbg(0, "sig 0x%x\n", cd->zipcensig);
306 if (cd->zipcensig != zip_cd_sig)
307 {
308 file_data_free(m->fi, (unsigned char *) cd);
309 //dbg(0,"_cd=NULL\n");
310 cd = NULL;
311 }
312 }
313
314 //dbg(0,"leave\n");
315 return cd;
316 }
317
318 static struct zip_cd_ext *
319 binfile_cd_ext(struct zip_cd *cd)
320 {
321 struct zip_cd_ext *ext;
322 if (cd->zipofst != 0xffffffff)
323 return NULL;
324 if (cd->zipcxtl != sizeof(*ext))
325 return NULL;
326 ext = (struct zip_cd_ext *) ((unsigned char *) cd + sizeof(*cd) + cd->zipcfnl);
327 if (ext->tag != 0x0001 || ext->size != 8)
328 return NULL;
329 return ext;
330 }
331
332 static long long binfile_cd_offset(struct zip_cd *cd)
333 {
334 struct zip_cd_ext *ext = binfile_cd_ext(cd);
335 if (ext)
336 return ext->zipofst;
337 else
338 return cd->zipofst;
339 }
340
341 static struct zip_lfh *
342 binfile_read_lfh(struct file *fi, long long offset)
343 {
344 struct zip_lfh *lfh;
345
346 lfh = (struct zip_lfh *) (file_data_read(fi, offset, sizeof(struct zip_lfh)));
347 if (lfh)
348 {
349 lfh_to_cpu(lfh);
350 if (lfh->ziplocsig != zip_lfh_sig)
351 {
352 file_data_free(fi, (unsigned char *) lfh);
353 lfh = NULL;
354 }
355 }
356 return lfh;
357 }
358
359 static unsigned char *
360 binfile_read_content(struct map_priv *m, struct file *fi, long long offset, struct zip_lfh *lfh)
361 {
362 struct zip_enc *enc;
363 unsigned char *ret = NULL;
364
365 offset += sizeof(struct zip_lfh) + lfh->zipfnln;
366 switch (lfh->zipmthd)
367 {
368 case 0:
369 offset += lfh->zipxtraln;
370 ret = file_data_read(fi, offset, lfh->zipuncmp);
371 break;
372 case 8:
373 offset += lfh->zipxtraln;
374 ret = file_data_read_compressed(fi, offset, lfh->zipsize, lfh->zipuncmp);
375 break;
376 case 99:
377 if (!m->passwd)
378 {
379 break;
380 }
381 enc = (struct zip_enc *) file_data_read(fi, offset, sizeof(*enc));
382 offset += lfh->zipxtraln;
383 switch (enc->compress_method)
384 {
385 case 0:
386 ret = file_data_read_encrypted(fi, offset, lfh->zipsize, lfh->zipuncmp, 0, m->passwd);
387 break;
388 case 8:
389 ret = file_data_read_encrypted(fi, offset, lfh->zipsize, lfh->zipuncmp, 1, m->passwd);
390 break;
391 default:
392 // dbg(0, "Unknown encrypted compression method %d\n", enc->compress_method);
393 break;
394 }
395 file_data_free(fi, (unsigned char *) enc);
396 break;
397 default:
398 // dbg(0, "Unknown compression method %d\n", lfh->zipmthd);
399 break;
400 }
401 return ret;
402 }
403
404 static int binfile_search_cd(struct map_priv *m, int offset, char *name, int partial, int skip)
405 {
406 //dbg(0,"_enter\n");
407
408 int size = 4096;
409 int end = m->eoc64 ? m->eoc64->zip64ecsz : m->eoc->zipecsz;
410 int len = strlen(name);
411 long long cdoffset = m->eoc64 ? m->eoc64->zip64eofst : m->eoc->zipeofst;
412 struct zip_cd *cd;
413 #if 0
414 // dbg(0,"end=%d\n",end);
415 #endif
416 while (offset < end)
417 {
418 cd = (struct zip_cd *) (m->search_data + offset - m->search_offset);
419 if (!m->search_data || m->search_offset > offset || offset - m->search_offset + sizeof(*cd) > m->search_size || offset - m->search_offset + sizeof(*cd) + cd->zipcfnl + cd->zipcxtl > m->search_size)
420 {
421 #if 0
422 // dbg(0,"reload %p %d %d\n", m->search_data, m->search_offset, offset);
423 #endif
424 if (m->search_data)
425 {
426 file_data_free(m->fi, m->search_data);
427 }
428 m->search_offset = offset;
429 m->search_size = end - offset;
430 if (m->search_size > size)
431 {
432 m->search_size = size;
433 }
434 m->search_data = file_data_read(m->fi, cdoffset + m->search_offset, m->search_size);
435 cd = (struct zip_cd *) m->search_data;
436 }
437 #if 0
438 // dbg(0,"offset=%d search_offset=%d search_size=%d search_data=%p cd=%p\n", offset, m->search_offset, m->search_size, m->search_data, cd);
439 // dbg(0,"offset=%d fn='%s'\n",offset,cd->zipcfn);
440 #endif
441 if (!skip && (partial || cd->zipcfnl == len) && !strncmp(cd->zipcfn, name, len))
442 {
443 return offset;
444 }
445 skip = 0;
446 offset += sizeof(*cd) + cd->zipcfnl + cd->zipcxtl + cd->zipccml;
447 ;
448 }
449 return -1;
450 }
451
452 static void map_destroy_binfile(struct map_priv *m)
453 {
454 // dbg(1, "map_destroy_binfile\n");
455 if (m->fi)
456 map_binfile_close(m);
457 map_binfile_destroy(m);
458 }
459
460 static void binfile_coord_rewind(void *priv_data)
461 {
462 struct map_rect_priv *mr = priv_data;
463 struct tile *t = mr->t;
464 t->pos_coord = t->pos_coord_start;
465 }
466
467 static int binfile_coord_get(void *priv_data, struct coord *c, int count)
468 {
469 struct map_rect_priv *mr = priv_data;
470 struct tile *t = mr->t;
471 int max, ret = 0;
472 max = (t->pos_attr_start - t->pos_coord) / 2;
473 if (count > max)
474 {
475 count = max;
476 }
477 #if __BYTE_ORDER == __LITTLE_ENDIAN
478 memcpy(c, t->pos_coord, count * sizeof(struct coord));
479 #else
480 {
481 int i=0,end=count*sizeof(struct coord)/sizeof(int);
482 int *src=(int *)t->pos_coord;
483 int *dst=(int *)c;
484 while (i++ < end)
485 {
486 *dst++=le32_to_cpu(*src);
487 src++;
488 }
489 }
490 #endif
491 t->pos_coord += count * 2;
492 ret = count;
493 return ret;
494 }
495
496 static void binfile_attr_rewind(void *priv_data)
497 {
498 struct map_rect_priv *mr = priv_data;
499 struct tile *t = mr->t;
500 t->pos_attr = t->pos_attr_start;
501 mr->label = 0;
502 memset(mr->label_attr, 0, sizeof(mr->label_attr));
503
504 }
505
506 static char *
507 binfile_extract(struct map_priv *m, char *dir, char *filename, int partial)
508 {
509 char *full, *fulld, *sep;
510 unsigned char *start;
511 int len, offset = m->index_offset;
512 struct zip_cd *cd;
513 struct zip_lfh *lfh;
514 FILE *f;
515
516 for (;;)
517 {
518 offset = binfile_search_cd(m, offset, filename, partial, 1);
519 if (offset == -1)
520 break;
521 cd = binfile_read_cd(m, offset, -1);
522 len = strlen(dir) + 1 + cd->zipcfnl + 1;
523 full = g_malloc(len);
524 strcpy(full, dir);
525 strcpy(full + strlen(full), "/");
526 strncpy(full + strlen(full), cd->zipcfn, cd->zipcfnl);
527 full[len - 1] = '\0';
528 fulld = g_strdup(full);
529 sep = strrchr(fulld, '/');
530 if (sep)
531 {
532 *sep = '\0';
533 file_mkdir(fulld, 1);
534 }
535 if (full[len - 2] != '/')
536 {
537 lfh = binfile_read_lfh(m->fi, binfile_cd_offset(cd));
538 start = binfile_read_content(m, m->fi, binfile_cd_offset(cd), lfh);
539 // dbg(0, "fopen '%s'\n", full);
540 f = fopen(full, "w");
541 fwrite(start, lfh->zipuncmp, 1, f);
542 fclose(f);
543 file_data_free(m->fi, start);
544 file_data_free(m->fi, (unsigned char *) lfh);
545 }
546 file_data_free(m->fi, (unsigned char *) cd);
547 g_free(fulld);
548 g_free(full);
549 if (!partial)
550 {
551 break;
552 }
553 }
554
555 return g_strdup_printf("%s/%s", dir, filename);
556 }
557
558 static int binfile_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
559 {
560 // try to return "0" on any problem, to avoid crash!!
561
562 struct map_rect_priv *mr = priv_data;
563 struct tile *t = mr->t;
564 enum attr_type type;
565 int i, size;
566
567 if (attr_type != mr->attr_last)
568 {
569 t->pos_attr = t->pos_attr_start;
570 mr->attr_last = attr_type;
571 }
572
573 while (t->pos_attr < t->pos_next)
574 {
575 //dbg(0,"batg:002 %d %d\n",t->pos_attr,(t->pos_attr+1));
576 size = le32_to_cpu(*(t->pos_attr++));
577 // dbg(0,"batg:002.1 %d %d\n",t->pos_attr, t->pos_attr[0]);
578 type = le32_to_cpu(t->pos_attr[0]);
579 // dbg(0, "type=%d\n", type);
580
581 #ifdef NAVIT_ATTR_SAFETY_CHECK
582 // safety check (always keep value in sync with "attr_def.h" !!) ---------------
583 if (type > 0x000effff)
584 {
585 return 0;
586 }
587 // safety check (always keep value in sync with "attr_def.h" !!) ---------------
588 #endif
589
590 //dbg(0,"batg:002.2\n");
591 if (type == attr_label)
592 mr->label = 1;
593 if (type == attr_house_number)
594 mr->label_attr[0] = t->pos_attr;
595 if (type == attr_street_name)
596 mr->label_attr[1] = t->pos_attr;
597 if (type == attr_street_name_systematic)
598 mr->label_attr[2] = t->pos_attr;
599 if (type == attr_district_name && mr->item.type < type_line)
600 mr->label_attr[3] = t->pos_attr;
601 if (type == attr_town_name && mr->item.type < type_line)
602 mr->label_attr[4] = t->pos_attr;
603
604 if (type == attr_type || attr_type == attr_any)
605 {
606 if (attr_type == attr_any)
607 {
608 // dbg(1, "pos %p attr %s size %d\n", t->pos_attr - 1, attr_to_name(type), size);
609 }
610 attr->type = type;
611 if (ATTR_IS_GROUP(type))
612 {
613 int i = 0;
614 int *subpos = t->pos_attr + 1;
615 int size_rem = size - 1;
616 i = 0;
617 while (size_rem > 0 && i < 7)
618 {
619 int subsize = le32_to_cpu(*subpos++);
620 int subtype = le32_to_cpu(subpos[0]);
621 mr->attrs[i].type = subtype;
622 attr_data_set_le(&mr->attrs[i], subpos + 1);
623 subpos += subsize;
624 size_rem -= subsize + 1;
625 i++;
626 }
627
628 mr->attrs[i].type = type_none;
629 mr->attrs[i].u.data = NULL;
630 attr->u.attrs = mr->attrs;
631 }
632 else
633 {
634 attr_data_set_le(attr, t->pos_attr + 1);
635 if (type == attr_url_local)
636 {
637 g_free(mr->url);
638 mr->url = binfile_extract(mr->m, mr->m->cachedir, attr->u.str, 1);
639 attr->u.str = mr->url;
640 }
641
642 if (type == attr_flags && mr->m->map_version < 1)
643 {
644 attr->u.num |= NAVIT_AF_CAR;
645 }
646 }
647 t->pos_attr += size;
648 return 1;
649 }
650 else
651 {
652 t->pos_attr += size;
653 }
654 }
655
656 if (!mr->label && (attr_type == attr_any || attr_type == attr_label))
657 {
658 for (i = 0; i < sizeof(mr->label_attr) / sizeof(int *); i++)
659 {
660 if (mr->label_attr[i])
661 {
662 mr->label = 1;
663 attr->type = attr_label;
664 attr_data_set_le(attr, mr->label_attr[i] + 1);
665 return 1;
666 }
667 }
668 }
669
670 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
671 dbg(0,"+#+:leave\n");
672 #endif
673
674 return 0;
675 }
676
677 struct binfile_hash_entry
678 {
679 struct item_id id;
680 int flags;
681 int data[0];
682 };
683
684 static guint binfile_hash_entry_hash(gconstpointer key)
685 {
686 const struct binfile_hash_entry *entry = key;
687 return (entry->id.id_hi ^ entry->id.id_lo);
688 }
689
690 static gboolean binfile_hash_entry_equal(gconstpointer a, gconstpointer b)
691 {
692 const struct binfile_hash_entry *entry1 = a, *entry2 = b;
693 return (entry1->id.id_hi == entry2->id.id_hi && entry1->id.id_lo == entry2->id.id_lo);
694 }
695
696 static int *
697 binfile_item_dup(struct map_priv *m, struct item *item, struct tile *t, int extend)
698 {
699 int size = le32_to_cpu(t->pos[0]);
700 struct binfile_hash_entry *entry = g_malloc(sizeof(struct binfile_hash_entry) + (size + 1 + extend) * sizeof(int));
701 void *ret = entry->data;
702 entry->id.id_hi = item->id_hi;
703 entry->id.id_lo = item->id_lo;
704 entry->flags = 1;
705 // dbg(0, "id 0x%x,0x%x\n", entry->id.id_hi, entry->id.id_lo);
706
707 memcpy(ret, t->pos, (size + 1) * sizeof(int));
708 if (!m->changes)
709 m->changes = g_hash_table_new_full(binfile_hash_entry_hash, binfile_hash_entry_equal, g_free_func, NULL);
710 g_hash_table_replace(m->changes, entry, entry);
711 // dbg(0, "ret %p\n", ret);
712 return ret;
713 }
714
715 static int binfile_coord_set(void *priv_data, struct coord *c, int count, enum change_mode mode)
716 {
717 struct map_rect_priv *mr = priv_data;
718 struct tile *t = mr->t, *tn, new;
719 int i, delta, move_len;
720 int write_offset, move_offset, aoffset, coffset, clen;
721 int *data;
722
723 //{
724 //int *i = t->pos, j = 0;
725 // dbg(0, "Before: pos_coord=%d\n", t->pos_coord - i);
726 //while (i < t->pos_next)
727 //{
728 // // dbg(0, "%d:0x%x\n", j++, *i++);
729 //}
730
731 //}
732
733 aoffset = t->pos_attr - t->pos_attr_start;
734 coffset = t->pos_coord - t->pos_coord_start - 2;
735 clen = t->pos_attr_start - t->pos_coord + 2;
736 // dbg(0, "coffset=%d clen=%d\n", coffset, clen);
737 switch (mode)
738 {
739 case change_mode_delete:
740 if (count * 2 > clen)
741 count = clen / 2;
742 delta = -count * 2;
743 move_offset = coffset + count * 2;
744 move_len = t->pos_next - t->pos_coord_start - move_offset;
745 write_offset = 0;
746 break;
747 case change_mode_modify:
748 write_offset = coffset;
749 if (count * 2 > clen)
750 {
751 delta = count * 2 - clen;
752 move_offset = t->pos_attr_start - t->pos_coord_start;
753 move_len = t->pos_next - t->pos_coord_start - move_offset;
754 }
755 else
756 {
757 move_len = 0;
758 move_offset = 0;
759 delta = 0;
760 }
761 break;
762 case change_mode_prepend:
763 delta = count * 2;
764 move_offset = coffset - 2;
765 move_len = t->pos_next - t->pos_coord_start - move_offset;
766 write_offset = coffset - 2;
767 break;
768 case change_mode_append:
769 delta = count * 2;
770 move_offset = coffset;
771 move_len = t->pos_next - t->pos_coord_start - move_offset;
772 write_offset = coffset;
773 break;
774 default:
775 return 0;
776 }
777 // dbg(0, "delta %d\n", delta);
778 data = binfile_item_dup(mr->m, &mr->item, t, delta > 0 ? delta : 0);
779 data[0] = cpu_to_le32(le32_to_cpu(data[0]) + delta);
780 data[2] = cpu_to_le32(le32_to_cpu(data[2]) + delta);
781 new.pos = new.start = data;
782 new.zipfile_num = t->zipfile_num;
783 new.mode = 2;
784 push_tile(mr, &new, 0, 0);
785 setup_pos(mr);
786 tn = mr->t;
787 tn->pos_coord = tn->pos_coord_start + coffset;
788 tn->pos_attr = tn->pos_attr_start + aoffset;
789 // dbg(0, "moving %d ints from offset %d to %d\n", move_len, tn->pos_coord_start + move_offset - data, tn->pos_coord_start + move_offset + delta - data);
790 memmove(tn->pos_coord_start + move_offset + delta, tn->pos_coord_start + move_offset, move_len * 4);
791 //{
792 //int *i = tn->pos, j = 0;
793 // dbg(0, "After move: pos_coord=%d\n", tn->pos_coord - i);
794 //while (i < tn->pos_next)
795 //{
796 // // dbg(0, "%d:0x%x\n", j++, *i++);
797 //}
798 //}
799 if (mode != change_mode_append)
800 {
801 tn->pos_coord += move_offset;
802 }
803 if (mode != change_mode_delete)
804 {
805 // dbg(0, "writing %d ints at offset %d\n", count * 2, write_offset + tn->pos_coord_start - data);
806 for (i = 0; i < count; i++)
807 {
808 tn->pos_coord_start[write_offset++] = c[i].x;
809 tn->pos_coord_start[write_offset++] = c[i].y;
810 }
811
812 }
813 //{
814 //int *i = tn->pos, j = 0;
815 //// dbg(0, "After: pos_coord=%d\n", tn->pos_coord - i);
816 //while (i < tn->pos_next)
817 //{
818 // // dbg(0, "%d:0x%x\n", j++, *i++);
819 //}
820 //}
821 return 1;
822 }
823
824 static int binfile_attr_set(void *priv_data, struct attr *attr, enum change_mode mode)
825 {
826 struct map_rect_priv *mr = priv_data;
827 struct tile *t = mr->t, *tn, new;
828 int extend, offset, delta, move_len;
829 int write_offset, move_offset, naoffset, coffset, oattr_len;
830 int nattr_size, nattr_len, pad;
831 int *data;
832
833 //{
834 //int *i = t->pos, j = 0;
835 //// dbg(0, "Before: pos_attr=%d\n", t->pos_attr - i);
836 //while (i < t->pos_next)
837 //{
838 // // dbg(0, "%d:0x%x\n", j++, *i++);
839 //}
840 //}
841
842 write_offset = 0;
843 naoffset = t->pos_attr - t->pos_attr_start;
844 coffset = t->pos_coord - t->pos_coord_start;
845 offset = 0;
846 oattr_len = 0;
847 if (!naoffset)
848 {
849 if (mode == change_mode_delete || mode == change_mode_modify)
850 {
851 // dbg(0, "no attribute selected\n");
852 return 0;
853 }
854 if (mode == change_mode_append)
855 {
856 naoffset = t->pos_next - t->pos_attr_start;
857 }
858 }
859 while (offset < naoffset)
860 {
861 oattr_len = le32_to_cpu(t->pos_attr_start[offset]) + 1;
862 // dbg(0, "len %d\n", oattr_len);
863 write_offset = offset;
864 offset += oattr_len;
865 }
866 move_len = t->pos_next - t->pos_attr_start - offset;
867 move_offset = offset;
868 switch (mode)
869 {
870 case change_mode_delete:
871 nattr_size = 0;
872 nattr_len = 0;
873 pad = 0;
874 extend = 0;
875 break;
876 case change_mode_modify:
877 case change_mode_prepend:
878 case change_mode_append:
879 nattr_size = attr_data_size(attr);
880 pad = (4 - (nattr_size % 4)) % 4;
881 nattr_len = (nattr_size + pad) / 4 + 2;
882 if (mode == change_mode_prepend)
883 {
884 move_offset = write_offset;
885 move_len += oattr_len;
886 }
887 if (mode == change_mode_append)
888 {
889 write_offset = move_offset;
890 }
891 break;
892 default:
893 return 0;
894 }
895 if (mode == change_mode_delete || mode == change_mode_modify)
896 {
897 delta = nattr_len - oattr_len;
898 }
899 else
900 {
901 delta = nattr_len;
902 }
903 // dbg(0, "delta %d oattr_len %d nattr_len %d\n", delta, oattr_len, nattr_len);
904 data = binfile_item_dup(mr->m, &mr->item, t, delta > 0 ? delta : 0);
905 data[0] = cpu_to_le32(le32_to_cpu(data[0]) + delta);
906 new.pos = new.start = data;
907 new.zipfile_num = t->zipfile_num;
908 new.mode = 2;
909 push_tile(mr, &new, 0, 0);
910 setup_pos(mr);
911 tn = mr->t;
912 tn->pos_coord = tn->pos_coord_start + coffset;
913 tn->pos_attr = tn->pos_attr_start + offset;
914 // dbg(0, "attr start %d offset %d\n", tn->pos_attr_start - data, offset);
915 // dbg(0, "moving %d ints from offset %d to %d\n", move_len, tn->pos_attr_start + move_offset - data, tn->pos_attr_start + move_offset + delta - data);
916 memmove(tn->pos_attr_start + move_offset + delta, tn->pos_attr_start + move_offset, move_len * 4);
917 if (mode != change_mode_append)
918 tn->pos_attr += delta;
919 {
920 int *i = tn->pos, j = 0;
921 // dbg(0, "After move: pos_attr=%d\n", tn->pos_attr - i);
922 while (i < tn->pos_next)
923 {
924 // dbg(0, "%d:0x%x\n", j++, *i++);
925 }
926 }
927
928 if (nattr_len)
929 {
930 int *nattr = tn->pos_attr_start + write_offset;
931 // dbg(0, "writing %d ints at %d\n", nattr_len, nattr - data);
932 nattr[0] = cpu_to_le32(nattr_len - 1);
933 nattr[1] = cpu_to_le32(attr->type);
934 memcpy(nattr + 2, attr_data_get(attr), nattr_size);
935 memset((unsigned char *) (nattr + 2) + nattr_size, 0, pad);
936 }
937
938 //{
939 //int *i = tn->pos, j = 0;
940 //// dbg(0, "After: pos_attr=%d\n", tn->pos_attr - i);
941 //while (i < tn->pos_next)
942 //{
943 // // dbg(0, "%d:0x%x\n", j++, *i++);
944 //}
945 //}
946 return 1;
947 }
948
949 static struct item_methods methods_binfile =
950 { binfile_coord_rewind, binfile_coord_get, binfile_attr_rewind, binfile_attr_get, NULL, binfile_attr_set, binfile_coord_set, };
951
952 static void push_tile(struct map_rect_priv *mr, struct tile *t, int offset, int length)
953 {
954 dbg_assert(mr->tile_depth < 8);
955 mr->t = &mr->tiles[mr->tile_depth++];
956 *(mr->t) = *t;
957 mr->t->pos = mr->t->pos_next = mr->t->start + offset;
958 if (length == -1)
959 length = le32_to_cpu(mr->t->pos[0]) + 1;
960 if (length > 0)
961 mr->t->end = mr->t->pos + length;
962 }
963
964 static int pop_tile(struct map_rect_priv *mr)
965 {
966 if (mr->tile_depth <= 1)
967 return 0;
968 if (mr->t->mode < 2)
969 file_data_free(mr->m->fi, (unsigned char *) (mr->t->start));
970 #ifdef DEBUG_SIZE
971 #if DEBUG_SIZE > 0
972 // dbg(0,"leave %d\n",mr->t->zipfile_num);
973 #endif
974 #endif
975 mr->t = &mr->tiles[--mr->tile_depth - 1];
976 return 1;
977 }
978
979 static int zipfile_to_tile(struct map_priv *m, struct zip_cd *cd, struct tile *t)
980 {
981 char buffer[1024];
982 struct zip_lfh *lfh;
983 char *zipfn;
984 struct file *fi;
985 // dbg(1, "enter %p %p %p\n", m, cd, t);
986 // dbg(1, "cd->zipofst=0x%Lx\n", binfile_cd_offset(cd));
987 t->start = NULL;
988 t->mode = 1;
989 if (m->fis)
990 fi = m->fis[cd->zipdsk];
991 else
992 fi = m->fi;
993 lfh = binfile_read_lfh(fi, binfile_cd_offset(cd));
994 zipfn = (char *) (file_data_read(fi, binfile_cd_offset(cd) + sizeof(struct zip_lfh), lfh->zipfnln));
995 strncpy(buffer, zipfn, lfh->zipfnln);
996 buffer[lfh->zipfnln] = '\0';
997 t->start = (int *) binfile_read_content(m, fi, binfile_cd_offset(cd), lfh);
998 t->end = t->start + lfh->zipuncmp / 4;
999 t->fi = fi;
1000 // dbg(1, "0x%x '%s' %d %d,%d\n", lfh->ziplocsig, buffer, sizeof(*cd) + cd->zipcfnl, lfh->zipsize, lfh->zipuncmp);
1001 file_data_free(fi, (unsigned char *) zipfn);
1002 file_data_free(fi, (unsigned char *) lfh);
1003 return t->start != NULL;
1004 }
1005
1006 static int map_binfile_handle_redirect(struct map_priv *m)
1007 {
1008 char *location = file_http_header(m->http, "location");
1009 if (!location)
1010 {
1011 m->redirect = 0;
1012 return 0;
1013 }
1014 if (m->redirect)
1015 return 0;
1016 m->redirect = 1;
1017 // dbg(0, "redirected from %s to %s\n", m->url, location);
1018 g_free(m->url);
1019 m->url = g_strdup(location);
1020 file_destroy(m->http);
1021 m->http = NULL;
1022
1023 return 1;
1024 }
1025
1026 static int map_binfile_http_request(struct map_priv *m, struct attr **attrs)
1027 {
1028 if (!m->http)
1029 {
1030 m->http = file_create(NULL, attrs);
1031 }
1032 else
1033 {
1034 file_request(m->http, attrs);
1035 }
1036 return 1;
1037 }
1038
1039 static long long map_binfile_download_size(struct map_priv *m)
1040 {
1041 struct attr url =
1042 { attr_url };
1043 struct attr http_method =
1044 { attr_http_method };
1045 struct attr persistent =
1046 { attr_persistent };
1047 struct attr *attrs[4];
1048 int size_ret;
1049 long long ret;
1050 void *data;
1051
1052 do
1053 {
1054 attrs[0] = &url;
1055 url.u.str = m->url;
1056 attrs[1] = &http_method;
1057 http_method.u.str = "HEAD";
1058 persistent.u.num = 1;
1059 attrs[2] = &persistent;
1060 attrs[3] = NULL;
1061
1062 map_binfile_http_request(m, attrs);
1063 data = file_data_read_special(m->http, 0, &size_ret);
1064 g_free(data);
1065 if (size_ret < 0)
1066 return 0;
1067 }
1068 while (map_binfile_handle_redirect(m));
1069
1070 ret = file_size(m->http);
1071 // dbg(1,"file size "LONGLONG_FMT"\n",ret);
1072 return ret;
1073 }
1074
1075 static int map_binfile_http_close(struct map_priv *m)
1076 {
1077 if (m->http)
1078 {
1079 file_destroy(m->http);
1080 m->http = NULL;
1081 }
1082 return 1;
1083 }
1084
1085 static struct file *
1086 map_binfile_http_range(struct map_priv *m, long long offset, int size)
1087 {
1088 struct attr *attrs[4];
1089 struct attr url =
1090 { attr_url };
1091 struct attr http_header =
1092 { attr_http_header };
1093 struct attr persistent =
1094 { attr_persistent };
1095
1096 persistent.u.num = 1;
1097 attrs[0] = &url;
1098 attrs[1] = &http_header;
1099 attrs[2] = &persistent;
1100 attrs[3] = NULL;
1101
1102 url.u.str = m->url;
1103 http_header.u.str=g_strdup_printf("Range: bytes="LONGLONG_FMT"-"LONGLONG_FMT,offset, offset+size-1);
1104 map_binfile_http_request(m, attrs);
1105 g_free(http_header.u.str);
1106 return m->http;
1107 }
1108
1109 static unsigned char *
1110 map_binfile_download_range(struct map_priv *m, long long offset, int size)
1111 {
1112 unsigned char *ret;
1113 int size_ret;
1114 struct file *http = map_binfile_http_range(m, offset, size);
1115
1116 ret = file_data_read_special(http, size, &size_ret);
1117 if (size_ret != size)
1118 {
1119 // dbg(0, "size %d vs %d\n", size, size_ret);
1120 g_free(ret);
1121 return NULL;
1122 }
1123 return ret;
1124 }
1125
1126 static struct zip_cd *
1127 download_cd(struct map_download *download)
1128 {
1129 struct map_priv *m = download->m;
1130 struct zip64_eoc *zip64_eoc = (struct zip64_eoc *) file_data_read(m->fi, 0, sizeof(*zip64_eoc));
1131 struct zip_cd *cd = (struct zip_cd *) map_binfile_download_range(m, zip64_eoc->zip64eofst + download->zipfile * m->cde_size, m->cde_size);
1132 file_data_free(m->fi, (unsigned char *) zip64_eoc);
1133 // dbg(0, "needed cd, result %p\n", cd);
1134 return cd;
1135 }
1136
1137 static int download_request(struct map_download *download)
1138 {
1139 struct attr url =
1140 { attr_url };
1141 struct attr http_header =
1142 { attr_http_header };
1143 struct attr persistent =
1144 { attr_persistent };
1145 struct attr *attrs[4];
1146
1147 if (!download->m->download_enabled)
1148 {
1149 // dbg(0, "Tried downloading while it's not allowed\n");
1150 return 0;
1151 }
1152 attrs[0] = &url;
1153 persistent.u.num = 1;
1154 attrs[1] = &persistent;
1155 attrs[2] = NULL;
1156 if (strchr(download->m->url, '?'))
1157 {
1158 url.u.str = g_strdup_printf("%smemberid=%d", download->m->url, download->zipfile);
1159 download->dl_size = -1;
1160 }
1161 else
1162 {
1163 long long offset = binfile_cd_offset(download->cd_copy);
1164 int size = download->cd_copy->zipcsiz + sizeof(struct zip_lfh) + download->cd_copy->zipcfnl;
1165 url.u.str = g_strdup(download->m->url);
1166 http_header.u.str=g_strdup_printf("Range: bytes="LONGLONG_FMT"-"LONGLONG_FMT,offset,offset+size-1);
1167 attrs[2] = &http_header;
1168 attrs[3] = NULL;
1169 download->dl_size = size;
1170 }
1171 // dbg(0,"encountered missing tile %d %s(%s), Downloading %d bytes at "LONGLONG_FMT"\n",download->zipfile, url.u.str,(char *)(download->cd_copy+1), download->dl_size, download->offset);
1172 map_binfile_http_request(download->m, attrs);
1173 g_free(url.u.str);
1174 download->http = download->m->http;
1175 return 1;
1176 }
1177
1178 static int download_start(struct map_download *download)
1179 {
1180 long long offset;
1181 struct zip_eoc *eoc;
1182
1183 if (!download->cd->zipcensig)
1184 {
1185 download->cd_copy = download_cd(download);
1186 }
1187 else
1188 {
1189 download->cd_copy = g_malloc(download->m->cde_size);
1190 memcpy(download->cd_copy, download->cd, download->m->cde_size);
1191 }
1192 file_data_remove(download->file, (unsigned char *) download->cd);
1193 download->cd = NULL;
1194 offset = file_size(download->file);
1195 offset -= sizeof(struct zip_eoc);
1196 eoc = (struct zip_eoc *) file_data_read(download->file, offset, sizeof(struct zip_eoc));
1197 download->zip_eoc = g_malloc(sizeof(struct zip_eoc));
1198 memcpy(download->zip_eoc, eoc, sizeof(struct zip_eoc));
1199 file_data_remove(download->file, (unsigned char *) eoc);
1200 download->start_offset = download->offset = offset;
1201 return download_request(download);
1202 }
1203
1204 static int download_download(struct map_download *download)
1205 {
1206 int size = 64 * 1024, size_ret;
1207 unsigned char *data;
1208 if (download->dl_size != -1 && size > download->dl_size)
1209 size = download->dl_size;
1210 if (!size)
1211 return 1;
1212 data = file_data_read_special(download->http, size, &size_ret);
1213 if (!download->read && download->m->http && map_binfile_handle_redirect(download->m))
1214 {
1215 g_free(data);
1216 download_request(download);
1217 return 0;
1218 }
1219
1220 // dbg(1,"got %d bytes writing at offset "LONGLONG_FMT"\n",size_ret,download->offset);
1221 if (size_ret <= 0)
1222 {
1223 g_free(data);
1224 return 1;
1225 }
1226 file_data_write(download->file, download->offset, size_ret, data);
1227 download->offset += size_ret;
1228 download->read += size_ret;
1229 download->dl_size -= size_ret;
1230 if (download->dl_size != -1)
1231 download->progress = download->read * 100 / (download->read + download->dl_size);
1232 return 0;
1233 }
1234
1235 static int download_finish(struct map_download *download)
1236 {
1237 struct zip_lfh *lfh;
1238 char *lfh_filename;
1239 struct zip_cd_ext *ext;
1240 long long lfh_offset;
1241 file_data_write(download->file, download->offset, sizeof(struct zip_eoc), (void *) download->zip_eoc);
1242 lfh = (struct zip_lfh *) (file_data_read(download->file, download->start_offset, sizeof(struct zip_lfh)));
1243 ext = binfile_cd_ext(download->cd_copy);
1244 if (ext)
1245 ext->zipofst = download->start_offset;
1246 else
1247 download->cd_copy->zipofst = download->start_offset;
1248 download->cd_copy->zipcsiz = lfh->zipsize;
1249 download->cd_copy->zipcunc = lfh->zipuncmp;
1250 download->cd_copy->zipccrc = lfh->zipcrc;
1251 lfh_offset = binfile_cd_offset(download->cd_copy) + sizeof(struct zip_lfh);
1252 lfh_filename = (char *) file_data_read(download->file, lfh_offset, lfh->zipfnln);
1253 memcpy(download->cd_copy + 1, lfh_filename, lfh->zipfnln);
1254 file_data_remove(download->file, (void *) lfh_filename);
1255 file_data_remove(download->file, (void *) lfh);
1256 file_data_write(download->file, download->m->eoc->zipeofst + download->zipfile * download->m->cde_size, binfile_cd_extra(download->cd_copy) + sizeof(struct zip_cd), (void *) download->cd_copy);
1257 file_data_flush(download->file, download->m->eoc->zipeofst + download->zipfile * download->m->cde_size, sizeof(struct zip_cd));
1258
1259 g_free(download->cd_copy);
1260 download->cd = (struct zip_cd *) (file_data_read(download->file, download->m->eoc->zipeofst + download->zipfile * download->m->cde_size, download->m->cde_size));
1261 cd_to_cpu(download->cd);
1262 // dbg(1, "Offset %d\n", download->cd->zipofst);
1263 return 1;
1264 }
1265
1266 static int download_planet_size(struct map_download *download)
1267 {
1268 download->size = map_binfile_download_size(download->m);
1269 // dbg(0,"Planet size "LONGLONG_FMT"\n",download->size);
1270 if (!download->size)
1271 return 0;
1272 return 1;
1273 }
1274
1275 static int download_eoc(struct map_download *download)
1276 {
1277 download->zip64_eoc = (struct zip64_eoc *) map_binfile_download_range(download->m, download->size - 98, 98);
1278 if (!download->zip64_eoc)
1279 return 0;
1280 download->zip64_eocl = (struct zip64_eocl *) (download->zip64_eoc + 1);
1281 download->zip_eoc = (struct zip_eoc *) (download->zip64_eocl + 1);
1282 if (download->zip64_eoc->zip64esig != zip64_eoc_sig || download->zip64_eocl->zip64lsig != zip64_eocl_sig || download->zip_eoc->zipesig != zip_eoc_sig)
1283 {
1284 // dbg(0,"wrong signature on zip64_eoc downloaded from "LONGLONG_FMT"\n",download->size-98);
1285 g_free(download->zip64_eoc);
1286 return 0;
1287 }
1288 return 1;
1289 }
1290
1291 static int download_directory_start(struct map_download *download)
1292 {
1293 download->http = map_binfile_http_range(download->m, download->zip64_eoc->zip64eofst, download->zip64_eoc->zip64ecsz);
1294 if (!download->http)
1295 return 0;
1296 return 1;
1297 }
1298
1299 static int download_directory_do(struct map_download *download)
1300 {
1301 int count;
1302
1303 for (count = 0; count < 100; count++)
1304 {
1305 int cd_xlen, size_ret;
1306 unsigned char *cd_data;
1307 struct zip_cd *cd;
1308 cd = (struct zip_cd *) file_data_read_special(download->http, sizeof(*cd), &size_ret);
1309 cd->zipcunc = 0;
1310 // dbg(1, "size_ret=%d\n", size_ret);
1311 if (!size_ret)
1312 return 0;
1313 if (size_ret != sizeof(*cd) || cd->zipcensig != zip_cd_sig)
1314 {
1315 // dbg(0, "error1 size=%d vs %d\n", size_ret, sizeof(*cd));
1316 return 0;
1317 }
1318 file_data_write(download->file, download->offset, sizeof(*cd), (unsigned char *) cd);
1319 download->offset += sizeof(*cd);
1320 cd_xlen = cd->zipcfnl + cd->zipcxtl;
1321 cd_data = file_data_read_special(download->http, cd_xlen, &size_ret);
1322 if (size_ret != cd_xlen)
1323 {
1324 // dbg(0, "error2 size=%d vs %d\n", size_ret, cd_xlen);
1325 return 0;
1326 }
1327 file_data_write(download->file, download->offset, cd_xlen, cd_data);
1328 download->offset += cd_xlen;
1329 g_free(cd);
1330 g_free(cd_data);
1331 }
1332 return 1;
1333 }
1334
1335 static int download_directory_finish(struct map_download *download)
1336 {
1337 download->http = NULL;
1338 return 1;
1339 }
1340
1341 static int download_initial_finish(struct map_download *download)
1342 {
1343 download->zip64_eoc->zip64eofst = download->cd1offset;
1344 download->zip64_eocl->zip64lofst = download->offset;
1345 download->zip_eoc->zipeofst = download->cd1offset;
1346 #if 0
1347 file_data_write(download->file, download->offset, sizeof(*download->zip64_eoc), (unsigned char *)download->zip64_eoc);
1348 download->offset+=sizeof(*download->zip64_eoc);
1349 file_data_write(download->file, download->offset, sizeof(*download->zip64_eocl), (unsigned char *)download->zip64_eocl);
1350 download->offset+=sizeof(*download->zip64_eocl);
1351 #endif
1352 file_data_write(download->file, download->offset, sizeof(*download->zip_eoc), (unsigned char *) download->zip_eoc);
1353 download->offset += sizeof(*download->zip_eoc);
1354 g_free(download->zip64_eoc);
1355 download->zip64_eoc = NULL;
1356 return 1;
1357 }
1358
1359 static void push_zipfile_tile_do(struct map_rect_priv *mr, struct zip_cd *cd, int zipfile, int offset, int length)
1360
1361 {
1362 struct tile t;
1363 struct map_priv *m = mr->m;
1364 struct file *f = m->fi;
1365
1366 // dbg(1, "enter %p %d\n", mr, zipfile);
1367 #ifdef DEBUG_SIZE
1368 #if DEBUG_SIZE > 0
1369 {
1370 char filename[cd->zipcfnl+1];
1371 memcpy(filename, cd+1, cd->zipcfnl);
1372 filename[cd->zipcfnl]='\0';
1373 // dbg(0,"enter %d (%s) %d\n",zipfile, filename, cd->zipcunc);
1374 }
1375 #endif
1376 mr->size+=cd->zipcunc;
1377 #endif
1378 t.zipfile_num = zipfile;
1379 if (zipfile_to_tile(m, cd, &t))
1380 push_tile(mr, &t, offset, length);
1381 file_data_free(f, (unsigned char *) cd);
1382 }
1383
1384 static struct zip_cd *
1385 download(struct map_priv *m, struct map_rect_priv *mr, struct zip_cd *cd, int zipfile, int offset, int length, int async)
1386 {
1387 struct map_download *download;
1388
1389 if (!m->download_enabled)
1390 return NULL;
1391
1392 if (async == 2)
1393 {
1394 download = m->download;
1395 }
1396 else
1397 {
1398 download=g_new0(struct map_download, 1);
1399 if (mr)
1400 {
1401 download->m = m;
1402 download->mr = mr;
1403 download->file = m->fi;
1404 download->cd = cd;
1405 download->zipfile = zipfile;
1406 download->toffset = offset;
1407 download->tlength = length;
1408 download->state = 1;
1409 }
1410 else
1411 {
1412 struct attr readwrite =
1413 { attr_readwrite,
1414 { (void *) 1 } };
1415 struct attr create =
1416 { attr_create,
1417 { (void *) 1 } };
1418 struct attr *attrs[3];
1419 attrs[0] = &readwrite;
1420 attrs[1] = &create;
1421 attrs[2] = NULL;
1422 download->file = file_create(m->filename, attrs);
1423 download->m = m;
1424 download->state = 4;
1425 }
1426 }
1427 if (async == 1)
1428 {
1429 m->download = download;
1430 g_free(m->progress);
1431 if (download->mr)
1432 m->progress = g_strdup_printf("Download Tile %d 0%%", download->zipfile);
1433 else
1434 m->progress = g_strdup("Download Map Information 0%%");
1435 callback_list_call_attr_0(m->cbl, attr_progress);
1436 return NULL;
1437 }
1438 for (;;)
1439 {
1440 // dbg(0, "state=%d\n", download->state);
1441 switch (download->state)
1442 {
1443 case 0:
1444 // dbg(0, "error\n");
1445 break;
1446 case 1:
1447 if (download_start(download))
1448 download->state = 2;
1449 else
1450 download->state = 0;
1451 break;
1452 case 2:
1453 if (download_download(download))
1454 download->state = 3;
1455 else
1456 {
1457 g_free(m->progress);
1458 m->progress = g_strdup_printf("Download Tile %d %d%%", download->zipfile, download->progress);
1459 callback_list_call_attr_0(m->cbl, attr_progress);
1460 }
1461 break;
1462 case 3:
1463 if (download_finish(download))
1464 {
1465 struct zip_cd *ret;
1466 g_free(m->progress);
1467 m->progress = g_strdup_printf("Download Tile %d 100%%", download->zipfile);
1468 callback_list_call_attr_0(m->cbl, attr_progress);
1469 if (async)
1470 {
1471 push_zipfile_tile_do(download->mr, download->cd, download->zipfile, download->toffset, download->tlength);
1472 ret = NULL;
1473 }
1474 else
1475 ret = download->cd;
1476 g_free(m->progress);
1477 m->progress = NULL;
1478 g_free(download);
1479 if (async)
1480 m->download = NULL;
1481 return ret;
1482 }
1483 else
1484 download->state = 0;
1485 break;
1486 case 4:
1487 if (download_planet_size(download))
1488 download->state = 5;
1489 else
1490 download->state = 0;
1491 break;
1492 case 5:
1493 g_free(m->progress);
1494 m->progress = g_strdup("Download Map Information 50%%");
1495 callback_list_call_attr_0(m->cbl, attr_progress);
1496 if (download_eoc(download))
1497 download->state = 6;
1498 else
1499 {
1500 // dbg(0, "download of eoc failed\n");
1501 download->state = 0;
1502 }
1503 break;
1504 case 6:
1505 g_free(m->progress);
1506 m->progress = g_strdup("Download Map Information 100%%");
1507 callback_list_call_attr_0(m->cbl, attr_progress);
1508 if (download_directory_start(download))
1509 download->state = 7;
1510 else
1511 download->state = 0;
1512 break;
1513 case 7:
1514 g_free(m->progress);
1515 m->progress = g_strdup_printf("Download Map Directory %d%%", (int) (download->offset * 100 / download->zip64_eoc->zip64ecsz));
1516 callback_list_call_attr_0(m->cbl, attr_progress);
1517 if (!download_directory_do(download))
1518 download->state = 8;
1519 break;
1520 case 8:
1521 if (download_directory_finish(download))
1522 download->state = 9;
1523 else
1524 download->state = 0;
1525 break;
1526 case 9:
1527 download_initial_finish(download);
1528 m->fi = download->file;
1529 g_free(m->progress);
1530 m->progress = NULL;
1531 g_free(download);
1532 if (async)
1533 m->download = NULL;
1534 map_binfile_open(m);
1535 break;
1536 }
1537 if (async)
1538 return NULL;
1539 }
1540 }
1541
1542 static int push_zipfile_tile(struct map_rect_priv *mr, int zipfile, int offset, int length, int async)
1543 {
1544 struct map_priv *m = mr->m;
1545 struct file *f = m->fi;
1546 long long cdoffset = m->eoc64 ? m->eoc64->zip64eofst : m->eoc->zipeofst;
1547 struct zip_cd *cd = (struct zip_cd *) (file_data_read(f, cdoffset + zipfile * m->cde_size, m->cde_size));
1548 // dbg(1,"read from "LONGLONG_FMT" %d bytes\n",cdoffset + zipfile*m->cde_size, m->cde_size);
1549 cd_to_cpu(cd);
1550 if (!cd->zipcunc && m->url)
1551 {
1552 cd = download(m, mr, cd, zipfile, offset, length, async);
1553 if (!cd)
1554 return 1;
1555 }
1556 push_zipfile_tile_do(mr, cd, zipfile, offset, length);
1557 return 0;
1558 }
1559
1560 static struct map_rect_priv *
1561 map_rect_new_binfile_int(struct map_priv *map, struct map_selection *sel)
1562 {
1563 struct map_rect_priv *mr;
1564
1565 binfile_check_version(map);
1566 // dbg(1, "map_rect_new_binfile\n");
1567 if (!map->fi && !map->url)
1568 {
1569 return NULL;
1570 }
1571 map_binfile_http_close(map);
1572 mr=g_new0(struct map_rect_priv, 1);
1573 mr->m = map;
1574 mr->sel = sel;
1575 mr->item.id_hi = 0;
1576 mr->item.id_lo = 0;
1577 mr->item.meth = &methods_binfile;
1578 mr->item.priv_data = mr;
1579 return mr;
1580 }
1581
1582 static void tile_bbox(char *tile, int len, struct coord_rect *r)
1583 {
1584 struct coord c;
1585 int overlap = 1;
1586 int xo, yo;
1587 struct coord_rect world_bbox =
1588 {
1589 { -20000000, 20000000 }, /* lu */
1590 { 20000000, -20000000 }, /* rl */
1591 };
1592 *r = world_bbox;
1593 while (len)
1594 {
1595 c.x = (r->lu.x + r->rl.x) / 2;
1596 c.y = (r->lu.y + r->rl.y) / 2;
1597 xo = (r->rl.x - r->lu.x) * overlap / 100;
1598 yo = (r->lu.y - r->rl.y) * overlap / 100;
1599 switch (*tile)
1600 {
1601 case 'a':
1602 r->lu.x = c.x - xo;
1603 r->rl.y = c.y - yo;
1604 break;
1605 case 'b':
1606 r->rl.x = c.x + xo;
1607 r->rl.y = c.y - yo;
1608 break;
1609 case 'c':
1610 r->lu.x = c.x - xo;
1611 r->lu.y = c.y + yo;
1612 break;
1613 case 'd':
1614 r->rl.x = c.x + xo;
1615 r->lu.y = c.y + yo;
1616 break;
1617 default:
1618 return;
1619 }
1620 tile++;
1621 len--;
1622 }
1623 }
1624
1625 static int map_download_selection_check(struct zip_cd *cd, struct map_selection *sel)
1626 {
1627 //// dbg(0,"EEnter\n");
1628
1629 struct coord_rect cd_rect;
1630 if (cd->zipcunc)
1631 return 0;
1632 tile_bbox((char *) (cd + 1), cd->zipcfnl, &cd_rect);
1633 while (sel)
1634 {
1635 if (coord_rect_overlap(&cd_rect, &sel->u.c_rect))
1636 return 1;
1637 sel = sel->next;
1638 }
1639 return 0;
1640 }
1641
1642 static void map_download_selection(struct map_priv *m, struct map_rect_priv *mr, struct map_selection *sel)
1643 {
1644 int i;
1645 struct zip_cd *cd;
1646 for (i = 0; i < m->zip_members; i++)
1647 {
1648 cd = binfile_read_cd(m, m->cde_size * i, -1);
1649 if (map_download_selection_check(cd, sel))
1650 download(m, mr, cd, i, 0, 0, 0);
1651 file_data_free(m->fi, (unsigned char *) cd);
1652 }
1653 }
1654
1655 static struct map_rect_priv *
1656 map_rect_new_binfile(struct map_priv *map, struct map_selection *sel)
1657 {
1658 struct map_rect_priv *mr = map_rect_new_binfile_int(map, sel);
1659 struct tile t;
1660 // dbg(1, "zip_members=%d\n", map->zip_members);
1661 if (map->url && map->fi && sel && sel->order == 255)
1662 {
1663 map_download_selection(map, mr, sel);
1664 }
1665 if (map->eoc)
1666 mr->status = 1;
1667 else
1668 {
1669 unsigned char *d;
1670 if (map->fi)
1671 {
1672 d = file_data_read(map->fi, 0, map->fi->size);
1673 t.start = (int *) d;
1674 t.end = (int *) (d + map->fi->size);
1675 t.fi = map->fi;
1676 t.zipfile_num = 0;
1677 t.mode = 0;
1678 push_tile(mr, &t, 0, 0);
1679 }
1680 else if (map->url && !map->download)
1681 {
1682 download(map, NULL, NULL, 0, 0, 0, 1);
1683 mr->status = 1;
1684 }
1685 }
1686 return mr;
1687 }
1688
1689 static void write_changes_do(gpointer key, gpointer value, gpointer user_data)
1690 {
1691 struct binfile_hash_entry *entry = key;
1692 FILE *out = user_data;
1693 if (entry->flags)
1694 {
1695 entry->flags = 0;
1696 fwrite(entry, sizeof(*entry) + (le32_to_cpu(entry->data[0]) + 1) * 4, 1, out);
1697 // dbg(0, "yes\n");
1698 }
1699 }
1700
1701 static void write_changes(struct map_priv *m)
1702 {
1703 FILE *changes;
1704 char *changes_file;
1705 if (!m->changes)
1706 return;
1707 changes_file = g_strdup_printf("%s.log", m->filename);
1708 changes = fopen(changes_file, "ab");
1709 g_hash_table_foreach(m->changes, write_changes_do, changes);
1710 fclose(changes);
1711 g_free(changes_file);
1712 }
1713
1714 static void load_changes(struct map_priv *m)
1715 {
1716 FILE *changes;
1717 char *changes_file;
1718 struct binfile_hash_entry entry, *e;
1719 int size;
1720 changes_file = g_strdup_printf("%s.log", m->filename);
1721 changes = fopen(changes_file, "rb");
1722 if (!changes)
1723 {
1724 g_free(changes_file);
1725 return;
1726 }
1727 m->changes = g_hash_table_new_full(binfile_hash_entry_hash, binfile_hash_entry_equal, g_free_func, NULL);
1728 while (fread(&entry, sizeof(entry), 1, changes) == 1)
1729 {
1730 if (fread(&size, sizeof(size), 1, changes) != 1)
1731 break;
1732 e = g_malloc(sizeof(struct binfile_hash_entry) + (le32_to_cpu(size) + 1) * 4);
1733 *e = entry;
1734 e->data[0] = size;
1735 if (fread(e->data + 1, le32_to_cpu(size) * 4, 1, changes) != 1)
1736 break;
1737 g_hash_table_replace(m->changes, e, e);
1738 }
1739 fclose(changes);
1740 g_free(changes_file);
1741 }
1742
1743 static void map_rect_destroy_binfile(struct map_rect_priv *mr)
1744 {
1745 write_changes(mr->m);
1746 while (pop_tile(mr))
1747 ;
1748 #ifdef DEBUG_SIZE
1749 // dbg(0,"size=%d kb\n",mr->size/1024);
1750 #endif
1751 if (mr->tiles[0].fi && mr->tiles[0].start)
1752 file_data_free(mr->tiles[0].fi, (unsigned char *) (mr->tiles[0].start));
1753 g_free(mr->url);
1754 map_binfile_http_close(mr->m);
1755 g_free(mr);
1756 }
1757
1758 static void setup_pos(struct map_rect_priv *mr)
1759 {
1760 int size, coord_size;
1761 struct tile *t = mr->t;
1762 size = le32_to_cpu(t->pos[0]);
1763 if (size > 1024 * 1024 || size < 0)
1764 {
1765 // dbg(0, "size=0x%x\n", size);
1766 #if 0
1767 fprintf(stderr,"offset=%d\n", (unsigned char *)(mr->pos)-mr->m->f->begin);
1768 #endif
1769 // dbg(0, "size error");
1770 }
1771 t->pos_next = t->pos + size + 1;
1772 mr->item.type = le32_to_cpu(t->pos[1]);
1773 coord_size = le32_to_cpu(t->pos[2]);
1774 t->pos_coord_start = t->pos + 3;
1775 t->pos_attr_start = t->pos_coord_start + coord_size;
1776 }
1777
1778 static int selection_contains(struct map_selection *sel, struct coord_rect *r, struct range *mima)
1779 {
1780 //// dbg(0,"EEnter\n");
1781
1782 int order;
1783 if (!sel)
1784 return 1;
1785 while (sel)
1786 {
1787 if (coord_rect_overlap(r, &sel->u.c_rect))
1788 {
1789 order = sel->order;
1790 // dbg(1, "min %d max %d order %d\n", mima->min, mima->max, order);
1791 if (!mima->min && !mima->max)
1792 return 1;
1793 if (order >= mima->min && order <= mima->max)
1794 return 1;
1795 }
1796 sel = sel->next;
1797 }
1798 return 0;
1799 }
1800
1801 static void map_parse_country_binfile(struct map_rect_priv *mr)
1802 {
1803 struct attr at;
1804 if (binfile_attr_get(mr->item.priv_data, attr_country_id, &at))
1805 {
1806 if (at.u.num == mr->country_id)
1807 {
1808 if (binfile_attr_get(mr->item.priv_data, attr_zipfile_ref, &at))
1809 {
1810 push_zipfile_tile(mr, at.u.num, 0, 0, 0);
1811 }
1812 }
1813 }
1814 }
1815
1816 static int map_parse_submap(struct map_rect_priv *mr, int async)
1817 {
1818 struct coord_rect r;
1819 struct coord c[2];
1820 struct attr at;
1821 struct range mima;
1822 if (binfile_coord_get(mr->item.priv_data, c, 2) != 2)
1823 return 0;
1824
1825 r.lu.x = c[0].x;
1826 r.lu.y = c[1].y;
1827 r.rl.x = c[1].x;
1828 r.rl.y = c[0].y;
1829 if (!binfile_attr_get(mr->item.priv_data, attr_order, &at))
1830 return 0;
1831
1832 #if __BYTE_ORDER == __BIG_ENDIAN
1833 mima.min = le16_to_cpu(at.u.range.max);
1834 mima.max = le16_to_cpu(at.u.range.min);
1835 #else
1836 mima=at.u.range;
1837 #endif
1838 if (!mr->m->eoc || !selection_contains(mr->sel, &r, &mima))
1839 return 0;
1840 if (!binfile_attr_get(mr->item.priv_data, attr_zipfile_ref, &at))
1841 return 0;
1842 // dbg(1, "pushing zipfile %d from %d\n", at.u.num, mr->t->zipfile_num);
1843 return push_zipfile_tile(mr, at.u.num, 0, 0, async);
1844 }
1845
1846 static int push_modified_item(struct map_rect_priv *mr)
1847 {
1848 struct item_id id;
1849 struct binfile_hash_entry *entry;
1850 id.id_hi = mr->item.id_hi;
1851 id.id_lo = mr->item.id_lo;
1852 entry = g_hash_table_lookup(mr->m->changes, &id);
1853 if (entry)
1854 {
1855 struct tile tn;
1856 tn.pos_next = tn.pos = tn.start = entry->data;
1857 tn.zipfile_num = mr->item.id_hi;
1858 tn.mode = 2;
1859 tn.end = tn.start + le32_to_cpu(entry->data[0]) + 1;
1860 push_tile(mr, &tn, 0, 0);
1861 return 1;
1862 }
1863 return 0;
1864 }
1865
1866 static struct item *
1867 map_rect_get_item_binfile(struct map_rect_priv *mr)
1868 {
1869 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
1870 dbg(0,"+#+:enter\n");
1871 #endif
1872
1873 struct tile *t;
1874 struct map_priv *m = mr->m;
1875
1876 if (m->download)
1877 {
1878 download(m, NULL, NULL, 0, 0, 0, 2);
1879 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
1880 dbg(0,"+#+:leave9\n");
1881 #endif
1882 return &busy_item;
1883 }
1884
1885 if (mr->status == 1)
1886 {
1887 mr->status = 0;
1888 if (push_zipfile_tile(mr, m->zip_members - 1, 0, 0, 1))
1889 {
1890 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
1891 dbg(0,"+#+:leave8\n");
1892 #endif
1893 return &busy_item;
1894 }
1895 }
1896
1897 for (;;)
1898 {
1899 t = mr->t;
1900
1901 if (!t)
1902 {
1903 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
1904 dbg(0,"+#+:leave6\n");
1905 #endif
1906 return NULL;
1907 }
1908
1909 t->pos = t->pos_next;
1910
1911 if (t->pos >= t->end)
1912 {
1913 if (pop_tile(mr))
1914 {
1915 continue;
1916 }
1917
1918 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
1919 dbg(0,"+#+:leave5\n");
1920 #endif
1921
1922 return NULL;
1923 }
1924
1925 setup_pos(mr);
1926 binfile_coord_rewind(mr);
1927 binfile_attr_rewind(mr);
1928 if ((mr->item.type == type_submap) && (!mr->country_id))
1929 {
1930 if (map_parse_submap(mr, 1))
1931 {
1932 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
1933 dbg(0,"+#+:leave4\n");
1934 #endif
1935 return &busy_item;
1936 }
1937 continue;
1938 }
1939 if (t->mode != 2)
1940 {
1941 mr->item.id_hi = t->zipfile_num;
1942 mr->item.id_lo = t->pos - t->start;
1943 if (mr->m->changes && push_modified_item(mr))
1944 continue;
1945 }
1946 if (mr->country_id)
1947 {
1948 if (mr->item.type == type_countryindex)
1949 {
1950 map_parse_country_binfile(mr);
1951 }
1952 if (item_is_town(mr->item))
1953 {
1954 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
1955 dbg(0,"+#+:leave3\n");
1956 #endif
1957 return &mr->item;
1958 }
1959 else
1960 {
1961 continue;
1962 }
1963 }
1964 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
1965 dbg(0,"+#+:leave 2\n");
1966 #endif
1967 return &mr->item;
1968 }
1969
1970 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
1971 dbg(0,"+#+:leave\n");
1972 #endif
1973 }
1974
1975 static struct item *
1976 map_rect_get_item_byid_binfile(struct map_rect_priv *mr, int id_hi, int id_lo)
1977 {
1978 struct tile *t;
1979 if (mr->m->eoc)
1980 {
1981 while (pop_tile(mr))
1982 ;
1983 push_zipfile_tile(mr, id_hi, 0, 0, 0);
1984 }
1985 t = mr->t;
1986 t->pos = t->start + id_lo;
1987 mr->item.id_hi = id_hi;
1988 mr->item.id_lo = id_lo;
1989 if (mr->m->changes)
1990 {
1991 push_modified_item(mr);
1992 }
1993 setup_pos(mr);
1994 binfile_coord_rewind(mr);
1995 binfile_attr_rewind(mr);
1996
1997 return &mr->item;
1998 }
1999
2000 static int binmap_search_by_index(struct map_priv *map, struct item *item, struct map_rect_priv **ret)
2001 {
2002 struct attr zipfile_ref;
2003 int *data;
2004
2005 if (!item)
2006 {
2007 *ret = NULL;
2008 return 0;
2009 }
2010 if (item_attr_get(item, attr_item_id, &zipfile_ref))
2011 {
2012 data = zipfile_ref.u.data;
2013 *ret = map_rect_new_binfile_int(map, NULL);
2014 push_zipfile_tile(*ret, le32_to_cpu(data[0]), le32_to_cpu(data[1]), -1, 0);
2015 return 3;
2016 }
2017 if (item_attr_get(item, attr_zipfile_ref, &zipfile_ref))
2018 {
2019 *ret = map_rect_new_binfile_int(map, NULL);
2020 push_zipfile_tile(*ret, zipfile_ref.u.num, 0, 0, 0);
2021 return 1;
2022 }
2023 if (item_attr_get(item, attr_zipfile_ref_block, &zipfile_ref))
2024 {
2025 data = zipfile_ref.u.data;
2026 *ret = map_rect_new_binfile_int(map, NULL);
2027 push_zipfile_tile(*ret, le32_to_cpu(data[0]), le32_to_cpu(data[1]), le32_to_cpu(data[2]), 0);
2028 return 2;
2029 }
2030 *ret = NULL;
2031 return 0;
2032 }
2033
2034 static struct map_rect_priv *
2035 binmap_search_street_by_place(struct map_priv *map, struct item *town, struct coord *c, struct map_selection *sel)
2036 {
2037 struct attr town_name, poly_town_name;
2038 struct map_rect_priv *map_rec2;
2039 struct item *place;
2040 int found = 0;
2041
2042 if (!item_attr_get(town, attr_label, &town_name))
2043 return NULL;
2044 sel->range = item_range_all;
2045 sel->order = 18;
2046 sel->next = NULL;
2047 sel->u.c_rect.lu = *c;
2048 sel->u.c_rect.rl = *c;
2049 map_rec2 = map_rect_new_binfile(map, sel);
2050 while ((place = map_rect_get_item_binfile(map_rec2)))
2051 {
2052 if (item_is_poly_place(*place) && item_attr_get(place, attr_label, &poly_town_name) && !strcmp(poly_town_name.u.str, town_name.u.str))
2053 {
2054 struct coord c[128];
2055 int i, count;
2056 found = 1;
2057 while ((count = item_coord_get(place, c, 128)))
2058 {
2059 for (i = 0; i < count; i++)
2060 {
2061 coord_rect_extend(&sel->u.c_rect, &c[i]);
2062 }
2063 }
2064 }
2065 }
2066
2067 map_rect_destroy_binfile(map_rec2);
2068 if (found)
2069 {
2070 return map_rect_new_binfile(map, sel);
2071 }
2072 return NULL;
2073 }
2074
2075 static struct map_rect_priv *
2076 binmap_search_street_by_estimate(struct map_priv *map, struct item *town, struct coord *c, struct map_selection *sel)
2077 {
2078 int size = 10000;
2079 switch (town->type)
2080 {
2081 case type_town_label_1e7:
2082 case type_town_label_5e6:
2083 case type_town_label_2e6:
2084 case type_town_label_1e6:
2085 case type_town_label_5e5:
2086 case type_town_label_2e5:
2087 size = 10000;
2088 break;
2089 case type_town_label_1e5:
2090 case type_town_label_5e4:
2091 case type_town_label_2e4:
2092 size = 5000;
2093 break;
2094 case type_town_label_1e4:
2095 case type_town_label_5e3:
2096 case type_town_label_2e3:
2097 size = 2500;
2098 break;
2099 case type_town_label_1e3:
2100 case type_town_label_5e2:
2101 case type_town_label_2e2:
2102 case type_town_label_1e2:
2103 case type_town_label_5e1:
2104 case type_town_label_2e1:
2105 case type_town_label_1e1:
2106 case type_town_label_5e0:
2107 case type_town_label_2e0:
2108 case type_town_label_1e0:
2109 case type_town_label_0e0:
2110 size = 1000;
2111 break;
2112 default:
2113 break;
2114 }
2115
2116 if (global_search_street_size_factor > 1)
2117 {
2118 size = size * global_search_street_size_factor;
2119 }
2120
2121 sel->u.c_rect.lu.x = c->x - size;
2122 sel->u.c_rect.lu.y = c->y + size;
2123 sel->u.c_rect.rl.x = c->x + size;
2124 sel->u.c_rect.rl.y = c->y - size;
2125 return map_rect_new_binfile(map, sel);
2126 }
2127
2128 static struct map_rect_priv *
2129 binmap_search_housenumber_by_estimate(struct map_priv *map, struct coord *c, struct map_selection *sel)
2130 {
2131 int size = 20;
2132 sel->u.c_rect.lu.x = c->x - size;
2133 sel->u.c_rect.lu.y = c->y + size;
2134 sel->u.c_rect.rl.x = c->x + size;
2135 sel->u.c_rect.rl.y = c->y - size;
2136
2137 sel->range = item_range_all;
2138 sel->order = 18;
2139 //sel->next = NULL;
2140
2141 return map_rect_new_binfile(map, sel);
2142 }
2143
2144 static struct map_search_priv *
2145 binmap_search_new(struct map_priv *map, struct item *item, struct attr *search, int partial)
2146 {
2147 struct map_rect_priv *map_rec;
2148 struct map_search_priv *msp=g_new0(struct map_search_priv, 1);
2149 struct item *town;
2150 int willsearch = 0;
2151
2152 msp->search = search;
2153 msp->partial = partial;
2154 /*
2155 * NOTE: If you implement search for other attributes than attr_town_name and attr_street_name,
2156 * please update this comment and the documentation for map_search_new() in map.c
2157 */
2158 switch (search->type)
2159 {
2160 case attr_country_name:
2161 break;
2162 case attr_town_name:
2163 case attr_town_or_district_name:
2164 map_rec = map_rect_new_binfile(map, NULL);
2165 if (!map_rec)
2166 {
2167 break;
2168 }
2169 map_rec->country_id = item->id_lo;
2170 msp->mr = map_rec;
2171 willsearch = 1;
2172 break;
2173 case attr_town_postal:
2174 break;
2175 case attr_street_name:
2176 if (!item->map)
2177 break;
2178 if (!map_priv_is(item->map, map))
2179 break;
2180 map_rec = map_rect_new_binfile(map, NULL);
2181 town = map_rect_get_item_byid_binfile(map_rec, item->id_hi, item->id_lo);
2182 if (town)
2183 {
2184 struct coord c;
2185
2186 if (binmap_search_by_index(map, town, &msp->mr))
2187 {
2188 //dbg(0, "search:mode=1\n");
2189 msp->mode = 1;
2190 }
2191 else
2192 {
2193 if (item_coord_get(town, &c, 1))
2194 {
2195 if ((msp->mr = binmap_search_street_by_place(map, town, &c, &msp->ms)))
2196 {
2197 //dbg(0, "search:mode=2\n");
2198 msp->mode = 2;
2199 }
2200 else
2201 {
2202 msp->mr = binmap_search_street_by_estimate(map, town, &c, &msp->ms);
2203 //dbg(0, "search:mode=3\n");
2204 msp->mode = 3;
2205 }
2206 }
2207 }
2208 map_rect_destroy_binfile(map_rec);
2209 if (!msp->mr)
2210 {
2211 break;
2212 }
2213 willsearch = 1;
2214 break;
2215 }
2216 map_rect_destroy_binfile(map_rec);
2217 break;
2218 case attr_house_number:
2219 // dbg(1, "case house_number");
2220 if (!item->map)
2221 break;
2222 if (!map_priv_is(item->map, map))
2223 break;
2224 msp->map = map;
2225 msp->mr_item = map_rect_new_binfile(map, NULL);
2226 msp->item = map_rect_get_item_byid_binfile(msp->mr_item, item->id_hi, item->id_lo);
2227 if (binmap_search_by_index(map, msp->item, &msp->mr) != 3)
2228 {
2229 struct coord c;
2230 if (item_coord_get(msp->item, &c, 1))
2231 {
2232 msp->mr = binmap_search_housenumber_by_estimate(map, &c, &msp->ms);
2233 msp->mode = 2;
2234 }
2235 map_rect_destroy_binfile(msp->mr_item);
2236 msp->mr_item = NULL;
2237 }
2238 if (!msp->mr)
2239 {
2240 break;
2241 }
2242 willsearch = 1;
2243 break;
2244 default:
2245 break;
2246 }
2247
2248 if (!willsearch)
2249 {
2250 g_free(msp);
2251 msp = NULL;
2252 }
2253 else
2254 {
2255 msp->str = linguistics_casefold(search->u.str);
2256 }
2257 return msp;
2258 }
2259
2260 static int ascii_cmp(char *name, char *match, int partial)
2261 {
2262 int ret = 1;
2263
2264 if (name == NULL)
2265 {
2266 return ret;
2267 }
2268
2269 if (match == NULL)
2270 {
2271 return ret;
2272 }
2273
2274 char *s2 = linguistics_casefold(match); // user entered search string
2275 char *s1 = linguistics_casefold(name); // string from mapfile
2276 char *s1_1 = linguistics_expand_special(s1, 1);
2277 char *s2_1 = linguistics_expand_special(s2, 1);
2278
2279 if (s1_1)
2280 {
2281 if (s2_1)
2282 {
2283 ret = linguistics_compare(s1_1, s2_1, partial);
2284 }
2285 else
2286 {
2287 ret = linguistics_compare(s1_1, s2, partial);
2288 }
2289 }
2290 else
2291 {
2292 if (s2_1)
2293 {
2294 ret = linguistics_compare(s1, s2_1, partial);
2295 }
2296 else
2297 {
2298 ret = linguistics_compare(s1, s2, partial);
2299 }
2300 }
2301
2302 if (s1_1)
2303 g_free(s1_1);
2304 if (s2_1)
2305 g_free(s2_1);
2306 if (s1)
2307 g_free(s1);
2308 if (s2)
2309 g_free(s2);
2310 return ret;
2311 }
2312
2313 struct duplicate
2314 {
2315 struct coord c;
2316 char str[0];
2317 };
2318
2319 static guint duplicate_hash(gconstpointer key)
2320 {
2321 const struct duplicate *d = key;
2322 return d->c.x ^ d->c.y ^ g_str_hash(d->str);
2323 }
2324
2325 static gboolean duplicate_equal(gconstpointer a, gconstpointer b)
2326 {
2327 const struct duplicate *da = a;
2328 const struct duplicate *db = b;
2329 return (da->c.x == db->c.x && da->c.y == db->c.y && g_str_equal(da->str, db->str));
2330 }
2331
2332
2333 static int duplicate(struct map_search_priv *msp, struct item *item, enum attr_type attr_type)
2334 {
2335 struct attr attr;
2336
2337 if (!msp->search_results)
2338 {
2339 msp->search_results = g_hash_table_new_full(duplicate_hash, duplicate_equal, g_free_func, NULL);
2340 }
2341
2342 binfile_attr_rewind(item->priv_data);
2343
2344 if (!item_attr_get(item, attr_type, &attr))
2345 {
2346 return 1;
2347 }
2348
2349 {
2350 int len = sizeof(struct coord) + strlen(attr.u.str) + 1;
2351 char *buffer = g_alloca(sizeof(char) * len);
2352 struct duplicate *d = (struct duplicate *) buffer;
2353 if (!item_coord_get(item, &d->c, 1))
2354 {
2355 d->c.x = 0;
2356 d->c.y = 0;
2357 }
2358 binfile_coord_rewind(item->priv_data);
2359 strcpy(d->str, attr.u.str);
2360 if (!g_hash_table_lookup(msp->search_results, d))
2361 {
2362 struct duplicate *dc = g_malloc(len);
2363 memcpy(dc, d, len);
2364 g_hash_table_insert(msp->search_results, dc, GINT_TO_POINTER(1));
2365 binfile_attr_rewind(item->priv_data);
2366 return 0;
2367 }
2368 }
2369 return 2;
2370 }
2371
2372 static struct item *
2373 binmap_search_get_item(struct map_search_priv *map_search)
2374 {
2375 struct item* it;
2376 struct attr at;
2377
2378 // // dbg(0,"Enter\n");
2379
2380 for (;;)
2381 {
2382 while ((it = map_rect_get_item_binfile(map_search->mr)))
2383 {
2384 switch (map_search->search->type)
2385 {
2386 case attr_town_name:
2387 case attr_district_name:
2388 case attr_town_or_district_name:
2389
2390 #if 0
2391 if (map_search->mr->tile_depth > 1 && item_is_town(*it) && !item_is_district(*it) && map_search->search->type != attr_district_name)
2392 {
2393 if (binfile_attr_get(it->priv_data, attr_town_name_match, &at) || binfile_attr_get(it->priv_data, attr_town_name, &at))
2394 {
2395 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial) && !duplicate(map_search, it, attr_town_name))
2396 return it;
2397 }
2398 }
2399 #endif
2400
2401 #if 1
2402 if (map_search->mr->tile_depth > 1 && item_is_town(*it) && !item_is_district(*it) && map_search->search->type != attr_district_name)
2403 {
2404 if (binfile_attr_get(it->priv_data, attr_town_name, &at))
2405 {
2406 //// dbg(0,"22town n:%s\n",at.u.str);
2407 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial)
2408 // && !duplicate(map_search, it, attr_town_name)
2409 )
2410 {
2411 //// dbg(0,"town n:%s\n",at.u.str);
2412 return it;
2413 }
2414 }
2415
2416 if (binfile_attr_get(it->priv_data, attr_town_name_match, &at))
2417 {
2418 //// dbg(0,"11town M:%s\n",at.u.str);
2419 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial)
2420 // && !duplicate(map_search, it, attr_town_name)
2421 )
2422 {
2423 //// dbg(0,"town M:%s\n",at.u.str);
2424 return it;
2425 }
2426 }
2427 }
2428 #endif
2429
2430 if (map_search->mr->tile_depth > 1 && item_is_district(*it) && map_search->search->type != attr_town_name)
2431 {
2432 if (binfile_attr_get(it->priv_data, attr_district_name_match, &at) || binfile_attr_get(it->priv_data, attr_district_name, &at))
2433 {
2434 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial) && !duplicate(map_search, it, attr_town_name))
2435 return it;
2436 }
2437 }
2438 break;
2439
2440 case attr_street_name:
2441
2442 if (map_search->mode == 1)
2443 {
2444 //dbg(0,"*in here 00*\n");
2445
2446 //if (binfile_attr_get(it->priv_data, attr_street_name_match, &at) || binfile_attr_get(it->priv_data, attr_street_name, &at)) {
2447 // if (!ascii_cmp(at.u.str, map_search->str, map_search->partial) && !duplicate(map_search, it, attr_street_name)) {
2448 // return it;
2449 // }
2450 //}
2451
2452 if (binfile_attr_get(it->priv_data, attr_street_name, &at))
2453 {
2454 //// dbg(0,"str AA:%s\n", at.u.str);
2455
2456 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial))
2457 {
2458 if ((offline_search_filter_duplicates != 1) || (!duplicate(map_search, it, attr_street_name)))
2459 {
2460 return it;
2461 }
2462 else
2463 {
2464 //// dbg(0,"dup street 1:%s\n",at.u.str);
2465 }
2466 }
2467 }
2468
2469 if (binfile_attr_get(it->priv_data, attr_street_name_match, &at))
2470 {
2471 //// dbg(0,"str BB:%s\n", at.u.str);
2472
2473 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial))
2474 {
2475 if ((offline_search_filter_duplicates != 1) || (!duplicate(map_search, it, attr_street_name_match)))
2476 {
2477 return it;
2478 }
2479 else
2480 {
2481 //// dbg(0,"dup street 2:%s\n",at.u.str);
2482 }
2483 }
2484 }
2485
2486 continue;
2487 }
2488
2489 #if 1
2490 // ------------------------------------
2491 // map_search->mode == 2 or 3
2492 // ------------------------------------
2493 if (item_is_street(*it))
2494 {
2495 // dbg(0,"*in here 11*\n");
2496
2497 struct attr at;
2498 if (map_selection_contains_item_rect(map_search->mr->sel, it))
2499 {
2500 if (binfile_attr_get(it->priv_data, attr_label, &at))
2501 {
2502 int match = 0;
2503 char *str = g_strdup(at.u.str);
2504 // dbg(0,"search=%s str is:%s\n",map_search->str, at.u.str);
2505 if (!ascii_cmp(str, map_search->str, map_search->partial))
2506 {
2507 match = 1;
2508 }
2509 g_free(str);
2510 if (match)
2511 {
2512 if ((offline_search_filter_duplicates != 1) || (!duplicate(map_search, it, attr_label)))
2513 {
2514 item_coord_rewind(it);
2515 return it;
2516 }
2517 }
2518 }
2519
2520 if (binfile_attr_get(it->priv_data, attr_street_name_match, &at))
2521 {
2522 int match = 0;
2523 char *str = g_strdup(at.u.str);
2524 // dbg(0,"search=%s mstr is:%s\n",map_search->str, at.u.str);
2525 if (!ascii_cmp(str, map_search->str, map_search->partial))
2526 {
2527 match = 1;
2528 }
2529 g_free(str);
2530 if (match)
2531 {
2532 if ((offline_search_filter_duplicates != 1) || (!duplicate(map_search, it, attr_street_name_match)))
2533 {
2534 item_coord_rewind(it);
2535 return it;
2536 }
2537 }
2538 }
2539 //else
2540 //{
2541 // if (binfile_attr_get(it->priv_data, attr_street_name, &at))
2542 // {
2543 // // dbg(0,"---str X*X:%s\n", at.u.str);
2544 // }
2545 //}
2546 }
2547 }
2548 #endif
2549 break;
2550 case attr_house_number:
2551 //if (it->type == type_house_number)
2552 if ((it->type == type_house_number) || (type_house_number_interpolation_even) || (type_house_number_interpolation_odd) || (type_house_number_interpolation_all))
2553 {
2554 // is it a housenumber?
2555 if (binfile_attr_get(it->priv_data, attr_house_number, &at))
2556 {
2557 // match housenumber to our string
2558 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial))
2559 {
2560 //binfile_attr_get(it->priv_data, attr_street_name, &at);
2561 //// dbg(0,"hnnn B1 street_name=%s",at.u.str);
2562
2563 if (!duplicate(map_search, it, attr_house_number))
2564 {
2565 binfile_attr_rewind(it->priv_data);
2566 return it;
2567 }
2568 }
2569 }
2570 else
2571 {
2572 return it;
2573 }
2574 }
2575 continue;
2576 default:
2577 return NULL;
2578 }
2579 }
2580
2581 if (!map_search->mr_item)
2582 {
2583 return NULL;
2584 }
2585 map_rect_destroy_binfile(map_search->mr);
2586 if (!binmap_search_by_index(map_search->map, map_search->item, &map_search->mr))
2587 {
2588 return NULL;
2589 }
2590 } // endless for-loop
2591
2592 return NULL; // this is never reached
2593 }
2594
2595 static void binmap_search_destroy(struct map_search_priv *ms)
2596 {
2597 if (ms->search_results)
2598 g_hash_table_destroy(ms->search_results);
2599 if (ms->mr_item)
2600 map_rect_destroy_binfile(ms->mr_item);
2601 if (ms->mr)
2602 map_rect_destroy_binfile(ms->mr);
2603 if (ms->str)
2604 g_free(ms->str);
2605 g_free(ms);
2606 }
2607
2608 static int binmap_get_attr(struct map_priv *m, enum attr_type type, struct attr *attr)
2609 {
2610 attr->type = type;
2611 switch (type)
2612 {
2613 case attr_map_release:
2614 if (m->map_release)
2615 {
2616 attr->u.str = m->map_release;
2617 return 1;
2618 }
2619 break;
2620 case attr_progress:
2621 if (m->progress)
2622 {
2623 attr->u.str = m->progress;
2624 return 1;
2625 }
2626 default:
2627 break;
2628 }
2629 return 0;
2630 }
2631
2632 static int binmap_set_attr(struct map_priv *map, struct attr *attr)
2633 {
2634 switch (attr->type)
2635 {
2636 case attr_update:
2637 map->download_enabled = attr->u.num;
2638 return 1;
2639 default:
2640 return 0;
2641 }
2642
2643 }
2644
2645 static struct map_methods map_methods_binfile =
2646 { projection_mg, "utf-8", map_destroy_binfile, map_rect_new_binfile, map_rect_destroy_binfile, map_rect_get_item_binfile, map_rect_get_item_byid_binfile, binmap_search_new, binmap_search_destroy, binmap_search_get_item, NULL, binmap_get_attr, binmap_set_attr, };
2647
2648 static int binfile_get_index(struct map_priv *m)
2649 {
2650 //dbg(0,"_enter\n");
2651 int len;
2652 int cde_index_size;
2653 long long offset; // int or long long ?
2654 struct zip_cd *cd;
2655
2656 len = strlen("index");
2657 cde_index_size = sizeof(struct zip_cd) + len;
2658 //dbg(0,"_cde_index_size=%d\n", cde_index_size);
2659 if (m->eoc64)
2660 {
2661 //dbg(0,"_m->eoc64->zip64ecsz=%d\n", m->eoc64->zip64ecsz);
2662 offset = m->eoc64->zip64ecsz - cde_index_size;
2663 //dbg(0,"_eoc64 offset="LONGLONG_FMT"\n", offset);
2664 }
2665 else
2666 {
2667 //dbg(0,"_m->eoc->zipecsz=%d\n", m->eoc->zipecsz);
2668 offset = m->eoc->zipecsz - cde_index_size;
2669 //dbg(0,"_eoc offset="LONGLONG_FMT"\n", offset);
2670 }
2671 cd = binfile_read_cd(m, offset, len);
2672
2673 if (!cd)
2674 {
2675 //dbg(0,"_!cd\n");
2676 cde_index_size += sizeof(struct zip_cd_ext);
2677 //dbg(0,"_cde_index_size=%d\n", cde_index_size);
2678 if (m->eoc64)
2679 {
2680 offset = m->eoc64->zip64ecsz - cde_index_size;
2681 //dbg(0,"_eoc64 offset aa.1="LONGLONG_FMT"\n", offset);
2682 }
2683 else
2684 {
2685 offset = m->eoc->zipecsz - cde_index_size;
2686 //dbg(0,"_offset 22.0="LONGLONG_FMT"\n", offset);
2687 }
2688 cd = binfile_read_cd(m, offset, len + sizeof(struct zip_cd_ext));
2689 }
2690 //dbg(0,"_offset 22="LONGLONG_FMT"\n", offset);
2691
2692 if (cd)
2693 {
2694 //dbg(0,"_cd 001\n");
2695 if (cd->zipcfnl == len && !strncmp(cd->zipcfn, "index", len))
2696 {
2697 m->index_offset = offset;
2698 m->index_cd = cd;
2699 //dbg(0,"_leave:offset 33="LONGLONG_FMT"\n", offset);
2700 return 1;
2701 }
2702 //dbg(0,"_cd 002\n");
2703 }
2704
2705 offset = binfile_search_cd(m, 0, "index", 0, 0);
2706 //dbg(0,"_offset 44="LONGLONG_FMT"\n", offset);
2707
2708 if (offset == -1)
2709 {
2710 //dbg(0,"_leave:55\n");
2711 return 0;
2712 }
2713
2714 cd = binfile_read_cd(m, offset, -1);
2715
2716 if (!cd)
2717 {
2718 //dbg(0,"_leave:66\n");
2719 return 0;
2720 }
2721
2722 m->index_offset = offset;
2723 m->index_cd = cd;
2724
2725 //dbg(0,"_leave:normal:offset 77="LONGLONG_FMT"\n", offset);
2726 return 1;
2727 }
2728
2729 static int map_binfile_zip_setup(struct map_priv *m, char *filename, int mmap)
2730 {
2731 //dbg(0,"_enter\n");
2732
2733 struct zip_cd *first_cd;
2734 int i;
2735 if (!(m->eoc = binfile_read_eoc(m->fi)))
2736 {
2737 //dbg(0,"_leave:1\n");
2738 return 0;
2739 }
2740 dbg_assert(m->eoc->zipedsk == m->eoc->zipecen);
2741 if (m->eoc->zipedsk && strlen(filename) > 3)
2742 {
2743 char *tmpfilename = g_strdup(filename);
2744 char *ext = tmpfilename + strlen(tmpfilename) - 3;
2745
2746 //dbg(0,"_ff-1:%s\n", tmpfilename);
2747 //dbg(0,"_ff-2:%s\n", ext);
2748
2749 m->fis=g_new(struct file *,m->eoc->zipedsk);
2750 for (i = 0; i < m->eoc->zipedsk - 1; i++)
2751 {
2752 sprintf(ext, "b%02d", i + 1);
2753 //dbg(0,"_ff--3:%s\n", ext);
2754 m->fis[i] = file_create(tmpfilename, 0);
2755 if (mmap)
2756 {
2757 //dbg(0,"_want mmap 2 %s\n", m->fis[i]->name);
2758 file_mmap(m->fis[i]);
2759 }
2760 }
2761 m->fis[m->eoc->zipedsk - 1] = m->fi;
2762 g_free(tmpfilename);
2763 }
2764 else
2765 {
2766 //dbg(0,"_ff-XX\n");
2767 }
2768 //dbg(0, "_num_disk %d\n", m->eoc->zipedsk);
2769 m->eoc64 = binfile_read_eoc64(m->fi);
2770
2771 if (!binfile_get_index(m))
2772 {
2773 //dbg(0,"_leave:2\n");
2774 return 0;
2775 }
2776
2777 if (!(first_cd = binfile_read_cd(m, 0, 0)))
2778 {
2779 //dbg(0,"_leave:3\n");
2780 return 0;
2781 }
2782
2783 m->cde_size = sizeof(struct zip_cd) + first_cd->zipcfnl + first_cd->zipcxtl;
2784 m->zip_members = m->index_offset / m->cde_size + 1;
2785 //dbg(0, "_cde_size %d\n", m->cde_size);
2786 //dbg(0, "_members %d\n", m->zip_members);
2787 file_data_free(m->fi, (unsigned char *) first_cd);
2788 if (mmap)
2789 {
2790 //dbg(0,"_want mmap 3 %s\n", m->fi->name);
2791 file_mmap(m->fi);
2792 }
2793 return 1;
2794 }
2795
2796 #if 0
2797 static int
2798 map_binfile_download_initial(struct map_priv *m)
2799 {
2800 struct attr readwrite=
2801 { attr_readwrite,
2802 { (void *)1}};
2803 struct attr create=
2804 { attr_create,
2805 { (void *)1}};
2806 struct attr *attrs[4];
2807 struct file *out;
2808 long long woffset=0,planet_size;
2809 int size_ret;
2810 int cd1size,cdisize;
2811 long long cd1offset,cdioffset;
2812 struct zip64_eoc *zip64_eoc;
2813 struct zip64_eocl *zip64_eocl;
2814 struct zip_eoc *zip_eoc;
2815 struct zip_cd *cd1,*cdn,*cdi;
2816 int count,chunk,cdoffset=0;
2817 int mode=1;
2818 struct map_download *download=g_new0(struct map_download, 1);
2819
2820 attrs[0]=&readwrite;
2821 attrs[1]=&create;
2822 attrs[2]=NULL;
2823 download->file=file_create(m->filename,attrs);
2824 download->m=m;
2825 download_planet_size(download);
2826 download_eoc(download);
2827 download_directory_start(download);
2828 while (download_directory_do(download));
2829 download_directory_finish(download);
2830 download_initial_finish(download);
2831 m->fi=download->file;
2832 g_free(download);
2833 return 1;
2834
2835 cd1size=sizeof(*cd1);
2836 cd1offset=zip64_eoc->zip64eofst;
2837 cd1=(struct zip_cd *)map_binfile_download_range(m, cd1offset, cd1size);
2838 if (!cd1)
2839 return 0;
2840 cd1size=sizeof(*cd1)+binfile_cd_extra(cd1);
2841 g_free(cd1);
2842 cd1=(struct zip_cd *)map_binfile_download_range(m, cd1offset, cd1size);
2843 if (!cd1)
2844 return 0;
2845 cd1->zipcunc=0;
2846 cdisize=sizeof(*cdi)+strlen("index")+cd1->zipcxtl;
2847 cdioffset=zip64_eoc->zip64eofst+zip64_eoc->zip64ecsz-cdisize;
2848 cdi=(struct zip_cd *)map_binfile_download_range(m, cdioffset, cdisize);
2849 if (!cdi)
2850 {
2851 g_free(cd1);
2852 return 0;
2853 }
2854 cdi->zipcunc=0;
2855 cdn=g_malloc0(cd1size*256);
2856
2857 file_data_write(out, woffset, sizeof(*zip64_eoc), (unsigned char *)zip64_eoc);
2858 woffset+=sizeof(*zip64_eoc);
2859 cdoffset=woffset;
2860
2861 file_data_write(out, woffset, cd1size, (unsigned char *)cd1);
2862 woffset+=cd1size;
2863 count=(cdioffset-cd1offset)/cd1size-1;
2864 while (count > 0)
2865 {
2866 if (count > 256)
2867 chunk=256;
2868 else
2869 chunk=count;
2870 file_data_write(out, woffset, cd1size*chunk, (unsigned char *)cdn);
2871 woffset+=cd1size*chunk;
2872 count-=chunk;
2873 }
2874 g_free(cdn);
2875 g_free(cd1);
2876 file_data_write(out, woffset, cdisize, (unsigned char *)cdi);
2877 woffset+=cdisize;
2878
2879 }
2880 #endif
2881
2882
2883 static int string_endswith(const char* ending, const char* instring)
2884 {
2885 int l1;
2886 int l2;
2887
2888 if (!ending)
2889 {
2890 return 0;
2891 }
2892
2893 if (!instring)
2894 {
2895 return 0;
2896 }
2897
2898 l1 = strlen(ending);
2899 l2 = strlen(instring);
2900
2901 if (l1 < 1)
2902 {
2903 return 0;
2904 }
2905
2906 if (l1 > l2)
2907 {
2908 return 0;
2909 }
2910
2911 int ret = strcmp(ending, instring + (l2 - l1));
2912 //dbg(0, "ending=%s in=%s ret=%d\n", ending, instring + (l2 - l1), (ret == 0));
2913 return (ret == 0);
2914 }
2915
2916
2917 static int map_binfile_open(struct map_priv *m)
2918 {
2919 int *magic;
2920 int version_exception = 0;
2921 struct map_rect_priv *mr;
2922 struct item *item;
2923 struct attr attr;
2924
2925 struct attr readwrite =
2926 { attr_readwrite,
2927 { (void *) 1 } };
2928
2929 struct attr *attrs[] =
2930 { &readwrite, NULL };
2931
2932 // dbg(0, "file_create %s\n", m->filename);
2933 m->fi = file_create(m->filename, m->url ? attrs : NULL);
2934 if (!m->fi && m->url)
2935 {
2936 return 0;
2937 }
2938
2939 if (!m->fi)
2940 {
2941 // dbg(0, "Failed to load '%s'\n", m->filename);
2942 return 0;
2943 }
2944
2945 if (m->check_version)
2946 {
2947 m->version = file_version(m->fi, m->check_version);
2948 }
2949
2950 magic = (int *) file_data_read(m->fi, 0, 4);
2951 if (!magic)
2952 {
2953 file_destroy(m->fi);
2954 m->fi = NULL;
2955 return 0;
2956 }
2957
2958 //dbg(0,"_zip_lfh_sig=%d\n", zip_lfh_sig);
2959
2960 //dbg(0,"_magic1=%d\n", magic[0]);
2961 //dbg(0,"_magic1=%d\n", magic[1]);
2962 //dbg(0,"_magic1=%d\n", magic[2]);
2963 //dbg(0,"_magic1=%d\n", magic[3]);
2964 *magic = le32_to_cpu(*magic);
2965 //dbg(0,"_magic2=%d\n", magic[0]);
2966 //dbg(0,"_magic2=%d\n", magic[1]);
2967 //dbg(0,"_magic2=%d\n", magic[2]);
2968 //dbg(0,"_magic2=%d\n", magic[3]);
2969 if (*magic == zip_lfh_sig || *magic == zip_split_sig || *magic == zip_cd_sig || *magic == zip64_eoc_sig)
2970 {
2971 if (!map_binfile_zip_setup(m, m->filename, m->flags & 1))
2972 {
2973 dbg(0, "invalid file format for '%s'\n", m->filename);
2974 file_destroy(m->fi);
2975 m->fi = NULL;
2976 return 0;
2977 }
2978 }
2979 else
2980 {
2981 //dbg(0,"_want mmap %s\n", m->fi->name);
2982 file_mmap(m->fi);
2983 }
2984
2985 //dbg(0,"_cont\n");
2986
2987 file_data_free(m->fi, (unsigned char *) magic);
2988 m->cachedir = g_strdup("/tmp/navit");
2989 m->map_version = 0;
2990
2991 mr = map_rect_new_binfile(m, NULL);
2992 if (mr)
2993 {
2994 while ((item = map_rect_get_item_binfile(mr)) == &busy_item)
2995 {
2996 ;
2997 }
2998
2999 if (item && item->type == type_map_information)
3000 {
3001 if (binfile_attr_get(item->priv_data, attr_version, &attr))
3002 {
3003 m->map_version = attr.u.num;
3004 dbg(0, "map version=%d\n", m->map_version);
3005 }
3006
3007 if (binfile_attr_get(item->priv_data, attr_map_release, &attr))
3008 {
3009 m->map_release = g_strdup(attr.u.str);
3010 dbg(0, "maptool version used=%s\n", m->map_release);
3011 }
3012
3013 if (string_endswith("borders.bin", m->filename) == 1)
3014 {
3015 dbg(0, "map exception added!\n");
3016 version_exception = 1;
3017 }
3018
3019 if (string_endswith("coastline.bin", m->filename) == 1)
3020 {
3021 dbg(0, "map exception added!\n");
3022 version_exception = 1;
3023 }
3024
3025 //if (m->url && binfile_attr_get(item->priv_data, attr_url, &attr))
3026 //{
3027 // dbg(0, "url config %s map %s\n", m->url, attr.u.str);
3028 // if (strcmp(m->url, attr.u.str))
3029 // {
3030 // m->update_available = 1;
3031 // }
3032 // g_free(m->url);
3033 // m->url = g_strdup(attr.u.str);
3034 //}
3035 }
3036
3037 map_rect_destroy_binfile(mr);
3038
3039 if (version_exception == 0)
3040 {
3041 if (m->map_version < (int)NEED_MIN_BINFILE_MAPVERSION)
3042 {
3043 dbg(0, "!!**Warning**!!: This map is too old for your version of ZANavi. You need at least a version %d map\n", (int)NEED_MIN_BINFILE_MAPVERSION);
3044
3045 #ifdef HAVE_API_ANDROID
3046 gchar* xy=g_strdup_printf("%d:%d:%s\n", (int)m->map_version, (int)NEED_MIN_BINFILE_MAPVERSION, m->filename);
3047 android_send_generic_text(31,xy);
3048 g_free(xy);
3049 #endif
3050 return 0;
3051 }
3052 }
3053 }
3054 return 1;
3055 }
3056
3057 static void map_binfile_close(struct map_priv *m)
3058 {
3059 int i;
3060 file_data_free(m->fi, (unsigned char *) m->index_cd);
3061 file_data_free(m->fi, (unsigned char *) m->eoc);
3062 file_data_free(m->fi, (unsigned char *) m->eoc64);
3063 g_free(m->cachedir);
3064 g_free(m->map_release);
3065
3066 if (m->fis)
3067 {
3068 for (i = 0; i < m->eoc->zipedsk; i++)
3069 {
3070 file_destroy(m->fis[i]);
3071 }
3072 }
3073 else
3074 {
3075 file_destroy(m->fi);
3076 }
3077 }
3078
3079 static void map_binfile_destroy(struct map_priv *m)
3080 {
3081 g_free(m->filename);
3082 g_free(m->url);
3083 g_free(m->progress);
3084 g_free(m);
3085 }
3086
3087 static void binfile_check_version(struct map_priv *m)
3088 {
3089 int version = -1;
3090
3091 if (!m->check_version)
3092 {
3093 return;
3094 }
3095
3096 if (m->fi)
3097 {
3098 version = file_version(m->fi, m->check_version);
3099 }
3100
3101 if (version != m->version)
3102 {
3103 if (m->fi)
3104 {
3105 map_binfile_close(m);
3106 }
3107 map_binfile_open(m);
3108 }
3109 }
3110
3111 struct map_priv *
3112 map_new_binfile(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
3113 {
3114 struct map_priv *m;
3115 struct attr *data = attr_search(attrs, NULL, attr_data);
3116 struct attr *check_version, *map_pass, *flags, *url, *download_enabled;
3117 struct file_wordexp *wexp;
3118 char **wexp_data;
3119
3120 if (!data)
3121 {
3122 return NULL;
3123 }
3124
3125 // wexp = file_wordexp_new(data->u.str);
3126 // wexp_data = file_wordexp_get_array(wexp);
3127 // dbg(0, "map_new_binfile %s\n", data->u.str);
3128 *meth = map_methods_binfile;
3129
3130 m=g_new0(struct map_priv, 1);
3131 m->cbl = cbl;
3132 m->id = ++map_id;
3133 m->filename = g_strdup(data->u.str);
3134 // file_wordexp_destroy(wexp);
3135 check_version = attr_search(attrs, NULL, attr_check_version);
3136
3137 if (check_version)
3138 {
3139 m->check_version = check_version->u.num;
3140 }
3141
3142 map_pass = attr_search(attrs, NULL, attr_map_pass);
3143
3144 if (map_pass)
3145 {
3146 m->passwd = g_strdup(map_pass->u.str);
3147 }
3148
3149 flags = attr_search(attrs, NULL, attr_flags);
3150
3151 if (flags)
3152 {
3153 m->flags = flags->u.num;
3154 }
3155
3156 url = attr_search(attrs, NULL, attr_url);
3157
3158 if (url)
3159 {
3160 m->url = g_strdup(url->u.str);
3161 }
3162
3163 download_enabled = attr_search(attrs, NULL, attr_update);
3164
3165 if (download_enabled)
3166 {
3167 m->download_enabled = download_enabled->u.num;
3168 }
3169
3170 if (!map_binfile_open(m) && !m->check_version && !m->url)
3171 {
3172 map_binfile_destroy(m);
3173 m = NULL;
3174 }
3175 else
3176 {
3177 load_changes(m);
3178 }
3179 return m;
3180 }
3181
3182 #ifdef PLUGSSS
3183 void plugin_init(void)
3184 {
3185 // dbg(1, "binfile: plugin_init\n");
3186 if (sizeof(struct zip_cd) != 46)
3187 {
3188 // dbg(0, "error: sizeof(struct zip_cd)=%d\n", sizeof(struct zip_cd));
3189 }
3190 plugin_register_map_type("binfile", map_new_binfile);
3191 }
3192 #endif
3193

   
Visit the ZANavi Wiki