1 //this file is part of MimeTools (plugin for Notepad++)
2 //Copyright (C)2013 Robert Meakins <rmeakins@users.sf.net>
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.saml;
18 
19 
20 private static import npp_mimetools.b64;
21 private static import npp_mimetools.tinflate;
22 private static import npp_mimetools.url;
23 
24 enum int SAML_DECODE_ERROR_URLDECODE = -1;
25 enum int SAML_DECODE_ERROR_BASE64DECODE = -2;
26 enum int SAML_DECODE_ERROR_INFLATE = -3;
27 enum int SAML_MESSAGE_MAX_SIZE = 200000;
28 
29 nothrow
30 int samlDecode(ref char[] dest, const char[] encodedSamlStr)
31 
32 	in
33 	{
34 		assert(dest.length != 0);
35 	}
36 
37 	do
38 	{
39 		static import npp_mimetools.b64;
40 		static import npp_mimetools.tinflate;
41 		static import npp_mimetools.url;
42 
43 		char[] pUrlDecodedText = new char[encodedSamlStr.length];
44 
45 		dest[] = '\0';
46 		pUrlDecodedText[] = '\0';
47 
48 		// URL Decode
49 		size_t urlDecodedLen = npp_mimetools.url.UrlToAscii(pUrlDecodedText, encodedSamlStr);
50 
51 		if (urlDecodedLen < 0) {
52 			return .SAML_DECODE_ERROR_URLDECODE;
53 		}
54 
55 		char[] base64DecodedText = new char[urlDecodedLen + 1];
56 
57 		int base64DecodedLen = npp_mimetools.b64.base64Decode(base64DecodedText, pUrlDecodedText, urlDecodedLen, true, false);
58 
59 		if (base64DecodedLen < 0) {
60 			return .SAML_DECODE_ERROR_BASE64DECODE;
61 		}
62 
63 		base64DecodedText[base64DecodedLen] = '\0';
64 
65 		// A SAML message should be longer than 10 chars
66 		if (base64DecodedLen < 10) {
67 			return .SAML_DECODE_ERROR_BASE64DECODE;
68 		}
69 
70 		// If the first 5 chars are "<?xml" or "<saml", no need to inflate
71 		if ((base64DecodedText[0] == '<')  && (base64DecodedText[3] == 'm') && (base64DecodedText[4] == 'l')) {
72 			dest[0 .. base64DecodedLen] = base64DecodedText[0 .. base64DecodedLen];
73 
74 			return base64DecodedLen;
75 		}
76 
77 		// Inflate the Base64 decoded text
78 		char[] inflatedText = new char[.SAML_MESSAGE_MAX_SIZE];
79 		uint inflatedTextLen = 0;
80 
81 		npp_mimetools.tinflate.tinf_init();
82 		int inflateReturnCode = npp_mimetools.tinflate.tinf_uncompress(inflatedText, inflatedTextLen, base64DecodedText);
83 
84 		if (inflateReturnCode != npp_mimetools.tinflate.TINF_OK) {
85 			return .SAML_DECODE_ERROR_INFLATE;
86 		}
87 
88 		dest[0 .. inflatedTextLen] = inflatedText[0 .. inflatedTextLen];
89 
90 		// If the first 5 chars are not "<?xml" or "<saml", there's a problem
91 		if (!((dest[0] == '<') && (dest[3] == 'm') && (dest[4] == 'l'))) {
92 			return .SAML_DECODE_ERROR_INFLATE;
93 		}
94 
95 		return inflatedTextLen;
96 	}