00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #ifdef HAVE_CONFIG_H
00058 # include "config.h"
00059 #endif
00060 #if NEED_GNUG_PRAGMAS
00061 # pragma implementation
00062 #endif
00063
00064
00065
00066
00067
00068
00069
00070
00071 #include "GException.h"
00072 #include "GOS.h"
00073 #include "GURL.h"
00074 #include "debug.h"
00075
00076 #include <stdlib.h>
00077 #include <stdio.h>
00078 #include <ctype.h>
00079 #include <math.h>
00080 #include <string.h>
00081
00082 #ifdef WIN32
00083 # include <atlbase.h>
00084 # include <windows.h>
00085 # include <direct.h>
00086 #endif
00087
00088
00089 #ifndef MAXPATHLEN
00090 # ifdef _MAX_PATH
00091 # define MAXPATHLEN _MAX_PATH
00092 # else
00093 # define MAXPATHLEN 1024
00094 # endif
00095 #else
00096 # if ( MAXPATHLEN < 1024 )
00097 # undef MAXPATHLEN
00098 # define MAXPATHLEN 1024
00099 # endif
00100 #endif
00101
00102 #if defined(UNIX) || defined(OS2)
00103 # include <unistd.h>
00104 # include <sys/types.h>
00105 # include <sys/stat.h>
00106 # include <errno.h>
00107 # include <fcntl.h>
00108 # include <pwd.h>
00109 # include <stdio.h>
00110 # ifdef AUTOCONF
00111 # ifdef TIME_WITH_SYS_TIME
00112 # include <sys/time.h>
00113 # include <time.h>
00114 # else
00115 # ifdef HAVE_SYS_TIME_H
00116 # include <sys/time.h>
00117 # else
00118 # include <time.h>
00119 # endif
00120 # endif
00121 # ifdef HAVE_DIRENT_H
00122 # include <dirent.h>
00123 # define NAMLEN(dirent) strlen((dirent)->d_name)
00124 # else
00125 # define dirent direct
00126 # define NAMLEN(dirent) (dirent)->d_namlen
00127 # ifdef HAVE_SYS_NDIR_H
00128 # include <sys/ndir.h>
00129 # endif
00130 # ifdef HAVE_SYS_DIR_H
00131 # include <sys/dir.h>
00132 # endif
00133 # ifdef HAVE_NDIR_H
00134 # include <ndir.h>
00135 # endif
00136 # endif
00137 # else
00138 # include <sys/time.h>
00139 # if defined(XENIX)
00140 # define USE_DIRECT
00141 # include <sys/ndir.h>
00142 # elif defined(OLDBSD)
00143 # define USE_DIRECT
00144 # include <sys/dir.h>
00145 # endif
00146 # ifdef USE_DIRECT
00147 # define dirent direct
00148 # define NAMLEN(dirent) (dirent)->d_namlen
00149 # else
00150 # include <dirent.h>
00151 # define NAMLEN(dirent) strlen((dirent)->d_name)
00152 # endif
00153 # endif
00154 #endif
00155
00156 #ifdef macintosh
00157 #include <unix.h>
00158 #include <errno.h>
00159 #include <unistd.h>
00160 #endif
00161
00162
00163 #ifdef HAVE_NAMESPACES
00164 namespace DJVU {
00165 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00166 }
00167 #endif
00168 #endif
00169
00170
00171 static const char djvuopts[]="DJVUOPTS";
00172 static const char localhost[]="file://localhost/";
00173 static const char backslash='\\';
00174 static const char colon=':';
00175 static const char dot='.';
00176 static const char filespecslashes[] = "file://";
00177 static const char filespec[] = "file:";
00178 static const char slash='/';
00179 static const char percent='%';
00180 static const char localhostspec1[] = "//localhost/";
00181 static const char localhostspec2[] = "///";
00182 static const char nillchar=0;
00183 #if defined(UNIX)
00184 static const char tilde='~';
00185 static const char root[] = "/";
00186 #elif defined(WIN32) || defined(OS2)
00187 static const char root[] = "\\";
00188 #elif defined(macintosh)
00189 static char const * const root = &nillchar;
00190 #else
00191 #error "Define something here for your operating system"
00192 #endif
00193
00194
00195 static const int
00196 pathname_start(const GUTF8String &url, const int protolength);
00197
00198
00199
00200
00201
00202 static int
00203 hexval(char c)
00204 {
00205 return ((c>='0' && c<='9')
00206 ?(c-'0')
00207 :((c>='A' && c<='F')
00208 ?(c-'A'+10)
00209 :((c>='a' && c<='f')
00210 ?(c-'a'+10):(-1))));
00211 }
00212
00213
00214 static bool
00215 is_argument(const char * start)
00216
00217
00218 {
00219
00220 return (*start=='#' || *start=='?' );
00221 }
00222
00223 static bool
00224 is_argument_sep(const char * start)
00225
00226
00227 {
00228 return (*start=='&')||(*start == ';');
00229 }
00230
00231 void
00232 GURL::convert_slashes(void)
00233 {
00234 GUTF8String xurl(get_string());
00235 #if defined(WIN32)
00236 const int protocol_length=protocol(xurl).length();
00237 for(char *ptr=(xurl.getbuf()+protocol_length);*ptr;ptr++)
00238 if(*ptr == backslash)
00239 *ptr=slash;
00240 url=xurl;
00241 #endif
00242 }
00243
00244 static void
00245 collapse(char * ptr, const int chars)
00246
00247
00248
00249 {
00250 const int length=strlen(ptr);
00251 const char *srcptr=ptr+((chars>length)?length:chars);
00252 while((*(ptr++) = *(srcptr++)))
00253 EMPTY_LOOP;
00254 }
00255
00256 GUTF8String
00257 GURL::beautify_path(GUTF8String xurl)
00258 {
00259
00260 const int protocol_length=GURL::protocol(xurl).length();
00261
00262
00263 char * buffer;
00264 GPBuffer<char> gbuffer(buffer,xurl.length()+1);
00265 strcpy(buffer, (const char *)xurl);
00266
00267
00268 char * start=buffer+pathname_start(xurl,protocol_length);
00269
00270
00271 char * ptr;
00272 GUTF8String args;
00273 for(ptr=start;*ptr;ptr++)
00274 {
00275 if (is_argument(ptr))
00276 {
00277 args=ptr;
00278 *ptr=0;
00279 break;
00280 }
00281 }
00282
00283
00284 for(;(ptr=strstr(start, "////"));collapse(ptr, 3))
00285 EMPTY_LOOP;
00286 for(;(ptr=strstr(start, "//"));collapse(ptr, 1))
00287 EMPTY_LOOP;
00288
00289 for(;(ptr=strstr(start, "/./"));collapse(ptr, 2))
00290 EMPTY_LOOP;
00291 #if defined(WIN32) || defined(OS2)
00292 if(!xurl.cmp(filespec,sizeof(filespec)-1))
00293 {
00294 int offset=1;
00295 if(start&&(start[0] == '/')&&
00296 !xurl.cmp("file:////",sizeof("file:////")-1))
00297 {
00298 collapse(start, 1);
00299 offset=0;
00300 }
00301 for(ptr=start+offset;(ptr=strchr(ptr, '/'));)
00302 {
00303 if(isalpha((++ptr)[0]))
00304 {
00305 if((ptr[1] == ':')&&(ptr[2]=='/'))
00306 {
00307 char *buffer2;
00308 GPBuffer<char> gbuffer2(buffer2,strlen(ptr)+1);
00309 strcpy(buffer2,ptr);
00310 gbuffer.resize(strlen(ptr)+sizeof(localhost));
00311 strcpy(buffer,localhost);
00312 strcat(buffer,buffer2);
00313 ptr=(start=buffer+sizeof(localhost))+1;
00314 }
00315 }
00316 }
00317 }
00318 #endif
00319
00320 while((ptr=strstr(start, "/../")))
00321 {
00322 for(char * ptr1=ptr-1;(ptr1>=start);ptr1--)
00323 {
00324 if (*ptr1==slash)
00325 {
00326 collapse(ptr1, ptr-ptr1+3);
00327 break;
00328 }
00329 }
00330 }
00331
00332
00333 ptr=start+strlen(start)-2;
00334 if((ptr>=start)&& (ptr == GUTF8String("/.")))
00335 {
00336 ptr[1]=0;
00337 }
00338
00339 ptr=start+strlen(start)-3;
00340 if((ptr >= start) && (ptr == GUTF8String("/..")))
00341 {
00342 for(char * ptr1=ptr-1;(ptr1>=start);ptr1--)
00343 {
00344 if (*ptr1==slash)
00345 {
00346 ptr1[1]=0;
00347 break;
00348 }
00349 }
00350 }
00351
00352
00353 xurl=buffer;
00354 return (xurl+args);
00355 }
00356
00357
00358 void
00359 GURL::beautify_path(void)
00360 {
00361 url=beautify_path(get_string());
00362 }
00363
00364 void
00365 GURL::init(const bool nothrow)
00366 {
00367 GCriticalSectionLock lock(&class_lock);
00368 validurl=true;
00369
00370 if (url.length())
00371 {
00372 GUTF8String proto=protocol();
00373 if (proto.length()<2)
00374 {
00375 validurl=false;
00376 if(!nothrow)
00377 G_THROW( ERR_MSG("GURL.no_protocol") "\t"+url);
00378 return;
00379 }
00380
00381
00382
00383
00384 if (proto=="file" && url[5]==slash &&
00385 (url[6]!=slash || !url.cmp(localhost, sizeof(localhost))))
00386 {
00387
00388 GUTF8String arg;
00389 {
00390 const char * const url_ptr=url;
00391 const char * ptr;
00392 for(ptr=url_ptr;*ptr&&!is_argument(ptr);ptr++)
00393 EMPTY_LOOP;
00394 arg=ptr;
00395 url=url.substr(0,(size_t)ptr-(size_t)url_ptr);
00396 }
00397
00398
00399 GUTF8String tmp=UTF8Filename();
00400 if (!tmp.length())
00401 {
00402 validurl=false;
00403 if(!nothrow)
00404 G_THROW( ERR_MSG("GURL.fail_to_file") );
00405 return;
00406 }
00407 url=GURL::Filename::UTF8(tmp).get_string();
00408 if (!url.length())
00409 {
00410 validurl=false;
00411 if(!nothrow)
00412 G_THROW( ERR_MSG("GURL.fail_to_URL") );
00413 return;
00414 }
00415
00416 url+=arg;
00417 }
00418 convert_slashes();
00419 beautify_path();
00420 parse_cgi_args();
00421 }
00422 }
00423
00424 GURL::GURL(void)
00425 : validurl(false)
00426 {
00427 }
00428
00429 GURL::GURL(const char * url_in)
00430 : url(url_in ? url_in : ""), validurl(false)
00431 {
00432 }
00433
00434 GURL::GURL(const GUTF8String & url_in)
00435 : url(url_in), validurl(false)
00436 {
00437 }
00438
00439 GURL::GURL(const GNativeString & url_in)
00440 : url(url_in.getNative2UTF8()), validurl(false)
00441 {
00442 #if defined(WIN32) || defined(OS2)
00443 if(is_valid() && is_local_file_url())
00444 {
00445 GURL::Filename::UTF8 xurl(UTF8Filename());
00446 url=xurl.get_string(true);
00447 validurl=false;
00448 }
00449 #endif
00450 }
00451
00452 GURL::GURL(const GURL & url_in)
00453 : validurl(false)
00454 {
00455 if(url_in.is_valid())
00456 {
00457 url=url_in.get_string();
00458 init();
00459 }else
00460 {
00461 url=url_in.url;
00462 }
00463 }
00464
00465 GURL &
00466 GURL::operator=(const GURL & url_in)
00467 {
00468 GCriticalSectionLock lock(&class_lock);
00469 if(url_in.is_valid())
00470 {
00471 url=url_in.get_string();
00472 init(true);
00473 }else
00474 {
00475 url=url_in.url;
00476 validurl=false;
00477 }
00478 return *this;
00479 }
00480
00481 GUTF8String
00482 GURL::protocol(const GUTF8String& url)
00483 {
00484 const char * const url_ptr=url;
00485 const char * ptr=url_ptr;
00486 for(char c=*ptr;
00487 c && (isalnum(c) || c == '+' || c == '-' || c == '.');
00488 c=*(++ptr)) EMPTY_LOOP;
00489 return(*ptr==colon)?GUTF8String(url_ptr, ptr-url_ptr):GUTF8String();
00490 }
00491
00492 GUTF8String
00493 GURL::hash_argument(void) const
00494
00495 {
00496 const GUTF8String xurl(get_string());
00497
00498 bool found=false;
00499 GUTF8String arg;
00500
00501
00502 for(const char * start=xurl;*start&&(*start!='?');start++)
00503 {
00504 if (found)
00505 {
00506 arg+=*start;
00507 }else
00508 {
00509 found=(*start=='#');
00510 }
00511 }
00512 return decode_reserved(arg);
00513 }
00514
00515 void
00516 GURL::set_hash_argument(const GUTF8String &arg)
00517 {
00518 const GUTF8String xurl(get_string());
00519
00520 GUTF8String new_url;
00521 bool found=false;
00522 const char * ptr;
00523 for(ptr=xurl;*ptr;ptr++)
00524 {
00525 if (is_argument(ptr))
00526 {
00527 if (*ptr!='#')
00528 {
00529 break;
00530 }
00531 found=true;
00532 } else if (!found)
00533 {
00534 new_url+=*ptr;
00535 }
00536 }
00537
00538 url=new_url+"#"+GURL::encode_reserved(arg)+ptr;
00539 }
00540
00541 void
00542 GURL::parse_cgi_args(void)
00543
00544
00545 {
00546 if(!validurl)
00547 init();
00548 GCriticalSectionLock lock1(&class_lock);
00549 cgi_name_arr.empty();
00550 cgi_value_arr.empty();
00551
00552
00553 const char * start=url;
00554 while(*start)
00555 {
00556 if(*(start++)=='?')
00557 {
00558 break;
00559 }
00560 }
00561
00562
00563 while(*start)
00564 {
00565 GUTF8String arg;
00566 while(*start)
00567 {
00568 if (is_argument_sep(start))
00569 {
00570 start++;
00571 break;
00572 } else
00573 {
00574 arg+=*start++;
00575 }
00576 }
00577 if (arg.length())
00578 {
00579
00580 const char * ptr;
00581 const char * const arg_ptr=arg;
00582 for(ptr=arg_ptr;*ptr&&(*ptr != '=');ptr++)
00583 EMPTY_LOOP;
00584
00585 GUTF8String name, value;
00586 if (*ptr)
00587 {
00588 name=GUTF8String(arg_ptr, (int)((ptr++)-arg_ptr));
00589 value=GUTF8String(ptr, arg.length()-name.length()-1);
00590 } else
00591 {
00592 name=arg;
00593 }
00594
00595 int args=cgi_name_arr.size();
00596 cgi_name_arr.resize(args);
00597 cgi_value_arr.resize(args);
00598 cgi_name_arr[args]=decode_reserved(name);
00599 cgi_value_arr[args]=decode_reserved(value);
00600 }
00601 }
00602 }
00603
00604 void
00605 GURL::store_cgi_args(void)
00606
00607
00608 {
00609 if(!validurl)
00610 init();
00611 GCriticalSectionLock lock1(&class_lock);
00612
00613 const char * const url_ptr=url;
00614 const char * ptr;
00615 for(ptr=url_ptr;*ptr&&(*ptr!='?');ptr++)
00616 EMPTY_LOOP;
00617
00618 GUTF8String new_url(url_ptr, ptr-url_ptr);
00619
00620 for(int i=0;i<cgi_name_arr.size();i++)
00621 {
00622 GUTF8String name=GURL::encode_reserved(cgi_name_arr[i]);
00623 GUTF8String value=GURL::encode_reserved(cgi_value_arr[i]);
00624 new_url+=(i?"&":"?")+name;
00625 if (value.length())
00626 new_url+="="+value;
00627 }
00628
00629 url=new_url;
00630 }
00631
00632 int
00633 GURL::cgi_arguments(void) const
00634 {
00635 if(!validurl)
00636 const_cast<GURL *>(this)->init();
00637 return cgi_name_arr.size();
00638 }
00639
00640 int
00641 GURL::djvu_cgi_arguments(void) const
00642 {
00643 if(!validurl)
00644 const_cast<GURL *>(this)->init();
00645 GCriticalSectionLock lock((GCriticalSection *) &class_lock);
00646
00647 int args=0;
00648 for(int i=0;i<cgi_name_arr.size();i++)
00649 {
00650 if (cgi_name_arr[i].upcase()==djvuopts)
00651 {
00652 args=cgi_name_arr.size()-(i+1);
00653 break;
00654 }
00655 }
00656 return args;
00657 }
00658
00659 GUTF8String
00660 GURL::cgi_name(int num) const
00661 {
00662 if(!validurl) const_cast<GURL *>(this)->init();
00663 GCriticalSectionLock lock((GCriticalSection *) &class_lock);
00664 return (num<cgi_name_arr.size())?cgi_name_arr[num]:GUTF8String();
00665 }
00666
00667 GUTF8String
00668 GURL::djvu_cgi_name(int num) const
00669 {
00670 if(!validurl) const_cast<GURL *>(this)->init();
00671 GCriticalSectionLock lock((GCriticalSection *) &class_lock);
00672
00673 GUTF8String arg;
00674 for(int i=0;i<cgi_name_arr.size();i++)
00675 if (cgi_name_arr[i].upcase()==djvuopts)
00676 {
00677 for(i++;i<cgi_name_arr.size();i++)
00678 if (! num--)
00679 {
00680 arg=cgi_name_arr[i];
00681 break;
00682 }
00683 break;
00684 }
00685 return arg;
00686 }
00687
00688 GUTF8String
00689 GURL::cgi_value(int num) const
00690 {
00691 if(!validurl) const_cast<GURL *>(this)->init();
00692 GCriticalSectionLock lock((GCriticalSection *) &class_lock);
00693 return (num<cgi_value_arr.size())?cgi_value_arr[num]:GUTF8String();
00694 }
00695
00696 GUTF8String
00697 GURL::djvu_cgi_value(int num) const
00698 {
00699 if(!validurl) const_cast<GURL *>(this)->init();
00700 GCriticalSectionLock lock((GCriticalSection *) &class_lock);
00701
00702 GUTF8String arg;
00703 for(int i=0;i<cgi_name_arr.size();i++)
00704 {
00705 if (cgi_name_arr[i].upcase()==djvuopts)
00706 {
00707 for(i++;i<cgi_name_arr.size();i++)
00708 {
00709 if (! num--)
00710 {
00711 arg=cgi_value_arr[i];
00712 break;
00713 }
00714 }
00715 break;
00716 }
00717 }
00718 return arg;
00719 }
00720
00721 DArray<GUTF8String>
00722 GURL::cgi_names(void) const
00723 {
00724 if(!validurl) const_cast<GURL *>(this)->init();
00725 GCriticalSectionLock lock((GCriticalSection *) &class_lock);
00726 return cgi_name_arr;
00727 }
00728
00729 DArray<GUTF8String>
00730 GURL::cgi_values(void) const
00731 {
00732 if(!validurl) const_cast<GURL *>(this)->init();
00733 GCriticalSectionLock lock((GCriticalSection *) &class_lock);
00734 return cgi_value_arr;
00735 }
00736
00737 DArray<GUTF8String>
00738 GURL::djvu_cgi_names(void) const
00739 {
00740 if(!validurl) const_cast<GURL *>(this)->init();
00741 GCriticalSectionLock lock((GCriticalSection *) &class_lock);
00742
00743 int i;
00744 DArray<GUTF8String> arr;
00745 for(i=0;(i<cgi_name_arr.size())&&
00746 (cgi_name_arr[i].upcase()!=djvuopts)
00747 ;i++)
00748 EMPTY_LOOP;
00749
00750 int size=cgi_name_arr.size()-(i+1);
00751 if (size>0)
00752 {
00753 arr.resize(size-1);
00754 for(i=0;i<arr.size();i++)
00755 arr[i]=cgi_name_arr[cgi_name_arr.size()-arr.size()+i];
00756 }
00757
00758 return arr;
00759 }
00760
00761 DArray<GUTF8String>
00762 GURL::djvu_cgi_values(void) const
00763 {
00764 if(!validurl) const_cast<GURL *>(this)->init();
00765 GCriticalSectionLock lock((GCriticalSection *) &class_lock);
00766
00767 int i;
00768 DArray<GUTF8String> arr;
00769 for(i=0;i<cgi_name_arr.size()&&(cgi_name_arr[i].upcase()!=djvuopts);i++)
00770 EMPTY_LOOP;
00771
00772 int size=cgi_name_arr.size()-(i+1);
00773 if (size>0)
00774 {
00775 arr.resize(size-1);
00776 for(i=0;i<arr.size();i++)
00777 arr[i]=cgi_value_arr[cgi_value_arr.size()-arr.size()+i];
00778 }
00779
00780 return arr;
00781 }
00782
00783 void
00784 GURL::clear_all_arguments(void)
00785 {
00786 clear_hash_argument();
00787 clear_cgi_arguments();
00788 }
00789
00790 void
00791 GURL::clear_hash_argument(void)
00792
00793 {
00794 if(!validurl) init();
00795 GCriticalSectionLock lock(&class_lock);
00796 bool found=false;
00797 GUTF8String new_url;
00798 for(const char * start=url;*start;start++)
00799 {
00800
00801 if (*start=='?')
00802 {
00803 new_url+=start;
00804 break;
00805 }
00806
00807 if (!found)
00808 {
00809 if (*start=='#')
00810 found=true;
00811 else
00812 new_url+=*start;
00813 }
00814 }
00815 url=new_url;
00816 }
00817
00818 void
00819 GURL::clear_cgi_arguments(void)
00820 {
00821 if(!validurl)
00822 init();
00823 GCriticalSectionLock lock1(&class_lock);
00824
00825
00826 cgi_name_arr.empty();
00827 cgi_value_arr.empty();
00828
00829
00830 for(const char * ptr=url;*ptr;ptr++)
00831 if (*ptr=='?')
00832 {
00833 url.setat(ptr-url, 0);
00834 break;
00835 }
00836 }
00837
00838 void
00839 GURL::clear_djvu_cgi_arguments(void)
00840 {
00841 if(!validurl) init();
00842
00843 GCriticalSectionLock lock(&class_lock);
00844 for(int i=0;i<cgi_name_arr.size();i++)
00845 {
00846 if (cgi_name_arr[i].upcase()==djvuopts)
00847 {
00848 cgi_name_arr.resize(i-1);
00849 cgi_value_arr.resize(i-1);
00850 break;
00851 }
00852 }
00853
00854
00855 store_cgi_args();
00856 }
00857
00858 void
00859 GURL::add_djvu_cgi_argument(const GUTF8String &name, const char * value)
00860 {
00861 if(!validurl)
00862 init();
00863 GCriticalSectionLock lock1(&class_lock);
00864
00865
00866 bool have_djvuopts=false;
00867 for(int i=0;i<cgi_name_arr.size();i++)
00868 {
00869 if (cgi_name_arr[i].upcase()==djvuopts)
00870 {
00871 have_djvuopts=true;
00872 break;
00873 }
00874 }
00875
00876
00877 if (!have_djvuopts)
00878 {
00879 int pos=cgi_name_arr.size();
00880 cgi_name_arr.resize(pos);
00881 cgi_value_arr.resize(pos);
00882 cgi_name_arr[pos]=djvuopts;
00883 }
00884
00885
00886 int pos=cgi_name_arr.size();
00887 cgi_name_arr.resize(pos);
00888 cgi_value_arr.resize(pos);
00889 cgi_name_arr[pos]=name;
00890 cgi_value_arr[pos]=value;
00891
00892
00893 store_cgi_args();
00894 }
00895
00896 bool
00897 GURL::is_local_file_url(void) const
00898 {
00899 if(!validurl) const_cast<GURL *>(this)->init();
00900 GCriticalSectionLock lock((GCriticalSection *) &class_lock);
00901 return (protocol()=="file" && url[5]==slash);
00902 }
00903
00904 static const int
00905 pathname_start(const GUTF8String &url, const int protolength)
00906 {
00907 const int length=url.length();
00908 int retval=0;
00909 if(protolength+1<length)
00910 {
00911 retval=url.search(slash,((url[protolength+1] == '/')
00912 ?((url[protolength+2] == '/')?(protolength+3):(protolength+2))
00913 :(protolength+1)));
00914 }
00915 return (retval>0)?retval:length;
00916 }
00917
00918 GUTF8String
00919 GURL::pathname(void) const
00920 {
00921 return (is_local_file_url())
00922 ?GURL::encode_reserved(UTF8Filename())
00923 :url.substr(pathname_start(url,protocol().length()),(unsigned int)(-1));
00924 }
00925
00926 GURL
00927 GURL::base(void) const
00928 {
00929 const GUTF8String xurl(get_string());
00930 const int protocol_length=protocol(xurl).length();
00931 const int xurl_length=xurl.length();
00932 const char * const url_ptr=xurl;
00933 const char * ptr, * xslash;
00934 ptr=xslash=url_ptr+protocol_length+1;
00935 if(xslash[0] == '/')
00936 {
00937 xslash++;
00938 if(xslash[0] == '/')
00939 xslash++;
00940 for(ptr=xslash;ptr[0] && !is_argument(ptr);ptr++)
00941 {
00942 if ((ptr[0]==slash)&&ptr[1]&&!is_argument(ptr+1))
00943 xslash=ptr;
00944 }
00945 if(xslash[0] != '/')
00946 {
00947 xslash=url_ptr+xurl_length;
00948 }
00949 }
00950 return GURL::UTF8(
00951
00952
00953
00954
00955 (GUTF8String(xurl,(int)(xslash-url_ptr))+"/"));
00956 }
00957
00958 bool
00959 GURL::operator==(const GURL & gurl2) const
00960 {
00961 bool retval=false;
00962 const GUTF8String g1(get_string());
00963 const int g1_length=g1.length();
00964 const GUTF8String g2(gurl2.get_string());
00965 const int g2_length=g2.length();
00966 if(g1_length == g2_length)
00967 {
00968 retval=(g1==g2);
00969 }else if(g1_length+1 == g2_length)
00970 {
00971 retval=(g2[g1_length] == '/')&&!g1.cmp(g2,g1_length);
00972 }else if(g2_length+1 == g1_length)
00973 {
00974 retval=(g1[g2_length] == '/')&&!g1.cmp(g2,g2_length);
00975 }
00976 return retval;
00977 }
00978
00979 GUTF8String
00980 GURL::name(void) const
00981 {
00982 if(!validurl)
00983 const_cast<GURL *>(this)->init();
00984 GUTF8String retval;
00985 if(!is_empty())
00986 {
00987 const GUTF8String xurl(url);
00988 const int protocol_length=protocol(xurl).length();
00989 const char * ptr, * xslash=(const char *)xurl+protocol_length-1;
00990 for(ptr=(const char *)xurl+protocol_length;
00991 *ptr && !is_argument(ptr);ptr++)
00992 {
00993 if (*ptr==slash)
00994 xslash=ptr;
00995 }
00996 retval=GUTF8String(xslash+1, ptr-xslash-1);
00997 }
00998 return retval;
00999 }
01000
01001 GUTF8String
01002 GURL::fname(void) const
01003 {
01004 if(!validurl)
01005 const_cast<GURL *>(this)->init();
01006 return decode_reserved(name());
01007 }
01008
01009 GUTF8String
01010 GURL::extension(void) const
01011 {
01012 if(!validurl)
01013 const_cast<GURL *>(this)->init();
01014 GUTF8String xfilename=name();
01015 GUTF8String retval;
01016
01017 for(int i=xfilename.length()-1;i>=0;i--)
01018 {
01019 if (xfilename[i]=='.')
01020 {
01021 retval=(const char*)xfilename+i+1;
01022 break;
01023 }
01024 }
01025 return retval;
01026 }
01027
01028 GUTF8String
01029 GURL::decode_reserved(const GUTF8String &gurl)
01030 {
01031 const char *url=gurl;
01032 char *res;
01033 GPBuffer<char> gres(res,gurl.length()+1);
01034 char *r=res;
01035 for(const char * ptr=url;*ptr;++ptr,++r)
01036 {
01037 if (*ptr!=percent)
01038 {
01039 r[0]=*ptr;
01040 }else
01041 {
01042 int c1,c2;
01043 if ( ((c1=hexval(ptr[1]))>=0)
01044 && ((c2=hexval(ptr[2]))>=0) )
01045 {
01046 r[0]=(c1<<4)|c2;
01047 ptr+=2;
01048 } else
01049 {
01050 r[0]=*ptr;
01051 }
01052 }
01053 }
01054 r[0]=0;
01055 GUTF8String retval(res);
01056 if(!retval.is_valid())
01057 {
01058 retval=GNativeString(res);
01059 }
01060 return retval;
01061 }
01062
01063 GUTF8String
01064 GURL::encode_reserved(const GUTF8String &gs)
01065 {
01066 const char *s=(const char *)gs;
01067
01068 static const char hex[] = "0123456789ABCDEF";
01069
01070 unsigned char *retval;
01071 GPBuffer<unsigned char> gd(retval,strlen(s)*3+1);
01072 unsigned char *d=retval;
01073 for (; *s; s++,d++)
01074 {
01075
01076 #if defined(WIN32) || defined(OS2)
01077 if (*s == backslash || *s== slash)
01078 #else
01079 #ifdef macintosh
01080 if (*s == colon )
01081 #else
01082 #ifdef UNIX
01083 if (*s == slash )
01084 #else
01085 #error "Define something here for your operating system"
01086 #endif
01087 #endif
01088 #endif
01089 {
01090 *d = slash;
01091 continue;
01092 }
01093 unsigned char const ss=(unsigned char const)(*s);
01094
01095
01096
01097
01098
01099
01100
01101 if ( (ss>='a' && ss<='z') ||
01102 (ss>='A' && ss<='Z') ||
01103 (ss>='0' && ss<='9') ||
01104 (strchr("$-_.+!*'(),:~=", ss)) )
01105 {
01106 *d = ss;
01107 continue;
01108 }
01109
01110 d[0] = percent;
01111 d[1] = hex[ (ss >> 4) & 0xf ];
01112 d[2] = hex[ (ss) & 0xf ];
01113 d+=2;
01114 }
01115 *d = 0;
01116 return retval;
01117 }
01118
01119
01120
01121
01122
01123 static GUTF8String
01124 url_from_UTF8filename(const GUTF8String &gfilename)
01125 {
01126 if(GURL::UTF8(gfilename).is_valid())
01127 {
01128 DEBUG_MSG("Debug: URL as Filename: " << gfilename << "\n");
01129 }
01130 const char *filename=gfilename;
01131 if(filename && (unsigned char)filename[0] == (unsigned char)0xEF
01132 && (unsigned char)filename[1] == (unsigned char)0xBB
01133 && (unsigned char)filename[2] == (unsigned char)0xBF)
01134 {
01135 filename+=3;
01136 }
01137
01138
01139 if(!filename || !filename[0])
01140 {
01141 return GUTF8String();
01142 }
01143
01144
01145 GUTF8String oname=GURL::expand_name(filename);
01146 GUTF8String nname=GURL::encode_reserved(oname);
01147
01148
01149
01150 GUTF8String url=filespecslashes;
01151 const char *cnname=nname;
01152 if (cnname[0] == slash)
01153 {
01154 if (cnname[1] == slash)
01155 {
01156 url += cnname+2;
01157 }else
01158 {
01159 url = localhost + nname;
01160 }
01161 }else
01162 {
01163 url += (localhostspec1+2) + nname;
01164 }
01165 return url;
01166 }
01167
01168 GUTF8String
01169 GURL::get_string(const bool nothrow) const
01170 {
01171 if(!validurl)
01172 const_cast<GURL *>(this)->init(nothrow);
01173 return url;
01174 }
01175
01176
01177
01178
01179 GUTF8String
01180 GURL::get_string(const GUTF8String &useragent) const
01181 {
01182 if(!validurl)
01183 const_cast<GURL *>(this)->init();
01184 GUTF8String retval(url);
01185 if(is_local_file_url()&&useragent.length())
01186 {
01187 if(useragent.search("MSIE") >= 0 || useragent.search("Microsoft")>=0)
01188 {
01189 retval=filespecslashes + expand_name(UTF8Filename());
01190 }
01191 }
01192 return retval;
01193 }
01194
01195 GURL::UTF8::UTF8(const GUTF8String &xurl)
01196 : GURL(xurl) {}
01197
01198 GURL::UTF8::UTF8(const GUTF8String &xurl,const GURL &codebase)
01199 : GURL(xurl,codebase) {}
01200
01201 GURL::GURL(const GUTF8String &xurl,const GURL &codebase)
01202 : validurl(false)
01203 {
01204 if(GURL::UTF8(xurl).is_valid())
01205 {
01206 url=xurl;
01207 }else
01208 {
01209 const char *c=xurl;
01210 if(c[0] == slash)
01211 {
01212 GURL base(codebase);
01213 for(GURL newbase=base.base();newbase!=base;newbase=base.base())
01214 {
01215 base=newbase;
01216 }
01217 url=base.get_string(true)+GURL::encode_reserved(xurl);
01218 }else
01219 {
01220 url=beautify_path(codebase.get_string(true)+GUTF8String(slash)+GURL::encode_reserved(xurl));
01221 }
01222 }
01223 }
01224
01225 GURL::Native::Native(const GNativeString &xurl)
01226 : GURL(xurl) {}
01227
01228 GURL::Native::Native(const GNativeString &xurl,const GURL &codebase)
01229 : GURL(xurl,codebase) {}
01230
01231 GURL::GURL(const GNativeString &xurl,const GURL &codebase)
01232 : validurl(false)
01233 {
01234 GURL retval(xurl.getNative2UTF8(),codebase);
01235 if(retval.is_valid())
01236 {
01237 #if defined(WIN32)
01238
01239 if(retval.is_local_file_url())
01240 {
01241 GURL::Filename::UTF8 retval2(retval.UTF8Filename());
01242 url=retval2.get_string(true);
01243 validurl=false;
01244 }else
01245 #endif // WIN32
01246 {
01247 url=retval.get_string(true);
01248 validurl=false;
01249 }
01250 }
01251 }
01252
01253 GURL::Filename::Filename(const GNativeString &gfilename)
01254 {
01255 url=url_from_UTF8filename(gfilename.getNative2UTF8());
01256 }
01257
01258 GURL::Filename::Native::Native(const GNativeString &gfilename)
01259 : GURL::Filename(gfilename) {}
01260
01261 GURL::Filename::Filename(const GUTF8String &gfilename)
01262 {
01263 url=url_from_UTF8filename(gfilename);
01264 }
01265
01266 GURL::Filename::UTF8::UTF8(const GUTF8String &gfilename)
01267 : GURL::Filename(gfilename) {}
01268
01269
01270
01271
01272 GUTF8String
01273 GURL::UTF8Filename(void) const
01274 {
01275 GUTF8String retval;
01276 if(! is_empty())
01277 {
01278 const char *url_ptr=url;
01279
01280
01281
01282
01283
01284
01285
01286
01287 GUTF8String urlcopy=decode_reserved(url);
01288 url_ptr = urlcopy;
01289
01290
01291 if (GStringRep::cmp(filespec, url_ptr, sizeof(filespec)-1))
01292 return GOS::basename(url_ptr);
01293 url_ptr += sizeof(filespec)-1;
01294
01295 #if defined(macintosh)
01296
01297 for(;*url_ptr==slash;url_ptr++)
01298 EMPTY_LOOP;
01299
01300 if ( !GStringRep::cmp(localhost, url_ptr, sizeof(localhost)-1) )
01301 url_ptr += sizeof(localhost)-1;
01302
01303 while(*url_ptr==slash)
01304 url_ptr++;
01305 #else
01306
01307 if ( !GStringRep::cmp(localhostspec1, url_ptr, sizeof(localhostspec1)-1) )
01308
01309 url_ptr += sizeof(localhostspec1)-1;
01310 else if ( !GStringRep::cmp(localhostspec2, url_ptr, sizeof(localhostspec2)-1 ) )
01311
01312 url_ptr += sizeof(localhostspec2)-1;
01313 else if ( (strlen(url_ptr) > 4)
01314 && (url_ptr[0] == slash)
01315 && (url_ptr[1] == slash)
01316 && isalpha(url_ptr[2])
01317 && ( url_ptr[3] == colon || url_ptr[3] == '|' )
01318 && (url_ptr[4] == slash) )
01319 url_ptr += 2;
01320 else if ( (strlen(url_ptr)) > 2
01321 && (url_ptr[0] == slash)
01322 && (url_ptr[1] != slash) )
01323 url_ptr++;
01324 #endif
01325
01326
01327 #if defined(macintosh)
01328 {
01329 char *l_url;
01330 GPBuffer<char> gl_url(l_url,strlen(url_ptr)+1);
01331 const char *s;
01332 char *r;
01333 for ( s=url_ptr,r=l_url; *s; s++,r++)
01334 {
01335 *r=(*s == slash)?colon:*s;
01336 }
01337 *r=0;
01338 retval = expand_name(l_url,root);
01339 }
01340 #else
01341 retval = expand_name(url_ptr,root);
01342 #endif
01343
01344 #if defined(WIN32) || defined(OS2)
01345 if (url_ptr[0] && url_ptr[1]=='|' && url_ptr[2]== slash)
01346 {
01347 if ((url_ptr[0]>='a' && url_ptr[0]<='z')
01348 || (url_ptr[0]>='A' && url_ptr[0]<='Z'))
01349 {
01350 GUTF8String drive;
01351 drive.format("%c%c%c", url_ptr[0],colon,backslash);
01352 retval = expand_name(url_ptr+3, drive);
01353 }
01354 }
01355 #endif
01356 }
01357
01358 return retval;
01359 }
01360
01361 GNativeString
01362 GURL::NativeFilename(void) const
01363 {
01364 return UTF8Filename().getUTF82Native();
01365 }
01366
01367 #if defined(UNIX) || defined(macintosh) || defined(OS2)
01368 static int
01369 urlstat(const GURL &url,struct stat &buf)
01370 {
01371 return ::stat(url.NativeFilename(),&buf);
01372 }
01373 #endif
01374
01375
01376
01377 bool
01378 GURL::is_file(void) const
01379 {
01380 bool retval=false;
01381 if(is_local_file_url())
01382 {
01383 #if defined(UNIX) || defined(macintosh) || defined(OS2)
01384 struct stat buf;
01385 if (!urlstat(*this,buf))
01386 {
01387 retval=!(buf.st_mode & S_IFDIR);
01388 }
01389 #elif defined(WIN32)
01390 GUTF8String filename(UTF8Filename());
01391 if(filename.length() >= MAX_PATH)
01392 {
01393 if(!filename.cmp("\\\\",2))
01394 filename="\\\\?\\UNC"+filename.substr(1,-1);
01395 else
01396 filename="\\\\?\\"+filename;
01397 }
01398 wchar_t *wfilename;
01399 const size_t wfilename_size=filename.length()+1;
01400 GPBuffer<wchar_t> gwfilename(wfilename,wfilename_size);
01401 filename.ncopy(wfilename,wfilename_size);
01402 DWORD dwAttrib;
01403 dwAttrib = GetFileAttributesW(wfilename);
01404 if((dwAttrib|1) == 0xFFFFFFFF)
01405 {
01406 USES_CONVERSION ;
01407 dwAttrib = GetFileAttributes(A2CT(NativeFilename())) ;
01408 }
01409 retval=!( dwAttrib & FILE_ATTRIBUTE_DIRECTORY );
01410 #else
01411 # error "Define something here for your operating system"
01412 #endif
01413 }
01414 return retval;
01415 }
01416
01417 bool
01418 GURL::is_local_path(void) const
01419 {
01420 bool retval=false;
01421 if(is_local_file_url())
01422 {
01423 #if defined(UNIX) || defined(macintosh) || defined(OS2)
01424 struct stat buf;
01425 retval=!urlstat(*this,buf);
01426 #else
01427 GUTF8String filename(UTF8Filename());
01428 if(filename.length() >= MAX_PATH)
01429 {
01430 if(!filename.cmp("\\\\",2))
01431 filename="\\\\?\\UNC"+filename.substr(1,-1);
01432 else
01433 filename="\\\\?\\"+filename;
01434 }
01435 wchar_t *wfilename;
01436 const size_t wfilename_size=filename.length()+1;
01437 GPBuffer<wchar_t> gwfilename(wfilename,wfilename_size);
01438 filename.ncopy(wfilename,wfilename_size);
01439 DWORD dwAttrib;
01440 dwAttrib = GetFileAttributesW(wfilename);
01441 if((dwAttrib|1) == 0xFFFFFFFF)
01442 {
01443 USES_CONVERSION ;
01444 dwAttrib = GetFileAttributes(A2CT(NativeFilename())) ;
01445 }
01446 retval=( (dwAttrib|1) != 0xFFFFFFFF);
01447 #endif
01448 }
01449 return retval;
01450 }
01451
01452
01453
01454 bool
01455 GURL::is_dir(void) const
01456 {
01457 bool retval=false;
01458 if(is_local_file_url())
01459 {
01460
01461 #if defined(UNIX) || defined(macintosh) || defined(OS2)
01462 struct stat buf;
01463 if (!urlstat(*this,buf))
01464 {
01465 retval=(buf.st_mode & S_IFDIR);
01466 }
01467 #elif defined(WIN32) // (either Windows or WCE)
01468 GUTF8String filename(UTF8Filename());
01469 if(filename.length() >= MAX_PATH)
01470 {
01471 if(!filename.cmp("\\\\",2))
01472 filename="\\\\?\\UNC"+filename.substr(1,-1);
01473 else
01474 filename="\\\\?\\"+filename;
01475 }
01476 wchar_t *wfilename;
01477 const size_t wfilename_size=filename.length()+1;
01478 GPBuffer<wchar_t> gwfilename(wfilename,wfilename_size);
01479 filename.ncopy(wfilename,wfilename_size);
01480 DWORD dwAttrib;
01481 dwAttrib = GetFileAttributesW(wfilename);
01482 if((dwAttrib|1) == 0xFFFFFFFF)
01483 {
01484 USES_CONVERSION ;
01485 dwAttrib = GetFileAttributes(A2CT(NativeFilename())) ;
01486 }
01487 retval=((dwAttrib != 0xFFFFFFFF)&&( dwAttrib & FILE_ATTRIBUTE_DIRECTORY ));
01488 #else
01489 # error "Define something here for your operating system"
01490 #endif
01491 }
01492 return retval;
01493 }
01494
01495
01496 GURL
01497 GURL::follow_symlinks(void) const
01498 {
01499 GURL ret = *this;
01500 #if defined(S_IFLNK)
01501 #if defined(UNIX) || defined(macintosh)
01502 int lnklen;
01503 char lnkbuf[MAXPATHLEN+1];
01504 struct stat buf;
01505 while ( (urlstat(ret, buf) >= 0) &&
01506 (buf.st_mode & S_IFLNK) &&
01507 ((lnklen = readlink(ret.NativeFilename(),lnkbuf,sizeof(lnkbuf))) > 0) )
01508 {
01509 lnkbuf[lnklen] = 0;
01510 GNativeString lnk(lnkbuf);
01511 ret = GURL(lnk, ret.base());
01512 }
01513 #endif
01514 #endif
01515 return ret;
01516 }
01517
01518 int
01519 GURL::mkdir() const
01520 {
01521 if(! is_local_file_url())
01522 return -1;
01523 int retval=0;
01524 const GURL baseURL=base();
01525 if (baseURL.get_string() != url && !baseURL.is_dir())
01526 retval = baseURL.mkdir();
01527 if(!retval)
01528 {
01529 #if defined(UNIX)
01530 if (is_dir())
01531 retval = 0;
01532 else
01533 retval = ::mkdir(NativeFilename(), 0755);
01534 #elif defined(WIN32)
01535 USES_CONVERSION;
01536 if (is_dir())
01537 retval = 0;
01538 else
01539 retval = CreateDirectory(A2CT(NativeFilename()), NULL);
01540 #else
01541 # error "Define something here for your operating system"
01542 #endif
01543 }
01544 return retval;
01545 }
01546
01547
01548
01549
01550 int
01551 GURL::deletefile(void) const
01552 {
01553 int retval = -1;
01554 if(is_local_file_url())
01555 {
01556 #if defined(UNIX)
01557 if (is_dir())
01558 retval = ::rmdir(NativeFilename());
01559 else
01560 retval = ::unlink(NativeFilename());
01561 #elif defined(WIN32)
01562 USES_CONVERSION;
01563 if (is_dir())
01564 retval = ::RemoveDirectory(A2CT(NativeFilename()));
01565 else
01566 retval = ::DeleteFile(A2CT(NativeFilename()));
01567 #else
01568 # error "Define something here for your operating system"
01569 #endif
01570 }
01571 return retval;
01572 }
01573
01574 GList<GURL>
01575 GURL::listdir(void) const
01576 {
01577 GList<GURL> retval;
01578 if(is_dir())
01579 {
01580 #if defined(UNIX) || defined(OS2)
01581 DIR * dir=opendir(NativeFilename());
01582 for(dirent *de=readdir(dir);de;de=readdir(dir))
01583 {
01584 const int len = NAMLEN(de);
01585 if (de->d_name[0]== dot && len==1)
01586 continue;
01587 if (de->d_name[0]== dot && de->d_name[1]== dot && len==2)
01588 continue;
01589 retval.append(GURL::Native(de->d_name,*this));
01590 }
01591 closedir(dir);
01592 #elif defined (WIN32)
01593 GURL::UTF8 wildcard("*.*",*this);
01594 WIN32_FIND_DATA finddata;
01595 HANDLE handle = FindFirstFile(wildcard.NativeFilename(), &finddata);
01596 const GUTF8String gpathname=pathname();
01597 const GUTF8String gbase=base().pathname();
01598 if( handle != INVALID_HANDLE_VALUE)
01599 {
01600 do
01601 {
01602 GURL::UTF8 Entry(finddata.cFileName,*this);
01603 const GUTF8String gentry=Entry.pathname();
01604 if((gentry != gpathname) && (gentry != gbase))
01605 retval.append(Entry);
01606 } while( FindNextFile(handle, &finddata) );
01607
01608 FindClose(handle);
01609 }
01610 #else
01611 # error "Define something here for your operating system"
01612 #endif
01613 }
01614 return retval;
01615 }
01616
01617 int
01618 GURL::cleardir(const int timeout) const
01619 {
01620 int retval=(-1);
01621 if(is_dir())
01622 {
01623 GList<GURL> dirlist=listdir();
01624 retval=0;
01625 for(GPosition pos=dirlist;pos&&!retval;++pos)
01626 {
01627 const GURL &Entry=dirlist[pos];
01628 if(Entry.is_dir())
01629 {
01630 if((retval=Entry.cleardir(timeout)) < 0)
01631 {
01632 break;
01633 }
01634 }
01635 if(((retval=Entry.deletefile())<0) && (timeout>0))
01636 {
01637 GOS::sleep(timeout);
01638 retval=Entry.deletefile();
01639 }
01640 }
01641 }
01642 return retval;
01643 }
01644
01645 int
01646 GURL::renameto(const GURL &newurl) const
01647 {
01648 if (is_local_file_url() && newurl.is_local_file_url())
01649 return rename(NativeFilename(),newurl.NativeFilename());
01650 return -1;
01651 }
01652
01653
01654
01655
01656
01657 GUTF8String
01658 GURL::expand_name(const GUTF8String &xfname, const char *from)
01659 {
01660 const char *fname=xfname;
01661 GUTF8String retval;
01662 const size_t maxlen=xfname.length()*9+MAXPATHLEN+10;
01663 char * const string_buffer = retval.getbuf(maxlen);
01664
01665 #if defined(UNIX)
01666
01667 GUTF8String senv;
01668 if (fname && fname[0]==tilde)
01669 {
01670 int n;
01671 for(n=1;fname[n] && fname[n]!= slash;n++)
01672 EMPTY_LOOP;
01673 struct passwd *pw=0;
01674 if (n!=1)
01675 {
01676 GUTF8String user(fname+1, n-1);
01677 pw=getpwnam(user);
01678 }else if ((senv=GOS::getenv("HOME")).length())
01679 {
01680 from=(const char *)senv;
01681 fname = fname + n;
01682 }else if ((senv=GOS::getenv("LOGNAME")).length())
01683 {
01684 pw = getpwnam((const char *)senv.getUTF82Native());
01685 }else
01686 {
01687 pw=getpwuid(getuid());
01688 }
01689 if (pw)
01690 {
01691 senv=GNativeString(pw->pw_dir).getNative2UTF8();
01692 from = (const char *)senv;
01693 fname = fname + n;
01694 }
01695 for(;fname[0] == slash; fname++)
01696 EMPTY_LOOP;
01697 }
01698
01699 if (fname && fname[0]== slash)
01700 {
01701 string_buffer[0]=slash;
01702 string_buffer[1]=0;
01703 }else if (from)
01704 {
01705 strcpy(string_buffer, expand_name(from));
01706 }else
01707 {
01708 strcpy(string_buffer, GOS::cwd());
01709 }
01710 char *s = string_buffer + strlen(string_buffer);
01711 if(fname)
01712 {
01713 for(;fname[0]== slash;fname++)
01714 EMPTY_LOOP;
01715
01716 while(fname[0])
01717 {
01718 if (fname[0] == dot )
01719 {
01720 if (!fname[1] || fname[1]== slash)
01721 {
01722 fname++;
01723 continue;
01724 }else if (fname[1]== dot && (fname[2]== slash || !fname[2]))
01725 {
01726 fname +=2;
01727 for(;s>string_buffer+1 && *(s-1)== slash; s--)
01728 EMPTY_LOOP;
01729 for(;s>string_buffer+1 && *(s-1)!= slash; s--)
01730 EMPTY_LOOP;
01731 continue;
01732 }
01733 }
01734 if ((s==string_buffer)||(*(s-1)!= slash))
01735 {
01736 *s = slash;
01737 s++;
01738 }
01739 while (*fname &&(*fname!= slash))
01740 {
01741 *s = *fname++;
01742 if ((size_t)((++s)-string_buffer) > maxlen)
01743 {
01744 G_THROW( ERR_MSG("GURL.big_name") );
01745 }
01746 }
01747 *s = 0;
01748 for(;fname[0]== slash;fname++)
01749 EMPTY_LOOP;
01750 }
01751 }
01752 if (!fname || !fname[0])
01753 {
01754 for(;s>string_buffer+1 && *(s-1) == slash; s--)
01755 EMPTY_LOOP;
01756 *s = 0;
01757 }
01758 #elif defined (WIN32) // WIN32 implementation
01759
01760 strcpy(string_buffer, (char const *)(from ? expand_name(from) : GOS::cwd()));
01761
01762 if (fname)
01763 {
01764 char *s = string_buffer;
01765 char drv[4];
01766
01767
01768
01769 if (fname[0]== slash || fname[0]== backslash)
01770 {
01771 if (fname[1]== slash || fname[1]== backslash)
01772 {
01773 s[0]=s[1]= backslash; s[2]=0;
01774 }
01775 else
01776 {
01777
01778
01779
01780
01781 fname++;
01782 s[3] = '\0';
01783 }
01784 }
01785 else if (fname[0] && fname[1]==colon)
01786 {
01787 if (fname[2]!= slash && fname[2]!= backslash)
01788 {
01789 if ( toupper((unsigned char)s[0]) != toupper((unsigned char)fname[0])
01790 || s[1]!=colon)
01791 {
01792 drv[0]=fname[0];
01793 drv[1]=colon;
01794 drv[2]= dot ;
01795 drv[3]=0;
01796 GetFullPathName(drv, maxlen, string_buffer, &s);
01797 strcpy(string_buffer,(const char *)GUTF8String(string_buffer).getNative2UTF8());
01798 s = string_buffer;
01799 }
01800 fname += 2;
01801 }
01802 else if (fname[3]!= slash && fname[3]!= backslash)
01803 {
01804 s[0]=toupper((unsigned char)fname[0]);
01805 s[1]=colon;
01806 s[2]=backslash;
01807 s[3]=0;
01808 fname += 3;
01809 }
01810 else
01811 {
01812 s[0]=s[1]=backslash;
01813 s[2]=0;
01814 fname += 4;
01815 }
01816 }
01817
01818 for(;*fname== slash || *fname==backslash;fname++)
01819 EMPTY_LOOP;
01820 while(*fname)
01821 {
01822 if (fname[0]== dot )
01823 {
01824 if (fname[1]== slash || fname[1]==backslash || !fname[1])
01825 {
01826 fname++;
01827 continue;
01828 }else if ((fname[1] == dot)
01829 && (fname[2]== slash || fname[2]==backslash || !fname[2]))
01830 {
01831 fname += 2;
01832 char *back=_tcsrchr(string_buffer,backslash);
01833 char *forward=_tcsrchr(string_buffer,slash);
01834 if(back>forward)
01835 {
01836 *back=0;
01837 }else if(forward)
01838 {
01839 *forward=0;
01840 }
01841 s = string_buffer;
01842 continue;
01843 }
01844 char* s2=s;
01845 for(;*s;s++)
01846 EMPTY_LOOP;
01847 char* back = _tcsrchr(s2,backslash);
01848 if ((s>string_buffer)&&(*(s-1)!= slash)&&
01849 (back == NULL || (back!=NULL && s-1 != back) ))
01850 {
01851 *s = backslash;
01852 s++;
01853 }
01854 while (*fname && *fname!= slash && *fname!=backslash)
01855 {
01856 *s = *fname++;
01857 if ((size_t)((++s)-string_buffer) > maxlen)
01858 G_THROW( ERR_MSG("GURL.big_name") );
01859 }
01860 *s = 0;
01861 }
01862 char* s2=s;
01863 for(;*s;s++)
01864 EMPTY_LOOP;
01865 char* back = _tcsrchr(s2,backslash);
01866 if ((s>string_buffer)&&(*(s-1)!= slash)
01867 &&(back == NULL || (back!=NULL && s-1 != back) ))
01868 {
01869 *s = backslash;
01870 s++;
01871 }
01872 while (*fname && (*fname!= slash) && (*fname!=backslash))
01873 {
01874 *s = *fname++;
01875 if ((size_t)((++s)-string_buffer) > maxlen)
01876 G_THROW( ERR_MSG("GURL.big_name") );
01877 }
01878 *s = 0;
01879 for(;(*fname== slash)||(*fname==backslash);fname++)
01880 EMPTY_LOOP;
01881 }
01882 }
01883 #elif defined(macintosh) // MACINTOSH implementation
01884 strcpy(string_buffer, (const char *)(from?from:GOS::cwd()));
01885
01886 if (!GStringRep::cmp(fname, string_buffer,strlen(string_buffer)) || is_file(fname))
01887 {
01888 strcpy(string_buffer, "");
01889 }
01890
01891
01892 char *s = string_buffer + strlen(string_buffer);
01893 if(fname)
01894 {
01895 for(;fname[0]==colon;fname++)
01896 EMPTY_LOOP;
01897 while(fname[0])
01898 {
01899 if (fname[0]== dot )
01900 {
01901 if (fname[1]==colon || !fname[1])
01902 {
01903 fname++;
01904 continue;
01905 }
01906 if ((fname[1]== dot )
01907 &&(fname[2]==colon || fname[2]==0))
01908 {
01909 fname +=2;
01910 for(;(s>string_buffer+1)&&(*(s-1)==colon);s--)
01911 EMPTY_LOOP;
01912 for(;(s>string_buffer+1)&&(*(s-1)!=colon);s--)
01913 EMPTY_LOOP;
01914 continue;
01915 }
01916 }
01917 if ((s==string_buffer)||(*(s-1)!=colon))
01918 {
01919 *s = colon;
01920 s++;
01921 }
01922 while (*fname!=0 && *fname!=colon)
01923 {
01924 *s = *fname++;
01925 if ((++s)-string_buffer > maxlen)
01926 G_THROW( ERR_MSG("GURL.big_name") );
01927 }
01928 *s = 0;
01929 for(;fname[0]==colon;fname++)
01930 EMPTY_LOOP;
01931 }
01932 }
01933 for(;(s>string_buffer+1) && (*(s-1)==colon);s--)
01934 EMPTY_LOOP;
01935 *s = 0;
01936 return ((string_buffer[0]==colon)?(string_buffer+1):string_buffer);
01937 #else
01938 # error "Define something here for your operating system"
01939 #endif
01940 return retval;
01941 }
01942
01943 unsigned int
01944 hash(const GURL & gurl)
01945 {
01946 unsigned int retval;
01947 const GUTF8String s(gurl.get_string());
01948 const int len=s.length();
01949 if(len && (s[len-1] == '/'))
01950 {
01951 retval=hash(s.substr(0,len-1));
01952 }else
01953 {
01954 retval=hash(s);
01955 }
01956 return retval;
01957 }
01958
01959
01960 #ifdef HAVE_NAMESPACES
01961 }
01962 # ifndef NOT_USING_DJVU_NAMESPACE
01963 using namespace DJVU;
01964 # endif
01965 #endif