Exemplo n.º 1
0
BOOL C4UpdatePackage::Optimize(C4Group *pGroup, const char *strTarget) {
    // Open target group
    C4GroupEx TargetGrp;
    if (!TargetGrp.Open(strTarget)) return FALSE;

    // Both groups must be packed
    if (!pGroup->IsPacked() || !TargetGrp.IsPacked()) {
        TargetGrp.Close(FALSE);
        return FALSE;
    }

    // update children
    char ItemFileName[_MAX_PATH];
    pGroup->ResetSearch();
    while (pGroup->FindNextEntry("*", ItemFileName))
        if (!SEqual(ItemFileName, C4CFN_UpdateCore) &&
                !SEqual(ItemFileName, C4CFN_UpdateEntries))
            Optimize(pGroup, &TargetGrp, ItemFileName);

    // set header
    if (TargetGrp.HeadIdentical(*pGroup, true)) TargetGrp.SetHead(*pGroup);

    // save
    TargetGrp.Close(FALSE);

    // okay
    return TRUE;
}
Exemplo n.º 2
0
BOOL C4UpdatePackage::MkUp(C4Group *pGrp1, C4Group *pGrp2, C4GroupEx *pUpGrp,
                           BOOL *fModified) {
    // (CAUTION: pGrp1 may be NULL - that means that there is no counterpart for
    // Grp2
    //           in the base group)

    // compare headers
    if (!pGrp1 || pGrp1->GetCreation() != pGrp2->GetCreation() ||
            pGrp1->GetOriginal() != pGrp2->GetOriginal() ||
            !SEqual(pGrp1->GetMaker(), pGrp2->GetMaker()) ||
            !SEqual(pGrp1->GetPassword(), pGrp2->GetPassword()))
        *fModified = TRUE;
    // set header
    pUpGrp->SetHead(*pGrp2);
    // compare entries
    char strItemName[_MAX_PATH], strItemName2[_MAX_PATH];
    StdStrBuf EntryList;
    strItemName[0] = strItemName2[0] = 0;
    pGrp2->ResetSearch();
    if (!*fModified) pGrp1->ResetSearch();
    int iChangedEntries = 0;
    while (pGrp2->FindNextEntry("*", strItemName, NULL, NULL, !!strItemName[0])) {
        // add to entry list
        if (!!EntryList) EntryList.AppendChar('|');
        EntryList.AppendFormat("%s=%d", strItemName, pGrp2->EntryTime(strItemName));
        // no modification detected yet? then check order
        if (!*fModified) {
            if (!pGrp1->FindNextEntry("*", strItemName2, NULL, NULL,
                                      !!strItemName2[0]))
                *fModified = TRUE;
            else if (!SEqual(strItemName, strItemName2))
                *fModified = TRUE;
        }

        // TODO: write DeleteEntries.txt

        // a child group?
        C4GroupEx ChildGrp2;
        if (ChildGrp2.OpenAsChild(pGrp2, strItemName)) {
            // open in Grp1
            C4Group *pChildGrp1 = new C4GroupEx();
            if (!pGrp1 || !pChildGrp1->OpenAsChild(pGrp1, strItemName)) {
                delete pChildGrp1;
                pChildGrp1 = NULL;
            }
            // open group for update data
            C4GroupEx UpdGroup;
            char strTempGroupName[_MAX_FNAME + 1];
            strTempGroupName[0] = 0;
            if (!UpdGroup.OpenAsChild(pUpGrp, strItemName)) {
                // create new group (may be temporary)
                // SCopy(GetCfg()->AtTempPath("~upd"), strTempGroupName, _MAX_FNAME);
                MakeTempFilename(strTempGroupName);
                if (!UpdGroup.Open(strTempGroupName, TRUE)) {
                    delete pChildGrp1;
                    WriteLog("Error: could not create temp group\n");
                    return FALSE;
                }
            }
            // do nested MkUp-search
            BOOL Modified = FALSE;
            BOOL fSuccess = MkUp(pChildGrp1, &ChildGrp2, &UpdGroup, &Modified);
            // sort & close
            extern const char **C4Group_SortList;
            UpdGroup.SortByList(C4Group_SortList, ChildGrp2.GetName());
            UpdGroup.Close(FALSE);
            // check entry times
            if (!pGrp1 ||
                    (pGrp1->EntryTime(strItemName) != pGrp2->EntryTime(strItemName)))
                Modified = TRUE;
            // add group (if modified)
            if (fSuccess && Modified) {
                if (strTempGroupName[0])
                    if (!pUpGrp->Move(strTempGroupName, strItemName)) {
                        WriteLog("Error: could not add modified group\n");
                        return FALSE;
                    }
                // copy core
                pUpGrp->SaveEntryCore(*pGrp2, strItemName);
                pUpGrp->SetSavedEntryCore(strItemName);
                // got a modification in a subgroup
                *fModified = TRUE;
                iChangedEntries++;
            } else
                // delete group (do not remove groups that existed before!)
                if (strTempGroupName[0])
                    if (remove(strTempGroupName))
                        if (rmdir(strTempGroupName)) {
                            WriteLog("Error: could not delete temporary directory\n");
                            return FALSE;
                        }
            delete pChildGrp1;
        } else {
            // compare them (size & crc32)
            if (!pGrp1 ||
                    pGrp1->EntrySize(strItemName) != pGrp2->EntrySize(strItemName) ||
                    pGrp1->EntryCRC32(strItemName) != pGrp2->EntryCRC32(strItemName)) {
                BOOL fCopied = FALSE;

                // save core (EntryCRC32 might set additional fields)
                pUpGrp->SaveEntryCore(*pGrp2, strItemName);

                // already in update grp?
                if (pUpGrp->EntryTime(strItemName) != pGrp2->EntryTime(strItemName) ||
                        pUpGrp->EntrySize(strItemName) != pGrp2->EntrySize(strItemName) ||
                        pUpGrp->EntryCRC32(strItemName) != pGrp2->EntryCRC32(strItemName)) {
                    // copy it
                    if (!C4Group_CopyEntry(pGrp2, pUpGrp, strItemName)) {
                        WriteLog("Error: could not add changed entry to update group\n");
                        return FALSE;
                    }
                    // set entry core
                    pUpGrp->SetSavedEntryCore(strItemName);
                    // modified...
                    *fModified = TRUE;
                    fCopied = TRUE;
                }
                iChangedEntries++;

                WriteLog("%s\\%s: update%s\n", pGrp2->GetFullName().getData(),
                         strItemName, fCopied ? "" : " (already in group)");
            }
        }
    }
    // write entries list (always)
    if (!pUpGrp->Add(C4CFN_UpdateEntries, EntryList, FALSE, TRUE)) {
        WriteLog("Error: could not save entry list!");
        return FALSE;
    }

    if (iChangedEntries > 0)
        WriteLog("%s: %d/%d changed (%s)\n", pGrp2->GetFullName().getData(),
                 iChangedEntries, pGrp2->EntryCount(),
                 *fModified ? "update" : "skip");

    // success
    return TRUE;
}
Exemplo n.º 3
0
BOOL C4UpdatePackage::MakeUpdate(const char *strFile1, const char *strFile2,
                                 const char *strUpdateFile,
                                 const char *strName) {
#ifdef UPDATE_DEBUG
    char *pData;
    int iSize;
    CStdFile MyFile;
    MyFile.Load(strFile2, (BYTE **)&pData, &iSize, 0, TRUE);
    MyFile.Create("SoIstRichtig.txt", FALSE);
    MyFile.Write(pData, iSize, FALSE);
    MyFile.Close();
    MemScramble((BYTE *)pData, iSize);
    MyFile.Create("UndSoAuch.txt", FALSE);
    MyFile.Write(pData, iSize, FALSE);
    MyFile.Close();
#endif

    // open Log
    if (!Log.Create("Update.log")) return FALSE;

    // begin message
    WriteLog("Source: %s\nTarget: %s\nOutput: %s\n\n", strFile1, strFile2,
             strUpdateFile);

    // open both groups
    C4Group Group1, Group2;
    if (!Group1.Open(strFile1)) {
        WriteLog("Error: could not open %s!\n", strFile1);
        return FALSE;
    }
    if (!Group2.Open(strFile2)) {
        WriteLog("Error: could not open %s!\n", strFile2);
        return FALSE;
    }

    // All groups to be compared need to be packed
    if (!Group1.IsPacked()) {
        WriteLog("Error: source group %s not packed!\n", strFile1);
        return FALSE;
    }
    if (!Group2.IsPacked()) {
        WriteLog("Error: target group %s not packed!\n", strFile2);
        return FALSE;
    }
    if (Group1.HasPackedMother()) {
        WriteLog("Error: source group %s must not have a packed mother group!\n",
                 strFile1);
        return FALSE;
    }
    if (Group2.HasPackedMother()) {
        WriteLog("Error: target group %s must not have a packed mother group!\n",
                 strFile2);
        return FALSE;
    }

    // create/open update-group
    C4GroupEx UpGroup;
    if (!UpGroup.Open(strUpdateFile, TRUE)) {
        WriteLog("Error: could not open %s!\n", strUpdateFile);
        return FALSE;
    }

    // may be continued update-file -> try to load core
    UpGrpCnt = 0;
    BOOL fContinued = C4UpdatePackageCore::Load(UpGroup);

    // save crc2 for later check
    unsigned int iOldChks2 = GrpChks2;

    // create core info
    if (strName)
        SCopy(strName, Name, C4MaxName);
    else
        sprintf(Name, "%s Update", GetFilename(strFile1));
    SCopy(strFile1, DestPath, _MAX_PATH);
    GrpUpdate = TRUE;
    if (!C4Group_GetFileCRC(strFile1, &GrpChks1[UpGrpCnt])) {
        WriteLog("Error: could not calc checksum for %s!\n", strFile1);
        return FALSE;
    }
    if (!C4Group_GetFileCRC(strFile2, &GrpChks2)) {
        WriteLog("Error: could not calc checksum for %s!\n", strFile2);
        return FALSE;
    }
    if (fContinued) {
        // continuation check: GrpChks2 matches?
        if (GrpChks2 != iOldChks2)
            // that would mess up the update result...
        {
            WriteLog(
                "Error: could not add to update package - target groups don't match "
                "(checksum error)\n");
            return FALSE;
        }
        // already supported by this update?
        int i = 0;
        for (; i < UpGrpCnt; i++)
            if (GrpChks1[UpGrpCnt] == GrpChks1[i]) break;
        if (i < UpGrpCnt) {
            WriteLog(
                "This update already supports the version of the source file.\n");
            return FALSE;
        }
    }

    UpGrpCnt++;

    // save core
    if (!C4UpdatePackageCore::Save(UpGroup)) {
        WriteLog("Could not save update package core!\n");
        return FALSE;
    }

    // compare groups, create update
    BOOL fModified = FALSE;
    BOOL fSuccess = MkUp(&Group1, &Group2, &UpGroup, &fModified);
    // close (save) it
    UpGroup.Close(FALSE);
    // error?
    if (!fSuccess) {
        WriteLog("Update package not created.\n");
        remove(strUpdateFile);
        return FALSE;
    }

    WriteLog("Update package created.\n");
    return TRUE;
}
Exemplo n.º 4
0
BOOL C4UpdatePackage::DoUpdate(C4Group *pGrpFrom, C4GroupEx *pGrpTo,
                               const char *strFileName) {
    // group file?
    C4Group ItemGroupFrom;
    if (ItemGroupFrom.OpenAsChild(pGrpFrom, strFileName)) {
        // try to open target group
        C4GroupEx ItemGroupTo;
        char strTempGroup[_MAX_PATH + 1];
        strTempGroup[0] = 0;
        if (!ItemGroupTo.OpenAsChild(pGrpTo, strFileName)) {
            // create (emtpy) temp dir
            //			SCopy(GetCfg()->AtExePath("~tmp"), strTempGroup,
            //_MAX_PATH);
            MakeTempFilename(strTempGroup);
            // open/create it
            if (!ItemGroupTo.Open(strTempGroup, TRUE)) return FALSE;
        }
        // update children
        char ItemFileName[_MAX_PATH];
        ItemGroupFrom.ResetSearch();
        while (ItemGroupFrom.FindNextEntry("*", ItemFileName))
            if (!SEqual(ItemFileName, C4CFN_UpdateCore) &&
                    !SEqual(ItemFileName, C4CFN_UpdateEntries))
                DoUpdate(&ItemGroupFrom, &ItemGroupTo, ItemFileName);
        // set maker (always)
        ItemGroupTo.SetMaker(ItemGroupFrom.GetMaker());
        if (GrpUpdate) {
            DoGrpUpdate(&ItemGroupFrom, &ItemGroupTo);
            // write group (do not change any headers set by DoGrpUpdate!)
            ItemGroupTo.Close(FALSE);
            // temporary group?
            if (strTempGroup[0])
                if (!pGrpTo->Move(strTempGroup, strFileName)) return FALSE;
            // set core (C4Group::Save overwrites it)
            pGrpTo->SaveEntryCore(*pGrpFrom, strFileName);
            pGrpTo->SetSavedEntryCore(strFileName);
            // flag as no-resort
            pGrpTo->SetNoSort(strFileName);
        } else {
            // write group
            ItemGroupTo.Close(TRUE);
            // temporary group?
            if (strTempGroup[0])
                if (!pGrpTo->Move(strTempGroup, strFileName)) return FALSE;
        }
    } else {
        char strMsg[1024];
        sprintf(strMsg, "updating %s\\%s\n", pGrpTo->GetFullName().getData(),
                strFileName);
#ifdef _MSC_VER
        OutputDebugString(strMsg);
#elif _DEBUG
        puts(strMsg);
#endif
        if (!C4Group_CopyEntry(pGrpFrom, pGrpTo, strFileName)) return FALSE;
        // set core
        pGrpTo->SaveEntryCore(*pGrpFrom, strFileName);
        pGrpTo->SetSavedEntryCore(strFileName);
    }
    // ok
    return TRUE;
}
Exemplo n.º 5
0
BOOL C4UpdatePackage::Execute(C4Group *pGroup) {
    // search target
    C4GroupEx TargetGrp;
    char strTarget[_MAX_PATH];
    SCopy(DestPath, strTarget, _MAX_PATH);
    char *p = strTarget, *lp = strTarget;
    while (p = strchr(p + 1, '\\')) {
        *p = 0;
        if (!*(p + 1)) break;
        if (!SEqual(lp, ".."))
            if (TargetGrp.Open(strTarget)) {
                // packed?
                bool fPacked = TargetGrp.IsPacked();
                // maker check (someone might try to unpack directories w/o asking user)
                if (fPacked)
                    if (!SEqual(TargetGrp.GetMaker(), pGroup->GetMaker())) return FALSE;
                // Close Group
                TargetGrp.Close(TRUE);
                if (fPacked)
                    // Unpack
                    C4Group_UnpackDirectory(strTarget);
            } else {
                // GrpUpdate -> file must exist
                if (GrpUpdate) return FALSE;
                // create dir
                CreateDirectory(strTarget, NULL);
            }
        *p = '\\';
        lp = p + 1;
    }

    // try to open it
    if (!TargetGrp.Open(strTarget, !GrpUpdate)) return FALSE;

    // check if the update is allowed
    if (GrpUpdate) {
        // maker must match
        /*if(!SEqual(TargetGrp.GetMaker(), pGroup->GetMaker())) - now allowing
           updates from different makers
                return FALSE;*/
        // check checksum
        uint32_t iCRC32;
        if (!C4Group_GetFileCRC(TargetGrp.GetFullName().getData(), &iCRC32))
            return FALSE;
        int i = 0;
        for (; i < UpGrpCnt; i++)
            if (iCRC32 == GrpChks1[i]) break;
        if (i >= UpGrpCnt) return FALSE;
    } else {
        // only allow Extra.c4g-Updates
        if (!SEqual2(DestPath, "Extra.c4g")) return FALSE;
    }

    // update children
    char ItemFileName[_MAX_PATH];
    pGroup->ResetSearch();
    while (pGroup->FindNextEntry("*", ItemFileName))
        if (!SEqual(ItemFileName, C4CFN_UpdateCore) &&
                !SEqual(ItemFileName, C4CFN_UpdateEntries))
            DoUpdate(pGroup, &TargetGrp, ItemFileName);

    // do GrpUpdate
    if (GrpUpdate) DoGrpUpdate(pGroup, &TargetGrp);

    // close the group
    TargetGrp.Close(FALSE);

    if (GrpUpdate) {
        // check the result
        uint32_t iResChks;
        if (!C4Group_GetFileCRC(strTarget, &iResChks)) return FALSE;
        if (iResChks != GrpChks2) {
#ifdef UPDATE_DEBUG
            char *pData;
            int iSize;
            CStdFile MyFile;
            MyFile.Load(strTarget, (BYTE **)&pData, &iSize, 0, TRUE);
            MyFile.Create("DiesesDingIstMist.txt", FALSE);
            MyFile.Write(pData, iSize, FALSE);
            MyFile.Close();
#endif
            return FALSE;
        }
    }

    return TRUE;
}