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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki