Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
(* bcprex.ml -- A little hack for downloading data to a Xircom Rex
organizer from a linux system.
Author: Benjamin C. Pierce
This code may be distributed under the terms of the GNU Public License.
This _very simple and unpolished_ little program takes all the
information in the directory where it is started and formats it so
that it can be downloaded to a Xircom Rex organizer. It handles just
the features I needed, and no more. You will probably need to hack
it yourself to adapt it to your needs.
WHAT YOU WILL NEED:
1) A Xircom RexPro organizer (buy from your favorite gadget store;
they cost about $100)
2) A copy of the "TruSync linux beta developer pack" from StarFish
software. Download this from
http://www.starfish.com/tsdn/linux.html
unpack it, and put the binary file ProConnect somewhere in your
search path.
3) An Objective Caml compiler to compile this file. Download the
O'Caml system from http://caml.inria.fr and install according to
the instructions. (If you haven't installed O'Caml before, it's
easy. RPMs are provided for Redhat systems.)
INSTRUCTIONS:
1) Compile the present file like this:
ocamlc -o bcprex unix.cma str.cma bcprex.ml -cclib -lunix
2) Put the executable file bcprex in your search path
3) Cd to the directory where you will keep the files you want to download
to the rex
4) Initialize the Rex (if you haven't already): tell it your name,
the current time, etc.
5) Insert the Rex card in your PCMCIA slot
6) Check that /dev/mem0c now exists. If it does, make sure that
it's readable by ProConnect, either by doing
chmod a+rw /dev/mem0c
or by making ProConnect itself owned by root and setuid.
7) Upload the current state by typing
ProConnect -o init.rexdump -f /dev/mem0c
8) Create some files that you want to download (see information
below on formats)
9) Download your data by executing 'bcprex' (from in this directory)
SUPPORTED FORMATS:
* TEXT FILES with extension .txt are downloaded as Rex memos. The first
line of the file is used as the title of the memo, the rest as the
body.
* VCARD FILES with extension .vcd are interpreted as lists of VCards
and downloaded as contact records. Each VCard looks like this:
BEGIN:VCARD
END:VCARD
where each can be:
N:lastname;firstname;middlename;title;suffix
(all fields optional, but the ; separators are required)
TEL;HOME:
TEL;WORK:
:
where is any other field name and is a
string terminated by a carriage return not immediately
followed by a space (a CR followed by a space is ignored).
Sample VCard:
BEGIN:VCARD
N:Smith;John;;;
TEL;WORK:123 222 3333
TEL;HOME:987 654 3210
ADR:222 Main St., Philadelphia, PA 19191
NOTE:Some information.
Some more information.
END:VCARD
The N, TEL;WORK, and TEL;HOME fields are treated specially. All other
fields are concatenated and dumped into the contact record as a note.
WISH LIST:
* It would be nice to download appointments as Rex calendar records
* At the moment, Rex categories are not supported in any way
* I couldn't figure out how to get a quote or hash character into the
Rex: the string escape convention in the TruSync thing seems
broken.
*)
open Printf
let outchan = ref None
let theoutchan() =
match !outchan with
None -> assert false
| Some(ch) -> ch
let emit s = output_string (theoutchan()) s
let emitln s = emit s; emit "\n"
let error s = print_string s; exit 1
let readdir f =
let dir = Unix.opendir f in
let rec loop files =
let f = try Unix.readdir dir with End_of_file -> "" in
if f="" then files
else if f="." || f=".." then loop files
else loop (f::files)
in
let files = loop [] in
Unix.closedir dir;
files
let rec trim s =
let l = String.length s in
if l=0 then s
else if s.[0]=' ' || s.[0]='\t' || s.[0]='\n' || s.[0]='\r' then
trim (String.sub s 1 (l-1))
else if s.[l-1]=' ' || s.[l-1]='\t' || s.[l-1]='\n' || s.[l-1]='\r' then
trim (String.sub s 0 (l-1))
else
s
let rec trimEnd s =
let l = String.length s in
if l=0 then s
else if s.[l-1]=' ' || s.[l-1]='\t' || s.[l-1]='\n' || s.[l-1]='\r' then
trimEnd (String.sub s 0 (l-1))
else
s
let readfile f =
try
let ch = open_in f in
let rec loop lines =
match
try Some(input_line ch) with End_of_file -> None
with
None -> List.rev lines
| Some(l) -> loop ((trimEnd l)::lines) in
let res = loop [] in
close_in ch;
res
with
Sys_error _ -> []
(* ---------------------------------------------------------------------- *)
let quotechar = Str.regexp "\""
let hashchar = Str.regexp "#"
let slashchar = Str.regexp "/"
let semichar = Str.regexp ";"
let escape s =
let s = Str.global_replace slashchar "//" s in
(* let s = Str.global_replace quotechar "/\"" s in *)
let s = Str.global_replace quotechar "'" s in
let s = Str.global_replace hashchar "" s in
s
let processMemo f =
printf "Memo %s\n" f;
let ll = readfile f in
let title = List.hd ll in
let body = List.tl ll in
emit (sprintf "memo 1 \"%s\" \"" title);
List.iter (fun l -> emit (escape l); emit " #\n") body;
emit "\"\n"
(* ---------------------------------------------------------------------- *)
let collectVCards ll =
let rec nextCard cards = function
[] -> List.rev cards
| "BEGIN:VCARD" :: rest -> nextField cards [] rest
| "" :: rest -> nextCard cards rest
| s :: rest -> error (sprintf "Unrecognized vcard format: %s\n" s)
and nextField cards fields = function
[] -> error "End of file while processing a VCARD"
| "END:VCARD"::rest -> nextCard ((List.rev fields)::cards) rest
| ""::rest -> nextField cards fields rest
| s::rest when s.[0] = ' ' ->
if fields=[] then
error "Line beginning with blank at beginning of VCARD"
else
nextField cards (((List.hd fields) ^ s) :: (List.tl fields)) rest
| s::rest ->
nextField cards (s::fields) rest
in nextCard [] ll
let notes = ref ""
let dumpfield f =
let colonpos =
try
String.index f ':'
with Not_found ->
error (sprintf "VCard field '%s' does not contain a colon" f) in
let kind = String.sub f 0 colonpos in
let body =
escape (String.sub f (colonpos+1) (String.length f - colonpos - 1)) in
match kind with
"N" ->
let parts = Str.split_delim semichar body in
if List.length parts <> 5 then
error (sprintf "VCARD name field should have five (not %d) parts (%s)"
(List.length parts) body);
emit " 1 0 \"";
emit (List.nth parts 0);
emit "\"\n";
emit " 2 0 \"";
if (List.nth parts 1) <> "" then begin
emit (List.nth parts 1);
emit " ";
end;
emit (List.nth parts 2);
if (List.nth parts 3) <> "" then begin
emit " ";
emit (List.nth parts 3);
end;
if (List.nth parts 4) <> "" then begin
emit " ";
emit (List.nth parts 4);
end;
emit "\"\n";
| "TEL;WORK" ->
emit " 17 0 \"";
emit body;
emit "\"\n"
| "TEL;HOME" ->
emit " 18 0 \"";
emit body;
emit "\"\n"
| _ ->
notes := !notes ^ " || " ^ body
let dumpnotes() =
if !notes <> "" then begin
emit " 0 0 \"";
emit !notes;
emit "\"\n";
end;
notes := ""
let dumpcard c =
emit "contact 1 0\n";
List.iter dumpfield c;
dumpnotes()
let processAddresses f =
List.iter dumpcard (collectVCards (readfile f))
(* ---------------------------------------------------------------------- *)
let processfile f =
if Filename.check_suffix f ".txt" then processMemo f
else if Filename.check_suffix f ".sp" then processMemo f
else if Filename.check_suffix f ".todo" then processMemo f
else if Filename.check_suffix f ".vcd" then processAddresses f
else printf "Skipping %s\n" f
let initrex() =
let init = readfile "init.rexdump" in
List.iter emitln init
let main() =
outchan := Some(open_out "rexdump.tmp");
initrex();
let files = readdir "." in
List.iter processfile files;
emit "done\n";
close_out (theoutchan());
flush stdout;
(*
let ll = readfile "rexdump.tmp" in
List.iter (fun l -> print_string l; print_newline()) ll
*)
let result = Sys.command "ProConnect -i rexdump.tmp -f /dev/mem0c" in
if result <> 0 then printf "ProConnect failed with exit code %d\n" result;
exit result
;; main()