~teejee2008/apt-toolkit/trunk

« back to all changes in this revision

Viewing changes to src/Utility.vala

  • Committer: Tony George
  • Date: 2017-04-01 12:46:26 UTC
  • Revision ID: tony.george.kol@gmail.com-20170401124626-5sujdsdq06gjm6qu
Updated download manager backend; Fixed a random crash on downloading packages;

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Utility.vala
3
 
 *
4
 
 * Copyright 2012 Tony George <teejeetech@gmail.com>
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
9
 
 * (at your option) any later version.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 
 * MA 02110-1301, USA.
20
 
 *
21
 
 *
22
 
 */
23
 
 
24
 
using Gtk;
25
 
using Json;
26
 
using TeeJee.Logging;
27
 
using TeeJee.FileSystem;
28
 
using TeeJee.JSON;
29
 
using TeeJee.ProcessManagement;
30
 
using TeeJee.GtkHelper;
31
 
using TeeJee.Multimedia;
32
 
using TeeJee.System;
33
 
using TeeJee.Misc;
34
 
 
35
 
/*
36
 
extern void exit(int exit_code);
37
 
*/
38
 
 
39
 
namespace TeeJee.Logging{
40
 
 
41
 
        /* Functions for logging messages to console and log files */
42
 
 
43
 
        using TeeJee.Misc;
44
 
 
45
 
        public DataOutputStream dos_log;
46
 
        public string err_log;
47
 
        public bool LOG_ENABLE = true;
48
 
        public bool LOG_TIMESTAMP = true;
49
 
        public bool LOG_COLORS = true;
50
 
        public bool LOG_DEBUG = false;
51
 
        public bool LOG_COMMANDS = false;
52
 
 
53
 
        public void log_msg (string message, bool highlight = false){
54
 
 
55
 
                if (!LOG_ENABLE) { return; }
56
 
 
57
 
                string msg = "";
58
 
 
59
 
                if (highlight && LOG_COLORS){
60
 
                        msg += "\033[1;38;5;34m";
61
 
                }
62
 
 
63
 
                if (LOG_TIMESTAMP){
64
 
                        msg += "[" + timestamp() +  "] ";
65
 
                }
66
 
 
67
 
                msg += message;
68
 
 
69
 
                if (highlight && LOG_COLORS){
70
 
                        msg += "\033[0m";
71
 
                }
72
 
 
73
 
                msg += "\n";
74
 
 
75
 
                stdout.printf (msg);
76
 
                stdout.flush();
77
 
 
78
 
                try {
79
 
                        if (dos_log != null){
80
 
                                dos_log.put_string ("[%s] %s\n".printf(timestamp(), message));
81
 
                        }
82
 
                }
83
 
                catch (Error e) {
84
 
                        stdout.printf (e.message);
85
 
                }
86
 
        }
87
 
 
88
 
        public void log_error (string message, bool highlight = false, bool is_warning = false){
89
 
                if (!LOG_ENABLE) { return; }
90
 
 
91
 
                string msg = "";
92
 
 
93
 
                if (highlight && LOG_COLORS){
94
 
                        msg += "\033[1;38;5;160m";
95
 
                }
96
 
 
97
 
                if (LOG_TIMESTAMP){
98
 
                        msg += "[" + timestamp() +  "] ";
99
 
                }
100
 
 
101
 
                string prefix = (is_warning) ? _("W") : _("E");
102
 
 
103
 
                msg += prefix + ": " + message;
104
 
 
105
 
                if (highlight && LOG_COLORS){
106
 
                        msg += "\033[0m";
107
 
                }
108
 
 
109
 
                msg += "\n";
110
 
 
111
 
                stdout.printf (msg);
112
 
                stdout.flush();
113
 
                
114
 
                try {
115
 
                        string str = "[%s] %s: %s\n".printf(timestamp(), prefix, message);
116
 
                        
117
 
                        if (dos_log != null){
118
 
                                dos_log.put_string (str);
119
 
                        }
120
 
 
121
 
                        if (err_log != null){
122
 
                                err_log += "%s\n".printf(message);
123
 
                        }
124
 
                }
125
 
                catch (Error e) {
126
 
                        stdout.printf (e.message);
127
 
                }
128
 
        }
129
 
 
130
 
        public void log_debug (string message){
131
 
                if (!LOG_ENABLE) { return; }
132
 
 
133
 
                if (LOG_DEBUG){
134
 
                        log_msg (message);
135
 
                }
136
 
 
137
 
                try {
138
 
                        if (dos_log != null){
139
 
                                dos_log.put_string ("[%s] %s\n".printf(timestamp(), message));
140
 
                        }
141
 
                }
142
 
                catch (Error e) {
143
 
                        stdout.printf (e.message);
144
 
                }
145
 
        }
146
 
 
147
 
        public void log_draw_line(){
148
 
                log_msg(string.nfill(70,'='));
149
 
        }
150
 
        
151
 
        public void show_err_log(Gtk.Window parent, bool disable_log = true){
152
 
                if ((err_log != null) && (err_log.length > 0)){
153
 
                        gtk_messagebox(_("Error"), err_log, parent, true);
154
 
                }
155
 
 
156
 
                if (disable_log){
157
 
                        disable_err_log();
158
 
                }
159
 
        }
160
 
 
161
 
        public void clear_err_log(){
162
 
                err_log = "";
163
 
        }
164
 
 
165
 
        public void disable_err_log(){
166
 
                err_log = null;
167
 
        }
168
 
}
169
 
 
170
 
namespace TeeJee.FileSystem{
171
 
 
172
 
        /* Convenience functions for handling files and directories */
173
 
 
174
 
        using TeeJee.Logging;
175
 
        using TeeJee.FileSystem;
176
 
        using TeeJee.ProcessManagement;
177
 
        using TeeJee.Misc;
178
 
 
179
 
        // path helpers ----------------------------
180
 
        
181
 
        public string file_parent(string file_path){
182
 
                return File.new_for_path(file_path).get_parent().get_path();
183
 
        }
184
 
 
185
 
        public string file_basename(string file_path){
186
 
                return File.new_for_path(file_path).get_basename();
187
 
        }
188
 
 
189
 
        public string path_combine(string path1, string path2){
190
 
                return GLib.Path.build_path("/", path1, path2);
191
 
        }
192
 
 
193
 
        // file helpers -----------------------------
194
 
 
195
 
        public bool file_or_dir_exists(string item_path){
196
 
                
197
 
                /* check if item exists on disk*/
198
 
 
199
 
                var item = File.parse_name(item_path);
200
 
                return item.query_exists();
201
 
        }
202
 
        
203
 
        public bool file_exists (string file_path){
204
 
                /* Check if file exists */
205
 
                return ( FileUtils.test(file_path, GLib.FileTest.EXISTS) && FileUtils.test(file_path, GLib.FileTest.IS_REGULAR));
206
 
        }
207
 
 
208
 
        public bool file_delete(string file_path){
209
 
 
210
 
                /* Check and delete file */
211
 
 
212
 
                try {
213
 
                        var file = File.new_for_path (file_path);
214
 
                        if (file.query_exists ()) {
215
 
                                file.delete ();
216
 
                        }
217
 
                        return true;
218
 
                } catch (Error e) {
219
 
                log_error (e.message);
220
 
                log_error(_("Failed to delete file") + ": %s".printf(file_path));
221
 
                return false;
222
 
            }
223
 
        }
224
 
 
225
 
        public string? file_read (string file_path){
226
 
 
227
 
                /* Reads text from file */
228
 
 
229
 
                string txt;
230
 
                size_t size;
231
 
 
232
 
                try{
233
 
                        GLib.FileUtils.get_contents (file_path, out txt, out size);
234
 
                        return txt;
235
 
                }
236
 
                catch (Error e){
237
 
                log_error (e.message);
238
 
                log_error(_("Failed to read file") + ": %s".printf(file_path));
239
 
            }
240
 
 
241
 
            return null;
242
 
        }
243
 
 
244
 
        public bool file_write (string file_path, string contents){
245
 
 
246
 
                /* Write text to file */
247
 
 
248
 
                try{
249
 
 
250
 
                        dir_create(file_parent(file_path));
251
 
                        
252
 
                        var file = File.new_for_path (file_path);
253
 
                        if (file.query_exists ()) {
254
 
                                file.delete ();
255
 
                        }
256
 
                        
257
 
                        var file_stream = file.create (FileCreateFlags.REPLACE_DESTINATION);
258
 
                        var data_stream = new DataOutputStream (file_stream);
259
 
                        data_stream.put_string (contents);
260
 
                        data_stream.close();
261
 
                        return true;
262
 
                }
263
 
                catch (Error e) {
264
 
                        log_error (e.message);
265
 
                        log_error(_("Failed to write file") + ": %s".printf(file_path));
266
 
                        return false;
267
 
                }
268
 
        }
269
 
 
270
 
        public bool file_copy (string src_file, string dest_file){
271
 
                try{
272
 
                        var file_src = File.new_for_path (src_file);
273
 
                        if (file_src.query_exists()) {
274
 
                                var file_dest = File.new_for_path (dest_file);
275
 
                                file_src.copy(file_dest,FileCopyFlags.OVERWRITE,null,null);
276
 
                                return true;
277
 
                        }
278
 
                }
279
 
                catch(Error e){
280
 
                log_error (e.message);
281
 
                log_error(_("Failed to copy file") + ": '%s', '%s'".printf(src_file, dest_file));
282
 
                }
283
 
 
284
 
                return false;
285
 
        }
286
 
 
287
 
        public void file_move (string src_file, string dest_file){
288
 
                try{
289
 
                        var file_src = File.new_for_path (src_file);
290
 
                        if (file_src.query_exists()) {
291
 
                                var file_dest = File.new_for_path (dest_file);
292
 
                                file_src.move(file_dest,FileCopyFlags.OVERWRITE,null,null);
293
 
                        }
294
 
                        else{
295
 
                                log_error (_("File not found") + ": %s".printf(src_file));
296
 
                                log_error("file_move()");
297
 
                        }
298
 
                }
299
 
                catch(Error e){
300
 
                log_error (e.message);
301
 
                log_error(_("Failed to move file") + ": '%s', '%s'".printf(src_file, dest_file));
302
 
                }
303
 
        }
304
 
 
305
 
        public DateTime file_modified_date(string file_path){
306
 
                try{
307
 
                        FileInfo info;
308
 
                        File file = File.parse_name (file_path);
309
 
                        if (file.query_exists()) {
310
 
                                info = file.query_info("%s".printf(FileAttribute.TIME_MODIFIED), 0);
311
 
                                return (new DateTime.from_timeval_utc(info.get_modification_time())).to_local();
312
 
                        }
313
 
                }
314
 
                catch (Error e) {
315
 
                        log_error (e.message);
316
 
                }
317
 
                
318
 
                return (new DateTime.from_unix_utc(0)); //1970
319
 
        }
320
 
 
321
 
        // directory helpers ----------------------
322
 
 
323
 
        public int64 file_get_size(string file_path){
324
 
                try{
325
 
                        File file = File.parse_name (file_path);
326
 
                        if (FileUtils.test(file_path, GLib.FileTest.EXISTS)){
327
 
                                if (FileUtils.test(file_path, GLib.FileTest.IS_REGULAR)
328
 
                                        && !FileUtils.test(file_path, GLib.FileTest.IS_SYMLINK)){
329
 
                                        return file.query_info("standard::size",0).get_size();
330
 
                                }
331
 
                        }
332
 
                }
333
 
                catch(Error e){
334
 
                        log_error (e.message);
335
 
                }
336
 
 
337
 
                return -1;
338
 
        }
339
 
        
340
 
        // dep: find wc    TODO: rewrite
341
 
        public long dir_count(string path){
342
 
 
343
 
                /* Return total count of files and directories */
344
 
 
345
 
                string cmd = "";
346
 
                string std_out;
347
 
                string std_err;
348
 
                int ret_val;
349
 
 
350
 
                cmd = "find '%s' | wc -l".printf(escape_single_quote(path));
351
 
                ret_val = exec_script_sync(cmd, out std_out, out std_err);
352
 
                return long.parse(std_out);
353
 
        }
354
 
 
355
 
        public bool dir_exists (string dir_path){
356
 
                /* Check if directory exists */
357
 
                return ( FileUtils.test(dir_path, GLib.FileTest.EXISTS) && FileUtils.test(dir_path, GLib.FileTest.IS_DIR));
358
 
        }
359
 
        
360
 
