~ubuntu-branches/ubuntu/wily/steam/wily

« back to all changes in this revision

Viewing changes to sources/libxslt/xslt.c

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2013-10-29 19:51:18 UTC
  • mfrom: (1.1.4) (0.1.4 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20131029195118-b9bxciz5hwx5z459
Tags: 1:1.0.0.39-2ubuntu1
Add an epoch to the version number as there was an unrelated steam package
in the archive with a higher version number.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2004  Thomas Bopp, Thorsten Hampel, Ludger Merkens
2
 
 *
3
 
 *  This program is free software; you can redistribute it and/or modify
4
 
 *  it under the terms of the GNU General Public License as published by
5
 
 *  the Free Software Foundation; either version 2 of the License, or
6
 
 *  (at your option) any later version.
7
 
 *
8
 
 *  This program is distributed in the hope that it will be useful,
9
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
 *  GNU General Public License for more details.
12
 
 *
13
 
 *  You should have received a copy of the GNU General Public License
14
 
 *  along with this program; if not, write to the Free Software
15
 
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
 
 * 
17
 
 * $Id: xslt.c,v 1.1.1.1 2006/03/27 12:40:19 exodusd Exp $
18
 
 */
19
 
 
20
 
#include <string.h>
21
 
#include <stdarg.h>
22
 
#include <libxml/xmlmemory.h>
23
 
#include <libxml/debugXML.h>
24
 
#include <libxml/HTMLtree.h>
25
 
#include <libxml/xmlIO.h>
26
 
#include <libxml/DOCBparser.h>
27
 
#include <libxml/xinclude.h>
28
 
#include <libxml/catalog.h>
29
 
#include <libxml/xmlversion.h>
30
 
#include <libxslt/xslt.h>
31
 
#include <libxslt/xsltInternals.h>
32
 
#include <libxslt/transform.h>
33
 
#include <libxslt/xsltutils.h>
34
 
#include <libxslt/xsltconfig.h>
35
 
 
36
 
 
37
 
#include "global.h"
38
 
#include "interpret.h"
39
 
#include "stralloc.h"
40
 
#include "pike_macros.h"
41
 
#include "module_support.h"
42
 
#include "mapping.h"
43
 
#include "threads.h"
44
 
 
45
 
#include <stdio.h>
46
 
#include <fcntl.h>
47
 
 
48
 
#include "xslt.h"
49
 
#include "xml_dom.h"
50
 
 
51
 
//#define XSLT_DEBUG 1
52
 
 
53
 
#ifdef XSLT_DEBUG
54
 
#define DEBUG_XSLT(d) fprintf(stderr, d)
55
 
#else
56
 
#define DEBUG_XSLT(d)
57
 
#endif
58
 
 
59
 
extern int xmlLoadExtDtdDefaultValue;
60
 
xmlExternalEntityLoader defaultLoader = NULL;
61
 
 
62
 
int xslWasInit;
63
 
struct program *xslt_program=NULL;
64
 
struct program *stylesheet_program=NULL;
65
 
 
66
 
//! Free the allocated xslt storage
67
 
//!
68
 
//!
69
 
static void free_xslt_storage(struct object *o)
70
 
{
71
 
    if(THIS->base_uri != NULL)  free_string(THIS->base_uri);
72
 
    if(THIS->variables != NULL) free_mapping(THIS->variables);
73
 
    if(THIS->xml != NULL)       free_string(THIS->xml);
74
 
    if(THIS->language != NULL)       free_string(THIS->language);
75
 
    if(THIS->charset)           free(THIS->charset);
76
 
    if(THIS->content_type)      free(THIS->content_type);
77
 
    if(THIS->stylesheet != NULL ) xsltFreeStylesheet(THIS->stylesheet);
78
 
    if(THIS->match_include != NULL ) free_svalue(THIS->match_include);
79
 
    if(THIS->open_include != NULL ) free_svalue(THIS->open_include);
80
 
    if(THIS->read_include != NULL ) free_svalue(THIS->read_include);
81
 
    if(THIS->close_include != NULL ) free_svalue(THIS->close_include);
82
 
    if(THIS->file != NULL ) free_object(THIS->file);
83
 
 
84
 
    MEMSET(THIS, 0, sizeof(xslt_storage));
85
 
}
86
 
 
87
 
//!
88
 
//! Free the stylesheet storage when the object is destructed
89
 
//!
90
 
static void free_stylesheet_storage(struct object *o)
91
 
{
92
 
    stylesheet_storage* store = (stylesheet_storage*)o->storage;
93
 
    
94
 
    MEMSET(store, 0, sizeof(stylesheet_storage));
95
 
}
96
 
 
97
 
//!
98
 
//! Initialization routine for the storage
99
 
//!
100
 
static void init_xslt_storage(struct object *o)
101
 
{
102
 
    MEMSET(o->storage, 0, sizeof(xslt_storage));
103
 
}
104
 
 
105
 
//!
106
 
//! Initialization for the stylesheet storage.
107
 
//!
108
 
static void init_stylesheet_storage(struct object *o)
109
 
{
110
 
    MEMSET(o->storage, 0, sizeof(stylesheet_storage));
111
 
}
112
 
 
113
 
//!
114
 
//! Creation function for the Parser object.
115
 
//!
116
 
void f_create(INT32 args)
117
 
{
118
 
    pop_n_elems(args);
119
 
}
120
 
 
121
 
//!
122
 
//! Set the xml Data for the transformation.
123
 
//!
124
 
void f_set_xml_data(INT32 args)
125
 
{
126
 
    struct pike_string* xml_data;
127
 
 
128
 
    if ( args != 1 )
129
 
        Pike_error("XSLT.Parser()->set_xml_data: Expected one argument.\n");
130
 
 
131
 
    if( THIS->xml != NULL ) 
132
 
        free_string(THIS->xml);
133
 
    if ( THIS->err_str != NULL ) {
134
 
        free_string(THIS->err_str);
135
 
        THIS->err_str = NULL;
136
 
    }
137
 
    THREADS_ALLOW();
138
 
    THREADS_DISALLOW();
139
 
    
140
 
    switch ( ARG(1).type ) {
141
 
    case T_STRING:
142
 
        xmlSetGenericErrorFunc(THIS, xml_error);
143
 
        xml_data = Pike_sp[-args].u.string;
144
 
        //add_ref(THIS->xml);
145
 
        THIS->doc = xmlParseMemory(xml_data->str, xml_data->len);
146
 
        if ( THIS->err_str != NULL ) {
147
 
            // only free doc at this point
148
 
            xmlFreeDoc(THIS->doc);
149
 
            Pike_error(THIS->err_str->str);
150
 
        }
151
 
        break;
152
 
    case T_OBJECT:
153
 
        CHECK_DOM(Pike_sp[0-1].u.object);
154
 
        add_ref(Pike_sp[0-1].u.object);
155
 
        THIS->doc = OBJ2_DOM(Pike_sp[0-1].u.object)->domDoc;
156
 
        break;
157
 
    default:
158
 
        Pike_error("XSLT.Parser()->set_xml_data: Expected string|object.\n");
159
 
    }
160
 
 
161
 
 
162
 
    
163
 
    pop_n_elems(args);    
164
 
}
165
 
 
166
 
 
167
 
//!
168
 
//! Set the variables used for transformation.
169
 
//!
170
 
void f_set_variables(INT32 args)
171
 
{
172
 
    if ( args != 1 )
173
 
        Pike_error("XSLT.Parser()->set_variables: Expected one argument.\n");
174
 
    if ( Pike_sp[-args].type != T_MAPPING )
175
 
        Pike_error("XSLT.Parser()->set_variables: Expected Mapping\n");
176
 
    if ( THIS->variables != NULL )
177
 
        free_mapping(THIS->variables);
178
 
    THIS->variables = Pike_sp[-args].u.mapping;
179
 
    add_ref(THIS->variables);
180
 
    pop_n_elems(args);
181
 
}
182
 
 
183
 
//!
184
 
//! @param
185
 
//!
186
 
void xsl_error(void* ctx, const char* msg, ...) {
187
 
    va_list args;
188
 
    char buf[1024];
189
 
    char out[2048] = { 0 };
190
 
    xslt_storage* store = (xslt_storage*) ctx;
191
 
 
192
 
 
193
 
    DEBUG_XSLT("xsl_error()\n");
194
 
    if ( ctx == NULL ) {
195
 
        fprintf(stderr, "No error context, error: %s\n", msg);
196
 
        return;
197
 
    } 
198
 
    if ( msg == NULL ) {
199
 
      fprintf(stderr, "xsl_error() with no messages !");
200
 
      return;
201
 
    }
202
 
      
203
 
    va_start(args, msg);
204
 
    vfprintf(stderr, msg, args);
205
 
    va_end(args);
206
 
 
207
 
    THREADS_ALLOW();
208
 
    THREADS_DISALLOW();
209
 
    
210
 
    va_start(args, msg);
211
 
    vsnprintf(buf, 1023, msg, args);
212
 
    va_end(args);    
213
 
    buf[1023] = 0;
214
 
 
215
 
    if ( store->err_str != NULL ) {
216
 
        if ( strlen(buf) + strlen(store->err_str->str) < 2048 ) 
217
 
            strcat(out, store->err_str->str);
218
 
        free_string(store->err_str);
219
 
    }
220
 
    strcat(out, buf);
221
 
 
222
 
    store->err_str = make_shared_string(&out[0]);
223
 
    add_ref(store->err_str);
224
 
    DEBUG_XSLT("leaving xsl_error() with:\n");
225
 
    DEBUG_XSLT(out);
226
 
    DEBUG_XSLT("----\n");
227
 
}
228
 
 
229
 
//!
230
 
//! Error function
231
 
//!
232
 
void xml_error(void* ctx, const char* msg, ...) {
233
 
    va_list args;
234
 
    char buf[1024];
235
 
    char out[2048] = { 0 };
236
 
    xslt_storage* store = (xslt_storage*) ctx;
237
 
 
238
 
    DEBUG_XSLT("xml_error()\n");
239
 
    DEBUG_XSLT(msg);
240
 
    if ( ctx == NULL ) {
241
 
        fprintf(stderr, "No error context, error: %s\n", msg);
242
 
        return;
243
 
    }
244
 
    THREADS_ALLOW();
245
 
    THREADS_DISALLOW();
246
 
    
247
 
    va_start(args, msg);
248
 
    vsnprintf(buf, 1023, msg, args);
249
 
    va_end(args);    
250
 
    buf[1023] = 0;
251
 
 
252
 
    if ( store->err_str != NULL ) {
253
 
        if ( strlen(buf) + strlen(store->err_str->str) < 2048 ) 
254
 
            strcat(out, store->err_str->str);
255
 
        free_string(store->err_str);
256
 
    }
257
 
    strcat(out, buf);
258
 
    DEBUG_XSLT("leaving xml_error():\n");
259
 
    DEBUG_XSLT(out);
260
 
    store->err_str = make_shared_string(&out[0]);
261
 
    add_ref(store->err_str);
262
 
}
263
 
 
264
 
#define MAX_PARAMS 100
265
 
 
266
 
//!
267
 
//! @param
268
 
//!
269
 
static void f_run( INT32 args )
270
 
{
271
 
    xsltStylesheetPtr cur = NULL;
272
 
    xmlDocPtr           doc, res;
273
 
    char        *xmlstr, *xslstr;
274
 
    xmlOutputBufferPtr    xmlBuf;
275
 
    struct keypair            *k;
276
 
    int           success, count;
277
 
    char*           resultBuffer;
278
 
    int              varcount, i;
279
 
    xmlChar*               value;
280
 
    const xmlChar*           str;
281
 
 
282
 
    char **vars            = NULL; // variables
283
 
    xmlChar* params[MAX_PARAMS+1];
284
 
    
285
 
    if ( args != 1 || Pike_sp[-args].type != T_OBJECT )
286
 
        Pike_error("XSLT.Parser->run(): requires XSL Stylesheet parameter.\n");
287
 
 
288
 
    if ( THIS->doc == NULL ) {
289
 
        Pike_error("XML input not set correctly.\n");
290
 
    }
291
 
    if ( THIS->err_str != NULL ) {
292
 
        free_string(THIS->err_str);
293
 
        THIS->err_str = NULL;
294
 
    }
295
 
    THREADS_ALLOW();
296
 
    THREADS_DISALLOW();
297
 
    
298
 
    DEBUG_XSLT("Running XSL transformation\n");
299
 
 
300
 
#if 0
301
 
    xmlstr = THIS->xml->str;
302
 
    if ( THIS->xml->len == 0 ) {
303
 
        Pike_error("No XML code given - cannot transform.\n");
304
 
        return;
305
 
    }
306
 
#endif
307
 
    doc = THIS->doc;
308
 
 
309
 
    if ( doc == NULL ) {
310
 
        Pike_error("Unable to parse xml source.\n");
311
 
    }
312
 
    xmlSetGenericErrorFunc(NULL, NULL);
313
 
    
314
 
    xsltSetGenericErrorFunc(THIS, xsl_error);
315
 
    // top object!
316
 
    cur = ((xslt_storage*)Pike_sp[-args].u.object->storage)->stylesheet; 
317
 
 
318
 
    if ( THIS->variables != NULL ) 
319
 
    {
320
 
        struct svalue sind, sval;
321
 
        int             tmpint=0;
322
 
      
323
 
        varcount = 0;
324
 
        vars = malloc( sizeof(char *) * 
325
 
                       ( 1 + ((m_sizeof(THIS->variables)) * 2 )));
326
 
        MY_MAPPING_LOOP(THIS->variables, count, k)  {
327
 
            sind = k->ind;
328
 
            sval = k->val;
329
 
            if(!(sind.type == T_STRING && sval.type == T_STRING)) {
330
 
                continue;
331
 
            }
332
 
            // index
333
 
 
334
 
            str  = (const xmlChar *) sval.u.string->str;
335
 
            if ( xmlStrstr(str, (xmlChar*) "\n") == NULL ) 
336
 
            {
337
 
                if ( xmlStrchr(str, '"') ) {
338
 
                    if (xmlStrchr(str, '\'')) {
339
 
                        xmlFreeDoc(doc);
340
 
                        Pike_error("Param contains quote and double-quotes.");
341
 
                        return;    
342
 
                    }
343
 
                    value = xmlStrdup((const xmlChar *)"'");
344
 
                    value = xmlStrcat(value, str);
345
 
                    value = xmlStrcat(value, (const xmlChar *)"'");
346
 
                } else {
347
 
                    value = xmlStrdup((const xmlChar *)"\"");
348
 
                    value = xmlStrcat(value, str);
349
 
                    value = xmlStrcat(value, (const xmlChar *)"\"");
350
 
                }
351
 
                
352
 
            }
353
 
            else {
354
 
                // param contains newlines
355
 
                value = xmlStrdup((const xmlChar *)"\"");
356
 
                value = xmlStrcat(value, (const xmlChar *)"\"");
357
 
            }
358
 
            
359
 
            str = (const xmlChar*) sind.u.string->str;
360
 
            // namespaces are bad
361
 
            if ( xmlStrchr(str, ':') ) {
362
 
                Pike_error("Invalid Parameter %s in namespace format !",
363
 
                           str);
364
 
            }
365
 
            else {
366
 
                vars[tmpint++] = sind.u.string->str;
367
 
            }
368
 
            vars[tmpint++] = value;
369
 
            params[varcount++] = value;
370
 
            if ( varcount > MAX_PARAMS )
371
 
                Pike_error("Too many params !");
372
 
        }
373
 
        vars[tmpint] = NULL;
374
 
    }
375
 
    else {
376
 
        vars = malloc(sizeof(char *));
377
 
        vars[0] = NULL;
378
 
        varcount = 0;
379
 
    }
380
 
    DEBUG_XSLT("Applying stylesheet!\n");
381
 
    res = xsltApplyStylesheet(cur, doc, vars);
382
 
    if ( THIS->err_str != NULL ) {
383
 
        // only free doc at this point
384
 
        xmlFreeDoc(doc);
385
 
        Pike_error(THIS->err_str->str);
386
 
    }
387
 
    DEBUG_XSLT("Preparing output buffer !\n");
388
 
    
389
 
    // find out the encoding and use EncodingHandler
390
 
    if ( cur->encoding != NULL && strcmp(cur->encoding, "iso-8859-1") == 0 ) 
391
 
    {
392
 
      xmlBuf = xmlAllocOutputBuffer(
393
 
                          xmlGetCharEncodingHandler((xmlCharEncoding)10));
394
 
    }
395
 
    else
396
 
    {
397
 
      // utf-8 does not required a handler
398
 
      xmlBuf = xmlAllocOutputBuffer(NULL);
399
 
    }
400
 
    
401
 
    xsltSaveResultTo( xmlBuf, res, cur );
402
 
 
403
 
 
404
 
    if ( THIS->err_str != NULL ) {
405
 
        Pike_error(THIS->err_str->str);
406
 
    }
407
 
    else {
408
 
        pop_n_elems(args);
409
 
        if ( cur->encoding != NULL && strcmp(cur->encoding,"iso-8859-1") == 0 )
410
 
        {
411
 
          resultBuffer = malloc(strlen(xmlBuf->conv->content)+1);
412
 
          strcpy(resultBuffer, xmlBuf->conv->content);
413
 
          push_text(resultBuffer);
414
 
          free(resultBuffer);
415
 
        }
416
 
        else
417
 
          push_text(xmlBuf->buffer->content);
418
 
    }
419
 
    xmlOutputBufferClose(xmlBuf);
420
 
    xmlFreeDoc(res);
421
 
    xmlFreeDoc(doc);
422
 
    
423
 
    free(vars);
424
 
    for ( i = 0; i < varcount; i++ )
425
 
        xmlFree(params[i]);
426
 
 
427
 
    if ( THIS->variables != NULL ) {
428
 
        free_mapping(THIS->variables);
429
 
        THIS->variables = NULL;
430
 
    }
431
 
    xsltCleanupGlobals();
432
 
    xmlCleanupParser();
433
 
    xmlMemoryDump();
434
 
    DEBUG_XSLT("done...\n");
435
 
}
436
 
 
437
 
//!
438
 
//! Get the libxml2 Version-
439
 
//!
440
 
void f_get_version(INT32 args)
441
 
{
442
 
    char *result = malloc(200);
443
 
    
444
 
    sprintf(result, "libxml %s, libxslt %s", 
445
 
            LIBXML_DOTTED_VERSION, LIBXSLT_DOTTED_VERSION);
446
 
 
447
 
    pop_n_elems(args);
448
 
    push_text(result);
449
 
}
450
 
 
451
 
 
452
 
 
453
 
//!
454
 
//! Create a new Stylesheet object and set the initial error function.
455
 
//!
456
 
void f_create_stylesheet(INT32 args)
457
 
{
458
 
    if ( THIS->err_str != NULL ) {
459
 
        free_string(THIS->err_str);
460
 
        THIS->err_str = NULL;
461
 
    }
462
 
    pop_n_elems(args);
463
 
}
464
 
 
465
 
int xmlInputRead(void* context, char* buffer, int len)
466
 
{
467
 
  
468
 
}
469
 
 
470
 
 
471
 
//!
472
 
//! Set the function to be called when parsing xsl:include tags.
473
 
//!
474
 
void f_set_include_callbacks(INT32 args)
475
 
{
476
 
  int i;
477
 
  if ( args != 4 )
478
 
    Pike_error("XSLT.Parser()->set_include_callbacks(): Expected four arguments (functions: match, open, read, close).\n");
479
 
  for ( i = 0; i < 4; i++ )
480
 
  if ( Pike_sp[-args+i].type != T_FUNCTION )
481
 
      Pike_error("Arguments must be function pointers !\n");
482
 
  
483
 
 
484
 
  if ( THIS->match_include != NULL )
485
 
    free_svalue(THIS->match_include);
486
 
  if ( THIS->open_include != NULL )
487
 
    free_svalue(THIS->open_include);
488
 
  if ( THIS->read_include != NULL )
489
 
    free_svalue(THIS->read_include);
490
 
  if ( THIS->close_include != NULL )
491
 
    free_svalue(THIS->close_include);
492
 
 
493
 
  THIS->match_include = malloc(sizeof(struct svalue));
494
 
  THIS->open_include = malloc(sizeof(struct svalue));
495
 
  THIS->read_include = malloc(sizeof(struct svalue));
496
 
  THIS->close_include = malloc(sizeof(struct svalue));
497
 
  
498
 
  assign_svalue_no_free(THIS->match_include, &Pike_sp[-4]);
499
 
  assign_svalue_no_free(THIS->open_include, &Pike_sp[-3]);
500
 
  assign_svalue_no_free(THIS->read_include, &Pike_sp[-2]);
501
 
  assign_svalue_no_free(THIS->close_include, &Pike_sp[-1]);
502
 
  pop_n_elems(args);
503
 
}
504
 
 
505
 
//!
506
 
//! Set a language for the Stylesheet.
507
 
//!
508
 
void f_set_language(INT32 args)
509
 
{
510
 
    struct pike_string* str;
511
 
 
512
 
    if ( args != 1 )
513
 
        Pike_error("XSLT.Stylesheeet->f_set_language(): Expected string.\n");
514
 
    if ( Pike_sp[-args].type != T_STRING )
515
 
        Pike_error("Argument must be the language string !\n");
516
 
    str = (struct pike_string*)Pike_sp[-args].u.string;
517
 
    THAT->language = str;
518
 
    add_ref(THAT->language);
519
 
    pop_n_elems(args);
520
 
    DEBUG_XSLT("Language set to ");
521
 
    DEBUG_XSLT(str->str);
522
 
    DEBUG_XSLT("\n");
523
 
}
524
 
 
525
 
 
526
 
//!
527
 
//! xsl:include callback registered to xslt. Only matches steam://
528
 
//!
529
 
int _include_match(const char* filename)
530
 
{
531
 
  int match;
532
 
  
533
 
  if ( THIS->match_include == NULL ) {
534
 
    DEBUG_XSLT("No include resolve callback !");
535
 
    return 0;
536
 
  }
537
 
  push_text(filename);
538
 
  apply_svalue(THIS->match_include, 1);
539
 
  
540
 
  if ( Pike_sp[-1].type != T_INT ) {
541
 
    pop_stack();
542
 
    return 0;
543
 
  }
544
 
  match = Pike_sp[-1].u.integer == 1;
545
 
  pop_stack();
546
 
  return match;
547
 
}
548
 
 
549
 
//!
550
 
//! Include open callback function.
551
 
//!
552
 
void * _include_open(const char* filename)
553
 
{
554
 
    struct object*    obj;
555
 
 
556
 
    if ( THIS->open_include == NULL )
557
 
      return 0;
558
 
    
559
 
    push_text(filename);
560
 
    apply_svalue(THIS->open_include, 1);
561
 
 
562
 
    if ( Pike_sp[-1].type == T_INT ) {
563
 
        pop_stack();
564
 
        return 0;
565
 
    }
566
 
    obj = Pike_sp[-1].u.object;
567
 
 
568
 
    if ( THIS->file != NULL )
569
 
        free_object(THIS->file);
570
 
    
571
 
    THIS->file = obj;
572
 
    add_ref(THIS->file);
573
 
    THIS->iPosition = 0;
574
 
 
575
 
    pop_stack();
576
 
    return THIS;
577
 
}
578
 
 
579
 
//!
580
 
//! Read from the opened include file. 
581
 
//!
582
 
int _include_read(void* context, char* buffer, int len)
583
 
{
584
 
    int result;
585
 
    THREAD_SAFE_RUN(result=f_include_read(context, buffer, len));
586
 
    return result;
587
 
}
588
 
 
589
 
 
590
 
//!
591
 
//! Read the content
592
 
//!
593
 
int f_include_read(void* context, char* buffer, int len)
594
 
{
595
 
    struct pike_string* str;
596
 
 
597
 
 
598
 
    if ( THIS->read_include == NULL )
599
 
        return 0;
600
 
 
601
 
    add_ref(THIS->file); // somehow the function call makes it loose refs
602
 
    push_object(THIS->file);
603
 
    if ( THAT->language == NULL )
604
 
        push_text("english");
605
 
    else {
606
 
        push_string(THAT->language);
607
 
        add_ref(THAT->language);
608
 
    }
609
 
 
610
 
    push_int(THIS->iPosition);
611
 
    apply_svalue(THIS->read_include, 3);
612
 
 
613
 
    if ( Pike_sp[-1].type == T_INT ) {
614
 
        pop_stack();
615
 
        return 0;
616
 
    }
617
 
 
618
 
    str = Pike_sp[-1].u.string;
619
 
    if ( str->len == 0 ) {
620
 
      pop_stack();
621
 
      return 0;
622
 
    }
623
 
    if ( str->len > len+THIS->iPosition ) {
624
 
        strncpy(buffer, &str->str[THIS->iPosition], len);
625
 
        THIS->iPosition += len;
626
 
    }
627
 
    else if ( str->len - THIS->iPosition >= 0 ) {
628
 
        strncpy(buffer, 
629
 
                &str->str[THIS->iPosition], 
630
 
                str->len-THIS->iPosition);
631
 
        buffer[str->len-THIS->iPosition] = '\0';
632
 
        len = str->len+1-THIS->iPosition;
633
 
    }
634
 
    else {
635
 
      fprintf(stdout, 
636
 
              "Fatal error while reading include file-length mismatch!\n");
637
 
    }
638
 
    pop_stack();
639
 
    return len;
640
 
}
641
 
 
642
 
//!
643
 
//! @param
644
 
//!
645
 
int _include_close(void* context)
646
 
{
647
 
  struct pike_string* str;
648
 
  
649
 
  if ( THIS->close_include == NULL )
650
 
    return;
651
 
  add_ref(THIS->file);
652
 
  push_object(THIS->file);
653
 
  apply_svalue(THIS->close_include, 1);
654
 
  return 0;
655
 
}
656
 
 
657
 
xmlParserInputPtr
658
 
steamExternalEntityLoader(const char *URL, const char *ID,
659
 
                          xmlParserCtxtPtr ctxt) 
660
 
{
661
 
  xmlParserInputPtr   ret;
662
 
  struct pike_string* str;
663
 
  xmlChar*            buf;        
664
 
  
665
 
 
666
 
  push_text(URL);
667
 
  if ( THAT->language == NULL )
668
 
    push_text("english");
669
 
  else {
670
 
    push_string(THAT->language);
671
 
    add_ref(THAT->language);
672
 
  }
673
 
  
674
 
  push_int(0);
675
 
  apply_svalue(THIS->read_include, 3);
676
 
  
677
 
  if ( Pike_sp[-1].type == T_INT ) {
678
 
    fprintf(stderr, "Fatal error - empty string: include not found");
679
 
    pop_stack();
680
 
    return NULL;
681
 
  }
682
 
  
683
 
  str = Pike_sp[-1].u.string;
684
 
  if ( str->len == 0 ) {
685
 
    fprintf(stderr, "Fatal error - empty string: include not found");
686
 
    pop_stack();
687
 
    return NULL;
688
 
  }
689
 
 
690
 
  buf = xmlCharStrdup(str->str);
691
 
  ret = xmlNewStringInputStream(ctxt, buf);
692
 
  ret->length = str->len;
693
 
  return(ret);
694
 
}
695
 
 
696
 
 
697
 
 
698
 
void f_get_method(INT32 args)
699
 
{
700
 
    if ( THAT->stylesheet == NULL )
701
 
        Pike_error("XSLT.Stylesheet(): no stylesheet!");
702
 
    if ( THAT->stylesheet->method == NULL )
703
 
      Pike_error("XSLT.Stylesheet does not define a method!");
704
 
 
705
 
    push_text((char*)THAT->stylesheet->method);
706
 
}
707
 
 
708
 
void f_get_encoding(INT32 args)
709
 
{
710
 
    if ( THAT->stylesheet == NULL )
711
 
        Pike_error("XSLT.Stylesheet(): no stylesheet!");
712
 
    if ( THAT->stylesheet->encoding == NULL )
713
 
      Pike_error("XSLT.Stylesheet does not define a method!");
714
 
 
715
 
    push_text((char*)THAT->stylesheet->encoding);
716
 
}
717
 
 
718
 
//!
719
 
//! Set the content of the Stylesheet which will create the parse
720
 
//! xsltStylesheet structure and store it in the objects storage.
721
 
//!
722
 
void f_set_content(INT32 args)
723
 
{
724
 
    struct pike_string* str;
725
 
    xmlDocPtr           xsl;
726
 
    
727
 
    if(args != 1)
728
 
        Pike_error("XSLT.Stylesheet(): Expected content string.\n");
729
 
    if(Pike_sp[-args].type != T_STRING)
730
 
        Pike_error("XSLT.Stylesheet(): need xsl data for creation.\n");
731
 
 
732
 
    if ( THAT->open_include == NULL || THAT->match_include == NULL ||
733
 
         THAT->read_include == NULL || THAT->close_include == NULL )
734
 
        Pike_error("XSLT.Stylesheet(): No callback functions defined.\n");
735
 
    if ( THAT->stylesheet != NULL ) 
736
 
        Pike_error("XSLT.Stylesheet(): stylesheet is not initialized correctly!\n");
737
 
    
738
 
    THREADS_ALLOW();
739
 
    THREADS_DISALLOW();
740
 
   
741
 
    str = (struct pike_string*)Pike_sp[-args].u.string;
742
 
    if ( str->len == 0 )
743
 
        Pike_error("XSLT.Stylesheet(): need content for stylesheet !\n");
744
 
 
745
 
    THAT->xsl = str;
746
 
    add_ref(THAT->xsl);
747
 
    pop_n_elems(args);
748
 
 
749
 
    xmlSetGenericErrorFunc(THAT, (xml_error));
750
 
 
751
 
    xsl = xmlParseMemory(str->str, str->len);
752
 
 
753
 
    if ( THAT->err_str != NULL ) {
754
 
        Pike_error(THAT->err_str->str);
755
 
        return;
756
 
    }
757
 
    xmlSetGenericErrorFunc(NULL, NULL);
758
 
 
759
 
    xsltSetGenericErrorFunc(THAT,(xsl_error));
760
 
 
761
 
    THAT->stylesheet = xsltParseStylesheetDoc(xsl);
762
 
    if ( THAT->err_str != NULL ) {
763
 
        Pike_error(THAT->err_str->str);
764
 
        return;
765
 
    }
766
 
    xsltSetGenericErrorFunc(NULL, NULL);
767
 
}
768
 
 
769
 
//!
770
 
//! Pike module initialization code. Offer two classes.
771
 
//!
772
 
void pike_module_init( void )
773
 
{
774
 
    xmlLoadExtDtdDefaultValue = 1;
775
 
    DEBUG_XSLT("RegisterInputCallbacks()");
776
 
    // old libxml (pre 2.6)
777
 
 
778
 
#if LIBXML_VERSION < 20600
779
 
    if ( xmlRegisterInputCallbacks(_include_match, _include_open, _include_read, _include_close) == -1 )
780
 
      fprintf(stderr, "Error registering input callbacks !");
781
 
#else
782
 
    defaultLoader = xmlGetExternalEntityLoader();
783
 
    xmlSetExternalEntityLoader(steamExternalEntityLoader);
784
 
    if ( xmlGetExternalEntityLoader() != steamExternalEntityLoader )
785
 
      fprintf(stderr, "XSLT: Failed to set external entity loader !\n");
786
 
#endif
787
 
 
788
 
    _init_xml_dom();
789
 
 
790
 
    start_new_program();
791
 
    ADD_STORAGE(xslt_storage);
792
 
    set_init_callback(init_xslt_storage);
793
 
    set_exit_callback(free_xslt_storage);
794
 
    ADD_FUNCTION2("create", f_create, tFunc(tNone,tVoid), 0,
795
 
                 OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
796
 
    ADD_FUNCTION2("set_xml_data", f_set_xml_data, tFunc(tOr(tStr, tObj), tVoid),0, OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
797
 
    ADD_FUNCTION2("set_variables", f_set_variables, 
798
 
                 tFunc(tMapping,tVoid), 0,
799
 
                 OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
800
 
    ADD_FUNCTION2("run", f_run, tFunc(tObj,tStr), 0,
801
 
                 OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
802
 
    ADD_FUNCTION2("get_version", f_get_version, tFunc(tVoid,tStr), 0,
803
 
                 OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
804
 
 
805
 
    end_class("Parser", 0);
806
 
 
807
 
    start_new_program();
808
 
    ADD_STORAGE(xslt_storage);
809
 
    set_init_callback(init_xslt_storage);
810
 
    set_exit_callback(free_xslt_storage);
811
 
 
812
 
    ADD_FUNCTION2("create", f_create_stylesheet, tFunc(tNone,tVoid), 0,
813
 
                 OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
814
 
    ADD_FUNCTION2("set_include_callbacks", f_set_include_callbacks, 
815
 
                 tFunc(tFunc(tStr,tInt) tFunc(tStr,tObj) tFunc(tObj tStr tInt,tStr) tFunc(tObj,tVoid), tVoid), 0,
816
 
                 OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
817
 
    ADD_FUNCTION2("set_content", f_set_content, tFunc(tStr,tVoid), 0,
818
 
                 OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
819
 
    ADD_FUNCTION2("set_language", f_set_language, tFunc(tStr,tVoid), 0,
820
 
                 OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
821
 
    ADD_FUNCTION2("get_method", f_get_method, tFunc(tVoid,tStr), 0,
822
 
                  OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
823
 
    ADD_FUNCTION2("get_encoding", f_get_encoding, tFunc(tVoid,tStr), 0,
824
 
                  OPT_EXTERNAL_DEPEND|OPT_SIDE_EFFECT);
825
 
    end_class("Stylesheet", 0);
826
 
}
827
 
 
828
 
/* Restore and exit module */
829
 
void pike_module_exit( void )
830
 
{
831
 
    if ( xslt_program )
832
 
        free_program(xslt_program);
833
 
    if ( stylesheet_program )
834
 
        free_program(stylesheet_program);
835
 
}
836
 
 
837