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

   
Visit the ZANavi Wiki