예제 #1
0
const char* CslGeoIP::GetCountryCodeByIPnum(const unsigned long ipnum)
{
    CslGeoIP& self = GetInstance();

    if (!g_geoIP)
        return NULL;

    GeoIPRecord *r = NULL;
    const char *code = NULL;

    switch (self.m_type)
    {
        case GEOIP_COUNTRY:
            code = GeoIP_country_code_by_ipnum(g_geoIP, wxUINT32_SWAP_ON_LE(ipnum));
            break;
        case GEOIP_CITY:
            if ((r = GeoIP_record_by_ipnum(g_geoIP, wxUINT32_SWAP_ON_LE(ipnum))))
            {
                code = r->country_code;
                GeoIPRecord_delete(r);
            }
            break;
    }

    return code;
}
예제 #2
0
wxString CslGeoIP::GetCountryNameByIPnum(const unsigned long ipnum)
{
    CslGeoIP& self = GetInstance();

    if (!g_geoIP)
        return wxEmptyString;

    GeoIPRecord *r = NULL;
    const char *country = NULL;

    switch (self.m_type)
    {
        case GEOIP_COUNTRY:
            country = GeoIP_country_name_by_ipnum(g_geoIP, wxUINT32_SWAP_ON_LE(ipnum));
            break;
        case GEOIP_CITY:
            if ((r = GeoIP_record_by_ipnum(g_geoIP, wxUINT32_SWAP_ON_LE(ipnum))))
            {
                country = r->country_name;
                GeoIPRecord_delete(r);
            }
            break;
    }

    return country ? C2U(country) : wxString(wxEmptyString);
}
예제 #3
0
bool wxServerConnectionThread::Cities3DCheck() const
{
	wxLogDebug(wxT("Server starting Cities3D check."));

	// Handshake to determine that we're talking to a client or the site.
	wxUint32 number = 0;
	mSocket->Read(&number, sizeof(wxUint32));

	// Magic numbers.
	wxUint32 site = wxUINT32_SWAP_ON_LE('SITE');
	wxUint32 client = wxUINT32_SWAP_ON_LE('CC3D');

	// If it's not the site or the client, bail.
	if( (site != number) &&
		(client != number))
	{
		throw std::runtime_error("Server Error: Not talking to a Cities3D app.");
	}

	// We've got a client or the site, reassure them this is a server.
	wxUint32 magic = wxUINT32_SWAP_ON_LE('CS3D');
	mSocket->Write(&magic, sizeof(wxUint32));

	wxLogDebug(wxT("Server ending Cities3D check."));

	// Return true if we got a client, false for the site.
	return (client == number);
}
예제 #4
0
//---------------------------------------------------------------------------------------
void GRHostWindow::OnHostButton(wxCommandEvent &evt)
{
    wxUint8 *payload = NULL;
    wxUint32 len = 0;
    GR_HOST_GAME_ROOM hostHeader;
    GRPlugin *plugin = NULL;
    int pos = 0;
    char lateJoiners[1];
    char nulls[1] = {0};

    if(gameCombo->GetSelection() == -1) return;
    plugin = (GRPlugin*)gameCombo->GetClientData(gameCombo->GetSelection());
    if(plugin == NULL) return;

    len += sizeof(GR_HOST_GAME_ROOM);
    len += 1; //unknown
    len += descText->GetValue().Length() + 1;
    len += passTextBox->GetValue().Length() + 1;
    len += 1; //premium only

    payload = new wxUint8[len];

    /* host header */
    hostHeader.gameID = wxUINT32_SWAP_ON_LE(plugin->gameCode);
    hostHeader.unknown = wxUINT32_SWAP_ON_LE(0xffffffff);
    hostHeader.maxPlayers = wxUINT32_SWAP_ON_LE(atoi((const char*)playersCombo->GetValue().mb_str()));
    hostHeader.lateJoiners = wxUINT32_SWAP_ON_LE(0);

    if(lateJoinersCheck->IsChecked())
        lateJoiners[0] = 0;
    else
        lateJoiners[0] = 1;

    memcpy(payload, &hostHeader, sizeof(hostHeader));
    pos += sizeof(hostHeader);

    /* null byte */
    memcpy(payload+pos, lateJoiners, 1);
    pos++;

    /* description */
    memcpy(payload+pos, (const char*)descText->GetValue().mb_str(), descText->GetValue().Length()+1);
    pos += descText->GetValue().Length()+1;

    /* pass */
    memcpy(payload+pos, (const char*)passTextBox->GetValue().mb_str(), passTextBox->GetValue().Length()+1);
    pos += passTextBox->GetValue().Length()+1;

    /* premium only */
    memcpy(payload+pos, nulls, 1);
    pos++;

    mainWindow->sendGRPacket(HOST_GAME_ROOM, len, payload);
    this->Close();

    delete[] payload;
}
예제 #5
0
// -----------------------------------------------------------------------------
// Checks if the file at [filename] is a valid Quake disk archive
// -----------------------------------------------------------------------------
bool DiskArchive::isDiskArchive(string filename)
{
	// Open file for reading
	wxFile file(filename);

	// Check it opened ok
	if (!file.IsOpened() || file.Length() < 4)
		return false;
	// Check given data is valid
	size_t mcsize = file.Length();
	if (mcsize < 80)
		return false;

	// Read disk header
	uint32_t num_entries;
	uint32_t size_entries;
	file.Seek(0, wxFromStart);
	file.Read(&num_entries, 4);
	num_entries = wxUINT32_SWAP_ON_LE(num_entries);

	size_t start_offset = (72 * num_entries) + 8;

	if (mcsize < start_offset)
		return false;

	// Read the directory
	for (uint32_t d = 0; d < num_entries; d++)
	{
		// Read entry info
		DiskEntry entry;
		file.Read(&entry, 72);

		// Byteswap if needed
		entry.length = wxUINT32_SWAP_ON_LE(entry.length);
		entry.offset = wxUINT32_SWAP_ON_LE(entry.offset);

		// Increase offset to make it relative to start of archive
		entry.offset += start_offset;

		// Check offset+size
		if (entry.offset + entry.length > mcsize)
			return false;
	}
	file.Read(&size_entries, 4);
	size_entries = wxUINT32_SWAP_ON_LE(size_entries);
	if (size_entries + start_offset != mcsize)
		return false;

	// That'll do
	return true;
}
예제 #6
0
/*--------------------------------------------------------------------------*/
void GRGameParser::parseGameRoomStatusChanged(GR_PACKET *Packet)
{
	GR_ROOM_STATUS_CHANGED *pck;
	GRGameRoom *room = NULL;
	wxInt32 index;
	int x;

	pck = (GR_ROOM_STATUS_CHANGED*)Packet->payload;

	//endian conversion
	pck->roomID = wxUINT32_SWAP_ON_LE(pck->roomID);
	pck->status = wxUINT32_SWAP_ON_LE(pck->status);

	conn->getGameManager()->gameStatusChanged(pck->roomID, pck->status);
}
예제 #7
0
bool CDVTOOLFileReader::open(const wxString& fileName)
{
	m_fileName = fileName;

	bool res = m_file.Open(fileName, wxT("rb"));
	if (!res)
		return false;

	unsigned char buffer[DVTOOL_SIGNATURE_LENGTH];
	size_t n = m_file.Read(buffer, DVTOOL_SIGNATURE_LENGTH);
	if (n != DVTOOL_SIGNATURE_LENGTH) {
		m_file.Close();
		return false;
	}

	if (::memcmp(buffer, DVTOOL_SIGNATURE, DVTOOL_SIGNATURE_LENGTH) != 0) {
		m_file.Close();
		return false;
	}

	wxUint32 uint32;
	n = m_file.Read(&uint32, sizeof(wxUint32));
	if (n != sizeof(wxUint32)) {
		m_file.Close();
		return false;
	}

	m_records = wxUINT32_SWAP_ON_LE(uint32);

	return true;
}
예제 #8
0
// -----------------------------------------------------------------------------
// Checks if the given data is a valid Nerve disk archive
// -----------------------------------------------------------------------------
bool DiskArchive::isDiskArchive(MemChunk& mc)
{
	// Check given data is valid
	size_t mcsize = mc.getSize();
	if (mcsize < 80)
		return false;

	// Read disk header
	uint32_t num_entries;
	uint32_t size_entries;
	mc.seek(0, SEEK_SET);
	mc.read(&num_entries, 4);
	num_entries = wxUINT32_SWAP_ON_LE(num_entries);

	size_t start_offset = (72 * num_entries) + 8;

	if (mcsize < start_offset)
		return false;

	// Read the directory
	for (uint32_t d = 0; d < num_entries; d++)
	{
		// Read entry info
		DiskEntry entry;
		mc.read(&entry, 72);

		// Byteswap if needed
		entry.length = wxUINT32_SWAP_ON_LE(entry.length);
		entry.offset = wxUINT32_SWAP_ON_LE(entry.offset);

		// Increase offset to make it relative to start of archive
		entry.offset += start_offset;

		// Check offset+size
		if (entry.offset + entry.length > mcsize)
			return false;
	}
	mc.read(&size_entries, 4);
	size_entries = wxUINT32_SWAP_ON_LE(size_entries);
	if (size_entries + start_offset != mcsize)
		return false;

	// That'll do
	return true;
}
예제 #9
0
wxUint32 wxDataInputStream::Read32()
{
    wxUint32 i32;

    m_input->Read(&i32, 4);

    if (m_be_order)
        return wxUINT32_SWAP_ON_LE(i32);
    else
        return wxUINT32_SWAP_ON_BE(i32);
}
예제 #10
0
wxUint32 wxArchive::LoadUint32()
{
	wxUint32 value = 0;

	// reads a 32bits from the stream
	if(CanLoad())
	{
		m_idstr.Read((void *)&value, sizeof(wxUint32));
		return wxUINT32_SWAP_ON_LE(value);
	}

	return value;
}
예제 #11
0
wxString CslGeoIP::GetCityNameByIPnum(const unsigned long ipnum)
{
    CslGeoIP& self = GetInstance();

    wxString city;

    if (g_geoIP && self.m_type==GEOIP_CITY)
    {
        GeoIPRecord *r = GeoIP_record_by_ipnum(g_geoIP, wxUINT32_SWAP_ON_LE(ipnum));

        if (r)
        {
            city = C2U(r->city);
            GeoIPRecord_delete(r);
        }
    }

    return city;
}
예제 #12
0
// -----------------------------------------------------------------------------
// Reads disk format data from a MemChunk.
// Returns true if successful, false otherwise
// -----------------------------------------------------------------------------
bool DiskArchive::open(MemChunk& mc)
{
	size_t mcsize = mc.getSize();

	// Check given data is valid
	if (mcsize < 80)
		return false;

	// Read disk header
	uint32_t num_entries;
	mc.seek(0, SEEK_SET);
	mc.read(&num_entries, 4);
	num_entries = wxUINT32_SWAP_ON_LE(num_entries);

	size_t start_offset = (72 * num_entries) + 8;

	if (mcsize < start_offset)
		return false;

	// Stop announcements (don't want to be announcing modification due to entries being added etc)
	setMuted(true);

	// Read the directory
	UI::setSplashProgressMessage("Reading disk archive data");
	for (uint32_t d = 0; d < num_entries; d++)
	{
		// Update splash window progress
		UI::setSplashProgress(((float)d / (float)num_entries));

		// Read entry info
		DiskEntry dent;
		mc.read(&dent, 72);

		// Byteswap if needed
		dent.length = wxUINT32_SWAP_ON_LE(dent.length);
		dent.offset = wxUINT32_SWAP_ON_LE(dent.offset);

		// Increase offset to make it relative to start of archive
		dent.offset += start_offset;

		// Check offset+size
		if (dent.offset + dent.length > mcsize)
		{
			LOG_MESSAGE(1, "DiskArchive::open: Disk archive is invalid or corrupt (entry goes past end of file)");
			Global::error = "Archive is invalid and/or corrupt";
			setMuted(false);
			return false;
		}

		// Parse name
		string name = wxString::FromAscii(dent.name, 64);
		name.Replace("\\", "/");
		name.Replace("GAME:/", "");
		wxFileName fn(name);

		// Create directory if needed
		ArchiveTreeNode* dir = createDir(fn.GetPath(true, wxPATH_UNIX));

		// Create entry
		ArchiveEntry* entry     = new ArchiveEntry(fn.GetFullName(), dent.length);
		entry->exProp("Offset") = (int)dent.offset;
		entry->setLoaded(false);
		entry->setState(0);

		// Add to directory
		dir->addEntry(entry);
	}

	// Detect all entry types
	MemChunk              edata;
	vector<ArchiveEntry*> all_entries;
	getEntryTreeAsList(all_entries);
	UI::setSplashProgressMessage("Detecting entry types");
	for (size_t a = 0; a < all_entries.size(); a++)
	{
		// Update splash window progress
		UI::setSplashProgress((((float)a / (float)num_entries)));

		// Get entry
		ArchiveEntry* entry = all_entries[a];

		// Read entry data if it isn't zero-sized
		if (entry->getSize() > 0)
		{
			// Read the entry data
			mc.exportMemChunk(edata, (int)entry->exProp("Offset"), entry->getSize());
			entry->importMemChunk(edata);
		}

		// Detect entry type
		EntryType::detectEntryType(entry);

		// Unload entry data if needed
		if (!archive_load_data)
			entry->unloadData();

		// Set entry to unchanged
		entry->setState(0);
	}

	// Setup variables
	setMuted(false);
	setModified(false);
	announce("opened");

	UI::setSplashProgressMessage("");

	return true;
}
예제 #13
0
/* EntryOperations::modifytRNSChunk
 * Add or remove the tRNS chunk from a PNG entry
 * Returns true if the entry was altered
 *******************************************************************/
