Ejemplo n.º 1
0
NPK_RESULT npk_package_add_file( NPK_PACKAGE package, NPK_CSTR filename, NPK_CSTR entityname, NPK_ENTITY* lpEntity )
{
    NPK_ENTITYBODY* eb;
    NPK_CSTR __entityname;
    NPK_RESULT res;
    NPK_CHAR namebuf[512];

    if( ( res = npk_entity_alloc( (NPK_ENTITY*)&eb ) ) != NPK_SUCCESS )
        return res;

    if( entityname == NULL )
    {
        __entityname = NULL;

        if( ( entityname = strrchr( filename, '\\' ) ) == NULL )
            if( ( entityname = strrchr( filename, '/' ) ) == NULL )
                __entityname = filename;

        if( __entityname == NULL )
            __entityname = entityname + sizeof(NPK_CHAR);
    }
    else
        __entityname = entityname;

    if( ( res = npk_prepare_entityname( __entityname, namebuf, 512) ) != NPK_SUCCESS )
        goto npk_package_add_file_return_with_error;

    if( ( res = npk_get_filetime( filename, &eb->info_.modified_ ) ) != NPK_SUCCESS )
        goto npk_package_add_file_return_with_error;

    if( ( res = npk_alloc_copy_string( &eb->localname_, filename ) ) != NPK_SUCCESS )
        goto npk_package_add_file_return_with_error;

    if( ( res = npk_alloc_copy_string( &eb->name_, namebuf ) ) != NPK_SUCCESS )
        goto npk_package_add_file_return_with_error;

    eb->info_.nameLength_ = (NPK_SIZE)strlen( eb->name_ );

    if( ( res = npk_package_add_entity( package, eb ) ) != NPK_SUCCESS )
        goto npk_package_add_file_return_with_error;

    if( lpEntity )
        *lpEntity = eb;

    return NPK_SUCCESS;

npk_package_add_file_return_with_error:
    NPK_SAFE_FREE( eb );
    return res;
}
Ejemplo n.º 2
0
Archivo: npk.c Proyecto: keedi/npk
NPK_RESULT __npk_package_open( NPK_PACKAGEBODY* pb, const NPK_CHAR* filename, long filesize, NPK_TEAKEY teakey[4] )
{
    NPK_CHAR            buf[512];
    NPK_ENTITYBODY*     eb = NULL;
    NPK_ENTITYINFO_V21  oldinfo;
    NPK_SIZE            entityCount = 0;
    NPK_CHAR*           entityheaderbuf;
    NPK_CHAR*           pos;
    long                entityheadersize = 0;
    NPK_RESULT          res;

    if( filesize == 0 )
    {
        filesize = npk_seek( pb->handle_, 0, SEEK_END );
        npk_seek( pb->handle_, 0, SEEK_SET );
    }

    if( filesize < sizeof(NPK_PACKAGEINFO) )
        return( npk_error( NPK_ERROR_PackageIsNotReady ) );

    // Read common header
    res = npk_read( pb->handle_,
                    (void*)&pb->info_,
                    sizeof(NPK_PACKAGEINFO),
                    g_callbackfp,
                    NPK_PROCESSTYPE_PACKAGEHEADER,
                    g_callbackSize,
                    filename );
    if( res != NPK_SUCCESS ) return res;

    if( strncmp( pb->info_.signature_, NPK_SIGNATURE, 4 ) != 0 )
        if( strncmp( pb->info_.signature_, NPK_OLD_SIGNATURE, 4 ) != 0 )
            return( npk_error( NPK_ERROR_NotValidPackage ) );

    // version 18 / read own tea key
    if( pb->info_.version_ < NPK_VERSION_REFACTORING )
    {
        return ( npk_error( NPK_ERROR_NotSupportedVersion ) );
    }
    else
    {
        if( teakey == NULL )
        {
            return ( npk_error( NPK_ERROR_NeedSpecifiedTeaKey ) );
        }
        memcpy( pb->teakey_, teakey, sizeof(NPK_TEAKEY) * 4 );
    }

    // version 23 / package timestamp
    if( pb->info_.version_ >= NPK_VERSION_PACKAGETIMESTAMP )
    {
        res = npk_read( pb->handle_,
                        (void*)&pb->modified_,
                        sizeof(NPK_TIME),
                        g_callbackfp,
                        NPK_PROCESSTYPE_PACKAGEHEADER,
                        g_callbackSize,
                        filename );
        if( res != NPK_SUCCESS ) return res;
    }

    entityCount = pb->info_.entityCount_;
    pb->info_.entityCount_ = 0;

    if( pb->info_.version_ >= NPK_VERSION_SINGLEPACKHEADER )
    {
        if( pb->info_.version_ >= NPK_VERSION_STREAMABLE )
        {
            if( filesize < (long)pb->info_.entityDataOffset_ )
                return( npk_error( NPK_ERROR_PackageIsNotReady ) );
            entityheadersize = (long)pb->info_.entityDataOffset_ - (long)pb->info_.entityInfoOffset_;
        }
        else
        {
            entityheadersize = filesize - (long)pb->info_.entityInfoOffset_;
            npk_seek( pb->handle_, (long)pb->info_.entityInfoOffset_+pb->offsetJump_, SEEK_SET );
        }

        entityheaderbuf = malloc( entityheadersize );
        if( !entityheaderbuf )
            return( npk_error( NPK_ERROR_NotEnoughMemory ) );

        res = npk_read_encrypt( teakey,
                                pb->handle_,
                                (void*)entityheaderbuf,
                                entityheadersize,
                                g_callbackfp,
                                NPK_PROCESSTYPE_ENTITYHEADER,
                                g_callbackSize,
                                filename,
                                pb->info_.version_ >= NPK_VERSION_ENCRYPTREMAINS,
                                pb->info_.version_ >= NPK_VERSION_USEXXTEAONHEADER
                                );
        if( res != NPK_SUCCESS ) return res;

        pos = entityheaderbuf;
        
        while( entityCount > 0 )
        {
            --entityCount;

            res = npk_entity_alloc( (NPK_ENTITY*)&eb );
            if( res != NPK_SUCCESS )
                goto __npk_package_open_return_res_with_free;

            eb->owner_ = pb;
            memcpy( &eb->info_, pos, sizeof(NPK_ENTITYINFO) );
            pos += sizeof(NPK_ENTITYINFO);

            if( pb->info_.version_ < NPK_VERSION_STREAMABLE )
                if( eb->info_.offset_ >= pb->info_.entityInfoOffset_ )
                {
                    res = npk_error( NPK_ERROR_InvalidTeaKey );
                    goto __npk_package_open_return_res_with_free;
                }

            eb->newflag_ = eb->info_.flag_;
            eb->name_ = malloc( sizeof(NPK_CHAR)*(eb->info_.nameLength_+1) );
            if( !eb->name_ )
            {
                res = npk_error( NPK_ERROR_NotEnoughMemory );
                goto __npk_package_open_return_res_with_free;
            }
            eb->name_[eb->info_.nameLength_] = '\0';
            memcpy( eb->name_, pos, eb->info_.nameLength_ );
            pos += eb->info_.nameLength_;

            __npk_package_add_entity( pb, eb, false );
        }
        NPK_SAFE_FREE( entityheaderbuf );
    }
    else    // old style entity header
    {
        npk_seek( pb->handle_, (long)pb->info_.entityInfoOffset_+pb->offsetJump_, SEEK_SET );
        while( entityCount > 0 )
        {
            --entityCount;

            res = npk_entity_alloc( (NPK_ENTITY*)&eb );
            if( res != NPK_SUCCESS )
                goto __npk_package_open_return_res_with_free;

            eb->owner_ = pb;

            // read entity info
            if( pb->info_.version_ < NPK_VERSION_UNIXTIMESUPPORT )
            {
                res = npk_read_encrypt( teakey,
                                        pb->handle_,
                                        (void*)&oldinfo,
                                        sizeof(NPK_ENTITYINFO),
                                        g_callbackfp,
                                        NPK_PROCESSTYPE_ENTITYHEADER,
                                        g_callbackSize,
                                        filename,
                                        false,
                                        false );
                if( res != NPK_SUCCESS )
                    goto __npk_package_open_return_res_with_free;

                eb->info_.offset_ = oldinfo.offset_;
                eb->info_.size_ = oldinfo.size_;
                eb->info_.originalSize_ = oldinfo.originalSize_;
                eb->info_.flag_ = oldinfo.flag_;
                npk_filetime_to_unixtime( &oldinfo.modified_, &eb->info_.modified_ );
                eb->info_.nameLength_ = oldinfo.nameLength_;
            }
            else
            {
                res = npk_read_encrypt( teakey,
                                        pb->handle_,
                                        (void*)&eb->info_,
                                        sizeof(NPK_ENTITYINFO),
                                        g_callbackfp,
                                        NPK_PROCESSTYPE_ENTITYHEADER,
                                        g_callbackSize,
                                        filename,
                                        false,
                                        false );
                if( res != NPK_SUCCESS )
                    goto __npk_package_open_return_res_with_free;
            }

            if( eb->info_.offset_ >= pb->info_.entityInfoOffset_ )
            {
                res = npk_error( NPK_ERROR_InvalidTeaKey );
                goto __npk_package_open_return_res_with_free;
            }

            
            res = npk_read_encrypt( teakey,
                                    pb->handle_,
                                    (void*)buf,
                                    sizeof(char) * eb->info_.nameLength_,
                                    g_callbackfp,
                                    NPK_PROCESSTYPE_ENTITYHEADER,
                                    g_callbackSize,
                                    filename,
                                    false,
                                    false );
            if( res != NPK_SUCCESS )
                goto __npk_package_open_return_res_with_free;

            eb->newflag_ = eb->info_.flag_;

            // copy name into entity body
            buf[eb->info_.nameLength_] = '\0';
            res = npk_alloc_copy_string( &eb->name_, buf );
            if( res != NPK_SUCCESS )
                goto __npk_package_open_return_res_with_free;

            __npk_package_add_entity( pb, eb, false );
        }
    }
    return NPK_SUCCESS;

__npk_package_open_return_res_with_free:

    NPK_SAFE_FREE( eb );
    return res;
}
Ejemplo n.º 3
0
NPK_RESULT npk_package_save( NPK_PACKAGE package, NPK_CSTR filename, bool forceoverwrite )
{
    NPK_PACKAGEBODY*    pb = package;
    NPK_ENTITYBODY*     eb = NULL;
    NPK_RESULT          res;
    bool                bUseTemporaryFile = false;
    NPK_SIZE            len;
    int                 savecount = 0;
    NPK_STR             savefilename = NULL;
    int                 savefilehandle;
    NPK_CHAR*           buf;
    NPK_CHAR*           buf_pos;
    NPK_PACKAGEINFO_V23 header_v23;

    if( !package )
        return npk_error( NPK_ERROR_PackageIsNull );

    if( !filename )
        return npk_error( NPK_ERROR_PackageHasNoName );

    if( ( res = npk_open( &savefilehandle, filename, true, true ) ) == NPK_SUCCESS )
    {
        npk_alloc_copy_string( &savefilename, filename );
    }
    else
    {
        if( res != NPK_ERROR_FileAlreadyExists )
            return res;

        if( !forceoverwrite )
            return res;

        len = (NPK_SIZE)strlen( filename );
        savefilename = malloc( sizeof(NPK_CHAR)*(len+2) );
        if( savefilename == NULL )
            return( npk_error( NPK_ERROR_NotEnoughMemory ) );

        strncpy( savefilename, filename, len );
        savefilename[len+0] = '_';
        savefilename[len+1] = '\0';
        bUseTemporaryFile = true;

        if( ( res = npk_open( &savefilehandle, savefilename, true, false ) ) != NPK_SUCCESS )
            return res;
    }

    strncpy( pb->info_.signature_, NPK_SIGNATURE, sizeof(NPK_CHAR)*4 );
    pb->info_.version_ = NPK_VERSION_CURRENT;
    pb->info_.entityDataOffset_ = sizeof(NPK_PACKAGEINFO)
                                + sizeof(NPK_PACKAGEINFO_V23);

    npk_seek( savefilehandle, (long)pb->info_.entityDataOffset_, SEEK_SET );

    eb = pb->pEntityHead_;
    while( eb != NULL )
    {
        if( g_callbackfp )
            if( (g_callbackfp)( NPK_ACCESSTYPE_WRITE, NPK_PROCESSTYPE_PACKAGE, filename, savecount, pb->info_.entityCount_ ) == false )
                return( npk_error( NPK_ERROR_CancelByCallback ) );

        npk_entity_write( eb, savefilehandle );
        ++savecount;
        eb = eb->next_;
    }

    pb->info_.entityInfoOffset_ = npk_tell( savefilehandle );
    pb->info_.entityCount_ = savecount;

    eb = pb->pEntityHead_;

    // version 24, Take single encryption to whole entity headers
    buf = malloc( (sizeof(NPK_ENTITYINFO)+260)*savecount ); // 260 = MAX_PATH on windows, isn't it enough?
    if( !buf )
        return( npk_error( NPK_ERROR_NotEnoughMemory ) );
    buf_pos = buf;

    while( eb != NULL )
    {
        memcpy( buf_pos, &eb->info_, sizeof(NPK_ENTITYINFO) );
        buf_pos += sizeof(NPK_ENTITYINFO);
        memcpy( buf_pos, eb->name_, sizeof(NPK_CHAR)*eb->info_.nameLength_ );
        buf_pos += sizeof(NPK_CHAR)*eb->info_.nameLength_;
        eb = eb->next_;
    }
    if( ( res = npk_write_encrypt( pb->teakey_,
                            savefilehandle,
                            buf,
                            buf_pos - buf,
                            g_callbackfp,
                            NPK_PROCESSTYPE_ENTITYHEADER,
                            g_callbackSize,
                            savefilename ) ) != NPK_SUCCESS )
        return res;
    NPK_SAFE_FREE( buf );

    npk_seek( savefilehandle, 0, SEEK_SET );
    if( ( res = npk_write( savefilehandle,
                    &pb->info_,
                    sizeof(NPK_PACKAGEINFO),
                    g_callbackfp,
                    NPK_PROCESSTYPE_PACKAGEHEADER,
                    g_callbackSize,
                    savefilename ) ) != NPK_SUCCESS )
        return res;

    // version 23, Write the package timestamp for other applications
    // TODO:reveal the return type of 'time' function on 64bit mac os
    time( (time_t*)&header_v23.modified_ );

    if( ( res = npk_write( savefilehandle,
                    &header_v23,
                    sizeof(NPK_PACKAGEINFO_V23),
                    g_callbackfp,
                    NPK_PROCESSTYPE_PACKAGEHEADER,
                    g_callbackSize,
                    savefilename ) ) != NPK_SUCCESS )
        return res;

    npk_flush( savefilehandle );
    npk_close( pb->handle_ );

    if( bUseTemporaryFile )
    {
        npk_close( savefilehandle );
        remove( filename );
        rename( savefilename, filename );

        if( (res = npk_open( &pb->handle_, filename, false, false ) ) != NPK_SUCCESS )
            return res;
    }
    else
    {
        pb->handle_ = savefilehandle;
    }
    NPK_SAFE_FREE( savefilename );
    return NPK_SUCCESS;
}