/[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 - (hide 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 zoff99 2 /**
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