28use Luracast\Restler\Format\UploadFormat;
 
   30if (!defined(
'NOCSRFCHECK')) {
 
   31  define(
'NOCSRFCHECK', 
'1'); 
 
   33if (!defined(
'NOTOKENRENEWAL')) {
 
   34  define(
'NOTOKENRENEWAL', 
'1'); 
 
   36if (!defined(
'NOREQUIREMENU')) {
 
   37  define(
'NOREQUIREMENU', 
'1'); 
 
   39if (!defined(
'NOREQUIREHTML')) {
 
   40  define(
'NOREQUIREHTML', 
'1'); 
 
   42if (!defined(
'NOREQUIREAJAX')) {
 
   43  define(
'NOREQUIREAJAX', 
'1'); 
 
   45if (!defined(
"NOLOGIN")) {
 
   46  define(
"NOLOGIN", 
'1'); 
 
   48if (!defined(
"NOSESSION")) {
 
   49  define(
"NOSESSION", 
'1');
 
   51if (!defined(
"NODEFAULTVALUES")) {
 
   52  define(
"NODEFAULTVALUES", 
'1');
 
   56if (!empty($_SERVER[
'HTTP_DOLAPIENTITY'])) {
 
   57  define(
"DOLENTITY", (
int) $_SERVER[
'HTTP_DOLAPIENTITY']);
 
   61if (!empty($_SERVER[
'REQUEST_METHOD']) && $_SERVER[
'REQUEST_METHOD'] == 
'OPTIONS' && !empty($_SERVER[
'HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
 
   62  header(
'Access-Control-Allow-Origin: *');
 
   63  header(
'Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
 
   64  header(
'Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY');
 
   65  http_response_code(204);
 
   70if (preg_match(
'/\/explorer\/swagger\.json/', $_SERVER[
"PHP_SELF"])) {
 
   71  header(
'Access-Control-Allow-Origin: *');
 
   72  header(
'Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
 
   73  header(
'Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY');
 
   76if (preg_match(
'/\/api\/index\.php/', $_SERVER[
"PHP_SELF"])) {
 
   77  header(
'Access-Control-Allow-Origin: *');
 
   78  header(
'Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
 
   79  header(
'Access-Control-Allow-Headers: Content-Type, Authorization, api_key, DOLAPIKEY');
 
   81header(
'X-Frame-Options: SAMEORIGIN');
 
   85if (!$res && file_exists(
"../main.inc.php")) {
 
   86  $res = include 
'../main.inc.php';
 
   89  die(
"Include of main fails");
 
   92require_once DOL_DOCUMENT_ROOT.
'/includes/restler/framework/Luracast/Restler/AutoLoader.php';
 
   94call_user_func(
function () {
 
   95  $loader = Luracast\Restler\AutoLoader::instance();
 
   96  spl_autoload_register($loader);
 
  100require_once DOL_DOCUMENT_ROOT.
'/api/class/api.class.php';
 
  101require_once DOL_DOCUMENT_ROOT.
'/api/class/api_access.class.php';
 
  102require_once DOL_DOCUMENT_ROOT.
'/core/lib/functions2.lib.php';
 
  105$url = $_SERVER[
'PHP_SELF'];
 
  106if (preg_match(
'/api\/index\.php$/', $url)) { 
 
  107  $url = $_SERVER[
'PHP_SELF'].(empty($_SERVER[
'PATH_INFO']) ? $_SERVER[
'ORIG_PATH_INFO'] : $_SERVER[
'PATH_INFO']);
 
  111  $url = (isset($_SERVER[
'SCRIPT_URI']) && $_SERVER[
"SCRIPT_URI"] !== 
null) ? $_SERVER[
"SCRIPT_URI"] : $_SERVER[
'PHP_SELF'];
 
  115if (!isModEnabled(
'api')) {
 
  116  $langs->load(
"admin");
 
  117  dol_syslog(
"Call of Dolibarr API interfaces with module API REST are disabled");
 
  118  print $langs->trans(
"WarningModuleNotActive", 
'Api').
'.<br><br>';
 
  119  print $langs->trans(
"ToActivateModule");
 
  125if (preg_match(
'/api\/index\.php\/explorer/', $url) && 
getDolGlobalString(
'API_EXPLORER_DISABLED')) {
 
  126  $langs->load(
"admin");
 
  127  dol_syslog(
"Call Dolibarr API interfaces with module API REST disabled");
 
  128  print $langs->trans(
"WarningAPIExplorerDisabled").
'.<br><br>';
 
  149preg_match(
'/index\.php\/([^\/]+)(.*)$/', $url, $reg);
 
  157$refreshcache = (!
getDolGlobalString(
'API_PRODUCTION_DO_NOT_ALWAYS_REFRESH_CACHE') ? true : 
false);
 
  158if (!empty($reg[1]) && $reg[1] == 
'explorer' && ($reg[2] == 
'/swagger.json' || $reg[2] == 
'/swagger.json/root' || $reg[2] == 
'/resources.json' || $reg[2] == 
'/resources.json/root')) {
 
  159  $refreshcache = 
true;
 
  160  if (!is_writable($conf->api->dir_temp)) {
 
  161    print 
'Erreur temp dir api/temp not writable';
 
  172  $r->onCall(
function () use ($r) {
 
  181    dol_syslog(
"Debug API url ".var_export($r->url, 
true), LOG_DEBUG, 0, 
'_api');
 
  182    dol_syslog(
"Debug API input ".var_export($r->getRequestData(), 
true), LOG_DEBUG, 0, 
'_api');
 
  190$api->r->addAPIClass(
'Luracast\\Restler\\Explorer');
 
  192$api->r->setSupportedFormats(
'JsonFormat', 
'XmlFormat', 
'UploadFormat'); 
 
  193$api->r->addAuthenticationClass(
'DolibarrApiAccess', 
'');
 
  196UploadFormat::$allowedMimeTypes = array(
'image/jpeg', 
'image/png', 
'text/plain', 
'application/octet-stream');
 
  203  if (!in_array($ipremote, $allowedip)) {
 
  205    print 
'APIs are not allowed from the IP '.$ipremote;
 
  206    header(
'HTTP/1.1 503 API not allowed from your IP '.$ipremote);
 
  214if (!empty($reg[1]) && $reg[1] == 
'explorer' && ($reg[2] == 
'/swagger.json' || $reg[2] == 
'/swagger.json/root' || $reg[2] == 
'/resources.json' || $reg[2] == 
'/resources.json/root')) {
 
  217  $listofapis = array();
 
  220  foreach ($modulesdir as $dir) {
 
  222    dol_syslog(
"Scan directory ".$dir.
" for module descriptor files, then search for API files");
 
  225    if (is_resource($handle)) {
 
  226      while (($file = readdir($handle)) !== 
false) {
 
  228        if (is_readable($dir.$file) && preg_match(
"/^mod(.*)\.class\.php$/i", $file, $regmod)) {
 
  229          $module = strtolower($regmod[1]);
 
  231          $modulenameforenabled = $module;
 
  232          if ($module == 
'propale') {
 
  233            $modulenameforenabled = 
'propal';
 
  235          if ($module == 
'supplierproposal') {
 
  236            $modulenameforenabled = 
'supplier_proposal';
 
  238          if ($module == 
'ficheinter') {
 
  239            $modulenameforenabled = 
'ficheinter';
 
  242          dol_syslog(
"Found module file ".$file.
" - module=".$module.
" - modulenameforenabled=".$modulenameforenabled.
" - moduledirforclass=".$moduledirforclass);
 
  246          if (!isModEnabled($modulenameforenabled)) {
 
  257            if (is_resource($handle_part)) {
 
  258              while (($file_searched = readdir($handle_part)) !== 
false) {
 
  259                if ($file_searched == 
'api_access.class.php') {
 
  264                if ($file_searched == 
'api_login.class.php' && 
getDolGlobalString(
'MAIN_MODULE_API_LOGIN_DISABLED')) {
 
  271                if (is_readable($dir_part.$file_searched) && preg_match(
"/^api_(.*)\.class\.php$/i", $file_searched, $regapi)) {
 
  272                  $classname = ucwords($regapi[1]);
 
  273                  $classname = str_replace(
'_', 
'', $classname);
 
  274                  require_once $dir_part.$file_searched;
 
  275                  if (class_exists($classname.
'Api')) {
 
  277                    $listofapis[strtolower($classname.
'Api')] = $classname.
'Api';
 
  278                  } elseif (class_exists($classname)) {
 
  280                    $listofapis[strtolower($classname)] = $classname;
 
  282                    dol_syslog(
"We found an api_xxx file (".$file_searched.
") but class ".$classname.
" does not exists after loading file", LOG_WARNING);
 
  296  foreach ($listofapis as $apiname => $classname) {
 
  297    $api->r->addAPIClass($classname, $apiname);
 
  304if (!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'))) {
 
  305  $moduleobject = $reg[1];
 
  306  if ($moduleobject == 
'explorer') {  
 
  307    $moduleobject = $regbis[2];
 
  310  $moduleobject = strtolower($moduleobject);
 
  314  dol_syslog(
"Load a dedicated API file moduleobject=".$moduleobject.
" moduledirforclass=".$moduledirforclass);
 
  316  $tmpmodule = $moduleobject;
 
  317  if ($tmpmodule != 
'api') {
 
  318    $tmpmodule = preg_replace(
'/api$/i', 
'', $tmpmodule);
 
  320  $classfile = str_replace(
'_', 
'', $tmpmodule);
 
  323  if ($moduleobject == 
'supplierproposals') {
 
  324    $classfile = 
'supplier_proposals';
 
  326  if ($moduleobject == 
'supplierorders') {
 
  327    $classfile = 
'supplier_orders';
 
  329  if ($moduleobject == 
'supplierinvoices') {
 
  330    $classfile = 
'supplier_invoices';
 
  332  if ($moduleobject == 
'ficheinter') {
 
  333    $classfile = 
'interventions';
 
  335  if ($moduleobject == 
'interventions') {
 
  336    $classfile = 
'interventions';
 
  339  $dir_part_file = 
dol_buildpath(
'/'.$moduledirforclass.
'/class/api_'.$classfile.
'.class.php', 0, 2);
 
  341  $classname = ucwords($moduleobject);
 
  347    $endpointisallowed = 
false;
 
  349    foreach ($listofendpoints as $endpointrule) {
 
  350      $tmparray = explode(
':', $endpointrule);
 
  351      if (($classfile == $tmparray[0] || $classfile.
'api' == $tmparray[0]) && $tmparray[1] == 1) {
 
  352        $endpointisallowed = 
true;
 
  357    if (! $endpointisallowed) {
 
  358      dol_syslog(
'The API with endpoint /'.$classfile.
' is forbidden by config API_ENDPOINT_RULES', LOG_WARNING);
 
  359      print 
'The API with endpoint /'.$classfile.
' is forbidden by config API_ENDPOINT_RULES';
 
  360      header(
'HTTP/1.1 501 API is forbidden by API_ENDPOINT_RULES');
 
  366  dol_syslog(
'Search api file /'.$moduledirforclass.
'/class/api_'.$classfile.
'.class.php => dir_part_file='.$dir_part_file.
', classname='.$classname);
 
  369  if ($dir_part_file) {
 
  370    $res = include_once $dir_part_file;
 
  373    dol_syslog(
'Failed to make include_once '.$dir_part_file, LOG_WARNING);
 
  374    print 
'API not found (failed to include API file)';
 
  375    header(
'HTTP/1.1 501 API not found (failed to include API file)');
 
  380  if (class_exists($classname)) {
 
  381    $api->r->addAPIClass($classname);
 
  391$usecompression = (!
getDolGlobalString(
'API_DISABLE_COMPRESSION') && !empty($_SERVER[
'HTTP_ACCEPT_ENCODING']));
 
  392$foundonealgorithm = 0;
 
  393if ($usecompression) {
 
  394  if (strpos($_SERVER[
'HTTP_ACCEPT_ENCODING'], 
'br') !== 
false && function_exists(
'brotli_compress')) {
 
  395    $foundonealgorithm++;
 
  397  if (strpos($_SERVER[
'HTTP_ACCEPT_ENCODING'], 
'bz') !== 
false && function_exists(
'bzcompress')) {
 
  398    $foundonealgorithm++;
 
  400  if (strpos($_SERVER[
'HTTP_ACCEPT_ENCODING'], 
'gzip') !== 
false && function_exists(
'gzencode')) {
 
  401    $foundonealgorithm++;
 
  403  if (!$foundonealgorithm) {
 
  404    $usecompression = 
false;
 
  410Luracast\Restler\Defaults::$returnResponse = $usecompression;
 
  414$result = $api->r->handle();
 
  416if (Luracast\Restler\Defaults::$returnResponse) {
 
  418  if (strpos($_SERVER[
'HTTP_ACCEPT_ENCODING'], 
'br') !== 
false && function_exists(
'brotli_compress') && defined(
'BROTLI_TEXT')) {
 
  419    header(
'Content-Encoding: br');
 
  420    $result = brotli_compress($result, 11, constant(
'BROTLI_TEXT'));
 
  421  } elseif (strpos($_SERVER[
'HTTP_ACCEPT_ENCODING'], 
'bz') !== 
false && function_exists(
'bzcompress')) {
 
  422    header(
'Content-Encoding: bz');
 
  423    $result = bzcompress($result, 9);
 
  424  } elseif (strpos($_SERVER[
'HTTP_ACCEPT_ENCODING'], 
'gzip') !== 
false && function_exists(
'gzencode')) {
 
  425    header(
'Content-Encoding: gzip');
 
  426    $result = gzencode($result, 9);
 
  428    header(
'Content-Encoding: text/html');
 
  429    print 
"No compression method found. Try to disable compression by adding API_DISABLE_COMPRESSION=1";
 
  437if (
getDolGlobalInt(
"API_ENABLE_COUNT_CALLS") && $api->r->responseCode == 200) {
 
  440  $userid = DolibarrApiAccess::$user->id;
 
  442  $sql = 
"SELECT up.value";
 
  443  $sql .= 
" FROM ".MAIN_DB_PREFIX.
"user_param as up";
 
  444  $sql .= 
" WHERE up.param = 'API_COUNT_CALL'";
 
  445  $sql .= 
" AND up.fk_user = ".((int) $userid);
 
  446  $sql .= 
" AND up.entity = ".((int) $conf->entity);
 
  448  $result = $db->query($sql);
 
  451    $nbrows = $db->num_rows($result);
 
  453      $sql2 = 
"INSERT INTO ".MAIN_DB_PREFIX.
"user_param";
 
  454      $sql2 .= 
" (fk_user, entity, param, value)";
 
  455      $sql2 .= 
" VALUES (".((int) $userid).
", ".((int) $conf->entity).
", 'API_COUNT_CALL', 1)";
 
  458      $sql2 = 
"UPDATE ".MAIN_DB_PREFIX.
"user_param as up";
 
  459      $sql2 .= 
" SET up.value = up.value + 1";
 
  460      $sql2 .= 
" WHERE up.param = 'API_COUNT_CALL'";
 
  461      $sql2 .= 
" AND up.fk_user = ".((int) $userid);
 
  462      $sql2 .= 
" AND up.entity = ".((int) $conf->entity);
 
  465    $result2 = $db->query($sql2);
 
  467      $modeapicall = $updateapi ? 
'updating' : 
'inserting';
 
  468      dol_syslog(
'Error while '.$modeapicall. 
' API_COUNT_CALL for user '.$userid, LOG_ERR);
 
  472    dol_syslog(
'Error on select API_COUNT_CALL for user '.$userid, LOG_ERR);
 
getModuleDirForApiClass($moduleobject)
Get name of directory where the api_...class.php file is stored.
 
dolGetModulesDirs($subdir='')
Return list of modules directories.
 
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
 
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
 
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
 
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
 
getUserRemoteIP()
Return the IP of remote user.
 
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.