bool EntryOperations::modifytRNSChunk(ArchiveEntry* entry, bool value)
{
	// Avoid NULL pointers, they're annoying.
	if (!entry || !entry->getType())
		return false;

	// Don't bother if the entry is locked.
	if (entry->isLocked())
		return false;

	// Check entry type
	if (!(entry->getType()->getFormat() == "img_png"))
	{
		wxLogMessage("Entry \"%s\" is of type \"%s\" rather than PNG", entry->getName(), entry->getTypeString());
		return false;
	}

	// Read width and height from IHDR chunk
	const uint8_t* data = entry->getData(true);
	const ihdr_t* ihdr = (ihdr_t*)(data + 12);

	// tRNS chunks are only valid for paletted PNGs, and must be before the first IDAT.
	// Specs say they must be after PLTE chunk as well, so to play it safe, we'll insert
	// them just before the first IDAT.
	uint32_t trns_start = 0;
	uint32_t trns_size	= 0;
	uint32_t idat_start = 0;
	for (uint32_t a = 0; a < entry->getSize(); a++)
	{

		// Check for 'tRNS' header
		if (data[a] == 't' && data[a + 1] == 'R' &&
		        data[a + 2] == 'N' && data[a + 3] == 'S')
		{
			trns_start = a - 4;
			trans_chunk_t* trns = (trans_chunk_t*)(data + a);
			trns_size = 12 + READ_B32(data, a-4);
		}

		// Stop when we get to the 'IDAT' chunk
		if (data[a] == 'I' && data[a + 1] == 'D' &&
		        data[a + 2] == 'A' && data[a + 3] == 'T')
		{
			idat_start = a - 4;
			break;
		}
	}

	// The IDAT chunk starts before the header is finished, this doesn't make sense, abort.
	if (idat_start < 33)
		return false;

	// We want to set tRNS, and it is already there: nothing to do.
	if (value && trns_start > 0)
		return false;

	// We want to unset tRNS, and it is already not there: nothing to do either.
	else if (!value && trns_start == 0)
		return false;

	// We want to set tRNS, which is missing: create it. We're just going to set index 0 to 0,
	// and leave the rest of the palette indices alone.
	else if (value && trns_start == 0)
	{
		// Build new PNG from the original w/ the new tRNS chunk
		MemChunk npng;

		// Init new png data size
		npng.reSize(entry->getSize() + 13);

		// Write PNG header stuff up to the first IDAT chunk
		npng.write(data, idat_start);

		// Create new tRNS chunk
		uint32_t csize = wxUINT32_SWAP_ON_LE(1);
		trans_chunk_t gc = { 't', 'R', 'N', 'S', '\0' };
		uint32_t dcrc = wxUINT32_SWAP_ON_LE(Misc::crc((uint8_t*)&gc, 5));

		// Write tRNS chunk
		npng.write(&csize, 4);
		npng.write(&gc, 5);
		npng.write(&dcrc, 4);

		// Write the rest of the PNG data
		uint32_t to_write = entry->getSize() - idat_start;
		npng.write(data + idat_start, to_write);

		// Load new png data to the entry
		entry->importMemChunk(npng);
	}

	// We want to unset tRNS, which is present: delete it.
	else if (!value && trns_start > 0)
	{
		// Build new PNG from the original without the tRNS chunk
		MemChunk npng;
		uint32_t rest_start = trns_start + trns_size;

		// Init new png data size
		npng.reSize(entry->getSize() - trns_size);

		// Write PNG header and stuff up to tRNS start
		npng.write(data, trns_start);

		// Write the rest of the PNG data
		uint32_t to_write = entry->getSize() - rest_start;
		npng.write(data + rest_start, to_write);

		// Load new png data to the entry
		entry->importMemChunk(npng);
	}

	// We don't know what we want, but it can't be good, so we do nothing.
	else
		return false;

	return true;
}
예제 #14
0
/* EntryOperations::modifyalPhChunk
 * Add or remove the alPh chunk from a PNG entry
 *******************************************************************/
