dolibarr  13.0.2
index.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
3  * Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2017 Regis Houssin <regis.houssin@inodbox.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
27 use Luracast\Restler\Format\UploadFormat;
28 
29 if (!defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check anti CSRF attack test
30 if (!defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not check anti POST attack test
31 if (!defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu
32 if (!defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php
33 if (!defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library
34 if (!defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session)
35 if (!defined("NOSESSION")) define("NOSESSION", '1');
36 
37 
38 // Force entity if a value is provided into HTTP header. Otherwise, will use the entity of user of token used.
39 if (!empty($_SERVER['HTTP_DOLAPIENTITY'])) define("DOLENTITY", (int) $_SERVER['HTTP_DOLAPIENTITY']);
40 
41 
42 $res = 0;
43 if (!$res && file_exists("../main.inc.php")) $res = include '../main.inc.php';
44 if (!$res) die("Include of main fails");
45 
46 require_once DOL_DOCUMENT_ROOT.'/includes/restler/framework/Luracast/Restler/AutoLoader.php';
47 
48 call_user_func(function () {
49  $loader = Luracast\Restler\AutoLoader::instance();
50  spl_autoload_register($loader);
51  return $loader;
52 });
53 
54 require_once DOL_DOCUMENT_ROOT.'/api/class/api.class.php';
55 require_once DOL_DOCUMENT_ROOT.'/api/class/api_access.class.php';
56 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
57 
58 
59 $url = $_SERVER['PHP_SELF'];
60 if (preg_match('/api\/index\.php$/', $url)) { // sometimes $_SERVER['PHP_SELF'] is 'api\/index\.php' instead of 'api\/index\.php/explorer.php' or 'api\/index\.php/method'
61  $url = $_SERVER['PHP_SELF'].$_SERVER['PATH_INFO'];
62 }
63 // Fix for some NGINX setups (this should not be required even with NGINX, however setup of NGINX are often mysterious and this may help is such cases)
64 if (!empty($conf->global->MAIN_NGINX_FIX))
65 {
66  $url = (isset($_SERVER['SCRIPT_URI']) && $_SERVER["SCRIPT_URI"] !== null) ? $_SERVER["SCRIPT_URI"] : $_SERVER['PHP_SELF'];
67 }
68 
69 // Enable and test if module Api is enabled
70 if (empty($conf->global->MAIN_MODULE_API))
71 {
72  $langs->load("admin");
73  dol_syslog("Call Dolibarr API interfaces with module REST disabled");
74  print $langs->trans("WarningModuleNotActive", 'Api').'.<br><br>';
75  print $langs->trans("ToActivateModule");
76  //session_destroy();
77  exit(0);
78 }
79 
80 // Test if explorer is not disabled
81 if (preg_match('/api\/index\.php\/explorer/', $url) && !empty($conf->global->API_EXPLORER_DISABLED))
82 {
83  $langs->load("admin");
84  dol_syslog("Call Dolibarr API interfaces with module REST disabled");
85  print $langs->trans("WarningAPIExplorerDisabled").'.<br><br>';
86  //session_destroy();
87  exit(0);
88 }
89 
90 
91 // This 2 lines are usefull only if we want to exclude some Urls from the explorer
92 //use Luracast\Restler\Explorer;
93 //Explorer::$excludedPaths = array('/categories');
94 
95 
96 // Analyze URLs
97 // index.php/explorer do a redirect to index.php/explorer/
98 // index.php/explorer/ called by swagger to build explorer page
99 // index.php/explorer/.../....png|.css|.js called by swagger for resources to build explorer page
100 // index.php/explorer/resources.json called by swagger to get list of all services
101 // index.php/explorer/resources.json/xxx called by swagger to get detail of services xxx
102 // index.php/xxx called by any REST client to run API
103 
104 
105 $reg = array();
106 preg_match('/index\.php\/([^\/]+)(.*)$/', $url, $reg);
107 // .../index.php/categories?sortfield=t.rowid&sortorder=ASC
108 
109 
110 // When in production mode, a file api/temp/routes.php is created with the API available of current call.
111 // But, if we set $refreshcache to false, so it may have only one API in the routes.php file if we make a call for one API without
112 // using the explorer. And when we make another call for another API, the API is not into the api/temp/routes.php and a 404 is returned.
113 // So we force refresh to each call.
114 $refreshcache = (empty($conf->global->API_PRODUCTION_DO_NOT_ALWAYS_REFRESH_CACHE) ? true : false);
115 if (!empty($reg[1]) && $reg[1] == 'explorer' && ($reg[2] == '/swagger.json' || $reg[2] == '/swagger.json/root' || $reg[2] == '/resources.json' || $reg[2] == '/resources.json/root'))
116 {
117  $refreshcache = true;
118 }
119 
120 $api = new DolibarrApi($db, '', $refreshcache);
121 //var_dump($api->r->apiVersionMap);
122 
123 // Enable the Restler API Explorer.
124 // See https://github.com/Luracast/Restler-API-Explorer for more info.
125 $api->r->addAPIClass('Luracast\\Restler\\Explorer');
126 
127 $api->r->setSupportedFormats('JsonFormat', 'XmlFormat', 'UploadFormat'); // 'YamlFormat'
128 $api->r->addAuthenticationClass('DolibarrApiAccess', '');
129 
130 // Define accepted mime types
131 UploadFormat::$allowedMimeTypes = array('image/jpeg', 'image/png', 'text/plain', 'application/octet-stream');
132 
133 
134 // Restrict API to some IPs
135 if (!empty($conf->global->API_RESTRICT_ON_IP))
136 {
137  $allowedip = explode(' ', $conf->global->API_RESTRICT_ON_IP);
138  $ipremote = getUserRemoteIP();
139  if (!in_array($ipremote, $allowedip))
140  {
141  dol_syslog('Remote ip is '.$ipremote.', not into list '.$conf->global->API_RESTRICT_ON_IP);
142  print 'APIs are not allowed from the IP '.$ipremote;
143  header('HTTP/1.1 503 API not allowed from your IP '.$ipremote);
144  //session_destroy();
145  exit(0);
146  }
147 }
148 
149 
150 // Call Explorer file for all APIs definitions (this part is slow)
151 if (!empty($reg[1]) && $reg[1] == 'explorer' && ($reg[2] == '/swagger.json' || $reg[2] == '/swagger.json/root' || $reg[2] == '/resources.json' || $reg[2] == '/resources.json/root'))
152 {
153  // Scan all API files to load them
154 
155  $listofapis = array();
156 
157  $modulesdir = dolGetModulesDirs();
158  foreach ($modulesdir as $dir)
159  {
160  // Search available module
161  dol_syslog("Scan directory ".$dir." for module descriptor files, then search for API files");
162 
163  $handle = @opendir(dol_osencode($dir));
164  if (is_resource($handle))
165  {
166  while (($file = readdir($handle)) !== false)
167  {
168  $regmod = array();
169  if (is_readable($dir.$file) && preg_match("/^mod(.*)\.class\.php$/i", $file, $regmod))
170  {
171  $module = strtolower($regmod[1]);
172  $moduledirforclass = getModuleDirForApiClass($module);
173  $modulenameforenabled = $module;
174  if ($module == 'propale') { $modulenameforenabled = 'propal'; }
175  if ($module == 'supplierproposal') { $modulenameforenabled = 'supplier_proposal'; }
176  if ($module == 'ficheinter') { $modulenameforenabled = 'ficheinter'; }
177 
178  dol_syslog("Found module file ".$file." - module=".$module." - modulenameforenabled=".$modulenameforenabled." - moduledirforclass=".$moduledirforclass);
179 
180  // Defined if module is enabled
181  $enabled = true;
182  if (empty($conf->$modulenameforenabled->enabled)) $enabled = false;
183 
184  if ($enabled)
185  {
186  // If exists, load the API class for enable module
187  // Search files named api_<object>.class.php into /htdocs/<module>/class directory
188  // @todo : use getElementProperties() function ?
189  $dir_part = dol_buildpath('/'.$moduledirforclass.'/class/');
190 
191  $handle_part = @opendir(dol_osencode($dir_part));
192  if (is_resource($handle_part))
193  {
194  while (($file_searched = readdir($handle_part)) !== false)
195  {
196  if ($file_searched == 'api_access.class.php') continue;
197 
198  $regapi = array();
199  if (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i", $file_searched, $regapi))
200  {
201  $classname = ucwords($regapi[1]);
202  $classname = str_replace('_', '', $classname);
203  require_once $dir_part.$file_searched;
204  if (class_exists($classname.'Api'))
205  {
206  //dol_syslog("Found API by index.php: classname=".$classname."Api for module ".$dir." into ".$dir_part.$file_searched);
207  $listofapis[strtolower($classname.'Api')] = $classname.'Api';
208  } elseif (class_exists($classname))
209  {
210  //dol_syslog("Found API by index.php: classname=".$classname." for module ".$dir." into ".$dir_part.$file_searched);
211  $listofapis[strtolower($classname)] = $classname;
212  } else {
213  dol_syslog("We found an api_xxx file (".$file_searched.") but class ".$classname." does not exists after loading file", LOG_WARNING);
214  }
215  }
216  }
217  }
218  }
219  }
220  }
221  }
222  }
223 
224  // Sort the classes before adding them to Restler.
225  // The Restler API Explorer shows the classes in the order they are added and it's a mess if they are not sorted.
226  asort($listofapis);
227  foreach ($listofapis as $apiname => $classname)
228  {
229  $api->r->addAPIClass($classname, $apiname);
230  }
231  //var_dump($api->r);
232 }
233 
234 // Call one APIs or one definition of an API
235 $regbis = array();
236 if (!empty($reg[1]) && ($reg[1] != 'explorer' || ($reg[2] != '/swagger.json' && $reg[2] != '/resources.json' && preg_match('/^\/(swagger|resources)\.json\/(.+)$/', $reg[2], $regbis) && $regbis[2] != 'root')))
237 {
238  $moduleobject = $reg[1];
239  if ($moduleobject == 'explorer') // If we call page to explore details of a service
240  {
241  $moduleobject = $regbis[2];
242  }
243 
244  $moduleobject = strtolower($moduleobject);
245  $moduledirforclass = getModuleDirForApiClass($moduleobject);
246 
247  // Load a dedicated API file
248  dol_syslog("Load a dedicated API file moduleobject=".$moduleobject." moduledirforclass=".$moduledirforclass);
249 
250  $tmpmodule = $moduleobject;
251  if ($tmpmodule != 'api')
252  $tmpmodule = preg_replace('/api$/i', '', $tmpmodule);
253  $classfile = str_replace('_', '', $tmpmodule);
254 
255  // Special cases that does not match name rules conventions
256  if ($moduleobject == 'supplierproposals')
257  $classfile = 'supplier_proposals';
258  if ($moduleobject == 'supplierorders')
259  $classfile = 'supplier_orders';
260  if ($moduleobject == 'supplierinvoices')
261  $classfile = 'supplier_invoices';
262  if ($moduleobject == 'ficheinter')
263  $classfile = 'interventions';
264  if ($moduleobject == 'interventions')
265  $classfile = 'interventions';
266 
267  $dir_part_file = dol_buildpath('/'.$moduledirforclass.'/class/api_'.$classfile.'.class.php', 0, 2);
268 
269  $classname = ucwords($moduleobject);
270 
271  dol_syslog('Search api file /'.$moduledirforclass.'/class/api_'.$classfile.'.class.php => dir_part_file='.$dir_part_file.' classname='.$classname);
272 
273  $res = false;
274  if ($dir_part_file)
275  $res = include_once $dir_part_file;
276  if (!$res) {
277  dol_syslog('Failed to make include_once '.$dir_part_file, LOG_WARNING);
278  print 'API not found (failed to include API file)';
279  header('HTTP/1.1 501 API not found (failed to include API file)');
280  //session_destroy();
281  exit(0);
282  }
283 
284  if (class_exists($classname))
285  $api->r->addAPIClass($classname);
286 }
287 
288 
289 //var_dump($api->r->apiVersionMap);
290 //exit;
291 
292 // Call API (we suppose we found it).
293 // The handle will use the file api/temp/routes.php to get data to run the API. If the file exists and the entry for API is not found, it will return 404.
294 
295 //Luracast\Restler\Defaults::$returnResponse = true;
296 //print $api->r->handle();
297 
298 $api->r->handle();
299 
300 //session_destroy();
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
getUserRemoteIP()
Return the IP of remote user.
getModuleDirForApiClass($moduleobject)
Get name of directory where the api_...class.php file is stored.
dolGetModulesDirs($subdir= '')
Return list of modules directories.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
Class for API REST v1.
Definition: api.class.php:30
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
print $_SERVER["PHP_SELF"]
Edit parameters.
print
Draft customers invoices.
Definition: index.php:89