Gtk
[ class tree: Gtk ] [ index: Gtk ] [ all elements ]

Source for file FileDrop.php

Documentation is available at FileDrop.php

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

Documentation generated on Mon, 11 Mar 2019 15:40:33 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.