bool EntryOperations::modifyalPhChunk(ArchiveEntry* entry, bool value)
{
	if (!entry || !entry->getType())
		return false;

	// Don't bother if the entry is locked.
	if (entry->isLocked())
		return false;

	// Check entry type
	if (!(entry->getType()->getFormat() == "img_png"))
	{
		wxLogMessage("Entry \"%s\" is of type \"%s\" rather than PNG", entry->getName(), entry->getType()->getName());
		return false;
	}

	// Read width and height from IHDR chunk
	const uint8_t* data = entry->getData(true);
	const ihdr_t* ihdr = (ihdr_t*)(data + 12);

	// Find existing alPh chunk
	uint32_t alph_start = 0;
	for (uint32_t a = 0; a < entry->getSize(); a++)
	{
		// Check for 'alPh' header
		if (data[a] == 'a' && data[a + 1] == 'l' &&
		        data[a + 2] == 'P' && data[a + 3] == 'h')
		{
			alph_start = a - 4;
			break;
		}

		// Stop when we get to the 'IDAT' chunk
		if (data[a] == 'I' && data[a + 1] == 'D' &&
		        data[a + 2] == 'A' && data[a + 3] == 'T')
			break;
	}

	// We want to set alPh, and it is already there: nothing to do.
	if (value && alph_start > 0)
		return false;

	// We want to unset alPh, and it is already not there: nothing to do either.
	else if (!value && alph_start == 0)
		return false;

	// We want to set alPh, which is missing: create it.
	else if (value && alph_start == 0)
	{
		// Build new PNG from the original w/ the new alPh chunk
		MemChunk npng;

		// Init new png data size
		npng.reSize(entry->getSize() + 12);

		// Write PNG header and IHDR chunk
		npng.write(data, 33);

		// Create new alPh chunk
		uint32_t csize = wxUINT32_SWAP_ON_LE(0);
		alph_chunk_t gc = { 'a', 'l', 'P', 'h' };
		uint32_t dcrc = wxUINT32_SWAP_ON_LE(Misc::crc((uint8_t*)&gc, 4));

		// Create alPh chunk
		npng.write(&csize, 4);
		npng.write(&gc, 4);
		npng.write(&dcrc, 4);

		// Write the rest of the PNG data
		uint32_t to_write = entry->getSize() - 33;
		npng.write(data + 33, to_write);

		// Load new png data to the entry
		entry->importMemChunk(npng);
	}

	// We want to unset alPh, which is present: delete it.
	else if (!value && alph_start > 0)
	{
		// Build new PNG from the original without the alPh chunk
		MemChunk npng;
		uint32_t rest_start = alph_start + 12;

		// Init new png data size
		npng.reSize(entry->getSize() - 12);

		// Write PNG info before alPh chunk
		npng.write(data, alph_start);

		// Write the rest of the PNG data
		uint32_t to_write = entry->getSize() - rest_start;
		npng.write(data + rest_start, to_write);

		// Load new png data to the entry
		entry->importMemChunk(npng);
	}

	// We don't know what we want, but it can't be good, so we do nothing.
	else
		return false;

	return true;
}
예제 #15
0
/* EntryOperations::setGfxOffsets
 * Changes the offsets of the given gfx entry. Returns false if the
 * entry is invalid or not an offset-supported format, true otherwise
 *******************************************************************/
