From 38f516e550b1fcffd43a15007d04f53cbbc87db6 Mon Sep 17 00:00:00 2001
From: Zjmainstay <admin@zjmainstay.cn>
Date: Thu, 14 Dec 2023 17:17:18 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=A0=BC=E5=BC=8F=E5=8C=96he?=
 =?UTF-8?q?ader=E5=A4=B4cookie=E6=88=90=E6=96=87=E4=BB=B6=E5=AD=98?=
 =?UTF-8?q?=E5=82=A8=E6=A0=BC=E5=BC=8F=E6=96=B9=E6=B3=95=EF=BC=9AformatHea?=
 =?UTF-8?q?derCookieToFileContent=EF=BC=9B=E5=A2=9E=E5=8A=A0cookie?=
 =?UTF-8?q?=E6=96=87=E4=BB=B6=E8=87=AA=E5=8A=A8=E6=B8=85=E7=90=86=EF=BC=9B?=
 =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=BB=93=E6=9D=9Fcookie=E6=96=87=E4=BB=B6?=
 =?UTF-8?q?=E6=B8=85=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/CurlAutoLogin.php | 74 ++++++++++++++++++++++++++++++++++++-------
 1 file changed, 63 insertions(+), 11 deletions(-)

diff --git a/src/CurlAutoLogin.php b/src/CurlAutoLogin.php
index 7d0c59f..dd7140d 100644
--- a/src/CurlAutoLogin.php
+++ b/src/CurlAutoLogin.php
@@ -19,8 +19,11 @@ class CurlAutoLogin {
     protected $globalOpts = [];
     //最后一次请求参数,用于重放请求
     protected $lastExecParams = [];
+    //程序完全退出时,清理cookie文件避免文件堆积
+    protected $removeCookieFileAtDestruct = false;
 
-    public function __construct($logPath = '') {
+    public function __construct($logPath = '', $removeCookieFileAtDestruct = false) {
+        $this->removeCookieFileAtDestruct = $removeCookieFileAtDestruct;
         if(!empty($logPath) && is_writable($logPath)) {
             $this->logPath = $logPath;
         } else {
@@ -33,6 +36,15 @@ public function __construct($logPath = '') {
         }
     }
 
+    //程序退出销毁处理
+    public function __destruct()
+    {
+        //如果设置了清理cookie文件
+        if($this->removeCookieFileAtDestruct && file_exists($this->getLastCookieFile())) {
+            unlink($this->getLastCookieFile());
+        }
+    }
+
     /**
      * 设置全局请求opt(方便使用代理之类的请求)
      * @param $opts
@@ -127,7 +139,7 @@ public function unsetLastExecParams()
      */
     public function parseCurl($curlContent) {
         if(!preg_match("#curl '([^']*)'#is", $curlContent, $matchUrl)
-        && !preg_match("#curl.*'([^']*)'\s*$#is", $curlContent, $matchUrl)
+            && !preg_match("#curl.*'([^']*)'\s*$#is", $curlContent, $matchUrl)
         ) {
             return false;
         }
@@ -199,13 +211,12 @@ protected function _execCurl($parseCurlResult) {
         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
 
         //add cookie support
-        //设置一个不存在的目录以在系统临时目录随机生成一个缓存文件,避免多进程cookie覆盖
-        $cookieFile = tempnam('/not_exist_dir/', 'autologin');
+        $cookieFile = $this->getTempFile();
         curl_setopt($ch,CURLOPT_COOKIEJAR,$cookieFile); //存储提交后得到的cookie数据
 
         //add previous curl cookie
-        if(!empty($this->lastCookieFile)) {
-            curl_setopt($ch,CURLOPT_COOKIEFILE, $this->lastCookieFile); //使用提交后得到的cookie数据
+        if($this->getLastCookieFile()) {
+            curl_setopt($ch,CURLOPT_COOKIEFILE, $this->getLastCookieFile()); //使用提交后得到的cookie数据
         }
 
         //add post data support
@@ -286,23 +297,49 @@ public function getLastCookieContent() {
 
     /**
      * 手动追加cookie内容到最后一次存储的cookie文件
-     * @param $content
+     * @param string $content
+     * @param bool $init
      * @return bool|int
      */
-    public function appendCookieContent($content)
+    public function appendCookieContent($content, $init = true)
     {
-        if(file_exists($file = $this->getLastCookieFile())) {
+        if(file_exists($file = $this->getLastCookieFile()) || $init) {
+            //初始cookie文件
+            if(empty($file)) {
+                $file = $this->getTempFile();
+                if(!$file) {
+                    return false;
+                }
+                $this->setLastCookieFile($file);
+            }
             return file_put_contents($file, $content . "\n", FILE_APPEND);
         }
         return false;
     }
 
+    /**
+     * 获取临时文件
+     * @return false|string
+     */
+    public function getTempFile() {
+        $file = tempnam(dirname($this->logPath), 'autologin_cookie_');
+        if(!$file) {
+            $this->_log("tempnam创建临时文件失败,请检查");
+            return false;
+        }
+        return $file;
+    }
+
     /**
      * 设置上一次存储cookie的文件
      * @param [type] $cookieFile [description]
      */
     public function setLastCookieFile($cookieFile) {
         if(!$this->lockedLastCookieFile) {
+            //移除上一个存储cookie的临时文件
+            if(file_exists($this->lastCookieFile) && $this->lastCookieFile != $cookieFile) {
+                unlink($this->lastCookieFile);
+            }
             $this->lastCookieFile = $cookieFile;
         }
         return $this;
@@ -367,7 +404,7 @@ public function getUrl($url, $header = false, $opts = []) {
         //add 302 support
         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
 
-        curl_setopt($ch,CURLOPT_COOKIEFILE, $this->lastCookieFile); //使用提交后得到的cookie数据
+        curl_setopt($ch,CURLOPT_COOKIEFILE, $this->getLastCookieFile()); //使用提交后得到的cookie数据
 
         //extend opt
         $opts += $this->globalOpts;
@@ -423,7 +460,7 @@ public function postUrl($url, $postData = false, $header = false, $opts = []) {
         //add 302 support
         curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
 
-        curl_setopt($ch,CURLOPT_COOKIEFILE, $this->lastCookieFile); //使用提交后得到的cookie数据
+        curl_setopt($ch,CURLOPT_COOKIEFILE, $this->getLastCookieFile()); //使用提交后得到的cookie数据
 
         //add post data support
         curl_setopt($ch,CURLOPT_POST, 1);
@@ -481,4 +518,19 @@ public function getLineBreak() {
 
         return $lineBreak;
     }
+
+    /**
+     * 格式化header头cookie成文件存储格式
+     * @param string $headerCookie //-H 'Cookie: xxxxx=xxxx;',单引号内容
+     * @param string $domain //授权域名,如www.baidu.com,则传入.baidu.com,根前面有个点
+     */
+    public function formatHeaderCookieToFileContent($headerCookie, $domain) {
+        $rows = [];
+        if(preg_match_all("#([^ ;]+)=([^ ;]+)#i", $headerCookie, $matches)) {
+            foreach($matches[0] as $key => $value) {
+                $rows[] = sprintf("#HttpOnly_%s\tTRUE\t/\tFALSE\t0\t%s\t%s", $domain, $matches[1][$key], $matches[2][$key]);
+            }
+        }
+        return implode("\n", $rows);
+    }
 }