1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/pre-inst/post.c Tue Jul 14 18:03:26 2020 +0100
1.3 @@ -0,0 +1,198 @@
1.4 +/*
1.5 + * Copyright (C) 2020 J. Ali Harlow <ali@juiblex.co.uk>
1.6 + *
1.7 + * This program is free software; you can redistribute it and/or modify
1.8 + * it under the terms of the GNU General Public License as published by
1.9 + * the Free Software Foundation; either version 2 of the License, or
1.10 + * (at your option) any later version.
1.11 + *
1.12 + * This program is distributed in the hope that it will be useful,
1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.15 + * GNU General Public License for more details.
1.16 + *
1.17 + * You should have received a copy of the GNU General Public License along
1.18 + * with this program; if not, write to the Free Software Foundation, Inc.,
1.19 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1.20 + */
1.21 +
1.22 +#include <string.h>
1.23 +#include <glib.h>
1.24 +#include <expat.h>
1.25 +#include <razor.h>
1.26 +#include <plover/plover.h>
1.27 +#include "pre-inst/post.h"
1.28 +
1.29 +#define PLOVER_XML_NS "http://project.juiblex.co.uk/plover/ns/2009"
1.30 +
1.31 +enum post_state {
1.32 + POST_STATE_BEGIN,
1.33 + POST_STATE_ROOT,
1.34 + POST_STATE_ARGUMENT,
1.35 + POST_STATE_INSTALL_PREFIX,
1.36 + POST_STATE_REPOSITORY,
1.37 +};
1.38 +
1.39 +struct post_context {
1.40 + struct post *post;
1.41 + enum post_state state;
1.42 + int unknown_elements;
1.43 + GPtrArray *args;
1.44 + GString *str;
1.45 +};
1.46 +
1.47 +static void post_start_element(void *data,const char *name,const char **atts)
1.48 +{
1.49 + struct post_context *ctx=data;
1.50 + if (ctx->unknown_elements)
1.51 + ctx->unknown_elements++;
1.52 + else if (ctx->state==POST_STATE_BEGIN &&
1.53 + !strcmp(name,PLOVER_XML_NS "\xFF" "post"))
1.54 + ctx->state=POST_STATE_ROOT;
1.55 + else if (ctx->state==POST_STATE_ROOT &&
1.56 + !strcmp(name,PLOVER_XML_NS "\xFF" "command"))
1.57 + {
1.58 + ctx->state=POST_STATE_ARGUMENT;
1.59 + if (ctx->args->len>0)
1.60 + {
1.61 + ctx->str=g_ptr_array_index(ctx->args,0);
1.62 + g_string_truncate(ctx->str,0);
1.63 + }
1.64 + else
1.65 + {
1.66 + ctx->str=g_string_new(NULL);
1.67 + g_ptr_array_add(ctx->args,ctx->str);
1.68 + }
1.69 + }
1.70 + else if (ctx->state==POST_STATE_ROOT &&
1.71 + !strcmp(name,PLOVER_XML_NS "\xFF" "argument"))
1.72 + {
1.73 + ctx->state=POST_STATE_ARGUMENT;
1.74 + ctx->str=g_string_new(NULL);
1.75 + if (ctx->args->len==0)
1.76 + g_ptr_array_add(ctx->args,NULL);
1.77 + g_ptr_array_add(ctx->args,ctx->str);
1.78 + }
1.79 + else if (ctx->state==POST_STATE_ARGUMENT)
1.80 + {
1.81 + if (!strcmp(name,PLOVER_XML_NS "\xFF" "install-prefix"))
1.82 + ctx->state=POST_STATE_INSTALL_PREFIX;
1.83 + else if (!strcmp(name,PLOVER_XML_NS "\xFF" "repository"))
1.84 + ctx->state=POST_STATE_REPOSITORY;
1.85 + else
1.86 + ctx->unknown_elements++;
1.87 + }
1.88 + else
1.89 + ctx->unknown_elements++;
1.90 +}
1.91 +
1.92 +static void post_end_element(void *data,const char *name)
1.93 +{
1.94 + struct post_context *ctx=data;
1.95 + if (ctx->unknown_elements)
1.96 + ctx->unknown_elements--;
1.97 + else
1.98 + switch (ctx->state)
1.99 + {
1.100 + case POST_STATE_ROOT:
1.101 + ctx->state=POST_STATE_BEGIN;
1.102 + break;
1.103 + case POST_STATE_ARGUMENT:
1.104 + ctx->state=POST_STATE_ROOT;
1.105 + break;
1.106 + case POST_STATE_INSTALL_PREFIX:
1.107 + if (ctx->post->install_prefix)
1.108 + g_string_append(ctx->str,ctx->post->install_prefix);
1.109 + ctx->state=POST_STATE_ARGUMENT;
1.110 + break;
1.111 + case POST_STATE_REPOSITORY:
1.112 + if (ctx->post->repository)
1.113 + g_string_append(ctx->str,ctx->post->repository);
1.114 + ctx->state=POST_STATE_ARGUMENT;
1.115 + break;
1.116 + }
1.117 +}
1.118 +
1.119 +static void post_character_data(void *data,const XML_Char *s,int len)
1.120 +{
1.121 + struct post_context *ctx=data;
1.122 + switch (ctx->state)
1.123 + {
1.124 + case POST_STATE_ARGUMENT:
1.125 + g_string_append_len(ctx->str,s,len);
1.126 + break;
1.127 + }
1.128 +}
1.129 +
1.130 +struct post *pre_install_post_new(const char *repository,
1.131 + const char *install_prefix)
1.132 +{
1.133 + struct post *post;
1.134 + post=g_new0(struct post,1);
1.135 + post->repository=g_strdup(repository);
1.136 + post->install_prefix=g_strdup(install_prefix);
1.137 + return post;
1.138 +}
1.139 +
1.140 +void pre_install_post_free(struct post *post)
1.141 +{
1.142 + g_free(post->repository);
1.143 + g_free(post->install_prefix);
1.144 + g_free(post);
1.145 +}
1.146 +
1.147 +gboolean pre_install_post_load_uri(struct post *post,const char *uri,
1.148 + GError **error)
1.149 +{
1.150 + int i;
1.151 + gboolean retval;
1.152 + struct post_context ctx={0,};
1.153 + struct razor_error *tmp_error=NULL;
1.154 + size_t length;
1.155 + void *contents;
1.156 + XML_Parser parser;
1.157 + contents=razor_uri_get_contents(uri,&length,FALSE,&tmp_error);
1.158 + if (!contents)
1.159 + {
1.160 + plover_propagate_razor_error(error,tmp_error);
1.161 + return FALSE;
1.162 + }
1.163 + parser=XML_ParserCreateNS(NULL,'\xFF');
1.164 + ctx.post=post;
1.165 + ctx.state=POST_STATE_BEGIN;
1.166 + ctx.args=g_ptr_array_new();
1.167 + XML_SetUserData(parser,&ctx);
1.168 + XML_SetElementHandler(parser,post_start_element,post_end_element);
1.169 + XML_SetCharacterDataHandler(parser,post_character_data);
1.170 + retval=XML_Parse(parser,contents,length,TRUE)!=XML_STATUS_ERROR;
1.171 + if (!retval)
1.172 + g_set_error(error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
1.173 + "%s on line %d of '%s'\n",
1.174 + XML_ErrorString(XML_GetErrorCode(parser)),
1.175 + XML_GetCurrentLineNumber(parser),uri);
1.176 + XML_ParserFree(parser);
1.177 + razor_uri_free_contents(contents,length);
1.178 + if (retval)
1.179 + {
1.180 + if (ctx.args->len>0 && !g_ptr_array_index(ctx.args,0))
1.181 + g_warning("post: ignoring arguments because no command specified");
1.182 + if (post->argv)
1.183 + g_strfreev(post->argv);
1.184 + if (ctx.args->len>0 && g_ptr_array_index(ctx.args,0))
1.185 + {
1.186 + post->argc=ctx.args->len;
1.187 + post->argv=g_new(gchar *,post->argc+1);
1.188 + for(i=0;i<post->argc;i++)
1.189 + post->argv[i]=
1.190 + g_string_free(g_ptr_array_index(ctx.args,i),FALSE);
1.191 + post->argv[i]=NULL;
1.192 + }
1.193 + else
1.194 + {
1.195 + post->argc=0;
1.196 + post->argv=g_new0(gchar *,1);
1.197 + }
1.198 + g_ptr_array_free(ctx.args,FALSE);
1.199 + }
1.200 + return retval;
1.201 +}