atmos/kernel/
app_sandbox.rs1#![allow(dead_code)]
2
3use crate::os_lib::json::{parse_json, JsonValue};
4use alloc::string::String;
5use alloc::vec::Vec;
6
7#[derive(Debug, Clone)]
10pub struct AppManifest {
11 pub name: String,
12 pub version: String,
13 pub display_name: String,
14 pub description: String,
15 pub entry: String,
16 pub permissions: Vec<String>,
17 pub width: Option<u32>,
19 pub height: Option<u32>,
21}
22
23impl Default for AppManifest {
24 fn default() -> Self {
25 AppManifest {
26 name: String::from("unknown"),
27 version: String::from("1.0.0"),
28 display_name: String::from("Unknown App"),
29 description: String::new(),
30 entry: String::from("main.aura"),
31 permissions: Vec::new(),
32 width: None,
33 height: None,
34 }
35 }
36}
37
38impl AppManifest {
39 pub fn parse(json_str: &str) -> Option<Self> {
40 let json = parse_json(json_str).ok()?;
41
42 if let JsonValue::Object(map) = json {
43 let name = match map.get("name") {
44 Some(JsonValue::String(s)) => s.clone(),
45 _ => return None,
46 };
47
48 let version = match map.get("version") {
49 Some(JsonValue::String(s)) => s.clone(),
50 _ => String::from("1.0.0"),
51 };
52
53 let display_name = match map.get("display_name") {
54 Some(JsonValue::String(s)) => s.clone(),
55 _ => name.clone(),
56 };
57
58 let description = match map.get("description") {
59 Some(JsonValue::String(s)) => s.clone(),
60 _ => String::new(),
61 };
62
63 let entry = match map.get("entry") {
64 Some(JsonValue::String(s)) => s.clone(),
65 _ => String::from("main.aura"),
66 };
67
68 let mut permissions = Vec::new();
69 if let Some(JsonValue::Array(arr)) = map.get("permissions") {
70 for item in arr {
71 if let JsonValue::String(s) = item {
72 permissions.push(s.clone());
73 }
74 }
75 }
76
77 let width = match map.get("width") {
79 Some(JsonValue::Number(n)) => Some(*n as u32),
80 _ => None,
81 };
82 let height = match map.get("height") {
83 Some(JsonValue::Number(n)) => Some(*n as u32),
84 _ => None,
85 };
86
87 return Some(AppManifest {
88 name,
89 version,
90 display_name,
91 description,
92 entry,
93 permissions,
94 width,
95 height,
96 });
97 }
98 None
99 }
100
101 pub fn has_permission(&self, perm: &str) -> bool {
102 self.permissions.iter().any(|p| p == perm)
103 }
104}
105
106#[derive(Debug, Clone)]
107pub struct AppSandbox {
108 pub app_id: usize,
109 pub manifest: AppManifest,
110 pub data_dir: String,
111}
112
113impl AppSandbox {
114 pub fn new(app_id: usize, manifest: AppManifest) -> Self {
115 let data_dir = alloc::format!("/data/apps/{}/", manifest.name);
116 Self {
117 app_id,
118 manifest,
119 data_dir,
120 }
121 }
122
123 pub fn resolve_path(&self, requested_path: &str) -> Option<String> {
126 if requested_path.contains("..") {
128 return None;
129 }
130
131 if requested_path.starts_with(&self.data_dir) {
133 return Some(String::from(requested_path));
134 }
135
136 if self.manifest.has_permission("fs_global") {
138 return Some(String::from(requested_path));
139 }
140
141 if requested_path.starts_with("/user/") && self.manifest.has_permission("fs_user") {
143 return Some(String::from(requested_path));
144 }
145
146 None
147 }
148}