r47300 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r47299‎ | r47300 | r47301 >
Date:21:44, 15 February 2009
Author:ipye
Status:deferred
Tags:
Comment:
Merge commit 'origin/ian-luca'
Modified paths:
  • /trunk/extensions/WikiTrust/analysis/Makefile (modified) (history)
  • /trunk/extensions/WikiTrust/analysis/server.ml (deleted) (history)
  • /trunk/extensions/WikiTrust/analysis/server_coloring_dispatcher.ml (deleted) (history)
  • /trunk/extensions/WikiTrust/analysis/tmpfile.ml (deleted) (history)
  • /trunk/extensions/WikiTrust/analysis/tmpfile.mli (deleted) (history)
  • /trunk/extensions/WikiTrust/analysis/wikipedia_api.ml (deleted) (history)
  • /trunk/extensions/WikiTrust/mediawiki/extensions/Trust/RemoteTrust.php (deleted) (history)
  • /trunk/extensions/WikiTrust/mediawiki/extensions/Trust/TrustUpdateScripts.inc (modified) (history)
  • /trunk/extensions/WikiTrust/mediawiki/extensions/Trust/css (added) (history)
  • /trunk/extensions/WikiTrust/mediawiki/extensions/Trust/css/trust.css (added) (history)
  • /trunk/extensions/WikiTrust/mediawiki/extensions/Trust/js/trust.js (added) (history)
  • /trunk/extensions/WikiTrust/remote (added) (history)
  • /trunk/extensions/WikiTrust/remote/README (added) (history)
  • /trunk/extensions/WikiTrust/remote/analysis (added) (history)
  • /trunk/extensions/WikiTrust/remote/analysis/Makefile (added) (history)
  • /trunk/extensions/WikiTrust/remote/analysis/server.ml (added) (history)
  • /trunk/extensions/WikiTrust/remote/analysis/server.py (added) (history)
  • /trunk/extensions/WikiTrust/remote/analysis/server_coloring_dispatcher.ml (added) (history)
  • /trunk/extensions/WikiTrust/remote/analysis/tmpfile.ml (added) (history)
  • /trunk/extensions/WikiTrust/remote/analysis/tmpfile.mli (added) (history)
  • /trunk/extensions/WikiTrust/remote/analysis/wikipedia_api.ml (added) (history)
  • /trunk/extensions/WikiTrust/remote/mediawiki (added) (history)
  • /trunk/extensions/WikiTrust/remote/mediawiki/extensions (added) (history)
  • /trunk/extensions/WikiTrust/remote/mediawiki/extensions/Trust (added) (history)
  • /trunk/extensions/WikiTrust/remote/mediawiki/extensions/Trust/RemoteTrust.i18n.php (added) (history)
  • /trunk/extensions/WikiTrust/remote/mediawiki/extensions/Trust/RemoteTrust.php (added) (history)
  • /trunk/extensions/WikiTrust/remote/mediawiki/extensions/Trust/RemoteTrustImpl.php (added) (history)
  • /trunk/extensions/WikiTrust/remote/mediawiki/extensions/Trust/RemoteTrustUpdate.php (added) (history)
  • /trunk/extensions/WikiTrust/test-scripts/load_data.py (modified) (history)

Diff [purge]

