////////////////////////////////////////////////////////////////////////// // // pgAdmin III - PostgreSQL Tools // // Copyright (C) 2002 - 2016, The pgAdmin Development Team // This software is released under the PostgreSQL Licence // // misc.cpp - Miscellaneous Utilities // ////////////////////////////////////////////////////////////////////////// #include "pgAdmin3.h" // wxWindows headers #include #include #include #include #include #include #include #include #include #include #include #include "utils/utffile.h" #include #ifdef __WXMSW__ #include #endif // Standard headers #include // App headers #include "utils/misc.h" #if !defined(PGSCLI) // App headers #include "frm/frmMain.h" wxImageList *imageList = 0; #endif // PGSCLI extern "C" { #define YYSTYPE_IS_DECLARED #define DECIMAL DECIMAL_P typedef int YYSTYPE; #include "parser/keywords.h" } // we dont have an appropriate wxLongLong method #ifdef __WIN32__ #define atolonglong _atoi64 #else #ifdef __WXMAC__ #define atolonglong(str) strtoll(str, (char **)NULL, 10) #else #ifdef __FreeBSD__ #define atolonglong(str) strtoll(str, (char **)NULL, 10) #else #define atolonglong atoll #endif #endif #endif // Conversions wxString BoolToYesNo(bool value) { return value ? _("Yes") : _("No"); } wxString BoolToStr(bool value) { return value ? wxT("true") : wxT("false"); } wxString escapeHtml(wxString text, bool pre) { text.Replace("&", "&"); text.Replace("<", "<"); text.Replace(">", ">"); if (!pre) text.Replace("\n", "¶
"); return text; } bool StrToBool(const wxString &value) { if (value.StartsWith(wxT("t"))) { return true; } else if (value.StartsWith(wxT("T"))) { return true; } else if (value.StartsWith(wxT("1"))) { return true; } else if (value.StartsWith(wxT("Y"))) { return true; } else if (value.StartsWith(wxT("y"))) { return true; } else if (value == wxT("on")) return true; return false; } wxString NumToStr(long value) { wxString result; result.Printf(wxT("%ld"), value); return result; } wxString NumToStr(long long value) { wxString result; result.Printf(wxT("%lld"), value); return result; } wxString NumToStr(OID value) { wxString result; result.Printf(wxT("%lu"), (long)value); return result; } long StrToLong(const wxString &value) { return atol(value.ToAscii()); } long long StrTolonglong(const wxString &value) { return atoll(value.ToAscii()); } OID StrToOid(const wxString &value) { return (OID)strtoul(value.ToAscii(), 0, 10); } wxString generate_spaces(int length) { return wxString().Pad(length); } wxString NumToStr(double value) { wxString result; static wxString decsep; if (decsep.Length() == 0) { decsep.Printf(wxT("%lf"), 1.2); decsep = decsep[(unsigned int)1]; } result.Printf(wxT("%lf"), value); result.Replace(decsep, wxT(".")); // Get rid of excessive decimal places if (result.Contains(wxT("."))) while (result.Right(1) == wxT("0")) result.RemoveLast(); if (result.Right(1) == wxT(".")) result.RemoveLast(); return result; } wxString NumToStrHuman(wxLongLong value) { // billion long ddiv = 1000000000; wxLongLong r = 0; wxString s; while ((r=value/ddiv)==0) { ddiv = ddiv / 1000; if (ddiv == 0) return wxEmptyString; } if (ddiv == 1000000000) s = _("Bi"); else if (ddiv == 1000000) s = _("Mi"); else if (ddiv == 1000) s = _("ths"); else return wxEmptyString; wxLongLong m = value % ddiv; m = m / (ddiv / 10); wxString rez; rez = NumToStr(r) + (m == 0 ? "": "." + NumToStr(m))+" "+s; return rez; } wxString NumToStr(wxLongLong value) { wxString str; #if wxCHECK_VERSION(2, 9, 0) str.Printf("%" wxLongLongFmtSpec "d", value.GetValue()); #else str.Printf(wxT("%") wxLongLongFmtSpec wxT("d"), value.GetValue()); #endif return str; } double StrToDouble(const wxString &value) { wxCharBuffer buf = value.ToAscii(); char *p = (char *)strchr(buf, '.'); if (p) *p = localeconv()->decimal_point[0]; return strtod(buf, 0); } wxLongLong StrToLongLong(const wxString &value) { return atolonglong(value.ToAscii()); } wxString DateToAnsiStr(const wxDateTime &datetime) { if (!datetime.IsValid()) return wxEmptyString; return datetime.FormatISODate() + wxT(" ") + datetime.FormatISOTime(); } wxString DateToStr(const wxDateTime &datetime) { if (!datetime.IsValid()) return wxEmptyString; return datetime.FormatDate() + wxT(" ") + datetime.FormatTime(); } wxString ContrastColorBlackOrWhite(wxColour &bgColor) { float k = bgColor.GetRed() * 0.299 + bgColor.GetGreen() * 0.587 + bgColor.GetBlue() * 0.114; if (k <= 150) return "#FFFFFF"; else return "#000000"; } /// /// /// /// NN MB , N bytes, N kB, N GB /// size MB double ConvertSizeToMB(const wxString& sourcestringsize) { double d = 0; if (sourcestringsize.ToCDouble(&d)) { d = 0; } else { if (sourcestringsize.Right(2) == "kB") d = d / 1024; //kB => MB else if (sourcestringsize.Right(2) == "GB") d = d * 1024;//GB => MB else if (sourcestringsize.Right(2) == "TB") d = d * 1024 * 1024;//TB => MB else if (sourcestringsize.Right(5) == "bytes") d = d / 1024 / 1024; //bytes => MB } return d; } wxString ElapsedTimeToStr(wxLongLong msec) { wxTimeSpan tsMsec(0, 0, 0, msec); int days = tsMsec.GetDays(); int hours = (wxTimeSpan(tsMsec.GetHours(), 0, 0, 0) - wxTimeSpan(days * 24)).GetHours(); int minutes = (wxTimeSpan(0, tsMsec.GetMinutes(), 0, 0) - wxTimeSpan(hours)).GetMinutes(); long seconds = (wxTimeSpan(0, 0, tsMsec.GetSeconds(), 0) - wxTimeSpan(hours, minutes)).GetSeconds().ToLong(); long milliseconds = (wxTimeSpan(0, 0, 0, tsMsec.GetMilliseconds()) - wxTimeSpan(0, 0, seconds)).GetMilliseconds().ToLong(); if (days > 0) return wxString::Format( wxT("%d %s, %02d:%02d:%02ld hours"), days, wxT("days"), hours, minutes, seconds ); else if (hours > 0) return wxString::Format( wxT("%02d:%02d:%02ld hours"), hours, minutes, seconds ); else if (msec >= 1000 * 60) return wxString::Format(wxT("%02d:%02ld minutes"), minutes, seconds); else if (msec >= 1000) return wxString::Format( wxT("%ld.%ld secs"), seconds, milliseconds / 100 ); else return msec.ToString() + wxT(" msec"); } wxDateTime StrToDateTime(const wxString &value) { wxDateTime dt; /* This hasn't just been used. ( Is not infinity ) */ if ( !value.IsEmpty() ) dt.ParseDateTime(value); return dt; } #if !defined(PGSCLI) void CheckOnScreen(wxWindow *win, wxPoint &pos, wxSize &size, const int w0, const int h0) { wxRect rect; int scrH, scrW; wxSize screenSize = wxGetDisplaySize(); scrW = screenSize.x; scrH = screenSize.y; if (pos.x > scrW - w0) pos.x = scrW - w0; if (pos.y > scrH - h0) pos.y = scrH - h0; if (pos.x < 0) pos.x = 0; if (pos.y < 0) pos.y = 0; if (size.GetWidth() < w0) size.SetWidth(w0); if (size.GetHeight() < h0) size.SetHeight(h0); if (size.GetWidth() > scrW) size.SetWidth(scrW); if (size.GetHeight() > scrH) size.SetHeight(scrH); } #endif // PGSCLI wxString qtConnString(const wxString &value) { wxString result = value; result.Replace(wxT("\\"), wxT("\\\\")); result.Replace(wxT("'"), wxT("\\'")); result.Append(wxT("'")); result.Prepend(wxT("'")); return result; } #if !defined(PGSCLI) wxString IdAndName(long id, const wxString &name) { wxString str; str.Printf(wxT("%ld - %s"), id, name.BeforeFirst('\n').c_str()); return str; } wxString qtDbStringDollar(const wxString &value) { wxString qtDefault = wxT("BODY"); wxString qt = qtDefault; int counter = 1; if (value.Find('\'') < 0 && value.Find('\n') < 0 && value.Find('\r') < 0) { wxString ret = value; ret.Replace(wxT("\\"), wxT("\\\\")); ret.Replace(wxT("'"), wxT("''")); ret.Append(wxT("'")); ret.Prepend(wxT("'")); return ret; } while (value.Find(wxT("$") + qt + wxT("$")) >= 0) qt.Printf(wxT("%s%d"), qtDefault.c_str(), counter++); return wxT("$") + qt + wxT("$") + value + wxT("$") + qt + wxT("$"); } void FillKeywords(wxString &str) { // unfortunately, the keyword list is static. int i; str = wxString(); for (i = 0; i < NumScanKeywords; i++) { str += wxT(" ") + wxString::FromAscii(ScanKeywords[i].name); } for (i = 0; i < NumScanKeywordsExtra; i++) { str += wxT(" ") + wxString::FromAscii(ScanKeywordsExtra[i].name); } } #endif // PGSCLI static bool needsQuoting(wxString &value, bool forTypes) { // Is it a number? if (value.IsNumber()) return true; else { // certain types should not be quoted even though it contains a space. Evilness. wxString valNoArray; if (forTypes && value.Right(2) == wxT("[]")) valNoArray = value.Mid(0, value.Len() - 2); else valNoArray = value; if (forTypes && (!valNoArray.CmpNoCase(wxT("character varying")) || !valNoArray.CmpNoCase(wxT("\"char\"")) || !valNoArray.CmpNoCase(wxT("bit varying")) || !valNoArray.CmpNoCase(wxT("double precision")) || !valNoArray.CmpNoCase(wxT("timestamp without time zone")) || !valNoArray.CmpNoCase(wxT("timestamp with time zone")) || !valNoArray.CmpNoCase(wxT("time without time zone")) || !valNoArray.CmpNoCase(wxT("time with time zone")) || !valNoArray.CmpNoCase(wxT("\"trigger\"")) || !valNoArray.CmpNoCase(wxT("\"unknown\"")))) return false; int pos = 0; while (pos < (int)valNoArray.length()) { wxChar c = valNoArray.GetChar(pos); if (!((pos > 0) && (c >= '0' && c <= '9')) && !(c >= 'a' && c <= 'z') && !(c == '_')) { return true; } pos++; } } // is it a keyword? const ScanKeyword *sk = ScanKeywordLookup(value.ToAscii()); if (!sk) return false; if (sk->category == UNRESERVED_KEYWORD) return false; if (forTypes && sk->category == COL_NAME_KEYWORD) return false; return true; } wxString qtTypeIdent(const wxString &value) { if (value.Length() == 0) return value; wxString result = value; if (needsQuoting(result, true)) { result.Replace(wxT("\""), wxT("\"\"")); return wxT("\"") + result + wxT("\""); } else return result; } wxString qtIdent(const wxString &value) { if (value.Length() == 0) return value; wxString result = value; if (needsQuoting(result, false)) { result.Replace(wxT("\""), wxT("\"\"")); return wxT("\"") + result + wxT("\""); } else return result; } #if !defined(PGSCLI) wxString qtStrip(const wxString &str) { if (str.Left(2) == wxT("\\\"")) return str.Mid(2, str.Length() - 4); else return str; } wxString TransformToNewDatconfig(const wxString &list) { const wxChar *cp = list.c_str(); wxString config = wxEmptyString; wxString str = wxEmptyString; bool quote = false; while (*cp) { switch (*cp) { case '\\': { if (cp[1] == '"') { str.Append(*cp); cp++; str.Append(*cp); } break; } case '"': case '\'': { quote = !quote; str.Append(*cp); break; } case ',': { if (!quote) { if (!config.IsEmpty()) config += wxT(","); config += wxT("=") + str; str = wxEmptyString; break; } } default: { str.Append(*cp); break; } } cp++; } if (!str.IsEmpty()) { if (!config.IsEmpty()) config += wxT(","); config += wxT("=") + str; } return config; } void FillArray(wxArrayString &array, const wxString &list) { const wxChar *cp = list.c_str(); wxString str; bool quote = false; while (*cp) { switch (*cp) { case '\\': { if (cp[1] == '"') { cp++; str.Append(*cp); } break; } case '"': case '\'': { quote = !quote; break; } case ',': { if (!quote) { array.Add(str); str = wxEmptyString; break; } } default: { str.Append(*cp); break; } } cp++; } if (!str.IsEmpty()) array.Add(str); } queryTokenizer::queryTokenizer(const wxString &str, const wxChar delim) : wxStringTokenizer() { if (delim == (wxChar)' ') SetString(str, wxT(" \n\r\t"), wxTOKEN_RET_EMPTY_ALL); else SetString(str, delim, wxTOKEN_RET_EMPTY_ALL); delimiter = delim; } void AppendIfFilled(wxString &str, const wxString &delimiter, const wxString &what) { if (!what.IsNull()) str += delimiter + what; } wxString queryTokenizer::GetNextToken() { // we need to override wxStringTokenizer, because we have to handle quotes wxString str; bool foundQuote = false; do { wxString s = wxStringTokenizer::GetNextToken(); str.Append(s); int quotePos; do { quotePos = s.Find('"'); if (quotePos >= 0) { foundQuote = !foundQuote; s = s.Mid(quotePos + 1); } } while (quotePos >= 0); if (foundQuote) str.Append(delimiter); } while (foundQuote && HasMoreTokens()); return str; } wxString FileRead(const wxString &filename, int format) { wxString str; wxFontEncoding encoding; if (format > 0) encoding = wxFONTENCODING_UTF8; else encoding = wxFONTENCODING_DEFAULT; wxUtfFile file(filename, wxFile::read, encoding); if (file.IsOpened()) file.Read(str); return wxTextBuffer::Translate(str, wxTextFileType_Unix); // we want only \n } bool FileWrite(const wxString &filename, const wxString &data, int format) { wxFontEncoding encoding = wxFONTENCODING_DEFAULT; wxUtfFile file; if (format < 0) { if (wxFile::Access(filename, wxFile::read)) { file.Open(filename); encoding = file.GetEncoding(); file.Close(); } if (encoding == wxFONTENCODING_DEFAULT) encoding = settings->GetUnicodeFile() ? wxFONTENCODING_UTF8 : wxFONTENCODING_SYSTEM; } else encoding = format ? wxFONTENCODING_UTF8 : wxFONTENCODING_SYSTEM; file.Open(filename, wxFile::write, wxS_DEFAULT, encoding); if (file.IsOpened()) return file.Write(wxTextBuffer::Translate(data)); return false; } wxString CleanHelpPath(const wxString &path) { wxString thePath = path; if (thePath.IsEmpty()) return wxEmptyString; // If the filename ends in .chm, .hhp, .pdf or .zip, it's // a file based help system and we can assumes it's // correct. if (thePath.Lower().EndsWith(wxT(".hhp")) || #if defined (__WXMSW__) || wxUSE_LIBMSPACK thePath.Lower().EndsWith(wxT(".chm")) || #endif thePath.Lower().EndsWith(wxT(".pdf")) || thePath.Lower().EndsWith(wxT(".zip"))) return thePath; // In all other cases we must have a directory wxString sep; // Figure out the appropriate seperator if (thePath.Lower().Contains(wxT("://"))) sep = wxT("/"); else sep = wxFileName::GetPathSeparator(); // First, correct the path separators thePath.Replace(wxT("/"), sep); thePath.Replace(wxT("\\"), sep); // Now, append the seperator if it's not there if (!thePath.EndsWith(sep)) thePath += sep; return thePath; } bool HelpPathValid(const wxString &path) { if (path.IsEmpty()) return true; // If the filename contains any of the sensible URL schemes // we just assume it's correct if the end also looks right. if ((path.Lower().StartsWith(wxT("http://")) || path.Lower().StartsWith(wxT("https://")) || path.Lower().StartsWith(wxT("file://")) || path.Lower().StartsWith(wxT("ftp://"))) && (path.Lower().EndsWith(wxT(".hhp")) || #if defined (__WXMSW__) || wxUSE_LIBMSPACK path.Lower().EndsWith(wxT(".chm")) || #endif path.Lower().EndsWith(wxT(".pdf")) || path.Lower().EndsWith(wxT(".zip")) || path.Lower().EndsWith(wxT("/")))) return true; // Otherwise, we're looking for a file (or directory) that // actually exists. wxString sep = wxFileName::GetPathSeparator(); if (path.Lower().EndsWith(wxT(".hhp")) || #if defined (__WXMSW__) || wxUSE_LIBMSPACK path.Lower().EndsWith(wxT(".chm")) || #endif path.Lower().EndsWith(wxT(".pdf")) || path.Lower().EndsWith(wxT(".zip"))) return wxFile::Exists(path); else if (path.Lower().EndsWith(sep)) return wxDir::Exists(path); else return false; } void DisplayHelp(const wxString &helpTopic, const HelpType helpType) { static wxHelpControllerBase *pgHelpCtl = 0; static wxHelpControllerBase *edbHelpCtl = 0; static wxHelpControllerBase *greenplumHelpCtl = 0; static wxHelpControllerBase *slonyHelpCtl = 0; static wxString pgInitPath = wxEmptyString; static wxString edbInitPath = wxEmptyString; static wxString gpInitPath = wxEmptyString; static wxString slonyInitPath = wxEmptyString; switch (helpType) { case HELP_PGADMIN: DisplayPgAdminHelp(helpTopic); break; case HELP_POSTGRESQL: DisplayExternalHelp(helpTopic, settings->GetPgHelpPath(), pgHelpCtl, (pgInitPath != settings->GetPgHelpPath() ? true : false)); pgInitPath = settings->GetPgHelpPath(); break; case HELP_ENTERPRISEDB: DisplayExternalHelp(helpTopic, settings->GetEdbHelpPath(), edbHelpCtl, (edbInitPath != settings->GetEdbHelpPath() ? true : false)); edbInitPath = settings->GetEdbHelpPath(); break; case HELP_GREENPLUM: { // the old help path (stored in the settings) is no longer working static wxString gpHelpPath = settings->GetGpHelpPath(); // Note: never end the URL on "index.html" // InitHelp() does obscure magic with this ending if (gpHelpPath.CmpNoCase(wxT("http://docs.gopivotal.com/gpdb/")) == 0) { gpHelpPath = wxT("http://gpdb.docs.pivotal.io/"); // Replace the path to the old domain with the link to // the new documentation path // The old link is working for now, but there is no guarantee // that it will stay this way // Also the new link automatically redirects to the latest version settings->SetGpHelpPath(gpHelpPath); } if (gpHelpPath.CmpNoCase(wxT("http://www.greenplum.com/docs/3300/")) == 0) { gpHelpPath = wxT("http://gpdb.docs.pivotal.io/"); // this is the old link, update the link to the new documentation link // problem: this saves the link into the configuration file settings->SetGpHelpPath(gpHelpPath); } DisplayExternalHelp(helpTopic, settings->GetGpHelpPath(), greenplumHelpCtl, (gpInitPath != settings->GetGpHelpPath() ? true : false)); gpInitPath = settings->GetGpHelpPath(); } break; case HELP_SLONY: DisplayExternalHelp(helpTopic, settings->GetSlonyHelpPath(), slonyHelpCtl, (slonyInitPath != settings->GetSlonyHelpPath() ? true : false)); slonyInitPath = settings->GetSlonyHelpPath(); break; default: DisplayPgAdminHelp(helpTopic); break; } } void DisplayPgAdminHelp(const wxString &helpTopic) { static wxHelpControllerBase *helpCtl = 0; static bool firstCall = true; // Startup the main help system if (firstCall) { firstCall = false; wxString helpdir = docPath + wxT("/") + settings->GetCanonicalLanguageName(); if (!wxFile::Exists(helpdir + wxT("/pgadmin3.hhp")) && #if defined(__WXMSW__) || wxUSE_LIBMSPACK !wxFile::Exists(helpdir + wxT("/pgadmin3.chm")) && #endif !wxFile::Exists(helpdir + wxT("/pgadmin3.zip"))) helpdir = docPath + wxT("/en_US"); #ifdef __WXMSW__ #ifndef __WXDEBUG__ if (wxFile::Exists(helpdir + wxT("/pgadmin3.chm"))) { helpCtl = new wxCHMHelpController(); helpCtl->Initialize(helpdir + wxT("/pgadmin3")); } else #endif #endif #if wxUSE_LIBMSPACK if (wxFile::Exists(helpdir + wxT("/pgadmin3.chm")) || wxFile::Exists(helpdir + wxT("/pgadmin3.hhp")) || wxFile::Exists(helpdir + wxT("/pgadmin3.zip"))) #else if (wxFile::Exists(helpdir + wxT("/pgadmin3.hhp")) || wxFile::Exists(helpdir + wxT("/pgadmin3.zip"))) #endif { helpCtl = new wxHtmlHelpController(); helpCtl->Initialize(helpdir + wxT("/pgadmin3")); } } wxString page; int hashPos = helpTopic.Find('#'); if (hashPos < 0) page = helpTopic + wxT(".html"); else page = helpTopic.Left(hashPos) + wxT(".html") + helpTopic.Mid(hashPos); if (helpCtl) { if (helpTopic == wxT("index.html")) helpCtl->DisplayContents(); else helpCtl->DisplaySection(page); } else { wxLaunchDefaultBrowser(page); } } void DisplayExternalHelp(const wxString &helpTopic, const wxString &docPath, wxHelpControllerBase *helpCtl, const bool init) { // Build the page name wxString page; int hashPos = helpTopic.Find('#'); if (hashPos < 0) page = helpTopic + wxT(".html"); else page = helpTopic.Left(hashPos) + wxT(".html") + helpTopic.Mid(hashPos); // If the docPath ends in .pdf, then open the file in the browser. No // bookmarks though :-( if (docPath.Lower().EndsWith(wxT(".pdf"))) { wxLaunchDefaultBrowser(docPath); return; } // If the docPath doesn't end in .chm, .zip or .hhp, then we must be using // plain HTML files, so just fire off the browser and be done with it. if (!docPath.Lower().EndsWith(wxT(".hhp")) && #if defined (__WXMSW__) || wxUSE_LIBMSPACK !docPath.Lower().EndsWith(wxT(".chm")) && #endif !docPath.Lower().EndsWith(wxT(".zip"))) { wxLaunchDefaultBrowser(docPath + page); return; } // We must be using HTML Help, so init the appropriate help controller // Note the path that we init for - if it changes, we need to init a // new controller in case it's no longer the same type if (init || !helpCtl) { // Get shot of the old help controller if there is one. if (helpCtl) delete helpCtl; #ifdef __WXMSW__ // For Windows builds we us the MS HTML Help viewer for .chm files if (docPath.Lower().EndsWith(wxT(".chm")) && wxFile::Exists(docPath)) { helpCtl = new wxCHMHelpController(); helpCtl->Initialize(docPath); } else #endif #if wxUSE_LIBMSPACK // If we can use a .chm file... if ((docPath.Lower().EndsWith(wxT(".chm")) && wxFile::Exists(docPath)) || (docPath.Lower().EndsWith(wxT(".hhp")) && wxFile::Exists(docPath)) || (docPath.Lower().EndsWith(wxT(".zip")) && wxFile::Exists(docPath))) #else // Otherwise... if ((docPath.Lower().EndsWith(wxT(".hhp")) && wxFile::Exists(docPath)) || (docPath.Lower().EndsWith(wxT(".zip")) && wxFile::Exists(docPath))) #endif { helpCtl = new wxHtmlHelpController(); helpCtl->Initialize(docPath); } } // Display the page using the help controller // If it's foobar'ed, use the browser. if (helpCtl) { if (helpTopic == wxT("index.html")) helpCtl->DisplayContents(); else helpCtl->DisplaySection(page); } else { wxLogError(_("The help source (\"%s\") could not be opened. Please check the help configuration options."), docPath.c_str()); } } wxString GetHtmlEntity(const wxChar ch) { // REWRITE THIS - IT'S (STILL) BLOODY INEFFICIENT!! // Quick bailout if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')) return wxString(ch); unsigned short ents[] = { 34, 39, 38, 60, 62, 160, 161, 164, 162, 163, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 8482, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 215, 247, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 248, 249, 250, 251, 252, 253, 254, 255, 338, 339, 352, 353, 376, 710, 732, 8194, 8195, 8201, 8204, 8205, 8206, 8207, 8211, 8212, 8216, 8217, 8218, 8220, 8221, 8222, 8224, 8225, 8230, 8240, 8249, 8250, 8364, 0 }; int elem = 0; while (ents[elem] != 0) { if (ch == ents[elem]) { wxString ret = wxT("&#"); ret += NumToStr((long)ents[elem]); ret += wxT(";"); return ret; } elem++; } return wxString(ch); } wxString HtmlEntities(const wxString &str) { wxString ret; for (unsigned int x = 0; x < str.Length(); x++) { if (str[x] != 13) ret += GetHtmlEntity(str[x]); } return ret; } #ifndef WIN32 wxString ExecProcess(const wxString &cmd) { wxString res; FILE *f = popen(cmd.ToAscii(), "r"); if (f) { char buffer[1024]; int cnt; while ((cnt = fread(buffer, 1, 1024, f)) > 0) { res += wxString::FromAscii(buffer); } pclose(f); } return res; } int ExecProcess(const wxString &command, wxArrayString &result) { FILE *fp_command; char buf[4098]; fp_command = popen(command.mb_str(wxConvUTF8), "r"); if (!fp_command) return -1; while(!feof(fp_command)) { if (fgets(buf, 4096, fp_command) != NULL) result.Add(wxString::FromAscii(buf)); } return pclose(fp_command); } #endif #ifdef WIN32 #if (_MSC_VER < 1300) /* _ftol2 is more than VC7. */ /* extern "C" long _ftol( double ); extern "C" long _ftol2( double dblSource ) { return _ftol( dblSource ); } */ #endif #endif wxString firstLineOnly(const wxString &str) { wxString ip, tmp; ip = str; ip = ip.Trim(true).Trim(false); if (ip.Contains(wxT("\r\n")) && (ip.First(wxT("\r")) < ip.First(wxT("\n")))) { tmp = ip.BeforeFirst('\r'); if (ip.BeforeFirst('\r').Length() != ip.Length()) tmp += wxT("..."); } else { tmp = ip.BeforeFirst('\n'); if (ip.BeforeFirst('\n').Length() != ip.Length()) tmp += wxT("..."); } return tmp; } bool pgAppMinimumVersion(const wxString &cmd, const int majorVer, const int minorVer) { wxArrayString output; bool isEnterpriseDB = false; #ifdef __WXMSW__ if (wxExecute(cmd + wxT(" --version"), output, 0) != 0) #else if (ExecProcess(cmd + wxT(" --version"), output) != 0) #endif { wxLogError(_("Failed to execute: %s --version"), cmd.c_str()); return false; } // Is this an EDB utility? if (output[0].Contains(wxT("EnterpriseDB"))) isEnterpriseDB = true; wxString version = output[0].AfterLast(' '); int len=version.Length(); long actualMajor = 0, actualMinor = 0; wxString tmp = wxT(""); int x = 0; while(x majorVer) return true; if (actualMajor == majorVer && actualMinor >= minorVer) return true; return false; } bool isPgApp(const wxString &app) { if (!wxFile::Exists(app)) return false; wxArrayString output; #ifdef __WXMSW__ if (wxExecute(app + wxT(" --version"), output, 0) != 0) #else if (ExecProcess(app + wxT(" --version"), output) != 0) #endif { wxLogError(_("Failed to execute: %s --version"), app.c_str()); return false; } if (output[0].Contains(wxT("PostgreSQL"))) return true; return false; } bool isEdbApp(const wxString &app) { if (!wxFile::Exists(app)) return false; wxArrayString output; #ifdef __WXMSW__ if (wxExecute(app + wxT(" --version"), output, 0) != 0) #else if (ExecProcess(app + wxT(" --version"), output) != 0) #endif { wxLogError(_("Failed to execute: %s --version"), app.c_str()); return false; } if (output[0].Contains(wxT("EnterpriseDB"))) return true; return false; } bool isGpApp(const wxString &app) { if (!wxFile::Exists(app)) return false; wxArrayString output; #ifdef __WXMSW__ if (wxExecute(app + wxT(" --version"), output, 0) != 0) #else if (ExecProcess(app + wxT(" --version"), output) != 0) #endif { wxLogError(_("Failed to execute: %s --version"), app.c_str()); return false; } if (output[0].Contains(wxT("8.2"))) // Ugly... No way to tell Greenplum app from PostgreSQL 8.2 app return true; return false; } wxString sanitizePath(const wxString &path) { if (path.Length()) { wxFileName fn = path; fn.Normalize(); return fn.GetLongPath(); } return wxEmptyString; } /** * FUNCTION: commandLineCleanOption * INPUTS: * option - input string needs to be reformatted * schemaObject - Is this an object related to schema? * PURPOSE: * - Fixup a (double-quoted) string for use on the command line */ wxString commandLineCleanOption(const wxString &option, bool schemaObject) { wxString tmp = option; if (schemaObject) { // Replace double-quote with slash & double-quote tmp.Replace(wxT("\""), wxT("\\\"")); } else { // If required, clean the string to know the real object name if (option.StartsWith(wxT("\"")) && option.EndsWith(wxT("\""))) tmp = option.AfterFirst((wxChar)'"').BeforeLast((wxChar)'"'); // Replace single splash to double-splash tmp.Replace(wxT("\\"), wxT("\\\\")); // Replace double-quote with slash & double-quote tmp.Replace(wxT("\""), wxT("\\\"")); // Replace double (slash & double-quote) combination to single (slash & double-quote) combination tmp.Replace(wxT("\\\"\\\""), wxT("\\\"")); // Add the double quotes tmp = wxT("\"") + tmp + wxT("\""); } return tmp; } #endif // PGSCLI // Get an array from a comma separated list bool getArrayFromCommaSeparatedList(const wxString &str, wxArrayString &res) { size_t len = str.Len(), index = 0, nBracketLevel = 0, startArray = 0; bool inSingleQuote = false, inDoubleQuote = false; if (len == 0) return true; for(; index < len; index++) { wxChar curr = str.GetChar(index); if (!inDoubleQuote && curr == (wxChar)'\'') inSingleQuote = !inSingleQuote; else if (!inSingleQuote && curr == (wxChar)'"') inDoubleQuote = !inDoubleQuote; else if (!inDoubleQuote && !inSingleQuote && curr == (wxChar)'(') nBracketLevel++; else if (!inDoubleQuote && !inSingleQuote && curr == (wxChar)')') nBracketLevel--; else if (!inDoubleQuote && !inSingleQuote && nBracketLevel == 0 && curr == (wxChar)',') { if (index != startArray) res.Add(str.SubString(startArray, index - 1).Trim(true).Trim(false)); else res.Add(wxEmptyString); startArray = index + 1; } } if (inDoubleQuote || inSingleQuote || nBracketLevel != 0) return false; // Add last value to array res.Add(str.SubString(startArray, index).Trim(true).Trim(false)); return true; } bool make_identifier(const wxString &strname, wxString &s, wxString &n, bool islower) { s=strname.BeforeFirst('.'); if (s==strname) { n=strname; s=""; } else { // full name n=strname.AfterFirst('.'); } // if (n.Find('"')>=0) { n.Replace("\"",""); } else {if (islower) n=n.MakeLower();} if (s.Find('"')>=0) { s.Replace("\"",""); } else {if (islower) s=s.MakeLower();} return true; } // Get display for ScreenPoint wxSize getScreenSizeForPoint(const wxPoint screenPos) { // screen size wxPoint posScreen; wxSize sizeScreen; const int displayNum = wxDisplay::GetFromPoint(screenPos); if (displayNum != wxNOT_FOUND) { const wxRect rectScreen = wxDisplay(displayNum).GetGeometry(); posScreen = rectScreen.GetPosition(); sizeScreen = rectScreen.GetSize(); } else // outside of any display? { // just use the primary one then posScreen = wxPoint(0, 0); sizeScreen = wxGetDisplaySize(); } return sizeScreen; } //show help window void showHelpHtml(wxWindow *parent, const wxString &htmlHelp,wxPoint screenPos, wxSize size) { FunctionPGHelper fh(htmlHelp); wxString key = "content"; wxSize sizeScreen=getScreenSizeForPoint(screenPos); wxSize rr(350, 70); if (size.x!=-1) rr=size; popuphelp *m_Popup = new popuphelp(parent, key, &fh, screenPos, rr); if (m_Popup && m_Popup->IsValid() && rr != m_Popup->GetSizePopup()) { // recreate with new size rr = m_Popup->GetSizePopup(); delete m_Popup; m_Popup = new popuphelp((wxWindow*)winMain, key, &fh, screenPos, rr); } if (m_Popup && m_Popup->IsValid()) { wxSize top_sz = m_Popup->GetSizePopup(); wxSize top_new(top_sz); wxPoint p(screenPos); wxPoint oldp(p); if (p.x + top_new.x > sizeScreen.x) p.x = sizeScreen.x - top_new.x - 20; if (p.y + top_new.y > sizeScreen.y) p.y = sizeScreen.y - top_new.y - 20; if (oldp == p) p.x = p.x + 20; m_Popup->Move(p); wxRect r = m_Popup->GetScreenRect(); m_Popup->Popup(); } //m_Popup->SetFocus(); }