plover/uri-handler.c
author J. Ali Harlow <ali@juiblex.co.uk>
Tue Jun 29 10:09:34 2021 +0100 (2021-06-29)
changeset 108 b3d8e196dac8
parent 51 ea1c42c3a780
permissions -rw-r--r--
Added tag 0.6.1 for changeset 6ae203c8b28d
ali@41
     1
/*
ali@41
     2
 * Copyright (C) 2016  J. Ali Harlow <ali@juiblex.co.uk>
ali@41
     3
 *
ali@41
     4
 * This program is free software; you can redistribute it and/or modify
ali@41
     5
 * it under the terms of the GNU General Public License as published by
ali@41
     6
 * the Free Software Foundation; either version 2 of the License, or
ali@41
     7
 * (at your option) any later version.
ali@41
     8
 *
ali@41
     9
 * This program is distributed in the hope that it will be useful,
ali@41
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@41
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@41
    12
 * GNU General Public License for more details.
ali@41
    13
 *
ali@41
    14
 * You should have received a copy of the GNU General Public License along
ali@41
    15
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@41
    16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@41
    17
 */
ali@41
    18
ali@41
    19
#include <stdlib.h>
ali@42
    20
#include <string.h>
ali@42
    21
#include <errno.h>
ali@41
    22
#include <razor.h>
ali@41
    23
#include <glib.h>
ali@41
    24
#include <gio/gio.h>
ali@41
    25
#include "config.h"
ali@41
    26
#include "plover/plover.h"
ali@44
    27
#include "uri-handler.h"
ali@81
    28
#include "ascii-ctype.h"
ali@51
    29
ali@42
    30
static gboolean has_valid_scheme(const char *uri)
ali@42
    31
{
ali@42
    32
    /*
ali@45
    33
     * RFC 3986 defines valid schemes as:
ali@45
    34
     * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
ali@42
    35
     */
ali@42
    36
    const char *s;
ali@51
    37
    if (!ascii_isalpha(*uri))
ali@42
    38
	return FALSE;
ali@42
    39
    for(s=uri+1;;s++)
ali@42
    40
	if (*s==':')
ali@42
    41
	    return TRUE;
ali@51
    42
	else if (!ascii_isalnum(*s) && *s!='+' && *s!='-' && *s!='.')
ali@42
    43
	    return FALSE;
ali@42
    44
}
ali@42
    45
ali@42
    46
static GFile *file_for_uri(const char *uri)
ali@42
    47
{
ali@42
    48
    GFile *file;
ali@42
    49
    if (!has_valid_scheme(uri))
ali@42
    50
    {
ali@42
    51
	g_warning("%s: Not a valid URI",uri);
ali@42
    52
	file=g_file_new_for_path(uri);
ali@42
    53
    }
ali@42
    54
    else
ali@42
    55
    {
ali@42
    56
	if (strstr(uri+1,"file:/"))
ali@42
    57
	    g_warning("%s: Implausible URI",uri);
ali@42
    58
	file=g_file_new_for_uri(uri);
ali@42
    59
    }
ali@42
    60
    return file;
ali@42
    61
}
ali@42
    62
ali@44
    63
int uri_mkdir(const char *uri,mode_t mode,struct razor_error **error)
ali@42
    64
{
ali@42
    65
    GFile *file;
ali@42
    66
    GFileInfo *info;
ali@42
    67
    int retval;
ali@42
    68
    GError *err=NULL;
ali@42
    69
    file=file_for_uri(uri);
ali@45
    70
    retval=!g_file_make_directory(file,NULL,&err);
ali@45
    71
    if (retval)
ali@42
    72
    {
ali@42
    73
	if (g_error_matches(err,G_IO_ERROR,G_IO_ERROR_EXISTS))
ali@42
    74
	{
ali@42
    75
	    info=g_file_query_info(file,G_FILE_ATTRIBUTE_STANDARD_TYPE,
ali@42
    76
	      G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,NULL);
ali@42
    77
	    if (info)
ali@42
    78
	    {
ali@42
    79
		g_clear_error(&err);
ali@42
    80
		if (g_file_info_get_file_type(info)==G_FILE_TYPE_DIRECTORY)
ali@42
    81
		    retval=0;
ali@42
    82
		else
ali@42
    83
		    razor_set_error(error,RAZOR_POSIX_ERROR,EEXIST,uri,
ali@42
    84
		      "Not a directory");
ali@42
    85
		g_object_unref(info);
ali@42
    86
	    }
ali@42
    87
	}
ali@42
    88
	if (err)
ali@42
    89
	    plover_propagate_g_error(error,err);
ali@42
    90
    }
ali@42
    91
    g_object_unref(file);
ali@42
    92
    return retval;
ali@42
    93
}
ali@42
    94
