<?PHP
/* Copyright 2005-2022, Lime Technology
 * Copyright 2014-2022, Guilherme Jardim, Eric Schultz, Jon Panozzo.
 * Copyright 2012-2022, Bergware International.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version 2,
 * as published by the Free Software Foundation.
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 */
?>
<?
function addRoute($ct) {
  // add static route(s) for remote WireGuard access
  [$pid,$net] = explode(' ',exec("docker inspect --format='{{.State.Pid}} {{.NetworkSettings.Networks}}' $ct"));
  $net = substr($net,4,strpos($net,':')-4);
  if (!$pid || $net != 'br0') return;
  $thisip  = ipaddr();
  foreach (glob('/etc/wireguard/wg*.cfg') as $cfg) {
    $network = exec("grep -Pom1 '^Network:0=\"\\K[^\"]+' $cfg");
    if ($network) exec("nsenter -n -t $pid ip -4 route add $network via $thisip 2>/dev/null");
  }
}

function xml_encode($string) {
  return htmlspecialchars($string, ENT_XML1, 'UTF-8');
}

function xml_decode($string) {
  return strval(html_entity_decode($string, ENT_XML1, 'UTF-8'));
}

function postToXML($post, $setOwnership=false) {
  $dom = new domDocument;
  $dom->appendChild($dom->createElement("Container"));
  $xml = simplexml_import_dom($dom);
  $xml['version']          = 2;
  $xml->Name               = xml_encode(preg_replace('/\s+/', '', $post['contName']));
  $xml->Repository         = xml_encode(trim($post['contRepository']));
  $xml->Registry           = xml_encode(trim($post['contRegistry']));
  $xml->Network            = xml_encode($post['contNetwork']);
  $xml->MyIP               = xml_encode($post['contMyIP']);
  $xml->Shell              = xml_encode($post['contShell']);
  $xml->Privileged         = strtolower($post['contPrivileged'])=='on' ? 'true' : 'false';
  $xml->Support            = xml_encode($post['contSupport']);
  $xml->Project            = xml_encode($post['contProject']);
  $xml->Overview           = xml_encode($post['contOverview']);
  $xml->Category           = xml_encode($post['contCategory']);
  $xml->WebUI              = xml_encode(trim($post['contWebUI']));
  $xml->TemplateURL        = xml_encode($post['contTemplateURL']);
  $xml->Icon               = xml_encode(trim($post['contIcon']));
  $xml->ExtraParams        = xml_encode($post['contExtraParams']);
  $xml->PostArgs           = xml_encode($post['contPostArgs']);
  $xml->CPUset             = xml_encode($post['contCPUset']);
  $xml->DateInstalled      = xml_encode(time());
  $xml->DonateText         = xml_encode($post['contDonateText']);
  $xml->DonateLink         = xml_encode($post['contDonateLink']);
  $xml->Requires           = xml_encode($post['contRequires']);

  $size = is_array($post['confName']) ? count($post['confName']) : 0;
  for ($i = 0; $i < $size; $i++) {
    $Type                  = $post['confType'][$i];
    $config                = $xml->addChild('Config', xml_encode($post['confValue'][$i]));
    $config['Name']        = xml_encode($post['confName'][$i]);
    $config['Target']      = xml_encode($post['confTarget'][$i]);
    $config['Default']     = xml_encode($post['confDefault'][$i]);
    $config['Mode']        = xml_encode($post['confMode'][$i]);
    $config['Description'] = xml_encode($post['confDescription'][$i]);
    $config['Type']        = xml_encode($post['confType'][$i]);
    $config['Display']     = xml_encode($post['confDisplay'][$i]);
    $config['Required']    = xml_encode($post['confRequired'][$i]);
    $config['Mask']        = xml_encode($post['confMask'][$i]);
  }
  $dom = new DOMDocument('1.0');
  $dom->preserveWhiteSpace = false;
  $dom->formatOutput = true;
  $dom->loadXML($xml->asXML());
  return $dom->saveXML();
}

