Task 042: .ASPX File Format
Task 042: .ASPX File Format
Understanding the .ASPX File Format
Before addressing the task, it’s important to clarify that .ASPX (Active Server Page Extended) is not a traditional file format with intrinsic file system properties like binary formats (e.g., .jpg or .pdf). Instead, it is a server-side web page format used within Microsoft’s ASP.NET framework to generate dynamic web content. An .ASPX file is essentially a text-based file containing a mix of HTML, server-side scripts (typically in C# or VB.NET), and ASP.NET-specific directives or controls. These files are processed by a web server (e.g., Microsoft IIS) to produce HTML output for browsers. Therefore, the "properties intrinsic to its file system" are limited to typical file metadata, as the content and behavior are defined by the ASP.NET runtime rather than a rigid file structure.
1. List of Properties Intrinsic to the .ASPX File Format in the File System
Since .ASPX files are text-based and lack a specific binary structure, their intrinsic file system properties are those associated with any text file. Based on the nature of .ASPX files and standard file system metadata, the relevant properties are:
- File Name: The name of the .ASPX file (e.g.,
index.aspx
). - File Extension: The
.aspx
extension, indicating it is an ASP.NET web form. - File Size: The size of the file in bytes.
- Creation Time: The timestamp when the file was created.
- Last Modified Time: The timestamp when the file was last modified.
- Last Accessed Time: The timestamp when the file was last accessed.
- File Path: The absolute or relative path to the file in the file system.
- File Permissions: Access control settings (e.g., read, write, execute permissions).
- Content Type: Typically
text/html
orapplication/xhtml+xml
, as .ASPX files are served as web content. - Encoding: The character encoding of the file, usually UTF-8 for modern ASP.NET applications.
- File Attributes: System-specific attributes like hidden, read-only, or system file flags.
These properties are not unique to .ASPX files but apply to any file in a file system. The actual content of an .ASPX file (HTML, server-side scripts, and ASP.NET directives) is interpreted at runtime by the ASP.NET framework and does not constitute fixed file system properties. Since .ASPX files are text-based, they can be read and written like any text file, but their dynamic behavior requires a server environment to execute.
2. Python Class for .ASPX File Handling
Below is a Python class that opens, reads, writes, and prints the file system properties of an .ASPX file. Since .ASPX files are text-based, the class uses standard file operations and the os
module to retrieve file system metadata.
import os
import mimetypes
import time
class ASPXFileHandler:
def __init__(self, file_path):
self.file_path = file_path
self.properties = {}
def get_file_properties(self):
"""Retrieve file system properties of the .ASPX file."""
try:
# Get file statistics
stats = os.stat(self.file_path)
# File name and extension
self.properties['file_name'] = os.path.basename(self.file_path)
self.properties['file_extension'] = os.path.splitext(self.file_path)[1].lower()
# File size
self.properties['file_size'] = stats.st_size
# Timestamps
self.properties['creation_time'] = time.ctime(stats.st_ctime)
self.properties['last_modified_time'] = time.ctime(stats.st_mtime)
self.properties['last_accessed_time'] = time.ctime(stats.st_atime)
# File path
self.properties['file_path'] = os.path.abspath(self.file_path)
# File permissions (octal format)
self.properties['file_permissions'] = oct(stats.st_mode)[-3:]
# Content type
content_type, _ = mimetypes.guess_type(self.file_path)
self.properties['content_type'] = content_type or 'text/html'
# Encoding (assuming UTF-8 for .ASPX, could be detected more robustly)
self.properties['encoding'] = 'utf-8'
# File attributes (Windows-specific or general)
self.properties['file_attributes'] = 'directory' if os.path.isdir(self.file_path) else 'regular file'
except FileNotFoundError:
print(f"Error: File {self.file_path} not found.")
except Exception as e:
print(f"Error retrieving properties: {e}")
def read_file(self):
"""Read the content of the .ASPX file."""
try:
with open(self.file_path, 'r', encoding='utf-8') as file:
content = file.read()
return content
except FileNotFoundError:
print(f"Error: File {self.file_path} not found.")
return None
except Exception as e:
print(f"Error reading file: {e}")
return None
def write_file(self, content):
"""Write content to the .ASPX file."""
try:
with open(self.file_path, 'w', encoding='utf-8') as file:
file.write(content)
print(f"Successfully wrote to {self.file_path}")
except Exception as e:
print(f"Error writing to file: {e}")
def print_properties(self):
"""Print all file system properties."""
if not self.properties:
self.get_file_properties()
for key, value in self.properties.items():
print(f"{key}: {value}")
# Example usage
if __name__ == "__main__":
aspx_file = ASPXFileHandler("example.aspx")
aspx_file.get_file_properties()
aspx_file.print_properties()
# Read and display file content
content = aspx_file.read_file()
if content:
print("\nFile Content:")
print(content)
# Write new content (example)
new_content = "<%@ Page Language='C#' %>\n<html>\n<body>\n<h1>Hello, ASP.NET!</h1>\n</body>\n</html>"
aspx_file.write_file(new_content)
Notes:
- This class assumes the .ASPX file is accessible locally and treats it as a text file.
- It uses the
os
module to retrieve file system metadata andmimetypes
to guess the content type. - The
read_file
method reads the file content as UTF-8 text, andwrite_file
allows overwriting or creating a new .ASPX file. - The class does not execute the server-side code, as that requires an ASP.NET runtime environment (e.g., IIS).
3. Java Class for .ASPX File Handling
Below is a Java class that performs similar operations using Java’s file handling capabilities.
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;
public class ASPXFileHandler {
private String filePath;
private Map<String, String> properties;
public ASPXFileHandler(String filePath) {
this.filePath = filePath;
this.properties = new HashMap<>();
}
public void getFileProperties() {
try {
Path path = Paths.get(filePath);
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
// File name and extension
properties.put("file_name", path.getFileName().toString());
properties.put("file_extension", filePath.substring(filePath.lastIndexOf(".")).toLowerCase());
// File size
properties.put("file_size", String.valueOf(attrs.size()) + " bytes");
// Timestamps
properties.put("creation_time", attrs.creationTime().toString());
properties.put("last_modified_time", attrs.lastModifiedTime().toString());
properties.put("last_accessed_time", attrs.lastAccessTime().toString());
// File path
properties.put("file_path", path.toAbsolutePath().toString());
// File permissions (simplified)
properties.put("file_permissions",
(Files.isReadable(path) ? "r" : "-") +
(Files.isWritable(path) ? "w" : "-") +
(Files.isExecutable(path) ? "x" : "-"));
// Content type (hardcoded for .aspx)
properties.put("content_type", "text/html");
// Encoding
properties.put("encoding", "UTF-8");
// File attributes
properties.put("file_attributes", attrs.isDirectory() ? "directory" : "regular file");
} catch (IOException e) {
System.err.println("Error retrieving properties: " + e.getMessage());
}
}
public String readFile() {
try {
return new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);
} catch (IOException e) {
System.err.println("Error reading file: " + e.getMessage());
return null;
}
}
public void writeFile(String content) {
try {
Files.write(Paths.get(filePath), content.getBytes(StandardCharsets.UTF_8));
System.out.println("Successfully wrote to " + filePath);
} catch (IOException e) {
System.err.println("Error writing to file: " + e.getMessage());
}
}
public void printProperties() {
if (properties.isEmpty()) {
getFileProperties();
}
for (Map.Entry<String, String> entry : properties.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
public static void main(String[] args) {
ASPXFileHandler handler = new ASPXFileHandler("example.aspx");
handler.getFileProperties();
handler.printProperties();
// Read and display file content
String content = handler.readFile();
if (content != null) {
System.out.println("\nFile Content:");
System.out.println(content);
}
// Write new content (example)
String newContent = "<%@ Page Language=\"C#\" %>\n<html>\n<body>\n<h1>Hello, ASP.NET!</h1>\n</body>\n</html>";
handler.writeFile(newContent);
}
}
Notes:
- Uses
java.nio.file
for file system metadata and file operations. - Assumes UTF-8 encoding for reading and writing.
- Handles exceptions for file access and provides basic permission information.
4. JavaScript Class for .ASPX File Handling (Node.js)
Since JavaScript typically runs in a browser or Node.js environment, this class uses Node.js’s fs
module for file system operations.
const fs = require('fs').promises;
const path = require('path');
const mime = require('mime-types');
class ASPXFileHandler {
constructor(filePath) {
this.filePath = filePath;
this.properties = {};
}
async getFileProperties() {
try {
const stats = await fs.stat(this.filePath);
// File name and extension
this.properties.file_name = path.basename(this.filePath);
this.properties.file_extension = path.extname(this.filePath).toLowerCase();
// File size
this.properties.file_size = `${stats.size} bytes`;
// Timestamps
this.properties.creation_time = stats.birthtime.toISOString();
this.properties.last_modified_time = stats.mtime.toISOString();
this.properties.last_accessed_time = stats.atime.toISOString();
// File path
this.properties.file_path = path.resolve(this.filePath);
// File permissions (simplified)
this.properties.file_permissions = (stats.mode & 0o777).toString(8);
// Content type
this.properties.content_type = mime.lookup(this.filePath) || 'text/html';
// Encoding
this.properties.encoding = 'utf-8';
// File attributes
this.properties.file_attributes = stats.isDirectory() ? 'directory' : 'regular file';
} catch (error) {
console.error(`Error retrieving properties: ${error.message}`);
}
}
async readFile() {
try {
return await fs.readFile(this.filePath, 'utf-8');
} catch (error) {
console.error(`Error reading file: ${error.message}`);
return null;
}
}
async writeFile(content) {
try {
await fs.writeFile(this.filePath, content, 'utf-8');
console.log(`Successfully wrote to ${this.filePath}`);
} catch (error) {
console.error(`Error writing to file: ${error.message}`);
}
}
async printProperties() {
if (Object.keys(this.properties).length === 0) {
await this.getFileProperties();
}
for (const [key, value] of Object.entries(this.properties)) {
console.log(`${key}: ${value}`);
}
}
}
// Example usage
(async () => {
const handler = new ASPXFileHandler('example.aspx');
await handler.getFileProperties();
await handler.printProperties();
// Read and display file content
const content = await handler.readFile();
if (content) {
console.log('\nFile Content:');
console.log(content);
}
// Write new content (example)
const newContent = `<%@ Page Language="C#" %>
<html>
<body>
<h1>Hello, ASP.NET!</h1>
</body>
</html>`;
await handler.writeFile(newContent);
})();
Notes:
- Requires Node.js and the
mime-types
package (npm install mime-types
). - Uses asynchronous file operations with
fs.promises
. - Assumes UTF-8 encoding and uses
mime-types
to determine content type.
5. C Class for .ASPX File Handling
C does not have classes, so we’ll use a struct and functions to achieve similar functionality. This implementation uses standard C file operations and system calls for metadata.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
#define MAX_PATH 256
#define MAX_CONTENT 1024
typedef struct {
char file_path[MAX_PATH];
char file_name[MAX_PATH];
char file_extension[16];
char file_size[32];
char creation_time[64];
char last_modified_time[64];
char last_accessed_time[64];
char file_permissions[16];
char content_type[32];
char encoding[16];
char file_attributes[32];
} ASPXFileHandler;
void init_aspx_handler(ASPXFileHandler* handler, const char* file_path) {
strncpy(handler->file_path, file_path, MAX_PATH - 1);
handler->file_path[MAX_PATH - 1] = '\0';
}
void get_file_properties(ASPXFileHandler* handler) {
struct stat stats;
if (stat(handler->file_path, &stats) == -1) {
printf("Error: File %s not found.\n", handler->file_path);
return;
}
// File name and extension
char* base_name = strrchr(handler->file_path, '/');
if (!base_name) base_name = handler->file_path;
else base_name++;
strncpy(handler->file_name, base_name, MAX_PATH - 1);
char* ext = strrchr(handler->file_name, '.');
strncpy(handler->file_extension, ext ? ext : ".aspx", 15);
// File size
snprintf(handler->file_size, 32, "%ld bytes", stats.st_size);
// Timestamps
strftime(handler->creation_time, 64, "%Y-%m-%d %H:%M:%S", localtime(&stats.st_ctime));
strftime(handler->last_modified_time, 64, "%Y-%m-%d %H:%M:%S", localtime(&stats.st_mtime));
strftime(handler->last_accessed_time, 64, "%Y-%m-%d %H:%M:%S", localtime(&stats.st_atime));
// File path
char abs_path[MAX_PATH];
realpath(handler->file_path, abs_path);
strncpy(handler->file_path, abs_path, MAX_PATH - 1);
// File permissions
snprintf(handler->file_permissions, 16, "%o", stats.st_mode & 0777);
// Content type (hardcoded)
strcpy(handler->content_type, "text/html");
// Encoding
strcpy(handler->encoding, "utf-8");
// File attributes
strcpy(handler->file_attributes, S_ISDIR(stats.st_mode) ? "directory" : "regular file");
}
void read_file(ASPXFileHandler* handler) {
FILE* file = fopen(handler->file_path, "r");
if (!file) {
printf("Error: Cannot read file %s\n", handler->file_path);
return;
}
printf("\nFile Content:\n");
char buffer[MAX_CONTENT];
while (fgets(buffer, MAX_CONTENT, file)) {
printf("%s", buffer);
}
fclose(file);
}
void write_file(ASPXFileHandler* handler, const char* content) {
FILE* file = fopen(handler->file_path, "w");
if (!file) {
printf("Error: Cannot write to file %s\n", handler->file_path);
return;
}
fputs(content, file);
fclose(file);
printf("Successfully wrote to %s\n", handler->file_path);
}
void print_properties(ASPXFileHandler* handler) {
printf("file_name: %s\n", handler->file_name);
printf("file_extension: %s\n", handler->file_extension);
printf("file_size: %s\n", handler->file_size);
printf("creation_time: %s\n", handler->creation_time);
printf("last_modified_time: %s\n", handler->last_modified_time);
printf("last_accessed_time: %s\n", handler->last_accessed_time);
printf("file_path: %s\n", handler->file_path);
printf("file_permissions: %s\n", handler->file_permissions);
printf("content_type: %s\n", handler->content_type);
printf("encoding: %s\n", handler->encoding);
printf("file_attributes: %s\n", handler->file_attributes);
}
int main() {
ASPXFileHandler handler;
init_aspx_handler(&handler, "example.aspx");
get_file_properties(&handler);
print_properties(&handler);
read_file(&handler);
const char* new_content = "<%@ Page Language=\"C#\" %>\n<html>\n<body>\n<h1>Hello, ASP.NET!</h1>\n</body>\n</html>";
write_file(&handler, new_content);
return 0;
}
Notes:
- Uses standard C libraries (
stdio.h
,sys/stat.h
) for file operations and metadata. - Assumes UTF-8 encoding and hardcodes
text/html
as the content type. - Simplified permission handling using POSIX-style octal notation.
Additional Notes
- Decoding and Execution: .ASPX files contain server-side code (e.g., C# or VB.NET) that requires an ASP.NET runtime (e.g., IIS) to execute. The classes above treat .ASPX files as text files and do not execute the server-side logic, as this is beyond the scope of simple file handling without a web server.
- Limitations: The task assumes .ASPX files have intrinsic file system properties beyond typical file metadata, but their dynamic nature (processed by ASP.NET) means most "properties" are runtime behaviors, not static attributes. The classes focus on file system metadata and content access.
- Sources: The implementation is based on general knowledge of .ASPX files as text-based web forms in ASP.NET, with metadata handling inspired by standard file system APIs. No specific external sources were required, as the properties and operations are standard for text files.
If you need further clarification or additional functionality (e.g., parsing ASP.NET directives or executing the files in a server context), please let me know!
.ASPX File Format Specifications
The .ASPX file format is a text-based format used for Active Server Pages Extended in Microsoft's ASP.NET framework. It is not a binary format but rather a markup file containing HTML, server-side controls, scripts, and directives processed by the ASP.NET runtime on web servers. The specifications are documented in Microsoft ASP.NET resources, focusing on syntax for page directives, controls, and code integration. The primary structural element is the @Page directive, which defines configuration attributes for the page compiler and parser. Files are typically encoded in UTF-8 and can reference code-behind files (.aspx.cs or .aspx.vb).
1. List of All Properties Intrinsic to the .ASPX File Format
Based on the format's specifications, the key properties are the attributes defined in the @Page directive, which are intrinsic to how the file is processed in the ASP.NET environment. These are not file system metadata but format-specific configurations embedded in the text. Here is the comprehensive list:
- AutoEventWireup: Specifies if page events should be auto-wired.
- ClassName: Specifies the class name that will be dynamically compiled when the page is requested.
- CodeFile: Specifies the code-behind class for the current page.
- CodeBehind: Specifies the path to the code-behind class for the current page.
- CodeFileBaseClass: Specifies the type name of a base class for a page and its associated code-behind class.
- CompilerOptions: Specifies compilation options for the current page.
- Description: Specifies a text description of the master page.
- Debug: Specifies if the page should be compiled with debug symbols.
- Language: Specifies the language used when compiling inline code blocks.
- Inherits: Specifies the base class for the page to inherit.
- Src: Specifies the source file that contains the implementation of the base class specified with Inherits.
- MasterPageFile: Specifies the master page for the current page.
- EnableSessionState: Specifies how the page should treat session data (true, false, readonly).
- EnableViewState: Specifies whether the page view state is maintained across page requests.
- EnableTheming: Specifies if the page will support themes for embedded controls.
- ErrorPage: Specifies the error page URL for unhandled page exceptions.
- ValidateRequest: Specifies whether page request validation should occur.
- CodePage: Specifies the code page value for the response.
- ContentType: Specifies the HTTP content type of the page response.
- Title: Specifies the title of the page.
- ResponseEncoding: Specifies the character encoding of the page.
- Buffer: Specifies the HTTP response buffer of the page.
Note: Not all properties are required in every .ASPX file; they are optional based on the page's configuration. The classes below will handle extracting and modifying these where present.
2. Python Class for .ASPX Files
import os
import re
class ASPXFile:
def __init__(self, filepath):
if not filepath.lower().endswith('.aspx'):
raise ValueError("File must have .aspx extension")
self.filepath = filepath
self.properties = self._decode_properties()
def _decode_properties(self):
with open(self.filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Find the @Page directive
match = re.search(r'<%@\s*Page\s+(.*?)%>', content, re.IGNORECASE | re.DOTALL)
if not match:
return {}
attr_str = match.group(1)
# Parse attributes: key="value" or key='value' or key=value
attrs = re.findall(r'(\w+)\s*=\s*(["\']?)(.*?)\2(?=\s+\w+=|\s*%>)', attr_str, re.DOTALL)
return {key: value for key, _, value in attrs}
def read_properties(self):
return self.properties
def write_properties(self, new_properties):
with open(self.filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Find existing directive
match = re.search(r'(<%@\s*Page\s+).*?(%>)', content, re.IGNORECASE | re.DOTALL)
if match:
# Rebuild directive with new properties
attr_str = ' '.join([f'{key}="{value}"' for key, value in new_properties.items()])
new_directive = f'{match.group(1)}{attr_str}{match.group(2)}'
content = content.replace(match.group(0), new_directive)
else:
# Add new directive at the top
attr_str = ' '.join([f'{key}="{value}"' for key, value in new_properties.items()])
new_directive = f'<%@ Page {attr_str} %>\n'
content = new_directive + content
with open(self.filepath, 'w', encoding='utf-8') as f:
f.write(content)
self.properties = new_properties
3. Java Class for .ASPX Files
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.regex.*;
public class ASPXFile {
private String filepath;
private Map<String, String> properties;
public ASPXFile(String filepath) throws IOException {
if (!filepath.toLowerCase().endsWith(".aspx")) {
throw new IllegalArgumentException("File must have .aspx extension");
}
this.filepath = filepath;
this.properties = decodeProperties();
}
private Map<String, String> decodeProperties() throws IOException {
String content = new String(Files.readAllBytes(Paths.get(filepath)), "UTF-8");
Pattern pattern = Pattern.compile("<%@\\s*Page\\s+(.*?)%>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
Matcher matcher = pattern.matcher(content);
if (!matcher.find()) {
return new HashMap<>();
}
String attrStr = matcher.group(1);
Map<String, String> attrs = new HashMap<>();
Pattern attrPattern = Pattern.compile("(\\w+)\\s*=\\s*([\"']?)(.*?)\\2(?=\\s+\\w+=|\\s*%>)", Pattern.DOTALL);
Matcher attrMatcher = attrPattern.matcher(attrStr);
while (attrMatcher.find()) {
attrs.put(attrMatcher.group(1), attrMatcher.group(3));
}
return attrs;
}
public Map<String, String> readProperties() {
return new HashMap<>(properties);
}
public void writeProperties(Map<String, String> newProperties) throws IOException {
String content = new String(Files.readAllBytes(Paths.get(filepath)), "UTF-8");
Pattern pattern = Pattern.compile("(<%@\\s*Page\\s+).*?(%>)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
StringBuilder attrStr = new StringBuilder();
for (Map.Entry<String, String> entry : newProperties.entrySet()) {
attrStr.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\" ");
}
String newDirective = matcher.group(1) + attrStr.toString().trim() + matcher.group(2);
content = content.replace(matcher.group(0), newDirective);
} else {
StringBuilder attrStr = new StringBuilder();
for (Map.Entry<String, String> entry : newProperties.entrySet()) {
attrStr.append(entry.getKey()).append("=\"").append(entry.getValue()).append("\" ");
}
String newDirective = "<%@ Page " + attrStr.toString().trim() + " %>\n";
content = newDirective + content;
}
Files.write(Paths.get(filepath), content.getBytes("UTF-8"));
this.properties = new HashMap<>(newProperties);
}
}
4. JavaScript Class for .ASPX Files (Node.js)
const fs = require('fs');
const path = require('path');
class ASPXFile {
constructor(filepath) {
if (!filepath.toLowerCase().endsWith('.aspx')) {
throw new Error('File must have .aspx extension');
}
this.filepath = filepath;
this.properties = this._decodeProperties();
}
_decodeProperties() {
const content = fs.readFileSync(this.filepath, 'utf-8');
const match = content.match(/<%@\s*Page\s+(.*?)%>/is);
if (!match) {
return {};
}
const attrStr = match[1];
const attrs = {};
const attrMatches = attrStr.matchAll(/(\w+)\s*=\s*(["']?)(.*?)\2(?=\s+\w+=|\s*%>)/gs);
for (const attrMatch of attrMatches) {
attrs[attrMatch[1]] = attrMatch[3];
}
return attrs;
}
readProperties() {
return { ...this.properties };
}
writeProperties(newProperties) {
let content = fs.readFileSync(this.filepath, 'utf-8');
const match = content.match(/(<%@\s*Page\s+).*?(%>)/is);
if (match) {
const attrStr = Object.entries(newProperties)
.map(([key, value]) => `${key}="${value}"`)
.join(' ');
const newDirective = `${match[1]}${attrStr}${match[2]}`;
content = content.replace(match[0], newDirective);
} else {
const attrStr = Object.entries(newProperties)
.map(([key, value]) => `${key}="${value}"`)
.join(' ');
const newDirective = `<%@ Page ${attrStr} %>\n`;
content = newDirective + content;
}
fs.writeFileSync(this.filepath, content, 'utf-8');
this.properties = { ...newProperties };
}
}
module.exports = ASPXFile;
5. C++ Class for .ASPX Files
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <regex>
#include <algorithm>
#include <cctype>
class ASPXFile {
private:
std::string filepath;
std::map<std::string, std::string> properties;
std::map<std::string, std::string> decodeProperties() {
std::ifstream file(filepath, std::ios::in);
if (!file.is_open()) {
throw std::runtime_error("Unable to open file");
}
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
file.close();
std::regex directiveRegex(R"(<\%\@\s*Page\s+(.*?)\%\>)", std::regex::icase | std::regex::ECMAScript);
std::smatch match;
if (!std::regex_search(content, match, directiveRegex)) {
return {};
}
std::string attrStr = match[1].str();
std::map<std::string, std::string> attrs;
std::regex attrRegex(R"((\w+)\s*=\s*(["']?)(.*?)\2(?=\s+\w+=|\s*\%>))", std::regex::ECMAScript);
auto attrsBegin = std::sregex_iterator(attrStr.begin(), attrStr.end(), attrRegex);
auto attrsEnd = std::sregex_iterator();
for (std::sregex_iterator i = attrsBegin; i != attrsEnd; ++i) {
std::smatch attrMatch = *i;
attrs[attrMatch[1].str()] = attrMatch[3].str();
}
return attrs;
}
public:
ASPXFile(const std::string& fp) : filepath(fp) {
std::string ext = filepath.substr(filepath.find_last_of(".") + 1);
std::transform(ext.begin(), ext.end(), ext.begin(),
[](unsigned char c){ return std::tolower(c); });
if (ext != "aspx") {
throw std::invalid_argument("File must have .aspx extension");
}
properties = decodeProperties();
}
std::map<std::string, std::string> readProperties() const {
return properties;
}
void writeProperties(const std::map<std::string, std::string>& newProperties) {
std::ifstream fileIn(filepath, std::ios::in);
if (!fileIn.is_open()) {
throw std::runtime_error("Unable to open file");
}
std::string content((std::istreambuf_iterator<char>(fileIn)), std::istreambuf_iterator<char>());
fileIn.close();
std::regex directiveRegex(R"((<\%\@\s*Page\s+).*?(\%\>))", std::regex::icase | std::regex::ECMAScript);
std::smatch match;
if (std::regex_search(content, match, directiveRegex)) {
std::string attrStr;
for (const auto& pair : newProperties) {
attrStr += pair.first + "=\"" + pair.second + "\" ";
}
if (!attrStr.empty()) attrStr.pop_back(); // Remove trailing space
std::string newDirective = match[1].str() + attrStr + match[2].str();
content = std::regex_replace(content, directiveRegex, newDirective, std::regex_constants::format_first_only);
} else {
std::string attrStr;
for (const auto& pair : newProperties) {
attrStr += pair.first + "=\"" + pair.second + "\" ";
}
if (!attrStr.empty()) attrStr.pop_back();
std::string newDirective = "<%@ Page " + attrStr + " %>\n";
content = newDirective + content;
}
std::ofstream fileOut(filepath, std::ios::out | std::ios::trunc);
if (!fileOut.is_open()) {
throw std::runtime_error("Unable to write to file");
}
fileOut << content;
fileOut.close();
properties = newProperties;
}
};