int CPatch::PatchFile(int nIndex, const CString& sPatchPath, const CString& sSavePath, const CString& sBaseFile, const bool force) { CString sPath = GetFullPath(sPatchPath, nIndex); if (PathIsDirectory(sPath)) { m_sErrorMessage.Format(IDS_ERR_PATCH_INVALIDPATCHFILE, (LPCTSTR)sPath); return FALSE; } if (nIndex < 0) { m_sErrorMessage.Format(IDS_ERR_PATCH_FILENOTINPATCH, (LPCTSTR)sPath); return FALSE; } if (!force && sPath == _T("NUL") && PathFileExists(GetFullPath(sPatchPath, nIndex, 1))) return FALSE; if (GetFullPath(sPatchPath, nIndex, 1) == _T("NUL") && !PathFileExists(sPath)) return 2; CString sLine; CString sPatchFile = sBaseFile.IsEmpty() ? sPath : sBaseFile; if (PathFileExists(sPatchFile)) { CCrashReport::Instance().AddFile2(sPatchFile, NULL, _T("File to patch"), CR_AF_MAKE_FILE_COPY); } CFileTextLines PatchLines; CFileTextLines PatchLinesResult; PatchLines.Load(sPatchFile); PatchLinesResult = PatchLines; //.Copy(PatchLines); PatchLines.CopySettings(&PatchLinesResult); Chunks * chunks = m_arFileDiffs.GetAt(nIndex); for (int i=0; i<chunks->chunks.GetCount(); i++) { Chunk * chunk = chunks->chunks.GetAt(i); LONG lRemoveLine = chunk->lRemoveStart; LONG lAddLine = chunk->lAddStart; for (int j=0; j<chunk->arLines.GetCount(); j++) { CString sPatchLine = chunk->arLines.GetAt(j); EOL ending = chunk->arEOLs[j]; if ((m_UnicodeType != CFileTextLines::UTF8)&&(m_UnicodeType != CFileTextLines::UTF8BOM)) { if ((PatchLines.GetUnicodeType()==CFileTextLines::UTF8)||(m_UnicodeType == CFileTextLines::UTF8BOM)) { // convert the UTF-8 contents in CString sPatchLine into a CStringA sPatchLine = CUnicodeUtils::GetUnicode(CStringA(sPatchLine)); } } int nPatchState = (int)chunk->arLinesStates.GetAt(j); switch (nPatchState) { case PATCHSTATE_REMOVED: { if ((lAddLine > PatchLines.GetCount())||(PatchLines.GetCount()==0)) { m_sErrorMessage.Format(IDS_ERR_PATCH_DOESNOTMATCH, _T(""), (LPCTSTR)sPatchLine); return FALSE; } if (lAddLine == 0) lAddLine = 1; if ((sPatchLine.Compare(PatchLines.GetAt(lAddLine-1))!=0)&&(!HasExpandedKeyWords(sPatchLine))) { m_sErrorMessage.Format(IDS_ERR_PATCH_DOESNOTMATCH, (LPCTSTR)sPatchLine, (LPCTSTR)PatchLines.GetAt(lAddLine-1)); return FALSE; } if (lAddLine > PatchLines.GetCount()) { m_sErrorMessage.Format(IDS_ERR_PATCH_DOESNOTMATCH, (LPCTSTR)sPatchLine, _T("")); return FALSE; } PatchLines.RemoveAt(lAddLine-1); } break; case PATCHSTATE_ADDED: { if (lAddLine == 0) lAddLine = 1; PatchLines.InsertAt(lAddLine-1, sPatchLine, ending); lAddLine++; } break; case PATCHSTATE_CONTEXT: { if (lAddLine > PatchLines.GetCount()) { m_sErrorMessage.Format(IDS_ERR_PATCH_DOESNOTMATCH, _T(""), (LPCTSTR)sPatchLine); return FALSE; } if (lAddLine == 0) lAddLine++; if (lRemoveLine == 0) lRemoveLine++; if ((sPatchLine.Compare(PatchLines.GetAt(lAddLine-1))!=0) && (!HasExpandedKeyWords(sPatchLine)) && (lRemoveLine <= PatchLines.GetCount()) && (sPatchLine.Compare(PatchLines.GetAt(lRemoveLine-1))!=0)) { if ((lAddLine < PatchLines.GetCount())&&(sPatchLine.Compare(PatchLines.GetAt(lAddLine))==0)) lAddLine++; else if (((lAddLine + 1) < PatchLines.GetCount())&&(sPatchLine.Compare(PatchLines.GetAt(lAddLine+1))==0)) lAddLine += 2; else if ((lRemoveLine < PatchLines.GetCount())&&(sPatchLine.Compare(PatchLines.GetAt(lRemoveLine))==0)) lRemoveLine++; else { m_sErrorMessage.Format(IDS_ERR_PATCH_DOESNOTMATCH, (LPCTSTR)sPatchLine, (LPCTSTR)PatchLines.GetAt(lAddLine-1)); return FALSE; } } lAddLine++; lRemoveLine++; } break; default: ASSERT(FALSE); break; } // switch (nPatchState) } // for (j=0; j<chunk->arLines.GetCount(); j++) } // for (int i=0; i<chunks->chunks.GetCount(); i++) if (!sSavePath.IsEmpty()) { PatchLines.Save(sSavePath, false); } return TRUE; }
BOOL CPatch::PatchFile(const CString& sPath, const CString& sSavePath, const CString& sBaseFile) { if (PathIsDirectory(sPath)) { m_sErrorMessage.Format(IDS_ERR_PATCH_INVALIDPATCHFILE, (LPCTSTR)sPath); return FALSE; } // find the entry in the patch file which matches the full path given in sPath. int nIndex = -1; // use the longest path that matches int nMaxMatch = 0; for (int i=0; i<GetNumberOfFiles(); i++) { CString temppath = sPath; CString temp = GetFilename(i); temppath.Replace('/', '\\'); temp.Replace('/', '\\'); if (temppath.Mid(temppath.GetLength()-temp.GetLength()-1, 1).CompareNoCase(_T("\\"))==0) { temppath = temppath.Right(temp.GetLength()); if ((temp.CompareNoCase(temppath)==0)) { if (nMaxMatch < temp.GetLength()) { nMaxMatch = temp.GetLength(); nIndex = i; } } } else if (temppath.CompareNoCase(temp)==0) { if ((nIndex < 0)&&(! temp.IsEmpty())) { nIndex = i; } } } if (nIndex < 0) { m_sErrorMessage.Format(IDS_ERR_PATCH_FILENOTINPATCH, (LPCTSTR)sPath); return FALSE; } CString sLine; CString sPatchFile = sBaseFile.IsEmpty() ? sPath : sBaseFile; if (PathFileExists(sPatchFile)) { g_crasher.AddFile((LPCSTR)(LPCTSTR)sPatchFile, (LPCSTR)(LPCTSTR)_T("File to patch")); } CFileTextLines PatchLines; CFileTextLines PatchLinesResult; PatchLines.Load(sPatchFile); PatchLinesResult = PatchLines; //.Copy(PatchLines); PatchLines.CopySettings(&PatchLinesResult); Chunks * chunks = m_arFileDiffs.GetAt(nIndex); for (int i=0; i<chunks->chunks.GetCount(); i++) { Chunk * chunk = chunks->chunks.GetAt(i); LONG lRemoveLine = chunk->lRemoveStart; LONG lAddLine = chunk->lAddStart; for (int j=0; j<chunk->arLines.GetCount(); j++) { CString sPatchLine = chunk->arLines.GetAt(j); EOL ending = chunk->arEOLs[j]; if ((m_UnicodeType != CFileTextLines::UTF8)&&(m_UnicodeType != CFileTextLines::UTF8BOM)) { if ((PatchLines.GetUnicodeType()==CFileTextLines::UTF8)||(m_UnicodeType == CFileTextLines::UTF8BOM)) { // convert the UTF-8 contents in CString sPatchLine into a CStringA sPatchLine = CUnicodeUtils::GetUnicode(CStringA(sPatchLine)); } } int nPatchState = (int)chunk->arLinesStates.GetAt(j); switch (nPatchState) { case PATCHSTATE_REMOVED: { if ((lAddLine > PatchLines.GetCount())||(PatchLines.GetCount()==0)) { m_sErrorMessage.Format(IDS_ERR_PATCH_DOESNOTMATCH, _T(""), (LPCTSTR)sPatchLine); return FALSE; } if (lAddLine == 0) lAddLine = 1; if ((sPatchLine.Compare(PatchLines.GetAt(lAddLine-1))!=0)&&(!HasExpandedKeyWords(sPatchLine))) { m_sErrorMessage.Format(IDS_ERR_PATCH_DOESNOTMATCH, (LPCTSTR)sPatchLine, (LPCTSTR)PatchLines.GetAt(lAddLine-1)); return FALSE; } if (lAddLine > PatchLines.GetCount()) { m_sErrorMessage.Format(IDS_ERR_PATCH_DOESNOTMATCH, (LPCTSTR)sPatchLine, _T("")); return FALSE; } PatchLines.RemoveAt(lAddLine-1); } break; case PATCHSTATE_ADDED: { if (lAddLine == 0) lAddLine = 1; PatchLines.InsertAt(lAddLine-1, sPatchLine, ending); lAddLine++; } break; case PATCHSTATE_CONTEXT: { if (lAddLine > PatchLines.GetCount()) { m_sErrorMessage.Format(IDS_ERR_PATCH_DOESNOTMATCH, _T(""), (LPCTSTR)sPatchLine); return FALSE; } if (lAddLine == 0) lAddLine++; if (lRemoveLine == 0) lRemoveLine++; if ((sPatchLine.Compare(PatchLines.GetAt(lAddLine-1))!=0) && (!HasExpandedKeyWords(sPatchLine)) && (lRemoveLine <= PatchLines.GetCount()) && (sPatchLine.Compare(PatchLines.GetAt(lRemoveLine-1))!=0)) { if ((lAddLine < PatchLines.GetCount())&&(sPatchLine.Compare(PatchLines.GetAt(lAddLine))==0)) lAddLine++; else if (((lAddLine + 1) < PatchLines.GetCount())&&(sPatchLine.Compare(PatchLines.GetAt(lAddLine+1))==0)) lAddLine += 2; else if ((lRemoveLine < PatchLines.GetCount())&&(sPatchLine.Compare(PatchLines.GetAt(lRemoveLine))==0)) lRemoveLine++; else { m_sErrorMessage.Format(IDS_ERR_PATCH_DOESNOTMATCH, (LPCTSTR)sPatchLine, (LPCTSTR)PatchLines.GetAt(lAddLine-1)); return FALSE; } } lAddLine++; lRemoveLine++; } break; default: ASSERT(FALSE); break; } // switch (nPatchState) } // for (j=0; j<chunk->arLines.GetCount(); j++) } // for (int i=0; i<chunks->chunks.GetCount(); i++) if (!sSavePath.IsEmpty()) { PatchLines.Save(sSavePath, false); } return TRUE; }