From 9a9c076554e179a1ff04abb9f958c3b9e1e3b0c0 Mon Sep 17 00:00:00 2001
From: "yuanqin.wyq" <yuanqin.wyq@antfin.com>
Date: Mon, 18 Mar 2019 20:35:14 +0800
Subject: [PATCH] fix: prevent path crossing #391

fix: compatibility with node version
---
 lib/recorder.js     | 101 ++++++++++++++++++++++++++------------------
 lib/webInterface.js |   2 +-
 2 files changed, 62 insertions(+), 41 deletions(-)

diff --git a/lib/recorder.js b/lib/recorder.js
index 1a37739..7e1049d 100644
--- a/lib/recorder.js
+++ b/lib/recorder.js
@@ -126,12 +126,12 @@ class Recorder extends events.EventEmitter {
   *
   */
   updateRecordWsMessage(id, message) {
-    const cachePath = this.cachePath;
     if (id < 0) return;
     try {
-      const recordWsMessageFile = path.join(cachePath, WS_MESSAGE_FILE_PRFIX + id);
-
-      fs.appendFile(recordWsMessageFile, wsMessageStingify(message) + ',', () => {});
+      this.getCacheFile(WS_MESSAGE_FILE_PRFIX + id, (err, recordWsMessageFile) => {
+        if (err) return;
+        fs.appendFile(recordWsMessageFile, wsMessageStingify(message) + ',', () => {});
+      });
     } catch (e) {
       console.error(e);
       logUtil.error(e.message + e.stack);
@@ -172,15 +172,16 @@ class Recorder extends events.EventEmitter {
 
   updateRecordBody(id, info) {
     const self = this;
-    const cachePath = self.cachePath;
 
     if (id === -1) return;
 
     if (!id || typeof info.resBody === 'undefined') return;
     //add to body map
     //ignore image data
-    const bodyFile = path.join(cachePath, BODY_FILE_PRFIX + id);
-    fs.writeFile(bodyFile, info.resBody, () => {});
+    self.getCacheFile(BODY_FILE_PRFIX + id, (err, bodyFile) => {
+      if (err) return;
+      fs.writeFile(bodyFile, info.resBody, () => {});
+    });
   }
 
   /**
@@ -189,19 +190,23 @@ class Recorder extends events.EventEmitter {
   */
   getBody(id, cb) {
     const self = this;
-    const cachePath = self.cachePath;
 
     if (id < 0) {
       cb && cb('');
+      return;
     }
-
-    const bodyFile = path.join(cachePath, BODY_FILE_PRFIX + id);
-    fs.access(bodyFile, fs.F_OK || fs.R_OK, (err) => {
-      if (err) {
-        cb && cb(err);
-      } else {
-        fs.readFile(bodyFile, cb);
+    self.getCacheFile(BODY_FILE_PRFIX + id, (error, bodyFile) => {
+      if (error) {
+        cb && cb(error);
+        return;
       }
+      fs.access(bodyFile, fs.F_OK || fs.R_OK, (err) => {
+        if (err) {
+          cb && cb(err);
+        } else {
+          fs.readFile(bodyFile, cb);
+        }
+      });
     });
   }
 
@@ -270,36 +275,39 @@ class Recorder extends events.EventEmitter {
   *
   */
   getDecodedWsMessage(id, cb) {
-    const self = this;
-    const cachePath = self.cachePath;
-
     if (id < 0) {
       cb && cb([]);
+      return;
     }
 
-    const wsMessageFile = path.join(cachePath, WS_MESSAGE_FILE_PRFIX + id);
-    fs.access(wsMessageFile, fs.F_OK || fs.R_OK, (err) => {
-      if (err) {
-        cb && cb(err);
-      } else {
-        fs.readFile(wsMessageFile, 'utf8', (error, content) => {
-          if (error) {
-            cb && cb(err);
-          }
-
-          try {
-            // remove the last dash "," if it has, since it's redundant
-            // and also add brackets to make it a complete JSON structure
-            content = `[${content.replace(/,$/, '')}]`;
-            const messages = JSON.parse(content);
-            cb(null, messages);
-          } catch (e) {
-            console.error(e);
-            logUtil.error(e.message + e.stack);
-            cb(e);
-          }
-        });
+    this.getCacheFile(WS_MESSAGE_FILE_PRFIX + id, (outError, wsMessageFile) => {
+      if (outError) {
+        cb && cb(outError);
+        return;
       }
+      fs.access(wsMessageFile, fs.F_OK || fs.R_OK, (err) => {
+        if (err) {
+          cb && cb(err);
+        } else {
+          fs.readFile(wsMessageFile, 'utf8', (error, content) => {
+            if (error) {
+              cb && cb(err);
+            }
+
+            try {
+              // remove the last dash "," if it has, since it's redundant
+              // and also add brackets to make it a complete JSON structure
+              content = `[${content.replace(/,$/, '')}]`;
+              const messages = JSON.parse(content);
+              cb(null, messages);
+            } catch (e) {
+              console.error(e);
+              logUtil.error(e.message + e.stack);
+              cb(e);
+            }
+          });
+        }
+      });
     });
   }
 
@@ -330,6 +338,19 @@ class Recorder extends events.EventEmitter {
     const self = this;
     proxyUtil.deleteFolderContentsRecursive(self.cachePath, true);
   }
+
+  getCacheFile(fileName, cb) {
+    const self = this;
+    const cachePath = self.cachePath;
+    const filepath = path.join(cachePath, fileName);
+
+    if (filepath.indexOf(cachePath) !== 0) {
+      cb && cb(new Error('invalid cache file path'));
+    } else {
+      cb && cb(null, filepath);
+      return filepath;
+    }
+  }
 }
 
 module.exports = Recorder;
diff --git a/lib/webInterface.js b/lib/webInterface.js
index f450221..9620663 100644
--- a/lib/webInterface.js
+++ b/lib/webInterface.js
@@ -161,7 +161,7 @@ class webInterface extends events.EventEmitter {
           }
         });
       } else {
-        res.end({});
+        res.end('');
       }
     });