1 /* $Id: util_misc.cpp 530021 2017-03-09 19:06:46Z ucko $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Sergey Satskiy,
27 * Anton Lavrentiev (providing line by line advices of how it must be
28 * implemented)
29 *
30 */
31
32 #include <ncbi_pch.hpp>
33 #include <util/util_misc.hpp>
34 #include <corelib/ncbi_param.hpp>
35 #include <corelib/ncbifile.hpp>
36
37 #if defined(NCBI_OS_UNIX)
38 # include <unistd.h>
39 #if defined(HAVE_READPASSPHRASE)
40 # include <readpassphrase.h>
41 #endif
42 #elif defined(NCBI_OS_MSWIN)
43 # include <conio.h>
44 #else
45 # error "Unsuported platform"
46 #endif
47
48
49 BEGIN_NCBI_SCOPE
50
51
GetErrCodeString(void) const52 const char* CGetPasswordFromConsoleException::GetErrCodeString(void) const
53 {
54 switch (GetErrCode()) {
55 case eGetPassError: return "eGetPassError";
56 case eKeyboardInterrupt: return "eKeyboardInterrupt";
57 default: return CException::GetErrCodeString();
58 }
59 }
60
61
g_GetPasswordFromConsole(const string & prompt)62 string g_GetPasswordFromConsole(const string& prompt)
63 {
64 string password;
65 CMutex lock;
66 CMutexGuard guard(lock);
67
68 #if defined(NCBI_OS_UNIX)
69 // UNIX implementation
70
71 #if defined(HAVE_READPASSPHRASE)
72
73 char password_buffer[1024];
74 char* raw_password = readpassphrase(prompt.c_str(), password_buffer,
75 sizeof(password_buffer),
76 RPP_ECHO_OFF | RPP_REQUIRE_TTY);
77
78 #elif defined(HAVE_GETPASSPHRASE)
79
80 char* raw_password = getpassphrase(prompt.c_str());
81
82 #elif defined(HAVE_GETPASS)
83
84 char* raw_password = getpass(prompt.c_str());
85
86 #else
87 # error "Unsupported Unix platform; the getpass, getpassphrase, and readpassphrase functions are all absent"
88 #endif
89
90 if (!raw_password)
91 NCBI_THROW
92 (CGetPasswordFromConsoleException, eGetPassError,
93 "g_GetPasswordFromConsole(): error getting password");
94 password = string(raw_password);
95
96 #elif defined(NCBI_OS_MSWIN)
97 // Windows implementation
98
99 for (size_t index = 0; index < prompt.size(); ++index) {
100 _putch(prompt[index]);
101 }
102
103 for (;;) {
104 char ch;
105 ch = _getch();
106 if (ch == '\r' || ch == '\n')
107 break;
108 if (ch == '\003')
109 NCBI_THROW(CGetPasswordFromConsoleException, eKeyboardInterrupt,
110 "g_GetPasswordFromConsole(): keyboard interrupt");
111 if (ch == '\b') {
112 if ( !password.empty() ) {
113 password.resize(password.size() - 1);
114 }
115 }
116 else
117 password.append(1, ch);
118 }
119
120 _putch('\r');
121 _putch('\n');
122 #endif
123
124 return password;
125 }
126
127
128 NCBI_PARAM_DECL (string, NCBI, DataPath);
129 NCBI_PARAM_DEF_EX(string, NCBI, DataPath, "", 0, NCBI_DATA_PATH);
130 typedef NCBI_PARAM_TYPE(NCBI, DataPath) TNCBIDataPath;
131
132 NCBI_PARAM_DECL(string, NCBI, Data);
133 NCBI_PARAM_DEF (string, NCBI, Data, "");
134 typedef NCBI_PARAM_TYPE(NCBI, Data) TNCBIDataDir;
135
136 typedef vector<string> TIgnoreDataFiles;
137 static CSafeStatic<TIgnoreDataFiles> s_IgnoredDataFiles;
138
g_FindDataFile(const CTempString & name,CDirEntry::EType type)139 string g_FindDataFile(const CTempString& name, CDirEntry::EType type)
140 {
141 #ifdef NCBI_OS_MSWIN
142 static const char* kDelim = ";";
143 #else
144 static const char* kDelim = ":";
145 #endif
146
147 if ( !s_IgnoredDataFiles->empty()
148 && CDirEntry::MatchesMask(name, *s_IgnoredDataFiles) ) {
149 return kEmptyStr;
150 }
151
152 list<string> dirs;
153
154 if (CDirEntry::IsAbsolutePath(name)) {
155 dirs.push_back(kEmptyStr);
156 } else {
157 TNCBIDataPath path;
158 TNCBIDataDir dir;
159
160 if ( !path.Get().empty() ) {
161 NStr::Split(path.Get(), kDelim, dirs,
162 NStr::fSplit_MergeDelimiters | NStr::fSplit_Truncate);
163 }
164 if ( !dir.Get().empty() ) {
165 dirs.push_back(dir.Get());
166 }
167 }
168
169 CDirEntry candidate;
170 EFollowLinks fl = (type == CDirEntry::eLink) ? eIgnoreLinks : eFollowLinks;
171 ITERATE (list<string>, dir, dirs) {
172 candidate.Reset(CDirEntry::MakePath(*dir, name));
173 if (candidate.Exists() && candidate.GetType(fl) == type) {
174 return candidate.GetPath();
175 }
176 }
177
178 return kEmptyStr; // not found
179 }
180
181
g_IgnoreDataFile(const string & pattern,bool do_ignore)182 void g_IgnoreDataFile(const string& pattern, bool do_ignore)
183 {
184 vector<string>& idf = *s_IgnoredDataFiles;
185 if (do_ignore) {
186 idf.push_back(pattern);
187 } else {
188 idf.erase(remove(idf.begin(), idf.end(), pattern), idf.end());
189 }
190 }
191
192
g_IsDataFileOld(const CTempString & path,const CTempString & id_line)193 bool g_IsDataFileOld(const CTempString& path, const CTempString& id_line)
194 {
195 // $Id: FILENAME REVISION DATE TIME ...
196 SIZE_TYPE pos = id_line.find("$Id: ");
197 if (pos == NPOS) {
198 return false;
199 }
200 pos = id_line.find(' ', pos + 5); // skip filename
201 if (pos == NPOS) {
202 return false;
203 }
204 pos = id_line.find(' ', pos + 1); // skip revision
205 if (pos == NPOS) {
206 return false;
207 }
208 SIZE_TYPE end = id_line.find(' ', ++pos);
209 if (end == NPOS) {
210 return false;
211 }
212 end = id_line.find(' ', end + 1); // got date, now want time too
213 if (end == NPOS) {
214 return false;
215 }
216 CTempString builtin_timestamp_str = id_line.substr(pos, end - pos);
217 CTime builtin_timestamp(builtin_timestamp_str, "Y-M-D h:m:sZ");
218 CTime file_timestamp;
219 CFile(path).GetTime(&file_timestamp);
220 return file_timestamp < builtin_timestamp;
221 }
222
223 END_NCBI_SCOPE
224
225