~ubuntu-branches/ubuntu/hardy/pxp/hardy

« back to all changes in this revision

Viewing changes to src/pxp-engine/pxp_reader.mli

  • Committer: Bazaar Package Importer
  • Author(s): Stefano Zacchiroli
  • Date: 2005-03-29 11:06:39 UTC
  • mfrom: (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050329110639-5p39hz1d4aq3r2ec
Tags: 1.1.95-6
* Rebuilt against ocaml 3.08.3
* No longer built with wlex support (since wlex is no longer supported
  upstream and corresponding package has been removed from the debian
  archive)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
(* $Id: pxp_reader.mli,v 1.9 2001/07/01 08:35:23 gerd Exp $
 
1
(* $Id: pxp_reader.mli 689 2004-08-07 17:01:52Z gerd $
2
2
 * ----------------------------------------------------------------------
3
3
 * PXP: The polymorphic XML parser for Objective Caml.
4
4
 * Copyright by Gerd Stolpmann. See LICENSE for details.
8
8
 * specify how external identifiers (SYSTEM or PUBLIC) are mapped to
9
9
 * files or channels. This is normally only necessary for advanced
10
10
 * configurations, as the functions from_file, from_channel, and
11
 
 * from_string in Pxp_yacc often suffice.
 
11
 * from_string in Pxp_types often suffice.
12
12
 *
13
13
 * There are two ways to use this module. First, you can compose the
14
14
 * desired behaviour by combining several predefined resolver objects
19
19
 *)
20
20
 
21
21
 
22
 
open Pxp_types;;
 
22
open Pxp_core_types;;
23
23
 
24
24
exception Not_competent;;
25
25
  (* Raised by the 'open_in' method if the object does not know how to
33
33
   * Not_resolvable(Not_found) serves as indicator for an unknown reason.
34
34
   *)
35
35
 
 
36
(* One must only use either [lsrc_lexbuf], or [lsrc_unicode_lexbuf] ! *)
 
37
type lexer_source =
 
38
    { lsrc_lexbuf : Lexing.lexbuf Lazy.t;
 
39
      lsrc_unicode_lexbuf : Netulex.ULB.unicode_lexbuf Lazy.t;
 
40
    }
 
41
 
36
42
 
37
43
(* The class type 'resolver' is the official type of all "resolvers".
38
44
 * Resolvers take file names (or better, external identifiers) and
99
105
     *
100
106
     * A resolver is like a file: it must be opened before one can work
101
107
     * with it, and it should be closed after all operations on it have been
102
 
     * done. The method 'open_in' is called with the external ID as argument
 
108
     * done. The method 'open_rid' is called with the resolver ID as argument
103
109
     * and it must return the lexbuf reading from the external resource.
 
110
     * (There is also the old method 'open_in' that expects an ext_id as
 
111
     * argument. It is less powerful and should not be used any longer.)
104
112
     * The method 'close_in' does not require an argument.
105
113
     *
106
114
     * It is allowed to re-open a resolver after it has been closed. It is
108
116
     * It is allowed to close a resolver several times: If 'close_in' is
109
117
     * invoked while the resolver is already closed, nothing happens.
110
118
     *
111
 
     * The method 'open_in' may raise Not_competent to indicate that this
 
119
     * The method 'open_rid' may raise Not_competent to indicate that this
112
120
     * resolver is not able to open this type of IDs.
113
121
     *
 
122
     * If 'open_rid' gets a PUBLIC ID, it can be assumed that the string
 
123
     * is already normalized (whitespace).
 
124
     *
114
125
     * The method 'change_encoding' is called from the parser after the
115
126
     * analysis of case (2) has been done; the argument is either the
116
127
     * string name of the encoding, or the empty string to indicate
145
156
     * original resolver.
146
157
     *)
147
158
    method init_rep_encoding : rep_encoding -> unit
148
 
    method init_warner : collect_warnings -> unit
 
159
    method init_warner : symbolic_warnings option -> collect_warnings -> unit
149
160
 
150
161
    method rep_encoding : rep_encoding
151
162
 
152
 
    method open_in : ext_id -> Lexing.lexbuf
153
 
      (* May raise Not_competent if the object does not know how to handle
154
 
       * this ext_id.
155
 
       *)
 
163
    method open_in : ext_id -> lexer_source
 
164
      (* This is the old method to open a resolver. It is superseded by
 
165
       * open_rid.
 
166
       * This method may raise Not_competent if the object does not know
 
167
       * how to handle this ext_id.
 
168
       *
 
169
       * PXP 1.2: Returns now a lexer_source, no longer a lexbuf
 
170
       *)
 
171
 
 
172
    method open_rid : resolver_id -> lexer_source
 
173
      (* This is the new method to open a resolver. It takes a resolver ID
 
174
       * instead of an ext_id but works in the same way.
 
175
       *
 
176
       * PXP 1.2: Returns now a lexer_source, no longer a lexbuf
 
177
       *)
 
178
 
156
179
    method close_in : unit
157
180
    method change_encoding : string -> unit
158
181
 
162
185
     *)
163
186
    method clone : resolver
164
187
 
165
 
    method close_all : unit
 
188
    method active_id : resolver_id
 
189
      (* Returns the actually used resolver ID. This is the ID passed to
 
190
       * open_rid where unused components have been set to None. The
 
191
       * resolver ID returned by [active_id] plays an important role when
 
192
       * expanding relative URLs.
 
193
       *)
 
194
 
 
195
(*  method close_all : unit *)
166
196
      (* Closes this resolver and every clone *)
 
197
      (* This method is no longer supported in PXP 1.2 *)
167
198
 
168
199
  end
169
200
;;
170
201
 
171
 
(* Note: resolve_general is no longer exported. In most cases, the classes
172
 
 * resolve_read_any_channel or resolve_read_any_string are applicable, too,
173
 
 * and much easier to configure.
174
 
 *)
175
 
 
176
202
 
177
203
(* The next classes are resolvers for concrete input sources. *)
178
204
 
179
 
class resolve_read_this_channel :
180
 
  ?id:ext_id -> ?fixenc:encoding -> ?close:(in_channel -> unit) ->
181
 
  in_channel -> resolver;;
182
 
 
183
 
  (* Reads from the passed channel (it may be even a pipe). If the ~id
184
 
   * argument is passed to the object, the created resolver accepts only
185
 
   * this ID. Otherwise all IDs are accepted.
186
 
   * Once the resolver has been cloned, it does not accept any ID. This
187
 
   * means that this resolver cannot handle inner references to external
188
 
   * entities. Note that you can combine this resolver with another resolver
189
 
   * that can handle inner references (such as resolve_as_file); see
190
 
   * class 'combine' below.
 
205
(* CHANGES IN PXP 1.2:
 
206
 *
 
207
 * All resolve_read_* classes are now deprecated. The new classes 
 
208
 * resolve_to_* base on the Netchannels classes as generalization of
 
209
 * input streams.
 
210
 *
 
211
 * Examples: To read from an in_channel, use:
 
212
 *
 
213
 *   let obj_channel = new Netchannels.input_channel in_channel in
 
214
 *   new Pxp_reader.resolve_to_this_obj_channel obj_channel
 
215
 *
 
216
 * To read from a string, use:
 
217
 *
 
218
 *   let obj_channel = new Netchannels.input_string string in
 
219
 *   new Pxp_reader.resolve_to_this_obj_channel obj_channel
 
220
 *
 
221
 * Furthermore, the new classes use the resolver_id record as generalized
 
222
 * names for entities. This solves most problems with relative URLs.
 
223
 *
 
224
 * The "Anonymous" ID: In previous versions of PXP, a resolver bound to
 
225
 * the Anonymous ID matched the Anonymous ID. This is no longer true.
 
226
 * The algebra has been changed such that Anonymous never matches, not 
 
227
 * even itself.
 
228
 * 
 
229
 *   Example: The new resolver
 
230
 *     let r = new resolve_to_this_obj_channel ~id:Anonymous ch 
 
231
 *   will never accept any ID. In contrast to this, the old, and now
 
232
 *   deprecated resolver
 
233
 *     let r' = new resolve_read_this_channel ~id:Anonymous ch
 
234
 *   accepted the ID Anonymous in previous versions of PXP.
 
235
 *
 
236
 * The rationale behind this change is that Anonymous acts now like 
 
237
 * an "empty set", and not like a concrete element. You can use Private
 
238
 * to create as many concrete elements as you want, so there is actually
 
239
 * no need for the old behaviour of Anonymous.
 
240
 *
 
241
 * Note that even the resolver classes provided for backwards compatibility
 
242
 * implement this change (to limit the confusion). This means that you
 
243
 * might have to change your application to use Private instead of 
 
244
 * Anonymous.
 
245
 * 
 
246
 *)
 
247
 
 
248
class resolve_to_this_obj_channel :
 
249
  ?id:ext_id ->
 
250
  ?rid:resolver_id ->
 
251
  ?fixenc:encoding ->
 
252
  ?close:(Netchannels.in_obj_channel -> unit) ->
 
253
 Netchannels.in_obj_channel -> 
 
254
   resolver;;
 
255
 
 
256
  (* Reads from the passed in_obj_channel. If the ~id or ~rid arguments
 
257
   * are passed to the object, the created resolver accepts only
 
258
   * these IDs (all mentioned private, system, or public IDs). Otherwise 
 
259
   * all IDs are accepted, even Anonymous.
 
260
   *
 
261
   * This resolver can only be used once (because the in_obj_channel
 
262
   * can only be used once). If it is opened a second time (either
 
263
   * in the base object or a clone), it will raise Not_competent.
 
264
   *
191
265
   * If you pass the ~fixenc argument, the encoding of the channel is
192
266
   * set to the passed value, regardless of any auto-recognition or
193
267
   * any XML declaration.
 
268
   *
194
269
   * When the resolver is closed, the function passed by the ~close
195
270
   * argument is called. By default, the channel is closed
196
 
   * (i.e. the default is: ~close:close_in).
197
 
   *)
198
 
 
199
 
 
200
 
class resolve_read_any_channel :
201
 
  ?close:(in_channel -> unit) ->
202
 
  channel_of_id:(ext_id -> (in_channel * encoding option)) ->
 
271
   * (i.e. the default is: ~close:(fun ch -> ch # close_in)).
 
272
   *)
 
273
 
 
274
type accepted_id =
 
275
    Netchannels.in_obj_channel * encoding option * resolver_id option
 
276
  (* When a resolver accepts an ID, this triple specifies how to proceed.
 
277
   * The in_obj_channel is the channel to read data from, the encoding option
 
278
   * may enforce a certain character encoding, and the resolver_id option
 
279
   * may detail the ID (this ID will be returned by active_id).
 
280
   *
 
281
   * If None is passed as encoding option, the standard autodetection of
 
282
   * the encoding is performed.
 
283
   *
 
284
   * If None is passed as resolver_id option, the original ID is taken
 
285
   * unchanged.
 
286
   *)
 
287
 
 
288
class resolve_to_any_obj_channel :
 
289
  ?close:(Netchannels.in_obj_channel -> unit) ->
 
290
  channel_of_id:(resolver_id -> accepted_id) ->
203
291
  unit ->
204
292
  resolver;;
205
293
 
206
 
  (* resolve_read_any_channel f_open ():
207
 
   * This resolver calls the function f_open to open a new channel for
208
 
   * the passed ext_id. This function must either return the channel and
209
 
   * the encoding, or it must fail with Not_competent.
210
 
   * The function must return None as encoding if the default mechanism to
211
 
   * recognize the encoding should be used. It must return Some e if it is
212
 
   * already known that the encoding of the channel is e.
 
294
  (* This resolver calls the function channel_of_id to open a new channel for
 
295
   * the passed resolver_id. This function must either return the accepted_id,
 
296
   * or it must fail with Not_competent.
 
297
   *
213
298
   * When the resolver is closed, the function passed by the ~close
214
299
   * argument is called. By default, the channel is closed
215
 
   * (i.e. the default is: ~close:close_in).
 
300
   * (i.e. the default is: ~close:(fun ch -> ch # close_in)).
216
301
   *)
217
302
 
218
303
 
219
 
class resolve_read_url_channel :
220
 
  ?base_url:Neturl.url ->
221
 
  ?close:(in_channel -> unit) ->
222
 
  url_of_id:(ext_id -> Neturl.url) ->
223
 
  channel_of_url:(ext_id -> Neturl.url -> (in_channel * encoding option)) ->
 
304
class resolve_to_url_obj_channel : 
 
305
  ?close:(Netchannels.in_obj_channel -> unit) ->
 
306
  url_of_id:(resolver_id -> Neturl.url) ->
 
307
  base_url_of_id:(resolver_id -> Neturl.url) ->
 
308
  channel_of_url:(resolver_id -> Neturl.url -> accepted_id) ->
224
309
  unit ->
225
310
    resolver;;
226
311
 
227
 
  (* resolve_read_url_channel url_of_id channel_of_url ():
228
 
   *
 
312
  (*
229
313
   * When this resolver gets an ID to read from, it calls the function
230
 
   * ~url_of_id to get the corresponding URL. This URL may be a relative
231
 
   * URL; however, a URL scheme must be used which contains a path.
232
 
   * The resolver converts the URL to an absolute URL if necessary.
233
 
   * The second function, ~channel_of_url, is fed with the absolute URL
 
314
   * ~url_of_id to get the corresponding URL (such IDs are normally 
 
315
   * system IDs, but it is also possible to map system IDs to URLs). 
 
316
   * This URL may be a relative URL; however, a URL scheme must be used
 
317
   * which contains a path. The resolver converts the URL to an absolute 
 
318
   * URL if necessary.
 
319
   *
 
320
   * To do so, the resolver calls ~base_url_of_id to get the URL the relative
 
321
   * URL must be interpreted relative to. Usually, this function returns
 
322
   * the rid_system_base as URL. This URL must be absolute.
 
323
   *
 
324
   * The third function, ~channel_of_url, is fed with the absolute URL
234
325
   * as input. This function opens the resource to read from, and returns
235
 
   * the channel and the encoding of the resource.
 
326
   * the accepted_id like resolve_to_any_obj_channel does. The resolver ID 
 
327
   * passed to ~channel_of_url contains the string representation of the
 
328
   * absolute URL as system ID.
236
329
   *
237
330
   * Both functions, ~url_of_id and ~channel_of_url, can raise
238
331
   * Not_competent to indicate that the object is not able to read from
239
332
   * the specified resource. However, there is a difference: A Not_competent
240
333
   * from ~url_of_id is left as it is, but a Not_competent from ~channel_of_url
241
334
   * is converted to Not_resolvable. So only ~url_of_id decides which URLs
242
 
   * are accepted by the resolver and which not.
243
 
   *
244
 
   * The function ~channel_of_url must return None as encoding if the default
245
 
   * mechanism to recognize the encoding should be used. It must return
246
 
   * Some e if it is already known that the encoding of the channel is e.
 
335
   * are accepted by the resolver and which not, and in the latter case,
 
336
   * other resolver can be tried. If ~channel_of_url raises Not_competent,
 
337
   * the whole resolution procedure will stop, and no other resolver will
 
338
   * be tried.
247
339
   *
248
340
   * When the resolver is closed, the function passed by the ~close
249
341
   * argument is called. By default, the channel is closed
250
 
   * (i.e. the default is: ~close:close_in).
251
 
   *
252
 
   * Objects of this class contain a base URL relative to which relative
253
 
   * URLs are interpreted. When creating a new object, you can specify
254
 
   * the base URL by passing it as ~base_url argument. When an existing
255
 
   * object is cloned, the base URL of the clone is the URL of the original
256
 
   * object.
257
 
   *
258
 
   * Note that the term "base URL" has a strict definition in RFC 1808.
259
 
   *)
260
 
 
261
 
 
262
 
class resolve_read_this_string :
263
 
  ?id:ext_id -> ?fixenc:encoding -> string -> resolver;;
264
 
 
265
 
  (* Reads from the passed string. If the ~id
266
 
   * argument is passed to the object, the created resolver accepts only
267
 
   * this ID. Otherwise all IDs are accepted.
268
 
   * Once the resolver has been cloned, it does not accept any ID. This
269
 
   * means that this resolver cannot handle inner references to external
270
 
   * entities. Note that you can combine this resolver with another resolver
271
 
   * that can handle inner references (such as resolve_as_file); see
272
 
   * class 'combine' below.
273
 
   * If you pass the ~fixenc argument, the encoding of the string is
274
 
   * set to the passed value, regardless of any auto-recognition or
275
 
   * any XML declaration.
276
 
   *)
277
 
 
278
 
 
279
 
class resolve_read_any_string :
280
 
  string_of_id:(ext_id -> (string * encoding option)) -> unit -> resolver;;
281
 
 
282
 
  (* resolver_read_any_string f_open ():
283
 
   * This resolver calls the function f_open to get the string for
284
 
   * the passed ext_id. This function must either return the string and
285
 
   * the encoding, or it must fail with Not_competent.
286
 
   * The function must return None as encoding if the default mechanism to
287
 
   * recognize the encoding should be used. It must return Some e if it is
288
 
   * already known that the encoding of the string is e.
 
342
   * (i.e. the default is: ~close:(fun ch -> ch # close_in())).
289
343
   *)
290
344
 
291
345
 
295
349
  ?system_encoding:encoding ->
296
350
  ?map_private_id:  (private_id -> Neturl.url) ->
297
351
  ?open_private_id: (private_id -> in_channel * encoding option) ->
 
352
  ?base_url_defaults_to_cwd: bool ->
 
353
  ?not_resolvable_if_not_found:bool ->
298
354
  unit ->
299
355
  resolver;;
300
356
 
322
378
   * Option ~system_encoding: Specifies the encoding of file names of
323
379
   * the local file system. Default: UTF-8.
324
380
   *
325
 
   * Options ~map_private_id and ~open_private_id: These must always be
 
381
   * Options ~map_private_id and ~open_private_id: THESE OPTIONS ARE
 
382
   * DEPRECATED! IT IS NOW POSSIBLE TO USE A COMBINED RESOLVER TO ACHIEVE
 
383
   * THE SAME EFFECT! - These must always be
326
384
   * used together. They specify an exceptional behaviour in case a private
327
385
   * ID is to be opened. map_private_id maps the private ID to an URL
328
386
   * (or raises Not_competent). However, instead of opening the URL 
329
387
   * the function open_private_id is called to get an in_channel to read
330
388
   * from and to get the character encoding. The URL is taken into account
331
389
   * when subsequently relative SYSTEM IDs must be resolved.
 
390
   *
 
391
   * Option ~base_url_defaults_to_cwd: If true, relative URLs
 
392
   * are interpreted relative to the current working directory at the time
 
393
   * the class is instantiated, but only if there is no parent URL, i.e.
 
394
   * rid_system_base=None. If false (the default), such URLs cannot be resolved.
 
395
   * In general, it is better to set this option to false, and to
 
396
   * initialize rid_system_base properly.
 
397
   *
 
398
   * Option ~not_resolvable_if_not_found: If true (the default), 
 
399
   * "File not found" errors stop the resolution process. If false,
 
400
   * "File not found" is treated as [Not_competent].
332
401
   *)
333
402
 
334
403
val make_file_url :
357
426
 * of PUBLIC or SYSTEM identifiers.
358
427
 *)
359
428
 
 
429
class lookup_id :
 
430
  (ext_id * resolver) list ->    (* catalog *)
 
431
    resolver;;
 
432
  (* The general catalog class. The catalog argument specifies pairs (xid,r)
 
433
   * mapping external IDs xid to subresolvers r. The subresolver is invoked
 
434
   * if an entity with the corresponding xid is to be opened.
 
435
   *
 
436
   * Note: SYSTEM IDs are simply compared literally, without making
 
437
   * relative IDs absolute. See norm_system_id below for this function.
 
438
   *)
 
439
 
 
440
 
 
441
class lookup_id_as_file :
 
442
  ?fixenc:encoding ->
 
443
  (ext_id * string) list ->      (* catalog *)
 
444
    resolver;;
 
445
 
 
446
  (* The catalog argument specifies pairs (xid,file) mapping external IDs xid
 
447
   * to files. The file is read  if an entity with the corresponding xid is
 
448
   * to be opened.
 
449
   *
 
450
   * Note: SYSTEM IDs are simply compared literally, without making
 
451
   * relative IDs absolute. See norm_system_id below for this function.
 
452
   *
 
453
   * ~fixenc: Overrides the encoding of the file contents. By default, the
 
454
   *     standard rule is applied to find out the encoding of the file.
 
455
   *)
 
456
 
 
457
 
 
458
class lookup_id_as_string :
 
459
  ?fixenc:encoding ->
 
460
  (ext_id * string) list ->      (* catalog *)
 
461
    resolver;;
 
462
 
 
463
  (* The catalog argument specifies pairs (xid,s) mapping external IDs xid
 
464
   * to strings s. The string is read if an entity with the corresponding
 
465
   * xid is to be opened.
 
466
   *
 
467
   * Note: SYSTEM IDs are simply compared literally, without making
 
468
   * relative IDs absolute. See norm_system_id below for this function.
 
469
   *)
 
470
 
 
471
 
360
472
class lookup_public_id :
361
473
  (string * resolver) list ->    (* catalog *)
362
474
    resolver;;
364
476
  (* This is the generic builder for PUBLIC id catalog resolvers: The catalog 
365
477
   * argument specifies pairs (pubid, r) mapping PUBLIC identifiers to
366
478
   * subresolvers.
 
479
   *
367
480
   * The subresolver is invoked if an entity with the corresponding PUBLIC
368
481
   * id is to be opened.
369
482
   *)
370
483
 
371
484
 
372
485
 
373
 
val lookup_public_id_as_file :
 
486
class lookup_public_id_as_file :
374
487
  ?fixenc:encoding ->
375
488
  (string * string) list ->     (* catalog *)
376
489
    resolver;;
380
493
   * filenames must already be encoded in the character set the system uses
381
494
   * for filenames.
382
495
   *
 
496
   * Note: This class does not enable the resolution of inner IDs of PUBLIC
 
497
   * entities by relative SYSTEM names. To get this effect, use
 
498
   * the class lookup_id, and feed it with combined 
 
499
   * Public(pubid,sysid) identifiers. In this case, the entity has both
 
500
   * a PUBLIC and a SYSTEM ID, and resolution of inner relative SYSTEM
 
501
   * names works.
 
502
   *
383
503
   * ~fixenc: Overrides the encoding of the file contents. By default, the
384
504
   *     standard rule is applied to find out the encoding of the file.
385
505
   *)
386
506
 
387
507
 
388
 
val lookup_public_id_as_string :
 
508
class lookup_public_id_as_string :
389
509
  ?fixenc:encoding ->
390
510
  (string * string) list ->    (* catalog *)
391
511
    resolver;;
403
523
    resolver;;
404
524
 
405
525
  (* This is the generic builder for SYSTEM id catalog resolvers: The catalog 
406
 
   * argument specifies pairs (pubid, r) mapping PUBLIC identifiers to 
 
526
   * argument specifies pairs (sysid, r) mapping SYSTEM identifiers to 
407
527
   * subresolvers.
408
528
   * The subresolver is invoked if an entity with the corresponding SYSTEM
409
529
   * id is to be opened.
411
531
   * Important note: Two SYSTEM IDs are considered as equal if they are
412
532
   * equal in their string representation. (This may not what you want
413
533
   * and may cause trouble... However, I currently do not know how to
414
 
   * implement a "sematical" comparison logic.)
 
534
   * implement a "semantical" comparison logic.)
 
535
   *
 
536
   * Note: SYSTEM IDs are simply compared literally, without making
 
537
   * relative IDs absolute. See norm_system_id below for this function.
415
538
   *)
416
539
 
417
540
 
418
 
val lookup_system_id_as_file :
 
541
class lookup_system_id_as_file :
419
542
  ?fixenc:encoding ->
420
543
  (string * string) list ->     (* catalog *)
421
544
    resolver;;
425
548
   * filenames must already be encoded in the character set the system uses
426
549
   * for filenames.
427
550
   *
 
551
   * Note: SYSTEM IDs are simply compared literally, without making
 
552
   * relative IDs absolute. See norm_system_id below for this function.
 
553
   *
428
554
   * ~fixenc: Overrides the encoding of the file contents. By default, the
429
555
   *     standard rule is applied to find out the encoding of the file.
430
556
   *)
431
557
 
432
558
 
433
 
val lookup_system_id_as_string :
 
559
class lookup_system_id_as_string :
434
560
  ?fixenc:encoding ->
435
561
  (string * string) list ->     (* catalog *)
436
562
    resolver;;
439
565
   * pairs (sysid, text) mapping SYSTEM identifiers to XML text (which must
440
566
   * begin with <?xml ...?>).
441
567
   *
 
568
   * Note: SYSTEM IDs are simply compared literally, without making
 
569
   * relative IDs absolute. See norm_system_id below for this function.
 
570
   *
442
571
   * ~fixenc: Overrides the encoding of the strings.
443
572
   *)
444
573
 
445
574
 
 
575
class norm_system_id : resolver -> resolver
 
576
  (* Normalizes the SYSTEM ID, and forwards the open request to the
 
577
   * passed resolver.
 
578
   *
 
579
   * Normalization includes:
 
580
   * - Relative URLs are made absolute. If this fails, the problematic
 
581
   *   relative URL will be rejected.
 
582
   * - .. and . and // in the middle of URLs are removed 
 
583
   * - Escaping of reserved characters is normalized
 
584
   *
 
585
   * Normalization is recommended for catalogs, e.g.
 
586
   * new norm_system_id
 
587
   *   (new lookup_system_id_as_file
 
588
   *      [ "http://h/p1", ...;
 
589
   *        "http://h/p2", ...;
 
590
   *      ])
 
591
   * First, the catalog now even works if the URL is written in an
 
592
   * unsual way, e.g. http://h/p1/../p2, or http://h/p%31. 
 
593
   * Second, relative URLs can be used. For instance, the document
 
594
   * referred to as http://h/p1 can now refer to the other document
 
595
   * as p2.
 
596
   *)
 
597
 
 
598
 
 
599
class rewrite_system_id :
 
600
        ?forward_unmatching_urls:bool ->
 
601
        (string * string) list ->
 
602
        resolver ->
 
603
          resolver
 
604
  (* Rewrites the SYSTEM URL according to the list of pairs. The left
 
605
   * component is the pattern, the right component is the substitute.
 
606
   * For example,
 
607
   *
 
608
   * new rewrite_system_id
 
609
   *       [ "http://host/foo/", "file:///dir/" ]
 
610
   *       r
 
611
   *
 
612
   * rewrites all URLs beginning with http://host/foo/ to file:///dir/,
 
613
   * e.g. http://host/foo/x becomes file:///dir/x.
 
614
   *
 
615
   * If the pattern ends with a slash (as in the example), a prefix match
 
616
   * is performed, i.e. the whole directory hierarchy is rewritten.
 
617
   * If the pattern does not end with a slash, an exact match is performed,
 
618
   * i.e. only a single URL is rewritten.
 
619
   *
 
620
   * The class normalizes URLs as norm_system_id does, before the match
 
621
   * is tried.
 
622
   *
 
623
   * By default, URLs that do not match any pattern are rejected
 
624
   * (Not_competent).
 
625
   *
 
626
   * The rewritten URL is only visible within the passed subresolver.
 
627
   * If the opened entity accesses other entities by relative URLs,
 
628
   * these will be resolved relative to the original URL as it was before
 
629
   * rewriting it. This gives some protection against unwanted accesses.
 
630
   * For example, if you map http://host/contents to file:///data/contents,
 
631
   * it will not be possible to access files outside this directory,
 
632
   * even if tricks are used like opening ../../etc/passwd relative to
 
633
   * http://host/contents.  Of course, this protection works only if
 
634
   * the resolver opening the file is a subresolver of rewrite_system_id.
 
635
   *
 
636
   * CHECK: Does this really work?
 
637
   *
 
638
   * Another application of this class is to use the identity as rewriting
 
639
   * rule. This resolver
 
640
   * 
 
641
   * new rewrite_system_id
 
642
   *       [ "file:///data/", "file:///data/" ]
 
643
   *       ( new resolve_as_file() )
 
644
   *
 
645
   * has the effect that only files under /data can be accessed, and
 
646
   * other such as /etc/passwd cannot.
 
647
   *
 
648
   * Option ~forward_unmatching_urls: If true, URLs that do not match any
 
649
   *   pattern are forwarded to the inner resolver. These URLs are not
 
650
   *   rewritten. NOTE THAT THE MENTIONED ACCESS RESTRICTIONS USUALLY DO
 
651
   *   NOT WORK ANYMORE IF THIS OPTION IS TURNED ON.
 
652
   *)
 
653
 
 
654
 
446
655
type combination_mode =
447
656
    Public_before_system    (* Try public identifiers first *)
448
657
  | System_before_public    (* Try system identifiers first *)
449
658
;;
450
659
 
 
660
 
451
661
class combine : 
452
 
        ?prefer:resolver -> 
453
662
        ?mode:combination_mode ->
454
663
        resolver list -> 
455
664
          resolver;;
457
666
  (* Combines several resolver objects. If a concrete entity with an
458
667
   * ext_id is to be opened, the combined resolver tries the contained
459
668
   * resolvers in turn until a resolver accepts opening the entity
460
 
   * (i.e. it does not raise Not_competent on open_in).
461
 
   *
462
 
   * If the ext_id is a public identifier Public(pubid,sysid), there are 
463
 
   * two possibilities:
 
669
   * (i.e. it does not raise Not_competent on open_rid).
 
670
   *
 
671
   * If the entity to open has several names, e.g. a public name and
 
672
   * a system name, these names are tried in parallel by default (this
 
673
   * is possible in the PXP 1.2 model). For backward compatibility, the
 
674
   * ~mode argument allows one to specify a different order:
 
675
   *
464
676
   * (1) Try first to open as public identifier, and if that fails,
465
 
   *     fall back to the system identifier
 
677
   *     fall back to the system identifier (Public_before_system)
466
678
   * (2) Try first to open as system identifier, and if that fails,
467
 
   *     fall back to the public identifier
468
 
   * You can select this by the ~mode argument. The default is to
469
 
   * try public identifiers first.
 
679
   *     fall back to the public identifier (System_before_public)
470
680
   *
471
 
   * Clones: If the 'clone' method is invoked before 'open_in', all contained
 
681
   * Clones: If the 'clone' method is invoked before 'open_rid', all contained
472
682
   * resolvers are cloned and again combined. If the 'clone' method is
473
 
   * invoked after 'open_in' (i.e. while the resolver is open), only the
 
683
   * invoked after 'open_rid' (i.e. while the resolver is open), only the
474
684
   * active resolver is cloned.
475
 
   *
476
 
   * ~prefer: This is an internally used option.
477
685
   *)
478
686
 
 
687
 
479
688
(* ====================================================================== *)
480
689
 
 
690
(* TODO: The following examples recommend deprecated classes. *)
 
691
 
481
692
(* EXAMPLES OF RESOLVERS:
482
693
 *
483
694
 * let r1 = new resolve_as_file ()
564
775
 * from_string are also applications of the Pxp_reader objects.
565
776
 *)
566
777
 
567
 
 
568
 
(* ======================================================================
569
 
 * History:
570
 
 *
571
 
 * $Log: pxp_reader.mli,v $
572
 
 * Revision 1.9  2001/07/01 08:35:23  gerd
573
 
 *      Instead of the ~auto_close argument, there is now a
574
 
 * ~close argument for several functions/classes. This allows some
575
 
 * additional action when the resolver is closed.
576
 
 *
577
 
 * Revision 1.8  2001/04/22 14:16:48  gerd
578
 
 *      resolve_as_file: you can map private IDs to arbitrary channels.
579
 
 *      resolve_read_url_channel: changed type of the channel_of_url
580
 
 * argument (ext_id is also passed)
581
 
 *      More examples and documentation.
582
 
 *
583
 
 * Revision 1.7  2001/04/03 20:22:44  gerd
584
 
 *      New resolvers for catalogs of PUBLIC and SYSTEM IDs.
585
 
 *      Improved "combine": PUBLIC and SYSTEM IDs are handled
586
 
 * separately.
587
 
 *      Rewritten from_file: Is now a simple application of the
588
 
 * Pxp_reader classes and functions. (The same has still to be done
589
 
 * for from_channel!)
590
 
 *
591
 
 * Revision 1.6  2001/02/01 20:38:49  gerd
592
 
 *      New support for PUBLIC identifiers.
593
 
 *
594
 
 * Revision 1.5  2000/07/09 01:05:33  gerd
595
 
 *      New methode 'close_all' that closes the clones, too.
596
 
 *
597
 
 * Revision 1.4  2000/07/08 16:24:56  gerd
598
 
 *      Introduced the exception 'Not_resolvable' to indicate that
599
 
 * 'combine' should not try the next resolver of the list.
600
 
 *
601
 
 * Revision 1.3  2000/07/06 23:04:46  gerd
602
 
 *      Quick fix for 'combine': The active resolver is "prefered",
603
 
 * but the other resolvers are also used.
604
 
 *
605
 
 * Revision 1.2  2000/07/04 22:06:49  gerd
606
 
 *      MAJOR CHANGE: Complete redesign of the reader classes.
607
 
 *
608
 
 * Revision 1.1  2000/05/29 23:48:38  gerd
609
 
 *      Changed module names:
610
 
 *              Markup_aux          into Pxp_aux
611
 
 *              Markup_codewriter   into Pxp_codewriter
612
 
 *              Markup_document     into Pxp_document
613
 
 *              Markup_dtd          into Pxp_dtd
614
 
 *              Markup_entity       into Pxp_entity
615
 
 *              Markup_lexer_types  into Pxp_lexer_types
616
 
 *              Markup_reader       into Pxp_reader
617
 
 *              Markup_types        into Pxp_types
618
 
 *              Markup_yacc         into Pxp_yacc
619
 
 * See directory "compatibility" for (almost) compatible wrappers emulating
620
 
 * Markup_document, Markup_dtd, Markup_reader, Markup_types, and Markup_yacc.
621
 
 *
622
 
 * ======================================================================
623
 
 * Old logs from markup_reader.mli:
624
 
 *
625
 
 * Revision 1.3  2000/05/29 21:14:57  gerd
626
 
 *      Changed the type 'encoding' into a polymorphic variant.
627
 
 *
628
 
 * Revision 1.2  2000/05/20 20:31:40  gerd
629
 
 *      Big change: Added support for various encodings of the
630
 
 * internal representation.
631
 
 *
632
 
 * Revision 1.1  2000/03/13 23:41:54  gerd
633
 
 *      Initial revision.
634
 
 *
635
 
 *
636
 
 *)
 
778
(**********************************************************************)
 
779
(* DEPRECATED CLASSES                                                 *)
 
780
(**********************************************************************)
 
781
 
 
782
class resolve_read_this_channel :
 
783
  ?id:ext_id -> ?fixenc:encoding -> ?close:(in_channel -> unit) ->
 
784
  in_channel -> resolver;;
 
785
 
 
786
  (* THIS CLASS IS DEPRECATED! USE resolve_to_this_obj_channel INSTEAD!
 
787
   *)
 
788
 
 
789
  (* Reads from the passed channel (it may be even a pipe). If the ~id
 
790
   * argument is passed to the object, the created resolver accepts only
 
791
   * this ID (except Anonymous). Otherwise all IDs are accepted, even
 
792
   * Anonymous.
 
793
   * Once the resolver has been cloned, it does not accept any ID. This
 
794
   * means that this resolver cannot handle inner references to external
 
795
   * entities. Note that you can combine this resolver with another resolver
 
796
   * that can handle inner references (such as resolve_as_file); see
 
797
   * class 'combine' below.
 
798
   * If you pass the ~fixenc argument, the encoding of the channel is
 
799
   * set to the passed value, regardless of any auto-recognition or
 
800
   * any XML declaration.
 
801
   * When the resolver is closed, the function passed by the ~close
 
802
   * argument is called. By default, the channel is closed
 
803
   * (i.e. the default is: ~close:close_in).
 
804
   *)
 
805
 
 
806
 
 
807
class resolve_read_any_channel :
 
808
  ?close:(in_channel -> unit) ->
 
809
  channel_of_id:(ext_id -> (in_channel * encoding option)) ->
 
810
  unit ->
 
811
  resolver;;
 
812
 
 
813
  (* THIS CLASS IS DEPRECATED! USE resolve_to_any_obj_channel INSTEAD!
 
814
   *
 
815
   * Note: The function channel_of_id may be called several times to find
 
816
   * out the right ext_id from the current resolver_id. The first result
 
817
   * is taken that is not Not_competent.
 
818
   *)
 
819
 
 
820
  (* resolve_read_any_channel f_open ():
 
821
   * This resolver calls the function f_open to open a new channel for
 
822
   * the passed ext_id. This function must either return the channel and
 
823
   * the encoding, or it must fail with Not_competent.
 
824
   * The function must return None as encoding if the default mechanism to
 
825
   * recognize the encoding should be used. It must return Some e if it is
 
826
   * already known that the encoding of the channel is e.
 
827
   * When the resolver is closed, the function passed by the ~close
 
828
   * argument is called. By default, the channel is closed
 
829
   * (i.e. the default is: ~close:close_in).
 
830
   *)
 
831
 
 
832
class resolve_read_url_channel :
 
833
  ?base_url:Neturl.url ->
 
834
  ?close:(in_channel -> unit) ->
 
835
  url_of_id:(ext_id -> Neturl.url) ->
 
836
  channel_of_url:(ext_id -> Neturl.url -> (in_channel * encoding option)) ->
 
837
  unit ->
 
838
    resolver;;
 
839
 
 
840
  (* THIS CLASS IS DEPRECATED! USE resolve_to_url_obj_channel INSTEAD!
 
841
   *
 
842
   * Note: The function url_of_id may be called several times to find
 
843
   * out the right ext_id from the current resolver_id. The first result
 
844
   * is taken that is not Not_competent.
 
845
   *
 
846
   * Note: The optional argument base_url is ignored. The class uses always
 
847
   * the rid_system_base string to interpret relative URLs.
 
848
   *)
 
849
 
 
850
  (* resolve_read_url_channel url_of_id channel_of_url ():
 
851
   *
 
852
   * When this resolver gets an ID to read from, it calls the function
 
853
   * ~url_of_id to get the corresponding URL. This URL may be a relative
 
854
   * URL; however, a URL scheme must be used which contains a path.
 
855
   * The resolver converts the URL to an absolute URL if necessary.
 
856
   * The second function, ~channel_of_url, is fed with the absolute URL
 
857
   * as input. This function opens the resource to read from, and returns
 
858
   * the channel and the encoding of the resource.
 
859
   *
 
860
   * Both functions, ~url_of_id and ~channel_of_url, can raise
 
861
   * Not_competent to indicate that the object is not able to read from
 
862
   * the specified resource. However, there is a difference: A Not_competent
 
863
   * from ~url_of_id is left as it is, but a Not_competent from ~channel_of_url
 
864
   * is converted to Not_resolvable. So only ~url_of_id decides which URLs
 
865
   * are accepted by the resolver and which not.
 
866
   *
 
867
   * The function ~channel_of_url must return None as encoding if the default
 
868
   * mechanism to recognize the encoding should be used. It must return
 
869
   * Some e if it is already known that the encoding of the channel is e.
 
870
   *
 
871
   * When the resolver is closed, the function passed by the ~close
 
872
   * argument is called. By default, the channel is closed
 
873
   * (i.e. the default is: ~close:close_in).
 
874
   *
 
875
   * [Does not apply to current implementation but to former ones:]
 
876
   * Objects of this class contain a base URL relative to which relative
 
877
   * URLs are interpreted. When creating a new object, you can specify
 
878
   * the base URL by passing it as ~base_url argument. When an existing
 
879
   * object is cloned, the base URL of the clone is the URL of the original
 
880
   * object.
 
881
   *
 
882
   * Note that the term "base URL" has a strict definition in RFC 1808.
 
883
   *)
 
884
 
 
885
 
 
886
class resolve_read_this_string :
 
887
  ?id:ext_id -> ?fixenc:encoding -> string -> resolver;;
 
888
 
 
889
  (* THIS CLASS IS DEPRECATED! USE resolve_to_this_obj_channel INSTEAD!
 
890
   *)
 
891
 
 
892
  (* Reads from the passed string. If the ~id
 
893
   * argument is passed to the object, the created resolver accepts only
 
894
   * this ID (except Anonymous). Otherwise all IDs are accepted, even
 
895
   * Anonymous.
 
896
   * Once the resolver has been cloned, it does not accept any ID. This
 
897
   * means that this resolver cannot handle inner references to external
 
898
   * entities. Note that you can combine this resolver with another resolver
 
899
   * that can handle inner references (such as resolve_as_file); see
 
900
   * class 'combine' below.
 
901
   * If you pass the ~fixenc argument, the encoding of the string is
 
902
   * set to the passed value, regardless of any auto-recognition or
 
903
   * any XML declaration.
 
904
   *)
 
905
 
 
906
 
 
907
class resolve_read_any_string :
 
908
  string_of_id:(ext_id -> (string * encoding option)) -> unit -> resolver;;
 
909
 
 
910
  (* THIS CLASS IS DEPRECATED! USE resolve_to_any_obj_channel INSTEAD!
 
911
   *)
 
912
 
 
913
  (* resolver_read_any_string f_open ():
 
914
   * This resolver calls the function f_open to get the string for
 
915
   * the passed ext_id. This function must either return the string and
 
916
   * the encoding, or it must fail with Not_competent.
 
917
   * The function must return None as encoding if the default mechanism to
 
918
   * recognize the encoding should be used. It must return Some e if it is
 
919
   * already known that the encoding of the string is e.
 
920
   *)
 
921
 
 
922
val lookup_public_id_as_file :
 
923
  ?fixenc:encoding ->
 
924
  (string * string) list ->     (* catalog *)
 
925
    resolver;;
 
926
  (* Same as the equally named class *)
 
927
 
 
928
val lookup_public_id_as_string :
 
929
  ?fixenc:encoding ->
 
930
  (string * string) list ->     (* catalog *)
 
931
    resolver;;
 
932
  (* Same as the equally named class *)
 
933
 
 
934
val lookup_system_id_as_file :
 
935
  ?fixenc:encoding ->
 
936
  (string * string) list ->     (* catalog *)
 
937
    resolver;;
 
938
  (* Same as the equally named class *)
 
939
 
 
940
val lookup_system_id_as_string :
 
941
  ?fixenc:encoding ->
 
942
  (string * string) list ->     (* catalog *)
 
943
    resolver;;
 
944
  (* Same as the equally named class *)
 
945