Index: trunk/extensions/WikiTrust/analysis/wikipedia_api.ml
@@ -1,193 +0,0 @@
2 -(*
3 -
4 -Copyright (c) 2007-2008 The Regents of the University of California
5 -All rights reserved.
6 -
7 -Authors: Luca de Alfaro, Ian Pye
8 -
9 -Redistribution and use in source and binary forms, with or without
10 -modification, are permitted provided that the following conditions are met:
11 -
12 -1. Redistributions of source code must retain the above copyright notice,
13 -this list of conditions and the following disclaimer.
14 -
15 -2. Redistributions in binary form must reproduce the above copyright notice,
16 -this list of conditions and the following disclaimer in the documentation
17 -and/or other materials provided with the distribution.
18 -
19 -3. The names of the contributors may not be used to endorse or promote
20 -products derived from this software without specific prior written
21 -permission.
22 -
23 -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 -POSSIBILITY OF SUCH DAMAGE.
34 -
35 - *)
36 -
37 -(* Using the wikipedia API, retrieves information about pages and revisions *)
38 -
39 -open Http_client;;
40 -open ExtLib;;
41 -open Gzip;;
42 -open Xml;;
43 -open Online_types;;
44 -open Str;;
45 -
46 -exception Http_client_error
47 -
48 -Random.self_init ()
49 -
50 -let pipeline = new pipeline
51 -let buf_len = 8192
52 -let requested_encoding_type = "gzip"
53 -let tmp_prefix = "wiki"
54 -let rev_lim = "50"
55 -let api_tz_re = Str.regexp "\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\)T\\([0-9][0-9]\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)Z"
56 -
57 -(* Maps the Wikipedias api timestamp to our internal one. *)
58 -let api_ts2mw_ts s =
59 - let ts = if string_match api_tz_re s 0 then
60 - (matched_group 1 s) ^ (matched_group 2 s) ^ (matched_group 3 s)
61 - ^ (matched_group 4 s) ^ (matched_group 5 s) ^ (matched_group 6 s)
62 - else "19700201000000" in
63 - ts
64 -
65 -(* Given an input channel, return a string representing all there is
66 - to be read of this channel. *)
67 -let input_all ic =
68 - let rec loop acc total buf ofs =
69 - let n = input ic buf ofs (buf_len - ofs) in
70 - if n = 0 then
71 - let res = String.create total in
72 - let pos = total - ofs in
73 - let _ = String.blit buf 0 res pos ofs in
74 - let coll pos buf =
75 - let new_pos = pos - buf_len in
76 - String.blit buf 0 res new_pos buf_len;
77 - new_pos in
78 - let _ = List.fold_left coll pos acc in
79 - res
80 - else
81 - let new_ofs = ofs + n in
82 - let new_total = total + n in
83 - if new_ofs = buf_len then
84 - loop (buf :: acc) new_total (String.create buf_len) 0
85 - else loop acc new_total buf new_ofs in
86 - loop [] 0 (String.create buf_len) 0
87 -
88 -(*
89 - Given a string url, make a get call and return the response as a string.
90 -*)
91 -let run_call url =
92 - let call = new get url in
93 - let request_header = call # request_header `Base in
94 - (* Accept gziped format *)
95 - request_header # update_field "Accept-encoding" requested_encoding_type;
96 - call # set_request_header request_header;
97 - pipeline # add call;
98 - pipeline # run();
99 - match call # status with
100 - | `Successful -> (
101 - let body = call # response_body # value in
102 - let repsponse_header = call # response_header in
103 - Printf.printf "content_type: %s\n"
104 - (let cnt,_ = (repsponse_header # content_type ()) in cnt);
105 - match (repsponse_header # content_type ()) with
106 - | ("text/xml",_) -> (
107 - let tmp_file = Tmpfile.new_tmp_file_name tmp_prefix in
108 - Std.output_file ~filename:tmp_file ~text:body;
109 - let in_chan = Gzip.open_in tmp_file in
110 - let decoded_body = input_all in_chan in
111 - Gzip.close_in in_chan;
112 - Tmpfile.remove_tmp_file tmp_file;
113 - decoded_body
114 - )
115 - | _ -> body
116 - )
117 - | _ -> raise Http_client_error
118 -;;
119 -
120 -(*
121 - Internal xml processing for the api
122 -*)
123 -let process_rev (rev : xml) : wiki_revision =
124 - let w_rev = {
125 - revision_id = int_of_string (Xml.attrib rev "revid");
126 - revision_page = 0;
127 - revision_text_id = int_of_string (Xml.attrib rev "revid");
128 - revision_comment = (try (Xml.attrib rev "comment")
129 - with Xml.No_attribute e -> "");
130 - revision_user = -1;
131 - revision_user_text = (Xml.attrib rev "user");
132 - revision_timestamp = api_ts2mw_ts (Xml.attrib rev "timestamp");
133 - revision_minor_edit = (try ignore(Xml.attrib rev "minor"); true
134 - with Xml.No_attribute e -> false);
135 - revision_deleted = false;
136 - revision_len = (try int_of_string (Xml.attrib rev "size") with Xml.No_attribute e -> 0);
137 - revision_parent_id = 0;
138 - revision_content = (Netencoding.Html.decode ~in_enc:`Enc_utf8
139 - ~out_enc:`Enc_utf8 ()
140 - (Xml.to_string (List.hd (Xml.children rev))));
141 - } in
142 - w_rev
143 -
144 -(*
145 - Internal xml processing for the api
146 -*)
147 -let process_page (page : xml) : (wiki_page option * wiki_revision list) =
148 - let w_page = {
149 - page_id = int_of_string (Xml.attrib page "pageid");
150 - page_namespace = (int_of_string (Xml.attrib page "ns"));
151 - page_title = (Xml.attrib page "title");
152 - page_restrictions = "";
153 - page_counter = int_of_string (Xml.attrib page "counter");
154 - page_is_redirect = (try ignore(Xml.attrib page "redirect"); true
155 - with Xml.No_attribute e -> false);
156 - page_is_new = false;
157 - page_random = (Random.float 1.0);
158 - page_touched = api_ts2mw_ts (Xml.attrib page "touched");
159 - page_latest = int_of_string (Xml.attrib page "lastrevid");
160 - page_len = int_of_string (Xml.attrib page "length")
161 - } in
162 - let revs = Xml.children page in
163 - (Some w_page, (Xml.map process_rev (List.hd revs)))
164 -
165 -(*
166 - Given a page and date to start with, returns the next n revs for this page.
167 -*)
168 -let fetch_page_and_revs_after (page_title : string) (rev_date : string) : (wiki_page option * wiki_revision list) =
169 - let url = !Online_command_line.target_wikimedia
170 - ^ "?action=query&prop=revisions|"
171 - ^ "info&format=xml&inprop=&rvprop=ids|flags|timestamp|user|size|comment|"
172 - ^ "content&rvstart=" ^ rev_date ^ "&rvlimit=" ^ rev_lim
173 - ^ "&rvdir=newer&titles=" ^ page_title in
174 - if !Online_command_line.dump_db_calls then Printf.printf "%s\n" url;
175 - let res = run_call url in
176 - let api = Xml.parse_string res in
177 - let query = Xml.children (api) in
178 - let poss_pages = Xml.children (List.hd query) in
179 - let pick_page acc page =
180 - if (Xml.tag page = "pages") then
181 - process_page (List.hd (Xml.children page))
182 - else acc
183 - in
184 - List.fold_left pick_page (None,[]) poss_pages
185 -;;
186 -
187 -(* Given a user_name, returns the corresponding user_id *)
188 -let get_user_id (user_name : string) : int =
189 - let url = !Online_command_line.user_id_server ^ "?n=" ^ user_name in
190 - if !Online_command_line.dump_db_calls then Printf.printf "%s\n" url;
191 - let uids = ExtString.String.nsplit (run_call url) "`" in
192 - let uid = List.nth uids 1 in
193 - try int_of_string uid with int_of_string -> 0 in
194 -;;
Index: trunk/extensions/WikiTrust/analysis/tmpfile.ml
@@ -1,37 +0,0 @@
2 -(***********************************************************************)
3 -(* *)
4 -(* Objective Caml *)
5 -(* *)
6 -(* Fran�ois Pessaux, projet Cristal, INRIA Rocquencourt *)
7 -(* Pierre Weis, projet Cristal, INRIA Rocquencourt *)
8 -(* Jun Furuse, projet Cristal, INRIA Rocquencourt *)
9 -(* *)
10 -(* Copyright 1999 - 2003 *)
11 -(* Institut National de Recherche en Informatique et en Automatique. *)
12 -(* Distributed only by permission. *)
13 -(* *)
14 -(***********************************************************************)
15 -
16 -(* temporary directory *)
17 -let tmp_dir = ref (try Sys.getenv "CAMLTMPDIR" with Not_found -> "/tmp");;
18 -
19 -let cnter = ref 0;;
20 -
21 -let rec new_tmp_name prefx =
22 - incr cnter;
23 - let name =
24 - Filename.concat !tmp_dir
25 - (Printf.sprintf "camltmp-%s-%d" prefx !cnter) in
26 - if not (Sys.file_exists name) then name else begin
27 - prerr_endline ("Warning: tmp file " ^ name ^ " already exists");
28 - new_tmp_name prefx
29 - end;;
30 -
31 -let remove_tmp_file tmpfile = try Sys.remove tmpfile with _ -> ();;
32 -
33 -let new_tmp_file_name prefx =
34 - if not (Sys.file_exists !tmp_dir) then
35 - failwith ("Temporary directory " ^ !tmp_dir ^ " does not exist") else
36 - let f = new_tmp_name prefx in
37 - at_exit (fun () -> remove_tmp_file f);
38 - f;;
Index: trunk/extensions/WikiTrust/analysis/server.ml
@@ -1,235 +0,0 @@
2 -(* This is a webserver built from the Netplex and Nethttpd components.
3 - * It is configured in the netplex.cfg file.
4 - * Note: start program with option "-conf netplex.cfg"
5 - * The basic code is copied from the nethttpd example.
6 - *)
7 -
8 -open Netcgi1_compat.Netcgi_types;;
9 -open Printf;;
10 -open Mysql;;
11 -open Online_db;;
12 -open Online_command_line;;
13 -open Gzip;;
14 -
15 -let tmp_prefix = "wiki-com"
16 -let not_found_text_token = "TEXT_NOT_FOUND"
17 -let sleep_time_sec = 3
18 -
19 -let dbh = ref None
20 -
21 -let text = Netencoding.Html.encode_from_latin1;;
22 -(* This function encodes "<", ">", "&", double quotes, and Latin 1 characters
23 - * as character entities. E.g. text "<" = "&lt;", and text "�" = "&auml;"
24 - *)
25 -
26 -let compress_str raw =
27 - let tmp_file = Tmpfile.new_tmp_file_name tmp_prefix in
28 - let out = Gzip.open_out tmp_file in
29 - Gzip.output out raw 0 (String.length raw);
30 - Gzip.close_out out;
31 - let compressed = Std.input_file ?bin:(Some true) tmp_file in
32 - Tmpfile.remove_tmp_file tmp_file;
33 - compressed
34 -;;
35 -
36 -let handle_missing_rev (rev_id : int) (page_id : int) (page_title : string)
37 - (rev_time : string) (user_id : int) =
38 - match !dbh with
39 - | Some db -> (
40 - db # mark_to_color rev_id page_id page_title rev_time user_id;
41 - Unix.sleep sleep_time_sec;
42 - try (db # read_colored_markup_with_median rev_id) with
43 - | Online_db.DB_Not_Found -> (not_found_text_token,1.0)
44 - )
45 - | None -> ("DB not initialized",1.0)
46 -
47 -(* Return colored markup *)
48 -let generate_text_page (cgi : Netcgi.cgi_activation) (rev_id : int)
49 - (page_id : int) (page_title : string) (rev_time : string) (user_id : int)
50 - =
51 - let out = cgi # out_channel # output_string in
52 - let safe_page_title = Mysql.escape page_title in
53 - let safe_rev_time = Mysql.escape rev_time in
54 - match !dbh with
55 - | Some db -> (
56 - let (colored_text,median) =
57 - try (db # read_colored_markup_with_median rev_id)
58 - with Online_db.DB_Not_Found -> (handle_missing_rev rev_id page_id
59 - safe_page_title safe_rev_time
60 - user_id)
61 - in
62 - if colored_text != not_found_text_token then
63 - let compressed = compress_str ((string_of_float median) ^
64 - "," ^ colored_text) in
65 - cgi # set_header
66 - ~content_type:"application/x-gzip"
67 - ~content_length:(String.length compressed)
68 - ();
69 - out compressed
70 - else
71 - out colored_text
72 - )
73 - | None -> out "DB not initialized"
74 -;;
75 -
76 -(* Return information about an incorrect request. *)
77 -let generate_help_page (cgi : Netcgi.cgi_activation) =
78 - let out = cgi # out_channel # output_string in
79 - out not_found_text_token
80 -;;
81 -
82 -(* Record that a vote happened. *)
83 -let generate_vote_page (cgi : Netcgi.cgi_activation) (rev_id : int)
84 - (page_id : int) (user_id : int) (v_time : string) (page_title : string) =
85 - let out = cgi # out_channel # output_string in
86 - let safe_page_title = Mysql.escape page_title in
87 - match !dbh with
88 - | Some db -> (
89 - let vote = {
90 - vote_time=(Mysql.escape v_time);
91 - vote_page_id=page_id;
92 - vote_revision_id=rev_id;
93 - vote_voter_id=user_id;
94 - } in
95 - let res = try (db # vote vote;
96 - db # mark_to_color rev_id page_id safe_page_title
97 - (Mysql.escape v_time) user_id;
98 - "good") with
99 - Online_db.DB_TXN_Bad -> "bad" in
100 - out res
101 - )
102 - | None -> out "DB not initialized"
103 -;;
104 -
105 -let generate_page (cgi : Netcgi.cgi_activation) =
106 - (* Check which page is to be displayed. This is contained in the CGI
107 - * argument "page".
108 - *)
109 -
110 - let page_id = try (int_of_string (cgi # argument_value "page"))
111 - with int_of_string -> -1 in
112 - let rev_id = try (int_of_string (cgi # argument_value "rev"))
113 - with int_of_string -> -1 in
114 - let page_title = (cgi # argument_value "page_title") in
115 - let time_str = (cgi # argument_value "time") in
116 - let user_id = try (int_of_string (cgi # argument_value "user"))
117 - with int_of_string -> 0 in
118 - match cgi # argument_value "vote" with
119 - | "" -> (
120 - if rev_id < 0 || page_id < 0 then generate_help_page cgi else
121 - generate_text_page cgi rev_id page_id page_title time_str
122 - user_id
123 - )
124 - | _ -> (
125 - generate_vote_page cgi rev_id page_id user_id time_str page_title
126 - )
127 -;;
128 -
129 -let process2 (cgi : Netcgi.cgi_activation) =
130 - (* The [try] block catches errors during the page generation. *)
131 - try
132 - (* Set the header. The header specifies that the page must not be
133 - * cached. This is important for dynamic pages called by the GET
134 - * method, otherwise the browser might display an old version of
135 - * the page.
136 - * Furthermore, we set the content type and the character set.
137 - * Note that the header is not sent immediately to the browser because
138 - * we have enabled HTML buffering.
139 - *)
140 - cgi # set_header
141 - ~cache:`No_cache
142 - ~content_type:"text/plain; charset=\"iso-8859-1\""
143 - ();
144 -
145 - generate_page cgi;
146 -
147 - (* After the page has been fully generated, we can send it to the
148 - * browser.
149 - *)
150 - cgi # out_channel # commit_work();
151 - with
152 - error ->
153 - (* An error has happened. Generate now an error page instead of
154 - * the current page. By rolling back the output buffer, any
155 - * uncomitted material is deleted.
156 - *)
157 - cgi # out_channel # rollback_work();
158 -
159 - (* We change the header here only to demonstrate that this is
160 - * possible.
161 - *)
162 - cgi # set_header
163 - ~status:`Forbidden (* Indicate the error *)
164 - ~cache:`No_cache
165 - ~content_type:"text/plain; charset=\"iso-8859-1\""
166 - ();
167 -
168 - cgi # out_channel # output_string "While processing the request an O'Caml exception has been raised:\n";
169 - cgi # out_channel # output_string ("" ^ text(Printexc.to_string error) ^ "\n");
170 -
171 - (* Now commit the error page: *)
172 - cgi # out_channel # commit_work()
173 -;;
174 -
175 -
176 -let process1 (cgi : Netcgi1_compat.Netcgi_types.cgi_activation) =
177 - let cgi' = Netcgi1_compat.Netcgi_types.of_compat_activation cgi in
178 - process2 cgi'
179 -
180 -
181 -(**********************************************************************)
182 -(* Create the webserver *)
183 -(**********************************************************************)
184 -
185 -
186 -let start() =
187 - let (opt_list, cmdline_cfg) = Netplex_main.args() in
188 -
189 - let use_mt = ref false in
190 -
191 - let opt_list' =
192 - [ ("-mt", Arg.Set use_mt,
193 - " Use multi-threading instead of multi-processing");
194 - ] @ (command_line_format @ opt_list) in
195 -
196 - Arg.parse
197 - opt_list'
198 - (fun s -> raise (Arg.Bad ("Don't know what to do with: " ^ s)))
199 - "usage: netplex [options]";
200 -
201 - (* Prepares the database connection information *)
202 - let mediawiki_db = {
203 - dbhost = Some !mw_db_host;
204 - dbname = Some !mw_db_name;
205 - dbport = Some !mw_db_port;
206 - dbpwd = Some !mw_db_pass;
207 - dbuser = Some !mw_db_user;
208 - } in
209 - dbh := Some (new Online_db.db !db_prefix mediawiki_db None !dump_db_calls);
210 -
211 - let parallelizer =
212 - if !use_mt then
213 - Netplex_mt.mt() (* multi-threading *)
214 - else
215 - Netplex_mp.mp() in (* multi-processing *)
216 - let trust_store =
217 - { Nethttpd_services.dyn_handler = (fun _ -> process1);
218 - dyn_activation = Nethttpd_services.std_activation `Std_activation_buffered;
219 - dyn_uri = None; (* not needed *)
220 - dyn_translator = (fun _ -> ""); (* not needed *)
221 - dyn_accept_all_conditionals = false;
222 - } in
223 - let nethttpd_factory =
224 - Nethttpd_plex.nethttpd_factory
225 - ~handlers:[ "trust", trust_store ]
226 - () in
227 - Netplex_main.startup
228 - parallelizer
229 - Netplex_log.logger_factories (* allow all built-in logging styles *)
230 - Netplex_workload.workload_manager_factories (* ... all ways of workload management *)
231 - [ nethttpd_factory ] (* make this nethttpd available *)
232 - cmdline_cfg
233 -;;
234 -
235 -Sys.set_signal Sys.sigpipe Sys.Signal_ignore;
236 -start();;
Index: trunk/extensions/WikiTrust/analysis/server_coloring_dispatcher.ml
@@ -1,257 +0,0 @@
2 -(*
3 -
4 -Copyright (c) 2007-2008 The Regents of the University of California
5 -All rights reserved.
6 -
7 -Authors: Luca de Alfaro, Ian Pye
8 -
9 -Redistribution and use in source and binary forms, with or without
10 -modification, are permitted provided that the following conditions are met:
11 -
12 -1. Redistributions of source code must retain the above copyright notice,
13 -this list of conditions and the following disclaimer.
14 -
15 -2. Redistributions in binary form must reproduce the above copyright notice,
16 -this list of conditions and the following disclaimer in the documentation
17 -and/or other materials provided with the distribution.
18 -
19 -3. The names of the contributors may not be used to endorse or promote
20 -products derived from this software without specific prior written
21 -permission.
22 -
23 -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 -POSSIBILITY OF SUCH DAMAGE.
34 -
35 - *)
36 -
37 -(* Figures out which pages to update, and starts them going. *)
38 -
39 -open Printf
40 -open Mysql
41 -open Unix
42 -open Online_command_line
43 -open Wikipedia_api
44 -open Online_db
45 -open Online_types
46 -
47 -let max_concurrent_procs = 10
48 -let sleep_time_sec = 1
49 -let custom_line_format = [] @ command_line_format
50 -
51 -let _ = Arg.parse custom_line_format noop "Usage: dispatcher";;
52 -
53 -let working_children = Hashtbl.create max_concurrent_procs
54 -
55 -(* Prepares the database connection information *)
56 -let mediawiki_db = {
57 - dbhost = Some !mw_db_host;
58 - dbname = Some !mw_db_name;
59 - dbport = Some !mw_db_port;
60 - dbpwd = Some !mw_db_pass;
61 - dbuser = Some !mw_db_user;
62 -}
63 -
64 -(* Here begins the sequential code *)
65 -let db = new Online_db.db !db_prefix mediawiki_db None !dump_db_calls in
66 -let logger = new Online_log.logger !log_name !synch_log in
67 -let n_processed_events = ref 0 in
68 -let trust_coeff = Online_types.get_default_coeff in
69 -
70 -(* There are two types of throttle delay: a second each time we are multiples of an int,
71 - or a number of seconds before each revision. *)
72 -let each_event_delay = int_of_float !color_delay in
73 -let every_n_events_delay =
74 - let frac = !color_delay -. (floor !color_delay) in
75 - if frac > 0.001
76 - then Some (max 1 (int_of_float (1. /. frac)))
77 - else None
78 -in
79 -
80 -(* Wait for the processes to stop before accepting more *)
81 -let clean_kids k v = (
82 - let stat = Unix.waitpid [WNOHANG] v in
83 - match (stat) with
84 - | (0,_) -> () (* Process not yet done. *)
85 - | (_, WEXITED s) -> Hashtbl.remove working_children k (* Otherwise, remove the process. *)
86 - | (_, WSIGNALED s) -> Hashtbl.remove working_children k
87 - | (_, WSTOPPED s) -> Hashtbl.remove working_children k
88 -) in
89 -
90 -(* This is the function that evaluates a revision.
91 - The function is recursive, because if some past revision of the same page
92 - that falls within the analysis horizon is not yet evaluated and colored
93 - for trust, it evaluates and colors it first.
94 - *)
95 -let rec evaluate_revision (page_id: int) (rev_id: int): unit =
96 - if !n_processed_events < !max_events_to_process then
97 - begin
98 - begin (* try ... with ... *)
99 - try
100 - Printf.printf "Evaluating revision %d of page %d\n" rev_id page_id;
101 - let page = new Online_page.page db logger page_id rev_id trust_coeff !times_to_retry_trans in
102 - n_processed_events := !n_processed_events + 1;
103 - if page#eval then begin
104 - Printf.printf "Done revision %d of page %d\n" rev_id page_id;
105 - end else begin
106 - Printf.printf "Revision %d of page %d was already done\n" rev_id page_id;
107 - end;
108 - (* Waits, if so requested to throttle the computation. *)
109 - if each_event_delay > 0 then Unix.sleep (each_event_delay);
110 - begin
111 - match every_n_events_delay with
112 - Some d -> begin
113 - if (!n_processed_events mod d) = 0 then Unix.sleep (1);
114 - end
115 - | None -> ()
116 - end;
117 -
118 - with Online_page.Missing_trust (page_id', rev_id') ->
119 - begin
120 - (* We need to evaluate page_id', rev_id' first *)
121 - (* This if is a basic sanity check only. It should always be true *)
122 - if rev_id' <> rev_id then
123 - begin
124 - Printf.printf "Missing trust info: we need first to evaluate revision %d of page %d\n" rev_id' page_id';
125 - evaluate_revision page_id' rev_id';
126 - evaluate_revision page_id rev_id
127 - end (* rev_id' <> rev_id *)
128 - end (* with: Was missing trust of a previous revision *)
129 - end (* End of try ... with ... *)
130 - end
131 -in
132 -
133 -(* This is the code that evaluates a vote *)
134 -let evaluate_vote (page_id: int) (revision_id: int) (voter_id: int) =
135 - if !n_processed_events < !max_events_to_process then
136 - begin
137 - Printf.printf "Evaluating vote by %d on revision %d of page %d\n" voter_id revision_id page_id;
138 - let page = new Online_page.page db logger page_id revision_id trust_coeff !times_to_retry_trans in
139 - if page#vote voter_id then begin
140 - n_processed_events := !n_processed_events + 1;
141 - Printf.printf "Done revision %d of page %d\n" revision_id page_id;
142 - end;
143 - (* Waits, if so requested to throttle the computation. *)
144 - if each_event_delay > 0 then Unix.sleep (each_event_delay);
145 - begin
146 - match every_n_events_delay with
147 - Some d -> begin
148 - if (!n_processed_events mod d) = 0 then Unix.sleep (1);
149 - end
150 - | None -> ()
151 - end;
152 - end
153 -in
154 -
155 -(*
156 - Returns the user id of the user name if we have it,
157 - or asks a web service for it if we do not.
158 -*)
159 -let get_user_id u_name =
160 - try db # get_user_id u_name with DB_Not_Found -> get_user_id u_name
161 -in
162 -
163 -(* Color the asked for revision. *)
164 -let process_revs (page_id : int) (rev_ids : int list) (page_title : string)
165 - (rev_timestamp : string) (user_id : int) =
166 - let rec do_processing (rev_id : int) =
167 - (* I assume that a user cannot vote on an unprocessed revision here. *)
168 - if (db # revision_needs_coloring rev_id) then (
169 - (* Grab the text and color it. *)
170 - let last_colored_timestamp = try db # get_latest_colored_rev_timestamp
171 - page_id with DB_Not_Found -> "19700201000000" in
172 - let (wpage, wrevs) = fetch_page_and_revs_after page_title last_colored_timestamp in
173 - match wpage with
174 - | None -> Printf.printf "Failed for page %s\n" page_title
175 - | Some pp -> (
176 - Printf.printf "Got page titled %s\n" pp.page_title;
177 - db # write_page pp
178 - );
179 - let update_and_write_rev rev =
180 - rev.revision_page <- page_id;
181 - rev.revision_user <- (get_user_id rev.revision_user_text);
182 - db # write_revision rev
183 - in
184 - List.iter update_and_write_rev wrevs;
185 - let f rev =
186 - evaluate_revision page_id rev.revision_id
187 - in
188 - List.iter f wrevs;
189 - Unix.sleep sleep_time_sec;
190 - if !synch_log then flush Pervasives.stdout;
191 - if (db # revision_needs_coloring rev_id) then (
192 - do_processing rev_id
193 - )
194 - else ()
195 - ) else ( (* Vote! *)
196 - let process_vote v = (
197 - if v.vote_page_id == page_id then
198 - evaluate_vote page_id rev_id v.vote_voter_id
199 - ) in
200 - let votes = db # fetch_unprocessed_votes !max_events_to_process in
201 - List.iter process_vote votes
202 - )
203 - in
204 - List.iter do_processing rev_ids;
205 - Printf.printf "Finished processing page %s\n" page_title;
206 - exit 0 (* No more work to do, stop this process. *)
207 -in
208 -
209 -(* Start a new process going which actually processes the missing page. *)
210 -let dispatch_page rev_pages =
211 - let new_pages = Hashtbl.create (List.length rev_pages) in
212 - let is_new_page p =
213 - try ignore (Hashtbl.find working_children p); false with Not_found -> true
214 - in
215 - let set_revs_to_get (r,p,title,time,uid) =
216 - Printf.printf "page %d\n" p;
217 - if (is_new_page p) then (
218 - (
219 - let current_revs = try Hashtbl.find new_pages p with
220 - Not_found -> ([],title,time,uid) in
221 - (Hashtbl.replace new_pages p ((r::(let x,_,_,_ =
222 - current_revs in x)),
223 - title,time,uid))
224 - )
225 - ) else ()
226 - in
227 - let launch_processing p (r,t,rt,uid) = (
228 - let new_pid = Unix.fork () in
229 - match new_pid with
230 - | 0 -> (
231 - Printf.printf "I'm the child\n Running on page %d rev %d\n" p
232 - (List.hd r);
233 - process_revs p r t rt uid
234 - )
235 - | _ -> (Printf.printf "Parent of pid %d\n" new_pid;
236 - Hashtbl.add working_children p (new_pid)
237 - )
238 - ) in
239 - Hashtbl.iter clean_kids working_children;
240 - List.iter set_revs_to_get rev_pages;
241 - Hashtbl.iter launch_processing new_pages
242 -in
243 -
244 -(* Poll to see if there is any more work to be done. *)
245 -let rec main_loop () =
246 - if (Hashtbl.length working_children) >= max_concurrent_procs then (
247 - Hashtbl.iter clean_kids working_children
248 - ) else (
249 - let revs_to_process = db # fetch_next_to_color
250 - (max (max_concurrent_procs - Hashtbl.length working_children) 0) in
251 - dispatch_page revs_to_process
252 - );
253 - Unix.sleep sleep_time_sec;
254 - if !synch_log then flush Pervasives.stdout;
255 - main_loop ()
256 -in
257 -
258 -main_loop ()
Index: trunk/extensions/WikiTrust/analysis/tmpfile.mli
@@ -1,25 +0,0 @@
2 -(***********************************************************************)
3 -(* *)
4 -(* Objective Caml *)
5 -(* *)
6 -(* Fran�ois Pessaux, projet Cristal, INRIA Rocquencourt *)
7 -(* Pierre Weis, projet Cristal, INRIA Rocquencourt *)
8 -(* Jun Furuse, projet Cristal, INRIA Rocquencourt *)
9 -(* *)
10 -(* Copyright 1999 - 2003 *)
11 -(* Institut National de Recherche en Informatique et en Automatique. *)
12 -(* Distributed only by permission. *)
13 -(* *)
14 -(***********************************************************************)
15 -
16 -val tmp_dir : string ref
17 -(* swap file directory: the default is /tmp, but note that it is often
18 - the case that /tmp is not large enough for some huge images!! *)
19 -
20 -val new_tmp_file_name : string -> string
21 -(* [new_swap_file_name prefix] returns a new swap file name with
22 - prefix [prefix]. *)
23 -
24 -val remove_tmp_file : string -> unit
25 -(* [remove_tmp_file fname] removes [fname] if it can; nothing
26 - happens if [fname] cannot be removed. *)
Index: trunk/extensions/WikiTrust/analysis/Makefile
@@ -30,7 +30,7 @@
3131 # POSSIBILITY OF SUCH DAMAGE.
3232
3333 # Vars we use in our rules to build ocaml programs
34 -PACKAGES = unix,str,vec,mapmin,hashtbl_bounded,fileinfo,intvmap,extlib,mysql,netsys,netclient,camlzip,xml-light,sexplib.syntax
 34+PACKAGES = unix,str,vec,mapmin,hashtbl_bounded,fileinfo,intvmap,extlib,mysql,sexplib.syntax
3535 SYNTAX = camlp4o
3636 OUR_LIBS = evalwiki.cma
3737 OUR_LIBS_OPT = evalwiki.cmxa
@@ -72,11 +72,11 @@
7373 # one for the optimizing compilation.
7474 OUR_ONLINE_OBJS = online_types.cmo online_db.cmo online_revision.cmo \
7575 db_page.cmo online_page.cmo online_log.cmo event_feed.cmo \
76 - online_command_line.cmo tmpfile.cmo wikipedia_api.cmo \
 76+ online_command_line.cmo \
7777
7878 OUR_OPT_ONLINE_OBJS = online_types.cmx online_db.cmx online_revision.cmx \
7979 db_page.cmx online_page.cmx online_log.cmx event_feed.cmx \
80 - online_command_line.cmx tmpfile.cmx wikipedia_api.cmx \
 80+ online_command_line.cmx \
8181
8282
8383 online_eval: $(OUR_ONLINE_OBJS)
@@ -91,37 +91,21 @@
9292 vote_revisionopt: $(OUR_OPT_ONLINE_OBJS)
9393 $(OCAMLOPT) -linkpkg -o vote_revision $(OCAMLOPT_FLAGS) $(OUR_LIBS_OPT) $(OUR_OPT_ONLINE_OBJS) vote_revision.ml
9494
95 -server: $(OUR_ONLINE_OBJS)
96 - $(OCAMLC) -package "netstring,netcgi2,unix,nethttpd-for-netcgi2,netplex" -linkpkg -o server $(OCAML_CFLAGS) $(OUR_LIBS) $(OUR_ONLINE_OBJS) -thread server.ml
97 -
98 -serveropt: $(OUR_OPT_ONLINE_OBJS)
99 - $(OCAMLOPT) -package "netstring,netcgi2,unix,nethttpd-for-netcgi2,netplex" -linkpkg -o server $(OCAMLOPT_FLAGS) $(OUR_LIBS_OPT) $(OUR_OPT_ONLINE_OBJS) -thread server.ml
100 -
101 -dispatcher: $(OUR_ONLINE_OBJS)
102 - $(OCAMLC) -linkpkg -o dispatcher $(OCAML_CFLAGS) $(OUR_LIBS) $(OUR_ONLINE_OBJS) server_coloring_dispatcher.ml
103 -
104 -dispatcheropt: $(OUR_OPT_ONLINE_OBJS)
105 - $(OCAMLOPT) -linkpkg -o dispatcher $(OCAMLOPT_FLAGS) $(OUR_LIBS_OPT) $(OUR_OPT_ONLINE_OBJS) server_coloring_dispatcher.ml
106 -
10795 all:
10896 cd ../batch/analysis; make all
10997 make online_eval
11098 make vote_revision
111 - make server
112 - make dispatcher
11399
114100 allopt:
115101 cd ../batch/analysis; make allopt
116102 make online_evalopt
117103 make vote_revisionopt
118 - make serveropt
119 - make dispatcheropt
120104
121105 universe: all allopt
122106
123107 clean:
124108 cd ../batch/analysis; make clean
125 - rm -f *.o *.cmo *.cmx *.cmi .depends run_harness eval_online_wiki vote_revision server dispatcher
 109+ rm -f *.o *.cmo *.cmx *.cmi .depends run_harness eval_online_wiki vote_revision
126110
127111 # Boilerplate code for building ocaml dependencies.
128112
Index: trunk/extensions/WikiTrust/mediawiki/extensions/Trust/RemoteTrust.php
@@ -1,675 +0,0 @@
2 -<?php
3 -
4 -# Copyright (c) 2007,2008 Luca de Alfaro
5 -# Copyright (c) 2007,2008 Ian Pye
6 -# Copyright (c) 2007 Jason Benterou
7 -#
8 -# This program is free software; you can redistribute it and/or
9 -# modify it under the terms of the GNU General Public License as
10 -# published by the Free Software Foundation; either version 2 of the
11 -# License, or (at your option) any later version.
12 -
13 -# This program is distributed in the hope that it will be useful, but
14 -# WITHOUT ANY WARRANTY; without even the implied warranty of
15 -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 -# General Public License for more details.
17 -
18 -# You should have received a copy of the GNU General Public License
19 -# along with this program; if not, write to the Free Software
20 -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 -# USA
22 -
23 -## MW extension
24 -# This defines a custom MW function to map trust values to HTML markup
25 -#
26 -# Uses Tool Tip JS library under the LGPL.
27 -# http://www.walterzorn.com/tooltip/tooltip_e.htm
28 -
29 - // Turn old style errors into exceptions.
30 -function exception_error_handler($errno, $errstr, $errfile, $errline ) {
31 - throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
32 -}
33 -
34 - // But only for warnings.
35 -set_error_handler("exception_error_handler", E_WARNING);
36 -
37 -class TextTrust extends TrustBase {
38 -
39 - ## Types of analysis to perform.
40 - const TRUST_EVAL_VOTE = 0;
41 - const TRUST_EVAL_EDIT = 10;
42 - const TRUST_EVAL_MISSING = 15;
43 -
44 - ## the css tag to use
45 - const TRUST_CSS_TAG = "background-color"; ## color the background
46 - #$TRUST_CSS_TAG = "color"; ## color just the text
47 -
48 - ## ColorText is called multiple times, but we only want to color true text.
49 - const DIFF_TOKEN_TO_COLOR = "Lin";
50 -
51 - ## Trust normalization values;
52 - const MAX_TRUST_VALUE = 9;
53 - const MIN_TRUST_VALUE = 0;
54 - const TRUST_MULTIPLIER = 10;
55 -
56 - ## Token to split trust and origin values on
57 - const TRUST_SPLIT_TOKEN = ',';
58 -
59 - ## Token to be replaed with <
60 - const TRUST_OPEN_TOKEN = "QQampo:";
61 -
62 - ## Token to be replaed with >
63 - const TRUST_CLOSE_TOKEN = ":ampc:";
64 -
65 - ## Server forms
66 - const NOT_FOUND_TEXT_TOKEN = "TEXT_NOT_FOUND";
67 - const TRUST_COLOR_TOKEN = "<!--trust-->";
68 -
69 - ## Context for communicating with the trust server
70 - const TRUST_TIMEOUT = 10;
71 -
72 - ## default values for variables found from LocalSettings.php
73 - var $DEFAULTS = array(
74 - 'wgShowVoteButton' => false,
75 - 'wgVoteText' => "I believe this information is correct",
76 - 'wgThankYouForVoting' => "Thank you for your vote.",
77 - 'wgNoTrustExplanation' =>
78 - "<p><center><b>There is no trust information available for this text yet.</b></center></p>",
79 - 'wgTrustCmd' => "eval_online_wiki",
80 - 'wgVoteRev' => "vote_revision",
81 - 'wgTrustLog' => "/dev/null",
82 - 'wgTrustDebugLog' => "/dev/null",
83 - 'wgRepSpeed' => 1.0,
84 - 'wgNotPartExplanation' => "This page is not part of the trust coloring experement",
85 - 'wgTrustTabText' => "Show Trust",
86 - 'wgTrustExplanation' =>
87 - "<p><center><b>This is a product of the text trust algoruthm.</b></center></p>",
88 - 'wgContentServerURL' => "http://localhost:4444/?"
89 - );
90 -
91 - ## Median Value of Trust
92 - var $median = 1.0;
93 -
94 - ## Number of times a revision is looked at.
95 - var $times_rev_loaded = 0;
96 -
97 - ## Load the article we are talking about
98 - var $title;
99 -
100 - ## Only color the text once.
101 - var $colored = false;
102 -
103 - ## Don't close the first opening span tag
104 - var $first_span = true;
105 -
106 - ## And the same for origin tags
107 - var $first_origin = true;
108 -
109 - ## And the last revision of the title
110 - var $current_rev;
111 -
112 - ## Only add the scripts once.
113 - var $scripts_added = false;
114 -
115 - ## Should we do all the fancy trust processing?
116 - var $trust_engaged = false;
117 -
118 - ## map trust values to html color codes
119 - var $COLORS = array(
120 - "trust0",
121 - "trust1",
122 - "trust2",
123 - "trust3",
124 - "trust4",
125 - "trust5",
126 - "trust6",
127 - "trust7",
128 - "trust9",
129 - "trust10",
130 - );
131 -
132 - ## Only write a new trust tag when the trust changes.
133 - var $current_trust = "trust0";
134 -
135 - var $trustJS = '
136 -<script type="text/javascript">/*<![CDATA[*/
137 -var ctrlState = false;
138 -function showOrigin(revnum) {
139 - document.location.href = wgScriptPath + "/index.php?title=" + encodeURIComponent(wgPageName) + "&diff=" + encodeURIComponent(revnum);
140 -}
141 -
142 -// The Vote functionality
143 -function voteCallback(http_request){
144 - if ((http_request.readyState == 4) && (http_request.status == 200)) {
145 - document.getElementById("vote-button-done").style.visibility = "visible";
146 - document.getElementById("vote-button").style.visibility = "hidden";
147 - // alert(http_request.responseText);
148 - return true;
149 - } else {
150 - alert(http_request.responseText);
151 - return false;
152 - }
153 -}
154 -
155 -function getQueryVariable(variable) {
156 - var query = window.location.search.substring(1);
157 - var vars = query.split("&");
158 - for (var i=0;i<vars.length;i++) {
159 - var pair = vars[i].split("=");
160 - if (pair[0] == variable) {
161 - return pair[1];
162 - }
163 - }
164 - return "";
165 -}
166 -
167 -function startVote(){
168 -
169 - var revID = getQueryVariable("oldid");
170 - if (revID == ""){
171 - revID = getQueryVariable("diff");
172 - if (revID == ""){
173 - revID = wgCurRevisionId;
174 - }
175 - }
176 -
177 - return sajax_do_call( "TextTrust::handleVote", [wgUserName, wgArticleId, revID, wgPageName] , voteCallback );
178 -}
179 -
180 -/*]]>*/</script>';
181 -
182 - var $trustCSS = '
183 -<style type="text/css">/*<![CDATA[*/
184 -.trust0 {
185 - background-color: #FFB947;
186 -}
187 -
188 -.trust1 {
189 - background-color: #FFC05C;
190 -}
191 -
192 -.trust2 {
193 - background-color: #FFC870;
194 -}
195 -
196 -.trust3 {
197 - background-color: #FFD085;
198 -}
199 -
200 -.trust4 {
201 - background-color: #FFD899;
202 -}
203 -
204 -.trust5 {
205 - background-color: #FFE0AD;
206 -}
207 -
208 -.trust6 {
209 - background-color: #FFE8C2;
210 -}
211 -
212 -.trust7 {
213 - background-color: #FFEFD6;
214 -}
215 -
216 -.trust8 {
217 - background-color: #FFF7EB;
218 -}
219 -
220 -.trust9 {
221 - background-color: #FFFFFF;
222 -}
223 -
224 -.trust10 {
225 - background-color: #FFFFFF;
226 -}
227 -
228 -#vote-button-done {
229 - visibility: hidden;
230 - position: absolute;
231 - top: 10px;
232 - left: 500px;
233 -}
234 -
235 -#vote-button {
236 - position: absolute;
237 - top: 10px;
238 - left: 500px;
239 -}
240 -
241 -/*]]>*/</style>';
242 -
243 - public static function &singleton( )
244 - { return parent::singleton( ); }
245 -
246 - public function TextTrust(){
247 - parent::__construct( );
248 - global $wgExtensionCredits, $wgShowVoteButton, $wgVoteText, $wgThankYouForVoting;
249 - global $wgNoTrustExplanation, $wgTrustCmd, $wgVoteRev, $wgTrustLog, $wgTrustDebugLog, $wgRepSpeed;
250 - global $wgTrustTabText, $wgTrustExplanation, $wgNotPartExplanation, $wgContentServerURL;
251 -
252 - //Add default values if globals not set.
253 - if(!$wgShowVoteButton)
254 - $wgShowVoteButton = $this->DEFAULTS['wgShowVoteButton'];
255 - if(!$wgVoteText)
256 - $wgVoteText = $this->DEFAULTS['wgVoteText' ];
257 - if(!$wgThankYouForVoting)
258 - $wgThankYouForVoting = $this->DEFAULTS['wgThankYouForVoting'];
259 - if(!$wgNoTrustExplanation)
260 - $wgNoTrustExplanation = $this->DEFAULTS['wgNoTrustExplanation'];
261 - if(!$wgNotPartExplanation)
262 - $wgNotPartExplanation = $this->DEFAULTS['wgNotPartExplanation'];
263 - if(!$wgTrustCmd)
264 - $wgTrustCmd = $this->DEFAULTS['wgTrustCmd' ];
265 - if(!$wgVoteRev)
266 - $wgVoteRev = $this->DEFAULTS['wgVoteRev'];
267 - if(!$wgTrustLog)
268 - $wgTrustLog = $this->DEFAULTS['wgTrustLog'];
269 - if(!$wgTrustDebugLog)
270 - $wgTrustDebugLog = $this->DEFAULTS['wgTrustDebugLog'];
271 - if(!$wgRepSpeed)
272 - $wgRepSpeed = $this->DEFAULTS['wgRepSpeed'];
273 - if(!$wgTrustTabText)
274 - $wgTrustTabText = $this->DEFAULTS['wgTrustTabText'];
275 - if(!$wgTrustExplanation)
276 - $wgTrustExplanation = $this->DEFAULTS['wgTrustExplanation'];
277 - if(!$wgContentServerURL)
278 - $wgContentServerURL = $this->DEFAULTS['wgContentServerURL'];
279 -
280 -# Define a setup function
281 - $wgExtensionFunctions[] = 'ucscColorTrust_Setup';
282 -
283 -# Credits
284 - $wgExtensionCredits['parserhook'][] = array(
285 - 'name' => 'Trust Coloring',
286 - 'author' =>'Ian Pye',
287 - 'url' =>
288 - 'http://trust.cse.ucsc.edu',
289 - 'description' => 'This Extension
290 -colors text according to trust.'
291 - );
292 - }
293 -
294 - // Sets the extension hooks.
295 - public function setup() {
296 - parent::setup();
297 - global $wgHooks, $wgParser, $wgRequest, $wgUseAjax, $wgShowVoteButton, $wgAjaxExportList, $wgUser;
298 -
299 -# Code which takes the "I vote" action.
300 -# This has to be statically called.
301 - if($wgUseAjax && $wgShowVoteButton){
302 - $wgAjaxExportList[] = "TextTrust::handleVote";
303 - }
304 -
305 - // Is the user opting to use wikitrust?
306 - $tname = "gadget-WikiTrust";
307 - if (!$wgUser->getOption( $tname ) ) {
308 - return;
309 - }
310 -
311 -# Updater fiered when updating to a new version of MW.
312 - $wgHooks['LoadExtensionSchemaUpdates'][] = array(&$this, 'updateDB');
313 -
314 -# And add and extra tab.
315 - $wgHooks['SkinTemplateTabs'][] = array(&$this, 'ucscTrustTemplate');
316 -
317 -# If the trust tab is not selected, or some other tabs are don't worry about things any more.
318 - if(!$wgRequest->getVal('trust') || $wgRequest->getVal('action')){
319 - $this->trust_engaged = false;
320 - return;
321 - }
322 - $this->trust_engaged = true;
323 -
324 -# Add trust CSS and JS
325 - $wgHooks['OutputPageBeforeHTML'][] = array( &$this, 'ucscColorTrust_OP');
326 -
327 -# Add a hook to initialise the magic words
328 - $wgHooks['LanguageGetMagic'][] = array( &$this, 'ucscColorTrust_Magic');
329 -
330 -# Set a function hook associating the blame and trust words with a callback function
331 - $wgParser->setFunctionHook( 't', array( &$this, 'ucscColorTrust_Render'));
332 -
333 -# After everything, make the blame info work
334 - $wgHooks['ParserAfterTidy'][] = array( &$this, 'ucscOrigin_Finalize');
335 - }
336 -
337 - /**
338 - * Update the DB when MW is updated.
339 - * This assums that the db has permissions to create tables.
340 - */
341 - function updateDB(){
342 - // Create only those tables missing.
343 - // Create the needed tables, if neccesary.
344 - // Pull in the create scripts.
345 - require_once("TrustUpdateScripts.inc");
346 -
347 - $db =& wfGetDB( DB_MASTER );
348 -
349 - // First check to see what tables have already been created.
350 - $res = $db->query("show tables");
351 - while ($row = $db->fetchRow($res)){
352 - $db_tables[$row[0]] = True;
353 - }
354 -
355 - foreach ($create_scripts as $table => $scripts) {
356 - if (!$db_tables[$table]){
357 - foreach ($scripts as $script){
358 - $db->query($script);
359 - }
360 - }
361 - }
362 - }
363 -
364 - /**
365 - Records the vote.
366 - Called via ajax, so this must be static.
367 - */
368 - static function handleVote($user_name_raw, $page_id_raw = 0, $rev_id_raw = 0, $page_title = ""){
369 -
370 - global $wgContentServerURL;
371 - $response = new AjaxResponse("0");
372 -
373 - $dbr =& wfGetDB( DB_SLAVE );
374 -
375 - $userName = $dbr->strencode($user_name_raw, $dbr);
376 - $page_id = $dbr->strencode($page_id_raw, $dbr);
377 - $rev_id = $dbr->strencode($rev_id_raw, $dbr);
378 -
379 - if($page_id){
380 - // First, look up the id numbers from the page and user strings
381 - $res = $dbr->select('user', array('user_id'), array('user_name' => $userName), array());
382 - if ($res){
383 - $row = $dbr->fetchRow($res);
384 - $user_id = $row['user_id'];
385 - if (!$user_id) {
386 - $user_id = 0;
387 - }
388 - }
389 - $dbr->freeResult( $res );
390 -
391 - $ctx = stream_context_create(
392 - array('http' => array(
393 - 'timeout' =>
394 - self::TRUST_TIMEOUT
395 - )
396 - )
397 - );
398 -
399 - $vote_str = ("Voting at " . $wgContentServerURL . "vote=1&rev=$rev_id&page=$page_id&user=$user_id&page_title=$page_title&time=" . wfTimestampNow());
400 - $colored_text = file_get_contents($wgContentServerURL . "vote=1&rev=$rev_id&page=$page_id&user=$user_id&page_title=$page_title&time=" .
401 - wfTimestampNow(), 0, $ctx);
402 - $response = new AjaxResponse($vote_str);
403 - }
404 - return $response;
405 - }
406 -
407 - /**
408 - Called just before rendering HTML.
409 - We add the coloring scripts here.
410 - */
411 - function ucscColorTrust_OP(&$out, &$text){
412 - if (!$this->scripts_added){ // Only add the scripts once.
413 - $out->addScript($this->trustJS);
414 - $out->addScript($this->trustCSS);
415 - $this->scripts_added = true;
416 - }
417 - return true;
418 - }
419 -
420 -# Actually add the tab.
421 - function ucscTrustTemplate($skin, &$content_actions) {
422 -
423 - global $wgTrustTabText, $wgRequest;
424 - if (!isset($wgTrustTabText)){
425 - $wgTrustTabText = "trust";
426 - }
427 -
428 - if ($wgRequest->getVal('action')){
429 - // we don't want trust for actions.
430 - return true;
431 - }
432 -
433 - if ($wgRequest->getVal('diff')){
434 - // or for diffs
435 - return true;
436 - }
437 -
438 - $trust_qs = $_SERVER['QUERY_STRING'];
439 - if($trust_qs){
440 - $trust_qs = "?" . $trust_qs . "&trust=t";
441 - } else {
442 - $trust_qs .= "?trust=t";
443 - }
444 -
445 - $content_actions['trust'] = array ( 'class' => '',
446 - 'text' => $wgTrustTabText,
447 - 'href' =>
448 - $_SERVER['PHP_SELF'] . $trust_qs );
449 -
450 - if($wgRequest->getVal('trust')){
451 - $content_actions['trust']['class'] = 'selected';
452 - $content_actions['nstab-main']['class'] = '';
453 - $content_actions['nstab-main']['href'] .= '';
454 - } else {
455 - $content_actions['trust']['href'] .= '';
456 - }
457 - return true;
458 - }
459 -
460 - /**
461 - If colored text exists, use it instead of the normal text,
462 - but only if the trust tab is selected.
463 - */
464 - function ucscSeeIfColored(&$parser, &$text, &$strip_state = Null) {
465 - global $wgRequest, $wgTrustExplanation, $wgUseAjax, $wgShowVoteButton, $wgDBprefix, $wgNoTrustExplanation, $wgVoteText, $wgThankYouForVoting, $wgNotPartExplanation, $wgContentServerURL;
466 -
467 - // Get the db.
468 - $dbr =& wfGetDB( DB_SLAVE );
469 -
470 - // Do we use a DB prefix?
471 - $prefix = ($wgDBprefix)? "-db_prefix " . $dbr->strencode($wgDBprefix): "";
472 -
473 - // Text for showing the "I like it" button
474 - $voteitText = "";
475 - if ($wgUseAjax && $wgShowVoteButton){
476 - $voteitText = "
477 -".self::TRUST_OPEN_TOKEN."div id='vote-button'".self::TRUST_CLOSE_TOKEN."".self::TRUST_OPEN_TOKEN."input type='button' name='vote' value='" . $wgVoteText . "' onclick='startVote()' /".self::TRUST_CLOSE_TOKEN."".self::TRUST_OPEN_TOKEN."/div".self::TRUST_CLOSE_TOKEN."
478 -".self::TRUST_OPEN_TOKEN."div id='vote-button-done'".self::TRUST_CLOSE_TOKEN.$wgThankYouForVoting.self::TRUST_OPEN_TOKEN."/div".self::TRUST_CLOSE_TOKEN."
479 -";
480 - }
481 -
482 - // Return if trust is not selected.
483 - if (!$this->trust_engaged)
484 - return true;
485 -
486 - // Save the title object, if it is not already present
487 - if (!$this->title){
488 - $this->title = $parser->getTitle();
489 - }
490 -
491 - // count the number of times we load this text
492 - $this->times_rev_loaded++;
493 -
494 - // Load the current revision id.
495 - if (!$this->current_rev){
496 - if ($parser->mRevisionId){
497 - $this->current_rev = $parser->mRevisionId;
498 - } else {
499 - // Sometimes the revisionId field is not filled in.
500 - $this->current_rev = $this->title->getPreviousRevisionID( PHP_INT_MAX );
501 - }
502 - }
503 -
504 - /**
505 - This method is being called multiple times for each page.
506 - We only pull the colored text for the first time through.
507 - */
508 - if ($this->colored){
509 - return true;
510 - }
511 -
512 - if ($wgRequest->getVal('diff')){
513 - // For diffs, look for the absence of the diff token instead of counting
514 - if(substr($text,0,3) == self::DIFF_TOKEN_TO_COLOR){
515 - return true;
516 - }
517 - }
518 -
519 - // if we made it here, we are going to color some text
520 - $this->colored = true;
521 -
522 - // Check to see if this page is part of the coloring project.
523 - // Disabled for now.
524 - //if (!strstr($text, self::TRUST_COLOR_TOKEN)){
525 - // $text = $wgNotPartExplanation . "\n" . $text;
526 - // return true;
527 - //}
528 -
529 - // Get the page id and other data
530 - $colored_text="";
531 - $page_id=0;
532 - $rev_timestamp="";
533 - $rev_user=0;
534 - $res = $dbr->select('revision', array('rev_page', 'rev_timestamp', 'rev_user'), array('rev_id' => $this->current_rev), array());
535 - if ($res){
536 - $row = $dbr->fetchRow($res);
537 - $page_id = $row['rev_page'];
538 - $rev_user = $row['rev_user'];
539 - $rev_timestamp = $row['rev_timestamp'];
540 - if (!$page_id) {
541 - $page_id = 0;
542 - }
543 - }
544 - $dbr->freeResult( $res );
545 -
546 - $page_title = $_GET['title'];
547 - $ctx = stream_context_create(
548 - array('http' => array(
549 - 'timeout' =>
550 - self::TRUST_TIMEOUT
551 - )
552 - )
553 - );
554 - try {
555 - // Should we do doing this via HTTPS?
556 - $colored_raw = (file_get_contents($wgContentServerURL . "rev=" . $this->current_rev . "&page=$page_id&page_title=$page_title&time=$rev_timestamp&user=$rev_user", 0, $ctx));
557 - } catch (Exception $e) {
558 - $colored_raw = "";
559 - }
560 -
561 - if ($colored_raw && $colored_raw != self::NOT_FOUND_TEXT_TOKEN){
562 - // Work around because of issues with php's built in
563 - // gzip function.
564 - $f = tempnam('/tmp', 'gz_fix');
565 - file_put_contents($f, $colored_raw);
566 - $colored_raw = file_get_contents('compress.zlib://' . $f);
567 - unlink($f);
568 -
569 - // Pick off the median value first.
570 - $colored_data = explode(",", $colored_raw, 2);
571 - $colored_text = $colored_data[1];
572 - if (preg_match("/^[+-]?(([0-9]+)|([0-9]*\.[0-9]+|[0-9]+\.[0-9]*)|
573 - (([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.[0-9]*))[eE][+-]?[0-9]+))$/", $colored_data[0])){
574 - $this->median = $colored_data[0];
575 - }
576 -
577 - // First, make sure that there are not any instances of our tokens in the colored_text
578 - $colored_text = str_replace(self::TRUST_OPEN_TOKEN, "", $colored_text);
579 - $colored_text = str_replace(self::TRUST_CLOSE_TOKEN, "", $colored_text);
580 -
581 - $colored_text = preg_replace("/&apos;/", "'", $colored_text, -1);
582 -
583 - $colored_text = preg_replace("/&amp;/", "&", $colored_text, -1);
584 -
585 - $colored_text = preg_replace("/&lt;/", self::TRUST_OPEN_TOKEN, $colored_text, -1);
586 - $colored_text = preg_replace("/&gt;/", self::TRUST_CLOSE_TOKEN, $colored_text, -1);
587 -
588 - // Now update the text.
589 - $text = $voteitText . $colored_text . "\n" . $wgTrustExplanation;
590 - } else {
591 - // Return a message about the missing text.
592 - $text = $wgNoTrustExplanation . "\n" . $text;
593 - }
594 -
595 - return true;
596 - }
597 -
598 - /* Register the tags we are intersted in expanding. */
599 - function ucscColorTrust_Magic( &$magicWords, $langCode ) {
600 - $magicWords[ 't' ] = array( 0, 't' );
601 - return true;
602 - }
603 -
604 - /* Pull in any colored text. Also handle closing tags. */
605 - function ucscOrigin_Finalize(&$parser, &$text) {
606 - global $wgScriptPath, $IP, $wgOut;
607 -
608 - if(!$this->colored){
609 - // This is to handle caching problems.
610 - if (!strstr($text, "This page has been accessed")){
611 - $colored_text = $text;
612 - $this->ucscSeeIfColored($parser, $colored_text);
613 - $text = $wgOut->parse( $colored_text );
614 - } else {
615 - $colored_text = $text;
616 - $this->ucscSeeIfColored($parser, $colored_text);
617 - $wgOut->mBodytext = $wgOut->parse( $colored_text );
618 - }
619 - }
620 -
621 - $count = 0;
622 - $text = '<script type="text/javascript" src="'.$wgScriptPath.'/extensions/Trust/js/wz_tooltip.js"></script>' . $text;
623 - $text = preg_replace('/' . self::TRUST_OPEN_TOKEN . '/', "<", $text, -1, $count);
624 - $text = preg_replace('/' . self::TRUST_CLOSE_TOKEN .'/', ">", $text, -1, $count);
625 - $text = preg_replace('/<\/p>/', "</span></p>", $text, -1, $count);
626 - $text = preg_replace('/<p><\/span>/', "<p>", $text, -1, $count);
627 - $text = preg_replace('/<li><\/span>/', "<li>", $text, -1, $count);
628 -
629 - return true;
630 - }
631 -
632 - /* Text Trust */
633 - function ucscColorTrust_Render( &$parser, $combinedValue = "0,0,0" ) {
634 -
635 - // Split the value into trust and origin information.
636 - // 0 = trust
637 - // 1 = origin
638 - // 2 = contributing author
639 - $splitVals = explode(self::TRUST_SPLIT_TOKEN, $combinedValue);
640 -
641 - $class = $this->computeColorFromFloat($splitVals[0]);
642 - $output = self::TRUST_OPEN_TOKEN . "span class=\"$class\""
643 - . "onmouseover=\"Tip('".$splitVals[2]."')\" onmouseout=\"UnTip()\""
644 - . "onclick=\"showOrigin("
645 - . $splitVals[1] . ")\"" . self::TRUST_CLOSE_TOKEN;
646 -
647 - $this->current_trust = $class;
648 - if ($this->first_span){
649 - $this->first_span = false;
650 - } else {
651 - $output = self::TRUST_OPEN_TOKEN . "/span" . self::TRUST_CLOSE_TOKEN . $output;
652 - }
653 -
654 - return array ( $output, "noparse" => false, "isHTML" => false );
655 - }
656 -
657 - /**
658 - Maps from the online trust values to the css trust values.
659 - Normalize the value for growing wikis.
660 - */
661 - function computeColorFromFloat($trust){
662 - $normalized_value = min(self::MAX_TRUST_VALUE, max(self::MIN_TRUST_VALUE,
663 - (($trust + .5) * self::TRUST_MULTIPLIER)
664 - / $this->median));
665 - return $this->computeColor3($normalized_value);
666 - }
667 -
668 - /* Maps a trust value to a HTML color representing the trust value. */
669 - function computeColor3($fTrustValue){
670 - return $this->COLORS[$fTrustValue];
671 - }
672 -}
673 -
674 -TextTrust::singleton();
675 -
676 -?>
Index: trunk/extensions/WikiTrust/mediawiki/extensions/Trust/TrustUpdateScripts.inc
@@ -112,6 +112,6 @@
113113 $remove_scripts[$wgDBprefix.'wikitrust_missing_revs'] = array("DROP TABLE
114114 ".$wgDBprefix."wikitrust_missing_revs");
115115
116 -$remove_index_scripts[$wgDBprefix . "revision"]['wikitrust_revision_id_timestamp_idx'] = "DROP INDEX wikitrust_revision_id_timestamp_idx ON revision";
 116+$remove_index_scripts[$wgDBprefix . "revision"]['wikitrust_revision_id_timestamp_idx'] = "DROP INDEX wikitrust_revision_id_timestamp_idx ON ".$wgDBprefix."revision";
117117
118118 ?>
Index: trunk/extensions/WikiTrust/mediawiki/extensions/Trust/css/trust.css
@@ -0,0 +1,56 @@
 2+.trust0 {
 3+ background-color: #FFB947;
 4+}
 5+
 6+.trust1 {
 7+ background-color: #FFC05C;
 8+}
 9+
 10+.trust2 {
 11+ background-color: #FFC870;
 12+}
 13+
 14+.trust3 {
 15+ background-color: #FFD085;
 16+}
 17+
 18+.trust4 {
 19+ background-color: #FFD899;
 20+}
 21+
 22+.trust5 {
 23+ background-color: #FFE0AD;
 24+}
 25+
 26+.trust6 {
 27+ background-color: #FFE8C2;
 28+}
 29+
 30+.trust7 {
 31+ background-color: #FFEFD6;
 32+}
 33+
 34+.trust8 {
 35+ background-color: #FFF7EB;
 36+}
 37+
 38+.trust9 {
 39+ background-color: #FFFFFF;
 40+}
 41+
 42+.trust10 {
 43+ background-color: #FFFFFF;
 44+}
 45+
 46+#vote-button-done {
 47+ visibility: hidden;
 48+ position: absolute;
 49+ top: 10px;
 50+ left: 500px;
 51+}
 52+
 53+#vote-button {
 54+ position: absolute;
 55+ top: 10px;
 56+ left: 500px;
 57+}
\ No newline at end of file
Index: trunk/extensions/WikiTrust/mediawiki/extensions/Trust/js/trust.js
@@ -0,0 +1,43 @@
 2+var ctrlState = false;
 3+function showOrigin(revnum) {
 4+ document.location.href = wgScriptPath + "/index.php?title=" + encodeURIComponent(wgPageName) + "&diff=" + encodeURIComponent(revnum);
 5+}
 6+
 7+// The Vote functionality
 8+function voteCallback(http_request){
 9+ if ((http_request.readyState == 4) && (http_request.status == 200)) {
 10+ document.getElementById("vote-button-done").style.visibility = "visible";
 11+ document.getElementById("vote-button").style.visibility = "hidden";
 12+ //alert(http_request.responseText);
 13+ return true;
 14+ } else {
 15+ // Turn off error reporting.
 16+ //alert(http_request.responseText);
 17+ return false;
 18+ }
 19+}
 20+
 21+function getQueryVariable(variable) {
 22+ var query = window.location.search.substring(1);
 23+ var vars = query.split("&");
 24+ for (var i=0;i<vars.length;i++) {
 25+ var pair = vars[i].split("=");
 26+ if (pair[0] == variable) {
 27+ return pair[1];
 28+ }
 29+ }
 30+ return "";
 31+}
 32+
 33+function startVote(){
 34+
 35+ var revID = getQueryVariable("oldid");
 36+ if (revID == ""){
 37+ revID = getQueryVariable("diff");
 38+ if (revID == ""){
 39+ revID = wgCurRevisionId;
 40+ }
 41+ }
 42+
 43+ return sajax_do_call( "TextTrustImpl::handleVote", [wgUserName, wgArticleId, revID, wgPageName] , voteCallback );
 44+}
Index: trunk/extensions/WikiTrust/test-scripts/load_data.py
@@ -94,9 +94,9 @@
9595
9696 # clear out the pull db if requested
9797 if do_clear:
98 - curs.execute("delete from text")
99 - curs.execute("delete from page")
100 - curs.execute("delete from revision")
 98+ curs.execute("delete from "+ini_config.get('db', 'prefix')+"text")
 99+ curs.execute("delete from "+ini_config.get('db', 'prefix')+"page")
 100+ curs.execute("delete from "+ini_config.get('db', 'prefix')+"revision")
101101 connection.commit()
102102
103103 for dump in dumps:
Index: trunk/extensions/WikiTrust/remote/analysis/Makefile
@@ -0,0 +1,115 @@
 2+# Copyright (c) 2007-2008 The Regents of the University of California
 3+# All rights reserved.
 4+#
 5+# Authors: Luca de Alfaro, B. Thomas Adler, Ian Pye
 6+#
 7+# Redistribution and use in source and binary forms, with or without
 8+# modification, are permitted provided that the following conditions are met:
 9+#
 10+# 1. Redistributions of source code must retain the above copyright notice,
 11+# this list of conditions and the following disclaimer.
 12+#
 13+# 2. Redistributions in binary form must reproduce the above copyright notice,
 14+# this list of conditions and the following disclaimer in the documentation
 15+# and/or other materials provided with the distribution.
 16+#
 17+# 3. The names of the contributors may not be used to endorse or promote
 18+# products derived from this software without specific prior written
 19+# permission.
 20+#
 21+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 22+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 23+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 24+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 25+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 26+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 27+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 28+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 29+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 30+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 31+# POSSIBILITY OF SUCH DAMAGE.
 32+
 33+# Vars we use in our rules to build ocaml programs
 34+PACKAGES = unix,str,vec,mapmin,hashtbl_bounded,fileinfo,intvmap,extlib,mysql,netsys,netclient,camlzip,xml-light,sexplib.syntax
 35+SYNTAX = camlp4o
 36+OUR_LIBS = evalwiki.cma online_types.cmo online_db.cmo online_revision.cmo \
 37+ db_page.cmo online_page.cmo online_log.cmo event_feed.cmo \
 38+ online_command_line.cmo
 39+
 40+OUR_LIBS_OPT = evalwiki.cmxa online_types.cmx online_db.cmx \
 41+ online_revision.cmx \
 42+ db_page.cmx online_page.cmx online_log.cmx event_feed.cmx \
 43+ online_command_line.cmx
 44+
 45+INCLUDES = -I ../../batch/analysis -I ../../analysis
 46+
 47+OCAMLC=ocamlfind ocamlc -package $(PACKAGES) -syntax $(SYNTAX)
 48+OCAMLOPT=ocamlfind ocamlopt -package $(PACKAGES) -syntax $(SYNTAX)
 49+
 50+OCAMLDEP=ocamlfind ocamldep -package $(PACKAGES) -syntax $(SYNTAX)
 51+OCAMLDOC=ocamldoc
 52+
 53+SUFFIXES= .ml .cmo .cmi .cmx
 54+
 55+# For profiling
 56+# OCAMLDEBUG = -g -p film
 57+OCAMLDEBUG = -g
 58+
 59+
 60+# Flags for commands, depending on optimization/debugging
 61+OCAML_CFLAGS=$(INCLUDES) $(OCAMLDEBUG)
 62+OCAMLOPT_FLAGS=$(INCLUDES)
 63+
 64+%.cmo: %.ml
 65+ @echo '$(OCAMLC) $(OCAML_CFLAGS) -c $<'; \
 66+ $(OCAMLC) $(OCAML_CFLAGS) -c $<
 67+
 68+%.cmi: %.mli
 69+ @echo '$(OCAMLC) $(OCAML_CFLAGS) -c $<'; \
 70+ $(OCAMLC) $(OCAML_CFLAGS) -c $<
 71+
 72+%.cmx: %.ml
 73+ @echo '$(OCAMLOPT) $(OCAMLOPT_FLAGS) -c $<'; \
 74+ $(OCAMLOPT) $(OCAMLOPT_FLAGS) -c $<
 75+
 76+.PHONY: all allopt universe clean
 77+
 78+# Here are the objects that we want to build.
 79+# We need two lines of these, one for the debugging compilation,
 80+# one for the optimizing compilation.
 81+OUR_ONLINE_OBJS = tmpfile.cmo wikipedia_api.cmo \
 82+
 83+OUR_OPT_ONLINE_OBJS = tmpfile.cmx wikipedia_api.cmx \
 84+
 85+server: $(OUR_ONLINE_OBJS)
 86+ $(OCAMLC) -package "netstring,netcgi2,unix,nethttpd-for-netcgi2,netplex" -linkpkg -o server $(OCAML_CFLAGS) $(OUR_LIBS) $(OUR_ONLINE_OBJS) -thread server.ml
 87+
 88+serveropt: $(OUR_OPT_ONLINE_OBJS)
 89+ $(OCAMLOPT) -package "netstring,netcgi2,unix,nethttpd-for-netcgi2,netplex" -linkpkg -o server $(OCAMLOPT_FLAGS) $(OUR_LIBS_OPT) $(OUR_OPT_ONLINE_OBJS) -thread server.ml
 90+
 91+dispatcher: $(OUR_ONLINE_OBJS)
 92+ $(OCAMLC) -linkpkg -o dispatcher $(OCAML_CFLAGS) $(OUR_LIBS) $(OUR_ONLINE_OBJS) server_coloring_dispatcher.ml
 93+
 94+dispatcheropt: $(OUR_OPT_ONLINE_OBJS)
 95+ $(OCAMLOPT) -linkpkg -o dispatcher $(OCAMLOPT_FLAGS) $(OUR_LIBS_OPT) $(OUR_OPT_ONLINE_OBJS) server_coloring_dispatcher.ml
 96+
 97+all:
 98+ make server
 99+ make dispatcher
 100+
 101+allopt:
 102+ make serveropt
 103+ make dispatcheropt
 104+
 105+universe: all allopt
 106+
 107+clean:
 108+ rm -f *.o *.cmo *.cmx *.cmi .depends server dispatcher
 109+
 110+# Boilerplate code for building ocaml dependencies.
 111+
 112+.depends: *.ml
 113+ $(OCAMLDEP) $^ > $@
 114+
 115+-include .depends
 116+
Property changes on: trunk/extensions/WikiTrust/remote/analysis/Makefile
___________________________________________________________________
Added: svn:eol-style
1117 + native
Index: trunk/extensions/WikiTrust/remote/analysis/server.ml
@@ -0,0 +1,235 @@
 2+(* This is a webserver built from the Netplex and Nethttpd components.
 3+ * It is configured in the netplex.cfg file.
 4+ * Note: start program with option "-conf netplex.cfg"
 5+ * The basic code is copied from the nethttpd example.
 6+ *)
 7+
 8+open Netcgi1_compat.Netcgi_types;;
 9+open Printf;;
 10+open Mysql;;
 11+open Online_db;;
 12+open Online_command_line;;
 13+open Gzip;;
 14+
 15+let tmp_prefix = "wiki-com"
 16+let not_found_text_token = "TEXT_NOT_FOUND"
 17+let sleep_time_sec = 3
 18+
 19+let dbh = ref None
 20+
 21+let text = Netencoding.Html.encode_from_latin1;;
 22+(* This function encodes "<", ">", "&", double quotes, and Latin 1 characters
 23+ * as character entities. E.g. text "<" = "&lt;", and text "�" = "&auml;"
 24+ *)
 25+
 26+let compress_str raw =
 27+ let tmp_file = Tmpfile.new_tmp_file_name tmp_prefix in
 28+ let out = Gzip.open_out tmp_file in
 29+ Gzip.output out raw 0 (String.length raw);
 30+ Gzip.close_out out;
 31+ let compressed = Std.input_file ?bin:(Some true) tmp_file in
 32+ Tmpfile.remove_tmp_file tmp_file;
 33+ compressed
 34+;;
 35+
 36+let handle_missing_rev (rev_id : int) (page_id : int) (page_title : string)
 37+ (rev_time : string) (user_id : int) =
 38+ match !dbh with
 39+ | Some db -> (
 40+ db # mark_to_color rev_id page_id page_title rev_time user_id;
 41+ Unix.sleep sleep_time_sec;
 42+ try (db # read_colored_markup_with_median rev_id) with
 43+ | Online_db.DB_Not_Found -> (not_found_text_token,1.0)
 44+ )
 45+ | None -> ("DB not initialized",1.0)
 46+
 47+(* Return colored markup *)
 48+let generate_text_page (cgi : Netcgi.cgi_activation) (rev_id : int)
 49+ (page_id : int) (page_title : string) (rev_time : string) (user_id : int)
 50+ =
 51+ let out = cgi # out_channel # output_string in
 52+ let safe_page_title = Mysql.escape page_title in
 53+ let safe_rev_time = Mysql.escape rev_time in
 54+ match !dbh with
 55+ | Some db -> (
 56+ let (colored_text,median) =
 57+ try (db # read_colored_markup_with_median rev_id)
 58+ with Online_db.DB_Not_Found -> (handle_missing_rev rev_id page_id
 59+ safe_page_title safe_rev_time
 60+ user_id)
 61+ in
 62+ if colored_text != not_found_text_token then
 63+ let compressed = compress_str ((string_of_float median) ^
 64+ "," ^ colored_text) in
 65+ cgi # set_header
 66+ ~content_type:"application/x-gzip"
 67+ ~content_length:(String.length compressed)
 68+ ();
 69+ out compressed
 70+ else
 71+ out colored_text
 72+ )
 73+ | None -> out "DB not initialized"
 74+;;
 75+
 76+(* Return information about an incorrect request. *)
 77+let generate_help_page (cgi : Netcgi.cgi_activation) =
 78+ let out = cgi # out_channel # output_string in
 79+ out not_found_text_token
 80+;;
 81+
 82+(* Record that a vote happened. *)
 83+let generate_vote_page (cgi : Netcgi.cgi_activation) (rev_id : int)
 84+ (page_id : int) (user_id : int) (v_time : string) (page_title : string) =
 85+ let out = cgi # out_channel # output_string in
 86+ let safe_page_title = Mysql.escape page_title in
 87+ match !dbh with
 88+ | Some db -> (
 89+ let vote = {
 90+ vote_time=(Mysql.escape v_time);
 91+ vote_page_id=page_id;
 92+ vote_revision_id=rev_id;
 93+ vote_voter_id=user_id;
 94+ } in
 95+ let res = try (db # vote vote;
 96+ db # mark_to_color rev_id page_id safe_page_title
 97+ (Mysql.escape v_time) user_id;
 98+ "good") with
 99+ Online_db.DB_TXN_Bad -> "bad" in
 100+ out res
 101+ )
 102+ | None -> out "DB not initialized"
 103+;;
 104+
 105+let generate_page (cgi : Netcgi.cgi_activation) =
 106+ (* Check which page is to be displayed. This is contained in the CGI
 107+ * argument "page".
 108+ *)
 109+
 110+ let page_id = try (int_of_string (cgi # argument_value "page"))
 111+ with int_of_string -> -1 in
 112+ let rev_id = try (int_of_string (cgi # argument_value "rev"))
 113+ with int_of_string -> -1 in
 114+ let page_title = (cgi # argument_value "page_title") in
 115+ let time_str = (cgi # argument_value "time") in
 116+ let user_id = try (int_of_string (cgi # argument_value "user"))
 117+ with int_of_string -> 0 in
 118+ match cgi # argument_value "vote" with
 119+ | "" -> (
 120+ if rev_id < 0 || page_id < 0 then generate_help_page cgi else
 121+ generate_text_page cgi rev_id page_id page_title time_str
 122+ user_id
 123+ )
 124+ | _ -> (
 125+ generate_vote_page cgi rev_id page_id user_id time_str page_title
 126+ )
 127+;;
 128+
 129+let process2 (cgi : Netcgi.cgi_activation) =
 130+ (* The [try] block catches errors during the page generation. *)
 131+ try
 132+ (* Set the header. The header specifies that the page must not be
 133+ * cached. This is important for dynamic pages called by the GET
 134+ * method, otherwise the browser might display an old version of
 135+ * the page.
 136+ * Furthermore, we set the content type and the character set.
 137+ * Note that the header is not sent immediately to the browser because
 138+ * we have enabled HTML buffering.
 139+ *)
 140+ cgi # set_header
 141+ ~cache:`No_cache
 142+ ~content_type:"text/plain; charset=\"iso-8859-1\""
 143+ ();
 144+
 145+ generate_page cgi;
 146+
 147+ (* After the page has been fully generated, we can send it to the
 148+ * browser.
 149+ *)
 150+ cgi # out_channel # commit_work();
 151+ with
 152+ error ->
 153+ (* An error has happened. Generate now an error page instead of
 154+ * the current page. By rolling back the output buffer, any
 155+ * uncomitted material is deleted.
 156+ *)
 157+ cgi # out_channel # rollback_work();
 158+
 159+ (* We change the header here only to demonstrate that this is
 160+ * possible.
 161+ *)
 162+ cgi # set_header
 163+ ~status:`Forbidden (* Indicate the error *)
 164+ ~cache:`No_cache
 165+ ~content_type:"text/plain; charset=\"iso-8859-1\""
 166+ ();
 167+
 168+ cgi # out_channel # output_string "While processing the request an O'Caml exception has been raised:\n";
 169+ cgi # out_channel # output_string ("" ^ text(Printexc.to_string error) ^ "\n");
 170+
 171+ (* Now commit the error page: *)
 172+ cgi # out_channel # commit_work()
 173+;;
 174+
 175+
 176+let process1 (cgi : Netcgi1_compat.Netcgi_types.cgi_activation) =
 177+ let cgi' = Netcgi1_compat.Netcgi_types.of_compat_activation cgi in
 178+ process2 cgi'
 179+
 180+
 181+(**********************************************************************)
 182+(* Create the webserver *)
 183+(**********************************************************************)
 184+
 185+
 186+let start() =
 187+ let (opt_list, cmdline_cfg) = Netplex_main.args() in
 188+
 189+ let use_mt = ref false in
 190+
 191+ let opt_list' =
 192+ [ ("-mt", Arg.Set use_mt,
 193+ " Use multi-threading instead of multi-processing");
 194+ ] @ (command_line_format @ opt_list) in
 195+
 196+ Arg.parse
 197+ opt_list'
 198+ (fun s -> raise (Arg.Bad ("Don't know what to do with: " ^ s)))
 199+ "usage: netplex [options]";
 200+
 201+ (* Prepares the database connection information *)
 202+ let mediawiki_db = {
 203+ dbhost = Some !mw_db_host;
 204+ dbname = Some !mw_db_name;
 205+ dbport = Some !mw_db_port;
 206+ dbpwd = Some !mw_db_pass;
 207+ dbuser = Some !mw_db_user;
 208+ } in
 209+ dbh := Some (new Online_db.db !db_prefix mediawiki_db None !dump_db_calls);
 210+
 211+ let parallelizer =
 212+ if !use_mt then
 213+ Netplex_mt.mt() (* multi-threading *)
 214+ else
 215+ Netplex_mp.mp() in (* multi-processing *)
 216+ let trust_store =
 217+ { Nethttpd_services.dyn_handler = (fun _ -> process1);
 218+ dyn_activation = Nethttpd_services.std_activation `Std_activation_buffered;
 219+ dyn_uri = None; (* not needed *)
 220+ dyn_translator = (fun _ -> ""); (* not needed *)
 221+ dyn_accept_all_conditionals = false;
 222+ } in
 223+ let nethttpd_factory =
 224+ Nethttpd_plex.nethttpd_factory
 225+ ~handlers:[ "trust", trust_store ]
 226+ () in
 227+ Netplex_main.startup
 228+ parallelizer
 229+ Netplex_log.logger_factories (* allow all built-in logging styles *)
 230+ Netplex_workload.workload_manager_factories (* ... all ways of workload management *)
 231+ [ nethttpd_factory ] (* make this nethttpd available *)
 232+ cmdline_cfg
 233+;;
 234+
 235+Sys.set_signal Sys.sigpipe Sys.Signal_ignore;
 236+start();;
Property changes on: trunk/extensions/WikiTrust/remote/analysis/server.ml
___________________________________________________________________
Added: svn:eol-style
1237 + native
Index: trunk/extensions/WikiTrust/remote/analysis/server.py
@@ -0,0 +1,186 @@
 2+"""
 3+Copyright (c) 2007-2008 The Regents of the University of California
 4+All rights reserved.
 5+
 6+Authors: Ian Pye
 7+
 8+Redistribution and use in source and binary forms, with or without
 9+modification, are permitted provided that the following conditions are met:
 10+
 11+1. Redistributions of source code must retain the above copyright notice,
 12+this list of conditions and the following disclaimer.
 13+
 14+2. Redistributions in binary form must reproduce the above copyright notice,
 15+this list of conditions and the following disclaimer in the documentation
 16+and/or other materials provided with the distribution.
 17+
 18+3. The names of the contributors may not be used to endorse or promote
 19+products derived from this software without specific prior written
 20+permission.
 21+
 22+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 23+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 24+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 25+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 26+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 27+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 28+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 29+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 30+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 31+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 32+POSSIBILITY OF SUCH DAMAGE.
 33+
 34+"""
 35+
 36+# Works with RemoteTrust for connecting to a remote wiki.
 37+
 38+import MySQLdb
 39+import getopt
 40+import ConfigParser
 41+import zlib
 42+import gzip
 43+import cStringIO
 44+import time
 45+
 46+from mod_python import util
 47+from mod_python import apache
 48+
 49+BASE_DIR = "/home/ipye/git/wikitrust/test-scripts/"
 50+INI_FILE = BASE_DIR + "db_access_data.ini"
 51+FILE_ENDING_SEP = " "
 52+DB_PREFIX = ""
 53+not_found_text_token = "TEXT_NOT_FOUND"
 54+sleep_time_sec = 3
 55+
 56+connection = None
 57+curs = None
 58+
 59+# Compress a string
 60+def compressBuf(buf):
 61+ zbuf = cStringIO.StringIO()
 62+ zfile = gzip.GzipFile(mode = 'wb', fileobj = zbuf, compresslevel = 6)
 63+ zfile.write(buf)
 64+ zfile.close()
 65+ return zbuf.getvalue()
 66+
 67+# Start a persisent connection to the db
 68+def connect_db():
 69+ global connection
 70+ global curs
 71+ global DB_PREFIX
 72+
 73+ ## parse the ini file
 74+ ini_config = ConfigParser.ConfigParser()
 75+ ini_config.readfp(open(INI_FILE))
 76+
 77+ ## init the DB
 78+ connection = MySQLdb.connect(host=ini_config.get('db', 'host'),
 79+ user=ini_config.get('db', 'user'), passwd=ini_config.get('db', 'pass') \
 80+ , db=ini_config.get('db', 'db') )
 81+ curs = connection.cursor()
 82+
 83+ ## Prefix
 84+ DB_PREFIX = ini_config.get('db', 'prefix')
 85+
 86+# add the revision to the queue for coloring
 87+def mark_for_coloring(rev_id, page_id, user_id, rev_time, page_title):
 88+ global DB_PREFIX
 89+ global curs
 90+
 91+ sql = """INSERT INTO """+DB_PREFIX+"""wikitrust_missing_revs (revision_id, page_id, page_title, rev_time, user_id) VALUES (%(rid)s, %(pid)s, %(title)s, %(time)s, %(vid)s) ON DUPLICATE KEY UPDATE requested_on = now(), processed = false"""
 92+ args = {'rid':rev_id, 'pid':page_id, 'title':page_title,
 93+ 'time':rev_time, 'vid':user_id }
 94+
 95+ curs.execute(sql, args)
 96+ connection.commit()
 97+
 98+# Insert the vote into the db
 99+def handle_vote(req, rev_id, page_id, user_id, v_time, page_title):
 100+ global DB_PREFIX
 101+ global curs
 102+
 103+ sql = """INSERT INTO """+DB_PREFIX+"""wikitrust_vote (revision_id, page_id, voter_id, voted_on) VALUES (%(rid)s, %(pid)s, %(vid)s, %(time)s) ON DUPLICATE KEY UPDATE voted_on = %(time)s"""
 104+ args = {'rid':rev_id, 'pid':page_id, 'vid':user_id, 'time':v_time}
 105+
 106+ curs.execute(sql, args)
 107+ connection.commit()
 108+
 109+ mark_for_coloring(rev_id, page_id, user_id, v_time, page_title)
 110+
 111+ # token saying things are ok
 112+ req.write("good")
 113+
 114+# Return colored text from the DB
 115+def fetch_colored_markup(rev_id, page_id, user_id, rev_time, page_title):
 116+ global DB_PREFIX
 117+ global curs
 118+ global not_found_text_token
 119+
 120+ sql = """SELECT revision_text,median FROM """ + DB_PREFIX + \
 121+ """wikitrust_colored_markup JOIN """+ DB_PREFIX + \
 122+ """wikitrust_global WHERE revision_id = %s"""
 123+ args = (rev_id)
 124+ numRows = curs.execute(sql, args)
 125+
 126+ if (numRows > 0):
 127+ dbRow = curs.fetchone()
 128+ return "%f,%s" % (dbRow[1],dbRow[0])
 129+ return not_found_text_token
 130+
 131+# Return colored text if it exists
 132+def handle_text_request(req, rev_id, page_id, user_id, rev_time, page_title):
 133+ global DB_PREFIX
 134+ global sleep_time_sec
 135+ global not_found_text_token
 136+
 137+ res = fetch_colored_markup(rev_id, page_id, user_id, rev_time, page_title)
 138+ if (res == not_found_text_token):
 139+ mark_for_coloring(rev_id, page_id, user_id, rev_time, page_title)
 140+ time.sleep(sleep_time_sec)
 141+
 142+ res = fetch_colored_markup(rev_id, page_id, user_id, rev_time, page_title)
 143+ if (res == not_found_text_token):
 144+ req.write(not_found_text_token)
 145+ else:
 146+ compressed = compressBuf(res)
 147+
 148+ req.content_type = "application/x-gzip"
 149+ req.content_length = len (compressed)
 150+ req.send_http_header()
 151+
 152+ req.write(compressed)
 153+
 154+# Before we start, connect to the db
 155+connect_db()
 156+
 157+# Entry point for web request.
 158+def handler(req):
 159+
 160+ ## Default mimetype
 161+ req.content_type = "text/plain"
 162+
 163+ # Restart the connection to the DB if its not good.
 164+ if (not connection.ping()):
 165+ connect_db()
 166+
 167+ ## Parse the form inputs
 168+ form = util.FieldStorage(req)
 169+ page_id = form.getfirst("page", -1)
 170+ rev_id = form.getfirst("rev", -1)
 171+ page_title =form.getfirst("page_title", "")
 172+ time_str = form.getfirst("time", "")
 173+ user_id = form.getfirst("user", -1)
 174+ is_vote = form.getfirst("vote", None)
 175+
 176+ if (page_id < 0) or (rev_id < 0) or (page_title == "") or (time_str == "") \
 177+ or (user_id < 0):
 178+ req.write("bad")
 179+ else:
 180+ if is_vote:
 181+ handle_vote(req, rev_id, page_id, user_id, time_str, page_title)
 182+ else:
 183+ handle_text_request(req, rev_id, page_id, user_id, time_str, page_title)
 184+
 185+ return apache.OK
 186+
 187+
Index: trunk/extensions/WikiTrust/remote/analysis/server_coloring_dispatcher.ml
@@ -0,0 +1,257 @@
 2+(*
 3+
 4+Copyright (c) 2007-2008 The Regents of the University of California
 5+All rights reserved.
 6+
 7+Authors: Luca de Alfaro, Ian Pye
 8+
 9+Redistribution and use in source and binary forms, with or without
 10+modification, are permitted provided that the following conditions are met:
 11+
 12+1. Redistributions of source code must retain the above copyright notice,
 13+this list of conditions and the following disclaimer.
 14+
 15+2. Redistributions in binary form must reproduce the above copyright notice,
 16+this list of conditions and the following disclaimer in the documentation
 17+and/or other materials provided with the distribution.
 18+
 19+3. The names of the contributors may not be used to endorse or promote
 20+products derived from this software without specific prior written
 21+permission.
 22+
 23+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 24+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 25+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 26+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 27+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 28+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 29+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 30+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 31+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 32+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 33+POSSIBILITY OF SUCH DAMAGE.
 34+
 35+ *)
 36+
 37+(* Figures out which pages to update, and starts them going. *)
 38+
 39+open Printf
 40+open Mysql
 41+open Unix
 42+open Online_command_line
 43+open Wikipedia_api
 44+open Online_db
 45+open Online_types
 46+
 47+let max_concurrent_procs = 10
 48+let sleep_time_sec = 1
 49+let custom_line_format = [] @ command_line_format
 50+
 51+let _ = Arg.parse custom_line_format noop "Usage: dispatcher";;
 52+
 53+let working_children = Hashtbl.create max_concurrent_procs
 54+
 55+(* Prepares the database connection information *)
 56+let mediawiki_db = {
 57+ dbhost = Some !mw_db_host;
 58+ dbname = Some !mw_db_name;
 59+ dbport = Some !mw_db_port;
 60+ dbpwd = Some !mw_db_pass;
 61+ dbuser = Some !mw_db_user;
 62+}
 63+
 64+(* Here begins the sequential code *)
 65+let db = new Online_db.db !db_prefix mediawiki_db None !dump_db_calls in
 66+let logger = new Online_log.logger !log_name !synch_log in
 67+let n_processed_events = ref 0 in
 68+let trust_coeff = Online_types.get_default_coeff in
 69+
 70+(* There are two types of throttle delay: a second each time we are multiples of an int,
 71+ or a number of seconds before each revision. *)
 72+let each_event_delay = int_of_float !color_delay in
 73+let every_n_events_delay =
 74+ let frac = !color_delay -. (floor !color_delay) in
 75+ if frac > 0.001
 76+ then Some (max 1 (int_of_float (1. /. frac)))
 77+ else None
 78+in
 79+
 80+(* Wait for the processes to stop before accepting more *)
 81+let clean_kids k v = (
 82+ let stat = Unix.waitpid [WNOHANG] v in
 83+ match (stat) with
 84+ | (0,_) -> () (* Process not yet done. *)
 85+ | (_, WEXITED s) -> Hashtbl.remove working_children k (* Otherwise, remove the process. *)
 86+ | (_, WSIGNALED s) -> Hashtbl.remove working_children k
 87+ | (_, WSTOPPED s) -> Hashtbl.remove working_children k
 88+) in
 89+
 90+(* This is the function that evaluates a revision.
 91+ The function is recursive, because if some past revision of the same page
 92+ that falls within the analysis horizon is not yet evaluated and colored
 93+ for trust, it evaluates and colors it first.
 94+ *)
 95+let rec evaluate_revision (page_id: int) (rev_id: int): unit =
 96+ if !n_processed_events < !max_events_to_process then
 97+ begin
 98+ begin (* try ... with ... *)
 99+ try
 100+ Printf.printf "Evaluating revision %d of page %d\n" rev_id page_id;
 101+ let page = new Online_page.page db logger page_id rev_id trust_coeff !times_to_retry_trans in
 102+ n_processed_events := !n_processed_events + 1;
 103+ if page#eval then begin
 104+ Printf.printf "Done revision %d of page %d\n" rev_id page_id;
 105+ end else begin
 106+ Printf.printf "Revision %d of page %d was already done\n" rev_id page_id;
 107+ end;
 108+ (* Waits, if so requested to throttle the computation. *)
 109+ if each_event_delay > 0 then Unix.sleep (each_event_delay);
 110+ begin
 111+ match every_n_events_delay with
 112+ Some d -> begin
 113+ if (!n_processed_events mod d) = 0 then Unix.sleep (1);
 114+ end
 115+ | None -> ()
 116+ end;
 117+
 118+ with Online_page.Missing_trust (page_id', rev_id') ->
 119+ begin
 120+ (* We need to evaluate page_id', rev_id' first *)
 121+ (* This if is a basic sanity check only. It should always be true *)
 122+ if rev_id' <> rev_id then
 123+ begin
 124+ Printf.printf "Missing trust info: we need first to evaluate revision %d of page %d\n" rev_id' page_id';
 125+ evaluate_revision page_id' rev_id';
 126+ evaluate_revision page_id rev_id
 127+ end (* rev_id' <> rev_id *)
 128+ end (* with: Was missing trust of a previous revision *)
 129+ end (* End of try ... with ... *)
 130+ end
 131+in
 132+
 133+(* This is the code that evaluates a vote *)
 134+let evaluate_vote (page_id: int) (revision_id: int) (voter_id: int) =
 135+ if !n_processed_events < !max_events_to_process then
 136+ begin
 137+ Printf.printf "Evaluating vote by %d on revision %d of page %d\n" voter_id revision_id page_id;
 138+ let page = new Online_page.page db logger page_id revision_id trust_coeff !times_to_retry_trans in
 139+ if page#vote voter_id then begin
 140+ n_processed_events := !n_processed_events + 1;
 141+ Printf.printf "Done revision %d of page %d\n" revision_id page_id;
 142+ end;
 143+ (* Waits, if so requested to throttle the computation. *)
 144+ if each_event_delay > 0 then Unix.sleep (each_event_delay);
 145+ begin
 146+ match every_n_events_delay with
 147+ Some d -> begin
 148+ if (!n_processed_events mod d) = 0 then Unix.sleep (1);
 149+ end
 150+ | None -> ()
 151+ end;
 152+ end
 153+in
 154+
 155+(*
 156+ Returns the user id of the user name if we have it,
 157+ or asks a web service for it if we do not.
 158+*)
 159+let get_user_id u_name =
 160+ try db # get_user_id u_name with DB_Not_Found -> get_user_id u_name
 161+in
 162+
 163+(* Color the asked for revision. *)
 164+let process_revs (page_id : int) (rev_ids : int list) (page_title : string)
 165+ (rev_timestamp : string) (user_id : int) =
 166+ let rec do_processing (rev_id : int) =
 167+ (* I assume that a user cannot vote on an unprocessed revision here. *)
 168+ if (db # revision_needs_coloring rev_id) then (
 169+ (* Grab the text and color it. *)
 170+ let last_colored_timestamp = try db # get_latest_colored_rev_timestamp
 171+ page_id with DB_Not_Found -> "19700201000000" in
 172+ let (wpage, wrevs) = fetch_page_and_revs_after page_title last_colored_timestamp in
 173+ match wpage with
 174+ | None -> Printf.printf "Failed for page %s\n" page_title
 175+ | Some pp -> (
 176+ Printf.printf "Got page titled %s\n" pp.page_title;
 177+ db # write_page pp
 178+ );
 179+ let update_and_write_rev rev =
 180+ rev.revision_page <- page_id;
 181+ rev.revision_user <- (get_user_id rev.revision_user_text);
 182+ db # write_revision rev
 183+ in
 184+ List.iter update_and_write_rev wrevs;
 185+ let f rev =
 186+ evaluate_revision page_id rev.revision_id
 187+ in
 188+ List.iter f wrevs;
 189+ Unix.sleep sleep_time_sec;
 190+ if !synch_log then flush Pervasives.stdout;
 191+ if (db # revision_needs_coloring rev_id) then (
 192+ do_processing rev_id
 193+ )
 194+ else ()
 195+ ) else ( (* Vote! *)
 196+ let process_vote v = (
 197+ if v.vote_page_id == page_id then
 198+ evaluate_vote page_id rev_id v.vote_voter_id
 199+ ) in
 200+ let votes = db # fetch_unprocessed_votes !max_events_to_process in
 201+ List.iter process_vote votes
 202+ )
 203+ in
 204+ List.iter do_processing rev_ids;
 205+ Printf.printf "Finished processing page %s\n" page_title;
 206+ exit 0 (* No more work to do, stop this process. *)
 207+in
 208+
 209+(* Start a new process going which actually processes the missing page. *)
 210+let dispatch_page rev_pages =
 211+ let new_pages = Hashtbl.create (List.length rev_pages) in
 212+ let is_new_page p =
 213+ try ignore (Hashtbl.find working_children p); false with Not_found -> true
 214+ in
 215+ let set_revs_to_get (r,p,title,time,uid) =
 216+ Printf.printf "page %d\n" p;
 217+ if (is_new_page p) then (
 218+ (
 219+ let current_revs = try Hashtbl.find new_pages p with
 220+ Not_found -> ([],title,time,uid) in
 221+ (Hashtbl.replace new_pages p ((r::(let x,_,_,_ =
 222+ current_revs in x)),
 223+ title,time,uid))
 224+ )
 225+ ) else ()
 226+ in
 227+ let launch_processing p (r,t,rt,uid) = (
 228+ let new_pid = Unix.fork () in
 229+ match new_pid with
 230+ | 0 -> (
 231+ Printf.printf "I'm the child\n Running on page %d rev %d\n" p
 232+ (List.hd r);
 233+ process_revs p r t rt uid
 234+ )
 235+ | _ -> (Printf.printf "Parent of pid %d\n" new_pid;
 236+ Hashtbl.add working_children p (new_pid)
 237+ )
 238+ ) in
 239+ Hashtbl.iter clean_kids working_children;
 240+ List.iter set_revs_to_get rev_pages;
 241+ Hashtbl.iter launch_processing new_pages
 242+in
 243+
 244+(* Poll to see if there is any more work to be done. *)
 245+let rec main_loop () =
 246+ if (Hashtbl.length working_children) >= max_concurrent_procs then (
 247+ Hashtbl.iter clean_kids working_children
 248+ ) else (
 249+ let revs_to_process = db # fetch_next_to_color
 250+ (max (max_concurrent_procs - Hashtbl.length working_children) 0) in
 251+ dispatch_page revs_to_process
 252+ );
 253+ Unix.sleep sleep_time_sec;
 254+ if !synch_log then flush Pervasives.stdout;
 255+ main_loop ()
 256+in
 257+
 258+main_loop ()
Property changes on: trunk/extensions/WikiTrust/remote/analysis/server_coloring_dispatcher.ml
___________________________________________________________________
Added: svn:eol-style
1259 + native
Index: trunk/extensions/WikiTrust/remote/analysis/tmpfile.mli
@@ -0,0 +1,25 @@
 2+(***********************************************************************)
 3+(* *)
 4+(* Objective Caml *)
 5+(* *)
 6+(* Fran�ois Pessaux, projet Cristal, INRIA Rocquencourt *)
 7+(* Pierre Weis, projet Cristal, INRIA Rocquencourt *)
 8+(* Jun Furuse, projet Cristal, INRIA Rocquencourt *)
 9+(* *)
 10+(* Copyright 1999 - 2003 *)
 11+(* Institut National de Recherche en Informatique et en Automatique. *)
 12+(* Distributed only by permission. *)
 13+(* *)
 14+(***********************************************************************)
 15+
 16+val tmp_dir : string ref
 17+(* swap file directory: the default is /tmp, but note that it is often
 18+ the case that /tmp is not large enough for some huge images!! *)
 19+
 20+val new_tmp_file_name : string -> string
 21+(* [new_swap_file_name prefix] returns a new swap file name with
 22+ prefix [prefix]. *)
 23+
 24+val remove_tmp_file : string -> unit
 25+(* [remove_tmp_file fname] removes [fname] if it can; nothing
 26+ happens if [fname] cannot be removed. *)
Property changes on: trunk/extensions/WikiTrust/remote/analysis/tmpfile.mli
___________________________________________________________________
Added: svn:eol-style
127 + native
Index: trunk/extensions/WikiTrust/remote/analysis/wikipedia_api.ml
@@ -0,0 +1,193 @@
 2+(*
 3+
 4+Copyright (c) 2007-2008 The Regents of the University of California
 5+All rights reserved.
 6+
 7+Authors: Luca de Alfaro, Ian Pye
 8+
 9+Redistribution and use in source and binary forms, with or without
 10+modification, are permitted provided that the following conditions are met:
 11+
 12+1. Redistributions of source code must retain the above copyright notice,
 13+this list of conditions and the following disclaimer.
 14+
 15+2. Redistributions in binary form must reproduce the above copyright notice,
 16+this list of conditions and the following disclaimer in the documentation
 17+and/or other materials provided with the distribution.
 18+
 19+3. The names of the contributors may not be used to endorse or promote
 20+products derived from this software without specific prior written
 21+permission.
 22+
 23+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 24+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 25+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 26+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 27+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 28+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 29+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 30+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 31+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 32+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 33+POSSIBILITY OF SUCH DAMAGE.
 34+
 35+ *)
 36+
 37+(* Using the wikipedia API, retrieves information about pages and revisions *)
 38+
 39+open Http_client;;
 40+open ExtLib;;
 41+open Gzip;;
 42+open Xml;;
 43+open Online_types;;
 44+open Str;;
 45+
 46+exception Http_client_error
 47+
 48+Random.self_init ()
 49+
 50+let pipeline = new pipeline
 51+let buf_len = 8192
 52+let requested_encoding_type = "gzip"
 53+let tmp_prefix = "wiki"
 54+let rev_lim = "50"
 55+let api_tz_re = Str.regexp "\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)-\\([0-9][0-9]\\)T\\([0-9][0-9]\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)Z"
 56+
 57+(* Maps the Wikipedias api timestamp to our internal one. *)
 58+let api_ts2mw_ts s =
 59+ let ts = if string_match api_tz_re s 0 then
 60+ (matched_group 1 s) ^ (matched_group 2 s) ^ (matched_group 3 s)
 61+ ^ (matched_group 4 s) ^ (matched_group 5 s) ^ (matched_group 6 s)
 62+ else "19700201000000" in
 63+ ts
 64+
 65+(* Given an input channel, return a string representing all there is
 66+ to be read of this channel. *)
 67+let input_all ic =
 68+ let rec loop acc total buf ofs =
 69+ let n = input ic buf ofs (buf_len - ofs) in
 70+ if n = 0 then
 71+ let res = String.create total in
 72+ let pos = total - ofs in
 73+ let _ = String.blit buf 0 res pos ofs in
 74+ let coll pos buf =
 75+ let new_pos = pos - buf_len in
 76+ String.blit buf 0 res new_pos buf_len;
 77+ new_pos in
 78+ let _ = List.fold_left coll pos acc in
 79+ res
 80+ else
 81+ let new_ofs = ofs + n in
 82+ let new_total = total + n in
 83+ if new_ofs = buf_len then
 84+ loop (buf :: acc) new_total (String.create buf_len) 0
 85+ else loop acc new_total buf new_ofs in
 86+ loop [] 0 (String.create buf_len) 0
 87+
 88+(*
 89+ Given a string url, make a get call and return the response as a string.
 90+*)
 91+let run_call url =
 92+ let call = new get url in
 93+ let request_header = call # request_header `Base in
 94+ (* Accept gziped format *)
 95+ request_header # update_field "Accept-encoding" requested_encoding_type;
 96+ call # set_request_header request_header;
 97+ pipeline # add call;
 98+ pipeline # run();
 99+ match call # status with
 100+ | `Successful -> (
 101+ let body = call # response_body # value in
 102+ let repsponse_header = call # response_header in
 103+ Printf.printf "content_type: %s\n"
 104+ (let cnt,_ = (repsponse_header # content_type ()) in cnt);
 105+ match (repsponse_header # content_type ()) with
 106+ | ("text/xml",_) -> (
 107+ let tmp_file = Tmpfile.new_tmp_file_name tmp_prefix in
 108+ Std.output_file ~filename:tmp_file ~text:body;
 109+ let in_chan = Gzip.open_in tmp_file in
 110+ let decoded_body = input_all in_chan in
 111+ Gzip.close_in in_chan;
 112+ Tmpfile.remove_tmp_file tmp_file;
 113+ decoded_body
 114+ )
 115+ | _ -> body
 116+ )
 117+ | _ -> raise Http_client_error
 118+;;
 119+
 120+(*
 121+ Internal xml processing for the api
 122+*)
 123+let process_rev (rev : xml) : wiki_revision =
 124+ let w_rev = {
 125+ revision_id = int_of_string (Xml.attrib rev "revid");
 126+ revision_page = 0;
 127+ revision_text_id = int_of_string (Xml.attrib rev "revid");
 128+ revision_comment = (try (Xml.attrib rev "comment")
 129+ with Xml.No_attribute e -> "");
 130+ revision_user = -1;
 131+ revision_user_text = (Xml.attrib rev "user");
 132+ revision_timestamp = api_ts2mw_ts (Xml.attrib rev "timestamp");
 133+ revision_minor_edit = (try ignore(Xml.attrib rev "minor"); true
 134+ with Xml.No_attribute e -> false);
 135+ revision_deleted = false;
 136+ revision_len = (try int_of_string (Xml.attrib rev "size") with Xml.No_attribute e -> 0);
 137+ revision_parent_id = 0;
 138+ revision_content = (Netencoding.Html.decode ~in_enc:`Enc_utf8
 139+ ~out_enc:`Enc_utf8 ()
 140+ (Xml.to_string (List.hd (Xml.children rev))));
 141+ } in
 142+ w_rev
 143+
 144+(*
 145+ Internal xml processing for the api
 146+*)
 147+let process_page (page : xml) : (wiki_page option * wiki_revision list) =
 148+ let w_page = {
 149+ page_id = int_of_string (Xml.attrib page "pageid");
 150+ page_namespace = (int_of_string (Xml.attrib page "ns"));
 151+ page_title = (Xml.attrib page "title");
 152+ page_restrictions = "";
 153+ page_counter = int_of_string (Xml.attrib page "counter");
 154+ page_is_redirect = (try ignore(Xml.attrib page "redirect"); true
 155+ with Xml.No_attribute e -> false);
 156+ page_is_new = false;
 157+ page_random = (Random.float 1.0);
 158+ page_touched = api_ts2mw_ts (Xml.attrib page "touched");
 159+ page_latest = int_of_string (Xml.attrib page "lastrevid");
 160+ page_len = int_of_string (Xml.attrib page "length")
 161+ } in
 162+ let revs = Xml.children page in
 163+ (Some w_page, (Xml.map process_rev (List.hd revs)))
 164+
 165+(*
 166+ Given a page and date to start with, returns the next n revs for this page.
 167+*)
 168+let fetch_page_and_revs_after (page_title : string) (rev_date : string) : (wiki_page option * wiki_revision list) =
 169+ let url = !Online_command_line.target_wikimedia
 170+ ^ "?action=query&prop=revisions|"
 171+ ^ "info&format=xml&inprop=&rvprop=ids|flags|timestamp|user|size|comment|"
 172+ ^ "content&rvstart=" ^ rev_date ^ "&rvlimit=" ^ rev_lim
 173+ ^ "&rvdir=newer&titles=" ^ page_title in
 174+ if !Online_command_line.dump_db_calls then Printf.printf "%s\n" url;
 175+ let res = run_call url in
 176+ let api = Xml.parse_string res in
 177+ let query = Xml.children (api) in
 178+ let poss_pages = Xml.children (List.hd query) in
 179+ let pick_page acc page =
 180+ if (Xml.tag page = "pages") then
 181+ process_page (List.hd (Xml.children page))
 182+ else acc
 183+ in
 184+ List.fold_left pick_page (None,[]) poss_pages
 185+;;
 186+
 187+(* Given a user_name, returns the corresponding user_id *)
 188+let get_user_id (user_name : string) : int =
 189+ let url = !Online_command_line.user_id_server ^ "?n=" ^ user_name in
 190+ if !Online_command_line.dump_db_calls then Printf.printf "%s\n" url;
 191+ let uids = ExtString.String.nsplit (run_call url) "`" in
 192+ let uid = List.nth uids 1 in
 193+ try int_of_string uid with int_of_string -> 0 in
 194+;;
Property changes on: trunk/extensions/WikiTrust/remote/analysis/wikipedia_api.ml
___________________________________________________________________
Added: svn:eol-style
1195 + native
Index: trunk/extensions/WikiTrust/remote/analysis/tmpfile.ml
@@ -0,0 +1,37 @@
 2+(***********************************************************************)
 3+(* *)
 4+(* Objective Caml *)
 5+(* *)
 6+(* Fran�ois Pessaux, projet Cristal, INRIA Rocquencourt *)
 7+(* Pierre Weis, projet Cristal, INRIA Rocquencourt *)
 8+(* Jun Furuse, projet Cristal, INRIA Rocquencourt *)
 9+(* *)
 10+(* Copyright 1999 - 2003 *)
 11+(* Institut National de Recherche en Informatique et en Automatique. *)
 12+(* Distributed only by permission. *)
 13+(* *)
 14+(***********************************************************************)
 15+
 16+(* temporary directory *)
 17+let tmp_dir = ref (try Sys.getenv "CAMLTMPDIR" with Not_found -> "/tmp");;
 18+
 19+let cnter = ref 0;;
 20+
 21+let rec new_tmp_name prefx =
 22+ incr cnter;
 23+ let name =
 24+ Filename.concat !tmp_dir
 25+ (Printf.sprintf "camltmp-%s-%d" prefx !cnter) in
 26+ if not (Sys.file_exists name) then name else begin
 27+ prerr_endline ("Warning: tmp file " ^ name ^ " already exists");
 28+ new_tmp_name prefx
 29+ end;;
 30+
 31+let remove_tmp_file tmpfile = try Sys.remove tmpfile with _ -> ();;
 32+
 33+let new_tmp_file_name prefx =
 34+ if not (Sys.file_exists !tmp_dir) then
 35+ failwith ("Temporary directory " ^ !tmp_dir ^ " does not exist") else
 36+ let f = new_tmp_name prefx in
 37+ at_exit (fun () -> remove_tmp_file f);
 38+ f;;
Property changes on: trunk/extensions/WikiTrust/remote/analysis/tmpfile.ml
___________________________________________________________________
Added: svn:eol-style
139 + native
Index: trunk/extensions/WikiTrust/remote/mediawiki/extensions/Trust/RemoteTrust.php
@@ -0,0 +1,163 @@
 2+<?php
 3+
 4+# Copyright (c) 2007,2008 Luca de Alfaro
 5+# Copyright (c) 2007,2008 Ian Pye
 6+# Copyright (c) 2007 Jason Benterou
 7+#
 8+# This program is free software; you can redistribute it and/or
 9+# modify it under the terms of the GNU General Public License as
 10+# published by the Free Software Foundation; either version 2 of the
 11+# License, or (at your option) any later version.
 12+
 13+# This program is distributed in the hope that it will be useful, but
 14+# WITHOUT ANY WARRANTY; without even the implied warranty of
 15+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 16+# General Public License for more details.
 17+
 18+# You should have received a copy of the GNU General Public License
 19+# along with this program; if not, write to the Free Software
 20+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 21+# USA
 22+
 23+## MW extension
 24+# This defines a custom MW function to map trust values to HTML markup
 25+#
 26+# Uses Tool Tip JS library under the LGPL.
 27+# http://www.walterzorn.com/tooltip/tooltip_e.htm
 28+
 29+$dir = dirname(__FILE__) . '/';
 30+
 31+$wgExtensionMessagesFiles['RemoteTrust'] = $dir.'/RemoteTrust.i18n.php';
 32+
 33+# Credits
 34+$wgExtensionCredits['other'][] = array(
 35+ 'name' =>
 36+ 'Text Attribution and Trust',
 37+ 'author' =>
 38+ 'Ian Pye, Luca de Alfaro',
 39+ 'url' =>
 40+ 'http://trust.cse.ucsc.edu',
 41+ 'description' =>
 42+ 'Text is colored according to how much it has been revised. An orange background indicates new, unrevised, text; white is for text that has been revised by many reputed authors. If you click on a word, you will be redirected to the diff corresponding to the edit where the word was introduced. If you hover over a word, a pop-up displays the word author.'
 43+ );
 44+
 45+$wgAutoloadClasses['TextTrustImpl'] = $dir . 'RemoteTrustImpl.php';
 46+$wgAutoloadClasses['TextTrustUpdate'] = $dir . 'RemoteTrustUpdate.php';
 47+$wgExtensionFunctions[] = 'TextTrust::init';
 48+
 49+class TextTrust {
 50+
 51+ // Instance of our TrustImpl class
 52+ private static $trust;
 53+
 54+ /**
 55+ * Initializes and configures the extension.
 56+ */
 57+ public static function init() {
 58+ global $wgHooks, $wgParser, $wgRequest, $wgUseAjax, $wgAjaxExportList,
 59+ $wgUser, $wgOut, $wgScriptPath, $wgExtensionMessagesFiles,
 60+ $wgShowVoteButton;
 61+
 62+ // ParserFirstCallInit was introduced in modern (1.12+) MW versions so as to
 63+ // avoid unstubbing $wgParser on setHook() too early, as per r35980
 64+ if (!defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' )) {
 65+ global $wgParser;
 66+ wfRunHooks( 'ParserFirstCallInit', $wgParser );
 67+ }
 68+
 69+# Updater fired when updating to a new version of MW.
 70+ $wgHooks['LoadExtensionSchemaUpdates'][] = 'TextTrustUpdate::updateDB';
 71+
 72+# And add and extra tab.
 73+ $wgHooks['SkinTemplateTabs'][] = 'TextTrust::ucscTrustTemplate';
 74+
 75+ // Is the user opting to use wikitrust?
 76+ $tname = "gadget-WikiTrust";
 77+ if (!$wgUser->getOption( $tname ) ) {
 78+ return;
 79+ }
 80+
 81+ // Return if trust is not selected.
 82+ if(!$wgRequest->getVal('trust') || $wgRequest->getVal('action')){
 83+ return;
 84+ }
 85+
 86+# Code which takes the "I vote" action.
 87+ if($wgUseAjax && $wgShowVoteButton){
 88+ $wgAjaxExportList[] = "TextTrustImpl::handleVote";
 89+ }
 90+
 91+# Add trust CSS and JS
 92+ $wgHooks['OutputPageBeforeHTML'][] ='TextTrust::ucscColorTrust_OP';
 93+
 94+# Add a hook to initialise the magic words
 95+ $wgHooks['LanguageGetMagic'][] = 'TextTrust::ucscColorTrust_Magic';
 96+
 97+# Set a function hook associating the blame and trust words with a callback function
 98+ $wgParser->setFunctionHook( 't', 'TextTrust::ucscColorTrust_Render');
 99+
 100+# After everything, make the blame info work
 101+ $wgHooks['ParserAfterTidy'][] = 'TextTrust::ucscOrigin_Finalize';
 102+ }
 103+
 104+ private static function getTrustObj(){
 105+ if (!self::$trust){
 106+ self::$trust = new TextTrustImpl();
 107+ }
 108+ }
 109+
 110+ // Handle trust tab.
 111+ // This is here because we use it all the time.
 112+ public static function ucscTrustTemplate($skin, &$content_actions){
 113+
 114+ global $wgRequest;
 115+ wfLoadExtensionMessages('RemoteTrust');
 116+
 117+ if ($wgRequest->getVal('action') || $wgRequest->getVal('diff')){
 118+ // we don't want trust for actions or diffs.
 119+ return true;
 120+ }
 121+
 122+ $trust_qs = $_SERVER['QUERY_STRING'];
 123+ if($trust_qs){
 124+ $trust_qs = "?" . $trust_qs . "&trust=t";
 125+ } else {
 126+ $trust_qs .= "?trust=t";
 127+ }
 128+
 129+ $content_actions['trust'] = array ( 'class' => '',
 130+ 'text' =>
 131+ wfMsgNoTrans("wgTrustTabText"),
 132+ 'href' =>
 133+ $_SERVER['PHP_SELF'] . $trust_qs );
 134+
 135+ if($wgRequest->getVal('trust')){
 136+ $content_actions['trust']['class'] = 'selected';
 137+ $content_actions['nstab-main']['class'] = '';
 138+ $content_actions['nstab-main']['href'] .= '';
 139+ } else {
 140+ $content_actions['trust']['href'] .= '';
 141+ }
 142+ return true;
 143+ }
 144+
 145+ public static function ucscColorTrust_OP(&$out, &$text){
 146+ self::getTrustObj();
 147+ return self::$trust->ucscColorTrust_OP($out, $text);
 148+ }
 149+ public static function ucscColorTrust_Magic(&$magicWords, $langCode){
 150+ self::getTrustObj();
 151+ return self::$trust->ucscColorTrust_Magic($magicWords, $langCode);
 152+ }
 153+ public static function ucscColorTrust_Render(&$parser,
 154+ $combinedValue = "0,0,0"){
 155+ self::getTrustObj();
 156+ return self::$trust->ucscColorTrust_Render($parser, $combinedValue);
 157+ }
 158+ public static function ucscOrigin_Finalize(&$parser, &$text){
 159+ self::getTrustObj();
 160+ return self::$trust->ucscOrigin_Finalize($parser, $text);
 161+ }
 162+}
 163+
 164+?>
Index: trunk/extensions/WikiTrust/remote/mediawiki/extensions/Trust/RemoteTrustImpl.php
@@ -0,0 +1,390 @@
 2+<?php
 3+
 4+class TextTrustImpl {
 5+
 6+ ## Types of analysis to perform.
 7+ const TRUST_EVAL_VOTE = 0;
 8+ const TRUST_EVAL_EDIT = 10;
 9+ const TRUST_EVAL_MISSING = 15;
 10+
 11+ ## the css tag to use
 12+ const TRUST_CSS_TAG = "background-color"; ## color the background
 13+ #$TRUST_CSS_TAG = "color"; ## color just the text
 14+
 15+ ## ColorText is called multiple times, but we only want to color true text.
 16+ const DIFF_TOKEN_TO_COLOR = "Lin";
 17+
 18+ ## Trust normalization values;
 19+ const MAX_TRUST_VALUE = 9;
 20+ const MIN_TRUST_VALUE = 0;
 21+ const TRUST_MULTIPLIER = 10;
 22+
 23+ ## Token to split trust and origin values on
 24+ const TRUST_SPLIT_TOKEN = ',';
 25+
 26+ ## Token to be replaed with <
 27+ const TRUST_OPEN_TOKEN = "QQampo:";
 28+
 29+ ## Token to be replaed with >
 30+ const TRUST_CLOSE_TOKEN = ":ampc:";
 31+
 32+ ## Server forms
 33+ const NOT_FOUND_TEXT_TOKEN = "TEXT_NOT_FOUND";
 34+ const TRUST_COLOR_TOKEN = "<!--trust-->";
 35+
 36+ ## Context for communicating with the trust server
 37+ const TRUST_TIMEOUT = 10;
 38+
 39+ ## Median Value of Trust
 40+ var $median = 1.0;
 41+
 42+ ## Number of times a revision is looked at.
 43+ var $times_rev_loaded = 0;
 44+
 45+ ## Load the article we are talking about
 46+ var $title;
 47+
 48+ ## Only color the text once.
 49+ var $colored = false;
 50+
 51+ ## Don't close the first opening span tag
 52+ var $first_span = true;
 53+
 54+ ## And the same for origin tags
 55+ var $first_origin = true;
 56+
 57+ ## And the last revision of the title
 58+ var $current_rev;
 59+
 60+ ## Only add the scripts once.
 61+ var $scripts_added = false;
 62+
 63+ ## map trust values to html color codes
 64+ var $COLORS = array(
 65+ "trust0",
 66+ "trust1",
 67+ "trust2",
 68+ "trust3",
 69+ "trust4",
 70+ "trust5",
 71+ "trust6",
 72+ "trust7",
 73+ "trust9",
 74+ "trust10",
 75+ );
 76+
 77+ ## default values for variables found from LocalSettings.php
 78+ var $DEFAULTS = array(
 79+ 'wgShowVoteButton' => false,
 80+ 'wgTrustCmd' => "eval_online_wiki",
 81+ 'wgTrustLog' => "/dev/null",
 82+ 'wgTrustDebugLog' => "/dev/null",
 83+ 'wgRepSpeed' => 1.0,
 84+ 'wgContentServerURL' => "http://localhost:10302/?",
 85+ );
 86+
 87+ ## Only write a new trust tag when the trust changes.
 88+ var $current_trust = "trust0";
 89+
 90+ public function TextTrustImpl(){
 91+ global $wgShowVoteButton, $wgTrustCmd, $wgTrustLog,
 92+ $wgTrustDebugLog, $wgContentServerURL, $wgRepSpeed;
 93+
 94+ # Add localized messages.
 95+ wfLoadExtensionMessages('RemoteTrust');
 96+
 97+ //Add default values if globals not set.
 98+ if(!$wgShowVoteButton)
 99+ $wgShowVoteButton = $this->DEFAULTS['wgShowVoteButton'];
 100+ if(!$wgTrustCmd)
 101+ $wgTrustCmd = $this->DEFAULTS['wgTrustCmd' ];
 102+ if(!$wgTrustLog)
 103+ $wgTrustLog = $this->DEFAULTS['wgTrustLog'];
 104+ if(!$wgTrustDebugLog)
 105+ $wgTrustDebugLog = $this->DEFAULTS['wgTrustDebugLog'];
 106+ if(!$wgRepSpeed)
 107+ $wgRepSpeed = $this->DEFAULTS['wgRepSpeed'];
 108+ if(!$wgContentServerURL)
 109+ $wgContentServerURL = $this->DEFAULTS['wgContentServerURL'];
 110+ }
 111+
 112+ /**
 113+ Records the vote.
 114+ Called via ajax, so this must be static.
 115+ */
 116+ static function handleVote($user_name_raw, $page_id_raw = 0,
 117+ $rev_id_raw = 0, $page_title = ""){
 118+
 119+ global $wgContentServerURL;
 120+ $response = new AjaxResponse("0");
 121+
 122+ $dbr =& wfGetDB( DB_SLAVE );
 123+
 124+ $userName = $dbr->strencode($user_name_raw, $dbr);
 125+ $page_id = $dbr->strencode($page_id_raw, $dbr);
 126+ $rev_id = $dbr->strencode($rev_id_raw, $dbr);
 127+
 128+ if($page_id){
 129+ // First, look up the id numbers from the page and user strings
 130+ $res = $dbr->select('user', array('user_id'),
 131+ array('user_name' => $userName), array());
 132+ if ($res){
 133+ $row = $dbr->fetchRow($res);
 134+ $user_id = $row['user_id'];
 135+ if (!$user_id) {
 136+ $user_id = 0;
 137+ }
 138+ }
 139+ $dbr->freeResult( $res );
 140+
 141+ $ctx = stream_context_create(
 142+ array('http' => array(
 143+ 'timeout' =>
 144+ self::TRUST_TIMEOUT
 145+ )
 146+ )
 147+ );
 148+
 149+ $vote_str = ("Voting at " . $wgContentServerURL . "vote=1&rev=$rev_id&page=$page_id&user=$user_id&page_title=$page_title&time=" . wfTimestampNow());
 150+ $colored_text = file_get_contents($wgContentServerURL . "vote=1&rev=".urlencode($rev_id)."&page=".urlencode($page_id)."&user=".urlencode($user_id)."&page_title=".urlencode($page_title)."&time=" . urlencode(wfTimestampNow()), 0, $ctx);
 151+ $response = new AjaxResponse($vote_str);
 152+ }
 153+ return $response;
 154+ }
 155+
 156+ /**
 157+ Called just before rendering HTML.
 158+ We add the coloring scripts here.
 159+ */
 160+ function ucscColorTrust_OP(&$out, &$text){
 161+ global $wgScriptPath;
 162+
 163+ if (!$this->scripts_added){ // Only add the scripts once.
 164+ $out->addScript("<script type=\"text/javascript\" src=\"".$wgScriptPath."/extensions/Trust/js/trust.js\"></script>\n");
 165+ $out->addScript("<link rel=\"stylesheet\" type=\"text/css\" href=\"".$wgScriptPath."/extensions/Trust/css/trust.css\" />\n");
 166+ $this->scripts_added = true;
 167+ }
 168+ return true;
 169+ }
 170+
 171+ /**
 172+ If colored text exists, use it instead of the normal text,
 173+ but only if the trust tab is selected.
 174+ */
 175+ function ucscSeeIfColored(&$parser, &$text, &$strip_state = Null) {
 176+ global $wgRequest, $wgUseAjax, $wgShowVoteButton, $wgDBprefix,
 177+ $wgContentServerURL;
 178+
 179+ // Get the db.
 180+ $dbr =& wfGetDB( DB_SLAVE );
 181+
 182+ // Do we use a DB prefix?
 183+ $prefix = ($wgDBprefix)? "-db_prefix " . $dbr->strencode($wgDBprefix): "";
 184+
 185+ // Text for showing the "I like it" button
 186+ $voteitText = "";
 187+ if ($wgUseAjax && $wgShowVoteButton){
 188+ $voteitText = "
 189+".self::TRUST_OPEN_TOKEN."div id='vote-button'".self::TRUST_CLOSE_TOKEN."".self::TRUST_OPEN_TOKEN."input type='button' name='vote' value='" . wfMsgNoTrans("wgVoteText") . "' onclick='startVote()' /".self::TRUST_CLOSE_TOKEN."".self::TRUST_OPEN_TOKEN."/div".self::TRUST_CLOSE_TOKEN."
 190+".self::TRUST_OPEN_TOKEN."div id='vote-button-done'".self::TRUST_CLOSE_TOKEN . wfMsgNoTrans("wgThankYouForVoting") . self::TRUST_OPEN_TOKEN."/div".self::TRUST_CLOSE_TOKEN."
 191+";
 192+ }
 193+
 194+ // Return if trust is not selected.
 195+ if(!$wgRequest->getVal('trust') || $wgRequest->getVal('action')){
 196+ return true;
 197+ }
 198+
 199+ // Save the title object, if it is not already present
 200+ if (!$this->title){
 201+ $this->title = $parser->getTitle();
 202+ }
 203+
 204+ // count the number of times we load this text
 205+ $this->times_rev_loaded++;
 206+
 207+ // Load the current revision id.
 208+ if (!$this->current_rev){
 209+ if ($parser->mRevisionId){
 210+ $this->current_rev = $parser->mRevisionId;
 211+ } else {
 212+ // Sometimes the revisionId field is not filled in.
 213+ $this->current_rev = $this->title->getPreviousRevisionID( PHP_INT_MAX );
 214+ }
 215+ }
 216+
 217+ /**
 218+ This method is being called multiple times for each page.
 219+ We only pull the colored text for the first time through.
 220+ */
 221+ if ($this->colored){
 222+ return true;
 223+ }
 224+
 225+ if ($wgRequest->getVal('diff')){
 226+ // For diffs, look for the absence of the diff token instead of counting
 227+ if(substr($text,0,3) == self::DIFF_TOKEN_TO_COLOR){
 228+ return true;
 229+ }
 230+ }
 231+
 232+ // if we made it here, we are going to color some text
 233+ $this->colored = true;
 234+
 235+ // Check to see if this page is part of the coloring project.
 236+ // Disabled for now.
 237+ //if (!strstr($text, self::TRUST_COLOR_TOKEN)){
 238+ // $text = $wgNotPartExplanation . "\n" . $text;
 239+ // return true;
 240+ //}
 241+
 242+ // Get the page id and other data
 243+ $colored_text="";
 244+ $page_id=0;
 245+ $rev_timestamp="";
 246+ $rev_user=0;
 247+ $res = $dbr->select('revision', array('rev_page', 'rev_timestamp',
 248+ 'rev_user'),
 249+ array('rev_id' => $this->current_rev), array());
 250+ if ($res){
 251+ $row = $dbr->fetchRow($res);
 252+ $page_id = $row['rev_page'];
 253+ $rev_user = $row['rev_user'];
 254+ $rev_timestamp = $row['rev_timestamp'];
 255+ if (!$page_id) {
 256+ $page_id = 0;
 257+ }
 258+ }
 259+ $dbr->freeResult( $res );
 260+
 261+ $page_title = $_GET['title'];
 262+ $ctx = stream_context_create(
 263+ array('http' => array(
 264+ 'timeout' =>
 265+ self::TRUST_TIMEOUT
 266+ )
 267+ )
 268+ );
 269+
 270+ // Should we do doing this via HTTPS?
 271+ $colored_raw = (file_get_contents($wgContentServerURL . "rev=" . urlencode($this->current_rev) . "&page=".urlencode($page_id)."&page_title=".urlencode($page_title)."&time=".urlencode($rev_timestamp)."&user=".urlencode($rev_user)."", 0, $ctx));
 272+
 273+ if ($colored_raw && $colored_raw != self::NOT_FOUND_TEXT_TOKEN){
 274+
 275+ // Inflate. Pick off the first 10 bytes for python-php conversion.
 276+ $colored_raw = gzinflate(substr($colored_raw, 10));
 277+
 278+ // Pick off the median value first.
 279+ $colored_data = explode(",", $colored_raw, 2);
 280+ $colored_text = $colored_data[1];
 281+ if (preg_match("/^[+-]?(([0-9]+)|([0-9]*\.[0-9]+|[0-9]+\.[0-9]*)|
 282+ (([0-9]+|([0-9]*\.[0-9]+|[0-9]+\.[0-9]*))[eE][+-]?[0-9]+))$/", $colored_data[0])){
 283+ $this->median = $colored_data[0];
 284+ }
 285+
 286+ // First, make sure that there are not any instances of our tokens in the colored_text
 287+ $colored_text = str_replace(self::TRUST_OPEN_TOKEN, "", $colored_text);
 288+ $colored_text = str_replace(self::TRUST_CLOSE_TOKEN, "", $colored_text);
 289+
 290+ $colored_text = preg_replace("/&apos;/", "'", $colored_text, -1);
 291+
 292+ $colored_text = preg_replace("/&amp;/", "&", $colored_text, -1);
 293+
 294+ $colored_text = preg_replace("/&lt;/", self::TRUST_OPEN_TOKEN, $colored_text, -1);
 295+ $colored_text = preg_replace("/&gt;/", self::TRUST_CLOSE_TOKEN, $colored_text, -1);
 296+
 297+ // Now update the text.
 298+ $text = $voteitText . $colored_text . "\n" .
 299+ wfMsgNoTrans("wgTrustExplanation");
 300+ } else {
 301+ // Return a message about the missing text.
 302+ $text = $parser->recursiveTagParse(wfMsgNoTrans("wgNoTrustExplanation")) . "\n" . $text;
 303+ return false;
 304+ }
 305+
 306+ return true;
 307+ }
 308+
 309+ /* Register the tags we are intersted in expanding. */
 310+ function ucscColorTrust_Magic( &$magicWords, $langCode ) {
 311+ $magicWords[ 't' ] = array( 0, 't' );
 312+ return true;
 313+ }
 314+
 315+ /* Pull in any colored text. Also handle closing tags. */
 316+ function ucscOrigin_Finalize(&$parser, &$text) {
 317+ global $wgScriptPath, $IP, $wgOut;
 318+
 319+ if(!$this->colored){
 320+ // This is to handle caching problems.
 321+ if (!strstr($text, "This page has been accessed")){
 322+ $colored_text = $text;
 323+ if ($this->ucscSeeIfColored($parser, $colored_text)){
 324+ $text = $wgOut->parse( $colored_text );
 325+ } else {
 326+ $text = $colored_text;
 327+ }
 328+ } else {
 329+ $colored_text = $text;
 330+ if ($this->ucscSeeIfColored($parser, $colored_text)){
 331+ $wgOut->mBodytext = $wgOut->parse( $colored_text );
 332+ } else {
 333+ $wgOut->mBodytext = $colored_text;
 334+ }
 335+ }
 336+ }
 337+
 338+ $count = 0;
 339+ $text = '<script type="text/javascript" src="'.$wgScriptPath.'/extensions/Trust/js/wz_tooltip.js"></script>' . $text;
 340+ $text = preg_replace('/' . self::TRUST_OPEN_TOKEN . '/', "<", $text, -1, $count);
 341+ $text = preg_replace('/' . self::TRUST_CLOSE_TOKEN .'/', ">", $text, -1, $count);
 342+ $text = preg_replace('/<\/p>/', "</span></p>", $text, -1, $count);
 343+ $text = preg_replace('/<p><\/span>/', "<p>", $text, -1, $count);
 344+ $text = preg_replace('/<li><\/span>/', "<li>", $text, -1, $count);
 345+
 346+ return true;
 347+ }
 348+
 349+ /* Text Trust */
 350+ function ucscColorTrust_Render( &$parser, $combinedValue = "0,0,0" ) {
 351+
 352+ // Split the value into trust and origin information.
 353+ // 0 = trust
 354+ // 1 = origin
 355+ // 2 = contributing author
 356+ $splitVals = explode(self::TRUST_SPLIT_TOKEN, $combinedValue);
 357+
 358+ $class = $this->computeColorFromFloat($splitVals[0]);
 359+ $output = self::TRUST_OPEN_TOKEN . "span class=\"$class\""
 360+ . "onmouseover=\"Tip('".$splitVals[2]."')\" onmouseout=\"UnTip()\""
 361+ . "onclick=\"showOrigin("
 362+ . $splitVals[1] . ")\"" . self::TRUST_CLOSE_TOKEN;
 363+
 364+ $this->current_trust = $class;
 365+ if ($this->first_span){
 366+ $this->first_span = false;
 367+ } else {
 368+ $output = self::TRUST_OPEN_TOKEN . "/span" . self::TRUST_CLOSE_TOKEN . $output;
 369+ }
 370+
 371+ return array ( $output, "noparse" => false, "isHTML" => false );
 372+ }
 373+
 374+ /**
 375+ Maps from the online trust values to the css trust values.
 376+ Normalize the value for growing wikis.
 377+ */
 378+ function computeColorFromFloat($trust){
 379+ $normalized_value = min(self::MAX_TRUST_VALUE, max(self::MIN_TRUST_VALUE,
 380+ (($trust + .5) * self::TRUST_MULTIPLIER)
 381+ / $this->median));
 382+ return $this->computeColor3($normalized_value);
 383+ }
 384+
 385+ /* Maps a trust value to a HTML color representing the trust value. */
 386+ function computeColor3($fTrustValue){
 387+ return $this->COLORS[$fTrustValue];
 388+ }
 389+}
 390+
 391+?>
\ No newline at end of file
Index: trunk/extensions/WikiTrust/remote/mediawiki/extensions/Trust/RemoteTrustUpdate.php
@@ -0,0 +1,29 @@
 2+<?php
 3+
 4+class TextTrustUpdate{
 5+
 6+ /**
 7+ * Update the DB when MW is updated.
 8+ * This assums that the db has permissions to create tables.
 9+ */
 10+ public static function updateDB(){
 11+
 12+ require_once(dirname(__FILE__) . '/' . "TrustUpdateScripts.inc");
 13+ $db =& wfGetDB( DB_MASTER );
 14+
 15+ // First check to see what tables have already been created.
 16+ $res = $db->query("show tables");
 17+ while ($row = $db->fetchRow($res)){
 18+ $db_tables[$row[0]] = True;
 19+ }
 20+
 21+ foreach ($create_scripts as $table => $scripts) {
 22+ if (!$db_tables[$table]){
 23+ foreach ($scripts as $script){
 24+ $db->query($script);
 25+ }
 26+ }
 27+ }
 28+ }
 29+}
 30+?>
\ No newline at end of file
Index: trunk/extensions/WikiTrust/remote/mediawiki/extensions/Trust/RemoteTrust.i18n.php
@@ -0,0 +1,27 @@
 2+<?php
 3+
 4+$messages = array();
 5+$messages['en'] = array (
 6+ 'wgVoteText' =>
 7+ "I believe this information is correct",
 8+ 'wgThankYouForVoting' => "Thank you for your vote",
 9+ 'wgTrustTabText' => "check text",
 10+ 'wgTrustExplanation' =>
 11+ '{| border="1" cellpadding="5" cellspacing="0" style="background:lightgreen; color:black"
 12+ |-
 13+ | The above text is colored according to how much it has been revised. An orange background indicates new, unrevised, text; white is for text that has been revised by many reputed authors. If you click on a word, you will be redirected to the diff corresponding to the edit where the word was introduced. If you hover over a word, a pop-up displays the word author.
 14+ |-
 15+ | The text color and origin are computed by [http://trust.cse.ucsc.edu/WikiTrust WikiTrust]; if you notice problems, you can submit a bug report [http://code.google.com/p/wikitrust/issues here].
 16+ |}',
 17+ 'wgNoTrustExplanation' =>
 18+ '{| border="1" cellpadding="5" cellspacing="0" style="background:lightgreen; color:black"
 19+ |-
 20+ | There is no trust information available for this text yet.
 21+ |}',
 22+ 'wgNotPartExplanation' =>
 23+ '{| border="1" cellpadding="5" cellspacing="0" style="background:lightgreen; color:black"
 24+ |-
 25+ | This page is not part of the trust experement yet.
 26+ |}',
 27+ );
 28+?>
Index: trunk/extensions/WikiTrust/remote/README
@@ -0,0 +1,185 @@
 2+Remote wiki processing.
 3+
 4+The code in this directory (/remote) is desinged to allow the
 5+processing of wiki reputation on a different server and/or network
 6+than the MediaWiki servers which host the actual wiki.
 7+
 8+====Directory Structure====
 9+
 10+analysis/
 11+
 12+This directory contains the ocaml source code which does the wiki
 13+processing.
 14+It also has a mod_python implementation for communicating with the
 15+MediaWiki server.
 16+
 17+It has the following source files:
 18+
 19+* server.py
 20+
 21+A mod_python web-server, it returns colored markup on request. It also
 22+records votes.
 23+
 24+* server.ml
 25+
 26+A depricated implementation of the wikitrust server. It is a
 27+standalone server, and does not require Apache.
 28+
 29+* server_coloring_dispatcher.ml
 30+
 31+This is the top-level file for processing wikitext and votes.
 32+
 33+* tmpfile.ml
 34+
 35+Very basic code which create a unique temp file.
 36+
 37+* wikipedia_api.ml
 38+
 39+A library which communicated with a mediawiki api. It also talks to a
 40+user-id mapping program, currently running on the toolserver.
 41+
 42+* mediawiki/extensions/Trust/
 43+
 44+All of the PHP code for the revised remote trust extension.
 45+
 46+===Setup===
 47+
 48+On Ubuntu,
 49+
 50+apt-get install libapache2-mod-python
 51+
 52+Link or copy server.py to an Apache directory.
 53+Enable mod_python for this site with
 54+
 55+SetHandler python-program
 56+PythonHandler server
 57+# Turn of for production
 58+PythonDebug On
 59+# adjust for your installation.
 60+PythonPath "['/var/www/wikis/coloring'] + sys.path"
 61+
 62+Replace /var/www/wikis/coloring with the path to your server.py
 63+
 64+Test that everything is working by going to
 65+http://192.168.135.130:10302/
 66+
 67+(replace 192.168.135.130:10302 with your ip address and port).
 68+
 69+You should see the text "bad".
 70+
 71+Now, you need to install these ocaml packages:
 72+netsys,netclient,camlzip
 73+
 74+apt-get install libzip-ocaml-dev
 75+
 76+For netsys and netclient however, it is needed to install from source
 77+(this one source tarball does both packages):
 78+
 79+wget http://download.camlcity.org/download/ocamlnet-2.2.9.tar.gz
 80+tar -zxf ocamlnet-2.2.9.tar.gz
 81+cd ocamlnet-2.2.9/
 82+./configure -with-nethttpd
 83+make all
 84+make opt
 85+make install
 86+
 87+Now, try compiling the ocaml files.
 88+
 89+make all
 90+make allopt
 91+
 92+At this point, the following binay programs should be created:
 93+
 94+server -- Depricated in faivor of server.py
 95+dispatcher -- Actually processes edits and votes
 96+
 97+Remote Trust requires a seperate MediaWiki type database in which to
 98+run. The easiest way to get this is to set up a dumy MW instalation,
 99+using the web-based form to create the initial db,
 100+and then run the sql/create_db.php script. The arguments for this are:
 101+sql/create_db.php path_to_mw_instalation db_root_user_name [remove]
 102+
 103+Now, setup the php component.
 104+
 105+In your mediawiki instalation, link the following files into
 106+wikitrust/mediawiki/extensions/Trust:
 107+
 108+RemoteTrust.i18n.php -> ../../../remote/mediawiki/extensions/Trust/RemoteTrust.i18n.php
 109+RemoteTrustImpl.php -> ../../../remote/mediawiki/extensions/Trust/RemoteTrustImpl.php
 110+RemoteTrust.php -> ../../../remote/mediawiki/extensions/Trust/RemoteTrust.php
 111+RemoteTrustUpdate.php -> ../../../remote/mediawiki/extensions/Trust/RemoteTrustUpdate.php
 112+
 113+Update LocalSettings.php, replacing ``all" old trust values with these values:
 114+
 115+# Trust extension
 116+$wgUseTidy = true;
 117+$wgUseAjax = true;
 118+$wgShowVoteButton = true; // If true, the vote button is shown.
 119+$wgTrustCmd = $IP . "/eval_online_wiki";
 120+$wgTrustLog = "/tmp/{$wgDBname}-trust.log";
 121+$wgTrustDebugLog = "/tmp/{$wgDBname}-trust-debug.log";
 122+$wgRepSpeed = 1.0;
 123+$wgContentServerURL = "http://localhost:10302/?";
 124+
 125+require_once( $IP . "/extensions/Gadgets/Gadgets.php" );
 126+require_once( $IP . "/extensions/Trust/RemoteTrust.php" );
 127+
 128+Update wgContentServerURL to point to the web server you set up for
 129+mod_python earlier.
 130+
 131+Lastly, add the Gadgets widget to your installation. Instructions are
 132+provided here:
 133+http://www.mediawiki.org/wiki/Extension:Gadgets
 134+
 135+Configure WikiTrust to run via Gadgets.
 136+Go here:
 137+http://192.168.135.130/testwiki/index.php/MediaWiki:Gadgets-definition
 138+
 139+And set the text to be:
 140+* WikiTrust|wikitrust.js
 141+
 142+You must be logged in as the WikiSysop admin user to do this.
 143+
 144+Now, log in as a regular user. Click on "my preferences", "Gadgets".
 145+Check the box for WikiTrust.
 146+
 147+===Running===
 148+
 149+You are now ready to try running the system.
 150+Click on a check-trust tab. You should get a message stating that
 151+trust for this page is not availible.
 152+
 153+Laucnch the dispatcher program to color the requested page.
 154+In remote/analysis, do:
 155+
 156+./dispatcher --help
 157+
 158+This shows all of the availible options.
 159+
 160+For general purpose, do:
 161+
 162+./dispatcher -db_user wikiuser -db_name wikidb -db_pass password
 163+-db_host localhost -db_port 3306 -wiki_api
 164+http://192.168.135.130/testwiki/api.php -user_id_api
 165+http://toolserver.org/~Ipye/UserName2UserId.php
 166+
 167+Update -wiki_api to point to the api.php page you want to target for
 168+requests for wiki-text. -user_id_api is a small program which returns
 169+the Wikipedia UserID for a username, because it is not exposed via the
 170+API currently.
 171+
 172+Run this in the forground for debugging, and in general as a deamon process.
 173+
 174+It prints out information about the edits and votes processed.
 175+With dispatcher running, the wikitrust extension should work exactly
 176+as before.
 177+
 178+
 179+
 180+
 181+
 182+
 183+
 184+
 185+
 186+===Run===
\ No newline at end of file

Status & tagging log