Diff of /corelib/PWScore.cpp [55f3b0] .. [ec62bb] Maximize Restore

  Switch to side-by-side view

--- a/corelib/PWScore.cpp
+++ b/corelib/PWScore.cpp
@@ -9,6 +9,7 @@
 //-----------------------------------------------------------------------------
 
 #include "PWScore.h"
+#include "corelib.h"
 #include "BlowFish.h"
 #include "PWSprefs.h"
 #include "PWSrand.h"
@@ -28,7 +29,7 @@
 unsigned char PWScore::m_session_key[20];
 unsigned char PWScore::m_session_salt[20];
 unsigned char PWScore::m_session_initialized = false;
-CString PWScore::m_hdr(_T("Group/Title\tUsername\tPassword\tURL\tAutoType\tCreated Time\tPassword Modified Time\tLast Access Time\tPassword Expiry Date\tRecord Modified Time\tHistory\tNotes"));
+CString PWScore::m_hdr;
 
 PWScore::PWScore() : m_currfile(_T("")), m_changed(false),
                      m_usedefuser(false), m_defusername(_T("")),
@@ -146,33 +147,59 @@
     return CANT_OPEN_FILE;
   if (bwrite_header) {
 	if ( bsFields.count() == bsFields.size()) {
+	  if (m_hdr.IsEmpty())
+	    m_hdr.LoadString(IDSC_EXPORTHEADER);
 	  ofs << m_hdr << endl;
 	} else {
-		CString hdr = _T("");
-		if (bsFields.test(CItemData::GROUP))
-			hdr += _T("Group/Title\t");
-		if (bsFields.test(CItemData::USER))
-			hdr += _T("Username\t");
-		if (bsFields.test(CItemData::PASSWORD))
-			hdr += _T("Password\t");
-		if (bsFields.test(CItemData::URL))
-			hdr += _T("URL\t");
-		if (bsFields.test(CItemData::AUTOTYPE))
-			hdr += _T("AutoType\t");
-		if (bsFields.test(CItemData::CTIME))
-			hdr += _T("Created Time\t");
-		if (bsFields.test(CItemData::PMTIME))
-			hdr += _T("Password Modified Time\t");
-		if (bsFields.test(CItemData::ATIME))
-			hdr += _T("Last Access Time\t");
-		if (bsFields.test(CItemData::LTIME))
-			hdr += _T("Password Expiry Date\t");
-		if (bsFields.test(CItemData::RMTIME))
-			hdr += _T("Record Modified Time\t");
-		if (bsFields.test(CItemData::PWHIST))
-			hdr += _T("History\t");
-		if (bsFields.test(CItemData::NOTES))
-			hdr += _T("Notes");
+		CString hdr = _T(""), cs_temp;
+		if (bsFields.test(CItemData::GROUP)) {
+			cs_temp.LoadString(IDSC_EXPHDRGROUPTITLE);
+			hdr += cs_temp;
+		}
+		if (bsFields.test(CItemData::USER)) {
+			cs_temp.LoadString(IDSC_EXPHDRUSERNAME);
+			hdr += cs_temp;
+		}
+		if (bsFields.test(CItemData::PASSWORD)) {
+			cs_temp.LoadString(IDSC_EXPHDRPASSWORD);
+			hdr += cs_temp;
+		}
+		if (bsFields.test(CItemData::URL)) {
+			cs_temp.LoadString(IDSC_EXPHDRURL);
+			hdr += cs_temp;
+		}
+		if (bsFields.test(CItemData::AUTOTYPE)) {
+			cs_temp.LoadString(IDSC_EXPHDRAUTOTYPE);
+			hdr += cs_temp;
+		}
+		if (bsFields.test(CItemData::CTIME)) {
+			cs_temp.LoadString(IDSC_EXPHDRCTIME);
+			hdr += cs_temp;
+		}
+		if (bsFields.test(CItemData::PMTIME)) {
+			cs_temp.LoadString(IDSC_EXPHDRPMTIME);
+			hdr += cs_temp;
+		}
+		if (bsFields.test(CItemData::ATIME)) {
+			cs_temp.LoadString(IDSC_EXPHDRATIME);
+			hdr += cs_temp;
+		}
+		if (bsFields.test(CItemData::LTIME)) {
+			cs_temp.LoadString(IDSC_EXPHDRLTIME);
+			hdr += cs_temp;
+		}
+		if (bsFields.test(CItemData::RMTIME)) {
+			cs_temp.LoadString(IDSC_EXPHDRRMTIME);
+			hdr += cs_temp;
+		}
+		if (bsFields.test(CItemData::PWHIST)) {
+			cs_temp.LoadString(IDSC_EXPHDRPWHISTORY);
+			hdr += cs_temp;
+		}
+		if (bsFields.test(CItemData::NOTES)) {
+			cs_temp.LoadString(IDCS_EXPHDRNOTES);
+			hdr += cs_temp;
+		}
 
 		int hdr_len = hdr.GetLength();
 		if (hdr.Right(1) == _T("\t"))
@@ -180,7 +207,7 @@
 
 		ofs << hdr.Left(hdr_len) << endl;
 	}
-	
+
   }
 
   CItemData temp;
@@ -214,10 +241,10 @@
 	CString cs_tmp;
 	uuid_array_t uuid_array;
 
-	char buffer[8];
+	TCHAR buffer[8];
 	time_t time_now;
 	int id = 1;
-	
+
 	pPWHistList = new CList<PWHistEntry, PWHistEntry&>;
 
 	const ItemList &pwlist = (il == NULL) ? m_pwlist : *il;
@@ -231,31 +258,31 @@
 		int ulen; 
 		TCHAR *lpszWLS = m_wholastsaved.GetBuffer(wls.GetLength() + 1);
 #if _MSC_VER >= 1400
-		int iread = sscanf_s(lpszWLS, "%4x", &ulen);
+		int iread = _stscanf_s(lpszWLS, _T("%4x"), &ulen);
 #else
-		int iread = sscanf(lpszWLS, "%4x", &ulen);
+		int iread = _stscanf(lpszWLS, _T("%4x"), &ulen);
 #endif
 		m_wholastsaved.ReleaseBuffer();
 		ASSERT(iread == 1);
-		wls.Format("%s on %s", m_wholastsaved.Mid(4, ulen), m_wholastsaved.Mid(ulen + 4));
+		wls.Format(_T("%s on %s"), m_wholastsaved.Mid(4, ulen), m_wholastsaved.Mid(ulen + 4));
 	}
-	of << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" << endl;
-	of << "<?xml-stylesheet type=\"text/xsl\" href=\"pwsafe.xsl\"?>" << endl;
+	of << _T("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>") << endl;
+	of << _T("<?xml-stylesheet type=\"text/xsl\" href=\"pwsafe.xsl\"?>") << endl;
 	of << endl;
-	of << "<passwordsafe" << endl;
+	of << _T("<passwordsafe") << endl;
 	tmp = m_currfile;
 	tmp.Replace(_T("&"), _T("&amp;"));
-	of << "delimiter=\"" << delimiter << "\"" << endl;
-	of << "Database=\"" << tmp << "\"" << endl;
-	of << "ExportTimeStamp=\"" << now << "\"" << endl;
+	of << _T("delimiter=\"") << delimiter << _T("\"") << endl;
+	of << _T("Database=\"") << tmp << _T("\"") << endl;
+	of << _T("ExportTimeStamp=\"") << now << _T("\"") << endl;
 	cs_tmp.Format(_T("%d.%02d"), m_nCurrentMajorVersion, m_nCurrentMinorVersion);
-	of << "FromDatabaseFormat=\"" << cs_tmp << "\"" << endl;
+	of << _T("FromDatabaseFormat=\"") << cs_tmp << _T("\"") << endl;
 	if (!m_wholastsaved.IsEmpty())
-		of << "WhoSaved=\"" << wls << "\"" << endl;
+		of << _T("WhoSaved=\"") << wls << _T("\"") << endl;
 	if (!m_whatlastsaved.IsEmpty())
