Warning, file /sdk/cervisia/misc.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (C) 1999-2002 Bernd Gehrmann 0003 * bernd@mail.berlios.de 0004 * Copyright (c) 2003 Christian Loose <christian.loose@hamburg.de> 0005 * 0006 * This program is free software; you can redistribute it and/or modify 0007 * it under the terms of the GNU General Public License as published by 0008 * the Free Software Foundation; either version 2 of the License, or 0009 * (at your option) any later version. 0010 * 0011 * This program is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program; if not, write to the Free Software 0018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "misc.h" 0022 #include "debug.h" 0023 0024 #include <KLocalizedString> 0025 #include <QTemporaryFile> 0026 #include <cctype> 0027 #include <kemailsettings.h> 0028 #include <kmessagebox.h> 0029 #include <kuser.h> 0030 #include <pwd.h> 0031 #include <qfile.h> 0032 #include <qfileinfo.h> 0033 #include <qregexp.h> 0034 #include <qstringlist.h> 0035 #include <sys/types.h> 0036 #include <unistd.h> 0037 0038 #include "cvsserviceinterface.h" 0039 #include "progressdialog.h" 0040 0041 // These regular expression parts aren't useful to check the validity of the 0042 // CVSROOT specification. They are just used to extract the different parts of it. 0043 static const QString userNameRegExp("([a-z0-9_][a-z0-9_-.]*)?"); 0044 static const QString passwordRegExp("(:[^@]+)?"); 0045 static const QString hostNameRegExp("([^:/@]+)"); 0046 static const QString portRegExp("(:(\\d*))?"); 0047 static const QString pathRegExp("(/.*)"); 0048 0049 static int FindWhiteSpace(const QString &str, int index) 0050 { 0051 const int length = str.length(); 0052 0053 if (index < 0) 0054 index += length; 0055 0056 if (index < 0 || index >= length) 0057 return -1; 0058 0059 const QChar *const startPos = str.unicode(); 0060 const QChar *const endPos = startPos + length; 0061 0062 const QChar *pos = startPos + index; 0063 while (pos < endPos && !pos->isSpace()) 0064 ++pos; 0065 0066 const int foundIndex = pos - startPos; 0067 return (foundIndex < length ? foundIndex : -1); 0068 } 0069 0070 static const QStringList FetchBranchesAndTags(const QString &searchedType, OrgKdeCervisia5CvsserviceCvsserviceInterface *cvsService, QWidget *parent) 0071 { 0072 QStringList branchOrTagList; 0073 0074 QDBusReply<QDBusObjectPath> job = cvsService->status(QStringList(), true, true); 0075 if (!job.isValid()) 0076 return branchOrTagList; 0077 0078 ProgressDialog dlg(parent, "Status", cvsService->service(), job, QString(), i18n("CVS Status")); 0079 0080 if (dlg.execute()) { 0081 QString line; 0082 while (dlg.getLine(line)) { 0083 int wsPos, bracketPos, colonPos; 0084 0085 if (line.isEmpty() || line[0] != '\t') 0086 continue; 0087 if ((wsPos = FindWhiteSpace(line, 2)) < 0) 0088 continue; 0089 if ((bracketPos = line.indexOf('(', wsPos + 1)) < 0) 0090 continue; 0091 if ((colonPos = line.indexOf(':', bracketPos + 1)) < 0) 0092 continue; 0093 0094 const QString tag = line.mid(1, wsPos - 1); 0095 const QString type = line.mid(bracketPos + 1, colonPos - bracketPos - 1); 0096 if (type == searchedType && !branchOrTagList.contains(tag)) 0097 branchOrTagList.push_back(tag); 0098 } 0099 0100 branchOrTagList.sort(); 0101 } 0102 0103 return branchOrTagList; 0104 } 0105 0106 bool Cervisia::IsValidTag(const QString &tag) 0107 { 0108 static const QString prohibitedChars("$,.:;@"); 0109 0110 if (!isalpha(tag[0].toLatin1())) 0111 return false; 0112 0113 for (int i = 1; i < tag.length(); ++i) { 0114 if (!isgraph(tag[i].toLatin1()) || prohibitedChars.contains(tag[i])) 0115 return false; 0116 } 0117 0118 return true; 0119 } 0120 0121 QString Cervisia::UserName() 0122 { 0123 // 1. Try to retrieve the information from the control center settings 0124 KEMailSettings settings; 0125 QString name = settings.getSetting(KEMailSettings::RealName); 0126 QString email = settings.getSetting(KEMailSettings::EmailAddress); 0127 0128 if (name.isEmpty() || email.isEmpty()) { 0129 // 2. Try to retrieve the information from the system 0130 struct passwd *pw = getpwuid(getuid()); 0131 if (!pw) 0132 return {}; 0133 0134 char hostname[512]; 0135 hostname[0] = '\0'; 0136 0137 if (!gethostname(hostname, sizeof(hostname))) 0138 hostname[sizeof(hostname) - 1] = '0'; 0139 0140 name = QString::fromLocal8Bit(pw->pw_gecos); 0141 email = QString::fromLocal8Bit(pw->pw_name) + '@' + QString::fromLocal8Bit(hostname); 0142 } 0143 0144 QString result = name; 0145 result += " <"; 0146 result += email; 0147 result += '>'; 0148 0149 return result; 0150 } 0151 0152 QString Cervisia::NormalizeRepository(const QString &repository) 0153 { 0154 // only :pserver: repositories 0155 if (!repository.startsWith(QLatin1String(":pserver:"))) 0156 return repository; 0157 0158 QRegExp rx(":pserver:(" + userNameRegExp + passwordRegExp + "@)?" + hostNameRegExp + portRegExp + pathRegExp); 0159 0160 // extract username, hostname, port and path from CVSROOT 0161 QString userName, hostName, port, path; 0162 if (repository.contains(rx)) { 0163 userName = rx.cap(2); 0164 hostName = rx.cap(4); 0165 port = rx.cap(6); 0166 path = rx.cap(7); 0167 0168 qCDebug(log_cervisia) << "username=" << userName; 0169 qCDebug(log_cervisia) << "hostname=" << hostName; 0170 qCDebug(log_cervisia) << "port =" << port; 0171 qCDebug(log_cervisia) << "path =" << path; 0172 0173 if (port.isEmpty()) 0174 port = "2401"; 0175 0176 if (userName.isEmpty()) 0177 userName = KUser().loginName(); 0178 0179 QString canonicalForm = ":pserver:" + userName + '@' + hostName + ':' + port + path; 0180 0181 qCDebug(log_cervisia) << "canonicalForm=" << canonicalForm << endl; 0182 return canonicalForm; 0183 } else 0184 return repository; 0185 } 0186 0187 bool Cervisia::CheckOverwrite(const QString &fileName, QWidget *parent) 0188 { 0189 bool result = true; 0190 0191 QFileInfo fi(fileName); 0192 0193 // does the file already exist? 0194 if (fi.exists()) { 0195 KGuiItem overwriteItem = KStandardGuiItem::overwrite(); 0196 overwriteItem.setIconName("document-save"); 0197 overwriteItem.setToolTip(i18n("Overwrite the file")); 0198 0199 result = (KMessageBox::warningContinueCancel(parent, 0200 i18n("A file named \"%1\" already exists. Are you sure you want to overwrite it?", fileName), 0201 i18n("Overwrite File?"), 0202 overwriteItem) 0203 == KMessageBox::Continue); 0204 } 0205 0206 return result; 0207 } 0208 0209 // Should be replaceable by QStringList::split 0210 QStringList splitLine(QString line, char delim) 0211 { 0212 int pos; 0213 QStringList list; 0214 0215 line = line.simplified(); 0216 while ((pos = line.indexOf(delim)) != -1) { 0217 list.append(line.left(pos)); 0218 line = line.mid(pos + 1, line.length() - pos - 1); 0219 } 0220 if (!line.isEmpty()) 0221 list.append(line); 0222 return list; 0223 } 0224 0225 const QStringList fetchBranches(OrgKdeCervisia5CvsserviceCvsserviceInterface *cvsService, QWidget *parent) 0226 { 0227 return FetchBranchesAndTags(QLatin1String("branch"), cvsService, parent); 0228 } 0229 0230 const QStringList fetchTags(OrgKdeCervisia5CvsserviceCvsserviceInterface *cvsService, QWidget *parent) 0231 { 0232 return FetchBranchesAndTags(QLatin1String("revision"), cvsService, parent); 0233 } 0234 0235 static QStringList *tempFiles = 0; 0236 0237 void cleanupTempFiles() 0238 { 0239 if (tempFiles) { 0240 QStringList::Iterator it; 0241 for (it = tempFiles->begin(); it != tempFiles->end(); ++it) 0242 QFile::remove(*it); 0243 delete tempFiles; 0244 } 0245 } 0246 0247 QString tempFileName(const QString &suffix) 0248 { 0249 if (!tempFiles) 0250 tempFiles = new QStringList; 0251 0252 QTemporaryFile f(QDir::tempPath() + QLatin1String("/cervisia_XXXXXX") + suffix); 0253 f.setAutoRemove(false); 0254 f.open(); 0255 tempFiles->append(f.fileName()); 0256 return f.fileName(); 0257 } 0258 0259 int compareRevisions(const QString &rev1, const QString &rev2) 0260 { 0261 const int length1(rev1.length()); 0262 const int length2(rev2.length()); 0263 0264 // compare all parts of the revision 0265 0266 int startPos1(0); 0267 int startPos2(0); 0268 while (startPos1 < length1 && startPos2 < length2) { 0269 int pos1(rev1.indexOf('.', startPos1)); 0270 if (pos1 < 0) 0271 pos1 = length1; 0272 const int partLength1(pos1 - startPos1); 0273 0274 int pos2(rev2.indexOf('.', startPos2)); 0275 if (pos2 < 0) 0276 pos2 = length2; 0277 const int partLength2(pos2 - startPos2); 0278 0279 // if the number of digits in both parts is not equal we are ready 0280 if (const int comp = ::compare(partLength1, partLength2)) 0281 return comp; 0282 0283 // if the parts are not equal we are ready 0284 if (const int comp = ::compare(rev1.mid(startPos1, partLength1), rev2.mid(startPos2, partLength2))) 0285 return comp; 0286 0287 // continue with next part 0288 startPos1 = pos1 + 1; 0289 startPos2 = pos2 + 1; 0290 } 0291 0292 // rev1 has more parts than rev2: rev2 < rev1 0293 if (startPos1 < length1) 0294 return 1; 0295 // rev2 has more parts than rev1: rev1 < rev2 0296 else if (startPos2 < length2) 0297 return -1; 0298 // all parts of rev1 and rev2 were compared (the number of parts is equal): rev1 == rev2 0299 else 0300 return 0; 0301 } 0302 0303 // Local Variables: 0304 // c-basic-offset: 4 0305 // End: