1+ <?php
2+ namespace Pdsinterop \PhpSolid ;
3+
4+ use Pdsinterop \PhpSolid \Server ;
5+ use Pdsinterop \PhpSolid \User ;
6+
7+ class StorageServer extends Server {
8+ public static function getFileSystem () {
9+ $ storageId = self ::getStorageId ();
10+
11+ // The internal adapter
12+ $ adapter = new \League \Flysystem \Adapter \Local (
13+ // Determine root directory
14+ STORAGEBASE . "$ storageId/ "
15+ );
16+
17+ $ graph = new \EasyRdf \Graph ();
18+ // Create Formats objects
19+ $ formats = new \Pdsinterop \Rdf \Formats ();
20+
21+ $ scheme = $ _SERVER ['REQUEST_SCHEME ' ];
22+ $ domain = $ _SERVER ['SERVER_NAME ' ];
23+ $ path = $ _SERVER ['REQUEST_URI ' ];
24+ $ serverUri = "{$ scheme }:// {$ domain }{$ path }" ; // FIXME: doublecheck that this is the correct url;
25+
26+ // Create the RDF Adapter
27+ $ rdfAdapter = new \Pdsinterop \Rdf \Flysystem \Adapter \Rdf ($ adapter , $ graph , $ formats , $ serverUri );
28+
29+ $ filesystem = new \League \Flysystem \Filesystem ($ rdfAdapter );
30+ $ filesystem ->addPlugin (new \Pdsinterop \Rdf \Flysystem \Plugin \AsMime ($ formats ));
31+ $ plugin = new \Pdsinterop \Rdf \Flysystem \Plugin \ReadRdf ($ graph );
32+ $ filesystem ->addPlugin ($ plugin );
33+ return $ filesystem ;
34+ }
35+
36+ public static function respond ($ response ) {
37+ $ statusCode = $ response ->getStatusCode ();
38+ $ response ->getBody ()->rewind ();
39+ $ headers = $ response ->getHeaders ();
40+
41+ $ body = $ response ->getBody ()->getContents ();
42+ header ("HTTP/1.1 $ statusCode " );
43+ foreach ($ headers as $ header => $ values ) {
44+ foreach ($ values as $ value ) {
45+ if ($ header == "Location " ) {
46+ $ value = preg_replace ("|%26%2334%3B| " , "%22 " , $ value ); // odoo weird encoding
47+ }
48+ header ($ header . ": " . $ value );
49+ }
50+ }
51+ echo $ body ;
52+ }
53+
54+ public static function getWebId ($ rawRequest ) {
55+ $ dpop = self ::getDpop ();
56+ $ webId = $ dpop ->getWebId ($ rawRequest );
57+ if (!isset ($ webId )) {
58+ $ bearer = self ::getBearer ();
59+ $ webId = $ bearer ->getWebId ($ rawRequest );
60+ }
61+ return $ webId ;
62+ }
63+
64+ private static function getStorageId () {
65+ $ serverName = $ _SERVER ['SERVER_NAME ' ];
66+ $ idParts = explode (". " , $ serverName , 2 );
67+ $ storageId = preg_replace ("/^storage-/ " , "" , $ idParts [0 ]);
68+ return $ storageId ;
69+ }
70+
71+ public static function getOwner () {
72+ $ storageId = self ::getStorageId ();
73+ return User::getUserById ($ storageId );
74+ }
75+
76+ public static function getOwnerWebId () {
77+ $ owner = self ::getOwner ();
78+ return $ owner ['webId ' ];
79+ }
80+
81+ public static function initializeStorage () {
82+ $ filesystem = self ::getFilesystem ();
83+ if (!$ filesystem ->has ("/.acl " )) {
84+ $ defaultAcl = self ::generateDefaultAcl ();
85+ $ filesystem ->write ("/.acl " , $ defaultAcl );
86+ }
87+
88+ // Generate default folders and ACLs:
89+ if (!$ filesystem ->has ("/inbox " )) {
90+ $ filesystem ->createDir ("/inbox " );
91+ }
92+ if (!$ filesystem ->has ("/inbox/.acl " )) {
93+ $ inboxAcl = self ::generatePublicAppendAcl ();
94+ $ filesystem ->write ("/inbox/.acl " , $ inboxAcl );
95+ }
96+ if (!$ filesystem ->has ("/settings " )) {
97+ $ filesystem ->createDir ("/settings " );
98+ }
99+ if (!$ filesystem ->has ("/settings/privateTypeIndex.ttl " )) {
100+ $ privateTypeIndex = self ::generateDefaultPrivateTypeIndex ();
101+ $ filesystem ->write ("/settings/privateTypeIndex.ttl " , $ privateTypeIndex );
102+ }
103+ if (!$ filesystem ->has ("/settings/publicTypeIndex.ttl " )) {
104+ $ publicTypeIndex = self ::generateDefaultPublicTypeIndex ();
105+ $ filesystem ->write ("/settings/publicTypeIndex.ttl " , $ publicTypeIndex );
106+ }
107+ if (!$ filesystem ->has ("/settings/preferences.ttl " )) {
108+ $ preferences = self ::generateDefaultPreferences ();
109+ $ filesystem ->write ("/settings/preferences.ttl " , $ preferences );
110+ }
111+ if (!$ filesystem ->has ("/public " )) {
112+ $ filesystem ->createDir ("/public " );
113+ }
114+ if (!$ filesystem ->has ("/public/.acl " )) {
115+ $ publicAcl = self ::generatePublicReadAcl ();
116+ $ filesystem ->write ("/public/.acl " , $ publicAcl );
117+ }
118+ if (!$ filesystem ->has ("/private " )) {
119+ $ filesystem ->createDir ("/private " );
120+ }
121+ }
122+
123+ public static function generateDefaultAcl () {
124+ $ webId = self ::getOwnerWebId ();
125+ $ acl = <<< "EOF"
126+ # Root ACL resource for the user account
127+ @prefix acl: <http://www.w3.org/ns/auth/acl#>.
128+ @prefix foaf: <http://xmlns.com/foaf/0.1/>.
129+
130+ # The homepage is readable by the public
131+ <#public>
132+ a acl:Authorization;
133+ acl:agentClass foaf:Agent;
134+ acl:accessTo <./>;
135+ acl:mode acl:Read.
136+
137+ # The owner has full access to every resource in their pod.
138+ # Other agents have no access rights,
139+ # unless specifically authorized in other .acl resources.
140+ <#owner>
141+ a acl:Authorization;
142+ acl:agent < $ webId>;
143+ # Set the access to the root storage folder itself
144+ acl:accessTo <./>;
145+ # All resources will inherit this authorization, by default
146+ acl:default <./>;
147+ # The owner has all of the access modes allowed
148+ acl:mode
149+ acl:Read, acl:Write, acl:Control.
150+ EOF ;
151+ return $ acl ;
152+ }
153+
154+ public static function generatePublicAppendAcl () {
155+ $ webId = self ::getOwnerWebId ();
156+ $ acl = <<< "EOF"
157+ # Inbox ACL resource for the user account
158+ @prefix acl: <http://www.w3.org/ns/auth/acl#>.
159+ @prefix foaf: <http://xmlns.com/foaf/0.1/>.
160+
161+ <#public>
162+ a acl:Authorization;
163+ acl:agentClass foaf:Agent;
164+ acl:accessTo <./>;
165+ acl:default <./>;
166+ acl:mode
167+ acl:Append.
168+
169+ <#owner>
170+ a acl:Authorization;
171+ acl:agent < $ webId>;
172+ # Set the access to the root storage folder itself
173+ acl:accessTo <./>;
174+ # All resources will inherit this authorization, by default
175+ acl:default <./>;
176+ # The owner has all of the access modes allowed
177+ acl:mode
178+ acl:Read, acl:Write, acl:Control.
179+ EOF ;
180+ return $ acl ;
181+ }
182+
183+ public static function generatePublicReadAcl () {
184+ $ webId = self ::getOwnerWebId ();
185+ $ acl = <<< "EOF"
186+ # Inbox ACL resource for the user account
187+ @prefix acl: <http://www.w3.org/ns/auth/acl#>.
188+ @prefix foaf: <http://xmlns.com/foaf/0.1/>.
189+
190+ <#public>
191+ a acl:Authorization;
192+ acl:agentClass foaf:Agent;
193+ acl:accessTo <./>;
194+ acl:default <./>;
195+ acl:mode
196+ acl:Read.
197+
198+ <#owner>
199+ a acl:Authorization;
200+ acl:agent < $ webId>;
201+ # Set the access to the root storage folder itself
202+ acl:accessTo <./>;
203+ # All resources will inherit this authorization, by default
204+ acl:default <./>;
205+ # The owner has all of the access modes allowed
206+ acl:mode
207+ acl:Read, acl:Write, acl:Control.
208+ EOF ;
209+ return $ acl ;
210+ }
211+
212+ public static function generateDefaultPrivateTypeIndex () {
213+ $ typeIndex = <<< "EOF"
214+ # Private type index
215+ @prefix : <#>.
216+ @prefix solid: <http://www.w3.org/ns/solid/terms#>.
217+
218+ <>
219+ a solid:UnlistedDocument, solid:TypeIndex.
220+ EOF ;
221+ return $ typeIndex ;
222+ }
223+
224+ public static function generateDefaultPublicTypeIndex () {
225+ $ typeIndex = <<< "EOF"
226+ # Public type index
227+ @prefix : <#>.
228+ @prefix solid: <http://www.w3.org/ns/solid/terms#>.
229+
230+ <>
231+ a solid:ListedDocument, solid:TypeIndex.
232+ EOF ;
233+ return $ typeIndex ;
234+ }
235+
236+ public static function generateDefaultPreferences () {
237+ $ webId = self ::getOwnerWebId ();
238+ $ preferences = <<< "EOF"
239+ # Preferences
240+ @prefix : <#>.
241+ @prefix sp: <http://www.w3.org/ns/pim/space#>.
242+ @prefix dct: <http://purl.org/dc/terms/>.
243+ @prefix profile: < $ webId>.
244+ @prefix solid: <http://www.w3.org/ns/solid/terms#>.
245+
246+ <>
247+ a sp:ConfigurationFile;
248+ dct:title "Preferences file".
249+
250+ profile:me
251+ a solid:Developer;
252+ solid:privateTypeIndex <privateTypeIndex.ttl>;
253+ solid:publicTypeIndex <publicTypeIndex.ttl>.
254+ EOF ;
255+ return $ preferences ;
256+ }
257+ }
258+
0 commit comments