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 		char[] pUrlDecodedText = new char[encodedSamlStr.length];
40 
41 		dest[] = '\0';
42 		pUrlDecodedText[] = '\0';
43 
44 		// URL Decode
45 		size_t urlDecodedLen = npp_mimetools.url.UrlToAscii(pUrlDecodedText, encodedSamlStr);
46 
47 		if (urlDecodedLen < 0) {
48 			return .SAML_DECODE_ERROR_URLDECODE;
49 		}
50 
51 		char[] base64DecodedText = new char[urlDecodedLen + 1];
52 
53 		int base64DecodedLen = npp_mimetools.b64.base64Decode(base64DecodedText, pUrlDecodedText, urlDecodedLen, true, false);
54 
55 		if (base64DecodedLen < 0) {
56 			return .SAML_DECODE_ERROR_BASE64DECODE;
57 		}
58 
59 		base64DecodedText[base64DecodedLen] = '\0';
60 
61 		// A SAML message should be longer than 10 chars
62 		if (base64DecodedLen < 10) {
63 			return .SAML_DECODE_ERROR_BASE64DECODE;
64 		}
65 
66 		// If the first 5 chars are "<?xml" or "<saml", no need to inflate
67 		if ((base64DecodedText[0] == '<')  && (base64DecodedText[3] == 'm') && (base64DecodedText[4] == 'l')) {
68 			dest[0 .. base64DecodedLen] = base64DecodedText[0 .. base64DecodedLen];
69 
70 			return base64DecodedLen;
71 		}
72 
73 		// Inflate the Base64 decoded text
74 		char[] inflatedText = new char[.SAML_MESSAGE_MAX_SIZE];
75 		uint inflatedTextLen = 0;
76 
77 		npp_mimetools.tinflate.tinf_init();
78 		int inflateReturnCode = npp_mimetools.tinflate.tinf_uncompress(inflatedText, inflatedTextLen, base64DecodedText);
79 
80 		if (inflateReturnCode != npp_mimetools.tinflate.TINF_OK) {
81 			return .SAML_DECODE_ERROR_INFLATE;
82 		}
83 
84 		dest[0 .. inflatedTextLen] = inflatedText[0 .. inflatedTextLen];
85 
86 		// If the first 5 chars are not "<?xml" or "<saml", there's a problem
87 		if (!((dest[0] == '<') && (dest[3] == 'm') && (dest[4] == 'l'))) {
88 			return .SAML_DECODE_ERROR_INFLATE;
89 		}
90 
91 		return inflatedTextLen;
92 	}