function xmlToVar($xml) {
  global $subnet;
  $xml                = is_file($xml) ? simplexml_load_file($xml) : simplexml_load_string($xml);
  $out                = [];
  $out['Name']        = preg_replace('/\s+/', '', xml_decode($xml->Name));
  $out['Repository']  = xml_decode($xml->Repository);
  $out['Registry']    = xml_decode($xml->Registry);
  $out['Network']     = xml_decode($xml->Network);
  $out['MyIP']        = xml_decode($xml->MyIP ?? '');
  $out['Shell']       = xml_decode($xml->Shell ?? 'sh');
  $out['Privileged']  = xml_decode($xml->Privileged);
  $out['Support']     = xml_decode($xml->Support);
  $out['Project']     = xml_decode($xml->Project);
  $out['Overview']    = stripslashes(xml_decode($xml->Overview));
  $out['Category']    = xml_decode($xml->Category);
  $out['WebUI']       = xml_decode($xml->WebUI);
  $out['TemplateURL'] = xml_decode($xml->TemplateURL);
  $out['Icon']        = xml_decode($xml->Icon);
  $out['ExtraParams'] = xml_decode($xml->ExtraParams);
  $out['PostArgs']    = xml_decode($xml->PostArgs);
  $out['CPUset']      = xml_decode($xml->CPUset);
  $out['DonateText']  = xml_decode($xml->DonateText);
  $out['DonateLink']  = xml_decode($xml->DonateLink);
  $out['Requires']    = xml_decode($xml->Requires);
  $out['Config']      = [];
  if (isset($xml->Config)) {
    foreach ($xml->Config as $config) {
      $c = [];
      $c['Value'] = strlen(xml_decode($config)) ? xml_decode($config) : xml_decode($config['Default']);
      foreach ($config->attributes() as $key => $value) {
        $value = xml_decode($value);
        $val = strtolower($value);
        if ($key == 'Mode') {
          switch (xml_decode($config['Type'])) {
          case 'Path':
            $value = ($val=='rw'||$val=='rw,slave'||$val=='rw,shared'||$val=='ro'||$val=='ro,slave'||$val=='ro,shared') ? $value : "rw";
            break;
          case 'Port':
            $value = ($val=='tcp'||$val=='udp') ? $value : "tcp";
            break;
          }
        }
        $c[$key] = strip_tags(html_entity_decode($value));
      }
      $out['Config'][] = $c;
    }
  }
  // some xml templates advertise as V2 but omit the new <Network> element
  // check for and use the V1 <Networking> element when this occurs
  if (empty($out['Network']) && isset($xml->Networking->Mode)) {
    $out['Network'] = xml_decode($xml->Networking->Mode);
  }
  // check if network exists
  if (!key_exists($out['Network'],$subnet)) $out['Network'] = 'none';
  // V1 compatibility
  if ($xml['version'] != '2') {
    if (isset($xml->Description)) {
      $out['Overview'] = stripslashes(xml_decode($xml->Description));
    }
    if (isset($xml->Networking->Publish->Port)) {
      $portNum = 0;
      foreach ($xml->Networking->Publish->Port as $port) {
        if (empty(xml_decode($port->ContainerPort))) continue;
        $portNum += 1;
        $out['Config'][] = [
          'Name'        => "Host Port ${portNum}",
          'Target'      => xml_decode($port->ContainerPort),
          'Default'     => xml_decode($port->HostPort),
          'Value'       => xml_decode($port->HostPort),
          'Mode'        => xml_decode($port->Protocol) ? xml_decode($port->Protocol) : "tcp",
          'Description' => '',
          'Type'        => 'Port',
          'Display'     => 'always',
          'Required'    => 'true',
          'Mask'        => 'false'
        ];
      }
    }
    if (isset($xml->Data->Volume)) {
      $volNum = 0;
      foreach ($xml->Data->Volume as $vol) {
        if (empty(xml_decode($vol->ContainerDir))) continue;
        $volNum += 1;
        $out['Config'][] = [
          'Name'        => "Host Path ${volNum}",
          'Target'      => xml_decode($vol->ContainerDir),
          'Default'     => xml_decode($vol->HostDir),
          'Value'       => xml_decode($vol->HostDir),
          'Mode'        => xml_decode($vol->Mode) ? xml_decode($vol->Mode) : "rw",
          'Description' => '',
          'Type'        => 'Path',
          'Display'     => 'always',
          'Required'    => 'true',
          'Mask'        => 'false'
        ];
      }
    }
    if (isset($xml->Environment->Variable)) {
      $varNum = 0;
      foreach ($xml->Environment->Variable as $varitem) {
        if (empty(xml_decode($varitem->Name))) continue;
        $varNum += 1;
        $out['Config'][] = [
          'Name'        => "Key ${varNum}",
          'Target'      => xml_decode($varitem->Name),
          'Default'     => xml_decode($varitem->Value),
          'Value'       => xml_decode($varitem->Value),
          'Mode'        => '',
          'Description' => '',
          'Type'        => 'Variable',
          'Display'     => 'always',
          'Required'    => 'false',
          'Mask'        => 'false'
        ];
      }
    }
    if (isset($xml->Labels->Variable)) {
      $varNum = 0;
      foreach ($xml->Labels->Variable as $varitem) {
        if (empty(xml_decode($varitem->Name))) continue;
        $varNum += 1;
        $out['Config'][] = [
          'Name'        => "Label ${varNum}",
          'Target'      => xml_decode($varitem->Name),
          'Default'     => xml_decode($varitem->Value),
          'Value'       => xml_decode($varitem->Value),
          'Mode'        => '',
          'Description' => '',
          'Type'        => 'Label',
          'Display'     => 'always',
          'Required'    => 'false',
          'Mask'        => 'false'
        ];
      }
    }
  }
  xmlSecurity($out);
  return $out;
}

