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

   
Visit the ZANavi Wiki