-		of << "WhatSaved=\"" << m_whatlastsaved << "\"" << endl;
-	of << "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" << endl;
-	of << "xsi:noNamespaceSchemaLocation=\"pwsafe.xsd\">" << endl;
+		of << _T("WhatSaved=\"") << m_whatlastsaved << _T("\"") << endl;
+	of << _T("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"") << endl;
+	of << _T("xsi:noNamespaceSchemaLocation=\"pwsafe.xsd\">") << endl;
 	of << endl;
 
 	while (listPos != NULL) {
@@ -265,116 +292,116 @@
 #else
 		_itoa( id, buffer, 10 );
 #endif
-		of << "\t<entry id=\"" << buffer << "\">" << endl;
+		of << _T("\t<entry id=\"") << buffer << _T("\">") << endl;
 		// TODO: need to handle entity escaping of values.
 		tmp =  temp.GetGroup();
 		if (!tmp.IsEmpty())
-			of << "\t\t<group><![CDATA[" << tmp << "]]></group>" << endl;
+			of << _T("\t\t<group><![CDATA[") << tmp << _T("]]></group>") << endl;
 
 		tmp = temp.GetTitle();
 		if (!tmp.IsEmpty())
-			of << "\t\t<title><![CDATA[" << tmp << "]]></title>" << endl;
+			of <<_T("\t\t<title><![CDATA[") << tmp << _T("]]></title>") << endl;
 
 		tmp = temp.GetUser();
 		if (!tmp.IsEmpty())
-			of << "\t\t<username><![CDATA[" << tmp << "]]></username>" << endl;
+			of << _T("\t\t<username><![CDATA[") << tmp << _T("]]></username>") << endl;
 
 		tmp = temp.GetPassword();
 		if (!tmp.IsEmpty())
-			of << "\t\t<password><![CDATA[" << tmp << "]]></password>" << endl;
+			of << _T("\t\t<password><![CDATA[") << tmp << _T("]]></password>") << endl;
 
 		tmp = temp.GetURL();
 		if (!tmp.IsEmpty())
-			of << "\t\t<url><![CDATA[" << tmp << "]]></url>" << endl;
+			of << _T("\t\t<url><![CDATA[") << tmp << _T("]]></url>") << endl;
 
 		tmp = temp.GetAutoType();
 		if (!tmp.IsEmpty())
-			of << "\t\t<autotype><![CDATA[" << tmp << "]]></autotype>" << endl;
+			of << _T("\t\t<autotype><![CDATA[") << tmp << _T("]]></autotype>") << endl;
 
 		tmp = temp.GetNotes(delimiter);
 		if (!tmp.IsEmpty())
-			of << "\t\t<notes><![CDATA[" << tmp << "]]></notes>" << endl;
+			of << _T("\t\t<notes><![CDATA[") << tmp << _T("]]></notes>") << endl;
 		temp.GetUUID(uuid_array);
-		char uuid_buffer[33];
+		TCHAR uuid_buffer[33];
 #if _MSC_VER >= 1400
-		sprintf_s(uuid_buffer, 33,
+		_stprintf_s(uuid_buffer, 33,
 #else
-		sprintf(uuid_buffer,
+		_stprintf(uuid_buffer,
 #endif
-			"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 
+			_T("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"), 
 			uuid_array[0], uuid_array[1], uuid_array[2], uuid_array[3],
 			uuid_array[4], uuid_array[5], uuid_array[6], uuid_array[7],
 			uuid_array[8], uuid_array[9], uuid_array[10], uuid_array[11],
 			uuid_array[12], uuid_array[13], uuid_array[14], uuid_array[15]);
-		uuid_buffer[32] = '\0';
-		of << "\t\t<uuid><![CDATA[" << uuid_buffer << "]]></uuid>" << endl;
+		uuid_buffer[32] = TCHAR('\0');
+		of << _T("\t\t<uuid><![CDATA[") << uuid_buffer << _T("]]></uuid>") << endl;
 
 		tmp = temp.GetCTimeXML();
 		if (!tmp.IsEmpty()) {
-			of << "\t\t<ctime>" << endl;
-			of << "\t\t\t<date>" << tmp.Left(10) << "</date>" << endl;
-			of << "\t\t\t<time>" << tmp.Right(8) << "</time>" << endl;
-			of << "\t\t</ctime>" << endl;
+			of << _T("\t\t<ctime>") << endl;
+			of << _T("\t\t\t<date>") << tmp.Left(10) << _T("</date>") << endl;
+			of << _T("\t\t\t<time>") << tmp.Right(8) << _T("</time>") << endl;
+			of << _T("\t\t</ctime>") << endl;
 		}
 
 		tmp = temp.GetATimeXML();
 		if (!tmp.IsEmpty()) {
-			of << "\t\t<atime>" << endl;
-			of << "\t\t\t<date>" << tmp.Left(10) << "</date>" << endl;
-			of << "\t\t\t<time>" << tmp.Right(8) << "</time>" << endl;
-			of << "\t\t</atime>" << endl;
+			of << _T("\t\t<atime>") << endl;
+			of << _T("\t\t\t<date>") << tmp.Left(10) << _T("</date>") << endl;
+			of << _T("\t\t\t<time>") << tmp.Right(8) << _T("</time>") << endl;
+			of << _T("\t\t</atime>") << endl;
 		}
 
 		tmp = temp.GetLTimeXML();
 		if (!tmp.IsEmpty()) {
-			of << "\t\t<ltime>" << endl;
-			of << "\t\t\t<date>" << tmp.Left(10) << "</date>" << endl;
-			of << "\t\t\t<time>" << tmp.Right(8) << "</time>" << endl;
-			of << "\t\t</ltime>" << endl;
+			of << _T("\t\t<ltime>") << endl;
+			of << _T("\t\t\t<date>") << tmp.Left(10) << _T("</date>") << endl;
+			of << _T("\t\t\t<time>") << tmp.Right(8) << _T("</time>") << endl;
+			of << _T("\t\t</ltime>") << endl;
 		}
 
 		tmp = temp.GetPMTimeXML();
 		if (!tmp.IsEmpty()) {
-			of << "\t\t<pmtime>" << endl;
-			of << "\t\t\t<date>" << tmp.Left(10) << "</date>" << endl;
-			of << "\t\t\t<time>" << tmp.Right(8) << "</time>" << endl;
-			of << "\t\t</pmtime>" << endl;
+			of << _T("\t\t<pmtime>") << endl;
+			of << _T("\t\t\t<date>") << tmp.Left(10) << _T("</date>") << endl;
+			of << _T("\t\t\t<time>") << tmp.Right(8) << _T("</time>") << endl;
+			of << _T("\t\t</pmtime>") << endl;
 		}
 
 		tmp = temp.GetRMTimeXML();
 		if (!tmp.IsEmpty()) {
-			of << "\t\t<rmtime>" << endl;
-			of << "\t\t\t<date>" << tmp.Left(10) << "</date>" << endl;
-			of << "\t\t\t<time>" << tmp.Right(8) << "</time>" << endl;
-			of << "\t\t</rmtime>" << endl;
+			of << _T("\t\t<rmtime>") << endl;
+			of << _T("\t\t\t<date>") << tmp.Left(10) << _T("</date>") << endl;
+			of << _T("\t\t\t<time>") << tmp.Right(8) << _T("</time>") << endl;
+			of << _T("\t\t</rmtime>") << endl;
 		}
 
 		BOOL pwh_status;
 		int pwh_max, pwh_num;
 		temp.CreatePWHistoryList(pwh_status, pwh_max, pwh_num, pPWHistList, TMC_XML);
 		if (pwh_status == TRUE || pwh_max > 0 || pwh_num > 0) {
-			of << "\t\t<pwhistory>" << endl;
+			of << _T("\t\t<pwhistory>") << endl;
 #if _MSC_VER >= 1400
-			sprintf_s(buffer, 3, "%1d", pwh_status);
-			of << "\t\t\t<status>" << buffer << "</status>" << endl;
-
-			sprintf_s(buffer, 3, "%2d", pwh_max);
-			of << "\t\t\t<max>" << buffer << "</max>" << endl;
-
-			sprintf_s(buffer, 3, "%2d", pwh_num);
-			of << "\t\t\t<num>" << buffer << "</num>" << endl;
+			_stprintf_s(buffer, 3, _T("%1d"), pwh_status);
+			of << _T("\t\t\t<status>") << buffer << _T("</status>") << endl;
+
+			_stprintf_s(buffer, 3, "%2d", pwh_max);
+			of << _T("\t\t\t<max>") << buffer << _T("</max>") << endl;
+
+			_stprintf_s(buffer, 3, "%2d", pwh_num);
+			of << _T("\t\t\t<num>") << buffer << _T("</num>") << endl;
 #else
-			sprintf(buffer, "%1d", pwh_status);
-			of << "\t\t\t<status>" << buffer << "</status>" << endl;
-
-			sprintf(buffer, "%2d", pwh_max);
-			of << "\t\t\t<max>" << buffer << "</max>" << endl;
-
-			sprintf(buffer, "%2d", pwh_num);
-			of << "\t\t\t<num>" << buffer << "</num>" << endl;
+			_stprintf(buffer, "%1d", pwh_status);
+			of << _T("\t\t\t<status>") << buffer << _T("</status>") << endl;
+
+			_stprintf(buffer, "%2d", pwh_max);
+			of << _T("\t\t\t<max>") << buffer << _T("</max>") << endl;
+
+			_stprintf(buffer, "%2d", pwh_num);
+			of << _T("\t\t\t<num>") << buffer << _T("</num>") << endl;
 #endif
 			if (pPWHistList->GetCount() > 0) {
-				of << "\t\t\t<history_entries>" << endl;
+				of << _T("\t\t\t<history_entries>") << endl;
 				POSITION listpos = pPWHistList->GetHeadPosition();
 				int num = 1;
 				while (listpos != NULL) {
@@ -383,31 +410,31 @@
 #else
 					_itoa( num, buffer, 10 );
 #endif
-					of << "\t\t\t\t<history_entry num=\"" << buffer << "\">" << endl;
+					of << _T("\t\t\t\t<history_entry num=\"") << buffer << _T("\">") << endl;
 					const PWHistEntry pwshe = pPWHistList->GetAt(listpos);
-					of << "\t\t\t\t\t<changed>" << endl;
-					of << "\t\t\t\t\t\t<date>" << pwshe.changedate.Left(10) << "</date>" << endl;
-					of << "\t\t\t\t\t\t<time>" << pwshe.changedate.Right(8) << "</time>" << endl;
-					of << "\t\t\t\t\t</changed>" << endl;
-					of << "\t\t\t\t\t<oldpassword><![CDATA[" << pwshe.password << "]]></oldpassword>" << endl;
-					of << "\t\t\t\t</history_entry>" << endl;
-					
+					of << _T("\t\t\t\t\t<changed>") << endl;
+					of << _T("\t\t\t\t\t\t<date>") << pwshe.changedate.Left(10) << _T("</date>") << endl;
+					of << _T("\t\t\t\t\t\t<time>") << pwshe.changedate.Right(8) << _T("</time>") << endl;
+					of << _T("\t\t\t\t\t</changed>") << endl;
+					of << _T("\t\t\t\t\t<oldpassword><![CDATA[") << pwshe.password << _T("]]></oldpassword>") << endl;
+					of << _T("\t\t\t\t</history_entry>") << endl;
+
 					pPWHistList->GetNext(listpos);
 					num++;
 				}
-				of << "\t\t\t</history_entries>" << endl;
+				of << _T("\t\t\t</history_entries>") << endl;
 			}
-			of << "\t\t</pwhistory>" << endl;
+			of << _T("\t\t</pwhistory>") << endl;
 			pPWHistList->RemoveAll();
 		}
 
-		of << "\t</entry>" << endl;
+		of << _T("\t</entry>") << endl;
 		of << endl;
 
 		pwlist.GetNext(listPos);
 		id++;
 	}
-	of << "</passwordsafe>" << endl;
+	of << _T("</passwordsafe>") << endl;
 	of.close();
 	delete pPWHistList;
 
@@ -447,6 +474,7 @@
 	numImported = iXML->m_numEntriesImported;
 
 	delete iXML;
+	m_changed = true;
 	return SUCCESS;
 }
 
@@ -467,6 +495,9 @@
   CItemData temp;
   CString buffer;
 
+  if (m_hdr.IsEmpty())
+    m_hdr.LoadString(IDSC_EXPORTHEADER);
+
   int numlines = 0;
 
   // Order of fields determined in CItemData::GetPlaintext()
@@ -484,13 +515,18 @@
   for (;;) {
     // read a single line.
     string linebuf;
-    if (!getline(ifs, linebuf, '\n')) break;
+    if (!getline(ifs, linebuf, TCHAR('\n'))) break;
     numlines++;
 
     // remove MS-DOS linebreaks, if needed.
-    if (!linebuf.empty() && *(linebuf.end() - 1) == '\r') {
+    if (!linebuf.empty() && *(linebuf.end() - 1) == TCHAR('\r')) {
       linebuf.resize(linebuf.size() - 1);
     }
+
+	if (numlines == 1 && CString(linebuf.c_str()) == m_hdr) {
+		strErrors.LoadString(IDSC_IMPHDRLINEIGNORED);
+		continue;
+	}
 
     // tokenize into separate elements
     vector<string> tokens;
@@ -509,22 +545,21 @@
           //there was exactly one quote, meaning that we've a multi-line Note
           bool noteClosed = false;
           do {
-            if (!getline(ifs, linebuf, '\n')) {
-              buffer.Format(_T("\nFile ends on line %d before ending double quote of last entry's note field."),
-               		numlines);
+            if (!getline(ifs, linebuf, TCHAR('\n'))) {
+              buffer.Format(IDSC_IMPMISSINGQUOTE, numlines);
               strErrors += buffer;
               ifs.close(); // file ends before note closes
               return (numImported > 0) ? SUCCESS : INVALID_FORMAT;
             }
             numlines++;
             // remove MS-DOS linebreaks, if needed.
-            if (!linebuf.empty() && *(linebuf.end() - 1) == '\r') {
+            if (!linebuf.empty() && *(linebuf.end() - 1) == TCHAR('\r')) {
               linebuf.resize(linebuf.size() - 1);
             }
             note += _T("\r\n");
             note += linebuf;
-            unsigned int fq = linebuf.find_first_of('\"');
-            unsigned int lq = linebuf.find_last_of('\"');
+            unsigned int fq = linebuf.find_first_of(TCHAR('\"'));
+            unsigned int lq = linebuf.find_last_of(TCHAR('\"'));
             noteClosed = (fq == lq && fq != string::npos);
           } while (!noteClosed);
         } // multiline note processed
@@ -533,14 +568,9 @@
       }
     }
 	if ((int)tokens.size() != i_numfields) {
-		if (numlines == 1 && CString(linebuf.c_str()) != m_hdr) {
-			strErrors = _T("\nHeader line ignored.");
-		} else {
-			buffer.Format(_T("\nInvalid input on line %d.  Number of fields separated by '%c' is not as expected."),
-						numlines, fieldSeparator);
-			strErrors += buffer;
-			numSkipped++; // malformed entry
-		}
+		buffer.Format(IDSC_IMPINVALIDINPUT, numlines, fieldSeparator);
+		strErrors += buffer;
+		numSkipped++; // malformed entry
 		continue; // try to process next records
     }
 
@@ -565,10 +595,10 @@
         temp.SetTitle(grouptitle.c_str(), delimiter);
       }
     } else { // title has no period
-      size_t lastdot = grouptitle.find_last_of('.');
+      size_t lastdot = grouptitle.find_last_of(TCHAR('.'));
       if (lastdot != string::npos) {
         CMyString newgroup(ImportedPrefix.IsEmpty() ?
-                           "" : ImportedPrefix + ".");
+                           _T("") : ImportedPrefix + _T("."));
         newgroup += grouptitle.substr(0, lastdot).c_str();
         temp.SetGroup(newgroup);
         temp.SetTitle(grouptitle.substr(lastdot + 1).c_str(), delimiter);
@@ -590,7 +620,7 @@
       temp.SetRMTime(tokens[RMTIME].c_str());
 		CMyString newPWHistory;
 		CString strPWHErrors;
-		buffer.Format(_T("\nError in Password History on line %d: "), numlines);
+		buffer.Format(IDSC_IMPINVALIDPWH, numlines);
 		switch (PWSUtil::VerifyImportPWHistoryString(tokens[HISTORY].c_str(), newPWHistory, strPWHErrors)) {
 			case PWH_OK:
 				temp.SetPWHistory(newPWHistory);
@@ -618,8 +648,8 @@
     // no special escaping of any other internal characters.
     string quotedNotes = tokens[i_notes];
     if (!quotedNotes.empty() &&
-        *quotedNotes.begin() == '\"' &&
-        *(quotedNotes.end() - 1) == '\"') {
+        *quotedNotes.begin() == TCHAR('\"') &&
+        *(quotedNotes.end() - 1) == TCHAR('\"')) {
       quotedNotes = quotedNotes.substr(1, quotedNotes.size() - 2);
       temp.SetNotes(CMyString(quotedNotes.c_str()), delimiter);
     }
@@ -629,6 +659,7 @@
   } // file processing for (;;) loop
   ifs.close();
 
+  m_changed = true;
   return SUCCESS;
 }
 
@@ -894,7 +925,7 @@
 int
 PWScore::ImportKeePassTextFile(const CMyString &filename)
 {
-  static const char *ImportedPrefix = { "ImportedKeePass" };
+  static const TCHAR *ImportedPrefix = { "ImportedKeePass" };
 #ifdef UNICODE
   wifstream ifs((const wchar_t *)LPCTSTR(filename));
 #else
@@ -914,7 +945,7 @@
   string notes;
 
   // read a single line.
-  if (!getline(ifs, linebuf, '\n') || linebuf.empty()) {
+  if (!getline(ifs, linebuf, TCHAR('\n')) || linebuf.empty()) {
     return INVALID_FORMAT;
   }
 
@@ -928,31 +959,31 @@
     notes.erase();
 
     // this line should always be a title contained in []'s
-    if (*(linebuf.begin()) != '[' || *(linebuf.end() - 1) != ']') {
+    if (*(linebuf.begin()) != '[' || *(linebuf.end() - 1) != TCHAR(']')) {
       return INVALID_FORMAT;
     }
 
     // set the title: line pattern: [<group>]
-    title = linebuf.substr(linebuf.find("[") + 1, linebuf.rfind("]") - 1).c_str();
+    title = linebuf.substr(linebuf.find(_T("[")) + 1, linebuf.rfind(_T("]")) - 1).c_str();
 
     // set the group: line pattern: Group: <user>
-    if (!getline(ifs, linebuf, '\n') || (pos = linebuf.find("Group: ")) == -1) {
+    if (!getline(ifs, linebuf, TCHAR('\n')) || (pos = linebuf.find(_T("Group: "))) == -1) {
       return INVALID_FORMAT;
     }
     group = ImportedPrefix;
     if (!linebuf.empty()) {
-      group.append(".");
+      group.append(_T("."));
       group.append(linebuf.substr(pos + 7));
     }
 
     // set the user: line pattern: UserName: <user>
-    if (!getline(ifs, linebuf, '\n') || (pos = linebuf.find("UserName: ")) == -1) {
+    if (!getline(ifs, linebuf, TCHAR('\n')) || (pos = linebuf.find(_T("UserName: "))) == -1) {
       return INVALID_FORMAT;
     }
     user = linebuf.substr(pos + 10);
 
     // set the url: line pattern: URL: <url>
-    if (!getline(ifs, linebuf, '\n') || (pos = linebuf.find("URL: ")) == -1) {
+    if (!getline(ifs, linebuf, TCHAR('\n')) || (pos = linebuf.find(_T("URL: "))) == -1) {
       return INVALID_FORMAT;
     }
     if (!linebuf.substr(pos + 5).empty()) {
@@ -961,13 +992,13 @@
     }
 
     // set the password: line pattern: Password: <passwd>
-    if (!getline(ifs, linebuf, '\n') || (pos = linebuf.find("Password: ")) == -1) {
+    if (!getline(ifs, linebuf, TCHAR('\n')) || (pos = linebuf.find(_T("Password: "))) == -1) {
       return INVALID_FORMAT;
     }
     passwd = linebuf.substr(pos + 10);
 
     // set the first line of notes: line pattern: Notes: <notes>
-    if (!getline(ifs, linebuf, '\n') || (pos = linebuf.find("Notes: ")) == -1) {
+    if (!getline(ifs, linebuf, TCHAR('\n')) || (pos = linebuf.find(_T("Notes: "))) == -1) {
       return INVALID_FORMAT;
     }
     notes.append(linebuf.substr(pos + 7));
@@ -975,16 +1006,16 @@
     // read in any remaining new notes and set up the next record
     for (;;) {
       // see if we hit the end of the file
-      if (!getline(ifs, linebuf, '\n')) {
+      if (!getline(ifs, linebuf, TCHAR('\n'))) {
         break;
       }
 
       // see if we hit a new record
-      if (linebuf.find("[") == 0 && linebuf.rfind("]") == linebuf.length() - 1) {
+      if (linebuf.find(_T("[")) == 0 && linebuf.rfind(_T("]")) == linebuf.length() - 1) {
         break;
       }
 
-      notes.append("\r\n");
+      notes.append(_T("\r\n"));
       notes.append(linebuf);
     }
 
@@ -993,9 +1024,9 @@
     temp.CreateUUID();
     temp.SetTitle(title.empty() ? group.c_str() : title.c_str());
     temp.SetGroup(group.c_str());
-    temp.SetUser(user.empty() ? " " : user.c_str());
-    temp.SetPassword(passwd.empty() ? " " : passwd.c_str());
-    temp.SetNotes(notes.empty() ? "" : notes.c_str());
+    temp.SetUser(user.empty() ? _T(" ") : user.c_str());
+    temp.SetPassword(passwd.empty() ? _T(" ") : passwd.c_str());
+    temp.SetNotes(notes.empty() ? _T("") : notes.c_str());
 
     AddEntryToTail(temp);
   }
@@ -1003,6 +1034,7 @@
 
   // TODO: maybe return an error if the full end of the file was not reached?
 
+  m_changed = true;
   return SUCCESS;
 }
 
@@ -1027,7 +1059,7 @@
   }
 }
 
-void PWScore::SetDisplayStatus(char *p_char_displaystatus, const int length)
+void PWScore::SetDisplayStatus(TCHAR *p_char_displaystatus, const int length)
 {
 	m_displaystatus = CString(p_char_displaystatus, length);
 }
@@ -1115,10 +1147,7 @@
   delete[] uuids;
   TRACE(_T("%s : End validation. %d entries processed\n"), PWSUtil::GetTimeStamp(), n + 1);
   if ((num_uuid_fixed + num_uuid_notunique + num_PWH_fixed) > 0) {
-	status.Format(_T("Number of entries processed: %d\n\n"
-	                 "Number of UUIDs fixed: %d\n\n"
-	                 "Number of UUIDs made unique: %d\n\n"
-	                 "Number of Password Histories fixed: %d"),
+	status.Format(IDSC_NUMPROCESSED,
                   n + 1, num_uuid_fixed, num_uuid_notunique, num_PWH_fixed);
     SetChanged(true);
     return true;