+
+/*
+====================
+FS_IsRegisteredQuakePack
+
+Look for a proof of purchase file file in the requested package
+
+If it is found, this file should NOT be downloaded.
+====================
+*/
+qboolean FS_IsRegisteredQuakePack(const char *name)
+{
+ searchpath_t *search;
+ pack_t *pak;
+
+ // search through the path, one element at a time
+ for (search = fs_searchpaths;search;search = search->next)
+ {
+ if (search->pack && !strcasecmp(FS_FileWithoutPath(search->filename), name))
+ {
+ int (*strcmp_funct) (const char* str1, const char* str2);
+ int left, right, middle;
+
+ pak = search->pack;
+ strcmp_funct = pak->ignorecase ? strcasecmp : strcmp;
+
+ // Look for the file (binary search)
+ left = 0;
+ right = pak->numfiles - 1;
+ while (left <= right)
+ {
+ int diff;
+
+ middle = (left + right) / 2;
+ diff = !strcmp_funct (pak->files[middle].name, "gfx/pop.lmp");
+
+ // Found it
+ if (!diff)
+ return true;
+
+ // If we're too far in the list
+ if (diff > 0)
+ right = middle - 1;
+ else
+ left = middle + 1;
+ }
+
+ // we found the requested pack but it is not registered quake
+ return false;
+ }
+ }
+
+ return false;
+}
+
+int FS_CRCFile(const char *filename, size_t *filesizepointer)
+{
+ int crc = -1;
+ unsigned char *filedata;
+ fs_offset_t filesize;
+ if (filesizepointer)
+ *filesizepointer = 0;
+ if (!filename || !*filename)
+ return crc;
+ filedata = FS_LoadFile(filename, tempmempool, true, &filesize);
+ if (filedata)
+ {
+ if (filesizepointer)
+ *filesizepointer = filesize;
+ crc = CRC_Block(filedata, filesize);
+ Mem_Free(filedata);
+ }
+ return crc;
+}
+
+unsigned char *FS_Deflate(const unsigned char *data, size_t size, size_t *deflated_size, int level, mempool_t *mempool)
+{
+ z_stream strm;
+ unsigned char *out = NULL;
+ unsigned char *tmp;
+
+ memset(&strm, 0, sizeof(strm));
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+
+ if(level < 0)
+ level = Z_DEFAULT_COMPRESSION;
+
+ if(qz_deflateInit2(&strm, level, Z_DEFLATED, -MAX_WBITS, Z_MEMLEVEL_DEFAULT, Z_BINARY) != Z_OK)
+ {
+ Con_Printf("FS_Deflate: deflate init error!\n");
+ return NULL;
+ }
+
+ strm.next_in = (unsigned char*)data;
+ strm.avail_in = size;
+
+ tmp = (unsigned char *) Mem_Alloc(tempmempool, size);
+ if(!tmp)
+ {
+ Con_Printf("FS_Deflate: not enough memory in tempmempool!\n");
+ qz_deflateEnd(&strm);
+ return NULL;
+ }
+
+ strm.next_out = tmp;
+ strm.avail_out = size;
+
+ if(qz_deflate(&strm, Z_FINISH) != Z_STREAM_END)
+ {
+ Con_Printf("FS_Deflate: deflate failed!\n");
+ qz_deflateEnd(&strm);
+ Mem_Free(tmp);
+ return NULL;
+ }
+
+ if(qz_deflateEnd(&strm) != Z_OK)
+ {
+ Con_Printf("FS_Deflate: deflateEnd failed\n");
+ Mem_Free(tmp);
+ return NULL;
+ }
+
+ if(strm.total_out >= size)
+ {
+ Con_Printf("FS_Deflate: deflate is useless on this data!\n");
+ Mem_Free(tmp);
+ return NULL;
+ }
+
+ out = (unsigned char *) Mem_Alloc(mempool, strm.total_out);
+ if(!out)
+ {
+ Con_Printf("FS_Deflate: not enough memory in target mempool!\n");
+ Mem_Free(tmp);
+ return NULL;
+ }
+
+ if(deflated_size)
+ *deflated_size = (size_t)strm.total_out;
+
+ memcpy(out, tmp, strm.total_out);
+ Mem_Free(tmp);
+
+ return out;
+}
+
+static void AssertBufsize(sizebuf_t *buf, int length)
+{
+ if(buf->cursize + length > buf->maxsize)
+ {
+ int oldsize = buf->maxsize;
+ unsigned char *olddata;
+ olddata = buf->data;
+ buf->maxsize += length;
+ buf->data = (unsigned char *) Mem_Alloc(tempmempool, buf->maxsize);
+ if(olddata)
+ {
+ memcpy(buf->data, olddata, oldsize);
+ Mem_Free(olddata);
+ }
+ }
+}
+
+unsigned char *FS_Inflate(const unsigned char *data, size_t size, size_t *inflated_size, mempool_t *mempool)
+{
+ int ret;
+ z_stream strm;
+ unsigned char *out = NULL;
+ unsigned char tmp[2048];
+ unsigned int have;
+ sizebuf_t outbuf;
+
+ memset(&outbuf, 0, sizeof(outbuf));
+ outbuf.data = (unsigned char *) Mem_Alloc(tempmempool, sizeof(tmp));
+ outbuf.maxsize = sizeof(tmp);
+
+ memset(&strm, 0, sizeof(strm));
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+
+ if(qz_inflateInit2(&strm, -MAX_WBITS) != Z_OK)
+ {
+ Con_Printf("FS_Inflate: inflate init error!\n");
+ Mem_Free(outbuf.data);
+ return NULL;
+ }
+
+ strm.next_in = (unsigned char*)data;
+ strm.avail_in = size;
+
+ do
+ {
+ strm.next_out = tmp;
+ strm.avail_out = sizeof(tmp);
+ ret = qz_inflate(&strm, Z_NO_FLUSH);
+ // it either returns Z_OK on progress, Z_STREAM_END on end
+ // or an error code
+ switch(ret)
+ {
+ case Z_STREAM_END:
+ case Z_OK:
+ break;
+
+ case Z_STREAM_ERROR:
+ Con_Print("FS_Inflate: stream error!\n");
+ break;
+ case Z_DATA_ERROR:
+ Con_Print("FS_Inflate: data error!\n");
+ break;
+ case Z_MEM_ERROR:
+ Con_Print("FS_Inflate: mem error!\n");
+ break;
+ case Z_BUF_ERROR:
+ Con_Print("FS_Inflate: buf error!\n");
+ break;
+ default:
+ Con_Print("FS_Inflate: unknown error!\n");
+ break;
+
+ }
+ if(ret != Z_OK && ret != Z_STREAM_END)
+ {
+ Con_Printf("Error after inflating %u bytes\n", (unsigned)strm.total_in);
+ Mem_Free(outbuf.data);
+ qz_inflateEnd(&strm);
+ return NULL;
+ }
+ have = sizeof(tmp) - strm.avail_out;
+ AssertBufsize(&outbuf, max(have, sizeof(tmp)));
+ SZ_Write(&outbuf, tmp, have);
+ } while(ret != Z_STREAM_END);
+
+ qz_inflateEnd(&strm);
+
+ out = (unsigned char *) Mem_Alloc(mempool, outbuf.cursize);
+ if(!out)
+ {
+ Con_Printf("FS_Inflate: not enough memory in target mempool!\n");
+ Mem_Free(outbuf.data);
+ return NULL;
+ }
+
+ memcpy(out, outbuf.data, outbuf.cursize);
+ Mem_Free(outbuf.data);
+
+ if(inflated_size)
+ *inflated_size = (size_t)outbuf.cursize;
+
+ return out;
+}