function xmlSecurity(&$template) {
  foreach ($template as &$element) {
    if (is_array($element)) {
      xmlSecurity($element);
    } else {
      if (is_string($element)) {
        $tempElement = htmlspecialchars_decode($element);
        $tempElement = str_replace("[","<",$tempElement);
        $tempElement = str_replace("]",">",$tempElement);
        if (preg_match('#<script(.*?)>(.*?)</script>#is',$tempElement) || preg_match('#<iframe(.*?)>(.*?)</iframe>#is',$tempElement) || (stripos($tempElement,"<link") !== false) ) {
          $element = "REMOVED";
        }
      }
    }
  }
}

function xmlToCommand($xml, $create_paths=false) {
  global $docroot, $var, $cfg, $driver;
  $xml           = xmlToVar($xml);
  $cmdName       = strlen($xml['Name']) ? '--name='.escapeshellarg($xml['Name']) : '';
  $cmdPrivileged = strtolower($xml['Privileged'])=='true' ? '--privileged=true' : '';
  $cmdNetwork    = preg_match('/\-\-net(work)?=/',$xml['ExtraParams']) ? "" : '--net='.escapeshellarg(strtolower($xml['Network']));
  $cmdMyIP       = '';
  foreach (explode(' ',str_replace(',',' ',$xml['MyIP'])) as $myIP) if ($myIP) $cmdMyIP .= (strpos($myIP,':')?'--ip6=':'--ip=').escapeshellarg($myIP).' ';
  $cmdCPUset     = strlen($xml['CPUset']) ? '--cpuset-cpus='.escapeshellarg($xml['CPUset']) : '';
  $Volumes       = [''];
  $Ports         = [''];
  $Variables     = [''];
  $Labels        = [''];
  $Devices       = [''];
  // Bind Time
  $Variables[]   = 'TZ="'.$var['timeZone'].'"';
  // Add HOST_OS variable
  $Variables[]   = 'HOST_OS="Unraid"';
  // Add HOST_HOSTNAME variable 
  $Variables[]   = 'HOST_HOSTNAME="'.$var['NAME'].'"';
  // Add HOST_CONTAINERNAME variable
  $Variables[]   = 'HOST_CONTAINERNAME="'.$xml['Name'].'"';
  // Docker labels for WebUI and Icon
  $Labels[]      = 'net.unraid.docker.managed=dockerman';
  if (strlen($xml['WebUI']))  $Labels[] = 'net.unraid.docker.webui='.escapeshellarg($xml['WebUI']);
  if (strlen($xml['Icon'])) $Labels[] = 'net.unraid.docker.icon='.escapeshellarg($xml['Icon']);

  foreach ($xml['Config'] as $key => $config) {
    $confType        = strtolower(strval($config['Type']));
    $hostConfig      = strlen($config['Value']) ? $config['Value'] : $config['Default'];
    $containerConfig = strval($config['Target']);
    $Mode            = strval($config['Mode']);
    if ($confType != "device" && !strlen($containerConfig)) continue;
    if ($confType == "path") {
      $Volumes[] = escapeshellarg($hostConfig).':'.escapeshellarg($containerConfig).':'.escapeshellarg($Mode);
      if (!file_exists($hostConfig) && $create_paths) {
        @mkdir($hostConfig, 0777, true);
        @chown($hostConfig, 99);
        @chgrp($hostConfig, 100);
      }
    } elseif ($confType == 'port') {
      switch ($driver[$xml['Network']]) {
      case 'host':
      case 'macvlan':
      case 'ipvlan':
        // Export ports as variable if network is set to host or macvlan or ipvlan
        $Variables[] = strtoupper(escapeshellarg($Mode.'_PORT_'.$containerConfig).'='.escapeshellarg($hostConfig));
        break;
      case 'bridge':
        // Export ports as port if network is set to (custom) bridge
        $Ports[] = escapeshellarg($hostConfig.':'.$containerConfig.'/'.$Mode);
        break;
      case 'none':
        // No export of ports if network is set to none
      }
    } elseif ($confType == "label") {
      $Labels[] = escapeshellarg($containerConfig).'='.escapeshellarg($hostConfig);
    } elseif ($confType == "variable") {
      $Variables[] = escapeshellarg($containerConfig).'='.escapeshellarg($hostConfig);
    } elseif ($confType == "device") {
      $Devices[] = escapeshellarg($hostConfig);
    }
  }
  $logSize = $logFile = '';
  if (($cfg['DOCKER_LOG_ROTATION']??'')=='yes') {
    $logSize = $cfg['DOCKER_LOG_SIZE'] ?? '10m';
    $logSize = "--log-opt max-size='$logSize'";
    $logFile = $cfg['DOCKER_LOG_FILES'] ?? '1';
    $logFile = "--log-opt max-file='$logFile'";
  }
  $cmd = sprintf($docroot.'/plugins/dynamix.docker.manager/scripts/docker create %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s',
         $cmdName, $cmdNetwork, $cmdMyIP, $cmdCPUset, $logSize, $logFile, $cmdPrivileged, implode(' -e ', $Variables), implode(' -l ', $Labels), implode(' -p ', $Ports), implode(' -v ', $Volumes), implode(' --device=', $Devices), $xml['ExtraParams'], escapeshellarg($xml['Repository']), $xml['PostArgs']);
  return [preg_replace('/\s\s+/', ' ', $cmd), $xml['Name'], $xml['Repository']];
}
function stopContainer($name, $t=10, $echo=true) {
  global $DockerClient;
  $waitID = mt_rand();
  if ($echo) {
    echo "<p class=\"logLine\" id=\"logBody\"></p>";
    echo "<script>addLog('<fieldset style=\"margin-top:1px;\" class=\"CMD\"><legend>"._('Stopping container').": ",addslashes(htmlspecialchars($name)),"</legend><p class=\"logLine\" id=\"logBody\"></p><span id=\"wait{$waitID}\">"._('Please wait')." </span></fieldset>');show_Wait($waitID);</script>\n";
    @flush();
  }
  $retval = $DockerClient->stopContainer($name, $t);
  $out = ($retval === true) ? _('Successfully stopped container')." '$name'" : _('Error').": ".$retval;
  if ($echo) {
    echo "<script>stop_Wait($waitID);addLog('<b>",addslashes(htmlspecialchars($out)),"</b>');</script>\n";
    @flush();
  }
}

