If you need help setting up either webhooks, or toolmapping let me know. I've also attached the old sedit script if it gives you some ideas. Haven't tried it--might come close to working as it is. You could easily change the markup that triggers the section marker from !! Header to [[#anchor]].
Don't have time right now to revise this myself, but if you get stuck, let me know. I can get to it early next week. Cheers, Dan On Fri Dec 05 2014 at 7:38:20 AM Tiffany Grenier <[email protected]> wrote: > Hi again, > > I totally get your points. About the complexity, I think that the part of > code in these functions that is currently dealing with anchors could be > externalized. Then I would simply have to use a webhooks for this. That's > the way I will explore now :-) > I also wanted to rewrite the sedit plugin later on with the use again of > its own "read/write" functions... but in a way that they would now > introduce start and end anchors. My main issue with the current way of > dealing with anchors, which also would also mess up sedit in the way you > would see it, is the following: let's simply suppose there is an anchor > [[#a]] in the section I want... then I would be unable to edit the entirery > of my section, since it would start at [[#section1]] and stop at [[#a]], > which comes before the end of the section! > > Cheers, > Tiffany > > Le jeudi 20 novembre 2014 08:18:14 UTC+1, Tiffany Grenier a écrit : > >> Hi, >> As promised some time ago, I have been working on a refactoring of sedit >> in order to extend it to editing anything between two given anchors, and >> not only between two section titles. >> If this were included into the core scripts, then the sedit plugin would >> only be a matter of inserting fake anchors at the beginning and ending of >> each section, thus even allowing to edit any level of sections one could >> wish. >> >> There it goes (I modified source and loadpage as well as savepage in >> order to be able to display as well as edit): >> >> function BOLTFsource($args) { >> global $pageLink, $BOLTid, $BOLTcommands, $BOLTsession; >> if (! is_array($args)) $args = BOLTargs($args); >> if (isset($args['post']) && isset($_POST[$args['post']])) return >> BOLTescape(htmlspecialchars($_POST[$args['post']])); >> if (isset($args['cookie']) && isset($_COOKIE[$args['cookie']])) >> return BOLTescape(htmlspecialchars($_COOKIE[$args['cookie']])); >> if (isset($args['get']) && isset($_GET[$args['get']])) return >> BOLTescape(htmlspecialchars($_GET[$args['get']])); >> if (isset($BOLTcommands[$args['command']])) return >> $BOLTcommands[$args['command']]; >> $page = BOLTinit($args[1], $args['page']); >> if ($page == '') return; >> if (strpos($page, ':') !== false) { >> $data = substr($page, strpos($page, ':')); >> $page = substr($page, 0, strpos($page, ':')); >> } >> if (strpos($page, '#') !== false) { >> $anchors = substr($page, strpos($page, '#')); >> $page = substr($page, 0, strpos($page, '#')); >> if (strrpos($anchors, '#',strpos($anchors, '#')+1) !== false) { >> $lastanchor = substr($anchors, strrpos($anchors, '#')); >> $firstanchor = substr($anchors, 0, strpos($anchors, >> $lastanchor)); >> } >> else { >> $firstanchor = $anchors; >> $lastanchor = ''; >> } >> } >> $page = BOLTpageshortcuts($page); >> if (BOLTfilter($page, 'page') == '') return; >> if (BOLTauth($page, $BOLTid, 'view') === false) >> BOLTmessage("func_source_auth::$page", $args); >> if ($data != '') { >> if ($args['dir'] == 'stamps') $out = BOLTvars("$page$firstanchor*$ >> data"); >> else $out = BOLTvars("$page$firstanchor$data"); >> } >> else { >> if ($args['dir'] == 'stamps') $out = >> BOLTloadpage("$page$firstanchor$lastanchor", >> $args['dir']); >> else $out = BOLTloadpage("$page$firstanchor$lastanchor"); >> if (isset($args['lines'])) $out = BOLTgetlines($out, >> $args['lines']); >> } >> $out = BOLTescape($out, false); >> $out = BOLTcharEncode($out, $args['fmt']); >> if (trim($out) == '') return $args['default']; >> if ($args['escape'] !== 'false') $out = BOLTescape($out); >> BOLTmessage("func_source::$page", $args); >> return $out; >> } >> >> >> function BOLTloadpage($page, $dir='', $data='', $auth=false) { >> ## LOADS PAGE AT $LOCATION (PAGES/FILE NAME), RETURNS CONTENTS. SET $DATA >> TO 'data' TO RETRIEVE DATA WITH PAGE TEXT >> if (function_exists('myBOLTloadpage')) return myBOLTloadpage($page, >> $dir, $data, $auth); >> if ($auth) { >> global $BOLTid; >> if (BOLTauth($page, $BOLTid, 'view') == false) return; >> } >> if ($page == '') return; >> global $systemPath, $BOLTpageStore, $BOLTpageLibraries; >> if (strpos($page, "#") !== false) { >> $anchors = substr($page, strpos($page, '#')); >> $page = substr($page, 0, strpos($page, "#")); >> if (strrpos($anchors, '#',strpos($anchors, '#')+1) !== false) { >> $lastanchor = BOLTurl2utf(substr($anchors, strrpos($anchors, >> '#'))); >> $firstanchor = BOLTurl2utf(substr($anchors, 0, >> strpos($anchors, $lastanchor))); >> } >> else { >> $firstanchor = BOLTurl2utf($anchors); >> $lastanchor = '#'; >> } >> } >> if ($dir == '' && $BOLTpageLibraries != '') { // checks for pages >> outside of pages folder... >> $index = substr($page, 0, strpos($page, '.')); >> if (isset($BOLTpageLibraries[$index])) $dir = >> $BOLTpageLibraries[$index]; >> } >> if ($page != 'site.config' && $page != 'site.folders') { >> $page = strtolower(BOLTutf2url($page)); >> $fpage = BOLTfolders($page); >> } >> else $fpage = $page; >> if ($dir != '') { >> $location = "$dir/$page"; >> if (file_exists($location) == false) return; >> } >> elseif (file_exists("pages/$fpage")) $location = "pages/$fpage"; >> elseif (file_exists("$systemPath/$page")) $location = >> "$systemPath/$page"; >> else return; >> if ($dir != '' || ($BOLTpageStore[$page] == '' && filesize($location) >> > 0)) { >> $handle = fopen($location, "rb"); >> $contents = fread($handle, filesize($location)); >> fclose($handle); >> $BOLTpageStore[$page] = str_replace(Array("\r\n", "\r"), "\n", >> $contents); >> } >> $out = $BOLTpageStore[$page]; >> if ($data != 'data' && strpos($out, "\n~data~\n") !== false) { >> $out = substr($out, 0, strpos($out, "\n~data~\n")); >> $out = str_replace('~', '~', $out); >> if (substr($page, 0, 5) != 'code.') $out = str_replace('<', >> '<', $out); >> } >> if (isset($firstanchor)) { >> if ($firstanchor == '#') { >> if (strpos($out, '[['.$lastanchor) !== false) return >> substr($out, 0, strpos($out, '[['.$lastanchor)); >> return $out; >> } >> elseif (preg_match('/\[\['.$firstanchor.'(\|.+)?\]\]/', $out, >> $matches) == 1) { >> $out = substr($out, strpos($out, $matches[0]) + >> strlen($matches[0])); >> if (strpos($out, '[['.$lastanchor) !== false) return >> substr($out, 0, strpos($out, '[['.$lastanchor)); >> return $out; >> } >> return; >> } >> return $out; >> } >> >> >> function BOLTsavepage($page, $newcontent='', $newdata='', $loadtime='') { >> ## SYSTEM FUNCTION FOR SAVING PAGES, SECURES AGAINST DISALLOWED CODE >> if (function_exists('myBOLTsavepage')) return myBOLTsavepage($page, >> $newcontent, $newdata, $loadtime); >> global $systemPath, $BOLTsession, $BOLTpageStore, $lastedit, >> $pageLink, $BOLTindexPages; >> if($loadtime == '') $loadtime = time(); >> if (strpos($page, '#') !== false) { // Note: can't find >> [[#anchor|label]], just [[#anchor]] >> $anchors = substr($page, strpos($page, '#')); >> if (strrpos($anchors, '#',strpos($anchors, '#')+1) !== false) { >> $lastanchor = '[[' . BOLTurl2utf(substr($anchors, >> strrpos($anchors, '#'))) . ']]'; >> $firstanchor = '[[' . BOLTurl2utf(substr($anchors, 0, >> strrpos($anchors, '#',strpos($anchors, '#')+1))) . ']]'; >> } >> else { >> $firstanchor = '[[' . BOLTurl2utf($anchors) . ']]'; >> $lastanchor = '[[#'; >> } >> $page = BOLTutf2url(substr($page, 0, strpos($page, '#'))); >> } >> $page = BOLTfilter(strtolower($page), 'page'); >> if ($page == '') BOLTabort('invalid_page_name'); >> $fpage = BOLTfolders($page); >> if (file_exists("pages/$fpage")) { >> $getpage = BOLTloadpage($page, '', 'data'); >> if (strpos($getpage, "\n~data~\n") !== false) { >> $data = substr($getpage, strpos($getpage, "\n~data~\n")); >> $oldcontent = substr($getpage, 0, strpos($getpage, >> "\n~data~\n")); >> } >> else $oldcontent = $getpage; >> } >> if ($newdata != '') $data = $newdata; // newdata must already be >> formatted... >> if ($newcontent != '') { >> $newcontent = BOLTsafetext($newcontent, $page); >> if ($firstanchor != '') { >> if (strpos($oldcontent, $firstanchor) === false) { >> $content = $oldcontent . "\n$firstanchor\n" . $newcontent; >> if($lastanchor != '[[#') { >> $content .= $lastanchor; >> } >> } >> else { >> $before = substr($oldcontent, 0, strpos($oldcontent, >> $firstanchor)); >> $start = substr($oldcontent, strpos($oldcontent, >> $firstanchor) + strlen($firstanchor)); >> if (strpos($start, $lastanchor) !== false) $after = >> substr($start, strpos($start, $lastanchor));//$lastanchor already belongs >> to $after >> else { >> $after = ''; >> if($lastanchor != '[[#') { >> $after = $lastanchor.$after; >> } >> } >> $content = $before . "\n" . $firstanchor . "\n" . >> $newcontent . $after; >> } >> } >> else $content = $newcontent; >> $content = trim($content); >> } >> else $content = $oldcontent; >> if ($content != $oldcontent) { >> if (substr($content, -8) == "\n~data~\n") $content = >> substr($content, 0, -8); // is this necessary? >> if ($loadtime != '' && file_exists("pages/$fpage")) { >> $lastmodified = filemtime("pages/$fpage") + >> BOLTconfig('localTime', 0) * 3600; >> if (is_int($loadtime) && $loadtime < $lastmodified) { >> $out = "<box>\n" . 'Page $1 has been modified by another >> user ('.strftime("%c",$lastmodified).') and their changes may have been >> overwritten. Click [[$1&action=undo|+]] to view changed content.' . >> "\n</box>\n\n"; >> $out = str_replace('$1', $page, $out); >> $content = $out.$content; >> } >> } >> } >> if ($oldcontent == '' || $content != $oldcontent || $date != >> $newdata) {//allow creation of new page but avoid unecessary writing into >> file >> $mypage = fopen("pages/$fpage", "wb"); >> fwrite($mypage, $content.$data); >> fclose($mypage); >> } >> $BOLTindexPages[] = $page; >> $BOLTpageStore[$page] = $content.$data; >> clearstatcache(); >> } >> >> >> I think one can do a bit of generalization from this, but did not yet >> figure out how to shorten these functions. Any help or thought wil be >> highly appreciated. >> >> Cheers, >> Tiffany >> > > > Le mercredi 26 novembre 2014 17:58:14 UTC+1, Dan a écrit : >> >> I've been looking at this for a while and decided not to implement these >> in the core, for several reasons: >> >> 1) it seems to introduce a level of complexity I'm not comfortable with. >> >> 2) there are easy webhooks for the loadpage and save page functions, and >> you can use toolmapping for the source function. In other words, you should >> be able to get full plug and play functionality in your plugin without >> requiring a change in the core. >> >> If you are not sure how to do either webhooks or toolmapping, let me know. >> >> Also, if I recall correctly, the sedit plugin worked differently >> anyway--with it's own read and write functions, so you didn't even have to >> use anchors. I'd be happy to either tinker with it and get it back up to >> speed, or send you the old scripts if you want to look at them. >> >> If I were to redo it now that BoltWire has the capability of editing >> sections in the core I'd be inclined to try something like this: >> >> [[#section1]] Some Section >> text >> text >> >> Then write a markup rule which simply converts the first line into code >> like the following: >> >> [[#section1]] >> !! Some Section >> [[{p}&action=sedit§ion=section1|Edit Section]] >> text >> text >> >> That would take just a handful of lines and be easy enough to deploy. >> Lot's of ways to tweak it too based on what you want, just thinking out >> loud. >> >> Let me know what you think? I'd like to see a good section edit plugin >> back in the extensions area... >> >> Cheers, >> Dan >> >> >> >> >> On Thu Nov 20 2014 at 1:18:15 AM Tiffany Grenier <[email protected]> >> wrote: >> > Hi, >>> As promised some time ago, I have been working on a refactoring of sedit >>> in order to extend it to editing anything between two given anchors, and >>> not only between two section titles. >>> If this were included into the core scripts, then the sedit plugin would >>> only be a matter of inserting fake anchors at the beginning and ending of >>> each section, thus even allowing to edit any level of sections one could >>> wish. >>> >>> There it goes (I modified source and loadpage as well as savepage in >>> order to be able to display as well as edit): >>> >>> function BOLTFsource($args) { >>> global $pageLink, $BOLTid, $BOLTcommands, $BOLTsession; >>> if (! is_array($args)) $args = BOLTargs($args); >>> if (isset($args['post']) && isset($_POST[$args['post']])) return >>> BOLTescape(htmlspecialchars($_POST[$args['post']])); >>> if (isset($args['cookie']) && isset($_COOKIE[$args['cookie']])) >>> return BOLTescape(htmlspecialchars($_COOKIE[$args['cookie']])); >>> if (isset($args['get']) && isset($_GET[$args['get']])) return >>> BOLTescape(htmlspecialchars($_GET[$args['get']])); >>> if (isset($BOLTcommands[$args['command']])) return >>> $BOLTcommands[$args['command']]; >>> $page = BOLTinit($args[1], $args['page']); >>> if ($page == '') return; >>> if (strpos($page, ':') !== false) { >>> $data = substr($page, strpos($page, ':')); >>> $page = substr($page, 0, strpos($page, ':')); >>> } >>> if (strpos($page, '#') !== false) { >>> $anchors = substr($page, strpos($page, '#')); >>> $page = substr($page, 0, strpos($page, '#')); >>> if (strrpos($anchors, '#',strpos($anchors, '#')+1) !== false) { >>> $lastanchor = substr($anchors, strrpos($anchors, '#')); >>> $firstanchor = substr($anchors, 0, strpos($anchors, >>> $lastanchor)); >>> } >>> else { >>> $firstanchor = $anchors; >>> $lastanchor = ''; >>> } >>> } >>> $page = BOLTpageshortcuts($page); >>> if (BOLTfilter($page, 'page') == '') return; >>> if (BOLTauth($page, $BOLTid, 'view') === false) >>> BOLTmessage("func_source_auth::$page", $args); >>> if ($data != '') { >>> if ($args['dir'] == 'stamps') $out = >>> BOLTvars("$page$firstanchor*$data"); >>> else $out = BOLTvars("$page$firstanchor$data"); >>> } >>> else { >>> if ($args['dir'] == 'stamps') $out = >>> BOLTloadpage("$page$firstanchor$lastanchor", >>> $args['dir']); >>> else $out = BOLTloadpage("$page$firstanchor$lastanchor"); >>> if (isset($args['lines'])) $out = BOLTgetlines($out, >>> $args['lines']); >>> } >>> $out = BOLTescape($out, false); >>> $out = BOLTcharEncode($out, $args['fmt']); >>> if (trim($out) == '') return $args['default']; >>> if ($args['escape'] !== 'false') $out = BOLTescape($out); >>> BOLTmessage("func_source::$page", $args); >>> return $out; >>> } >>> >>> >>> function BOLTloadpage($page, $dir='', $data='', $auth=false) { >>> ## LOADS PAGE AT $LOCATION (PAGES/FILE NAME), RETURNS CONTENTS. SET >>> $DATA TO 'data' TO RETRIEVE DATA WITH PAGE TEXT >>> if (function_exists('myBOLTloadpage')) return myBOLTloadpage($page, >>> $dir, $data, $auth); >>> if ($auth) { >>> global $BOLTid; >>> if (BOLTauth($page, $BOLTid, 'view') == false) return; >>> } >>> if ($page == '') return; >>> global $systemPath, $BOLTpageStore, $BOLTpageLibraries; >>> if (strpos($page, "#") !== false) { >>> $anchors = substr($page, strpos($page, '#')); >>> $page = substr($page, 0, strpos($page, "#")); >>> if (strrpos($anchors, '#',strpos($anchors, '#')+1) !== false) { >>> $lastanchor = BOLTurl2utf(substr($anchors, strrpos($anchors, >>> '#'))); >>> $firstanchor = BOLTurl2utf(substr($anchors, 0, >>> strpos($anchors, $lastanchor))); >>> } >>> else { >>> $firstanchor = BOLTurl2utf($anchors); >>> $lastanchor = '#'; >>> } >>> } >>> if ($dir == '' && $BOLTpageLibraries != '') { // checks for pages >>> outside of pages folder... >>> $index = substr($page, 0, strpos($page, '.')); >>> if (isset($BOLTpageLibraries[$index])) $dir = >>> $BOLTpageLibraries[$index]; >>> } >>> if ($page != 'site.config' && $page != 'site.folders') { >>> $page = strtolower(BOLTutf2url($page)); >>> $fpage = BOLTfolders($page); >>> } >>> else $fpage = $page; >>> if ($dir != '') { >>> $location = "$dir/$page"; >>> if (file_exists($location) == false) return; >>> } >>> elseif (file_exists("pages/$fpage")) $location = "pages/$fpage"; >>> elseif (file_exists("$systemPath/$page")) $location = >>> "$systemPath/$page"; >>> else return; >>> if ($dir != '' || ($BOLTpageStore[$page] == '' && >>> filesize($location) > 0)) { >>> $handle = fopen($location, "rb"); >>> $contents = fread($handle, filesize($location)); >>> fclose($handle); >>> $BOLTpageStore[$page] = str_replace(Array("\r\n", "\r"), "\n", >>> $contents); >>> } >>> $out = $BOLTpageStore[$page]; >>> if ($data != 'data' && strpos($out, "\n~data~\n") !== false) { >>> $out = substr($out, 0, strpos($out, "\n~data~\n")); >>> $out = str_replace('~', '~', $out); >>> if (substr($page, 0, 5) != 'code.') $out = str_replace('<', >>> '<', $out); >>> } >>> if (isset($firstanchor)) { >>> if ($firstanchor == '#') { >>> if (strpos($out, '[['.$lastanchor) !== false) return >>> substr($out, 0, strpos($out, '[['.$lastanchor)); >>> return $out; >>> } >>> elseif (preg_match('/\[\['.$firstanchor.'(\|.+)?\]\]/', $out, >>> $matches) == 1) { >>> $out = substr($out, strpos($out, $matches[0]) + >>> strlen($matches[0])); >>> if (strpos($out, '[['.$lastanchor) !== false) return >>> substr($out, 0, strpos($out, '[['.$lastanchor)); >>> return $out; >>> } >>> return; >>> } >>> return $out; >>> } >>> >>> >>> function BOLTsavepage($page, $newcontent='', $newdata='', $loadtime='') { >>> ## SYSTEM FUNCTION FOR SAVING PAGES, SECURES AGAINST DISALLOWED CODE >>> if (function_exists('myBOLTsavepage')) return myBOLTsavepage($page, >>> $newcontent, $newdata, $loadtime); >>> global $systemPath, $BOLTsession, $BOLTpageStore, $lastedit, >>> $pageLink, $BOLTindexPages; >>> if($loadtime == '') $loadtime = time(); >>> if (strpos($page, '#') !== false) { // Note: can't find >>> [[#anchor|label]], just [[#anchor]] >>> $anchors = substr($page, strpos($page, '#')); >>> if (strrpos($anchors, '#',strpos($anchors, '#')+1) !== false) { >>> $lastanchor = '[[' . BOLTurl2utf(substr($anchors, >>> strrpos($anchors, '#'))) . ']]'; >>> $firstanchor = '[[' . BOLTurl2utf(substr($anchors, 0, >>> strrpos($anchors, '#',strpos($anchors, '#')+1))) . ']]'; >>> } >>> else { >>> $firstanchor = '[[' . BOLTurl2utf($anchors) . ']]'; >>> $lastanchor = '[[#'; >>> } >>> $page = BOLTutf2url(substr($page, 0, strpos($page, '#'))); >>> } >>> $page = BOLTfilter(strtolower($page), 'page'); >>> if ($page == '') BOLTabort('invalid_page_name'); >>> $fpage = BOLTfolders($page); >>> if (file_exists("pages/$fpage")) { >>> $getpage = BOLTloadpage($page, '', 'data'); >>> if (strpos($getpage, "\n~data~\n") !== false) { >>> $data = substr($getpage, strpos($getpage, "\n~data~\n")); >>> $oldcontent = substr($getpage, 0, strpos($getpage, >>> "\n~data~\n")); >>> } >>> else $oldcontent = $getpage; >>> } >>> if ($newdata != '') $data = $newdata; // newdata must already be >>> formatted... >>> if ($newcontent != '') { >>> $newcontent = BOLTsafetext($newcontent, $page); >>> if ($firstanchor != '') { >>> if (strpos($oldcontent, $firstanchor) === false) { >>> $content = $oldcontent . "\n$firstanchor\n" . >>> $newcontent; >>> if($lastanchor != '[[#') { >>> $content .= $lastanchor; >>> } >>> } >>> else { >>> $before = substr($oldcontent, 0, strpos($oldcontent, >>> $firstanchor)); >>> $start = substr($oldcontent, strpos($oldcontent, >>> $firstanchor) + strlen($firstanchor)); >>> if (strpos($start, $lastanchor) !== false) $after = >>> substr($start, strpos($start, $lastanchor));//$lastanchor already belongs >>> to $after >>> else { >>> $after = ''; >>> if($lastanchor != '[[#') { >>> $after = $lastanchor.$after; >>> } >>> } >>> $content = $before . "\n" . $firstanchor . "\n" . >>> $newcontent . $after; >>> } >>> } >>> else $content = $newcontent; >>> $content = trim($content); >>> } >>> else $content = $oldcontent; >>> if ($content != $oldcontent) { >>> if (substr($content, -8) == "\n~data~\n") $content = >>> substr($content, 0, -8); // is this necessary? >>> if ($loadtime != '' && file_exists("pages/$fpage")) { >>> $lastmodified = filemtime("pages/$fpage") + >>> BOLTconfig('localTime', 0) * 3600; >>> if (is_int($loadtime) && $loadtime < $lastmodified) { >>> $out = "<box>\n" . 'Page $1 has been modified by another >>> user ('.strftime("%c",$lastmodified).') and their changes may have been >>> overwritten. Click [[$1&action=undo|+]] to view changed content.' . >>> "\n</box>\n\n"; >>> $out = str_replace('$1', $page, $out); >>> $content = $out.$content; >>> } >>> } >>> } >>> if ($oldcontent == '' || $content != $oldcontent || $date != >>> $newdata) {//allow creation of new page but avoid unecessary writing into >>> file >>> $mypage = fopen("pages/$fpage", "wb"); >>> fwrite($mypage, $content.$data); >>> fclose($mypage); >>> } >>> $BOLTindexPages[] = $page; >>> $BOLTpageStore[$page] = $content.$data; >>> clearstatcache(); >>> } >>> >>> >>> I think one can do a bit of generalization from this, but did not yet >>> figure out how to shorten these functions. Any help or thought wil be >>> highly appreciated. >>> >>> Cheers, >>> Tiffany >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "BoltWire" group. >>> >> To unsubscribe from this group and stop receiving emails from it, send an >>> email to [email protected]. >>> To post to this group, send email to [email protected]. >> >> >>> Visit this group at http://groups.google.com/group/boltwire. >>> For more options, visit https://groups.google.com/d/optout. >>> >> -- > You received this message because you are subscribed to the Google Groups > "BoltWire" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/boltwire. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "BoltWire" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/boltwire. For more options, visit https://groups.google.com/d/optout.
<<attachment: sedit.php>>
