3 require_once "Socket.php";
4 require_once "LoomClient.php";
7 * iPhone interface to the Loom folder.
8 * Don't run this unencrypted.
9 * See http://www.whoopis.com/howtos/apache-rewrite.html
10 * for unstructions on setting up a .htaccess file to rewrite
11 * http://... to https://...
15 if (get_magic_quotes_gpc()) return stripslashes($x);
19 $passphrase = mq($_POST['passphrase']);
20 $qty = mq($_POST['zip']);
21 $type = mq($_POST['type']);
22 $location = mq($_POST['location']);
23 $folderkv = mq($_POST['folderkv']);
24 $valueskv = mq($_POST['valueskv']);
25 $take = mq($_POST['take']);
26 $give = mq($_POST['give']);
27 $page = mq($_POST['page']);
28 $greendot = mq($_POST['greendot']);
29 $showfolder = mq($_POST['showfolder']);
31 $client = new LoomClient();
38 if ($page == 'refresh') {
43 if ($folderkv != '') $folder = $client->parsekv($folderkv, TRUE);
44 if ($valueskv != '') $values = $client->parsekv($valueskv, TRUE);
47 if ($passphrase == '' ||
!login()) {
48 $onload = 'passphrase';
52 $values = scanFolder($folder);
53 $valueskv = $client->array2kv($values);
59 <meta name
="viewport" content
="width=device-width" user
-scalable
="no" minimum
-scale
="1.0" maximum
-scale
="1.0"/>
60 <title
>Loom Folder
</title
>
62 <script language
="JavaScript">
63 function submitPage(page
) {
64 document
.forms
["mainform"].page
.value
= page
;
65 document
.mainform
.submit();
68 function greenDot(greendot
) {
69 document
.forms
["mainform"].greendot
.value
= greendot
;
70 document
.mainform
.submit();
74 <style type
="text/css">
75 body
{ font
-family
: verdana
, arial
, sans
-serif
; font
-size
: 12pt
}
76 div
{ font
-size
:12pt
}
83 li
{ padding
-bottom
: 7px
}
84 pre
{ font
-family
: verdana
, arial
, sans
-serif
; }
85 A
:link
, A
:visited
{ color
:blue
; text
-decoration
:none
}
86 A
:hover
{ color
:blue
; text
-decoration
:underline
}
87 A
:active
{ color
:#FAD805; text-decoration:underline }
88 .tt
{ font
-family
: Courier
; font
-size
:10pt
}
89 .mono
{ font
-family
: monospace
; font
-size
: 11pt
}
90 .large_mono
{ font
-family
: monospace
; font
-size
: 10pt
}
91 .giant_mono
{ font
-family
: monospace
; font
-size
: 14pt
}
92 .tiny_mono
{ font
-family
: monospace
; font
-size
: 6pt
}
93 .normal
{ font
-size
:10pt
}
94 .smaller
{ font
-size
:6pt
}
95 .small
{ font
-size
:8pt
}
96 .large
{ font
-size
:12pt
}
98 .focus_value
{ background
-color
:#DDDDDD }
99 .color_heading
{ margin
-top
:12px
; padding
:1px
; background
-color
:#DDDDDD; width:100% }
100 A
.label_link
{ font
-weight
:bold
; }
101 A
.highlight_link
{ font
-weight
:bold
; }
102 A
.cancel
{ background
-color
:#FFDDDD }
103 A
.plain
:link
, A
.plain
:visited
{ color
:black
; text
-decoration
:none
}
104 A
.plain
:hover
{ color
:blue
; text
-decoration
:underline
}
105 A
.plain
:active
{ color
:#FAD805; text-decoration:underline }
106 A
.name_dot
{ font
-size
:16pt
; font
-weight
:bold
; color
:green
; }
110 <body onload
="document.forms[0].<? echo $onload; ?>.focus()">
111 <table width
="320px">
115 if ($page == 'main') doMain();
116 elseif ($page == 'locations') doLocations();
118 if ($page == 'login') drawLogin();
119 elseif ($page == 'main') drawMain();
120 elseif ($page == 'locations') drawLocations();
129 global $qty, $type, $location, $take, $give;
130 global $client, $folder, $folder_loc, $folder_name;
131 global $values, $valueskv;
136 if ($type != '-- choose asset --') {
137 $t = $folder['types'][$type];
140 $min_precision = $t['min_precision'];
141 if ($min_precision == '') $min_precision = 0;
142 $scale = $t['scale'];
143 if ($scale == '') $scale = 0;
146 if ($location != '-- choose location --') {
147 $loc = $folder['locs'][$location];
149 if ($id != '' && $loc != '') {
150 if ($scale != '') $count = bcmul($qty, bcpow(10, $scale), 0);
152 if ($count != '' && $id != '' && $loc != '') {
154 $res = $client->move($id, $count, $loc, $folder_loc, $url);
155 $loc_orig = $location;
156 $loc_dest = $folder_name;
157 } else if ($give != '') {
158 $res = $client->move($id, $count, $folder_loc, $loc, $url);
159 $loc_dest = $location;
160 $loc_orig = $folder_name;
161 } else $transferred = FALSE;
163 $status = $res['status'];
164 if ($status == 'success') {
165 $value_orig = applyScale($res['value_orig'], $min_precision, $scale);
166 $value_dest = applyScale($res['value_dest'], $min_precision, $scale);
167 $values[$loc_orig][$type] = $value_orig;
168 ksort($values[$loc_orig]);
169 $values[$loc_dest][$type] = $value_dest;
170 ksort($values[$loc_dest]);
171 $valueskv = $client->array2kv($values);
172 } else $message = "Insufficient funds";
178 function doLocations() {
181 function drawLogin() {
184 <p
>Welcome to Loom
for iPhone
. Note that in order to
use this
185 confidently
, you must trust that the PHP scripts at billstclair
.com
do
186 not steal your passphrase
. I promise that unless somebody hacks my
187 site
, the code running is what you can download from
188 <a href
="index.html">here
</a
>, but don
't trust that unless you know
190 <form method="post" action="" autocomplete="off">
191 <input type="hidden" name="page" value="main"/>
195 <td><input type="password" name="passphrase" size="35" /></td>
199 <td><input type="submit" name="login" text="Login" /></td>
202 <p>It can take 10 or 20 seconds to read the initial values of all your
203 folder's locations
, more
if you have lots of locations
and asset
204 types
. Please be patient
. After the initial load
, things should be
210 function hsc($text) {
211 return htmlspecialchars($text);
214 function hiddenValue($name) {
215 eval('global $' . $name . ';');
216 echo '<input type="hidden" name="' . $name .
217 '" value="' . hsc(eval('return $' . $name . ';')) . '"/>' . "\n";
220 function drawValues($name, $typevalues) {
221 if (is_array($typevalues)) {
223 foreach ($typevalues as $type => $value) {
226 $str .= "<b>$name</b>\n";
227 $str .= '<table border="0"><tr><td width="50px"> </td><td>';
228 $str .= '<table border="0">' . "\n";
230 $str .= '<tr><td align="right">' . $value . "<td><td>$type</td></tr>\n";
235 echo "</table></td></tr></table>\n";
240 function drawMain() {
241 global $passphrase, $folder, $values, $folder_name;
242 global $qty, $type, $location;
248 <table border
="0" width
="99%" cellpadding
="3">
250 <td colspan
="2" style
="background-color: #c0c0c0; text-align: center;"><span style
="font-weight: bold; font-size: 110%;"><a href
="javascript:submitPage('refresh');">Refresh
</a
>
252 <a href
="javascript:submitPage('locations');">Locations
</a
>
258 drawValues($folder_name, $values[$folder_name]);
260 <table border
="0" width
="99%">
261 <form name
="mainform" method
="post" action
="" autocomplete
="off">
263 hiddenValue('passphrase'); echo "\n";
264 hiddenValue('folderkv'); echo "\n";
265 hiddenValue('valueskv');
269 <td align
="right">Qty
:</td
>
270 <td
><input style
="font-size: 12pt;" type
="text" size
="25" name
="zip" value
="<? echo $qty; ?>" style
="text-align:right;"></td
>
274 <select name
="type" style
="font-size: 10pt;">
275 <option value
="">-- choose asset
--</option
>
277 foreach ($folder['types'] as $typename => $typearray) {
278 echo '<option value="' . hsc($typename) . '"';
279 if ($type == $typename) echo ' selected="selected"';
280 echo '>' . hsc($typename) . "</option>\n";
288 <select name
="location" style
="font-size: 10pt;">
289 <option value
="">-- choose location
--</option
>
291 foreach($values as $loc => $value) {
292 if ($loc != $folder_name) {
293 echo '<option value="' . hsc($loc) . '"';
294 if ($loc == $location) echo ' selected="selected"';
295 echo '>' . hsc($loc) . "</option>\n";
304 <input style
="font-size: 10pt;" type
="submit" name
="take" value
="Take"/>
305 <input style
="font-size: 10pt;" type
="submit" name
="give" value
="Give"/>
309 if ($message != '') {
310 echo '<tr><td></td><td><span style="color: red; font-weight: bold;">' . hsc($message) . "</span></td></tr>\n";
315 foreach ($values as $name => $typevalues) {
316 if ($name != $folder_name) {
317 drawValues($name, $typevalues);
324 function drawLocations() {
325 global $passphrase, $folder, $values, $folder_name;
326 global $qty, $type, $location, $greendot;
331 <table border
="0" width
="99%" cellpadding
="3">
333 <td colspan
="2" style
="background-color: #c0c0c0; text-align: center;"><span style
="font-weight: bold; font-size: 110%;"><a href
="javascript:submitPage('main');">Folder
</a
>
340 <table border
="0" width
="99%">
341 <form name
="mainform" method
="post" action
="" autocomplete
="off">
343 hiddenValue('passphrase'); echo "\n";
344 hiddenValue('folderkv'); echo "\n";
345 hiddenValue('valueskv');
346 echo '<input type="hidden" name="zip" value="' . $qty . '"/>' . "\n";
348 hiddenValue('location');
351 <input type
="hidden" name
="greendot" value
=""/>
354 <td valign
="top"><a
class=name_dot href
="javascript: greenDot('<? echo $folder_name; ?>')" title
="Edit Name"> 
;&bull
; 
;</a
></td
>
357 if ($greendot != $folder_name) echo "<b>$folder_name</b>";
359 echo '<input style="font-size: 12pt;" type="text" size="25" name="newname" value="' . $folder_name . '"/><br/>' . "\n";
360 echo '<input type="submit" name="savename" value="Save"/>';
361 echo '<input type="submit" name="cancel" value="Cancel"/>';
364 $locs = $folder['locs'];
365 foreach ($locs as $name => $loc) {
366 if ($name != $folder_name) {
369 <td valign
="top"><a
class=name_dot href
="javascript: greenDot('<? echo $name; ?>')" title
="Edit Name or Delete Folder"> 
;&bull
; 
;</a
></td
>
372 if ($greendot != $name) echo $name;
374 echo '<input style="font-size: 12pt;" type="text" size="25" name="newname" value="' . $name . '"/><br/>' . "\n";
375 echo '<input type="submit" name="savename" value="Save"/>';
376 echo '<input type="submit" name="cancel" value="Cancel"/>';
378 echo '<input type="submit" name="delete" value="Delete..."/><br/>';
379 echo '</td></tr><tr><td colspan="2"><span class="mono">' . "<b>$loc</b></span><br/>\n";
384 ?
><tr
><td colspan
="2"><input type
="submit" name
="add_location" value
="Add Location"/></td
></tr
>
387 <p
>Click the green dot by a folder name to see its hex value
, or to rename
or delete it
.</p
>
392 global $client, $passphrase, $folder, $folderkv, $folder_name, $folder_loc;
395 $loc = $client->hash2location($client->sha256($passphrase));
396 $res = $client->touch_archive($loc, $url);
397 if ($res['status'] != 'success') return FALSE;
398 $folder = $client->parseFolder($loc, $res['content']);
399 $folderkv = $client->array2kv($folder);
401 $folder_name = $folder['name'];
402 $folder_loc = $folder['loc'];
406 function blankToZero($x) {
407 if ($x == '') return 0;
411 function applyScale($value, $min_precision, $scale) {
412 if ($value < 0) $value++
;
413 if ($scale > 0) $value = bcdiv($value, bcpow(10, $scale, 0), $scale);
415 $dotpos = strpos($value, '.');
418 while (substr($value, -1) == '0') {
419 $value = substr($value, 0, strlen($value)-1);
421 if (substr($value, -1) == '.') {
422 $value = substr($value, 0, strlen($value)-1);
427 if ($min_precision > 0) {
430 $dotpos = strlen($value);
432 $places = strlen($value) - $dotpos;
433 if ($min_precision > $places) {
434 $value .= str_repeat("0", $min_precision - $places);
440 // This is currently n-squared for pretty big n, since it has to do
441 // a web call for each location/type pair.
442 // Patrick has promised a scan() function in the web API that would
443 // allow it to be done with a single call.
444 function scanFolder($folder) {
447 $types = $folder['types'];
448 $locs = $folder['locs'];
450 foreach ($locs as $locname => $loc) {
451 $loc_values = array();
452 foreach ($types as $typename => $type) {
454 $min_precision = $type['min_precision'];
455 $scale = $type['scale'];
456 $res = $client->touch($id, $loc, $url);
457 if ($res['status'] == 'success') {
458 $value = applyScale($res['value'], $min_precision, $scale);
459 $loc_values[$typename] = $value;
462 $values[$locname] = $loc_values;