bool EntryOperations::setGfxOffsets(ArchiveEntry* entry, int x, int y)
{
	if (entry == NULL || entry->getType() == NULL)
		return false;

	// Check entry type
	EntryType* type = entry->getType();
	string entryformat = type->getFormat();
	if (!(entryformat == "img_doom" || entryformat == "img_doom_arah" ||
		entryformat == "img_doom_alpha" || entryformat == "img_doom_beta" ||
		entryformat == "img_png"))
	{
		wxLogMessage("Entry \"%s\" is of type \"%s\" which does not support offsets", entry->getName(), entry->getType()->getName());
		return false;
	}

	// Doom gfx format, normal and beta version.
	// Also arah format from alpha 0.2 because it uses the same header format.
	if (entryformat == "img_doom" || entryformat == "img_doom_beta" || entryformat == "image_doom_arah")
	{
		// Get patch header
		patch_header_t header;
		entry->seek(0, SEEK_SET);
		entry->read(&header, 8);

		// Apply new offsets
		header.left = wxINT16_SWAP_ON_BE((int16_t)x);
		header.top = wxINT16_SWAP_ON_BE((int16_t)y);

		// Write new header to entry
		entry->seek(0, SEEK_SET);
		entry->write(&header, 8);
	}

	// Doom alpha gfx format
	else if (entryformat == "img_doom_alpha")
	{
		// Get patch header
		entry->seek(0, SEEK_SET);
		oldpatch_header_t header;
		entry->read(&header, 4);

		// Apply new offsets
		header.left = (int8_t)x;
		header.top = (int8_t)y;

		// Write new header to entry
		entry->seek(0, SEEK_SET);
		entry->write(&header, 4);
	}

	// PNG format
	else if (entryformat == "img_png")
	{
		// Find existing grAb chunk
		const uint8_t* data = entry->getData(true);
		uint32_t grab_start = 0;
		for (uint32_t a = 0; a < entry->getSize(); a++)
		{
			// Check for 'grAb' header
			if (data[a] == 'g' && data[a + 1] == 'r' &&
				data[a + 2] == 'A' && data[a + 3] == 'b')
			{
				grab_start = a - 4;
				break;
			}

			// Stop when we get to the 'IDAT' chunk
			if (data[a] == 'I' && data[a + 1] == 'D' &&
				data[a + 2] == 'A' && data[a + 3] == 'T')
				break;
		}

		// Create new grAb chunk
		uint32_t csize = wxUINT32_SWAP_ON_LE(8);
		grab_chunk_t gc ={ { 'g', 'r', 'A', 'b' }, wxINT32_SWAP_ON_LE(x), wxINT32_SWAP_ON_LE(y) };
		uint32_t dcrc = wxUINT32_SWAP_ON_LE(Misc::crc((uint8_t*)&gc, 12));

		// Build new PNG from the original w/ the new grAb chunk
		MemChunk npng;
		uint32_t rest_start = 33;

		// Init new png data size
		if (grab_start == 0)
			npng.reSize(entry->getSize() + 20);
		else
			npng.reSize(entry->getSize());

		// Write PNG header and IHDR chunk
		npng.write(data, 33);

		// If no existing grAb chunk was found, write new one here
		if (grab_start == 0)
		{
			npng.write(&csize, 4);
			npng.write(&gc, 12);
			npng.write(&dcrc, 4);
		}
		else
		{
			// Otherwise write any other data before the existing grAb chunk
			uint32_t to_write = grab_start - 33;
			npng.write(data + 33, to_write);
			rest_start = grab_start + 20;

			// And now write the new grAb chunk
			npng.write(&csize, 4);
			npng.write(&gc, 12);
			npng.write(&dcrc, 4);
		}

		// Write the rest of the PNG data
		uint32_t to_write = entry->getSize() - rest_start;
		npng.write(data + rest_start, to_write);

		// Load new png data to the entry
		entry->importMemChunk(npng);

		// Set its type back to png
		entry->setType(type);
	}
	else
		return false;

	return true;
}
예제 #16
0
// Stolen from  https://github.com/etexteditor/e/blob/master/src/Strings.cpp
//        and:  https://github.com/etexteditor/e/blob/master/src/Utf.cpp
// Copyright (c) 2009, Alexander Stigsen, e-texteditor.com (All rights reserved)
// http://www.e-texteditor.com/
bool EncodingDetector::DetectEncodingEx(const wxByte* buffer, size_t size)
{
    if (!buffer || size == 0) return false;

    const wxByte*  buff_ptr = buffer;
    const wxByte*  buff_end = &buffer[size];
    wxFontEncoding enc      = wxFONTENCODING_DEFAULT;

    // Check if the buffer starts with a BOM (Byte Order Marker)
    if (size >= 2)
    {
        if      (size >= 4 && memcmp(buffer, "\xFF\xFE\x00\x00", 4) == 0)
        {
            enc = wxFONTENCODING_UTF32LE;
            m_BOMSizeInBytes = 4;
            m_UseBOM = true;
        }
        else if (size >= 4 && memcmp(buffer, "\xFE\xFF\x00\x00", 4) == 0)
        {
            // FE FF 00 00  UCS-4, unusual octet order BOM (3412)
            // X-ISO-10646-UCS-4-3412 can not (yet) be handled by wxWidgets
            enc = (wxFontEncoding)-1;
        }
        else if (size >= 4 && memcmp(buffer, "\x00\x00\xFE\xFF", 4) == 0)
        {
            enc = wxFONTENCODING_UTF32BE;
            m_BOMSizeInBytes = 4;
            m_UseBOM = true;
        }
        else if (size >= 4 && memcmp(buffer, "\x00\x00\xFF\xFE", 4) == 0)
        {
            // 00 00 FF FE  UCS-4, unusual octet order BOM (2143)
            // X-ISO-10646-UCS-4-2143 can not (yet) be handled by wxWidgets
            enc = (wxFontEncoding)-1;
        }
        else if (             memcmp(buffer, "\xFF\xFE", 2) == 0)
        {
            enc = wxFONTENCODING_UTF16LE;
            m_BOMSizeInBytes = 2;
            m_UseBOM = true;
        }
        else if (             memcmp(buffer, "\xFE\xFF", 2) == 0)
        {
            enc = wxFONTENCODING_UTF16BE;
            m_BOMSizeInBytes = 2;
            m_UseBOM = true;
        }
        else if (size >= 3 && memcmp(buffer, "\xEF\xBB\xBF", 3) == 0)
        {
            enc = wxFONTENCODING_UTF8;
            m_BOMSizeInBytes = 3;
            m_UseBOM = true;
        }
        else if (size >= 5 && memcmp(buffer, "\x2B\x2F\x76\x38\x2D", 5) == 0)
        {
            enc = wxFONTENCODING_UTF7;
            m_BOMSizeInBytes = 5;
            m_UseBOM = true;
        }

        buff_ptr += m_BOMSizeInBytes;
    }

    // If the file starts with a leading < (less) sign, it is probably an XML file
    // and we can determine the encoding by how the sign is encoded.
    if (enc == wxFONTENCODING_DEFAULT && size >= 2)
    {
        if      (size >= 4 && memcmp(buffer, "\x3C\x00\x00\x00", 4) == 0) enc = wxFONTENCODING_UTF32LE;
        else if (size >= 4 && memcmp(buffer, "\x00\x00\x00\x3C", 4) == 0) enc = wxFONTENCODING_UTF32BE;
        else if (             memcmp(buffer, "\x3C\x00",         2) == 0) enc = wxFONTENCODING_UTF16LE;
        else if (             memcmp(buffer, "\x00\x3C",         2) == 0) enc = wxFONTENCODING_UTF16BE;
    }

    // Unicode Detection
    if (enc == wxFONTENCODING_DEFAULT)
    {
        unsigned int null_byte_count  = 0;
        unsigned int utf_bytes        = 0;
        unsigned int good_utf_count   = 0;
        unsigned int bad_utf_count    = 0;
        unsigned int bad_utf32_count  = 0;
        unsigned int bad_utf16_count  = 0;
        unsigned int nl_utf32le_count = 0;
        unsigned int nl_utf32be_count = 0;
        unsigned int nl_utf16le_count = 0;
        unsigned int nl_utf16be_count = 0;

        while (buff_ptr != buff_end)
        {
            if (*buff_ptr == 0) ++null_byte_count;

            // Detect UTF-8 by scanning for invalid sequences
            if (utf_bytes == 0)
            {
                if ((*buff_ptr & 0xC0) == 0x80 || *buff_ptr == 0)
                    ++bad_utf_count;
                else
                {
                    const char c = *buff_ptr;
                    utf_bytes = 5; // invalid length
                    if      ((c & 0x80) == 0x00) utf_bytes = 1;
                    else if ((c & 0xE0) == 0xC0) utf_bytes = 2;
                    else if ((c & 0xF0) == 0xE0) utf_bytes = 3;
                    else if ((c & 0xF8) == 0xF0) utf_bytes = 4;
                    if (utf_bytes > 3)
                    {
                        ++bad_utf_count;
                        utf_bytes = 0;
                    }
                }
            }
            else if ((*buff_ptr & 0xC0) == 0x80)
            {
                --utf_bytes;
                if (utf_bytes == 0)
                    ++good_utf_count;
            }
            else
            {
                ++bad_utf_count;
                utf_bytes = 0;
            }

            // Detect UTF-32 by scanning for newlines (and lack of null chars)
            if ((wxUIntPtr)buff_ptr % 4 == 0 && buff_ptr+4 <= buff_end)
            {
                if (*((wxUint32*)buff_ptr) == 0                        ) ++bad_utf32_count;
                if (*((wxUint32*)buff_ptr) == wxUINT32_SWAP_ON_BE(0x0A)) ++nl_utf32le_count;
                if (*((wxUint32*)buff_ptr) == wxUINT32_SWAP_ON_LE(0x0A)) ++nl_utf32be_count;
            }

            // Detect UTF-16 by scanning for newlines (and lack of null chars)
            if ((wxUIntPtr)buff_ptr % 2 == 0 && buff_ptr+4 <= buff_end)
            {
                if (*((wxUint16*)buff_ptr) == 0)                         ++bad_utf16_count;
                if (*((wxUint16*)buff_ptr) == wxUINT16_SWAP_ON_BE(0x0A)) ++nl_utf16le_count;
                if (*((wxUint16*)buff_ptr) == wxUINT16_SWAP_ON_LE(0x0A)) ++nl_utf16be_count;
            }

            ++buff_ptr;
        }

        if      (bad_utf_count   == 0)                                  enc = wxFONTENCODING_UTF8;
        else if (bad_utf32_count == 0 && nl_utf32le_count > size / 400) enc = wxFONTENCODING_UTF32LE;
        else if (bad_utf32_count == 0 && nl_utf32be_count > size / 400) enc = wxFONTENCODING_UTF32BE;
        else if (bad_utf16_count == 0 && nl_utf16le_count > size / 200) enc = wxFONTENCODING_UTF16LE;
        else if (bad_utf16_count == 0 && nl_utf16be_count > size / 200) enc = wxFONTENCODING_UTF16BE;
        else if (null_byte_count)
            return false; // Maybe this is a binary file?
    }

    if (enc != wxFONTENCODING_DEFAULT)
    {
        m_Encoding = enc; // Success.
        return true;
    }

    // If we can't detect encoding and it does not contain null bytes
    // just ignore it and try backup-procedures (Mozilla) later...
    return false;
}
예제 #17
0
wxDataInputStream::wxDataInputStream(wxInputStream& s, const wxMBConv& conv)
  : m_input(&s), m_be_order(false), m_conv(conv.Clone())
