mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
rewrote the HTTP encoding, and missing functions
This commit is contained in:
parent
7313a258b4
commit
a860e67443
4 changed files with 92 additions and 70 deletions
|
|
@ -4,8 +4,13 @@
|
||||||
#directory "_build/tests/";;
|
#directory "_build/tests/";;
|
||||||
#load "containers.cma";;
|
#load "containers.cma";;
|
||||||
#require "threads";;
|
#require "threads";;
|
||||||
#load "thread_containers.cma";;
|
#load "containers_thread.cma";;
|
||||||
|
open Containers;;
|
||||||
open Sequence.Infix;;
|
open Sequence.Infix;;
|
||||||
#install_printer Bencode.pretty;;
|
#install_printer Bencode.pretty;;
|
||||||
|
#require "CamlGI";;
|
||||||
|
#load "containers_cgi.cma";;
|
||||||
|
let pp_html fmt h = Format.pp_print_string fmt (ToWeb.HTML.render h);;
|
||||||
|
#install_printer pp_html;;
|
||||||
(* vim:syntax=ocaml:
|
(* vim:syntax=ocaml:
|
||||||
*)
|
*)
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ debug="true"
|
||||||
profile="false"
|
profile="false"
|
||||||
native_dynlink="true"
|
native_dynlink="true"
|
||||||
ocamlbuildflags=""
|
ocamlbuildflags=""
|
||||||
cgi="false"
|
cgi="true"
|
||||||
lwt="false"
|
lwt="false"
|
||||||
thread="true"
|
thread="true"
|
||||||
bench="false"
|
bench="false"
|
||||||
|
|
@ -58,6 +58,7 @@ tests="false"
|
||||||
ocaml_version_ge_4_00_1="4.00.1"
|
ocaml_version_ge_4_00_1="4.00.1"
|
||||||
pkg_unix="/usr/lib/ocaml"
|
pkg_unix="/usr/lib/ocaml"
|
||||||
pkg_threads="/usr/lib/ocaml"
|
pkg_threads="/usr/lib/ocaml"
|
||||||
|
pkg_camlgi="/home/simon/.opam/system/lib/CamlGI"
|
||||||
ocamldoc="/usr/bin/ocamldoc"
|
ocamldoc="/usr/bin/ocamldoc"
|
||||||
pkg_bench="/home/simon/.opam/system/lib/bench"
|
pkg_bench="/home/simon/.opam/system/lib/bench"
|
||||||
pkg_ounit="/home/simon/.opam/system/lib/oUnit"
|
pkg_ounit="/home/simon/.opam/system/lib/oUnit"
|
||||||
|
|
|
||||||
139
toWeb.ml
139
toWeb.ml
|
|
@ -44,6 +44,7 @@ module HTML = struct
|
||||||
| H of int * t
|
| H of int * t
|
||||||
| Link of link
|
| Link of link
|
||||||
| Tag of string * t
|
| Tag of string * t
|
||||||
|
| TagWith of string * (string * string) list * t
|
||||||
and url = {
|
and url = {
|
||||||
url_alt : string option;
|
url_alt : string option;
|
||||||
url_url : string;
|
url_url : string;
|
||||||
|
|
@ -62,16 +63,19 @@ module HTML = struct
|
||||||
|
|
||||||
let bprintf format =
|
let bprintf format =
|
||||||
let buffer = Buffer.create 64 in
|
let buffer = Buffer.create 64 in
|
||||||
|
let r = ref (str "") in
|
||||||
Printf.kbprintf
|
Printf.kbprintf
|
||||||
(fun fmt -> str (Buffer.contents buffer))
|
(fun x -> r := str (Buffer.contents buffer))
|
||||||
buffer
|
buffer
|
||||||
format
|
format;
|
||||||
|
!r
|
||||||
|
|
||||||
let bprintf format =
|
let sprintf format =
|
||||||
let buffer = Buffer.create 64 in
|
let r = ref (str "") in
|
||||||
Printf.ksprintf
|
Printf.ksprintf
|
||||||
str
|
(fun s -> r := str s)
|
||||||
format
|
format;
|
||||||
|
!r
|
||||||
|
|
||||||
let list l = List l
|
let list l = List l
|
||||||
|
|
||||||
|
|
@ -97,6 +101,22 @@ module HTML = struct
|
||||||
let h3 x = H (3, x)
|
let h3 x = H (3, x)
|
||||||
|
|
||||||
let h n x = H (n, x)
|
let h n x = H (n, x)
|
||||||
|
|
||||||
|
let p x = Tag ("p", x)
|
||||||
|
|
||||||
|
let div ?id ?class_ x =
|
||||||
|
match id, class_ with
|
||||||
|
| None, None -> Tag ("div", x)
|
||||||
|
| Some i, None -> TagWith ("div", ["id", i], x)
|
||||||
|
| None, Some c -> TagWith ("div", ["class", c], x)
|
||||||
|
| Some i, Some c -> TagWith ("div", ["id", i; "class", c], x)
|
||||||
|
|
||||||
|
let span ?id ?class_ x =
|
||||||
|
match id, class_ with
|
||||||
|
| None, None -> Tag ("span", x)
|
||||||
|
| Some i, None -> TagWith ("span", ["id", i], x)
|
||||||
|
| None, Some c -> TagWith ("span", ["class", c], x)
|
||||||
|
| Some i, Some c -> TagWith ("span", ["id", i; "class", c], x)
|
||||||
|
|
||||||
let link ~rel ~url = Link {
|
let link ~rel ~url = Link {
|
||||||
link_rel = rel;
|
link_rel = rel;
|
||||||
|
|
@ -109,69 +129,39 @@ module HTML = struct
|
||||||
|
|
||||||
let html x = Tag ("html", x)
|
let html x = Tag ("html", x)
|
||||||
|
|
||||||
(* XXX UGLY: I copied code from CamlGI because it doesn't provide a way
|
let _to_hex n = match n with
|
||||||
to encode strings with HTML conventions. Bad bad bad. *)
|
| _ when n >= 0 && n < 10 -> Char.chr (Char.code '0' + n)
|
||||||
module Encode = struct
|
| 10 -> 'A'
|
||||||
(* Use a table lookup for speed. *)
|
| 11 -> 'B'
|
||||||
let char_of_hex =
|
| 12 -> 'C'
|
||||||
let hex = [| '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9';
|
| 13 -> 'D'
|
||||||
'A'; 'B'; 'C'; 'D'; 'E'; 'F' |] in
|
| 14 -> 'E'
|
||||||
fun i -> Array.unsafe_get hex i
|
| 15 -> 'F'
|
||||||
|
| _ -> failwith "not an hexadecimal digit"
|
||||||
|
|
||||||
|
let _encode_char buf c =
|
||||||
|
Buffer.add_string buf "&#x";
|
||||||
|
let h, l = Char.code c / 16, Char.code c mod 16 in
|
||||||
|
Buffer.add_char buf (_to_hex h);
|
||||||
|
Buffer.add_char buf (_to_hex l)
|
||||||
|
|
||||||
let encode_wrt is_special s0 =
|
let encode str =
|
||||||
let len = String.length s0 in
|
let b = Buffer.create (String.length str + 10) in
|
||||||
let encoded_length = ref len in
|
for i = 0 to String.length str - 1 do
|
||||||
for i = 0 to len - 1 do
|
match str.[i] with
|
||||||
if is_special(String.unsafe_get s0 i) then
|
| ';' | '/' | '?' | ':' | '@' | '&' | '=' | '+' | '$' | ',' | '<'
|
||||||
encoded_length := !encoded_length + 2
|
| '>' | '#' | '%' | '"' | '{' | '}' | '|' | '\\' | '^' | '[' | ']'
|
||||||
done;
|
| '`' -> _encode_char b str.[i]
|
||||||
let s = String.create !encoded_length in
|
| c when Char.code c < 32 -> _encode_char b str.[i]
|
||||||
let rec do_enc i0 i = (* copy the encoded string in s *)
|
| c when Char.code c > 127 -> _encode_char b str.[i]
|
||||||
if i0 < len then begin
|
| _ -> Buffer.add_char b str.[i]
|
||||||
let s0i0 = String.unsafe_get s0 i0 in
|
done;
|
||||||
if is_special s0i0 then begin
|
Buffer.contents b
|
||||||
let c = Char.code s0i0 in
|
|
||||||
let i1 = succ i in
|
|
||||||
let i2 = succ i1 in
|
|
||||||
String.unsafe_set s i '%';
|
|
||||||
String.unsafe_set s i1 (char_of_hex (c lsr 4));
|
|
||||||
String.unsafe_set s i2 (char_of_hex (c land 0x0F));
|
|
||||||
do_enc (succ i0) (succ i2)
|
|
||||||
end
|
|
||||||
else if s0i0 = ' ' then begin
|
|
||||||
String.unsafe_set s i '+';
|
|
||||||
do_enc (succ i0) (succ i)
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
String.unsafe_set s i s0i0;
|
|
||||||
do_enc (succ i0) (succ i)
|
|
||||||
end
|
|
||||||
end in
|
|
||||||
do_enc 0 0;
|
|
||||||
s
|
|
||||||
|
|
||||||
|
|
||||||
(* Unreserved characters consist of all alphanumeric chars and the
|
|
||||||
following limited set of punctuation marks and symbols: '-' | '_' |
|
|
||||||
'.' | '!' | '~' | '*' | '\'' | '(' | ')'. According to RFC 2396,
|
|
||||||
they should not be escaped unless the context requires it. *)
|
|
||||||
let special_rfc2396 = function
|
|
||||||
| ';' | '/' | '?' | ':' | '@' | '&' | '=' | '+' | '$' | ',' (* Reserved *)
|
|
||||||
| '\000' .. '\031' | '\127' .. '\255' (* Control chars and non-ASCII *)
|
|
||||||
| '<' | '>' | '#' | '%' | '"' (* delimiters *)
|
|
||||||
| '{' | '}' | '|' | '\\' | '^' | '[' | ']' | '`' (* unwise *)
|
|
||||||
-> true
|
|
||||||
| _ -> false
|
|
||||||
(* ' ' must also be encoded but its encoding '+' takes a single char. *)
|
|
||||||
|
|
||||||
let encode = encode_wrt special_rfc2396
|
|
||||||
end
|
|
||||||
|
|
||||||
(* real rendering is always into a buffer (for now) *)
|
(* real rendering is always into a buffer (for now) *)
|
||||||
let rec to_buf buf x =
|
let rec to_buf buf x =
|
||||||
match x with
|
match x with
|
||||||
| Str s -> Buffer.add_string buf (Encode.encode s)
|
| Str s -> Buffer.add_string buf (encode s)
|
||||||
| List l ->
|
| List l ->
|
||||||
Buffer.add_string buf "<ul>";
|
Buffer.add_string buf "<ul>";
|
||||||
List.iter
|
List.iter
|
||||||
|
|
@ -182,17 +172,26 @@ module HTML = struct
|
||||||
begin match url.url_alt with
|
begin match url.url_alt with
|
||||||
| None ->
|
| None ->
|
||||||
Printf.bprintf buf "<a href=\"%s\">%s</a>" url.url_url
|
Printf.bprintf buf "<a href=\"%s\">%s</a>" url.url_url
|
||||||
(Encode.encode url.url_descr)
|
(encode url.url_descr)
|
||||||
| Some alt ->
|
| Some alt ->
|
||||||
Printf.bprintf buf "<a href=\"%s\" alt=\"%s\">%s</a>"
|
Printf.bprintf buf "<a href=\"%s\" alt=\"%s\">%s</a>"
|
||||||
url.url_url (Encode.encode alt) (Encode.encode url.url_descr)
|
url.url_url (encode alt) (encode url.url_descr)
|
||||||
end
|
end
|
||||||
| Img i -> failwith "img: not implemented"
|
| Img i -> failwith "img: not implemented"
|
||||||
| Concat l -> List.iter (to_buf buf) l
|
| Concat l ->
|
||||||
|
List.iteri
|
||||||
|
(fun i y ->
|
||||||
|
if i > 0 then Buffer.add_char buf ' ';
|
||||||
|
to_buf buf y)
|
||||||
|
l
|
||||||
| H (n, y) ->
|
| H (n, y) ->
|
||||||
Printf.bprintf buf "<h%i> %a </h%i>" n to_buf y n
|
Printf.bprintf buf "<h%i> %a </h%i>" n to_buf y n
|
||||||
| Link _ -> failwith "link: not implemented"
|
| Link _ -> failwith "link: not implemented"
|
||||||
| Tag (str, y) -> Printf.bprintf buf "<%s> %a </%s>" str to_buf y str
|
| Tag (str, y) -> Printf.bprintf buf "<%s> %a </%s>" str to_buf y str
|
||||||
|
| TagWith (str, attrs, y) ->
|
||||||
|
Printf.bprintf buf "<%s " str;
|
||||||
|
List.iter (fun (name,attr) -> Printf.bprintf buf "%s=\"%s\"" name attr) attrs;
|
||||||
|
Printf.bprintf buf "> %a </%s>" to_buf y str
|
||||||
|
|
||||||
let render x =
|
let render x =
|
||||||
let buf = Buffer.create 256 in
|
let buf = Buffer.create 256 in
|
||||||
|
|
@ -339,3 +338,11 @@ module Router = struct
|
||||||
match st with
|
match st with
|
||||||
| State.Wrap st -> State.handle_request st req
|
| State.Wrap st -> State.handle_request st req
|
||||||
end
|
end
|
||||||
|
|
||||||
|
(** {2 Main Interface} *)
|
||||||
|
|
||||||
|
let serve_state ?sockaddr st =
|
||||||
|
CamlGI.Cgi.register_script ?sockaddr (State.handle_request st)
|
||||||
|
|
||||||
|
let serve_router ?sockaddr router =
|
||||||
|
CamlGI.Cgi.register_script ?sockaddr (Router.handle_request router)
|
||||||
|
|
|
||||||
13
toWeb.mli
13
toWeb.mli
|
|
@ -41,10 +41,10 @@ module HTML : sig
|
||||||
val str : string -> t
|
val str : string -> t
|
||||||
(** Simple string *)
|
(** Simple string *)
|
||||||
|
|
||||||
val bprintf : ('a, Buffer.t, unit, string) format4 -> t
|
val bprintf : ('a, Buffer.t, unit, unit) format4 -> t
|
||||||
(** Use a buffer printer to render a string. Shortcut for {!str} *)
|
(** Use a buffer printer to render a string. Shortcut for {!str} *)
|
||||||
|
|
||||||
val sprintf : ('a, unit, string) format -> t
|
val sprintf : ('a, unit, string, unit) format4 -> t
|
||||||
(** Use a string printer to render into a string. Shortcut for {!str} *)
|
(** Use a string printer to render into a string. Shortcut for {!str} *)
|
||||||
|
|
||||||
val list : t list -> t
|
val list : t list -> t
|
||||||
|
|
@ -71,6 +71,15 @@ module HTML : sig
|
||||||
val h : int -> t -> t
|
val h : int -> t -> t
|
||||||
(** Title of level parametrized by the integer *)
|
(** Title of level parametrized by the integer *)
|
||||||
|
|
||||||
|
val p : t -> t
|
||||||
|
(** Paragraph *)
|
||||||
|
|
||||||
|
val div : ?id:string -> ?class_:string -> t -> t
|
||||||
|
(** Div tag, to specify a block *)
|
||||||
|
|
||||||
|
val span : ?id:string -> ?class_:string -> t -> t
|
||||||
|
(** Non semantic tag, mostly useful for CSS *)
|
||||||
|
|
||||||
val link : rel:string -> url:string -> t
|
val link : rel:string -> url:string -> t
|
||||||
(** Link (for head) *)
|
(** Link (for head) *)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue