vdr-plugin-skindesigner/extensions/skinrepo.c

376 lines
11 KiB
C

#include <iostream>
#include <fstream>
#include "skinrepo.h"
#include "helpers.h"
using namespace std;
// --- cSkinRepo -------------------------------------------------------------
cSkinRepo::cSkinRepo(void) {
name = "";
repoType = rtUndefined;
action = eaUndefined;
url = "";
author = "unknown";
minSDVersion = "0.0.1";
command = "";
command2 = "";
tempfile = "";
result = -1;
skinPath = "";
themesPath = "";
}
cSkinRepo::~cSkinRepo() {
}
bool cSkinRepo::Valid(void) {
if (!name.size())
return false;
if (repoType == rtUndefined)
return false;
if (!url.size())
return false;
return true;
}
void cSkinRepo::Install(string path, string themesPath) {
if (Running())
return;
action = eaInstall;
this->skinPath = path + name;
this->themesPath = themesPath;
if (repoType == rtGit) {
command = *cString::sprintf("git clone --depth=1 --progress %s %s", url.c_str(), skinPath.c_str());
tempfile = *cString::sprintf("gitclone_%s_%ld.out", name.c_str(), time(0));
dsyslog("skindesigner: installing skin from Git, command: %s, logfile: %s", command.c_str(), tempfile.c_str());
Start();
} else if (repoType == rtZipUrl) {
size_t hit = url.find_last_of('/');
if (hit == string::npos)
return;
string filename = url.substr(hit+1);
command = *cString::sprintf("wget -P /tmp/ %s", url.c_str());
command2 = *cString::sprintf("unzip /tmp/%s -d %s", filename.c_str(), path.c_str());
dsyslog("skindesigner: installing skin from Zip, command: %s, %s", command.c_str(), command2.c_str());
Start();
}
}
void cSkinRepo::Update(string path) {
if (Running())
return;
action = eaUpdate;
this->skinPath = path + name;
if (repoType == rtGit) {
command = *cString::sprintf("cd %s; git pull", skinPath.c_str());
tempfile = *cString::sprintf("gitpull_%s_%ld.out", name.c_str(), time(0));
dsyslog("skindesigner: updating skin from Git, command: %s, logfile: /tmp/%s", command.c_str(), tempfile.c_str());
Start();
} else if (repoType == rtZipUrl) {
//TODO
}
}
void cSkinRepo::Action(void) {
if (command.size() < 1)
return;
if (tempfile.size() > 0) {
command = *cString::sprintf("%s > /tmp/%s 2>&1", command.c_str(), tempfile.c_str());
}
result = system (command.c_str());
if (result == 0 && command2.size() > 0) {
result = system (command2.c_str());
}
if (result == 0) {
if (action == eaInstall)
CreateThemeFiles();
dsyslog("skindesigner: %s successfully executed", command.c_str());
} else {
esyslog("skindesigner: ERROR executing %s", command.c_str());
}
}
void cSkinRepo::CreateThemeFiles(void) {
string availableThemesPath = skinPath + "/themes/";
DIR *folder = NULL;
struct dirent *dirEntry;
folder = opendir(availableThemesPath.c_str());
if (!folder) {
return;
}
vector<string> skinThemes;
while (dirEntry = readdir(folder)) {
string dirEntryName = dirEntry->d_name;
int dirEntryType = dirEntry->d_type;
if (!dirEntryName.compare(".") || !dirEntryName.compare("..") || dirEntryType != DT_DIR)
continue;
skinThemes.push_back(dirEntryName);
}
for (vector<string>::iterator it = skinThemes.begin(); it != skinThemes.end(); it++) {
string themeName = *it;
string themeFileName = themesPath;
themeFileName += name + "-" + themeName + ".theme";
if (FileExists(themeFileName)) {
continue;
}
ofstream themeFile (themeFileName.c_str());
if (themeFile.is_open()) {
themeFile << "Description = ";
themeFile << themeName << "\n";
themeFile.close();
}
}
}
bool cSkinRepo::SuccessfullyUpdated(void) {
string logfilePath = "/tmp/" + tempfile;
bool updated = true;
string line;
ifstream logfile(logfilePath.c_str());
if (logfile.is_open()) {
while ( getline (logfile, line) ) {
if (line.find("up-to-date") != string::npos) {
updated = false;
break;
}
}
logfile.close();
}
return updated;
}
void cSkinRepo::Debug() {
string strRepoType = "Undefined";
if (repoType == rtGit)
strRepoType = "Git";
else if (repoType == rtZipUrl)
strRepoType = "ZipUrl";
dsyslog("skindesigner: --- skinrepo %s, Type %s ---", name.c_str(), strRepoType.c_str());
dsyslog("skindesigner: url %s", url.c_str());
dsyslog("skindesigner: author %s", author.c_str());
dsyslog("skindesigner: minimum Skindesigner Version required %s", minSDVersion.c_str());
if (specialFonts.size() > 0) {
for (vector<string>::iterator it = specialFonts.begin(); it != specialFonts.end(); it++) {
dsyslog("skindesigner: special font %s", (*it).c_str());
}
}
if (supportedPlugins.size() > 0) {
for (vector<string>::iterator it = supportedPlugins.begin(); it != supportedPlugins.end(); it++) {
dsyslog("skindesigner: supported plugin %s", (*it).c_str());
}
}
if (screenshots.size() > 0) {
for (vector<pair<string,string> >::iterator it = screenshots.begin(); it != screenshots.end(); it++) {
string desc = (it->first).c_str();
string url = (it->second).c_str();
dsyslog("skindesigner: screenshot \"%s\", url %s", desc.c_str(), url.c_str());
}
}
}
// --- cSkinRepos -------------------------------------------------------------
cSkinRepos::cSkinRepos(void) {
skinRepoUrl = "https://github.com/louisbraun/skinrepository.git";
repoFolder = "skinrepositories/";
}
cSkinRepos::~cSkinRepos() {
for (vector<cSkinRepo*>::iterator it = repos.begin(); it != repos.end(); it++) {
delete (*it);
}
}
void cSkinRepos::Init(string path) {
string repoPath = path + repoFolder;
if (FolderExists(repoPath)) {
PullRepoGit(repoPath);
} else {
InitRepoGit(repoPath);
}
}
void cSkinRepos::Read(string path) {
string repoPath = path + repoFolder;
DIR *folder = NULL;
struct dirent *dirEntry;
folder = opendir(repoPath.c_str());
if (!folder) {
esyslog("skindesigner: no skinrepository folder available in %s", repoPath.c_str());
return;
}
while (dirEntry = readdir(folder)) {
string fileName = dirEntry->d_name;
if (!fileName.compare(".") || !fileName.compare("..") || !fileName.compare(".git"))
continue;
string filePath = repoPath + fileName;
if (! ReadXMLFile(filePath.c_str(), false) ) {
esyslog("skindesigner: error reading skinrepo %s", filePath.c_str());
continue;
}
if (! SetDocument() )
continue;
if (!ParseRepository())
esyslog("skindesigner: error parsing skinrepository %s", filePath.c_str());
DeleteDocument();
}
}
cSkinRepo *cSkinRepos::GetRepo(string name) {
for (vector<cSkinRepo*>::iterator it = repos.begin(); it != repos.end(); it++) {
cSkinRepo *repo = (*it);
if (!name.compare(repo->Name()))
return repo;
}
return NULL;
}
cSkinRepo *cSkinRepos::GetNextRepo(void) {
if (repoIt == repos.end())
return NULL;
cSkinRepo *repo = *repoIt;
repoIt++;
return repo;
}
void cSkinRepos::Debug(void) {
for (vector<cSkinRepo*>::iterator it = repos.begin(); it != repos.end(); it++) {
(*it)->Debug();
}
}
bool cSkinRepos::ParseRepository(void) {
if (!LevelDown())
return false;
cSkinRepo *repo = new cSkinRepo();
do {
string value = "";
if (CheckNodeName("name")) {
if (GetNodeValue(value)) {
repo->SetName(value);
}
} else if (CheckNodeName("type")) {
if (GetNodeValue(value)) {
eRepoType repoType = rtUndefined;
if (!value.compare("git"))
repoType = rtGit;
else if (!value.compare("zip"))
repoType = rtZipUrl;
repo->SetRepoType(repoType);
}
} else if (CheckNodeName("url")) {
if (GetNodeValue(value)) {
repo->SetUrl(value);
}
} else if (CheckNodeName("author")) {
if (GetNodeValue(value)) {
repo->SetAuthor(value);
}
} else if (CheckNodeName("minimumskindesignerversion")) {
if (GetNodeValue(value)) {
repo->SetMinSDVersion(value);
}
} else if (CheckNodeName("specialfonts")) {
if (!LevelDown())
continue;
do {
if (CheckNodeName("font")) {
if (GetNodeValue(value)) {
repo->SetSpecialFont(value);
}
}
} while (NextNode());
LevelUp();
} else if (CheckNodeName("supportedplugins")) {
if (!LevelDown())
continue;
do {
if (CheckNodeName("plugin")) {
if (GetNodeValue(value)) {
repo->SetSupportedPlugin(value);
}
}
} while (NextNode());
LevelUp();
} else if (CheckNodeName("screenshots")) {
if (!LevelDown()) {
continue;
}
do {
if (CheckNodeName("screenshot")) {
if (!LevelDown()) {
continue;
}
string desc = "";
string url = "";
do {
if (CheckNodeName("description")) {
GetNodeValue(desc);
} else if (CheckNodeName("url")) {
GetNodeValue(url);
}
} while (NextNode());
LevelUp();
if (desc.size() && url.size())
repo->SetScreenshot(desc, url);
}
} while (NextNode());
LevelUp();
}
} while (NextNode());
LevelUp();
if (repo->Valid()) {
repos.push_back(repo);
return true;
}
return false;
}
void cSkinRepos::InitRepoGit(string path) {
dsyslog("skindesigner: initiating skin repository %s", path.c_str());
CreateFolder(path);
cString command = cString::sprintf("git clone --depth=1 %s %s", skinRepoUrl.c_str(), path.c_str());
int result = system (*command);
if (result == 0) {
dsyslog("skindesigner: skinrepository successfully initiated");
} else {
esyslog("skindesigner: ERROR initiating skinrepository. Command: %s", *command);
}
}
void cSkinRepos::PullRepoGit(string path) {
dsyslog("skindesigner: updating skin repository %s", path.c_str());
cString command = *cString::sprintf("cd %s; git pull", path.c_str());
int result = system (*command);
if (result == 0) {
dsyslog("skindesigner: skinrepository successfully updated");
} else {
esyslog("skindesigner: ERROR updating skinrepository. Command: %s", *command);
}
}