ali@44
    95
int uri_unlink(const char *uri,struct razor_error **error)
ali@42
    96
{
ali@42
    97
    GFile *file;
ali@42
    98
    int retval;
ali@42
    99
    GError *err=NULL;
ali@42
   100
    file=file_for_uri(uri);
ali@45
   101
    retval=!g_file_delete(file,NULL,&err);
ali@45
   102
    if (retval)
ali@42
   103
	plover_propagate_g_error(error,err);
ali@42
   104
    g_object_unref(file);
ali@42
   105
    return retval;
ali@42
   106
}
ali@42
   107
ali@44
   108
int uri_move(const char *src_uri,const char *dst_uri,
ali@42
   109
  struct razor_error **error)
ali@42
   110
{
ali@42
   111
    GFile *src,*dst;
ali@42
   112
    int retval;
ali@42
   113
    GError *err=NULL;
ali@42
   114
    src=file_for_uri(src_uri);
ali@42
   115
    dst=file_for_uri(dst_uri);
ali@45
   116
    retval=!g_file_move(src,dst,G_FILE_COPY_OVERWRITE,NULL,NULL,NULL,&err);
ali@45
   117
    if (retval)
ali@42
   118
	plover_propagate_g_error(error,err);
ali@42
   119
    g_object_unref(src);
ali@42
   120
    g_object_unref(dst);
ali@42
   121
    return retval;
ali@42
   122
}
ali@42
   123
ali@44
   124
static void *uri_get_contents(const char *uri,size_t *length,int private,
ali@41
   125
  struct razor_error **error)
ali@41
   126
{
ali@41
   127
    GFile *file;
ali@41
   128
    void *addr;
ali@41
   129
    char *contents;
ali@41
   130
    gsize len;
ali@41
   131
    GError *err=NULL;
ali@42
   132
    file=file_for_uri(uri);
ali@45
   133
    if (!g_file_load_contents(file,NULL,&contents,&len,NULL,&err))
ali@41
   134
    {
ali@41
   135
	plover_propagate_g_error(error,err);
ali@41
   136
	addr=NULL;
ali@41
   137
    }
ali@41
   138
    else
ali@41
   139
    {
ali@41
   140
	addr=contents;
ali@41
   141
	if (length)
ali@41
   142
	    *length=len;
ali@41
   143
    }
ali@45
   144
    g_object_unref(file);
ali@41
   145
    return addr;
ali@41
   146
}
ali@41
   147
ali@44
   148
static int uri_free_contents(void *addr,size_t length)
ali@41
   149
{
ali@45
   150
    g_free(addr);
ali@45
   151
    return 0;
ali@41
   152
}
ali@41
   153
ali@44
   154