function removeContainer($name, $cache=false, $echo=true) {
  global $DockerClient;
  $waitID = mt_rand();
  if ($echo) {
    echo "<p class=\"logLine\" id=\"logBody\"></p>";
    echo "<script>addLog('<fieldset style=\"margin-top:1px;\" class=\"CMD\"><legend>"._('Removing container').": ",addslashes(htmlspecialchars($name)),"</legend><p class=\"logLine\" id=\"logBody\"></p><span id=\"wait{$waitID}\">"._('Please wait')." </span></fieldset>');show_Wait($waitID);</script>\n";
    @flush();
  }
  $retval = $DockerClient->removeContainer($name, false, $cache);
  $out = ($retval === true) ? _('Successfully removed container')." '$name'" : _('Error').": ".$retval;
  if ($echo) {
    echo "<script>stop_Wait($waitID);addLog('<b>",addslashes(htmlspecialchars($out)),"</b>');</script>\n";
    @flush();
  }
}

function removeImage($image, $echo=true) {
  global $DockerClient;
  $waitID = mt_rand();
  if ($echo) {
    echo "<p class=\"logLine\" id=\"logBody\"></p>";
    echo "<script>addLog('<fieldset style=\"margin-top:1px;\" class=\"CMD\"><legend>"._('Removing orphan image').": ",addslashes(htmlspecialchars($image)),"</legend><p class=\"logLine\" id=\"logBody\"></p><span id=\"wait{$waitID}\">"._('Please wait')." </span></fieldset>');show_Wait($waitID);</script>\n";
    @flush();
  }
  $retval = $DockerClient->removeImage($image);
  $out = ($retval === true) ? _('Successfully removed orphan image')." '$image'" : _('Error').": ".$retval;
  if ($echo) {
    echo "<script>stop_Wait($waitID);addLog('<b>",addslashes(htmlspecialchars($out))."</b>');</script>\n";
    @flush();
  }
}

