Source for file ktapi.inc.php

Documentation is available at ktapi.inc.php

  1. <?
  2. /**
  3.  *
  4.  * Implements a cleaner wrapper API for KnowledgeTree.
  5.  * @license http://www.knowledgetree.com/KPL KnowledgeTree Public License Version 1.1
  6.  * @package KTAPI
  7.  */
  8.  
  9. /*
  10.  *
  11.  * The contents of this file are subject to the KnowledgeTree Public
  12.  * License Version 1.1 ("License"); You may not use this file except in
  13.  * compliance with the License. You may obtain a copy of the License at
  14.  * http://www.knowledgetree.com/KPL
  15.  * 
  16.  * Software distributed under the License is distributed on an "AS IS"
  17.  * basis,
  18.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  19.  * for the specific language governing rights and limitations under the
  20.  * License.
  21.  * 
  22.  * The Original Code is: KnowledgeTree Open Source
  23.  * 
  24.  * The Initial Developer of the Original Code is The Jam Warehouse Software
  25.  * (Pty) Ltd, trading as KnowledgeTree.
  26.  * Portions created by The Jam Warehouse Software (Pty) Ltd are Copyright
  27.  * (C) 2007 The Jam Warehouse Software (Pty) Ltd;
  28.  * All Rights Reserved.
  29.  *
  30.  */
  31.  
  32. require_once('../config/dmsDefaults.php');
  33. require_once(KT_LIB_DIR '/filelike/fsfilelike.inc.php');
  34. require_once(KT_LIB_DIR '/foldermanagement/folderutil.inc.php');
  35.  
  36. // Generic error messages used in the API. There may be some others specific to functionality
  37. // directly in the code.
  38. // TODO: Check that they are all relevant. 
  39.  
  40. define('KTAPI_ERROR_SESSION_INVALID',             'The session could not be resolved.');
  41. define('KTAPI_ERROR_PERMISSION_INVALID',         'The permission could not be resolved.');
  42. define('KTAPI_ERROR_FOLDER_INVALID',             'The folder could not be resolved.');
  43. define('KTAPI_ERROR_DOCUMENT_INVALID',             'The document could not be resolved.');
  44. define('KTAPI_ERROR_USER_INVALID',                 'The user could not be resolved.');
  45. define('KTAPI_ERROR_KTAPI_INVALID',             'The ktapi could not be resolved.');
  46. define('KTAPI_ERROR_INSUFFICIENT_PERMISSIONS',     'The user does not have sufficient permissions to access the resource.');
  47. define('KTAPI_ERROR_INTERNAL_ERROR',             'An internal error occurred. Please review the logs.');
  48. define('KTAPI_ERROR_DOCUMENT_TYPE_INVALID',     'The document type could not be resolved.');
  49. define('KTAPI_ERROR_DOCUMENT_CHECKED_OUT',         'The document is checked out.');
  50. define('KTAPI_ERROR_DOCUMENT_NOT_CHECKED_OUT',     'The document is not checked out.');
  51. define('KTAPI_ERROR_WORKFLOW_INVALID',             'The workflow could not be resolved.');
  52. define('KTAPI_ERROR_WORKFLOW_NOT_IN_PROGRESS',     'The workflow is not in progress.');
  53.  
  54. // Mapping of permissions to actions.
  55. // TODO: Check that they are all correct.
  56. // Note, currently, all core actions have permissions that are defined in the plugins.
  57. // As the permissions are currently associated with actions which are quite closely linked
  58. // to the web interface, it is not the nicest way to do things. They should be associated at
  59. // a lower level, such as in the api. probably, better, would be at some stage to assocate
  60. // the permissions to the action/transaction in the database so administrators can really customise 
  61. // as required.
  62.  
  63. define('KTAPI_PERMISSION_DELETE',            'ktcore.permissions.delete');
  64. define('KTAPI_PERMISSION_READ',                'ktcore.permissions.read');
  65. define('KTAPI_PERMISSION_WRITE',            'ktcore.permissions.write');
  66. define('KTAPI_PERMISSION_ADD_FOLDER',        'ktcore.permissions.addFolder');
  67. define('KTAPI_PERMISSION_RENAME_FOLDER',    'ktcore.permissions.folder_rename');
  68. define('KTAPI_PERMISSION_CHANGE_OWNERSHIP',    'ktcore.permissions.security');
  69. define('KTAPI_PERMISSION_DOCUMENT_MOVE',    'ktcore.permissions.write');
  70. define('KTAPI_PERMISSION_WORKFLOW',            'ktcore.permissions.workflow');
  71.  
  72. //
  73.  
  74. {
  75.     var $ktapi;
  76.     var $user = null;
  77.     var $session = '';
  78.     var $sessionid = -1;
  79.     var $ip = null;
  80.     
  81.     function KTAPI_Session(&$ktapi&$user$session$sessionid$ip)
  82.     {
  83.         assert(!is_null($ktapi));
  84.         assert(is_a($ktapi,'KTAPI'));
  85.         assert(!is_null($user));
  86.         assert(is_a($user,'User'));
  87.                 
  88.         $this->ktapi     = &$ktapi;
  89.         $this->user     = &$user;
  90.         $this->session     = $session;
  91.         $this->sessionid = $sessionid;
  92.         $this->ip         = $ip;
  93.  
  94.         // TODO: get documenttransaction to not look at the session variable!
  95.         $_SESSION["userID"$user->getId();
  96.         $_SESSION["sessionID"$this->sessionid;            
  97.     }
  98.     
  99.     /**
  100.      * This returns the session string
  101.      *
  102.      * @return string 
  103.      */
  104.     function get_session()
  105.     {
  106.         return $this->session;
  107.     }
  108.     
  109.     /**
  110.      * This returns the sessionid in the database.
  111.      *
  112.      * @return int 
  113.      */
  114.     function get_sessionid()
  115.     {
  116.         return $this->sessionid;
  117.     }
  118.     
  119.     /**
  120.      * This returns a user object for the use rassociated with the session.
  121.      *
  122.      * @return User 
  123.      */
  124.     function &get_user()
  125.     {
  126.          return $this->user;
  127.     }
  128.         
  129.     /**
  130.      * This resolves the user's ip
  131.      *
  132.      * @access private
  133.      * @return string 
  134.      */
  135.     function resolveIP()
  136.     {
  137.         if (getenv("REMOTE_ADDR")) 
  138.         {
  139.             $ip getenv("REMOTE_ADDR");
  140.         
  141.         elseif (getenv("HTTP_X_FORWARDED_FOR")) 
  142.         {
  143.             $forwardedip getenv("HTTP_X_FORWARDED_FOR");
  144.             list($ip,$ip2,$ip3,$ip4)split (","$forwardedip);
  145.         
  146.         elseif (getenv("HTTP_CLIENT_IP")) 
  147.         {
  148.             $ip getenv("HTTP_CLIENT_IP");
  149.         }
  150.         
  151.         if ($ip == '')
  152.         {
  153.             $ip '127.0.0.1';
  154.         }
  155.         
  156.         return $ip;
  157.     }
  158.     
  159.     /**
  160.      * This returns a session object based on authentication credentials.
  161.      *
  162.      * @access private
  163.      * @param string $username 
  164.      * @param string $password 
  165.      * @return KTAPI_Session 
  166.      */
  167.     function &start_session(&$ktapi$username$password$ip=null)
  168.     {        
  169.         
  170.         if empty($username) ) 
  171.         {
  172.             return new PEAR_Error(_kt('The username is empty.'));
  173.         }
  174.  
  175.         $user =User::getByUsername($username);
  176.         if (PEAR::isError($user|| ($user === false)) 
  177.         {
  178.            return new PEAR_Error(_kt("The user '$usernamecound not be found."));      
  179.         }
  180.         
  181.         if ($user->isAnonymous())
  182.         {
  183.             $authenticated true;
  184.             
  185.             $config &KTConfig::getSingleton();    
  186.             $allow_anonymous $config->get('session/allowAnonymousLogin'false);
  187.             
  188.             if (!$allow_anonymous)
  189.             {
  190.                 return new PEAR_Error(_kt('Anonymous user not allowed'));
  191.             }   
  192.             
  193.         }
  194.         else
  195.         {
  196.             
  197.             if empty($password) ) 
  198.             {
  199.                 return new PEAR_Error(_kt('The password is empty.'));
  200.             }        
  201.             
  202.             $authenticated KTAuthenticationUtil::checkPassword($user$password);
  203.  
  204.             if (PEAR::isError($authenticated|| $authenticated === false)
  205.             {
  206.                 return new PEAR_Error(_kt("The password is invalid."));
  207.             }
  208.         }
  209.         
  210.         
  211.     
  212.         
  213.         if (is_null($ip))
  214.         {
  215.             $ip '127.0.0.1';
  216.             //$ip = KTAPI_Session::resolveIP();
  217.         }
  218.         
  219.         session_start();
  220.         
  221.         $user_id $user->getId();
  222.         
  223.         $sql "SELECT count(*) >= u.max_sessions as over_limit FROM active_sessions ass INNER JOIN users u ON ass.user_id=u.id WHERE ass.user_id = $user_id";
  224.         $row DBUtil::getOneResult($sql);
  225.         if (PEAR::isError($row))
  226.         {
  227.             return $row;
  228.         }
  229.         if (is_null($row))
  230.         {
  231.             return new PEAR_Error('No record found for user?');
  232.         }  
  233.         if ($row['over_limit'== 1)
  234.         {
  235.             return new PEAR_Error('Session limit exceeded. Logout of any active sessions.');
  236.         }
  237.         
  238.         $session session_id();
  239.         
  240.         $sessionid DBUtil::autoInsert('active_sessions',
  241.             array(
  242.                 'user_id' => $user_id,
  243.                 'session_id' => session_id(),
  244.                 'lastused' => date('Y-m-d H:i:s'),
  245.                 'ip' => $ip
  246.             ));
  247.         if (PEAR::isError($sessionid) )
  248.         {
  249.             return $sessionid;
  250.         }
  251.                 
  252.         $session &new KTAPI_Session($ktapi$user$session$sessionid$ip);        
  253.         
  254.         return $session;
  255.     }    
  256.     
  257.     /**
  258.      * This returns an active session.
  259.      *
  260.      * @param KTAPI $ktapi 
  261.      * @param string $session 
  262.      * @param string $ip 
  263.      * @return KTAPI_Session 
  264.      */
  265.     function &get_active_session(&$ktapi$session$ip)
  266.     {                
  267.         $sql "SELECT iduser_id FROM active_sessions WHERE session_id='$session'";
  268.         if (!empty($ip))
  269.         {
  270.             $sql .= " AND ip='$ip'";
  271.         }        
  272.         
  273.         $row DBUtil::getOneResult($sql);
  274.         if (is_null($row|| PEAR::isError($row))
  275.         {
  276.             return new PEAR_Error(KTAPI_ERROR_SESSION_INVALID);
  277.         }
  278.         
  279.         $sessionid $row['id'];
  280.         $userid $row['user_id'];
  281.         
  282.         $user &User::get($userid);
  283.         if (is_null($user|| PEAR::isError($user))
  284.         {
  285.             return new PEAR_Error(KTAPI_ERROR_USER_INVALID);
  286.         }
  287.         
  288.  
  289.         
  290.         $now=date('Y-m-d H:i:s');
  291.         $sql "UPDATE active_sessions SET last_used='$nowWHERE id=$sessionid";
  292.         DBUtil::runQuery($sql);
  293.         
  294.         $session &new KTAPI_Session($ktapi$user$session$sessionid$ip);        
  295.         return $session;
  296.     }
  297.     
  298.     /**
  299.      * This closes the current session.
  300.      *
  301.      */
  302.     function logout()
  303.     {
  304.         $sql "DELETE FROM active_sessions WHERE id=$this->sessionid";
  305.         $result DBUtil::runQuery($sql);
  306.         if (PEAR::isError($result))
  307.         {
  308.             return $result;
  309.         }
  310.             
  311.         $this->user         = null;
  312.         $this->session         = '';
  313.         $this->sessionid     = -1;
  314.         return true;
  315.     }
  316.     
  317. }
  318.  
  319. {
  320.     /**
  321.      * This is a reference to the core KTAPI controller
  322.      *
  323.      * @access protected
  324.      * @var KTAPI 
  325.      */
  326.     var $ktapi;    
  327.     
  328.     function &can_user_access_object_requiring_permission(&$object$permission)
  329.     {    
  330.         return $this->ktapi->can_user_access_object_requiring_permission($object$permission);
  331.     }
  332. }
  333.  
  334.  
  335. {    
  336.     /**
  337.      * This is a reference to a base Folder object.
  338.      *
  339.      * @access private
  340.      * @var Folder 
  341.      */
  342.     var $folder;
  343.     
  344.     /**
  345.      * This is the id of the folder on the database.
  346.      *
  347.      * @access private
  348.      * @var int 
  349.      */
  350.     var $folderid;
  351.  
  352.     /**
  353.      * This is used to get a folder based on a folder id.
  354.      *
  355.      * @access private
  356.      * @param KTAPI $ktapi 
  357.      * @param int $folderid 
  358.      * @return KTAPI_Folder 
  359.      */
  360.     function &get(&$ktapi$folderid)
  361.     {
  362.         assert(!is_null($ktapi));
  363.         assert(is_a($ktapi'KTAPI'));
  364.         assert(is_numeric($folderid));
  365.         
  366.         $folderid += 0;
  367.         
  368.         $folder &Folder::get($folderid);
  369.         if (is_null($folder|| PEAR::isError($folder))
  370.         {
  371.             return new PEAR_Error(KTAPI_ERROR_FOLDER_INVALID);
  372.         }
  373.         
  374.         $user $ktapi->can_user_access_object_requiring_permission($folderKTAPI_PERMISSION_READ);
  375.         
  376.         if (is_null($user|| PEAR::isError($user))
  377.         {
  378.             return $user;
  379.         }
  380.  
  381.         return new KTAPI_Folder($ktapi$folder);    
  382.     }    
  383.     
  384.     /**
  385.      * This is the constructor for the KTAPI_Folder.
  386.      *
  387.      * @access private
  388.      * @param KTAPI $ktapi 
  389.      * @param Folder $folder 
  390.      * @return KTAPI_Folder 
  391.      */
  392.     function KTAPI_Folder(&$ktapi&$folder)
  393.     {
  394.         $this->ktapi = &$ktapi;
  395.         $this->folder = &$folder;    
  396.         $this->folderid = $folder->getId();
  397.     }
  398.     
  399.     /**
  400.      * This returns a reference to the internal folder object.
  401.      *
  402.      * @access protected
  403.      * @return Folder 
  404.      */    
  405.     function &get_folder()
  406.     {
  407.         return $this->folder;
  408.     }
  409.     
  410.         
  411.     /**
  412.      * This returns detailed information on the document.
  413.      *
  414.      * @return array 
  415.      */    
  416.     function get_detail()
  417.     {
  418.         $detail array(
  419.             'id'=>$this->folderid,
  420.             'folder_name'=>$this->get_folder_name(),
  421.             'parent_id'=>$this->get_parent_folder_id(),
  422.             'full_path'=>$this->get_full_path(),
  423.         );
  424.         
  425.         return $detail;
  426.     }
  427.     
  428.     function get_parent_folder_id()
  429.     {
  430.         return $this->folder->getParentID();
  431.     }
  432.     
  433.     function get_folder_name()
  434.     {
  435.         return $this->folder->getFolderName($this->folderid);
  436.     }
  437.     
  438.     
  439.     /**
  440.      * This returns the folderid.
  441.      *
  442.      * @return int 
  443.      */
  444.     function get_folderid()
  445.     {
  446.         return $this->folderid;
  447.     }
  448.     
  449.     /**
  450.      * This can resolve a folder relative to the current directy by name
  451.      *
  452.      * @access public
  453.      * @param string $foldername 
  454.      * @return KTAPI_Folder 
  455.      */    
  456.     function &get_folder_by_name($foldername)
  457.     {
  458.         $foldername=trim($foldername);
  459.         if (empty($foldername))
  460.         {
  461.             return new PEAR_Error('A valid folder name must be specified.');
  462.         }
  463.         
  464.         $split explode('/'$foldername);
  465.         
  466.         $folderid=$this->folderid;
  467.         foreach($split as $foldername)
  468.         {
  469.             $sql "SELECT id FROM folders WHERE name='$foldernameand parent_id=$folderid";
  470.             $row DBUtil::getOneResult($sql);
  471.             if (is_null($row|| PEAR::isError($row))
  472.             {
  473.                 return new PEAR_Error(KTAPI_ERROR_FOLDER_INVALID);
  474.             }
  475.             $folderid $row['id'];            
  476.         }
  477.         
  478.         return KTAPI_Folder::get($this->ktapi$folderid);        
  479.     }
  480.         
  481.     function get_full_path()
  482.     {
  483.         $path $this->folder->getFullPath('/' $this->folder->getName();
  484.         
  485.         return $path;
  486.     }
  487.     
  488.     /**
  489.      * This gets a document by filename or name.
  490.      *
  491.      * @access private
  492.      * @param string $documentname 
  493.      * @param string $function 
  494.      * @return KTAPI_Document 
  495.      */    
  496.     function &_get_document_by_name($documentname$function='getByNameAndFolder')
  497.     {
  498.         $documentname=trim($documentname);
  499.         if (empty($documentname))
  500.         {
  501.             return new PEAR_Error('A valid document name must be specified.');
  502.         }
  503.         
  504.         $foldername dirname($documentname);
  505.         $documentname basename($documentname);
  506.         
  507.         $ktapi_folder $this;
  508.         
  509.         if (!empty($foldername&& ($foldername != '.'))
  510.         {
  511.             $ktapi_folder $this->get_folder_by_name($foldername);
  512.         }
  513.         
  514.         if (is_null($ktapi_folder|| PEAR::isError($ktapi_folder))
  515.         {
  516.             return new PEAR_Error(KTAPI_ERROR_FOLDER_INVALID);
  517.         }
  518.         
  519.         //$folder = $ktapi_folder->get_folder();
  520.         $folderid $ktapi_folder->folderid;
  521.         
  522.         $document Document::$function($documentname$folderid);        
  523.         if (is_null($document|| PEAR::isError($document))
  524.         {
  525.             return new PEAR_Error(KTAPI_ERROR_DOCUMENT_INVALID);
  526.         }
  527.         
  528.         $user $this->can_user_access_object_requiring_permission($documentKTAPI_PERMISSION_READ);                
  529.         if (PEAR::isError($user))
  530.         {
  531.             return $user;
  532.         }
  533.          
  534.         return new KTAPI_Document($this->ktapi$ktapi_folder$document);
  535.     }
  536.     
  537.     /**
  538.      * This can resolve a document relative to the current directy by name.
  539.      *
  540.      * @access public
  541.      * @param string $documentname 
  542.      * @return KTAPI_Document 
  543.      */    
  544.     function &get_document_by_name($documentname)
  545.     {
  546.         return $this->_get_document_by_name($documentname,'getByNameAndFolder');
  547.     }
  548.     
  549.     /**
  550.      * This can resolve a document relative to the current directy by filename .
  551.      *
  552.      * @access public
  553.      * @param string $documentname 
  554.      * @return KTAPI_Document 
  555.      */    
  556.     function &get_document_by_filename($documentname)
  557.     {
  558.         return $this->_get_document_by_name($documentname,'getByFilenameAndFolder');
  559.     }    
  560.     
  561.     function get_listing($depth=1$what='DF'