2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
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.
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.
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.
28 #include "projection.h"
34 #include "transform.h"
37 #include "linguistics.h"
38 #include "endianess.h"
46 * @brief A map tile, a rectangular region of the world.
48 * Represents a "map tile", a rectangular region of the world. The
49 * binfile format divides the world into tiles of different sizes for
51 * A binfile is a ZIP archive; each member file (with the exception of
52 * index files) represents one tile. The data from a tile file is read
53 * into memory and used directly as the tile data of this struct.
55 * See the Navit wiki for details on the binfile format:
57 * http://wiki.navit-project.org/index.php/Navit%27s_binary_map_driver
59 * Note that this tile struct also maintains pointers to several current positions
60 * inside the tile. These are not part of the actual tile data, but are
61 * used for working with the data.
64 int *start; //!< Memory address of the buffer containing the tile data (the actual map data).
65 int *end; //!< First memory address not belonging to the tile data.
66 /**< Thus tile->end - tile->start represents the size of the tile data
67 * in multiples of 4 Bytes.
69 int *pos; //!< Pointer to current position (start of current item) inside the tile data.
70 int *pos_coord_start; //!< Pointer to the first element inside the current item that is a coordinate.
71 /**< That is the first position after the header of an
72 * item. The header holds 3 entries each 32bit wide integers:
73 * header[0] holds the size of the whole item (excluding this size field)
74 * header[1] holds the type of the item
75 * header[2] holds the size of the coordinates in the tile
77 int *pos_coord; //!< Current position in the coordinates region of the current item.
78 int *pos_attr_start; //!< Pointer to the first attr data structure of the current item.
79 int *pos_attr; //!< Current position in the attr region of the current item.
80 int *pos_next; //!< Pointer to the next item (the item which follows the "current item" as indicated by *pos).
81 struct file *fi; //!< The file from which this tile was loaded.
90 struct map_rect_priv *mr;
91 struct file *http,*file;
92 int zipfile,toffset,tlength,progress,read,dl_size;
93 long long offset,start_offset,cd1offset,size;
94 struct zip64_eoc *zip64_eoc;
95 struct zip64_eocl *zip64_eocl;
96 struct zip_eoc *zip_eoc;
97 struct zip_cd *cd_copy,*cd;
101 * @brief Represents the map from a single binfile.
106 char *filename; //!< Filename of the binfile.
108 struct file *fi,*http;
110 struct zip_cd *index_cd;
114 struct zip64_eoc *eoc64;
116 unsigned char *search_data;
127 int update_available;
129 struct callback_list *cbl;
130 struct map_download *download;
132 long download_enabled;
135 struct map_rect_priv {
138 enum attr_type attr_last;
141 struct map_selection *sel;
145 struct tile tiles[8];
149 struct attr attrs[8];
157 * @brief Represents a search on a map.
158 * This struct represents a search on a map; it is created
159 * when starting a search, and is used for retrieving results.
161 struct map_search_priv {
162 struct map_priv *map;
163 struct map_rect_priv *mr;
164 struct map_rect_priv *mr_item;
167 struct map_selection ms;
170 GHashTable *search_results;
174 static void push_tile(struct map_rect_priv *mr, struct tile *t, int offset, int length);
175 static void setup_pos(struct map_rect_priv *mr);
176 static void map_binfile_close(struct map_priv *m);
177 static int map_binfile_open(struct map_priv *m);
178 static void map_binfile_destroy(struct map_priv *m);
180 static void lfh_to_cpu(struct zip_lfh *lfh) {
181 dbg_assert(lfh != NULL);
182 if (lfh->ziplocsig != zip_lfh_sig) {
183 lfh->ziplocsig = le32_to_cpu(lfh->ziplocsig);
184 lfh->zipver = le16_to_cpu(lfh->zipver);
185 lfh->zipgenfld = le16_to_cpu(lfh->zipgenfld);
186 lfh->zipmthd = le16_to_cpu(lfh->zipmthd);
187 lfh->ziptime = le16_to_cpu(lfh->ziptime);
188 lfh->zipdate = le16_to_cpu(lfh->zipdate);
189 lfh->zipcrc = le32_to_cpu(lfh->zipcrc);
190 lfh->zipsize = le32_to_cpu(lfh->zipsize);
191 lfh->zipuncmp = le32_to_cpu(lfh->zipuncmp);
192 lfh->zipfnln = le16_to_cpu(lfh->zipfnln);
193 lfh->zipxtraln = le16_to_cpu(lfh->zipxtraln);
197 static void cd_to_cpu(struct zip_cd *zcd) {
198 dbg_assert(zcd != NULL);
199 if (zcd->zipcensig != zip_cd_sig) {
200 zcd->zipcensig = le32_to_cpu(zcd->zipcensig);
201 zcd->zipccrc = le32_to_cpu(zcd->zipccrc);
202 zcd->zipcsiz = le32_to_cpu(zcd->zipcsiz);
203 zcd->zipcunc = le32_to_cpu(zcd->zipcunc);
204 zcd->zipcfnl = le16_to_cpu(zcd->zipcfnl);
205 zcd->zipcxtl = le16_to_cpu(zcd->zipcxtl);
206 zcd->zipccml = le16_to_cpu(zcd->zipccml);
207 zcd->zipdsk = le16_to_cpu(zcd->zipdsk);
208 zcd->zipint = le16_to_cpu(zcd->zipint);
209 zcd->zipext = le32_to_cpu(zcd->zipext);
210 zcd->zipofst = le32_to_cpu(zcd->zipofst);
214 static void eoc_to_cpu(struct zip_eoc *eoc) {
215 dbg_assert(eoc != NULL);
216 if (eoc->zipesig != zip_eoc_sig) {
217 eoc->zipesig = le32_to_cpu(eoc->zipesig);
218 eoc->zipedsk = le16_to_cpu(eoc->zipedsk);
219 eoc->zipecen = le16_to_cpu(eoc->zipecen);
220 eoc->zipenum = le16_to_cpu(eoc->zipenum);
221 eoc->zipecenn = le16_to_cpu(eoc->zipecenn);
222 eoc->zipecsz = le32_to_cpu(eoc->zipecsz);
223 eoc->zipeofst = le32_to_cpu(eoc->zipeofst);
224 eoc->zipecoml = le16_to_cpu(eoc->zipecoml);
228 static void binfile_check_version(struct map_priv *m);
230 static struct zip_eoc *
231 binfile_read_eoc(struct file *fi)
234 eoc=(struct zip_eoc *)file_data_read(fi,fi->size-sizeof(struct zip_eoc), sizeof(struct zip_eoc));
237 dbg(1,"sig 0x%x\n", eoc->zipesig);
238 if (eoc->zipesig != zip_eoc_sig) {
239 dbg(0,"eoc signature check failed: 0x%x vs 0x%x\n",eoc->zipesig,zip_eoc_sig);
240 file_data_free(fi,(unsigned char *)eoc);
247 static struct zip64_eoc *
248 binfile_read_eoc64(struct file *fi)
250 struct zip64_eocl *eocl;
251 struct zip64_eoc *eoc;
252 eocl=(struct zip64_eocl *)file_data_read(fi,fi->size-sizeof(struct zip_eoc)-sizeof(struct zip64_eocl), sizeof(struct zip64_eocl));
255 dbg(1,"sig 0x%x\n", eocl->zip64lsig);
256 if (eocl->zip64lsig != zip64_eocl_sig) {
257 file_data_free(fi,(unsigned char *)eocl);
258 dbg(1,"eocl wrong\n");
261 eoc=(struct zip64_eoc *)file_data_read(fi,eocl->zip64lofst, sizeof(struct zip64_eoc));
263 if (eoc->zip64esig != zip64_eoc_sig) {
264 file_data_free(fi,(unsigned char *)eoc);
265 dbg(1,"eoc wrong\n");
268 dbg(1,"eoc64 ok 0x%Lx 0x%Lx\n",eoc->zip64eofst,eoc->zip64ecsz);
270 file_data_free(fi,(unsigned char *)eocl);
275 binfile_cd_extra(struct zip_cd *cd)
277 return cd->zipcfnl+cd->zipcxtl;
280 static struct zip_cd *
281 binfile_read_cd(struct map_priv *m, int offset, int len)
284 long long cdoffset=m->eoc64?m->eoc64->zip64eofst:m->eoc->zipeofst;
286 cd=(struct zip_cd *)file_data_read(m->fi,cdoffset+offset, sizeof(*cd));
288 len=binfile_cd_extra(cd);
289 file_data_free(m->fi,(unsigned char *)cd);
291 cd=(struct zip_cd *)file_data_read(m->fi,cdoffset+offset, sizeof(*cd)+len);
293 dbg(1,"cd at "LONGLONG_FMT" %d bytes\n",cdoffset+offset, sizeof(*cd)+len);
295 dbg(1,"sig 0x%x\n", cd->zipcensig);
296 if (cd->zipcensig != zip_cd_sig) {
297 file_data_free(m->fi,(unsigned char *)cd);
305 * @brief Get the ZIP64 extra field data corresponding to a zip central
308 * @param cd pointer to zip central directory structure
309 * @return pointer to ZIP64 extra field, or NULL if not available
311 static struct zip_cd_ext *
312 binfile_cd_ext(struct zip_cd *cd)
314 struct zip_cd_ext *ext;
315 if (cd->zipofst != zip_size_64bit_placeholder)
317 if (cd->zipcxtl != sizeof(*ext))
319 ext=(struct zip_cd_ext *)((unsigned char *)cd+sizeof(*cd)+cd->zipcfnl);
320 if (ext->tag != zip_extra_header_id_zip64 || ext->size != 8)
326 * @param cd pointer to zip central directory structure
327 * @return Offset of local file header in zip file.
328 * Will use ZIP64 data if present.
331 binfile_cd_offset(struct zip_cd *cd)
333 struct zip_cd_ext *ext=binfile_cd_ext(cd);
340 static struct zip_lfh *
341 binfile_read_lfh(struct file *fi, long long offset)
345 lfh=(struct zip_lfh *)(file_data_read(fi,offset,sizeof(struct zip_lfh)));
348 if (lfh->ziplocsig != zip_lfh_sig) {
349 file_data_free(fi,(unsigned char *)lfh);
356 static unsigned char *
357 binfile_read_content(struct map_priv *m, struct file *fi, long long offset, struct zip_lfh *lfh)
360 unsigned char *ret=NULL;
362 offset+=sizeof(struct zip_lfh)+lfh->zipfnln;
363 switch (lfh->zipmthd) {
365 offset+=lfh->zipxtraln;
366 ret=file_data_read(fi,offset, lfh->zipuncmp);
369 offset+=lfh->zipxtraln;
370 ret=file_data_read_compressed(fi,offset, lfh->zipsize, lfh->zipuncmp);
375 enc=(struct zip_enc *)file_data_read(fi, offset, sizeof(*enc));
376 offset+=lfh->zipxtraln;
377 switch (enc->compress_method) {
379 ret=file_data_read_encrypted(fi, offset, lfh->zipsize, lfh->zipuncmp, 0, m->passwd);
382 ret=file_data_read_encrypted(fi, offset, lfh->zipsize, lfh->zipuncmp, 1, m->passwd);
385 dbg(0,"Unknown encrypted compression method %d\n",enc->compress_method);
387 file_data_free(fi, (unsigned char *)enc);
390 dbg(0,"Unknown compression method %d\n", lfh->zipmthd);
396 binfile_search_cd(struct map_priv *m, int offset, char *name, int partial, int skip)
399 int end=m->eoc64?m->eoc64->zip64ecsz:m->eoc->zipecsz;
400 int len=strlen(name);
401 long long cdoffset=m->eoc64?m->eoc64->zip64eofst:m->eoc->zipeofst;
404 dbg(0,"end=%d\n",end);
406 while (offset < end) {
407 cd=(struct zip_cd *)(m->search_data+offset-m->search_offset);
408 if (! m->search_data ||
409 m->search_offset > offset ||
410 offset-m->search_offset+sizeof(*cd) > m->search_size ||
411 offset-m->search_offset+sizeof(*cd)+cd->zipcfnl+cd->zipcxtl > m->search_size
414 dbg(0,"reload %p %d %d\n", m->search_data, m->search_offset, offset);
417 file_data_free(m->fi,m->search_data);
418 m->search_offset=offset;
419 m->search_size=end-offset;
420 if (m->search_size > size)
422 m->search_data=file_data_read(m->fi,cdoffset+m->search_offset,m->search_size);
423 cd=(struct zip_cd *)m->search_data;
426 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);
427 dbg(0,"offset=%d fn='%s'\n",offset,cd->zipcfn);
430 (partial || cd->zipcfnl == len) &&
431 !strncmp(cd->zipcfn, name, len))
434 offset+=sizeof(*cd)+cd->zipcfnl+cd->zipcxtl+cd->zipccml;
441 map_destroy_binfile(struct map_priv *m)
443 dbg(1,"map_destroy_binfile\n");
445 map_binfile_close(m);
446 map_binfile_destroy(m);
450 binfile_coord_rewind(void *priv_data)
452 struct map_rect_priv *mr=priv_data;
453 struct tile *t=mr->t;
454 t->pos_coord=t->pos_coord_start;
458 binfile_coord_get(void *priv_data, struct coord *c, int count)
460 struct map_rect_priv *mr=priv_data;
461 struct tile *t=mr->t;
463 max=(t->pos_attr_start-t->pos_coord)/2;
466 #if __BYTE_ORDER == __LITTLE_ENDIAN
467 memcpy(c, t->pos_coord, count*sizeof(struct coord));
470 int i=0,end=count*sizeof(struct coord)/sizeof(int);
471 int *src=(int *)t->pos_coord;
474 *dst++=le32_to_cpu(*src);
479 t->pos_coord+=count*2;
490 binfile_attr_rewind(void *priv_data)
492 struct map_rect_priv *mr=priv_data;
493 struct tile *t=mr->t;
494 t->pos_attr=t->pos_attr_start;
496 memset(mr->label_attr, 0, sizeof(mr->label_attr));
501 binfile_extract(struct map_priv *m, char *dir, char *filename, int partial)
503 char *full,*fulld,*sep;
504 unsigned char *start;
505 int len,offset=m->index_offset;
511 offset=binfile_search_cd(m, offset, filename, partial, 1);
514 cd=binfile_read_cd(m, offset, -1);
515 len=strlen(dir)+1+cd->zipcfnl+1;
518 strcpy(full+strlen(full),"/");
519 strncpy(full+strlen(full),cd->zipcfn,cd->zipcfnl);
521 fulld=g_strdup(full);
522 sep=strrchr(fulld, '/');
525 file_mkdir(fulld, 1);
527 if (full[len-2] != '/') {
528 lfh=binfile_read_lfh(m->fi, binfile_cd_offset(cd));
529 start=binfile_read_content(m, m->fi, binfile_cd_offset(cd), lfh);
530 dbg(0,"fopen '%s'\n", full);
532 fwrite(start, lfh->zipuncmp, 1, f);
534 file_data_free(m->fi, start);
535 file_data_free(m->fi, (unsigned char *)lfh);
537 file_data_free(m->fi, (unsigned char *)cd);
544 return g_strdup_printf("%s/%s",dir,filename);
548 binfile_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
550 struct map_rect_priv *mr=priv_data;
551 struct tile *t=mr->t;
555 if (attr_type != mr->attr_last) {
556 t->pos_attr=t->pos_attr_start;
557 mr->attr_last=attr_type;
559 while (t->pos_attr < t->pos_next) {
560 size=le32_to_cpu(*(t->pos_attr++));
561 type=le32_to_cpu(t->pos_attr[0]);
562 if (type == attr_label)
564 if (type == attr_house_number)
565 mr->label_attr[0]=t->pos_attr;
566 if (type == attr_street_name)
567 mr->label_attr[1]=t->pos_attr;
568 if (type == attr_street_name_systematic)
569 mr->label_attr[2]=t->pos_attr;
570 if (type == attr_district_name && mr->item.type < type_line)
571 mr->label_attr[3]=t->pos_attr;
572 if (type == attr_town_name && mr->item.type < type_line)
573 mr->label_attr[4]=t->pos_attr;
574 if (type == attr_type || attr_type == attr_any) {
575 if (attr_type == attr_any) {
576 dbg(1,"pos %p attr %s size %d\n", t->pos_attr-1, attr_to_name(type), size);
579 if (ATTR_IS_GROUP(type)) {
581 int *subpos=t->pos_attr+1;
584 while (size_rem > 0 && i < 7) {
585 int subsize=le32_to_cpu(*subpos++);
586 int subtype=le32_to_cpu(subpos[0]);
587 mr->attrs[i].type=subtype;
588 attr_data_set_le(&mr->attrs[i], subpos+1);
593 mr->attrs[i].type=type_none;
594 mr->attrs[i].u.data=NULL;
595 attr->u.attrs=mr->attrs;
597 attr_data_set_le(attr, t->pos_attr+1);
598 if (type == attr_url_local) {
600 mr->url=binfile_extract(mr->m, mr->m->cachedir, attr->u.str, 1);
603 if (type == attr_flags && mr->m->map_version < 1)
604 attr->u.num |= AF_CAR;
612 if (!mr->label && (attr_type == attr_any || attr_type == attr_label)) {
613 for (i = 0 ; i < sizeof(mr->label_attr)/sizeof(int *) ; i++) {
614 if (mr->label_attr[i]) {
616 attr->type=attr_label;
617 attr_data_set_le(attr,mr->label_attr[i]+1);
625 struct binfile_hash_entry {
632 binfile_hash_entry_hash(gconstpointer key)
634 const struct binfile_hash_entry *entry=key;
635 return (entry->id.id_hi ^ entry->id.id_lo);
639 binfile_hash_entry_equal(gconstpointer a, gconstpointer b)
641 const struct binfile_hash_entry *entry1=a,*entry2=b;
642 return (entry1->id.id_hi==entry2->id.id_hi && entry1->id.id_lo == entry2->id.id_lo);
646 binfile_item_dup(struct map_priv *m, struct item *item, struct tile *t, int extend)
648 int size=le32_to_cpu(t->pos[0]);
649 struct binfile_hash_entry *entry=g_malloc(sizeof(struct binfile_hash_entry)+(size+1+extend)*sizeof(int));
650 void *ret=entry->data;
651 entry->id.id_hi=item->id_hi;
652 entry->id.id_lo=item->id_lo;
654 dbg(0,"id 0x%x,0x%x\n",entry->id.id_hi,entry->id.id_lo);
656 memcpy(ret, t->pos, (size+1)*sizeof(int));
658 m->changes=g_hash_table_new_full(binfile_hash_entry_hash, binfile_hash_entry_equal, g_free, NULL);
659 g_hash_table_replace(m->changes, entry, entry);
660 dbg(0,"ret %p\n",ret);
665 binfile_coord_set(void *priv_data, struct coord *c, int count, enum change_mode mode)
667 struct map_rect_priv *mr=priv_data;
668 struct tile *t=mr->t,*tn,new;
669 int i,delta,move_len;
670 int write_offset,move_offset,aoffset,coffset,clen;
675 dbg(0,"Before: pos_coord=%d\n",t->pos_coord-i);
676 while (i < t->pos_next)
677 dbg(0,"%d:0x%x\n",j++,*i++);
680 aoffset=t->pos_attr-t->pos_attr_start;
681 coffset=t->pos_coord-t->pos_coord_start-2;
682 clen=t->pos_attr_start-t->pos_coord+2;
683 dbg(0,"coffset=%d clen=%d\n",coffset,clen);
685 case change_mode_delete:
689 move_offset=coffset+count*2;
690 move_len=t->pos_next-t->pos_coord_start-move_offset;
693 case change_mode_modify:
694 write_offset=coffset;
695 if (count*2 > clen) {
697 move_offset=t->pos_attr_start-t->pos_coord_start;
698 move_len=t->pos_next-t->pos_coord_start-move_offset;
705 case change_mode_prepend:
707 move_offset=coffset-2;
708 move_len=t->pos_next-t->pos_coord_start-move_offset;
709 write_offset=coffset-2;
711 case change_mode_append:
714 move_len=t->pos_next-t->pos_coord_start-move_offset;
715 write_offset=coffset;
720 dbg(0,"delta %d\n",delta);
721 data=binfile_item_dup(mr->m, &mr->item, t, delta > 0 ? delta:0);
722 data[0]=cpu_to_le32(le32_to_cpu(data[0])+delta);
723 data[2]=cpu_to_le32(le32_to_cpu(data[2])+delta);
724 new.pos=new.start=data;
725 new.zipfile_num=t->zipfile_num;
727 push_tile(mr, &new, 0, 0);
730 tn->pos_coord=tn->pos_coord_start+coffset;
731 tn->pos_attr=tn->pos_attr_start+aoffset;
732 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);
733 memmove(tn->pos_coord_start+move_offset+delta, tn->pos_coord_start+move_offset, move_len*4);
736 dbg(0,"After move: pos_coord=%d\n",tn->pos_coord-i);
737 while (i < tn->pos_next)
738 dbg(0,"%d:0x%x\n",j++,*i++);
740 if (mode != change_mode_append)
741 tn->pos_coord+=move_offset;
742 if (mode != change_mode_delete) {
743 dbg(0,"writing %d ints at offset %d\n",count*2,write_offset+tn->pos_coord_start-data);
744 for (i = 0 ; i < count ; i++) {
745 tn->pos_coord_start[write_offset++]=c[i].x;
746 tn->pos_coord_start[write_offset++]=c[i].y;
752 dbg(0,"After: pos_coord=%d\n",tn->pos_coord-i);
753 while (i < tn->pos_next)
754 dbg(0,"%d:0x%x\n",j++,*i++);
760 binfile_attr_set(void *priv_data, struct attr *attr, enum change_mode mode)
762 struct map_rect_priv *mr=priv_data;
763 struct tile *t=mr->t,*tn,new;
764 int offset,delta,move_len;
765 int write_offset,move_offset,naoffset,coffset,oattr_len;
766 int nattr_size,nattr_len,pad;
771 dbg(0,"Before: pos_attr=%d\n",t->pos_attr-i);
772 while (i < t->pos_next)
773 dbg(0,"%d:0x%x\n",j++,*i++);
778 naoffset=t->pos_attr-t->pos_attr_start;
779 coffset=t->pos_coord-t->pos_coord_start;
783 if (mode == change_mode_delete || mode == change_mode_modify) {
784 dbg(0,"no attribute selected\n");
787 if (mode == change_mode_append)
788 naoffset=t->pos_next-t->pos_attr_start;
790 while (offset < naoffset) {
791 oattr_len=le32_to_cpu(t->pos_attr_start[offset])+1;
792 dbg(0,"len %d\n",oattr_len);
796 move_len=t->pos_next-t->pos_attr_start-offset;
799 case change_mode_delete:
804 case change_mode_modify:
805 case change_mode_prepend:
806 case change_mode_append:
807 nattr_size=attr_data_size(attr);
808 pad=(4-(nattr_size%4))%4;
809 nattr_len=(nattr_size+pad)/4+2;
810 if (mode == change_mode_prepend) {
811 move_offset=write_offset;
814 if (mode == change_mode_append) {
815 write_offset=move_offset;
821 if (mode == change_mode_delete || mode == change_mode_modify)
822 delta=nattr_len-oattr_len;
825 dbg(0,"delta %d oattr_len %d nattr_len %d\n",delta,oattr_len, nattr_len);
826 data=binfile_item_dup(mr->m, &mr->item, t, delta > 0 ? delta:0);
827 data[0]=cpu_to_le32(le32_to_cpu(data[0])+delta);
828 new.pos=new.start=data;
829 new.zipfile_num=t->zipfile_num;
831 push_tile(mr, &new, 0, 0);
834 tn->pos_coord=tn->pos_coord_start+coffset;
835 tn->pos_attr=tn->pos_attr_start+offset;
836 dbg(0,"attr start %d offset %d\n",tn->pos_attr_start-data,offset);
837 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);
838 memmove(tn->pos_attr_start+move_offset+delta, tn->pos_attr_start+move_offset, move_len*4);
839 if (mode != change_mode_append)
843 dbg(0,"After move: pos_attr=%d\n",tn->pos_attr-i);
844 while (i < tn->pos_next)
845 dbg(0,"%d:0x%x\n",j++,*i++);
848 int *nattr=tn->pos_attr_start+write_offset;
849 dbg(0,"writing %d ints at %d\n",nattr_len,nattr-data);
850 nattr[0]=cpu_to_le32(nattr_len-1);
851 nattr[1]=cpu_to_le32(attr->type);
852 memcpy(nattr+2, attr_data_get(attr), nattr_size);
853 memset((unsigned char *)(nattr+2)+nattr_size, 0, pad);
857 dbg(0,"After: pos_attr=%d\n",tn->pos_attr-i);
858 while (i < tn->pos_next)
859 dbg(0,"%d:0x%x\n",j++,*i++);
864 static struct item_methods methods_binfile = {
865 binfile_coord_rewind,
875 push_tile(struct map_rect_priv *mr, struct tile *t, int offset, int length)
877 dbg_assert(mr->tile_depth < 8);
878 mr->t=&mr->tiles[mr->tile_depth++];
880 mr->t->pos=mr->t->pos_next=mr->t->start+offset;
882 length=le32_to_cpu(mr->t->pos[0])+1;
884 mr->t->end=mr->t->pos+length;
888 pop_tile(struct map_rect_priv *mr)
890 if (mr->tile_depth <= 1)
893 file_data_free(mr->m->fi, (unsigned char *)(mr->t->start));
896 dbg(0,"leave %d\n",mr->t->zipfile_num);
899 mr->t=&mr->tiles[--mr->tile_depth-1];
905 zipfile_to_tile(struct map_priv *m, struct zip_cd *cd, struct tile *t)
911 dbg(1,"enter %p %p %p\n", m, cd, t);
912 dbg(1,"cd->zipofst=0x%Lx\n", binfile_cd_offset(cd));
916 fi=m->fis[cd->zipdsk];
919 lfh=binfile_read_lfh(fi, binfile_cd_offset(cd));
920 zipfn=(char *)(file_data_read(fi,binfile_cd_offset(cd)+sizeof(struct zip_lfh), lfh->zipfnln));
921 strncpy(buffer, zipfn, lfh->zipfnln);
922 buffer[lfh->zipfnln]='\0';
923 t->start=(int *)binfile_read_content(m, fi, binfile_cd_offset(cd), lfh);
924 t->end=t->start+lfh->zipuncmp/4;
926 dbg(1,"0x%x '%s' %d %d,%d\n", lfh->ziplocsig, buffer, sizeof(*cd)+cd->zipcfnl, lfh->zipsize, lfh->zipuncmp);
927 file_data_free(fi, (unsigned char *)zipfn);
928 file_data_free(fi, (unsigned char *)lfh);
929 return t->start != NULL;
934 map_binfile_handle_redirect(struct map_priv *m)
936 char *location=file_http_header(m->http, "location");
944 dbg(0,"redirected from %s to %s\n",m->url,location);
946 m->url=g_strdup(location);
947 file_destroy(m->http);
954 map_binfile_http_request(struct map_priv *m, struct attr **attrs)
957 m->http=file_create(NULL, attrs);
959 file_request(m->http, attrs);
966 map_binfile_download_size(struct map_priv *m)
968 struct attr url={attr_url};
969 struct attr http_method={attr_http_method};
970 struct attr persistent={attr_persistent};
971 struct attr *attrs[4];
979 attrs[1]=&http_method;
980 http_method.u.str="HEAD";
982 attrs[2]=&persistent;
985 map_binfile_http_request(m, attrs);
986 data=file_data_read_special(m->http, 0, &size_ret);
990 } while (map_binfile_handle_redirect(m));
992 ret=file_size(m->http);
993 dbg(1,"file size "LONGLONG_FMT"\n",ret);
999 map_binfile_http_close(struct map_priv *m)
1002 file_destroy(m->http);
1009 static struct file *
1010 map_binfile_http_range(struct map_priv *m, long long offset, int size)
1012 struct attr *attrs[4];
1013 struct attr url={attr_url};
1014 struct attr http_header={attr_http_header};
1015 struct attr persistent={attr_persistent};
1019 attrs[1]=&http_header;
1020 attrs[2]=&persistent;
1024 http_header.u.str=g_strdup_printf("Range: bytes="LONGLONG_FMT"-"LONGLONG_FMT,offset, offset+size-1);
1025 map_binfile_http_request(m, attrs);
1026 g_free(http_header.u.str);
1030 static unsigned char *
1031 map_binfile_download_range(struct map_priv *m, long long offset, int size)
1035 struct file *http=map_binfile_http_range(m, offset, size);
1037 ret=file_data_read_special(http, size, &size_ret);
1038 if (size_ret != size) {
1039 dbg(0,"size %d vs %d\n",size,size_ret);
1046 static struct zip_cd *
1047 download_cd(struct map_download *download)
1049 struct map_priv *m=download->m;
1050 struct zip64_eoc *zip64_eoc=(struct zip64_eoc *)file_data_read(m->fi, 0, sizeof(*zip64_eoc));
1051 struct zip_cd *cd=(struct zip_cd *)map_binfile_download_range(m, zip64_eoc->zip64eofst+download->zipfile*m->cde_size,m->cde_size);
1052 file_data_free(m->fi, (unsigned char *)zip64_eoc);
1053 dbg(0,"needed cd, result %p\n",cd);
1058 download_request(struct map_download *download)
1060 struct attr url={attr_url};
1061 struct attr http_header={attr_http_header};
1062 struct attr persistent={attr_persistent};
1063 struct attr *attrs[4];
1065 if(!download->m->download_enabled)
1067 dbg(0,"Tried downloading while it's not allowed\n");
1072 attrs[1]=&persistent;
1074 if (strchr(download->m->url,'?')) {
1075 url.u.str=g_strdup_printf("%smemberid=%d",download->m->url,download->zipfile);
1076 download->dl_size=-1;
1078 long long offset=binfile_cd_offset(download->cd_copy);
1079 int size=download->cd_copy->zipcsiz+sizeof(struct zip_lfh)+download->cd_copy->zipcfnl;
1080 url.u.str=g_strdup(download->m->url);
1081 http_header.u.str=g_strdup_printf("Range: bytes="LONGLONG_FMT"-"LONGLONG_FMT,offset,offset+size-1);
1082 attrs[2]=&http_header;
1084 download->dl_size=size;
1086 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);
1087 map_binfile_http_request(download->m, attrs);
1089 download->http=download->m->http;
1095 download_start(struct map_download *download)
1098 struct zip_eoc *eoc;
1100 if (!download->cd->zipcensig) {
1101 download->cd_copy=download_cd(download);
1103 download->cd_copy=g_malloc(download->m->cde_size);
1104 memcpy(download->cd_copy, download->cd, download->m->cde_size);
1106 file_data_remove(download->file, (unsigned char *)download->cd);
1108 offset=file_size(download->file);
1109 offset-=sizeof(struct zip_eoc);
1110 eoc=(struct zip_eoc *)file_data_read(download->file, offset, sizeof(struct zip_eoc));
1111 download->zip_eoc=g_malloc(sizeof(struct zip_eoc));
1112 memcpy(download->zip_eoc, eoc, sizeof(struct zip_eoc));
1113 file_data_remove(download->file, (unsigned char *)eoc);
1114 download->start_offset=download->offset=offset;
1115 return download_request(download);
1119 download_download(struct map_download *download)
1121 int size=64*1024,size_ret;
1122 unsigned char *data;
1123 if (download->dl_size != -1 && size > download->dl_size)
1124 size=download->dl_size;
1127 data=file_data_read_special(download->http, size, &size_ret);
1128 if (!download->read && download->m->http && map_binfile_handle_redirect(download->m)) {
1130 download_request(download);
1134 dbg(1,"got %d bytes writing at offset "LONGLONG_FMT"\n",size_ret,download->offset);
1135 if (size_ret <= 0) {
1139 file_data_write(download->file, download->offset, size_ret, data);
1140 download->offset+=size_ret;
1141 download->read+=size_ret;
1142 download->dl_size-=size_ret;
1143 if (download->dl_size != -1)
1144 download->progress=download->read*100/(download->read+download->dl_size);
1149 download_finish(struct map_download *download)
1151 struct zip_lfh *lfh;
1153 struct zip_cd_ext *ext;
1154 long long lfh_offset;
1155 file_data_write(download->file, download->offset, sizeof(struct zip_eoc), (void *)download->zip_eoc);
1156 lfh=(struct zip_lfh *)(file_data_read(download->file,download->start_offset, sizeof(struct zip_lfh)));
1157 ext=binfile_cd_ext(download->cd_copy);
1159 ext->zipofst=download->start_offset;
1161 download->cd_copy->zipofst=download->start_offset;
1162 download->cd_copy->zipcsiz=lfh->zipsize;
1163 download->cd_copy->zipcunc=lfh->zipuncmp;
1164 download->cd_copy->zipccrc=lfh->zipcrc;
1165 lfh_offset = binfile_cd_offset(download->cd_copy)+sizeof(struct zip_lfh);
1166 lfh_filename=(char *)file_data_read(download->file,lfh_offset,lfh->zipfnln);
1167 memcpy(download->cd_copy+1,lfh_filename,lfh->zipfnln);
1168 file_data_remove(download->file,(void *)lfh_filename);
1169 file_data_remove(download->file,(void *)lfh);
1170 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);
1171 file_data_flush(download->file, download->m->eoc->zipeofst + download->zipfile*download->m->cde_size, sizeof(struct zip_cd));
1173 g_free(download->cd_copy);
1174 download->cd=(struct zip_cd *)(file_data_read(download->file, download->m->eoc->zipeofst + download->zipfile*download->m->cde_size, download->m->cde_size));
1175 cd_to_cpu(download->cd);
1176 dbg(1,"Offset %d\n",download->cd->zipofst);
1181 download_planet_size(struct map_download *download)
1183 download->size=map_binfile_download_size(download->m);
1184 dbg(0,"Planet size "LONGLONG_FMT"\n",download->size);
1185 if (!download->size)
1191 download_eoc(struct map_download *download)
1193 download->zip64_eoc=(struct zip64_eoc *)map_binfile_download_range(download->m, download->size-98, 98);
1194 if (!download->zip64_eoc)
1196 download->zip64_eocl=(struct zip64_eocl *)(download->zip64_eoc+1);
1197 download->zip_eoc=(struct zip_eoc *)(download->zip64_eocl+1);
1198 if (download->zip64_eoc->zip64esig != zip64_eoc_sig || download->zip64_eocl->zip64lsig != zip64_eocl_sig || download->zip_eoc->zipesig != zip_eoc_sig)
1200 dbg(0,"wrong signature on zip64_eoc downloaded from "LONGLONG_FMT"\n",download->size-98);
1201 g_free(download->zip64_eoc);
1208 download_directory_start(struct map_download *download)
1210 download->http=map_binfile_http_range(download->m, download->zip64_eoc->zip64eofst, download->zip64_eoc->zip64ecsz);
1211 if (!download->http)
1217 download_directory_do(struct map_download *download)
1221 for (count = 0 ; count < 100 ; count++) {
1222 int cd_xlen, size_ret;
1223 unsigned char *cd_data;
1225 cd=(struct zip_cd *)file_data_read_special(download->http, sizeof(*cd), &size_ret);
1227 dbg(1,"size_ret=%d\n",size_ret);
1230 if (size_ret != sizeof(*cd) || cd->zipcensig != zip_cd_sig) {
1231 dbg(0,"error1 size=%d vs %d\n",size_ret, sizeof(*cd));
1234 file_data_write(download->file, download->offset, sizeof(*cd), (unsigned char *)cd);
1235 download->offset+=sizeof(*cd);
1236 cd_xlen=cd->zipcfnl+cd->zipcxtl;
1237 cd_data=file_data_read_special(download->http, cd_xlen, &size_ret);
1238 if (size_ret != cd_xlen) {
1239 dbg(0,"error2 size=%d vs %d\n",size_ret,cd_xlen);
1242 file_data_write(download->file, download->offset, cd_xlen, cd_data);
1243 download->offset+=cd_xlen;
1251 download_directory_finish(struct map_download *download)
1253 download->http=NULL;
1258 download_initial_finish(struct map_download *download)
1260 download->zip64_eoc->zip64eofst=download->cd1offset;
1261 download->zip64_eocl->zip64lofst=download->offset;
1262 download->zip_eoc->zipeofst=download->cd1offset;
1264 file_data_write(download->file, download->offset, sizeof(*download->zip64_eoc), (unsigned char *)download->zip64_eoc);
1265 download->offset+=sizeof(*download->zip64_eoc);
1266 file_data_write(download->file, download->offset, sizeof(*download->zip64_eocl), (unsigned char *)download->zip64_eocl);
1267 download->offset+=sizeof(*download->zip64_eocl);
1269 file_data_write(download->file, download->offset, sizeof(*download->zip_eoc), (unsigned char *)download->zip_eoc);
1270 download->offset+=sizeof(*download->zip_eoc);
1271 g_free(download->zip64_eoc);
1272 download->zip64_eoc=NULL;
1277 push_zipfile_tile_do(struct map_rect_priv *mr, struct zip_cd *cd, int zipfile, int offset, int length)
1281 struct map_priv *m=mr->m;
1282 struct file *f=m->fi;
1284 dbg(1,"enter %p %d\n", mr, zipfile);
1288 char filename[cd->zipcfnl+1];
1289 memcpy(filename, cd+1, cd->zipcfnl);
1290 filename[cd->zipcfnl]='\0';
1291 dbg(0,"enter %d (%s) %d\n",zipfile, filename, cd->zipcunc);
1294 mr->size+=cd->zipcunc;
1296 t.zipfile_num=zipfile;
1297 if (zipfile_to_tile(m, cd, &t))
1298 push_tile(mr, &t, offset, length);
1299 file_data_free(f, (unsigned char *)cd);
1303 static struct zip_cd *
1304 download(struct map_priv *m, struct map_rect_priv *mr, struct zip_cd *cd, int zipfile, int offset, int length, int async)
1306 struct map_download *download;
1308 if(!m->download_enabled)
1312 download=m->download;
1314 download=g_new0(struct map_download, 1);
1318 download->file=m->fi;
1320 download->zipfile=zipfile;
1321 download->toffset=offset;
1322 download->tlength=length;
1325 struct attr readwrite={attr_readwrite,{(void *)1}};
1326 struct attr create={attr_create,{(void *)1}};
1327 struct attr *attrs[3];
1328 attrs[0]=&readwrite;
1331 download->file=file_create(m->filename,attrs);
1337 m->download=download;
1338 g_free(m->progress);
1340 m->progress=g_strdup_printf("Download Tile %d 0%%",download->zipfile);
1342 m->progress=g_strdup_printf("Download Map Information 0%%");
1343 callback_list_call_attr_0(m->cbl, attr_progress);
1347 dbg(0,"state=%d\n",download->state);
1348 switch (download->state) {
1353 if (download_start(download))
1359 if (download_download(download))
1362 g_free(m->progress);
1363 m->progress=g_strdup_printf("Download Tile %d %d%%",download->zipfile,download->progress);
1364 callback_list_call_attr_0(m->cbl, attr_progress);
1368 if (download_finish(download)) {
1370 g_free(m->progress);
1371 m->progress=g_strdup_printf("Download Tile %d 100%%",download->zipfile);
1372 callback_list_call_attr_0(m->cbl, attr_progress);
1374 push_zipfile_tile_do(download->mr, download->cd, download->zipfile, download->toffset, download->tlength);
1378 g_free(m->progress);
1388 if (download_planet_size(download))
1394 g_free(m->progress);
1395 m->progress=g_strdup_printf("Download Map Information 50%%");
1396 callback_list_call_attr_0(m->cbl, attr_progress);
1397 if (download_eoc(download))
1400 dbg(0,"download of eoc failed\n");
1405 g_free(m->progress);
1406 m->progress=g_strdup_printf("Download Map Information 100%%");
1407 callback_list_call_attr_0(m->cbl, attr_progress);
1408 if (download_directory_start(download))
1414 g_free(m->progress);
1415 m->progress=g_strdup_printf("Download Map Directory %d%%",(int)(download->offset*100/download->zip64_eoc->zip64ecsz));
1416 callback_list_call_attr_0(m->cbl, attr_progress);
1417 if (!download_directory_do(download))
1421 if (download_directory_finish(download))
1427 download_initial_finish(download);
1428 m->fi=download->file;
1429 g_free(m->progress);
1434 map_binfile_open(m);
1443 push_zipfile_tile(struct map_rect_priv *mr, int zipfile, int offset, int length, int async)
1445 struct map_priv *m=mr->m;
1446 struct file *f=m->fi;
1447 long long cdoffset=m->eoc64?m->eoc64->zip64eofst:m->eoc->zipeofst;
1448 struct zip_cd *cd=(struct zip_cd *)(file_data_read(f, cdoffset + zipfile*m->cde_size, m->cde_size));
1449 dbg(1,"read from "LONGLONG_FMT" %d bytes\n",cdoffset + zipfile*m->cde_size, m->cde_size);
1451 if (!cd->zipcunc && m->url) {
1452 cd=download(m, mr, cd, zipfile, offset, length, async);
1456 push_zipfile_tile_do(mr, cd, zipfile, offset, length);
1460 static struct map_rect_priv *
1461 map_rect_new_binfile_int(struct map_priv *map, struct map_selection *sel)
1463 struct map_rect_priv *mr;
1465 binfile_check_version(map);
1466 dbg(1,"map_rect_new_binfile\n");
1467 if (!map->fi && !map->url)
1469 map_binfile_http_close(map);
1470 mr=g_new0(struct map_rect_priv, 1);
1475 mr->item.meth=&methods_binfile;
1476 mr->item.priv_data=mr;
1481 tile_bbox(char *tile, int len, struct coord_rect *r)
1486 struct coord_rect world_bbox = {
1487 { -20000000, 20000000}, /* lu */
1488 { 20000000, -20000000}, /* rl */
1492 c.x=(r->lu.x+r->rl.x)/2;
1493 c.y=(r->lu.y+r->rl.y)/2;
1494 xo=(r->rl.x-r->lu.x)*overlap/100;
1495 yo=(r->lu.y-r->rl.y)*overlap/100;
1522 map_download_selection_check(struct zip_cd *cd, struct map_selection *sel)
1524 struct coord_rect cd_rect;
1527 tile_bbox((char *)(cd+1), cd->zipcfnl, &cd_rect);
1529 if (coord_rect_overlap(&cd_rect, &sel->u.c_rect))
1537 map_download_selection(struct map_priv *m, struct map_rect_priv *mr, struct map_selection *sel)
1541 for (i = 0 ; i < m->zip_members ; i++) {
1542 cd=binfile_read_cd(m, m->cde_size*i, -1);
1543 if (map_download_selection_check(cd, sel))
1544 download(m, mr, cd, i, 0, 0, 0);
1545 file_data_free(m->fi, (unsigned char *)cd);
1549 static struct map_rect_priv *
1550 map_rect_new_binfile(struct map_priv *map, struct map_selection *sel)
1552 struct map_rect_priv *mr=map_rect_new_binfile_int(map, sel);
1554 dbg(1,"zip_members=%d\n", map->zip_members);
1555 if (map->url && map->fi && sel && sel->order == 255) {
1556 map_download_selection(map, mr, sel);
1563 d=file_data_read(map->fi, 0, map->fi->size);
1565 t.end=(int *)(d+map->fi->size);
1569 push_tile(mr, &t, 0, 0);
1570 } else if (map->url && !map->download) {
1571 download(map, NULL, NULL, 0, 0, 0, 1);
1579 write_changes_do(gpointer key, gpointer value, gpointer user_data)
1581 struct binfile_hash_entry *entry=key;
1582 FILE *out=user_data;
1585 fwrite(entry, sizeof(*entry)+(le32_to_cpu(entry->data[0])+1)*4, 1, out);
1591 write_changes(struct map_priv *m)
1597 changes_file=g_strdup_printf("%s.log",m->filename);
1598 changes=fopen(changes_file,"ab");
1599 g_hash_table_foreach(m->changes, write_changes_do, changes);
1601 g_free(changes_file);
1605 load_changes(struct map_priv *m)
1609 struct binfile_hash_entry entry,*e;
1611 changes_file=g_strdup_printf("%s.log",m->filename);
1612 changes=fopen(changes_file,"rb");
1614 g_free(changes_file);
1617 m->changes=g_hash_table_new_full(binfile_hash_entry_hash, binfile_hash_entry_equal, g_free, NULL);
1618 while (fread(&entry, sizeof(entry), 1, changes) == 1) {
1619 if (fread(&size, sizeof(size), 1, changes) != 1)
1621 e=g_malloc(sizeof(struct binfile_hash_entry)+(le32_to_cpu(size)+1)*4);
1624 if (fread(e->data+1, le32_to_cpu(size)*4, 1, changes) != 1)
1626 g_hash_table_replace(m->changes, e, e);
1629 g_free(changes_file);
1634 map_rect_destroy_binfile(struct map_rect_priv *mr)
1636 write_changes(mr->m);
1637 while (pop_tile(mr));
1639 dbg(0,"size=%d kb\n",mr->size/1024);
1641 if (mr->tiles[0].fi && mr->tiles[0].start)
1642 file_data_free(mr->tiles[0].fi, (unsigned char *)(mr->tiles[0].start));
1644 map_binfile_http_close(mr->m);
1649 setup_pos(struct map_rect_priv *mr)
1651 int size,coord_size;
1652 struct tile *t=mr->t;
1653 size=le32_to_cpu(t->pos[0]);
1654 if (size > 1024*1024 || size < 0) {
1655 dbg(0,"size=0x%x\n", size);
1657 fprintf(stderr,"offset=%d\n", (unsigned char *)(mr->pos)-mr->m->f->begin);
1659 dbg(0,"size error");
1661 t->pos_next=t->pos+size+1;
1662 mr->item.type=le32_to_cpu(t->pos[1]);
1663 coord_size=le32_to_cpu(t->pos[2]);
1664 t->pos_coord_start=t->pos+3;
1665 t->pos_attr_start=t->pos_coord_start+coord_size;
1669 selection_contains(struct map_selection *sel, struct coord_rect *r, struct range *mima)
1675 if (coord_rect_overlap(r, &sel->u.c_rect)) {
1677 dbg(1,"min %d max %d order %d\n", mima->min, mima->max, order);
1678 if (!mima->min && !mima->max)
1680 if (order >= mima->min && order <= mima->max)
1689 map_parse_country_binfile(struct map_rect_priv *mr)
1692 if (binfile_attr_get(mr->item.priv_data, attr_country_id, &at)) {
1693 if (at.u.num == mr->country_id)
1695 if (binfile_attr_get(mr->item.priv_data, attr_zipfile_ref, &at))
1697 push_zipfile_tile(mr, at.u.num, 0, 0, 0);
1704 map_parse_submap(struct map_rect_priv *mr, int async)
1706 struct coord_rect r;
1710 if (binfile_coord_get(mr->item.priv_data, c, 2) != 2)
1716 if (!binfile_attr_get(mr->item.priv_data, attr_order, &at))
1718 #if __BYTE_ORDER == __BIG_ENDIAN
1719 mima.min=le16_to_cpu(at.u.range.max);
1720 mima.max=le16_to_cpu(at.u.range.min);
1724 if (!mr->m->eoc || !selection_contains(mr->sel, &r, &mima))
1726 if (!binfile_attr_get(mr->item.priv_data, attr_zipfile_ref, &at))
1728 dbg(1,"pushing zipfile %d from %d\n", at.u.num, mr->t->zipfile_num);
1729 return push_zipfile_tile(mr, at.u.num, 0, 0, async);
1733 push_modified_item(struct map_rect_priv *mr)
1736 struct binfile_hash_entry *entry;
1737 id.id_hi=mr->item.id_hi;
1738 id.id_lo=mr->item.id_lo;
1739 entry=g_hash_table_lookup(mr->m->changes, &id);
1742 tn.pos_next=tn.pos=tn.start=entry->data;
1743 tn.zipfile_num=mr->item.id_hi;
1745 tn.end=tn.start+le32_to_cpu(entry->data[0])+1;
1746 push_tile(mr, &tn, 0, 0);
1752 static struct item *
1753 map_rect_get_item_binfile(struct map_rect_priv *mr)
1756 struct map_priv *m=mr->m;
1758 download(m, NULL, NULL, 0, 0, 0, 2);
1761 if (mr->status == 1) {
1763 if (push_zipfile_tile(mr, m->zip_members-1, 0, 0, 1))
1771 if (t->pos >= t->end) {
1777 binfile_coord_rewind(mr);
1778 binfile_attr_rewind(mr);
1779 if ((mr->item.type == type_submap) && (!mr->country_id)) {
1780 if (map_parse_submap(mr, 1))
1785 mr->item.id_hi=t->zipfile_num;
1786 mr->item.id_lo=t->pos-t->start;
1787 if (mr->m->changes && push_modified_item(mr))
1792 if (mr->item.type == type_countryindex) {
1793 map_parse_country_binfile(mr);
1795 if (item_is_town(mr->item))
1806 static struct item *
1807 map_rect_get_item_byid_binfile(struct map_rect_priv *mr, int id_hi, int id_lo)
1811 while (pop_tile(mr));
1812 push_zipfile_tile(mr, id_hi, 0, 0, 0);
1815 t->pos=t->start+id_lo;
1816 mr->item.id_hi=id_hi;
1817 mr->item.id_lo=id_lo;
1819 push_modified_item(mr);
1821 binfile_coord_rewind(mr);
1822 binfile_attr_rewind(mr);
1827 binmap_search_by_index(struct map_priv *map, struct item *item, struct map_rect_priv **ret)
1829 struct attr zipfile_ref;
1836 if (item_attr_get(item, attr_item_id, &zipfile_ref)) {
1837 data=zipfile_ref.u.data;
1838 *ret=map_rect_new_binfile_int(map, NULL);
1839 push_zipfile_tile(*ret, le32_to_cpu(data[0]), le32_to_cpu(data[1]), -1, 0);
1842 if (item_attr_get(item, attr_zipfile_ref, &zipfile_ref)) {
1843 *ret=map_rect_new_binfile_int(map, NULL);
1844 push_zipfile_tile(*ret, zipfile_ref.u.num, 0, 0, 0);
1847 if (item_attr_get(item, attr_zipfile_ref_block, &zipfile_ref)) {
1848 data=zipfile_ref.u.data;
1849 *ret=map_rect_new_binfile_int(map, NULL);
1850 push_zipfile_tile(*ret, le32_to_cpu(data[0]), le32_to_cpu(data[1]), le32_to_cpu(data[2]), 0);
1857 static struct map_rect_priv *
1858 binmap_search_street_by_place(struct map_priv *map, struct item *town, struct coord *c, struct map_selection *sel)
1860 struct attr town_name, poly_town_name;
1861 struct map_rect_priv *map_rec2;
1865 if (!item_attr_get(town, attr_label, &town_name))
1867 sel->range = item_range_all;
1870 sel->u.c_rect.lu=*c;
1871 sel->u.c_rect.rl=*c;
1872 map_rec2=map_rect_new_binfile(map, sel);
1873 while ((place=map_rect_get_item_binfile(map_rec2))) {
1874 if (item_is_poly_place(*place) &&
1875 item_attr_get(place, attr_label, &poly_town_name) &&
1876 !strcmp(poly_town_name.u.str,town_name.u.str)) {
1877 struct coord c[128];
1880 while ((count=item_coord_get(place, c, 128))) {
1881 for (i = 0 ; i < count ; i++)
1882 coord_rect_extend(&sel->u.c_rect, &c[i]);
1886 map_rect_destroy_binfile(map_rec2);
1888 return map_rect_new_binfile(map, sel);
1892 static struct map_rect_priv *
1893 binmap_search_street_by_estimate(struct map_priv *map, struct item *town, struct coord *c, struct map_selection *sel)
1896 switch (town->type) {
1897 case type_town_label_1e7:
1898 case type_town_label_5e6:
1899 case type_town_label_2e6:
1900 case type_town_label_1e6:
1901 case type_town_label_5e5:
1902 case type_town_label_2e5:
1903 case type_district_label_1e7:
1904 case type_district_label_5e6:
1905 case type_district_label_2e6:
1906 case type_district_label_1e6:
1907 case type_district_label_5e5:
1908 case type_district_label_2e5:
1911 case type_town_label_1e5:
1912 case type_town_label_5e4:
1913 case type_town_label_2e4:
1914 case type_district_label_1e5:
1915 case type_district_label_5e4:
1916 case type_district_label_2e4:
1919 case type_town_label_1e4:
1920 case type_town_label_5e3:
1921 case type_town_label_2e3:
1922 case type_district_label_1e4:
1923 case type_district_label_5e3:
1924 case type_district_label_2e3:
1927 case type_town_label_1e3:
1928 case type_town_label_5e2:
1929 case type_town_label_2e2:
1930 case type_town_label_1e2:
1931 case type_town_label_5e1:
1932 case type_town_label_2e1:
1933 case type_town_label_1e1:
1934 case type_town_label_5e0:
1935 case type_town_label_2e0:
1936 case type_town_label_1e0:
1937 case type_town_label_0e0:
1938 case type_district_label_1e3:
1939 case type_district_label_5e2:
1940 case type_district_label_2e2:
1941 case type_district_label_1e2:
1942 case type_district_label_5e1:
1943 case type_district_label_2e1:
1944 case type_district_label_1e1:
1945 case type_district_label_5e0:
1946 case type_district_label_2e0:
1947 case type_district_label_1e0:
1948 case type_district_label_0e0:
1954 sel->u.c_rect.lu.x = c->x-size;
1955 sel->u.c_rect.lu.y = c->y+size;
1956 sel->u.c_rect.rl.x = c->x+size;
1957 sel->u.c_rect.rl.y = c->y-size;
1958 return map_rect_new_binfile(map, sel);
1961 static struct map_rect_priv *
1962 binmap_search_housenumber_by_estimate(struct map_priv *map, struct coord *c, struct map_selection *sel)
1965 sel->u.c_rect.lu.x = c->x-size;
1966 sel->u.c_rect.lu.y = c->y+size;
1967 sel->u.c_rect.rl.x = c->x+size;
1968 sel->u.c_rect.rl.y = c->y-size;
1970 sel->range = item_range_all;
1974 return map_rect_new_binfile(map, sel);
1977 static struct map_search_priv *
1978 binmap_search_new(struct map_priv *map, struct item *item, struct attr *search, int partial)
1980 struct map_rect_priv *map_rec;
1981 struct map_search_priv *msp=g_new0(struct map_search_priv, 1);
1984 msp->search = search;
1985 msp->partial = partial;
1987 * NOTE: If you implement search for other attributes than attr_town_name and attr_street_name,
1988 * please update this comment and the documentation for map_search_new() in map.c
1990 switch (search->type) {
1991 case attr_country_name:
1993 case attr_town_name:
1994 case attr_town_or_district_name:
1995 map_rec = map_rect_new_binfile(map, NULL);
1998 map_rec->country_id = item->id_lo;
2002 case attr_town_postal:
2004 case attr_street_name:
2007 if (!map_priv_is(item->map, map))
2009 map_rec = map_rect_new_binfile(map, NULL);
2010 town = map_rect_get_item_byid_binfile(map_rec, item->id_hi, item->id_lo);
2014 if (binmap_search_by_index(map, town, &msp->mr))
2017 if (item_coord_get(town, &c, 1)) {
2018 if ((msp->mr=binmap_search_street_by_place(map, town, &c, &msp->ms)))
2021 msp->mr=binmap_search_street_by_estimate(map, town, &c, &msp->ms);
2026 map_rect_destroy_binfile(map_rec);
2031 map_rect_destroy_binfile(map_rec);
2033 case attr_house_number:
2034 dbg(1,"case house_number");
2037 if (!map_priv_is(item->map, map))
2040 msp->mr_item = map_rect_new_binfile(map, NULL);
2041 msp->item = map_rect_get_item_byid_binfile(msp->mr_item, item->id_hi, item->id_lo);
2042 if (binmap_search_by_index(map, msp->item, &msp->mr) != 3) {
2044 if (item_coord_get(msp->item, &c, 1))
2046 msp->mr=binmap_search_housenumber_by_estimate(map, &c, &msp->ms);
2049 map_rect_destroy_binfile(msp->mr_item);
2065 ascii_cmp(char *name, char *match, int partial)
2068 return g_ascii_strncasecmp(name, match, strlen(match));
2070 return g_ascii_strcasecmp(name, match);
2080 duplicate_hash(gconstpointer key)
2082 const struct duplicate *d=key;
2083 return d->c.x^d->c.y^g_str_hash(d->str);
2087 duplicate_equal(gconstpointer a, gconstpointer b)
2089 const struct duplicate *da=a;
2090 const struct duplicate *db=b;
2091 return (da->c.x == db->c.x && da->c.y == da->c.y && g_str_equal(da->str,db->str));
2096 * @param msp pointer to private map search data
2097 * @param item item to check
2101 duplicate(struct map_search_priv *msp, struct item *item, enum attr_type attr_type)
2104 if (!msp->search_results)
2105 msp->search_results = g_hash_table_new_full(duplicate_hash, duplicate_equal, g_free, NULL);
2106 binfile_attr_rewind(item->priv_data);
2107 if (!item_attr_get(item, attr_type, &attr))
2110 int len=sizeof(struct coord)+strlen(attr.u.str)+1;
2111 char *buffer=g_alloca(sizeof(char)*len);
2112 struct duplicate *d=(struct duplicate *)buffer;
2113 if (!item_coord_get(item, &d->c, 1)) {
2117 binfile_coord_rewind(item->priv_data);
2118 strcpy(d->str, attr.u.str);
2119 if (!g_hash_table_lookup(msp->search_results, d)) {
2120 struct duplicate *dc=g_malloc(len);
2122 g_hash_table_insert(msp->search_results, dc, GINT_TO_POINTER(1));
2123 binfile_attr_rewind(item->priv_data);
2130 static struct item *
2131 binmap_search_get_item(struct map_search_priv *map_search)
2137 while ((it = map_rect_get_item_binfile(map_search->mr))) {
2138 switch (map_search->search->type) {
2139 case attr_town_name:
2140 case attr_district_name:
2141 case attr_town_or_district_name:
2142 if (map_search->mr->tile_depth > 1 && item_is_town(*it) && map_search->search->type != attr_district_name) {
2143 if (binfile_attr_get(it->priv_data, attr_town_name_match, &at) || binfile_attr_get(it->priv_data, attr_town_name, &at)) {
2144 if (!ascii_cmp(at.u.str, map_search->search->u.str, map_search->partial) && !duplicate(map_search, it, attr_town_name))
2148 if (map_search->mr->tile_depth > 1 && item_is_district(*it) && map_search->search->type != attr_town_name) {
2149 if (binfile_attr_get(it->priv_data, attr_district_name_match, &at) || binfile_attr_get(it->priv_data, attr_district_name, &at)) {
2150 if (!ascii_cmp(at.u.str, map_search->search->u.str, map_search->partial) && !duplicate(map_search, it, attr_town_name))
2155 case attr_street_name:
2156 if (map_search->mode == 1) {
2157 if (binfile_attr_get(it->priv_data, attr_street_name_match, &at) || binfile_attr_get(it->priv_data, attr_street_name, &at)) {
2158 if (!ascii_cmp(at.u.str, map_search->search->u.str, map_search->partial) && !duplicate(map_search, it, attr_street_name)) {
2164 if (item_is_street(*it)) {
2166 if (map_selection_contains_item_rect(map_search->mr->sel, it) && binfile_attr_get(it->priv_data, attr_label, &at)) {
2168 char *str=g_strdup(at.u.str);
2171 for (i = 0 ; i < 3 ; i++) {
2172 char *name=linguistics_expand_special(word,i);
2173 if (name && !ascii_cmp(name, map_search->search->u.str, map_search->partial))
2181 word=linguistics_next_word(word);
2184 if (match && !duplicate(map_search, it, attr_label)) {
2185 item_coord_rewind(it);
2191 case attr_house_number:
2192 //if (it->type == type_house_number)
2193 if ((it->type == type_house_number)||(type_house_number_interpolation_even)
2194 ||(type_house_number_interpolation_odd)
2195 ||(type_house_number_interpolation_all)
2198 // is it a housenumber?
2199 if (binfile_attr_get(it->priv_data, attr_house_number, &at))
2201 // match housenumber to our string
2202 if (!ascii_cmp(at.u.str, map_search->search->u.str, map_search->partial))
2204 //binfile_attr_get(it->priv_data, attr_street_name, &at);
2205 //dbg(0,"hnnn B1 street_name=%s",at.u.str);
2206 if (!duplicate(map_search, it, attr_house_number))
2208 binfile_attr_rewind(it->priv_data);
2220 if (!map_search->mr_item)
2222 map_rect_destroy_binfile(map_search->mr);
2223 if (!binmap_search_by_index(map_search->map, map_search->item, &map_search->mr))
2230 binmap_search_destroy(struct map_search_priv *ms)
2232 if (ms->search_results)
2233 g_hash_table_destroy(ms->search_results);
2235 map_rect_destroy_binfile(ms->mr_item);
2237 map_rect_destroy_binfile(ms->mr);
2242 binmap_get_attr(struct map_priv *m, enum attr_type type, struct attr *attr)
2246 case attr_map_release:
2247 if (m->map_release) {
2248 attr->u.str=m->map_release;
2254 attr->u.str=m->progress;
2264 binmap_set_attr(struct map_priv *map, struct attr *attr)
2266 switch (attr->type) {
2268 map->download_enabled = attr->u.num;
2276 static struct map_methods map_methods_binfile = {
2279 map_destroy_binfile,
2280 map_rect_new_binfile,
2281 map_rect_destroy_binfile,
2282 map_rect_get_item_binfile,
2283 map_rect_get_item_byid_binfile,
2285 binmap_search_destroy,
2286 binmap_search_get_item,
2293 binfile_get_index(struct map_priv *m)
2300 len = strlen("index");
2301 cde_index_size = sizeof(struct zip_cd)+len;
2303 offset = m->eoc64->zip64ecsz-cde_index_size;
2305 offset = m->eoc->zipecsz-cde_index_size;
2306 cd = binfile_read_cd(m, offset, len);
2309 cde_index_size+=sizeof(struct zip_cd_ext);
2311 offset = m->eoc64->zip64ecsz-cde_index_size;
2313 offset = m->eoc->zipecsz-cde_index_size;
2314 cd = binfile_read_cd(m, offset, len+sizeof(struct zip_cd_ext));
2317 if (cd->zipcfnl == len && !strncmp(cd->zipcfn, "index", len)) {
2318 m->index_offset=offset;
2323 offset=binfile_search_cd(m, 0, "index", 0, 0);
2326 cd=binfile_read_cd(m, offset, -1);
2329 m->index_offset=offset;
2335 map_binfile_zip_setup(struct map_priv *m, char *filename, int mmap)
2337 struct zip_cd *first_cd;
2339 if (!(m->eoc=binfile_read_eoc(m->fi))) {
2340 dbg(0,"unable to read eoc\n");
2343 dbg_assert(m->eoc->zipedsk == m->eoc->zipecen);
2344 if (m->eoc->zipedsk && strlen(filename) > 3) {
2345 char *tmpfilename=g_strdup(filename),*ext=tmpfilename+strlen(tmpfilename)-3;
2346 m->fis=g_new(struct file *,m->eoc->zipedsk);
2347 for (i = 0 ; i < m->eoc->zipedsk-1 ; i++) {
2348 sprintf(ext,"b%02d",i+1);
2349 m->fis[i]=file_create(tmpfilename, 0);
2351 file_mmap(m->fis[i]);
2353 m->fis[m->eoc->zipedsk-1]=m->fi;
2354 g_free(tmpfilename);
2356 dbg(1,"num_disk %d\n",m->eoc->zipedsk);
2357 m->eoc64=binfile_read_eoc64(m->fi);
2358 if (!binfile_get_index(m)) {
2359 dbg(0,"no index found\n");
2362 if (!(first_cd=binfile_read_cd(m, 0, 0))) {
2363 dbg(0,"unable to get first cd\n");
2366 m->cde_size=sizeof(struct zip_cd)+first_cd->zipcfnl+first_cd->zipcxtl;
2367 m->zip_members=m->index_offset/m->cde_size+1;
2368 dbg(1,"cde_size %d\n", m->cde_size);
2369 dbg(1,"members %d\n",m->zip_members);
2370 file_data_free(m->fi, (unsigned char *)first_cd);
2379 map_binfile_download_initial(struct map_priv *m)
2381 struct attr readwrite={attr_readwrite,{(void *)1}};
2382 struct attr create={attr_create,{(void *)1}};
2383 struct attr *attrs[4];
2385 long long woffset=0,planet_size;
2387 int cd1size,cdisize;
2388 long long cd1offset,cdioffset;
2389 struct zip64_eoc *zip64_eoc;
2390 struct zip64_eocl *zip64_eocl;
2391 struct zip_eoc *zip_eoc;
2392 struct zip_cd *cd1,*cdn,*cdi;
2393 int count,chunk,cdoffset=0;
2395 struct map_download *download=g_new0(struct map_download, 1);
2397 attrs[0]=&readwrite;
2400 download->file=file_create(m->filename,attrs);
2402 download_planet_size(download);
2403 download_eoc(download);
2404 download_directory_start(download);
2405 while (download_directory_do(download));
2406 download_directory_finish(download);
2407 download_initial_finish(download);
2408 m->fi=download->file;
2413 cd1size=sizeof(*cd1);
2414 cd1offset=zip64_eoc->zip64eofst;
2415 cd1=(struct zip_cd *)map_binfile_download_range(m, cd1offset, cd1size);
2418 cd1size=sizeof(*cd1)+binfile_cd_extra(cd1);
2420 cd1=(struct zip_cd *)map_binfile_download_range(m, cd1offset, cd1size);
2424 cdisize=sizeof(*cdi)+strlen("index")+cd1->zipcxtl;
2425 cdioffset=zip64_eoc->zip64eofst+zip64_eoc->zip64ecsz-cdisize;
2426 cdi=(struct zip_cd *)map_binfile_download_range(m, cdioffset, cdisize);
2432 cdn=g_malloc0(cd1size*256);
2434 file_data_write(out, woffset, sizeof(*zip64_eoc), (unsigned char *)zip64_eoc);
2435 woffset+=sizeof(*zip64_eoc);
2438 file_data_write(out, woffset, cd1size, (unsigned char *)cd1);
2440 count=(cdioffset-cd1offset)/cd1size-1;
2446 file_data_write(out, woffset, cd1size*chunk, (unsigned char *)cdn);
2447 woffset+=cd1size*chunk;
2452 file_data_write(out, woffset, cdisize, (unsigned char *)cdi);
2459 map_binfile_open(struct map_priv *m)
2462 struct map_rect_priv *mr;
2465 struct attr readwrite={attr_readwrite, {(void *)1}};
2466 struct attr *attrs[]={&readwrite, NULL};
2468 dbg(1,"file_create %s\n", m->filename);
2469 m->fi=file_create(m->filename, m->url?attrs:NULL);
2470 if (! m->fi && m->url)
2473 dbg(0,"Failed to load '%s'\n", m->filename);
2476 if (m->check_version)
2477 m->version=file_version(m->fi, m->check_version);
2478 magic=(int *)file_data_read(m->fi, 0, 4);
2480 file_destroy(m->fi);
2484 *magic = le32_to_cpu(*magic);
2485 if (*magic == zip_lfh_sig || *magic == zip_split_sig || *magic == zip_cd_sig || *magic == zip64_eoc_sig) {
2486 if (!map_binfile_zip_setup(m, m->filename, m->flags & 1)) {
2487 dbg(0,"invalid file format for '%s'\n", m->filename);
2488 file_destroy(m->fi);
2492 } else if (*magic == zip_lfh_sig_rev || *magic == zip_split_sig_rev || *magic == zip_cd_sig_rev || *magic == zip64_eoc_sig_rev) {
2493 dbg(0,"endianness mismatch\n");
2494 file_destroy(m->fi);
2499 file_data_free(m->fi, (unsigned char *)magic);
2500 m->cachedir=g_strdup("/tmp/navit");
2502 mr=map_rect_new_binfile(m, NULL);
2504 while ((item=map_rect_get_item_binfile(mr)) == &busy_item);
2505 if (item && item->type == type_map_information) {
2506 if (binfile_attr_get(item->priv_data, attr_version, &attr))
2507 m->map_version=attr.u.num;
2508 if (binfile_attr_get(item->priv_data, attr_map_release, &attr))
2509 m->map_release=g_strdup(attr.u.str);
2510 if (m->url && binfile_attr_get(item->priv_data, attr_url, &attr)) {
2511 dbg(0,"url config %s map %s\n",m->url,attr.u.str);
2512 if (strcmp(m->url, attr.u.str))
2513 m->update_available=1;
2515 m->url=g_strdup(attr.u.str);
2518 map_rect_destroy_binfile(mr);
2519 if (m->map_version >= 16) {
2520 dbg(0,"Warning: This map is incompatible with your navit version. Please update navit.\n");
2528 map_binfile_close(struct map_priv *m)
2531 file_data_free(m->fi, (unsigned char *)m->index_cd);
2532 file_data_free(m->fi, (unsigned char *)m->eoc);
2533 file_data_free(m->fi, (unsigned char *)m->eoc64);
2534 g_free(m->cachedir);
2535 g_free(m->map_release);
2537 for (i = 0 ; i < m->eoc->zipedsk ; i++) {
2538 file_destroy(m->fis[i]);
2541 file_destroy(m->fi);
2545 map_binfile_destroy(struct map_priv *m)
2547 g_free(m->filename);
2549 g_free(m->progress);
2555 binfile_check_version(struct map_priv *m)
2558 if (!m->check_version)
2561 version=file_version(m->fi, m->check_version);
2562 if (version != m->version) {
2564 map_binfile_close(m);
2565 map_binfile_open(m);
2570 static struct map_priv *
2571 map_new_binfile(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
2574 struct attr *data=attr_search(attrs, NULL, attr_data);
2575 struct attr *check_version,*map_pass,*flags,*url,*download_enabled;
2576 struct file_wordexp *wexp;
2581 wexp=file_wordexp_new(data->u.str);
2582 wexp_data=file_wordexp_get_array(wexp);
2583 dbg(1,"map_new_binfile %s\n", data->u.str);
2584 *meth=map_methods_binfile;
2586 m=g_new0(struct map_priv, 1);
2589 m->filename=g_strdup(wexp_data[0]);
2590 file_wordexp_destroy(wexp);
2591 check_version=attr_search(attrs, NULL, attr_check_version);
2593 m->check_version=check_version->u.num;
2594 map_pass=attr_search(attrs, NULL, attr_map_pass);
2596 m->passwd=g_strdup(map_pass->u.str);
2597 flags=attr_search(attrs, NULL, attr_flags);
2599 m->flags=flags->u.num;
2600 url=attr_search(attrs, NULL, attr_url);
2602 m->url=g_strdup(url->u.str);
2603 download_enabled = attr_search(attrs, NULL, attr_update);
2604 if (download_enabled)
2605 m->download_enabled=download_enabled->u.num;
2607 if (!map_binfile_open(m) && !m->check_version && !m->url) {
2608 map_binfile_destroy(m);
2619 dbg(1,"binfile: plugin_init\n");
2620 if (sizeof(struct zip_cd) != 46) {
2621 dbg(0,"error: sizeof(struct zip_cd)=%d\n",sizeof(struct zip_cd));
2623 plugin_register_map_type("binfile", map_new_binfile);