function pullImage($name, $image, $echo=true) {
  global $DockerClient, $DockerTemplates, $DockerUpdate;
  $waitID = mt_rand();
  if (!preg_match("/:\S+$/", $image)) $image .= ":latest";
  if ($echo) {
    echo "<p class=\"logLine\" id=\"logBody\"></p>";
    echo "<script>addLog('<fieldset style=\"margin-top:1px;\" class=\"CMD\"><legend>"._('Pulling image').": ",addslashes(htmlspecialchars($image)),"</legend><p class=\"logLine\" id=\"logBody\"></p><span id=\"wait{$waitID}\">"._('Please wait')." </span></fieldset>');show_Wait($waitID);</script>\n";
    @flush();
  }
  $alltotals = [];
  $laststatus = [];
  $strError = '';
  $DockerClient->pullImage($image, function ($line) use (&$alltotals, &$laststatus, &$waitID, &$strError, $image, $DockerClient, $DockerUpdate, $echo) {
    $cnt = json_decode($line, true);
    $id = $cnt['id'] ?? '';
    $status = $cnt['status'] ?? '';
    if (isset($cnt['error'])) $strError = $cnt['error'];
    if ($waitID !== false) {
      if ($echo) {
        echo "<script>stop_Wait($waitID);</script>\n";
        @flush();
      }
      $waitID = false;
    }
    if (empty($status)) return;
    if (!empty($id)) {
      if (!empty($cnt['progressDetail']) && !empty($cnt['progressDetail']['total'])) {
        $alltotals[$id] = $cnt['progressDetail']['total'];
      }
      if (empty($laststatus[$id])) {
        $laststatus[$id] = '';
      }
      switch ($status) {
      case 'Waiting':
        // Omit
        break;
      case 'Downloading':
        if ($laststatus[$id] != $status) {
          if ($echo) echo "<script>addToID('$id','",addslashes(htmlspecialchars($status)),"');</script>\n";
        }
        $total = $cnt['progressDetail']['total'];
        $current = $cnt['progressDetail']['current'];
        if ($total > 0) {
          $percentage = round(($current / $total) * 100);
          if ($echo) echo "<script>progress('$id',' ",$percentage,"% ",_('of')," ",$DockerClient->formatBytes($total),"');</script>\n";
        } else {
          // Docker must not know the total download size (http-chunked or something?)
          // just show the current download progress without the percentage
          $alltotals[$id] = $current;
          if ($echo) echo "<script>progress('$id',' ",$DockerClient->formatBytes($current),"');</script>\n";
        }
        break;
      default:
        if ($laststatus[$id] == "Downloading") {
          if ($echo) echo "<script>progress('$id',' 100% ",_('of')," ",$DockerClient->formatBytes($alltotals[$id]),"');</script>\n";
        }
        if ($laststatus[$id] != $status) {
          if ($echo) echo "<script>addToID('",($id=='latest'?mt_rand():$id),"','",addslashes(htmlspecialchars($status)),"');</script>\n";
        }
        break;
      }
      $laststatus[$id] = $status;
    } else {
      if (strpos($status, 'Status: ') === 0) {
        if ($echo) echo "<script>addLog('",addslashes(htmlspecialchars($status)),"');</script>\n";
      }
      if (strpos($status, 'Digest: ') === 0) {
        $DockerUpdate->setUpdateStatus($image, substr($status, 8));
      }
    }
    if ($echo) @flush();
  });
  if ($echo) {
    echo "<script>addLog('<br><b>",_('TOTAL DATA PULLED'),":</b> ",$DockerClient->formatBytes(array_sum($alltotals)),"');</script>\n";
    @flush();
  }
  if (!empty($strError)) {
    if ($echo) {
      echo "<script>addLog('<br><span class=\"error\"><b>",_('Error'),":</b> ",addslashes(htmlspecialchars($strError)),"</span>');</script>\n";
      @flush();
    }
    return false;
  }
  return true;
}

