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