pre-inst/post.c
author J. Ali Harlow <ali@juiblex.co.uk>
Mon Aug 31 07:12:16 2020 +0100 (2020-08-31)
changeset 104 5cb36c12ac49
parent 96 d2d88f14283e
permissions -rw-r--r--
Prepare to release 0.6
     1 /*
     2  * Copyright (C) 2020  J. Ali Harlow <ali@juiblex.co.uk>
     3  *
     4  * This program is free software; you can redistribute it and/or modify
     5  * it under the terms of the GNU General Public License as published by
     6  * the Free Software Foundation; either version 2 of the License, or
     7  * (at your option) any later version.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License along
    15  * with this program; if not, write to the Free Software Foundation, Inc.,
    16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    17  */
    18 
    19 #include "config.h"
    20 #include <string.h>
    21 #include <glib.h>
    22 #include <expat.h>
    23 #include <razor.h>
    24 #include <plover/plover.h>
    25 #include "pre-inst/post.h"
    26 
    27 #define PLOVER_XML_NS "http://project.juiblex.co.uk/plover/ns/2009"
    28 
    29 enum post_state {
    30     POST_STATE_BEGIN,
    31     POST_STATE_ROOT,
    32     POST_STATE_ARGUMENT,
    33     POST_STATE_INSTALL_PREFIX,
    34     POST_STATE_REPOSITORY,
    35 };
    36 
    37 struct post_context {
    38     struct post *post;
    39     enum post_state state;
    40     int unknown_elements;
    41     GPtrArray *args;
    42     GString *str;
    43 };
    44 
    45 static void post_start_element(void *data,const char *name,const char **atts)
    46 {
    47     struct post_context *ctx=data;
    48     if (ctx->unknown_elements)
    49 	ctx->unknown_elements++;
    50     else if (ctx->state==POST_STATE_BEGIN &&
    51       !strcmp(name,PLOVER_XML_NS "\xFF" "post"))
    52 	ctx->state=POST_STATE_ROOT;
    53     else if (ctx->state==POST_STATE_ROOT &&
    54       !strcmp(name,PLOVER_XML_NS "\xFF" "command"))
    55     {
    56 	ctx->state=POST_STATE_ARGUMENT;
    57 	if (ctx->args->len>0)
    58 	{
    59 	    ctx->str=g_ptr_array_index(ctx->args,0);
    60 	    g_string_truncate(ctx->str,0);
    61 	}
    62 	else
    63 	{
    64 	    ctx->str=g_string_new(NULL);
    65 	    g_ptr_array_add(ctx->args,ctx->str);
    66 	}
    67     }
    68     else if (ctx->state==POST_STATE_ROOT &&
    69       !strcmp(name,PLOVER_XML_NS "\xFF" "argument"))
    70     {
    71 	ctx->state=POST_STATE_ARGUMENT;
    72 	ctx->str=g_string_new(NULL);
    73 	if (ctx->args->len==0)
    74 	    g_ptr_array_add(ctx->args,NULL);
    75 	g_ptr_array_add(ctx->args,ctx->str);
    76     }
    77     else if (ctx->state==POST_STATE_ARGUMENT)
    78     {
    79 	if (!strcmp(name,PLOVER_XML_NS "\xFF" "install-prefix"))
    80 	    ctx->state=POST_STATE_INSTALL_PREFIX;
    81 	else if (!strcmp(name,PLOVER_XML_NS "\xFF" "repository"))
    82 	    ctx->state=POST_STATE_REPOSITORY;
    83 	else
    84 	    ctx->unknown_elements++;
    85     }
    86     else
    87 	ctx->unknown_elements++;
    88 }
    89 
    90 static void post_end_element(void *data,const char *name)
    91 {
    92     struct post_context *ctx=data;
    93     if (ctx->unknown_elements)
    94 	ctx->unknown_elements--;
    95     else
    96 	switch (ctx->state)
    97 	{
    98 	    case POST_STATE_BEGIN:
    99 		g_assert_not_reached();
   100 		break;
   101 	    case POST_STATE_ROOT:
   102 		ctx->state=POST_STATE_BEGIN;
   103 		break;
   104 	    case POST_STATE_ARGUMENT:
   105 		ctx->state=POST_STATE_ROOT;
   106 		break;
   107 	    case POST_STATE_INSTALL_PREFIX:
   108 		if (ctx->post->install_prefix)
   109 		    g_string_append(ctx->str,ctx->post->install_prefix);
   110 		ctx->state=POST_STATE_ARGUMENT;
   111 		break;
   112 	    case POST_STATE_REPOSITORY:
   113 		if (ctx->post->repository)
   114 		    g_string_append(ctx->str,ctx->post->repository);
   115 		ctx->state=POST_STATE_ARGUMENT;
   116 		break;
   117 	}
   118 }
   119 
   120 static void post_character_data(void *data,const XML_Char *s,int len)
   121 {
   122     struct post_context *ctx=data;
   123     switch (ctx->state)
   124     {
   125 	case POST_STATE_ARGUMENT:
   126 	    g_string_append_len(ctx->str,s,len);
   127 	    break;
   128 	default:
   129 	    break;
   130     }
   131 }
   132 
   133 struct post *pre_install_post_new(const char *repository,
   134   const char *install_prefix)
   135 {
   136     struct post *post;
   137     post=g_new0(struct post,1);
   138     post->repository=g_strdup(repository);
   139     post->install_prefix=g_strdup(install_prefix);
   140     return post;
   141 }
   142 
   143 void pre_install_post_free(struct post *post)
   144 {
   145     g_free(post->repository);
   146     g_free(post->install_prefix);
   147     g_free(post);
   148 }
   149 
   150 gboolean pre_install_post_load_uri(struct post *post,const char *uri,
   151   GError **error)
   152 {
   153     int i;
   154     gboolean retval;
   155     struct post_context ctx={0,};
   156     struct razor_error *tmp_error=NULL;
   157     size_t length;
   158     void *contents;
   159     XML_Parser parser;
   160     contents=razor_uri_get_contents(uri,&length,FALSE,&tmp_error);
   161     if (!contents)
   162     {
   163 	plover_propagate_razor_error(error,tmp_error);
   164 	return FALSE;
   165     }
   166     parser=XML_ParserCreateNS(NULL,'\xFF');
   167     ctx.post=post;
   168     ctx.state=POST_STATE_BEGIN;
   169     ctx.args=g_ptr_array_new();
   170     XML_SetUserData(parser,&ctx);
   171     XML_SetElementHandler(parser,post_start_element,post_end_element);
   172     XML_SetCharacterDataHandler(parser,post_character_data);
   173     retval=XML_Parse(parser,contents,length,TRUE)!=XML_STATUS_ERROR;
   174     if (!retval)
   175 	g_set_error(error,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_FAILED,
   176 	  "%s on line %lu of '%s'\n",
   177 	  XML_ErrorString(XML_GetErrorCode(parser)),
   178 	  (unsigned long)XML_GetCurrentLineNumber(parser),uri);
   179     XML_ParserFree(parser);
   180     razor_uri_free_contents(contents,length);
   181     if (retval)
   182     {
   183 	if (ctx.args->len>0 && !g_ptr_array_index(ctx.args,0))
   184 	    g_warning("post: ignoring arguments because no command specified");
   185 	if (post->argv)
   186 	    g_strfreev(post->argv);
   187 	if (ctx.args->len>0 && g_ptr_array_index(ctx.args,0))
   188 	{
   189 	    post->argc=ctx.args->len;
   190 	    post->argv=g_new(gchar *,post->argc+1);
   191 	    for(i=0;i<post->argc;i++)
   192 		post->argv[i]=
   193 		  g_string_free(g_ptr_array_index(ctx.args,i),FALSE);
   194 	    post->argv[i]=NULL;
   195 	}
   196 	else
   197 	{
   198 	    post->argc=0;
   199 	    post->argv=g_new0(gchar *,1);
   200 	}
   201 	g_ptr_array_free(ctx.args,FALSE);
   202     }
   203     return retval;
   204 }