function execCommand($command, $echo=true) {
  $waitID = mt_rand();
  if ($echo) {
    [$cmd,$args] = explode(' ',$command,2);
    echo '<p class="logLine" id="logBody"></p>';
    echo '<script>addLog(\'<fieldset style="margin-top:1px;" class="CMD"><legend>',_('Command execution'),'</legend>';
    echo basename($cmd),' ',str_replace(" -","<br>&nbsp;&nbsp;-",addslashes(htmlspecialchars($args))),'<br>';
    echo '<span id="wait'.$waitID.'">',_('Please wait').' </span>';
    echo '<p class="logLine" id="logBody"></p></fieldset>\');show_Wait('.$waitID.');</script>';
    @flush();
  }
  $proc = popen("$command 2>&1",'r');
  while ($out = fgets($proc)) {
    $out = preg_replace("%[\t\n\x0B\f\r]+%", '', $out);
    if ($echo) {
      echo '<script>addLog("',htmlspecialchars($out),'");</script>';
      @flush();
    }
  }
  $retval = pclose($proc);
  if ($echo) echo '<script>stop_Wait('.$waitID.');</script>';
  $out = $retval ?  _('The command failed').'.' : _('The command finished successfully').'!';
  if ($echo) echo '<script>addLog(\'<br><b>',$out,'</b>\');</script>';
  return $retval===0;
}

function getXmlVal($xml, $element, $attr=null, $pos=0) {
  $xml = (is_file($xml)) ? simplexml_load_file($xml) : simplexml_load_string($xml);
  $element = $xml->xpath("//$element")[$pos];
  return isset($element) ? (isset($element[$attr]) ? strval($element[$attr]) : strval($element)) : "";
}

function setXmlVal(&$xml, $value, $el, $attr=null, $pos=0) {
  $xml = (is_file($xml)) ? simplexml_load_file($xml) : simplexml_load_string($xml);
  $element = $xml->xpath("//$el")[$pos];
  if (!isset($element)) $element = $xml->addChild($el);
  if ($attr) {
    $element[$attr] = $value;
  } else {
    $element->{0} = $value;
  }
  $dom = new DOMDocument('1.0');
  $dom->preserveWhiteSpace = false;
  $dom->formatOutput = true;
  $dom->loadXML($xml->asXML());
  $xml = $dom->saveXML();
}

function getAllocations() {
  global $DockerClient, $host;
  foreach ($DockerClient->getDockerContainers() as $ct) {
    $list = $port = [];
    $nat = $ip = false;
    $list['Name'] = $ct['Name'];
    foreach ($ct['Ports'] as $tmp) {
      $nat = $tmp['NAT'];
      $ip = $tmp['IP'];
      $port[] = $tmp['PublicPort'];
    }
    sort($port);
    $ip = $ct['NetworkMode']=='host'||$nat ? $host : ($ip ?: DockerUtil::myIP($ct['Name']) ?: '0.0.0.0');
    $list['Port'] = "<span class='net'>{$ct['NetworkMode']}</span><span class='ip'>$ip</span>".(implode(', ',array_unique($port)) ?: '???');
    $ports[] = $list;
  }
  return $ports;
}

function getCurlHandle($url, $method='GET') {
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
  curl_setopt($ch, CURLOPT_TIMEOUT, 45);
  curl_setopt($ch, CURLOPT_ENCODING, "");
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  curl_setopt($ch, CURLOPT_REFERER, "");
  if ($method === 'HEAD') {
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD');
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_NOBODY, true);
  }
  return $ch;
}
?>
