public static List <LogInfo> TXTAddLineOp(EngineState s, CodeCommand cmd) { List <LogInfo> logs = new List <LogInfo>(8); CodeInfo_TXTAddLineOp infoOp = cmd.Info.Cast <CodeInfo_TXTAddLineOp>(); CodeInfo_TXTAddLine firstInfo = infoOp.Infos[0]; string fileName = StringEscaper.Preprocess(s, firstInfo.FileName); string modeStr = StringEscaper.Preprocess(s, firstInfo.Mode); TXTAddLineMode mode; if (modeStr.Equals("Append", StringComparison.OrdinalIgnoreCase)) { mode = TXTAddLineMode.Append; } else if (modeStr.Equals("Prepend", StringComparison.OrdinalIgnoreCase)) { mode = TXTAddLineMode.Prepend; } else { throw new ExecuteException($"Mode [{modeStr}] must be one of [Append, Prepend]"); } if (!StringEscaper.PathSecurityCheck(fileName, out string errorMsg)) { return(LogInfo.LogErrorMessage(logs, errorMsg)); } // Detect encoding of text. If text does not exists, create blank file (ANSI) Encoding encoding; if (File.Exists(fileName)) { encoding = EncodingHelper.SmartDetectEncoding(fileName, infoOp.Infos.Select(x => x.Line)); } else { encoding = EncodingHelper.DefaultAnsi; } string linesToWrite; if (mode == TXTAddLineMode.Prepend) { string tempPath = FileHelper.GetTempFile(); using (StreamReader r = new StreamReader(fileName, encoding, false)) using (StreamWriter w = new StreamWriter(tempPath, false, encoding)) { StringBuilder b = new StringBuilder(); List <CodeInfo_TXTAddLine> infos = infoOp.Infos; infos.Reverse(); foreach (CodeInfo_TXTAddLine subInfo in infos) { b.AppendLine(StringEscaper.Preprocess(s, subInfo.Line)); } linesToWrite = b.ToString(); w.Write(linesToWrite); w.Write(r.ReadToEnd()); } FileHelper.FileReplaceEx(tempPath, fileName); logs.Add(new LogInfo(LogState.Success, $"Lines prepended to [{fileName}] : \r\n{linesToWrite}", cmd)); } else if (mode == TXTAddLineMode.Append) { StringBuilder b = new StringBuilder(); foreach (CodeInfo_TXTAddLine subInfo in infoOp.Infos) { b.AppendLine(StringEscaper.Preprocess(s, subInfo.Line)); } linesToWrite = b.ToString(); bool newLineExist = true; if (File.Exists(fileName)) { using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { long bomLen = EncodingHelper.TextBomLength(fs); byte[] lastChar = new byte[2]; if (2 + bomLen <= fs.Length) { fs.Position = fs.Length - 2; fs.Read(lastChar, 0, 2); if (lastChar[0] != '\r' || lastChar[1] != '\n') { newLineExist = false; } } } } if (newLineExist) { File.AppendAllText(fileName, linesToWrite, encoding); } else { File.AppendAllText(fileName, "\r\n" + linesToWrite, encoding); } logs.Add(new LogInfo(LogState.Success, $"Lines appended to [{fileName}] : \r\n{linesToWrite}", cmd)); } else { throw new InvalidOperationException("Internal Logic Error at TXTAddLine"); } return(logs); }
public static List <LogInfo> TXTAddLineOp(EngineState s, CodeCommand cmd) { List <LogInfo> logs = new List <LogInfo>(); Debug.Assert(cmd.Info.GetType() == typeof(CodeInfo_TXTAddLineOp)); CodeInfo_TXTAddLineOp infoOp = cmd.Info as CodeInfo_TXTAddLineOp; string fileName = StringEscaper.Preprocess(s, infoOp.InfoList[0].FileName); string modeStr = StringEscaper.Preprocess(s, infoOp.InfoList[0].Mode); TXTAddLineMode mode; if (modeStr.Equals("Append", StringComparison.OrdinalIgnoreCase)) { mode = TXTAddLineMode.Append; } else if (modeStr.Equals("Prepend", StringComparison.OrdinalIgnoreCase)) { mode = TXTAddLineMode.Prepend; } else { throw new ExecuteException($"Mode [{modeStr}] must be one of [Append, Prepend]"); } if (StringEscaper.PathSecurityCheck(fileName, out string errorMsg) == false) { logs.Add(new LogInfo(LogState.Error, errorMsg)); return(logs); } // Detect encoding of text // If text does not exists, create blank file Encoding encoding = Encoding.Default; if (File.Exists(fileName)) { encoding = FileHelper.DetectTextEncoding(fileName); } string linesToWrite; if (mode == TXTAddLineMode.Prepend) { string tempPath = Path.GetTempFileName(); using (StreamReader reader = new StreamReader(fileName, encoding)) using (StreamWriter writer = new StreamWriter(tempPath, false, encoding)) { StringBuilder b = new StringBuilder(); for (int i = infoOp.InfoList.Count - 1; 0 <= i; i--) { b.AppendLine(StringEscaper.Preprocess(s, infoOp.InfoList[i].Line)); } linesToWrite = b.ToString(); writer.Write(linesToWrite); writer.Write(reader.ReadToEnd()); } FileHelper.FileReplaceEx(tempPath, fileName); logs.Add(new LogInfo(LogState.Success, $"Lines prepened to [{fileName}] : \r\n{linesToWrite}", cmd)); } else if (mode == TXTAddLineMode.Append) { StringBuilder b = new StringBuilder(); for (int i = 0; i < infoOp.InfoList.Count; i++) { b.AppendLine(StringEscaper.Preprocess(s, infoOp.InfoList[i].Line)); } linesToWrite = b.ToString(); bool newLineExist = true; if (File.Exists(fileName)) { using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { long bomLen = FileHelper.TextBOMLength(fs); byte[] lastChar = new byte[2]; if (2 + bomLen <= fs.Length) { fs.Position = fs.Length - 2; fs.Read(lastChar, 0, 2); if (lastChar[0] != '\r' || lastChar[1] != '\n') { newLineExist = false; } } } } if (newLineExist) { File.AppendAllText(fileName, linesToWrite, encoding); } else { File.AppendAllText(fileName, "\r\n" + linesToWrite, encoding); } logs.Add(new LogInfo(LogState.Success, $"Lines appended to [{fileName}] : \r\n{linesToWrite}", cmd)); } return(logs); }
private static CodeCommand PackCommand(CodeType type, List <CodeCommand> cmds) { Debug.Assert(0 < cmds.Count); CodeType packType; CodeInfo packInfo; switch (type) { case CodeType.TXTAddLine: packType = CodeType.TXTAddLineOp; packInfo = new CodeInfo_TXTAddLineOp(cmds); break; case CodeType.TXTReplace: packType = CodeType.TXTReplaceOp; packInfo = new CodeInfo_TXTReplaceOp(cmds); break; case CodeType.TXTDelLine: packType = CodeType.TXTDelLineOp; packInfo = new CodeInfo_TXTDelLineOp(cmds); break; case CodeType.IniRead: packType = CodeType.IniReadOp; packInfo = new CodeInfo_IniReadOp(cmds); break; case CodeType.IniWrite: packType = CodeType.IniWriteOp; packInfo = new CodeInfo_IniWriteOp(cmds); break; case CodeType.IniDelete: packType = CodeType.IniDeleteOp; packInfo = new CodeInfo_IniDeleteOp(cmds); break; case CodeType.IniReadSection: packType = CodeType.IniReadSectionOp; packInfo = new CodeInfo_IniReadSectionOp(cmds); break; case CodeType.IniAddSection: packType = CodeType.IniAddSectionOp; packInfo = new CodeInfo_IniAddSectionOp(cmds); break; case CodeType.IniDeleteSection: packType = CodeType.IniDeleteSectionOp; packInfo = new CodeInfo_IniDeleteSectionOp(cmds); break; case CodeType.IniWriteTextLine: packType = CodeType.IniWriteTextLineOp; packInfo = new CodeInfo_IniWriteTextLineOp(cmds); break; case CodeType.Visible: packType = CodeType.VisibleOp; packInfo = new CodeInfo_VisibleOp(cmds); break; case CodeType.ReadInterface: packType = CodeType.ReadInterfaceOp; packInfo = new CodeInfo_ReadInterfaceOp(cmds); break; case CodeType.WriteInterface: packType = CodeType.WriteInterfaceOp; packInfo = new CodeInfo_WriteInterfaceOp(cmds); break; case CodeType.WimExtract: packType = CodeType.WimExtractOp; packInfo = new CodeInfo_WimExtractOp(cmds); break; case CodeType.WimPathAdd: // Use WimPathAdd as representative of WimPath* packType = CodeType.WimPathOp; packInfo = new CodeInfo_WimPathOp(cmds); break; default: throw new InternalException("Internal Logic Error at CodeOptimizer.InternalOptimize"); } return(new CodeCommand(MergeRawCodes(cmds), cmds[0].Section, packType, packInfo, cmds[0].LineIdx)); }