From: dan Date: Tue, 27 Feb 2018 19:50:28 +0000 (+0000) Subject: Rationalize some code in zonefile.c. Fix other minor issues in the same. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f736acd40cab2e136808bdd0f0dea6c288298468;p=thirdparty%2Fsqlite.git Rationalize some code in zonefile.c. Fix other minor issues in the same. FossilOrigin-Name: f11beb16a87cc967e896cf67121b1e4045e427ebdc6a424e9f009ffced955d36 --- diff --git a/ext/zonefile/README.md b/ext/zonefile/README.md index b91a4553f9..ffbf2049cf 100644 --- a/ext/zonefile/README.md +++ b/ext/zonefile/README.md @@ -55,7 +55,14 @@ except for "zstd_global_dict", are also valid for this option. encryptionType"none" The encryption type to use. At present the only valid values are "none" (no encryption) and "xor" (an insecure mock encryption method -useful for testing only). +useful for testing only). Enhanced implementations may support any or +all of the following encryption schemes: + encryptionKey"" The encryption key to use. The encryption key must be specified as an @@ -89,7 +96,7 @@ named "z1", with a schema equivalent to: > CREATE TABLE z1( -- this whole table is read-only > k INTEGER PRIMARY KEY, -- key value > v BLOB, -- associated blob of data -> file TEXT, -- file this key is read from +> fileid INTEGER, -- file id (rowid value for z1_files) > sz INTEGER -- size of blob of data in bytes > ); @@ -98,7 +105,6 @@ And a read-write table named "z1_files" with a schema like: > CREATE TABLE z1_files( > filename TEXT PRIMARY KEY, > ekey BLOB, -- encryption key -> fileid INTEGER, -- read-only > header JSON HIDDEN -- read-only > ); diff --git a/ext/zonefile/zonefile.c b/ext/zonefile/zonefile.c index 656aa2324f..f98d35c8e2 100644 --- a/ext/zonefile/zonefile.c +++ b/ext/zonefile/zonefile.c @@ -334,10 +334,10 @@ static int zonefileKeyStore( /* ** Search the key-store passed as the first argument for an encryption ** key to use with the file with file-id iFileid in zonefile table zTab -** in database zDb. If successful, set (*pzKey) to point to the key +** in database zDb. If successful, set (*paKey) to point to the key ** buffer and return the size of the key in bytes. ** -** If no key is found, return 0. The final value of (*pzKey) is undefined +** If no key is found, return 0. The final value of (*paKey) is undefined ** in this case. */ static int zonefileKeyFind( @@ -693,6 +693,14 @@ static struct ZonefileCompress { #endif /* SQLITE_HAVE_LZ4 */ }; +/* +** Find the ZonefileCompress object for the compression scheme named +** by zName. If successful, set output variable (*pp) to point to the +** object and return SQLITE_OK. Otherwise, return SQLITE_ERROR and +** leave output variable (*pzErr) pointing to an English language error +** message. It is the reponsibility of the caller to eventually free +** the error message buffer using sqlite3_free(). +*/ static int zonefileCompress( const char *zName, /* Name of requested compression method */ ZonefileCompress **pp, /* OUT: Pointer to compression object */ @@ -710,6 +718,13 @@ static int zonefileCompress( return SQLITE_ERROR; } +/* +** Find a compression routine based on its associated integer constant +** (defined as part of the zonefile file format). If successful, return +** a pointer to the associated ZonefileCompression object. Or, if the +** nominated compression scheme is not supported in this build, return +** NULL. +*/ static ZonefileCompress *zonefileCompressByValue(int eType){ int i; for(i=0; imaxAutoFrameSize = ZONEFILE_DEFAULT_MAXAUTOFRAMESIZE; p->encryptionType = ZONEFILE_DEFAULT_ENCRYPTION; - p->pCmpData = p->pCmpIdx = zonefileCompressByValue(0); + p->pCmpData = p->pCmpIdx = zonefileCompressByValue(ZONEFILE_COMPRESSION_NONE); rc = zonefilePrepare(db, &pStmt, &zErr,"SELECT key, value FROM json_each(?)"); if( rc==SQLITE_OK ){ @@ -983,11 +1037,18 @@ static int zonefileBufferGrow( return SQLITE_OK; } +/* +** Free the memory allocation associated with buffer pBuf. +*/ static void zonefileBufferFree(ZonefileBuffer *pBuf){ sqlite3_free(pBuf->a); memset(pBuf, 0, sizeof(ZonefileBuffer)); } +/* +** Read and return a 64-bit unsigned integer in big-endian format from +** buffer aBuf. +*/ static u64 zonefileGet64(u8 *aBuf){ return (((u64)aBuf[0]) << 56) + (((u64)aBuf[1]) << 48) @@ -999,35 +1060,67 @@ static u64 zonefileGet64(u8 *aBuf){ + (((u64)aBuf[7]) << 0); } +/* +** Append a 32-bit big-endian integer with value v to buffer pBuf. Space +** must have already been reserved in the buffer using zonefileBufferGrow(). +*/ static void zonefileAppend32(ZonefileBuffer *pBuf, u32 v){ zonefilePut32(&pBuf->a[pBuf->n], v); pBuf->n += 4; } +/* +** Append a 64-bit big-endian integer with value v to buffer pBuf. Space +** must have already been reserved in the buffer using zonefileBufferGrow(). +*/ static void zonefileAppend64(ZonefileBuffer *pBuf, u64 v){ zonefileAppend32(pBuf, v>>32); zonefileAppend32(pBuf, v & 0xFFFFFFFF); } +/* +** Append the n bytse of data in buffer p to buffer pBuf. Space must have +** already been reserved in the buffer using zonefileBufferGrow(). +*/ static void zonefileAppendBlob(ZonefileBuffer *pBuf, const u8 *p, int n){ memcpy(&pBuf->a[pBuf->n], p, n); pBuf->n += n; } +/* +** Write nBuf bytes of data from buffer aBuf to the file opened by +** file-handle pFd. Return SQLITE_OK if successful, or SQLITE_ERROR +** otherwise. +*/ static int zonefileFileWrite(FILE *pFd, const u8 *aBuf, int nBuf){ size_t res = fwrite(aBuf, 1, nBuf, pFd); return res!=(size_t)nBuf ? SQLITE_ERROR : SQLITE_OK; } +/* +** Read nBuf bytes of data from offset iOff of the file opened by +** file-handle pFd into buffer aBuf. Return SQLITE_OK if successful, or +** SQLITE_ERROR otherwise. +*/ static int zonefileFileRead(FILE *pFd, u8 *aBuf, int nBuf, i64 iOff){ int rc = fseek(pFd, (long)iOff, SEEK_SET); if( rc==0 ){ rc = fread(aBuf, 1, nBuf, pFd); rc = (rc==nBuf) ? SQLITE_OK : SQLITE_ERROR; + }else{ + rc = SQLITE_ERROR; } return rc; } +/* +** Open the file identified by path zFile for writing (if bWrite==1) or +** reading (if bWrite==0). If successful, return a pointer to the new +** file-handle object. Otherwise, return NULL and set output variable +** (*pzErr) to point to a buffer containing an English language error +** message. It is the responsibility of the caller to eventually free +** any error message buffer using sqlite3_free(). +*/ static FILE *zonefileFileOpen(const char *zFile, int bWrite, char **pzErr){ FILE *pFd = fopen(zFile, bWrite ? "wb" : "rb"); if( pFd==0 ){ @@ -1038,10 +1131,23 @@ static FILE *zonefileFileOpen(const char *zFile, int bWrite, char **pzErr){ return pFd; } +/* +** Close the file handle passed as the only argument. +*/ static void zonefileFileClose(FILE *pFd){ if( pFd ) fclose(pFd); } +/* +** Append the contents of buffer pFrom to buffer pTo. If successful, return +** SQLITE_OK. Otherwise, return an SQLite error code and leave an error +** message in context object pCtx. +** +** If argument pMethod is not NULL, then it is used along with pCmp to +** compress the data before appending it to pFrom. Similarly, if argument +** pCodec is not NULL, then it is used to encrypt the data before it is +** appended. +*/ static int zonefileAppendData( sqlite3_context *pCtx, /* Leave any error message here */ ZonefileCompress *pMethod, /* Compression method object */ @@ -1095,6 +1201,10 @@ static int zonefilePad(FILE *pFd, int nByte){ return SQLITE_OK; } +/* +** If character c is not a hexadecimal digit, return -1. Otherwise, return +** the value of the hex digit (a value between 0 and 15). +*/ static int zonefileHexChar(char c){ if( c>='0' && c<='9' ) return c-'0'; c = c & ~0x20; @@ -1102,6 +1212,20 @@ static int zonefileHexChar(char c){ return -1; } +/* +** String ZonefileParam.encryptionKey currently contains a string specified +** for the encryptionKey attribute of a JSON object passed to SQL function +** zonefile_write(). The string is (*pn) bytes in size. +** +** If the ZonefileParam.debugEncryptionKeyText flag is true this function +** is a no-op. Otherwise, an attempt is made to overwrite the hex string in +** ZonefileParam.encryptionKey with the corresponding binary data. If +** successful, SQLITE_OK is returned and (*pn) is set to the number of +** bytes in the binary key. Otherwise, if an error occurs, an SQLite error +** code is returned and (*pzErr) set to point to an English language error +** message. It is the responsibility of the caller to eventually free any +** error message buffer using sqlite3_free(). +*/ static int zonefileDecodeEncryptionKey(ZonefileParam *p, int *pn, char **pzErr){ if( p->debugEncryptionKeyText==0 ){ u8 *z = (u8*)p->encryptionKey; @@ -1383,6 +1507,9 @@ static void zonefileWriteFunc( } } +/* +** Virtual table type for zonefile_files virtual tables. +*/ typedef struct ZonefileFilesTab ZonefileFilesTab; struct ZonefileFilesTab { sqlite3_vtab base; /* Base class - must be first */ @@ -1396,6 +1523,9 @@ struct ZonefileFilesTab { sqlite3_stmt *pDelete; /* Delete by rowid from %_shadow_file table */ }; +/* +** Virtual table cursor type for zonefile_files virtual tables. +*/ typedef struct ZonefileFilesCsr ZonefileFilesCsr; struct ZonefileFilesCsr { sqlite3_vtab_cursor base; /* Base class - must be first */ @@ -1575,6 +1705,10 @@ static int zffEof(sqlite3_vtab_cursor *cur){ return pCsr->pSelect==0; } +/* +** Deserialize the ZONEFILE_SZ_HEADER byte zonefile header in the +** buffer. Populate (*pHdr) with the results. +*/ static void zonefileHeaderDeserialize(u8 *aBuf, ZonefileHeader *pHdr){ pHdr->magicNumber = zonefileGet32(&aBuf[0]); pHdr->compressionTypeIndexData = aBuf[4]; @@ -1589,58 +1723,95 @@ static void zonefileHeaderDeserialize(u8 *aBuf, ZonefileHeader *pHdr){ pHdr->extendedHeaderSize = aBuf[25]; } +/* +** Read and decode a Zonefile header from the start of the file opened +** by file-handle pFd. If successful, populate object (*pHdr) before +** returning SQLITE_OK. Otherwise, if an error occurs, set output +** parameter (*pzErr) to point to an English language error message and +** return an SQLite error code. +** +** It is the responsibility of the caller to eventually free any error +** message returned via (*pzErr) using sqlite3_free(). +*/ +static int zonefileReadHeader( + FILE *pFd, /* File to read from */ + const char *zFile, /* Name of file opened by pFd */ + ZonefileHeader *pHdr, /* Populate this object before returning */ + char **pzErr /* OUT: Error message */ +){ + u8 aBuf[ZONEFILE_SZ_HEADER]; + int rc = zonefileFileRead(pFd, aBuf, ZONEFILE_SZ_HEADER, 0); + if( rc==SQLITE_OK ){ + zonefileHeaderDeserialize(aBuf, pHdr); + if( pHdr->magicNumber!=ZONEFILE_MAGIC_NUMBER ){ + rc = SQLITE_ERROR; + } + } + + if( rc!=SQLITE_OK ){ + *pzErr = sqlite3_mprintf( + "failed to read zonefile header from file \"%s\"", zFile + ); + } + + return rc; +} + +/* +** Read the zonefile header from file zFile and set the result of pCtx +** to a JSON object that represents the contents. Or, if an error occurs, +** leave an error message in pCtx. This function is called whenever the +** "header" column of a zonefile_files virtual table is requested. +*/ static void zonefileJsonHeader(sqlite3_context *pCtx, const char *zFile){ char *zErr = 0; + int rc = SQLITE_OK; + ZonefileHeader hdr = {0}; + FILE *pFd = zonefileFileOpen(zFile, 0, &zErr); if( pFd ){ - int rc; - ZonefileHeader hdr = { 0 }; - u8 aBuf[ZONEFILE_SZ_HEADER]; - - rc = zonefileFileRead(pFd, aBuf, ZONEFILE_SZ_HEADER, 0); - if( rc==SQLITE_OK ){ - zonefileHeaderDeserialize(aBuf, &hdr); - } + rc = zonefileReadHeader(pFd, zFile, &hdr, &zErr); + }else{ + rc = SQLITE_ERROR; + } - if( rc!=SQLITE_OK ){ - zonefileCtxError(pCtx, "failed to read header from file: \"%s\"", zFile); + if( rc==SQLITE_OK ){ + char *zJson = sqlite3_mprintf("{" + "\"magicNumber\":%u," + "\"compressionTypeIndexData\":%u," + "\"compressionTypeContent\":%u," + "\"byteOffsetDictionary\":%u," + "\"byteOffsetFrames\":%u," + "\"numFrames\":%u," + "\"numKeys\":%u," + "\"encryptionType\":%u," + "\"encryptionKeyIdx\":%u," + "\"extendedHeaderVersion\":%u," + "\"extendedHeaderSize\":%u}", + (u32)hdr.magicNumber, + (u32)hdr.compressionTypeIndexData, + (u32)hdr.compressionTypeContent, + (u32)hdr.byteOffsetDictionary, + (u32)hdr.byteOffsetFrames, + (u32)hdr.numFrames, + (u32)hdr.numKeys, + (u32)hdr.encryptionType, + (u32)hdr.encryptionKeyIdx, + (u32)hdr.extendedHeaderVersion, + (u32)hdr.extendedHeaderSize + ); + if( zJson ){ + sqlite3_result_text(pCtx, zJson, -1, SQLITE_TRANSIENT); + sqlite3_free(zJson); }else{ - char *zJson = sqlite3_mprintf("{" - "\"magicNumber\":%u," - "\"compressionTypeIndexData\":%u," - "\"compressionTypeContent\":%u," - "\"byteOffsetDictionary\":%u," - "\"byteOffsetFrames\":%u," - "\"numFrames\":%u," - "\"numKeys\":%u," - "\"encryptionType\":%u," - "\"encryptionKeyIdx\":%u," - "\"extendedHeaderVersion\":%u," - "\"extendedHeaderSize\":%u}", - (u32)hdr.magicNumber, - (u32)hdr.compressionTypeIndexData, - (u32)hdr.compressionTypeContent, - (u32)hdr.byteOffsetDictionary, - (u32)hdr.byteOffsetFrames, - (u32)hdr.numFrames, - (u32)hdr.numKeys, - (u32)hdr.encryptionType, - (u32)hdr.encryptionKeyIdx, - (u32)hdr.extendedHeaderVersion, - (u32)hdr.extendedHeaderSize - ); - if( zJson ){ - sqlite3_result_text(pCtx, zJson, -1, SQLITE_TRANSIENT); - sqlite3_free(zJson); - }else{ - sqlite3_result_error_nomem(pCtx); - } + sqlite3_result_error_nomem(pCtx); } - fclose(pFd); }else{ sqlite3_result_error(pCtx, zErr, -1); sqlite3_free(zErr); } + + zonefileFileClose(pFd); } /* @@ -1677,44 +1848,22 @@ static int zffRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ } /* -** Read and decode a Zonefile header from the start of the file opened -** by file-handle pFd. If successful, populate object (*pHdr) before -** returning SQLITE_OK. Otherwise, if an error occurs, set output -** parameter (*pzErr) to point to an English language error message and -** return an SQLite error code. +** Uncompress buffer aIn/nIn using the compression routines pMethod +** and the compressor instance pCmp into space obtained from +** sqlite3_malloc(). If successful, return SQLITE_OK and set output +** parameters (*paOut) and (*pnOut) to point to the allocated buffer +** and its size in bytes respectively. In this case it is the +** responsibility of the caller to eventually free buffer (*paOut) +** using sqlite3_free(). ** -** It is the responsibility of the caller to eventually free any error -** message returned via (*pzErr) using sqlite3_free(). +** Or, if an error occurs, set both output parameters to zero and +** return an SQLite error code. */ -static int zonefileReadHeader( - FILE *pFd, /* File to read from */ - const char *zFile, /* Name of file opened by pFd */ - ZonefileHeader *pHdr, /* Populate this object before returning */ - char **pzErr /* OUT: Error message */ -){ - u8 aBuf[ZONEFILE_SZ_HEADER]; - int rc = zonefileFileRead(pFd, aBuf, ZONEFILE_SZ_HEADER, 0); - if( rc==SQLITE_OK ){ - zonefileHeaderDeserialize(aBuf, pHdr); - if( pHdr->magicNumber!=ZONEFILE_MAGIC_NUMBER ){ - rc = SQLITE_ERROR; - } - } - - if( rc!=SQLITE_OK ){ - *pzErr = sqlite3_mprintf( - "failed to read zonefile header from file \"%s\"", zFile - ); - } - - return rc; -} - static int zonefileUncompress( - ZonefileCompress *pMethod, - void *pCmp, - u8 *aIn, int nIn, - u8 **paOut, int *pnOut + ZonefileCompress *pMethod, /* Compression routines */ + void *pCmp, /* Compressor instance */ + u8 *aIn, int nIn, /* Input buffer */ + u8 **paOut, int *pnOut /* Output buffer */ ){ int rc; int nOut = pMethod->xUncompressSize(pCmp, aIn, nIn); @@ -1736,7 +1885,16 @@ static int zonefileUncompress( return rc; } -static int zfFindCompress(int eType, ZonefileCompress **pp, char **pzErr){ +/* +** Attempt to find the compression methods object for the compression method +** identified by integer constant eType (defined as part of the zonefile file +** format). If successful, set output parameter (*pp) to point to the object +** and return SQLITE_OK. Otherwise, return an SQLite error code and set +** (*pzErr) to point to a buffer containing an English language error +** message. It is the responsibility of the caller to eventually free any +** error message buffer using sqlite3_free(). +*/ +static int zonefileFindCompress(int eType, ZonefileCompress **pp, char **pzErr){ int rc = SQLITE_OK; ZonefileCompress *pCmp; pCmp = zonefileCompressByValue(eType); @@ -1750,18 +1908,31 @@ static int zfFindCompress(int eType, ZonefileCompress **pp, char **pzErr){ return rc; } +/* +** Argument pHdr points to a deserialized zonefile header read from the +** zonefile opened by file handle pFd. This function attempts to read +** the entire zonefile-index structure into space obtained from +** sqlite3_malloc(). If successful, it sets output parameters (*paIdx) +** and (*pnIdx) to point to the buffer and its size in bytes respectively +** before returning SQLITE_OK. +** +** Otherwise, if an error occurs, an SQLite error code is returned and +** output parameter (*pzErr) may be set to point to a buffer containing an +** English language error message. It is the responsibility of the caller to +** eventually free any error message buffer using sqlite3_free(). +*/ static int zonefileLoadIndex( - ZonefileHeader *pHdr, - FILE *pFd, - u8 **paIdx, int *pnIdx, - char **pzErr + ZonefileHeader *pHdr, /* Deserialized header read from file */ + FILE *pFd, /* File to read from */ + u8 **paIdx, int *pnIdx, /* OUT: Buffer containing zonefile index */ + char **pzErr /* OUT: Error message */ ){ ZonefileCompress *pCmp = 0; int rc; u8 *aIdx = 0; int nIdx = 0; - rc = zfFindCompress(pHdr->compressionTypeIndexData, &pCmp, pzErr); + rc = zonefileFindCompress(pHdr->compressionTypeIndexData, &pCmp, pzErr); if( rc==SQLITE_OK ){ if( pHdr->byteOffsetDictionary ){ nIdx = pHdr->byteOffsetDictionary - ZONEFILE_SZ_HEADER; @@ -2606,7 +2777,7 @@ static int zonefileValueReadCache(sqlite3_context *pCtx, ZonefileCsr *pCsr){ /* Find the compression method and open the compressor handle. */ if( rc==SQLITE_OK ){ - rc = zfFindCompress(hdr.compressionTypeContent, &pCmpMethod, &zErr); + rc = zonefileFindCompress(hdr.compressionTypeContent, &pCmpMethod, &zErr); } if( pCmpMethod ){ int nDict = 0; diff --git a/ext/zonefile/zonefile1.test b/ext/zonefile/zonefile1.test index ee1cebce75..96f7810339 100644 --- a/ext/zonefile/zonefile1.test +++ b/ext/zonefile/zonefile1.test @@ -250,7 +250,7 @@ do_execsql_test 3.3 { close [open test.zonefile w+] do_catchsql_test 3.4 { SELECT header FROM cc_files -} {1 {failed to read header from file: "test.zonefile"}} +} {1 {failed to read zonefile header from file "test.zonefile"}} forcedelete test.zonefile do_catchsql_test 3.5 { diff --git a/manifest b/manifest index 874311d0c6..0a13db4f1e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\stest\s'zonefile1-6.5'\sto\saccount\sfor\splatform\sdifferences. -D 2018-02-27T15:47:41.523 +C Rationalize\ssome\scode\sin\szonefile.c.\sFix\sother\sminor\sissues\sin\sthe\ssame. +D 2018-02-27T19:50:28.876 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in a2d2fb8d17c39ab5ec52beb27850b903949080848236923f436156b72a958737 @@ -408,9 +408,9 @@ F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f -F ext/zonefile/README.md 5beb84b8f8326d23319003d57d88be88759fdc3296071a2c5f13c0209703738a -F ext/zonefile/zonefile.c b83136e629c6768e9ff06bb37ae7d102b5b267f8ff5d9481bd65dc87d7f2d483 -F ext/zonefile/zonefile1.test 4bf76f5ad4d818576cdd97f436226bb83bf743fbbd677911645d875892ec5108 +F ext/zonefile/README.md dcf953e519a153e10e6b75aafa44d2865666b66b1c6d152d85d6c0618255d304 +F ext/zonefile/zonefile.c ce917d60a62c8e384087954f482ab703b75a0660385e7a685bcafc0cff1c3038 +F ext/zonefile/zonefile1.test 3719e1d069064f4e12e915f8d9f6256c769b1582258b3997e0492076a01d5f36 F ext/zonefile/zonefileenc.test e8624853ac224bfdeab8d2a231796499c3032e2a8bb1d2208f52fddf9507e38f F ext/zonefile/zonefilefault.test 6df281fc1ec7859d4ae2a3133d8783184a263edf6d081218958b6ae86b22ee13 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x @@ -1712,7 +1712,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 55de6f14d49342394397c0dc29c1e98c927ef99d57ec1f71c79099f584be20d1 -R fc611854e763802d1a0d828294c3f825 -U mistachkin -Z 6a6ffe92b9cb183673ef4c86cb11d527 +P 8b6178403fb6a7f87502c42026caf3da1c355b2ed9e780b347f4a05d7ffc1e18 +R c87480dddaa8bbeda004ab3a9673ad61 +U dan +Z 889fdff2d5ef75d6ead6cee236eee7c1 diff --git a/manifest.uuid b/manifest.uuid index d1a448bfff..5f24abe2c1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8b6178403fb6a7f87502c42026caf3da1c355b2ed9e780b347f4a05d7ffc1e18 \ No newline at end of file +f11beb16a87cc967e896cf67121b1e4045e427ebdc6a424e9f009ffced955d36 \ No newline at end of file