#else
wxDataInputStream::wxDataInputStream(wxInputStream& s)
  : m_input(&s), m_be_order(false)
#endif
{
}

wxDataInputStream::~wxDataInputStream()
{
#if wxUSE_UNICODE
    delete m_conv;
#endif // wxUSE_UNICODE
}

#if wxHAS_INT64
wxUint64 wxDataInputStream::Read64()
{
  wxUint64 tmp;
  Read64(&tmp, 1);
  return tmp;
}
#endif // wxHAS_INT64

wxUint32 wxDataInputStream::Read32()
{
  wxUint32 i32;

  m_input->Read(&i32, 4);

  if (m_be_order)
    return wxUINT32_SWAP_ON_LE(i32);
  else
    return wxUINT32_SWAP_ON_BE(i32);
}

wxUint16 wxDataInputStream::Read16()
{
  wxUint16 i16;

  m_input->Read(&i16, 2);

  if (m_be_order)
    return wxUINT16_SWAP_ON_LE(i16);
  else
    return wxUINT16_SWAP_ON_BE(i16);
}

wxUint8 wxDataInputStream::Read8()
{
  wxUint8 buf;

  m_input->Read(&buf, 1);
  return (wxUint8)buf;
}

double wxDataInputStream::ReadDouble()
{
#if wxUSE_APPLE_IEEE
  char buf[10];

  m_input->Read(buf, 10);
  return ConvertFromIeeeExtended((const wxInt8 *)buf);
#else
  return 0.0;
#endif
}
예제 #18
0
파일: Strings.cpp 프로젝트: GunioRobot/e
bool DetectTextEncoding(const char* buffer, size_t len, wxFontEncoding& encoding, unsigned int& BOM_len) {
	wxASSERT(buffer);
	if (!buffer || len == 0) return false;

	const char* buff_ptr = buffer;
	const char* buff_end = &buffer[len];
	wxFontEncoding enc = wxFONTENCODING_DEFAULT;

	// Check if the buffer starts with a BOM (Byte Order Marker)
	if (len >= 2) {
		if (len >= 4 && memcmp(buffer, "\xFF\xFE\x00\x00", 4) == 0) {enc = wxFONTENCODING_UTF32LE; BOM_len = 4;}
		else if (len >= 4 && memcmp(buffer, "\x00\x00\xFE\xFF", 4) == 0) {enc = wxFONTENCODING_UTF32BE; BOM_len = 4;}
		else if (memcmp(buffer, "\xFF\xFE", 2) == 0) {enc = wxFONTENCODING_UTF16LE; BOM_len = 2;}
		else if (memcmp(buffer, "\xFE\xFF", 2) == 0) {enc = wxFONTENCODING_UTF16BE; BOM_len = 2;}
		else if (len >= 3 && memcmp(buffer, "\xEF\xBB\xBF", 3) == 0) {enc = wxFONTENCODING_UTF8; BOM_len = 3;}
		else if (len >= 5 && memcmp(buffer, "\x2B\x2F\x76\x38\x2D", 5) == 0) {enc = wxFONTENCODING_UTF7; BOM_len = 5;}

		buff_ptr += BOM_len;
	}

	// If the file starts with a leading < (less) sign, it is probably an XML file
	// and we can determine the encoding by how the sign is encoded.
	if (enc == wxFONTENCODING_DEFAULT && len >= 2) {
		if (len >= 4 && memcmp(buffer, "\x3C\x00\x00\x00", 4) == 0) enc = wxFONTENCODING_UTF32LE;
		else if (len >= 4 && memcmp(buffer, "\x00\x00\x00\x3C", 4) == 0) enc = wxFONTENCODING_UTF32BE;
		else if (memcmp(buffer, "\x3C\x00", 2) == 0) enc = wxFONTENCODING_UTF16LE;
		else if (memcmp(buffer, "\x00\x3C", 2) == 0) enc = wxFONTENCODING_UTF16BE;
	}

	// Unicode Detection
	if (enc == wxFONTENCODING_DEFAULT) {
		unsigned int null_byte_count = 0;
		unsigned int utf_bytes = 0;
		unsigned int good_utf_count = 0;
		unsigned int bad_utf_count = 0;
		unsigned int bad_utf32_count = 0;
		unsigned int bad_utf16_count = 0;
		unsigned int nl_utf32le_count = 0;
		unsigned int nl_utf32be_count = 0;
		unsigned int nl_utf16le_count = 0;
		unsigned int nl_utf16be_count = 0;

		while (buff_ptr != buff_end) {
			if (*buff_ptr == 0) ++null_byte_count;

			// Detect UTF-8 by scanning for invalid sequences
			if (utf_bytes == 0) {
				if ((*buff_ptr & 0xC0) == 0x80 || *buff_ptr == 0) ++bad_utf_count;
				else {
					utf_bytes = utf8_len(*buff_ptr) - 1;
					if (utf_bytes > 3) {
						++bad_utf_count;
						utf_bytes = 0;
					}
				}
			}
			else if ((*buff_ptr & 0xC0) == 0x80) {
				--utf_bytes;
				if (utf_bytes == 0) ++good_utf_count;
			}
			else {
				++bad_utf_count;
				utf_bytes = 0;
			}

			// Detect UTF-32 by scanning for newlines (and lack of null chars)
			if ((uintptr_t)buff_ptr % 4 == 0 && buff_ptr+4 <= buff_end) {
				if (*((wxUint32*)buff_ptr) == 0) ++bad_utf32_count;
				if (*((wxUint32*)buff_ptr) == wxUINT32_SWAP_ON_BE(0x0A)) ++nl_utf32le_count;
				if (*((wxUint32*)buff_ptr) == wxUINT32_SWAP_ON_LE(0x0A)) ++nl_utf32be_count;
			}

			// Detect UTF-16 by scanning for newlines (and lack of null chars)
			if ((uintptr_t)buff_ptr % 2 == 0  && buff_ptr+4 <= buff_end) {
				if (*((wxUint16*)buff_ptr) == 0) ++bad_utf16_count;
				if (*((wxUint16*)buff_ptr) == wxUINT16_SWAP_ON_BE(0x0A)) ++nl_utf16le_count;
				if (*((wxUint16*)buff_ptr) == wxUINT16_SWAP_ON_LE(0x0A)) ++nl_utf16be_count;
			}

			++buff_ptr;
		}

		if (bad_utf_count == 0) enc = wxFONTENCODING_UTF8;
		else if (bad_utf32_count == 0 && nl_utf32le_count > len / 400) enc = wxFONTENCODING_UTF32LE;
		else if (bad_utf32_count == 0 && nl_utf32be_count > len / 400) enc = wxFONTENCODING_UTF32BE;
		else if (bad_utf16_count == 0 && nl_utf16le_count > len / 200) enc = wxFONTENCODING_UTF16LE;
		else if (bad_utf16_count == 0 && nl_utf16be_count > len / 200) enc = wxFONTENCODING_UTF16BE;
		else if (null_byte_count) return false; // Maybe this is a binary file?
	}

	// If we can't detect encoding and it does not contain null bytes just set it to the default encoding.
	if (enc == wxFONTENCODING_DEFAULT)
		enc = wxFONTENCODING_SYSTEM;

	encoding = enc;
	return true;
}
예제 #19
0
// -----------------------------------------------------------------------------
// Writes the disk archive to a MemChunk.
// Returns true if successful, false otherwise
// -----------------------------------------------------------------------------
bool DiskArchive::write(MemChunk& mc, bool update)
{
	// Clear current data
	mc.clear();

	// Get archive tree as a list
	vector<ArchiveEntry*> entries;
	getEntryTreeAsList(entries);

	// Process entry list
	uint32_t num_entries  = 0;
	uint32_t size_entries = 0;
	for (unsigned a = 0; a < entries.size(); a++)
	{
		// Ignore folder entries
		if (entries[a]->getType() == EntryType::folderType())
			continue;

		// Increment directory offset and size
		size_entries += entries[a]->getSize();
		++num_entries;
	}

	// Init data size
	uint32_t start_offset = 8 + (num_entries * 72);
	uint32_t offset       = start_offset;
	mc.reSize(size_entries + start_offset, false);

	// Write header
	num_entries = wxUINT32_SWAP_ON_LE(num_entries);
	mc.seek(0, SEEK_SET);
	mc.write(&num_entries, 4);

	// Write directory
	for (unsigned a = 0; a < entries.size(); a++)
	{
		// Skip folders
		if (entries[a]->getType() == EntryType::folderType())
			continue;

		// Update entry
		if (update)
		{
			entries[a]->setState(0);
			entries[a]->exProp("Offset") = (int)offset;
		}

		// Check entry name
		string name = entries[a]->getPath(true);
		name.Replace("/", "\\");
		// The leading "GAME:\" part of the name means there is only 58 usable characters for path
		if (name.Len() > 58)
		{
			LOG_MESSAGE(
				1, "Warning: Entry %s path is too long (> 58 characters), putting it in the root directory", name);
			wxFileName fn(name);
			name = fn.GetFullName();
			if (name.Len() > 57)
				name.Truncate(57);
			// Add leading "\"
			name = "\\" + name;
		}
		name = "GAME:" + name;

		DiskEntry dent;

		// Write entry name
		// The names field are padded with FD for doom.disk, FE for doom2.disk. No idea whether
		// a non-null padding is actually required, though. It probably should work with anything.
		memset(dent.name, 0xFE, 64);
		memcpy(dent.name, CHR(name), name.Length());
		dent.name[name.Length()] = 0;

		// Write entry offset
		dent.offset = wxUINT32_SWAP_ON_LE(offset - start_offset);

		// Write entry size
		dent.length = wxUINT32_SWAP_ON_LE(entries[a]->getSize());

		// Actually write stuff
		mc.write(&dent, 72);

		// Increment/update offset
		offset += wxUINT32_SWAP_ON_LE(dent.length);
	}

	// Finish writing header
	size_entries = wxUINT32_SWAP_ON_LE(size_entries);
	mc.write(&size_entries, 4);

	// Write entry data
	for (unsigned a = 0; a < entries.size(); a++)
	{
		// Skip folders
		if (entries[a]->getType() == EntryType::folderType())
			continue;

		// Write data
		mc.write(entries[a]->getData(), entries[a]->getSize());
	}

	return true;
}
예제 #20
0
void wxArchive::SaveUint32(wxUint32 value)
{
	wxUint32 tmpval = wxUINT32_SWAP_ON_LE(value);
	if(CanStore())
        m_odstr.Write(&tmpval, sizeof(wxUint32));
}