gnome-cmd-file.cc 28.2 KB
Newer Older
1
/**
Uwe Scholz's avatar
Uwe Scholz committed
2
3
4
 * @file gnome-cmd-file.cc
 * @copyright (C) 2001-2006 Marcus Bjurman\n
 * @copyright (C) 2007-2012 Piotr Eljasiak\n
Uwe Scholz's avatar
Uwe Scholz committed
5
 * @copyright (C) 2013-2021 Uwe Scholz\n
Uwe Scholz's avatar
Uwe Scholz committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 *
 * @copyright This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * @copyright This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * @copyright You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 */
Piotr Eljasiak's avatar
wq    
Piotr Eljasiak committed
21

Marcus Bjurman's avatar
Marcus Bjurman committed
22
23
#include <config.h>
#include <errno.h>
Piotr Eljasiak's avatar
Piotr Eljasiak committed
24

Marcus Bjurman's avatar
Marcus Bjurman committed
25
26
#include "gnome-cmd-includes.h"
#include "utils.h"
27
#include "gnome-cmd-owner.h"
Marcus Bjurman's avatar
Marcus Bjurman committed
28
29
30
31
#include "imageloader.h"
#include "gnome-cmd-data.h"
#include "gnome-cmd-plain-path.h"
#include "gnome-cmd-main-win.h"
Piotr Eljasiak's avatar
Piotr Eljasiak committed
32
#include "gnome-cmd-con-list.h"
Marcus Bjurman's avatar
Marcus Bjurman committed
33
#include "gnome-cmd-xfer.h"
34
#include "tags/gnome-cmd-tags.h"
35
#include "intviewer/libgviewer.h"
36
#include "dialogs/gnome-cmd-file-props-dialog.h"
Marcus Bjurman's avatar
Marcus Bjurman committed
37

38
39
using namespace std;

Piotr Eljasiak's avatar
Piotr Eljasiak committed
40

Marcus Bjurman's avatar
Marcus Bjurman committed
41
42
43
44
45
46
47
48
49
50
#define MAX_TYPE_LENGTH 2
#define MAX_NAME_LENGTH 128
#define MAX_OWNER_LENGTH 128
#define MAX_GROUP_LENGTH 128
#define MAX_PERM_LENGTH 10
#define MAX_DATE_LENGTH 64
#define MAX_SIZE_LENGTH 32

gint created_files_cnt = 0;
gint deleted_files_cnt = 0;
51
GList *all_files = nullptr;
Marcus Bjurman's avatar
Marcus Bjurman committed
52

Piotr Eljasiak's avatar
Piotr Eljasiak committed
53
struct GnomeCmdFile::Private
Marcus Bjurman's avatar
Marcus Bjurman committed
54
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
55
56
57
    Handle *dir_handle;
    GTimeVal last_update;
    gint ref_cnt;
58
    guint64 tree_size;
Marcus Bjurman's avatar
Marcus Bjurman committed
59
60
61
};


62
G_DEFINE_TYPE (GnomeCmdFile, gnome_cmd_file, GNOME_CMD_TYPE_FILE_BASE)
63
64


Piotr Eljasiak's avatar
Piotr Eljasiak committed
65
inline gboolean has_parent_dir (GnomeCmdFile *f)
Marcus Bjurman's avatar
Marcus Bjurman committed
66
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
67
    return f->priv->dir_handle && f->priv->dir_handle->ref;
Marcus Bjurman's avatar
Marcus Bjurman committed
68
69
70
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
71
inline GnomeCmdDir *get_parent_dir (GnomeCmdFile *f)
Marcus Bjurman's avatar
Marcus Bjurman committed
72
{
73
    g_return_val_if_fail (f->priv->dir_handle != nullptr, nullptr);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
74

Piotr Eljasiak's avatar
Piotr Eljasiak committed
75
    return GNOME_CMD_DIR (f->priv->dir_handle->ref);
Marcus Bjurman's avatar
Marcus Bjurman committed
76
77
78
}


79
80
static void gnome_cmd_file_init (GnomeCmdFile *f)
{
81
82
    // f->info = nullptr;
    // f->collate_key = nullptr;
83
84
85

    f->priv = g_new0 (GnomeCmdFile::Private, 1);

86
    // f->priv->dir_handle = nullptr;
87
88
89
90
91
92
93
94
95
96
97
98
99

    // f->priv->last_update.tv_sec = 0;
    // f->priv->last_update.tv_usec = 0;

    f->priv->tree_size = -1;

    if (DEBUG_ENABLED ('c'))
    {
        all_files = g_list_append (all_files, f);
        created_files_cnt++;
    }
}

Marcus Bjurman's avatar
Marcus Bjurman committed
100

101
static void gnome_cmd_file_finalize (GObject *object)
Marcus Bjurman's avatar
Marcus Bjurman committed
102
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
103
    GnomeCmdFile *f = GNOME_CMD_FILE (object);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
104

Piotr Eljasiak's avatar
Piotr Eljasiak committed
105
    delete f->metadata;
106

107
    if (f->gFileInfo && strcmp(g_file_info_get_display_name(f->gFileInfo), "..") != 0)
108
        DEBUG ('f', "file destroying %p %s\n", f, g_file_info_get_display_name(f->gFileInfo));
109

Piotr Eljasiak's avatar
Piotr Eljasiak committed
110
    g_free (f->collate_key);
111
    g_object_unref(f->gFileInfo);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
112
113
    if (f->priv->dir_handle)
        handle_unref (f->priv->dir_handle);
Marcus Bjurman's avatar
Marcus Bjurman committed
114

