Save OpenAI API token to .env file
()
| 19258 | file_size = os.path.getsize(actual_path) |
| 19259 | ext = os.path.splitext(actual_path)[1].lower() |
| 19260 | |
| 19261 | TEXT_EXTENSIONS = {'.txt', '.log', '.csv', '.json', '.xml', '.yaml', '.yml', |
| 19262 | '.md', '.conf', '.cfg', '.ini', '.nmap', '.gnmap', '.sh', '.py'} |
| 19263 | IMAGE_EXTENSIONS = {'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp', '.svg'} |
| 19264 | |
| 19265 | if ext in IMAGE_EXTENSIONS: |
| 19266 | if file_size > 5 * 1024 * 1024: # 5MB limit for images |
| 19267 | return jsonify({'type': 'too_large', 'size': file_size, 'name': os.path.basename(actual_path)}) |
| 19268 | with open(actual_path, 'rb') as f: |
| 19269 | data = base64.b64encode(f.read()).decode('ascii') |
| 19270 | return jsonify({'type': 'image', 'mime': mime_type, 'data': data, 'name': os.path.basename(actual_path)}) |
| 19271 | |
| 19272 | elif ext in TEXT_EXTENSIONS or (mime_type and mime_type.startswith('text/')): |
| 19273 | if file_size > 512 * 1024: # 512KB limit for text |
| 19274 | # Return first 512KB with truncation notice |
| 19275 | with open(actual_path, 'r', encoding='utf-8', errors='replace') as f: |
| 19276 | content = f.read(512 * 1024) |
| 19277 | return jsonify({'type': 'text', 'content': content, 'truncated': True, |
| 19278 | 'size': file_size, 'name': os.path.basename(actual_path)}) |
| 19279 | with open(actual_path, 'r', encoding='utf-8', errors='replace') as f: |
| 19280 | content = f.read() |
| 19281 | return jsonify({'type': 'text', 'content': content, 'truncated': False, |
| 19282 | 'size': file_size, 'name': os.path.basename(actual_path)}) |
| 19283 | else: |
| 19284 | return jsonify({'type': 'binary', 'mime': mime_type, |
| 19285 | 'size': file_size, 'name': os.path.basename(actual_path)}) |
| 19286 | |
| 19287 | except Exception as e: |
| 19288 | logger.error(f"Error previewing file: {e}") |
| 19289 | return jsonify({'error': str(e)}), 500 |
| 19290 | |
| 19291 | |
| 19292 | @app.route('/api/files/download') |
| 19293 | def download_file_api(): |
| 19294 | """Download a file""" |
| 19295 | try: |
| 19296 | file_path = request.args.get('path') |
| 19297 | if not file_path: |
| 19298 | return jsonify({'error': 'File path required'}), 400 |
| 19299 | |
| 19300 | # Map virtual path to actual path |
| 19301 | actual_path = "" |
| 19302 | if file_path.startswith('/data_stolen'): |
| 19303 | resolved = _resolve_loot_path('/data_stolen', 'loot/data_stolen', file_path) |
| 19304 | if resolved is None: |
| 19305 | return jsonify({'error': 'Invalid file path'}), 400 |
| 19306 | actual_path = resolved |
| 19307 | elif file_path.startswith('/scan_results'): |
| 19308 | resolved = _resolve_loot_path('/scan_results', 'output/scan_results', file_path) |
| 19309 | if resolved is None: |
| 19310 | return jsonify({'error': 'Invalid file path'}), 400 |
| 19311 | actual_path = resolved |
| 19312 | elif file_path.startswith('/crackedpwd'): |
| 19313 | resolved = _resolve_loot_path('/crackedpwd', 'loot/credentials', file_path) |
| 19314 | if resolved is None: |
| 19315 | return jsonify({'error': 'Invalid file path'}), 400 |
| 19316 | actual_path = resolved |
| 19317 | elif file_path.startswith('/vulnerabilities'): |
nothing calls this directly
no test coverage detected