ali@96: /* ali@96: * Copyright (C) 2020 J. Ali Harlow ali@96: * ali@96: * This program is free software; you can redistribute it and/or modify ali@96: * it under the terms of the GNU General Public License as published by ali@96: * the Free Software Foundation; either version 2 of the License, or ali@96: * (at your option) any later version. ali@96: * ali@96: * This program is distributed in the hope that it will be useful, ali@96: * but WITHOUT ANY WARRANTY; without even the implied warranty of ali@96: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ali@96: * GNU General Public License for more details. ali@96: * ali@96: * You should have received a copy of the GNU General Public License along ali@96: * with this program; if not, write to the Free Software Foundation, Inc., ali@96: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ali@96: */ ali@96: ali@96: #include ali@96: #include ali@96: #include ali@96: #include ali@96: #include ali@96: #include "pre-inst/post.h" ali@96: ali@96: #define PLOVER_XML_NS "http://project.juiblex.co.uk/plover/ns/2009" ali@96: ali@96: enum post_state { ali@96: POST_STATE_BEGIN, ali@96: POST_STATE_ROOT, ali@96: POST_STATE_ARGUMENT, ali@96: POST_STATE_INSTALL_PREFIX, ali@96: POST_STATE_REPOSITORY, ali@96: }; ali@96: ali@96: struct post_context { ali@96: struct post *post; ali@96: enum post_state state; ali@96: int unknown_elements; ali@96: GPtrArray *args; ali@96: GString *str; ali@96: }; ali@96: ali@96: static void post_start_element(void *data,const char *name,const char **atts) ali@96: { ali@96: struct post_context *ctx=data; ali@96: if (ctx->unknown_elements) ali@96: ctx->unknown_elements++; ali@96: else if (ctx->state==POST_STATE_BEGIN && ali@96: !strcmp(name,PLOVER_XML_NS "\xFF" "post")) ali@96: ctx->state=POST_STATE_ROOT; ali@96: else if (ctx->state==POST_STATE_ROOT && ali@96: !strcmp(name,PLOVER_XML_NS "\xFF" "command")) ali@96: { ali@96: ctx->state=POST_STATE_ARGUMENT; ali@96: if (ctx->args->len>0) ali@96: { ali@96: ctx->str=g_ptr_array_index(ctx->args,0); ali@96: g_string_truncate(ctx->str,0); ali@96: } ali@96: else ali@96: { ali@96: ctx->str=g_string_new(NULL); ali@96: g_ptr_array_add(ctx->args,ctx->str); ali@96: } ali@96: } ali@96: else if (ctx->state==POST_STATE_ROOT && ali@96: !strcmp(name,PLOVER_XML_NS "\xFF" "argument")) ali@96: { ali@96: ctx->state=POST_STATE_ARGUMENT; ali@96: ctx->str=g_string_new(NULL); ali@96: if (ctx->args->len==0) ali@96: g_ptr_array_add(ctx->args,NULL); ali@96: g_ptr_array_add(ctx->args,ctx->str); ali@96: } ali@96: else if (ctx->state==POST_STATE_ARGUMENT) ali@96: { ali@96: if (!strcmp(name,PLOVER_XML_NS "\xFF" "install-prefix")) ali@96: ctx->state=POST_STATE_INSTALL_PREFIX; ali@96: else if (!strcmp(name,PLOVER_XML_NS "\xFF" "repository")) ali@96: ctx->state=POST_STATE_REPOSITORY; ali@96: else ali@96: ctx->unknown_elements++; ali@96: } ali@96: else ali@96: ctx->unknown_elements++; ali@96: } ali@96: ali@96: static void post_end_element(void *data,const char *name) ali@96: { ali@96: struct post_context *ctx=data; ali@96: if (ctx->unknown_elements) ali@96: ctx->unknown_elements--; ali@96: else ali@96: switch (ctx->state) ali@96: { ali@96: case POST_STATE_ROOT: ali@96: ctx->state=POST_STATE_BEGIN; ali@96: break; ali@96: case POST_STATE_ARGUMENT: ali@96: ctx->state=POST_STATE_ROOT; ali@96: break; ali@96: case POST_STATE_INSTALL_PREFIX: ali@96: if (ctx->post->install_prefix) ali@96: g_string_append(ctx->str,ctx->post->install_prefix); ali@96: ctx->state=POST_STATE_ARGUMENT; ali@96: break; ali@96: case POST_STATE_REPOSITORY: ali@96: if (ctx->post->repository) ali@96: g_string_append(ctx->str,ctx->post->repository); ali@96: ctx->state=POST_STATE_ARGUMENT; ali@96: break; ali@96: } ali@96: } ali@96: ali@96: static void post_character_data(void *data,const XML_Char *s,int len) ali@96: { ali@96: struct post_context *ctx=data; ali@96: switch (ctx->state) ali@96: { ali@96: case POST_STATE_ARGUMENT: ali@96: g_string_append_len(ctx->str,s,len); ali@96: break; ali@96: } ali@96: } ali@96: ali@96: struct post *pre_install_post_new(const char *repository, ali@96: const char *install_prefix) ali@96: { ali@96: struct post *post; ali@96: post=g_new0(struct post,1); ali@96: post->repository=g_strdup(repository); ali@96: post->install_prefix=g_strdup(install_prefix); ali@96: return post; ali@96: } ali@96: ali@96: void pre_install_post_free(struct post *post) ali@96: { ali@96: g_free(post->repository); ali@96: g_free(post->install_prefix); ali@96: g_free(post); ali@96: } ali@96: ali@96: gboolean pre_install_post_load_uri(struct post *post,const char *uri, ali@96: GError **error) ali@96: { ali@96: int i; ali@96: gboolean retval; ali@96: struct post_context ctx={0,}; ali@96: struct razor_error *tmp_error=NULL; ali@96: size_t length; ali@96: void *contents; ali@96: XML_Parser parser; ali@96: contents=razor_uri_get_contents(uri,&length,FALSE,&tmp_error); ali@96: if (!contents) ali@96: { ali@96: plover_propagate_razor_error(error,tmp_error); ali@96: return FALSE; ali@96: } ali@96: parser=XML_ParserCreateNS(NULL,'\xFF'); ali@96: ctx.post=post; ali@96: ctx.state=POST_STATE_BEGIN; ali@96: ctx.args=g_ptr_array_new(); ali@96: XML_SetUserData(parser,&ctx); ali@96: XML_SetElementHandler(parser,post_start_element,post_end_element); ali@96: XML_SetCharacterDataHandler(parser,post_character_data); ali@96: retval=XML_Parse(parser,contents,length,TRUE)!=XML_STATUS_ERROR; ali@96: if (!retval) ali@96: g_set_error(error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED, ali@96: "%s on line %d of '%s'\n", ali@96: XML_ErrorString(XML_GetErrorCode(parser)), ali@96: XML_GetCurrentLineNumber(parser),uri); ali@96: XML_ParserFree(parser); ali@96: razor_uri_free_contents(contents,length); ali@96: if (retval) ali@96: { ali@96: if (ctx.args->len>0 && !g_ptr_array_index(ctx.args,0)) ali@96: g_warning("post: ignoring arguments because no command specified"); ali@96: if (post->argv) ali@96: g_strfreev(post->argv); ali@96: if (ctx.args->len>0 && g_ptr_array_index(ctx.args,0)) ali@96: { ali@96: post->argc=ctx.args->len; ali@96: post->argv=g_new(gchar *,post->argc+1); ali@96: for(i=0;iargc;i++) ali@96: post->argv[i]= ali@96: g_string_free(g_ptr_array_index(ctx.args,i),FALSE); ali@96: post->argv[i]=NULL; ali@96: } ali@96: else ali@96: { ali@96: post->argc=0; ali@96: post->argv=g_new0(gchar *,1); ali@96: } ali@96: g_ptr_array_free(ctx.args,FALSE); ali@96: } ali@96: return retval; ali@96: }