1 // CoreUtil
2 //
3 // Copyright (C) 2012-2014 Daiyuu Nobori. All Rights Reserved.
4 // Copyright (C) 2012-2014 SoftEther VPN Project at University of Tsukuba. All Rights Reserved.
5 //
6 // License: The Apache License, Version 2.0
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // DISCLAIMER
10 // ==========
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18 // SOFTWARE.
19 //
20 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
21 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
22 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
23 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
24 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
25 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
26 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
27 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
28 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
29 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
30 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
31 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
32 // LAW OR COURT RULE.
33 //
34 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
35 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
36 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
37 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
38 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
39 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
40 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
41 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
42 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
43 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
44 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
45 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
46 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
47 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
48 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
49 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
50 // STATEMENT FOR WARNING AND DISCLAIMER.
51 //
52 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
53 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
54 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
55 //
56 //
57 // SOURCE CODE CONTRIBUTION
58 // ------------------------
59 //
60 // Your contribution to SoftEther VPN Project is much appreciated.
61 // Please send patches to us through GitHub.
62 // Read the SoftEther VPN Patch Acceptance Policy in advance:
63 // http://www.softether.org/5-download/src/9.patch
64 //
65 //
66 // DEAR SECURITY EXPERTS
67 // ---------------------
68 //
69 // If you find a bug or a security vulnerability please kindly inform us
70 // about the problem immediately so that we can fix the security problem
71 // to protect a lot of users around the world as soon as possible.
72 //
73 // Our e-mail address for security reports is:
74 // softether-vpn-security [at] softether.org
75 //
76 // Please note that the above e-mail address is not a technical support
77 // inquiry address. If you need technical assistance, please visit
78 // http://www.softether.org/ and ask your question on the users forum.
79 //
80 // Thank you for your cooperation.
81 //
82 //
83 // NO MEMORY OR RESOURCE LEAKS
84 // ---------------------------
85 //
86 // The memory-leaks and resource-leaks verification under the stress
87 // test has been passed before release this source code.
88 
89 
90 using System;
91 using System.Threading;
92 using System.Data;
93 using System.Data.Sql;
94 using System.Data.SqlClient;
95 using System.Data.SqlTypes;
96 using System.Text;
97 using System.Configuration;
98 using System.Collections;
99 using System.Collections.Generic;
100 using System.Security.Cryptography;
101 using System.Web;
102 using System.Web.Security;
103 using System.Web.UI;
104 using System.Web.UI.WebControls;
105 using System.Web.UI.WebControls.WebParts;
106 using System.Web.UI.HtmlControls;
107 using System.IO;
108 using System.Drawing;
109 using System.Drawing.Imaging;
110 using System.Drawing.Drawing2D;
111 using System.Runtime.InteropServices;
112 
113 namespace CoreUtil
114 {
115 	[StructLayout(LayoutKind.Sequential, Pack = 1)]
116 	public struct ZipDataHeader
117 	{
118 		public uint Signature;
119 		public ushort NeedVer;
120 		public ushort Option;
121 		public ushort CompType;
122 		public ushort FileTime;
123 		public ushort FileDate;
124 		public uint Crc32;
125 		public uint CompSize;
126 		public uint UncompSize;
127 		public ushort FileNameLen;
128 		public ushort ExtraLen;
129 	}
130 
131 	[StructLayout(LayoutKind.Sequential, Pack = 1)]
132 	public struct ZipDataFooter
133 	{
134 		public uint Signature;
135 		public uint Crc32;
136 		public uint CompSize;
137 		public uint UncompSize;
138 	}
139 
140 	[StructLayout(LayoutKind.Sequential, Pack = 1)]
141 	public struct ZipDirHeader
142 	{
143 		public uint Signature;
144 		public ushort MadeVer;
145 		public ushort NeedVer;
146 		public ushort Option;
147 		public ushort CompType;
148 		public ushort FileTime;
149 		public ushort FileDate;
150 		public uint Crc32;
151 		public uint CompSize;
152 		public uint UncompSize;
153 		public ushort FileNameLen;
154 		public ushort ExtraLen;
155 		public ushort CommentLen;
156 		public ushort DiskNum;
157 		public ushort InAttr;
158 		public uint OutAttr;
159 		public uint HeaderPos;
160 	}
161 
162 	[StructLayout(LayoutKind.Sequential, Pack = 1)]
163 	public struct ZipEndHeader
164 	{
165 		public uint Signature;
166 		public ushort DiskNum;
167 		public ushort StartDiskNum;
168 		public ushort DiskDirEntry;
169 		public ushort DirEntry;
170 		public uint DirSize;
171 		public uint StartPos;
172 		public ushort CommentLen;
173 	}
174 
175 	public static class ZipUtil
176 	{
ZipUtil()177 		static ZipUtil()
178 		{
179 			initCrc32();
180 		}
181 
182 		static uint[] table;
183 		const int crcTableSize = 256;
184 
initCrc32()185 		static void initCrc32()
186 		{
187 			table = new uint[crcTableSize];
188 
189 			uint poly = 0xEDB88320;
190 			uint u, i, j;
191 
192 			for (i = 0; i < 256; i++)
193 			{
194 				u = i;
195 
196 				for (j = 0; j < 8; j++)
197 				{
198 					if ((u & 0x1) != 0)
199 					{
200 						u = (u >> 1) ^ poly;
201 					}
202 					else
203 					{
204 						u >>= 1;
205 					}
206 				}
207 
208 				table[i] = u;
209 			}
210 		}
211 
Crc32(byte[] buf)212 		public static uint Crc32(byte[] buf)
213 		{
214 			return Crc32(buf, 0, buf.Length);
215 		}
Crc32(byte[] buf, int pos, int len)216 		public static uint Crc32(byte[] buf, int pos, int len)
217 		{
218 			return Crc32Finish(Crc32First(buf, pos, len));
219 		}
Crc32First(byte[] buf, int pos, int len)220 		public static uint Crc32First(byte[] buf, int pos, int len)
221 		{
222 			return Crc32Next(buf, pos, len, 0xffffffff);
223 		}
Crc32Next(byte[] buf, int pos, int len, uint lastCrc32)224 		public static uint Crc32Next(byte[] buf, int pos, int len, uint lastCrc32)
225 		{
226 			uint ret = lastCrc32;
227 			for (uint i = 0; i < len; i++)
228 			{
229 				ret = (ret >> 8) ^ table[buf[pos + i] ^ (ret & 0xff)];
230 			}
231 			return ret;
232 		}
Crc32Finish(uint lastCrc32)233 		public static uint Crc32Finish(uint lastCrc32)
234 		{
235 			return ~lastCrc32;
236 		}
237 	}
238 
239 	public class ZipPacker
240 	{
241 		public const uint Signature = 0x04034B50;
242 		public const uint SignatureEnd = 0x06054B50;
243 		public const ushort Version = 10;
244 		public const ushort VersionWithCompress = 20;
245 		public Encoding Encoding = Str.ShiftJisEncoding;
246 
247 		class File
248 		{
249 			public string Name;
250 			public long Size;
251 			public DateTime DateTime;
252 			public FileAttributes Attributes;
253 			public long CurrentSize;
254 			public long CompressSize;
255 			public uint Crc32;
256 			public uint HeaderPos;
257 			public Encoding Encoding;
258 			public bool Compress;
259 			public CoreUtil.Internal.ZStream ZStream;
260 
WriteZipDataHeader(ref ZipDataHeader h, bool writeSizes)261 			public void WriteZipDataHeader(ref ZipDataHeader h, bool writeSizes)
262 			{
263 				h.Signature = Signature;
264 				h.NeedVer = Version;
265 				h.CompType = 0;
266 				h.FileTime = Util.DateTimeToDosTime(this.DateTime);
267 				h.FileDate = Util.DateTimeToDosDate(this.DateTime);
268 				h.Option = 8;
269 
270 				if (writeSizes == false)
271 				{
272 					h.CompSize = h.UncompSize = 0;
273 					h.Crc32 = 0;
274 
275 					if (this.Compress)
276 					{
277 						h.NeedVer = VersionWithCompress;
278 						h.CompType = 8;
279 					}
280 				}
281 				else
282 				{
283 					h.CompSize = h.UncompSize = (uint)this.Size;
284 					if (this.Compress)
285 					{
286 						h.CompSize = (uint)this.CompressSize;
287                         h.CompType = 8;
288                     }
289 					h.Crc32 = this.Crc32;
290 				}
291 
292 				h.FileNameLen = (ushort)this.Encoding.GetByteCount(this.Name);
293 				h.ExtraLen = 0;
294 			}
295 
WriteZipDataFooter(ref ZipDataFooter h)296 			public void WriteZipDataFooter(ref ZipDataFooter h)
297 			{
298 				h.Signature = 0x08074B50;
299 
300 				if (this.Compress == false)
301 				{
302 					h.CompSize = h.UncompSize = (uint)this.Size;
303 				}
304 				else
305 				{
306 					h.CompSize = (uint)this.CompressSize;
307 					h.UncompSize = (uint)this.Size;
308 				}
309 				h.Crc32 = this.Crc32;
310 			}
311 		}
312 
313 		Fifo fifo;
314 		List<File> fileList;
315 
316 		public Fifo GeneratedData
317 		{
318 			get
319 			{
320 				return this.fifo;
321 			}
322 		}
323 
ZipPacker()324 		public ZipPacker()
325 		{
326 			fifo = new Fifo();
327 			fileList = new List<File>();
328 		}
329 
330 		File currentFile = null;
331 
AddFileSimple(string name, DateTime dt, FileAttributes attribute, byte[] data)332 		public void AddFileSimple(string name, DateTime dt, FileAttributes attribute, byte[] data)
333 		{
334 			AddFileSimple(name, dt, attribute, data, false);
335 		}
AddFileSimple(string name, DateTime dt, FileAttributes attribute, byte[] data, bool compress)336 		public void AddFileSimple(string name, DateTime dt, FileAttributes attribute, byte[] data, bool compress)
337 		{
338 			AddFileStart(name, data.Length, dt, attribute, compress);
339 			AddFileData(data, 0, data.Length);
340 		}
341 
AddFileStart(string name, long size, DateTime dt, FileAttributes attribute)342 		public void AddFileStart(string name, long size, DateTime dt, FileAttributes attribute)
343 		{
344 			AddFileStart(name, size, dt, attribute, false);
345 		}
AddFileStart(string name, long size, DateTime dt, FileAttributes attribute, bool compress)346 		public void AddFileStart(string name, long size, DateTime dt, FileAttributes attribute, bool compress)
347 		{
348 			if (currentFile != null)
349 			{
350 				throw new ApplicationException("currentFile != null");
351 			}
352 
353 			name = name.Replace("/", "\\");
354 
355 			File f = new File();
356 
357 			f.Encoding = this.Encoding;
358 			f.Name = name;
359 			f.Size = size;
360 			f.DateTime = dt;
361 			f.Attributes = attribute;
362 			f.Compress = compress;
363 
364 			this.fileList.Add(f);
365 
366 			ZipDataHeader h = new ZipDataHeader();
367 			f.HeaderPos = (uint)fifo.TotalWriteSize;
368 			f.WriteZipDataHeader(ref h, false);
369 			fifo.Write(Util.StructToByte(h));
370 			fifo.Write(this.Encoding.GetBytes(f.Name));
371 			f.Crc32 = 0xffffffff;
372 
373 			if (compress)
374 			{
375 				f.ZStream = new CoreUtil.Internal.ZStream();
376 				f.ZStream.deflateInit(-1, -15);
377 			}
378 
379 			currentFile = f;
380 		}
381 
AddFileData(byte[] data, int pos, int len)382 		public long AddFileData(byte[] data, int pos, int len)
383 		{
384 			long totalSize = currentFile.CurrentSize + len;
385 
386 			if (totalSize > currentFile.Size)
387 			{
388 				throw new ApplicationException("totalSize > currentFile.Size");
389 			}
390 
391 			if (currentFile.Compress == false)
392 			{
393 				fifo.Write(data, pos, len);
394 			}
395 			else
396 			{
397 				CoreUtil.Internal.ZStream zs = currentFile.ZStream;
398 
399 				byte[] srcData = Util.ExtractByteArray(data, pos, len);
400 				byte[] dstData = new byte[srcData.Length * 2 + 100];
401 
402 				zs.next_in = srcData;
403 				zs.avail_in = srcData.Length;
404 				zs.next_in_index = 0;
405 
406 				zs.next_out = dstData;
407 				zs.avail_out = dstData.Length;
408 				zs.next_out_index = 0;
409 
410 				if (currentFile.Size == (currentFile.CurrentSize + len))
411 				{
412 					zs.deflate(CoreUtil.Internal.zlibConst.Z_FINISH);
413 				}
414 				else
415 				{
416 					zs.deflate(CoreUtil.Internal.zlibConst.Z_SYNC_FLUSH);
417 				}
418 
419 				fifo.Write(dstData, 0, dstData.Length - zs.avail_out);
420 
421 				currentFile.CompressSize += dstData.Length - zs.avail_out;
422 
423 				Util.NoOP();
424 			}
425 
426 			currentFile.CurrentSize += len;
427 
428 			currentFile.Crc32 = ZipUtil.Crc32Next(data, pos, len, currentFile.Crc32);
429 
430 			long ret = currentFile.Size - currentFile.CurrentSize;
431 
432 			if (ret == 0)
433 			{
434 				currentFile.Crc32 = ~currentFile.Crc32;
435 				addFileFooter();
436 
437 				currentFile = null;
438 			}
439 
440 			return ret;
441 		}
442 
addFileFooter()443 		void addFileFooter()
444 		{
445 			ZipDataFooter f = new ZipDataFooter();
446 			currentFile.WriteZipDataFooter(ref f);
447 			fifo.Write(Util.StructToByte(f));
448 		}
449 
Finish()450 		public void Finish()
451 		{
452 			long posStart = fifo.TotalWriteSize;
453 			foreach (File f in this.fileList)
454 			{
455 				ZipDirHeader d = new ZipDirHeader();
456 				d.Signature = 0x02014B50;// ZipPacker.Signature;
457 				d.MadeVer = Version;
458 				ZipDataHeader dh = new ZipDataHeader();
459 				f.WriteZipDataHeader(ref dh, true);
460 				if (f.Compress)
461 				{
462 					dh.CompType = 8;
463 					dh.CompSize = (uint)f.CompressSize;
464 					dh.NeedVer = ZipPacker.VersionWithCompress;
465 				}
466 				d.NeedVer = dh.NeedVer;
467 				d.Option = dh.Option;
468 				d.CompType = dh.CompType;
469 				d.FileTime = dh.FileTime;
470 				d.FileDate = dh.FileDate;
471 				d.Crc32 = dh.Crc32;
472 				d.CompSize = dh.CompSize;
473 				d.UncompSize = dh.UncompSize;
474 				d.FileNameLen = dh.FileNameLen;
475 				d.ExtraLen = dh.ExtraLen;
476 				d.CommentLen = 0;
477 				d.DiskNum = 0;
478 				d.InAttr = 0;
479 				d.OutAttr = (ushort)f.Attributes;
480 				d.HeaderPos = f.HeaderPos;
481 
482 				fifo.Write(Util.StructToByte(d));
483 				fifo.Write(this.Encoding.GetBytes(f.Name));
484 			}
485 			long posEnd = fifo.TotalWriteSize;
486 
487 			ZipEndHeader e = new ZipEndHeader();
488 			e.Signature = ZipPacker.SignatureEnd;
489 			e.DiskNum = e.StartDiskNum = 0;
490 			e.DiskDirEntry = e.DirEntry = (ushort)this.fileList.Count;
491 			e.DirSize = (uint)(posEnd - posStart);
492 			e.StartPos = (uint)posStart;
493 			e.CommentLen = 0;
494 			fifo.Write(Util.StructToByte(e));
495 		}
496 	}
497 }
498