115
116
    if (DEBUG_ENABLED ('c'))
    {
Piotr Eljasiak's avatar
Piotr Eljasiak committed
117
        all_files = g_list_remove (all_files, f);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
118
119
        deleted_files_cnt++;
    }
Marcus Bjurman's avatar
Marcus Bjurman committed
120

121
122
123
124
    if (f->gFile)
    {
        g_object_unref(f->gFile);
    }
Piotr Eljasiak's avatar
Piotr Eljasiak committed
125
    g_free (f->priv);
Marcus Bjurman's avatar
Marcus Bjurman committed
126

127
    G_OBJECT_CLASS (gnome_cmd_file_parent_class)->finalize (object);
Marcus Bjurman's avatar
Marcus Bjurman committed
128
129
}

130

131
static void gnome_cmd_file_class_init (GnomeCmdFileClass *klass)
Marcus Bjurman's avatar
Marcus Bjurman committed
132
{
133
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
134

135
    object_class->finalize = gnome_cmd_file_finalize;
Marcus Bjurman's avatar
Marcus Bjurman committed
136
137
138
139
140
141
142
}


/***********************************
 * Public functions
 ***********************************/

143
144
GnomeCmdFile *gnome_cmd_file_new (const gchar *local_full_path)
{
145
    g_return_val_if_fail (local_full_path != nullptr, nullptr);
146

147
148
    auto gFile = g_file_new_for_path(local_full_path);
    GnomeCmdFile *f = gnome_cmd_file_new_from_gfile (gFile);
149
150
151
152
153

    return f;
}


154
155
156
157
GnomeCmdFile *gnome_cmd_file_new (GFileInfo *gFileInfo, GnomeCmdDir *dir)
{
    auto gnomeCmdFile = static_cast<GnomeCmdFile*> (g_object_new (GNOME_CMD_TYPE_FILE, nullptr));

158
    gnome_cmd_file_setup (G_OBJECT(gnomeCmdFile), gFileInfo, dir);
159
160
161
162
163
164
165
166
167
168
169

    if(!gnomeCmdFile->gFile)
    {
        g_object_unref(gnomeCmdFile);
        return nullptr;
    }

    return gnomeCmdFile;
}


170
GnomeCmdFile *gnome_cmd_file_new_from_gfile (GFile *gFile)
171
{
172
    g_return_val_if_fail (gFile != nullptr, nullptr);
173
174
    g_return_val_if_fail (G_IS_FILE(gFile), nullptr);
    GError *error = nullptr;
175

176
177
    auto gFileInfo = g_file_query_info(gFile, "*", G_FILE_QUERY_INFO_NONE, nullptr, &error);
    if (!gFileInfo || error)
178
    {
179
180
181
        g_object_unref (gFileInfo);
        g_critical ("gnome_cmd_file_new_from_gfile error: %s\n", error->message);
        g_error_free (error);
182
        return nullptr;
183
184
    }

185
186
187
188
189
190
191
192
193
    auto gFileParent = g_file_get_parent(gFile);
    if (gFileParent)
    {
        auto gFileParentPath = g_file_get_path(gFileParent);
        GnomeCmdDir *dir = gnome_cmd_dir_new (get_home_con(), new GnomeCmdPlainPath(gFileParentPath));
        g_free(gFileParentPath);
        g_object_unref(gFileParent);
        return gnome_cmd_file_new (gFileInfo, dir);
    }
194

195
196
197
198
199
    auto gFileParentPath = g_file_get_path(gFileParent);
    GnomeCmdDir *dir = gnome_cmd_dir_new (get_home_con(), new GnomeCmdPlainPath(G_DIR_SEPARATOR_S));
    g_free(gFileParentPath);
    g_object_unref(gFileParent);
    return gnome_cmd_file_new (gFileInfo, dir);
200
201
202
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
203
void GnomeCmdFile::invalidate_metadata()
204
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
205
    delete metadata;
206
    metadata = nullptr;
207
208
209
}


