/// Extracts the nth substring from a delimited string /// This is a wxWidgets port of MFC's AfxExtractSubString /// @param string Holds the returned substring /// @param fullString String to extract the substring from /// @param subString Zero-based index of the substring to extract /// @param separator Character used to separator the substrings /// @return True if the substring was extracted, false if not bool wxExtractSubString(wxString& string, const wxChar* fullString, wxUint32 subString, wxChar separator) { //------Last Verified------// // - Nov 27, 2004 wxCHECK(fullString != (wxChar*)NULL, false); string.Clear(); while (subString--) { fullString = wxStrchr(fullString, separator); if (fullString == NULL) { string.Clear(); // return empty string as well return (false); } fullString++; // point past the separator } const wxChar* end = wxStrchr(fullString, separator); wxInt32 length = (end == NULL) ? wxStrlen_(fullString) : (wxInt32)(end - fullString); wxASSERT(length >= 0); memcpy(string.GetWriteBuf(length), fullString, length * sizeof(wxChar)); string.UngetWriteBuf(); // Need to call ReleaseBuffer // after calling GetBufferSetLength return (true); }
void CrtTestCase::Strchr() { // test that searching for a wide character in a narrow string simply // doesn't find it but doesn't fail with an assert (#11487) const wxUniChar smiley = *wxString::FromUTF8("\xe2\x98\xba").begin(); CPPUNIT_ASSERT( !wxStrchr("hello", smiley) ); // but searching for an explicitly wide character does find it CPPUNIT_ASSERT( wxStrchr(wxString::FromUTF8(":-) == \xe2\x98\xba"), static_cast<wchar_t>(smiley)) ); }
// -------------------------------------------------------------------------------- // wxString guFileDnDEncode( const wxString &file ) { wxString RetVal; wxString HexCode; size_t index; wxCharBuffer CharBuffer = file.ToUTF8(); size_t StrLen = strlen( CharBuffer ); for( index = 0; index < StrLen; index++ ) { wxChar C = CharBuffer[ index ]; { static const wxChar marks[] = wxT( " -_.\"/+!~*()'[]%" ); //~!@#$&*()=:/,;?+' if( ( C >= 'a' && C <= 'z' ) || ( C >= 'A' && C <= 'Z' ) || ( C >= '0' && C <= '9' ) || wxStrchr( marks, C ) ) { RetVal += C; } else { HexCode.Printf( wxT( "%%%02X" ), C & 0xFF ); RetVal += HexCode; } } } return RetVal; }
inline wxString GetNextField(const wxString& str, size_t& cookie) { // These are taken to seperate "fields" static const wxChar* s_delims = wxT("\t\n\x0b\x0c\r !\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~"); wxString field; ECharType curType = ECTNone; for (; cookie < str.Length(); ++cookie) { wxChar c = str[cookie]; if ((c >= wxT('0')) && (c <= wxT('9'))) { if (curType == ECTText) { break; } curType = ECTInteger; field += c; } else if (wxStrchr(s_delims, c)) { if (curType == ECTNone) { continue; } else { break; } } else { if (curType == ECTInteger) { break; } curType = ECTText; field += c; } } return field; }
wxString wxFileConfig::GetLocalFileName(const wxChar *szFile) { #ifdef __VMS__ // On VMS I saw the problem that the home directory was appended // twice for the configuration file. Does that also happen for other // platforms? wxString str = wxT( '.' ); #else wxString str = GetLocalDir(); #endif #if defined( __UNIX__ ) && !defined( __VMS ) str << wxT('.'); #endif str << szFile; #ifdef __WXMSW__ if ( wxStrchr(szFile, wxT('.')) == NULL ) str << wxT(".ini"); #endif #ifdef __WXMAC__ str << " Preferences"; #endif return str; }
bool wxGetFullHostName(wxChar *buf, int sz) { bool ok = wxGetHostNameInternal(buf, sz); if ( ok ) { if ( !wxStrchr(buf, wxT('.')) ) { struct hostent *host = gethostbyname(wxSafeConvertWX2MB(buf)); if ( !host ) { wxLogSysError(_("Cannot get the official hostname")); ok = false; } else { // the canonical name wxStrlcpy(buf, wxSafeConvertMB2WX(host->h_name), sz); } } //else: it's already a FQDN (BSD behaves this way) } return ok; }
// -------------------------------------------------------------------------------- // wxString guURLEncode( const wxString &url ) { static const wxChar marks[] = wxT( "-_.\"!~*()'" ); wxString RetVal; wxChar CurChar; wxCharBuffer CharBuffer = url.ToUTF8(); int Index; int Count = strlen( CharBuffer ); for( Index = 0; Index < Count; ++Index ) { CurChar = CharBuffer[ Index ]; if( ( CurChar >= 'a' && CurChar <= 'z' ) || ( CurChar >= 'A' && CurChar <= 'Z' ) || ( CurChar >= '0' && CurChar <= '9' ) || wxStrchr( marks, CurChar ) ) { RetVal += CurChar; } else if( CurChar == wxT( ' ' ) ) { RetVal += wxT( "+" ); } else { RetVal += wxString::Format( wxT( "%%%02X" ), CurChar & 0xFF ); } } //guLogMessage( wxT( "URLEncode: '%s' => '%s'" ), url.c_str(), RetVal.c_str() ); return RetVal; }
void wxMacConvertNewlines10To13( wxChar * data ) { wxChar * buf = data ; while( (buf=wxStrchr(buf,0x0a)) != NULL ) { *buf = 0x0d ; buf++ ; } }
int ecUtils::Chop(const wxString& str, wxArrayString &ar, const wxString& sep, bool bObserveStrings/*=false*/,bool bBackslashQuotes/*=false*/) { ar.Clear(); const wxChar* pszSep = (const wxChar*) sep; const wxChar* psz = (const wxChar*) str; int i=0; for(;;){ // Skip multiple separators while(*psz && wxStrchr(pszSep,*psz)){ psz++; } if(!*psz){ return i; } wxString strTok; if(bObserveStrings){ bool bInString=FALSE; do{ if(*psz == wxT('\\') && bBackslashQuotes && psz[1]){ strTok += psz[1]; psz++; } else if(*psz == wxT('"')){ bInString ^= 1; } else if (!bInString && *psz && NULL != wxStrchr(pszSep,*psz)) { break; } else { strTok+=*psz; } } while (*++psz); } else { const wxChar* pszStart=psz; do { psz++; } while (*psz && ! wxStrchr(pszSep,*psz)); strTok=wxString(pszStart,psz-pszStart); } ar.Add(strTok); i++; } return ar.GetCount(); }
bool wxDatabaseConfig::RenameEntry(const wxString& oldName, const wxString& newName) { wxASSERT_MSG(!wxStrchr(oldName, wxCONFIG_PATH_SEPARATOR), wxT("RenameEntry(): paths are not supported")); dbentries entries; if ( FindEntries(newName, entries)) return false; entries.clear(); if (!FindEntries(oldName, entries)) return false; return WriteEntry(entries[0], newName, entries[0].value); }
bool wxDatabaseConfig::WriteEntry(dbentry& entry, const wxString& name, const wxString& value) { if (name.empty()) return false; wxASSERT_MSG(!wxStrchr(name, wxCONFIG_PATH_SEPARATOR), wxT("WriteEntry(): paths are not supported")); m_pStatementSqlEditEntry->SetParamInt(3, entry.id); m_pStatementSqlEditEntry->SetParamString(1, name); m_pStatementSqlEditEntry->SetParamString(2, value); m_self->ExecuteStatement(m_pStatementSqlEditEntry); return true; }
bool wxRegKey::Rename(const wxString& szNewName) { wxCHECK_MSG( !m_strKey.empty(), false, wxT("registry hives can't be renamed") ); if ( !Exists() ) { wxLogError(_("Registry key '%s' does not exist, cannot rename it."), GetFullName(this)); return false; } // do we stay in the same hive? bool inSameHive = !wxStrchr(szNewName, REG_SEPARATOR); // construct the full new name of the key wxRegKey keyDst; if ( inSameHive ) { // rename the key to the new name under the same parent wxString strKey = m_strKey.BeforeLast(REG_SEPARATOR); if ( !strKey.empty() ) { // don't add '\\' in the start if strFullNewName is empty strKey += REG_SEPARATOR; } strKey += szNewName; keyDst.SetName(GetStdKeyFromHkey(m_hRootKey), strKey); } else { // this is the full name already keyDst.SetName(szNewName); } bool ok = keyDst.Create(false /* fail if alredy exists */); if ( !ok ) { wxLogError(_("Registry key '%s' already exists."), GetFullName(&keyDst)); } else { ok = Copy(keyDst) && DeleteSelf(); } if ( !ok ) { wxLogError(_("Failed to rename the registry key '%s' to '%s'."), GetFullName(this), GetFullName(&keyDst)); } else { m_hRootKey = keyDst.m_hRootKey; m_strKey = keyDst.m_strKey; } return ok; }
/* Returns a string which is equal to the string pointed to by p, but up to the point where p contains an character that's not allowed. Allowable characters are letters and numbers, and characters pointed to by the parameter allowedChars. For example, if p points to "abcde-@-_", and allowedChars is "-_", this function returns "abcde-". */ static wxString GetOptionName(const wxChar *p, const wxChar *allowedChars) { wxString argName; while ( *p && (wxIsalnum(*p) || wxStrchr(allowedChars, *p)) ) { argName += *p++; } return argName; }
void wxMacConvertNewlines10To13( wxString * data ) { size_t len = data->Length() ; if ( data->Length() == 0 || wxStrchr(data->c_str(),0x0a)==NULL) return ; wxString temp(*data) ; wxStringBuffer buf(*data,len ) ; memcpy( buf , temp.c_str() , (len+1)*sizeof(wxChar) ) ; wxMacConvertNewlines10To13( buf ) ; }
/* Returns a string which is equal to the string pointed to by p, but up to the point where p contains an character that's not allowed. Allowable characters are letters and numbers, and characters pointed to by the parameter allowedChars. For example, if p points to "abcde-@-_", and allowedChars is "-_", this function returns "abcde-". */ static wxString GetOptionName(wxString::const_iterator p, wxString::const_iterator end, const wxChar *allowedChars) { wxString argName; while ( p != end && (wxIsalnum(*p) || wxStrchr(allowedChars, *p)) ) { argName += *p++; } return argName; }
void StringTestCase::Constructors() { CPPUNIT_ASSERT_EQUAL( "", wxString('Z', 0) ); CPPUNIT_ASSERT_EQUAL( "Z", wxString('Z') ); CPPUNIT_ASSERT_EQUAL( "ZZZZ", wxString('Z', 4) ); CPPUNIT_ASSERT_EQUAL( "Hell", wxString("Hello", 4) ); CPPUNIT_ASSERT_EQUAL( "Hello", wxString("Hello", 5) ); #if wxUSE_UNICODE CPPUNIT_ASSERT_EQUAL( L"", wxString(L'Z', 0) ); CPPUNIT_ASSERT_EQUAL( L"Z", wxString(L'Z') ); CPPUNIT_ASSERT_EQUAL( L"ZZZZ", wxString(L'Z', 4) ); CPPUNIT_ASSERT_EQUAL( L"Hell", wxString(L"Hello", 4) ); CPPUNIT_ASSERT_EQUAL( L"Hello", wxString(L"Hello", 5) ); #endif // wxUSE_UNICODE CPPUNIT_ASSERT_EQUAL( 0, wxString(wxString(), 17).length() ); #if wxUSE_UNICODE_UTF8 // This string has 3 characters (<h>, <e'> and <l>), not 4 when using UTF-8 // locale! if ( wxConvLibc.IsUTF8() ) { wxString s3("h\xc3\xa9llo", 4); CPPUNIT_ASSERT_EQUAL( 3, s3.length() ); CPPUNIT_ASSERT_EQUAL( 'l', (char)s3[2] ); } #endif // wxUSE_UNICODE_UTF8 static const char *s = "?really!"; const char *start = wxStrchr(s, 'r'); const char *end = wxStrchr(s, '!'); CPPUNIT_ASSERT_EQUAL( "really", wxString(start, end) ); // test if creating string from NULL C pointer works: CPPUNIT_ASSERT_EQUAL( "", wxString((const char *)NULL) ); }
wxString wxFileConfig::GetGlobalFileName(const wxChar *szFile) { wxString str = GetGlobalDir(); str << szFile; if ( wxStrchr(szFile, wxT('.')) == NULL ) #ifdef __UNIX__ str << wxT(".conf"); #elif defined( __WXMAC__ ) str << " Preferences"; #else // Windows str << wxT(".ini"); #endif // UNIX/Win return str; }
bool wxGetHostName(wxChar *buf, int sz) { bool ok = wxGetHostNameInternal(buf, sz); if ( ok ) { // BSD systems return the FQDN, we only want the hostname, so extract // it (we consider that dots are domain separators) wxChar *dot = wxStrchr(buf, wxT('.')); if ( dot ) { // nuke it *dot = wxT('\0'); } } return ok; }
bool wxDatabaseConfig::AddEntry(dbentry& parent, const wxString& name, const wxString* value) { if (name.empty()) return false; wxASSERT_MSG(!wxStrchr(name, wxCONFIG_PATH_SEPARATOR), wxT("AddEntry(): paths are not supported")); m_pStatementSqlAddEntry->SetParamInt(1, parent.id); m_pStatementSqlAddEntry->SetParamString(2, name); if (value == NULL) { m_pStatementSqlAddEntry->SetParamNull(3); } else { wxString strValue(*value); m_pStatementSqlAddEntry->SetParamString(3, strValue); } m_self->ExecuteStatement(m_pStatementSqlAddEntry); return true; }
// sanitize entry or group name: insert '\\' before any special characters static wxString FilterOutEntryName(const wxString& str) { wxString strResult; strResult.Alloc(str.Len()); for ( const wxChar *pc = str.c_str(); *pc != wxT('\0'); pc++ ) { wxChar c = *pc; // we explicitly allow some of "safe" chars and 8bit ASCII characters // which will probably never have special meaning // NB: note that wxCONFIG_IMMUTABLE_PREFIX and wxCONFIG_PATH_SEPARATOR // should *not* be quoted if ( !wxIsalnum(c) && !wxStrchr(wxT("@_/-!.*%"), c) && ((c & 0x80) == 0) ) strResult += wxT('\\'); strResult += c; } return strResult; }
void wxDatabaseConfig::GetChildren(dbentry& parent, dbentries* groups, dbentries* entries, bool recursive) { dbentries wild; m_self->FindEntries(parent.path+wxCONFIG_PATH_SEPARATOR+'%', wild); for (dbentries::iterator it = wild.begin(); it != wild.end(); ++it) { wxString localpath(it->path.Right(it->path.Length()-parent.path.Length()-1)); if (!recursive && wxStrchr(localpath, wxCONFIG_PATH_SEPARATOR)) continue; if (it->isgroup) { if (groups == NULL) continue; groups->push_back(*it); } else { if (entries == NULL) continue; entries->push_back(*it); } } }
bool IsSpaceChar(wxChar c, const wxChar *spaceChars = wxT("\t ")) { return wxStrchr(spaceChars, c) != NULL; }
bool MfStatusCache::DoLoad(const wxTextFile& file, int version) { bool isFmtOk = true; CacheFileFormat fmt; if ( version == BuildVersion(1, 1) ) { fmt = CacheFile_1_1; } else if ( version == BuildVersion(1, 0) ) { fmt = CacheFile_1_0; } else { fmt = CacheFile_Max; } // read the data wxString str, name; str.Alloc(1024); // avoid extra memory allocations name.Alloc(1024); MailFolderStatus status; size_t count = file.GetLineCount(); for ( size_t n = 1; n < count; n++ ) { str = file[n]; // first get the end of the full folder name knowing that we should // skip all "::" as they could have only resulted from quoting a ':' // in the folder name and so the loop below looks for the first ':' // not followed by another ':' const wxChar *p = wxStrchr(str, CACHE_DELIMITER_CH); while ( p && p[1] == CACHE_DELIMITER_CH ) { p = wxStrchr(p + 2, CACHE_DELIMITER_CH); } if ( !p ) { wxLogError(_("Missing '%c' at line %d."), CACHE_DELIMITER_CH, n + 1); isFmtOk = false; break; } name = wxString(str.c_str(), p); // now unquote ':' which were doubled by Save() name.Replace(CACHE_DELIMITER CACHE_DELIMITER, CACHE_DELIMITER); // get the rest status.Init(); switch ( fmt ) { case CacheFile_1_0: isFmtOk = wxSscanf(p + 1, _T("%lu") CACHE_DELIMITER _T("%lu") CACHE_DELIMITER _T("%lu"), &status.total, &status.unread, &status.flagged) == 3; break; default: FAIL_MSG( _T("unknown cache file format") ); // fall through nevertheless case CacheFile_1_1: isFmtOk = wxSscanf(p + 1, _T("%lu") CACHE_DELIMITER _T("%lu") CACHE_DELIMITER _T("%lu") CACHE_DELIMITER _T("%lu"), &status.total, &status.newmsgs, &status.unread, &status.flagged) == 4; } if ( !isFmtOk ) { wxLogError(_("Missing field(s) at line %d."), n + 1); break; } // ignore the folders which were deleted during the last program run MFolder *folder = MFolder::Get(name); if ( folder ) { folder->DecRef(); // do add the entry to the cache size_t entry = m_folderNames.Add(name); m_folderData.Insert(new MailFolderStatus(status), entry); } else { wxLogDebug(_T("Removing deleted folder '%s' from status cache."), name.c_str()); } } if ( !isFmtOk ) { wxLogWarning(_("Your mail folder status cache file (%s) was corrupted."), file.GetName()); return false; } return true; }
bool wxLocale::Init(int language, int flags) { #if WXWIN_COMPATIBILITY_2_8 wxASSERT_MSG( !(flags & wxLOCALE_CONV_ENCODING), wxS("wxLOCALE_CONV_ENCODING is no longer supported, add charset to your catalogs") ); #endif bool ret = true; int lang = language; if (lang == wxLANGUAGE_DEFAULT) { // auto detect the language lang = GetSystemLanguage(); } // We failed to detect system language, so we will use English: if (lang == wxLANGUAGE_UNKNOWN) { return false; } const wxLanguageInfo *info = GetLanguageInfo(lang); // Unknown language: if (info == NULL) { wxLogError(wxS("Unknown language %i."), lang); return false; } wxString name = info->Description; wxString canonical = info->CanonicalName; wxString locale; // Set the locale: #if defined(__OS2__) const char *retloc = wxSetlocale(LC_ALL , wxEmptyString); #elif defined(__UNIX__) && !defined(__WXMAC__) if (language != wxLANGUAGE_DEFAULT) locale = info->CanonicalName; const char *retloc = wxSetlocaleTryUTF8(LC_ALL, locale); const wxString langOnly = ExtractLang(locale); if ( !retloc ) { // Some C libraries don't like xx_YY form and require xx only retloc = wxSetlocaleTryUTF8(LC_ALL, langOnly); } #if wxUSE_FONTMAP // some systems (e.g. FreeBSD and HP-UX) don't have xx_YY aliases but // require the full xx_YY.encoding form, so try using UTF-8 because this is // the only thing we can do generically // // TODO: add encodings applicable to each language to the lang DB and try // them all in turn here if ( !retloc ) { const wxChar **names = wxFontMapperBase::GetAllEncodingNames(wxFONTENCODING_UTF8); while ( *names ) { retloc = wxSetlocale(LC_ALL, locale + wxS('.') + *names++); if ( retloc ) break; } } #endif // wxUSE_FONTMAP if ( !retloc ) { // Some C libraries (namely glibc) still use old ISO 639, // so will translate the abbrev for them wxString localeAlt; if ( langOnly == wxS("he") ) localeAlt = wxS("iw") + ExtractNotLang(locale); else if ( langOnly == wxS("id") ) localeAlt = wxS("in") + ExtractNotLang(locale); else if ( langOnly == wxS("yi") ) localeAlt = wxS("ji") + ExtractNotLang(locale); else if ( langOnly == wxS("nb") ) localeAlt = wxS("no_NO"); else if ( langOnly == wxS("nn") ) localeAlt = wxS("no_NY"); if ( !localeAlt.empty() ) { retloc = wxSetlocaleTryUTF8(LC_ALL, localeAlt); if ( !retloc ) retloc = wxSetlocaleTryUTF8(LC_ALL, ExtractLang(localeAlt)); } } if ( !retloc ) ret = false; #ifdef __AIX__ // at least in AIX 5.2 libc is buggy and the string returned from // setlocale(LC_ALL) can't be passed back to it because it returns 6 // strings (one for each locale category), i.e. for C locale we get back // "C C C C C C" // // this contradicts IBM own docs but this is not of much help, so just work // around it in the crudest possible manner char* p = const_cast<char*>(wxStrchr(retloc, ' ')); if ( p ) *p = '\0'; #endif // __AIX__ #elif defined(__WIN32__) const char *retloc = "C"; if ( language != wxLANGUAGE_DEFAULT ) { if ( info->WinLang == 0 ) { wxLogWarning(wxS("Locale '%s' not supported by OS."), name.c_str()); // retloc already set to "C" } else // language supported by Windows { // Windows CE doesn't have SetThreadLocale() and there doesn't seem // to be any equivalent #ifndef __WXWINCE__ const wxUint32 lcid = info->GetLCID(); // change locale used by Windows functions ::SetThreadLocale(lcid); #endif // and also call setlocale() to change locale used by the CRT locale = info->GetLocaleName(); if ( locale.empty() ) { ret = false; } else // have a valid locale { retloc = wxSetlocale(LC_ALL, locale); } } } else // language == wxLANGUAGE_DEFAULT { retloc = wxSetlocale(LC_ALL, wxEmptyString); } #if wxUSE_UNICODE && (defined(__VISUALC__) || defined(__MINGW32__)) // VC++ setlocale() (also used by Mingw) can't set locale to languages that // can only be written using Unicode, therefore wxSetlocale() call fails // for such languages but we don't want to report it as an error -- so that // at least message catalogs can be used. if ( !retloc ) { if ( wxGetANSICodePageForLocale(LOCALE_USER_DEFAULT).empty() ) { // we set the locale to a Unicode-only language, don't treat the // inability of CRT to use it as an error retloc = "C"; } } #endif // CRT not handling Unicode-only languages if ( !retloc ) ret = false; #elif defined(__WXMAC__) if (lang == wxLANGUAGE_DEFAULT) locale = wxEmptyString; else locale = info->CanonicalName; const char *retloc = wxSetlocale(LC_ALL, locale); if ( !retloc ) { // Some C libraries don't like xx_YY form and require xx only retloc = wxSetlocale(LC_ALL, ExtractLang(locale)); } #else wxUnusedVar(flags); return false; #define WX_NO_LOCALE_SUPPORT #endif #ifndef WX_NO_LOCALE_SUPPORT if ( !ret ) { wxLogWarning(_("Cannot set locale to language \"%s\"."), name.c_str()); // continue nevertheless and try to load at least the translations for // this language } if ( !DoInit(name, canonical, retloc) ) { ret = false; } if (IsOk()) // setlocale() succeeded m_language = lang; // NB: don't use 'lang' here, 'language' wxTranslations *t = wxTranslations::Get(); if ( t ) { t->SetLanguage(static_cast<wxLanguage>(language)); if ( flags & wxLOCALE_LOAD_DEFAULT ) t->AddStdCatalog(); } return ret; #endif // !WX_NO_LOCALE_SUPPORT }
/* static */ wxString wxFileType::ExpandCommand(const wxString& command, const wxFileType::MessageParameters& params) { bool hasFilename = false; wxString str; for ( const wxChar *pc = command.c_str(); *pc != wxT('\0'); pc++ ) { if ( *pc == wxT('%') ) { switch ( *++pc ) { case wxT('s'): // '%s' expands into file name (quoted because it might // contain spaces) - except if there are already quotes // there because otherwise some programs may get confused // by double double quotes #if 0 if ( *(pc - 2) == wxT('"') ) str << params.GetFileName(); else str << wxT('"') << params.GetFileName() << wxT('"'); #endif str << params.GetFileName(); hasFilename = true; break; case wxT('t'): // '%t' expands into MIME type (quote it too just to be // consistent) str << wxT('\'') << params.GetMimeType() << wxT('\''); break; case wxT('{'): { const wxChar *pEnd = wxStrchr(pc, wxT('}')); if ( pEnd == NULL ) { wxString mimetype; wxLogWarning(_("Unmatched '{' in an entry for mime type %s."), params.GetMimeType().c_str()); str << wxT("%{"); } else { wxString param(pc + 1, pEnd - pc - 1); str << wxT('\'') << params.GetParamValue(param) << wxT('\''); pc = pEnd; } } break; case wxT('n'): case wxT('F'): // TODO %n is the number of parts, %F is an array containing // the names of temp files these parts were written to // and their mime types. break; default: wxLogDebug(wxT("Unknown field %%%c in command '%s'."), *pc, command.c_str()); str << *pc; } } else { str << *pc; } } // metamail(1) man page states that if the mailcap entry doesn't have '%s' // the program will accept the data on stdin so normally we should append // "< %s" to the end of the command in such case, but not all commands // behave like this, in particular a common test is 'test -n "$DISPLAY"' // and appending "< %s" to this command makes the test fail... I don't // know of the correct solution, try to guess what we have to do. // test now carried out on reading file so test should never get here if ( !hasFilename && !str.empty() #ifdef __UNIX__ && !str.StartsWith(_T("test ")) #endif // Unix ) { str << wxT(" < '") << params.GetFileName() << wxT('\''); } return str; }
void frmMainConfig::DisplayFile(const wxString &str) { lines.Clear(); filetype = wxTextFileType_Unix; wxStringTokenizer strtok; wxArrayString *unknownCategory = 0; if (str.Find('\r') >= 0) { if (str.Find(wxT("\n\r")) >= 0 || str.Find(wxT("\r\n"))) filetype = wxTextFileType_Dos; else filetype = wxTextFileType_Mac; strtok.SetString(wxTextBuffer::Translate(str, wxTextFileType_Unix), wxT("\n"), wxTOKEN_RET_EMPTY); } else strtok.SetString(str, wxT("\n"), wxTOKEN_RET_EMPTY); while (strtok.HasMoreTokens()) { pgConfigOrgLine *line = new pgConfigOrgLine(strtok.GetNextToken()); lines.Add(line); // identify option bool isComment = false; const wxChar *p = line->text.c_str(); // identify keywords while (*p && wxStrchr(wxT("# \n"), *p)) { if (*p == '#') isComment = true; p++; } if (!*p) isComment = true; line->isComment = isComment; const wxChar *p2 = p; while (*p2 && *p2 != '#' && *p2 != ' ' && *p2 != '\t' && *p2 != '=') p2++; if (p2 != p) { wxString keyword = line->text.Mid(p - line->text.c_str(), p2 - p); pgSettingItemHashmap::iterator it = options.find(keyword); pgSettingItem *item; if (it == options.end()) { if (isComment) continue; item = new pgSettingItem; item->name = keyword; item->category = _("Unknown"); item->short_desc = _("Unknown option"); item->extra_desc = _("This option is present in the configuration file, but not known to the configuration tool."); item->SetType(wxT("string")); options[item->name] = item; if (!unknownCategory) { unknownCategory = new wxArrayString; categories[item->category] = unknownCategory; } unknownCategory->Add(item->name); } else item = it->second; if (!isComment || !item->orgLine || item->orgLine->isComment) { line->item = item; if (item->orgLine) item->orgLine->item = 0; item->orgLine = line; } while (*p2 && *p2 != '=') p2++; p2++; // skip = while (*p2 && wxStrchr(wxT(" \t"), *p2)) p2++; wxChar quoteChar = 0; if (wxStrchr(wxT("'\""), *p2)) quoteChar = *p2++; const wxChar *p3 = p2; while (*p3) { if (*p3 == quoteChar || (!quoteChar && wxStrchr(wxT(" \t#"), *p3))) break; p3++; } if (p2 != p3) { line->value = line->text.Mid(p2 - line->text.c_str(), p3 - p2); if (quoteChar) p3++; const wxChar *p4 = p3; while (*p4 && wxStrchr(wxT(" \t#"), *p4)) p4++; line->commentIndent = line->text.Mid(p3 - line->text.c_str(), p4 - p3); line->comment = p4; } } } cfgList->DeleteAllItems(); // we want to show options ordered by category/name // category might be localized, and we want a distinct category ordering FillList(wxT("listen_addresses")); // Connections and Authentication / Connection Settings FillList(wxT("authentication_timeout")); // Connections and Authentication / Security and Authentication FillList(wxT("check_function_bodies")); // Client Connection Defaults / Statement Behaviour FillList(wxT("lc_messages")); // Client Connection Defaults / Locale and Formatting FillList(wxT("explain_pretty_print")); // Client Connection Defaults / Other Defaults FillList(wxT("enable_hashjoin")); // Query Tuning / Planner Method Configuration FillList(wxT("cpu_operator_cost")); // Query Tuning / Planner Cost Constants if (!conn || !conn->GetIsGreenplum()) // Greenplum doesn't have the Genetic Query Optimizer FillList(wxT("geqo")); // Query Tuning / Genetic Query Optimizer FillList(wxT("default_statistics_target")); // Query Tuning / Other Planner Options FillList(wxT("deadlock_timeout")); // Lock Management FillList(wxT("shared_buffers")); // Resource Usage / Memory FillList(wxT("max_fsm_pages")); // Resource Usage / Free Space Map FillList(wxT("bgwriter_delay")); // Resource Usage FillList(wxT("max_files_per_process")); // Resource Usage / Kernel Resources FillList(wxT("log_connections")); // Reporting and Logging / What to Log FillList(wxT("client_min_messages")); // Reporting and Logging / When to Log FillList(wxT("log_destination")); // Reporting and Logging / Where to Log FillList(wxT("stats_command_string"), wxT("track_activities")); // Statistics / Query and Index Statistics Collector FillList(wxT("log_executor_stats")); // Statistics / Monitoring FillList(wxT("fsync")); // Write-Ahead Log / Settings FillList(wxT("checkpoint_segments")); // Write-Ahead Log / Checkpoints FillList(wxT("add_missing_from")); // Version and Platform Compatibility / Previous PostgreSQL Version FillList(wxT("transform_null_equals")); // Version and Platform Compatibility / Other Platforms and Clients if (!conn || !conn->GetIsGreenplum()) // Greenplum doesn't have trace_notify visible FillList(wxT("trace_notify")); // Developer Options FillList(wxT("hba_file")); // Ungrouped // for all we didn't get while (!categories.empty()) { pgCategoryHashmap::iterator it = categories.begin(); wxString missed = it->first; FillList(it->second); categories.erase(it); } }
int wxCmdLineParser::Parse(bool showUsage) { bool maybeOption = true; // can the following arg be an option? bool ok = true; // true until an error is detected bool helpRequested = false; // true if "-h" was given bool hadRepeatableParam = false; // true if found param with MULTIPLE flag size_t currentParam = 0; // the index in m_paramDesc size_t countParam = m_data->m_paramDesc.GetCount(); wxString errorMsg; Reset(); // parse everything wxString arg; size_t count = m_data->m_arguments.size(); for ( size_t n = 1; ok && (n < count); n++ ) // 0 is program name { arg = m_data->m_arguments[n]; // special case: "--" should be discarded and all following arguments // should be considered as parameters, even if they start with '-' and // not like options (this is POSIX-like) if ( arg == wxT("--") ) { maybeOption = false; continue; } // empty argument or just '-' is not an option but a parameter if ( maybeOption && arg.length() > 1 && // FIXME-UTF8: use wc_str() after removing ANSI build wxStrchr(m_data->m_switchChars.c_str(), arg[0u]) ) { bool isLong; wxString name; int optInd = wxNOT_FOUND; // init to suppress warnings // an option or a switch: find whether it's a long or a short one if ( arg.length() >= 3 && arg[0u] == wxT('-') && arg[1u] == wxT('-') ) { // a long one isLong = true; // Skip leading "--" wxString::const_iterator p = arg.begin() + 2; bool longOptionsEnabled = AreLongOptionsEnabled(); name = GetLongOptionName(p, arg.end()); if (longOptionsEnabled) { optInd = m_data->FindOptionByLongName(name); if ( optInd == wxNOT_FOUND ) { errorMsg << wxString::Format(_("Unknown long option '%s'"), name.c_str()) << wxT('\n'); } } else { optInd = wxNOT_FOUND; // Sanity check // Print the argument including leading "--" name.Prepend( wxT("--") ); errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str()) << wxT('\n'); } } else // not a long option { isLong = false; // a short one: as they can be cumulated, we try to find the // longest substring which is a valid option wxString::const_iterator p = arg.begin() + 1; name = GetShortOptionName(p, arg.end()); size_t len = name.length(); do { if ( len == 0 ) { // we couldn't find a valid option name in the // beginning of this string errorMsg << wxString::Format(_("Unknown option '%s'"), name.c_str()) << wxT('\n'); break; } else { optInd = m_data->FindOption(name.Left(len)); // will try with one character less the next time len--; } } while ( optInd == wxNOT_FOUND ); len++; // compensates extra len-- above if ( (optInd != wxNOT_FOUND) && (len != name.length()) ) { // first of all, the option name is only part of this // string name = name.Left(len); // our option is only part of this argument, there is // something else in it - it is either the value of this // option or other switches if it is a switch if ( m_data->m_options[(size_t)optInd].kind == wxCMD_LINE_SWITCH ) { // pretend that all the rest of the argument is the // next argument, in fact wxString arg2 = arg[0u]; arg2 += arg.Mid(len + 1); // +1 for leading '-' m_data->m_arguments.insert (m_data->m_arguments.begin() + n + 1, arg2); count++; // only leave the part which wasn't extracted into the // next argument in this one arg = arg.Left(len + 1); } //else: it's our value, we'll deal with it below } } if ( optInd == wxNOT_FOUND ) { ok = false; continue; // will break, in fact } // look at what follows: // +1 for leading '-' wxString::const_iterator p = arg.begin() + 1 + name.length(); wxString::const_iterator end = arg.end(); if ( isLong ) ++p; // for another leading '-' wxCmdLineOption& opt = m_data->m_options[(size_t)optInd]; if ( opt.kind == wxCMD_LINE_SWITCH ) { // we must check that there is no value following the switch if ( p != arg.end() ) { errorMsg << wxString::Format(_("Unexpected characters following option '%s'."), name.c_str()) << wxT('\n'); ok = false; } else // no value, as expected { // nothing more to do opt.SetHasValue(); if ( opt.flags & wxCMD_LINE_OPTION_HELP ) { helpRequested = true; // it's not an error, but we still stop here ok = false; } } } else // it's an option. not a switch { switch ( p == end ? '\0' : (*p).GetValue() ) { case '=': case ':': // the value follows ++p; break; case '\0': // the value is in the next argument if ( ++n == count ) { // ... but there is none errorMsg << wxString::Format(_("Option '%s' requires a value."), name.c_str()) << wxT('\n'); ok = false; } else { // ... take it from there p = m_data->m_arguments[n].begin(); end = m_data->m_arguments[n].end(); } break; default: // the value is right here: this may be legal or // not depending on the option style if ( opt.flags & wxCMD_LINE_NEEDS_SEPARATOR ) { errorMsg << wxString::Format(_("Separator expected after the option '%s'."), name.c_str()) << wxT('\n'); ok = false; } } if ( ok ) { wxString value(p, end); switch ( opt.type ) { default: wxFAIL_MSG( wxT("unknown option type") ); // still fall through case wxCMD_LINE_VAL_STRING: opt.SetStrVal(value); break; case wxCMD_LINE_VAL_NUMBER: { long val; if ( value.ToLong(&val) ) { opt.SetLongVal(val); } else { errorMsg << wxString::Format(_("'%s' is not a correct numeric value for option '%s'."), value.c_str(), name.c_str()) << wxT('\n'); ok = false; } } break; case wxCMD_LINE_VAL_DOUBLE: { double val; if ( value.ToDouble(&val) ) { opt.SetDoubleVal(val); } else { errorMsg << wxString::Format(_("'%s' is not a correct numeric value for option '%s'."), value.c_str(), name.c_str()) << wxT('\n'); ok = false; } } break; #if wxUSE_DATETIME case wxCMD_LINE_VAL_DATE: { wxDateTime dt; wxString::const_iterator end; if ( !dt.ParseDate(value, &end) || end != value.end() ) { errorMsg << wxString::Format(_("Option '%s': '%s' cannot be converted to a date."), name.c_str(), value.c_str()) << wxT('\n'); ok = false; } else { opt.SetDateVal(dt); } } break; #endif // wxUSE_DATETIME } } } } else // not an option, must be a parameter { if ( currentParam < countParam ) { wxCmdLineParam& param = m_data->m_paramDesc[currentParam]; // TODO check the param type m_data->m_parameters.push_back(arg); if ( !(param.flags & wxCMD_LINE_PARAM_MULTIPLE) ) { currentParam++; } else { wxASSERT_MSG( currentParam == countParam - 1, wxT("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") ); // remember that we did have this last repeatable parameter hadRepeatableParam = true; } } else { errorMsg << wxString::Format(_("Unexpected parameter '%s'"), arg.c_str()) << wxT('\n'); ok = false; } } } // verify that all mandatory options were given if ( ok ) { size_t countOpt = m_data->m_options.GetCount(); for ( size_t n = 0; ok && (n < countOpt); n++ ) { wxCmdLineOption& opt = m_data->m_options[n]; if ( (opt.flags & wxCMD_LINE_OPTION_MANDATORY) && !opt.HasValue() ) { wxString optName; if ( !opt.longName ) { optName = opt.shortName; } else { if ( AreLongOptionsEnabled() ) { optName.Printf( _("%s (or %s)"), opt.shortName.c_str(), opt.longName.c_str() ); } else { optName.Printf( wxT("%s"), opt.shortName.c_str() ); } } errorMsg << wxString::Format(_("The value for the option '%s' must be specified."), optName.c_str()) << wxT('\n'); ok = false; } } for ( ; ok && (currentParam < countParam); currentParam++ ) { wxCmdLineParam& param = m_data->m_paramDesc[currentParam]; if ( (currentParam == countParam - 1) && (param.flags & wxCMD_LINE_PARAM_MULTIPLE) && hadRepeatableParam ) { // special case: currentParam wasn't incremented, but we did // have it, so don't give error continue; } if ( !(param.flags & wxCMD_LINE_PARAM_OPTIONAL) ) { errorMsg << wxString::Format(_("The required parameter '%s' was not specified."), param.description.c_str()) << wxT('\n'); ok = false; } } } // if there was an error during parsing the command line, show this error // and also the usage message if it had been requested if ( !ok && (!errorMsg.empty() || (helpRequested && showUsage)) ) { wxMessageOutput* msgOut = wxMessageOutput::Get(); if ( msgOut ) { wxString usage; if ( showUsage ) usage = GetUsageString(); msgOut->Printf( wxT("%s%s"), usage.c_str(), errorMsg.c_str() ); } else { wxFAIL_MSG( wxT("no wxMessageOutput object?") ); } } return ok ? 0 : helpRequested ? -1 : 1; }
static CharType *wxDoExpandPath(CharType *buf, const wxString& name) { CharType *d, *s, *nm; CharType lnm[_MAXPATHLEN]; int q; // Some compilers don't like this line. // const CharType trimchars[] = wxT("\n \t"); CharType trimchars[4]; trimchars[0] = wxT('\n'); trimchars[1] = wxT(' '); trimchars[2] = wxT('\t'); trimchars[3] = 0; static const CharType SEP = wxFILE_SEP_PATH; #ifdef __WINDOWS__ //wxUnix2DosFilename(path); #endif buf[0] = wxT('\0'); if (name.empty()) return buf; nm = ::MYcopystring(static_cast<const CharType*>(name.c_str())); // Make a scratch copy CharType *nm_tmp = nm; /* Skip leading whitespace and cr */ while (wxStrchr(trimchars, *nm) != NULL) nm++; /* And strip off trailing whitespace and cr */ s = nm + (q = wxStrlen(nm)) - 1; while (q-- && wxStrchr(trimchars, *s) != NULL) *s = wxT('\0'); s = nm; d = lnm; #ifdef __WINDOWS__ q = FALSE; #else q = nm[0] == wxT('\\') && nm[1] == wxT('~'); #endif /* Expand inline environment variables */ while ((*d++ = *s) != 0) { # ifndef __WINDOWS__ if (*s == wxT('\\')) { if ((*(d - 1) = *++s)!=0) { s++; continue; } else break; } else # endif #ifdef __WINDOWS__ if (*s++ == wxT('$') && (*s == wxT('{') || *s == wxT(')'))) #else if (*s++ == wxT('$')) #endif { CharType *start = d; int braces = (*s == wxT('{') || *s == wxT('(')); CharType *value; while ((*d++ = *s) != 0) if (braces ? (*s == wxT('}') || *s == wxT(')')) : !(wxIsalnum(*s) || *s == wxT('_')) ) break; else s++; *--d = 0; value = wxGetenv(braces ? start + 1 : start); if (value) { for ((d = start - 1); (*d++ = *value++) != 0;) { // Empty } d--; if (braces && *s) s++; } } } /* Expand ~ and ~user */ wxString homepath; nm = lnm; if (nm[0] == wxT('~') && !q) { /* prefix ~ */ if (nm[1] == SEP || nm[1] == 0) { /* ~/filename */ homepath = wxGetUserHome(wxEmptyString); if (!homepath.empty()) { s = (CharType*)(const CharType*)homepath.c_str(); if (*++nm) nm++; } } else { /* ~user/filename */ CharType *nnm; for (s = nm; *s && *s != SEP; s++) { // Empty } int was_sep; /* MATTHEW: Was there a separator, or NULL? */ was_sep = (*s == SEP); nnm = *s ? s + 1 : s; *s = 0; homepath = wxGetUserHome(wxString(nm + 1)); if (homepath.empty()) { if (was_sep) /* replace only if it was there: */ *s = SEP; s = NULL; } else { nm = nnm; s = (CharType*)(const CharType*)homepath.c_str(); } } } d = buf; if (s && *s) { /* MATTHEW: s could be NULL if user '~' didn't exist */ /* Copy home dir */ while (wxT('\0') != (*d++ = *s++)) /* loop */; // Handle root home if (d - 1 > buf && *(d - 2) != SEP) *(d - 1) = SEP; } s = nm; while ((*d++ = *s++) != 0) { // Empty } delete[] nm_tmp; // clean up alloc /* Now clean up the buffer */ return wxRealPath(buf); }
/* static */ wxString wxFileType::ExpandCommand(const wxString& command, const wxFileType::MessageParameters& params) { bool hasFilename = false; // We consider that only the file names with spaces in them need to be // handled specially. This is not perfect, but this can be done easily // under all platforms while handling the file names with quotes in them, // for example, needs to be done differently. const bool needToQuoteFilename = params.GetFileName().find_first_of(" \t") != wxString::npos; wxString str; for ( const wxChar *pc = command.c_str(); *pc != wxT('\0'); pc++ ) { if ( *pc == wxT('%') ) { switch ( *++pc ) { case wxT('s'): // don't quote the file name if it's already quoted: notice // that we check for a quote following it and not preceding // it as at least under Windows we can have commands // containing "file://%s" (with quotes) in them so the // argument may be quoted even if there is no quote // directly before "%s" itself if ( needToQuoteFilename && pc[1] != '"' ) str << wxT('"') << params.GetFileName() << wxT('"'); else str << params.GetFileName(); hasFilename = true; break; case wxT('t'): // '%t' expands into MIME type (quote it too just to be // consistent) str << wxT('\'') << params.GetMimeType() << wxT('\''); break; case wxT('{'): { const wxChar *pEnd = wxStrchr(pc, wxT('}')); if ( pEnd == NULL ) { wxString mimetype; wxLogWarning(_("Unmatched '{' in an entry for mime type %s."), params.GetMimeType().c_str()); str << wxT("%{"); } else { wxString param(pc + 1, pEnd - pc - 1); str << wxT('\'') << params.GetParamValue(param) << wxT('\''); pc = pEnd; } } break; case wxT('n'): case wxT('F'): // TODO %n is the number of parts, %F is an array containing // the names of temp files these parts were written to // and their mime types. break; default: wxLogDebug(wxT("Unknown field %%%c in command '%s'."), *pc, command.c_str()); str << *pc; } } else { str << *pc; } } // metamail(1) man page states that if the mailcap entry doesn't have '%s' // the program will accept the data on stdin so normally we should append // "< %s" to the end of the command in such case, but not all commands // behave like this, in particular a common test is 'test -n "$DISPLAY"' // and appending "< %s" to this command makes the test fail... I don't // know of the correct solution, try to guess what we have to do. // test now carried out on reading file so test should never get here if ( !hasFilename && !str.empty() #ifdef __UNIX__ && !str.StartsWith(wxT("test ")) #endif // Unix ) { str << wxT(" < "); if ( needToQuoteFilename ) str << '"'; str << params.GetFileName(); if ( needToQuoteFilename ) str << '"'; } return str; }
void PGPFilter::DoProcess(String& text, MessageViewer *viewer, MTextStyle& style) { // do we have something looking like a PGP message? // // there should be a BEGIN line near the start of the message const wxChar *beginNext = NULL; const wxChar *start = text.c_str(); for ( size_t numLines = 0; numLines < 10; numLines++ ) { const wxChar *p = start; if ( AdvanceIfMatches(&p, PGP_BEGIN_PREFIX) ) { beginNext = p; break; } // try the next line (but only if not already at the end) if ( !*p ) break; p = wxStrchr(start, _T('\n')); if ( !p ) break; // no more text start = p + 1; // skip '\n' itself } if ( beginNext ) { // is the message just signed or encrypted? bool isKey = false; const bool isSigned = AdvanceIfMatches(&beginNext, _T("SIGNED ")); if ( !isSigned ) { isKey = AdvanceIfMatches(&beginNext, _T("PUBLIC KEY ")); } // this flag tells us if everything is ok so far -- as soon as it becomes // false, we skip all subsequent steps // We do not know (yet) what to do with public key blocks, so let's consider // that they're not ok. // TODO: propose to import it into the keyring? bool ok = !isKey; if ( ok && !AdvanceIfMatches(&beginNext, PGP_BEGIN_SUFFIX) ) { wxLogWarning(_("The BEGIN line doesn't end with expected suffix.")); ok = false; } // end of the PGP part const wxChar *end = NULL; // unneeded but suppresses the compiler warning const wxChar *endNext = NULL; // same if ( ok ) // ok, it starts with something valid { // now locate the end line const wxChar *pc = start + text.length() - 1; bool foundEnd = false; for ( ;; ) { // optimistically suppose that this line will be the END one end = pc + 2; // find the beginning of this line while ( *pc != '\n' && pc >= start ) { pc--; } // we took one extra char pc++; if ( AdvanceIfMatches(&pc, PGP_END_PREFIX) ) { endNext = pc; foundEnd = true; break; } // undo the above pc--; if ( pc < start ) { // we exhausted the message without finding the END line, leave // foundEnd at false and exit the loop break; } pc--; ASSERT_MSG( *pc == '\r', _T("line doesn't end in\"\\r\\n\"?") ); } if ( !foundEnd ) { wxLogWarning(_("END line not found.")); ok = false; } } // check that the END line matches the BEGIN one if ( ok ) { const wxChar * const suffix = isSigned ? PGP_END_SIG_SUFFIX : PGP_END_CRYPT_SUFFIX; if ( !AdvanceIfMatches(&endNext, suffix) ) { wxLogWarning(_("Mismatch between BEGIN and END lines.")); ok = false; } } // if everything was ok so far, continue with decoding/verifying if ( ok ) { // output the part before the BEGIN line, if any String prolog(text.c_str(), start); if ( !prolog.empty() ) { m_next->Process(prolog, viewer, style); } CHECK_RET( m_engine, _T("PGP filter can't work without PGP engine") ); ClickablePGPInfo *pgpInfo = NULL; MCryptoEngineOutputLog * log = new MCryptoEngineOutputLog(m_msgView->GetWindow()); String in(start, end), out; if ( isSigned ) { // pass everything between start and end to PGP for verification const MCryptoEngine::Status rc = m_engine->VerifySignature(in, out, log); pgpInfo = ClickablePGPInfo:: CreateFromSigStatusCode(m_engine, rc, m_msgView, log); // if we failed to check the signature, we need to remove the // BEGIN/END lines from output ourselves (otherwise it would have // been done by VerifySignature() itself) if ( rc != MCryptoEngine::OK ) { // beginNext points to the end of BEGIN line, go forward to the // end of the headers. // // Normally the end of the headers must be signalled by a blank // line, but in practice some implementations, notably Enigmail // used with Thunderbird, put a space in this "empty" line, so // accept any line containing only spaces as indicating the end // of headers. const wxChar* startBody = beginNext; for ( ;; ) { startBody = wxStrstr(startBody, _T("\r\n")); if ( !startBody || startBody >= endNext ) break; // end of headers not found startBody += 2; // skip "\r\n" we just matched while ( *startBody == ' ' ) startBody++; if ( startBody[0] == '\r' && startBody[1] == '\n' ) { // we found the end of the headers startBody += 2; break; } } if ( startBody && startBody < endNext ) { // endNext currently points to the end of END PGP SIGNATURE // line, rewind to the PGP_BEGIN_SIG line const wxChar *pc = endNext; for ( ;; ) { // find the beginning of this line while ( *pc != '\n' && pc >= start ) { pc--; } if ( pc < start ) { // we exhausted the message without finding the // PGP_BEGIN_SIG line break; } pc++; // skip the "\n" if ( AdvanceIfMatches(&pc, PGP_BEGIN_SIG) ) { // chop off PGP_BEGIN_SIG line as well while ( *pc != '\n' && pc >= start ) pc--; if ( pc > start ) { out = String(startBody, pc - 1); } break; } pc -= 3; // rewind beyond "\r\n" ASSERT_MSG( pc[1] == '\r', _T("line doesn't end in\"\\r\\n\"?") ); } } else { wxLogWarning(_("Blank line separating header " "from body in PGP message not found.")); } } } else // encrypted { // try to decrypt MCryptoEngine::Status rc = m_engine->Decrypt(in, out, log); switch ( rc ) { case MCryptoEngine::OK: pgpInfo = new PGPInfoGoodMsg(m_msgView); break; default: wxLogError(_("Decrypting the PGP message failed.")); // fall through // if the user cancelled decryption, don't complain about it case MCryptoEngine::OPERATION_CANCELED_BY_USER: // using unmodified text is not very helpful here anyhow so // simply replace it with an icon pgpInfo = new PGPInfoBadMsg(m_msgView); } } m_next->Process(out, viewer, style); pgpInfo->SetLog(log); pgpInfo->SetRaw(in); // we want the PGP stuff to stand out viewer->InsertText(_T("\r\n"), style); viewer->InsertClickable(pgpInfo->GetBitmap(), pgpInfo, pgpInfo->GetColour()); viewer->InsertText(_T("\r\n"), style); // output the part after the END line, if any String epilog(end); if ( !epilog.empty() ) { m_next->Process(epilog, viewer, style); } } if ( ok ) { // skip the normal display below return; } // give a warning (unless this is a KEY blok and display the message normally if ( !isKey ) { wxLogWarning(_("This message seems to be PGP signed or encrypted " "but in fact is not.")); } } m_next->Process(text, viewer, style); }