diff -r 000000000000 -r d2d88f14283e pre-inst/post.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pre-inst/post.c Wed Jul 15 11:54:06 2020 +0100 @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2020 J. Ali Harlow + * + * 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. + * + * 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. + * + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include +#include +#include "pre-inst/post.h" + +#define PLOVER_XML_NS "http://project.juiblex.co.uk/plover/ns/2009" + +enum post_state { + POST_STATE_BEGIN, + POST_STATE_ROOT, + POST_STATE_ARGUMENT, + POST_STATE_INSTALL_PREFIX, + POST_STATE_REPOSITORY, +}; + +struct post_context { + struct post *post; + enum post_state state; + int unknown_elements; + GPtrArray *args; + GString *str; +}; + +static void post_start_element(void *data,const char *name,const char **atts) +{ + struct post_context *ctx=data; + if (ctx->unknown_elements) + ctx->unknown_elements++; + else if (ctx->state==POST_STATE_BEGIN && + !strcmp(name,PLOVER_XML_NS "\xFF" "post")) + ctx->state=POST_STATE_ROOT; + else if (ctx->state==POST_STATE_ROOT && + !strcmp(name,PLOVER_XML_NS "\xFF" "command")) + { + ctx->state=POST_STATE_ARGUMENT; + if (ctx->args->len>0) + { + ctx->str=g_ptr_array_index(ctx->args,0); + g_string_truncate(ctx->str,0); + } + else + { + ctx->str=g_string_new(NULL); + g_ptr_array_add(ctx->args,ctx->str); + } + } + else if (ctx->state==POST_STATE_ROOT && + !strcmp(name,PLOVER_XML_NS "\xFF" "argument")) + { + ctx->state=POST_STATE_ARGUMENT; + ctx->str=g_string_new(NULL); + if (ctx->args->len==0) + g_ptr_array_add(ctx->args,NULL); + g_ptr_array_add(ctx->args,ctx->str); + } + else if (ctx->state==POST_STATE_ARGUMENT) + { + if (!strcmp(name,PLOVER_XML_NS "\xFF" "install-prefix")) + ctx->state=POST_STATE_INSTALL_PREFIX; + else if (!strcmp(name,PLOVER_XML_NS "\xFF" "repository")) + ctx->state=POST_STATE_REPOSITORY; + else + ctx->unknown_elements++; + } + else + ctx->unknown_elements++; +} + +static void post_end_element(void *data,const char *name) +{ + struct post_context *ctx=data; + if (ctx->unknown_elements) + ctx->unknown_elements--; + else + switch (ctx->state) + { + case POST_STATE_ROOT: + ctx->state=POST_STATE_BEGIN; + break; + case POST_STATE_ARGUMENT: + ctx->state=POST_STATE_ROOT; + break; + case POST_STATE_INSTALL_PREFIX: + if (ctx->post->install_prefix) + g_string_append(ctx->str,ctx->post->install_prefix); + ctx->state=POST_STATE_ARGUMENT; + break; + case POST_STATE_REPOSITORY: + if (ctx->post->repository) + g_string_append(ctx->str,ctx->post->repository); + ctx->state=POST_STATE_ARGUMENT; + break; + } +} + +static void post_character_data(void *data,const XML_Char *s,int len) +{ + struct post_context *ctx=data; + switch (ctx->state) + { + case POST_STATE_ARGUMENT: + g_string_append_len(ctx->str,s,len); + break; + } +} + +struct post *pre_install_post_new(const char *repository, + const char *install_prefix) +{ + struct post *post; + post=g_new0(struct post,1); + post->repository=g_strdup(repository); + post->install_prefix=g_strdup(install_prefix); + return post; +} + +void pre_install_post_free(struct post *post) +{ + g_free(post->repository); + g_free(post->install_prefix); + g_free(post); +} + +gboolean pre_install_post_load_uri(struct post *post,const char *uri, + GError **error) +{ + int i; + gboolean retval; + struct post_context ctx={0,}; + struct razor_error *tmp_error=NULL; + size_t length; + void *contents; + XML_Parser parser; + contents=razor_uri_get_contents(uri,&length,FALSE,&tmp_error); + if (!contents) + { + plover_propagate_razor_error(error,tmp_error); + return FALSE; + } + parser=XML_ParserCreateNS(NULL,'\xFF'); + ctx.post=post; + ctx.state=POST_STATE_BEGIN; + ctx.args=g_ptr_array_new(); + XML_SetUserData(parser,&ctx); + XML_SetElementHandler(parser,post_start_element,post_end_element); + XML_SetCharacterDataHandler(parser,post_character_data); + retval=XML_Parse(parser,contents,length,TRUE)!=XML_STATUS_ERROR; + if (!retval) + g_set_error(error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED, + "%s on line %d of '%s'\n", + XML_ErrorString(XML_GetErrorCode(parser)), + XML_GetCurrentLineNumber(parser),uri); + XML_ParserFree(parser); + razor_uri_free_contents(contents,length); + if (retval) + { + if (ctx.args->len>0 && !g_ptr_array_index(ctx.args,0)) + g_warning("post: ignoring arguments because no command specified"); + if (post->argv) + g_strfreev(post->argv); + if (ctx.args->len>0 && g_ptr_array_index(ctx.args,0)) + { + post->argc=ctx.args->len; + post->argv=g_new(gchar *,post->argc+1); + for(i=0;iargc;i++) + post->argv[i]= + g_string_free(g_ptr_array_index(ctx.args,i),FALSE); + post->argv[i]=NULL; + } + else + { + post->argc=0; + post->argv=g_new0(gchar *,1); + } + g_ptr_array_free(ctx.args,FALSE); + } + return retval; +}