        public bool dir_create (string dir_path){
361
 
 
362
 
                /* Creates a directory along with parents */
363
 
 
364
 
                try{
365
 
                        var dir = File.parse_name (dir_path);
366
 
                        if (dir.query_exists () == false) {
367
 
                                dir.make_directory_with_parents (null);
368
 
                        }
369
 
                        return true;
370
 
                }
371
 
                catch (Error e) {
372
 
                        log_error (e.message);
373
 
                        log_error(_("Failed to create dir") + ": %s".printf(dir_path));
374
 
                        return false;
375
 
                }
376
 
        }
377
 
 
378
 
        public bool dir_tar (string src_dir, string tar_file, bool recursion){
379
 
                if (dir_exists(src_dir)) {
380
 
                        
381
 
                        if (file_exists(tar_file)){
382
 
                                file_delete(tar_file);
383
 
                        }
384
 
 
385
 
                        var src_parent = file_parent(src_dir);
386
 
                        var src_name = file_basename(src_dir);
387
 
                        
388
 
                        string cmd = "tar cvf '%s' --overwrite --%srecursion -C '%s' '%s'\n".printf(tar_file, (recursion ? "" : "no-"), src_parent, src_name);
389
 
 
390
 
                        log_debug(cmd);
391
 
                        
392
 
                        string stdout, stderr;
393
 
                        int status = exec_script_sync(cmd, out stdout, out stderr);
394
 
                        if (status == 0){
395
 
                                return true;
396
 
                        }
397
 
                        else{
398
 
                                log_msg(stderr);
399
 
                        }
400
 
                }
401
 
                else{
402
 
                        log_error(_("Dir not found") + ": %s".printf(src_dir));
403
 
                }
404
 
 
405
 
                return false;
406
 
        }
407
 
 
408
 
        public bool dir_untar (string tar_file, string dst_dir){
409
 
                if (file_exists(tar_file)) {
410
 
 
411
 
                        if (!dir_exists(dst_dir)){
412
 
                                dir_create(dst_dir);
413
 
                        }
414
 
                        
415
 
                        string cmd = "tar xvf '%s' --overwrite --same-permissions -C '%s'\n".printf(tar_file, dst_dir);
416
 
 
417
 
                        log_debug(cmd);
418
 
                        
419
 
                        string stdout, stderr;
420
 
                        int status = exec_script_sync(cmd, out stdout, out stderr);
421
 
                        if (status == 0){
422
 
                                return true;
423
 
                        }
424
 
                        else{
425
 
                                log_msg(stderr);
426
 
                        }
427
 
                }
428
 
                else{
429
 
                        log_error(_("File not found") + ": %s".printf(tar_file));
430
 
                }
431
 
                
432
 
                return false;
433
 
        }
434
 
 
435
 
        // archiving and encryption ----------------
436
 
 
437
 
        public bool file_tar_encrypt (string src_file, string dst_file, string password){
438
 
                if (file_exists(src_file)) {
439
 
                        if (file_exists(dst_file)){
440
 
                                file_delete(dst_file);
441
 
                        }
442
 
 
443
 
                        var src_dir = file_parent(src_file);
444
 
                        var src_name = file_basename(src_file);
445
 
 
446
 
                        var dst_dir = file_parent(dst_file);
447
 
                        var dst_name = file_basename(dst_file);
448
 
                        var tar_name = dst_name[0 : dst_name.index_of(".gpg")];
449
 
                        var tar_file = "%s/%s".printf(dst_dir, tar_name);
450
 
                        
451
 
                        string cmd = "tar cvf '%s' --overwrite -C '%s' '%s'\n".printf(tar_file, src_dir, src_name);
452
 
                        cmd += "gpg --passphrase '%s' -o '%s' --symmetric '%s'\n".printf(password, dst_file, tar_file);
453
 
                        cmd += "rm -f '%s'\n".printf(tar_file);
454
 
 
455
 
                        log_debug(cmd);
456
 
                        
457
 
                        string stdout, stderr;
458
 
                        int status = exec_script_sync(cmd, out stdout, out stderr);
459
 
                        if (status == 0){
460
 
                                return true;
461
 
                        }
462
 
                        else{
463
 
                                log_msg(stderr);
464
 
                        }
465
 
                }
466
 
 
467
 
                return false;
468
 
        }
469
 
 
470
 
        public string file_decrypt_untar_read (string src_file, string password){
471
 
                
472
 
                if (file_exists(src_file)) {
473
 
                        
474
 
                        //var src_name = file_basename(src_file);
475
 
                        //var tar_name = src_name[0 : src_name.index_of(".gpg")];
476
 
                        //var tar_file = "%s/%s".printf(TEMP_DIR, tar_name);
477
 
                        //var temp_file = "%s/%s".printf(TEMP_DIR, random_string());
478
 
 
479
 
                        string cmd = "";
480
 
                        cmd += "gpg --quiet --no-verbose --passphrase '%s' -o- --decrypt '%s'".printf(password, src_file);
481
 
                        cmd += " | tar xf - --to-stdout 2>/dev/null\n";
482
 
                        cmd += "exit $?\n";
483
 
                        
484
 
                        log_debug(cmd);
485
 
                        
486
 
                        string std_out, std_err;
487
 
                        int status = exec_script_sync(cmd, out std_out, out std_err);
488
 
                        if (status == 0){
489
 
                                return std_out;
490
 
                        }
491
 
                        else{
492
 
                                log_error(std_err);
493
 
                                return "";
494
 
                        }
495
 
                }
496
 
                else{
497
 
                        log_error(_("File is missing") + ": %s".printf(src_file));
498
 
                }
499
 
 
500
 
                return "";
501
 
        }
502
 
 
503
 
        public bool decrypt_and_untar (string src_file, string dst_file, string password){
504
 
                if (file_exists(src_file)) {
505
 
                        if (file_exists(dst_file)){
506
 
                                file_delete(dst_file);
507
 
                        }
508
 
 
509
 
                        var src_dir = file_parent(src_file);
510
 
                        var src_name = file_basename(src_file);
511
 
                        var tar_name = src_name[0 : src_name.index_of(".gpg")];
512
 
                        var tar_file = "%s/%s".printf(src_dir, tar_name);
513
 
 
514
 
                        string cmd = "";
515
 
                        cmd += "rm -f '%s'\n".printf(tar_file); // gpg cannot overwrite - remove tar file if it exists
516
 
                        cmd += "gpg --passphrase '%s' -o '%s' --decrypt '%s'\n".printf(password, tar_file, src_file);
517
 
                        cmd += "status=$?; if [ $status -ne 0 ]; then exit $status; fi\n";
518
 
                        cmd += "tar xvf '%s' --overwrite --same-permissions -C '%s'\n".printf(tar_file, file_parent(dst_file));
519
 
                        cmd += "rm -f '%s'\n".printf(tar_file);
520
 
 
521
 
                        log_debug(cmd);
522
 
                        
523
 
                        string stdout, stderr;
524
 
                        int status = exec_script_sync(cmd, out stdout, out stderr);
525
 
                        if (status == 0){
526
 
                                return true;
527
 
                        }
528
 
                        else{
529
 
                                log_error(stderr);
530
 
                                return false;
531
 
                        }
532
 
                }
533
 
                else{
534
 
                        log_error(_("File is missing") + ": %s".printf(src_file));
535
 
                }
536
 
 
537
 
                return false;
538
 
        }
539
 
 
540
 
        // misc --------------------
541
 
        
542
 
        public long get_file_count(string path){
543
 
 
544
 
                /* Return total count of files and directories */
545
 
 
546
 
                string cmd = "";
547
 
                string std_out;
548
 
                string std_err;
549
 
                int ret_val;
550
 
 
551
 
                cmd = "find \"%s\" | wc -l".printf(path);
552
 
                ret_val = exec_script_sync(cmd, out std_out, out std_err);
553
 
                return long.parse(std_out);
554
 
        }
555
 
 
556
 
        public long get_file_size(string path){
557
 
 
558
 
                /* Returns size of files and directories in KB*/
559
 
 
560
 
                string cmd = "";
561
 
                string output = "";
562
 
 
563
 
                cmd = "du -s \"%s\"".printf(path);
564
 
                output = execute_command_sync_get_output(cmd);
565
 
                return long.parse(output.split("\t")[0]);
566
 
        }
567
 
 
568
 
        public int64 get_file_size_bytes(string file_path){
569
 
                try{
570
 
                        File file = File.parse_name (file_path);
571
 
                        if (FileUtils.test(file_path, GLib.FileTest.EXISTS)){
572
 
                                if (FileUtils.test(file_path, GLib.FileTest.IS_REGULAR)
573
 
                                        && !FileUtils.test(file_path, GLib.FileTest.IS_SYMLINK)){
574
 
                                        return file.query_info("standard::size",0).get_size();
575
 
                                }
576
 
                        }
577
 
                }
578
 
                catch(Error e){
579
 
                        log_error (e.message);
580
 
                }
581
 
 
582
 
                return -1;
583
 
        }
584
 
 
585
 
        public uint64 dir_size(string path){
586
 
                /* Returns size of directories */
587
 
 
588
 
                string cmd = "";
589
 
                string output = "";
590
 
 
591
 
                cmd = "du -s \"%s\"".printf(path);
592
 
                output = execute_command_sync_get_output(cmd);
593
 
                return uint64.parse(output.split("\t")[0].strip()) * 1024;
594
 
        }
595
 
        
596
 
        public string get_file_size_formatted2(string path){
597
 
 
598
 
                /* Returns size of files and directories in KB*/
599
 
 
600
 
                string cmd = "";
601
 
                string output = "";
602
 
 
603
 
                cmd = "du -s -h \"%s\"".printf(path);
604
 
                output = execute_command_sync_get_output(cmd);
605
 
                return output.split("\t")[0].strip();
606
 
        }
607
 
 
608
 
        public string format_file_size (uint64 size, bool binary_units = false){
609
 
                int64 KB = binary_units ? 1024 : 1000;
610
 
                int64 MB = binary_units ? 1024 * KB : 1000 * KB;
611
 
                int64 GB = binary_units ? 1024 * MB : 1000 * MB;
612
 
 
613
 
                if (size > GB){
614
 
                        return "%'0.1f %sB".printf(size/(1.0*GB), (binary_units)?"Gi":"G");
615
 
                }
616
 
                else if (size > MB){
617
 
                        return "%'0.1f %sB".printf(size/(1.0*MB), (binary_units)?"Mi":"M");
618
 
                }
619
 
                else if (size > KB){
620
 
                        return "%'0.0f %sB".printf(size/(1.0*KB), (binary_units)?"Ki":"K");
621
 
                }
622
 
                else{
623
 
                        return "%'0lld B".printf(size);
624
 
                }
625
 
        }
626
 
        
627
 
        public int chmod (string file, string permission){
628
 
 
629
 
                /* Change file permissions */
630
 
 
631
 
                return exec_sync ("chmod " + permission + " \"%s\"".printf(file));
632
 
        }
633
 
 
634
 
        public string resolve_relative_path (string filePath){
635
 
 
636
 
                /* Resolve the full path of given file using 'realpath' command */
637
 
 
638
 
                string filePath2 = filePath;
639
 
                if (filePath2.has_prefix ("~")){
640
 
                        filePath2 = Environment.get_home_dir () + "/" + filePath2[2:filePath2.length];
641
 
                }
642
 
 
643
 
                try {
644
 
                        string output = "";
645
 
                        Process.spawn_command_line_sync("realpath \"%s\"".printf(filePath2), out output);
646
 
                        output = output.strip ();
647
 
                        if (FileUtils.test(output, GLib.FileTest.EXISTS)){
648
 
                                return output;
649
 
                        }
650
 
                }
651
 
                catch(Error e){
652
 
                log_error (e.message);
653
 
            }
654
 
 
655
 
            return filePath2;
656
 
        }
657
 
 
658
 
        public int rsync (string sourceDirectory, string destDirectory, bool updateExisting, bool deleteExtra){
659
 
 
660
 
                /* Sync files with rsync */
661
 
 
662
 
                string cmd = "rsync --recursive --perms --chmod=a=rwx";
663
 
                cmd += updateExisting ? "" : " --ignore-existing";
664
 
                cmd += deleteExtra ? " --delete" : "";
665
 
                cmd += " \"%s\"".printf(sourceDirectory + "//");
666
 
                cmd += " \"%s\"".printf(destDirectory);
667
 
                return exec_sync (cmd);
668
 
        }
669
 
 
670
 
        public string escape_single_quote(string file_path){
671
 
                return file_path.replace("'","'\\''");
672
 
        }
673
 
}
674
 
 
675
 
namespace TeeJee.JSON{
676
 
 
677
 
