/[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 30 - (show annotations) (download)
Wed Aug 22 17:01:27 2012 UTC (11 years, 8 months ago) by zoff99
File MIME type: text/plain
File size: 75237 byte(s)
ZANavi 2.0, lots of changes, everything in its own thread, more performance
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 struct map_rect_priv *mr = priv_data;
561 struct tile *t = mr->t;
562 enum attr_type type;
563 int i, size;
564
565 if (attr_type != mr->attr_last)
566 {
567 t->pos_attr = t->pos_attr_start;
568 mr->attr_last = attr_type;
569 }
570 while (t->pos_attr < t->pos_next)
571 {
572 size = le32_to_cpu(*(t->pos_attr++));
573 type = le32_to_cpu(t->pos_attr[0]);
574 if (type == attr_label)
575 mr->label = 1;
576 if (type == attr_house_number)
577 mr->label_attr[0] = t->pos_attr;
578 if (type == attr_street_name)
579 mr->label_attr[1] = t->pos_attr;
580 if (type == attr_street_name_systematic)
581 mr->label_attr[2] = t->pos_attr;
582 if (type == attr_district_name && mr->item.type < type_line)
583 mr->label_attr[3] = t->pos_attr;
584 if (type == attr_town_name && mr->item.type < type_line)
585 mr->label_attr[4] = t->pos_attr;
586 if (type == attr_type || attr_type == attr_any)
587 {
588 if (attr_type == attr_any)
589 {
590 // dbg(1, "pos %p attr %s size %d\n", t->pos_attr - 1, attr_to_name(type), size);
591 }
592 attr->type = type;
593 if (ATTR_IS_GROUP(type))
594 {
595 int i = 0;
596 int *subpos = t->pos_attr + 1;
597 int size_rem = size - 1;
598 i = 0;
599 while (size_rem > 0 && i < 7)
600 {
601 int subsize = le32_to_cpu(*subpos++);
602 int subtype = le32_to_cpu(subpos[0]);
603 mr->attrs[i].type = subtype;
604 attr_data_set_le(&mr->attrs[i], subpos + 1);
605 subpos += subsize;
606 size_rem -= subsize + 1;
607 i++;
608 }
609 mr->attrs[i].type = type_none;
610 mr->attrs[i].u.data = NULL;
611 attr->u.attrs = mr->attrs;
612 }
613 else
614 {
615 attr_data_set_le(attr, t->pos_attr + 1);
616 if (type == attr_url_local)
617 {
618 g_free(mr->url);
619 mr->url = binfile_extract(mr->m, mr->m->cachedir, attr->u.str, 1);
620 attr->u.str = mr->url;
621 }
622 if (type == attr_flags && mr->m->map_version < 1)
623 attr->u.num |= AF_CAR;
624 }
625 t->pos_attr += size;
626 return 1;
627 }
628 else
629 {
630 t->pos_attr += size;
631 }
632 }
633 if (!mr->label && (attr_type == attr_any || attr_type == attr_label))
634 {
635 for (i = 0; i < sizeof(mr->label_attr) / sizeof(int *); i++)
636 {
637 if (mr->label_attr[i])
638 {
639 mr->label = 1;
640 attr->type = attr_label;
641 attr_data_set_le(attr, mr->label_attr[i] + 1);
642 return 1;
643 }
644 }
645 }
646 return 0;
647 }
648
649 struct binfile_hash_entry
650 {
651 struct item_id id;
652 int flags;
653 int data[0];
654 };
655
656 static guint binfile_hash_entry_hash(gconstpointer key)
657 {
658 const struct binfile_hash_entry *entry = key;
659 return (entry->id.id_hi ^ entry->id.id_lo);
660 }
661
662 static gboolean binfile_hash_entry_equal(gconstpointer a, gconstpointer b)
663 {
664 const struct binfile_hash_entry *entry1 = a, *entry2 = b;
665 return (entry1->id.id_hi == entry2->id.id_hi && entry1->id.id_lo == entry2->id.id_lo);
666 }
667
668 static int *
669 binfile_item_dup(struct map_priv *m, struct item *item, struct tile *t, int extend)
670 {
671 int size = le32_to_cpu(t->pos[0]);
672 struct binfile_hash_entry *entry = g_malloc(sizeof(struct binfile_hash_entry) + (size + 1 + extend) * sizeof(int));
673 void *ret = entry->data;
674 entry->id.id_hi = item->id_hi;
675 entry->id.id_lo = item->id_lo;
676 entry->flags = 1;
677 // dbg(0, "id 0x%x,0x%x\n", entry->id.id_hi, entry->id.id_lo);
678
679 memcpy(ret, t->pos, (size + 1) * sizeof(int));
680 if (!m->changes)
681 m->changes = g_hash_table_new_full(binfile_hash_entry_hash, binfile_hash_entry_equal, g_free, NULL);
682 g_hash_table_replace(m->changes, entry, entry);
683 // dbg(0, "ret %p\n", ret);
684 return ret;
685 }
686
687 static int binfile_coord_set(void *priv_data, struct coord *c, int count, enum change_mode mode)
688 {
689 struct map_rect_priv *mr = priv_data;
690 struct tile *t = mr->t, *tn, new;
691 int i, delta, move_len;
692 int write_offset, move_offset, aoffset, coffset, clen;
693 int *data;
694
695 //{
696 //int *i = t->pos, j = 0;
697 // dbg(0, "Before: pos_coord=%d\n", t->pos_coord - i);
698 //while (i < t->pos_next)
699 //{
700 // // dbg(0, "%d:0x%x\n", j++, *i++);
701 //}
702
703 //}
704
705 aoffset = t->pos_attr - t->pos_attr_start;
706 coffset = t->pos_coord - t->pos_coord_start - 2;
707 clen = t->pos_attr_start - t->pos_coord + 2;
708 // dbg(0, "coffset=%d clen=%d\n", coffset, clen);
709 switch (mode)
710 {
711 case change_mode_delete:
712 if (count * 2 > clen)
713 count = clen / 2;
714 delta = -count * 2;
715 move_offset = coffset + count * 2;
716 move_len = t->pos_next - t->pos_coord_start - move_offset;
717 write_offset = 0;
718 break;
719 case change_mode_modify:
720 write_offset = coffset;
721 if (count * 2 > clen)
722 {
723 delta = count * 2 - clen;
724 move_offset = t->pos_attr_start - t->pos_coord_start;
725 move_len = t->pos_next - t->pos_coord_start - move_offset;
726 }
727 else
728 {
729 move_len = 0;
730 move_offset = 0;
731 delta = 0;
732 }
733 break;
734 case change_mode_prepend:
735 delta = count * 2;
736 move_offset = coffset - 2;
737 move_len = t->pos_next - t->pos_coord_start - move_offset;
738 write_offset = coffset - 2;
739 break;
740 case change_mode_append:
741 delta = count * 2;
742 move_offset = coffset;
743 move_len = t->pos_next - t->pos_coord_start - move_offset;
744 write_offset = coffset;
745 break;
746 default:
747 return 0;
748 }
749 // dbg(0, "delta %d\n", delta);
750 data = binfile_item_dup(mr->m, &mr->item, t, delta > 0 ? delta : 0);
751 data[0] = cpu_to_le32(le32_to_cpu(data[0]) + delta);
752 data[2] = cpu_to_le32(le32_to_cpu(data[2]) + delta);
753 new.pos = new.start = data;
754 new.zipfile_num = t->zipfile_num;
755 new.mode = 2;
756 push_tile(mr, &new, 0, 0);
757 setup_pos(mr);
758 tn = mr->t;
759 tn->pos_coord = tn->pos_coord_start + coffset;
760 tn->pos_attr = tn->pos_attr_start + aoffset;
761 // 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);
762 memmove(tn->pos_coord_start + move_offset + delta, tn->pos_coord_start + move_offset, move_len * 4);
763 //{
764 //int *i = tn->pos, j = 0;
765 // dbg(0, "After move: pos_coord=%d\n", tn->pos_coord - i);
766 //while (i < tn->pos_next)
767 //{
768 // // dbg(0, "%d:0x%x\n", j++, *i++);
769 //}
770 //}
771 if (mode != change_mode_append)
772 {
773 tn->pos_coord += move_offset;
774 }
775 if (mode != change_mode_delete)
776 {
777 // dbg(0, "writing %d ints at offset %d\n", count * 2, write_offset + tn->pos_coord_start - data);
778 for (i = 0; i < count; i++)
779 {
780 tn->pos_coord_start[write_offset++] = c[i].x;
781 tn->pos_coord_start[write_offset++] = c[i].y;
782 }
783
784 }
785 //{
786 //int *i = tn->pos, j = 0;
787 //// dbg(0, "After: pos_coord=%d\n", tn->pos_coord - i);
788 //while (i < tn->pos_next)
789 //{
790 // // dbg(0, "%d:0x%x\n", j++, *i++);
791 //}
792 //}
793 return 1;
794 }
795
796 static int binfile_attr_set(void *priv_data, struct attr *attr, enum change_mode mode)
797 {
798 struct map_rect_priv *mr = priv_data;
799 struct tile *t = mr->t, *tn, new;
800 int extend, offset, delta, move_len;
801 int write_offset, move_offset, naoffset, coffset, oattr_len;
802 int nattr_size, nattr_len, pad;
803 int *data;
804
805 //{
806 //int *i = t->pos, j = 0;
807 //// dbg(0, "Before: pos_attr=%d\n", t->pos_attr - i);
808 //while (i < t->pos_next)
809 //{
810 // // dbg(0, "%d:0x%x\n", j++, *i++);
811 //}
812 //}
813
814 write_offset = 0;
815 naoffset = t->pos_attr - t->pos_attr_start;
816 coffset = t->pos_coord - t->pos_coord_start;
817 offset = 0;
818 oattr_len = 0;
819 if (!naoffset)
820 {
821 if (mode == change_mode_delete || mode == change_mode_modify)
822 {
823 // dbg(0, "no attribute selected\n");
824 return 0;
825 }
826 if (mode == change_mode_append)
827 {
828 naoffset = t->pos_next - t->pos_attr_start;
829 }
830 }
831 while (offset < naoffset)
832 {
833 oattr_len = le32_to_cpu(t->pos_attr_start[offset]) + 1;
834 // dbg(0, "len %d\n", oattr_len);
835 write_offset = offset;
836 offset += oattr_len;
837 }
838 move_len = t->pos_next - t->pos_attr_start - offset;
839 move_offset = offset;
840 switch (mode)
841 {
842 case change_mode_delete:
843 nattr_size = 0;
844 nattr_len = 0;
845 pad = 0;
846 extend = 0;
847 break;
848 case change_mode_modify:
849 case change_mode_prepend:
850 case change_mode_append:
851 nattr_size = attr_data_size(attr);
852 pad = (4 - (nattr_size % 4)) % 4;
853 nattr_len = (nattr_size + pad) / 4 + 2;
854 if (mode == change_mode_prepend)
855 {
856 move_offset = write_offset;
857 move_len += oattr_len;
858 }
859 if (mode == change_mode_append)
860 {
861 write_offset = move_offset;
862 }
863 break;
864 default:
865 return 0;
866 }
867 if (mode == change_mode_delete || mode == change_mode_modify)
868 {
869 delta = nattr_len - oattr_len;
870 }
871 else
872 {
873 delta = nattr_len;
874 }
875 // dbg(0, "delta %d oattr_len %d nattr_len %d\n", delta, oattr_len, nattr_len);
876 data = binfile_item_dup(mr->m, &mr->item, t, delta > 0 ? delta : 0);
877 data[0] = cpu_to_le32(le32_to_cpu(data[0]) + delta);
878 new.pos = new.start = data;
879 new.zipfile_num = t->zipfile_num;
880 new.mode = 2;
881 push_tile(mr, &new, 0, 0);
882 setup_pos(mr);
883 tn = mr->t;
884 tn->pos_coord = tn->pos_coord_start + coffset;
885 tn->pos_attr = tn->pos_attr_start + offset;
886 // dbg(0, "attr start %d offset %d\n", tn->pos_attr_start - data, offset);
887 // 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);
888 memmove(tn->pos_attr_start + move_offset + delta, tn->pos_attr_start + move_offset, move_len * 4);
889 if (mode != change_mode_append)
890 tn->pos_attr += delta;
891 {
892 int *i = tn->pos, j = 0;
893 // dbg(0, "After move: pos_attr=%d\n", tn->pos_attr - i);
894 while (i < tn->pos_next)
895 {
896 // dbg(0, "%d:0x%x\n", j++, *i++);
897 }
898 }
899
900 if (nattr_len)
901 {
902 int *nattr = tn->pos_attr_start + write_offset;
903 // dbg(0, "writing %d ints at %d\n", nattr_len, nattr - data);
904 nattr[0] = cpu_to_le32(nattr_len - 1);
905 nattr[1] = cpu_to_le32(attr->type);
906 memcpy(nattr + 2, attr_data_get(attr), nattr_size);
907 memset((unsigned char *) (nattr + 2) + nattr_size, 0, pad);
908 }
909
910 //{
911 //int *i = tn->pos, j = 0;
912 //// dbg(0, "After: pos_attr=%d\n", tn->pos_attr - i);
913 //while (i < tn->pos_next)
914 //{
915 // // dbg(0, "%d:0x%x\n", j++, *i++);
916 //}
917 //}
918 return 1;
919 }
920
921 static struct item_methods methods_binfile =
922 { binfile_coord_rewind, binfile_coord_get, binfile_attr_rewind, binfile_attr_get, NULL, binfile_attr_set, binfile_coord_set, };
923
924 static void push_tile(struct map_rect_priv *mr, struct tile *t, int offset, int length)
925 {
926 dbg_assert(mr->tile_depth < 8);
927 mr->t = &mr->tiles[mr->tile_depth++];
928 *(mr->t) = *t;
929 mr->t->pos = mr->t->pos_next = mr->t->start + offset;
930 if (length == -1)
931 length = le32_to_cpu(mr->t->pos[0]) + 1;
932 if (length > 0)
933 mr->t->end = mr->t->pos + length;
934 }
935
936 static int pop_tile(struct map_rect_priv *mr)
937 {
938 if (mr->tile_depth <= 1)
939 return 0;
940 if (mr->t->mode < 2)
941 file_data_free(mr->m->fi, (unsigned char *) (mr->t->start));
942 #ifdef DEBUG_SIZE
943 #if DEBUG_SIZE > 0
944 // dbg(0,"leave %d\n",mr->t->zipfile_num);
945 #endif
946 #endif
947 mr->t = &mr->tiles[--mr->tile_depth - 1];
948 return 1;
949 }
950
951 static int zipfile_to_tile(struct map_priv *m, struct zip_cd *cd, struct tile *t)
952 {
953 char buffer[1024];
954 struct zip_lfh *lfh;
955 char *zipfn;
956 struct file *fi;
957 // dbg(1, "enter %p %p %p\n", m, cd, t);
958 // dbg(1, "cd->zipofst=0x%Lx\n", binfile_cd_offset(cd));
959 t->start = NULL;
960 t->mode = 1;
961 if (m->fis)
962 fi = m->fis[cd->zipdsk];
963 else
964 fi = m->fi;
965 lfh = binfile_read_lfh(fi, binfile_cd_offset(cd));
966 zipfn = (char *) (file_data_read(fi, binfile_cd_offset(cd) + sizeof(struct zip_lfh), lfh->zipfnln));
967 strncpy(buffer, zipfn, lfh->zipfnln);
968 buffer[lfh->zipfnln] = '\0';
969 t->start = (int *) binfile_read_content(m, fi, binfile_cd_offset(cd), lfh);
970 t->end = t->start + lfh->zipuncmp / 4;
971 t->fi = fi;
972 // dbg(1, "0x%x '%s' %d %d,%d\n", lfh->ziplocsig, buffer, sizeof(*cd) + cd->zipcfnl, lfh->zipsize, lfh->zipuncmp);
973 file_data_free(fi, (unsigned char *) zipfn);
974 file_data_free(fi, (unsigned char *) lfh);
975 return t->start != NULL;
976 }
977
978 static int map_binfile_handle_redirect(struct map_priv *m)
979 {
980 char *location = file_http_header(m->http, "location");
981 if (!location)
982 {
983 m->redirect = 0;
984 return 0;
985 }
986 if (m->redirect)
987 return 0;
988 m->redirect = 1;
989 // dbg(0, "redirected from %s to %s\n", m->url, location);
990 g_free(m->url);
991 m->url = g_strdup(location);
992 file_destroy(m->http);
993 m->http = NULL;
994
995 return 1;
996 }
997
998 static int map_binfile_http_request(struct map_priv *m, struct attr **attrs)
999 {
1000 if (!m->http)
1001 {
1002 m->http = file_create(NULL, attrs);
1003 }
1004 else
1005 {
1006 file_request(m->http, attrs);
1007 }
1008 return 1;
1009 }
1010
1011 static long long map_binfile_download_size(struct map_priv *m)
1012 {
1013 struct attr url =
1014 { attr_url };
1015 struct attr http_method =
1016 { attr_http_method };
1017 struct attr persistent =
1018 { attr_persistent };
1019 struct attr *attrs[4];
1020 int size_ret;
1021 long long ret;
1022 void *data;
1023
1024 do
1025 {
1026 attrs[0] = &url;
1027 url.u.str = m->url;
1028 attrs[1] = &http_method;
1029 http_method.u.str = "HEAD";
1030 persistent.u.num = 1;
1031 attrs[2] = &persistent;
1032 attrs[3] = NULL;
1033
1034 map_binfile_http_request(m, attrs);
1035 data = file_data_read_special(m->http, 0, &size_ret);
1036 g_free(data);
1037 if (size_ret < 0)
1038 return 0;
1039 }
1040 while (map_binfile_handle_redirect(m));
1041
1042 ret = file_size(m->http);
1043 // dbg(1,"file size "LONGLONG_FMT"\n",ret);
1044 return ret;
1045 }
1046
1047 static int map_binfile_http_close(struct map_priv *m)
1048 {
1049 if (m->http)
1050 {
1051 file_destroy(m->http);
1052 m->http = NULL;
1053 }
1054 return 1;
1055 }
1056
1057 static struct file *
1058 map_binfile_http_range(struct map_priv *m, long long offset, int size)
1059 {
1060 struct attr *attrs[4];
1061 struct attr url =
1062 { attr_url };
1063 struct attr http_header =
1064 { attr_http_header };
1065 struct attr persistent =
1066 { attr_persistent };
1067
1068 persistent.u.num = 1;
1069 attrs[0] = &url;
1070 attrs[1] = &http_header;
1071 attrs[2] = &persistent;
1072 attrs[3] = NULL;
1073
1074 url.u.str = m->url;
1075 http_header.u.str=g_strdup_printf("Range: bytes="LONGLONG_FMT"-"LONGLONG_FMT,offset, offset+size-1);
1076 map_binfile_http_request(m, attrs);
1077 g_free(http_header.u.str);
1078 return m->http;
1079 }
1080
1081 static unsigned char *
1082 map_binfile_download_range(struct map_priv *m, long long offset, int size)
1083 {
1084 unsigned char *ret;
1085 int size_ret;
1086 struct file *http = map_binfile_http_range(m, offset, size);
1087
1088 ret = file_data_read_special(http, size, &size_ret);
1089 if (size_ret != size)
1090 {
1091 // dbg(0, "size %d vs %d\n", size, size_ret);
1092 g_free(ret);
1093 return NULL;
1094 }
1095 return ret;
1096 }
1097
1098 static struct zip_cd *
1099 download_cd(struct map_download *download)
1100 {
1101 struct map_priv *m = download->m;
1102 struct zip64_eoc *zip64_eoc = (struct zip64_eoc *) file_data_read(m->fi, 0, sizeof(*zip64_eoc));
1103 struct zip_cd *cd = (struct zip_cd *) map_binfile_download_range(m, zip64_eoc->zip64eofst + download->zipfile * m->cde_size, m->cde_size);
1104 file_data_free(m->fi, (unsigned char *) zip64_eoc);
1105 // dbg(0, "needed cd, result %p\n", cd);
1106 return cd;
1107 }
1108
1109 static int download_request(struct map_download *download)
1110 {
1111 struct attr url =
1112 { attr_url };
1113 struct attr http_header =
1114 { attr_http_header };
1115 struct attr persistent =
1116 { attr_persistent };
1117 struct attr *attrs[4];
1118
1119 if (!download->m->download_enabled)
1120 {
1121 // dbg(0, "Tried downloading while it's not allowed\n");
1122 return 0;
1123 }
1124 attrs[0] = &url;
1125 persistent.u.num = 1;
1126 attrs[1] = &persistent;
1127 attrs[2] = NULL;
1128 if (strchr(download->m->url, '?'))
1129 {
1130 url.u.str = g_strdup_printf("%smemberid=%d", download->m->url, download->zipfile);
1131 download->dl_size = -1;
1132 }
1133 else
1134 {
1135 long long offset = binfile_cd_offset(download->cd_copy);
1136 int size = download->cd_copy->zipcsiz + sizeof(struct zip_lfh) + download->cd_copy->zipcfnl;
1137 url.u.str = g_strdup(download->m->url);
1138 http_header.u.str=g_strdup_printf("Range: bytes="LONGLONG_FMT"-"LONGLONG_FMT,offset,offset+size-1);
1139 attrs[2] = &http_header;
1140 attrs[3] = NULL;
1141 download->dl_size = size;
1142 }
1143 // 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);
1144 map_binfile_http_request(download->m, attrs);
1145 g_free(url.u.str);
1146 download->http = download->m->http;
1147 return 1;
1148 }
1149
1150 static int download_start(struct map_download *download)
1151 {
1152 long long offset;
1153 struct zip_eoc *eoc;
1154
1155 if (!download->cd->zipcensig)
1156 {
1157 download->cd_copy = download_cd(download);
1158 }
1159 else
1160 {
1161 download->cd_copy = g_malloc(download->m->cde_size);
1162 memcpy(download->cd_copy, download->cd, download->m->cde_size);
1163 }
1164 file_data_remove(download->file, (unsigned char *) download->cd);
1165 download->cd = NULL;
1166 offset = file_size(download->file);
1167 offset -= sizeof(struct zip_eoc);
1168 eoc = (struct zip_eoc *) file_data_read(download->file, offset, sizeof(struct zip_eoc));
1169 download->zip_eoc = g_malloc(sizeof(struct zip_eoc));
1170 memcpy(download->zip_eoc, eoc, sizeof(struct zip_eoc));
1171 file_data_remove(download->file, (unsigned char *) eoc);
1172 download->start_offset = download->offset = offset;
1173 return download_request(download);
1174 }
1175
1176 static int download_download(struct map_download *download)
1177 {
1178 int size = 64 * 1024, size_ret;
1179 unsigned char *data;
1180 if (download->dl_size != -1 && size > download->dl_size)
1181 size = download->dl_size;
1182 if (!size)
1183 return 1;
1184 data = file_data_read_special(download->http, size, &size_ret);
1185 if (!download->read && download->m->http && map_binfile_handle_redirect(download->m))
1186 {
1187 g_free(data);
1188 download_request(download);
1189 return 0;
1190 }
1191
1192 // dbg(1,"got %d bytes writing at offset "LONGLONG_FMT"\n",size_ret,download->offset);
1193 if (size_ret <= 0)
1194 {
1195 g_free(data);
1196 return 1;
1197 }
1198 file_data_write(download->file, download->offset, size_ret, data);
1199 download->offset += size_ret;
1200 download->read += size_ret;
1201 download->dl_size -= size_ret;
1202 if (download->dl_size != -1)
1203 download->progress = download->read * 100 / (download->read + download->dl_size);
1204 return 0;
1205 }
1206
1207 static int download_finish(struct map_download *download)
1208 {
1209 struct zip_lfh *lfh;
1210 char *lfh_filename;
1211 struct zip_cd_ext *ext;
1212 long long lfh_offset;
1213 file_data_write(download->file, download->offset, sizeof(struct zip_eoc), (void *) download->zip_eoc);
1214 lfh = (struct zip_lfh *) (file_data_read(download->file, download->start_offset, sizeof(struct zip_lfh)));
1215 ext = binfile_cd_ext(download->cd_copy);
1216 if (ext)
1217 ext->zipofst = download->start_offset;
1218 else
1219 download->cd_copy->zipofst = download->start_offset;
1220 download->cd_copy->zipcsiz = lfh->zipsize;
1221 download->cd_copy->zipcunc = lfh->zipuncmp;
1222 download->cd_copy->zipccrc = lfh->zipcrc;
1223 lfh_offset = binfile_cd_offset(download->cd_copy) + sizeof(struct zip_lfh);
1224 lfh_filename = (char *) file_data_read(download->file, lfh_offset, lfh->zipfnln);
1225 memcpy(download->cd_copy + 1, lfh_filename, lfh->zipfnln);
1226 file_data_remove(download->file, (void *) lfh_filename);
1227 file_data_remove(download->file, (void *) lfh);
1228 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);
1229 file_data_flush(download->file, download->m->eoc->zipeofst + download->zipfile * download->m->cde_size, sizeof(struct zip_cd));
1230
1231 g_free(download->cd_copy);
1232 download->cd = (struct zip_cd *) (file_data_read(download->file, download->m->eoc->zipeofst + download->zipfile * download->m->cde_size, download->m->cde_size));
1233 cd_to_cpu(download->cd);
1234 // dbg(1, "Offset %d\n", download->cd->zipofst);
1235 return 1;
1236 }
1237
1238 static int download_planet_size(struct map_download *download)
1239 {
1240 download->size = map_binfile_download_size(download->m);
1241 // dbg(0,"Planet size "LONGLONG_FMT"\n",download->size);
1242 if (!download->size)
1243 return 0;
1244 return 1;
1245 }
1246
1247 static int download_eoc(struct map_download *download)
1248 {
1249 download->zip64_eoc = (struct zip64_eoc *) map_binfile_download_range(download->m, download->size - 98, 98);
1250 if (!download->zip64_eoc)
1251 return 0;
1252 download->zip64_eocl = (struct zip64_eocl *) (download->zip64_eoc + 1);
1253 download->zip_eoc = (struct zip_eoc *) (download->zip64_eocl + 1);
1254 if (download->zip64_eoc->zip64esig != zip64_eoc_sig || download->zip64_eocl->zip64lsig != zip64_eocl_sig || download->zip_eoc->zipesig != zip_eoc_sig)
1255 {
1256 // dbg(0,"wrong signature on zip64_eoc downloaded from "LONGLONG_FMT"\n",download->size-98);
1257 g_free(download->zip64_eoc);
1258 return 0;
1259 }
1260 return 1;
1261 }
1262
1263 static int download_directory_start(struct map_download *download)
1264 {
1265 download->http = map_binfile_http_range(download->m, download->zip64_eoc->zip64eofst, download->zip64_eoc->zip64ecsz);
1266 if (!download->http)
1267 return 0;
1268 return 1;
1269 }
1270
1271 static int download_directory_do(struct map_download *download)
1272 {
1273 int count;
1274
1275 for (count = 0; count < 100; count++)
1276 {
1277 int cd_xlen, size_ret;
1278 unsigned char *cd_data;
1279 struct zip_cd *cd;
1280 cd = (struct zip_cd *) file_data_read_special(download->http, sizeof(*cd), &size_ret);
1281 cd->zipcunc = 0;
1282 // dbg(1, "size_ret=%d\n", size_ret);
1283 if (!size_ret)
1284 return 0;
1285 if (size_ret != sizeof(*cd) || cd->zipcensig != zip_cd_sig)
1286 {
1287 // dbg(0, "error1 size=%d vs %d\n", size_ret, sizeof(*cd));
1288 return 0;
1289 }
1290 file_data_write(download->file, download->offset, sizeof(*cd), (unsigned char *) cd);
1291 download->offset += sizeof(*cd);
1292 cd_xlen = cd->zipcfnl + cd->zipcxtl;
1293 cd_data = file_data_read_special(download->http, cd_xlen, &size_ret);
1294 if (size_ret != cd_xlen)
1295 {
1296 // dbg(0, "error2 size=%d vs %d\n", size_ret, cd_xlen);
1297 return 0;
1298 }
1299 file_data_write(download->file, download->offset, cd_xlen, cd_data);
1300 download->offset += cd_xlen;
1301 g_free(cd);
1302 g_free(cd_data);
1303 }
1304 return 1;
1305 }
1306
1307 static int download_directory_finish(struct map_download *download)
1308 {
1309 download->http = NULL;
1310 return 1;
1311 }
1312
1313 static int download_initial_finish(struct map_download *download)
1314 {
1315 download->zip64_eoc->zip64eofst = download->cd1offset;
1316 download->zip64_eocl->zip64lofst = download->offset;
1317 download->zip_eoc->zipeofst = download->cd1offset;
1318 #if 0
1319 file_data_write(download->file, download->offset, sizeof(*download->zip64_eoc), (unsigned char *)download->zip64_eoc);
1320 download->offset+=sizeof(*download->zip64_eoc);
1321 file_data_write(download->file, download->offset, sizeof(*download->zip64_eocl), (unsigned char *)download->zip64_eocl);
1322 download->offset+=sizeof(*download->zip64_eocl);
1323 #endif
1324 file_data_write(download->file, download->offset, sizeof(*download->zip_eoc), (unsigned char *) download->zip_eoc);
1325 download->offset += sizeof(*download->zip_eoc);
1326 g_free(download->zip64_eoc);
1327 download->zip64_eoc = NULL;
1328 return 1;
1329 }
1330
1331 static void push_zipfile_tile_do(struct map_rect_priv *mr, struct zip_cd *cd, int zipfile, int offset, int length)
1332
1333 {
1334 struct tile t;
1335 struct map_priv *m = mr->m;
1336 struct file *f = m->fi;
1337
1338 // dbg(1, "enter %p %d\n", mr, zipfile);
1339 #ifdef DEBUG_SIZE
1340 #if DEBUG_SIZE > 0
1341 {
1342 char filename[cd->zipcfnl+1];
1343 memcpy(filename, cd+1, cd->zipcfnl);
1344 filename[cd->zipcfnl]='\0';
1345 // dbg(0,"enter %d (%s) %d\n",zipfile, filename, cd->zipcunc);
1346 }
1347 #endif
1348 mr->size+=cd->zipcunc;
1349 #endif
1350 t.zipfile_num = zipfile;
1351 if (zipfile_to_tile(m, cd, &t))
1352 push_tile(mr, &t, offset, length);
1353 file_data_free(f, (unsigned char *) cd);
1354 }
1355
1356 static struct zip_cd *
1357 download(struct map_priv *m, struct map_rect_priv *mr, struct zip_cd *cd, int zipfile, int offset, int length, int async)
1358 {
1359 struct map_download *download;
1360
1361 if (!m->download_enabled)
1362 return NULL;
1363
1364 if (async == 2)
1365 {
1366 download = m->download;
1367 }
1368 else
1369 {
1370 download=g_new0(struct map_download, 1);
1371 if (mr)
1372 {
1373 download->m = m;
1374 download->mr = mr;
1375 download->file = m->fi;
1376 download->cd = cd;
1377 download->zipfile = zipfile;
1378 download->toffset = offset;
1379 download->tlength = length;
1380 download->state = 1;
1381 }
1382 else
1383 {
1384 struct attr readwrite =
1385 { attr_readwrite,
1386 { (void *) 1 } };
1387 struct attr create =
1388 { attr_create,
1389 { (void *) 1 } };
1390 struct attr *attrs[3];
1391 attrs[0] = &readwrite;
1392 attrs[1] = &create;
1393 attrs[2] = NULL;
1394 download->file = file_create(m->filename, attrs);
1395 download->m = m;
1396 download->state = 4;
1397 }
1398 }
1399 if (async == 1)
1400 {
1401 m->download = download;
1402 g_free(m->progress);
1403 if (download->mr)
1404 m->progress = g_strdup_printf("Download Tile %d 0%%", download->zipfile);
1405 else
1406 m->progress = g_strdup_printf("Download Map Information 0%%");
1407 callback_list_call_attr_0(m->cbl, attr_progress);
1408 return NULL;
1409 }
1410 for (;;)
1411 {
1412 // dbg(0, "state=%d\n", download->state);
1413 switch (download->state)
1414 {
1415 case 0:
1416 // dbg(0, "error\n");
1417 break;
1418 case 1:
1419 if (download_start(download))
1420 download->state = 2;
1421 else
1422 download->state = 0;
1423 break;
1424 case 2:
1425 if (download_download(download))
1426 download->state = 3;
1427 else
1428 {
1429 g_free(m->progress);
1430 m->progress = g_strdup_printf("Download Tile %d %d%%", download->zipfile, download->progress);
1431 callback_list_call_attr_0(m->cbl, attr_progress);
1432 }
1433 break;
1434 case 3:
1435 if (download_finish(download))
1436 {
1437 struct zip_cd *ret;
1438 g_free(m->progress);
1439 m->progress = g_strdup_printf("Download Tile %d 100%%", download->zipfile);
1440 callback_list_call_attr_0(m->cbl, attr_progress);
1441 if (async)
1442 {
1443 push_zipfile_tile_do(download->mr, download->cd, download->zipfile, download->toffset, download->tlength);
1444 ret = NULL;
1445 }
1446 else
1447 ret = download->cd;
1448 g_free(m->progress);
1449 m->progress = NULL;
1450 g_free(download);
1451 if (async)
1452 m->download = NULL;
1453 return ret;
1454 }
1455 else
1456 download->state = 0;
1457 break;
1458 case 4:
1459 if (download_planet_size(download))
1460 download->state = 5;
1461 else
1462 download->state = 0;
1463 break;
1464 case 5:
1465 g_free(m->progress);
1466 m->progress = g_strdup_printf("Download Map Information 50%%");
1467 callback_list_call_attr_0(m->cbl, attr_progress);
1468 if (download_eoc(download))
1469 download->state = 6;
1470 else
1471 {
1472 // dbg(0, "download of eoc failed\n");
1473 download->state = 0;
1474 }
1475 break;
1476 case 6:
1477 g_free(m->progress);
1478 m->progress = g_strdup_printf("Download Map Information 100%%");
1479 callback_list_call_attr_0(m->cbl, attr_progress);
1480 if (download_directory_start(download))
1481 download->state = 7;
1482 else
1483 download->state = 0;
1484 break;
1485 case 7:
1486 g_free(m->progress);
1487 m->progress = g_strdup_printf("Download Map Directory %d%%", (int) (download->offset * 100 / download->zip64_eoc->zip64ecsz));
1488 callback_list_call_attr_0(m->cbl, attr_progress);
1489 if (!download_directory_do(download))
1490 download->state = 8;
1491 break;
1492 case 8:
1493 if (download_directory_finish(download))
1494 download->state = 9;
1495 else
1496 download->state = 0;
1497 break;
1498 case 9:
1499 download_initial_finish(download);
1500 m->fi = download->file;
1501 g_free(m->progress);
1502 m->progress = NULL;
1503 g_free(download);
1504 if (async)
1505 m->download = NULL;
1506 map_binfile_open(m);
1507 break;
1508 }
1509 if (async)
1510 return NULL;
1511 }
1512 }
1513
1514 static int push_zipfile_tile(struct map_rect_priv *mr, int zipfile, int offset, int length, int async)
1515 {
1516 struct map_priv *m = mr->m;
1517 struct file *f = m->fi;
1518 long long cdoffset = m->eoc64 ? m->eoc64->zip64eofst : m->eoc->zipeofst;
1519 struct zip_cd *cd = (struct zip_cd *) (file_data_read(f, cdoffset + zipfile * m->cde_size, m->cde_size));
1520 // dbg(1,"read from "LONGLONG_FMT" %d bytes\n",cdoffset + zipfile*m->cde_size, m->cde_size);
1521 cd_to_cpu(cd);
1522 if (!cd->zipcunc && m->url)
1523 {
1524 cd = download(m, mr, cd, zipfile, offset, length, async);
1525 if (!cd)
1526 return 1;
1527 }
1528 push_zipfile_tile_do(mr, cd, zipfile, offset, length);
1529 return 0;
1530 }
1531
1532 static struct map_rect_priv *
1533 map_rect_new_binfile_int(struct map_priv *map, struct map_selection *sel)
1534 {
1535 struct map_rect_priv *mr;
1536
1537 binfile_check_version(map);
1538 // dbg(1, "map_rect_new_binfile\n");
1539 if (!map->fi && !map->url)
1540 return NULL;
1541 map_binfile_http_close(map);
1542 mr=g_new0(struct map_rect_priv, 1);
1543 mr->m = map;
1544 mr->sel = sel;
1545 mr->item.id_hi = 0;
1546 mr->item.id_lo = 0;
1547 mr->item.meth = &methods_binfile;
1548 mr->item.priv_data = mr;
1549 return mr;
1550 }
1551
1552 static void tile_bbox(char *tile, int len, struct coord_rect *r)
1553 {
1554 struct coord c;
1555 int overlap = 1;
1556 int xo, yo;
1557 struct coord_rect world_bbox =
1558 {
1559 { -20000000, 20000000 }, /* lu */
1560 { 20000000, -20000000 }, /* rl */
1561 };
1562 *r = world_bbox;
1563 while (len)
1564 {
1565 c.x = (r->lu.x + r->rl.x) / 2;
1566 c.y = (r->lu.y + r->rl.y) / 2;
1567 xo = (r->rl.x - r->lu.x) * overlap / 100;
1568 yo = (r->lu.y - r->rl.y) * overlap / 100;
1569 switch (*tile)
1570 {
1571 case 'a':
1572 r->lu.x = c.x - xo;
1573 r->rl.y = c.y - yo;
1574 break;
1575 case 'b':
1576 r->rl.x = c.x + xo;
1577 r->rl.y = c.y - yo;
1578 break;
1579 case 'c':
1580 r->lu.x = c.x - xo;
1581 r->lu.y = c.y + yo;
1582 break;
1583 case 'd':
1584 r->rl.x = c.x + xo;
1585 r->lu.y = c.y + yo;
1586 break;
1587 default:
1588 return;
1589 }
1590 tile++;
1591 len--;
1592 }
1593 }
1594
1595 static int map_download_selection_check(struct zip_cd *cd, struct map_selection *sel)
1596 {
1597 //// dbg(0,"EEnter\n");
1598
1599 struct coord_rect cd_rect;
1600 if (cd->zipcunc)
1601 return 0;
1602 tile_bbox((char *) (cd + 1), cd->zipcfnl, &cd_rect);
1603 while (sel)
1604 {
1605 if (coord_rect_overlap(&cd_rect, &sel->u.c_rect))
1606 return 1;
1607 sel = sel->next;
1608 }
1609 return 0;
1610 }
1611
1612 static void map_download_selection(struct map_priv *m, struct map_rect_priv *mr, struct map_selection *sel)
1613 {
1614 int i;
1615 struct zip_cd *cd;
1616 for (i = 0; i < m->zip_members; i++)
1617 {
1618 cd = binfile_read_cd(m, m->cde_size * i, -1);
1619 if (map_download_selection_check(cd, sel))
1620 download(m, mr, cd, i, 0, 0, 0);
1621 file_data_free(m->fi, (unsigned char *) cd);
1622 }
1623 }
1624
1625 static struct map_rect_priv *
1626 map_rect_new_binfile(struct map_priv *map, struct map_selection *sel)
1627 {
1628 struct map_rect_priv *mr = map_rect_new_binfile_int(map, sel);
1629 struct tile t;
1630 // dbg(1, "zip_members=%d\n", map->zip_members);
1631 if (map->url && map->fi && sel && sel->order == 255)
1632 {
1633 map_download_selection(map, mr, sel);
1634 }
1635 if (map->eoc)
1636 mr->status = 1;
1637 else
1638 {
1639 unsigned char *d;
1640 if (map->fi)
1641 {
1642 d = file_data_read(map->fi, 0, map->fi->size);
1643 t.start = (int *) d;
1644 t.end = (int *) (d + map->fi->size);
1645 t.fi = map->fi;
1646 t.zipfile_num = 0;
1647 t.mode = 0;
1648 push_tile(mr, &t, 0, 0);
1649 }
1650 else if (map->url && !map->download)
1651 {
1652 download(map, NULL, NULL, 0, 0, 0, 1);
1653 mr->status = 1;
1654 }
1655 }
1656 return mr;
1657 }
1658
1659 static void write_changes_do(gpointer key, gpointer value, gpointer user_data)
1660 {
1661 struct binfile_hash_entry *entry = key;
1662 FILE *out = user_data;
1663 if (entry->flags)
1664 {
1665 entry->flags = 0;
1666 fwrite(entry, sizeof(*entry) + (le32_to_cpu(entry->data[0]) + 1) * 4, 1, out);
1667 // dbg(0, "yes\n");
1668 }
1669 }
1670
1671 static void write_changes(struct map_priv *m)
1672 {
1673 FILE *changes;
1674 char *changes_file;
1675 if (!m->changes)
1676 return;
1677 changes_file = g_strdup_printf("%s.log", m->filename);
1678 changes = fopen(changes_file, "ab");
1679 g_hash_table_foreach(m->changes, write_changes_do, changes);
1680 fclose(changes);
1681 g_free(changes_file);
1682 }
1683
1684 static void load_changes(struct map_priv *m)
1685 {
1686 FILE *changes;
1687 char *changes_file;
1688 struct binfile_hash_entry entry, *e;
1689 int size;
1690 changes_file = g_strdup_printf("%s.log", m->filename);
1691 changes = fopen(changes_file, "rb");
1692 if (!changes)
1693 {
1694 g_free(changes_file);
1695 return;
1696 }
1697 m->changes = g_hash_table_new_full(binfile_hash_entry_hash, binfile_hash_entry_equal, g_free, NULL);
1698 while (fread(&entry, sizeof(entry), 1, changes) == 1)
1699 {
1700 if (fread(&size, sizeof(size), 1, changes) != 1)
1701 break;
1702 e = g_malloc(sizeof(struct binfile_hash_entry) + (le32_to_cpu(size) + 1) * 4);
1703 *e = entry;
1704 e->data[0] = size;
1705 if (fread(e->data + 1, le32_to_cpu(size) * 4, 1, changes) != 1)
1706 break;
1707 g_hash_table_replace(m->changes, e, e);
1708 }
1709 fclose(changes);
1710 g_free(changes_file);
1711 }
1712
1713 static void map_rect_destroy_binfile(struct map_rect_priv *mr)
1714 {
1715 write_changes(mr->m);
1716 while (pop_tile(mr))
1717 ;
1718 #ifdef DEBUG_SIZE
1719 // dbg(0,"size=%d kb\n",mr->size/1024);
1720 #endif
1721 if (mr->tiles[0].fi && mr->tiles[0].start)
1722 file_data_free(mr->tiles[0].fi, (unsigned char *) (mr->tiles[0].start));
1723 g_free(mr->url);
1724 map_binfile_http_close(mr->m);
1725 g_free(mr);
1726 }
1727
1728 static void setup_pos(struct map_rect_priv *mr)
1729 {
1730 int size, coord_size;
1731 struct tile *t = mr->t;
1732 size = le32_to_cpu(t->pos[0]);
1733 if (size > 1024 * 1024 || size < 0)
1734 {
1735 // dbg(0, "size=0x%x\n", size);
1736 #if 0
1737 fprintf(stderr,"offset=%d\n", (unsigned char *)(mr->pos)-mr->m->f->begin);
1738 #endif
1739 // dbg(0, "size error");
1740 }
1741 t->pos_next = t->pos + size + 1;
1742 mr->item.type = le32_to_cpu(t->pos[1]);
1743 coord_size = le32_to_cpu(t->pos[2]);
1744 t->pos_coord_start = t->pos + 3;
1745 t->pos_attr_start = t->pos_coord_start + coord_size;
1746 }
1747
1748 static int selection_contains(struct map_selection *sel, struct coord_rect *r, struct range *mima)
1749 {
1750 //// dbg(0,"EEnter\n");
1751
1752 int order;
1753 if (!sel)
1754 return 1;
1755 while (sel)
1756 {
1757 if (coord_rect_overlap(r, &sel->u.c_rect))
1758 {
1759 order = sel->order;
1760 // dbg(1, "min %d max %d order %d\n", mima->min, mima->max, order);
1761 if (!mima->min && !mima->max)
1762 return 1;
1763 if (order >= mima->min && order <= mima->max)
1764 return 1;
1765 }
1766 sel = sel->next;
1767 }
1768 return 0;
1769 }
1770
1771 static void map_parse_country_binfile(struct map_rect_priv *mr)
1772 {
1773 struct attr at;
1774 if (binfile_attr_get(mr->item.priv_data, attr_country_id, &at))
1775 {
1776 if (at.u.num == mr->country_id)
1777 {
1778 if (binfile_attr_get(mr->item.priv_data, attr_zipfile_ref, &at))
1779 {
1780 push_zipfile_tile(mr, at.u.num, 0, 0, 0);
1781 }
1782 }
1783 }
1784 }
1785
1786 static int map_parse_submap(struct map_rect_priv *mr, int async)
1787 {
1788 struct coord_rect r;
1789 struct coord c[2];
1790 struct attr at;
1791 struct range mima;
1792 if (binfile_coord_get(mr->item.priv_data, c, 2) != 2)
1793 return 0;
1794 r.lu.x = c[0].x;
1795 r.lu.y = c[1].y;
1796 r.rl.x = c[1].x;
1797 r.rl.y = c[0].y;
1798 if (!binfile_attr_get(mr->item.priv_data, attr_order, &at))
1799 return 0;
1800 #if __BYTE_ORDER == __BIG_ENDIAN
1801 mima.min = le16_to_cpu(at.u.range.max);
1802 mima.max = le16_to_cpu(at.u.range.min);
1803 #else
1804 mima=at.u.range;
1805 #endif
1806 if (!mr->m->eoc || !selection_contains(mr->sel, &r, &mima))
1807 return 0;
1808 if (!binfile_attr_get(mr->item.priv_data, attr_zipfile_ref, &at))
1809 return 0;
1810 // dbg(1, "pushing zipfile %d from %d\n", at.u.num, mr->t->zipfile_num);
1811 return push_zipfile_tile(mr, at.u.num, 0, 0, async);
1812 }
1813
1814 static int push_modified_item(struct map_rect_priv *mr)
1815 {
1816 struct item_id id;
1817 struct binfile_hash_entry *entry;
1818 id.id_hi = mr->item.id_hi;
1819 id.id_lo = mr->item.id_lo;
1820 entry = g_hash_table_lookup(mr->m->changes, &id);
1821 if (entry)
1822 {
1823 struct tile tn;
1824 tn.pos_next = tn.pos = tn.start = entry->data;
1825 tn.zipfile_num = mr->item.id_hi;
1826 tn.mode = 2;
1827 tn.end = tn.start + le32_to_cpu(entry->data[0]) + 1;
1828 push_tile(mr, &tn, 0, 0);
1829 return 1;
1830 }
1831 return 0;
1832 }
1833
1834 static struct item *
1835 map_rect_get_item_binfile(struct map_rect_priv *mr)
1836 {
1837 struct tile *t;
1838 struct map_priv *m = mr->m;
1839 if (m->download)
1840 {
1841 download(m, NULL, NULL, 0, 0, 0, 2);
1842 return &busy_item;
1843 }
1844 if (mr->status == 1)
1845 {
1846 mr->status = 0;
1847 if (push_zipfile_tile(mr, m->zip_members - 1, 0, 0, 1))
1848 return &busy_item;
1849 }
1850 for (;;)
1851 {
1852 t = mr->t;
1853 if (!t)
1854 return NULL;
1855 t->pos = t->pos_next;
1856 if (t->pos >= t->end)
1857 {
1858 if (pop_tile(mr))
1859 continue;
1860 return NULL;
1861 }
1862 setup_pos(mr);
1863 binfile_coord_rewind(mr);
1864 binfile_attr_rewind(mr);
1865 if ((mr->item.type == type_submap) && (!mr->country_id))
1866 {
1867 if (map_parse_submap(mr, 1))
1868 return &busy_item;
1869 continue;
1870 }
1871 if (t->mode != 2)
1872 {
1873 mr->item.id_hi = t->zipfile_num;
1874 mr->item.id_lo = t->pos - t->start;
1875 if (mr->m->changes && push_modified_item(mr))
1876 continue;
1877 }
1878 if (mr->country_id)
1879 {
1880 if (mr->item.type == type_countryindex)
1881 {
1882 map_parse_country_binfile(mr);
1883 }
1884 if (item_is_town(mr->item))
1885 {
1886 return &mr->item;
1887 }
1888 else
1889 {
1890 continue;
1891 }
1892 }
1893 return &mr->item;
1894 }
1895 }
1896
1897 static struct item *
1898 map_rect_get_item_byid_binfile(struct map_rect_priv *mr, int id_hi, int id_lo)
1899 {
1900 struct tile *t;
1901 if (mr->m->eoc)
1902 {
1903 while (pop_tile(mr))
1904 ;
1905 push_zipfile_tile(mr, id_hi, 0, 0, 0);
1906 }
1907 t = mr->t;
1908 t->pos = t->start + id_lo;
1909 mr->item.id_hi = id_hi;
1910 mr->item.id_lo = id_lo;
1911 if (mr->m->changes)
1912 {
1913 push_modified_item(mr);
1914 }
1915 setup_pos(mr);
1916 binfile_coord_rewind(mr);
1917 binfile_attr_rewind(mr);
1918
1919 return &mr->item;
1920 }
1921
1922 static int binmap_search_by_index(struct map_priv *map, struct item *item, struct map_rect_priv **ret)
1923 {
1924 struct attr zipfile_ref;
1925 int *data;
1926
1927 if (!item)
1928 {
1929 *ret = NULL;
1930 return 0;
1931 }
1932 if (item_attr_get(item, attr_item_id, &zipfile_ref))
1933 {
1934 data = zipfile_ref.u.data;
1935 *ret = map_rect_new_binfile_int(map, NULL);
1936 push_zipfile_tile(*ret, le32_to_cpu(data[0]), le32_to_cpu(data[1]), -1, 0);
1937 return 3;
1938 }
1939 if (item_attr_get(item, attr_zipfile_ref, &zipfile_ref))
1940 {
1941 *ret = map_rect_new_binfile_int(map, NULL);
1942 push_zipfile_tile(*ret, zipfile_ref.u.num, 0, 0, 0);
1943 return 1;
1944 }
1945 if (item_attr_get(item, attr_zipfile_ref_block, &zipfile_ref))
1946 {
1947 data = zipfile_ref.u.data;
1948 *ret = map_rect_new_binfile_int(map, NULL);
1949 push_zipfile_tile(*ret, le32_to_cpu(data[0]), le32_to_cpu(data[1]), le32_to_cpu(data[2]), 0);
1950 return 2;
1951 }
1952 *ret = NULL;
1953 return 0;
1954 }
1955
1956 static struct map_rect_priv *
1957 binmap_search_street_by_place(struct map_priv *map, struct item *town, struct coord *c, struct map_selection *sel)
1958 {
1959 struct attr town_name, poly_town_name;
1960 struct map_rect_priv *map_rec2;
1961 struct item *place;
1962 int found = 0;
1963
1964 if (!item_attr_get(town, attr_label, &town_name))
1965 return NULL;
1966 sel->range = item_range_all;
1967 sel->order = 18;
1968 sel->next = NULL;
1969 sel->u.c_rect.lu = *c;
1970 sel->u.c_rect.rl = *c;
1971 map_rec2 = map_rect_new_binfile(map, sel);
1972 while ((place = map_rect_get_item_binfile(map_rec2)))
1973 {
1974 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))
1975 {
1976 struct coord c[128];
1977 int i, count;
1978 found = 1;
1979 while ((count = item_coord_get(place, c, 128)))
1980 {
1981 for (i = 0; i < count; i++)
1982 {
1983 coord_rect_extend(&sel->u.c_rect, &c[i]);
1984 }
1985 }
1986 }
1987 }
1988
1989 map_rect_destroy_binfile(map_rec2);
1990 if (found)
1991 {
1992 return map_rect_new_binfile(map, sel);
1993 }
1994 return NULL;
1995 }
1996
1997 static struct map_rect_priv *
1998 binmap_search_street_by_estimate(struct map_priv *map, struct item *town, struct coord *c, struct map_selection *sel)
1999 {
2000 int size = 10000;
2001 switch (town->type)
2002 {
2003 case type_town_label_1e7:
2004 case type_town_label_5e6:
2005 case type_town_label_2e6:
2006 case type_town_label_1e6:
2007 case type_town_label_5e5:
2008 case type_town_label_2e5:
2009 size = 10000;
2010 break;
2011 case type_town_label_1e5:
2012 case type_town_label_5e4:
2013 case type_town_label_2e4:
2014 size = 5000;
2015 break;
2016 case type_town_label_1e4:
2017 case type_town_label_5e3:
2018 case type_town_label_2e3:
2019 size = 2500;
2020 break;
2021 case type_town_label_1e3:
2022 case type_town_label_5e2:
2023 case type_town_label_2e2:
2024 case type_town_label_1e2:
2025 case type_town_label_5e1:
2026 case type_town_label_2e1:
2027 case type_town_label_1e1:
2028 case type_town_label_5e0:
2029 case type_town_label_2e0:
2030 case type_town_label_1e0:
2031 case type_town_label_0e0:
2032 size = 1000;
2033 break;
2034 default:
2035 break;
2036 }
2037
2038 if (global_search_street_size_factor > 1)
2039 {
2040 size = size * global_search_street_size_factor;
2041 }
2042
2043 sel->u.c_rect.lu.x = c->x - size;
2044 sel->u.c_rect.lu.y = c->y + size;
2045 sel->u.c_rect.rl.x = c->x + size;
2046 sel->u.c_rect.rl.y = c->y - size;
2047 return map_rect_new_binfile(map, sel);
2048 }
2049
2050 static struct map_rect_priv *
2051 binmap_search_housenumber_by_estimate(struct map_priv *map, struct coord *c, struct map_selection *sel)
2052 {
2053 int size = 20;
2054 sel->u.c_rect.lu.x = c->x - size;
2055 sel->u.c_rect.lu.y = c->y + size;
2056 sel->u.c_rect.rl.x = c->x + size;
2057 sel->u.c_rect.rl.y = c->y - size;
2058
2059 sel->range = item_range_all;
2060 sel->order = 18;
2061 //sel->next = NULL;
2062
2063 return map_rect_new_binfile(map, sel);
2064 }
2065
2066 static struct map_search_priv *
2067 binmap_search_new(struct map_priv *map, struct item *item, struct attr *search, int partial)
2068 {
2069 struct map_rect_priv *map_rec;
2070 struct map_search_priv *msp=g_new0(struct map_search_priv, 1);
2071 struct item *town;
2072 int willsearch = 0;
2073
2074 msp->search = search;
2075 msp->partial = partial;
2076 /*
2077 * NOTE: If you implement search for other attributes than attr_town_name and attr_street_name,
2078 * please update this comment and the documentation for map_search_new() in map.c
2079 */
2080 switch (search->type)
2081 {
2082 case attr_country_name:
2083 break;
2084 case attr_town_name:
2085 case attr_town_or_district_name:
2086 map_rec = map_rect_new_binfile(map, NULL);
2087 if (!map_rec)
2088 {
2089 break;
2090 }
2091 map_rec->country_id = item->id_lo;
2092 msp->mr = map_rec;
2093 willsearch = 1;
2094 break;
2095 case attr_town_postal:
2096 break;
2097 case attr_street_name:
2098 if (!item->map)
2099 break;
2100 if (!map_priv_is(item->map, map))
2101 break;
2102 map_rec = map_rect_new_binfile(map, NULL);
2103 town = map_rect_get_item_byid_binfile(map_rec, item->id_hi, item->id_lo);
2104 if (town)
2105 {
2106 struct coord c;
2107
2108 if (binmap_search_by_index(map, town, &msp->mr))
2109 {
2110 //dbg(0, "search:mode=1\n");
2111 msp->mode = 1;
2112 }
2113 else
2114 {
2115 if (item_coord_get(town, &c, 1))
2116 {
2117 if ((msp->mr = binmap_search_street_by_place(map, town, &c, &msp->ms)))
2118 {
2119 //dbg(0, "search:mode=2\n");
2120 msp->mode = 2;
2121 }
2122 else
2123 {
2124 msp->mr = binmap_search_street_by_estimate(map, town, &c, &msp->ms);
2125 //dbg(0, "search:mode=3\n");
2126 msp->mode = 3;
2127 }
2128 }
2129 }
2130 map_rect_destroy_binfile(map_rec);
2131 if (!msp->mr)
2132 {
2133 break;
2134 }
2135 willsearch = 1;
2136 break;
2137 }
2138 map_rect_destroy_binfile(map_rec);
2139 break;
2140 case attr_house_number:
2141 // dbg(1, "case house_number");
2142 if (!item->map)
2143 break;
2144 if (!map_priv_is(item->map, map))
2145 break;
2146 msp->map = map;
2147 msp->mr_item = map_rect_new_binfile(map, NULL);
2148 msp->item = map_rect_get_item_byid_binfile(msp->mr_item, item->id_hi, item->id_lo);
2149 if (binmap_search_by_index(map, msp->item, &msp->mr) != 3)
2150 {
2151 struct coord c;
2152 if (item_coord_get(msp->item, &c, 1))
2153 {
2154 msp->mr = binmap_search_housenumber_by_estimate(map, &c, &msp->ms);
2155 msp->mode = 2;
2156 }
2157 map_rect_destroy_binfile(msp->mr_item);
2158 msp->mr_item = NULL;
2159 }
2160 if (!msp->mr)
2161 {
2162 break;
2163 }
2164 willsearch = 1;
2165 break;
2166 default:
2167 break;
2168 }
2169
2170 if (!willsearch)
2171 {
2172 g_free(msp);
2173 msp = NULL;
2174 }
2175 else
2176 {
2177 msp->str = linguistics_casefold(search->u.str);
2178 }
2179 return msp;
2180 }
2181
2182 static int ascii_cmp(char *name, char *match, int partial)
2183 {
2184 int ret = 1;
2185
2186 if (name == NULL)
2187 {
2188 return ret;
2189 }
2190
2191 if (match == NULL)
2192 {
2193 return ret;
2194 }
2195
2196 char *s2 = linguistics_casefold(match); // user entered search string
2197 char *s1 = linguistics_casefold(name); // string from mapfile
2198 char *s1_1 = linguistics_expand_special(s1, 1);
2199 char *s2_1 = linguistics_expand_special(s2, 1);
2200
2201 if (s1_1)
2202 {
2203 if (s2_1)
2204 {
2205 ret = linguistics_compare(s1_1, s2_1, partial);
2206 }
2207 else
2208 {
2209 ret = linguistics_compare(s1_1, s2, partial);
2210 }
2211 }
2212 else
2213 {
2214 if (s2_1)
2215 {
2216 ret = linguistics_compare(s1, s2_1, partial);
2217 }
2218 else
2219 {
2220 ret = linguistics_compare(s1, s2, partial);
2221 }
2222 }
2223
2224 if (s1_1)
2225 g_free(s1_1);
2226 if (s2_1)
2227 g_free(s2_1);
2228 if (s1)
2229 g_free(s1);
2230 if (s2)
2231 g_free(s2);
2232 return ret;
2233 }
2234
2235 struct duplicate
2236 {
2237 struct coord c;
2238 char str[0];
2239 };
2240
2241 static guint duplicate_hash(gconstpointer key)
2242 {
2243 const struct duplicate *d = key;
2244 return d->c.x ^ d->c.y ^ g_str_hash(d->str);
2245 }
2246
2247 static gboolean duplicate_equal(gconstpointer a, gconstpointer b)
2248 {
2249 const struct duplicate *da = a;
2250 const struct duplicate *db = b;
2251 return (da->c.x == db->c.x && da->c.y == da->c.y && g_str_equal(da->str, db->str));
2252 }
2253
2254 static int duplicate(struct map_search_priv *msp, struct item *item, enum attr_type attr_type)
2255 {
2256 struct attr attr;
2257 if (!msp->search_results)
2258 msp->search_results = g_hash_table_new_full(duplicate_hash, duplicate_equal, g_free, NULL);
2259 binfile_attr_rewind(item->priv_data);
2260 if (!item_attr_get(item, attr_type, &attr))
2261 return 1;
2262 {
2263 int len = sizeof(struct coord) + strlen(attr.u.str) + 1;
2264 char *buffer = g_alloca(sizeof(char) * len);
2265 struct duplicate *d = (struct duplicate *) buffer;
2266 if (!item_coord_get(item, &d->c, 1))
2267 {
2268 d->c.x = 0;
2269 d->c.y = 0;
2270 }
2271 binfile_coord_rewind(item->priv_data);
2272 strcpy(d->str, attr.u.str);
2273 if (!g_hash_table_lookup(msp->search_results, d))
2274 {
2275 struct duplicate *dc = g_malloc(len);
2276 memcpy(dc, d, len);
2277 g_hash_table_insert(msp->search_results, dc, GINT_TO_POINTER(1));
2278 binfile_attr_rewind(item->priv_data);
2279 return 0;
2280 }
2281 }
2282 return 2;
2283 }
2284
2285 static struct item *
2286 binmap_search_get_item(struct map_search_priv *map_search)
2287 {
2288 struct item* it;
2289 struct attr at;
2290
2291 // // dbg(0,"Enter\n");
2292
2293 for (;;)
2294 {
2295 while ((it = map_rect_get_item_binfile(map_search->mr)))
2296 {
2297 switch (map_search->search->type)
2298 {
2299 case attr_town_name:
2300 case attr_district_name:
2301 case attr_town_or_district_name:
2302
2303 #if 0
2304 if (map_search->mr->tile_depth > 1 && item_is_town(*it) && !item_is_district(*it) && map_search->search->type != attr_district_name)
2305 {
2306 if (binfile_attr_get(it->priv_data, attr_town_name_match, &at) || binfile_attr_get(it->priv_data, attr_town_name, &at))
2307 {
2308 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial) && !duplicate(map_search, it, attr_town_name))
2309 return it;
2310 }
2311 }
2312 #endif
2313
2314 #if 1
2315 if (map_search->mr->tile_depth > 1 && item_is_town(*it) && !item_is_district(*it) && map_search->search->type != attr_district_name)
2316 {
2317 if (binfile_attr_get(it->priv_data, attr_town_name, &at))
2318 {
2319 //// dbg(0,"22town n:%s\n",at.u.str);
2320 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial)
2321 // && !duplicate(map_search, it, attr_town_name)
2322 )
2323 {
2324 //// dbg(0,"town n:%s\n",at.u.str);
2325 return it;
2326 }
2327 }
2328
2329 if (binfile_attr_get(it->priv_data, attr_town_name_match, &at))
2330 {
2331 //// dbg(0,"11town M:%s\n",at.u.str);
2332 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial)
2333 // && !duplicate(map_search, it, attr_town_name)
2334 )
2335 {
2336 //// dbg(0,"town M:%s\n",at.u.str);
2337 return it;
2338 }
2339 }
2340 }
2341 #endif
2342
2343 if (map_search->mr->tile_depth > 1 && item_is_district(*it) && map_search->search->type != attr_town_name)
2344 {
2345 if (binfile_attr_get(it->priv_data, attr_district_name_match, &at) || binfile_attr_get(it->priv_data, attr_district_name, &at))
2346 {
2347 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial) && !duplicate(map_search, it, attr_town_name))
2348 return it;
2349 }
2350 }
2351 break;
2352
2353 case attr_street_name:
2354
2355 if (map_search->mode == 1)
2356 {
2357 //dbg(0,"*in here 00*\n");
2358
2359 //if (binfile_attr_get(it->priv_data, attr_street_name_match, &at) || binfile_attr_get(it->priv_data, attr_street_name, &at)) {
2360 // if (!ascii_cmp(at.u.str, map_search->str, map_search->partial) && !duplicate(map_search, it, attr_street_name)) {
2361 // return it;
2362 // }
2363 //}
2364
2365 if (binfile_attr_get(it->priv_data, attr_street_name, &at))
2366 {
2367 //// dbg(0,"str AA:%s\n", at.u.str);
2368
2369 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial))
2370 {
2371 if ((offline_search_filter_duplicates != 1) || (!duplicate(map_search, it, attr_street_name)))
2372 {
2373 return it;
2374 }
2375 else
2376 {
2377 //// dbg(0,"dup street 1:%s\n",at.u.str);
2378 }
2379 }
2380 }
2381
2382 if (binfile_attr_get(it->priv_data, attr_street_name_match, &at))
2383 {
2384 //// dbg(0,"str BB:%s\n", at.u.str);
2385
2386 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial))
2387 {
2388 if ((offline_search_filter_duplicates != 1) || (!duplicate(map_search, it, attr_street_name_match)))
2389 {
2390 return it;
2391 }
2392 else
2393 {
2394 //// dbg(0,"dup street 2:%s\n",at.u.str);
2395 }
2396 }
2397 }
2398
2399 continue;
2400 }
2401
2402 #if 1
2403 // ------------------------------------
2404 // map_search->mode == 2 or 3
2405 // ------------------------------------
2406 if (item_is_street(*it))
2407 {
2408 // dbg(0,"*in here 11*\n");
2409
2410 struct attr at;
2411 if (map_selection_contains_item_rect(map_search->mr->sel, it))
2412 {
2413 if (binfile_attr_get(it->priv_data, attr_label, &at))
2414 {
2415 int match = 0;
2416 char *str = g_strdup(at.u.str);
2417 // dbg(0,"search=%s str is:%s\n",map_search->str, at.u.str);
2418 if (!ascii_cmp(str, map_search->str, map_search->partial))
2419 {
2420 match = 1;
2421 }
2422 g_free(str);
2423 if (match)
2424 {
2425 if ((offline_search_filter_duplicates != 1) || (!duplicate(map_search, it, attr_label)))
2426 {
2427 item_coord_rewind(it);
2428 return it;
2429 }
2430 }
2431 }
2432
2433 if (binfile_attr_get(it->priv_data, attr_street_name_match, &at))
2434 {
2435 int match = 0;
2436 char *str = g_strdup(at.u.str);
2437 // dbg(0,"search=%s mstr is:%s\n",map_search->str, at.u.str);
2438 if (!ascii_cmp(str, map_search->str, map_search->partial))
2439 {
2440 match = 1;
2441 }
2442 g_free(str);
2443 if (match)
2444 {
2445 if ((offline_search_filter_duplicates != 1) || (!duplicate(map_search, it, attr_street_name_match)))
2446 {
2447 item_coord_rewind(it);
2448 return it;
2449 }
2450 }
2451 }
2452 //else
2453 //{
2454 // if (binfile_attr_get(it->priv_data, attr_street_name, &at))
2455 // {
2456 // // dbg(0,"---str X*X:%s\n", at.u.str);
2457 // }
2458 //}
2459 }
2460 }
2461 #endif
2462 break;
2463 case attr_house_number:
2464 //if (it->type == type_house_number)
2465 if ((it->type == type_house_number) || (type_house_number_interpolation_even) || (type_house_number_interpolation_odd) || (type_house_number_interpolation_all))
2466 {
2467 // is it a housenumber?
2468 if (binfile_attr_get(it->priv_data, attr_house_number, &at))
2469 {
2470 // match housenumber to our string
2471 if (!ascii_cmp(at.u.str, map_search->str, map_search->partial))
2472 {
2473 //binfile_attr_get(it->priv_data, attr_street_name, &at);
2474 //// dbg(0,"hnnn B1 street_name=%s",at.u.str);
2475
2476 if (!duplicate(map_search, it, attr_house_number))
2477 {
2478 binfile_attr_rewind(it->priv_data);
2479 return it;
2480 }
2481 }
2482 }
2483 else
2484 {
2485 return it;
2486 }
2487 }
2488 continue;
2489 default:
2490 return NULL;
2491 }
2492 }
2493
2494 if (!map_search->mr_item)
2495 {
2496 return NULL;
2497 }
2498 map_rect_destroy_binfile(map_search->mr);
2499 if (!binmap_search_by_index(map_search->map, map_search->item, &map_search->mr))
2500 {
2501 return NULL;
2502 }
2503 } // endless for-loop
2504
2505 return NULL; // this is never reached
2506 }
2507
2508 static void binmap_search_destroy(struct map_search_priv *ms)
2509 {
2510 if (ms->search_results)
2511 g_hash_table_destroy(ms->search_results);
2512 if (ms->mr_item)
2513 map_rect_destroy_binfile(ms->mr_item);
2514 if (ms->mr)
2515 map_rect_destroy_binfile(ms->mr);
2516 if (ms->str)
2517 g_free(ms->str);
2518 g_free(ms);
2519 }
2520
2521 static int binmap_get_attr(struct map_priv *m, enum attr_type type, struct attr *attr)
2522 {
2523 attr->type = type;
2524 switch (type)
2525 {
2526 case attr_map_release:
2527 if (m->map_release)
2528 {
2529 attr->u.str = m->map_release;
2530 return 1;
2531 }
2532 break;
2533 case attr_progress:
2534 if (m->progress)
2535 {
2536 attr->u.str = m->progress;
2537 return 1;
2538 }
2539 default:
2540 break;
2541 }
2542 return 0;
2543 }
2544
2545 static int binmap_set_attr(struct map_priv *map, struct attr *attr)
2546 {
2547 switch (attr->type)
2548 {
2549 case attr_update:
2550 map->download_enabled = attr->u.num;
2551 return 1;
2552 default:
2553 return 0;
2554 }
2555
2556 }
2557
2558 static struct map_methods map_methods_binfile =
2559 { 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, };
2560
2561 static int binfile_get_index(struct map_priv *m)
2562 {
2563 //dbg(0,"_enter\n");
2564 int len;
2565 int cde_index_size;
2566 long long offset; // int or long long ?
2567 struct zip_cd *cd;
2568
2569 len = strlen("index");
2570 cde_index_size = sizeof(struct zip_cd) + len;
2571 //dbg(0,"_cde_index_size=%d\n", cde_index_size);
2572 if (m->eoc64)
2573 {
2574 //dbg(0,"_m->eoc64->zip64ecsz=%d\n", m->eoc64->zip64ecsz);
2575 offset = m->eoc64->zip64ecsz - cde_index_size;
2576 //dbg(0,"_eoc64 offset="LONGLONG_FMT"\n", offset);
2577 }
2578 else
2579 {
2580 //dbg(0,"_m->eoc->zipecsz=%d\n", m->eoc->zipecsz);
2581 offset = m->eoc->zipecsz - cde_index_size;
2582 //dbg(0,"_eoc offset="LONGLONG_FMT"\n", offset);
2583 }
2584 cd = binfile_read_cd(m, offset, len);
2585
2586 if (!cd)
2587 {
2588 //dbg(0,"_!cd\n");
2589 cde_index_size += sizeof(struct zip_cd_ext);
2590 //dbg(0,"_cde_index_size=%d\n", cde_index_size);
2591 if (m->eoc64)
2592 {
2593 offset = m->eoc64->zip64ecsz - cde_index_size;
2594 //dbg(0,"_eoc64 offset aa.1="LONGLONG_FMT"\n", offset);
2595 }
2596 else
2597 {
2598 offset = m->eoc->zipecsz - cde_index_size;
2599 //dbg(0,"_offset 22.0="LONGLONG_FMT"\n", offset);
2600 }
2601 cd = binfile_read_cd(m, offset, len + sizeof(struct zip_cd_ext));
2602 }
2603 //dbg(0,"_offset 22="LONGLONG_FMT"\n", offset);
2604
2605 if (cd)
2606 {
2607 //dbg(0,"_cd 001\n");
2608 if (cd->zipcfnl == len && !strncmp(cd->zipcfn, "index", len))
2609 {
2610 m->index_offset = offset;
2611 m->index_cd = cd;
2612 //dbg(0,"_leave:offset 33="LONGLONG_FMT"\n", offset);
2613 return 1;
2614 }
2615 //dbg(0,"_cd 002\n");
2616 }
2617
2618 offset = binfile_search_cd(m, 0, "index", 0, 0);
2619 //dbg(0,"_offset 44="LONGLONG_FMT"\n", offset);
2620
2621 if (offset == -1)
2622 {
2623 //dbg(0,"_leave:55\n");
2624 return 0;
2625 }
2626
2627 cd = binfile_read_cd(m, offset, -1);
2628
2629 if (!cd)
2630 {
2631 //dbg(0,"_leave:66\n");
2632 return 0;
2633 }
2634
2635 m->index_offset = offset;
2636 m->index_cd = cd;
2637
2638 //dbg(0,"_leave:normal:offset 77="LONGLONG_FMT"\n", offset);
2639 return 1;
2640 }
2641
2642 static int map_binfile_zip_setup(struct map_priv *m, char *filename, int mmap)
2643 {
2644 //dbg(0,"_enter\n");
2645
2646 struct zip_cd *first_cd;
2647 int i;
2648 if (!(m->eoc = binfile_read_eoc(m->fi)))
2649 {
2650 //dbg(0,"_leave:1\n");
2651 return 0;
2652 }
2653 dbg_assert(m->eoc->zipedsk == m->eoc->zipecen);
2654 if (m->eoc->zipedsk && strlen(filename) > 3)
2655 {
2656 char *tmpfilename = g_strdup(filename);
2657 char *ext = tmpfilename + strlen(tmpfilename) - 3;
2658
2659 //dbg(0,"_ff-1:%s\n", tmpfilename);
2660 //dbg(0,"_ff-2:%s\n", ext);
2661
2662 m->fis=g_new(struct file *,m->eoc->zipedsk);
2663 for (i = 0; i < m->eoc->zipedsk - 1; i++)
2664 {
2665 sprintf(ext, "b%02d", i + 1);
2666 //dbg(0,"_ff--3:%s\n", ext);
2667 m->fis[i] = file_create(tmpfilename, 0);
2668 if (mmap)
2669 {
2670 //dbg(0,"_want mmap 2 %s\n", m->fis[i]->name);
2671 file_mmap(m->fis[i]);
2672 }
2673 }
2674 m->fis[m->eoc->zipedsk - 1] = m->fi;
2675 g_free(tmpfilename);
2676 }
2677 else
2678 {
2679 //dbg(0,"_ff-XX\n");
2680 }
2681 //dbg(0, "_num_disk %d\n", m->eoc->zipedsk);
2682 m->eoc64 = binfile_read_eoc64(m->fi);
2683
2684 if (!binfile_get_index(m))
2685 {
2686 //dbg(0,"_leave:2\n");
2687 return 0;
2688 }
2689
2690 if (!(first_cd = binfile_read_cd(m, 0, 0)))
2691 {
2692 //dbg(0,"_leave:3\n");
2693 return 0;
2694 }
2695
2696 m->cde_size = sizeof(struct zip_cd) + first_cd->zipcfnl + first_cd->zipcxtl;
2697 m->zip_members = m->index_offset / m->cde_size + 1;
2698 //dbg(0, "_cde_size %d\n", m->cde_size);
2699 //dbg(0, "_members %d\n", m->zip_members);
2700 file_data_free(m->fi, (unsigned char *) first_cd);
2701 if (mmap)
2702 {
2703 //dbg(0,"_want mmap 3 %s\n", m->fi->name);
2704 file_mmap(m->fi);
2705 }
2706 return 1;
2707 }
2708
2709 #if 0
2710 static int
2711 map_binfile_download_initial(struct map_priv *m)
2712 {
2713 struct attr readwrite=
2714 { attr_readwrite,
2715 { (void *)1}};
2716 struct attr create=
2717 { attr_create,
2718 { (void *)1}};
2719 struct attr *attrs[4];
2720 struct file *out;
2721 long long woffset=0,planet_size;
2722 int size_ret;
2723 int cd1size,cdisize;
2724 long long cd1offset,cdioffset;
2725 struct zip64_eoc *zip64_eoc;
2726 struct zip64_eocl *zip64_eocl;
2727 struct zip_eoc *zip_eoc;
2728 struct zip_cd *cd1,*cdn,*cdi;
2729 int count,chunk,cdoffset=0;
2730 int mode=1;
2731 struct map_download *download=g_new0(struct map_download, 1);
2732
2733 attrs[0]=&readwrite;
2734 attrs[1]=&create;
2735 attrs[2]=NULL;
2736 download->file=file_create(m->filename,attrs);
2737 download->m=m;
2738 download_planet_size(download);
2739 download_eoc(download);
2740 download_directory_start(download);
2741 while (download_directory_do(download));
2742 download_directory_finish(download);
2743 download_initial_finish(download);
2744 m->fi=download->file;
2745 g_free(download);
2746 return 1;
2747
2748 cd1size=sizeof(*cd1);
2749 cd1offset=zip64_eoc->zip64eofst;
2750 cd1=(struct zip_cd *)map_binfile_download_range(m, cd1offset, cd1size);
2751 if (!cd1)
2752 return 0;
2753 cd1size=sizeof(*cd1)+binfile_cd_extra(cd1);
2754 g_free(cd1);
2755 cd1=(struct zip_cd *)map_binfile_download_range(m, cd1offset, cd1size);
2756 if (!cd1)
2757 return 0;
2758 cd1->zipcunc=0;
2759 cdisize=sizeof(*cdi)+strlen("index")+cd1->zipcxtl;
2760 cdioffset=zip64_eoc->zip64eofst+zip64_eoc->zip64ecsz-cdisize;
2761 cdi=(struct zip_cd *)map_binfile_download_range(m, cdioffset, cdisize);
2762 if (!cdi)
2763 {
2764 g_free(cd1);
2765 return 0;
2766 }
2767 cdi->zipcunc=0;
2768 cdn=g_malloc0(cd1size*256);
2769
2770 file_data_write(out, woffset, sizeof(*zip64_eoc), (unsigned char *)zip64_eoc);
2771 woffset+=sizeof(*zip64_eoc);
2772 cdoffset=woffset;
2773
2774 file_data_write(out, woffset, cd1size, (unsigned char *)cd1);
2775 woffset+=cd1size;
2776 count=(cdioffset-cd1offset)/cd1size-1;
2777 while (count > 0)
2778 {
2779 if (count > 256)
2780 chunk=256;
2781 else
2782 chunk=count;
2783 file_data_write(out, woffset, cd1size*chunk, (unsigned char *)cdn);
2784 woffset+=cd1size*chunk;
2785 count-=chunk;
2786 }
2787 g_free(cdn);
2788 g_free(cd1);
2789 file_data_write(out, woffset, cdisize, (unsigned char *)cdi);
2790 woffset+=cdisize;
2791
2792 }
2793 #endif
2794
2795 static int map_binfile_open(struct map_priv *m)
2796 {
2797 int *magic;
2798 struct map_rect_priv *mr;
2799 struct item *item;
2800 struct attr attr;
2801 struct attr readwrite =
2802 { attr_readwrite,
2803 { (void *) 1 } };
2804 struct attr *attrs[] =
2805 { &readwrite, NULL };
2806
2807 // dbg(0, "file_create %s\n", m->filename);
2808 m->fi = file_create(m->filename, m->url ? attrs : NULL);
2809 if (!m->fi && m->url)
2810 {
2811 return 0;
2812 }
2813 if (!m->fi)
2814 {
2815 // dbg(0, "Failed to load '%s'\n", m->filename);
2816 return 0;
2817 }
2818 if (m->check_version)
2819 {
2820 m->version = file_version(m->fi, m->check_version);
2821 }
2822
2823 magic = (int *) file_data_read(m->fi, 0, 4);
2824 if (!magic)
2825 {
2826 file_destroy(m->fi);
2827 m->fi = NULL;
2828 return 0;
2829 }
2830
2831 //dbg(0,"_zip_lfh_sig=%d\n", zip_lfh_sig);
2832
2833 //dbg(0,"_magic1=%d\n", magic[0]);
2834 //dbg(0,"_magic1=%d\n", magic[1]);
2835 //dbg(0,"_magic1=%d\n", magic[2]);
2836 //dbg(0,"_magic1=%d\n", magic[3]);
2837 *magic = le32_to_cpu(*magic);
2838 //dbg(0,"_magic2=%d\n", magic[0]);
2839 //dbg(0,"_magic2=%d\n", magic[1]);
2840 //dbg(0,"_magic2=%d\n", magic[2]);
2841 //dbg(0,"_magic2=%d\n", magic[3]);
2842 if (*magic == zip_lfh_sig || *magic == zip_split_sig || *magic == zip_cd_sig || *magic == zip64_eoc_sig)
2843 {
2844 if (!map_binfile_zip_setup(m, m->filename, m->flags & 1))
2845 {
2846 dbg(0, "invalid file format for '%s'\n", m->filename);
2847 file_destroy(m->fi);
2848 m->fi = NULL;
2849 return 0;
2850 }
2851 }
2852 else
2853 {
2854 //dbg(0,"_want mmap %s\n", m->fi->name);
2855 file_mmap(m->fi);
2856 }
2857
2858 //dbg(0,"_cont\n");
2859
2860 file_data_free(m->fi, (unsigned char *) magic);
2861 m->cachedir = g_strdup("/tmp/navit");
2862 m->map_version = 0;
2863
2864 mr = map_rect_new_binfile(m, NULL);
2865 if (mr)
2866 {
2867 while ((item = map_rect_get_item_binfile(mr)) == &busy_item)
2868 {
2869 ;
2870 }
2871
2872 if (item && item->type == type_map_information)
2873 {
2874 if (binfile_attr_get(item->priv_data, attr_version, &attr))
2875 {
2876 m->map_version = attr.u.num;
2877 dbg(0, "map_version=%d\n", m->map_version);
2878 }
2879 if (binfile_attr_get(item->priv_data, attr_map_release, &attr))
2880 {
2881 m->map_release = g_strdup(attr.u.str);
2882 dbg(0, "map_release=%s\n", m->map_release);
2883 }
2884 if (m->url && binfile_attr_get(item->priv_data, attr_url, &attr))
2885 {
2886 //dbg(0, "url config %s map %s\n", m->url, attr.u.str);
2887 if (strcmp(m->url, attr.u.str))
2888 {
2889 m->update_available = 1;
2890 }
2891 g_free(m->url);
2892 m->url = g_strdup(attr.u.str);
2893 }
2894 }
2895
2896 map_rect_destroy_binfile(mr);
2897
2898 if (m->map_version >= 16)
2899 {
2900 dbg(0, "Warning: This map is incompatible with your versionof ZANavi. Please update ZANavi.\n");
2901 return 0;
2902 }
2903 }
2904 return 1;
2905 }
2906
2907 static void map_binfile_close(struct map_priv *m)
2908 {
2909 int i;
2910 file_data_free(m->fi, (unsigned char *) m->index_cd);
2911 file_data_free(m->fi, (unsigned char *) m->eoc);
2912 file_data_free(m->fi, (unsigned char *) m->eoc64);
2913 g_free(m->cachedir);
2914 g_free(m->map_release);
2915 if (m->fis)
2916 {
2917 for (i = 0; i < m->eoc->zipedsk; i++)
2918 {
2919 file_destroy(m->fis[i]);
2920 }
2921 }
2922 else
2923 file_destroy(m->fi);
2924 }
2925
2926 static void map_binfile_destroy(struct map_priv *m)
2927 {
2928 g_free(m->filename);
2929 g_free(m->url);
2930 g_free(m->progress);
2931 g_free(m);
2932 }
2933
2934 static void binfile_check_version(struct map_priv *m)
2935 {
2936 int version = -1;
2937 if (!m->check_version)
2938 return;
2939 if (m->fi)
2940 version = file_version(m->fi, m->check_version);
2941 if (version != m->version)
2942 {
2943 if (m->fi)
2944 map_binfile_close(m);
2945 map_binfile_open(m);
2946 }
2947 }
2948
2949 static struct map_priv *
2950 map_new_binfile(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
2951 {
2952 struct map_priv *m;
2953 struct attr *data = attr_search(attrs, NULL, attr_data);
2954 struct attr *check_version, *map_pass, *flags, *url, *download_enabled;
2955 struct file_wordexp *wexp;
2956 char **wexp_data;
2957 if (!data)
2958 return NULL;
2959
2960 wexp = file_wordexp_new(data->u.str);
2961 wexp_data = file_wordexp_get_array(wexp);
2962 // dbg(0, "map_new_binfile %s\n", data->u.str);
2963 *meth = map_methods_binfile;
2964
2965 m=g_new0(struct map_priv, 1);
2966 m->cbl = cbl;
2967 m->id = ++map_id;
2968 m->filename = g_strdup(wexp_data[0]);
2969 file_wordexp_destroy(wexp);
2970 check_version = attr_search(attrs, NULL, attr_check_version);
2971 if (check_version)
2972 m->check_version = check_version->u.num;
2973 map_pass = attr_search(attrs, NULL, attr_map_pass);
2974 if (map_pass)
2975 m->passwd = g_strdup(map_pass->u.str);
2976 flags = attr_search(attrs, NULL, attr_flags);
2977 if (flags)
2978 m->flags = flags->u.num;
2979 url = attr_search(attrs, NULL, attr_url);
2980 if (url)
2981 m->url = g_strdup(url->u.str);
2982 download_enabled = attr_search(attrs, NULL, attr_update);
2983 if (download_enabled)
2984 m->download_enabled = download_enabled->u.num;
2985
2986 if (!map_binfile_open(m) && !m->check_version && !m->url)
2987 {
2988 map_binfile_destroy(m);
2989 m = NULL;
2990 }
2991 else
2992 {
2993 load_changes(m);
2994 }
2995 return m;
2996 }
2997
2998 void plugin_init(void)
2999 {
3000 // dbg(1, "binfile: plugin_init\n");
3001 if (sizeof(struct zip_cd) != 46)
3002 {
3003 // dbg(0, "error: sizeof(struct zip_cd)=%d\n", sizeof(struct zip_cd));
3004 }
3005 plugin_register_map_type("binfile", map_new_binfile);
3006 }
3007

   
Visit the ZANavi Wiki