1 //UTILITIES.cpp
2
3 #include "utilities.h"
4
5 //#include <unistd.h>
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <iostream>
10 #include <fstream>
11
12 #include <QtNetwork>
13 #include <QWidgetList>
14
15 #include "QTDefs.h"
16
17 using namespace std;
18
writeFile(const QString & filePath,const QString & content)19 void writeFile(const QString& filePath, const QString& content)
20 {
21 QFile f(filePath);
22
23 if (f.open(QFile::WriteOnly | QIODevice::Truncate)) {
24 QTextStream textWriting(&f);
25 textWriting<<content;
26 f.close();
27 }
28 }
29
readFile(const QString & filePath)30 QString readFile(const QString& filePath)
31 {
32 QString content("");
33 QFile f(filePath);
34
35 if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
36 content = QLatin1String(f.readAll());
37 f.close();
38 }
39
40 return content;
41 }
42
43 //Returns the content of a file passed in path
pathToContent(const QString & path)44 QString pathToContent(const QString& path)
45 {
46 ifstream file(path.toStdString().c_str(), std::ifstream::binary);
47
48 file.seekg (0, file.end);
49 int size = file.tellg();
50 if (size <= 0) {
51 cerr << path.toStdString() << ": pathToContent failed with size=" << size << endl;
52 return ""; // something wrong here: abort
53 }
54 file.seekg (0, file.beg);
55
56 // And allocate buffer to that a single line can be read...
57 char* buffer = new char[size + 1];
58 file.read(buffer, size);
59
60 // Terminate the string
61 buffer[size] = 0;
62 QString result = buffer;
63 file.close();
64 delete [] buffer;
65 return result;
66 }
67
touchFolder(const QString & path)68 void touchFolder(const QString& path)
69 {
70 QString instruction = "touch " + path;
71 QString error("");
72 executeInstruction(instruction, error);
73 }
74
executeInstruction(const QString & instruct,QString & errorMsg)75 bool executeInstruction(const QString& instruct, QString& errorMsg)
76 {
77 QProcess myCmd;
78 QByteArray error;
79 QStringList args;
80
81 myCmd.start(instruct, args);
82 myCmd.waitForFinished();
83 error = myCmd.readAllStandardError();
84
85 if (myCmd.readChannel() == QProcess::StandardError ) {
86 errorMsg = error.data();
87 return false;
88 } else {
89 return true;
90 }
91 }
92
93 //Delete recursively the content of a folder
deleteDirectoryAndContent(const QString & directory)94 void deleteDirectoryAndContent(const QString& directory)
95 {
96 QString rmInstruct("rm -r ");
97 rmInstruct += directory;
98 QString errorMsg("");
99 executeInstruction(rmInstruct, errorMsg);
100 }
101
tarFolder(const QString & folder,QString & errorMsg)102 bool tarFolder(const QString& folder, QString& errorMsg)
103 {
104 QString systemInstruct("tar cfv ");
105 systemInstruct += folder + ".tar " + folder;
106 return executeInstruction(systemInstruct, errorMsg);
107 }
108
untarFolder(const QString & folder,QString & errorMsg)109 bool untarFolder(const QString& folder, QString& errorMsg)
110 {
111 QString systemInstruct("tar xfv ");
112 systemInstruct += folder +" -C /";
113 return executeInstruction(systemInstruct, errorMsg);
114 }
115
116 //Remove a directory
rmDir(const QString & dirPath)117 bool rmDir(const QString &dirPath)
118 {
119 QDir dir(dirPath);
120
121 if (!dir.exists()) {
122 return true;
123 }
124
125 foreach(const QFileInfo &info, dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
126 if (info.isDir()) {
127 if (!rmDir(info.filePath()))
128 return false;
129 } else {
130 if (!dir.remove(info.fileName()))
131 return false;
132 }
133 }
134 QDir parentDir(QFileInfo(dirPath).path());
135 return parentDir.rmdir(QFileInfo(dirPath).fileName());
136 }
137
138 //Copy a directory
cpDir(const QString & srcPath,const QString & dstPath)139 bool cpDir(const QString &srcPath, const QString &dstPath)
140 {
141 rmDir(dstPath);
142 QDir parentDstDir(QFileInfo(dstPath).path());
143 if (!parentDstDir.mkdir(QFileInfo(dstPath).fileName()))
144 return false;
145
146 QDir srcDir(srcPath);
147 foreach(const QFileInfo &info, srcDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
148 QString srcItemPath = srcPath + "/" + info.fileName();
149 QString dstItemPath = dstPath + "/" + info.fileName();
150 if (info.isDir()) {
151 if (!cpDir(srcItemPath, dstItemPath)) {
152 return false;
153 }
154 } else if (info.isFile()) {
155 if (!QFile::copy(srcItemPath, dstItemPath)) {
156 return false;
157 }
158 } else {
159 qDebug() << "Unhandled item" << info.filePath() << "in cpDir";
160 }
161 }
162 return true;
163 }
164
165 //Verify if the word is a number
isStringInt(const char * word)166 bool isStringInt(const char* word)
167 {
168 bool returning = true;
169 for (size_t i = 0; i < strlen(word); i++) {
170 if (!isdigit(word[i])) {
171 returning = false;
172 break;
173 }
174 }
175 return returning;
176 }
177
178 //Search IP adress in ifconfig result
searchLocalIP()179 QString searchLocalIP()
180 {
181 printf("Utilities... Search for IP\n");
182
183 QList<QHostAddress> ipAdresses = QNetworkInterface::allAddresses();
184 QList<QHostAddress>::iterator it;
185 QString localhost("localhost");
186
187 for(it = ipAdresses.begin(); it != ipAdresses.end(); it++){
188 if ((*it).protocol() == QAbstractSocket::IPv4Protocol && (*it) != QHostAddress::LocalHost) {
189 printf("HOST = %s at pos = %i\n", it->toString().toStdString().c_str(), it->toString().indexOf("169."));
190 //Filter strange windows default adress 169.x.x.x
191 if(it->toString().indexOf("169.") != 0)
192 return it->toString();
193 } else if ((*it).protocol() == QAbstractSocket::IPv4Protocol && (*it) == QHostAddress::LocalHost) {
194 localhost = it->toString();
195 }
196 }
197
198 return localhost;
199 }
200
201 //Look for 'key' in 'options' and modify the parameter 'position' if found
parseKey(vector<string> options,const string & key,int & position)202 bool parseKey(vector<string> options, const string& key, int& position)
203 {
204 for (size_t i = 0; i < options.size(); i++){
205 if (key == options[i]){
206 position = i;
207 return true;
208 }
209 }
210
211 return false;
212 }
213
214 //Add 'key' if existing in 'options', otherwise add 'defaultKey' (if different from "")
215 //#return true if 'key' was added
addKeyIfExisting(vector<string> & options,vector<string> & newoptions,const string & key,const string & defaultKey,int & position)216 bool addKeyIfExisting(vector<string>& options, vector<string>& newoptions, const string& key, const string& defaultKey, int& position)
217 {
218 if (parseKey(options, key, position)) {
219 newoptions.push_back(options[position]);
220 options.erase(options.begin()+position);
221 position--;
222 return true;
223 } else if (defaultKey != "") {
224 newoptions.push_back(defaultKey);
225 }
226
227 return false;
228 }
229
230 //Add 'key' & it's associated value if existing in 'options', otherwise add 'defaultValue' (if different from "")
addKeyValueIfExisting(vector<string> & options,vector<string> & newoptions,const string & key,const string & defaultValue)231 void addKeyValueIfExisting(vector<string>& options, vector<string>& newoptions, const string& key, const string& defaultValue)
232 {
233 int position = 0;
234
235 if (addKeyIfExisting(options, newoptions, key, "", position)) {
236 if (position+1 < int(options.size()) && options[position+1][0] != '-') {
237 newoptions.push_back(options[position+1]);
238 options.erase(options.begin()+position+1);
239 position--;
240 } else {
241 newoptions.push_back(defaultValue);
242 }
243 }
244 }
245
246 /* Reorganizes the compilation options
247 * Following the tree of compilation (Faust_Compilation_Options.pdf in distribution)
248 */
reorganizeCompilationOptionsAux(vector<string> & options)249 vector<string> reorganizeCompilationOptionsAux(vector<string>& options)
250 {
251 bool vectorize = false;
252 int position = 0;
253
254 vector<string> newoptions;
255
256 //------STEP 1 - Single or Double ?
257 addKeyIfExisting(options, newoptions, "-double", "-single", position);
258
259 //------STEP 2 - Options Leading to -vec inclusion
260 if (addKeyIfExisting(options, newoptions, "-sch", "", position)) {
261 vectorize = true;
262 }
263
264 if (addKeyIfExisting(options, newoptions, "-omp", "", position)){
265 vectorize = true;
266 addKeyIfExisting(options, newoptions, "-pl", "", position);
267 }
268
269 if (vectorize) {
270 newoptions.push_back("-vec");
271 }
272
273 //------STEP3 - Add options depending on -vec/-scal option
274 if (vectorize || addKeyIfExisting(options, newoptions, "-vec", "", position)) {
275 addKeyIfExisting(options, newoptions, "-dfs", "", position);
276 addKeyIfExisting(options, newoptions, "-vls", "", position);
277 addKeyIfExisting(options, newoptions, "-fun", "", position);
278 addKeyIfExisting(options, newoptions, "-g", "", position);
279 addKeyValueIfExisting(options, newoptions, "-vs", "32");
280 addKeyValueIfExisting(options, newoptions, "-lv", "0");
281 } else {
282 addKeyIfExisting(options, newoptions, "-scal", "-scal", position);
283 addKeyIfExisting(options, newoptions, "-inpl", "", position);
284 }
285
286 addKeyValueIfExisting(options, newoptions, "-mcd", "16");
287 addKeyValueIfExisting(options, newoptions, "-cn", "");
288
289 //------STEP4 - Add other types of Faust options
290 /*
291 addKeyIfExisting(options, newoptions, "-tg", "", position);
292 addKeyIfExisting(options, newoptions, "-sg", "", position);
293 addKeyIfExisting(options, newoptions, "-ps", "", position);
294 addKeyIfExisting(options, newoptions, "-svg", "", position);
295
296 if (addKeyIfExisting(options, newoptions, "-mdoc", "", position)) {
297 addKeyValueIfExisting(options, newoptions, "-mdlang", "");
298 addKeyValueIfExisting(options, newoptions, "-stripdoc", "");
299 }
300
301 addKeyIfExisting(options, newoptions, "-sd", "", position);
302 addKeyValueIfExisting(options, newoptions, "-f", "25");
303 addKeyValueIfExisting(options, newoptions, "-mns", "40");
304 addKeyIfExisting(options, newoptions, "-sn", "", position);
305 addKeyIfExisting(options, newoptions, "-xml", "", position);
306 addKeyIfExisting(options, newoptions, "-blur", "", position);
307 addKeyIfExisting(options, newoptions, "-lb", "", position);
308 addKeyIfExisting(options, newoptions, "-mb", "", position);
309 addKeyIfExisting(options, newoptions, "-rb", "", position);
310 addKeyIfExisting(options, newoptions, "-lt", "", position);
311 addKeyValueIfExisting(options, newoptions, "-a", "");
312 addKeyIfExisting(options, newoptions, "-i", "", position);
313 addKeyValueIfExisting(options, newoptions, "-cn", "");
314 addKeyValueIfExisting(options, newoptions, "-t", "120");
315 addKeyIfExisting(options, newoptions, "-time", "", position);
316 addKeyValueIfExisting(options, newoptions, "-o", "");
317 addKeyValueIfExisting(options, newoptions, "-lang", "cpp");
318 addKeyIfExisting(options, newoptions, "-flist", "", position);
319 addKeyValueIfExisting(options, newoptions, "-l", "");
320 addKeyValueIfExisting(options, newoptions, "-O", "");
321
322 //-------Add Other Options that are possibily passed to the compiler (-I, -blabla, ...)
323 while (options.size() != 0) {
324 if (options[0] != "faust") newoptions.push_back(options[0]); // "faust" first argument
325 options.erase(options.begin());
326 }
327 */
328
329 return newoptions;
330 }
331
FL_reorganize_compilation_options(QString compilationOptions)332 string FL_reorganize_compilation_options(QString compilationOptions)
333 {
334 int argc = get_numberParameters(compilationOptions);
335 vector<string> res1;
336 for (int i = 0; i < argc; i++) {
337 res1.push_back(parse_compilationParams(compilationOptions));
338 }
339
340 vector<string> res2 = reorganizeCompilationOptionsAux(res1);
341 string res3;
342 string sep;
343 for (size_t i = 0; i < res2.size(); i++) {
344 res3 = res3 + sep + res2[i];
345 sep = " ";
346 }
347
348 return "\"" + res3 + "\"";
349 }
350
351 // Code by: B-Con (http://b-con.us)
352 // Released under the GNU GPL
353 // MD5 Hash Digest implementation (little endian byte order)
354
355 // Signed variables are for wimps
356 #define uchar unsigned char
357 #define uint unsigned int
358
359 // DBL_INT_ADD treats two unsigned ints a and b as one 64-bit integer and adds c to it
360 #define ROTLEFT(a,b) ((a << b) | (a >> (32-b)))
361 #define DBL_INT_ADD(a,b,c) if (a > 0xffffffff - c) ++b; a += c;
362
363 typedef struct {
364 uchar data[64];
365 uint datalen;
366 uint bitlen[2];
367 uint state[5];
368 uint k[4];
369 } SHA1_CTX;
370
sha1_transform(SHA1_CTX * ctx,uchar data[])371 static void sha1_transform(SHA1_CTX* ctx, uchar data[])
372 {
373 uint a,b,c,d,e,i,j,t,m[80];
374
375 for (i = 0,j = 0; i < 16; ++i, j += 4) {
376 m[i] = (data[j] << 24) + (data[j+1] << 16) + (data[j+2] << 8) + (data[j+3]);
377 }
378 for ( ; i < 80; ++i) {
379 m[i] = (m[i-3] ^ m[i-8] ^ m[i-14] ^ m[i-16]);
380 m[i] = (m[i] << 1) | (m[i] >> 31);
381 }
382
383 a = ctx->state[0];
384 b = ctx->state[1];
385 c = ctx->state[2];
386 d = ctx->state[3];
387 e = ctx->state[4];
388
389 for (i=0; i < 20; ++i) {
390 t = ROTLEFT(a,5) + ((b & c) ^ (~b & d)) + e + ctx->k[0] + m[i];
391 e = d;
392 d = c;
393 c = ROTLEFT(b,30);
394 b = a;
395 a = t;
396 }
397 for ( ; i < 40; ++i) {
398 t = ROTLEFT(a,5) + (b ^ c ^ d) + e + ctx->k[1] + m[i];
399 e = d;
400 d = c;
401 c = ROTLEFT(b,30);
402 b = a;
403 a = t;
404 }
405 for ( ; i < 60; ++i) {
406 t = ROTLEFT(a,5) + ((b & c) ^ (b & d) ^ (c & d)) + e + ctx->k[2] + m[i];
407 e = d;
408 d = c;
409 c = ROTLEFT(b,30);
410 b = a;
411 a = t;
412 }
413 for ( ; i < 80; ++i) {
414 t = ROTLEFT(a,5) + (b ^ c ^ d) + e + ctx->k[3] + m[i];
415 e = d;
416 d = c;
417 c = ROTLEFT(b,30);
418 b = a;
419 a = t;
420 }
421
422 ctx->state[0] += a;
423 ctx->state[1] += b;
424 ctx->state[2] += c;
425 ctx->state[3] += d;
426 ctx->state[4] += e;
427 }
428
sha1_init(SHA1_CTX * ctx)429 static void sha1_init(SHA1_CTX* ctx)
430 {
431 ctx->datalen = 0;
432 ctx->bitlen[0] = 0;
433 ctx->bitlen[1] = 0;
434 ctx->state[0] = 0x67452301;
435 ctx->state[1] = 0xEFCDAB89;
436 ctx->state[2] = 0x98BADCFE;
437 ctx->state[3] = 0x10325476;
438 ctx->state[4] = 0xc3d2e1f0;
439 ctx->k[0] = 0x5a827999;
440 ctx->k[1] = 0x6ed9eba1;
441 ctx->k[2] = 0x8f1bbcdc;
442 ctx->k[3] = 0xca62c1d6;
443 }
444
sha1_update(SHA1_CTX * ctx,uchar data[],uint len)445 static void sha1_update(SHA1_CTX* ctx, uchar data[], uint len)
446 {
447 uint i;
448
449 for (i = 0; i < len; ++i) {
450 ctx->data[ctx->datalen] = data[i];
451 ctx->datalen++;
452 if (ctx->datalen == 64) {
453 sha1_transform(ctx, ctx->data);
454 DBL_INT_ADD(ctx->bitlen[0], ctx->bitlen[1], 512);
455 ctx->datalen = 0;
456 }
457 }
458 }
459
sha1_final(SHA1_CTX * ctx,uchar hash[])460 static void sha1_final(SHA1_CTX *ctx, uchar hash[])
461 {
462 uint i;
463
464 i = ctx->datalen;
465
466 // Pad whatever data is left in the buffer.
467 if (ctx->datalen < 56) {
468 ctx->data[i++] = 0x80;
469 while (i < 56) {
470 ctx->data[i++] = 0x00;
471 }
472 } else {
473 ctx->data[i++] = 0x80;
474 while (i < 64) {
475 ctx->data[i++] = 0x00;
476 }
477 sha1_transform(ctx, ctx->data);
478 memset(ctx->data,0,56);
479 }
480
481 // Append to the padding the total message's length in bits and transform.
482 DBL_INT_ADD(ctx->bitlen[0], ctx->bitlen[1], 8 * ctx->datalen);
483 ctx->data[63] = ctx->bitlen[0];
484 ctx->data[62] = ctx->bitlen[0] >> 8;
485 ctx->data[61] = ctx->bitlen[0] >> 16;
486 ctx->data[60] = ctx->bitlen[0] >> 24;
487 ctx->data[59] = ctx->bitlen[1];
488 ctx->data[58] = ctx->bitlen[1] >> 8;
489 ctx->data[57] = ctx->bitlen[1] >> 16;
490 ctx->data[56] = ctx->bitlen[1] >> 24;
491 sha1_transform(ctx,ctx->data);
492
493 // Since this implementation uses little endian byte ordering and MD uses big endian,
494 // reverse all the bytes when copying the final state to the output hash.
495 for (i = 0; i < 4; ++i) {
496 hash[i] = (ctx->state[0] >> (24-i*8)) & 0x000000ff;
497 hash[i+4] = (ctx->state[1] >> (24-i*8)) & 0x000000ff;
498 hash[i+8] = (ctx->state[2] >> (24-i*8)) & 0x000000ff;
499 hash[i+12] = (ctx->state[3] >> (24-i*8)) & 0x000000ff;
500 hash[i+16] = (ctx->state[4] >> (24-i*8)) & 0x000000ff;
501 }
502 }
503
FL_generate_sha1(const string & dsp_content)504 string FL_generate_sha1(const string& dsp_content)
505 {
506 SHA1_CTX ctx;
507 unsigned char obuf[20] = {0};
508
509 // Hash one
510 sha1_init(&ctx);
511 sha1_update(&ctx, (unsigned char*)dsp_content.c_str(), dsp_content.size());
512 sha1_final(&ctx, obuf);
513
514 // convert SHA1 key into hexadecimal string
515 string sha1key;
516 for (int i = 0; i < 20; i++) {
517 const char* H = "0123456789ABCDEF";
518 char c1 = H[(obuf[i] >> 4)];
519 char c2 = H[(obuf[i] & 15)];
520 sha1key += c1;
521 sha1key += c2;
522 }
523
524 return sha1key;
525 }
526
527 //---------------COMPILATION OPTIONS
528
529 //Get number of compilation options
get_numberParameters(const QString & compilOptions)530 int get_numberParameters(const QString& compilOptions)
531 {
532 int argc = 0;
533 int pos = compilOptions.indexOf("-");
534
535 while (pos != -1 && pos < compilOptions.size()) {
536
537 argc++;
538 pos = compilOptions.indexOf(" ", pos);
539
540 while (pos != -1 && pos < compilOptions.size()) {
541 if (compilOptions[pos] == ' ') {
542 pos++;
543 } else if(compilOptions[pos] == '-') {
544 break;
545 } else {
546 argc++;
547 pos = compilOptions.indexOf(" ", pos);
548 }
549 }
550 }
551
552 return argc;
553 }
554
555 //Hand written Parser
556 //Returns : the first option found, skipping the ' '
557 //CompilOptions : the rest of the options are kept in
parse_compilationParams(QString & compilOptions)558 string parse_compilationParams(QString& compilOptions)
559 {
560 QString returning = "";
561 int pos = 0;
562
563 while (pos != -1 && pos < compilOptions.size()) {
564 if (compilOptions[pos] == ' ') {
565 pos++;
566 } else {
567 int pos2 = compilOptions.indexOf(" ", pos);
568 returning = compilOptions.mid(pos, pos2-pos);
569 if (pos2 == -1) {
570 pos2 = compilOptions.size();
571 }
572 compilOptions.remove(0, pos2);
573 break;
574 }
575 }
576
577 return returning.toStdString();
578 }
579
580 // center a widget on the primary screen of the machine or
581 // on the screen of the top level widget
centerOnPrimaryScreen(QWidget * w)582 void centerOnPrimaryScreen(QWidget* w)
583 {
584 QWidgetList l = QApplication::topLevelWidgets();
585 #ifdef QTNEWPRIMARYSCREEN
586 QPoint center = QGuiApplication::primaryScreen()->virtualGeometry().center();
587 #else
588 QDesktopWidget *dw = QApplication::desktop();
589 QPoint center = dw->availableGeometry(dw->primaryScreen()).center() - w->geometry().center();
590 #endif
591 const QRect r = w->geometry();
592 w->move(center.x() - r.width()/2, center.y() - r.height()/2);
593
594 // if (l.empty()) {
595 // w->move(center);
596 // } else {
597 // QWidget* topwidget = l.first();
598 //#ifdef QTNEWPRIMARYSCREEN
599 // QPoint center = QGuiApplication::primaryScreen()->virtualGeometry().center();
600 //#else
601 // dw->screenGeometry(topwidget).center()
602 //#endif
603 // w->move(dw->screenGeometry(topwidget).center() - w->geometry().center());
604 // }
605 }
606
607
608