        using TeeJee.Logging;
678
 
 
679
 
        /* Convenience functions for reading and writing JSON files */
680
 
 
681
 
        public string json_get_string(Json.Object jobj, string member, string def_value){
682
 
                if (jobj.has_member(member)){
683
 
                        return jobj.get_string_member(member);
684
 
                }
685
 
                else{
686
 
                        log_error ("Member not found in JSON object: " + member, false, true);
687
 
                        return def_value;
688
 
                }
689
 
        }
690
 
 
691
 
        public bool json_get_bool(Json.Object jobj, string member, bool def_value){
692
 
                if (jobj.has_member(member)){
693
 
                        return bool.parse(jobj.get_string_member(member));
694
 
                }
695
 
                else{
696
 
                        log_error ("Member not found in JSON object: " + member, false, true);
697
 
                        return def_value;
698
 
                }
699
 
        }
700
 
 
701
 
        public int json_get_int(Json.Object jobj, string member, int def_value){
702
 
                if (jobj.has_member(member)){
703
 
                        return int.parse(jobj.get_string_member(member));
704
 
                }
705
 
                else{
706
 
                        log_error ("Member not found in JSON object: " + member, false, true);
707
 
                        return def_value;
708
 
                }
709
 
        }
710
 
 
711
 
}
712
 
 
713
 
namespace TeeJee.ProcessManagement{
714
 
        using TeeJee.Logging;
715
 
        using TeeJee.FileSystem;
716
 
        using TeeJee.Misc;
717
 
 
718
 
        public string TEMP_DIR;
719
 
 
720
 
        /* Convenience functions for executing commands and managing processes */
721
 
        
722
 
    public static void init_tmp(){
723
 
                string std_out, std_err;
724
 
 
725
 
                TEMP_DIR = Environment.get_tmp_dir() + "/" + AppShortName + "/" + random_string();
726
 
                dir_create(TEMP_DIR);
727
 
 
728
 
                exec_script_sync("echo 'ok'",out std_out,out std_err, true);
729
 
                if ((std_out == null)||(std_out.strip() != "ok")){
730
 
                        TEMP_DIR = Environment.get_home_dir() + "/.temp/" + AppShortName + "/" + random_string();
731
 
                        exec_sync("rm -rf '%s'".printf(TEMP_DIR));
732
 
                        dir_create(TEMP_DIR);
733
 
                }
734
 
 
735
 
                //log_debug("TEMP_DIR=" + TEMP_DIR);
736
 
        }
737
 
 
738
 
        public int exec_sync (string cmd, out string? std_out = null, out string? std_err = null){
739
 
 
740
 
                /* Executes single command synchronously.
741
 
                 * Pipes and multiple commands are not supported.
742
 
                 * std_out, std_err can be null. Output will be written to terminal if null. */
743
 
 
744
 
                try {
745
 
                        int status;
746
 
                        Process.spawn_command_line_sync(cmd, out std_out, out std_err, out status);
747
 
                return status;
748
 
                }
749
 
                catch (Error e){
750
 
                log_error (e.message);
751
 
                return -1;
752
 
            }
753
 
        }
754
 
        
755
 
        public int exec_script_sync (string script, out string? std_out = null, out string? std_err = null, bool supress_errors = false){
756
 
 
757
 
                /* Executes commands synchronously.
758
 
                 * Pipes and multiple commands are fully supported.
759
 
                 * Commands are written to a temporary bash script and executed.
760
 
                 * std_out, std_err can be null. Output will be written to terminal if null.
761
 
                 * */
762
 
 
763
 
                string path = save_bash_script_temp(script, supress_errors);
764
 
 
765
 
                try {
766
 
 
767
 
                        string[] argv = new string[1];
768
 
                        argv[0] = path;
769
 
 
770
 
                        string[] env = Environ.get();
771
 
                        
772
 
                        int exit_code;
773
 
 
774
 
                        Process.spawn_sync (
775
 
                            TEMP_DIR, //working dir
776
 
                            argv, //argv
777
 
                            env, //environment
778
 
                            SpawnFlags.SEARCH_PATH,
779
 
                            null,   // child_setup
780
 
                            out std_out,
781
 
                            out std_err,
782
 
                            out exit_code
783
 
                            );
784
 
 
785
 
                        return exit_code;
786
 
                }
787
 
                catch (Error e){
788
 
                        if (!supress_errors){
789
 
                                log_error (e.message);
790
 
                        }
791
 
                        return -1;
792
 
                }
793
 
        }
794
 
 
795
 
        public int exec_script_async (string script){
796
 
 
797
 
                /* Executes commands synchronously.
798
 
                 * Pipes and multiple commands are fully supported.
799
 
                 * Commands are written to a temporary bash script and executed.
800
 
                 * Return value indicates if script was started successfully.
801
 
                 *  */
802
 
 
803
 
                try {
804
 
 
805
 
                        string scriptfile = save_bash_script_temp (script);
806
 
 
807
 
                        string[] argv = new string[1];
808
 
                        argv[0] = scriptfile;
809
 
 
810
 
                        string[] env = Environ.get();
811
 
                        
812
 
                        Pid child_pid;
813
 
                        Process.spawn_async_with_pipes(
814
 
                            TEMP_DIR, //working dir
815
 
                            argv, //argv
816
 
                            env, //environment
817
 
                            SpawnFlags.SEARCH_PATH,
818
 
                            null,
819
 
                            out child_pid);
820
 
 
821
 
                        return 0;
822
 
                }
823
 
                catch (Error e){
824
 
                log_error (e.message);
825
 
                return 1;
826
 
            }
827
 
        }
828
 
 
829
 
 
830
 
        //TODO: Deprecated, Remove this
831
 
        public string execute_command_sync_get_output (string cmd){
832
 
 
833
 
                /* Executes single command synchronously and returns std_out
834
 
                 * Pipes and multiple commands are not supported */
835
 
 
836
 
                try {
837
 
                        int exitCode;
838
 
                        string std_out;
839
 
                        Process.spawn_command_line_sync(cmd, out std_out, null, out exitCode);
840
 
                return std_out;
841
 
                }
842
 
                catch (Error e){
843
 
                log_error (e.message);
844
 
                return "";
845
 
            }
846
 
        }
847
 
 
848
 
        //TODO: Deprecated, Remove this
849
 
        public bool execute_command_script_async (string cmd){
850
 
 
851
 
                /* Creates a temporary bash script with given commands and executes it asynchronously
852
 
                 * Return value indicates if script was started successfully */
853
 
 
854
 
                try {
855
 
 
856
 
                        string scriptfile = save_bash_script_temp (cmd);
857
 
 
858
 
                        string[] argv = new string[1];
859
 
                        argv[0] = scriptfile;
860
 
 
861
 
                        string[] env = Environ.get();
862
 
                        
863
 
                        Pid child_pid;
864
 
                        Process.spawn_async_with_pipes(
865
 
                            TEMP_DIR, //working dir
866
 
                            argv, //argv
867
 
                            env, //environment
868
 
                            SpawnFlags.SEARCH_PATH,
869
 
                            null,
870
 
                            out child_pid);
871
 
 
872
 
                        return true;
873
 
                }
874
 
                catch (Error e){
875
 
                log_error (e.message);
876
 
                return false;
877
 
            }
878
 
        }
879
 
 
880
 
        public string? save_bash_script_temp (string commands, bool force_locale = true, bool supress_errors = false){
881
 
 
882
 
                /* Creates a temporary bash script with given commands
883
 
                 * Returns the script file path */
884
 
 
885
 
                var script = new StringBuilder();
886
 
                script.append ("#!/bin/bash\n");
887
 
                script.append ("\n");
888
 
                if (force_locale){
889
 
                        script.append ("LANG=C\n");
890
 
                }
891
 
                script.append ("\n");
892
 
                script.append ("%s\n".printf(commands));
893
 
                script.append ("\n\nexitCode=$?\n");
894
 
                script.append ("echo ${exitCode} > ${exitCode}\n");
895
 
                script.append ("echo ${exitCode} > status\n");
896
 
                
897
 
                string script_path = get_temp_file_path() + ".sh";
898
 
 
899
 
                try{
900
 
                        //write script file
901
 
                        var file = File.new_for_path (script_path);
902
 
                        if (file.query_exists ()) { file.delete (); }
903
 
                        var file_stream = file.create (FileCreateFlags.REPLACE_DESTINATION);
904
 
                        var data_stream = new DataOutputStream (file_stream);
905
 
                        data_stream.put_string (script.str);
906
 
                        data_stream.close();
907
 
 
908
 
                        // set execute permission
909
 
                        chmod (script_path, "u+x");
910
 
 
911
 
                        return script_path;
912
 
                }
913
 
                catch (Error e) {
914
 
                        if (!supress_errors){
915
 
                                log_error (e.message);
916
 
                        }
917
 
                }
918
 
 
919
 
                return null;
920
 
        }
921
 
 
922
 
        public string get_temp_file_path(){
923
 
 
924
 
                /* Generates temporary file path */
925
 
 
926
 
                return TEMP_DIR + "/" + timestamp2() + (new Rand()).next_int().to_string();
927
 
        }
928
 
 
929
 
        public string get_cmd_path (string cmd){
930
 
 
931
 
                /* Returns the full path to a command */
932
 
 
933
 
                try {
934
 
                        int exitCode;
935
 
                        string stdout, stderr;
936
 
                        Process.spawn_command_line_sync("which " + cmd, out stdout, out stderr, out exitCode);
937
 
                return stdout;
938
 
                }
939
 
                catch (Error e){
940
 
                log_error (e.message);
941
 
                return "";
942
 
            }
943
 
        }
944
 
 
945
 
        public int get_pid_by_name (string name){
946
 
 
947
 
                /* Get the process ID for a process with given name */
948
 
 
949
 
                try{
950
 
                        string output = "";
951
 
                        Process.spawn_command_line_sync("pidof \"%s\"".printf(name), out output);
952
 
                        if (output != null){
953
 
                                string[] arr = output.split ("\n");
954
 
                                if (arr.length > 0){
955
 
                                        return int.parse (arr[0]);
956
 
                                }
957
 
                        }
958
 
                }
959
 
                catch (Error e) {
960
 
                        log_error (e.message);
961
 
                }
962
 
 
963
 
                return -1;
964
 
        }
965
 
 
966
 
        public int get_pid_by_command(string cmdline){
967
 
                try {
968
 
                        FileEnumerator enumerator;
969
 
                        FileInfo info;
970
 
                        File file = File.parse_name ("/proc");
971
 
 
972
 
                        enumerator = file.enumerate_children ("standard::name", 0);
973
 
                        while ((info = enumerator.next_file()) != null) {
974
 
                                try {
975
 
                                        string io_stat_file_path = "/proc/%s/cmdline".printf(info.get_name());
976
 
                                        var io_stat_file = File.new_for_path(io_stat_file_path);
977
 
                                        if (file.query_exists()){
978
 
                                                var dis = new DataInputStream (io_stat_file.read());
979
 
 
980
 
                                                string line;
981
 
                                                string text = "";
982
 
                                                size_t length;
983
 
                                                while((line = dis.read_until ("\0", out length)) != null){
984
 
                                                        text += " " + line;
985
 
                                                }
986
 
 
987
 
                                                if ((text != null) && text.contains(cmdline)){
988
 
                                                        return int.parse(info.get_name());
989
 
                                                }
990
 
                                        } //stream closed
991
 
                                }
992
 
                                catch(Error e){
993
 
                                  //log_error (e.message);
994
 
                                }
995
 
                        }
996
 
                }
997
 
                catch(Error e){
998
 
                  log_error (e.message);
999
 
                }
1000
 
 
1001
 
                return -1;
1002
 
        }
1003
 
 
1004
 
        public void get_proc_io_stats(int pid, out int64 read_bytes, out int64 write_bytes){
1005
 
                string io_stat_file_path = "/proc/%d/io".printf(pid);
1006
 
                var file = File.new_for_path(io_stat_file_path);
1007
 
 
1008
 
                read_bytes = 0;
1009
 
                write_bytes = 0;
1010
 
 
1011
 
                try {
1012
 
                        if (file.query_exists()){
1013
 
                                var dis = new DataInputStream (file.read());
1014
 
                                string line;
1015
 
                                while ((line = dis.read_line (null)) != null) {
1016
 
                                        if(line.has_prefix("rchar:")){
1017
 
                                                read_bytes = int64.parse(line.replace("rchar:","").strip());
1018
 
                                        }
1019
 
                                        else if(line.has_prefix("wchar:")){
1020
 
                                                write_bytes = int64.parse(line.replace("wchar:","").strip());
1021
 
                                        }
1022
 
                                }
1023
 
                        } //stream closed
1024
 
                }
1025
 
                catch(Error e){
1026
 
                        log_error (e.message);
1027
 
                }
1028
 
        }
1029
 
 
1030
 
        public bool process_is_running(long pid){
1031
 
 
1032
 
                /* Checks if given process is running */
1033
 
 
1034
 
                string cmd = "";
1035
 
                string std_out;
1036
 
                string std_err;
1037
 
                int ret_val;
1038
 
 
1039
 
                try{
1040
 
                        cmd = "ps --pid %ld".printf(pid);
1041
 
                        Process.spawn_command_line_sync(cmd, out std_out, out std_err, out ret_val);
1042
 
                }
1043
 
                catch (Error e) {
1044
 
                        log_error (e.message);
1045
 
                        return false;
1046
 
                }
1047
 
 
1048
 
                return (ret_val == 0);
1049
 
        }
1050
 
 
1051
 
        public int[] get_process_children (Pid parentPid){
1052
 
 
1053
 
                /* Returns the list of child processes spawned by given process */
1054
 
 
1055
 
                string output;
1056
 
 
1057
 
                try {
1058
 
                        Process.spawn_command_line_sync("ps --ppid %d".printf(parentPid), out output);
1059
 
                }
1060
 
                catch(Error e){
1061
 
                log_error (e.message);
1062
 
            }
1063
 
 
1064
 
                int pid;
1065
 
                int[] procList = {};
1066
 
                string[] arr;
1067
 
 
1068
 
                foreach (string line in output.split ("\n")){
1069
 
                        arr = line.strip().split (" ");
1070
 
                        if (arr.length < 1) { continue; }
1071
 
 
1072
 
                        pid = 0;
1073
 
                        pid = int.parse (arr[0]);
1074
 
 
1075
 
                        if (pid != 0){
1076
 
                                procList += pid;
1077
 
                        }
1078
 
                }
1079
 
                return procList;
1080
 
        }
1081
 
 
1082
 
        public void process_quit(Pid process_pid, bool killChildren = true){
1083
 
 
1084
 
                /* Kills specified process and its children (optional) */
1085
 
 
1086
 
                int[] child_pids = get_process_children (process_pid);
1087
 
                Posix.kill (process_pid, Posix.SIGTERM);
1088
 
 
1089
 
                if (killChildren){
1090
 
                        Pid childPid;
1091
 
                        foreach (long pid in child_pids){
1092
 
                                childPid = (Pid) pid;
1093
 
                                Posix.kill (childPid, Posix.SIGTERM);
1094
 
                        }
1095
 
                }
1096
 
        }
1097
 
        
1098
 
        public void process_kill(Pid process_pid, bool killChildren = true){
1099
 
 
1100
 
                /* Kills specified process and its children (optional) */
1101
 
 
1102
 
                int[] child_pids = get_process_children (process_pid);
1103
 
                Posix.kill (process_pid, Posix.SIGKILL);
1104
 
 
1105
 
                if (killChildren){
1106
 
                        Pid childPid;
1107
 
                        foreach (long pid in child_pids){
1108
 
                                childPid = (Pid) pid;
1109
 
                                Posix.kill (childPid, Posix.SIGKILL);
1110
 
                        }
1111
 
                }
1112
 
        }
1113
 
 
1114
 
        public int process_pause (Pid procID){
1115
 
 
1116
 
                /* Pause/Freeze a process */
1117
 
 
1118
 
                return exec_sync ("kill -STOP %d".printf(procID));
1119
 
        }
1120
 
 
1121
 
        public int process_resume (Pid procID){
1122
 
 
1123
 
                /* Resume/Un-freeze a process*/
1124
 
 
1125
 
                return exec_sync ("kill -CONT %d".printf(procID));
1126
 
        }
1127
 
 
1128
 
        public void command_kill(string cmd_name, string cmd_to_match, bool exact_match){
1129
 
 
1130
 
                /* Kills a specific command */
1131
 
 
1132
 
                string txt = execute_command_sync_get_output ("ps w -C '%s'".printf(cmd_name));
1133
 
                //use 'ps ew -C conky' for all users
1134
 
 
1135
 
                string pid = "";
1136
 
                foreach(string line in txt.split("\n")){
1137
 
                        if ((exact_match && line.has_suffix(" " + cmd_to_match))
1138
 
                        || (!exact_match && (line.index_of(cmd_to_match) != -1))){
1139
 
                                pid = line.strip().split(" ")[0];
1140
 
                                Posix.kill ((Pid) int.parse(pid), 15);
1141
 
                                log_debug(_("Stopped") + ": [PID=" + pid + "] ");
1142
 
                        }
1143
 
                }
1144
 
        }
1145
 
 
1146
 
        public bool process_is_running_by_name(string proc_name){
1147
 
 
1148
 
                /* Checks if given process is running */
1149
 
 
1150
 
                string cmd = "";
1151
 
                string std_out;
1152
 
                string std_err;
1153
 
                int ret_val;
1154
 
 
1155
 
                try{
1156
 
                        cmd = "pgrep -f '%s'".printf(proc_name);
1157
 
                        Process.spawn_command_line_sync(cmd, out std_out, out std_err, out ret_val);
1158
 
                }
1159
 
                catch (Error e) {
1160
 
                        log_error (e.message);
1161
 
                        return false;
1162
 
                }
1163
 
 
1164
 
                return (ret_val == 0);
1165
 
        }
1166
 
        
1167
 
        public void process_set_priority (Pid procID, int prio){
1168
 
 
1169
 
                /* Set process priority */
1170
 
 
1171
 
                if (Posix.getpriority (Posix.PRIO_PROCESS, procID) != prio)
1172
 
                        Posix.setpriority (Posix.PRIO_PROCESS, procID, prio);
1173
 
        }
1174
 
 
1175
 
        public int process_get_priority (Pid procID){
1176
 
 
1177
 
                /* Get process priority */
1178
 
 
1179
 
                return Posix.getpriority (Posix.PRIO_PROCESS, procID);
1180
 
        }
1181
 
 
1182
 
        public void process_set_priority_normal (Pid procID){
1183
 
 
1184
 
                /* Set normal priority for process */
1185
 
 
1186
 
                process_set_priority (procID, 0);
1187
 
        }
1188
 
 
1189
 
        public void process_set_priority_low (Pid procID){
1190
 
 
1191
 
                /* Set low priority for process */
1192
 
 
1193
 
                process_set_priority (procID, 5);
1194
 
        }
1195
 
 
1196
 
 
1197
 
        public bool user_is_admin (){
1198
 
 
1199
 
                /* Check if current application is running with admin priviledges */
1200
 
 
1201
 
                try{
1202
 
                        // create a process
1203
 
                        string[] argv = { "sleep", "10" };
1204
 
                        Pid procId;
1205
 
                        Process.spawn_async(null, argv, null, SpawnFlags.SEARCH_PATH, null, out procId);
1206
 
 
1207
 
                        // try changing the priority
1208
 
                        Posix.setpriority (Posix.PRIO_PROCESS, procId, -5);
1209
 
 
1210
 
                        // check if priority was changed successfully
1211
 
                        if (Posix.getpriority (Posix.PRIO_PROCESS, procId) == -5)
1212
 
                                return true;
1213
 
                        else
1214
 
                                return false;
1215
 
                }
1216
 
                catch (Error e) {
1217
 
                        log_error (e.message);
1218
 
                        return false;
1219
 
                }
1220
 
        }
1221
 
 
1222
 
        public int get_user_id(){
1223
 
 
1224
 
                // returns actual user id of current user (even for applications executed with sudo and pkexec)
1225
 
                
1226
 
                int user_id = -1;
1227
 
 
1228
 
                string pkexec_uid = GLib.Environment.get_variable("PKEXEC_UID");
1229
 
 
1230
 
                if (pkexec_uid != null){
1231
 
                        return int.parse(pkexec_uid);
1232
 
                }
1233
 
 
1234
 
                string sudo_user = GLib.Environment.get_variable("SUDO_USER");
1235
 
 
1236
 
                if (sudo_user != null){
1237
 
                        return get_user_id_from_username(sudo_user);
1238
 
                }
1239
 
 
1240
 
                return get_user_id_effective(); // normal user
1241
 
        }
1242
 
 
1243
 
        public string get_username(){
1244
 
 
1245
 
                // returns actual username of current user (even for applications executed with sudo and pkexec)
1246
 
                
1247
 
                return get_username_from_uid(get_user_id());
1248
 
        }
1249
 
 
1250
 
        public int get_user_id_effective(){
1251
 
                
1252
 
                // returns effective user id (0 for applications executed with sudo and pkexec)
1253
 
 
1254
 
                int uid = -1;
1255
 
                string cmd = "id -u";
1256
 
                string std_out, std_err;
1257
 
                exec_sync(cmd, out std_out, out std_err);
1258
 
                if ((std_out != null) && (std_out.length > 0)){
1259
 
                        uid = int.parse(std_out);
1260
 
                }
1261
 
 
1262
 
                return uid;
1263
 
        }
1264
 
 
1265
 
        public int get_user_id_from_username(string username){
1266
 
                
1267
 
                int user_id = -1;
1268
 
 
1269
 
                foreach(var line in file_read("/etc/passwd").split("\n")){
1270
 
                        var arr = line.split(":");
1271
 
                        if (arr.length < 3) { continue; }
1272
 
                        if (arr[0] == username){
1273
 
                                user_id = int.parse(arr[2]);
1274
 
                                break;
1275
 
                        }
1276
 
                }
1277
 
 
1278
 
                return user_id;
1279
 
        }
1280
 
 
1281
 
        public string get_username_from_uid(int user_id){
1282
 
                
1283
 
                string username = "";
1284
 
 
1285
 
                foreach(var line in file_read("/etc/passwd").split("\n")){
1286
 
                        var arr = line.split(":");
1287
 
                        if (arr.length < 3) { continue; }
1288
 
                        if (int.parse(arr[2]) == user_id){
1289
 
                                username = arr[0];
1290
 
                                break;
1291
 
                        }
1292
 
                }
1293
 
 
1294
 
                return username;
1295
 
        }
1296
 
 
1297
 
        public string get_user_home(string username = get_username()){
1298
 
                
1299
 
                string userhome = "";
1300
 
 
1301
 
                foreach(var line in file_read("/etc/passwd").split("\n")){
1302
 
                        var arr = line.split(":");
1303
 
                        if (arr.length < 6) { continue; }
1304
 
                        if (arr[0] == username){
1305
 
                                userhome = arr[5];
1306
 
                                break;
1307
 
                        }
1308
 
                }
1309
 
 
1310
 
                return userhome;
1311
 
        }
1312
 
        
1313
 
        public string get_app_path (){
1314
 
 
1315
 
                /* Get path of current process */
1316
 
 
1317
 
                try{
1318
 
                        return GLib.FileUtils.read_link ("/proc/self/exe");
1319
 
                }
1320
 
                catch (Error e){
1321
 
                log_error (e.message);
1322
 
                return "";
1323
 
            }
1324
 
        }
1325
 
 
1326
 
        public string get_app_dir (){
1327
 
 
1328
 
                /* Get parent directory of current process */
1329
 
 
1330
 
                try{
1331
 
                        return (File.new_for_path (GLib.FileUtils.read_link ("/proc/self/exe"))).get_parent ().get_path ();
1332
 
                }
1333
 
                catch (Error e){
1334
 
                log_error (e.message);
1335
 
                return "";
1336
 
            }
1337
 
        }
1338
 
 
1339
 
}
1340
 
 
1341
 
namespace TeeJee.GtkHelper{
1342
 
 
1343
 
        using Gtk;
1344
 
 
1345
 
        public void gtk_do_events (){
1346
 
 
1347
 
                /* Do pending events */
1348
 
 
1349
 
                while(Gtk.events_pending ())
1350
 
                        Gtk.main_iteration ();
1351
 
        }
1352
 
 
1353
 
        public void gtk_set_busy (bool busy, Gtk.Window win) {
1354
 
 
1355
 
                /* Show or hide busy cursor on window */
1356
 
 
1357
 
                Gdk.Cursor? cursor = null;
1358
 
 
1359
 
                if (busy){
1360
 
                        cursor = new Gdk.Cursor(Gdk.CursorType.WATCH);
1361
 
                }
1362
 
                else{
1363
 
                        cursor = new Gdk.Cursor(Gdk.CursorType.ARROW);
1364
 
                }
1365
 
 
1366
 
                var window = win.get_window ();
1367
 
 
1368
 
                if (window != null) {
1369
 
                        window.set_cursor (cursor);
1370
 
                }
1371
 
 
1372
 
                gtk_do_events ();
1373
 
        }
1374
 
 
1375
 
        public void gtk_messagebox(string title, string message, Gtk.Window? parent_win, bool is_error = false){
1376
 
 
1377
 
                /* Shows a simple message box */
1378
 
 
1379
 
                var type = Gtk.MessageType.INFO;
1380
 
                if (is_error){
1381
 
                        type = Gtk.MessageType.ERROR;
1382
 
                }
1383
 
                else{
1384
 
                        type = Gtk.MessageType.INFO;
1385
 
                }
1386
 
 
1387
 
                /*var dlg = new Gtk.MessageDialog.with_markup(null, Gtk.DialogFlags.MODAL, type, Gtk.ButtonsType.OK, message);
1388
 
                dlg.title = title;
1389
 
                dlg.set_default_size (200, -1);
1390
 
                if (parent_win != null){
1391
 
                        dlg.set_transient_for(parent_win);
1392
 
                        dlg.set_modal(true);
1393
 
                }
1394
 
                dlg.run();
1395
 
                dlg.destroy();*/
1396
 
 
1397
 
                var dlg = new CustomMessageDialog(title,message,type,parent_win, Gtk.ButtonsType.OK);
1398
 
                dlg.run();
1399
 
                dlg.destroy();
1400
 
        }
1401
 
 
1402
 
        public bool gtk_combobox_set_value (ComboBox combo, int index, string val){
1403
 
 
1404
 
                /* Conveniance function to set combobox value */
1405
 
 
1406
 
                TreeIter iter;
1407
 
                string comboVal;
1408
 
                TreeModel model = (TreeModel) combo.model;
1409
 
 
1410
 
                bool iterExists = model.get_iter_first (out iter);
1411
 
                while (iterExists){
1412
 
                        model.get(iter, 1, out comboVal);
1413
 
                        if (comboVal == val){
1414
 
                                combo.set_active_iter(iter);
1415
 
                                return true;
1416
 
                        }
1417
 
                        iterExists = model.iter_next (ref iter);
1418
 
                }
1419
 
 
1420
 
                return false;
1421
 
        }
1422
 
 
1423
 
        public string gtk_combobox_get_value (ComboBox combo, int index, string default_value){
1424
 
 
1425
 
                /* Conveniance function to get combobox value */
1426
 
 
1427
 
                if ((combo.model == null) || (combo.active < 0)) { return default_value; }
1428
 
 
1429
 
                TreeIter iter;
1430
 
                string val = "";
1431
 
                combo.get_active_iter (out iter);
1432
 
                TreeModel model = (TreeModel) combo.model;
1433
 
                model.get(iter, index, out val);
1434
 
 
1435
 
                return val;
1436
 
        }
1437
 
        
1438
 
        public int gtk_combobox_get_value_enum (ComboBox combo, int index, int default_value){
1439
 
 
1440
 
                /* Conveniance function to get combobox value */
1441
 
 
1442
 
                if ((combo.model == null) || (combo.active < 0)) { return default_value; }
1443
 
 
1444
 
                TreeIter iter;
1445
 
                int val;
1446
 
                combo.get_active_iter (out iter);
1447
 
                TreeModel model = (TreeModel) combo.model;
1448
 
                model.get(iter, index, out val);
1449
 
 
1450
 
                return val;
1451
 
        }
1452
 
 
1453
 
        public class CellRendererProgress2 : Gtk.CellRendererProgress{
1454
 
                public override void render (Cairo.Context cr, Gtk.Widget widget, Gdk.Rectangle background_area, Gdk.Rectangle cell_area, Gtk.CellRendererState flags) {
1455
 
                        if (text == "--")
1456
 
                                return;
1457
 
 
1458
 
                        int diff = (int) ((cell_area.height - height)/2);
1459
 
 
1460
 
                        // Apply the new height into the bar, and center vertically:
1461
 
                        Gdk.Rectangle new_area = Gdk.Rectangle() ;
1462
 
                        new_area.x = cell_area.x;
1463
 
                        new_area.y = cell_area.y + diff;
1464
 
                        new_area.width = width - 5;
1465
 
                        new_area.height = height;
1466
 
 
1467
 
                        base.render(cr, widget, background_area, new_area, flags);
1468
 
                }
1469
 
        }
1470
 
 
1471
 
        public Gdk.Pixbuf? get_app_icon(int icon_size, string format = ".png"){
1472
 
                var img_icon = get_shared_icon(AppShortName, AppShortName + format,icon_size,"pixmaps");
1473
 
                if (img_icon != null){
1474
 
                        return img_icon.pixbuf;
1475
 
                }
1476
 
                else{
1477
 
                        return null;
1478
 
                }
1479
 
        }
1480
 
 
1481
 
        public Gtk.Image? get_shared_icon(string icon_name, string fallback_icon_file_name, int icon_size, string icon_directory = AppShortName + "/images"){
1482
 
                Gdk.Pixbuf pix_icon = null;
1483
 
                Gtk.Image img_icon = null;
1484
 
 
1485
 
                try {
1486
 
                        Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default();
1487
 
                        pix_icon = icon_theme.load_icon (icon_name, icon_size, 0);
1488
 
                } catch (Error e) {
1489
 
                        //log_error (e.message);
1490
 
                }
1491
 
 
1492
 
                string fallback_icon_file_path = "/usr/share/%s/%s".printf(icon_directory, fallback_icon_file_name);
1493
 
 
1494
 
                if (pix_icon == null){
1495
 
                        try {
1496
 
                                pix_icon = new Gdk.Pixbuf.from_file_at_size (fallback_icon_file_path, icon_size, icon_size);
1497
 
                        } catch (Error e) {
1498
 
                                log_error (e.message);
1499
 
                        }
1500
 
                }
1501
 
 
1502
 
                if (pix_icon == null){
1503
 
                        log_error (_("Missing Icon") + ": '%s', '%s'".printf(icon_name, fallback_icon_file_path));
1504
 
                }
1505
 
                else{
1506
 
                        img_icon = new Gtk.Image.from_pixbuf(pix_icon);
1507
 
                }
1508
 
 
1509
 
                return img_icon;
1510
 
        }
1511
 
 
1512
 
        public int gtk_treeview_model_count(TreeModel model){
1513
 
                int count = 0;
1514
 
                TreeIter iter;
1515
 
                if (model.get_iter_first(out iter)){
1516
 
                        count++;
1517
 
                        while(model.iter_next(ref iter)){
1518
 
                                count++;
1519
 
                        }
1520
 
                }
1521
 
                return count;
1522
 
        }
1523
 
}
1524
 
 
1525
 
namespace TeeJee.Multimedia{
1526
 
 
1527
 
        using TeeJee.Logging;
1528
 
 
1529
 
        /* Functions for working with audio/video files */
1530
 
 
1531
 
        public long get_file_duration(string filePath){
1532
 
 
1533
 
                /* Returns the duration of an audio/video file using MediaInfo */
1534
 
 
1535
 
                string output = "0";
1536
 
 
1537
 
                try {
1538
 
                        Process.spawn_command_line_sync("mediainfo \"--Inform=General;%Duration%\" \"" + filePath + "\"", out output);
1539
 
                }
1540
 
                catch(Error e){
1541
 
                log_error (e.message);
1542
 
            }
1543
 
 
1544
 
                return long.parse(output);
1545
 
        }
1546
 
 
1547
 
        public string get_file_crop_params (string filePath){
1548
 
 
1549
 
                /* Returns cropping parameters for a video file using avconv */
1550
 
 
1551
 
                string output = "";
1552
 
                string error = "";
1553
 
 
1554
 
                try {
1555
 
                        Process.spawn_command_line_sync("avconv -i \"%s\" -vf cropdetect=30 -ss 5 -t 5 -f matroska -an -y /dev/null".printf(filePath), out output, out error);
1556
 
                }
1557
 
                catch(Error e){
1558
 
                log_error (e.message);
1559
 
            }
1560
 
 
1561
 
            int w=0,h=0,x=10000,y=10000;
1562
 
                int num=0;
1563
 
                string key,val;
1564
 
            string[] arr;
1565
 
 
1566
 
            foreach (string line in error.split ("\n")){
1567
 
                        if (line == null) { continue; }
1568
 
                        if (line.index_of ("crop=") == -1) { continue; }
1569
 
 
1570
 
                        foreach (string part in line.split (" ")){
1571
 
                                if (part == null || part.length == 0) { continue; }
1572
 
 
1573
 
                                arr = part.split (":");
1574
 
                                if (arr.length != 2) { continue; }
1575
 
 
1576
 
                                key = arr[0].strip ();
1577
 
                                val = arr[1].strip ();
1578
 
 
1579
 
                                switch (key){
1580
 
                                        case "x":
1581
 
                                                num = int.parse (arr[1]);
1582
 
                                                if (num < x) { x = num; }
1583
 
                                                break;
1584
 
                                        case "y":
1585
 
                                                num = int.parse (arr[1]);
1586
 
                                                if (num < y) { y = num; }
1587
 
                                                break;
1588
 
                                        case "w":
1589
 
                                                num = int.parse (arr[1]);
1590
 
                                                if (num > w) { w = num; }
1591
 
                                                break;
1592
 
                                        case "h":
1593
 
                                                num = int.parse (arr[1]);
1594
 
                                                if (num > h) { h = num; }
1595
 
                                                break;
1596
 
                                }
1597
 
                        }
1598
 
                }
1599
 
 
1600
 
                if (x == 10000 || y == 10000)
1601
 
                        return "%i:%i:%i:%i".printf(0,0,0,0);
1602
 
                else
1603
 
                        return "%i:%i:%i:%i".printf(w,h,x,y);
1604
 
        }
1605
 
 
1606
 
        public string get_mediainfo (string filePath){
1607
 
 
1608
 
                /* Returns the multimedia properties of an audio/video file using MediaInfo */
1609
 
 
1610
 
                string output = "";
1611
 
 
1612
 
                try {
1613
 
                        Process.spawn_command_line_sync("mediainfo \"%s\"".printf(filePath), out output);
1614
 
                }
1615
 
                catch(Error e){
1616
 
                log_error (e.message);
1617
 
            }
1618
 
 
1619
 
                return output;
1620
 
        }
1621
 
 
1622
 
 
1623
 
 
1624
 
}
1625
 
 
1626
 
namespace TeeJee.System{
1627
 
 
1628
 
        using TeeJee.ProcessManagement;
1629
 
        using TeeJee.Logging;
1630
 
 
1631
 
        public double get_system_uptime_seconds(){
1632
 
 
1633
 
                /* Returns the system up-time in seconds */
1634
 
 
1635
 
                string cmd = "";
1636
 
                string std_out;
1637
 
                string std_err;
1638
 
                int ret_val;
1639
 
 
1640
 
                try{
1641
 
                        cmd = "cat /proc/uptime";
1642
 
                        Process.spawn_command_line_sync(cmd, out std_out, out std_err, out ret_val);
1643
 
                        string uptime = std_out.split(" ")[0];
1644
 
                        double secs = double.parse(uptime);
1645
 
                        return secs;
1646
 
                }
1647
 
                catch(Error e){
1648
 
                        log_error (e.message);
1649
 
                        return 0;
1650
 
                }
1651
 
        }
1652
 
 
1653
 
        public string get_desktop_name(){
1654
 
 
1655
 
                /* Return the names of the current Desktop environment */
1656
 
 
1657
 
                int pid = -1;
1658
 
 
1659
 
                pid = get_pid_by_name("cinnamon");
1660
 
                if (pid > 0){
1661
 
                        return "Cinnamon";
1662
 
                }
1663
 
 
1664
 
                pid = get_pid_by_name("xfdesktop");
1665
 
                if (pid > 0){
1666
 
                        return "Xfce";
1667
 
                }
1668
 
 
1669
 
                pid = get_pid_by_name("lxsession");
1670
 
                if (pid > 0){
1671
 
                        return "LXDE";
1672
 
                }
1673
 
 
1674
 
                pid = get_pid_by_name("gnome-shell");
1675
 
                if (pid > 0){
1676
 
                        return "Gnome";
1677
 
                }
1678
 
 
1679
 
                pid = get_pid_by_name("wingpanel");
1680
 
                if (pid > 0){
1681
 
                        return "Elementary";
1682
 
                }
1683
 
 
1684
 
                pid = get_pid_by_name("unity-panel-service");
1685
 
                if (pid > 0){
1686
 
                        return "Unity";
1687
 
                }
1688
 
 
1689
 
                pid = get_pid_by_name("plasma-desktop");
1690
 
                if (pid > 0){
1691
 
                        return "KDE";
1692
 
                }
1693
 
 
1694
 
                return "Unknown";
1695
 
        }
1696
 
 
1697
 
