aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/NOTES.txt
diff options
context:
space:
mode:
Diffstat (limited to 'src/NOTES.txt')
-rw-r--r--src/NOTES.txt651
1 files changed, 651 insertions, 0 deletions
diff --git a/src/NOTES.txt b/src/NOTES.txt
new file mode 100644
index 0000000..93ed815
--- /dev/null
+++ b/src/NOTES.txt
@@ -0,0 +1,651 @@
1I'm re-purposing this for SledjHamr https://sledjhamr.org/git/docs/index.html
2
3The general structure of SledjHamr is a bunch of servers talking to each
4other via Internet (or just local) connections. One of them is a web
5server for assets, world data, and inventory.
6
7Originally I didn't think using a web based world client was a good idea,
8however it might be better to have one, for reasons. Now I need a web
9management console that can do all the things the current tmux console
10can, including OpenSim console and commands. Plus account management for
11users. I can also use a web based Jabber / XMPP front end to chat, IM,
12and group chatter, which would run in the normal viewers web browser.
13This provides a doorway into putting SledjHamr stuff in existing viewers
14without needing them to support it. So a web based viewer now makes more
15sense, and also means we can get away with not needing a viewer at all.
16
17Toybox itself doesn't include a web server, and I don't think there is
18one on the roadmap. So we have to use an external web server, which was
19a design goal of SledjHamr in the first place, using existing mature
20HTTP infrastructure, coz that's already solved problems for a bunch of
21things that plague OS/SL to this day. Clear your cache! Pffft.
22
23So sledjchisl.c will be the "love world server", though initially it just
24drives OpenSim_SC in tmux via tmux commands to send keys and read output.
25Later it might run opensim_SC directly and use STDIN and STDOUT to do
26everything. It'll also provide the text management front end that runs
27in the left tmux panel of the first window, which is why it's based on
28boxes in the first place. Later still it can take over opensim_SC
29functions as I move them out of mono.
30
31We will need a text, web, and GUI version of this management front end.
32Hmmm, maybe don't need a GUI version, GUI users can just run a terminal.
33
34After much research, FastCGI / FCGI seems to be the most portable way of
35interfacing with existing web servers. FCGI protocol closes STDERR and
36STDOUT, and uses STDIN as it's two way communications channel to the web
37server, so our FCGI module can't be used as the text management front
38end. This is probably a good idea to keep them seperate anyway, for
39security, coz the web server is exposed to the world, the console isn't.
40
41Currently sledjchisl.c tests to see if it's running in tmux already, if
42it isn't it starts up tmux runs itself into this new tmux, then exits.
43So it could also test if it's running from FCGI, and switch to web mode,
44then it'll need to find the tmuxed instance to send commands to it.
45Either via nails connection, or sending tmux commands via shell.
46
47FCGI has methods of dealing with auth and templates. B-)
48
49So for now I think I'll have the text and web management front ends in
50sledjchisl.c, and the love world server as well. I can split them up
51later if I need to.
52
53
54
55
56I has Apache 2.4.25-3+deb9u9
57 MariaDB 10.1.44-MariaDB
58
59
60https://gist.github.com/dermesser/e2f9b66457ae19ebd116
61 Multithreaded example in C.
62
63
64-------------------------------------------------------------------
65
66Apache doesn't seem to support FCGI filter role, so I might have to do
67without. Might be better anyway.
68
69
70"A Filter is similar in functionality to a Responder that takes a data
71file as a parameter. The difference is that with a Filter, both the data
72file and the Filter itself can be access controlled using the Web
73server's access control mechanisms, while a Responder that takes the name
74of a data file as a parameter must perform its own access control checks
75on the data file."
76
77 Which is fine, our access control checks will be "Is this database
78 defined user already logged on via our FCGI script?". We should have
79 total control over that. I was planning on using the FCGI auth
80 mechanism anyway.
81
82
83RESPONDER
84 web server sends FCGI_PARAMS
85 CONTENT_LENGTH
86 web server sends input body FCGI_STDIN
87 fcgi app sends result data over FCGI_STDOUT and error messages over FCGI_STDERR
88 it has to finish reading FCGI_PARAMS first
89 fcgi app sends FCGI_END_REQUEST(protocolStatus = FCGI_REQUEST_COMPLETE)
90
91
92FILTER
93 filtered file has last modified time
94 web server sets FCGI_DATA_LAST_MOD accordingly
95 web server sends FCGI_PARAMS
96 CONTENT_LENGTH FCGI_DATA_LAST_MOD FCGI_DATA_LENGTH
97 web server sends input body FCGI_STDIN
98 web servers sends file over FCGI_DATA
99 fcgi app can ignore FCGI_DATA and use it's own cached copy based on FCGI_DATA_LAST_MOD
100 fcgi app sends result data over FCGI_STDOUT and error messages over FCGI_STDERR
101 it has to finish reading FCGI_STDIN first, but not FCGI_DATA
102 fcgi app sends FCGI_END_REQUEST(protocolStatus = FCGI_REQUEST_COMPLETE)
103
104
105Soooo, FILTER might be slower anyway if we are caching the filtered file,
106or mmapping it, coz filter has to start sending the filtered file, even
107if it's to be served from cache. Plus no need to wait for FCGI_STDIN
108before spewing it out.
109
110
111Last update time for parameters, plus an update frequency. Once a minute.
112
113 NOTE - SSI is a bit more complex than what I'm currently using.
114 https://en.wikipedia.org/wiki/Server_Side_Includes
115 <!--#include virtual="menu.cgi" -->
116 <!--#include file="footer.html" -->
117 <!--#exec cgi="/cgi-bin/foo.cgi" -->
118 <!--#exec cmd="ls -l" -->
119. <!--#echo var="REMOTE_ADDR" -->
120 <!--#config timefmt="%y %m %d" -->
121 <!--#config sizefmt="bytes" -->
122 <!--#config errmsg="SSI command failed!" -->
123 <!--#flastmod virtual="index.html" -->
124 <!--#fsize file="script.pl" -->
125 <!--#if expr="${Sec_Nav}" -->
126 <!--#include virtual="secondary_nav.txt" -->
127 <!--#elif expr="${Pri_Nav}" -->
128 <!--#include virtual="primary_nav.txt" -->
129 <!--#else -->
130 <!--#include virtual="article.txt" -->
131 <!--#endif -->
132 <!--#set var="foo" value="bar" -->
133 <!--#printenv -->
134 https://www.w3.org/Jigsaw/Doc/User/SSI.html
135 Adds lots of others, including Java stuff.
136 Mine
137 <!--#lua lua="print(table[key])" -->
138 <!--#lua file="/path/to/script.lua" -->
139 <!--#lua virtual="https://example.com/script.lua" -->
140
141-------------------------------------------------------------------
142
143Account creation process in the database.
144
145Apart from the usual input validation of things...
146
147
148OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs
149 byte[] CreateUser(Dictionary<string, object> request)
150 Looks like their built in web front end, perhaps what is triggered by the console?
151 createdUserAccount
152 = ((UserAccountService)m_UserAccountService).CreateUser(scopeID, principalID, firstName, lastName, password, email, model);
153
154OpenSim/opensim-SC/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
155 An XML RPC interface to -
156 private UserAccount CreateUser(UUID scopeID, string firstName, string lastName, string password, string email)
157 account = new UserAccount(scopeID, UUID.Random(), firstName, lastName, email);
158 if (userAccountService.StoreUserAccount(account))
159 success = authenticationService.SetPassword(account.PrincipalID, password)
160 gridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0));
161 success = inventoryService.CreateUserInventory(account.PrincipalID);
162
163OpenSim/opensim-SC/OpenSim/Services/UserAccountService/UserAccountService.cs
164 Looks like the console command handler.
165 create user [<first> [<last> [<pass> [<email> [<user id> [<model>]]]]]] - Create a new user
166 protected void HandleCreateUser(string module, string[] cmdparams)
167 Gathers console arguments, or prompts for them.
168 CreateUser(UUID.Zero, principalId, firstName, lastName, password, email, model);
169 public UserAccount CreateUser(UUID scopeID, UUID principalID, string firstName, string lastName, string password, string email, string model = "")
170 Looks almost identical to the OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs one above, but they add -
171 CreateDefaultAppearanceEntries(account.PrincipalID)
172
173
174
175account = new UserAccount(scopeID, UUID.Random(), firstName, lastName, email);
176 OpenSim/opensim-SC/OpenSim/Services/Interfaces/IUserAccountService.cs
177 public UserAccount(UUID scopeID, UUID principalID, string firstName, string lastName, string email)
178 Just holds the data in memory, in a dictionary I think.
179 OpenSim/opensim-SC/OpenSim/Services/UserAccountService/UserAccountService.cs
180 public bool StoreUserAccount(UserAccount data)
181 Stuffs the data into a new UserAccountData()
182 m_Database.Store(d)
183 As far as I can tell, just dumps this data into the UserAccounts table -
184 FirstName, LastName, PrincipleID, ScopeID, Email, Created, UserLevel, UserFlags, UserTitle
185 PrincipleID is their randomly generated with no thought to collisions UUID.
186 ScopeID is 00000000-0000-0000-0000-000000000000
187 Userlevel is 0 for most, -1 for Waki, determines if they can log on. Also higher for gods and things.
188 UserFlags, I think the only one is "64 god can login to this account using gods password.
189 UserTitle might default to "Local", or be configurable / and editable.
190 something something URL encoded "ServiceURLs" mumble
191 HomeURI=http%3a%2f%2fgrid.infinitegrid.org%3a8002%2f GatekeeperURI= InventoryServerURI=http%3a%2f%2fgrid.infinitegrid.org%3a8002%2f AssetServerURI=http%3a%2f%2fgrid.infinitegrid.org%3a8002%2f ProfileServerURI=http%3a%2f%2fgrid.infinitegrid.org%3a8002%2f FriendsServerURI=http%3a%2f%2fgrid.infinitegrid.org%3a8002%2f IMServerURI=http%3a%2f%2fgrid.infinitegrid.org%3a8002%2f GroupsServerURI=http%3a%2f%2fgrid.infinitegrid.org%3a8002%2f
192 Though most are either NULL, empty, or -
193 HomeURI= GatekeeperURI= InventoryServerURI= AssetServerURI=
194 Doesn't metion "active", which is always equal to 1 I guess.
195
196
197
198success = authenticationService.SetPassword(account.PrincipalID, password)
199 OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs
200 stores password details in "auth" table -
201 UUID
202 passwordSalt = Util.Md5Hash(UUID.Random().ToString());
203 passwdHash = Util.Md5Hash(Util.Md5Hash(password) + ":" + passwordSalt);
204 accountType = "UserAccount";
205 webLoginKey = UUID.Zero.ToString();
206
207
208
209gridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0));
210 OpenSim/Services/UserAccountService/GridUserService.cs
211 Stores in database table GridUser
212 HomeRegionID, HomePosition, HomeLookAt
213 The other fields in that table -
214 UserID, LastRegionID, LastPosition, LastLookAt, Online (true or false), Login (timestamp or 0), Logout (timestamp or 0).
215
216
217
218success = inventoryService.CreateUserInventory(account.PrincipalID);
219 OpenSim/Services/InventoryService/XInventoryService.cs
220 Create a bunch of folders in the users inventory, of specific types.
221 rootFolder = ConvertToOpenSim(CreateFolder(principalID, UUID.Zero, (int)FolderType.Root, InventoryFolderBase.ROOT_FOLDER_NAME));
222 XInventoryFolder[] sysFolders = GetSystemFolders(principalID, rootFolder.ID)
223 if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)FolderType.Animation) return true; return false; }))
224 CreateFolder(principalID, rootFolder.ID, (int)FolderType.Animation, "Animations");
225 FolderType.BodyPart, "Body Parts"
226 XInventoryFolder folder = CreateFolder(principalID, rootFolder.ID, (int)FolderType.CallingCard, "Calling Cards");
227 folder = CreateFolder(principalID, folder.folderID, (int)FolderType.CallingCard, "Friends")
228 CreateFolder(principalID, folder.folderID, (int)FolderType.CallingCard, "All");
229 FolderType.Clothing, "Clothing"
230 FolderType.CurrentOutfit, "Current Outfit"
231 FolderType.Favorites, "Favorites"
232 FolderType.Gesture, "Gestures")
233 FolderType.Landmark, "Landmarks"
234 FolderType.LostAndFound, "Lost And Found"
235 FolderType.Notecard, "Notecards"
236 FolderType.Object, "Objects"
237 FolderType.Snapshot, "Photo Album"
238 FolderType.LSLText, "Scripts"
239 FolderType.Sound, "Sounds"
240 FolderType.Texture, "Textures"
241 FolderType.Trash, "Trash"
242
243 Stores in database inventoryFolders ????
244 folderName, type, version = 1, folderID = UUID.Random(), agentID = principalID, parentFolderID = parentID
245
246
247
248
249CreateDefaultAppearanceEntries(account.PrincipalID)
250 OpenSim/Services/UserAccountService/UserAccountService.cs
251 protected void CreateDefaultAppearanceEntries(UUID principalID)
252 Creates a bunch of "Default *" body parts and clothes, Ruth 1.0, links them in Inventories current outfit folder.
253 Creates a AvatarWearable[] and puts them all in it.
254 AvatarAppearance ap = new AvatarAppearance();
255 ap.SetWearable(i, wearables[i]);
256 m_AvatarService.SetAppearance(principalID, ap);
257
258
259
260
261
262UserAccounts table -
263 UserFlags 64 is "allow gods to log in as me"
264 0xf00 is membershipType, unles there's a title. Only sent to viewers I think.
265 32 is Minors for estate banning purposes.
266 4 is Anonymous for estate banning purposes.
267 1 is AllowPublish in profile, but userprofile has this as separate field.
268 2 is MaturePublish in profile, but userprofile has this as separate field.
269Presence table -
270 UserID varchar(255)
271 RegionID char(36)
272 SessionID char(36)
273 SecureSessionID char(36)
274 LastSeen timestamp
275tokens table (I think this is actually used for something) -
276 UUID char(36)
277 token varchar(255) current example looks like a UUID.
278 validity datetime
279userdata (empty, can't find any actual usage in the source code, part of profiles) -
280 UserId char(36) primary index
281 TagId varchar(64) primary index
282 DataKey varchar(255)
283 DataVal varchar(255)
284auth.webLoginKey seems to be some sort of passwordy type thing, though perhaps not actually hashed, rarely used, none of IG members have one.
285
286
287PLAN-
288. username
289. password
290. create login
291
292.check if it's a proper two word name
293.login -> check if it's an existing account, get their UUID.
294 create toke_n_munchie
295 write session record
296
297create -> new user
298 create new UUID
299 check if it's an existing UUID
300 dbCount(, "UserAccounts", "PrincipleID='new-UUID'")
301 loop until we get a new one
302 create toke_n_munchie
303 write session record
304
305
306 Create ->
307 (wait a few seconds before showing this page)
308. email
309. email again
310. password again
311. DoB
312. accept terms of service
313. claim to be an adult
314. confirm / cancel
315
316 New user
317 UserAccounts.FirstName = ???
318 UserAccounts.LastName = ???
319 UserAccounts.Email = ???
320 UserAccounts.Created = timestamp
321 UserAccounts.PrincipleID = randomly generate UUID, but check for collisions with other accounts.
322 It's a UNIQUE KEY.
323 UserAccounts.ScopeID = 00000000-0000-0000-0000-000000000000
324 UserAccounts.Userlevel = -200
325 UserAccounts.UserFlags = 64
326 UserAccounts.UserTitle = newbie
327 UserAccounts.ServiceURLs = ""
328 UserAccounts.active = 0
329
330 auth.UUID = UserAccounts.PrincipleID
331 It's a PRIMARY KEY.
332 auth.passwordSalt = Util.Md5Hash(UUID.Random().ToString())
333 auth.passwdHash = Util.Md5Hash(Util.Md5Hash(password) + ":" + passwordSalt)
334 auth.accountType = "UserAccount"
335 auth.webLoginKey (varchar(255)) = "00000000-0000-0000-0000-000000000000"
336
337 userdata.UserId = UserAccounts.PrincipleID
338 userdata.TagId = "account creation data"
339 It's a UNIQUE KEY
340 userdata.DataKey = "DoB"
341 userdata.DataVal = ???
342
343 userdata.UserId = UserAccounts.PrincipleID
344 userdata.TagId = "account creation data"
345 userdata.DataKey = "timezone"
346 userdata.DataVal = ???
347
348 userdata.UserId = UserAccounts.PrincipleID
349 userdata.TagId = "account creation data"
350 userdata.DataKey = "Terms of service"
351 userdata.DataVal = "True"
352
353 userdata.UserId = UserAccounts.PrincipleID
354 userdata.TagId = "account creation data"
355 userdata.DataKey = "claims to be an adult"
356 userdata.DataVal = "True"
357
358
359 Validated via email
360 (wait a few seconds before showing this page)
361 UserAccounts.Userlevel = -100
362 UserAccounts.UserTitle = validated
363
364
365 Vouched for
366 userdata.UserId = UserAccounts.PrincipleID
367 userdata.TagId = "vouches"
368 userdata.DataKey = UUID of voucher
369 userdata.DataVal = timestamp of vouching
370
371 UserAccounts.Userlevel = -50
372 UserAccounts.UserTitle = vouched for
373
374
375 Admin approved
376 GridUser.UserID = UserAccounts.PrincipleID
377 It's a PRIMARY KEY.
378 GridUser.HomeRegionID = ???
379 GridUser.HomePosition = ???
380 GridUser.HomeLookAt = ???
381 GridUser.LastRegionID = ???
382 GridUser.LastPosition = ???
383 GridUser.LastLookAt = ???
384 GridUser.Online = False
385 GridUser.Login = 0
386 GridUser.Logout = 0
387
388 UserAccounts.active = 1
389 UserAccounts.Userlevel = 1
390 UserAccounts.UserTitle = Member / Local / whatever
391
392 Load the default IAR.
393
394
395-------------------------------------------------------------------
396
397https://project-awesome.org/aleksandar-todorovic/awesome-c
398 A curated list of C good stuff.
399
400https://wolkykim.github.io/qdecoder/
401 CGI library made by the qlibc guy, does support FCGI.
402 Might be a wrapper around the fcgi_stdio stuff I'm already using?
403
404
405https://danielmiessler.com/study/http/
406 A Security-focused HTTP Primer
407 Nothing much new except to say this about the Referer header -
408 "should not be used to make security decisions as it is controlled by the client"
409 Though others tell us to do precisely that. lol
410
411
412-------------------------------------------------------------------
413
414apt install libmariadbclient-dev libapache2-mod-fcgid libssl1.0-dev uuid-dev spawn-fcgi
415
416BTW, everything is some BSD licence variation, except MariaDB, which is
417some combination of GPLv2, 2+, 3, and BSD variants. With FOSS License
418Exception, which seems to mean "Oracles GPL isn't viral". Though my
419license is "fuck you viral GPL, that's not your decision to make for my
420fucking code" BSD.
421
422-------------------------------------------------------------------
423
424Install / update / upgrade.
425
426I could keep the version number around.
427 Include version numbers / branches of dependencies.
428 Update will grab any security updates for the installed version.
429 Upgrade will upgrade to a chosen later different version.
430 Downgrade will downgrade to a chosen earlier different version.
431
432Note that we are currently using the LuaJIT 2.1.0-beta3 branch of the
433main Luajit repo. Everything else is on their master branches.
434
435Bootstrap -
436 bootstrap.sh or bootstrap.bat
437
438 Build the LuaJIT that comes with our source. It "builds out-of-the
439 box on most systems" and has no dependencies, other than a C build system.
440
441 Or download a prebuilt LuaJIT from somewhere.
442
443 After toybox has been LuaJITized.
444
445 Build the LuaJIT that comes with our source. It "builds out-of-the
446 box on most systems" and has no dependencies, other than a C build system.
447
448 Similar should apply to toybox, though it's our LuaJITized version.
449 Will need a specific miniconfig for this that doesn't include sledjchisl.
450
451 Or download a prebuilt toybox+LuaJIT from a SledjHamr package repo.
452
453Install -
454 install.lua
455
456 Will need a pre flight check if the dependencies are installed.
457 It checks if the system is built and has source.
458 Build it all.
459 Do the usual copy stuff to a directory thing.
460 Run "sledjchisl -install" in that directory.
461 Which does the usual "check health of system and fix up problems" thing, then quits instead of keep running.
462 The health check should include making sure our database creds exist / work.
463
464Update / upgrade / downgrade
465 install.lua -update
466 install.lua -upgrade
467 install.lua -downgrade
468
469 Check if we are a binary only, or a source install.
470 wget new binaries / git pull new source
471 Toybox has a wget in pending, otherwise it only has ftpget.
472 Git is standalone outside of the system, but if you are
473 running from source, you likely have standard build tools
474 like git.
475
476
477Yeah I hate things that have their own packaging system, for needing to
478step outside the operating systems packaging system, and adding to the too
479long list of stuff I have to deal with manually, and now I are one. lol
480
481
482-------------------------------------------------------------------
483
484Time for a restructure of the web page / field / database stuff.
485
486Will need to include a "what page is this" cookie, or maybe query ?mode=add
487
488
489
490old validate UUID
491 define the UUID based UserAccounts db static dbRequest, fill it if needed.
492 if create
493 try to find an unused UUID
494 fill Rd->stuff with UUID
495 if confirm
496 check it's length
497 otherwise
498 check it's length
499 look it up, bitch if not found
500 If we found it, put level into Rd->database
501 fill Rd->stuff with UUID
502
503old validateName
504 define the name based UserAccounts db static dbRequest, fill it if needed.
505 Do the Lua file lookup, fill a tnm hash.
506 Do the database lookup, fill rows.
507 if login
508 convert tnm to Rd->database, or dbPull(rows)
509 fill Rd->stuff with name, UUID, and level
510 if create
511 complain if we found a record
512 try to find an unused UUID
513 fill Rd->database with new data
514 fill Rd->stuff with name, UUID, and level
515
516old validatePassword
517 define the UUID based auth db static dbRequest, fill it if needed.
518 if login
519 do the database lookup, fill rows
520 check if the name validation found us a UUID, fail login if it didn't
521 do the pasword+salt hash and compare
522 fill Rd->stuff with passwordHash and passwordSalt
523 if create
524 fill Rd->stuff with paswordHash and passwordSalt
525 if confirm
526 check if password hashess are the same
527
528
529
530
531
532freeSesh(Rd, linky, wipe)
533 linky - Rd->shs or Rd->lnk
534 %s/sessions/%s.lua or %s/sessions/%s.linky
535 wipe - wipe or delete session
536 wiping means remove session stuff from Rd->stuff
537 Which happens on - session failing to write, redirecting login form, showing login form if not confirm, vegOut (session timeout, bitchSession)
538
539newSesh(Rd, linky)
540 linky - old Rd->shs or a new Rd->lnk
541 setToken_n_munchie(Rd, linky); Only caller of setToken_n_munchie(Rd, linky);
542
543
544setToken_n_munchie(Rd, linky)
545 linky - Rd->shs or Rd->lnk
546 %s/sessions/%s.lua or %s/sessions/%s.linky
547 !linky - actually set the cookies.
548 if error writing session file - freeSesh(Rd, linky, TRUE);
549
550
551//validateSesh()
552sessionValidate()
553 bitchSession() for bad session things.
554 sets chillOut for validated session linky.
555 Rd->chillOut = TRUE;
556 freeSesh(Rd, linky, FALSE);
557 Rd->func = (pageBuildFunction) loginPage;
558 Rd->doit = "logout";
559 sets vegOut if the session timed out.
560
561//validatePassword()
562 sets chillOut for validated password on create.
563
564bitchSession() called if there's anything wrong with the session trackers, if we can't load / run the users Lua file,
565 sets vegOut
566
567account_HTML()
568 sets chillOut for POST confirm
569 createUser(Rd);
570 newSesh(Rd, TRUE);
571 Rd->chillOut = TRUE;
572 sets chillOut for POST login
573 Rd->chillOut = TRUE;
574
575
576 POST with no errors will
577 form == accountLogin freeSesh(Rd, FALSE, TRUE)
578 doit == login chillOut = TRUE
579 vegOut freeSesh(Rd, FALSE, TRUE);
580 else chillOut freeSesh(Rd, FALSE, FALSE); newSesh(Rd, FALSE);
581 else no Rd->shs.leaf newSesh(Rd, FALSE);
582 redirect to GET
583 otherwise
584 form == accountLogin
585 doit == confirm freeSesh(Rd, FALSE, TRUE)
586 newSesh(Rd, FALSE)
587 else if errors reeSesh(Rd, FALSE, FALSE) newSesh(Rd, FALSE)
588 show page
589
590
591
592LOGGED IN means that the session stored on disk has a valid UUID.
593 When creating a new user, we create a new UUID firstish.
594
595
596accountLoginWeb() / accountOut()
597 freeSesh(Rd, FALSE, TRUE)
598 newSesh(Rd, FALSE)
599
600accountView()
601 freeSesh(Rd, FALSE, FALSE)
602 newSesh(Rd, FALSE)
603
604accountAdd()
605 Note that this is in two parts, first they click "create" on login page, then "confirm" on the account creation page.
606
607
608
609Account creation
610 accountLoginWeb()
611 "create" ->
612 Show accountCreateWeb and await confirmation.
613 accountCreateWeb()
614 "confirm" -> accountAdd()
615 create UUID
616 create user
617 store user
618 wipe old session
619 store new session with UUID, user is logged in now
620 create linky
621 email linky
622 Show usual logged in page.
623 "cancel" ->
624
625
626-------------------------------------------------------------------
627
628
629Maybe - /opt/opensim_SC/var/cache/sessions/uuid-uuid-uuid-uuid.logged symlink to session.
630
631https://localhost/sledjchisl.fcgi/account.html?user=account_name
632https://localhost/sledjchisl.fcgi/account.html/users/account_name
633 logged in user is in the sesion, but they can view / vouch / edit / delete any other user depending on their access level
634
635
636For logged in user, at the top show their name as linky to their accountView http://localhost/sledjchisl.fcgi/account.html/users/account_name
637 That accountView offers edit / logout button, etc.
638 Display account stuff, but not edit it until they hit the edit button.
639
640When showing other users
641 accountView, with edit / delete buttons if logged in user is high enough level.
642
643-------------------------------------------------------------------
644-------------------------------------------------------------------
645-------------------------------------------------------------------
646
647
648BUGS!
649-----
650Redo the santize(), though that needs extensive changes each time we read Rd->cookies, Rd->queries, and Rd->body
651