source: src-qt4/pc-softwaremanager/pbiDBAccess.cpp @ 78fa8b2

9.2-releasereleng/10.0releng/10.0.1releng/10.0.2releng/10.0.3
Last change on this file since 78fa8b2 was 78fa8b2, checked in by Ken Moore <ken@…>, 16 months ago

Merge the new AppCafe? into the src-qt4 tree from the projects directory

  • Property mode set to 100644
File size: 12.8 KB
Line 
1/***************************************************************************
2 *   Copyright (C) 2011 - iXsystems                                       *
3 *   kris@pcbsd.org  *
4 *   tim@pcbsd.org   *
5 *   ken@pcbsd.org   *
6 *                                                                         *
7 *   Permission is hereby granted, free of charge, to any person obtaining *
8 *   a copy of this software and associated documentation files (the       *
9 *   "Software"), to deal in the Software without restriction, including   *
10 *   without limitation the rights to use, copy, modify, merge, publish,   *
11 *   distribute, sublicense, and/or sell copies of the Software, and to    *
12 *   permit persons to whom the Software is furnished to do so, subject to *
13 *   the following conditions:                                             *
14 *                                                                         *
15 *   The above copyright notice and this permission notice shall be        *
16 *   included in all copies or substantial portions of the Software.       *
17 *                                                                         *
18 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
19 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
20 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
21 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
22 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
23 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
24 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
25 ***************************************************************************/
26 #include "pbiDBAccess.h"
27
28// ================================
29// =======  SETUP FUNCTIONS =======
30// ================================
31bool PBIDBAccess::setDBPath(QString fullPath){
32  bool ok = FALSE;
33  //Make sure the directory exists first
34  if(QFile::exists(fullPath)){
35    DBPath = fullPath;
36    if(!DBPath.endsWith("/")){DBPath.append("/");}
37    DBDir->setPath(fullPath);
38    //Now read the list of available repos
39    reloadRepoList();
40    ok = TRUE;
41  }
42  return ok;
43}
44
45void PBIDBAccess::setRootCMDPrefix(QString prefix){
46  //All commands need root permissions to run, so this is used
47  //    to add the proper cmd prefix to prompt to run with root permissions
48  // Example: "pc-su" or "warden chroot <ip>"
49  cmdPrefix = prefix;
50  if(!cmdPrefix.endsWith(" ")){ cmdPrefix.append(" "); }
51  //qDebug() << "DB command prefix:" << cmdPrefix;
52}
53
54void PBIDBAccess::reloadRepoList(){
55  repoList.clear();
56  if(DBDir->cd(DBPath+"repos")){ //directory exists
57    repoList = DBDir->entryList(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks | QDir::Readable);
58  }     
59}
60
61bool PBIDBAccess::setRepo(QString repoNum){
62  //Make sure the repo is available
63  bool ok = DBDir->cd(DBPath+"repos");
64  if(ok){ //directory exists
65    QStringList rL = DBDir->entryList(QStringList()<<repoNum+"*",QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks | QDir::Readable);
66    if(rL.length() == 1){ //this repo exists
67      currentRepoNumber=rL[0].section(".",0,0,QString::SectionSkipEmpty);
68      currentRepoID=rL[0].section(".",1,1,QString::SectionSkipEmpty);
69      return TRUE;
70    }
71  }
72  return FALSE;
73}
74
75bool PBIDBAccess::currentRepoInvalid(){
76  //Check to make sure that the current Repo is still valid
77  reloadRepoList();
78  if(repoList.contains(currentRepoNumber+"."+currentRepoID)){ return FALSE; }
79  else{ return TRUE; }
80}
81
82QStringList PBIDBAccess::availableRepos(){
83  QStringList output;
84  for(int i=0; i<repoList.length(); i++){
85    output << repoList[i].section(".",0,0,QString::SectionSkipEmpty);
86  }
87  return output;
88}
89
90QStringList PBIDBAccess::repoInfo(QString repoNum){
91  //Returns: output=[Name, Master URL] 
92  QStringList output;
93  QString ID = getIDFromNum(repoNum);
94    QStringList lines = Extras::readFile(DBPath+"repos/"+repoNum+"."+ID);
95    if(!lines.isEmpty()){
96      output <<"" << ""; //make sure there are two entries available
97      for(int j=0; j<lines.length(); j++){
98         if(lines[j].startsWith("URL: ")){ output[1] = lines[j].section("URL: ",1,50).simplified(); }
99         else if(lines[j].startsWith("Desc: ")){ output[0] = lines[j].section("Desc: ",1,50).simplified(); }
100      }
101    }
102  return output;
103}
104
105QStringList PBIDBAccess::repoMirrors(QString repoNum){
106  QStringList output;
107  QString ID = getIDFromNum(repoNum);
108  if(!ID.isEmpty()){
109    output = Extras::readFile(DBPath+"mirrors/"+ID);     
110  }
111  return output;
112}
113
114// ========================================
115// =======  PUBLIC ACCESS FUNCTIONS =======
116// ========================================
117QStringList PBIDBAccess::installed(){
118  QStringList output;
119  bool ok = DBDir->cd(DBPath+"installed");
120  if(ok){
121    output = DBDir->entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks | QDir::Readable);
122  }
123  return output;
124}
125
126QStringList PBIDBAccess::installedPbiInfo(QString pbiID){
127  //Output format: output[ name, version, arch, date created, author, website, installpath, iconpath]
128  QStringList output;
129  QString path = DBPath+"installed/"+pbiID;
130  bool ok = DBDir->cd(path);
131  if(ok){
132    output << readOneLineFile(path+"/pbi_name");
133    output << readOneLineFile(path+"/pbi_version");
134    output << readOneLineFile(path+"/pbi_arch");
135    output << readOneLineFile(path+"/pbi_mdate");
136    output << readOneLineFile(path+"/pbi_author");
137    output << readOneLineFile(path+"/pbi_web");
138    output << readOneLineFile(path+"/pbi_installedpath");
139    if(DBDir->exists("pbi_icon.png")){ output << path+"/pbi_icon.png"; }
140    else{ output << ""; }
141  }
142  return output;
143}
144
145bool PBIDBAccess::installedPbiAutoUpdate(QString pbiID){
146   bool ok = FALSE;
147   if( QFile::exists(DBPath+"installed/"+pbiID+"/autoupdate-enable") ){ ok = TRUE; }
148   //qDebug() << "AutoUpdate:" << pbiID << ok;
149   return ok;
150}
151
152bool PBIDBAccess::installedPbiNeedsRoot(QString pbiID){
153  bool ok=FALSE;
154  if( QFile::exists(DBPath+"installed/"+pbiID+"/pbi_requiresroot") ){ ok=TRUE; }
155  else{
156    //Also check who installed the PBI if not flagged directly
157    QFileInfo fInfo(DBPath+"installed/"+pbiID);
158    if( fInfo.owner() == "root" ){ ok=TRUE; }
159  }
160  //qDebug() << pbiID << "requires root:" << ok;
161  return ok;
162}
163
164bool PBIDBAccess::installedPbiHasXdgDesktop(QString installPath){
165  if(!installPath.endsWith("/")){ installPath.append("/"); }
166  bool ok = DBDir->cd(installPath+".xdg-desktop");
167  if(ok){
168    if( DBDir->entryList(QStringList()<<"*.desktop",QDir::Files).length() > 0 ){ return TRUE; }   
169  }
170  return FALSE;
171}
172
173bool PBIDBAccess::installedPbiHasXdgMenu(QString installPath){
174  if(!installPath.endsWith("/")){ installPath.append("/"); }
175  bool ok = DBDir->cd(installPath+".xdg-menu");
176  if(ok){
177    if( DBDir->entryList(QStringList()<<"*.desktop",QDir::Files).length() > 0 ){ return TRUE; }   
178  }
179  return FALSE;
180}
181
182QString PBIDBAccess::indexFilePath(){
183  return DBPath+"index/"+currentRepoID+"-index";
184}
185
186QString PBIDBAccess::metaFilePath(){
187  return DBPath+"index/"+currentRepoID+"-meta"; 
188}
189
190QStringList PBIDBAccess::parseIndexLine(QString line){
191  //output[name, arch, version, datetime, sizeK, isLatest(bool), filename]
192  //line format 5/1/2013: [name,arch,version,checksum,datetime,mirrorPathToPBI,?,?,current/active,sizeInK,?]
193      // NOTE: last two entries missing quite often
194  QStringList lineInfo = line.split(":");
195  QStringList output;
196  if(lineInfo.length() < 9 ){ return output; } //skip incomplete entries
197  output << lineInfo[0]; //name
198  output << lineInfo[1]; //architecture
199  output << lineInfo[2]; //version
200  output << lineInfo[4]; //datetime
201  if(lineInfo.length() >= 10){ output << lineInfo[9]; }//Size in KB
202  else{ output << ""; }
203  if(lineInfo[8].simplified() == "current"){ output << "true"; } //is most recent version
204  else{ output << "false"; }  //is an older version
205  output << lineInfo[5].section("/",-1); //filename (Example: myapp-0.1-amd64.pbi)
206  return output;
207}
208
209QStringList PBIDBAccess::parseAppMetaLine(QString line){
210  // line format 5/1/2013: [name,category,remoteIcon,author,website,license,apptype,tags,description,requiresroot]
211  QStringList output = line.split(";");
212  if(output.length() < 10){ output.clear();} //invalid line
213  else if(output[9]=="YES"){ output[9]="true"; } //change to the same true/false syntax as elsewhere
214  return output;
215}
216
217QStringList PBIDBAccess::parseCatMetaLine(QString line){
218  // line format 5/1/2013: [name,remoteicon,description,?]
219  QStringList output = line.split(";");
220  if(output.length() < 3){output.clear(); } //incomplete line
221  return output;
222}
223       
224QString PBIDBAccess::remoteToLocalIcon(QString name, QString remoteIconPath){
225  QString output = DBPath+"repo-icons/"+currentRepoID+"-"+name+"."+remoteIconPath.section(".",-1);
226  //qDebug() << "Remote to Local Icon Path conversion:" << remoteIconPath << output;
227  return output;
228}
229
230// ===== Database Modification Functions =====
231bool PBIDBAccess::addRepoFile(QString rpofilepath){
232  if(!QFile::exists(rpofilepath)){ return FALSE; }
233  //Generate the command
234  QString cmd;
235  if(cmdPrefix.isEmpty()){ return FALSE; }
236  else{ cmd = cmdPrefix; }
237  cmd.append("\"pbi_addrepo "+rpofilepath+"\"");
238  qDebug() <<"DB cmd generated:" << cmd;
239  //Now run the command
240  QStringList result = runCMD(cmd).split("\n");
241  if(!result.isEmpty()){
242    if(result[result.length()-1].startsWith("Added new repo:")){ 
243      //Make sure to prompt the PBI Daemon to refresh the meta/index files now
244      runCMD( cmdPrefix+"\"pbid --refresh\"" ); //don't care about output
245      return TRUE;
246    }
247  } 
248  qDebug() << "PBI Database Error:";
249  qDebug() << " - CMD:"<<cmd;
250  qDebug() << " - Error:"<<result;
251  return FALSE;
252}
253
254bool PBIDBAccess::removeRepo(QString repoNum){
255  //Generate the command
256  QString cmd;
257  if(cmdPrefix.isEmpty()){ return FALSE; }
258  else{ cmd = cmdPrefix; }
259  cmd.append("\"pbi_deleterepo "+repoNum+"\"");
260  qDebug() <<"DB cmd generated:" << cmd;
261  //Now run the command
262  QStringList result = runCMD(cmd).split("\n");
263  if(!result.isEmpty()){
264    //qDebug() << "Repo Removed:" << result;
265    if(result[result.length()-1].startsWith("Deleted Repository")){ return TRUE; }
266  } 
267  qDebug() << "PBI Database Error:";
268  qDebug() << " - CMD:"<<cmd;
269  qDebug() << " - Error:"<<result;
270  return FALSE; 
271}
272
273bool PBIDBAccess::moveRepoUp(QString repoNum){
274  //Generate the command
275  QString cmd;
276  if(cmdPrefix.isEmpty()){ return FALSE; }
277  else{ cmd = cmdPrefix; }
278  cmd.append("\"pbi_listrepo --up "+repoNum+"\"");
279  qDebug() <<"DB cmd generated:" << cmd;
280  //Now run the command
281  QStringList result = runCMD(cmd).split("\n");
282  if(!result.isEmpty()){
283    return TRUE; //no special check for this - will need to re-load repos anyway
284  } 
285  return FALSE;
286}
287
288bool PBIDBAccess::moveRepoDown(QString repoNum){
289  //Generate the command
290  QString cmd;
291  if(cmdPrefix.isEmpty()){ return FALSE; }
292  else{ cmd = cmdPrefix; }
293  cmd.append("\"pbi_listrepo --down "+repoNum+"\"");
294  qDebug() <<"DB cmd generated:" << cmd;
295  //Now run the command
296  QStringList result = runCMD(cmd).split("\n");
297  if(!result.isEmpty()){
298    return TRUE; //no special check for this - will need to re-load repos anyway
299  } 
300  return FALSE;
301}
302
303bool PBIDBAccess::setRepoMirrors(QString repoNum, QStringList mirrors){
304  QString cmd;
305  if(cmdPrefix.isEmpty()){ return FALSE; }
306  else{ cmd = cmdPrefix; }
307  cmd.append("\"pbi_listrepo --mirror "+mirrors.join(",")+" "+repoNum+"\"");
308  qDebug() <<"DB cmd generated:" << cmd;
309  //Now run the command
310  QStringList result = runCMD(cmd).split("\n");
311  if(!result.isEmpty()){
312    if(mirrors.isEmpty()){
313      if(result[result.length()-1].startsWith("Mirror(s):")){ return TRUE; }
314    }else{
315      if(result[result.length()-1] == mirrors[mirrors.length()-1] ){ return TRUE; }
316    }
317  } 
318  qDebug() << "PBI Database Error:";
319  qDebug() << " - CMD:"<<cmd;
320  qDebug() << " - Error:"<<result;
321  return FALSE;         
322}
323
324// ========================================
325// =======  PRIVATE ACCESS FUNCTIONS ======
326// ========================================
327QString PBIDBAccess::readOneLineFile(QString path){
328  QFile file(path);
329  if(!file.exists()){ return ""; } //Return nothing for missing file
330  //Now read the file
331  QString output;
332  if(file.open(QIODevice::ReadOnly | QIODevice::Text)){
333    QTextStream in(&file);
334    while(!in.atEnd()){
335      output.append(in.readLine());
336    }
337    file.close();
338  }
339  return output;
340}
341
342QString PBIDBAccess::getIDFromNum(QString repoNum){
343  QString output;
344  for(int i=0; i<repoList.length(); i++){
345    if(repoList[i].startsWith(repoNum+".")){
346      output = repoList[i].section(".",1,1);
347      break;       
348    }
349  }     
350  return output;
351}
352
353QString PBIDBAccess::runCMD(QString cmd){
354  //Small function to run quick database modification commands
355  QString output;
356  proc->start(cmd);
357  if(proc->waitForFinished(30000)){
358    output = proc->readAll();     
359  }else{
360    proc->terminate();
361    output = "Process timed out (30 sec)";
362  }
363  if(output.endsWith("\n")){ output.chop(1); }
364  output.simplified();
365  return output;
366}
Note: See TracBrowser for help on using the repository browser.