        public Gee.ArrayList<string> list_dir_names(string path){
1698
 
                var list = new Gee.ArrayList<string>();
1699
 
                
1700
 
                try
1701
 
                {
1702
 
                        File f_home = File.new_for_path (path);
1703
 
                        FileEnumerator enumerator = f_home.enumerate_children ("%s".printf(FileAttribute.STANDARD_NAME), 0);
1704
 
                        FileInfo file;
1705
 
                        while ((file = enumerator.next_file ()) != null) {
1706
 
                                string name = file.get_name();
1707
 
                                //string item = path + "/" + name;
1708
 
                                list.add(name);
1709
 
                        }
1710
 
                }
1711
 
                catch (Error e) {
1712
 
                        log_error (e.message);
1713
 
                }
1714
 
 
1715
 
                //sort the list
1716
 
                CompareDataFunc<string> entry_compare = (a, b) => {
1717
 
                        return strcmp(a,b);
1718
 
                };
1719
 
                list.sort((owned) entry_compare);
1720
 
 
1721
 
                return list;
1722
 
        }
1723
 
        
1724
 
        public bool check_internet_connectivity(){
1725
 
                bool connected = false;
1726
 
                connected = check_internet_connectivity_test1();
1727
 
 
1728
 
                if (connected){
1729
 
                        return connected;
1730
 
                }
1731
 
                
1732
 
                if (!connected){
1733
 
                        connected = check_internet_connectivity_test2();
1734
 
                }
1735
 
 
1736
 
            return connected;
1737
 
        }
1738
 
 
1739
 
        public bool check_internet_connectivity_test1(){
1740
 
                int exit_code = -1;
1741
 
                string std_err;
1742
 
                string std_out;
1743
 
 
1744
 
                string cmd = "ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3`\n";
1745
 
                cmd += "exit $?";
1746
 
                exit_code = exec_script_sync(cmd, out std_out, out std_err, false);
1747
 
 
1748
 
            return (exit_code == 0);
1749
 
        }
1750
 
 
1751
 
        public bool check_internet_connectivity_test2(){
1752
 
                int exit_code = -1;
1753
 
                string std_err;
1754
 
                string std_out;
1755
 
 
1756
 
                string cmd = "ping -q -w 1 -c 1 google.com\n";
1757
 
                cmd += "exit $?";
1758
 
                exit_code = exec_script_sync(cmd, out std_out, out std_err, false);
1759
 
 
1760
 
            return (exit_code == 0);
1761
 
        }
1762
 
        
1763
 
        
1764
 
        public bool shutdown (){
1765
 
 
1766
 
                /* Shutdown the system immediately */
1767
 
 
1768
 
                try{
1769
 
                        string[] argv = { "shutdown", "-h", "now" };
1770
 
                        Pid procId;
1771
 
                        Process.spawn_async(null, argv, null, SpawnFlags.SEARCH_PATH, null, out procId);
1772
 
                        return true;
1773
 
                }
1774
 
                catch (Error e) {
1775
 
                        log_error (e.message);
1776
 
                        return false;
1777
 
                }
1778
 
        }
1779
 
 
1780
 
        public bool xdg_open (string file, string user = ""){
1781
 
                string path = get_cmd_path ("xdg-open");
1782
 
                if ((path != null) && (path != "")){
1783
 
                        string cmd = "xdg-open '%s'".printf(escape_single_quote(file));
1784
 
                        if (user.length > 0){
1785
 
                                cmd = "pkexec --user %s env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY ".printf(user) + cmd;
1786
 
                        }
1787
 
                        int status = exec_script_async(cmd);
1788
 
                        return (status == 0);
1789
 
                }
1790
 
                return false;
1791
 
        }
1792
 
 
1793
 
        public bool exo_open_folder (string dir_path, bool xdg_open_try_first = true){
1794
 
 
1795
 
                /* Tries to open the given directory in a file manager */
1796
 
 
1797
 
                /*
1798
 
                xdg-open is a desktop-independent tool for configuring the default applications of a user.
1799
 
                Inside a desktop environment (e.g. GNOME, KDE, Xfce), xdg-open simply passes the arguments
1800
 
                to that desktop environment's file-opener application (gvfs-open, kde-open, exo-open, respectively).
1801
 
                We will first try using xdg-open and then check for specific file managers if it fails.
1802
 
                */
1803
 
 
1804
 
                string path;
1805
 
 
1806
 
                if (xdg_open_try_first){
1807
 
                        //try using xdg-open
1808
 
                        path = get_cmd_path ("xdg-open");
1809
 
                        if ((path != null)&&(path != "")){
1810
 
                                return execute_command_script_async ("xdg-open \"" + dir_path + "\"");
1811
 
                        }
1812
 
                }
1813
 
 
1814
 
                path = get_cmd_path ("nemo");
1815
 
                if ((path != null)&&(path != "")){
1816
 
                        return execute_command_script_async ("nemo \"" + dir_path + "\"");
1817
 
                }
1818
 
 
1819
 
                path = get_cmd_path ("nautilus");
1820
 
                if ((path != null)&&(path != "")){
1821
 
                        return execute_command_script_async ("nautilus \"" + dir_path + "\"");
1822
 
                }
1823
 
 
1824
 
                path = get_cmd_path ("thunar");
1825
 
                if ((path != null)&&(path != "")){
1826
 
                        return execute_command_script_async ("thunar \"" + dir_path + "\"");
1827
 
                }
1828
 
 
1829
 
                path = get_cmd_path ("pantheon-files");
1830
 
                if ((path != null)&&(path != "")){
1831
 
                        return execute_command_script_async ("pantheon-files \"" + dir_path + "\"");
1832
 
                }
1833
 
 
1834
 
                path = get_cmd_path ("marlin");
1835
 
                if ((path != null)&&(path != "")){
1836
 
                        return execute_command_script_async ("marlin \"" + dir_path + "\"");
1837
 
                }
1838
 
 
1839
 
                if (xdg_open_try_first == false){
1840
 
                        //try using xdg-open
1841
 
                        path = get_cmd_path ("xdg-open");
1842
 
                        if ((path != null)&&(path != "")){
1843
 
                                return execute_command_script_async ("xdg-open \"" + dir_path + "\"");
1844
 
                        }
1845
 
                }
1846
 
 
1847
 
                return false;
1848
 
        }
1849
 
 
1850
 
        public bool exo_open_textfile (string txt){
1851
 
 
1852
 
                /* Tries to open the given text file in a text editor */
1853
 
 
1854
 
                string path;
1855
 
 
1856
 
                path = get_cmd_path ("exo-open");
1857
 
                if ((path != null)&&(path != "")){
1858
 
                        return execute_command_script_async ("exo-open \"" + txt + "\"");
1859
 
                }
1860
 
 
1861
 
                path = get_cmd_path ("gedit");
1862
 
                if ((path != null)&&(path != "")){
1863
 
                        return execute_command_script_async ("gedit --new-document \"" + txt + "\"");
1864
 
                }
1865
 
 
1866
 
                return false;
1867
 
        }
1868
 
 
1869
 
        public bool exo_open_url (string url){
1870
 
 
1871
 
                /* Tries to open the given text file in a text editor */
1872
 
 
1873
 
                string path;
1874
 
 
1875
 
                path = get_cmd_path ("exo-open");
1876
 
                if ((path != null)&&(path != "")){
1877
 
                        return execute_command_script_async ("exo-open \"" + url + "\"");
1878
 
                }
1879
 
 
1880
 
                path = get_cmd_path ("firefox");
1881
 
                if ((path != null)&&(path != "")){
1882
 
                        return execute_command_script_async ("firefox \"" + url + "\"");
1883
 
                }
1884
 
 
1885
 
                path = get_cmd_path ("chromium-browser");
1886
 
                if ((path != null)&&(path != "")){
1887
 
                        return execute_command_script_async ("chromium-browser \"" + url + "\"");
1888
 
                }
1889
 
 
1890
 
                return false;
1891
 
        }
1892
 
 
1893
 
        public GLib.Timer timer_start(){
1894
 
                var timer = new GLib.Timer();
1895
 
                timer.start();
1896
 
                return timer;
1897
 
        }
1898
 
 
1899
 
        public ulong timer_elapsed(GLib.Timer timer){
1900
 
                ulong microseconds;
1901
 
                double seconds;
1902
 
                seconds = timer.elapsed (out microseconds);
1903
 
                return microseconds;
1904
 
        }
1905
 
 
1906
 
        public void sleep(int milliseconds){
1907
 
                Thread.usleep ((ulong) milliseconds * 1000);
1908
 
        }
1909
 
 
1910
 
        public string timer_elapsed_string(GLib.Timer timer, bool stop = true){
1911
 
                ulong microseconds;
1912
 
                double seconds;
1913
 
                seconds = timer.elapsed (out microseconds);
1914
 
                if (stop){
1915
 
                        timer.stop();
1916
 
                }
1917
 
                return "%.0f ms".printf((seconds * 1000 ) + microseconds/1000);
1918
 
        }
1919
 
 
1920
 
        public void timer_elapsed_print(GLib.Timer timer, bool stop = true){
1921
 
                ulong microseconds;
1922
 
                double seconds;
1923
 
                seconds = timer.elapsed (out microseconds);
1924
 
                if (stop){
1925
 
                        timer.stop();
1926
 
                }
1927
 
                log_msg("%s %lu\n".printf(seconds.to_string(), microseconds));
1928
 
        }
1929
 
 
1930
 
        public string[] array_concat(string[] a, string[] b){
1931
 
                string[] c = {};
1932
 
                foreach(string str in a){ c += str; }
1933
 
                foreach(string str in b){ c += str; }
1934
 
                return c;
1935
 
        }
1936
 
        
1937
 
        private DateTime dt_last_notification = null;
1938
 
        private const int NOTIFICATION_INTERVAL = 3;
1939
 
 
1940
 
        public int notify_send (string title, string message, int durationMillis, string urgency, string dialog_type = "info"){
1941
 
 
1942
 
                /* Displays notification bubble on the desktop */
1943
 
 
1944
 
                int retVal = 0;
1945
 
 
1946
 
                switch (dialog_type){
1947
 
                        case "error":
1948
 
                        case "info":
1949
 
                        case "warning":
1950
 
                                //ok
1951
 
                                break;
1952
 
                        default:
1953
 
                                dialog_type = "info";
1954
 
                                break;
1955
 
                }
1956
 
 
1957
 
                long seconds = 9999;
1958
 
                if (dt_last_notification != null){
1959
 
                        DateTime dt_end = new DateTime.now_local();
1960
 
                        TimeSpan elapsed = dt_end.difference(dt_last_notification);
1961
 
                        seconds = (long)(elapsed * 1.0 / TimeSpan.SECOND);
1962
 
                }
1963
 
 
1964
 
                if (seconds > NOTIFICATION_INTERVAL){
1965
 
                        string s = "notify-send -t %d -u %s -i %s \"%s\" \"%s\"".printf(durationMillis, urgency, "gtk-dialog-" + dialog_type, title, message);
1966
 
                        retVal = exec_sync (s);
1967
 
                        dt_last_notification = new DateTime.now_local();
1968
 
                }
1969
 
 
1970
 
                return retVal;
1971
 
        }
1972
 
 
1973
 
        public bool set_directory_ownership(string dir_name, string login_name){
1974
 
                try {
1975
 
                        string cmd = "chown %s:%s -R '%s'".printf(login_name, login_name, dir_name);
1976
 
                        int exit_code;
1977
 
                        Process.spawn_command_line_sync(cmd, null, null, out exit_code);
1978
 
 
1979
 
                        if (exit_code == 0){
1980
 
                                log_debug(_("Set owner: %s, dir: %s").printf(login_name, dir_name));
1981
 
                                return true;
1982
 
                        }
1983
 
                        else{
1984
 
                                log_error(_("Failed to set ownership") + ": %s, '%s'".printf(login_name, dir_name));
1985
 
                                return false;
1986
 
                        }
1987
 
                }
1988
 
                catch (Error e){
1989
 
                        log_error (e.message);
1990
 
                        return false;
1991
 
                }
1992
 
        }
1993
 
 
1994
 
