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 }