{"version":3,"sources":["jsdelivr-header.js","/npm/ppg@0.3.1/lib/ppg.js"],"names":[],"mappings":"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","file":"/npm/ppg@0.3.1/lib/ppg.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/ppg@0.3.1/lib/ppg.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","'use strict';\n\nvar path = require('path');\nvar express = require('express');\nvar http = require('http');\nvar socketio = require('socket.io');\nvar sampServer = require('samp-server');\nvar pawnCompiler = require('samp-server/lib/pawn-compiler');\nvar wineProxy = require('samp-server/lib/wine-proxy');\nvar AMX = require('./amx');\nvar fs = require('fs');\nvar async = require('async');\nvar pstree = require('./pstree');\nvar cors = require('cors');\n\nvar app = express();\napp.use(cors());\nvar server = http.createServer(app);\nvar io = socketio(server);\n\nvar DISABLED_NATIVES = [\n  'SendRconCommand', 'sendstring', 'sendpacket', 'listenport'\n];\n\nvar ALLOWED_COMPILER_FLAGS = [\n  'dataAlignment', 'outputAsm', 'compactEncoding', 'codepage', 'debugLevel',\n  'optimizationLevel', 'stackHeapSize', 'skipLines', 'tabsize',\n  'verbosityLevel', 'disableWarning', 'requireSemicolons',\n  'requireParentheses'\n];\n\nvar reStripNonPrintable = /[^\\x20-\\x7E]/;\n\napp.start = app.listen = function() {\n  return server.listen.apply(server, arguments);\n};\n\nvar serverBinary, windowsBinary, activeServers = 0, activePlugins = [];\n\nvar isWindows = (process.platform === 'win32');\n\nif (process.platform === 'win32' || process.platform === 'darwin') {\n  windowsBinary = true;\n  serverBinary = 'samp-server.exe';\n} else {\n  windowsBinary = false;\n  serverBinary = 'samp03svr';\n}\n\nfs.readdirSync('plugins').forEach(function(file) {\n  var ext = path.extname(file).toLowerCase();\n\n  file = path.resolve('plugins', file);\n\n  if (!windowsBinary && ext === '.so') {\n    activePlugins.push(file);\n  } else if (windowsBinary && ext === '.dll') {\n    activePlugins.push(file);\n  }\n});\n\nserverBinary = path.resolve(__dirname, '..', 'bin', 'server', serverBinary);\n\napp.use(express.static('public'));\n\nvar operations = [];\n\nvar includePath = path.resolve('include').replace(/[\\/\\\\]+$/, '');\n\nif (!isWindows && windowsBinary) {\n  operations.push(function(fn) {\n    wineProxy.convertPath('w', includePath, function(err, path) {\n      if (err) return fn(err);\n\n      includePath = path.replace(/[\\/\\\\]+$/, '');\n\n      fn(null);\n    });\n  });\n}\n\nasync.series(operations, function(err) {\n  if (err) throw err;\n\n  app.start(7070);\n});\n\nfunction compilerFlagOverrides(info, socket, flags) {\n  var reCompilerFlag = /^\\/\\/@pawncc (\\w+)\\s*=\\s*(\\S+)\\s*$/gm;\n  var match;\n\n  while ((match=reCompilerFlag.exec(info.code))) {\n    var key = match[1];\n    var value = match[2];\n\n    if (ALLOWED_COMPILER_FLAGS.indexOf(key) === -1) {\n      socket.emit('compiler-output', {\n        runId: info.runId,\n        data: 'Notice: Compiler option not in whitelist: ' + key + '\\n'\n      });\n    }\n\n    try {\n      value = JSON.parse(value);\n    } catch (e) {\n      continue;\n    }\n\n    if (['string', 'number', 'boolean'].indexOf(typeof value) === -1) {\n      continue;\n    }\n\n    flags[key] = value;\n  }\n\n  return flags;\n}\n\nio.sockets.on('connection', function(socket) {\n  var activeServer = null;\n  var activeRunId = null;\n  var isCompiling = false;\n\n  socket.on('compile-lst', function(info) {\n    if (isCompiling) {\n      socket.emit('compiler-output', {\n        runId: info.runId,\n        data: 'Error: A compiler process is running. Please wait a couple seconds.'\n      });\n\n      return;\n    }\n\n    if (activeServer && activeServer.term && activeServer.term.pid) {\n      pstree.kill(activeServer.term.pid, function(err) {});\n\n      activeServer = null;\n    }\n\n    activeRunId = info.runId;\n    isCompiling = true;\n\n    var flags = compilerFlagOverrides(info, socket, {\n      debugLevel: 2,\n      requireSemicolons: true,\n      requireParentheses: true,\n      tabsize: 4,\n      includeDirectory: 'include',\n      outputLst: true,\n      outputMacros: true\n    });\n\n    pawnCompiler.compile(new Buffer('' + info.code), flags, function(err, errors, outputFile, otherErrors, macroReplacements) {\n      isCompiling = false;\n\n      if (info.runId !== activeRunId) {\n        return;\n      }\n\n      if (errors && errors.length) {\n        errors.forEach(function(error) {\n          error.file = 'input';\n        });\n\n        errors = errors.filter(function(error) {\n          if (error.message === 'symbol is never used: \"TODO\"') {\n            return false;\n          }\n\n          return true;\n        });\n\n        socket.emit('compiler-output', {\n          runId: info.runId,\n          data: errors.join('\\n') + '\\n'\n        });\n\n        socket.emit('compiler-errors', {\n          runId: info.runId,\n          data: errors\n        });\n      }\n\n      if (otherErrors && otherErrors.length) {\n        socket.emit('compiler-output', {\n          runId: info.runId,\n          data: otherErrors.join('\\n') + '\\n'\n        });\n      }\n\n      if (err) {\n        socket.emit('compiler-output', {\n          runId: info.runId,\n          failed: true,\n          data: 'Error: ' + err.message +\n                ' (' + (err.code || 'no error code') + ')\\n'\n        });\n\n        return;\n      }\n\n      fs.readFile(outputFile, {\n        encoding: 'utf-8'\n      }, function(err, data) {\n        var pos = data.lastIndexOf('#file \"' + outputFile.replace(/\\.lst$/, '.pwn') + '\"');\n\n        if (pos === -1) {\n          socket.emit('compiler-output', {\n            runId: info.runId,\n            failed: true,\n            data: 'Error: Unexpected output.'\n          });\n\n          return;\n        }\n\n        data = data.substr(pos + 9 + outputFile.length);\n\n        macroReplacements = macroReplacements.filter(function(repl) {\n          return (repl.file === 'input');\n        });\n\n        socket.emit('compiler-lst', {\n          runId: info.runId,\n          data: data,\n          macroReplacements: macroReplacements\n        });\n      });\n    });\n  });\n\n  socket.on('compile-asm', function(info) {\n    if (isCompiling) {\n      socket.emit('compiler-output', {\n        runId: info.runId,\n        data: 'Error: A compiler process is running. Please wait a couple seconds.'\n      });\n\n      return;\n    }\n\n    if (activeServer && activeServer.term && activeServer.term.pid) {\n      pstree.kill(activeServer.term.pid, function(err) {});\n\n      activeServer = null;\n    }\n\n    activeRunId = info.runId;\n    isCompiling = true;\n\n    var flags = compilerFlagOverrides(info, socket, {\n      debugLevel: 2,\n      requireSemicolons: true,\n      requireParentheses: true,\n      tabsize: 4,\n      includeDirectory: 'include',\n      outputAsm: true,\n      outputMacros: true\n    });\n\n    pawnCompiler.compile(new Buffer('' + info.code), flags, function(err, errors, outputFile, otherErrors, macroReplacements) {\n      isCompiling = false;\n\n      if (info.runId !== activeRunId) {\n        return;\n      }\n\n      if (errors && errors.length) {\n        errors.forEach(function(error) {\n          error.file = 'input';\n        });\n\n        errors = errors.filter(function(error) {\n          if (error.message === 'symbol is never used: \"TODO\"') {\n            return false;\n          }\n\n          return true;\n        });\n\n        socket.emit('compiler-output', {\n          runId: info.runId,\n          data: errors.join('\\n') + '\\n'\n        });\n\n        socket.emit('compiler-errors', {\n          runId: info.runId,\n          data: errors\n        });\n      }\n\n      if (otherErrors && otherErrors.length) {\n        socket.emit('compiler-output', {\n          runId: info.runId,\n          data: otherErrors.join('\\n') + '\\n'\n        });\n      }\n\n      if (err) {\n        socket.emit('compiler-output', {\n          runId: info.runId,\n          failed: true,\n          data: 'Error: ' + err.message +\n                ' (' + (err.code || 'no error code') + ')\\n'\n        });\n\n        return;\n      }\n\n      fs.readFile(outputFile, {\n        encoding: 'utf-8'\n      }, function(err, data) {\n        var pos = data.lastIndexOf('; file ' + outputFile.replace(/\\.asm$/, '.pwn'));\n\n        if (pos === -1) {\n          socket.emit('compiler-output', {\n            runId: info.runId,\n            failed: true,\n            data: 'Error: Unexpected output.'\n          });\n\n          return;\n        }\n\n        data = data.substr(pos + 8 + outputFile.length);\n\n        socket.emit('compiler-asm', {\n          runId: info.runId,\n          data: data\n        });\n      });\n    });\n  });\n\n  socket.on('run-code', function(info) {\n    if (activeServers > 20) {\n      socket.emit('compiler-output', {\n        runId: info.runId,\n        failed: true,\n        data: 'Error: Too many active servers. Please wait.'\n      });\n\n      return;\n    }\n\n    if (isCompiling) {\n      socket.emit('compiler-output', {\n        runId: info.runId,\n        failed: true,\n        data: 'Error: A compiler process is running. Please wait a couple seconds.'\n      });\n\n      return;\n    }\n\n    if (activeServer && activeServer.term && activeServer.term.pid) {\n      pstree.kill(activeServer.term.pid, function(err) {});\n\n      activeServer = null;\n    }\n\n    activeRunId = info.runId;\n    isCompiling = true;\n\n    var flags = compilerFlagOverrides(info, socket, {\n      debugLevel: 2,\n      requireSemicolons: true,\n      requireParentheses: true,\n      tabsize: 4,\n      includeDirectory: 'include'\n    });\n\n    pawnCompiler.compile(new Buffer('' + info.code), flags, function(err, errors, outputFile, otherErrors) {\n      isCompiling = false;\n\n      if (info.runId !== activeRunId) {\n        return;\n      }\n\n      if (errors && errors.length) {\n        errors.forEach(function(error) {\n          error.file = 'input';\n        });\n\n        errors = errors.filter(function(error) {\n          if (error.message === 'symbol is never used: \"TODO\"') {\n            return false;\n          }\n\n          return true;\n        });\n\n        socket.emit('compiler-output', {\n          runId: info.runId,\n          data: errors.join('\\n') + '\\n'\n        });\n\n        socket.emit('compiler-errors', {\n          runId: info.runId,\n          data: errors\n        });\n      }\n\n      if (otherErrors && otherErrors.length) {\n        socket.emit('compiler-output', {\n          runId: info.runId,\n          data: otherErrors.join('\\n') + '\\n'\n        });\n      }\n\n      if (err) {\n        socket.emit('compiler-output', {\n          runId: info.runId,\n          failed: true,\n          data: 'Error: ' + err.message +\n                ' (' + (err.code || 'no error code') + ')\\n'\n        });\n\n        return;\n      }\n\n      // TODO: async\n      var amx = new AMX(fs.readFileSync(outputFile)), disabled = [];\n\n      amx.header.natives.forEach(function(f) {\n        if (DISABLED_NATIVES.indexOf(f.name) !== -1) {\n          disabled.push(f.name);\n          f.name = 'random';\n        }\n      });\n\n      if (disabled.length) {\n        socket.emit('server-output', {\n          runId: info.runId,\n          data: '\\nWarning: Disabled native function(s) used: ' +\n                disabled.join(', ') + '.\\n\\n'\n        });\n      }\n\n      var inputBasename = path.basename(outputFile, '.amx') + '.pwn';\n\n      if (amx.debug) {\n        amx.debug.files.forEach(function(file) {\n          if (file.name.replace(/.+[\\/\\\\]/, '') === inputBasename) {\n            file.name = 'input.pwn';\n          } else {\n            file.name = file.name.replace(includePath, 'include');\n          }\n\n          file.name = file.name.replace(/\\\\/g, '/');\n        });\n      }\n\n      amx = amx.build();\n\n      // TODO: async\n      fs.writeFileSync(outputFile, amx);\n\n      sampServer.tempServer(\n        outputFile, {\n          binary: serverBinary,\n          plugins: activePlugins,\n          maxLogSize: 10240,\n          filterscripts: [\n            path.resolve(__dirname, '..', 'bin', 'server', 'fix_OnRconCommand')\n          ]\n        }, function(err, server) {\n          if (err) {\n            socket.emit('server-output', {\n              runId: info.runId,\n              data: 'Error: ' + err.message + ' ( ' + err.code + ')\\n'\n            });\n\n            return;\n          }\n\n          var beginOutput = false, onlyBlank = true;\n\n          activeServers++;\n          activeServer = server;\n\n          var killServer = function () {\n            if (server && server.term && server.term.pid) {\n              pstree.kill(server.term.pid, function(err) {});\n            }\n          };\n\n          var disconnectCallback = function() {\n            killServer();\n          };\n\n          socket.on('disconnect', disconnectCallback);\n\n          var killTimeout = setTimeout(function() {\n            killTimeout = null;\n\n            killServer();\n          }, 120000);\n\n          var outputLines = 0;\n\n          var runLineCallback = function(lineInfo) {\n            if (lineInfo.runId !== info.runId) {\n              return;\n            }\n\n            var code = lineInfo.code.replace(reStripNonPrintable, '');\n\n            socket.emit('server-output', {\n              runId: info.runId,\n              data: '> ' + code + '\\n'\n            });\n\n            server.send('runcode ' + code);\n          };\n\n          socket.on('run-line', runLineCallback);\n\n          var stopRunCallback = function() {\n            killServer();\n          };\n\n          socket.on('stop-run', stopRunCallback);\n\n          fs.writeFile(\n            path.join(server.cwd, 'scriptfiles', 'ppg-gm.amx'),\n            amx,\n            function(err) {\n              server.start();\n            }\n          );\n\n          server\n            .on('error', function(err) {\n              if (err.code === 'EIO') {\n                return;\n              }\n\n              socket.emit('server-output', {\n                runId: info.runId,\n                data: 'Error: ' + err.message + (\n                  err.code ? ' (' + err.code + ')\\n' : '\\n'\n                )\n              });\n            })\n            .on('output', function(data) {\n              if (outputLines++ > 10000) {\n                if (outputLines > 10001) {\n                  return;\n                }\n\n                try {\n                  server.logTail.pause();\n                  server.logTail.close();\n                  pstree.kill(server.child.pid, function(err) {});\n                } catch (e) {}\n\n                socket.emit('server-output', {\n                  runId: info.runId,\n                  data: '\\n\\nError: Output limit exceeded\\n'\n                });\n\n                return;\n              }\n\n              if (data.indexOf('Number of vehicle models') !== -1) {\n                return;\n              }\n\n              if (!beginOutput) {\n                if (data.indexOf('Loaded 1 filterscripts.') !== -1) {\n                  beginOutput = true;\n\n                  socket.emit('server-output', {\n                    runId: info.runId,\n                    data: 'Server started.\\n\\n'\n                  });\n                }\n\n                return;\n              }\n\n              if (onlyBlank) {\n                if (data.trim().length) {\n                  onlyBlank = false;\n                } else {\n                  return;\n                }\n              }\n\n              socket.emit('server-output', {\n                runId: info.runId,\n                data: data.replace(/\\r/g, '') + '\\n'\n              });\n            })\n            .on('stop', function(timeout) {\n              socket.removeListener('run-line', runLineCallback);\n              socket.removeListener('stop-run', stopRunCallback);\n              socket.removeListener('disconnect', disconnectCallback);\n\n              activeServers--;\n\n              var msg = '\\nServer stopped.';\n\n              if (killTimeout !== null) {\n                clearTimeout(killTimeout);\n              } else {\n                msg = '\\nServer killed (max time exceeded).';\n              }\n\n              socket.emit('server-output', {\n                runId: info.runId,\n                data: msg\n              });\n\n              socket.emit('server-stopped', {\n                runId: info.runId\n              });\n            });\n        }\n      );\n    });\n  });\n});\n"]}