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