210
void gnome_cmd_file_setup (GObject *gObject, GFileInfo *gFileInfo, GnomeCmdDir *parentDir)
211
{
212
213
    g_return_if_fail (gObject != nullptr);
    g_return_if_fail (GNOME_CMD_IS_FILE(gObject));
214
215
    g_return_if_fail (gFileInfo != nullptr);

216
    auto gnomeCmdFile = (GnomeCmdFile*) gObject;
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
    gnomeCmdFile->gFileInfo = gFileInfo;

    auto filename = g_file_info_get_attribute_string (gFileInfo, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);

    // check if file is '..'
    gnomeCmdFile->is_dotdot = g_file_info_get_attribute_uint32 (gFileInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE) == G_FILE_TYPE_DIRECTORY
                              && g_strcmp0(filename, "..") == 0;

    gchar *utf8_name;

    if (!gnome_cmd_data.options.case_sens_sort)
    {
        utf8_name = g_utf8_casefold (filename, -1);
    }
    else
        utf8_name = g_strdup(filename);

    gnomeCmdFile->collate_key = g_utf8_collate_key_for_filename (utf8_name, -1);
    g_free (utf8_name);

237
    if (parentDir)
238
    {
239
        gnomeCmdFile->priv->dir_handle = gnome_cmd_dir_get_handle (parentDir);
240
241
242
243
244
245
        handle_ref (gnomeCmdFile->priv->dir_handle);
    }

    auto path = gnomeCmdFile->get_path();
    if (path)
    {
246
247
248
249
250
251
252
253
254
255
256
257
        GnomeCmdCon *con = nullptr;
        if (parentDir)
        {
            con = gnome_cmd_dir_get_connection(parentDir);
        }
        else
        {
            if (GNOME_CMD_IS_DIR(gObject))
            {
                con = gnome_cmd_dir_get_connection(GNOME_CMD_DIR(gObject));
            }
        }
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
        if (con && !con->is_local)
        {
            auto conUri = gnome_cmd_con_get_uri(con);
            auto gFileTmp = g_file_new_for_uri (conUri);

            GNOME_CMD_FILE_BASE (gnomeCmdFile)->gFile = g_file_resolve_relative_path (gFileTmp, path);
            gnomeCmdFile->gFile = GNOME_CMD_FILE_BASE (gnomeCmdFile)->gFile;
            g_free(path);
            g_object_unref (gFileTmp);
        }
        else
        {
            GNOME_CMD_FILE_BASE (gnomeCmdFile)->gFile = g_file_new_for_path(path);
            gnomeCmdFile->gFile = GNOME_CMD_FILE_BASE (gnomeCmdFile)->gFile;
            g_free(path);
        }
274
275
276
277
278
279
280
281
282
283
    }
    // EVERY GnomeCmdFile instance must have a gFile reference
    if (!gnomeCmdFile->gFile)
    {
        g_object_unref(gnomeCmdFile->gFileInfo);
        return;
    }
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
284
GnomeCmdFile *GnomeCmdFile::ref()
Marcus Bjurman's avatar
Marcus Bjurman committed
285
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
286
    priv->ref_cnt++;
Marcus Bjurman's avatar
Marcus Bjurman committed
287

Piotr Eljasiak's avatar
Piotr Eljasiak committed
288
    if (priv->ref_cnt == 1)
289
        g_object_ref (this);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
290

Piotr Eljasiak's avatar
Piotr Eljasiak committed
291
    char c = GNOME_CMD_IS_DIR (this) ? 'd' : 'f';
Piotr Eljasiak's avatar
Piotr Eljasiak committed
292

293
    DEBUG (c, "refing: %p %s to %d\n", this, g_file_info_get_name(gFileInfo), priv->ref_cnt);
294

Piotr Eljasiak's avatar
Piotr Eljasiak committed
295
    return this;
Marcus Bjurman's avatar
Marcus Bjurman committed
296
297
298
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
299
void GnomeCmdFile::unref()
Marcus Bjurman's avatar
Marcus Bjurman committed
300
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
301
    priv->ref_cnt--;
Piotr Eljasiak's avatar
Piotr Eljasiak committed
302

Piotr Eljasiak's avatar
Piotr Eljasiak committed
303
    char c = GNOME_CMD_IS_DIR (this) ? 'd' : 'f';
Piotr Eljasiak's avatar
Piotr Eljasiak committed
304

305
    DEBUG (c, "un-refing: %p %s to %d\n", this, g_file_info_get_display_name(gFileInfo), priv->ref_cnt);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
306
    if (priv->ref_cnt < 1)
307
        g_object_unref (this);
Marcus Bjurman's avatar
Marcus Bjurman committed
308
309
310
}


311
gboolean GnomeCmdFile::chmod(guint32 permissions, GError **error)
Marcus Bjurman's avatar
Marcus Bjurman committed
312
{
313
    GError *tmp_error = nullptr;
Marcus Bjurman's avatar
Marcus Bjurman committed
314

315
316
317
318
    auto gFileInfoPerms = g_file_query_info(gFile,
                                            G_FILE_ATTRIBUTE_UNIX_MODE,
                                            G_FILE_QUERY_INFO_NONE,
                                            nullptr,
319
320
                                            &tmp_error);
    if (tmp_error)
321
    {
322
        g_propagate_error (error, tmp_error);
323
        return false;
324
325
    }

326
327
    tmp_error = nullptr;

328
329
330
331
332
333
334
335
    g_file_info_set_attribute_uint32(gFileInfoPerms,
                                     G_FILE_ATTRIBUTE_UNIX_MODE,
                                     permissions);

    g_file_set_attributes_from_info(gFile,
                                    gFileInfoPerms,
                                    G_FILE_QUERY_INFO_NONE,
                                    nullptr,
336
337
                                    &tmp_error);
    if (tmp_error)
338
339
    {
        g_object_unref(gFileInfoPerms);
340
        g_propagate_error (error, tmp_error);
341
        return false;
342
    }
Marcus Bjurman's avatar
Marcus Bjurman committed
343

Uwe Scholz's avatar
Uwe Scholz committed
344
345
    g_object_unref(gFileInfoPerms);

Piotr Eljasiak's avatar
Piotr Eljasiak committed
346
    if (has_parent_dir (this))
347
    {
Piotr Eljasiak's avatar
Piotr Eljasiak committed
348
        GnomeCmdDir *dir = ::get_parent_dir (this);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
349
        gchar *uri_str = get_uri_str();
Piotr Eljasiak's avatar
Piotr Eljasiak committed
350
351
        gnome_cmd_dir_file_changed (dir, uri_str);
        g_free (uri_str);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
352
    }
353
    return true;
Marcus Bjurman's avatar
Marcus Bjurman committed
354
355
356
}


