tweak C1-era CARR
[openc2e.git] / qtgui / AgentInjector.cpp
blob9b6572a22218fb8264ce67f0c3a2d8de1020a574
1 /*
2 This program is free software; you can redistribute it and/or modify
3 it under the terms of the GNU General Public License as published by
4 the Free Software Foundation; either version 2 of the License, or
5 (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License along
13 with this program; if not, write to the Free Software Foundation, Inc.,
14 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 #include "World.h"
18 #include "Engine.h"
20 #include "AgentInjector.h"
21 #include "c1cobfile.h"
22 #include "cobFile.h"
24 #include <boost/filesystem/path.hpp>
25 #include <boost/filesystem/convenience.hpp>
27 #include <QMessageBox>
28 #include <QPainter>
30 namespace fs = boost::filesystem;
32 AgentInjector::AgentInjector(QWidget *parent) : QDialog(parent) {
33 ui.setupUi(this);
35 connect(ui.injectButton, SIGNAL(clicked()), this, SLOT(onInject()));
36 connect(ui.removeButton, SIGNAL(clicked()), this, SLOT(onRemove()));
37 connect(ui.agentList, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), this, SLOT(onSelect(QListWidgetItem *, QListWidgetItem *)));
38 connect(ui.agentList, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), ui.imagePreview, SLOT(onSelect(QListWidgetItem *, QListWidgetItem *)));
40 setAttribute(Qt::WA_QuitOnClose, false);
42 resize(400,500);
44 readAgents();
47 AgentInjector::~AgentInjector() {
48 resetAgents();
51 void AgentInjector::onSelect(QListWidgetItem *current, QListWidgetItem *prev) {
52 if (!current) return;
54 ui.injectButton->setEnabled(true);
56 if (engine.version == 2) {
57 cobAgentBlock *b = (cobAgentBlock *)current->data(Qt::UserRole).value<void *>();
58 assert(b);
59 ui.Description->setText(b->description.c_str());
60 ui.removeButton->setEnabled(b->removescript.size() != 0);
61 } else {
62 ui.removeButton->setEnabled(false); // TODO: support remover files!
63 ui.Description->setText("");
67 void AgentInjector::resetAgents() {
68 ui.agentList->clear();
69 ui.injectButton->setEnabled(false);
70 ui.removeButton->setEnabled(false);
72 for (std::vector<class cobFile *>::iterator i = cobfiles.begin(); i != cobfiles.end(); i++) {
73 delete *i;
77 void AgentInjector::readAgents() {
78 resetAgents();
80 for (unsigned int i = 0; i < world.data_directories.size(); i++) {
81 fs::path p = world.data_directories[i];
82 if (engine.version == 2) p = p / "/Objects/";
83 if (!fs::exists(p) || !fs::is_directory(p)) {
84 continue;
87 fs::directory_iterator end_itr; // default constructor is the end
88 for (fs::directory_iterator itr(p); itr != end_itr; itr++) {
89 std::string cobext = fs::extension(itr->path());
90 std::transform(cobext.begin(), cobext.end(), cobext.begin(), (int(*)(int))tolower); // downcase
91 if (cobext != ".cob") continue;
93 std::string cob = itr->path().native_file_string();
95 if (engine.version == 1) {
96 std::ifstream cobstream(cob.c_str(), std::ios::binary);
97 if (!cobstream.fail()) {
98 c1cobfile cobfile(cobstream);
99 QListWidgetItem *newItem = new QListWidgetItem(cobfile.name.c_str(), ui.agentList);
100 newItem->setToolTip(cob.c_str());
102 } else if (engine.version == 2) {
103 cobFile *cobfile = new cobFile(itr->path());
104 cobfiles.push_back(cobfile);
106 for (std::vector<cobBlock *>::iterator i = cobfile->blocks.begin(); i != cobfile->blocks.end(); i++) {
107 if ((*i)->type != "agnt") continue;
108 cobAgentBlock *a = new cobAgentBlock(*i);
109 QListWidgetItem *newItem = new QListWidgetItem(a->name.c_str(), ui.agentList);
110 newItem->setToolTip(cob.c_str());
111 newItem->setData(Qt::UserRole, QVariant::fromValue((void *)a));
118 void AgentInjector::onInject() {
119 std::string idata;
121 if (!ui.agentList->currentItem()) return;
123 if (engine.version == 1) {
124 QString filename = ui.agentList->currentItem()->toolTip();
125 std::ifstream cobstream(filename.toAscii(), std::ios::binary);
126 if (cobstream.fail()) {
127 return; // TODO: throw some kind of warning or something
130 c1cobfile cobfile(cobstream);
131 for (unsigned int i = 0; i < cobfile.scripts.size(); i++) {
132 idata += cobfile.scripts[i] + "\n";
134 for (unsigned int i = 0; i < cobfile.imports.size(); i++) {
135 idata += "iscr," + cobfile.imports[i] + "\n";
137 } else if (engine.version == 2) {
138 cobAgentBlock *b = (cobAgentBlock *)ui.agentList->currentItem()->data(Qt::UserRole).value<void *>();
139 assert(b);
141 cobFile *cobfile = b->getParent()->getParent();
142 assert(cobfile);
144 // dependencies
145 assert(b->deptypes.size() == b->depnames.size());
146 for (unsigned int i = 0; i < b->deptypes.size(); i++) {
147 unsigned short type = b->deptypes[i];
148 std::string name = b->depnames[i];
150 unsigned int praytype;
151 switch (type) {
152 case 0: praytype = 2; break;
153 case 1: praytype = 1; break;
154 default: QMessageBox::warning(this, tr("Couldn't inject:"), tr("Unknown dependency type")); return;
157 std::string directory = world.praymanager.getResourceDir(praytype);
158 caos_assert(!directory.empty());
160 fs::path possiblefile = fs::path(directory, fs::native) / fs::path(name, fs::native);
161 if (!world.findFile(possiblefile.native_directory_string()).empty()) continue; // TODO: update file if necessary?
163 std::vector<cobBlock *>::iterator j;
165 std::string encounteredfilenames;
167 // check all of the available file blocks in this COB
168 for (j = cobfile->blocks.begin(); j != cobfile->blocks.end(); j++) {
169 if ((*j)->type != "file") continue;
170 cobFileBlock *a = new cobFileBlock(*j);
171 if (a->filetype == type && a->filename == name) {
172 // Found dependency!
173 fs::path dir = fs::path(world.getUserDataDir(), fs::native) / fs::path(directory, fs::native);
174 if (!fs::exists(dir))
175 fs::create_directory(dir);
176 assert(fs::exists(dir) && fs::is_directory(dir)); // TODO: error handling
178 fs::path outputfile = dir / fs::path(name, fs::native);
179 assert(!fs::exists(outputfile));
181 std::ofstream output(outputfile.native_directory_string().c_str(), std::ios::binary);
182 output.write((char *)a->getFileContents(), a->filesize);
184 a->getParent()->free();
186 break;
188 encounteredfilenames += " '" + a->filename + "'";
191 if (j == cobfile->blocks.end()) {
192 // Couldn't find dependency!
193 std::string error = "Failed to find required dependency '" + name + "', possible choices were:" + encounteredfilenames;
194 QMessageBox::warning(this, tr("Couldn't inject:"), error.c_str());
195 return;
199 // script injection
200 for (unsigned int i = 0; i < b->scripts.size(); i++) {
201 idata += b->scripts[i] + "\n";
203 idata += "iscr," + b->installscript + "\n";
206 idata += "rscr\n";
208 std::string result = engine.executeNetwork(idata);
209 if (result.size())
210 QMessageBox::warning(this, tr("Injection returned data (error?):"), result.c_str());
213 void AgentInjector::onRemove() {
214 std::string idata;
216 if (!ui.agentList->currentItem()) return;
218 if (engine.version == 2) {
219 cobAgentBlock *b = (cobAgentBlock *)ui.agentList->currentItem()->data(Qt::UserRole).value<void *>();
220 assert(b);
222 idata += b->removescript += "\n";
225 idata += "rscr\n";
227 std::string result = engine.executeNetwork(idata);
228 if (result.size())
229 QMessageBox::warning(this, tr("Removal returned data (error?):"), result.c_str());