annotate src/common.cpp @ 452:d0b7dbc3ba46 authfile_refactor

Refactor into classes
author Chris Cannam
date Wed, 29 Jun 2011 15:27:01 +0100
parents 8506333fe65c
children 856da063d76e
rev   line source
Chris@57 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@57 2
Chris@57 3 /*
Chris@57 4 EasyMercurial
Chris@57 5
Chris@57 6 Based on HgExplorer by Jari Korhonen
Chris@57 7 Copyright (c) 2010 Jari Korhonen
Chris@244 8 Copyright (c) 2011 Chris Cannam
Chris@244 9 Copyright (c) 2011 Queen Mary, University of London
Chris@57 10
Chris@57 11 This program is free software; you can redistribute it and/or
Chris@57 12 modify it under the terms of the GNU General Public License as
Chris@57 13 published by the Free Software Foundation; either version 2 of the
Chris@57 14 License, or (at your option) any later version. See the file
Chris@57 15 COPYING included with this distribution for more information.
Chris@57 16 */
jtkorhonen@0 17
Chris@62 18 #include "common.h"
Chris@62 19 #include "debug.h"
jtkorhonen@0 20
Chris@62 21 #include <QFileInfo>
Chris@62 22 #include <QProcessEnvironment>
Chris@62 23 #include <QStringList>
Chris@77 24 #include <QDir>
Chris@172 25 #include <QRegExp>
jtkorhonen@0 26
Chris@62 27 #include <sys/types.h>
Chris@76 28
Chris@76 29 #ifdef Q_OS_WIN32
Chris@76 30 #define _WIN32_WINNT 0x0500
Chris@166 31 #define SECURITY_WIN32
Chris@76 32 #include <windows.h>
Chris@76 33 #include <security.h>
Chris@76 34 #else
Chris@78 35 #include <errno.h>
Chris@62 36 #include <pwd.h>
Chris@78 37 #include <unistd.h>
Chris@80 38 #include <sys/ioctl.h>
Chris@80 39 #include <sys/types.h>
Chris@80 40 #include <sys/stat.h>
Chris@80 41 #include <fcntl.h>
Chris@105 42 #include <signal.h>
Chris@443 43 #include <stdio.h>
Chris@76 44 #endif
Chris@62 45
Chris@172 46 QString findInPath(QString name, QString installPath, bool executableRequired)
Chris@62 47 {
Chris@77 48 bool found = false;
Chris@62 49 if (name != "") {
Chris@172 50 if (name[0] != '/'
Chris@172 51 #ifdef Q_OS_WIN32
Chris@178 52 && (QRegExp("^\\w:").indexIn(name) != 0)
Chris@172 53 #endif
Chris@178 54 ) {
Chris@77 55 #ifdef Q_OS_WIN32
Chris@77 56 QChar pathSep = ';';
Chris@77 57 #else
Chris@77 58 QChar pathSep = ':';
Chris@77 59 #endif
Chris@62 60 name = QFileInfo(name).fileName();
Chris@62 61 QString path =
Chris@62 62 QProcessEnvironment::systemEnvironment().value("PATH");
Chris@214 63 DEBUG << "findInPath: seeking location for binary " << name
Chris@74 64 << ": system path is " << path << endl;
Chris@172 65 if (installPath != "") {
Chris@214 66 DEBUG << "findInPath: install path is " << installPath
Chris@172 67 << ", adding to system path" << endl;
Chris@172 68 //!!! path = path + pathSep + installPath;
Chris@172 69 path = installPath + pathSep + path;
Chris@172 70 }
Chris@74 71 #ifndef Q_OS_WIN32
Chris@178 72 //!!!
Chris@74 73 path = path + ":/usr/local/bin";
Chris@74 74 DEBUG << "... adding /usr/local/bin just in case (fix and add settings dlg please)"
Chris@74 75 << endl;
Chris@74 76 #endif
Chris@62 77 QStringList elements = path.split(pathSep, QString::SkipEmptyParts);
Chris@62 78 foreach (QString element, elements) {
Chris@77 79 QString full = QDir(element).filePath(name);
Chris@62 80 QFileInfo fi(full);
Chris@214 81 DEBUG << "findInPath: looking at " << full << endl;
Chris@172 82 if (fi.exists() && fi.isFile()) {
Chris@214 83 DEBUG << "findInPath: it's a file" << endl;
Chris@172 84 if (!executableRequired || fi.isExecutable()) {
Chris@172 85 name = full;
Chris@214 86 DEBUG << "findInPath: found at " << name << endl;
Chris@172 87 found = true;
Chris@172 88 break;
Chris@172 89 }
Chris@62 90 }
Chris@62 91 }
Chris@214 92 } else {
Chris@214 93 // absolute path given
Chris@214 94 QFileInfo fi(name);
Chris@214 95 DEBUG << "findInPath: looking at absolute path " << name << endl;
Chris@214 96 if (fi.exists() && fi.isFile()) {
Chris@214 97 DEBUG << "findInPath: it's a file" << endl;
Chris@214 98 if (!executableRequired || fi.isExecutable()) {
Chris@214 99 DEBUG << "findInPath: found at " << name << endl;
Chris@214 100 found = true;
Chris@214 101 }
Chris@214 102 }
Chris@62 103 }
Chris@62 104 }
Chris@77 105 #ifdef Q_OS_WIN32
Chris@77 106 if (!found) {
Chris@77 107 if (!name.endsWith(".exe")) {
Chris@172 108 return findInPath(name + ".exe", installPath, executableRequired);
Chris@77 109 }
Chris@77 110 }
Chris@77 111 #endif
Chris@213 112 if (found) {
Chris@213 113 return name;
Chris@213 114 } else {
Chris@213 115 return "";
Chris@213 116 }
Chris@62 117 }
jtkorhonen@0 118
Chris@62 119 #ifdef Q_OS_WIN32
Chris@62 120 QString getUserRealName()
Chris@62 121 {
Chris@76 122 TCHAR buf[1024];
Chris@76 123 long unsigned int maxlen = 1000;
Chris@62 124 LPTSTR info = buf;
jtkorhonen@0 125
Chris@76 126 if (!GetUserNameEx(NameDisplay, info, &maxlen)) {
Chris@76 127 DEBUG << "GetUserNameEx failed: " << GetLastError() << endl;
Chris@62 128 return "";
Chris@62 129 }
jtkorhonen@0 130
Chris@76 131 #ifdef UNICODE
Chris@76 132 return QString::fromUtf16((const unsigned short *)info);
Chris@76 133 #else
Chris@76 134 return QString::fromLocal8Bit(info);
Chris@76 135 #endif
Chris@62 136 }
luisf@71 137 #else
luisf@71 138 #ifdef Q_OS_MAC
Chris@62 139 // Nothing here: definition is in common_osx.mm
Chris@62 140 #else
Chris@62 141 QString getUserRealName()
Chris@62 142 {
Chris@62 143 const int maxlen = 1023;
Chris@62 144 char buf[maxlen + 2];
jtkorhonen@0 145
Chris@62 146 if (getlogin_r(buf, maxlen)) return "";
jtkorhonen@0 147
Chris@62 148 struct passwd *p = getpwnam(buf);
Chris@62 149 if (!p) return "";
Chris@62 150
Chris@62 151 QString s(p->pw_gecos);
Chris@62 152 if (s != "") s = s.split(',')[0];
Chris@62 153 return s;
Chris@62 154 }
Chris@62 155 #endif
luisf@71 156 #endif
jtkorhonen@0 157
Chris@78 158 void loseControllingTerminal()
Chris@78 159 {
Chris@78 160 #ifndef Q_OS_WIN32
Chris@80 161
Chris@80 162 if (!isatty(0)) {
Chris@80 163 DEBUG << "stdin is not a terminal" << endl;
Chris@80 164 } else {
Chris@80 165 DEBUG << "stdin is a terminal, detaching from it" << endl;
Chris@80 166 if (ioctl(0, TIOCNOTTY, NULL) < 0) {
Chris@80 167 perror("ioctl failed");
Chris@83 168 DEBUG << "ioctl for TIOCNOTTY on stdin failed (errno = " << errno << ")" << endl;
Chris@78 169 } else {
Chris@83 170 DEBUG << "ioctl for TIOCNOTTY on stdin succeeded" << endl;
Chris@83 171 return;
Chris@78 172 }
Chris@80 173 }
Chris@80 174
Chris@80 175 int ttyfd = open("/dev/tty", O_RDWR);
Chris@80 176 if (ttyfd < 0) {
Chris@80 177 DEBUG << "failed to open controlling terminal" << endl;
Chris@80 178 } else {
Chris@80 179 if (ioctl(ttyfd, TIOCNOTTY, NULL) < 0) {
Chris@80 180 perror("ioctl failed");
Chris@83 181 DEBUG << "ioctl for TIOCNOTTY on controlling terminal failed (errno = " << errno << ")" << endl;
Chris@80 182 } else {
Chris@83 183 DEBUG << "ioctl for TIOCNOTTY on controlling terminal succeeded" << endl;
Chris@83 184 return;
Chris@78 185 }
Chris@78 186 }
Chris@80 187
Chris@78 188 #endif
Chris@78 189 }
Chris@79 190
Chris@105 191 void installSignalHandlers()
Chris@105 192 {
Chris@105 193 #ifndef Q_OS_WIN32
Chris@105 194 sigset_t sgnals;
Chris@105 195 sigemptyset (&sgnals);
Chris@105 196 sigaddset(&sgnals, SIGHUP);
Chris@105 197 sigaddset(&sgnals, SIGCONT);
Chris@105 198 pthread_sigmask(SIG_BLOCK, &sgnals, 0);
Chris@105 199 #endif
Chris@105 200 }
Chris@105 201
Chris@79 202 FolderStatus getFolderStatus(QString path)
Chris@79 203 {
Chris@85 204 if (path != "/" && path.endsWith("/")) {
Chris@85 205 path = path.left(path.length()-1);
Chris@85 206 }
Chris@84 207 DEBUG << "getFolderStatus: " << path << endl;
Chris@79 208 QFileInfo fi(path);
Chris@79 209 if (fi.exists()) {
Chris@84 210 DEBUG << "exists" << endl;
Chris@79 211 QDir dir(path);
Chris@79 212 if (!dir.exists()) { // returns false for files
Chris@84 213 DEBUG << "not directory" << endl;
Chris@79 214 return FolderIsFile;
Chris@79 215 }
Chris@79 216 if (QDir(dir.filePath(".hg")).exists()) {
Chris@84 217 DEBUG << "has repo" << endl;
Chris@79 218 return FolderHasRepo;
Chris@79 219 }
Chris@79 220 return FolderExists;
Chris@79 221 } else {
Chris@79 222 QDir parent = fi.dir();
Chris@79 223 if (parent.exists()) {
Chris@84 224 DEBUG << "parent exists" << endl;
Chris@79 225 return FolderParentExists;
Chris@79 226 }
Chris@79 227 return FolderUnknown;
Chris@79 228 }
Chris@79 229 }
Chris@79 230
Chris@79 231 QString getContainingRepoFolder(QString path)
Chris@79 232 {
Chris@79 233 if (getFolderStatus(path) == FolderHasRepo) return "";
Chris@79 234
Chris@79 235 QFileInfo me(path);
Chris@79 236 QFileInfo parent(me.dir().absolutePath());
Chris@79 237
Chris@79 238 while (me != parent) {
Chris@79 239 QString parentPath = parent.filePath();
Chris@79 240 if (getFolderStatus(parentPath) == FolderHasRepo) {
Chris@79 241 return parentPath;
Chris@79 242 }
Chris@79 243 me = parent;
Chris@79 244 parent = me.dir().absolutePath();
Chris@79 245 }
Chris@79 246
Chris@79 247 return "";
Chris@79 248 }
Chris@79 249
Chris@79 250 QString xmlEncode(QString s)
Chris@79 251 {
Chris@79 252 s
Chris@79 253 .replace("&", "&amp;")
Chris@79 254 .replace("<", "&lt;")
Chris@79 255 .replace(">", "&gt;")
Chris@79 256 .replace("\"", "&quot;")
Chris@79 257 .replace("'", "&apos;");
Chris@79 258
Chris@79 259 return s;
Chris@79 260 }
Chris@408 261
Chris@408 262 QString uniDecode(QString s)
Chris@408 263 {
Chris@408 264 QString d;
Chris@408 265 for (int i = 0; i < s.length(); ++i) {
Chris@412 266 // backslash escaped with another backslash: replace with a
Chris@410 267 // single backslash and skip on
Chris@411 268 if (i+1 < s.length() && s[i] == '\\' && s[i+1] == '\\') {
Chris@411 269 d += '\\';
Chris@411 270 i += 1;
Chris@410 271 continue;
Chris@410 272 }
Chris@410 273 // unescaped backslash followed by u and at least four more
Chris@410 274 // chars: replace with Unicode character
Chris@408 275 if (i+5 < s.length() && s[i] == '\\' && s[i+1] == 'u') {
Chris@408 276 QString uni = s.mid(i+2, 4);
Chris@408 277 QByteArray ba = QByteArray::fromHex(uni.toAscii());
Chris@408 278 d += QChar(ba[1], ba[0]);
Chris@408 279 i += 5;
Chris@410 280 continue;
Chris@408 281 }
Chris@410 282 // default case: leave alone
Chris@410 283 d += s[i];
Chris@408 284 }
Chris@408 285 return d;
Chris@408 286 }
Chris@443 287
Chris@443 288 QByteArray randomKey()
Chris@443 289 {
Chris@443 290 static int len = 16;
Chris@443 291
Chris@443 292 QByteArray ba;
Chris@443 293 ba.resize(len);
Chris@443 294 char *buffer = ba.data();
Chris@443 295
Chris@443 296 #ifdef Q_OS_WIN32
Chris@443 297
Chris@443 298 HCRYPTPROV provider = 0;
Chris@443 299 if (!CryptAcquireContextW(&provider, 0, 0,
Chris@443 300 PROV_RSA_FULL,
Chris@443 301 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
Chris@443 302 return QByteArray();
Chris@443 303 }
Chris@443 304
chris@447 305 if (!CryptGenRandom(provider, len, (BYTE *)buffer)) {
Chris@443 306 CryptReleaseContext(provider, 0);
Chris@443 307 return QByteArray();
Chris@443 308 }
Chris@443 309
Chris@443 310 CryptReleaseContext(provider, 0);
Chris@443 311
Chris@443 312 #else
Chris@443 313
Chris@443 314 FILE *rf = fopen("/dev/urandom", "r");
Chris@443 315 if (!rf) {
Chris@443 316 return QByteArray();
Chris@443 317 }
Chris@443 318
Chris@443 319 for (int i = 0; i < len; ++i) {
Chris@443 320 buffer[i] = fgetc(rf);
Chris@443 321 }
Chris@443 322
Chris@443 323 fclose(rf);
Chris@443 324
Chris@443 325 #endif
Chris@443 326
Chris@443 327 return ba;
Chris@443 328 }
Chris@443 329