changed git call from https to git readonly
[atutor.git] / mods / wiki / plugins / lib / webdav.php
1 <?php
2 /*
3    WebDAV provides authoring and file access features via HTTP (it is
4    in fact an extension to it). This fits very well with Wiki, and a
5    nice client assumed provides another useful page editing interface.
6    
7    This snippet is innovocated by "z.php", and itself depends upon a
8    modified version of the HTTP_WebDAV_Server module (originally PEAR).
9    It does not yet work together with _PROTECTED_MODE settings, that's
10    why "fragments/funcs/auth.php" should be used meanwhile (as always),
11    even if the WebDAV standard actually forbidds to use the Basic auth
12    mechanism (most implementations ignore this stupid rule, and as it
13    is AntiWiki we ignore it even harder).
14    
15    Because ewiki has a really flat namespace (despite of subpages, we
16    don't have PageGroups or SubWikis fired up per default), and even
17    pagenames with a slash inside won't be treated as directories in
18    any case. That's why the implementation of our WebDAV interface is
19    much shorter than for other systems.
20    
21    - not tested at all
22    - likely to work with Wiki pages only (handling of _BINARY entries
23      is undefined)
24    - enriched with content-coding (compression) support, though it'll
25      only work for GET and PUT (won't patch the WebDAV class), but
26      todays WebDAV clients are plain stupid in this regard anyhow
27    - use the "plugins/debug/xerror.php" script together with this, if
28      you'd like to see error messages (for debugging)
29 */
30
31
32 #-- config
33 define("EWIKI_SCRIPT_WEBDAV", EWIKI_BASE_URL . "z.php/");  // may be we should use a separate z_dav.php script or so?
34 define("EWIKI_PAGE_CTYPE", "text/wiki; variant=ewiki; charset=iso-8859-1");
35 $ewiki_config["ua"] .= " WebDav/0.0.3";
36 define("WEBDAV_DIR_DEPTH", 1);   // make 0 to always include files from a collection
37
38
39 #-- implementation
40 class WikiDav extends MiniDav
41 {
42
43
44     #-- constructor
45     function WikiDav() {
46        parent::MiniDav();
47        $this->int_charset = strtolower(EWIKI_CHARSET);  // L1 only!
48        if (!function_exists("ewiki_http_header_errors") && !function_exists("ewiki_xml_comment_errors")) {
49           error_reporting(0);
50        }
51        $this->xmlns["page"] = "urn:x-ewiki:db:page-data";
52        $this->xmlns["meta"] = "urn:x-ewiki:db:meta-meta";
53     }
54
55
56
57     #-- retrieve a page
58     function GET($path) {
59
60        #-- page name, look it up in database
61        $id = $this->id($path);
62        $version = NULL;
63        $data = ewiki_db::GET($id, $version);
64
65        #-- found?
66        if ($id && $data && $data["version"]) {
67
68           #-- headers
69           ewiki_http_headers($data["content"], $id, $data, "view", $_saveasfn=0);
70           
71           #-- send
72           return $this->GET_response($data["content"], $data["lastmodified"], EWIKI_PAGE_CTYPE);
73
74        }
75        else {
76           return "404 Not Found";
77        }
78     }
79
80
81
82     #-- get meta data of page 
83     function PROPFIND($path, $props) {
84
85        #-- page name, prep
86        $id = $this->id($path);
87        $files = array();
88
89        #-- list pages
90        if (!strlen($id) || ($id=="/")) {
91
92           $oldest_time = 2*UNIX_MILLENNIUM;
93           $result = ewiki_db::GETALL(array());
94           while ($data = $result->get(1, 0x137f)) {
95              if ($this->depth >= WEBDAV_DIR_DEPTH) {
96                 $files[] = $this->fileinfo($data);
97              }
98              $oldest_time = min($oldest_time, $data["created"]);
99           }
100
101           #-- add entry for virtual root directory
102           $data = array(
103              "id"=>"/",
104              "created"=>$oldest_time,
105           );
106           $files[] = $this->dirinfo($data);
107        }
108
109        #-- just the specified one
110        else {
111           $version = NULL;
112           $data = ewiki_db::GET($id, $version);
113           if ($data) {
114              $files[] = $this->fileinfo($data);
115           }
116        }
117
118        #-- fin
119        return($files);
120     }
121
122
123     
124     #-- rearrange page meta data fields as array for WebDAV class
125     function fileinfo(&$data) {
126
127        #-- create meta/properties array
128        ($ct = $data["meta"]["Content-Type"]) or ($ct = EWIKI_PAGE_CTYPE);
129        $m = array(
130           "path" => "/" . $data["id"],   // yes just a slash, no _SCRIPT_WEBDAV prefix
131           "resourcetype" => "",  // "" ordinary page, was "collection" for dirs
132           "creationdate" => $data["created"],
133           "getcontentlength" => strlen($data["content"]),
134           "getlastmodified" => $data["lastmodified"],
135           "getcontenttype" => $ct,
136           "displayname" => ewiki_split_title($data["id"]),
137           "getetag" => ewiki_etag($data),
138           "getcontentlanguage" => EWIKI_DEFAULT_LANG,
139           "page:author" => $data["author"],
140           "page:version" => $data["version"],
141           "page:hits" => $data["hits"],
142           "page:log" => $data["meta"]["log"],
143           "page:user-agent" => $data["meta"]["user-agent"],
144        );
145        
146        #-- add {meta}² entries
147        if ($meta = $data["meta"]["meta"]) foreach ($meta as $i=>$v) {
148           $m["meta:$i"] = implode(", ", $v);
149        }
150        
151        return($m);
152     }
153
154
155     #-- needed only for (virtual) root element/dir
156     function dirinfo(&$data) {
157
158        #-- create meta/properties array
159        $ct = "httpd/unix-directory";
160        $m = array(
161           "path" => "/" . trim($data["id"], "/"),
162           "resourcetype" => "collection",  // it's a dir
163           "creationdate" => $data["created"],
164           "getcontentlength" => 0,
165 //             "getlastmodified" => $data["lastmodified"],
166           "getcontenttype" => $ct, 
167 //          "displayname" => EWIKI_NAME.":",
168        );
169        
170        return($m);
171     }
172
173
174
175     #-- save page into database (no overwriting)
176     function PUT($path, $ct, $charset) {
177
178        #-- let's call the auth routine once more??
179        $this->auth();
180
181        #-- get old page version
182        $id = $this->id($path);
183        ($data = ewiki_db::GET($id))
184        or ($data = ewiki_db::CREATE($id));
185
186        #-- read from whereever
187        $data["content"] = $this->get_body();
188
189        #-- check content-type
190        if (($ct != "text/wiki") && ($ct != "text/plain")) {
191           return("422 Only WikiPages Accepted");
192        }
193
194        #-- save back to db
195        ewiki_db::UPDATE($data);
196        $data["version"] += 1;
197        $ok = ewiki_db::WRITE($data);
198        
199        #-- handle response here
200        if ($ok) {
201           return("200 Written Successfully");
202        }
203        return("500 Couldn't Save");
204     }
205
206
207 //    #-- returns only the HTTP headers for a given page
208 //    function HEAD() {
209 //    }   // will anyhow get emulated via GET()
210
211
212     function PROPPATCH() {
213     }
214
215
216     #-- no real page deletion without authenticated admin/pw, and we
217     #   simply clear the page, if it exists (content:="DeletedPage")
218     function DELETE() {
219     }
220
221
222     function COPY() {
223     }
224     function MOVE() {
225     }
226
227
228 //    #-- we could emulate this via 'plugins/edit/lock|warn'
229 //    function LOCK() {
230 //    }
231 //    function UNLOCK() {
232 //    }
233
234
235
236     #-- just to be sure we call it again (already done in z.php)
237     function auth() {
238        parent::auth();
239        include("plugins/../fragments/funcs/auth.php");
240     }
241
242
243
244
245
246     #-- decode page id from the $path arg
247     function id($path) {
248        $id = $path;
249 //       if (strpos($id, EWIKI_SCRIPT_WEBDAV) === 0) {
250 //          $id = substr($id, strlen(EWIKI_SCRIPT_WEBDAV));
251 //       }
252        #-- MiniDav base class always leaves the slash in (originally came from PATH_INFO)
253        if ($id[0] == "/") {
254           $id = substr($id, 1);
255        }
256        return $id;
257     }
258
259
260 } // end of class
261
262
263 ?>