[Feature][S300][task-view-993][webui] add web upload upgrade package upgrade function

Change-Id: Ieba32458a073443c11f112036c5834ca089624cf
diff --git a/lynq/CPE_COMMON/ap/app/cgi/cgi.c b/lynq/CPE_COMMON/ap/app/cgi/cgi.c
new file mode 100755
index 0000000..3aaddd0
--- /dev/null
+++ b/lynq/CPE_COMMON/ap/app/cgi/cgi.c
@@ -0,0 +1,372 @@
+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+#include <unistd.h>

+#include <fcntl.h>

+#include <errno.h>

+

+#define BUFFER_SIZE (1024 * 20) // Define the buffer size for each read

+#define FIND_STR_LEN 128 // Define the length of the string to find

+#define FOTA_UPDATE_STATUS_FILE "/cache/zte_fota/update_status"

+

+// Custom memmem function

+static void* custom_memmem(const void* haystack, size_t haystack_len, const void* needle, size_t needle_len)

+{

+    if (needle_len == 0 || haystack_len < needle_len)

+    {

+        return NULL;

+    }

+

+    size_t i = 0;

+    const unsigned char* h = (const unsigned char*)haystack;

+    const unsigned char* n = (const unsigned char*)needle;

+

+    for (i = 0; i <= haystack_len - needle_len; ++i)

+    {

+        if (memcmp(h + i, n, needle_len) == 0)

+        {

+            return (void*)(h + i);

+        }

+    }

+

+    return NULL;

+}

+

+// Remove the last boundary marker from the file

+static int remove_last_boundary(const char *filename, const char *boundary_marker, int boundary_marker_len)

+{

+    int fd = open(filename, O_RDWR);

+    if (fd == -1)

+    {

+        perror("Unable to open file for reading and writing");

+        return 1;

+    }

+

+    // Get the file size

+    off_t file_size = lseek(fd, 0, SEEK_END);

+    if (file_size == -1)

+    {

+        perror("Unable to get file size");

+        close(fd);

+        return 1;

+    }

+

+    // Search for the boundary_marker from the end of the file

+    off_t search_start = file_size - FIND_STR_LEN;

+    if (search_start < 0)

+    {

+        search_start = 0;

+    }

+

+    lseek(fd, search_start, SEEK_SET);

+

+    char buffer[FIND_STR_LEN + 1]; // +1 for storing '\0'

+    int bytes_read = read(fd, buffer, FIND_STR_LEN);

+    if (bytes_read <= 0)

+    {

+        perror("Unable to read file");

+        close(fd);

+        return 1;

+    }

+    buffer[bytes_read] = '\0'; // Ensure the string is null-terminated

+

+    // Find the boundary_marker

+    char *boundary = custom_memmem(buffer, bytes_read, boundary_marker, boundary_marker_len);

+    if (boundary)

+    {

+        // Found boundary_marker, calculate the truncate position

+        off_t truncate_pos = search_start + (boundary - buffer);

+        if (ftruncate(fd, truncate_pos) == -1)

+        {

+            perror("Unable to truncate file");

+            close(fd);

+            return 1;

+        }

+    }

+

+    close(fd);

+    return 0;

+}

+

+// Function to handle file upload

+static int handle_file_upload(const char *source_filename, const char *target_filename, int content_length)

+{

+    char buffer[BUFFER_SIZE];

+    int bytes_read;

+    int target_fd = -1;

+    int source_fd = -1; // Source file descriptor

+    char *content_start_ptr = NULL;

+    int content_start = 0;

+    const char *boundary_marker = "\r\n------WebKitFormBoundary"; // Boundary marker

+    int boundary_marker_len = strlen(boundary_marker);

+

+    // Open the target file

+    target_fd = open(target_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);

+    if (target_fd == -1)

+    {

+        perror("Unable to open target file");

+        return 1;

+    }

+

+    // Open the source file

+    source_fd = open(source_filename, O_RDONLY);

+    if (source_fd == -1)

+    {

+        perror("Unable to open source file");

+        close(target_fd);

+        return 1;

+    }

+

+    // Read the request header to find the start position of file content

+    bytes_read = read(source_fd, buffer, BUFFER_SIZE);

+    if (bytes_read <= 0)

+    {

+        printf("Content-type: text/html\r\n\r\n");

+        printf("<h1>Error: Failed to read data</h1>");

+        printf("<p>Error number: %d - %s</p>", errno, strerror(errno));

+        close(target_fd);

+        close(source_fd);

+        return 1;

+    }

+

+    // Find the start position of the file content (usually after \r\n\r\n)

+    content_start_ptr = strstr(buffer, "\r\n\r\n");

+    if (!content_start_ptr)

+    {

+        printf("Content-type: text/html\r\n\r\n");

+        printf("<h1>Error: Unable to find the start position of file content</h1>");

+        close(target_fd);

+        close(source_fd);

+        return 1;

+    }

+

+    // Calculate the actual start position of the file content

+    content_start = content_start_ptr - buffer + 4;

+

+    // Write the first part of the file content

+    if (content_start < bytes_read)

+    {

+        if (write(target_fd, buffer + content_start, bytes_read - content_start) == -1)

+        {

+            perror("Unable to write to target file");

+            close(target_fd);

+            close(source_fd);

+            return 1;

+        }

+    }

+

+    // Update the remaining content length

+    content_length -= (bytes_read - content_start);

+

+    // Continue reading and writing the file in segments

+    while (content_length > 0)

+    {

+        bytes_read = read(source_fd, buffer, BUFFER_SIZE);

+        if (bytes_read <= 0)

+        {

+            // If reading is complete, normally break out of the loop

+            break;

+        }

+

+        // Write the file content

+        if (write(target_fd, buffer, bytes_read) == -1)

+        {

+            perror("Unable to write to target file");

+            close(target_fd);

+            close(source_fd);

+            return 1;

+        }

+

+        // Update the remaining content length

+        content_length -= bytes_read;

+    }

+

+    // Close file descriptors

+    close(target_fd);

+    close(source_fd);

+

+    // Remove the last boundary marker from the file

+    return remove_last_boundary(target_filename, boundary_marker, boundary_marker_len);

+}