        public string random_string(int length = 8, string charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"){
1995
 
                string random = "";
1996
 
 
1997
 
                for(int i=0;i<length;i++){
1998
 
                        int random_index = Random.int_range(0,charset.length);
1999
 
                        string ch = charset.get_char(charset.index_of_nth_char(random_index)).to_string();
2000
 
                        random += ch;
2001
 
                }
2002
 
 
2003
 
                return random;
2004
 
        }
2005
 
        
2006
 
        public class ProcStats{
2007
 
                public double user = 0;
2008
 
                public double nice = 0;
2009
 
                public double system = 0;
2010
 
                public double idle = 0;
2011
 
                public double iowait = 0;
2012
 
 
2013
 
                public double user_delta = 0;
2014
 
                public double nice_delta = 0;
2015
 
                public double system_delta = 0;
2016
 
                public double idle_delta = 0;
2017
 
                public double iowait_delta = 0;
2018
 
 
2019
 
                public double usage_percent = 0;
2020
 
 
2021
 
                public static ProcStats stat_prev = null;
2022
 
 
2023
 
                public ProcStats(string line){
2024
 
                        string[] arr = line.split(" ");
2025
 
                        int col = 0;
2026
 
                        if (arr[col++] == "cpu"){
2027
 
                                if (arr[col].length == 0){ col++; };
2028
 
 
2029
 
                                user = double.parse(arr[col++]);
2030
 
                                nice = double.parse(arr[col++]);
2031
 
                                system = double.parse(arr[col++]);
2032
 
                                idle = double.parse(arr[col++]);
2033
 
                                iowait = double.parse(arr[col++]);
2034
 
 
2035
 
                                if (ProcStats.stat_prev != null){
2036
 
                                        user_delta = user - ProcStats.stat_prev.user;
2037
 
                                        nice_delta = nice - ProcStats.stat_prev.nice;
2038
 
                                        system_delta = system - ProcStats.stat_prev.system;
2039
 
                                        idle_delta = idle - ProcStats.stat_prev.idle;
2040
 
                                        iowait_delta = iowait - ProcStats.stat_prev.iowait;
2041
 
 
2042
 
                                        usage_percent = (user_delta + nice_delta + system_delta) * 100 / (user_delta + nice_delta + system_delta + idle_delta);
2043
 
                                }
2044
 
                                else{
2045
 
                                        usage_percent = 0;
2046
 
 
2047
 
                                }
2048
 
 
2049
 
                                ProcStats.stat_prev = this;
2050
 
                        }
2051
 
                }
2052
 
                
2053
 
                //returns 0 when it is called first time
2054
 
                public static double get_cpu_usage(){
2055
 
                        string txt = file_read("/proc/stat");
2056
 
                        foreach(string line in txt.split("\n")){
2057
 
                                string[] arr = line.split(" ");
2058
 
                                if (arr[0] == "cpu"){
2059
 
                                        ProcStats stat = new ProcStats(line);
2060
 
                                        return stat.usage_percent;
2061
 
                                }
2062
 
                        }
2063
 
                        return 0;
2064
 
                }
2065
 
        }
2066
 
 
2067
 
        public class SystemGroup : GLib.Object {
2068
 
                public string name = "";
2069
 
                public string password = "";
2070
 
                public int gid = -1;
2071
 
                public string user_names = "";
2072
 
 
2073
 
                public string shadow_line = "";
2074
 
                public string password_hash = "";
2075
 
                public string admin_list = "";
2076
 
                public string member_list = "";
2077
 
 
2078
 
                public bool is_selected = false;
2079
 
                public Gee.ArrayList<string> users;
2080
 
                
2081
 
                public static Gee.HashMap<string,SystemGroup> all_groups;
2082
 
 
2083
 
                public SystemGroup(string name){
2084
 
                        this.name = name;
2085
 
                        this.users = new Gee.ArrayList<string>();
2086
 
                }
2087
 
 
2088
 
                public static void query_groups(){
2089
 
                        all_groups = read_groups_from_file("/etc/group","/etc/gshadow", "");
2090
 
                }
2091
 
 
2092
 
                public bool is_installed{
2093
 
                        get{
2094
 
                                return SystemGroup.all_groups.has_key(name);
2095
 
                        }
2096
 
                }
2097
 
 
2098
 
                public static Gee.HashMap<string,SystemGroup> read_groups_from_file(string group_file, string gshadow_file, string password){
2099
 
                        var list = new Gee.HashMap<string,SystemGroup>();
2100
 
 
2101
 
                        // read 'group' file -------------------------------
2102
 
                        
2103
 
                        string txt = "";
2104
 
                        
2105
 
                        if (group_file.has_suffix(".tar.gpg")){
2106
 
                                txt = file_decrypt_untar_read(group_file, password);
2107
 
                        }
2108
 
                        else{
2109
 
                                txt = file_read(group_file);
2110
 
                        }
2111
 
                        
2112
 
                        if (txt.length == 0){
2113
 
                                return list;
2114
 
                        }
2115
 
                        
2116
 
                        foreach(string line in txt.split("\n")){
2117
 
                                if ((line == null) || (line.length == 0)){
2118
 
                                        continue;
2119
 
                                }
2120
 
                                
2121
 
                                var group = parse_line_group(line);
2122
 
                                if (group != null){
2123
 
                                        list[group.name] = group;
2124
 
                                }
2125
 
                        }
2126
 
 
2127
 
                        // read 'gshadow' file -------------------------------
2128
 
 
2129
 
                        txt = "";
2130
 
                        
2131
 
                        if (gshadow_file.has_suffix(".tar.gpg")){
2132
 
                                txt = file_decrypt_untar_read(gshadow_file, password);
2133
 
                        }
2134
 
                        else{
2135
 
                                txt = file_read(gshadow_file);
2136
 
                        }
2137
 
                        
2138
 
                        if (txt.length == 0){
2139
 
                                return list;
2140
 
                        }
2141
 
                        
2142
 
                        foreach(string line in txt.split("\n")){
2143
 
                                if ((line == null) || (line.length == 0)){
2144
 
                                        continue;
2145
 
                                }
2146
 
                                
2147
 
                                parse_line_gshadow(line, list);
2148
 
                        }
2149
 
 
2150
 
                        return list;
2151
 
                }
2152
 
 
2153
 
                private static SystemGroup? parse_line_group(string line){
2154
 
                        if ((line == null) || (line.length == 0)){
2155
 
                                return null;
2156
 
                        }
2157
 
                        
2158
 
                        SystemGroup group = null;
2159
 
 
2160
 
                        //cdrom:x:24:teejee,user2
2161
 
                        string[] fields = line.split(":");
2162
 
 
2163
 
                        if (fields.length == 4){
2164
 
                                group = new SystemGroup(fields[0].strip());
2165
 
                                group.password = fields[1].strip();
2166
 
                                group.gid = int.parse(fields[2].strip());
2167
 
                                group.user_names = fields[3].strip();
2168
 
                                foreach(string user_name in group.user_names.split(",")){
2169
 
                                        group.users.add(user_name);
2170
 
                                }
2171
 
                        }
2172
 
                        else{
2173
 
                                log_error("'group' file contains a record with non-standard fields" + ": %d".printf(fields.length));
2174
 
                                return null;
2175
 
                        }
2176
 
                        
2177
 
                        return group;
2178
 
                }
2179
 
 
2180
 
                private static SystemGroup? parse_line_gshadow(string line, Gee.HashMap<string,SystemGroup> list){
2181
 
                        if ((line == null) || (line.length == 0)){
2182
 
                                return null;
2183
 
                        }
2184
 
                        
2185
 
                        SystemGroup group = null;
2186
 
 
2187
 
                        //adm:*::syslog,teejee
2188
 
                        //<groupname>:<encrypted-password>:<admins>:<members>
2189
 
                        string[] fields = line.split(":");
2190
 
 
2191
 
                        if (fields.length == 4){
2192
 
                                string group_name = fields[0].strip();
2193
 
                                if (list.has_key(group_name)){
2194
 
                                        group = list[group_name];
2195
 
                                        group.shadow_line = line;
2196
 
                                        group.password_hash = fields[1].strip();
2197
 
                                        group.admin_list = fields[2].strip();
2198
 
                                        group.member_list = fields[3].strip();
2199
 
                                        return group;
2200
 
                                }
2201
 
                                else{
2202
 
                                        log_error("group in file 'gshadow' does not exist in file 'group'" + ": %s".printf(group_name));
2203
 
                                        return null;
2204
 
                                }
2205
 
                        }
2206
 
                        else{
2207
 
                                log_error("'gshadow' file contains a record with non-standard fields" + ": %d".printf(fields.length));
2208
 
                                return null;
2209
 
                        }
2210
 
                }
2211
 
 
2212
 
                public static int add_group(string group_name, bool system_account = false){
2213
 
                        string std_out, std_err;
2214
 
                        string cmd = "groupadd%s %s".printf((system_account)? " --system" : "", group_name);
2215
 
                        int status = exec_sync(cmd, out std_out, out std_err);
2216
 
                        if (status != 0){
2217
 
                                log_error(std_err);
2218
 
                        }
2219
 
                        else{
2220
 
                                //log_msg(std_out);
2221
 
                        }
2222
 
                        return status;
2223
 
                }
2224
 
 
2225
 
                public int add(){
2226
 
                        return add_group(name,is_system);
2227
 
                }
2228
 
 
2229
 
                public static int add_user_to_group(string user_name, string group_name){
2230
 
                        string std_out, std_err;
2231
 
                        string cmd = "adduser %s %s".printf(user_name, group_name);
2232
 
                        log_debug(cmd);
2233
 
                        int status = exec_sync(cmd, out std_out, out std_err);
2234
 
                        if (status != 0){
2235
 
                                log_error(std_err);
2236
 
                        }
2237
 
                        else{
2238
 
                                //log_msg(std_out);
2239
 
                        }
2240
 
                        return status;
2241
 
                }
2242
 
 
2243
 
                public int add_to_group(string user_name){
2244
 
                        return add_user_to_group(user_name, name);
2245
 
                }
2246
 
                
2247
 
                public bool is_system{
2248
 
                        get {
2249
 
                                return (gid < 1000);
2250
 
                        }
2251
 
                }
2252
 
 
2253
 
                public bool update_group_file(){
2254
 
                        string file_path = "/etc/group";
2255
 
                        string txt = file_read(file_path);
2256
 
                        
2257
 
                        var txt_new = "";
2258
 
                        foreach(string line in txt.split("\n")){
2259
 
                                if (line.strip().length == 0) {
2260
 
                                        continue;
2261
 
                                }
2262
 
 
2263
 
                                string[] parts = line.split(":");
2264
 
                                
2265
 
                                if (parts.length != 4){
2266
 
                                        log_error("'group' file contains a record with non-standard fields" + ": %d".printf(parts.length));
2267
 
                                        return false;
2268
 
                                }
2269
 
 
2270
 
                                if (parts[0].strip() == name){
2271
 
                                        txt_new += get_group_line() + "\n";
2272
 
                                }
2273
 
                                else{
2274
 
                                        txt_new += line + "\n";
2275
 
                                }
2276
 
                        }
2277
 
 
2278
 
                        file_write(file_path, txt_new);
2279
 
                        
2280
 
                        log_msg("Updated group settings in /etc/group" + ": %s".printf(name));
2281
 
                        
2282
 
                        return true;
2283
 
                }
2284
 
 
2285
 
                public string get_group_line(){
2286
 
                        string txt = "";
2287
 
                        txt += "%s".printf(name);
2288
 
                        txt += ":%s".printf(password);
2289
 
                        txt += ":%d".printf(gid);
2290
 
                        txt += ":%s".printf(user_names);
2291
 
                        return txt;
2292
 
                }
2293
 
        
2294
 
                public bool update_gshadow_file(){
2295
 
                        string file_path = "/etc/gshadow";
2296
 
                        string txt = file_read(file_path);
2297
 
                        
2298
 
                        var txt_new = "";
2299
 
                        foreach(string line in txt.split("\n")){
2300
 
                                if (line.strip().length == 0) {
2301
 
                                        continue;
2302
 
                                }
2303
 
 
2304
 
                                string[] parts = line.split(":");
2305
 
                                
2306
 
                                if (parts.length != 4){
2307
 
                                        log_error("'gshadow' file contains a record with non-standard fields" + ": %d".printf(parts.length));
2308
 
                                        return false;
2309
 
                                }
2310
 
 
2311
 
                                if (parts[0].strip() == name){
2312
 
                                        txt_new += get_gshadow_line() + "\n";
2313
 
                                }
2314
 
                                else{
2315
 
                                        txt_new += line + "\n";
2316
 
                                }
2317
 
                        }
2318
 
 
2319
 
                        file_write(file_path, txt_new);
2320
 
                        
2321
 
                        log_msg("Updated group settings in /etc/gshadow" + ": %s".printf(name));
2322
 
                        
2323
 
                        return true;
2324
 
                }
2325
 
 
2326
 
