Example #1
0
HIDE void deserializeSEXP(SEXP o) {
  _dbg(rjprintf("attempt to deserialize %p (clCL=%p, oCL=%p)\n", o, clClassLoader, oClassLoader));
  SEXP s = EXTPTR_PROT(o);
  if (TYPEOF(s) == RAWSXP && EXTPTR_PTR(o) == NULL) {
    JNIEnv *env = getJNIEnv();
    if (env && clClassLoader && oClassLoader) {
      jbyteArray ser = newByteArray(env, RAW(s), LENGTH(s));
      if (ser) {
	jmethodID mid = (*env)->GetMethodID(env, clClassLoader, "toObject", "([B)Ljava/lang/Object;");
	if (mid) {
	  jobject res = (*env)->CallObjectMethod(env, oClassLoader, mid, ser);
	  if (res) {
	    jobject go = makeGlobal(env, res);
	    _mp(MEM_PROF_OUT("R %08x RNEW %08x\n", (int) go, (int) res))
	    if (go) {
	      _dbg(rjprintf(" - succeeded: %p\n", go));
	      /* set the deserialized object */
	      EXTPTR_PTR(o) = (SEXP) go;
	      /* Note: currently we don't remove the serialized content, because it was created explicitly using .jcache to allow repeated saving. Once this is handled by a hook, we shall remove it. However, to assure compatibility TAG is always NULL for now, so we do clear the cache if TAG is non-null for future use. */
	      if (EXTPTR_TAG(o) != R_NilValue) {
		/* remove the serialized raw vector */
		SETCDR(o, R_NilValue); /* Note: this is abuse of the API since it uses the fact that PROT is stored in CDR */
	      }
	    }
	  }
	}
	releaseObject(env, ser);
      }
    }    
Example #2
0
static bool decodeIndex(NexasPackage* package) {
	fseek(package->file, -4, SEEK_END);
	u32 encodedLen;
	if (fread(&encodedLen, sizeof(u32), 1, package->file) != 1) {
		writeLog(LOG_QUIET, L"ERROR: Unable to read the length of the encoded index!");
		return false;
	}
	writeLog(LOG_VERBOSE, L"The length of the compressed index is %d.", encodedLen);

	if (fseek(package->file, -4-encodedLen, SEEK_END) != 0) {
		writeLog(LOG_QUIET, L"ERROR: Unable to locate the compressed index!");
		return false;
	}

	ByteArray* encodedData = newByteArray(encodedLen);
	byte* data = baData(encodedData);
	if (fread(data, sizeof(byte), encodedLen, package->file) != encodedLen) {
		writeLog(LOG_QUIET, L"ERROR: Unable to read the compressed index!");
		deleteByteArray(encodedData);
		return false;
	}

	for (u32 i = 0; i < encodedLen; ++i) {
		data[i] ^= 0xFF;
	}

	u32 decodedLen = sizeof(IndexEntry) * package->header->entryCount;
	ByteArray* originalIndexes =
			huffmanDecode(L"Entry Indexes", data, encodedLen, decodedLen);
	deleteByteArray(encodedData);
	package->indexes = originalIndexes;
	return (package->indexes != NULL);
}
Example #3
0
static ByteArray* decodeWithTree(const wchar_t* treeName, TreeNode tree[], BitStream* data, u32 originalLen) {
	u16 treeIndex = 0;
	u32 resIndex = 0;
	byte rbyte = 0;
	ByteArray* result = newByteArray(originalLen);

	while (true) {
		if (!bsNextBit(data, &rbyte)) {
			writeLog(LOG_QUIET, L"ERROR: Cannot decode the huffman code for %s: encoded data exhausted!", treeName);
			return false;
		}

		if (rbyte) {
			treeIndex = tree[treeIndex].rchild;
		} else {
			treeIndex = tree[treeIndex].lchild;
		}

		if (treeIndex >= 1024) {
			/// Byte value
			baData(result)[resIndex++] = treeIndex - 1024;
			treeIndex = 0;

			/**
			 * The encoded data may not take up whole bytes, so there would be
			 * some unused bits in the source array. To determine whether we have
			 * decoded all the data we needed, we just do the following:
			 */
			if (resIndex == originalLen) {
				return result;
			}
		}
	}
	return NULL;
}
Example #4
0
static bool readIndex(NexasPackage* package) {
	/// First, try to read plain text index (used in Baldr Force EXE, PAC variant 2).
	writeLog(LOG_VERBOSE, L"Trying to read the index as plain text.");
	u32 indexesLen = package->header->entryCount * sizeof(IndexEntry);
	fseek(package->file, 12, SEEK_SET);
	package->indexes = newByteArray(indexesLen);
	if (fread(baData(package->indexes), sizeof(byte), indexesLen, package->file) != indexesLen) {
		writeLog(LOG_QUIET, L"ERROR: Unable to read the 'plain text' index!");
		deleteByteArray(package->indexes);
		return false;
	}

	/**
	 * If the index data is valid, the packed file contents should be immediately following,
	 * or we can conclude that the real index data is at the end of the file and encoded.
	 */
	IndexEntry* indexes = (IndexEntry*)(baData(package->indexes));
	if (indexes[0].offset != 12 + indexesLen) {
		writeLog(LOG_VERBOSE, L"The index is invalid, trying to read encoded index.");
		return decodeIndex(package);
	}
	return true;
}
Example #5
0
QScriptValue FilePrototype::readAll()
{
    return newByteArray(thisFile()->readAll());
}
Example #6
0
QScriptValue FilePrototype::readLine(qint64 maxSize)
{
    return newByteArray(thisFile()->readLine(maxSize));
}
Example #7
0
QScriptValue FilePrototype::peek(qint64 maxSize)
{
    return newByteArray(thisFile()->peek(maxSize));
}
Example #8
0
static bool recordAndWriteEntries(NexasPackage* package, bool isBfeFormat) {
	package->indexes = newByteArray(package->header->entryCount * sizeof(IndexEntry));
	IndexEntry* indexes = (IndexEntry*)baData(package->indexes);

	u32 i = 0;
	u32 offset = 12;

	if (isBfeFormat) {
		/// This PAC Variant puts index first, but now we do not know
		/// the index, so we reserve the space.
		u32 len = baLength(package->indexes);
		for (u32 i = 0; i < len; ++i) {
			if (fputc('\0', package->file) == EOF) {
				writeLog(LOG_QUIET, L"ERROR: Unable to reserve space for the index!");
				return false;
			}
		}
		offset += len;
	}

	struct _wfinddata_t foundFile;
	intptr_t handle = _wfindfirst(L"*", &foundFile);
	int status = 0;
	while (status == 0) {
		if ((foundFile.attrib & _A_SUBDIR) == 0) {
			char* fname = toMBString(foundFile.name, L"japanese");
			if (strlen(fname) >= 64) {
				writeLog(LOG_QUIET, L"ERROR: Entry %u: %s, The file name is too long!", i, foundFile.name);
				free(fname);
				return false;
			}
			strncpy(indexes[i].name, fname, 64);
			free(fname);

			indexes[i].encodedLen = foundFile.size;
			indexes[i].decodedLen = foundFile.size;
			indexes[i].offset = offset;
			writeLog(LOG_VERBOSE, L"Entry %u: %s, Offset: %u, OLen: %u",
					i, foundFile.name, indexes[i].offset, indexes[i].decodedLen);

			FILE* infile = _wfopen(foundFile.name, L"rb");
			byte* decodedData = malloc(indexes[i].decodedLen);

			if (fread(decodedData, 1, indexes[i].decodedLen, infile) != indexes[i].decodedLen) {
				writeLog(LOG_QUIET, L"ERROR: Entry %u: %s, Unable to read the file!", i, foundFile.name);
				free(decodedData);
				fclose(infile);
				return false;
			}
			fclose(infile);

			byte* encodedData = NULL;
			ByteArray* encodedArray = NULL;

			if (isBfeFormat) {
				encodedArray = lzssEncode(decodedData, indexes[i].decodedLen);
				encodedData = baData(encodedArray);
				indexes[i].encodedLen = baLength(encodedArray);
			} else if (shouldZip(foundFile.name)) {
				encodedData = malloc(indexes[i].decodedLen);
				unsigned long len = indexes[i].encodedLen;
				if (compress(encodedData, &len, decodedData, indexes[i].decodedLen) != Z_OK) {
					free(encodedData);
					free(decodedData);
					return false;
				}
				indexes[i].encodedLen = len;
				writeLog(LOG_VERBOSE, L"Entry %u is compressed: ELen: %u", i, len);
			} else {
				encodedData = decodedData;
			}
			offset += indexes[i].encodedLen;
			writeLog(LOG_VERBOSE, L"Entry %u: ELen: %u", i, indexes[i].encodedLen);

			if (fwrite(encodedData, 1, indexes[i].encodedLen, package->file) != indexes[i].encodedLen) {
				writeLog(LOG_QUIET, L"ERROR: Entry %u: %s, Unable to write to the package!", i, foundFile.name);
				if (encodedArray != NULL) {
					deleteByteArray(encodedArray);
				} else if (encodedData != decodedData) {
					free(encodedData);
				}
				free(decodedData);
				return false;
			}

			if (encodedArray != NULL) {
				deleteByteArray(encodedArray);
			} else if (encodedData != decodedData) {
				free(encodedData);
			}
			free(decodedData);

			writeLog(LOG_NORMAL, L"Packed: Entry %u: %s.", i, foundFile.name);
			++i;
		}
		status = _wfindnext(handle, &foundFile);
	}
	_findclose(handle);
	return true;
}
Example #9
0
static bool extractFiles(NexasPackage* package, const wchar_t* targetDir) {
	IndexEntry* indexes = (IndexEntry*)baData(package->indexes);
	u32 count = package->header->entryCount;

	for (u32 i = 0; i < count; ++i) {
		wchar_t* wName = toWCString(indexes[i].name, L"japanese");
		writeLog(LOG_VERBOSE, L"Entry %u: %s, Offset: %u, ELen: %u, DLen: %u",
				i, wName, indexes[i].offset, indexes[i].encodedLen,
				indexes[i].decodedLen);
		if (fseek(package->file, indexes[i].offset, SEEK_SET) != 0) {
			writeLog(LOG_QUIET, L"ERROR: Entry %u: %s, Unable to locate data!",
													i, wName);
			cleanupForEntry(wName, NULL, NULL, NULL, false);
			return false;
		}

		ByteArray* encodedData = newByteArray(indexes[i].encodedLen);
		ByteArray* decodedData = encodedData;
		if (fread(baData(encodedData), 1, indexes[i].encodedLen, package->file) != indexes[i].encodedLen) {
			writeLog(LOG_QUIET, L"ERROR: Entry %u: %s, Unable to read data from package!",
							i, wName);
			cleanupForEntry(wName, NULL, encodedData, NULL, false);
			return false;
		}

		/**
		 * Now we support two PAC variants.
		 * The first is Variant 4, where contents are either uncompressed (like ogg files),
		 * or compressed using zlib (the deflate algorithm).
		 * We should do a test to determine if the particular file is compressed or not.
		 */
		if (package->header->variantTag == CONTENT_MAYBE_DEFLATE) {
			unsigned long decodedLen = indexes[i].decodedLen;
			if (decodedLen > indexes[i].encodedLen) {
				decodedData = newByteArray(decodedLen);
				if (uncompress(baData(decodedData), &decodedLen, baData(encodedData), indexes[i].encodedLen) != Z_OK) {
					writeLog(LOG_QUIET, L"ERROR: Entry %u: %s, Unable to extract data!", i, wName);
					cleanupForEntry(wName, NULL, encodedData, decodedData, false);
					return false;
				}
			}
		} else if (package->header->variantTag == CONTENT_LZSS) {
			decodedData = lzssDecode(baData(encodedData), indexes[i].encodedLen, indexes[i].decodedLen);
			if (decodedData == NULL) {
				writeLog(LOG_QUIET, L"ERROR: Entry %u: %s, Unable to extract data!", i, wName);
				cleanupForEntry(wName, NULL, encodedData, decodedData, false);
				return false;
			}
		}

		wchar_t* wPath = fsCombinePath(targetDir, wName);
		FILE* outFile = _wfopen(wPath, L"wb");
		if (outFile == NULL) {
			writeLog(LOG_QUIET,
					L"ERROR: Entry %u: %s, Unable to open output file!",
						i, wName);
			cleanupForEntry(wName, wPath, encodedData, decodedData, false);
			return false;
		}
		if (fwrite(baData(decodedData), 1, indexes[i].decodedLen, outFile)
				!= indexes[i].decodedLen) {
			writeLog(LOG_QUIET,
					L"ERROR: Entry %u: %s, Unable to write file content!",
						i, wName);
			cleanupForEntry(wName, wPath, encodedData, decodedData, false);
			fclose(outFile);
			return false;
		}
		fclose(outFile);
		writeLog(LOG_NORMAL, L"Unpacked: Entry %u: %s", i, wName);
		cleanupForEntry(wName, wPath, encodedData, decodedData, true);
	}

	return true;
}