home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / Gtk / FileDrop.php next >
Encoding:
PHP Script  |  2005-12-02  |  12.0 KB  |  344 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at the following url:           |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Christian Weiske <cweiske@php.net>                          |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: FileDrop.php,v 1.1 2004/11/06 16:22:36 cweiske Exp $
  20.  
  21. require_once('MIME/Type.php');
  22. require_once('PEAR.php');
  23.  
  24. /**
  25.  * A FileDrop error code.
  26.  * @const GTK_FILEDROP_WIDGET_NOT_SUPPORTED
  27.  */
  28. define('GTK_FILEDROP_WIDGET_NOT_SUPPORTED', 1);
  29.  
  30. /**
  31. *   A class which makes it easy to
  32. *   make a GtkWidget accept the dropping
  33. *   of files or folders
  34. *   @author Christian Weiske <cweiske@cweiske.de>
  35. *   @package Gtk
  36. *
  37. *   @date 2004-10-21 13:12
  38. *   @license PHP
  39. *
  40. *   @todo
  41. *   - reject files when moving the dragging mouse over the widget, just like opera does
  42. *       how does this work? I don't know, but I suppose I should
  43. *
  44. *   @example
  45. *   Usage:
  46. *   Simply change the text of a widget 
  47. *   (accept files with MIME-Types text/plain and text/html and files with .sgml extension):
  48. *       Gtk_FileDrop::attach($entry, array('text/plain', 'text/html', '.sgml'));
  49. *   Call a callback, and don't change the text (accept directories only):
  50. *       Gtk_FileDrop::attach($entry, array( 'inode/directory'), array( &$this, 'callback'), false);
  51. */
  52. class Gtk_FileDrop
  53. {
  54.     /**
  55.     *   prepares a widget to accept file drops
  56.     *   @static
  57.     *   @param GtkWidget    The widget which shall accept files
  58.     *   @param array        List of MIME-Types to accept OR extensions, beginning with a dot "."
  59.     *   @param mixed        Callback to call when a drop with valid files happened
  60.     *   @param boolean      If the widget's text/label/content shall be changed automatically
  61.     *
  62.     *   @return boolean     If all was ok
  63.     */
  64.     function attach($widget, $arTypes, $objCallback = null, $bSetText = true)
  65.     {
  66.         $widget->drag_dest_set(GTK_DEST_DEFAULT_ALL, array(array('text/uri-list', 0, 0)), GDK_ACTION_COPY | GDK_ACTION_MOVE);
  67.         
  68.         $fd = new Gtk_FileDrop( $arTypes, $objCallback, $bSetText);
  69.         $widget->connect('drag-data-received', array( &$fd, 'dragDataReceived'));
  70.         
  71.         return true;
  72.     }
  73.     
  74.  
  75.     
  76.     /**
  77.     *   constructor
  78.     *   Use attach() instead!
  79.     *
  80.     *   @access private
  81.     */
  82.     function Gtk_FileDrop( $arTypes, $objCallback = null, $bSetText = true) 
  83.     {
  84.         $this->arTypes     = $arTypes;
  85.         $this->objCallback = $objCallback;
  86.         $this->bSetText    = $bSetText;
  87.     }
  88.     
  89.     
  90.     
  91.     /**
  92.     *   prepares a widget to accept directories only
  93.     *   Just a shortcut for the exhausted programmer
  94.     *   @static
  95.     *   @param GtkWidget    The widget which shall accept directories
  96.     *
  97.     *   @return boolean     If all was ok
  98.     */
  99.     function attachDirectory($widget)
  100.     {
  101.         return Gtk_FileDrop::attach($widget, array('inode/directory'));
  102.     }
  103.  
  104.     
  105.     
  106.     /**
  107.     *   Data have been dropped over the widget
  108.     *   @param GtkWidget      The widget on which the data have been dropped
  109.     *   @param GdkDragContext The context of the drop
  110.     *   @param int            X position
  111.     *   @param int            Y position
  112.     *   @param int            Info parameter (0 in our case)
  113.     *   @param int            The time on which the event happened
  114.     */
  115.     function dragDataReceived($widget, $context , $x, $y, $data , $info, $time)
  116.     {
  117.         $arData     = explode("\n", $data->data);
  118.         $arAccepted = array();
  119.         $arRejected = array();
  120.         $bDirectories = false;
  121.         foreach ($arData as $strLine) {
  122.             $strLine = trim($strLine);
  123.             if ($strLine == '') { 
  124.                 continue; 
  125.             }
  126.             $strFile     = Gtk_FileDrop::getPathFromUrilistEntry($strLine);
  127.             $strFileMime = Gtk_FileDrop::getMimeType($strFile);
  128.             $bAccepted   = false;
  129.             foreach ($this->arTypes as $strType) {
  130.                 if ($strType == 'inode/directory') { 
  131.                     $bDirectories = true; 
  132.                 }
  133.                 if (($strType[0] == '.' && Gtk_FileDrop::getFileExtension($strFile) == $strType)
  134.                  || $strType == $strFileMime || MIME_Type::wildcardMatch($strType, $strFileMime)) {
  135.                     $arAccepted[] = $strFile;
  136.                     $bAccepted    = true;
  137.                     break;
  138.                 }
  139.             }//foreach type
  140.             if (!$bAccepted) {
  141.                 $arRejected[] = $strFile;
  142.             }
  143.         }//foreach line
  144.         
  145.         //make directories from the files if dirs are accepted
  146.         //this is done here to give native directories first places on the list
  147.         if ($bDirectories && count($arRejected) > 0) {
  148.             foreach ($arRejected as $strFile) {
  149.                 $arAccepted[] = dirname( $strFile);
  150.             }
  151.         }
  152.         
  153.         if (count($arAccepted) == 0) {
  154.             //no matching files
  155.             return;
  156.         }
  157.         
  158.         if ($this->bSetText) {
  159.             $strClass = get_class($widget);
  160.             switch ($strClass) {
  161.             case 'GtkEntry':
  162.             case 'GtkLabel':
  163.                 $widget->set_text($arAccepted[0]);
  164.                 break;
  165.             case 'GtkButton':
  166.             case 'GtkToggleButton':
  167.             case 'GtkCheckButton':
  168.             case 'GtkRadioButton':
  169.                 $childs = $widget->children();
  170.                 $child = $childs[0];
  171.                 if (get_class($child) == 'GtkLabel') {
  172.                     $child->set_text($arAccepted[0]);
  173.                 } else {
  174.                     trigger_error('No label found on widget.');
  175.                 }
  176.                 break;
  177.             case 'GtkCombo':
  178.                 $entry = $widget->entry;
  179.                 $entry->set_text($arAccepted[0]);
  180.                 break;
  181.             case 'GtkFileSelection':
  182.                 $widget->set_filename($arAccepted[0]);
  183.                 break;
  184.             case 'GtkList':
  185.                 foreach ($arAccepted as $strFile) {
  186.                     $items[] =& new GtkListItem($strFile);
  187.                 }
  188.                 $widget->append_items($items);
  189.                 $widget->show_all();
  190.                 break;
  191.             default:
  192.                 PEAR::raiseError( 'Widget class "' . $strClass . '" is not supported', GTK_FILEDROP_WIDGET_NOT_SUPPORTED, PEAR_ERROR_TRIGGER, E_USER_WARNING);
  193.                 break;
  194.             }
  195.         }//if bSetText
  196.         
  197.         if ($this->objCallback !== null) {
  198.             call_user_func( $this->objCallback, $widget, $arAccepted);
  199.         }//objCallback !== null
  200.     }
  201.     
  202.     
  203.     
  204.     /**
  205.     *   converts a file path gotten from a text/uri-list
  206.     *   drop to a usable local filepath
  207.     *
  208.     *   Php functions like parse_url can't be used as it is
  209.     *   likely that the dropped URI is no real URI but a 
  210.     *   strange thing which tries to look like one
  211.     *   See the explanation at:
  212.     *   http://gtk.php.net/manual/en/tutorials.filednd.urilist.php
  213.     *
  214.     *   @static
  215.     *   @param  string  The line from the uri-list
  216.     *   @return string  The usable local filepath
  217.     */
  218.     function getPathFromUrilistEntry($strUriFile)
  219.     {
  220.         $strUriFile = urldecode($strUriFile);//should be URL-encoded
  221.         $bUrl = false;
  222.         if (substr($strUriFile, 0, 5) == 'file:') {
  223.             //(maybe buggy) file protocol
  224.             if (substr($strUriFile, 0, 17) == 'file://localhost/') {
  225.                 //correct implementation
  226.                 $strFile = substr($strUriFile, 16);
  227.             } else if (substr($strUriFile, 0, 8) == 'file:///') {
  228.                 //no hostname, but three slashes - nearly correct
  229.                 $strFile = substr($strUriFile, 7);
  230.             } else if ($strUriFile[5] == '/') {
  231.                 //theoretically, the hostname should be the first
  232.                 //but no one implements it
  233.                 $strUriFile = substr($strUriFile, 5);
  234.                 for( $n = 1; $n < 5; $n++) {
  235.                     if ($strUriFile[$n] != '/') { 
  236.                         break; 
  237.                     }
  238.                 }
  239.                 $strUriFile = substr($strUriFile, $n - 1);
  240.                 if (!file_exists($strUriFile)) {
  241.                     //perhaps a correct implementation with hostname???
  242.                     $strUriFileNoHost = strstr(substr($strUriFile, 1), '/');
  243.                     if (file_exists($strUriFileNoHost)) {
  244.                         //seems so
  245.                         $strUriFile = $strUriFileNoHost;
  246.                     }
  247.                 }
  248.                 $strFile = $strUriFile;
  249.             } else {
  250.                 //NO slash after "file:" - what is that for a crappy program?
  251.                 $strFile = substr ($strUriFile, 5);
  252.             }
  253.         } else if (strstr($strUriFile, '://')) {
  254.             //real protocol, but not file
  255.             $strFile = $strUriFile;
  256.             $bUrl    = true;
  257.         } else {
  258.             //local file?
  259.             $strFile = $strUriFile;
  260.         }
  261.         if (!$bUrl && $strFile[2] == ':' && $strFile[0] == '/') {
  262.             //windows file path
  263.             $strFile = str_replace('/', '\\', substr($strFile, 1));
  264.         }
  265.         return $strFile;
  266.     }
  267.     
  268.     
  269.     
  270.     /**
  271.     *   returns the extension if a filename
  272.     *   including the leading dot
  273.     *   @static
  274.     *   @param  string  The filename
  275.     *   @return string  The extension with a leading dot
  276.     */
  277.     function getFileExtension($strFile)
  278.     {
  279.         $strExt = strrchr($strFile, '.');
  280.         if ($strExt == false) { 
  281.             return ''; 
  282.         }
  283.         $strExt = str_replace('\\', '/', $strExt);
  284.         if (strpos($strExt, '/') !== false) {
  285.             return ''; 
  286.         }
  287.         return $strExt;
  288.     }
  289.     
  290.     
  291.     
  292.     /**
  293.     *   determines the mime-type for the given file
  294.     *   @static
  295.     *   @param  string  The file name
  296.     *   @return string  The MIME type or FALSE in the case of an error
  297.     */
  298.     function getMimeType($strFile)
  299.     {
  300.         //MIME_Type doesn't return the right type for directories
  301.         //The underlying functions MIME_Type used don't return it right, 
  302.         //so there is no chance to fix MIME_Type itself
  303.         if ((file_exists($strFile) && is_dir($strFile))
  304.           || substr($strFile, -1) == '/') {
  305.             return 'inode/directory';
  306.         }
  307.         $strMime = MIME_Type::autoDetect($strFile);
  308.         if (!PEAR::isError($strMime)) {
  309.             return $strMime;
  310.         }
  311.         
  312.         //determine by extension | as MIME_TYPE doesn't support this, I have to do this myself
  313.         $strExtension = Gtk_FileDrop::getFileExtension($strFile);
  314.         switch ($strExtension) {
  315.             case '.txt' : 
  316.                 $strType = 'text/plain'; 
  317.                 break;
  318.             case '.gif' : 
  319.                 $strType = 'image/gif'; 
  320.                 break;
  321.             case '.jpg' :
  322.             case '.jpeg': 
  323.                 $strType = 'image/jpg'; 
  324.                 break;
  325.             case '.png' : 
  326.                 $strType = 'image/png'; 
  327.                 break;
  328.             case '.xml' : 
  329.                 $strType = 'text/xml';
  330.                 break;
  331.             case '.htm' :
  332.             case '.html': 
  333.                 $strType = 'text/html'; 
  334.                 break;
  335.             default:     
  336.                 $strType = false; 
  337.                 break;
  338.         }
  339.         return $strType;
  340.     }
  341.     
  342. }
  343. ?>
  344.