1 /*****************************************************************************
2  *
3  * Copyright (c) 2008-2010, CoreCodec, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *     * Redistributions of source code must retain the above copyright
9  *       notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above copyright
11  *       notice, this list of conditions and the following disclaimer in the
12  *       documentation and/or other materials provided with the distribution.
13  *     * Neither the name of CoreCodec, Inc. nor the
14  *       names of its contributors may be used to endorse or promote products
15  *       derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY CoreCodec, Inc. ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL CoreCodec, Inc. BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  ****************************************************************************/
29 
30 #include "file.h"
31 
SetFileExt(tchar_t * URL,size_t URLLen,const tchar_t * Ext)32 bool_t SetFileExt(tchar_t* URL, size_t URLLen, const tchar_t* Ext)
33 {
34 	tchar_t *p,*q,*p2;
35 	bool_t HasHost;
36 
37 	p = (tchar_t*) GetProtocol(URL,NULL,0,&HasHost);
38 	q = p;
39 
40 	p = tcsrchr(q,'\\');
41     p2 = tcsrchr(q,'/');
42     if (!p || (p2 && p2>p))
43 		p=p2;
44 	if (p)
45 		q = p+1;
46 	else
47 	if (HasHost) // only hostname
48 		return 0;
49 
50 	if (!q[0]) // no filename at all?
51 		return 0;
52 
53 	p = tcsrchr(q,'.');
54 	if (p)
55 		*p = 0;
56 
57 	tcscat_s(URL,URLLen,T("."));
58 	tcscat_s(URL,URLLen,Ext);
59 	return 1;
60 }
61 
AddPathDelimiter(tchar_t * Path,size_t PathLen)62 void AddPathDelimiter(tchar_t* Path,size_t PathLen)
63 {
64     size_t n = tcslen(Path);
65 #if defined(TARGET_WIN) || defined(TARGET_SYMBIAN)
66     bool_t HasProtocol = GetProtocol(Path,NULL,0,NULL)==Path;
67 	if (!n || (n>0 && (HasProtocol || Path[n-1] != '/') && (!HasProtocol || Path[n-1] != '\\')))
68 	{
69         if (HasProtocol)
70             tcscat_s(Path,PathLen,T("\\"));
71         else
72 	    	tcscat_s(Path,PathLen,T("/"));
73 	}
74 #elif defined(TARGET_PS2SDK)
75 	if (!n || (n>0 && Path[n-1] != '/' && Path[n-1] != '\\' && Path[n-1] != ':'))
76 		tcscat_s(Path,PathLen,T("/"));
77 #else
78 	if (!n || (n>0 && Path[n-1] != '/'))
79 		tcscat_s(Path,PathLen,T("/"));
80 #endif
81 }
82 
RemovePathDelimiter(tchar_t * Path)83 void RemovePathDelimiter(tchar_t* Path)
84 {
85     size_t n = tcslen(Path);
86 	const tchar_t* s = GetProtocol(Path,NULL,0,NULL);
87 #if defined(TARGET_WIN) || defined(TARGET_SYMBIAN)
88     bool_t HasProtocol = s==Path;
89 	if (s[0] && n>0 && ((HasProtocol && Path[n-1] == '\\') || (!HasProtocol && Path[n-1] == '/')))
90 #else
91 	if (s[0] && n>0 && Path[n-1] == '/' && n > 1)
92 #endif
93 		Path[n-1] = 0;
94 }
95 
GetProtocol(const tchar_t * URL,tchar_t * Proto,int ProtoLen,bool_t * HasHost)96 const tchar_t* GetProtocol(const tchar_t* URL, tchar_t* Proto, int ProtoLen, bool_t* HasHost)
97 {
98 	const tchar_t* s = tcschr(URL,':');
99 	if (s && s[1] == '/' && s[2] == '/')
100 	{
101         while (URL<s && IsSpace(*URL)) ++URL;
102 		if (Proto)
103 			tcsncpy_s(Proto,ProtoLen,URL,s-URL);
104 		if (HasHost)
105         {
106             if (tcsnicmp(URL,T("urlpart"),7)==0)
107                 // skip this protocol for the Host checking
108                 GetProtocol(URL+10,NULL,0,HasHost);
109             else
110 			*HasHost = tcsnicmp(URL,T("file"),4)!=0 &&
111 			           tcsnicmp(URL,T("conf"),3)!=0 &&
112 			           tcsnicmp(URL,T("res"),3)!=0 &&
113 			           tcsnicmp(URL,T("root"),4)!=0 &&
114 			           tcsnicmp(URL,T("mem"),3)!=0 &&
115 			           tcsnicmp(URL,T("pose"),4)!=0 &&
116 			           tcsnicmp(URL,T("vol"),3)!=0 &&
117 			           tcsnicmp(URL,T("slot"),4)!=0 &&
118 					   tcsnicmp(URL,T("simu"),4)!=0 &&
119 					   tcsnicmp(URL,T("local"),5)!=0 &&
120 					   tcsnicmp(URL,T("sdcard"),6)!=0;
121         }
122 		s += 3;
123 	}
124 	else
125 	{
126 		if (HasHost)
127 			*HasHost = 0;
128 		if (Proto)
129 			tcscpy_s(Proto,ProtoLen,T("file"));
130 		s = URL;
131 	}
132 	return s;
133 }
134 
GetProtocolKind(anynode * AnyNode,tchar_t * Protocol)135 fourcc_t GetProtocolKind(anynode* AnyNode, tchar_t *Protocol)
136 {
137     fourcc_t Class = NodeEnumClassStr(AnyNode,NULL,STREAM_CLASS,NODE_PROTOCOL,Protocol);
138     if (Class)
139     {
140         const nodeclass *NodeClass = NodeContext_FindClass(AnyNode,Class);
141         if (NodeClass)
142             return (fourcc_t)NodeClass_Meta(NodeClass,STREAM_KIND,META_PARAM_CUSTOM);
143     }
144     return 0;
145 }
146 
SplitAddr(const tchar_t * URL,tchar_t * Peer,int PeerLen,tchar_t * Local,int LocalLen)147 bool_t SplitAddr(const tchar_t* URL, tchar_t* Peer, int PeerLen, tchar_t* Local, int LocalLen)
148 {
149 	const tchar_t* p = NULL;
150 	const tchar_t* p2;
151     const tchar_t* Addr;
152 	bool_t HasHost;
153     bool_t Result = 0;
154 
155 	Addr = GetProtocol(URL,NULL,0,&HasHost);
156 
157     if (HasHost)
158     {
159 	    p = tcschr(Addr,'\\');
160         p2 = tcschr(Addr,'/');
161         if (!p || (p2 && p2>p))
162 		    p=p2;
163     }
164     if (!p)
165         p = Addr+tcslen(Addr);
166 
167     p2 = tcschr(Addr,'@');
168     if (!p2 || p2>p)
169         p2 = p;
170     else
171         Result = 1;
172 
173     if (Peer)
174         tcsncpy_s(Peer,PeerLen,URL,p2-URL);
175 
176     if (Local)
177     {
178         if (p2<p)
179             ++p2;
180         tcsncpy_s(Local,LocalLen,URL,Addr-URL);
181         tcsncat_s(Local,LocalLen,p2,p-p2);
182     }
183     return Result;
184 }
185 
SplitURL(const tchar_t * URL,tchar_t * Protocol,int ProtocolLen,tchar_t * Host,int HostLen,int * Port,tchar_t * Path,int PathLen)186 void SplitURL(const tchar_t* URL, tchar_t* Protocol, int ProtocolLen, tchar_t* Host, int HostLen, int* Port, tchar_t* Path, int PathLen)
187 {
188 	bool_t HasHost;
189 	URL = GetProtocol(URL,Protocol,ProtocolLen,&HasHost);
190 
191     if (HasHost)
192     {
193 	    const tchar_t* p;
194 	    const tchar_t* p2;
195 
196 	    p = tcschr(URL,'\\');
197         p2 = tcschr(URL,'/');
198         if (!p || (p2 && p2>p))
199 		    p=p2;
200         if (!p)
201             p = URL+tcslen(URL);
202 
203         p2 = tcschr(URL,':');
204 	    if (p2 && p2<p)
205 	    {
206             if (Port)
207                 stscanf(p2+1,T("%d"),Port);
208 	    }
209         else
210             p2 = p;
211 
212 	    if (Host)
213 		    tcsncpy_s(Host,HostLen,URL,p2-URL);
214 
215         URL = p;
216     }
217     else
218     {
219         if (Host && HostLen>0)
220             *Host = 0;
221     }
222 
223     if (Path)
224     {
225         if (URL[0])
226         {
227             tchar_t* p;
228             tcscpy_s(Path,PathLen,URL);
229             for (p=Path;*p;++p)
230                 if (*p == '\\')
231                     *p = '/';
232         }
233         else
234             tcscpy_s(Path,PathLen,T("/"));
235     }
236 }
237 
SplitPath(const tchar_t * URL,tchar_t * Dir,int DirLen,tchar_t * Name,int NameLen,tchar_t * Ext,int ExtLen)238 void SplitPath(const tchar_t* URL, tchar_t* Dir, int DirLen, tchar_t* Name, int NameLen, tchar_t* Ext, int ExtLen)
239 {
240 	const tchar_t *p,*p2,*p3;
241 	bool_t HasHost;
242 	tchar_t LocalURL[MAXPATH];
243 	tchar_t Protocol[MAXPATH];
244 
245 	// mime
246 	p = GetProtocol(URL,Protocol,TSIZEOF(Protocol),&HasHost);
247 
248 	// dir
249 	p2 = tcsrchr(p,'\\');
250     p3 = tcsrchr(p,'/');
251 	if (!p2 || (p3 && p3>p2))
252         p2 = p3;
253 
254 #ifdef TARGET_PS2SDK
255     // "host:test.elf" -> "host:"
256     // "host:/test.elf" -> "host:/" (keeping end delimiter)
257     if ((p2 && p2>p && p2[-1]==':') || (!p2 && (p2 = tcschr(p,':'))!=NULL))
258 	{
259 		if (Dir)
260 			tcsncpy_s(Dir,DirLen,URL,p2-URL+1);
261 		URL = p2+1;
262 	}
263 	else
264 #endif
265 	if (p2)
266 	{
267 		if (Dir)
268 			tcsncpy_s(Dir,DirLen,URL,p2-URL);
269 		URL = p2+1;
270 	}
271 	else
272 	if (HasHost) // no filename, only host
273 	{
274 		if (Dir)
275 			tcscpy_s(Dir,DirLen,URL);
276 		URL += tcslen(URL);
277 	}
278 	else // no directory
279 	{
280 		if (Dir)
281 			tcsncpy_s(Dir,DirLen,URL,p-URL);
282 		URL = p;
283 	}
284 
285 	// name
286 	if (tcsicmp(Protocol,T("http"))==0 && tcsrchr(URL,T('#')))
287 	{
288 		tchar_t *NulChar;
289 		tcscpy_s(LocalURL,TSIZEOF(LocalURL),URL);
290 		URL = LocalURL;
291 		NulChar = tcsrchr(LocalURL,T('#'));
292 		*NulChar = 0;
293 	}
294 
295 	if (Name && Name == Ext)
296 		tcscpy_s(Name,NameLen,URL);
297 	else
298 	{
299 		p = tcsrchr(URL,'.');
300 		if (p)
301 		{
302 			if (Name)
303 				tcsncpy_s(Name,NameLen,URL,p-URL);
304 			if (Ext)
305             {
306                 if (p[1]) ++p; // remove '.', but only if there is a real extension
307 				tcscpy_s(Ext,ExtLen,p);
308             }
309 		}
310 		else
311 		{
312 			if (Name)
313 				tcscpy_s(Name,NameLen,URL);
314 			if (Ext)
315 				Ext[0] = 0;
316 		}
317 	}
318 }
319 
RelPath(tchar_t * Rel,int RelLen,const tchar_t * Path,const tchar_t * Base)320 void RelPath(tchar_t* Rel, int RelLen, const tchar_t* Path, const tchar_t* Base)
321 {
322 	size_t n;
323 	bool_t HasHost;
324 	const tchar_t* p = GetProtocol(Base,NULL,0,&HasHost);
325 	if (p != Base)
326 	{
327 		if (HasHost)
328 		{
329 			// include host name too
330 			tchar_t *a,*b;
331 			a = tcschr(p,'\\');
332 			b = tcschr(p,'/');
333 			if (!a || (b && b<a))
334 				a=b;
335 			if (a)
336 				p=a;
337 			else
338 				p+=tcslen(p);
339 		}
340 
341 		// check if mime and host is the same
342 		n = p-Base;
343 		if (n>0 && n<tcslen(Path) && (Path[n]=='\\' || Path[n]=='/') && tcsnicmp(Path,Base,n)==0)
344 		{
345 			Base += n;
346 			Path += n;
347 		}
348 	}
349 
350 	n = tcslen(Base);
351 	if (n>0 && n<tcslen(Path) && (Path[n]=='\\' || Path[n]=='/') && tcsnicmp(Path,Base,n)==0)
352 		Path += n+1;
353 
354 	tcscpy_s(Rel,RelLen,Path);
355 }
356 
UpperPath(tchar_t * Path,tchar_t * Last,size_t LastLen)357 bool_t UpperPath(tchar_t* Path, tchar_t* Last, size_t LastLen)
358 {
359 	tchar_t *a,*b,*c;
360 	bool_t HasHost;
361     tchar_t Mime[32];
362 
363 	if (!*Path)
364 		return 0;
365 
366 	RemovePathDelimiter(Path);
367 	c = (tchar_t*)GetProtocol(Path,Mime,TSIZEOF(Mime),&HasHost);
368 
369 	a = tcsrchr(c,'\\');
370 	b = tcsrchr(c,'/');
371 	if (!a || (b && b>a))
372 		a=b;
373 
374 #ifdef TARGET_PS2SDK
375     if (!a && (a = tcschr(c,':'))!=NULL)
376         if (a[1]==0)
377             a = NULL;
378 #endif
379 
380 	if (!a)
381 	{
382         if (tcsicmp(Mime, T("smb")) == 0) {
383             *c = 0;
384             tcscpy_s(Last, LastLen, Path);
385             return 1;
386         }
387 
388         if (HasHost && tcsicmp(Mime, T("upnp"))!=0)
389 			return 0;
390 		a=c;
391 		if (!a[0]) // only mime left
392 			a=c=Path;
393 	}
394 	else
395 		++a;
396 
397 	if (Last)
398 		tcscpy_s(Last,LastLen,a);
399 
400 	if (a==c)
401 		*a = 0;
402 
403 #ifdef TARGET_PS2SDK
404     if (a>c && a[-1]==':')
405         *a = 0;
406 #endif
407 
408 	while (--a>=c && (*a=='\\' || *a=='/'))
409 		*a = 0;
410 
411 	return 1;
412 }
413 
AbsPath(tchar_t * Abs,int AbsLen,const tchar_t * Path,const tchar_t * Base)414 void AbsPath(tchar_t* Abs, int AbsLen, const tchar_t* Path, const tchar_t* Base)
415 {
416 	if (Base && GetProtocol(Base,NULL,0,NULL)!=Base && (Path[0] == '/' || Path[0] == '\\') &&
417         (Path[1] != '/' && Path[1] != '\\'))
418 	{
419 		tchar_t* s;
420 		bool_t HasHost;
421 
422 		tcscpy_s(Abs,AbsLen,Base);
423 		s = (tchar_t*)GetProtocol(Abs,NULL,0,&HasHost);
424 		if (!HasHost)
425 		{
426 			// keep "mime://" from Base
427 			++Path;
428 			*s = 0;
429 		}
430 		else
431 		{
432 			// keep "mime://host" from Base
433 			tchar_t *a,*b;
434 			a = tcschr(s,'\\');
435 			b = tcschr(s,'/');
436 			if (!a || (b && b<a))
437 				a=b;
438 			if (a)
439 				*a=0;
440 		}
441 	}
442 	else
443 	if (Base && GetProtocol(Path,NULL,0,NULL)==Path && Path[0] != '/' && Path[0] != '\\' &&
444 		!(Path[0] && Path[1]==':' && (Path[2]=='\\' || Path[2]=='\0')))
445 	{
446 		// doesn't have mime or drive letter or pathdelimiter at the start
447 		const tchar_t* MimeEnd = GetProtocol(Base,NULL,0,NULL);
448 		tcscpy_s(Abs,AbsLen,Base);
449 
450 #if defined(TARGET_WIN) || defined(TARGET_SYMBIAN)
451 		if (MimeEnd==Base)
452 			AddPathDelimiter(Abs,AbsLen);
453 		else
454 #endif
455 		if (MimeEnd[0])
456 			AddPathDelimiter(Abs,AbsLen);
457 	}
458 	else
459 		Abs[0] = 0;
460 
461 	tcscat_s(Abs,AbsLen,Path);
462     AbsPathNormalize(Abs,AbsLen);
463 }
464 
AbsPathNormalize(tchar_t * Abs,size_t AbsLen)465 void AbsPathNormalize(tchar_t* Abs,size_t AbsLen)
466 {
467 	if (GetProtocol(Abs,NULL,0,NULL)!=Abs)
468     {
469         tchar_t *i;
470 		for (i=Abs;*i;++i)
471 			if (*i == '\\')
472 				*i = '/';
473     }
474     else
475     {
476 #if defined(TARGET_WIN) || defined(TARGET_SYMBIAN)
477         tchar_t *i;
478 		for (i=Abs;*i;++i)
479 			if (*i == '/')
480 				*i = '\\';
481 
482 #if defined(TARGET_WINCE)
483         if (Abs[0]!='\\')
484         {
485             size_t n = tcslen(Abs)+1;
486             if (n>=AbsLen)
487             {
488                 n=AbsLen-1;
489                 Abs[n-1]=0;
490             }
491             memmove(Abs+1,Abs,n*sizeof(tchar_t));
492             Abs[0]='\\';
493         }
494 #endif
495 #endif
496     }
497 }
498 
ReduceLocalPath(tchar_t * Abs,size_t UNUSED_PARAM (AbsLen))499 void ReduceLocalPath(tchar_t* Abs,size_t UNUSED_PARAM(AbsLen))
500 {
501     tchar_t *Folder,*Back;
502     Folder = tcsstr(Abs,T("://")); // skip the protocol
503     if (Folder)
504         Abs = Folder+3;
505 #if defined(TARGET_WIN) || defined(TARGET_SYMBIAN)
506     Back = tcsstr(Abs,T("\\\\"));
507 #else
508     Back = tcsstr(Abs,T("//"));
509 #endif
510     while (Back)
511     {
512         memmove(Back,Back+1,tcsbytes(Back+1));
513 #if defined(TARGET_WIN) || defined(TARGET_SYMBIAN)
514         Back = tcsstr(Abs,T("\\\\"));
515 #else
516         Back = tcsstr(Abs,T("//"));
517 #endif
518     }
519 
520 #if defined(TARGET_WIN) || defined(TARGET_SYMBIAN)
521     Back = tcsstr(Abs,T("\\.."));
522 #else
523     Back = tcsstr(Abs,T("/.."));
524 #endif
525     while (Back)
526     {
527         Folder = Back;
528         while (--Folder >= Abs)
529         {
530 #if defined(TARGET_WIN) || defined(TARGET_SYMBIAN)
531             if (*Folder == T('\\'))
532 #else
533             if (*Folder == T('/'))
534 #endif
535             {
536                 memmove(Folder,Back+3,tcsbytes(Back+3));
537                 break;
538             }
539         }
540 #if defined(TARGET_WIN) || defined(TARGET_SYMBIAN)
541         Back = tcsstr(Abs,T("\\.."));
542 #else
543         Back = tcsstr(Abs,T("/.."));
544 #endif
545     }
546 }
547 
CheckExts(const tchar_t * URL,const tchar_t * Exts)548 int CheckExts(const tchar_t* URL, const tchar_t* Exts)
549 {
550 	tchar_t Ext[MAXPATH];
551 	tchar_t* Tail;
552     intptr_t ExtLen;
553 
554 	SplitPath(URL,NULL,0,NULL,0,Ext,TSIZEOF(Ext));
555 	Tail = tcschr(Ext,'?');
556 	if (Tail) *Tail = 0;
557     ExtLen = tcslen(Ext);
558 
559 	while (Exts)
560 	{
561 		const tchar_t* p = tcschr(Exts,':');
562 		if (p && (ExtLen == p-Exts) && tcsnicmp(Ext,Exts,p-Exts)==0)
563 			return p[1]; // return type char
564 		Exts = tcschr(Exts,';');
565 		if (Exts) ++Exts;
566 	}
567 	return 0;
568 }
569 
ScaleRound(int_fast32_t v,int_fast32_t Num,int_fast32_t Den)570 int ScaleRound(int_fast32_t v,int_fast32_t Num,int_fast32_t Den)
571 {
572 	int64_t i;
573 	if (!Den)
574 		return 0;
575 	i = (int64_t)v * Num;
576 	if (i<0)
577 		i-=Den/2;
578 	else
579 		i+=Den/2;
580 	i/=Den;
581 	return (int)i;
582 }
583 
StreamLoginInfo(node * p,tchar_t * URL,bool_t Proxy)584 void StreamLoginInfo(node* p, tchar_t* URL, bool_t Proxy)
585 {
586     tchar_t LoginPass[MAXPATH];
587     if (SplitAddr(URL,LoginPass,TSIZEOF(LoginPass),NULL,0))
588     {
589         // extract the login:pass from the URL as there seems to be one
590         tchar_t *s,*t;
591         if (!Proxy)
592         {
593             Node_SetData(p,STREAM_FULL_URL,TYPE_STRING,URL);
594 
595             t = (tchar_t*)GetProtocol(URL,NULL,0,NULL);
596             s = tcschr(t,T('@'));
597             assert(s!=NULL);
598             ++s;
599             memmove(t, s, tcsbytes(s));
600         }
601 
602         t = (tchar_t*)GetProtocol(LoginPass,NULL,0,NULL);
603         s=tcschr(t,T(':'));
604         if (s)
605             *s++ = 0;
606 
607         if (Proxy)
608         {
609             Node_SetData(p,STREAM_PROXY_PASSWORD,TYPE_STRING,s);
610             Node_SetData(p,STREAM_PROXY_USERNAME,TYPE_STRING,t);
611         }
612         else
613         {
614             Node_SetData(p,STREAM_PASSWORD,TYPE_STRING,s);
615             Node_SetData(p,STREAM_USERNAME,TYPE_STRING,t);
616         }
617     }
618     else
619         Node_RemoveData(p,STREAM_FULL_URL,TYPE_STRING);
620 }
621 
FirstSepar(const tchar_t * Path)622 tchar_t* FirstSepar(const tchar_t *Path)
623 {
624     tchar_t *s1, *s2;
625     s1 = tcschr(Path, '\\');
626     s2 = tcschr(Path, '/');
627     if (!s1 || (s2 && s2 < s1))
628         s1 = s2;
629     return s1;
630 }
631 
SplitURLLogin(const tchar_t * URL,tchar_t * UserName,size_t UserNameLen,tchar_t * Password,size_t PasswordLen,tchar_t * URL2,size_t URL2Len)632 void SplitURLLogin(const tchar_t *URL, tchar_t *UserName, size_t UserNameLen, tchar_t *Password, size_t PasswordLen, tchar_t *URL2, size_t URL2Len)
633 {
634     tchar_t LoginPass[MAXPATH];
635     if (SplitAddr(URL, LoginPass, TSIZEOF(LoginPass), NULL, 0))
636     {
637         tchar_t *s,*t;
638         if (URL2)
639         {
640             tcscpy_s(URL2, URL2Len, URL);
641             t = (tchar_t*)GetProtocol(URL2,NULL,0,NULL);
642             s = tcschr(t,T('@'));
643             assert(s!=NULL);
644             ++s;
645             memmove(t, s, tcsbytes(s));
646         }
647 
648         t = (tchar_t*)GetProtocol(LoginPass,NULL,0,NULL);
649         s=tcschr(t,T(':'));
650         if (s)
651         {
652             *s++ = 0;
653 // missing: resolving escape sequences
654             if (Password)
655                 tcscpy_s(Password, PasswordLen, s);
656         }
657         else
658             tcsclr_s(Password, PasswordLen);
659         if (UserName)
660             tcscpy_s(UserName, UserNameLen, t);
661     } else {
662         tcsclr_s(UserName, UserNameLen);
663         tcsclr_s(Password, PasswordLen);
664         if (URL2)
665             tcscpy_s(URL2, URL2Len, URL);
666     }
667 }
668 
SplitShare(const tchar_t * Path,tchar_t * Share,size_t ShareLen,tchar_t * Path2,size_t Path2Len)669 void SplitShare(const tchar_t *Path, tchar_t *Share, size_t ShareLen, tchar_t *Path2, size_t Path2Len)
670 {
671     tchar_t *s1;
672     s1 = FirstSepar(Path);
673     if (s1 == Path)
674     {
675         Path++;
676         s1 = FirstSepar(Path);
677     }
678     if (s1) {
679         if (Share)
680              tcsncpy_s(Share, ShareLen, Path, s1 - Path);
681         if (Path2)
682              tcscpy_s(Path2, Path2Len, s1);
683     } else
684     {
685         if (Share)
686              tcscpy_s(Share, ShareLen, Path);
687         tcsclr_s(Path2, Path2Len);
688     }
689 }
690 
MergeURL(tchar_t * URL,size_t URLLen,const tchar_t * Protocol,const tchar_t * Host,int Port,const tchar_t * Path)691 tchar_t *MergeURL(tchar_t *URL, size_t URLLen, const tchar_t *Protocol, const tchar_t *Host, int Port, const tchar_t *Path)
692 {
693     *URL = 0;
694     if (Protocol && *Protocol)
695         stcatprintf_s(URL, URLLen, T("%s://"), Protocol);
696     if (Host && *Host)
697     {
698         stcatprintf_s(URL, URLLen, T("%s"), Host);
699         if (Port > 0)
700             stcatprintf_s(URL, URLLen, T(":%d"), Port);
701     }
702     if (Path && *Path)
703     {
704         if (FirstSepar(Path) == Path)
705             stcatprintf_s(URL, URLLen, T("%s"), Path);
706         else
707             stcatprintf_s(URL, URLLen, T("/%s"), Path);
708     }
709     return URL;
710 }
711 
GetIP(tchar_t * sIP,size_t IPLen,long IP)712 tchar_t *GetIP(tchar_t *sIP, size_t IPLen, long IP)
713 {
714     stprintf_s(sIP, IPLen, T("%d.%d.%d.%d"), (IP >> 24) & 0xFF, (IP >> 16) & 0xFF, (IP >> 8) & 0xFF, IP & 0xFF);
715     return sIP;
716 }
717 
SplitURLParams(const tchar_t * URL,tchar_t * URL2,int URL2Len,tchar_t * Params,int ParamsLen)718 void SplitURLParams(const tchar_t* URL, tchar_t* URL2, int URL2Len, tchar_t* Params, int ParamsLen)
719 {
720 	tchar_t* p;
721     p = tcschr(URL, '?');
722     if (p)
723     {
724         if (URL2)
725             tcsncpy_s(URL2, URL2Len, URL, p-URL);
726         if (Params)
727             tcscpy_s(Params, ParamsLen, p);
728     } else
729     {
730         if (URL2)
731             tcscpy_s(URL2, URL2Len, URL);
732         if (Params)
733             *Params = 0;
734     }
735 }
736 
AddCacheURL(tchar_t * Out,size_t Len,const tchar_t * In)737 tchar_t *AddCacheURL(tchar_t* Out, size_t Len, const tchar_t *In)
738 {
739     CheckRemoveCacheURL(&In);
740     if (!In || !*In) {
741         if (Out && Len)
742             *Out = 0;
743     }
744     else
745         stprintf_s(Out, Len, T("cache://%s"), In);
746     return Out;
747 }
748 
CheckRemoveCacheURL(const tchar_t ** URL)749 bool_t CheckRemoveCacheURL(const tchar_t** URL)
750 {
751     if (*URL && !tcsncmp(*URL, T("cache://"), 8))
752     {
753         *URL += 8;
754         return 1;
755     }
756     return 0;
757 }
758 
RemoveURLParam(tchar_t * URL,const tchar_t * Param)759 bool_t RemoveURLParam(tchar_t* URL, const tchar_t* Param)
760 {
761     size_t l;
762     tchar_t *s1, *s2;
763     l = tcslen(Param);
764     if (!l)
765         return 0;
766     s1 = tcschr(URL, '?');
767     if (!s1)
768         s1 = tcschr(URL, ';');
769     while (s1)
770     {
771         s2 = tcschr(s1+1, '&');
772         if (!s2)
773             s2 = tcschr(s1+1, ';');
774         if (tcsncmp(s1+1, Param, l) == 0 && s1[l+1] == '=')
775         {
776             if (s2)
777                 memcpy(s1+1, s2+1, (tcslen(s2)+1)*sizeof(tchar_t));
778             else
779                 *s1 = 0;
780             return 1;
781         }
782         s1 = s2;
783     }
784     return 0;
785 }
786 
FileStat(nodecontext * p,const tchar_t * Path,streamdir * Item)787 err_t FileStat(nodecontext* p, const tchar_t* Path, streamdir* Item)
788 {
789     err_t Result;
790     stream *s;
791     tchar_t Dir[MAXPATH];
792     tchar_t NameExt[MAXPATH];
793     tchar_t Ext[MAXPATH+2];
794     size_t l;
795     SplitPath(Path, Dir, MAXPATH, NameExt, MAXPATH, Ext, MAXPATH);
796 	if (*Ext)
797     {
798         if (!tcschr(NameExt,T('.')))
799     		SetFileExt(NameExt, MAXPATH, Ext);
800         else
801         {
802             tcscat_s(NameExt,TSIZEOF(NameExt),T("."));
803             tcscat_s(NameExt,TSIZEOF(NameExt),Ext);
804         }
805     }
806     l = tcslen(Ext);
807     Ext[l] = ':';
808     Ext[l + 1] = '1';
809     Ext[l + 2] = '\0';
810     s = GetStream(p, Dir, SFLAG_SILENT);
811     if (!s)
812         return ERR_FILE_NOT_FOUND;
813     Result = Stream_OpenDir(s, Dir, SFLAG_SILENT);
814     if (Result == ERR_NONE) {
815         do {
816             Result = Stream_EnumDir(s, Ext, 1, Item);
817             if (Result == ERR_NONE && tcscmp(Item->FileName, NameExt) == 0)
818                 break;
819         } while (Result == ERR_NONE);
820     }
821     NodeDelete((node *) s);
822 	if (Result != ERR_NONE)
823 		Result = ERR_FILE_NOT_FOUND;
824     return Result;
825 }
826 
827