1 /* Copyright (C) 2000-2006  Thomas Bopp, Thorsten Hampel, Ludger Merkens
     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.
     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.
    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
    17  * $Id: types.pike,v 1.2 2009/08/07 16:14:56 nicke Exp $
    19 inherit "/kernel/module";
    20 inherit "/base/xml_parser";
    21 inherit "/base/xml_data";
    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{
    38 #define MIME_FILE _Server->query_config("config-dir")+"mimetypes.txt"
    39 #define CLASS_FILE _Server->query_config("config-dir")+"classtypes.txt"
    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" });
    51 private  mapping mClasses = ([ ]);
    53 array get_classes() { return indices(mClasses); }
    64  * Register a new class with a filename to create and a mimetype.
    65  * This will change the content of the CLASS_FILE.
    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.
    74 register_class(string cl, string doc_class, string mime, string desc)
    76     if ( !_SECURITY->access_register_class(0, 0, CALLER) )
    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");
    86     f->write("</classes>\n");
    93  * query_document_type, returns an array of document type information 
    94  * depending on the given filename.
    96  * @param filename - the filename
    97  * @return the document-type of that file (depends only on extension)
    98  * @see query_mime_type
   101 query_document_type(string filename)
   103     string base_type, file_extension;
   107     LOG("query_document_type()");
   108     if ( !mappingp(mMime) )
   115     ploder = filename / "."; /* explode, hmm */
   116     if ( !sizeof(ploder) )
   117    return ({ "Document", "gen" });
   119     file_extension = ploder[sizeof(ploder)-1];
   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]) )
   128    return ({ mMime[file_extension][DATA_TYPE], 
   132     return ({ "Document", file_extension });
   136  * Returns the documents extensions for a given mimetype.
   138  * @param string mtype - the mimetype
   139  * @return array of extensions for this mime type with information
   141 array query_document_type_mime(string mtype)
   143     if ( arrayp(mExts[mtype]) )
   144    return ({ mExts[mtype][DATA_TYPE], "" });
   146    return ({ "Document", "" });
   150  * Return the array of possible extensions for the given mimetype.
   152  * @param string mtype - the mimetype
   153  * @return array of extensions for mtype
   155 array query_mimetype_extensions(string mtype)
   157     array extensions = ({ });
   158     if ( !arrayp(mExts[mtype]) )
   161     foreach( mExts[mtype], mixed ext ) {
   162    extensions += ({ ext[DATA_EXT] });
   168 register_extensions(string mtype, string desc, array extensions, void|int def)
   172    error("Cannot reregister extension !");
   173     mExts[mtype] = extensions;
   175     foreach(extensions, string ext) {
   177    mMime[ext] = ({ "Document", mtype, desc, i, ext });
   179     if ( def && search(asDefaults, mtype) == -1 )
   180    asDefaults += ({ mtype });
   183 array get_default_mimetypes()
   185     return copy_value(asDefaults);
   189  * Return the mimetype for a given extension.
   191  * @param doc - the document extension
   192  * @return the mime-type of the document
   193  * @see query_document_type
   196 query_mime_type(string doc)
   198     if ( ! stringp( doc ) )
   199         return MIMETYPE_UNKNOWN;
   203     if ( !mappingp(mMime) )
   206     data = mMime[lower_case(doc)];
   208    return MIMETYPE_UNKNOWN;
   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);
   215     return data[DATA_MIME];
   219  * Return the mime description for an extension.
   221  * @param doc - the document extension
   222  * @return the description of the mime-type
   223  * @see query_mime_type
   226 query_mime_desc(string doc)
   230     if ( !mappingp(mMime) )
   233     data = mMime[lower_case(doc)];
   237     return data[DATA_DESC];
   253     int                  start, i, j, len;
   256     buf = Stdio.read_file(CLASS_FILE);
   258     ASSERTINFO(stringp(buf),
   259           "Initialization error: class file missing ["+CLASS_FILE+"]\n");
   261     //lines = buf / "\n";
   263     NodeXML n = parse_data(buf);
   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,
   272                        type->get_node("desc")->data, 0 });
   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");
   283     for ( i = sizeof(lines) - 1; i >= 0; i-- ) {
   284    len = strlen(lines[i]);
   285    if ( len == 0 || lines[i][0] == '#' )
   287    j = 0; start = -1; tokens = ({ });
   289        if ( lines[i][j] == ' ' || lines[i][j] == '\t' ) {
   291                tokens += ({ lines[i][start..j-1] });
   295        else if ( start == -1 ) {
   301        tokens += ({ lines[i][start..] });
   303    if ( sizeof(tokens) > 1 ) {
   304        for ( j = sizeof(tokens) - 1; j >= 1; j-- ) {
   305            data = mMime[tokens[j]];
   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;
   315                    ({ "Document", tokens[0], "Generic", j });
   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 }) });
   325        mExts[mMime[ext][DATA_MIME]]  = ({ mMime[ext]+({ ext })  });
   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);
   341  * Return the whole mapping of saved types. The mapping contains
   342  * file extension: informations (array)
   344  * @return the mapping with all type definitions
   351     return copy_value(mMime);
   358  * return the class for a doctype (extension of a file).
   360  * @param doc - the doctype (or extension)
   363 string query_document_class(string doc)
   369    return CLASS_NAME_DOCUMENT;
   370     LOG("class is " + data[DATA_TYPE]);
   371     return data[DATA_TYPE];
   375  * Return the document class for the given mimetype.
   376  * The class can be found in the classes/ Folder of sTeam.
   378  * @param string mtype - the mimetype
   379  * @return string of class type used
   381 string query_document_class_mime(string mtype)
   383     if ( arrayp(mExts[mtype]) )
   384    return mExts[mtype][0][DATA_TYPE];
   386    return CLASS_NAME_DOCUMENT;
   390 string get_identifier() { return "types"; }