                public string get_gshadow_line(){
2327
 
                        string txt = "";
2328
 
                        txt += "%s".printf(name);
2329
 
                        txt += ":%s".printf(password_hash);
2330
 
                        txt += ":%s".printf(admin_list);
2331
 
                        txt += ":%s".printf(member_list);
2332
 
                        return txt;
2333
 
                }
2334
 
        }
2335
 
}
2336
 
 
2337
 
namespace TeeJee.Misc {
2338
 
 
2339
 
        /* Various utility functions */
2340
 
 
2341
 
        using Gtk;
2342
 
        using TeeJee.Logging;
2343
 
        using TeeJee.FileSystem;
2344
 
        using TeeJee.ProcessManagement;
2345
 
 
2346
 
        public class DistInfo : GLib.Object{
2347
 
 
2348
 
                /* Class for storing information about linux distribution */
2349
 
 
2350
 
                public string dist_id = "";
2351
 
                public string description = "";
2352
 
                public string release = "";
2353
 
                public string codename = "";
2354
 
 
2355
 
                public DistInfo(){
2356
 
                        dist_id = "";
2357
 
                        description = "";
2358
 
                        release = "";
2359
 
                        codename = "";
2360
 
                }
2361
 
 
2362
 
                public string full_name(){
2363
 
                        if (dist_id == ""){
2364
 
                                return "";
2365
 
                        }
2366
 
                        else{
2367
 
                                string val = "";
2368
 
                                val += dist_id;
2369
 
                                val += (release.length > 0) ? " " + release : "";
2370
 
                                val += (codename.length > 0) ? " (" + codename + ")" : "";
2371
 
                                return val;
2372
 
                        }
2373
 
                }
2374
 
 
2375
 
                public static DistInfo get_dist_info(string root_path){
2376
 
 
2377
 
                        /* Returns information about the Linux distribution
2378
 
                         * installed at the given root path */
2379
 
 
2380
 
                        DistInfo info = new DistInfo();
2381
 
 
2382
 
                        string dist_file = root_path + "/etc/lsb-release";
2383
 
                        var f = File.new_for_path(dist_file);
2384
 
                        if (f.query_exists()){
2385
 
 
2386
 
                                /*
2387
 
                                        DISTRIB_ID=Ubuntu
2388
 
                                        DISTRIB_RELEASE=13.04
2389
 
                                        DISTRIB_CODENAME=raring
2390
 
                                        DISTRIB_DESCRIPTION="Ubuntu 13.04"
2391
 
                                */
2392
 
 
2393
 
                                foreach(string line in file_read(dist_file).split("\n")){
2394
 
 
2395
 
                                        if (line.split("=").length != 2){ continue; }
2396
 
 
2397
 
                                        string key = line.split("=")[0].strip();
2398
 
                                        string val = line.split("=")[1].strip();
2399
 
 
2400
 
                                        if (val.has_prefix("\"")){
2401
 
                                                val = val[1:val.length];
2402
 
                                        }
2403
 
 
2404
 
                                        if (val.has_suffix("\"")){
2405
 
                                                val = val[0:val.length-1];
2406
 
                                        }
2407
 
 
2408
 
                                        switch (key){
2409
 
                                                case "DISTRIB_ID":
2410
 
                                                        info.dist_id = val;
2411
 
                                                        break;
2412
 
                                                case "DISTRIB_RELEASE":
2413
 
                                                        info.release = val;
2414
 
                                                        break;
2415
 
                                                case "DISTRIB_CODENAME":
2416
 
                                                        info.codename = val;
2417
 
                                                        break;
2418
 
                                                case "DISTRIB_DESCRIPTION":
2419
 
                                                        info.description = val;
2420
 
                                                        break;
2421
 
                                        }
2422
 
                                }
2423
 
                        }
2424
 
                        else{
2425
 
 
2426
 
                                dist_file = root_path + "/etc/os-release";
2427
 
                                f = File.new_for_path(dist_file);
2428
 
                                if (f.query_exists()){
2429
 
 
2430
 
                                        /*
2431
 
                                                NAME="Ubuntu"
2432
 
                                                VERSION="13.04, Raring Ringtail"
2433
 
                                                ID=ubuntu
2434
 
                                                ID_LIKE=debian
2435
 
                                                PRETTY_NAME="Ubuntu 13.04"
2436
 
                                                VERSION_ID="13.04"
2437
 
                                                HOME_URL="http://www.ubuntu.com/"
2438
 
                                                SUPPORT_URL="http://help.ubuntu.com/"
2439
 
                                                BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
2440
 
                                        */
2441
 
 
2442
 
                                        foreach(string line in file_read(dist_file).split("\n")){
2443
 
 
2444
 
                                                if (line.split("=").length != 2){ continue; }
2445
 
 
2446
 
                                                string key = line.split("=")[0].strip();
2447
 
                                                string val = line.split("=")[1].strip();
2448
 
 
2449
 
                                                switch (key){
2450
 
                                                        case "ID":
2451
 
                                                                info.dist_id = val;
2452
 
                                                                break;
2453
 
                                                        case "VERSION_ID":
2454
 
                                                                info.release = val;
2455
 
                                                                break;
2456
 
                                                        //case "DISTRIB_CODENAME":
2457
 
                                                                //info.codename = val;
2458
 
                                                                //break;
2459
 
                                                        case "PRETTY_NAME":
2460
 
                                                                info.description = val;
2461
 
                                                                break;
2462
 
                                                }
2463
 
                                        }
2464
 
                                }
2465
 
                        }
2466
 
 
2467
 
                        return info;
2468
 
                }
2469
 
 
2470
 
        }
2471
 
 
2472
 
        public static Gdk.RGBA hex_to_rgba (string hex_color){
2473
 
 
2474
 
                /* Converts the color in hex to RGBA */
2475
 
 
2476
 
                string hex = hex_color.strip().down();
2477
 
                if (hex.has_prefix("#") == false){
2478
 
                        hex = "#" + hex;
2479
 
                }
2480
 
 
2481
 
                Gdk.RGBA color = Gdk.RGBA();
2482
 
                if(color.parse(hex) == false){
2483
 
                        color.parse("#000000");
2484
 
                }
2485
 
                color.alpha = 255;
2486
 
 
2487
 
                return color;
2488
 
        }
2489
 
 
2490
 
        public static string rgba_to_hex (Gdk.RGBA color, bool alpha = false, bool prefix_hash = true){
2491
 
 
2492
 
                /* Converts the color in RGBA to hex */
2493
 
 
2494
 
                string hex = "";
2495
 
 
2496
 
                if (alpha){
2497
 
                        hex = "%02x%02x%02x%02x".printf((uint)(Math.round(color.red*255)),
2498
 
                                                                        (uint)(Math.round(color.green*255)),
2499
 
                                                                        (uint)(Math.round(color.blue*255)),
2500
 
                                                                        (uint)(Math.round(color.alpha*255)))
2501
 
                                                                        .up();
2502
 
                }
2503
 
                else {
2504
 
                        hex = "%02x%02x%02x".printf((uint)(Math.round(color.red*255)),
2505
 
                                                                        (uint)(Math.round(color.green*255)),
2506
 
                                                                        (uint)(Math.round(color.blue*255)))
2507
 
                                                                        .up();
2508
 
                }
2509
 
 
2510
 
                if (prefix_hash){
2511
 
                        hex = "#" + hex;
2512
 
                }
2513
 
 
2514
 
                return hex;
2515
 
        }
2516
 
 
2517
 
        public string timestamp2 (){
2518
 
 
2519
 
                /* Returns a numeric timestamp string */
2520
 
 
2521
 
                return "%ld".printf((long) time_t ());
2522
 
        }
2523
 
 
2524
 
        public string timestamp (){
2525
 
 
2526
 
                /* Returns a formatted timestamp string */
2527
 
 
2528
 
                Time t = Time.local (time_t ());
2529
 
                return t.format ("%H:%M:%S");
2530
 
        }
2531
 
 
2532
 
        public string timestamp3 (){
2533
 
 
2534
 
                /* Returns a formatted timestamp string */
2535
 
 
2536
 
                Time t = Time.local (time_t ());
2537
 
                return t.format ("%Y-%d-%m_%H-%M-%S");
2538
 
        }
2539
 
 
2540
 
        public string format_duration (long millis){
2541
 
 
2542
 
                /* Converts time in milliseconds to format '00:00:00.0' */
2543
 
 
2544
 
            double time = millis / 1000.0; // time in seconds
2545
 
 
2546
 
            double hr = Math.floor(time / (60.0 * 60));
2547
 
            time = time - (hr * 60 * 60);
2548
 
            double min = Math.floor(time / 60.0);
2549
 
            time = time - (min * 60);
2550
 
            double sec = Math.floor(time);
2551
 
 
2552
 
        return "%02.0lf:%02.0lf:%02.0lf".printf (hr, min, sec);
2553
 
        }
2554
 
 
2555
 
        public double parse_time (string time){
2556
 
 
2557
 
                /* Converts time in format '00:00:00.0' to milliseconds */
2558
 
 
2559
 
                string[] arr = time.split (":");
2560
 
                double millis = 0;
2561
 
                if (arr.length >= 3){
2562
 
                        millis += double.parse(arr[0]) * 60 * 60;
2563
 
                        millis += double.parse(arr[1]) * 60;
2564
 
                        millis += double.parse(arr[2]);
2565
 
                }
2566
 
                return millis;
2567
 
        }
2568
 
 
2569
 
        public string string_replace(string str, string search, string replacement, int count = -1){
2570
 
                string[] arr = str.split(search);
2571
 
                string new_txt = "";
2572
 
                bool first = true;
2573
 
                
2574
 
                foreach(string part in arr){
2575
 
                        if (first){
2576
 
                                new_txt += part;
2577
 
                        }
2578
 
                        else{
2579
 
                                if (count == 0){
2580
 
                                        new_txt += search;
2581
 
                                        new_txt += part;
2582
 
                                }
2583
 
                                else{
2584
 
                                        new_txt += replacement;
2585
 
                                        new_txt += part;
2586
 
                                        count--;
2587
 
                                }
2588
 
                        }
2589
 
                        first = false;
2590
 
                }
2591
 
 
2592
 
                return new_txt;
2593
 
        }
2594
 
        
2595
 
        public string escape_html(string html){
2596
 
                return html
2597
 
                .replace("&","&amp;")
2598
 
                .replace("\"","&quot;")
2599
 
                //.replace(" ","&nbsp;") //pango markup throws an error with &nbsp;
2600
 
                .replace("<","&lt;")
2601
 
                .replace(">","&gt;")
2602
 
                ;
2603
 
        }
2604
 
 
2605
 
        public string unescape_html(string html){
2606
 
                return html
2607
 
                .replace("&amp;","&")
2608
 
                .replace("&quot;","\"")
2609
 
                //.replace("&nbsp;"," ") //pango markup throws an error with &nbsp;
2610
 
                .replace("&lt;","<")
2611
 
                .replace("&gt;",">")
2612
 
                ;
2613
 
        }
2614
 
 
2615
 
        public DateTime datetime_from_string (string date_time_string){
2616
 
 
2617
 
                /* Converts date time string to DateTime
2618
 
                 * 
2619
 
                 * Supported inputs:
2620
 
                 * 'yyyy-MM-dd'
2621
 
                 * 'yyyy-MM-dd HH'
2622
 
                 * 'yyyy-MM-dd HH:mm'
2623
 
                 * 'yyyy-MM-dd HH:mm:ss'
2624
 
                 * */
2625
 
 
2626
 
                string[] arr = date_time_string.replace(":"," ").replace("-"," ").strip().split(" ");
2627
 
 
2628
 
                int year  = (arr.length >= 3) ? int.parse(arr[0]) : 0;
2629
 
                int month = (arr.length >= 3) ? int.parse(arr[1]) : 0;
2630
 
                int day   = (arr.length >= 3) ? int.parse(arr[2]) : 0;
2631
 
                int hour  = (arr.length >= 4) ? int.parse(arr[3]) : 0;
2632
 
                int min   = (arr.length >= 5) ? int.parse(arr[4]) : 0;
2633
 
                int sec   = (arr.length >= 6) ? int.parse(arr[5]) : 0;
2634
 
 
2635
 
                return new DateTime.utc(year,month,day,hour,min,sec);
2636
 
        }
2637
 
        
2638
 
}