types._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2006 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * $Id: types.pike,v 1.2 2009/08/07 16:14:56 nicke Exp $
18  */
19 inherit "/kernel/module";
20 inherit "/base/xml_parser";
21 inherit "/base/xml_data";
22 #include <macros.h>
23 #include <database.h>
24 #include <classes.h>
25 #include <assert.h>
26 #include <config.h>
27 //! This module reads some configuration files located in the
28 //! servers config/ directory and stores information about all
29 //! mime types and what sTeam class to create for a specific mime type.
30 class types : public module,xml_parser,xml_data{
31 public:
32 
33 
34 
35 
36 
37 
38 #define MIME_FILE _Server->query_config("config-dir")+"mimetypes.txt"
39 #define CLASS_FILE _Server->query_config("config-dir")+"classtypes.txt"
40 
41 #define DATA_TYPE 0
42 #define DATA_MIME 1
43 #define DATA_DESC 2
44 #define DATA_PRIO 3
45 #define DATA_EXT 4
46 
47 private mapping mMime;
48 private mapping mExts;
49 private array asDefaults = ({ "text/plain", "text/html", "text/wiki", "application/msword", "application/vnd.ms-powerpoint", "image/gif", "image/jpeg", "image/png", "application/pdf" });
50 
51 private mapping mClasses = ([ ]);
52 
53 array get_classes() { return indices(mClasses); }
54 
55 private:
56  void init_module()
57 {
58  init_mime();
59 }
60 
61 public:
62 
63 /**
64  * Register a new class with a filename to create and a mimetype.
65  * This will change the content of the CLASS_FILE.
66  *
67  * @param string cl - the class to register
68  * @param string doc_class - the class to clone
69  * @param string mime - the mimetype
70  * @param string desc - the description for this document class.
71  */
72 protected:
73  void
74 register_class(string cl, string doc_class, string mime, string desc)
75 {
76  if ( !_SECURITY->access_register_class(0, 0, CALLER) )
77  return;
78  mMime[cl] = ({ doc_class, mime, desc });
79  Stdio.File f = Stdio.File(CLASS_FILE, "wct");
80  f->write("<classes>\n");
81  foreach(indices(mMime), string ext) {
82  f->write("\t<type>\n\t\t<ext>"+ext+"</ext>\n\t\t<class>"+
83  mMime[ext][DATA_TYPE]+"</class>\n\t\t<desc>"+
84  mMime[ext][DATA_DESC]+"</desc>\n\t</type>\n");
85  }
86  f->write("</classes>\n");
87  f->close();
88 }
89 
90 public:
91 
92 /**
93  * query_document_type, returns an array of document type information
94  * depending on the given filename.
95  *
96  * @param filename - the filename
97  * @return the document-type of that file (depends only on extension)
98  * @see query_mime_type
99  */
100 array
101 query_document_type(string filename)
102 {
103  string base_type, file_extension;
104  array ploder;
105  int i;
106 
107  LOG("query_document_type()");
108  if ( !mappingp(mMime) )
109  init_mime();
110 
111  /* initialization */
112  base_type = "";
113  file_extension = "";
114 
115  ploder = filename / "."; /* explode, hmm */
116  if ( !sizeof(ploder) )
117  return ({ "Document", "gen" });
118 
119  file_extension = ploder[sizeof(ploder)-1];
120 
121  for ( i = strlen(file_extension) - 1; i >= 0; i-- )
122  if ( file_extension[i] >= 'A' && file_extension[i] <= 'Z' )
123  file_extension[i] -= ('A' - 'a');
124  file_extension = lower_case(file_extension);
125  LOG("File Extension:" + file_extension);
126  if ( arrayp(mMime[file_extension]) )
127  {
128  return ({ mMime[file_extension][DATA_TYPE],
129  file_extension });
130  }
131 
132  return ({ "Document", file_extension });
133 }
134 
135 /**
136  * Returns the documents extensions for a given mimetype.
137  *
138  * @param string mtype - the mimetype
139  * @return array of extensions for this mime type with information
140  */
141 array query_document_type_mime(string mtype)
142 {
143  if ( arrayp(mExts[mtype]) )
144  return ({ mExts[mtype][DATA_TYPE], "" });
145  else
146  return ({ "Document", "" });
147 }
148 
149 /**
150  * Return the array of possible extensions for the given mimetype.
151  *
152  * @param string mtype - the mimetype
153  * @return array of extensions for mtype
154  */
155 array query_mimetype_extensions(string mtype)
156 {
157  array extensions = ({ });
158  if ( !arrayp(mExts[mtype]) )
159  return extensions;
160 
161  foreach( mExts[mtype], mixed ext ) {
162  extensions += ({ ext[DATA_EXT] });
163  }
164  return extensions;
165 }
166 
167 void
168 register_extensions(string mtype, string desc, array extensions, void|int def)
169 {
170  int i = 0;
171  if ( mExts[mtype] )
172  error("Cannot reregister extension !");
173  mExts[mtype] = extensions;
174 
175  foreach(extensions, string ext) {
176  i++;
177  mMime[ext] = ({ "Document", mtype, desc, i, ext });
178  }
179  if ( def && search(asDefaults, mtype) == -1 )
180  asDefaults += ({ mtype });
181 }
182 
183 array get_default_mimetypes()
184 {
185  return copy_value(asDefaults);
186 }
187 
188 /**
189  * Return the mimetype for a given extension.
190  *
191  * @param doc - the document extension
192  * @return the mime-type of the document
193  * @see query_document_type
194  */
195 string
196 query_mime_type(string doc)
197 {
198  if ( ! stringp( doc ) )
199  return MIMETYPE_UNKNOWN;
200 
201  array data;
202 
203  if ( !mappingp(mMime) )
204  init_mime();
205 
206  data = mMime[lower_case(doc)];
207  if ( !arrayp(data) )
208  return MIMETYPE_UNKNOWN;
209 
210  if ( !stringp(data[DATA_MIME]) )
211  steam_error("Failure in types: Non-string value for mimetype "+doc);
212  if ( data[DATA_MIME] == "" )
213  steam_error("Failure in types: Empty string value for mimetype "+doc);
214 
215  return data[DATA_MIME];
216 }
217 
218 /**
219  * Return the mime description for an extension.
220  *
221  * @param doc - the document extension
222  * @return the description of the mime-type
223  * @see query_mime_type
224  */
225 string
226 query_mime_desc(string doc)
227 {
228  array data;
229 
230  if ( !mappingp(mMime) )
231  init_mime();
232 
233  data = mMime[lower_case(doc)];
234  if ( !arrayp(data) )
235  return "Generic";
236 
237  return data[DATA_DESC];
238 }
239 
240 /**
241 private:
242  * init_mime
243  *
244  * @see query_types
245  */
246 nomask void
247 private:
248 init_mime()
249 {
250  array lines;
251  array tokens;
252  string buf;
253  int start, i, j, len;
254  mixed data;
255 
256  buf = Stdio.read_file(CLASS_FILE);
257 
258  ASSERTINFO(stringp(buf),
259  "Initialization error: class file missing ["+CLASS_FILE+"]\n");
260 
261  //lines = buf / "\n";
262  mMime = ([ ]);
263  NodeXML n = parse_data(buf);
264  string classname;
265  foreach(n->children, NodeXML type) {
266  NodeXML t = type->get_node("ext");
267  classname = type->get_node("class")->data;
268  if ( stringp(classname) )
269  mClasses[classname] = 1;
270  mMime[t->data] = ({ classname,
271  MIMETYPE_UNKNOWN,
272  type->get_node("desc")->data, 0 });
273  }
274 
275  // read the mimetypes.txt
276  buf = Stdio.read_file(MIME_FILE);
277  if ( !stringp(buf) ) {
278  FATAL("Initialization error: mime file missing! ["+MIME_FILE +"]\n");
279  return;
280  }
281  lines = buf / "\n";
282 
283  for ( i = sizeof(lines) - 1; i >= 0; i-- ) {
284  len = strlen(lines[i]);
285  if ( len == 0 || lines[i][0] == '#' )
286  continue;
287  j = 0; start = -1; tokens = ({ });
288  while ( j < len ) {
289  if ( lines[i][j] == ' ' || lines[i][j] == '\t' ) {
290  if ( start != -1 ) {
291  tokens += ({ lines[i][start..j-1] });
292  }
293  start = -1;
294  }
295  else if ( start == -1 ) {
296  start = j;
297  }
298  j++;
299  }
300  if ( start != -1 )
301  tokens += ({ lines[i][start..] });
302 
303  if ( sizeof(tokens) > 1 ) {
304  for ( j = sizeof(tokens) - 1; j >= 1; j-- ) {
305  data = mMime[tokens[j]];
306 
307  if ( arrayp(data) ) {
308  // remember the priority of extensions
309  // html htm wiki, then html should have priority (lowest j)
310  mMime[tokens[j]][DATA_MIME] = tokens[0];
311  mMime[tokens[j]][DATA_PRIO] = j;
312  }
313  else
314  mMime[tokens[j]] =
315  ({ "Document", tokens[0], "Generic", j });
316  }
317  }
318  }
319  mExts = ([ ]);
320  foreach ( indices(mMime), string ext ) {
321  // mExts mapping holds mimetype:data
322  if ( arrayp(mExts[mMime[ext][DATA_MIME]]) )
323  mExts[mMime[ext][DATA_MIME]] += ({ mMime[ext]+({ ext }) });
324  else {
325  mExts[mMime[ext][DATA_MIME]] = ({ mMime[ext]+({ ext }) });
326  }
327  }
328  foreach ( indices(mExts), string mtype ) {
329  if ( sizeof(mExts[mtype]) > 1 ) {
330  array sorter = ({ });
331  foreach(mExts[mtype], mixed ext)
332  sorter += ({ ext[DATA_PRIO] });
333  sort(mExts[mtype], sorter);
334  }
335  }
336 }
337 
338 public:
339 
340 /**
341  * Return the whole mapping of saved types. The mapping contains
342  * file extension: informations (array)
343  *
344  * @return the mapping with all type definitions
345 private:
346  * @see init_mime
347  */
348 mapping
349 query_types()
350 {
351  return copy_value(mMime);
352 }
353 
354 public:
355 
356 
357 /**
358  * return the class for a doctype (extension of a file).
359  *
360  * @param doc - the doctype (or extension)
361  * @return the class
362  */
363 string query_document_class(string doc)
364 {
365  mixed data;
366 
367  data = mMime[doc];
368  if ( !arrayp(data) )
369  return CLASS_NAME_DOCUMENT;
370  LOG("class is " + data[DATA_TYPE]);
371  return data[DATA_TYPE];
372 }
373 
374 /**
375  * Return the document class for the given mimetype.
376  * The class can be found in the classes/ Folder of sTeam.
377  *
378  * @param string mtype - the mimetype
379  * @return string of class type used
380  */
381 string query_document_class_mime(string mtype)
382 {
383  if ( arrayp(mExts[mtype]) )
384  return mExts[mtype][0][DATA_TYPE];
385  else
386  return CLASS_NAME_DOCUMENT;
387 }
388 
389 
390 string get_identifier() { return "types"; }
391 
392 
393 };