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.Web.Mail; 112 113 namespace CoreUtil 114 { 115 internal class HamCoreEntry : IComparable 116 { 117 public string FileName = ""; 118 public uint Size = 0; 119 public uint SizeCompressed = 0; 120 public uint Offset = 0; 121 public byte[] Buffer = null; 122 public long LastAccess = 0; 123 CompareTo(object obj)124 public int CompareTo(object obj) 125 { 126 HamCoreEntry hc1, hc2; 127 hc1 = this; 128 hc2 = (HamCoreEntry)obj; 129 130 return Str.StrCmpiRetInt(hc1.FileName, hc2.FileName); 131 } 132 } 133 134 public class HamCoreBuilderFileEntry : IComparable<HamCoreBuilderFileEntry> 135 { 136 public string Name; 137 public Buf RawData; 138 public Buf CompressedData; 139 public int Offset = 0; 140 CompareTo(HamCoreBuilderFileEntry other)141 int IComparable<HamCoreBuilderFileEntry>.CompareTo(HamCoreBuilderFileEntry other) 142 { 143 return this.Name.CompareTo(other.Name); 144 } 145 } 146 147 public class HamCoreBuilder 148 { 149 List<HamCoreBuilderFileEntry> fileList; 150 public List<HamCoreBuilderFileEntry> FileList 151 { 152 get { return fileList; } 153 } 154 IsFile(string name)155 public bool IsFile(string name) 156 { 157 foreach (HamCoreBuilderFileEntry f in fileList) 158 { 159 if (f.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) 160 { 161 return true; 162 } 163 } 164 165 return false; 166 } 167 DeleteFile(string name)168 public bool DeleteFile(string name) 169 { 170 foreach (HamCoreBuilderFileEntry f in fileList) 171 { 172 if (f.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) 173 { 174 fileList.Remove(f); 175 return true; 176 } 177 } 178 179 return false; 180 } 181 HamCoreBuilder()182 public HamCoreBuilder() 183 { 184 fileList = new List<HamCoreBuilderFileEntry>(); 185 } 186 AddDir(string dirName)187 public void AddDir(string dirName) 188 { 189 dirName = IO.RemoteLastEnMark(dirName); 190 191 DirEntry[] ee = IO.EnumDirEx(dirName); 192 193 foreach (DirEntry e in ee) 194 { 195 if (e.IsFolder == false) 196 { 197 AddFile(e.FullPath, dirName); 198 } 199 } 200 } 201 AddFile(string fileName, string baseDirFileName)202 public void AddFile(string fileName, string baseDirFileName) 203 { 204 string name = IO.GetRelativeFileName(fileName, baseDirFileName); 205 206 AddFile(name, File.ReadAllBytes(fileName)); 207 } 208 AddFile(string name, byte[] data)209 public void AddFile(string name, byte[] data) 210 { 211 if (IsFile(name)) 212 { 213 throw new InvalidOperationException("fileName"); 214 } 215 216 HamCoreBuilderFileEntry f = new HamCoreBuilderFileEntry(); 217 218 Console.Write("{0}: ", name); 219 220 f.Name = name; 221 f.RawData = new Buf(Util.CloneByteArray(data)); 222 Console.Write("{0} -> ", f.RawData.Size); 223 f.CompressedData = new Buf(ZLib.Compress(f.RawData.ByteData)); 224 Console.WriteLine("{0}", f.CompressedData.Size); 225 226 this.fileList.Add(f); 227 } 228 Build(string dstFileName)229 public void Build(string dstFileName) 230 { 231 Buf b = Build(); 232 233 IO.SaveFile(dstFileName, b.ByteData); 234 } 235 Build()236 public Buf Build() 237 { 238 int z; 239 Buf b; 240 241 this.fileList.Sort(); 242 243 z = 0; 244 245 z += HamCore.HamcoreHeaderSize; 246 247 z += sizeof(int); 248 249 foreach (HamCoreBuilderFileEntry f in this.fileList) 250 { 251 z += Str.ShiftJisEncoding.GetByteCount(f.Name) + sizeof(int); 252 z += sizeof(int); 253 z += sizeof(int); 254 z += sizeof(int); 255 } 256 foreach (HamCoreBuilderFileEntry f in this.fileList) 257 { 258 f.Offset = z; 259 z += (int)f.CompressedData.Size; 260 } 261 262 b = new Buf(); 263 b.Write(Str.ShiftJisEncoding.GetBytes(HamCore.HamcoreHeaderData)); 264 b.WriteInt((uint)this.fileList.Count); 265 foreach (HamCoreBuilderFileEntry f in this.fileList) 266 { 267 b.WriteStr(f.Name, true); 268 b.WriteInt(f.RawData.Size); 269 b.WriteInt(f.CompressedData.Size); 270 b.WriteInt((uint)f.Offset); 271 } 272 foreach (HamCoreBuilderFileEntry f in this.fileList) 273 { 274 b.Write(f.CompressedData.ByteData); 275 } 276 277 b.SeekToBegin(); 278 279 return b; 280 } 281 } 282 283 public class HamCore 284 { 285 public const string HamcoreDirName = "@hamcore"; 286 public const string HamcoreHeaderData = "HamCore"; 287 public const int HamcoreHeaderSize = 7; 288 public const long HamcoreCacheExpires = 5 * 60 * 1000; 289 bool disableReadRawFile = false; 290 public bool DisableReadRawFile 291 { 292 get { return disableReadRawFile; } 293 set { disableReadRawFile = value; } 294 } 295 296 Dictionary<string, HamCoreEntry> list; 297 298 IO hamcore_io; 299 HamCore(string filename)300 public HamCore(string filename) 301 { 302 init(filename); 303 } 304 GetFileNames()305 public string[] GetFileNames() 306 { 307 List<string> ret = new List<string>(); 308 309 foreach (HamCoreEntry e in list.Values) 310 { 311 ret.Add(e.FileName); 312 } 313 314 return ret.ToArray(); 315 } 316 init(string filename)317 void init(string filename) 318 { 319 filename = IO.InnerFilePath(filename); 320 string filenameOnly = Path.GetFileName(filename); 321 string filenameAlt = Path.Combine(Path.GetDirectoryName(filename), "_" + filenameOnly); 322 323 try 324 { 325 IO.FileReplaceRename(filenameAlt, filename); 326 } 327 catch 328 { 329 } 330 331 list = new Dictionary<string, HamCoreEntry>(); 332 333 try 334 { 335 hamcore_io = IO.FileOpen(filename); 336 } 337 catch 338 { 339 return; 340 } 341 342 try 343 { 344 byte[] header = hamcore_io.Read(HamcoreHeaderSize); 345 byte[] header2 = Str.AsciiEncoding.GetBytes(HamcoreHeaderData); 346 if (header == null || Util.CompareByte(header, header2) == false) 347 { 348 throw new SystemException(); 349 } 350 351 uint num = 0; 352 byte[] buf = hamcore_io.Read(Util.SizeOfInt32); 353 num = Util.ByteToUInt(buf); 354 uint i; 355 for (i = 0; i < num; i++) 356 { 357 uint str_size; 358 359 buf = hamcore_io.Read(Util.SizeOfInt32); 360 str_size = Util.ByteToUInt(buf); 361 if (str_size >= 1) 362 { 363 str_size--; 364 } 365 366 byte[] str_data = hamcore_io.Read((int)str_size); 367 string tmp = Str.ShiftJisEncoding.GetString(str_data); 368 369 HamCoreEntry c = new HamCoreEntry(); 370 c.FileName = tmp; 371 372 buf = hamcore_io.Read(Util.SizeOfInt32); 373 c.Size = Util.ByteToUInt(buf); 374 375 buf = hamcore_io.Read(Util.SizeOfInt32); 376 c.SizeCompressed = Util.ByteToUInt(buf); 377 378 buf = hamcore_io.Read(Util.SizeOfInt32); 379 c.Offset = Util.ByteToUInt(buf); 380 381 list.Add(c.FileName.ToUpper(), c); 382 } 383 } 384 catch 385 { 386 hamcore_io.Close(); 387 } 388 } 389 ReadHamcore(string name)390 public Buf ReadHamcore(string name) 391 { 392 if (name[0] == '|') 393 { 394 name = name.Substring(1); 395 } 396 if (name[0] == '/' || name[0] == '\\') 397 { 398 name = name.Substring(1); 399 } 400 401 string filename = name; 402 403 filename = filename.Replace("/", "\\"); 404 405 Buf b; 406 407 if (this.disableReadRawFile == false) 408 { 409 try 410 { 411 b = Buf.ReadFromFile(HamcoreDirName + "\\" + filename); 412 413 return b; 414 } 415 catch 416 { 417 } 418 } 419 420 lock (list) 421 { 422 HamCoreEntry c; 423 string key = filename.ToUpper(); 424 425 b = null; 426 427 if (list.ContainsKey(key)) 428 { 429 c = list[key]; 430 431 if (c.Buffer != null) 432 { 433 b = new Buf(c.Buffer); 434 b.SeekToBegin(); 435 c.LastAccess = Time.Tick64; 436 } 437 else 438 { 439 if (hamcore_io.Seek(SeekOrigin.Begin, (int)c.Offset)) 440 { 441 byte[] data = hamcore_io.Read((int)c.SizeCompressed); 442 443 int dstSize = (int)c.Size; 444 byte[] buffer = ZLib.Uncompress(data, dstSize); 445 446 c.Buffer = buffer; 447 b = new Buf(buffer); 448 b.SeekToBegin(); 449 c.LastAccess = Time.Tick64; 450 } 451 } 452 } 453 454 long now = Time.Tick64; 455 foreach (HamCoreEntry cc in list.Values) 456 { 457 if (cc.Buffer != null) 458 { 459 if (((cc.LastAccess + HamcoreCacheExpires) < now) || 460 cc.FileName.StartsWith("Li", StringComparison.CurrentCultureIgnoreCase)) 461 { 462 cc.Buffer = null; 463 } 464 } 465 } 466 } 467 468 return b; 469 } 470 } 471 472 public class DirEntry : IComparable<DirEntry> 473 { 474 internal bool folder; 475 public bool IsFolder 476 { 477 get { return folder; } 478 } 479 internal string fileName; 480 public string FileName 481 { 482 get { return fileName; } 483 } 484 internal string fullPath; 485 public string FullPath 486 { 487 get { return fullPath; } 488 } 489 internal string relativePath; 490 public string RelativePath 491 { 492 get { return relativePath; } 493 } 494 internal long fileSize; 495 public long FileSize 496 { 497 get { return fileSize; } 498 } 499 internal DateTime createDate; 500 public DateTime CreateDate 501 { 502 get { return createDate; } 503 } 504 internal DateTime updateDate; 505 public DateTime UpdateDate 506 { 507 get { return updateDate; } 508 } 509 CompareTo(DirEntry other)510 public int CompareTo(DirEntry other) 511 { 512 int i; 513 i = Str.StrCmpiRetInt(this.fileName, other.fileName); 514 if (i == 0) 515 { 516 i = Str.StrCmpRetInt(this.fileName, other.fileName); 517 } 518 519 return i; 520 } 521 ToString()522 public override string ToString() 523 { 524 return FileName; 525 } 526 }; 527 528 public class IO 529 { CopyDirPreCopyDelegate(FileInfo srcFileInfo)530 public delegate bool CopyDirPreCopyDelegate(FileInfo srcFileInfo); CopyDir(string srcDirName, string destDirName, CopyDirPreCopyDelegate preCopy, bool ignoreError, bool printStatus)531 public static void CopyDir(string srcDirName, string destDirName, CopyDirPreCopyDelegate preCopy, bool ignoreError, bool printStatus) 532 { 533 CopyDir(srcDirName, destDirName, preCopy, ignoreError, printStatus, false, false, false); 534 } CopyDir(string srcDirName, string destDirName, CopyDirPreCopyDelegate preCopy, bool ignoreError, bool printStatus, bool skipIfNoChange, bool deleteBom)535 public static void CopyDir(string srcDirName, string destDirName, CopyDirPreCopyDelegate preCopy, bool ignoreError, bool printStatus, 536 bool skipIfNoChange, bool deleteBom) 537 { 538 CopyDir(srcDirName, destDirName, preCopy, ignoreError, printStatus, skipIfNoChange, deleteBom, false); 539 } CopyDir(string srcDirName, string destDirName, CopyDirPreCopyDelegate preCopy, bool ignoreError, bool printStatus, bool skipIfNoChange, bool deleteBom, bool useTimeStampToCheckNoChange)540 public static void CopyDir(string srcDirName, string destDirName, CopyDirPreCopyDelegate preCopy, bool ignoreError, bool printStatus, 541 bool skipIfNoChange, bool deleteBom, bool useTimeStampToCheckNoChange) 542 { 543 string[] files = Directory.GetFiles(srcDirName, "*", SearchOption.AllDirectories); 544 545 foreach (string srcFile in files) 546 { 547 FileInfo info = new FileInfo(srcFile); 548 549 string relativeFileName = IO.GetRelativeFileName(srcFile, srcDirName); 550 string destFileName = Path.Combine(destDirName, relativeFileName); 551 string destFileDirName = Path.GetDirectoryName(destFileName); 552 553 if (preCopy != null) 554 { 555 if (preCopy(info) == false) 556 { 557 continue; 558 } 559 } 560 561 try 562 { 563 if (Directory.Exists(destFileDirName) == false) 564 { 565 Directory.CreateDirectory(destFileDirName); 566 } 567 568 FileCopy(srcFile, destFileName, skipIfNoChange, deleteBom, useTimeStampToCheckNoChange); 569 } 570 catch 571 { 572 if (ignoreError == false) 573 { 574 throw; 575 } 576 } 577 578 if (printStatus) 579 { 580 Con.WriteLine(relativeFileName); 581 } 582 } 583 } 584 585 public const string DefaultHamcoreFileName = "@hamcore.se2"; 586 587 static string hamcoreFileName = DefaultHamcoreFileName; 588 public static string HamcoreFileName 589 { 590 get { return IO.hamcoreFileName; } 591 set 592 { 593 lock (hamLockObj) 594 { 595 if (hamCore != null) 596 { 597 throw new ApplicationException(); 598 } 599 600 IO.hamcoreFileName = value; 601 tryToUseHamcore = false; 602 } 603 } 604 } 605 606 static bool tryToUseHamcore = true; 607 static HamCore hamCore = null; 608 static object hamLockObj = new object(); 609 public static HamCore HamCore 610 { 611 get 612 { 613 HamCore ret = null; 614 615 lock (hamLockObj) 616 { 617 if (hamCore == null) 618 { 619 if (tryToUseHamcore) 620 { 621 if (hamCore == null) 622 { 623 try 624 { 625 ret = hamCore = new HamCore(hamcoreFileName); 626 } 627 catch 628 { 629 tryToUseHamcore = false; 630 } 631 } 632 } 633 } 634 } 635 636 return ret; 637 } 638 } 639 640 string name; 641 public string Name 642 { 643 get { return name; } 644 } 645 FileStream p; 646 public FileStream InnerFileStream 647 { 648 get { return p; } 649 } 650 bool writeMode; 651 public bool WriteMode 652 { 653 get { return writeMode; } 654 } 655 bool hamMode; 656 public bool HamMode 657 { 658 get { return hamMode; } 659 } 660 Buf hamBuf; 661 662 object lockObj; 663 IO()664 private IO() 665 { 666 name = ""; 667 p = null; 668 writeMode = hamMode = false; 669 lockObj = new object(); 670 hamBuf = null; 671 } 672 ~IO()673 ~IO() 674 { 675 Close(); 676 } 677 WriteAllTextWithEncoding(string fileName, string str, Encoding encoding)678 public static void WriteAllTextWithEncoding(string fileName, string str, Encoding encoding) 679 { 680 WriteAllTextWithEncoding(fileName, str, encoding, false); 681 } WriteAllTextWithEncoding(string fileName, string str, Encoding encoding, bool appendBom)682 public static void WriteAllTextWithEncoding(string fileName, string str, Encoding encoding, bool appendBom) 683 { 684 fileName = InnerFilePath(fileName); 685 686 byte[] data = encoding.GetBytes(str); 687 byte[] bom = null; 688 if (appendBom) 689 { 690 bom = Str.GetBOM(encoding); 691 } 692 693 data = Util.CombineByteArray(bom, data); 694 695 File.WriteAllBytes(fileName, data); 696 } 697 ReadAllTextWithAutoGetEncoding(string fileName)698 public static string ReadAllTextWithAutoGetEncoding(string fileName) 699 { 700 fileName = InnerFilePath(fileName); 701 702 byte[] data = File.ReadAllBytes(fileName); 703 704 int bomSize; 705 Encoding enc = Str.GetEncoding(data, out bomSize); 706 if (enc == null) 707 { 708 enc = Encoding.Default; 709 } 710 711 data = Util.RemoveStartByteArray(data, bomSize); 712 713 return enc.GetString(data); 714 } 715 CreateTempFileByExt(string ext)716 public static IO CreateTempFileByExt(string ext) 717 { 718 return IO.FileCreate(CreateTempFileNameByExt(ext)); 719 } 720 CreateTempFileNameByExt(string ext)721 public static string CreateTempFileNameByExt(string ext) 722 { 723 if (Str.IsEmptyStr(ext)) 724 { 725 ext = "tmp"; 726 } 727 if (ext[0] == '.') 728 { 729 ext = ext.Substring(1); 730 } 731 732 while (true) 733 { 734 string newFilename; 735 string fullPath; 736 string randStr; 737 738 randStr = Str.GenRandStr(); 739 newFilename = "__" + randStr + "." + ext; 740 741 fullPath = CreateTempFileName(newFilename); 742 743 if (IO.IsFileExists(fullPath) == false) 744 { 745 return fullPath; 746 } 747 } 748 } 749 CreateTempFile(string name)750 public static IO CreateTempFile(string name) 751 { 752 return IO.FileCreate(CreateTempFileName(name)); 753 } 754 CreateTempFileName(string name)755 public static string CreateTempFileName(string name) 756 { 757 return Path.Combine(Env.MyTempDir, name); 758 } 759 EnumDirEx(string dirName)760 public static DirEntry[] EnumDirEx(string dirName) 761 { 762 List<DirEntry> list = new List<DirEntry>(); 763 764 enumDirEx(dirName, dirName, list); 765 766 return list.ToArray(); 767 } enumDirEx(string dirName, string baseDirName, List<DirEntry> list)768 static void enumDirEx(string dirName, string baseDirName, List<DirEntry> list) 769 { 770 string tmp = IO.InnerFilePath(dirName); 771 772 string[] dirs = Directory.GetDirectories(tmp); 773 foreach (string name in dirs) 774 { 775 string fullPath = name; 776 DirectoryInfo info = new DirectoryInfo(fullPath); 777 778 DirEntry e = new DirEntry(); 779 780 e.fileName = Path.GetFileName(name); 781 e.fileSize = 0; 782 e.createDate = info.CreationTimeUtc; 783 e.folder = true; 784 e.updateDate = info.LastWriteTimeUtc; 785 e.fullPath = fullPath; 786 e.relativePath = GetRelativeFileName(fullPath, baseDirName); 787 788 list.Add(e); 789 790 enumDirEx(fullPath, baseDirName, list); 791 } 792 793 string[] files = Directory.GetFiles(tmp); 794 foreach (string name in files) 795 { 796 string fullPath = name; 797 FileInfo info = new FileInfo(fullPath); 798 799 DirEntry e = new DirEntry(); 800 801 e.fileName = Path.GetFileName(name); 802 e.fileSize = info.Length; 803 e.createDate = info.CreationTimeUtc; 804 e.folder = false; 805 e.updateDate = info.LastWriteTimeUtc; 806 e.fullPath = fullPath; 807 e.relativePath = GetRelativeFileName(fullPath, baseDirName); 808 809 list.Add(e); 810 } 811 } 812 EnumDir(string dirName)813 public static DirEntry[] EnumDir(string dirName) 814 { 815 List<DirEntry> list = new List<DirEntry>(); 816 string tmp = IO.InnerFilePath(dirName); 817 818 string[] dirs = Directory.GetDirectories(tmp); 819 foreach (string name in dirs) 820 { 821 string fullPath = name; 822 DirectoryInfo info = new DirectoryInfo(fullPath); 823 824 DirEntry e = new DirEntry(); 825 826 e.fileName = Path.GetFileName(name); 827 e.fileSize = 0; 828 e.createDate = info.CreationTimeUtc; 829 e.folder = true; 830 e.updateDate = info.LastWriteTimeUtc; 831 e.fullPath = fullPath; 832 e.relativePath = GetRelativeFileName(fullPath, dirName); 833 834 list.Add(e); 835 } 836 837 string[] files = Directory.GetFiles(tmp); 838 foreach (string name in files) 839 { 840 string fullPath = name; 841 FileInfo info = new FileInfo(fullPath); 842 843 DirEntry e = new DirEntry(); 844 845 e.fileName = Path.GetFileName(name); 846 e.fileSize = info.Length; 847 e.createDate = info.CreationTimeUtc; 848 e.folder = false; 849 e.updateDate = info.LastWriteTimeUtc; 850 e.fullPath = fullPath; 851 e.relativePath = GetRelativeFileName(fullPath, dirName); 852 853 list.Add(e); 854 } 855 856 list.Sort(); 857 858 return list.ToArray(); 859 } 860 FileReplaceRename(string oldName, string newName)861 public static void FileReplaceRename(string oldName, string newName) 862 { 863 try 864 { 865 FileCopy(oldName, newName); 866 FileDelete(oldName); 867 } 868 catch (Exception e) 869 { 870 throw e; 871 } 872 } 873 FileCopy(string oldName, string newName)874 public static void FileCopy(string oldName, string newName) 875 { 876 FileCopy(oldName, newName, false, false); 877 } FileCopy(string oldName, string newName, bool skipIfNoChange, bool deleteBom)878 public static void FileCopy(string oldName, string newName, bool skipIfNoChange, bool deleteBom) 879 { 880 FileCopy(oldName, newName, skipIfNoChange, deleteBom, false); 881 } FileCopy(string oldName, string newName, bool skipIfNoChange, bool deleteBom, bool useTimeStampToCheckNoChange)882 public static void FileCopy(string oldName, string newName, bool skipIfNoChange, bool deleteBom, bool useTimeStampToCheckNoChange) 883 { 884 string tmp1 = InnerFilePath(oldName); 885 string tmp2 = InnerFilePath(newName); 886 887 if (useTimeStampToCheckNoChange && skipIfNoChange) 888 { 889 DateTime dt1, dt2; 890 891 try 892 { 893 dt1 = Directory.GetLastWriteTimeUtc(tmp1); 894 dt2 = Directory.GetLastWriteTimeUtc(tmp2); 895 896 TimeSpan ts = dt2 - dt1; 897 if (ts.TotalSeconds >= -5.0) 898 { 899 return; 900 } 901 } 902 catch 903 { 904 } 905 } 906 907 if (skipIfNoChange || deleteBom) 908 { 909 byte[] srcData = File.ReadAllBytes(tmp1); 910 byte[] destData = new byte[0]; 911 bool changed = true; 912 int bomSize; 913 914 Str.GetEncoding(srcData, out bomSize); 915 if (bomSize >= 1) 916 { 917 srcData = Util.ExtractByteArray(srcData, bomSize, srcData.Length - bomSize); 918 } 919 920 if (skipIfNoChange) 921 { 922 try 923 { 924 FileStream fs = File.OpenRead(tmp2); 925 long size = 0xffffffff; 926 try 927 { 928 size = fs.Length; 929 } 930 finally 931 { 932 fs.Close(); 933 } 934 935 if (size == srcData.Length || srcData.Length == 0) 936 { 937 destData = File.ReadAllBytes(tmp2); 938 } 939 } 940 catch 941 { 942 } 943 944 if (Util.CompareByte(srcData, destData)) 945 { 946 changed = false; 947 } 948 } 949 950 if (changed) 951 { 952 File.WriteAllBytes(tmp2, srcData); 953 CopyFileTimestamp(tmp2, tmp1); 954 } 955 } 956 else 957 { 958 File.Copy(tmp1, tmp2, true); 959 } 960 } 961 CopyFileTimestamp(string dstFileName, string srcFileName)962 public static void CopyFileTimestamp(string dstFileName, string srcFileName) 963 { 964 DateTime dt1 = File.GetCreationTimeUtc(srcFileName); 965 DateTime dt2 = File.GetLastAccessTimeUtc(srcFileName); 966 DateTime dt3 = File.GetLastWriteTimeUtc(srcFileName); 967 968 File.SetCreationTimeUtc(dstFileName, dt1); 969 File.SetLastAccessTimeUtc(dstFileName, dt2); 970 File.SetLastWriteTimeUtc(dstFileName, dt3); 971 } 972 SetFileTimestamp(string dstFileName, FileInfo fi)973 public static void SetFileTimestamp(string dstFileName, FileInfo fi) 974 { 975 File.SetCreationTimeUtc(dstFileName, fi.CreationTimeUtc); 976 File.SetLastAccessTimeUtc(dstFileName, fi.LastAccessTimeUtc); 977 File.SetLastWriteTimeUtc(dstFileName, fi.LastWriteTimeUtc); 978 } 979 ReadFile(string name)980 static public byte[] ReadFile(string name) 981 { 982 IO io = FileOpen(name); 983 try 984 { 985 int size = io.FileSize; 986 byte[] ret = io.Read(size); 987 return ret; 988 } 989 finally 990 { 991 io.Close(); 992 } 993 } 994 SaveFile(string name, byte[] data)995 static public void SaveFile(string name, byte[] data) 996 { 997 SaveFile(name, data, 0, data.Length); 998 } SaveFile(string name, byte[] data, int offset, int size)999 static public void SaveFile(string name, byte[] data, int offset, int size) 1000 { 1001 IO io = FileCreate(name); 1002 try 1003 { 1004 io.Write(data, offset, size); 1005 } 1006 finally 1007 { 1008 io.Close(); 1009 } 1010 } 1011 MakeSafeFileName(string src)1012 static public string MakeSafeFileName(string src) 1013 { 1014 return src 1015 .Replace("..", "__") 1016 .Replace("/", "_") 1017 .Replace("\\", "_") 1018 .Replace("@", "_") 1019 .Replace("|", "_"); 1020 } 1021 IsDirExists(string name)1022 public static bool IsDirExists(string name) 1023 { 1024 string tmp = InnerFilePath(name); 1025 1026 return Directory.Exists(tmp); 1027 } 1028 IsFileExists(string name)1029 public static bool IsFileExists(string name) 1030 { 1031 string tmp = InnerFilePath(name); 1032 1033 return File.Exists(tmp); 1034 } 1035 fileDeleteInner(string name)1036 static void fileDeleteInner(string name) 1037 { 1038 string name2 = ConvertPath(name); 1039 1040 File.Delete(name2); 1041 } FileDelete(string name)1042 public static void FileDelete(string name) 1043 { 1044 string tmp = InnerFilePath(name); 1045 1046 fileDeleteInner(tmp); 1047 } 1048 Seek(SeekOrigin mode, int offset)1049 public bool Seek(SeekOrigin mode, int offset) 1050 { 1051 lock (lockObj) 1052 { 1053 if (p != null) 1054 { 1055 try 1056 { 1057 p.Seek(offset, mode); 1058 1059 return true; 1060 } 1061 catch 1062 { 1063 return false; 1064 } 1065 } 1066 else 1067 { 1068 return false; 1069 } 1070 } 1071 } 1072 1073 public long FileSize64 1074 { 1075 get 1076 { 1077 lock (lockObj) 1078 { 1079 if (p != null) 1080 { 1081 return p.Length; 1082 } 1083 else 1084 { 1085 if (hamMode) 1086 { 1087 return (long)hamBuf.Size; 1088 } 1089 } 1090 1091 return 0; 1092 } 1093 } 1094 } 1095 public int FileSize 1096 { 1097 get 1098 { 1099 long size64 = this.FileSize64; 1100 1101 if (size64 >= 2147483647) 1102 { 1103 size64 = 2147483647; 1104 } 1105 1106 return (int)size64; 1107 } 1108 } GetFileSize(string name)1109 public static int GetFileSize(string name) 1110 { 1111 IO io = IO.FileOpen(name, false); 1112 try 1113 { 1114 return io.FileSize; 1115 } 1116 finally 1117 { 1118 io.Close(); 1119 } 1120 } 1121 ReadAll()1122 public byte[] ReadAll() 1123 { 1124 this.Seek(SeekOrigin.Begin, 0); 1125 int size = this.FileSize; 1126 1127 byte[] data = new byte[size]; 1128 this.Read(data, 0, size); 1129 1130 this.Seek(SeekOrigin.Begin, 0); 1131 1132 return data; 1133 } 1134 Read(int size)1135 public byte[] Read(int size) 1136 { 1137 byte[] buf = new byte[size]; 1138 bool ret = Read(buf, size); 1139 if (ret == false) 1140 { 1141 return null; 1142 } 1143 return buf; 1144 } Read(byte[] buf, int size)1145 public bool Read(byte[] buf, int size) 1146 { 1147 return Read(buf, 0, size); 1148 } Read(byte[] buf, int offset, int size)1149 public bool Read(byte[] buf, int offset, int size) 1150 { 1151 if (size == 0) 1152 { 1153 return true; 1154 } 1155 1156 lock (lockObj) 1157 { 1158 if (this.HamMode) 1159 { 1160 byte[] ret = hamBuf.Read((uint)size); 1161 1162 if (ret.Length != size) 1163 { 1164 return false; 1165 } 1166 1167 Util.CopyByte(buf, offset, ret, 0, size); 1168 1169 return true; 1170 } 1171 1172 if (p != null) 1173 { 1174 try 1175 { 1176 int ret = p.Read(buf, offset, size); 1177 if (ret == size) 1178 { 1179 return true; 1180 } 1181 else 1182 { 1183 return false; 1184 } 1185 } 1186 catch 1187 { 1188 return false; 1189 } 1190 } 1191 else 1192 { 1193 return false; 1194 } 1195 } 1196 } 1197 Write(byte[] buf)1198 public bool Write(byte[] buf) 1199 { 1200 return Write(buf, 0, buf.Length); 1201 } Write(byte[] buf, int size)1202 public bool Write(byte[] buf, int size) 1203 { 1204 return Write(buf, 0, size); 1205 } Write(byte[] buf, int offset, int size)1206 public bool Write(byte[] buf, int offset, int size) 1207 { 1208 if (writeMode == false) 1209 { 1210 return false; 1211 } 1212 if (size == 0) 1213 { 1214 return true; 1215 } 1216 1217 lock (lockObj) 1218 { 1219 if (p != null) 1220 { 1221 try 1222 { 1223 p.Write(buf, offset, size); 1224 1225 return true; 1226 } 1227 catch 1228 { 1229 return false; 1230 } 1231 } 1232 else 1233 { 1234 return false; 1235 } 1236 } 1237 } 1238 CloseAndDelete()1239 public bool CloseAndDelete() 1240 { 1241 string name = this.Name; 1242 1243 Close(); 1244 1245 try 1246 { 1247 FileDelete(name); 1248 return true; 1249 } 1250 catch 1251 { 1252 return false; 1253 } 1254 } 1255 Close()1256 public void Close() 1257 { 1258 Close(false); 1259 } Close(bool noFlush)1260 public void Close(bool noFlush) 1261 { 1262 lock (this.lockObj) 1263 { 1264 if (this.hamMode == false) 1265 { 1266 if (this.p != null) 1267 { 1268 if (this.writeMode && noFlush == false) 1269 { 1270 Flush(); 1271 } 1272 1273 this.p.Close(); 1274 } 1275 1276 this.p = null; 1277 } 1278 } 1279 } 1280 Flush()1281 public void Flush() 1282 { 1283 try 1284 { 1285 lock (this.lockObj) 1286 { 1287 if (this.p != null) 1288 { 1289 this.p.Flush(); 1290 } 1291 } 1292 } 1293 catch 1294 { 1295 } 1296 } 1297 fileCreateInner(string name)1298 static IO fileCreateInner(string name) 1299 { 1300 IO o = new IO(); 1301 1302 string name2 = ConvertPath(name); 1303 1304 lock (o.lockObj) 1305 { 1306 o.p = File.Open(name2, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); 1307 o.name = name2; 1308 o.writeMode = true; 1309 } 1310 1311 return o; 1312 } 1313 FileCreate(string name)1314 public static IO FileCreate(string name) 1315 { 1316 name = InnerFilePath(name); 1317 1318 return fileCreateInner(name); 1319 } 1320 fileOpenInner(string name, bool writeMode, bool readLock)1321 static IO fileOpenInner(string name, bool writeMode, bool readLock) 1322 { 1323 IO o = new IO(); 1324 1325 string name2 = ConvertPath(name); 1326 1327 lock (o.lockObj) 1328 { 1329 o.p = File.Open(name2, FileMode.Open, (writeMode ? FileAccess.ReadWrite : FileAccess.Read), 1330 (readLock ? FileShare.None : FileShare.Read)); 1331 1332 o.name = name2; 1333 o.writeMode = writeMode; 1334 } 1335 1336 return o; 1337 } 1338 FileOpen(string name)1339 public static IO FileOpen(string name) 1340 { 1341 return FileOpen(name, false); 1342 } FileOpen(string name, bool writeMode)1343 public static IO FileOpen(string name, bool writeMode) 1344 { 1345 return FileOpen(name, writeMode, false); 1346 } FileOpen(string name, bool writeMode, bool readLock)1347 public static IO FileOpen(string name, bool writeMode, bool readLock) 1348 { 1349 name = InnerFilePath(name); 1350 1351 if (name[0] == '|') 1352 { 1353 HamCore hc = IO.HamCore; 1354 1355 Buf b = hc.ReadHamcore(name); 1356 if (b == null) 1357 { 1358 throw new FileNotFoundException(); 1359 } 1360 1361 IO o = new IO(); 1362 o.name = name.Substring(1); 1363 o.hamMode = true; 1364 o.hamBuf = b; 1365 1366 return o; 1367 } 1368 else 1369 { 1370 return fileOpenInner(name, writeMode, readLock); 1371 } 1372 } 1373 FileCreateOrAppendOpen(string name)1374 public static IO FileCreateOrAppendOpen(string name) 1375 { 1376 if (IsFileExists(name)) 1377 { 1378 IO io = FileOpen(name, true); 1379 io.Seek(SeekOrigin.End, 0); 1380 return io; 1381 } 1382 else 1383 { 1384 return FileCreate(name); 1385 } 1386 } 1387 GetRelativeFileName(string fileName, string baseDirName)1388 public static string GetRelativeFileName(string fileName, string baseDirName) 1389 { 1390 baseDirName = RemoteLastEnMark(baseDirName).Trim() + "\\"; 1391 fileName = fileName.Trim(); 1392 1393 if (fileName.Length <= baseDirName.Length) 1394 { 1395 throw new ArgumentException("fileName, baseDirName"); 1396 } 1397 1398 if (fileName.StartsWith(baseDirName, StringComparison.InvariantCultureIgnoreCase) == false) 1399 { 1400 throw new ArgumentException("fileName, baseDirName"); 1401 } 1402 1403 return fileName.Substring(baseDirName.Length); 1404 } 1405 RemoteLastEnMark(string path)1406 public static string RemoteLastEnMark(string path) 1407 { 1408 if (path == null) 1409 { 1410 path = ""; 1411 } 1412 if (path.EndsWith("\\")) 1413 { 1414 path = path.Substring(0, path.Length - 1); 1415 } 1416 return path; 1417 } 1418 FileRename(string oldName, string newName)1419 public static void FileRename(string oldName, string newName) 1420 { 1421 string tmp1 = InnerFilePath(oldName); 1422 string tmp2 = InnerFilePath(newName); 1423 1424 File.Move(tmp1, tmp2); 1425 } 1426 DeleteFilesAndSubDirsInDir(string dirName)1427 public static void DeleteFilesAndSubDirsInDir(string dirName) 1428 { 1429 dirName = InnerFilePath(dirName); 1430 1431 if (Directory.Exists(dirName) == false) 1432 { 1433 Directory.CreateDirectory(dirName); 1434 return; 1435 } 1436 1437 string[] files = Directory.GetFiles(dirName); 1438 string[] dirs = Directory.GetDirectories(dirName); 1439 1440 foreach (string file in files) 1441 { 1442 File.SetAttributes(file, FileAttributes.Normal); 1443 File.Delete(file); 1444 } 1445 1446 foreach (string dir in dirs) 1447 { 1448 Directory.Delete(dir, true); 1449 } 1450 } 1451 DeleteDir(string dirName)1452 public static bool DeleteDir(string dirName) 1453 { 1454 return DeleteDir(dirName, false); 1455 } DeleteDir(string dirName, bool deleteSubDirs)1456 public static bool DeleteDir(string dirName, bool deleteSubDirs) 1457 { 1458 try 1459 { 1460 Directory.Delete(InnerFilePath(dirName), deleteSubDirs); 1461 return true; 1462 } 1463 catch 1464 { 1465 return false; 1466 } 1467 } 1468 MakeDir(string dirName)1469 public static bool MakeDir(string dirName) 1470 { 1471 try 1472 { 1473 Directory.CreateDirectory(InnerFilePath(dirName)); 1474 return true; 1475 } 1476 catch 1477 { 1478 return false; 1479 } 1480 } MakeDirIfNotExists(string dirName)1481 public static bool MakeDirIfNotExists(string dirName) 1482 { 1483 string path = InnerFilePath(dirName); 1484 1485 if (Directory.Exists(path) == false) 1486 { 1487 Directory.CreateDirectory(path); 1488 1489 return true; 1490 } 1491 1492 return false; 1493 } 1494 NormalizePath(string src)1495 public static string NormalizePath(string src) 1496 { 1497 bool first_double_slash = false; 1498 bool first_single_slash = false; 1499 string win32_drive_char = ""; 1500 int i; 1501 string tmp; 1502 1503 tmp = ConvertPath(src).Trim(); 1504 1505 if (tmp.StartsWith(".\\") || tmp.StartsWith("..\\") || tmp.StartsWith(".") || tmp.StartsWith("..")) 1506 { 1507 if (tmp.StartsWith("..")) 1508 { 1509 tmp = Env.CurrentDir + "/../" + tmp.Substring(2); 1510 } 1511 else 1512 { 1513 tmp = Env.CurrentDir + "/" + tmp; 1514 } 1515 } 1516 1517 if (tmp.StartsWith("~/") || tmp.StartsWith("~\\")) 1518 { 1519 tmp = Env.HomeDir + "/" + tmp.Substring(2); 1520 } 1521 1522 if (tmp.StartsWith("//") || tmp.StartsWith("\\\\")) 1523 { 1524 first_double_slash = true; 1525 } 1526 else 1527 { 1528 if (tmp.StartsWith("/") || tmp.StartsWith("\\")) 1529 { 1530 first_single_slash = true; 1531 } 1532 } 1533 1534 if (tmp.Length >= 2) 1535 { 1536 if (tmp[1] == ':') 1537 { 1538 win32_drive_char = "" + tmp[0]; 1539 tmp = tmp.Substring(2); 1540 } 1541 } 1542 1543 if (tmp == "/" || tmp == "\\") 1544 { 1545 tmp = ""; 1546 } 1547 1548 char[] splitChars = { '/', '\\' }; 1549 string[] t = tmp.Split(splitChars, StringSplitOptions.RemoveEmptyEntries); 1550 1551 Stack<string> sk = new Stack<string>(); 1552 1553 for (i = 0; i < t.Length; i++) 1554 { 1555 string s = t[i]; 1556 1557 if (Str.StrCmpi(s, ".")) 1558 { 1559 continue; 1560 } 1561 else if (Str.StrCmpi(s, "..")) 1562 { 1563 if (sk.Count >= 1 && (first_double_slash == false || sk.Count >= 2)) 1564 { 1565 sk.Pop(); 1566 } 1567 } 1568 else 1569 { 1570 sk.Push(s); 1571 } 1572 } 1573 1574 tmp = ""; 1575 1576 if (first_double_slash) 1577 { 1578 tmp += "//"; 1579 } 1580 else if (first_single_slash) 1581 { 1582 tmp += "/"; 1583 } 1584 1585 if (Str.IsEmptyStr(win32_drive_char) == false) 1586 { 1587 tmp = win32_drive_char + ":/" + tmp; 1588 } 1589 1590 string[] sks = sk.ToArray(); 1591 Array.Reverse(sks); 1592 for (i = 0; i < sks.Length; i++) 1593 { 1594 tmp += sks[i]; 1595 if (i != (sks.Length - 1)) 1596 { 1597 tmp += "/"; 1598 } 1599 } 1600 1601 tmp = ConvertPath(tmp); 1602 1603 return tmp; 1604 } 1605 ConvertPath(string path)1606 public static string ConvertPath(string path) 1607 { 1608 return path.Replace('/', '\\'); 1609 } 1610 ConbinePath(string dirname, string filename)1611 public static string ConbinePath(string dirname, string filename) 1612 { 1613 return CombinePath(dirname, filename); 1614 } CombinePath(string dirname, string filename)1615 public static string CombinePath(string dirname, string filename) 1616 { 1617 bool is_full_path; 1618 string filename_ident = NormalizePath(filename); 1619 1620 is_full_path = false; 1621 1622 if (filename_ident.StartsWith("\\") || filename_ident.StartsWith("/")) 1623 { 1624 is_full_path = true; 1625 } 1626 1627 filename = filename_ident; 1628 1629 if (filename.Length >= 2) 1630 { 1631 char c = filename[0]; 1632 if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) 1633 { 1634 if (filename[1] == ':') 1635 { 1636 is_full_path = true; 1637 } 1638 } 1639 } 1640 1641 string tmp; 1642 1643 if (is_full_path == false) 1644 { 1645 tmp = dirname; 1646 if (tmp.EndsWith("/") == false && tmp.EndsWith("\\") == false) 1647 { 1648 tmp += "/"; 1649 } 1650 1651 tmp += filename; 1652 } 1653 else 1654 { 1655 tmp = filename; 1656 } 1657 1658 return NormalizePath(tmp); 1659 } 1660 InnerFilePath(string src)1661 public static string InnerFilePath(string src) 1662 { 1663 if (src[0] != '@') 1664 { 1665 return NormalizePath(src); 1666 } 1667 else 1668 { 1669 return CombinePath(Env.ExeFileDir, src.Substring(1)); 1670 } 1671 } 1672 GetCreationTimeUtc(string filename)1673 public static DateTime GetCreationTimeUtc(string filename) 1674 { 1675 return File.GetCreationTimeUtc(InnerFilePath(filename)); 1676 } GetCreationTimeLocal(string filename)1677 public static DateTime GetCreationTimeLocal(string filename) 1678 { 1679 return File.GetCreationTime(InnerFilePath(filename)); 1680 } 1681 GetLastWriteTimeUtc(string filename)1682 public static DateTime GetLastWriteTimeUtc(string filename) 1683 { 1684 return File.GetLastWriteTimeUtc(InnerFilePath(filename)); 1685 } GetLastWriteTimeLocal(string filename)1686 public static DateTime GetLastWriteTimeLocal(string filename) 1687 { 1688 return File.GetLastWriteTime(InnerFilePath(filename)); 1689 } 1690 GetLastAccessTimeUtc(string filename)1691 public static DateTime GetLastAccessTimeUtc(string filename) 1692 { 1693 return File.GetLastAccessTimeUtc(InnerFilePath(filename)); 1694 } GetLastAccessTimeLocal(string filename)1695 public static DateTime GetLastAccessTimeLocal(string filename) 1696 { 1697 return File.GetLastAccessTime(InnerFilePath(filename)); 1698 } 1699 ReadFileData(string filename)1700 public static byte[] ReadFileData(string filename) 1701 { 1702 FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 1703 try 1704 { 1705 long size = fs.Length; 1706 int size2 = (int)Math.Min(size, int.MaxValue); 1707 byte[] ret = new byte[size2]; 1708 fs.Read(ret, 0, size2); 1709 return ret; 1710 } 1711 finally 1712 { 1713 fs.Close(); 1714 } 1715 } 1716 } 1717 } 1718