#include "exploit_cli.h" // Login command implementation int cmd_login(int argc, char *argv[]) { if (argc < 3) { printf("\033[33m📝 Usage: exp login \033[0m\n"); return 1; } const char *username = argv[1]; const char *password = argv[2]; printf("\033[36m╔══════════════════════════════════════╗\033[0m\n"); printf("\033[36m║ 🔐 Login Process ║\033[0m\n"); printf("\033[36m╚══════════════════════════════════════╝\033[0m\n"); print_progress("Authenticating with exploit.or.id..."); // Create JSON for login request char json_data[MAX_BUFFER]; snprintf(json_data, MAX_BUFFER, "{\"username\":\"%s\",\"password\":\"%s\"}", username, password); // Create URL for login char url[MAX_PATH]; snprintf(url, MAX_PATH, "%s/auth/login", API_BASE_URL); // Send login request http_response_t response = http_post(url, NULL, json_data); if (!response.data) { print_error("Failed to make login request"); return 1; } // Parse JSON response struct json_object *parsed_json; struct json_object *status_obj; struct json_object *message_obj; struct json_object *data_obj; struct json_object *token_obj; parsed_json = json_tokener_parse(response.data); if (!parsed_json) { print_error("Failed to parse JSON response"); free(response.data); return 1; } // Check response status json_object_object_get_ex(parsed_json, "status", &status_obj); json_object_object_get_ex(parsed_json, "message", &message_obj); const char *status = json_object_get_string(status_obj); const char *message = json_object_get_string(message_obj); if (strcmp(status, "success") != 0) { print_error(message); json_object_put(parsed_json); free(response.data); return 1; } // Get token json_object_object_get_ex(parsed_json, "data", &data_obj); json_object_object_get_ex(data_obj, "token", &token_obj); const char *token = json_object_get_string(token_obj); // Save token save_token(token); // Save username to configuration file char config_path[MAX_PATH]; snprintf(config_path, MAX_PATH, "%s/config", get_config_dir()); FILE *fp = fopen(config_path, "w"); if (fp) { fprintf(fp, "username=%s\n", username); fclose(fp); } printf("\n"); print_success("Login successful!"); printf("\033[37m👤 Logged in as: \033[32m%s\033[0m\n", username); printf("\033[90m🔑 Token saved securely\033[0m\n"); printf("\033[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m\n"); // Clean up memory json_object_put(parsed_json); free(response.data); return 0; } // Status command implementation int cmd_status(int argc, char *argv[]) { (void)argc; // Suppress unused parameter warning (void)argv; // Suppress unused parameter warning printf("\033[36m╔══════════════════════════════════════╗\033[0m\n"); printf("\033[36m║ 📊 Repository Status ║\033[0m\n"); printf("\033[36m╚══════════════════════════════════════╝\033[0m\n"); // Check if user is logged in char *token = get_token(); if (!token) { print_warning("You are not logged in"); printf("\033[90m💡 Use 'exp login ' to login\033[0m\n"); return 1; } // Get username from config char username[MAX_BUFFER] = {0}; char config_path[MAX_PATH]; snprintf(config_path, MAX_PATH, "%s/config", get_config_dir()); FILE *config_fp = fopen(config_path, "r"); if (config_fp) { char line[MAX_BUFFER]; while (fgets(line, sizeof(line), config_fp)) { if (strncmp(line, "username=", 9) == 0) { strncpy(username, line + 9, MAX_BUFFER - 1); // Remove newline char *newline = strchr(username, '\n'); if (newline) *newline = '\0'; break; } } fclose(config_fp); } if (strlen(username) > 0) { printf("\033[37m👤 Logged in as: \033[32m%s\033[0m\n", username); } else { printf("\033[37m👤 User: \033[90mUnknown\033[0m\n"); } // Get repository config char *repo_config_path = get_repo_config_path(); if (!repo_config_path) { print_warning("No repository configuration found"); printf("\033[90m💡 Use 'exp init ' to create a new repository\033[0m\n"); printf("\033[90m💡 Use 'exp change-repo ' to switch repository\033[0m\n"); free(token); return 1; } FILE *repo_fp = fopen(repo_config_path, "r"); if (!repo_fp) { print_warning("No active repository found"); printf("\033[90m💡 Use 'exp init ' to create a new repository\033[0m\n"); printf("\033[90m💡 Use 'exp change-repo ' to switch repository\033[0m\n"); free(repo_config_path); free(token); return 1; } char repo_name[MAX_BUFFER] = {0}; char repo_username[MAX_BUFFER] = {0}; char line[MAX_BUFFER]; while (fgets(line, sizeof(line), repo_fp)) { if (strncmp(line, "name=", 5) == 0) { strncpy(repo_name, line + 5, MAX_BUFFER - 1); // Remove newline char *newline = strchr(repo_name, '\n'); if (newline) *newline = '\0'; } else if (strncmp(line, "username=", 9) == 0) { strncpy(repo_username, line + 9, MAX_BUFFER - 1); // Remove newline char *newline = strchr(repo_username, '\n'); if (newline) *newline = '\0'; } } fclose(repo_fp); if (strlen(repo_name) > 0 && strlen(repo_username) > 0) { printf("\033[37m📦 Active Repository: \033[32m%s/%s\033[0m\n", repo_username, repo_name); printf("\033[90m💡 Ready for upload and release operations\033[0m\n"); } else { print_warning("Repository configuration is incomplete"); printf("\033[90m💡 Use 'exp change-repo ' to fix configuration\033[0m\n"); } printf("\033[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m\n"); // Clean up free(repo_config_path); free(token); return 0; } // Init command implementation int cmd_init(int argc, char *argv[]) { if (argc < 2) { printf("\033[33m📝 Usage: exp init [description] [private]\033[0m\n"); return 1; } char repo_name[MAX_BUFFER]; char desc[MAX_BUFFER] = {0}; int is_private = 0; strncpy(repo_name, argv[1], MAX_BUFFER - 1); if (argc > 2) { strncpy(desc, argv[2], MAX_BUFFER - 1); } is_private = (argc > 3 && strcmp(argv[3], "private") == 0) ? 1 : 0; printf("\033[36m╔══════════════════════════════════════╗\033[0m\n"); printf("\033[36m║ 📁 Repository Setup ║\033[0m\n"); printf("\033[36m╚══════════════════════════════════════╝\033[0m\n"); printf("\033[37m📦 Repository: \033[32m%s\033[0m\n", repo_name); if (strlen(desc) > 0) { printf("\033[37m📝 Description: \033[90m%s\033[0m\n", desc); } printf("\033[37m🔒 Visibility: \033[%s%s\033[0m\n", is_private ? "31m" : "32m", is_private ? "Private" : "Public"); printf("\n"); // Get token char *token = get_token(); if (!token) { print_error("You are not logged in. Please login first."); return 1; } print_progress("Verifying authentication..."); // Get username from configuration file or API char username[MAX_BUFFER] = {0}; // Always get the latest username from the API char url[MAX_PATH]; snprintf(url, MAX_PATH, "%s/auth/me", API_BASE_URL); http_response_t response = http_get(url, token); if (!response.data) { print_error("Failed to get user information"); free(token); return 1; } // Parse JSON response struct json_object *parsed_json; struct json_object *status_obj; struct json_object *data_obj; struct json_object *username_obj; parsed_json = json_tokener_parse(response.data); if (!parsed_json) { print_error("Failed to parse JSON response"); free(response.data); free(token); return 1; } // Check response status json_object_object_get_ex(parsed_json, "status", &status_obj); const char *status = json_object_get_string(status_obj); if (strcmp(status, "success") != 0) { print_error("Failed to get user information"); json_object_put(parsed_json); free(response.data); free(token); return 1; } // Get username json_object_object_get_ex(parsed_json, "data", &data_obj); json_object_object_get_ex(data_obj, "username", &username_obj); strncpy(username, json_object_get_string(username_obj), MAX_BUFFER - 1); // Save username to configuration file char config_path[MAX_PATH]; snprintf(config_path, MAX_PATH, "%s/config", get_config_dir()); FILE *fp = fopen(config_path, "w"); if (fp) { fprintf(fp, "username=%s\n", username); fclose(fp); } // Clean up memory json_object_put(parsed_json); free(response.data); if (strlen(username) == 0) { print_error("Username not found in configuration"); free(token); return 1; } // Create JSON for create repository request char json_data[MAX_BUFFER]; snprintf(json_data, MAX_BUFFER, "{\"name\":\"%s\",\"description\":\"%s\",\"private\":%s}", repo_name, desc, is_private ? "true" : "false"); // Create URL for create repository char create_url[MAX_PATH]; snprintf(create_url, MAX_PATH, "%s/repository/create/", API_BASE_URL); // Send create repository request http_response_t create_response = http_post(create_url, token, json_data); if (!create_response.data) { print_error("Failed to create repository"); free(token); return 1; } // Parse JSON response struct json_object *create_parsed_json; struct json_object *create_status_obj; struct json_object *create_message_obj; create_parsed_json = json_tokener_parse(create_response.data); if (!create_parsed_json) { print_error("Failed to parse JSON response"); free(create_response.data); free(token); return 1; } // Check response status json_object_object_get_ex(create_parsed_json, "status", &create_status_obj); json_object_object_get_ex(create_parsed_json, "message", &create_message_obj); const char *create_status = json_object_get_string(create_status_obj); const char *create_message = json_object_get_string(create_message_obj); if (strcmp(create_status, "success") != 0) { print_error(create_message); json_object_put(create_parsed_json); free(create_response.data); free(token); return 1; } // Try to get repository owner from response struct json_object *repo_data_obj = NULL; struct json_object *owner_obj = NULL; char repo_owner[MAX_BUFFER] = {0}; if (json_object_object_get_ex(create_parsed_json, "data", &repo_data_obj) && repo_data_obj) { if (json_object_object_get_ex(repo_data_obj, "owner", &owner_obj) && owner_obj) { strncpy(repo_owner, json_object_get_string(owner_obj), MAX_BUFFER - 1); } } // If we got a repository owner from the API response, use it if (strlen(repo_owner) > 0) { strncpy(username, repo_owner, MAX_BUFFER - 1); } // Create file for repository config char repo_config_path[MAX_PATH]; snprintf(repo_config_path, MAX_PATH, "%s/repo_config", get_config_dir()); FILE *repo_fp = fopen(repo_config_path, "w"); if (repo_fp) { fprintf(repo_fp, "name=%s\n", repo_name); fprintf(repo_fp, "username=%s\n", username); fclose(repo_fp); } printf("\n"); print_success("Repository created successfully!"); printf("\033[36m╔══════════════════════════════════════╗\033[0m\n"); printf("\033[36m║ 🎉 Repository Ready! ║\033[0m\n"); printf("\033[36m╚══════════════════════════════════════╝\033[0m\n"); printf("\033[37m📦 Repository: \033[32m%s/%s\033[0m\n", username, repo_name); if (strlen(desc) > 0) { printf("\033[37m📝 Description: \033[90m%s\033[0m\n", desc); } printf("\033[37m🔒 Visibility: \033[%s%s\033[0m\n", is_private ? "31m" : "32m", is_private ? "Private" : "Public"); printf("\033[37m💡 You can now upload files using: exp upload \033[0m\n"); printf("\033[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m\n"); // Clean up memory json_object_put(create_parsed_json); free(create_response.data); free(token); return 0; } // Change repository command implementation int cmd_change_repo(int argc, char *argv[]) { if (argc < 3) { printf("\033[33m🔄 Usage: exp change-repo \033[0m\n"); printf("\033[37mExample: exp change-repo admin my-project\033[0m\n"); return 1; } const char *username = argv[1]; const char *repo_name = argv[2]; printf("\033[36m╔══════════════════════════════════════╗\033[0m\n"); printf("\033[36m║ 🔄 Change Repository ║\033[0m\n"); printf("\033[36m╚══════════════════════════════════════╝\033[0m\n"); // Get token to verify authentication char *token = get_token(); if (!token) { print_error("You are not logged in. Please login first."); return 1; } print_progress("Verifying repository access..."); // Verify repository access using the new verify endpoint char url[MAX_PATH]; snprintf(url, MAX_PATH, "%s/repository/verify", API_BASE_URL); // Prepare JSON payload struct json_object *json_payload = json_object_new_object(); struct json_object *username_obj = json_object_new_string(username); struct json_object *repo_name_obj = json_object_new_string(repo_name); json_object_object_add(json_payload, "username", username_obj); json_object_object_add(json_payload, "repo_name", repo_name_obj); const char *json_string = json_object_to_json_string(json_payload); http_response_t response = http_post(url, token, json_string); // Clean up JSON payload json_object_put(json_payload); if (!response.data) { print_error("Failed to verify repository access"); free(token); return 1; } // Parse JSON response struct json_object *parsed_json; struct json_object *status_obj; struct json_object *message_obj; parsed_json = json_tokener_parse(response.data); if (!parsed_json) { print_error("Failed to parse JSON response"); free(response.data); free(token); return 1; } // Check response status json_object_object_get_ex(parsed_json, "status", &status_obj); json_object_object_get_ex(parsed_json, "message", &message_obj); const char *status = json_object_get_string(status_obj); const char *message = json_object_get_string(message_obj); if (strcmp(status, "success") != 0) { char error_msg[256]; snprintf(error_msg, sizeof(error_msg), "Repository not found or access denied: %s", message); print_error(error_msg); json_object_put(parsed_json); free(response.data); free(token); return 1; } // Check access permissions from the verify endpoint response struct json_object *data_obj; struct json_object *has_access_obj; struct json_object *access_type_obj; json_object_object_get_ex(parsed_json, "data", &data_obj); if (data_obj) { json_object_object_get_ex(data_obj, "has_access", &has_access_obj); json_object_object_get_ex(data_obj, "access_type", &access_type_obj); if (has_access_obj && !json_object_get_boolean(has_access_obj)) { print_error("You do not have access to this repository"); json_object_put(parsed_json); free(response.data); free(token); return 1; } // Display access information if (access_type_obj) { const char *access_type = json_object_get_string(access_type_obj); if (access_type) { printf("\033[32m✓ Access granted: %s\033[0m\n", access_type); } } } // Update repository configuration char *repo_config_path = get_repo_config_path(); if (!repo_config_path) { print_error("Failed to get repository config path"); json_object_put(parsed_json); free(response.data); free(token); return 1; } FILE *repo_fp = fopen(repo_config_path, "w"); if (!repo_fp) { print_error("Failed to update repository configuration"); free(repo_config_path); json_object_put(parsed_json); free(response.data); free(token); return 1; } fprintf(repo_fp, "name=%s\n", repo_name); fprintf(repo_fp, "username=%s\n", username); fclose(repo_fp); printf("\n"); print_success("Repository changed successfully!"); printf("\033[36m╔══════════════════════════════════════╗\033[0m\n"); printf("\033[36m║ 🎯 Active Repository ║\033[0m\n"); printf("\033[36m╚══════════════════════════════════════╝\033[0m\n"); printf("\033[37m📦 Repository: \033[32m%s/%s\033[0m\n", username, repo_name); printf("\033[37m💡 You can now upload files using: exp upload \033[0m\n"); printf("\033[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m\n"); // Clean up memory free(repo_config_path); json_object_put(parsed_json); free(response.data); free(token); return 0; }