int uri_is_directory(const char *uri,struct razor_error **error)
ali@42
   155
{
ali@42
   156
    GFile *file;
ali@42
   157
    GFileInfo *info;
ali@42
   158
    int retval;
ali@42
   159
    GError *err=NULL;
ali@42
   160
    file=file_for_uri(uri);
ali@45
   161
    info=g_file_query_info(file,G_FILE_ATTRIBUTE_STANDARD_TYPE,
ali@45
   162
      G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,&err);
ali@45
   163
    if (info)
ali@42
   164
    {
ali@45
   165
	if (g_file_info_get_file_type(info)==G_FILE_TYPE_DIRECTORY)
ali@45
   166
	    retval=1;
ali@45
   167
	else
ali@45
   168
	    retval=0;
ali@45
   169
	g_object_unref(info);
ali@42
   170
    }
ali@42
   171
    else
ali@42
   172
    {
ali@45
   173
	retval=-1;
ali@45
   174
	plover_propagate_g_error(error,err);
ali@42
   175
    }
ali@42
   176
    g_object_unref(file);
ali@42
   177
    return retval;
ali@42
   178
}
ali@42
   179
ali@44
   180
void *uri_opendir(const char *uri,struct razor_error **error)
ali@42
   181
{
ali@42
   182
    GFile *file;
ali@45
   183
    GFileEnumerator *dir;
ali@42
   184
    GError *err=NULL;
ali@42
   185
    file=file_for_uri(uri);
ali@45
   186
    dir=g_file_enumerate_children(file,G_FILE_ATTRIBUTE_STANDARD_NAME,
ali@45
   187
      G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,NULL,&err);
ali@45
   188
    if (!dir)
ali@45
   189
	plover_propagate_g_error(error,err);
ali@42
   190
    g_object_unref(file);
ali@42
   191
    return dir;
ali@42
   192
}
ali@42
   193
ali@44
   194
char *uri_readdir(void *dp,struct razor_error **error)
ali@42
   195
{
ali@45
   196
    GFileEnumerator *dir=dp;
ali@42
   197
    char *name;
ali@42
   198
    GError *err=NULL;
ali@42
   199
    GFileInfo *info;
ali@45
   200
    info=g_file_enumerator_next_file(dir,NULL,&err);
ali@45
   201
    if (!info)
ali@45
   202
    {
ali@45
   203
	name=NULL;
ali@45
   204
	plover_propagate_g_error(error,err);
ali@45
   205
    }
ali@42
   206
    else
ali@42
   207
    {
ali@45
   208
	name=strdup(g_file_info_get_name(info));
ali@45
   209
	g_object_unref(info);
ali@42
   210
    }
ali@42
   211
    return name;
ali@42
   212
}
ali@42
   213
ali@44
   214
int uri_closedir(void *dp,struct razor_error **error)
ali@42
   215
{
ali@45
   216
    GFileEnumerator *dir=dp;
ali@42
   217
    int retval;
ali@42
   218
    GError *err=NULL;
ali@45
   219
    retval=!g_file_enumerator_close(dir,NULL,&err);
ali@45
   220
    if (retval)
ali@45
   221
	plover_propagate_g_error(error,err);
ali@45
   222
    g_object_unref(dir);
ali@42
   223
    return retval;
ali@42
   224
}
ali@42
   225
ali@44
   226
void plover__uri_handler_init(void)
ali@41
   227
{
ali@41
   228
    static gsize init=0;
ali@44
   229
    struct razor_uri_vtable uri_vtable={0,};
ali@41
   230
    if (g_once_init_enter(&init))
ali@41
   231
    {
ali@44
   232
	uri_vtable.structure_size=sizeof(uri_vtable);
ali@44
   233
	uri_vtable.mkdir=uri_mkdir;
ali@44
   234
	uri_vtable.unlink=uri_unlink;
ali@44
   235
	uri_vtable.move=uri_move;
ali@44
   236
	uri_vtable.get_contents=uri_get_contents;
ali@44
   237
	uri_vtable.free_contents=uri_free_contents;
ali@44
   238
	uri_vtable.is_directory=uri_is_directory;
ali@44
   239
	uri_vtable.opendir=uri_opendir;
ali@44
   240
	uri_vtable.readdir=uri_readdir;
ali@44
   241
	uri_vtable.closedir=uri_closedir;
ali@49
   242
	razor_uri_set_vtable(NULL,&uri_vtable,NULL);
ali@41
   243
	g_once_init_leave(&init,1);
ali@41
   244
    }
ali@41
   245
}