1 //this file is part of MimeTools (plugin for Notepad++)
2 //Copyright (C)2019 Don HO <don.h@free.fr>
3 //
4 //This program is free software; you can redistribute it and/or
5 //modify it under the terms of the GNU General Public License
6 //as published by the Free Software Foundation; either
7 //version 2 of the License, or (at your option) any later version.
8 //
9 //This program is distributed in the hope that it will be useful,
10 //but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //GNU General Public License for more details.
13 //
14 //You should have received a copy of the GNU General Public License
15 //along with this program; if not, write to the Free Software
16 //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 module npp_mimetools.url;
18 
19 
20 private static import core.stdc.ctype;
21 private static import core.stdc.string;
22 
23 // These characters must be encoded in a URL, as per RFC1738
24 enum gReservedAscii = "<>\"#%{}|\\^~[]`;/?:@=& ";
25 enum gHexChar = "0123456789ABCDEF";
26 
27 pure nothrow @nogc
28 size_t AsciiToUrl(ref char[] dest, const char[] src, bool encodeAll)
29 
30 	in
31 	{
32 		assert(dest.length > 2);
33 	}
34 
35 	do
36 	{
37 		size_t i = 0;
38 		size_t k = 0;
39 		size_t l = 0;
40 		size_t end_length = dest.length - 2;
41 		dest[] = '\0';
42 
43 		for (; (i < end_length) && ((l < src.length) && (src[l] != '\0')); ++i, ++l) {
44 			// Encode source if it is a reserved or non-printable character.
45 			if (encodeAll || (core.stdc..string.strchr(&(.gReservedAscii[0]), src[l]) != null) || !core.stdc.ctype.isprint(src[l])) {
46 				dest[k++] = '%';
47 				dest[k++] = .gHexChar[((src[l] >> 4) & 0x0F)];
48 				dest[k++] = .gHexChar[(src[l] & 0x0F)];
49 				i += 2;
50 			} else {
51 				// don't encode character
52 				dest[k++] = src[l];
53 			}
54 		}
55 
56 		// return characters stored to destination
57 		return i;
58 	}
59 
60 pure nothrow @safe @nogc
61 size_t UrlToAscii(ref char[] dest, const char[] src)
62 
63 	do
64 	{
65 		size_t i = 0;
66 		size_t l = 0;
67 		dest[] = '\0';
68 
69 		for (i = 0; (i < dest.length) && ((l < src.length) && (src[l] != '\0')); ++i) {
70 			if (src[l] == '%') {
71 				++l;
72 
73 				if (l >= (src.length - 1)) {
74 					return 0;
75 				}
76 
77 				// Found an encoded triplet.
78 				// The next two characters must be hex.
79 				if (core.stdc.ctype.isxdigit(src[l]) && core.stdc.ctype.isxdigit(src[l + 1])) {
80 					char val = 0;
81 					size_t j = 0;
82 
83 					for (; j < 2; ++j, ++l) {
84 						val <<= 4;
85 
86 						if (l >= src.length) {
87 							return 0;
88 						}
89 
90 						if (core.stdc.ctype.isdigit(src[l])) {
91 							val += src[l] - '0';
92 						} else if (core.stdc.ctype.isupper(src[l])) {
93 							val += src[l] - 'A' + 10;
94 						} else {
95 							val += src[l] - 'a' + 10;
96 						}
97 					}
98 
99 					dest[i] = val;
100 				} else {
101 					// invalid encoding
102 					return 0;
103 				}
104 			} else {
105 				// non-encoded character, so just copy it
106 				dest[i] = src[l];
107 				++l;
108 			}
109 		}
110 
111 		return i;
112 	}