// XXX taken from Windows PWSTreeCtrl.cpp // XXX move to core static StringX GetPathElem(StringX &sxPath) { // Get first path element and chop it off, i.e., if // path = "a.b.c.d" // will return "a" and path will be "b.c.d" // path = "a..b.c.d" // will return "a." and path will be "b.c.d" // (assuming GROUP_SEP is '.') StringX sxElement; size_t dotPos = sxPath.find_first_of(GROUP_SEP); size_t len=sxPath.length(); if (dotPos == StringX::npos){ sxElement = sxPath; sxPath = wxT(""); } else { while ((dotPos < len) && (sxPath[dotPos] == GROUP_SEP)) {// look for consecutive dots dotPos++; } if (dotPos < len) { sxElement = sxPath.substr(0, dotPos-1); sxPath = sxPath.substr(dotPos); } else { // trailing dots sxElement = sxPath; sxPath = wxT(""); } } return sxElement; }
// Return whether first '«g» «t» «u»' is greater than the second '«g» «t» «u»' // used in std::sort below. // Need this as '»' is not in the correct lexical order for blank fields in entry bool MergeSyncGTUCompare(const StringX &elem1, const StringX &elem2) { StringX g1, t1, u1, g2, t2, u2, tmp1, tmp2; StringX::size_type i1 = elem1.find(L'\xbb'); g1 = (i1 == StringX::npos) ? elem1 : elem1.substr(0, i1 - 1); StringX::size_type i2 = elem2.find(L'\xbb'); g2 = (i2 == StringX::npos) ? elem2 : elem2.substr(0, i2 - 1); if (g1 != g2) return g1.compare(g2) < 0; tmp1 = elem1.substr(g1.length() + 3); tmp2 = elem2.substr(g2.length() + 3); i1 = tmp1.find(L'\xbb'); t1 = (i1 == StringX::npos) ? tmp1 : tmp1.substr(0, i1 - 1); i2 = tmp2.find(L'\xbb'); t2 = (i2 == StringX::npos) ? tmp2 : tmp2.substr(0, i2 - 1); if (t1 != t2) return t1.compare(t2) < 0; tmp1 = tmp1.substr(t1.length() + 3); tmp2 = tmp2.substr(t2.length() + 3); i1 = tmp1.find(L'\xbb'); u1 = (i1 == StringX::npos) ? tmp1 : tmp1.substr(0, i1 - 1); i2 = tmp2.find(L'\xbb'); u2 = (i2 == StringX::npos) ? tmp2 : tmp2.substr(0, i2 - 1); return u1.compare(u2) < 0; }
static void ParseNotes(StringX &sxNotes, std::vector<StringX> &vsxnotes_lines) { if (!sxNotes.empty()) { // Use \n and \r to tokenise this line StringX::size_type st_start(0), st_end(0); const StringX sxdelim = _T("\r\n"); StringX sxline; StringX::size_type st_index; while (st_end != StringX::npos) { st_end = sxNotes.find(sxdelim, st_start); sxline = (sxNotes.substr(st_start, (st_end == StringX::npos) ? StringX::npos : st_end - st_start)); st_index = 0; // Remove all tabs - \t for (;;) { st_index = sxline.find(_T("\\t"), st_index); if (st_index == StringX::npos) break; sxline.replace(st_index, 2, _T("")); st_index += 1; } vsxnotes_lines.push_back(sxline); st_start = ((st_end > (StringX::npos - sxdelim.size())) ? StringX::npos : st_end + sxdelim.size()); } } }
pws_os::CUUID::CUUID(const StringX &s) : m_ua(NULL), m_canonic(false) { // s is a hex string as returned by cast to StringX ASSERT(s.length() == 32); unsigned char *uu = m_uuid; int x; for (int i = 0; i < 16; i++) { iStringXStream is(s.substr(i*2, 2)); is >> hex >> x; uu[i] = static_cast<unsigned char>(x); } }
pws_os::CUUID::CUUID(const StringX &s) : m_ua(NULL), m_canonic(false) { // s is a hex string as returned by cast to StringX ASSERT(s.length() == 32); uuid_array_t ua; unsigned int x(0); for (size_t i = 0; i < 16; i++) { iStringXStream is(s.substr(i * 2, 2)); is >> hex >> x; ua[i] = static_cast<unsigned char>(x); } array2UUUID(ua, m_uuid); }
static void ExtractURL(StringX ¬esStr, StringX &outurl) { StringX instr(notesStr); // Extract first instance of (http|https|ftp)://[^ \t\r\n]+ StringX::size_type left = instr.find(_T("http://")); if (left == StringX::npos) left = instr.find(_T("https://")); if (left == StringX::npos) left = instr.find(_T("ftp://")); if (left == StringX::npos) { outurl = _T(""); } else { StringX url(instr); instr = notesStr.substr(0, left); url = url.substr(left); // throw out everything left of URL StringX::size_type right = url.find_first_of(_T(" \t\r\n")); if (right != StringX::npos) { instr += url.substr(right); url = url.substr(0, right); } outurl = url; notesStr = instr; } }
static void GetFilterTestXML(const st_FilterRow &st_fldata, ostringstream &oss, bool bFile) { CUTF8Conv utf8conv; const unsigned char *utf8 = NULL; size_t utf8Len = 0; const char *sztab4, *sztab5, *szendl; if (bFile) { sztab4 = "\t\t\t\t"; sztab5 = "\t\t\t\t\t"; szendl = "\n"; } else { sztab4 = sztab5 = "\0"; szendl = "\0"; } if (st_fldata.mtype != PWSMatch::MT_BOOL) oss << sztab4 << "<test>" << szendl; switch (st_fldata.mtype) { case PWSMatch::MT_STRING: // Even if rule == 'present'/'not present', need to put 'string' & 'case' XML // elements to make schema work, since W3C Schema V1.0 does NOT support // conditional processing :-( // 'string' needs special processing to place within CDATA XML construct if (!st_fldata.fstring.empty()) { // string empty if 'present' or 'not present' PWSUtil::WriteXMLField(oss, "string", st_fldata.fstring, utf8conv, sztab5); } else { oss << sztab5 << "<string></string>" << szendl; } oss << sztab5 << "<case>" << st_fldata.fcase << "</case>" << szendl; break; case PWSMatch::MT_PASSWORD: // 'string' needs special processing to place within CDATA XML construct PWSUtil::WriteXMLField(oss, "string", st_fldata.fstring, utf8conv, sztab5); oss << sztab5 << "<case>" << st_fldata.fcase << "</case>" << szendl; oss << sztab5 << "<warn>" << st_fldata.fcase << "</warn>" << szendl; break; case PWSMatch::MT_INTEGER: oss << sztab5 << "<num1>" << st_fldata.fnum1 << "</num1>" << endl; oss << sztab5 << "<num2>" << st_fldata.fnum2 << "</num2>" << endl; break; case PWSMatch::MT_DATE: { if (st_fldata.fdatetype == 0 /* DTYPE_ABS */) { const StringX tmp1 = PWSUtil::ConvertToDateTimeString(st_fldata.fdate1, PWSUtil::TMC_XML); utf8conv.ToUTF8(tmp1.substr(0, 10), utf8, utf8Len); oss << sztab5 << "<date1>" << utf8 << "</date1>" << szendl; const StringX tmp2 = PWSUtil::ConvertToDateTimeString(st_fldata.fdate2, PWSUtil::TMC_XML); utf8conv.ToUTF8(tmp2.substr(0, 10), utf8, utf8Len); oss << sztab5 << "<date2>" << utf8 << "</date2>" << szendl; } else { oss << sztab5 << "<num1>" << st_fldata.fnum1 << "</num1>" << endl; oss << sztab5 << "<num2>" << st_fldata.fnum2 << "</num2>" << endl; } break; } case PWSMatch::MT_ENTRYTYPE: { // Get index for string values int index(0); switch (st_fldata.etype) { case CItemData::ET_NORMAL: index = 0; break; case CItemData::ET_ALIASBASE: index = 1; break; case CItemData::ET_ALIAS: index = 2; break; case CItemData::ET_SHORTCUTBASE: index = 3; break; case CItemData::ET_SHORTCUT: index = 4; break; default: ASSERT(0); } oss << sztab5 << "<type>" << szentry[index] << "</type>" << szendl; break; } case PWSMatch::MT_DCA: oss << sztab5 << "<dca>" << st_fldata.fdca << "</dca>" << szendl; break; case PWSMatch::MT_SHIFTDCA: oss << sztab5 << "<shiftdca>" << st_fldata.fdca << "</shiftdca>" << szendl; break; case PWSMatch::MT_ENTRYSTATUS: { // Get index for string values int index(0); switch (st_fldata.estatus) { case CItemData::ES_CLEAN: index = 0; break; case CItemData::ES_ADDED: index = 1; break; case CItemData::ES_MODIFIED: index = 2; break; case CItemData::ES_DELETED: index = 3; break; default: ASSERT(0); } oss << sztab5 << "<status>" << szstatus[index] << "</status>" << szendl; break; } case PWSMatch::MT_ENTRYSIZE: oss << sztab5 << "<num1>" << st_fldata.fnum1 << "</num1>" << endl; oss << sztab5 << "<num2>" << st_fldata.fnum2 << "</num2>" << endl; oss << sztab5 << "<unit>" << st_fldata.funit << "</unit>" << endl; break; case PWSMatch::MT_BOOL: break; default: ASSERT(0); } if (st_fldata.mtype != PWSMatch::MT_BOOL) oss << sztab4 << "</test>" << szendl; }
//----------------------------------------------------------------- // Externally visible functions //----------------------------------------------------------------- StringX PWSAuxParse::GetExpandedString(const StringX &sxRun_Command, const StringX &sxCurrentDB, const CItemData *pci, bool &bAutoType, StringX &sxAutotype, stringT &serrmsg, StringX::size_type &st_column, bool &bURLSpecial) { std::vector<st_RunCommandTokens> v_rctokens; std::vector<st_RunCommandTokens>::iterator rc_iter; StringX sxretval(_T("")), sxurl; stringT spath, sdrive, sdir, sfname, sextn; stringT sdbdir; bURLSpecial = false; UINT uierr = ParseRunCommand(sxRun_Command, v_rctokens, bAutoType, sxAutotype, serrmsg, st_column); // if called with NULL ci, then we just parse to validate if (uierr > 0 || pci == NULL || sxCurrentDB.empty()) { v_rctokens.clear(); return sxretval; } // derive current db's directory and basename: spath = sxCurrentDB.c_str(); pws_os::splitpath(spath, sdrive, sdir, sfname, sextn); sdbdir = pws_os::makepath(sdrive, sdir, _T(""), _T("")); for (rc_iter = v_rctokens.begin(); rc_iter < v_rctokens.end(); rc_iter++) { st_RunCommandTokens &st_rctoken = *rc_iter; if (!st_rctoken.is_variable) { sxretval += st_rctoken.sxname.c_str(); continue; } if (st_rctoken.sxname == _T("appdir")) { sxretval += pws_os::getexecdir().c_str(); } else if (st_rctoken.sxname == _T("dbdir")) { sxretval += sdbdir.c_str(); } else if (st_rctoken.sxname == _T("fulldb")) { sxretval += spath.c_str(); } else if (st_rctoken.sxname == _T("dbname")) { sxretval += sfname.c_str(); } else if (st_rctoken.sxname == _T("dbextn")) { sxretval += sextn.c_str(); } else if (st_rctoken.sxname == _T("g") || st_rctoken.sxname == _T("group")) { sxretval += pci->GetGroup(); } else if (st_rctoken.sxname == _T("G") || st_rctoken.sxname == _T("GROUP")) { StringX sxg = pci->GetGroup(); StringX::size_type st_index; st_index = sxg.rfind(_T(".")); if (st_index != StringX::npos) { sxg = sxg.substr(st_index + 1); } sxretval += sxg; } else if (st_rctoken.sxname == _T("t") || st_rctoken.sxname == _T("title")) { sxretval += pci->GetTitle(); } else if (st_rctoken.sxname == _T("u") || st_rctoken.sxname == _T("user")) { sxretval += pci->GetUser(); } else if (st_rctoken.sxname == _T("p") || st_rctoken.sxname == _T("password")) { sxretval += pci->GetPassword(); } else if (st_rctoken.sxname == _T("e") || st_rctoken.sxname == _T("email")) { sxretval += pci->GetEmail(); } else if (st_rctoken.sxname == _T("a") || st_rctoken.sxname == _T("autotype")) { // Do nothing - autotype variable handled elsewhere } else if (st_rctoken.sxname == _T("url")) { sxurl = pci->GetURL(); if (sxurl.length() > 0) { // Remove 'Browse to' specifics StringX::size_type ipos; ipos = sxurl.find(_T("[alt]")); if (ipos != StringX::npos) { bURLSpecial = true; sxurl.erase(ipos, 5); } ipos = sxurl.find(_T("[ssh]")); if (ipos != StringX::npos) { bURLSpecial = true; sxurl.erase(ipos, 5); } ipos = sxurl.find(_T("{alt}")); if (ipos != StringX::npos) { bURLSpecial = true; sxurl.erase(ipos, 5); } ipos = sxurl.find(_T("[autotype]")); if (ipos != StringX::npos) { sxurl.erase(ipos, 10); } ipos = sxurl.find(_T("[xa]")); if (ipos != StringX::npos) { sxurl.erase(ipos, 4); } sxretval += sxurl; } } else if (st_rctoken.sxname == _T("n") || st_rctoken.sxname == _T("notes")) { StringX sx_notes = pci->GetNotes(); if (st_rctoken.index == 0) { sxretval += sx_notes; } else { std::vector<StringX> vsxnotes_lines; ParseNotes(sx_notes, vsxnotes_lines); // If line there - use it; otherwise ignore it if (st_rctoken.index > 0 && st_rctoken.index <= static_cast<int>(vsxnotes_lines.size())) { sxretval += vsxnotes_lines[st_rctoken.index - 1]; } else if (st_rctoken.index < 0 && abs(st_rctoken.index) <= static_cast<int>(vsxnotes_lines.size())) { sxretval += vsxnotes_lines[vsxnotes_lines.size() + st_rctoken.index]; } } } else { // Unknown variable name - rebuild it sxretval += _T("$"); if (st_rctoken.has_brackets) sxretval += _T("("); sxretval += st_rctoken.sxname.c_str(); if (st_rctoken.index != 0) sxretval += st_rctoken.sxindex.c_str(); if (st_rctoken.has_brackets) sxretval += _T(")"); } } v_rctokens.clear(); return sxretval; }
//----------------------------------------------------------------- // Internal functions //----------------------------------------------------------------- static UINT ParseRunCommand(const StringX &sxInputString, std::vector<st_RunCommandTokens> &v_rctokens, bool &bDoAutoType, StringX &sxAutoType, stringT &serrmsg, StringX::size_type &st_column) { // tokenize into separate elements std::vector<st_RunCommandTokens>::iterator rc_iter; std::vector<size_t> v_pos; StringX::iterator str_Iter; st_RunCommandTokens st_rctoken; size_t st_num_quotes(0); UINT uierr(0); int var_index(0); const stringT alphanum = _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); if (sxInputString.empty()) { // String is empty! uierr = IDSC_EXS_INPUTEMPTY; goto exit; } for (StringX::size_type l = 0; l < sxInputString.length(); l++) { if (sxInputString[l] == _T('"')) st_num_quotes++; } if (st_num_quotes % 2 != 0) { st_column = sxInputString.find(_T('"')); // Unmatched quotes uierr = IDSC_EXS_UNMATCHEDQUOTES; goto exit; } // tokenize into separate elements using $ as the field separator for (StringX::size_type st_startpos = 0; st_startpos < sxInputString.size(); /* st_startpos advanced in body */) { StringX::size_type st_next = sxInputString.find(_T('$'), st_startpos); if (st_next == StringX::npos) st_next = sxInputString.size(); if (st_next > 0) { st_rctoken.sxname = sxInputString.substr(st_startpos, st_next - st_startpos); st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = st_startpos == 0 ? false : true; st_rctoken.has_brackets = false; v_rctokens.push_back(st_rctoken); v_pos.push_back(st_startpos); } st_startpos = st_next + 1; // too complex for for statement } // tokenization for loop // Check if escaped - ending character of previous token == '\' // Make sure this '\' is not escaped itself! for (size_t st_idx = v_rctokens.size() - 1; st_idx > 0 ; st_idx--) { st_RunCommandTokens &st_rctokens = v_rctokens[st_idx - 1]; StringX::size_type name_len = st_rctokens.sxname.length(); if (name_len == 0 || (name_len >= 2 && st_rctokens.sxname.substr(name_len - 2, 2).compare(_T("\\\\")) == 0)) continue; if (st_rctokens.sxname.substr(name_len - 1, 1).compare(_T("\\")) == 0) { st_rctokens.sxname = st_rctokens.sxname.substr(0, name_len - 1) + _T("$") + v_rctokens[st_idx].sxname; v_rctokens.erase(v_rctokens.begin() + st_idx); } } // Check if variable enclosed in curly brackets for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) { if (v_rctokens[st_idx].sxname.length() == 0) continue; str_Iter = v_rctokens[st_idx].sxname.begin(); // Does it start with a curly bracket? if (*str_Iter == _T('{')) { v_rctokens[st_idx].has_brackets = true; StringX sxvar, sxnonvar, sxindex(_T("")); // Yes - Find end curly bracket StringX::size_type st_end_cb = v_rctokens[st_idx].sxname.find(_T('}')); if (st_end_cb == StringX::npos) { st_column = v_pos[st_idx] + v_rctokens[st_idx].sxname.length(); // Missing end curly bracket uierr = IDSC_EXS_MISSINGCURLYBKT; goto exit; } // Now see if there is an Index here StringX::size_type st_start_sb = v_rctokens[st_idx].sxname.find(_T('[')); if (st_start_sb != StringX::npos) { // Yes - find end square bracket if (st_start_sb > st_end_cb) { // Square backet after end of variable sxvar = v_rctokens[st_idx].sxname.substr(1, st_end_cb - 1); sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1); v_rctokens[st_idx].sxname = sxvar; if (sxnonvar.length() > 0) { st_rctoken.sxname = sxnonvar; st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = false; st_rctoken.has_brackets = false; v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken); v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_end_cb); } continue; } StringX::size_type st_end_sb = v_rctokens[st_idx].sxname.find(_T(']'), st_start_sb); if (st_end_sb == StringX::npos) { st_column = v_pos[st_idx] + 1; // Missing end square bracket uierr = IDSC_EXS_MISSINGSQUAREBKT; goto exit; } // The end-curly backet must immediately follow the end-square bracket if (st_end_cb != st_end_sb + 1) { st_column = v_pos[st_idx] + st_end_sb + 1; // Characters between ']' and ')' uierr = IDSC_EXS_INVALIDBRACKETS; goto exit; } sxindex = v_rctokens[st_idx].sxname.substr(st_start_sb + 1, st_end_sb - st_start_sb - 1); v_rctokens[st_idx].sxindex = sxindex; // Now check index uierr = ProcessIndex(sxindex, var_index, st_column); if (uierr > 0) { st_column += v_pos[st_idx]; goto exit; } v_rctokens[st_idx].index = var_index; sxvar = v_rctokens[st_idx].sxname.substr(1, st_start_sb - 1); sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1); } else { // No square bracket // Split current token into 'variable' and 'non-variable' parts sxvar = v_rctokens[st_idx].sxname.substr(1, st_end_cb - 1); sxnonvar = v_rctokens[st_idx].sxname.substr(st_end_cb + 1); } v_rctokens[st_idx].sxname = sxvar; if (sxnonvar.length() > 0) { st_rctoken.sxname = sxnonvar; st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = false; st_rctoken.has_brackets = false; v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken); v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_end_cb); } } } // Now use rules of variables to get the real variable for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) { if (!v_rctokens[st_idx].is_variable) continue; if (v_rctokens[st_idx].sxname.length() == 0) { st_column = v_pos[st_idx]; // Variable name is empty uierr = IDSC_EXS_VARNAMEEMPTY; goto exit; } str_Iter = v_rctokens[st_idx].sxname.begin(); if (!isalpha(*str_Iter)) { st_column = v_pos[st_idx]; // First character of variable is not alphabetic uierr = IDSC_EXS_FIRSTNOTALPHA; goto exit; } StringX::size_type st_next = v_rctokens[st_idx].sxname.find_first_not_of(alphanum.c_str()); if (st_next != StringX::npos) { // Split current token into 'variable' and 'non-variable' parts StringX sxvar = v_rctokens[st_idx].sxname.substr(0, st_next); StringX sxnonvar = v_rctokens[st_idx].sxname.substr(st_next); v_rctokens[st_idx].sxname = sxvar; // Before saving non-variable part - check if it is an Index e.g. var[i] if (sxnonvar.c_str()[0] == _T('[')) { // Find ending square bracket StringX::size_type st_end_sb = sxnonvar.find(_T(']')); if (st_end_sb == StringX::npos) { st_column = v_pos[st_idx] + sxvar.length() + 2; // Missing end square bracket uierr = IDSC_EXS_MISSINGSQUAREBKT; goto exit; } StringX sxindex = sxnonvar.substr(1, st_end_sb - 1); v_rctokens[st_idx].sxindex = sxindex; // Now check index uierr = ProcessIndex(sxindex, var_index, st_column); if (uierr > 0) { st_column += v_pos[st_idx] + sxvar.length(); goto exit; } v_rctokens[st_idx].index = var_index; sxnonvar = sxnonvar.substr(st_end_sb + 1); } else { // Not a square bracket if (v_rctokens[st_idx].has_brackets) { st_column = v_pos[st_idx] + st_next + 1; // Variable must be alphanumeric uierr = IDSC_EXS_VARNAMEINVALID; goto exit; } } if (!sxnonvar.empty()) { st_rctoken.sxname = sxnonvar; st_rctoken.sxindex = _T(""); st_rctoken.index = 0; st_rctoken.is_variable = false; st_rctoken.has_brackets = false; v_rctokens.insert(v_rctokens.begin() + st_idx + 1, st_rctoken); v_pos.insert(v_pos.begin() + st_idx + 1, v_pos[st_idx] + st_next); } } } // Special Autotype processing bDoAutoType = false; sxAutoType = _T(""); for (size_t st_idx = 0; st_idx < v_rctokens.size(); st_idx++) { if (!v_rctokens[st_idx].is_variable) continue; // Is it a autotype variable? if (v_rctokens[st_idx].sxname == _T("a") || v_rctokens[st_idx].sxname == _T("autotype")) { bDoAutoType = true; // Is the next token text and starts with '('? if (st_idx + 1 < v_rctokens.size() && !v_rctokens[st_idx + 1].is_variable && v_rctokens[st_idx + 1].sxname.c_str()[0] == _T('(')) { // Find ending round bracket StringX sx_autotype = v_rctokens[st_idx + 1].sxname; StringX::size_type st_end_rb = sx_autotype.find(_T(')')); if (st_end_rb == StringX::npos) { st_column = v_pos[st_idx + 1] + sx_autotype.length() + 2; // Missing end round bracket uierr = IDSC_EXS_MISSINGROUNDBKT; goto exit; } sxAutoType = sx_autotype.substr(1, st_end_rb - 1); v_rctokens[st_idx + 1].sxname = sx_autotype.substr(st_end_rb + 1); // Check if anything left in this text - none -> delete if (v_rctokens[st_idx + 1].sxname.length() == 0) v_rctokens.erase(v_rctokens.begin() + st_idx + 1); // Now delete Autotype variable v_rctokens.erase(v_rctokens.begin() + st_idx); break; } } } exit: if (uierr != 0) LoadAString(serrmsg, uierr); else serrmsg = _T(""); if (uierr > 0) { v_rctokens.clear(); } v_pos.clear(); return uierr; }
StringX PWSAuxParse::GetAutoTypeString(const StringX &sx_in_autotype, const StringX &sx_group, const StringX &sx_title, const StringX &sx_user, const StringX &sx_pwd, const StringX &sx_notes, const StringX &sx_url, const StringX &sx_email, std::vector<size_t> &vactionverboffsets) { StringX sxtmp(_T("")); StringX sxNotes(sx_notes); TCHAR curChar; StringX sx_autotype(sx_in_autotype); StringX::size_type st_index; std::vector<StringX> vsxnotes_lines; vactionverboffsets.clear(); // If empty, try the database default if (sx_autotype.empty()) { sx_autotype = PWSprefs::GetInstance()-> GetPref(PWSprefs::DefaultAutotypeString); // If still empty, take this default if (sx_autotype.empty()) { // checking for user and password for default settings if (!sx_pwd.empty()){ if (!sx_user.empty()) sx_autotype = DEFAULT_AUTOTYPE; else sx_autotype = _T("\\p\\n"); } } } // No recursive substitution (e.g. \p or \u), although '\t' will be replaced by a tab if (!sx_notes.empty()) { // Use \n and \r to tokenise this line StringX::size_type st_start(0), st_end(0); const StringX sxdelim = _T("\r\n"); StringX sxline; while (st_end != StringX::npos) { st_end = sxNotes.find_first_of(sxdelim, st_start); sxline = (sxNotes.substr(st_start, (st_end == StringX::npos) ? StringX::npos : st_end - st_start)); st_index = 0; for (;;) { st_index = sxline.find(_T("\\t"), st_index); if (st_index == StringX::npos) break; sxline.replace(st_index, 2, _T("\t")); st_index += 1; } vsxnotes_lines.push_back(sxline); // If we just hit a "\r\n", move past it. Or else, it is a "\r" without // a following "\n" or a "\n", so just move past one single char if (st_end != StringX::npos) { st_start = st_end + (sxNotes.compare(st_end, 2, sxdelim) == 0 ? 2 : 1); if (st_start >= sxNotes.length()) break; } } // Now change '\n' to '\r' in the complete notes field st_index = 0; for (;;) { st_index = sxNotes.find(sxdelim, st_index); if (st_index == StringX::npos) break; sxNotes.replace(st_index, 2, _T("\r")); st_index += 1; } st_index = 0; for (;;) { st_index = sxNotes.find(_T("\\t"), st_index); if (st_index == StringX::npos) break; sxNotes.replace(st_index, 2, _T("\t")); st_index += 1; } } const size_t N = sx_autotype.length(); const StringX sxZeroes = _T("000"); int gNumIts; for (size_t n = 0; n < N; n++){ curChar = sx_autotype[n]; if (curChar == TCHAR('\\')) { n++; if (n < N) curChar = sx_autotype[n]; switch (curChar){ case TCHAR('\\'): sxtmp += TCHAR('\\'); break; case TCHAR('n'): case TCHAR('r'): sxtmp += TCHAR('\r'); break; case TCHAR('t'): sxtmp += TCHAR('\t'); break; case TCHAR('s'): sxtmp += TCHAR('\v'); break; case TCHAR('g'): sxtmp += sx_group; break; case TCHAR('i'): sxtmp += sx_title; break; case TCHAR('u'): sxtmp += sx_user; break; case TCHAR('p'): sxtmp += sx_pwd; break; case TCHAR('l'): sxtmp += sx_url; break; case TCHAR('m'): sxtmp += sx_email; break; case TCHAR('o'): { if (n == (N - 1)) { // This was the last character - send the lot! sxtmp += sxNotes; break; } size_t line_number(0); gNumIts = 0; for (n++; n < N && (gNumIts < 3); ++gNumIts, n++) { if (_istdigit(sx_autotype[n])) { line_number *= 10; line_number += (sx_autotype[n] - TCHAR('0')); } else break; // for loop } if (line_number == 0) { // Send the lot sxtmp += sx_notes; } else if (line_number <= vsxnotes_lines.size()) { // User specifies a too big a line number - ignore the lot sxtmp += vsxnotes_lines[line_number - 1]; } // Backup the extra character that delimited the \oNNN string n--; break; // case 'o' } // Action Verbs: // These are the only ones processed specially by the UI as they involve // actions it performs whilst doing the key sending. // Copy them to output string unchanged. case TCHAR('b'): // backspace! case TCHAR('z'): // Use older method vactionverboffsets.push_back(sxtmp.length()); sxtmp += _T("\\"); sxtmp += curChar; break; // case 'b' & 'z' case TCHAR('d'): // Delay case TCHAR('w'): // Wait milli-seconds case TCHAR('W'): // Wait seconds { // Need to ensure that the field length is 3, even if it wasn't vactionverboffsets.push_back(sxtmp.length()); sxtmp += _T("\\"); sxtmp += curChar; gNumIts = 0; size_t i = n; for (i++; i < N && (gNumIts < 3); ++gNumIts, i++) { if (!_istdigit(sx_autotype[i])) break; } // Insert sufficient zeroes to ensure field is 3 characters long sxtmp += sxZeroes.substr(0, 3 - gNumIts); break; // case 'd', 'w' & 'W' } // Also copy explicit control characters to output string unchanged. case TCHAR('a'): // bell (can't hear it during testing!) case TCHAR('v'): // vertical tab case TCHAR('f'): // form feed case TCHAR('e'): // escape case TCHAR('x'): // hex digits (\xNN) // and any others we have forgotten! // '\cC', '\uXXXX', '\OOO', '\<any other charatcer not recognised above>' default: sxtmp += L'\\'; sxtmp += curChar; break; } } else sxtmp += curChar; } vsxnotes_lines.clear(); return sxtmp; }