+

+static int fota_is_file_exist(const char* path)

+{

+	if ( (path == NULL) || (*path == '\0') )

+		return 0;

+	if (access(path, R_OK) != 0)

+		return 0;

+

+	return 1;

+}

+

+static int fota_read_file(const char*path, char*buf, size_t sz)

+{

+	int fd = -1;

+	size_t cnt;

+

+	fd = open(path, O_RDONLY, 0);

+	if(fd < 0)

+	{

+		printf("fota_read_file failed to open %s: %s\n", path, strerror(errno));

+		cnt = -1;

+		return cnt;

+	}

+	cnt = read(fd, buf, sz - 1);

+	if(cnt <= 0)

+	{

+		printf("failed to read %s: %s\n", path, strerror(errno));

+		close(fd);

+		cnt = -1;

+		return cnt;

+	}

+	buf[cnt] = '\0';

+	if(buf[cnt - 1] == '\n')

+	{

+		cnt--;

+		buf[cnt] = '\0';

+	}

+	close(fd);

+

+	return cnt;

+}

+

+static int fota_read_file_int(const char* path, int *val)

+{

+	char buf[32];

+	char *end;

+	int ret;

+	int tmp;

+

+	ret = fota_read_file(path, buf, sizeof(buf));

+	if(ret < 0)

+		return -1;

+

+	errno = 0;

+	tmp = strtol(buf, &end, 0);

+	if (errno == ERANGE)

+    {

+		printf("strtol errno %d: %s\n", errno, strerror(errno));

+	}

+

+	if ((end == buf) || ((end < buf + sizeof(buf)) && (*end != '\0')))

+	{

+		return -1;

+	}

+

+	*val = tmp;

+

+	return 0;

+}

+

+static int fota_get_update_status(int *fota_status)

+{

+	int status = 0;

+	int ret = 0;

+	if(!fota_is_file_exist(FOTA_UPDATE_STATUS_FILE))

+    {

+		*fota_status = -1;

+		return -1;

+	}

+	ret = fota_read_file_int(FOTA_UPDATE_STATUS_FILE, &status);

+	if(ret < 0)

+    {

+		*fota_status = -1;

+		return -1;

+	}

+	*fota_status = status;

+	return 0;

+}

+

+static void cgi_fota_update_progress()

+{

+    int upgradeStatus, result;

+

+    system("fota_upi -u verify > /dev/null 2>&1");

+	result = fota_get_update_status(&upgradeStatus);

+	if(result < 0)

+	{

+        printf("<h1 style='color: red;'>Error: Fail to read update file!</h1>");

+	}

+	else if(upgradeStatus != 0)

+	{

+		printf("<h1 style='color: red;'>Error: Verify update file failed!</h1>");

+	}

+	else

+	{

+		printf("<h1 style='color: green;'>File verification successful, start updating...</h1>");

+		system("fota_upi -u recovery &");

+	}

+}

+

+static void html_print_start()

+{

+    printf("Content-type: text/html\r\n\r\n");

+    printf("<!DOCTYPE html>\n");

+    printf("<html lang=\"en\">\n");

+    printf("<head>\n");

+    printf("<meta charset=\"UTF-8\">\n");

+    printf("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n");

+    printf("<title>File Upload Status</title>\n");

+    printf("<style>\n");

+    printf("body { font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 0; padding-top: 20px; }\n");

+    printf(".container { background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); text-align: center; width: 80%%; max-width: 500px; margin: 0 auto; }\n");

+    printf("h1 { margin: 10px 0; }\n");

+    printf("</style>\n");

+    printf("</head>\n");

+    printf("<body>\n");

+    printf("<div class=\"container\">\n");    

+}

+

+static void html_print_end()

+{

+    printf("</div>\n");

+    printf("</body>\n");

+    printf("</html>\n");

+}

+

+int main()

+{

+    const char *source_filename = "/firmware_tmp_file"; // Source file path

+    const char *target_filename = "/cache/zte_fota/delta.package";  // Target file path

+    const char *content_length_str = NULL;

+    int content_length = 0;

+

+    system("rm -rf /cache/zte_fota");

+	system("mkdir -p /cache/zte_fota");

+

+    // Get environment variables

+    content_length_str = getenv("CONTENT_LENGTH");

+    if (!content_length_str)

+    {

+        printf("Content-type: text/html\r\n\r\n");

+        printf("<h1>Error: Missing CONTENT_LENGTH environment variable</h1>");

+        return 1;

+    }

+

+    content_length = atoi(content_length_str);

+    if (content_length <= 0)

+    {

+        printf("Content-type: text/html\r\n\r\n");

+        printf("<h1>Error: Invalid CONTENT_LENGTH</h1>");

+        return 1;

+    }

+

+    // Call the file upload handling function

+    if (handle_file_upload(source_filename, target_filename, content_length) != 0)

+    {

+        printf("Content-type: text/html\r\n\r\n");

+        printf("<h1>Error: File upload failed</h1>");

+        return 1;

+    }

+

+    // Output success information

+    html_print_start();

+    printf("<h1 style='color: green;'>File upload successful!</h1>");

+    //printf("<p>The file has been saved to %s</p>", target_filename);

+

+    cgi_fota_update_progress();

+

+    html_print_end();

+

+    return 0;

+}