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 		static import core.stdc.ctype;
38 		static import core.stdc.string;
39 
40 		size_t i = 0;
41 		size_t k = 0;
42 		size_t l = 0;
43 		size_t end_length = dest.length - 2;
44 		dest[] = '\0';
45 
46 		for (; (i < end_length) && ((l < src.length) && (src[l] != '\0')); ++i, ++l) {
47 			// Encode source if it is a reserved or non-printable character.
48 			if (encodeAll || (core.stdc..string.strchr(&(.gReservedAscii[0]), src[l]) != null) || !core.stdc.ctype.isprint(src[l])) {
49 				dest[k++] = '%';
50 				dest[k++] = .gHexChar[((src[l] >> 4) & 0x0F)];
51 				dest[k++] = .gHexChar[(src[l] & 0x0F)];
52 				i += 2;
53 			} else {
54 				// don't encode character
55 				dest[k++] = src[l];
56 			}
57 		}
58 
59 		// return characters stored to destination
60 		return i;
61 	}
62 
63 pure nothrow @safe @nogc
64 size_t UrlToAscii(ref char[] dest, const char[] src)
65 
66 	do
67 	{
68 		static import core.stdc.ctype;
69 
70 		size_t i = 0;
71 		size_t l = 0;
72 		dest[] = '\0';
73 
74 		for (i = 0; (i < dest.length) && ((l < src.length) && (src[l] != '\0')); ++i) {
75 			if (src[l] == '%') {
76 				++l;
77 
78 				if (l >= (src.length - 1)) {
79 					return 0;
80 				}
81 
82 				// Found an encoded triplet.
83 				// The next two characters must be hex.
84 				if (core.stdc.ctype.isxdigit(src[l]) && core.stdc.ctype.isxdigit(src[l + 1])) {
85 					char val = 0;
86 					size_t j = 0;
87 
88 					for (; j < 2; ++j, ++l) {
89 						val <<= 4;
90 
91 						if (l >= src.length) {
92 							return 0;
93 						}
94 
95 						if (core.stdc.ctype.isdigit(src[l])) {
96 							val += src[l] - '0';
97 						} else if (core.stdc.ctype.isupper(src[l])) {
98 							val += src[l] - 'A' + 10;
99 						} else {
100 							val += src[l] - 'a' + 10;
101 						}
102 					}
103 
104 					dest[i] = val;
105 				} else {
106 					// invalid encoding
107 					return 0;
108 				}
109 			} else {
110 				// non-encoded character, so just copy it
111 				dest[i] = src[l];
112 				++l;
113 			}
114 		}
115 
116 		return i;
117 	}