357
gboolean GnomeCmdFile::chown(uid_t uid, gid_t gid, GError **error)
Marcus Bjurman's avatar
Marcus Bjurman committed
358
{
359
360
    g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

361
    GError *tmp_error = nullptr;
Marcus Bjurman's avatar
Marcus Bjurman committed
362

Uwe Scholz's avatar
Uwe Scholz committed
363
364
365
366
    auto gFileInfoMods = g_file_query_info(gFile,
                                           G_FILE_ATTRIBUTE_UNIX_UID "," G_FILE_ATTRIBUTE_UNIX_GID,
                                           G_FILE_QUERY_INFO_NONE,
                                           nullptr,
367
368
                                           &tmp_error);
    if (tmp_error)
Uwe Scholz's avatar
Uwe Scholz committed
369
    {
370
        g_propagate_error (error, tmp_error);
Uwe Scholz's avatar
Uwe Scholz committed
371
372
373
        return false;
    }

374
375
    tmp_error = nullptr;

Uwe Scholz's avatar
Uwe Scholz committed
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
    if (uid != (uid_t) -1)
    {
        g_file_info_set_attribute_uint32(gFileInfoMods,
                                         G_FILE_ATTRIBUTE_UNIX_UID,
                                         uid);
    }

    g_file_info_set_attribute_uint32(gFileInfoMods,
                                     G_FILE_ATTRIBUTE_UNIX_GID,
                                     gid);

    g_file_set_attributes_from_info(gFile,
                                    gFileInfoMods,
                                    G_FILE_QUERY_INFO_NONE,
                                    nullptr,
391
392
                                    &tmp_error);
    if (tmp_error)
Uwe Scholz's avatar
Uwe Scholz committed
393
394
    {
        g_object_unref(gFileInfoMods);
395
        g_propagate_error (error, tmp_error);
Uwe Scholz's avatar
Uwe Scholz committed
396
397
398
399
        return false;
    }

    g_object_unref(gFileInfoMods);
Marcus Bjurman's avatar
Marcus Bjurman committed
400

Piotr Eljasiak's avatar
Piotr Eljasiak committed
401
    if (has_parent_dir (this))
402
    {
Piotr Eljasiak's avatar
Piotr Eljasiak committed
403
        GnomeCmdDir *dir = ::get_parent_dir (this);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
404
        gchar *uri_str = get_uri_str();
Piotr Eljasiak's avatar
Piotr Eljasiak committed
405
406
        gnome_cmd_dir_file_changed (dir, uri_str);
        g_free (uri_str);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
407
    }
Uwe Scholz's avatar
Uwe Scholz committed
408
    return true;
Marcus Bjurman's avatar
Marcus Bjurman committed
409
410
411
}


