/// <summary>
        /// Enumerates all non-archive local files, BLT encodes them and adds them to the InstallFile
        /// </summary>
        /// <param name="maxDegreeOfParallelism"></param>
        /// <returns></returns>
        public void ExportFiles(int maxDegreeOfParallelism = 15)
        {
            var results = new ConcurrentBag <CASRecord>();

            var block = new ActionBlock <string>(file =>
            {
                // strip the local path and normalise
                var name = file[(file.IndexOf(BaseDirectory, Comparison) + BaseDirectory.Length)..].WoWNormalise();

                // block table encode and export to the temp folder
                // then add appropiate tags
                var record  = BlockTableEncoder.EncodeAndExport(file, Options.TempDirectory, name);
                record.Tags = TagGenerator.GetTags(file);

                if (!EncodingCache.ContainsEKey(record.EKey))
                {
                    EncodingCache.AddOrUpdate(record);
                }
                else
                {
                    record.BLTEPath = "";
                }

                results.Add(record);
            },
Beispiel #2
0
 /// <summary>
 /// 设置输出数据
 /// </summary>
 /// <param name="charStream"></param>
 /// <param name="encoding"></param>
 internal unsafe void SetBody(CharStream charStream, ref EncodingCache encoding)
 {
     if (charStream.Data.CurrentIndex == 0)
     {
         SetBody();
     }
     else
     {
         freeBody();
         int size = encoding.GetByteCountNotNull(charStream);
         AutoCSer.SubBuffer.Pool.GetBuffer(ref SubBuffer, size);
         if (SubBuffer.PoolBuffer.Pool == null)
         {
             encoding.WriteBytes(charStream, Body.Array = SubBuffer.Buffer);
             SubBuffer.Buffer = null;
             Type             = ResponseType.ByteArray;
         }
         else
         {
             Body.Set(SubBuffer.Buffer, SubBuffer.StartIndex, size);
             encoding.WriteBytes(charStream, ref Body);
             Type = ResponseType.SubBuffer;
         }
     }
 }
Beispiel #3
0
        /// <summary>
        /// Extracts a collection of files from an archive and BLTE encodes them
        /// </summary>
        /// <param name="mpq"></param>
        /// <param name="filenames"></param>
        /// <param name="maxDegreeOfParallelism"></param>
        /// <returns></returns>
        private async Task ExportFiles(MpqArchive mpq, IEnumerable <string> filenames, bool applyTags = false, int maxDegreeOfParallelism = 150)
        {
            var block = new ActionBlock <string>(file =>
            {
                using var fs = mpq.OpenFile(file);

                // ignore PTCH files
                if (fs.Flags.HasFlag(MPQFileAttributes.PatchFile))
                {
                    return;
                }

                // patch has marked file for deletion so remove from filelist
                if (fs.Flags.HasFlag(MPQFileAttributes.DeleteMarker))
                {
                    FileList.TryRemove(file, out _);
                    return;
                }

                if (fs.CanRead && fs.Length > 0)
                {
                    var map = BlockTableEncoder.GetEMapFromExtension(file, fs.Length);

                    if (!EncodingCache.TryGetRecord(MD5Hash.Parse(fs.GetMD5Hash()), file, out var record))
                    {
                        record = BlockTableEncoder.EncodeAndExport(fs, map, Options.TempDirectory, file);
                        EncodingCache.AddOrUpdate(record);
                    }

                    if (applyTags)
                    {
                        record.Tags = TagGenerator.GetTags(file, fs);
                    }

                    record.EBlock.EncodingMap = map;
                    FileList.TryAdd(file, record);
                }
            },
                                                 new ExecutionDataflowBlockOptions {
                MaxDegreeOfParallelism = maxDegreeOfParallelism
            });

            foreach (var file in filenames)
            {
                if (!FileList.ContainsKey(file))
                {
                    block.Post(file);
                }
            }

            block.Complete();
            await block.Completion;
        }
Beispiel #4
0
 /// <summary>
 /// 文件服务
 /// </summary>
 protected FileServer()
 {
     ResponseEncoding = new EncodingCache(WebConfig.Encoding ?? AutoCSer.Config.Pub.Default.Encoding);
     if (ResponseEncoding.Encoding.CodePage == AutoCSer.Config.Pub.Default.Encoding.CodePage)
     {
         HtmlContentType = Http.ContentTypeAttribute.Html;
         JsContentType   = Http.ContentTypeAttribute.Js;
     }
     else
     {
         HtmlContentType = EncodingCache.Ascii.GetBytesNotEmpty("text/html; charset=" + ResponseEncoding.Encoding.WebName);
         JsContentType   = EncodingCache.Ascii.GetBytesNotEmpty("application/x-javascript; charset=" + ResponseEncoding.Encoding.WebName);
     }
 }
Beispiel #5
0
 /// <summary>
 /// 设置输出数据
 /// </summary>
 /// <param name="value"></param>
 /// <param name="isAscii"></param>
 /// <param name="encoding"></param>
 internal unsafe void SetBody(string value, bool isAscii, ref EncodingCache encoding)
 {
     if (value.Length == 0)
     {
         SetBody();
     }
     else
     {
         freeBody();
         if (isAscii && encoding.IsCompatibleAscii != 0)
         {
             int size = value.Length;
             AutoCSer.SubBuffer.Pool.GetBuffer(ref SubBuffer, size);
             fixed(char *textFixed = value)
             fixed(byte *bufferFixed = SubBuffer.GetFixedBuffer())
             {
                 if (SubBuffer.PoolBuffer.Pool == null)
                 {
                     Body.Array = SubBuffer.Buffer;
                     AutoCSer.Extensions.StringExtension.WriteBytes(textFixed, size, bufferFixed);
                     SubBuffer.Buffer = null;
                     Type             = ResponseType.ByteArray;
                 }
                 else
                 {
                     Body.Set(SubBuffer.Buffer, SubBuffer.StartIndex, size);
                     AutoCSer.Extensions.StringExtension.WriteBytes(textFixed, size, bufferFixed + Body.Start);
                     Type = ResponseType.SubBuffer;
                 }
             }
         }
         else
         {
             int size = encoding.GetByteCountNotNull(value);
             AutoCSer.SubBuffer.Pool.GetBuffer(ref SubBuffer, size);
             if (SubBuffer.PoolBuffer.Pool == null)
             {
                 encoding.WriteBytesNotEmpty(value, Body.Array = SubBuffer.Buffer);
                 SubBuffer.Buffer = null;
                 Type             = ResponseType.ByteArray;
             }
             else
             {
                 Body.Set(SubBuffer.Buffer, SubBuffer.StartIndex, size);
                 encoding.WriteBytesNotEmpty(value, Body.Array, Body.Start);
                 Type = ResponseType.SubBuffer;
             }
         }
     }
 }
 /// <summary>
 /// 文件流写入器
 /// </summary>
 /// <param name="fileName">文件全名</param>
 /// <param name="mode">打开方式</param>
 /// <param name="fileShare">共享访问方式</param>
 /// <param name="fileOption">附加选项</param>
 /// <param name="bufferSize">缓冲区字节大小</param>
 /// <param name="log">日志处理</param>
 /// <param name="encoding">文件编码</param>
 internal FileStreamWriter(string fileName, FileMode mode, FileShare fileShare, FileOptions fileOption, SubBuffer.Size bufferSize, ILog log, EncodingCache encoding)
 {
     if (string.IsNullOrEmpty(fileName))
     {
         throw new ArgumentNullException("fileName is null");
     }
     FileName        = fileName;
     this.log        = log;
     this.fileShare  = fileShare;
     this.fileOption = fileOption;
     this.encoding   = encoding;
     bufferPool      = SubBuffer.Pool.GetPool(bufferSize);
     open(mode);
 }
Beispiel #7
0
        /// <summary>
        /// Iterates all loose files within the data directory and BLT encodes them
        /// </summary>
        /// <param name="filenames"></param>
        public void EnumerateLooseDataFiles(IEnumerable <string> filenames)
        {
            if (!filenames.Any())
            {
                return;
            }

            Log.WriteLine("Exporting loose Data files");

            var block = new ActionBlock <string>(file =>
            {
                var filename = GetInternalPath(file);

                var record  = BlockTableEncoder.EncodeAndExport(file, Options.TempDirectory, filename);
                record.Tags = TagGenerator.GetTags(file);

                if (!EncodingCache.ContainsEKey(record.EKey))
                {
                    EncodingCache.AddOrUpdate(record);
                }
                else
                {
                    record.BLTEPath = "";
                }

                FileList.TryAdd(filename, record);
            },
                                                 new ExecutionDataflowBlockOptions {
                MaxDegreeOfParallelism = 150
            });

            foreach (var f in filenames)
            {
                block.Post(f);
            }

            block.Complete();
            block.Completion.Wait();
        }
Beispiel #8
0
        /// <summary>
        /// Some alpha MPQs are hotswappable and only contain a single file and it's checksum
        /// </summary>
        /// <param name="mpq"></param>
        /// <param name="archivename"></param>
        private bool TryReadAlpha(MpqArchive mpq, string archivename)
        {
            // strip the local path and extension to get the filename
            var file = Path.ChangeExtension(GetInternalPath(archivename), null).WoWNormalise();

            if (FileList.ContainsKey(file))
            {
                return(true);
            }

            // add the filename as the listfile
            var internalname = Path.GetFileName(file);

            mpq.AddListFile(internalname);

            // read file if known
            if (mpq.HasFile(internalname))
            {
                using var fs = mpq.OpenFile(internalname);

                if (fs.CanRead && fs.Length > 0)
                {
                    var map = BlockTableEncoder.GetEMapFromExtension(file, fs.Length);

                    if (!EncodingCache.TryGetRecord(MD5Hash.Parse(fs.GetMD5Hash()), file, out var record))
                    {
                        record = BlockTableEncoder.EncodeAndExport(fs, map, Options.TempDirectory, file);
                        EncodingCache.AddOrUpdate(record);
                    }

                    record.EBlock.EncodingMap = map;
                    FileList.TryAdd(file, record);
                    return(true);
                }
            }

            return(false);
        }
 internal void WriteNotPool(string value, byte[] buffer, ref EncodingCache encoding)
 {
     Buffer.Set(buffer, 0);
     WriteIndex = encoding.WriteBytesNotEmpty(value, buffer);
     IsWait     = false;
 }
 internal void Write(string value, ref EncodingCache encoding)
 {
     WriteIndex += encoding.WriteBytesNotEmpty(value, Buffer.Buffer, WriteIndex);
 }
Beispiel #11
0
 internal void Set(UnmanagedStream responseStream, ref EncodingCache encoding)
 {
     this.ResponseStream = responseStream;
     this.encoding       = encoding;
 }