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; }
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); }
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); }
//--------------------------------------------------------------------------------------- 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; }
// ----------------------------------------------------------------------------- // 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; }
/*--------------------------------------------------------------------------*/ 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); }
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; }
// ----------------------------------------------------------------------------- // 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; }
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); }
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; }
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; }
// ----------------------------------------------------------------------------- // 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; }
/* 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; }
/* 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; }
/* 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; }
// 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; }
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 }
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; }
// ----------------------------------------------------------------------------- // 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; }
void wxArchive::SaveUint32(wxUint32 value) { wxUint32 tmpval = wxUINT32_SWAP_ON_LE(value); if(CanStore()) m_odstr.Write(&tmpval, sizeof(wxUint32)); }