412
gboolean GnomeCmdFile::rename(const gchar *new_name, GError **error)
Marcus Bjurman's avatar
Marcus Bjurman committed
413
{
Uwe Scholz's avatar
Uwe Scholz committed
414
    g_return_val_if_fail (gFileInfo, false);
Marcus Bjurman's avatar
Marcus Bjurman committed
415

Uwe Scholz's avatar
Uwe Scholz committed
416
    gchar *old_uri_str = get_uri_str();
Marcus Bjurman's avatar
Marcus Bjurman committed
417

418
419
    GError *tmp_error;
    tmp_error = nullptr;
420

421
    auto newgFile = g_file_set_display_name (this->gFile, new_name, nullptr, &tmp_error);
Marcus Bjurman's avatar
Marcus Bjurman committed
422

423
    if (tmp_error || newgFile == nullptr)
424
    {
425
426
427
        g_message ("rename to \"%s\" failed: %s", new_name, tmp_error->message);
        g_propagate_error (error, tmp_error);
        return FALSE;
428
429
    }

430
431
432
    g_object_unref(this->gFile);
    this->gFile = newgFile;

Uwe Scholz's avatar
Uwe Scholz committed
433
434
435
436
437
438
439
440
    auto gFileInfoNew = g_file_query_info(gFile,
                                          "*",
                                          G_FILE_QUERY_INFO_NONE,
                                          nullptr,
                                          &tmp_error);
    if (tmp_error)
    {
        g_propagate_error (error, tmp_error);
441
        return false;
Uwe Scholz's avatar
Uwe Scholz committed
442
    }
443

Uwe Scholz's avatar
Uwe Scholz committed
444
    if (has_parent_dir (this))
445
    {
Uwe Scholz's avatar
Uwe Scholz committed
446
        update_gFileInfo(gFileInfoNew);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
447
        gnome_cmd_dir_file_renamed (::get_parent_dir (this), this, old_uri_str);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
448
449
        if (GNOME_CMD_IS_DIR (this))
            gnome_cmd_dir_update_path (GNOME_CMD_DIR (this));
Piotr Eljasiak's avatar
Piotr Eljasiak committed
450
    }
451

Uwe Scholz's avatar
Uwe Scholz committed
452
453
    g_free(old_uri_str);

454
    return true;
Marcus Bjurman's avatar
Marcus Bjurman committed
455
456
457
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
458
gchar *GnomeCmdFile::get_quoted_name()
Marcus Bjurman's avatar
Marcus Bjurman committed
459
{
460
    g_return_val_if_fail (gFileInfo != nullptr, nullptr);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
461

462
    return quote_if_needed (g_file_info_get_display_name(gFileInfo));
Marcus Bjurman's avatar
Marcus Bjurman committed
463
464
465
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
466
gchar *GnomeCmdFile::get_path()
Marcus Bjurman's avatar
Marcus Bjurman committed
467
{
468
    g_return_val_if_fail (gFileInfo != nullptr, nullptr);
469
470

    auto filename = g_file_info_get_name (this->gFileInfo);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
471

472
473
474
    if (!filename)
        return nullptr;

475
476
    if (strcmp (filename, G_DIR_SEPARATOR_S) == 0)
        return g_strdup(filename);
Marcus Bjurman's avatar
Marcus Bjurman committed
477

Piotr Eljasiak's avatar
Piotr Eljasiak committed
478
479
480
    GnomeCmdPath *path;
    gchar *path_str;

Piotr Eljasiak's avatar
Piotr Eljasiak committed
481
    if (!has_parent_dir (this))
482
    {
Piotr Eljasiak's avatar
Piotr Eljasiak committed
483
        if (GNOME_CMD_IS_DIR (this))
484
        {
Piotr Eljasiak's avatar
Piotr Eljasiak committed
485
            path = gnome_cmd_dir_get_path (GNOME_CMD_DIR (this));
486
            return g_strdup (path->get_path());
Piotr Eljasiak's avatar
Piotr Eljasiak committed
487
488
489
        }
        g_assert ("Non directory file without owning directory");
    }
Marcus Bjurman's avatar
Marcus Bjurman committed
490

491
    path = gnome_cmd_dir_get_path (::get_parent_dir (this))->get_child(filename);
492
493
494
495
496
    if (!path)
    {
        return nullptr;
    }

497
498
    path_str = g_strdup (path->get_path());
    delete path;
Marcus Bjurman's avatar
Marcus Bjurman committed
499

Piotr Eljasiak's avatar
Piotr Eljasiak committed
500
    return path_str;
Marcus Bjurman's avatar
Marcus Bjurman committed
501
502
503
}


504
//ToDo: Try to remove usage of this method.
Piotr Eljasiak's avatar
Piotr Eljasiak committed
505
gchar *GnomeCmdFile::get_real_path()
Marcus Bjurman's avatar
Marcus Bjurman committed
506
{
507
508
509
    auto gfile = get_gfile();
    gchar *path = g_file_get_path (gfile);
    g_object_unref (gfile);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
510
511

    return path;
Marcus Bjurman's avatar
Marcus Bjurman committed
512
513
514
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
515
gchar *GnomeCmdFile::get_quoted_real_path()
Marcus Bjurman's avatar
Marcus Bjurman committed
516
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
517
    gchar *path = get_real_path();
Piotr Eljasiak's avatar
Piotr Eljasiak committed
518
    gchar *ret = quote_if_needed (path);
Marcus Bjurman's avatar
Marcus Bjurman committed
519

Piotr Eljasiak's avatar
Piotr Eljasiak committed
520
    g_free (path);
Marcus Bjurman's avatar
Marcus Bjurman committed
521

Piotr Eljasiak's avatar
Piotr Eljasiak committed
522
    return ret;
Marcus Bjurman's avatar
Marcus Bjurman committed
523
524
525
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
526
gchar *GnomeCmdFile::get_dirname()
527
{
528
529
530
531
532
533
534
535
536
537
    auto gFileTmp = get_gfile();
    auto gFileParent = g_file_get_parent(gFileTmp);
    if (!gFileParent)
    {
        g_object_unref(gFileTmp);
        return nullptr;
    }
    gchar *path = g_file_get_path (gFileParent);
    g_object_unref (gFileTmp);
    g_object_unref (gFileParent);
538
539
540
541
542

    return path;
}


543
544
GAppInfo *GnomeCmdFile::GetAppInfoForContentType()
{
545
    auto contentTypeString = this->GetGfileAttributeString(G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
546
547
548
549
550
551
552
    auto appInfo = g_app_info_get_default_for_type (contentTypeString, false);
    g_free(contentTypeString);

    return appInfo;
}


553
554
555
556
557
558
gboolean GnomeCmdFile::GetGfileAttributeBoolean(const char *attribute)
{
    return get_gfile_attribute_boolean(this->gFile, attribute);
}


559
gchar *GnomeCmdFile::GetGfileAttributeString(const char *attribute)
560
{
561
    return get_gfile_attribute_string(this->gFile, attribute);
562
563
564
}


565
566
guint32 GnomeCmdFile::GetGfileAttributeUInt32(const char *attribute)
{
567
    return get_gfile_attribute_uint32(this->gFile, attribute);
568
569
570
}


571
572
guint64 GnomeCmdFile::GetGfileAttributeUInt64(const char *attribute)
{
573
    return get_gfile_attribute_uint64(this->gFile, attribute);
574
575
576
}


577
578
gchar *GnomeCmdFile::get_default_application_name_string()
{
579
    auto contentType = GetGfileAttributeString (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
580
581
582
583
584
585
586
587
588
589

    auto appInfo = g_app_info_get_default_for_type (contentType, false);

    g_free(contentType);
    return g_strdup(g_app_info_get_name (appInfo));
}


gchar *GnomeCmdFile::get_default_application_action_label(GAppInfo *gAppInfo)
{
Uwe Scholz's avatar
Uwe Scholz committed
590
    gchar *escaped_app_name = get_default_application_name (gAppInfo);
591
592
593
594
595
596
597
598
599
600
601
602
    if (escaped_app_name == nullptr)
    {
        return g_strdup (_("_Open"));
    }

    gchar *retval = g_strdup_printf (_("_Open with “%s”"), escaped_app_name);
    g_free (escaped_app_name);

    return retval;
}


Uwe Scholz's avatar
Uwe Scholz committed
603
gchar *GnomeCmdFile::get_default_application_name(GAppInfo *gAppInfo)
604
605
606
607
608
609
610
{
    gchar *escaped_app_name = string_double_underscores (g_app_info_get_name (gAppInfo));

    return escaped_app_name;
}


611
GFile *GnomeCmdFile::get_gfile(const gchar *name)
Marcus Bjurman's avatar
Marcus Bjurman committed
612
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
613
    if (!has_parent_dir (this))
614
    {
Piotr Eljasiak's avatar
Piotr Eljasiak committed
615
        if (GNOME_CMD_IS_DIR (this))
616
        {
Piotr Eljasiak's avatar
Piotr Eljasiak committed
617
618
            GnomeCmdPath *path = gnome_cmd_dir_get_path (GNOME_CMD_DIR (this));
            GnomeCmdCon *con = gnome_cmd_dir_get_connection (GNOME_CMD_DIR (this));
619
            return gnome_cmd_con_create_gfile (con, path);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
620
621
622
623
        }
        else
            g_assert ("Non directory file without owning directory");
    }
624
    auto filename = g_file_get_basename(gFile);
625
    auto childGFile = gnome_cmd_dir_get_child_gfile (::get_parent_dir (this), name ? name : filename);
626
    g_free(filename);
627
    return childGFile;
Marcus Bjurman's avatar
Marcus Bjurman committed
628
629
630
}


631
gchar *GnomeCmdFile::get_uri_str()
Marcus Bjurman's avatar
Marcus Bjurman committed
632
{
633
    return g_file_get_uri(this->gFile);
Marcus Bjurman's avatar
Marcus Bjurman committed
634
635
636
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
637
const gchar *GnomeCmdFile::get_extension()
Marcus Bjurman's avatar
Marcus Bjurman committed
638
{
639
    g_return_val_if_fail (gFileInfo != nullptr, nullptr);
Marcus Bjurman's avatar
Marcus Bjurman committed
640

641
    if (GetGfileAttributeUInt32(G_FILE_ATTRIBUTE_STANDARD_TYPE) == G_FILE_TYPE_DIRECTORY)
642
        return nullptr;
Marcus Bjurman's avatar
Marcus Bjurman committed
643

644
    const char *s = strrchr (g_file_info_get_name(gFileInfo), '.');
645
    return s ? s+1 : nullptr;
Marcus Bjurman's avatar
Marcus Bjurman committed
646
647
648
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
649
const gchar *GnomeCmdFile::get_owner()
Marcus Bjurman's avatar
Marcus Bjurman committed
650
{
651
    g_return_val_if_fail (gFileInfo != nullptr, nullptr);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
652

653
    return g_file_info_get_attribute_string(gFileInfo, G_FILE_ATTRIBUTE_OWNER_USER);
Marcus Bjurman's avatar
Marcus Bjurman committed
654
655
656
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
657
const gchar *GnomeCmdFile::get_group()
Marcus Bjurman's avatar
Marcus Bjurman committed
658
{
659
    g_return_val_if_fail (gFileInfo != nullptr, nullptr);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
660

661
    return g_file_info_get_attribute_string(gFileInfo, G_FILE_ATTRIBUTE_OWNER_GROUP);
Marcus Bjurman's avatar
Marcus Bjurman committed
662
663
664
}


665
inline const gchar *date2string (GDateTime *date, gboolean overide_disp_setting)
Marcus Bjurman's avatar
Marcus Bjurman committed
666
{
667
    return time2string (date, overide_disp_setting ? "%c" : gnome_cmd_data.options.date_format);
Marcus Bjurman's avatar
Marcus Bjurman committed
668
669
670
}


671
#ifdef GLIB_2_70
Piotr Eljasiak's avatar
Piotr Eljasiak committed
672
const gchar *GnomeCmdFile::get_adate(gboolean overide_disp_setting)
Marcus Bjurman's avatar
Marcus Bjurman committed
673
{
674
    g_return_val_if_fail (gFileInfo != nullptr, nullptr);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
675

676
    return date2string (g_file_info_get_access_date_time(gFileInfo), overide_disp_setting);
Marcus Bjurman's avatar
Marcus Bjurman committed
677
}
678
#endif
Marcus Bjurman's avatar
Marcus Bjurman committed
679

Piotr Eljasiak's avatar
Piotr Eljasiak committed
680
const gchar *GnomeCmdFile::get_mdate(gboolean overide_disp_setting)
Marcus Bjurman's avatar
Marcus Bjurman committed
681
{
682
    g_return_val_if_fail (gFileInfo != nullptr, nullptr);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
683

684
    return date2string (g_file_info_get_modification_date_time(gFileInfo), overide_disp_setting);
Marcus Bjurman's avatar
Marcus Bjurman committed
685
686
687
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
688
const gchar *GnomeCmdFile::get_size()
Marcus Bjurman's avatar
Marcus Bjurman committed
689
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
690
691
    static gchar dir_indicator[] = "<DIR> ";

692
    if (GetGfileAttributeUInt32(G_FILE_ATTRIBUTE_STANDARD_TYPE) == G_FILE_TYPE_DIRECTORY)
Piotr Eljasiak's avatar
Piotr Eljasiak committed
693
694
        return dir_indicator;

695
696
    auto size = GetGfileAttributeUInt64(G_FILE_ATTRIBUTE_STANDARD_SIZE);
    return size2string (size, gnome_cmd_data.options.size_disp_mode);
Marcus Bjurman's avatar
Marcus Bjurman committed
697
698
699
}


700
guint64 GnomeCmdFile::get_tree_size()
701
{
702
    if (GetGfileAttributeUInt32(G_FILE_ATTRIBUTE_STANDARD_TYPE) != G_FILE_TYPE_DIRECTORY)
703
        return g_file_info_get_attribute_uint64 (gFileInfo, G_FILE_ATTRIBUTE_STANDARD_SIZE);
704

Piotr Eljasiak's avatar
Piotr Eljasiak committed
705
    if (is_dotdot)
706
707
        return 0;

708
    if (priv->tree_size != (guint64)-1)
Piotr Eljasiak's avatar
Piotr Eljasiak committed
709
        return priv->tree_size;
710

711
    priv->tree_size = calc_tree_size (nullptr);
712

Piotr Eljasiak's avatar
Piotr Eljasiak committed
713
    return priv->tree_size;
714
715
716
}


717
718
719
720
guint64 GnomeCmdFile::calc_tree_size (gulong *count)
{
    g_return_val_if_fail (this->gFile != NULL, -1);

721
    guint64 size = 0;
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

    if (GetGfileAttributeUInt32(G_FILE_ATTRIBUTE_STANDARD_TYPE) == G_FILE_TYPE_DIRECTORY)
    {
        GError *error;
        error = nullptr;

        g_file_measure_disk_usage (this->gFile,
                           G_FILE_MEASURE_NONE,
                           nullptr,
                           nullptr,
                           nullptr,
                           &size,
                           nullptr,
                           nullptr,
                           &error);

        if (error)
        {
Uwe Scholz's avatar
Uwe Scholz committed
740
            g_message ("calc_tree_size: g_file_measure_disk_usage failed: %s", error->message);
741
742
743
744
745
746
747
748
749
750
751
752
753
754
            g_error_free (error);
        }
    }
    else
    {
        size += GetGfileAttributeUInt32(G_FILE_ATTRIBUTE_STANDARD_SIZE);
        if (count!=NULL) {
            (*count)++;
        }
    }
    return size;
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
755
const gchar *GnomeCmdFile::get_tree_size_as_str()
Marcus Bjurman's avatar
Marcus Bjurman committed
756
{
757
    if (GetGfileAttributeUInt32(G_FILE_ATTRIBUTE_STANDARD_TYPE) != G_FILE_TYPE_DIRECTORY)
Piotr Eljasiak's avatar
Piotr Eljasiak committed
758
        return get_size();
Marcus Bjurman's avatar
Marcus Bjurman committed
759

Piotr Eljasiak's avatar
Piotr Eljasiak committed
760
761
    if (is_dotdot)
        return get_size();
Marcus Bjurman's avatar
Marcus Bjurman committed
762

763
    return size2string (get_tree_size(), gnome_cmd_data.options.size_disp_mode);
Marcus Bjurman's avatar
Marcus Bjurman committed
764
765
766
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
767
const gchar *GnomeCmdFile::get_perm()
Marcus Bjurman's avatar
Marcus Bjurman committed
768
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
769
    static gchar perm_str[MAX_PERM_LENGTH];
Marcus Bjurman's avatar
Marcus Bjurman committed
770

771
    perm2string (GetGfileAttributeUInt32(G_FILE_ATTRIBUTE_UNIX_MODE) & 0xFFF, perm_str, MAX_PERM_LENGTH);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
772
    return perm_str;
Marcus Bjurman's avatar
Marcus Bjurman committed
773
774
775
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
776
const gchar *GnomeCmdFile::get_type_string()
Marcus Bjurman's avatar
Marcus Bjurman committed
777
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
778
779
    static gchar type_str[MAX_TYPE_LENGTH];

780
    type2string (GetGfileAttributeUInt32(G_FILE_ATTRIBUTE_STANDARD_TYPE), type_str, MAX_TYPE_LENGTH);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
781
    return type_str;
Marcus Bjurman's avatar
Marcus Bjurman committed
782
783
784
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
785
gboolean GnomeCmdFile::get_type_pixmap_and_mask(GdkPixmap **pixmap, GdkBitmap **mask)
786
{
787
    g_return_val_if_fail (gFileInfo != nullptr, FALSE);
788

789
    return IMAGE_get_pixmap_and_mask (GetGfileAttributeUInt32(G_FILE_ATTRIBUTE_STANDARD_TYPE),
790
791
792
793
                                      g_file_info_get_content_type(gFileInfo),
                                      g_file_info_get_is_symlink (gFileInfo),
                                      pixmap,
                                      mask);
794
795
796
}


797
gboolean GnomeCmdFile::has_content_type(const gchar *contentType)
Marcus Bjurman's avatar
Marcus Bjurman committed
798
{
799
    g_return_val_if_fail (contentType != nullptr, FALSE);
Marcus Bjurman's avatar
Marcus Bjurman committed
800

801
802
803
804
805
806
807
808
809
810
811
    auto actualContentType = GetGfileAttributeString(G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);

    if (!actualContentType)
    {
        return false;
    }

    auto compareValue = strcmp (actualContentType, contentType);
    g_free(actualContentType);

    return compareValue == 0;
Marcus Bjurman's avatar
Marcus Bjurman committed
812
813
814
}


815
gboolean GnomeCmdFile::content_type_begins_with(const gchar *contentTypeStart)
Marcus Bjurman's avatar
Marcus Bjurman committed
816
{
817
818
819
820
821
822
823
824
825
826
827
    g_return_val_if_fail (contentTypeStart != nullptr, FALSE);

    auto actualContentType = GetGfileAttributeString(G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);

    if (!actualContentType)
    {
        return false;
    }

    auto compareValue = strncmp (actualContentType, contentTypeStart, strlen(contentTypeStart));
    g_free(actualContentType);
Marcus Bjurman's avatar
Marcus Bjurman committed
828

829
    return compareValue == 0;
Marcus Bjurman's avatar
Marcus Bjurman committed
830
831
832
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
833
void gnome_cmd_file_show_properties (GnomeCmdFile *f)
Marcus Bjurman's avatar
Marcus Bjurman committed
834
{
Piotr Eljasiak's avatar
Piotr Eljasiak committed
835
    GtkWidget *dialog = gnome_cmd_file_props_dialog_create (f);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
836
    if (!dialog) return;
837

838
    g_object_ref (dialog);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
839
    gtk_widget_show (dialog);
Marcus Bjurman's avatar
Marcus Bjurman committed
840
841
842
}


843
inline void do_view_file (GnomeCmdFile *f, gint internal_viewer=-1)
Marcus Bjurman's avatar
Marcus Bjurman committed
844
{
Piotr Eljasiak's avatar
wq    
Piotr Eljasiak committed
845
    if (internal_viewer==-1)
846
        internal_viewer = gnome_cmd_data.options.use_internal_viewer;
Piotr Eljasiak's avatar
wq    
Piotr Eljasiak committed
847
848
849
850

    switch (internal_viewer)
    {
        case TRUE : {
851
852
                        GtkWidget *viewer = gviewer_window_file_view (f);
                        gtk_widget_show (viewer);
853
                        gdk_window_set_icon (viewer->window, nullptr,
Piotr Eljasiak's avatar
Piotr Eljasiak committed
854
855
                                             IMAGE_get_pixmap (PIXMAP_INTERNAL_VIEWER),
                                             IMAGE_get_mask (PIXMAP_INTERNAL_VIEWER));
Piotr Eljasiak's avatar
wq    
Piotr Eljasiak committed
856
857
858
859
                    }
                    break;

        case FALSE: {
Piotr Eljasiak's avatar
Piotr Eljasiak committed
860
                        gchar *filename = f->get_quoted_real_path();
861
862
863
864
#if defined (__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
865
                        gchar *command = g_strdup_printf (gnome_cmd_data.options.viewer, filename);
866
867
868
#if defined (__GNUC__)
#pragma GCC diagnostic pop
#endif
869
                        run_command (command);
870
                        g_free (filename);
Piotr Eljasiak's avatar
wq    
Piotr Eljasiak committed
871
872
                    }
                    break;
873
874

        default: break;
Piotr Eljasiak's avatar
wq    
Piotr Eljasiak committed
875
    }
Marcus Bjurman's avatar
Marcus Bjurman committed
876
877
878
}


879
static void on_file_downloaded_for_view (GFile *gFile)
Marcus Bjurman's avatar
Marcus Bjurman committed
880
{
881
    GnomeCmdFile *f = gnome_cmd_file_new_from_gfile (gFile);
882
883
884
885

    if (!f)
        return;

886
    do_view_file (f);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
887
    f->unref();
Marcus Bjurman's avatar
Marcus Bjurman committed
888
889
890
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
891
void gnome_cmd_file_view (GnomeCmdFile *f, gint internal_viewer)
Marcus Bjurman's avatar
Marcus Bjurman committed
892
{
893
    g_return_if_fail (f != nullptr);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
894
    g_return_if_fail (has_parent_dir (f));
Piotr Eljasiak's avatar
Piotr Eljasiak committed
895

Piotr Eljasiak's avatar
Piotr Eljasiak committed
896
    // If the file is local there is no need to download it
Piotr Eljasiak's avatar
Piotr Eljasiak committed
897
    if (f->is_local())
898
    {
899
        do_view_file (f, internal_viewer);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
900
901
        return;
    }
Marcus Bjurman's avatar
Marcus Bjurman committed
902

Piotr Eljasiak's avatar
Piotr Eljasiak committed
903
    // The file is remote, let's download it to a temporary file first
Piotr Eljasiak's avatar
Piotr Eljasiak committed
904
    gchar *path_str = get_temp_download_filepath (f->get_name());
905
    if (!path_str)  return;
Marcus Bjurman's avatar
Marcus Bjurman committed
906

907
    GnomeCmdPlainPath path(path_str);
908
909
    auto srcGFile = f->get_gfile();
    auto destGFile = gnome_cmd_con_create_gfile (get_home_con (), &path);
910
    auto gFile = gnome_cmd_con_create_gfile (get_home_con (), &path);
Marcus Bjurman's avatar
Marcus Bjurman committed
911

Piotr Eljasiak's avatar
Piotr Eljasiak committed
912
    g_printerr ("Copying to: %s\n", path_str);
913
    g_free (path_str);
Piotr Eljasiak's avatar
Piotr Eljasiak committed
914

915
916
917
918
919
    gnome_cmd_tmp_download (g_list_append (nullptr, srcGFile),
                            g_list_append (nullptr, destGFile),
                            G_FILE_COPY_OVERWRITE,
                            GTK_SIGNAL_FUNC (on_file_downloaded_for_view),
                            gFile);
Marcus Bjurman's avatar
Marcus Bjurman committed
920
921
922
}


Piotr Eljasiak's avatar
Piotr Eljasiak committed
923
void gnome_cmd_file_edit (GnomeCmdFile *f)
Marcus Bjurman's avatar
Marcus Bjurman committed
924
{
925
    g_return_if_fail (f != nullptr);
Marcus Bjurman's avatar
Marcus Bjurman committed
926

Piotr Eljasiak's avatar
Piotr Eljasiak committed
927
    if (!f->is_local())
928
929
        return;

Piotr Eljasiak's avatar
Piotr Eljasiak committed
930
    gchar *fpath = f->get_quoted_real_path();
931
932
933
    auto parentDir = g_file_get_parent(f->gFile);
    gchar *dpath = g_file_get_parse_name (parentDir);
    g_object_unref(parentDir);
Uwe Scholz's avatar