diff --git a/inc/app/cms/boxes/parallel/approve/CVS/Entries b/inc/app/cms/boxes/parallel/approve/CVS/Entries new file mode 100644 index 00000000..1c8667ac --- /dev/null +++ b/inc/app/cms/boxes/parallel/approve/CVS/Entries @@ -0,0 +1,2 @@ +/index.php/1.1/Tue Feb 20 19:26:57 2007// +D diff --git a/inc/app/cms/boxes/parallel/approve/CVS/Repository b/inc/app/cms/boxes/parallel/approve/CVS/Repository new file mode 100644 index 00000000..287991a0 --- /dev/null +++ b/inc/app/cms/boxes/parallel/approve/CVS/Repository @@ -0,0 +1 @@ +pro/inc/app/cms/boxes/parallel/approve diff --git a/inc/app/cms/boxes/parallel/approve/CVS/Root b/inc/app/cms/boxes/parallel/approve/CVS/Root new file mode 100644 index 00000000..a46761f7 --- /dev/null +++ b/inc/app/cms/boxes/parallel/approve/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@jd:/usr/local/cvsroot diff --git a/inc/app/cms/boxes/parallel/approve/index.php b/inc/app/cms/boxes/parallel/approve/index.php new file mode 100755 index 00000000..6467bd30 --- /dev/null +++ b/inc/app/cms/boxes/parallel/approve/index.php @@ -0,0 +1,16 @@ +approve ($parameters['revision_id'])) { + die ($p->error); +} + +header ('Location: ' . site_prefix () . '/index/' . $parameters['id']); +exit; + +?> \ No newline at end of file diff --git a/inc/app/cms/boxes/parallel/index.php b/inc/app/cms/boxes/parallel/index.php new file mode 100755 index 00000000..e85c7cbf --- /dev/null +++ b/inc/app/cms/boxes/parallel/index.php @@ -0,0 +1,59 @@ +set_goal ($parameters['goal_url']); +} + +function parallel_filter_height ($value, $total, $new_base) { + $div_by = $total / $new_base; + if ($div_by > 0) { + $ret = ceil ($value / $div_by); + if ($ret > 250) { + return 250; + } + if ($ret < 16) { + return 16; + } + return $ret; + } + return 16; +} + +if (empty ($p->goal_url)) { + page_title (intl_get ('Parallel Page') . ': ' . $parameters['id']); + echo template_simple ('parallel_goal.spt', $parameters); +} else { + page_title (intl_get ('Parallel Stats') . ': ' . $parameters['id']); + $parameters['stats'] = $p->get_stats (); + if ($p->total_views == 0) { + echo template_simple ('parallel_nostats.spt'); + return; + } + foreach ($parameters['stats'] as $k => $v) { + $parameters['stats'][$k]['click_height'] = parallel_filter_height ($v['clicked'], $p->total_clicks, 150); + $parameters['stats'][$k]['view_height'] = parallel_filter_height ($v['viewed'], $p->total_views, 450); + } + $parameters['total_views'] = $p->total_views; + $parameters['total_clicks'] = $p->total_clicks; + + loader_import ('saf.Date'); + + $parameters['duration'] = round ((time () - strtotime ($p->campaign_start)) / 86400, 1); + $parameters['goal'] = $p->goal_url; + $parameters['versions'] = count ($parameters['stats']); + + page_add_style ( + template_simple ( + 'parallel_css.spt', + $parameters + ) + ); + echo template_simple ('parallel_stats.spt', $parameters); + //info ($stats, true); +} + +?> \ No newline at end of file diff --git a/inc/app/cms/boxes/parallel/rpc/CVS/Entries b/inc/app/cms/boxes/parallel/rpc/CVS/Entries new file mode 100644 index 00000000..78ac730e --- /dev/null +++ b/inc/app/cms/boxes/parallel/rpc/CVS/Entries @@ -0,0 +1,3 @@ +/access.php/1.1/Tue Feb 20 19:26:57 2007// +/index.php/1.1/Tue Feb 20 19:26:57 2007// +D diff --git a/inc/app/cms/boxes/parallel/rpc/CVS/Repository b/inc/app/cms/boxes/parallel/rpc/CVS/Repository new file mode 100644 index 00000000..1f88e6dc --- /dev/null +++ b/inc/app/cms/boxes/parallel/rpc/CVS/Repository @@ -0,0 +1 @@ +pro/inc/app/cms/boxes/parallel/rpc diff --git a/inc/app/cms/boxes/parallel/rpc/CVS/Root b/inc/app/cms/boxes/parallel/rpc/CVS/Root new file mode 100644 index 00000000..a46761f7 --- /dev/null +++ b/inc/app/cms/boxes/parallel/rpc/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@jd:/usr/local/cvsroot diff --git a/inc/app/cms/boxes/parallel/rpc/access.php b/inc/app/cms/boxes/parallel/rpc/access.php new file mode 100755 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/cms/boxes/parallel/rpc/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/cms/boxes/parallel/rpc/index.php b/inc/app/cms/boxes/parallel/rpc/index.php new file mode 100755 index 00000000..6750c10b --- /dev/null +++ b/inc/app/cms/boxes/parallel/rpc/index.php @@ -0,0 +1,16 @@ + $page_id)); + return $p->clicked ($revision_id); + } +} + +echo rpc_handle (new Parallel_RPC_Handler (), $parameters); +exit; + +?> \ No newline at end of file diff --git a/inc/app/cms/conf/collections/sitebanner_ad.php b/inc/app/cms/conf/collections/sitebanner_ad.php new file mode 100755 index 00000000..d75ffa28 --- /dev/null +++ b/inc/app/cms/conf/collections/sitebanner_ad.php @@ -0,0 +1,163 @@ +; 'Yes', 'no' => 'No')" + +[facet:section] + +type = select +display = Section +values = "loader_call ('sitebanner.MenuSections', 'menu_get_sections')" + +[hint:name] + +alt = Ad Name +rule 1 = not empty, You must enter a name for your ad. + +[hint:purchased] + +type = text +alt = "Purchased Impressions (-1 for unlimited)" + +[hint:impressions] + +type = hidden + +[hint:url] + +alt = URL +extra = "size='40'" + +[hint:description] + +type = textarea +cols = 40 +rows = 2 +labelPosition = left + +[hint:client] + +type = select +setValues = "eval: db_pairs ('select username, concat(role, ` - `, lastname, ` `, firstname, ` (`, username, `)`) as name from sitellite_user order by name asc')" + +[hint:display_url] + +alt = Alternate Text +extra = "size='40'" + +[hint:file] + +type = sitebanner.Widgets.Shapeshifter + +[hint:section] + +type = multiple +size = 5 +alt = Display in Sections +setValues = "eval: array_merge (array ('' => '- ALL -'), loader_call ('sitebanner.MenuSections', 'menu_get_sections'))" + +[hint:position] + +type = selector +alt = Screen Position +table = sitebanner_position +key = name + +[hint:active] + +alt = "Is Active?" + +[hint:format] + +setValues = "eval: array ('external' => 'External Link', 'adsense' => 'Google(TM) AdSense', 'html' => 'HTML', 'image' => 'Image', 'text' => 'Text')" +extra = "onchange='this.form.submit ()'"; + +[hint:target] + +setValues = "eval: array ('blank' => 'New Window', 'parent' => 'Parent Frame', 'self' => 'Same Frame', 'top' => 'Top Frame')" + +; */ ?> \ No newline at end of file diff --git a/inc/app/cms/conf/collections/sitelinks_item.php b/inc/app/cms/conf/collections/sitelinks_item.php new file mode 100755 index 00000000..b36fdac6 --- /dev/null +++ b/inc/app/cms/conf/collections/sitelinks_item.php @@ -0,0 +1,164 @@ +; \ No newline at end of file diff --git a/inc/app/cms/conf/collections/sitellite_form_submission.php b/inc/app/cms/conf/collections/sitellite_form_submission.php index af00f77c..54b8af99 100755 --- a/inc/app/cms/conf/collections/sitellite_form_submission.php +++ b/inc/app/cms/conf/collections/sitellite_form_submission.php @@ -43,6 +43,13 @@ text = Export Contacts url = /index/sitellite-export-form +[link:sitemailer2] + +requires = r +requires resource = app_sitemailer2 +text = "Add to Newsletter" +url = "/index/sitemailer2-import-submissions-form" + [browse:id] header = ID diff --git a/inc/app/cms/conf/collections/sitemailer2_message.php b/inc/app/cms/conf/collections/sitemailer2_message.php new file mode 100755 index 00000000..4076c1c0 --- /dev/null +++ b/inc/app/cms/conf/collections/sitemailer2_message.php @@ -0,0 +1,80 @@ +; diff --git a/inc/app/cms/conf/collections/sitemailer2_recipient.php b/inc/app/cms/conf/collections/sitemailer2_recipient.php new file mode 100755 index 00000000..3f659de5 --- /dev/null +++ b/inc/app/cms/conf/collections/sitemailer2_recipient.php @@ -0,0 +1,106 @@ +; 'Active', 'unverified' => 'Unverified', 'disabled' => 'Disabled')" +count = off + +; */ ?> \ No newline at end of file diff --git a/inc/app/cms/conf/collections/sitemailer2_template.php b/inc/app/cms/conf/collections/sitemailer2_template.php new file mode 100755 index 00000000..eed27884 --- /dev/null +++ b/inc/app/cms/conf/collections/sitemailer2_template.php @@ -0,0 +1,72 @@ +; diff --git a/inc/app/cms/conf/collections/siteshop_product.php b/inc/app/cms/conf/collections/siteshop_product.php new file mode 100755 index 00000000..d9561c81 --- /dev/null +++ b/inc/app/cms/conf/collections/siteshop_product.php @@ -0,0 +1,81 @@ +; \ No newline at end of file diff --git a/inc/app/cms/html/parallel_css.spt b/inc/app/cms/html/parallel_css.spt new file mode 100755 index 00000000..9e52f4b1 --- /dev/null +++ b/inc/app/cms/html/parallel_css.spt @@ -0,0 +1,96 @@ +#parallel-stats-graph { + position: relative; + width: {php obj[versions] x 150}px; + height: 300px; + margin: 1.1em 0 3.5em; + padding: 0; + background: #eee; + border: 1px solid #0081d6; + list-style: none; + font: 9px Helvetica, Geneva, sans-serif; +} + +#parallel-stats-graph ul { + margin: 0; + padding: 0; + list-style: none; +} + +#parallel-stats-graph li { + position: absolute; + bottom: 0; + width: 150px; + z-index: 2; + margin: 0; + padding: 0; + text-align: center; + list-style: none; +} + +#parallel-stats-graph li.version { + height: 298px; + padding-top: 2px; + border-right: 1px solid #ddd; + color: #000; + font-size: 12px; +} + +#parallel-stats-graph li.bar { + width: 60px; + border: 1px solid; + border-bottom: none; + color: #000; + /*font: 9px Helvetica, Arial, sans-serif;*/ +} + +#parallel-stats-graph li.bar p { + margin: 5px 0 0; + padding: 0; +} + +#parallel-stats-graph li.highest { + /*background: #ffc8c8; + border: 1px solid #0081d6;*/ +} + +#parallel-stats-graph li.clicked { + left: 13px; + background: #ceffc8; + border: 0px none; + border-right: 1px solid #A6DA9F; +} + +#parallel-stats-graph li.viewed { + left: 77px; + background: #c7e9ff; + border: 0px none; + border-right: 1px solid #A2C3D9; +} + +{loop obj[stats]} + #parallel-stats-graph #v{loop/_index} { + left: {php (loop[_index] x 150) - 150}px; + {if loop[_index] eq obj[versions]} + border-right: none; + {end if} + } +{end loop} + +#parallel-stats-graph #ticks { + width: {php obj[versions] x 150}px; + height: 300px; + z-index: 1; +} + +#parallel-stats-graph #ticks .tick { + position: relative; + border-bottom: 1px solid #BBB; + width: {php obj[versions] x 150}px; +} + +#parallel-stats-graph #ticks .tick p { + position: absolute; + left: 100%; + top: -0.67em; + margin: 0 0 0 0.5em; +} diff --git a/inc/app/cms/html/parallel_goal.spt b/inc/app/cms/html/parallel_goal.spt new file mode 100755 index 00000000..918f913e --- /dev/null +++ b/inc/app/cms/html/parallel_goal.spt @@ -0,0 +1,12 @@ +

{intl Please enter the complete URL of the goal link to track for this parallel test.}
+{intl The goal link is the link you are trying to direct visitors to follow on this page.}

+ +
+ + +

{intl Goal Link}:
+(ie. http://www.example.com/buy_now.html)

+ +

+ +
diff --git a/inc/app/cms/html/parallel_nostats.spt b/inc/app/cms/html/parallel_nostats.spt new file mode 100755 index 00000000..be53c468 --- /dev/null +++ b/inc/app/cms/html/parallel_nostats.spt @@ -0,0 +1,3 @@ +

{intl There are no stats for this test yet. Please check back later.}

+ +

{intl Back}

diff --git a/inc/app/cms/html/parallel_stats.spt b/inc/app/cms/html/parallel_stats.spt new file mode 100755 index 00000000..5398fc73 --- /dev/null +++ b/inc/app/cms/html/parallel_stats.spt @@ -0,0 +1,32 @@ +{alt #fff #eee} + +

{intl Back}

+ + + +

{intl Goal Link}: {goal}

+

{intl Total Views}: {total_views}

+

{intl Total Clicks}: {total_clicks}

+

{intl Test Duration}: {duration} {intl days}

diff --git a/inc/app/cms/lib/Product.php b/inc/app/cms/lib/Product.php index 62ba55af..0a954803 100755 --- a/inc/app/cms/lib/Product.php +++ b/inc/app/cms/lib/Product.php @@ -36,6 +36,6 @@ define ('PRODUCT_HEADER_GRAPHIC', site_prefix () . '/inc/app/cms/pix/sitellite-cms.gif'); } -define ('PRODUCT_EDITION', 'Open Source Edition'); +define ('PRODUCT_EDITION', ''); ?> \ No newline at end of file diff --git a/inc/app/cms/lib/Versioning/Parallel.php b/inc/app/cms/lib/Versioning/Parallel.php new file mode 100755 index 00000000..ed552b07 --- /dev/null +++ b/inc/app/cms/lib/Versioning/Parallel.php @@ -0,0 +1,220 @@ +page_id = $pg->id; + } else { + $this->page_id = $pg; + } + $sp = db_single ('select * from sitellite_parallel where page = ?', $this->page_id); + if ($sp) { + $this->parallel_id = $sp->id; + $this->goal_url = $sp->goal; + } else { + db_execute ('insert into sitellite_parallel values (null, ?, "")', $this->page_id); + $this->parallel_id = db_lastid (); + $this->goal_url = ''; + } + } + + function next () { + global $cgi; + + $show = session_get ('parallel_id'); + if ($show && ! $cgi->parallel_show) { + $cgi->parallel_show = $show; + } + + if ($cgi->parallel_show) { + $selected = 0; + $list[$selected] = db_single ('select * from sitellite_page_sv where id = ? and sv_autoid = ?', $this->page_id, $cgi->parallel_show); + } else { + // determine which parallel version to serve + $list = db_fetch_array ('select * from sitellite_page_sv where id = ? order by sv_revision desc limit 10', $this->page_id); + $good = array (); + foreach (array_keys ($list) as $k) { + if ($list[$k]->sitellite_status != 'parallel') { + break; + } + $good[] = $k; + } + + $selected = array_rand ($good); + } + $this->revision_id = $list[$selected]->sv_autoid; + + if (! session_admin ()) { + session_set ('parallel_id', $this->revision_id); + } + + unset ($list[$selected]->sv_autoid); + unset ($list[$selected]->sv_author); + unset ($list[$selected]->sv_action); + unset ($list[$selected]->sv_revision); + unset ($list[$selected]->sv_changelog); + unset ($list[$selected]->sv_deleted); + unset ($list[$selected]->sv_current); + + // load javascript for goal tracking + $this->load_script (); + + // track view + $this->viewed (); + + return $list[$selected]; + } + + function viewed () { + // track view + if (! session_admin ()) { + return db_execute ( + 'insert into sitellite_parallel_view values (?, ?, now())', + $this->parallel_id, + $this->revision_id + ); + } + } + + function clicked ($revision_id) { + // track click + if (! session_admin ()) { + return db_execute ( + 'insert into sitellite_parallel_click values (?, ?, now())', + $this->parallel_id, + $revision_id + ); + } + } + + function load_script () { + page_add_script (site_prefix () . '/js/rpc.js'); + page_add_script (site_prefix () . '/js/parallel.js'); + page_add_script (' + var parallel_script_url = "' . site_prefix () . '/index/cms-parallel-rpc-action"; + var parallel_page_id = "' . $this->page_id . '"; + var parallel_revision_id = "' . $this->revision_id . '"; + var parallel_goal_url = "' . $this->goal_url . '"; + '); + } + + function set_goal ($goal) { + db_execute ( + 'update sitellite_parallel set goal = ? where id = ?', + $goal, + $this->parallel_id + ); + $this->goal_url = $goal; + } + + function get_stats () { + $stats = array (); + $list = db_fetch_array ('select * from sitellite_page_sv where id = ? order by sv_revision desc limit 10', $this->page_id); + $good = array (); + foreach (array_keys ($list) as $k) { + if ($list[$k]->sitellite_status != 'parallel') { + break; + } + $good[] = $k; + } + + $highest_id = 0; + $oldest_id = 0; + $highest = 0; + $oldest = false; + + $good = array_reverse ($good); + + foreach ($good as $k) { + $stats[$list[$k]->sv_autoid] = array ( + 'description' => $list[$k]->sv_changelog, + 'ts' => $list[$k]->sv_revision, + 'viewed' => db_shift ('select count(*) from sitellite_parallel_view where parallel_id = ? and revision_id = ?', $this->parallel_id, $list[$k]->sv_autoid), + 'clicked' => db_shift ('select count(*) from sitellite_parallel_click where parallel_id = ? and revision_id = ?', $this->parallel_id, $list[$k]->sv_autoid), + 'highest' => false, + 'oldest' => false, + ); + if ($stats[$list[$k]->sv_autoid]['viewed'] > 0) { + $stats[$list[$k]->sv_autoid]['ratio'] = ($stats[$list[$k]->sv_autoid]['clicked'] / $stats[$list[$k]->sv_autoid]['viewed']) * 100; + } else { + $stats[$list[$k]->sv_autoid]['ratio'] = 0; + } + if ($stats[$list[$k]->sv_autoid]['ratio'] > $highest) { + $highest = $stats[$list[$k]->sv_autoid]['ratio']; + $highest_id = $list[$k]->sv_autoid; + } + if ($oldest == false || $stats[$list[$k]->sv_autoid]['ts'] < $oldest) { + $oldest = $stats[$list[$k]->sv_autoid]['ts']; + $oldest_id = $list[$k]->sv_autoid; + } + $this->total_views += $stats[$list[$k]->sv_autoid]['viewed']; + $this->total_clicks += $stats[$list[$k]->sv_autoid]['clicked']; + } + if ($highest_id) { + $stats[$highest_id]['highest'] = true; + } + $stats[$oldest_id]['oldest'] = true; + $this->campaign_start = $stats[$oldest_id]['ts']; + return $stats; + } + + function clear_series () { + db_execute ('delete from sitellite_parallel where id = ?', $this->parallel_id); + db_execute ('delete from sitellite_parallel_view where parallel_id = ?', $this->parallel_id); + db_execute ('delete from sitellite_parallel_click where parallel_id = ?', $this->parallel_id); + } + + function approve ($revision_id = false) { + if (! $revision_id) { + $revision_id = $this->revision_id; + } + + loader_import ('cms.Versioning.Rex'); + + $rex = new Rex ('sitellite_page'); + + $info = db_single ( + 'select * from sitellite_page_sv where id = ? and sv_autoid = ?', + $this->page_id, + $revision_id + ); + + unset ($info->sv_autoid); + unset ($info->sv_author); + unset ($info->sv_action); + unset ($info->sv_revision); + unset ($info->sv_changelog); + unset ($info->sv_deleted); + unset ($info->sv_current); + + $method = $rex->determineAction ($this->page_id, 'approved'); + if (! $method) { + $this->error = $rex->error; + return false; + } + + $info = (array) $info; + $info['sitellite_status'] = 'approved'; + + $res = $rex->{$method} ($this->page_id, $info, intl_get ('Approved from parallel testing campaign')); + if (! $res) { + $this->error = $rex->error; + return false; + } + + $this->clear_series (); + + return true; + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitebanner/boxes/access.php b/inc/app/sitebanner/boxes/access.php new file mode 100644 index 00000000..13777b5d --- /dev/null +++ b/inc/app/sitebanner/boxes/access.php @@ -0,0 +1,7 @@ +; diff --git a/inc/app/sitebanner/boxes/click/index.php b/inc/app/sitebanner/boxes/click/index.php new file mode 100644 index 00000000..1b6b883e --- /dev/null +++ b/inc/app/sitebanner/boxes/click/index.php @@ -0,0 +1,28 @@ +client != session_username ()) { + db_execute ( + 'insert into sitebanner_click + (id, campaign, ip, ts, ua) + values + (null, ?, ?, now(), ?)', + $parameters['id'], + $_SERVER['REMOTE_ADDR'], + $_SERVER['HTTP_USER_AGENT'] + ); +} + +header ('Location: ' . $banner->url); +exit; + +?> \ No newline at end of file diff --git a/inc/app/sitebanner/boxes/client/index.php b/inc/app/sitebanner/boxes/client/index.php new file mode 100644 index 00000000..5b8db3af --- /dev/null +++ b/inc/app/sitebanner/boxes/client/index.php @@ -0,0 +1,36 @@ +impressions = sitebanner_filter_impressions ($banners[$k]->impressions); + $banners[$k]->purchased = sitebanner_filter_purchased ($banners[$k]->purchased); + $banners[$k]->clicks = sitebanner_virtual_clicks ($banners[$k]); + $banners[$k]->clicks_percent = sitebanner_virtual_clicks_percent ($banners[$k]); +} + +echo template_simple ( + 'client.spt', + array ( + 'list' => $banners, + ) +); + +?> \ No newline at end of file diff --git a/inc/app/sitebanner/boxes/display/access.php b/inc/app/sitebanner/boxes/display/access.php new file mode 100644 index 00000000..fec3b1c7 --- /dev/null +++ b/inc/app/sitebanner/boxes/display/access.php @@ -0,0 +1,8 @@ +; diff --git a/inc/app/sitebanner/boxes/display/index.php b/inc/app/sitebanner/boxes/display/index.php new file mode 100644 index 00000000..bf309886 --- /dev/null +++ b/inc/app/sitebanner/boxes/display/index.php @@ -0,0 +1,84 @@ +client != session_username ()) { + db_execute ( + 'update sitebanner_ad set impressions = impressions + 1 where id = ?', + $banners[$key] + ); + + db_execute ( + 'insert into sitebanner_view + (id, campaign, ip, ts, ua) + values + (null, ?, ?, now(), ?)', + $banners[$key], + $_SERVER['REMOTE_ADDR'], + $_SERVER['HTTP_USER_AGENT'] + ); +} + +if ($banner->format == 'image') { // get image width/height + $info = parse_url ($banner->file); + if (strpos ($info['path'], '/') === 0) { + $info['path'] = substr ($info['path'], 1); + } + $dimensions = getimagesize ($info['path']); + $banner->width = $dimensions[0]; + $banner->height = $dimensions[1]; +} elseif ($banner->format == 'adsense') { // display only one google ad per page + if (defined ('SITEBANNER_ADSENSE')) { + return; + } + //define ('SITEBANNER_ADSENSE', true); +} + +if ($box['context'] == 'action') { + echo template_simple ('display/' . $banner->format . '_action.spt', $banner); + exit; +} + +echo template_simple ('display/' . $banner->format . '.spt', $banner); + +?> \ No newline at end of file diff --git a/inc/app/sitebanner/boxes/display/settings.php b/inc/app/sitebanner/boxes/display/settings.php new file mode 100755 index 00000000..e2f0e742 --- /dev/null +++ b/inc/app/sitebanner/boxes/display/settings.php @@ -0,0 +1,14 @@ +; \ No newline at end of file diff --git a/inc/app/sitebanner/boxes/stats/client/index.php b/inc/app/sitebanner/boxes/stats/client/index.php new file mode 100644 index 00000000..a16162bf --- /dev/null +++ b/inc/app/sitebanner/boxes/stats/client/index.php @@ -0,0 +1,220 @@ +_range)) { + $cgi->_range = 'week'; +} + +if (! isset ($cgi->date)) { + $cgi->date = date ('Y-m-d'); +} + +if (! isset ($cgi->id)) { + header ('Location: ' . site_prefix () . '/index'); + exit; +} + +if (session_username () != db_shift ('select client from sitebanner_ad where id = ?', $cgi->id)) { + header ('Location: ' . site_prefix () . '/index'); + exit; +} + +$data = array (); + +$rex = new Rex (false); + +$rex->facets['range'] = new rSelectFacet ('range', array ('display' => intl_get ('Date Range'), 'type' => 'select')); +$rex->facets['range']->preserve = array ('date', 'id'); +$rex->facets['range']->options = array ( + 'day' => intl_get ('Day'), + 'week' => intl_get ('Week'), + 'month' => intl_get ('Month'), + 'year' => intl_get ('Year'), +); +$rex->facets['range']->count = false; +$rex->facets['range']->all = false; + +$data['facets'] = $rex->renderFacets (1); +$data['bookmark'] = true; + +$data['date'] = $cgi->date; +$data['previous'] = Date::subtract ($cgi->date, '1 ' . $cgi->_range); +$data['next'] = Date::add ($cgi->date, '1 ' . $cgi->_range); + +switch ($cgi->_range) { + case 'day': + $parts = array ( + 'Midnight-1am' => array ($cgi->date . ' 00:00:00', $cgi->date . ' 00:59:59'), + '1:00-2:00' => array ($cgi->date . ' 01:00:00', $cgi->date . ' 01:59:59'), + '2:00-3:00' => array ($cgi->date . ' 02:00:00', $cgi->date . ' 02:59:59'), + '3:00-4:00' => array ($cgi->date . ' 03:00:00', $cgi->date . ' 03:59:59'), + '4:00-5:00' => array ($cgi->date . ' 04:00:00', $cgi->date . ' 04:59:59'), + '5:00-6:00' => array ($cgi->date . ' 05:00:00', $cgi->date . ' 05:59:59'), + '6:00-7:00' => array ($cgi->date . ' 06:00:00', $cgi->date . ' 06:59:59'), + '7:00-8:00' => array ($cgi->date . ' 07:00:00', $cgi->date . ' 07:59:59'), + '8:00-9:00' => array ($cgi->date . ' 08:00:00', $cgi->date . ' 08:59:59'), + '9:00-10:00' => array ($cgi->date . ' 09:00:00', $cgi->date . ' 09:59:59'), + '10:00-11:00' => array ($cgi->date . ' 10:00:00', $cgi->date . ' 10:59:59'), + '11am-Noon' => array ($cgi->date . ' 11:00:00', $cgi->date . ' 11:59:59'), + 'Noon-1:00' => array ($cgi->date . ' 12:00:00', $cgi->date . ' 12:59:59'), + '1:00-2:00 ' => array ($cgi->date . ' 13:00:00', $cgi->date . ' 13:59:59'), + '2:00-3:00 ' => array ($cgi->date . ' 14:00:00', $cgi->date . ' 14:59:59'), + '3:00-4:00 ' => array ($cgi->date . ' 15:00:00', $cgi->date . ' 15:59:59'), + '4:00-5:00 ' => array ($cgi->date . ' 16:00:00', $cgi->date . ' 16:59:59'), + '5:00-6:00 ' => array ($cgi->date . ' 17:00:00', $cgi->date . ' 17:59:59'), + '6:00-7:00 ' => array ($cgi->date . ' 18:00:00', $cgi->date . ' 18:59:59'), + '7:00-8:00 ' => array ($cgi->date . ' 19:00:00', $cgi->date . ' 19:59:59'), + '8:00-9:00 ' => array ($cgi->date . ' 20:00:00', $cgi->date . ' 20:59:59'), + '9:00-10:00 ' => array ($cgi->date . ' 21:00:00', $cgi->date . ' 21:59:59'), + '10:00-11:00 ' => array ($cgi->date . ' 22:00:00', $cgi->date . ' 22:59:59'), + '11pm-Midnight' => array ($cgi->date . ' 23:00:00', $cgi->date . ' 23:59:59'), + ); + break; + case 'week': + $day = strtolower (date ('D', strtotime ($cgi->date))); + $days = array ('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'); + $key = array_search ($day, $days); + if ($key === false) { + return; + } + $orig = $key; + + loader_import ('saf.Date'); + + while ($key >= 0) { + $minus = $orig - $key; + + if ($orig == $key) { + ${'_' . $day} = $cgi->date; + } else { + ${'_' . $days[$key]} = Date::subtract ($cgi->date, abs ($minus) . ' days'); + } + + $key--; + } + + $key = $orig; + $c = 0; + while ($key <= 6) { + $add = $key - $orig; + + if ($orig != $key) { + ${'_' . $days[$key]} = Date::add ($cgi->date, $add . ' days'); + } + + $key++; + } + + $parts = array ( + intl_get ('Sunday') => array ($_sun . ' 00:00:00', $_sun . ' 23:59:59'), + intl_get ('Monday') => array ($_mon . ' 00:00:00', $_mon . ' 23:59:59'), + intl_get ('Tuesday') => array ($_tue . ' 00:00:00', $_tue . ' 23:59:59'), + intl_get ('Wednesday') => array ($_wed . ' 00:00:00', $_wed . ' 23:59:59'), + intl_get ('Thursday') => array ($_thu . ' 00:00:00', $_thu . ' 23:59:59'), + intl_get ('Friday') => array ($_fri . ' 00:00:00', $_fri . ' 23:59:59'), + intl_get ('Saturday') => array ($_sat . ' 00:00:00', $_sat . ' 23:59:59'), + ); + break; + case 'month': + list ($y, $m, $d) = split ('-', $cgi->date); + if ($y . '-' . $m == date ('Y-m')) { + $days = date ('d'); + } else { + $days = date ('t', strtotime ($cgi->date)); + } + $parts = array (); + for ($i = 1; $i <= $days; $i++) { + $parts[date ('jS', strtotime ($y . '-' . $m . '-' . str_pad ($i, 2, '0', STR_PAD_LEFT)))] = array ( + $y . '-' . $m . '-' . str_pad ($i, 2, '0', STR_PAD_LEFT) . ' 00:00:00', + $y . '-' . $m . '-' . str_pad ($i, 2, '0', STR_PAD_LEFT) . ' 23:59:59', + ); + } + break; + case 'year': + list ($y, $m, $d) = split ('-', $cgi->date); + $parts = array ( + intl_get ('January') => array ($y . '-01-01 00:00:00', $y . '-01-31 23:59:59'), + intl_get ('February') => array ($y . '-02-01 00:00:00', $y . '-02-31 23:59:59'), + intl_get ('March') => array ($y . '-03-01 00:00:00', $y . '-03-31 23:59:59'), + intl_get ('April') => array ($y . '-04-01 00:00:00', $y . '-04-31 23:59:59'), + intl_get ('May') => array ($y . '-05-01 00:00:00', $y . '-05-31 23:59:59'), + intl_get ('June') => array ($y . '-06-01 00:00:00', $y . '-06-31 23:59:59'), + intl_get ('July') => array ($y . '-07-01 00:00:00', $y . '-07-31 23:59:59'), + intl_get ('August') => array ($y . '-08-01 00:00:00', $y . '-08-31 23:59:59'), + intl_get ('September') => array ($y . '-09-01 00:00:00', $y . '-09-31 23:59:59'), + intl_get ('October') => array ($y . '-10-01 00:00:00', $y . '-10-31 23:59:59'), + intl_get ('November') => array ($y . '-11-01 00:00:00', $y . '-11-31 23:59:59'), + intl_get ('December') => array ($y . '-12-01 00:00:00', $y . '-12-31 23:59:59'), + ); + break; +} + +$data['parts'] = array (); +$data['views_total'] = 0; +$data['clicks_total'] = 0; +$data['ctr_total'] = 0; +$count = 0; + +foreach ($parts as $k => $range) { + $views = db_shift ( + 'select count(*) from sitebanner_view where ts >= ? and ts <= ? and campaign = ?', + $range[0], + $range[1], + $cgi->id + ); + $clicks = db_shift ( + 'select count(*) from sitebanner_click where ts >= ? and ts <= ? and campaign = ?', + $range[0], + $range[1], + $cgi->id + ); + $ctr = @number_format (($clicks / $views) * 100, 2); + + $data['parts'][] = array ( + 'part' => $k, + 'from' => $range[0], + 'to' => $range[1], + 'views' => $views, + 'clicks' => $clicks, + 'ctr' => $ctr, + ); + + if ($views > 0) { + $count++; + } + $data['views_total'] += $views; + $data['clicks_total'] += $clicks; + $data['ctr_total'] += $ctr; +} + +$data['views_avg'] = @number_format (ceil ($data['views_total'] / $count), 0); +$data['clicks_avg'] = @number_format (ceil ($data['clicks_total'] / $count), 0); +$data['ctr_avg'] = @number_format ($data['ctr_total'] / $count, 2); + +$data['ctr_total'] = @number_format ($data['ctr_total'], 2); + +if ($cgi->csv == 'true') { + $data['title'] = intl_get ('Banner Stats') . ': ' . db_shift ( + 'select name from sitebanner_ad where id = ?', + $cgi->id + ) . ', ' . sitebanner_filter_date ($cgi->date); + + header ('Content-Type: application/octet-stream'); + header ('Content-Disposition: attachment; filename="csv.txt"'); + echo template_simple ('stats_csv.spt', $data); + exit; +} else { + page_title (intl_get ('Banner Stats') . ': ' . db_shift ( + 'select name from sitebanner_ad where id = ?', + $cgi->id + )); + + echo template_simple ('stats_client.spt', $data); +} + +?> \ No newline at end of file diff --git a/inc/app/sitebanner/boxes/stats/index.php b/inc/app/sitebanner/boxes/stats/index.php new file mode 100644 index 00000000..1afaed00 --- /dev/null +++ b/inc/app/sitebanner/boxes/stats/index.php @@ -0,0 +1,221 @@ +_range)) { + $cgi->_range = 'week'; +} + +if (! isset ($cgi->date)) { + $cgi->date = date ('Y-m-d'); +} + +if (! isset ($cgi->id)) { + header ('Location: ' . site_prefix () . '/index/cms-browse-action?collection=sitebanner_ad'); + exit; +} + +$data = array (); + +$rex = new Rex (false); + +$rex->facets['range'] = new rSelectFacet ('range', array ('display' => intl_get ('Date Range'), 'type' => 'select')); +$rex->facets['range']->preserve = array ('date', 'id'); +$rex->facets['range']->options = array ( + 'day' => intl_get ('Day'), + 'week' => intl_get ('Week'), + 'month' => intl_get ('Month'), + 'year' => intl_get ('Year'), +); +$rex->facets['range']->count = false; +$rex->facets['range']->all = false; + +$data['facets'] = $rex->renderFacets (1); +$data['bookmark'] = true; + +$data['date'] = $cgi->date; +$data['previous'] = Date::subtract ($cgi->date, '1 ' . $cgi->_range); +$data['next'] = Date::add ($cgi->date, '1 ' . $cgi->_range); + +switch ($cgi->_range) { + case 'day': + $parts = array ( + 'Midnight-1am' => array ($cgi->date . ' 00:00:00', $cgi->date . ' 00:59:59'), + '1:00-2:00' => array ($cgi->date . ' 01:00:00', $cgi->date . ' 01:59:59'), + '2:00-3:00' => array ($cgi->date . ' 02:00:00', $cgi->date . ' 02:59:59'), + '3:00-4:00' => array ($cgi->date . ' 03:00:00', $cgi->date . ' 03:59:59'), + '4:00-5:00' => array ($cgi->date . ' 04:00:00', $cgi->date . ' 04:59:59'), + '5:00-6:00' => array ($cgi->date . ' 05:00:00', $cgi->date . ' 05:59:59'), + '6:00-7:00' => array ($cgi->date . ' 06:00:00', $cgi->date . ' 06:59:59'), + '7:00-8:00' => array ($cgi->date . ' 07:00:00', $cgi->date . ' 07:59:59'), + '8:00-9:00' => array ($cgi->date . ' 08:00:00', $cgi->date . ' 08:59:59'), + '9:00-10:00' => array ($cgi->date . ' 09:00:00', $cgi->date . ' 09:59:59'), + '10:00-11:00' => array ($cgi->date . ' 10:00:00', $cgi->date . ' 10:59:59'), + '11am-Noon' => array ($cgi->date . ' 11:00:00', $cgi->date . ' 11:59:59'), + 'Noon-1:00' => array ($cgi->date . ' 12:00:00', $cgi->date . ' 12:59:59'), + '1:00-2:00 ' => array ($cgi->date . ' 13:00:00', $cgi->date . ' 13:59:59'), + '2:00-3:00 ' => array ($cgi->date . ' 14:00:00', $cgi->date . ' 14:59:59'), + '3:00-4:00 ' => array ($cgi->date . ' 15:00:00', $cgi->date . ' 15:59:59'), + '4:00-5:00 ' => array ($cgi->date . ' 16:00:00', $cgi->date . ' 16:59:59'), + '5:00-6:00 ' => array ($cgi->date . ' 17:00:00', $cgi->date . ' 17:59:59'), + '6:00-7:00 ' => array ($cgi->date . ' 18:00:00', $cgi->date . ' 18:59:59'), + '7:00-8:00 ' => array ($cgi->date . ' 19:00:00', $cgi->date . ' 19:59:59'), + '8:00-9:00 ' => array ($cgi->date . ' 20:00:00', $cgi->date . ' 20:59:59'), + '9:00-10:00 ' => array ($cgi->date . ' 21:00:00', $cgi->date . ' 21:59:59'), + '10:00-11:00 ' => array ($cgi->date . ' 22:00:00', $cgi->date . ' 22:59:59'), + '11pm-Midnight' => array ($cgi->date . ' 23:00:00', $cgi->date . ' 23:59:59'), + ); + break; + case 'week': + $day = strtolower (date ('D', strtotime ($cgi->date))); + $days = array ('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'); + $key = array_search ($day, $days); + if ($key === false) { + return; + } + $orig = $key; + + loader_import ('saf.Date'); + + while ($key >= 0) { + $minus = $orig - $key; + + if ($orig == $key) { + ${'_' . $day} = $cgi->date; + } else { + ${'_' . $days[$key]} = Date::subtract ($cgi->date, abs ($minus) . ' days'); + } + + $key--; + } + + $key = $orig; + $c = 0; + while ($key <= 6) { + $add = $key - $orig; + + if ($orig != $key) { + ${'_' . $days[$key]} = Date::add ($cgi->date, $add . ' days'); + } + + $key++; + } + + $parts = array ( + intl_get ('Sunday') => array ($_sun . ' 00:00:00', $_sun . ' 23:59:59'), + intl_get ('Monday') => array ($_mon . ' 00:00:00', $_mon . ' 23:59:59'), + intl_get ('Tuesday') => array ($_tue . ' 00:00:00', $_tue . ' 23:59:59'), + intl_get ('Wednesday') => array ($_wed . ' 00:00:00', $_wed . ' 23:59:59'), + intl_get ('Thursday') => array ($_thu . ' 00:00:00', $_thu . ' 23:59:59'), + intl_get ('Friday') => array ($_fri . ' 00:00:00', $_fri . ' 23:59:59'), + intl_get ('Saturday') => array ($_sat . ' 00:00:00', $_sat . ' 23:59:59'), + ); + break; + case 'month': + list ($y, $m, $d) = split ('-', $cgi->date); + if ($y . '-' . $m == date ('Y-m')) { + $days = date ('d'); + } else { + $days = date ('t', strtotime ($cgi->date)); + } + $parts = array (); + for ($i = 1; $i <= $days; $i++) { + $parts[date ('jS', strtotime ($y . '-' . $m . '-' . str_pad ($i, 2, '0', STR_PAD_LEFT)))] = array ( + $y . '-' . $m . '-' . str_pad ($i, 2, '0', STR_PAD_LEFT) . ' 00:00:00', + $y . '-' . $m . '-' . str_pad ($i, 2, '0', STR_PAD_LEFT) . ' 23:59:59', + ); + } + break; + case 'year': + list ($y, $m, $d) = split ('-', $cgi->date); + $parts = array ( + intl_get ('January') => array ($y . '-01-01 00:00:00', $y . '-01-31 23:59:59'), + intl_get ('February') => array ($y . '-02-01 00:00:00', $y . '-02-31 23:59:59'), + intl_get ('March') => array ($y . '-03-01 00:00:00', $y . '-03-31 23:59:59'), + intl_get ('April') => array ($y . '-04-01 00:00:00', $y . '-04-31 23:59:59'), + intl_get ('May') => array ($y . '-05-01 00:00:00', $y . '-05-31 23:59:59'), + intl_get ('June') => array ($y . '-06-01 00:00:00', $y . '-06-31 23:59:59'), + intl_get ('July') => array ($y . '-07-01 00:00:00', $y . '-07-31 23:59:59'), + intl_get ('August') => array ($y . '-08-01 00:00:00', $y . '-08-31 23:59:59'), + intl_get ('September') => array ($y . '-09-01 00:00:00', $y . '-09-31 23:59:59'), + intl_get ('October') => array ($y . '-10-01 00:00:00', $y . '-10-31 23:59:59'), + intl_get ('November') => array ($y . '-11-01 00:00:00', $y . '-11-31 23:59:59'), + intl_get ('December') => array ($y . '-12-01 00:00:00', $y . '-12-31 23:59:59'), + ); + break; +} + +$data['parts'] = array (); +$data['views_total'] = 0; +$data['clicks_total'] = 0; +$data['ctr_total'] = 0; +$count = 0; + +foreach ($parts as $k => $range) { + $views = db_shift ( + 'select count(*) from sitebanner_view where ts >= ? and ts <= ? and campaign = ?', + $range[0], + $range[1], + $cgi->id + ); + $clicks = db_shift ( + 'select count(*) from sitebanner_click where ts >= ? and ts <= ? and campaign = ?', + $range[0], + $range[1], + $cgi->id + ); + $ctr = @number_format (($clicks / $views) * 100, 2); + + $data['parts'][] = array ( + 'part' => $k, + 'from' => $range[0], + 'to' => $range[1], + 'views' => $views, + 'clicks' => $clicks, + 'ctr' => $ctr, + ); + + if ($views > 0) { + $count++; + } + $data['views_total'] += $views; + $data['clicks_total'] += $clicks; + $data['ctr_total'] += $ctr; +} + +$data['views_avg'] = @number_format (ceil ($data['views_total'] / $count), 0); +$data['clicks_avg'] = @number_format (ceil ($data['clicks_total'] / $count), 0); +$data['ctr_avg'] = @number_format ($data['ctr_total'] / $count, 2); + +$data['ctr_total'] = @number_format ($data['ctr_total'], 2); + +if ($cgi->csv == 'true') { + $data['title'] = intl_get ('Banner Stats') . ': ' . db_shift ( + 'select name from sitebanner_ad where id = ?', + $cgi->id + ) . ', ' . sitebanner_filter_date ($cgi->date); + + header ('Content-Type: application/octet-stream'); + header ('Content-Disposition: attachment; filename="csv.txt"'); + echo template_simple ('stats_csv.spt', $data); + exit; +} else { + page_title (intl_get ('Banner Stats') . ': ' . db_shift ( + 'select name from sitebanner_ad where id = ?', + $cgi->id + )); + + page_template_set ('admin'); + echo template_simple ('stats.spt', $data); +} + +?> \ No newline at end of file diff --git a/inc/app/sitebanner/conf/config.ini.php b/inc/app/sitebanner/conf/config.ini.php new file mode 100755 index 00000000..6cee57ed --- /dev/null +++ b/inc/app/sitebanner/conf/config.ini.php @@ -0,0 +1,24 @@ +; diff --git a/inc/app/sitebanner/conf/properties.php b/inc/app/sitebanner/conf/properties.php new file mode 100755 index 00000000..caf96d6d --- /dev/null +++ b/inc/app/sitebanner/conf/properties.php @@ -0,0 +1,23 @@ + \ No newline at end of file diff --git a/inc/app/sitebanner/data/hosting-small.jpg b/inc/app/sitebanner/data/hosting-small.jpg new file mode 100755 index 00000000..25b220fb Binary files /dev/null and b/inc/app/sitebanner/data/hosting-small.jpg differ diff --git a/inc/app/sitebanner/data/multisite-small.jpg b/inc/app/sitebanner/data/multisite-small.jpg new file mode 100755 index 00000000..5bb8fd64 Binary files /dev/null and b/inc/app/sitebanner/data/multisite-small.jpg differ diff --git a/inc/app/sitebanner/forms/access.php b/inc/app/sitebanner/forms/access.php new file mode 100644 index 00000000..13777b5d --- /dev/null +++ b/inc/app/sitebanner/forms/access.php @@ -0,0 +1,7 @@ +; diff --git a/inc/app/sitebanner/forms/create/index.php b/inc/app/sitebanner/forms/create/index.php new file mode 100644 index 00000000..ee13c795 --- /dev/null +++ b/inc/app/sitebanner/forms/create/index.php @@ -0,0 +1,36 @@ +parseSettings ('inc/app/sitebanner/forms/create/settings.php'); + page_title (intl_get ('Create a New Banner')); + } + function onSubmit ($vals) { + db_execute ( + 'insert into sitebanner_ad + (id, name, description, client, purchased, impressions, display_url, url, target, format, file, section, position, active) + values + (null, ?, ?, ?, 0, 0, ?, ?, ?, ?, ?, ?, ?, "no")', + $vals['name'], + $vals['description'], + session_username (), + $vals['display_url'], + $vals['url'], + 'top', + 'external', + $vals['file'], + $vals['section'], + $vals['position'] + ); + + if (appconf ('email')) { + @mail (appconf ('email'), 'SiteBanner Submission Notice', template_simple ('create_email.spt', $vals)); + } + + page_title (intl_get ('Banner Created')); + echo template_simple ('create_reply.spt'); + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitebanner/forms/create/settings.php b/inc/app/sitebanner/forms/create/settings.php new file mode 100644 index 00000000..a7879ce6 --- /dev/null +++ b/inc/app/sitebanner/forms/create/settings.php @@ -0,0 +1,54 @@ +; \ No newline at end of file diff --git a/inc/app/sitebanner/html/client.spt b/inc/app/sitebanner/html/client.spt new file mode 100644 index 00000000..3c59bcc1 --- /dev/null +++ b/inc/app/sitebanner/html/client.spt @@ -0,0 +1,26 @@ + + + + + + + + + + {loop obj[list]} + + + + + + + + + {end loop} +
{intl Banner}{intl Impressions}{intl Remaining}{intl Clicks}%{intl Active}
+ {loop/name} + {loop/impressions}{loop/purchased}{loop/clicks}{loop/clicks_percent}{filter ucfirst}{loop/active}{end filter}
+ +

+ {intl Create New Banner} +

diff --git a/inc/app/sitebanner/html/create_email.spt b/inc/app/sitebanner/html/create_email.spt new file mode 100644 index 00000000..c855eff7 --- /dev/null +++ b/inc/app/sitebanner/html/create_email.spt @@ -0,0 +1,22 @@ +Banner Submission + +- User Info - + +User: {session/username} +IP Address: {_SERVER/REMOTE_ADDR} + +- Banner Info - + +ID: {id} +Name: {name} +Web Site: {url} +Image: {file} +Alt Text: {display_url} +Sections: {section} +Position: {position} + +- Additional Comments - + +{filter none}{description}{end filter} + +-- diff --git a/inc/app/sitebanner/html/create_reply.spt b/inc/app/sitebanner/html/create_reply.spt new file mode 100644 index 00000000..5f030783 --- /dev/null +++ b/inc/app/sitebanner/html/create_reply.spt @@ -0,0 +1 @@ +

{intl Your banner has been received, and we will be in touch with you shortly.}

diff --git a/inc/app/sitebanner/html/display.spt b/inc/app/sitebanner/html/display.spt new file mode 100644 index 00000000..85390846 --- /dev/null +++ b/inc/app/sitebanner/html/display.spt @@ -0,0 +1,2 @@ + + {display_url} \ No newline at end of file diff --git a/inc/app/sitebanner/html/display/adsense.spt b/inc/app/sitebanner/html/display/adsense.spt new file mode 100644 index 00000000..9bc0b3ea --- /dev/null +++ b/inc/app/sitebanner/html/display/adsense.spt @@ -0,0 +1 @@ +{filter none}{file}{end filter} \ No newline at end of file diff --git a/inc/app/sitebanner/html/display/adsense_action.spt b/inc/app/sitebanner/html/display/adsense_action.spt new file mode 100644 index 00000000..5ba4d767 --- /dev/null +++ b/inc/app/sitebanner/html/display/adsense_action.spt @@ -0,0 +1,36 @@ + + +
+ +{filter none}{file}{end filter} + +
+
+{intl Close Window} + +
+ +

{intl Banner Stats}

+ +{box sitebanner/stats/client?id=[cgi/id]} + diff --git a/inc/app/sitebanner/html/display/external.spt b/inc/app/sitebanner/html/display/external.spt new file mode 100644 index 00000000..6d6e0d78 --- /dev/null +++ b/inc/app/sitebanner/html/display/external.spt @@ -0,0 +1,2 @@ + + {display_url} \ No newline at end of file diff --git a/inc/app/sitebanner/html/display/external_action.spt b/inc/app/sitebanner/html/display/external_action.spt new file mode 100644 index 00000000..1eb42edf --- /dev/null +++ b/inc/app/sitebanner/html/display/external_action.spt @@ -0,0 +1,37 @@ + + +
+ + + {display_url} + +
+
+{intl Close Window} + +
+ +

{intl Banner Stats}

+ +{box sitebanner/stats/client?id=[cgi/id]} + diff --git a/inc/app/sitebanner/html/display/html.spt b/inc/app/sitebanner/html/display/html.spt new file mode 100644 index 00000000..9bc0b3ea --- /dev/null +++ b/inc/app/sitebanner/html/display/html.spt @@ -0,0 +1 @@ +{filter none}{file}{end filter} \ No newline at end of file diff --git a/inc/app/sitebanner/html/display/html_action.spt b/inc/app/sitebanner/html/display/html_action.spt new file mode 100644 index 00000000..5ba4d767 --- /dev/null +++ b/inc/app/sitebanner/html/display/html_action.spt @@ -0,0 +1,36 @@ + + +
+ +{filter none}{file}{end filter} + +
+
+{intl Close Window} + +
+ +

{intl Banner Stats}

+ +{box sitebanner/stats/client?id=[cgi/id]} + diff --git a/inc/app/sitebanner/html/display/image.spt b/inc/app/sitebanner/html/display/image.spt new file mode 100644 index 00000000..85390846 --- /dev/null +++ b/inc/app/sitebanner/html/display/image.spt @@ -0,0 +1,2 @@ + + {display_url} \ No newline at end of file diff --git a/inc/app/sitebanner/html/display/image_action.spt b/inc/app/sitebanner/html/display/image_action.spt new file mode 100644 index 00000000..129f65e9 --- /dev/null +++ b/inc/app/sitebanner/html/display/image_action.spt @@ -0,0 +1,36 @@ + + +
+ + + {display_url} + +
+
+{intl Close Window} + +
+ +

{intl Banner Stats}

+ +{box sitebanner/stats/client?id=[cgi/id]} diff --git a/inc/app/sitebanner/html/display/text.spt b/inc/app/sitebanner/html/display/text.spt new file mode 100644 index 00000000..8a30d659 --- /dev/null +++ b/inc/app/sitebanner/html/display/text.spt @@ -0,0 +1 @@ +{file} \ No newline at end of file diff --git a/inc/app/sitebanner/html/display/text_action.spt b/inc/app/sitebanner/html/display/text_action.spt new file mode 100644 index 00000000..0b93e5b7 --- /dev/null +++ b/inc/app/sitebanner/html/display/text_action.spt @@ -0,0 +1,36 @@ + + +
+ +{file} + +
+
+{intl Close Window} + +
+ +

{intl Banner Stats}

+ +{box sitebanner/stats/client?id=[cgi/id]} + diff --git a/inc/app/sitebanner/html/display_action.spt b/inc/app/sitebanner/html/display_action.spt new file mode 100644 index 00000000..ba18dd4b --- /dev/null +++ b/inc/app/sitebanner/html/display_action.spt @@ -0,0 +1,16 @@ + + +
+ + + {display_url} + +
+
+{intl Close Window} + +
diff --git a/inc/app/sitebanner/html/facets_onecol.spt b/inc/app/sitebanner/html/facets_onecol.spt new file mode 100644 index 00000000..30883fcc --- /dev/null +++ b/inc/app/sitebanner/html/facets_onecol.spt @@ -0,0 +1,20 @@ + + + 
+ + {loop obj[facets]} + + {loop loop} + + {end loop} + + {end loop} +
+ {filter none}{loop/_value}{end filter} +
diff --git a/inc/app/sitebanner/html/stats.spt b/inc/app/sitebanner/html/stats.spt new file mode 100644 index 00000000..a4fb8a78 --- /dev/null +++ b/inc/app/sitebanner/html/stats.spt @@ -0,0 +1,58 @@ +{alt #ffffff #eeeeee} + +

+ {intl Back} +         + {intl Save as CSV} +

+ +

+ {filter none}{facets}{end filter} +

+ +

+ + + + + + +
+ {intl Previous} {intl Previous}: {filter sitebanner_filter_date}{previous}{end filter} + + {filter sitebanner_filter_date}{date}{end filter} + + {intl Next}: {filter sitebanner_filter_date}{next}{end filter} {intl Next} +
+

+ +

+ + + + + + + +{loop obj[parts]} + + + + + + +{end loop} + + + + + + + + + + + +
 {intl Views}{intl Clicks}{intl CTR}
{if loop[link]}{loop/part}{end if}{if else}{loop/part}{end if}{loop/views}{loop/clicks}{loop/ctr}%
{intl Average} + {views_avg}{clicks_avg}{ctr_avg}%
{intl Total}{views_total}{clicks_total}{ctr_total}%
+

diff --git a/inc/app/sitebanner/html/stats_client.spt b/inc/app/sitebanner/html/stats_client.spt new file mode 100644 index 00000000..1b2e8f85 --- /dev/null +++ b/inc/app/sitebanner/html/stats_client.spt @@ -0,0 +1,56 @@ +{alt #ffffff #eeeeee} + +

+ {intl Save as CSV} +

+ +

+ {filter none}{facets}{end filter} +

+ +

+ + + + + + +
+ {intl Previous} {intl Previous}: {filter sitebanner_filter_date}{previous}{end filter} + + {filter sitebanner_filter_date}{date}{end filter} + + {intl Next}: {filter sitebanner_filter_date}{next}{end filter} {intl Next} +
+

+ +

+ + + + + + + +{loop obj[parts]} + + + + + + +{end loop} + + + + + + + + + + + +
 {intl Views}{intl Clicks}{intl CTR}
{if loop[link]}{loop/part}{end if}{if else}{loop/part}{end if}{loop/views}{loop/clicks}{loop/ctr}%
{intl Average} + {views_avg}{clicks_avg}{ctr_avg}%
{intl Total}{views_total}{clicks_total}{ctr_total}%
+

diff --git a/inc/app/sitebanner/html/stats_csv.spt b/inc/app/sitebanner/html/stats_csv.spt new file mode 100644 index 00000000..2248992a --- /dev/null +++ b/inc/app/sitebanner/html/stats_csv.spt @@ -0,0 +1,7 @@ +{title} + +Day Views Clicks CTR +{loop obj[parts]}{loop/part} {loop/views} {loop/clicks} {loop/ctr}% +{end loop} +Average {views_avg} {clicks_avg} {ctr_avg}% +Total {views_total} {clicks_total} {ctr_total}% diff --git a/inc/app/sitebanner/install/INSTALL b/inc/app/sitebanner/install/INSTALL new file mode 100644 index 00000000..502e6ad1 --- /dev/null +++ b/inc/app/sitebanner/install/INSTALL @@ -0,0 +1,16 @@ +SITEBANNER INSTALL INSTRUCTIONS + +1. Install the necessary database tables: + +$ mysql -p -u USER DBNAME < inc/app/sitebanner/install/install-mysql.sql +(enter password when prompted) + +2. Copy the banner collection definition into the cms app: + +$ cd /PATH/TO/SITELLITE +$ cp -R inc/app/sitebanner/install/sitebanner_ad.php inc/app/cms/conf/collections/ + +3. Call sitebanner/display in your templates and/or sidebars, and create some +banners. + +That's all there is to it! diff --git a/inc/app/sitebanner/install/changes.txt b/inc/app/sitebanner/install/changes.txt new file mode 100644 index 00000000..298ee1b5 --- /dev/null +++ b/inc/app/sitebanner/install/changes.txt @@ -0,0 +1,21 @@ +Changes in 1.0.4 + +- Fixed a compatibility issue with Sitellite 5's new lazy-loading menu code. +- Added SiteBanner to the box chooser. + +Changes in 1.0.3 + +- Removed Google AdSense limit of one per page, since Google has removed + theirs. + +Changes in 1.0.2 + +- Fixed array_rand() on zero-item array error. + +Changes in 1.0.1 + +- Added full stats view for both admin and user. +- Added target field. +- Added format field, and support for images, html, text, external, and + Google AdSense ad types now. +- Added CSV export of stats. diff --git a/inc/app/sitebanner/install/install-mysql.sql b/inc/app/sitebanner/install/install-mysql.sql new file mode 100644 index 00000000..b3deaa5d --- /dev/null +++ b/inc/app/sitebanner/install/install-mysql.sql @@ -0,0 +1,41 @@ +# Your database schema goes here + +CREATE TABLE sitebanner_ad ( + id int not null auto_increment primary key, + name char(72) not null, + description char(255) not null, + client char(48) not null, + purchased int not null, + impressions int not null, + display_url char(128) not null, + url char(255) not null, + target enum('parent','self','top','blank') not null default 'top', + format enum('image','html','text','external','adsense') not null default 'image', + file text not null, + section char(200) not null, + position char(48) not null, + active enum('yes','no') not null default 'yes', + index (purchased, impressions, section, position, active, client, format) +); + +CREATE TABLE sitebanner_position ( + name char(48) not null primary key +); + +CREATE TABLE sitebanner_view ( + id int not null auto_increment primary key, + campaign int not null, + ip char(15) not null, + ts datetime not null, + ua char(128) not null, + index (campaign, ip, ts, ua) +); + +CREATE TABLE sitebanner_click ( + id int not null auto_increment primary key, + campaign int not null, + ip char(15) not null, + ts datetime not null, + ua char(128) not null, + index (campaign, ip, ts, ua) +); diff --git a/inc/app/sitebanner/install/sitebanner_ad.php b/inc/app/sitebanner/install/sitebanner_ad.php new file mode 100644 index 00000000..1041d584 --- /dev/null +++ b/inc/app/sitebanner/install/sitebanner_ad.php @@ -0,0 +1,162 @@ +; 'Yes', 'no' => 'No')" + +[facet:section] + +type = select +display = Section +values = "loader_call ('sitebanner.MenuSections', 'menu_get_sections')" + +[hint:name] + +alt = Ad Name +rule 1 = not empty, You must enter a name for your ad. + +[hint:purchased] + +type = text +alt = "Purchased Impressions (-1 for unlimited)" + +[hint:impressions] + +type = hidden + +[hint:url] + +alt = URL +extra = "size='40'" + +[hint:description] + +type = textarea +cols = 40 +rows = 2 +labelPosition = left + +[hint:client] + +type = select +setValues = "eval: db_pairs ('select username, concat(role, ` - `, lastname, ` `, firstname, ` (`, username, `)`) as name from sitellite_user order by name asc')" + +[hint:display_url] + +alt = Alternate Text +extra = "size='40'" + +[hint:file] + +type = sitebanner.Widgets.Shapeshifter + +[hint:section] + +type = multiple +size = 5 +alt = Display in Sections +setValues = "eval: array_merge (array ('' => '- ALL -'), loader_call ('sitebanner.MenuSections', 'menu_get_sections'))" + +[hint:position] + +type = selector +alt = Screen Position +table = sitebanner_position +key = name + +[hint:active] + +alt = "Is Active?" + +[hint:format] + +setValues = "eval: array ('external' => 'External Link', 'adsense' => 'Google(TM) AdSense', 'html' => 'HTML', 'image' => 'Image', 'text' => 'Text')" +extra = "onchange='this.form.submit ()'"; + +[hint:target] + +setValues = "eval: array ('blank' => 'New Window', 'parent' => 'Parent Frame', 'self' => 'Same Frame', 'top' => 'Top Frame')" + +; */ ?> \ No newline at end of file diff --git a/inc/app/sitebanner/install/update-1.0.0-1.0.1.sql b/inc/app/sitebanner/install/update-1.0.0-1.0.1.sql new file mode 100644 index 00000000..288dce28 --- /dev/null +++ b/inc/app/sitebanner/install/update-1.0.0-1.0.1.sql @@ -0,0 +1,4 @@ +alter table sitebanner_ad add column target enum('parent','self','top','blank') not null default 'top' after url; +alter table sitebanner_ad add column format enum('image','html','text','external','adsense') not null default 'image' after target; +alter table sitebanner_ad change column file file text not null; +alter table sitebanner_ad add index (format); diff --git a/inc/app/sitebanner/lib/Filters.php b/inc/app/sitebanner/lib/Filters.php new file mode 100644 index 00000000..376e64d5 --- /dev/null +++ b/inc/app/sitebanner/lib/Filters.php @@ -0,0 +1,56 @@ +id); + if ($num == 0) { + $num = '0'; + } + $GLOBALS['sitebanner_virtual_clicks'] = $num; + return $num; +} + +function sitebanner_virtual_clicks_percent (&$obj) { + global $sitebanner_virtual_clicks; + if ($sitebanner_virtual_clicks > 0) { + return number_format (($sitebanner_virtual_clicks / $obj->impressions) * 100, 2); + } + return '0.00'; +} + +function sitebanner_virtual_stats (&$obj) { + return template_simple ( + ' + {intl Click here for stats}', + $obj + ); +} + +function sitebanner_filter_date ($date) { + global $cgi; + return Date::format ($date, appconf ('date_format_' . $cgi->_range)); +} + +?> \ No newline at end of file diff --git a/inc/app/sitebanner/lib/MenuSections.php b/inc/app/sitebanner/lib/MenuSections.php new file mode 100644 index 00000000..790e758d --- /dev/null +++ b/inc/app/sitebanner/lib/MenuSections.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/inc/app/sitebanner/lib/Widgets/Shapeshifter.php b/inc/app/sitebanner/lib/Widgets/Shapeshifter.php new file mode 100644 index 00000000..dc6cf5ec --- /dev/null +++ b/inc/app/sitebanner/lib/Widgets/Shapeshifter.php @@ -0,0 +1,137 @@ + | +// +----------------------------------------------------------------------+ +// | Authors: John Luxford | +// +----------------------------------------------------------------------+ +// +// Text widget. Displays an HTML form field. +// + +/** + * Text widget. Displays an HTML form field. + * + * New in 1.2: + * - Made sure to call parent::display() in the display() method. + * + * + * validation ('is "foo"'); + * $widget->setValue ('foo'); + * $widget->error_message = 'Oops! This widget is being unruly!'; + * + * ? > + * + * + * @package MailForm + * @author John Luxford + * @copyright Copyright (C) 2001-2003, Simian Systems Inc. + * @license http://www.sitellite.org/index/license Simian Open Software License + * @version 1.2, 2002-05-03, $Id: Shapeshifter.php,v 1.1 2004/06/21 22:13:00 lux Exp $ + * @access public + * + */ + +class MF_Widget_shapeshifter extends MF_Widget { + /** + * A way to pass extra parameters to the HTML form tag, for + * example 'enctype="multipart/formdata"'. + * + * @access public + * + */ + var $extra = ''; + + /** + * This is the short name for this widget. The short name is + * the class name minus the 'MF_Widget_' prefix. + * + * @access public + * + */ + var $type = 'shapeshifter'; + + /** + * Returns the display HTML for this widget. The optional + * parameter determines whether or not to automatically display the widget + * nicely, or whether to simply return the widget (for use in a template). + * + * @access public + * @param boolean $generate_html + * @return string + * + */ + function display ($generate_html = 0) { + parent::display ($generate_html); + global $intl, $simple; + $attrstr = $this->getAttrs (); + + global $cgi; + if (! isset ($cgi->format) || empty ($cgi->format)) { + $val = $this->form->widgets['format']->getValue (); + if (empty ($val)) { + $cgi->format = 'image'; + } else { + $cgi->format = $val; + } + } + + switch ($cgi->format) { + case 'image': + $obj =& $this->changeType ('imagechooser'); + $obj->alt = 'Image File'; + $obj->path = '/inc/app/sitebanner/data'; + $obj->webpath = '/inc/app/sitebanner/data'; + return $obj->display ($generate_html); + break; + case 'html': + $obj =& $this->changeType ('textarea'); + $obj->alt = 'HTML Code'; + $obj->labelPosition = 'left'; + $obj->cols = 40; + $obj->rows = 10; + return $obj->display ($generate_html); + break; + case 'text': + $obj =& $this->changeType ('textarea'); + $obj->alt = 'Ad Text'; + $obj->labelPosition = 'left'; + $obj->cols = 40; + $obj->rows = 5; + return $obj->display ($generate_html); + break; + case 'external': + $obj =& $this->changeType ('text'); + $obj->alt = 'External Link'; + $obj->extra = 'size="40"'; + return $obj->display ($generate_html); + break; + case 'adsense': + $obj =& $this->changeType ('textarea'); + $obj->alt = 'Google(TM) AdSense Code'; + $obj->labelPosition = 'left'; + $obj->cols = 40; + $obj->rows = 10; + return $obj->display ($generate_html); + break; + } + } +} + + + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/access.php b/inc/app/sitelinks/boxes/access.php new file mode 100644 index 00000000..13777b5d --- /dev/null +++ b/inc/app/sitelinks/boxes/access.php @@ -0,0 +1,7 @@ +; diff --git a/inc/app/sitelinks/boxes/admin/access.php b/inc/app/sitelinks/boxes/admin/access.php new file mode 100644 index 00000000..f34a5359 --- /dev/null +++ b/inc/app/sitelinks/boxes/admin/access.php @@ -0,0 +1,8 @@ +; diff --git a/inc/app/sitelinks/boxes/admin/index.php b/inc/app/sitelinks/boxes/admin/index.php new file mode 100644 index 00000000..8f6c83e1 --- /dev/null +++ b/inc/app/sitelinks/boxes/admin/index.php @@ -0,0 +1,66 @@ +top_range)) { + $cgi->top_range = 'month'; +} +$data->top_range = $cgi->top_range; + +if (empty ($cgi->top_date)) { + $cgi->top_date = date ('Y-m-d'); +} +$data->top_date = $cgi->top_date; + +list ($start, $end) = sitelinks_get_range ($cgi->top_range, $cgi->top_date); +$data->top_start = $start; +$data->top_end = $end; +list ($prev, $next) = sitelinks_get_dates ($cgi->top_range, $cgi->top_date); +$data->top_prev = $prev; +$data->top_next = $next; + +// views +$list = db_fetch_array ( + 'select item_id, count(*) as total from sitelinks_view where ts >= ? and ts <= ? group by item_id order by total desc limit 10', + $start, + $end +); + +$data->views = $list; + +// hits +$list = db_fetch_array ( + 'select item_id, count(*) as total from sitelinks_hit where ts >= ? and ts <= ? group by item_id order by total desc limit 10', + $start, + $end +); + +$data->hits = $list; + +// ratings +$list = db_fetch_array ( + 'select item_id, avg(rating) as rating, count(*) as votes from sitelinks_rating where ts >= ? and ts <= ? group by item_id order by rating desc limit 10', + $start, + $end +); + +foreach (array_keys ($list) as $k) { + $list[$k]->rating = number_format ($list[$k]->rating, 2); +} + +$data->ratings = $list; + +$data->drafts = db_shift ('select count(*) from sitelinks_item where sitellite_status = "draft"'); + +echo template_simple ('admin.spt', $data); + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/categories/index.php b/inc/app/sitelinks/boxes/categories/index.php new file mode 100644 index 00000000..bbf250fa --- /dev/null +++ b/inc/app/sitelinks/boxes/categories/index.php @@ -0,0 +1,16 @@ +getCategories (); + +$data = array ( + 'sitesearch' => @file_exists ('inc/app/sitesearch/data/sitesearch.pid'), + 'categories' => $categories, +); + +echo template_simple ('categories.spt', $data); + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/category/index.php b/inc/app/sitelinks/boxes/category/index.php new file mode 100644 index 00000000..68e6e1ea --- /dev/null +++ b/inc/app/sitelinks/boxes/category/index.php @@ -0,0 +1,49 @@ +getCategory ($parameters['category']); + + echo template_simple ('category.spt', $parameters); + +} else { + + global $cgi; + + if (! isset ($cgi->offset)) { + $cgi->offset = 0; + } + + $item = new SiteLinks_Item; + + $list = $item->getCategory ($parameters['category'], appconf ('limit'), $cgi->offset); + + loader_import ('saf.GUI.Pager'); + + $pg = new Pager ($cgi->offset, appconf ('limit'), $item->total); + $pg->setUrl ('%s/index/sitelinks-app?category=%s', site_prefix (), $parameters['category']); + $pg->getInfo (); + $parameters['pager'] = true; + + template_simple_register ('pager', $pg); + template_simple_register ('cgi', $cgi); + echo template_simple ('category_top.spt', $parameters); + + foreach (array_keys ($list) as $k) { + if (@file_exists ('inc/app/sitelinks/html/summary/' . $list[$k]->ctype . '.spt')) { + echo template_simple ('summary/' . $list[$k]->ctype . '.spt', $list[$k]); + } else { + echo template_simple ('summary/default.spt', $list[$k]); + } + } + +} + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/forward/index.php b/inc/app/sitelinks/boxes/forward/index.php new file mode 100644 index 00000000..6df927f3 --- /dev/null +++ b/inc/app/sitelinks/boxes/forward/index.php @@ -0,0 +1,23 @@ +get ($parameters['forward']); + if ($i) { + $item->addHit ($parameters['forward']); + header ('Location: ' . $i->url); + exit; + } + +} + +header ('Location: ' . site_prefix () . '/index/sitelinks-app'); +exit; + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/index/access.php b/inc/app/sitelinks/boxes/index/access.php new file mode 100644 index 00000000..fec3b1c7 --- /dev/null +++ b/inc/app/sitelinks/boxes/index/access.php @@ -0,0 +1,8 @@ +; diff --git a/inc/app/sitelinks/boxes/index/index.php b/inc/app/sitelinks/boxes/index/index.php new file mode 100644 index 00000000..3011b9eb --- /dev/null +++ b/inc/app/sitelinks/boxes/index/index.php @@ -0,0 +1,88 @@ +get ($parameters['item']); + if (! $i) { + header ('Location: ' . site_prefix () . '/index/sitelinks-app'); + exit; + } + + $item->addView ($parameters['item']); + + $i->sitesearch = @file_exists ('inc/app/sitesearch/data/sitesearch.pid'); + + global $cgi; + + if (! empty ($cgi->highlight)) { + loader_import ('saf.Misc.Search'); + $i->search_bar = search_bar ($cgi->highlight, '/index/sitesearch-app?ctype=sitelinks_item&show_types=yes'); + $queries = search_split_query ($cgi->highlight); + $i->summary = search_highlight ($i->summary, $queries); + } + + if (@file_exists ('inc/app/sitelinks/html/full/' . $i->ctype . '.spt')) { + echo template_simple ('full/' . $i->ctype . '.spt', $i); + } else { + echo template_simple ('full/default.spt', $i); + } + + if (appconf ('user_ratings')) { + echo loader_box ('sitelinks/ratings', $parameters); + } + + if (appconf ('show_related')) { + $related = $item->getRelated ($parameters['item']); + if (count ($related) > 0) { + echo template_simple ('related.spt', $related); + } + } + +} elseif ($parameters['category']) { // display category list + + echo loader_box ('sitelinks/category', $parameters); + +} elseif ($parameters['type']) { // display category list + + echo loader_box ('sitelinks/type', $parameters); + +} elseif ($parameters['forward']) { // forward click-through + + echo loader_box ('sitelinks/forward', $parameters); + +} else { // display main screen + + switch (appconf ('index_screen')) { + + case 'categories': + echo loader_box ('sitelinks/categories', $parameters); + break; + + case 'types': + echo loader_box ('sitelinks/types', $parameters); + break; + + case 'top': + echo loader_box ('sitelinks/top', $parameters); + break; + + case 'newest': + echo loader_box ('sitelinks/newest', $parameters); + break; + + default: + echo loader_box ('sitelinks/category', $parameters); + break; + + } + +} + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/index/settings.php b/inc/app/sitelinks/boxes/index/settings.php new file mode 100644 index 00000000..29595439 --- /dev/null +++ b/inc/app/sitelinks/boxes/index/settings.php @@ -0,0 +1,14 @@ +; '- SELECT -'), assocify (db_shift_array ('select distinct id from sitelinks_category where id != `` order by id asc')))" + +; */ ?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/mylinks/index.php b/inc/app/sitelinks/boxes/mylinks/index.php new file mode 100644 index 00000000..df08ab38 --- /dev/null +++ b/inc/app/sitelinks/boxes/mylinks/index.php @@ -0,0 +1,55 @@ +getStoreList ( + array ( + 'user_id' => new rEqual ('user_id', session_username ()), + ) +); + +if (empty ($res)) { + echo template_simple ('mylinks_none.spt', array ('context' => $context)); + return; +} + +$ps = new PropertySet ('sitelinks_item', false); + +foreach (array_keys ($res) as $key) { + $res[$key] = $rex->getCurrent ($res[$key]->id); + $ps->entity = $res[$key]->id; + foreach ($ps->get () as $k => $v) { + $res[$key]->{$k} = $v; + } +} + +if (appconf ('category_screen') == 'default' || ! appconf ('item_pages')) { + echo template_simple ('mylinks_short.spt', array ('list' => $res, 'context' => $context)); +} else { + echo template_simple ('mylinks_top.spt', array ('context' => $context)); + foreach (array_keys ($res) as $k) { + if (@file_exists ('inc/app/sitelinks/html/mylinks/' . $res[$k]->ctype . '.spt')) { + echo template_simple ('mylinks/' . $res[$k]->ctype . '.spt', $res[$k]); + } else { + echo template_simple ('mylinks/default.spt', $res[$k]); + } + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/mylinks/profile/index.php b/inc/app/sitelinks/boxes/mylinks/profile/index.php new file mode 100644 index 00000000..658f1da1 --- /dev/null +++ b/inc/app/sitelinks/boxes/mylinks/profile/index.php @@ -0,0 +1,43 @@ +getList ( + array ( + 'user_id' => new rEqual ('user_id', $parameters['user']), + ) +); + +foreach (array_keys ($res) as $k) { + $res[$k] = $rex->getCurrent ($res[$k]->id); +} + +if ($box['context'] == 'action') { + page_title (appconf ('sitelinks_name') . ' / ' . intl_get ('By') . ' ' . $parameters['user']); +} + +$url = site_prefix () . '/index/sitelinks-app/item.'; + +echo template_simple ( + 'mylinks_profile.spt', + array ( + 'list' => $res, + 'url' => $url, + ) +); + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/mylinks/remove/index.php b/inc/app/sitelinks/boxes/mylinks/remove/index.php new file mode 100644 index 00000000..dacc28c5 --- /dev/null +++ b/inc/app/sitelinks/boxes/mylinks/remove/index.php @@ -0,0 +1,28 @@ +delete ($parameters['id']); + +loader_import ('saf.Database.PropertySet'); + +$ps = new PropertySet ('sitelinks_item', $parameters['id']); + +$ps->delete (); + +header ('Location: ' . site_prefix () . '/index/sitelinks-mylinks-action'); +exit; + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/mylinks/submit/index.php b/inc/app/sitelinks/boxes/mylinks/submit/index.php new file mode 100644 index 00000000..96650067 --- /dev/null +++ b/inc/app/sitelinks/boxes/mylinks/submit/index.php @@ -0,0 +1,108 @@ +category)) { + page_title (intl_get ('Category')); + echo template_simple ( + 'category_selector.spt', + db_fetch_array ('select id from sitelinks_category') + ); + return; +} + +loader_import ('saf.MailForm'); + +class SitelinksMylinksSubmitForm extends MailForm { + function SitelinksMylinksSubmitForm () { + parent::MailForm (); + $this->parseSettings ('inc/app/sitelinks/boxes/mylinks/submit/settings.php'); + $w =& $this->widgets['submit_button']; + unset ($this->widgets['submit_button']); + + $type = appconf ('sitelinks_default_type'); + if (is_array ($type)) { + global $cgi; + if (isset ($type[$cgi->category])) { + $type = $type[$cgi->category]; + } elseif (isset ($type['default'])) { + $type = $type['default']; + } else { + $type = 'default'; + } + } + $this->_sitelinks_type = $type; + + $this->_info = @ini_parse ('inc/app/sitelinks/conf/types/' . $type . '.php'); + unset ($this->_info['Type']); + foreach ($this->_info as $k => $v) { + $this->createWidget ($k, $v); + } + + $this->widgets['submit_button'] =& $w; + $this->widgets['submit_button']->buttons[1]->extra = 'onclick="window.location.href = \'' . site_prefix () . '/index/sitelinks-mylinks-action\'; return false"'; + } + + function onSubmit ($vals) { + loader_import ('cms.Versioning.Rex'); + + $rex = new Rex ('sitelinks_item'); + + $res = $rex->create ( + array ( + 'title' => $vals['title'], + 'url' => $vals['url'], + 'user_id' => session_username (), + 'category' => $vals['category'], + 'ctype' => $this->_sitelinks_type, + 'ts' => date ('Y-m-d H:i:s'), + 'summary' => $vals['summary'], + 'sitellite_status' => 'draft', + 'sitellite_access' => 'public', + ) + ); + + if (! $res) { + die ($rex->error); + } + + loader_import ('saf.Database.PropertySet'); + + $ps = new PropertySet ('sitelinks_item', $res); + + foreach (array_keys ($this->_info) as $k) { + $r = $ps->set ($k, $vals[$k]); + if (! $r) { + die ($ps->error); + } + } + + if (appconf ('email_user_submissions')) { + @mail ( + appconf ('email_user_submissions'), + 'User Submission Notice', + template_simple ('submission_notice.spt', $vals) + ); + } + + page_title (appconf ('sitelinks_name_singular') . ' ' . intl_get ('Submitted')); + echo template_simple ('submission_received.spt'); + } +} + +page_title (intl_get ('Add') . ' ' . appconf ('sitelinks_name_singular')); +$form = new SitelinksMylinksSubmitForm; +echo $form->run (); + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/mylinks/submit/settings.php b/inc/app/sitelinks/boxes/mylinks/submit/settings.php new file mode 100644 index 00000000..e99341db --- /dev/null +++ b/inc/app/sitelinks/boxes/mylinks/submit/settings.php @@ -0,0 +1,32 @@ +; \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/mylinks/update/index.php b/inc/app/sitelinks/boxes/mylinks/update/index.php new file mode 100644 index 00000000..e5b5170b --- /dev/null +++ b/inc/app/sitelinks/boxes/mylinks/update/index.php @@ -0,0 +1,121 @@ +parseSettings ('inc/app/sitelinks/boxes/mylinks/update/settings.php'); + $w =& $this->widgets['submit_button']; + unset ($this->widgets['submit_button']); + + $type = appconf ('sitelinks_default_type'); + if (is_array ($type)) { + global $cgi; + if (isset ($type[$cgi->category])) { + $type = $type[$cgi->category]; + } elseif (isset ($type['default'])) { + $type = $type['default']; + } else { + $type = 'default'; + } + } + $this->_sitelinks_type = $type; + + $this->_info = @ini_parse ('inc/app/sitelinks/conf/types/' . $type . '.php'); + unset ($this->_info['Type']); + foreach ($this->_info as $k => $v) { + $this->createWidget ($k, $v); + } + + $this->widgets['submit_button'] =& $w; + $this->widgets['submit_button']->buttons[1]->extra = 'onclick="window.location.href = \'' . site_prefix () . '/index/sitelinks-mylinks-action\'; return false"'; + + global $cgi; + + loader_import ('cms.Versioning.Rex'); + $rex = new Rex ('sitelinks_item'); + $item = $rex->getCurrent ($cgi->id); + + foreach ((array) $item as $k => $v) { + if (isset ($this->widgets[$k])) { + $this->widgets[$k]->setDefault ($v); + } + } + + loader_import ('saf.Database.PropertySet'); + $ps = new PropertySet ('sitelinks_item', $cgi->id); + foreach ($ps->get () as $k => $v) { + if (isset ($this->widgets[$k])) { + $this->widgets[$k]->setDefault ($v); + } + } + } + + function onSubmit ($vals) { + loader_import ('cms.Versioning.Rex'); + + $rex = new Rex ('sitelinks_item'); + + $action = $rex->determineAction ($vals['id'], 'draft'); + + $res = $rex->{$action} ( + $vals['id'], + array ( + 'title' => $vals['title'], + 'url' => $vals['url'], + 'user_id' => session_username (), + 'category' => $vals['category'], + 'ctype' => $this->_sitelinks_type, + 'ts' => date ('Y-m-d H:i:s'), + 'summary' => $vals['summary'], + 'sitellite_status' => 'draft', + 'sitellite_access' => 'public', + ) + ); + + if (! $res) { + die ($rex->error); + } + + loader_import ('saf.Database.PropertySet'); + + $ps = new PropertySet ('sitelinks_item', $vals['id']); + + foreach (array_keys ($this->_info) as $k) { + $r = $ps->set ($k, $vals[$k]); + if (! $r) { + die ($ps->error); + } + } + + if (appconf ('email_user_submissions')) { + @mail ( + appconf ('email_user_submissions'), + 'User Submission Notice', + template_simple ('submission_notice.spt', $vals) + ); + } + + page_title (appconf ('sitelinks_name_singular') . ' ' . intl_get ('Submitted')); + echo template_simple ('submission_received.spt'); + } +} + +page_title (intl_get ('Update') . ' ' . appconf ('sitelinks_name_singular')); +$form = new SitelinksMylinksSubmitForm; +echo $form->run (); + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/mylinks/update/settings.php b/inc/app/sitelinks/boxes/mylinks/update/settings.php new file mode 100644 index 00000000..d04035f1 --- /dev/null +++ b/inc/app/sitelinks/boxes/mylinks/update/settings.php @@ -0,0 +1,36 @@ +; \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/newest/index.php b/inc/app/sitelinks/boxes/newest/index.php new file mode 100644 index 00000000..a20fdd53 --- /dev/null +++ b/inc/app/sitelinks/boxes/newest/index.php @@ -0,0 +1,36 @@ +getNewest (appconf ('limit')); + + echo template_simple ('category.spt', $parameters); + +} else { + + global $cgi; + + $item = new SiteLinks_Item; + + $list = $item->getNewest (appconf ('limit')); + + echo template_simple ('category_top.spt', $parameters); + + foreach (array_keys ($list) as $k) { + if (@file_exists ('inc/app/sitelinks/html/summary/' . $list[$k]->ctype . '.spt')) { + echo template_simple ('summary/' . $list[$k]->ctype . '.spt', $list[$k]); + } else { + echo template_simple ('summary/default.spt', $list[$k]); + } + } + +} + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/newest/sidebar/access.php b/inc/app/sitelinks/boxes/newest/sidebar/access.php new file mode 100644 index 00000000..93d93c95 --- /dev/null +++ b/inc/app/sitelinks/boxes/newest/sidebar/access.php @@ -0,0 +1,9 @@ +; diff --git a/inc/app/sitelinks/boxes/newest/sidebar/index.php b/inc/app/sitelinks/boxes/newest/sidebar/index.php new file mode 100644 index 00000000..ed39fa3b --- /dev/null +++ b/inc/app/sitelinks/boxes/newest/sidebar/index.php @@ -0,0 +1,12 @@ +getNewest (appconf ('limit')); + +echo template_simple ('sidebar.spt', $parameters); + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/newest/sidebar/settings.php b/inc/app/sitelinks/boxes/newest/sidebar/settings.php new file mode 100644 index 00000000..a932947d --- /dev/null +++ b/inc/app/sitelinks/boxes/newest/sidebar/settings.php @@ -0,0 +1,8 @@ +; \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/ratings/index.php b/inc/app/sitelinks/boxes/ratings/index.php new file mode 100644 index 00000000..fca5839d --- /dev/null +++ b/inc/app/sitelinks/boxes/ratings/index.php @@ -0,0 +1,27 @@ +hasVoted ($parameters['item'])) { + $parameters['has_voted'] = true; +} else { + $parameters['has_voted'] = false; +} + +if (! $parameters['has_voted'] && isset ($parameters['rating'])) { + $item->addRating ($parameters['item'], $parameters['rating']); + + page_title (intl_get ('Thank You')); + echo template_simple ('ratings_thanks.spt', $parameters); +} else { + $ratings = $item->rating ($parameters['item']); + $parameters['votes'] = $ratings->votes; + $parameters['ratings'] = $ratings->rating; + echo template_simple ('ratings.spt', $parameters); +} + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/rss/index.php b/inc/app/sitelinks/boxes/rss/index.php new file mode 100644 index 00000000..78bf3b92 --- /dev/null +++ b/inc/app/sitelinks/boxes/rss/index.php @@ -0,0 +1,52 @@ +offset)) { + $cgi->offset = 0; +} + +if (! isset ($cgi->limit)) { + $cgi->limit = 10; +} + +if ($parameters['display'] == 'newest') { + $parameters['category'] = intl_get ('Newest Links'); +} elseif ($parameters['display'] == 'top') { + $parameters['category'] = intl_get ('Top-Rated Links'); +} + +if ($parameters['category'] == intl_get ('Newest Links')) { + $list = $item->getNewest ($cgi->limit); + $title = appconf ('rss_title') . ': ' . intl_get ('Newest Links'); +} elseif ($parameters['category'] == intl_get ('Top-Rated Links')) { + $list = $item->getTop ($cgi->limit); + $title = appconf ('rss_title') . ': ' . intl_get ('Top-Rated Links'); +} else { + $list = $item->getCategory ($parameters['category'], $cgi->limit, $cgi->offset); + $title = appconf ('rss_title') . ': ' . $parameters['category']; +} + +header ('Content-Type: text/xml'); +echo template_simple ( + 'rss_category.spt', + array ( + 'list' => $list, + 'date' => $parameters['date'], + 'rss_title' => $title, + 'rss_description' => appconf ('rss_description'), + 'rss_date' => date ('Y-m-d\TH:i:s') . sitelinks_timezone (date ('Z')), + ) +); + +exit; + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/top/index.php b/inc/app/sitelinks/boxes/top/index.php new file mode 100644 index 00000000..2e113850 --- /dev/null +++ b/inc/app/sitelinks/boxes/top/index.php @@ -0,0 +1,37 @@ +getTop (appconf ('limit')); + + echo template_simple ('top.spt', $parameters); + +} else { + + global $cgi; + + $item = new SiteLinks_Item; + + $list = $item->getTop (appconf ('limit')); + + echo template_simple ('category_top.spt', $parameters); + + foreach (array_keys ($list) as $k) { + $list[$k]->sitelinks_top = true; + if (@file_exists ('inc/app/sitelinks/html/summary/' . $list[$k]->ctype . '.spt')) { + echo template_simple ('summary/' . $list[$k]->ctype . '.spt', $list[$k]); + } else { + echo template_simple ('summary/default.spt', $list[$k]); + } + } + +} + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/top/sidebar/access.php b/inc/app/sitelinks/boxes/top/sidebar/access.php new file mode 100644 index 00000000..93d93c95 --- /dev/null +++ b/inc/app/sitelinks/boxes/top/sidebar/access.php @@ -0,0 +1,9 @@ +; diff --git a/inc/app/sitelinks/boxes/top/sidebar/index.php b/inc/app/sitelinks/boxes/top/sidebar/index.php new file mode 100644 index 00000000..c5ec1b48 --- /dev/null +++ b/inc/app/sitelinks/boxes/top/sidebar/index.php @@ -0,0 +1,12 @@ +getTop (appconf ('limit')); + +echo template_simple ('sidebar.spt', $parameters); + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/top/sidebar/settings.php b/inc/app/sitelinks/boxes/top/sidebar/settings.php new file mode 100644 index 00000000..ca60ce9c --- /dev/null +++ b/inc/app/sitelinks/boxes/top/sidebar/settings.php @@ -0,0 +1,8 @@ +; \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/type/index.php b/inc/app/sitelinks/boxes/type/index.php new file mode 100644 index 00000000..63d9bc22 --- /dev/null +++ b/inc/app/sitelinks/boxes/type/index.php @@ -0,0 +1,49 @@ +getByType ($parameters['type']); + + echo template_simple ('type.spt', $parameters); + +} else { + + global $cgi; + + if (! isset ($cgi->offset)) { + $cgi->offset = 0; + } + + $item = new SiteLinks_Item; + + $list = $item->getByType ($parameters['type'], appconf ('limit'), $cgi->offset); + + loader_import ('saf.GUI.Pager'); + + $pg = new Pager ($cgi->offset, appconf ('limit'), $item->total); + $pg->setUrl ('%s/index/sitelinks-app?type=%s', site_prefix (), $parameters['type']); + $pg->getInfo (); + $parameters['pager'] = true; + + template_simple_register ('pager', $pg); + template_simple_register ('cgi', $cgi); + echo template_simple ('type_top.spt', $parameters); + + foreach (array_keys ($list) as $k) { + if (@file_exists ('inc/app/sitelinks/html/summary/' . $list[$k]->ctype . '.spt')) { + echo template_simple ('summary/' . $list[$k]->ctype . '.spt', $list[$k]); + } else { + echo template_simple ('summary/default.spt', $list[$k]); + } + } + +} + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/boxes/types/index.php b/inc/app/sitelinks/boxes/types/index.php new file mode 100644 index 00000000..1900b529 --- /dev/null +++ b/inc/app/sitelinks/boxes/types/index.php @@ -0,0 +1,16 @@ +getTypes (); + +$data = array ( + 'sitesearch' => @file_exists ('inc/app/sitesearch/data/sitesearch.pid'), + 'types' => $types, +); + +echo template_simple ('types.spt', $data); + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/conf/config.ini.php b/inc/app/sitelinks/conf/config.ini.php new file mode 100755 index 00000000..768f8d79 --- /dev/null +++ b/inc/app/sitelinks/conf/config.ini.php @@ -0,0 +1,24 @@ +; " +copyright = "Copyright (C) 2004, SIMIAN systems Inc." +license = "http://www.opensource.org/licenses/index.php#PICK ONE!!!" +version = "0.1 alpha : $Id: config.ini.php,v 1.2 2005/03/24 22:23:13 lux Exp $" + +; These allow you to call your app via the /index/myapp-app syntax. +default_handler = index +default_handler_type = box + +; Comment these lines out if your app doesn't have an administrative UI to it. +admin_handler = admin +admin_handler_type = box + +boxchooser = on + +; DO NOT ALTER THIS LINE, IT IS HERE FOR SECURITY REASONS */ ?> diff --git a/inc/app/sitelinks/conf/properties.php b/inc/app/sitelinks/conf/properties.php new file mode 100755 index 00000000..c05c2037 --- /dev/null +++ b/inc/app/sitelinks/conf/properties.php @@ -0,0 +1,197 @@ + 'software', + * 'Software' => 'software', + * 'Templates' => 'template', + * 'Web Sites' => 'company', + * 'Music' => 'music', + * )); + * + */ +appconf_set ('sitelinks_default_type', 'default'); + +/** + * Set this to true if you want item links to first go to their own page + * before going to the link site. Please note: This is required for + * user ratings (below), as that is the template they appear in. + */ +appconf_set ('item_pages', true); + +/** + * Set this to true if you want items to be browseable by type as well as + * by category. + */ +appconf_set ('browse_by_type', true); + +/** + * Set this to true if you want users (visitors) to be able to rate items + * in your list. + */ +appconf_set ('user_ratings', true); + +/** + * Set this to true if you want users (visitors) to be able to make + * submissions to your list. + */ +appconf_set ('user_submissions', true); + +/** + * Set this to the email address you want user submission notifications + * to go to, or false if you don't want to receive such emails. + */ +appconf_set ('email_user_submissions', false); + +/** + * Set this to one of the following to determine what to display on the + * main screen (ie. /index/sitelinks-app): + * + * - 'categories' - A list of categories. + * - 'types' - A list of types. + * - 'top' - The most popular items (if user_ratings is true). + * - 'newest' - The most recently added or updated items. + * - 'default' - A default list, useful for single-page link lists. + */ +appconf_set ('index_screen', 'categories'); + +/** + * Set this to one of the following to determine how to display the + * category listing screens (ie. /index/sitelinks-app/category.CatName): + * + * - 'full' - A full template of each listing including summary. Please + * note that this view requires 'item_pages' to be set to true, and + * will display as 'default' if it is not. + * - 'default' - A default bulleted list. + */ +appconf_set ('category_screen', 'full'); + +/** + * If 'category_screen' is set to 'full', then a pager is used when + * there are too many items to display on a single screen. This number + * is determined by the 'limit' setting. + */ +appconf_set ('limit', 10); + +/** + * If this is set to true, it will display a list of links that are + * attributed to the same user_id. + */ +appconf_set ('show_related', true); + +/** + * Set to true for RSS links to appear in the bottom navigation links + * of the SiteLinks app. If it is false, RSS feeds are still available + * via the /index/sitelinks-rss-action box, however they simply won't be + * linked to automatically for you. + */ +appconf_set ('rss_links', true); + +/** + * Set this to whatever you want your RSS field to contain. + */ +appconf_set ('rss_title', site_domain () . ' ' . intl_get ('links')); + +/** + * Set this to whatever you want your RSS <description> field to + * contain. + */ +appconf_set ('rss_description', intl_get ('Links from') . ' ' . site_domain ()); + +/** + * These are a few date display format settings. See www.php.net/date + * for more info on the formatting syntax. + */ +appconf_set ('shortdate', 'M/d'); +appconf_set ('date', 'F j, Y'); +appconf_set ('time', 'g:i A'); +appconf_set ('date_time', 'M d, Y g:i A'); +appconf_set ('admin_date_short', 'M d, Y'); +appconf_set ('admin_date_month', 'M, Y'); +appconf_set ('admin_date_year', 'Y'); + +formdata_set ('types_software_cost', array ( + 'Public Domain', + 'Open Source/GPL', + 'Open Source/LGPL', + 'Open Source/BSD', + 'Open Source/Apache', + 'Open Source/Other', + 'Free/Closed Source', + 'Shareware', + 'Commercial/$1-50', + 'Commercial/$50-100', + 'Commercial/$100-200', + 'Commercial/$200-300', + 'Commercial/$300-500', + 'Commercial/$500-1,000', + 'Commercial/Over $1,000', +)); + +formdata_set ('types_software_platform', array ( + 'Windows Desktop', + 'Linux Desktop/KDE', + 'Linux Desktop/GNOME', + 'Linux Desktop/Other', + 'Mac OS X Desktop', + 'Windows/Mac OS X Desktop', + 'Windows/Linux Desktop', + 'Linux/Mac OS X Desktop', + 'All Desktops', + 'Windows Server', + 'Linux Server', + 'Mac OS X Server', + 'Windows/Mac OS X Server', + 'Windows/Linux Server', + 'Linux/Mac OS X Server', + 'All Servers', +)); + +formdata_set ('types_music_genre', array ( + 'Alternative', + 'Blues', + 'Broadway', + 'Classic Rock', + 'Classical', + 'Country', + 'Dance', + 'Doo Wop', + 'Electronic', + 'Folk', + 'Hard Rock', + 'Hip Hop/Rap', + 'Inspirational', + 'Jazz', + 'Latin', + 'Metal', + 'Motown', + 'New Age', + 'Opera', + 'Pop', + 'Punk', + 'R&B/Soul', + 'Rock \'n\' Roll', + 'Vocal', + 'World', +)); + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/conf/types/default.php b/inc/app/sitelinks/conf/types/default.php new file mode 100755 index 00000000..f832f5cb --- /dev/null +++ b/inc/app/sitelinks/conf/types/default.php @@ -0,0 +1,7 @@ +; <?php /* + +[Type] + +name = Default + +; */ ?> \ No newline at end of file diff --git a/inc/app/sitelinks/conf/types/music.php b/inc/app/sitelinks/conf/types/music.php new file mode 100755 index 00000000..c19c1fbd --- /dev/null +++ b/inc/app/sitelinks/conf/types/music.php @@ -0,0 +1,12 @@ +; <?php /* + +[Type] + +name = Music + +[genre] + +type = select +eval = "formdata_get ('types_music_genre')" + +; */ ?> \ No newline at end of file diff --git a/inc/app/sitelinks/conf/types/software.php b/inc/app/sitelinks/conf/types/software.php new file mode 100755 index 00000000..fe6622f2 --- /dev/null +++ b/inc/app/sitelinks/conf/types/software.php @@ -0,0 +1,21 @@ +; <?php /* + +[Type] + +name = Software + +[version] + +type = text + +[cost] + +type = select +setValues = "eval: formdata_get ('types_software_cost')" + +[platform] + +type = select +setValues = "eval: formdata_get ('types_software_platform')" + +; */ ?> \ No newline at end of file diff --git a/inc/app/sitelinks/docs/en/001-intro.html b/inc/app/sitelinks/docs/en/001-intro.html new file mode 100644 index 00000000..b27740f0 --- /dev/null +++ b/inc/app/sitelinks/docs/en/001-intro.html @@ -0,0 +1,9 @@ +<h1>Introduction</h1> + +SiteLinks is a multi-purpose link/object listing utility.  +SiteLinks features multiple categories, per-category user-defined +object types (ie. real estate listing, classifieds, careers, software, +song, employee, etc.), automatic SiteSearch integration, +user-contributed listings, user ratings or admin-controlled ordering, +RSS listing syndication, and much more.  SiteLinks is Sitellite's +swiss army knife add-on, solving a wide variety of solutions with ease.<br /> diff --git a/inc/app/sitelinks/docs/en/002-install.html b/inc/app/sitelinks/docs/en/002-install.html new file mode 100644 index 00000000..17f383f2 --- /dev/null +++ b/inc/app/sitelinks/docs/en/002-install.html @@ -0,0 +1,18 @@ +<h1>Installation</h1> + +<p>1. From the Unix command-line, enter the following:</p> + + +<pre><code><br />mysql -p -u USER DBNAME < inc/app/sitelinks/install/install-mysql.sql<br /></code></pre> + + +<p>Then enter your password when prompted. You may also use an +alternate MySQL client, such as phpMyAdmin, if you prefer. This will +create the necessary database tables that SiteTracker needs to store +your site traffic information.<br /> +</p> +<p>2. Copy the SiteLinks collection definition file into the global location:<br /> +</p> +<pre><br />cp inc/app/sitelinks/install/sitelinks_item.php inc/app/cms/conf/collections/<br /></pre> +<p>You should now be ready to start creating links for your web site.<br /> +</p> diff --git a/inc/app/sitelinks/docs/en/003-accessing.html b/inc/app/sitelinks/docs/en/003-accessing.html new file mode 100644 index 00000000..ead40272 --- /dev/null +++ b/inc/app/sitelinks/docs/en/003-accessing.html @@ -0,0 +1,6 @@ +<h1>Accessing SiteLinks</h1> + +To access your SiteLinks listings, either provide a link on your site or create a web page that is an alias of the URL:<br /> +<br /> +<pre>http://www.yourWebSite.com/index/sitelinks-app</pre> +This will load the main SiteLinks screen.<br /> diff --git a/inc/app/sitelinks/docs/en/004-admin.html b/inc/app/sitelinks/docs/en/004-admin.html new file mode 100644 index 00000000..7fc6ab21 --- /dev/null +++ b/inc/app/sitelinks/docs/en/004-admin.html @@ -0,0 +1,11 @@ +<h1>The SiteLinks Admin UI</h1> + +SiteLinks comes with a built-in statistic screen, which shows you the +top viewed links, the top click-throughs, and the top rated links as +well.  You can view each of these for any day, month, or year.<br /> +<br /> +The SiteLinks admin user-interface also tells you if there are any +pending user-contributed submissions for you to approve, how many, and +provides a link for you to view them in the Sitellite content browser.<br /> +<br /> +The SiteLinks admin user-interface is accessible under the Control Panel > Tools > SiteLinks select box.<br /> diff --git a/inc/app/sitelinks/docs/en/005-types.html b/inc/app/sitelinks/docs/en/005-types.html new file mode 100644 index 00000000..45cd8f7b --- /dev/null +++ b/inc/app/sitelinks/docs/en/005-types.html @@ -0,0 +1,33 @@ +<h1>Custom Types</h1> + +New content types can be defined in SiteLinks by adding INI files to +the inc/app/sitelinks/conf/types folder.  These files define the +additional fields available to that custom type.  An example INI +file is shown below:<br /> +<br /> +<pre>;<?php /* + +[Type] + +name = Software + +[version] + +type = text + +[cost] + +type = select +setValues = "eval: formdata_get ('types_software_cost')" + +[platform] + +type = select +setValues = "eval: formdata_get ('types_software_platform')" + +; */ ?><br /></pre>The formdata_get() function calls are retrieving lists of select options defined in inc/app/sitelinks/conf/properties.php<br /> +<br /> +Additionally, you can define custom templates for the summary and full +display of each custom type by adding them to the +inc/app/sitelinks/html/summary and inc/app/sitelinks/html/full +folders.  These templates are in SimpleTemplate format.<br /> \ No newline at end of file diff --git a/inc/app/sitelinks/docs/en/006-options.html b/inc/app/sitelinks/docs/en/006-options.html new file mode 100644 index 00000000..7b5d3ba9 --- /dev/null +++ b/inc/app/sitelinks/docs/en/006-options.html @@ -0,0 +1,22 @@ +<h1>Configuration Options</h1> + +All of the configuration options for SiteLinks are in the +inc/app/sitelinks/conf/properties.php file.  Each option has a +description of what it does in the source of the file itself.  +Some of the main options include:<br /> +<ul> + <li>Default type - allows you to control which item type the +add/edit/submission forms should default to, globally as well as +per-category.<br /> + </li> + <li>Item pages - allows you to specify whether listings should have a full-page view, or simply a summary.</li> + <li>User ratings - whether or not you want users to be able to rate links.</li> + <li>User submissions - whether or not you want users to be able to contribute links of their own.</li> + <li>Index screen - what to show on the main screen of the SiteLinks +app.  This can be a list of categories, the top rated items, the +most recently added or updated items,or a simple default list, which is useful for single-page link lists (because you don't <em>have</em> to use SiteLinks to the max to use SiteLinks).</li> + <li>Category screen - whether to show summaries of the items, or simply a bulleted list to complement the default index screen view.</li> + <li>Show related - whether to show related items, which are items added by the same contributer.</li> + <li>RSS links - whether to offer RSS news feed links in the SiteLinks navigation, or you can keep the RSS links private.<br /> + </li> +</ul> diff --git a/inc/app/sitelinks/forms/properties/index.php b/inc/app/sitelinks/forms/properties/index.php new file mode 100644 index 00000000..014398dd --- /dev/null +++ b/inc/app/sitelinks/forms/properties/index.php @@ -0,0 +1,73 @@ +<?php + +loader_import ('saf.Database.PropertySet'); + +class SitelinksPropertiesForm extends MailForm { + function SitelinksPropertiesForm () { + parent::MailForm (); + + page_title (intl_get ('Editing Extras')); + + global $cgi; + + // 1. read config and build widgets + $this->type = db_shift ('select ctype from sitelinks_item where id = ?', $cgi->_key); + if (empty ($this->type)) { + $this->type = 'default'; + } + + ini_add_filter ('ini_filter_split_comma_single', array ( + 'rule 0', 'rule 1', 'rule 2', 'rule 3', 'rule 4', 'rule 5', 'rule 6', 'rule 7', 'rule 8', + 'button 0', 'button 1', 'button 2', 'button 3', 'button 4', 'button 5', 'button 6', 'button 7', 'button 8', + )); + $this->config = ini_parse ('inc/app/sitelinks/conf/types/' . $this->type . '.php'); + unset ($this->config['Type']); + ini_clear (); + + foreach ($this->config as $name => $data) { + $w =& $this->createWidget ($name, $data); + } + + // 2. load values from ps + $ps = new PropertySet ('sitelinks_item', $cgi->_key); + + foreach ($ps->get () as $k => $v) { + if (isset ($this->widgets[$k])) { + $this->widgets[$k]->setDefault ($v); + } + } + + // misc widgets + $this->addWidget ('hidden', '_collection'); + $this->addWidget ('hidden', '_key'); + $this->addWidget ('hidden', '_return'); + + $w =& $this->addWidget ('msubmit', 'submitButton'); + + $b =& $w->getButton (); + $b->setValues (intl_get ('Save')); + + $b =& $w->addButton (); + $b->setValues (intl_get ('Cancel')); + $b->extra = 'onclick="history.go (-1); return false"'; + } + + function onSubmit ($vals) { + // 1. set values to ps + $ps = new PropertySet ('sitelinks_item', $vals['_key']); + + // 2. send user back + foreach (array_keys ($this->config) as $k) { + $ps->set ($k, $vals[$k]); + } + + if (! empty ($vals['_return'])) { + header ('Location: ' . $vals['_return']); + exit; + } + header ('Location: ' . site_prefix () . '/index/cms-browse-action?collection=sitelinks_item'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/html/admin.spt b/inc/app/sitelinks/html/admin.spt new file mode 100644 index 00000000..a7a722eb --- /dev/null +++ b/inc/app/sitelinks/html/admin.spt @@ -0,0 +1,101 @@ +<p> +<table width="100%"> + <tr> + <td> +{if obj.drafts gt 0} +<p><a href="{site/prefix}/index/cms-browse-action?collection=sitelinks_item&_sitellite_status=draft">{intl There are} {drafts} {intl links pending approval.}</a></p> +{end if} +{if else} +<p>{intl There are no links pending approval.}</p> +{end if} + </td> + <td align="right"> +<form method="get"> + {intl Range}: + <select name="top_range" onchange="this.form.submit ()"> + <option value="day" {if obj.top_range eq 'day'}selected="selected"{end if}>{intl Day}</option> + <!-- option value="week" {if obj.top_range eq 'week'}selected="selected"{end if}>{intl Week}</option --> + <option value="month" {if obj.top_range eq 'month'}selected="selected"{end if}>{intl Month}</option> + <option value="year" {if obj.top_range eq 'year'}selected="selected"{end if}>{intl Year}</option> + </select> + <input type="hidden" name="top_date" value="{top_date}" /> +</form> + </td> + </tr> +</table> +</p> + +<p> +<table width="100%"> + <tr> + <td width="33%"> + <a href="{site/prefix}/index/sitelinks-admin-action?top_range={top_range}&top_date={top_prev}">{filter sitelinks_filter_shortdate}{top_prev}{end filter}</a> + </td> + <td width="33%" align="center"> + <strong>{filter sitelinks_filter_shortdate}{top_date}{end filter}</strong> + </td> + <td width="33%" align="right"> + <a href="{site/prefix}/index/sitelinks-admin-action?top_range={top_range}&top_date={top_next}">{filter sitelinks_filter_shortdate}{top_next}{end filter}</a> + </td> + </tr> +</table> +</p> + +<h2>{intl Top} {php count (obj.views)} {intl Views}</h2> + +<p> +<table border="0" cellspacing="1" cellpadding="3" width="100%"> + <tr> + <th width="10%">{intl Rank}</th> + <th width="15%"># {intl of Views}</th> + <th>{intl Link}</th> + </tr> + {loop obj.views} + <tr style="background-color: {alt/next}"> + <td align="center">{loop/_index}</td> + <td align="right">{loop/total}</td> + <td><a href="{site/prefix}/index/sitelinks-app/item.{loop/item_id}">{filter sitelinks_filter_get_title}{loop/item_id}{end filter}</a></td> + </tr> + {end loop} +</table> +</p> + +<h2>{intl Top} {php count (obj.hits)} {intl Hits}</h2> + +<p> +<table border="0" cellspacing="1" cellpadding="3" width="100%"> + <tr> + <th width="10%">{intl Rank}</th> + <th width="15%"># {intl of Hits}</th> + <th>{intl Link}</th> + </tr> + {loop obj.hits} + <tr style="background-color: {alt/next}"> + <td align="center">{loop/_index}</td> + <td align="right">{loop/total}</td> + <td><a href="{site/prefix}/index/sitelinks-app/item.{loop/item_id}">{filter sitelinks_filter_get_title}{loop/item_id}{end filter}</a></td> + </tr> + {end loop} +</table> +</p> + +<h2>{intl Top} {php count (obj.ratings)} {intl Ratings}</h2> + +<p> +<table border="0" cellspacing="1" cellpadding="3" width="100%"> + <tr> + <th width="10%">{intl Rank}</th> + <th width="15%">{intl Rating}</th> + <th width="15%">{intl Votes}</th> + <th>{intl Link}</th> + </tr> + {loop obj.ratings} + <tr style="background-color: {alt/next}"> + <td align="center">{loop/_index}</td> + <td align="right">{loop/rating}</td> + <td align="right">{loop/votes}</td> + <td><a href="{site/prefix}/index/sitelinks-app/item.{loop/item_id}">{filter sitelinks_filter_get_title}{loop/item_id}{end filter}</a></td> + </tr> + {end loop} +</table> +</p> diff --git a/inc/app/sitelinks/html/categories.spt b/inc/app/sitelinks/html/categories.spt new file mode 100644 index 00000000..46c8389c --- /dev/null +++ b/inc/app/sitelinks/html/categories.spt @@ -0,0 +1,27 @@ +<h1>{appconf/sitelinks_name}</h1> + +{if obj[sitesearch]} +<p> + <a href="{site/prefix}/index/sitesearch-app?ctype=sitelinks_item&show_types=yes">{intl Search}</a> + {if appconf ('user_submissions')} +     + <a href="{site/prefix}/index/sitelinks-mylinks-action">{intl My} {appconf/sitelinks_name}</a> +     + <a href="{site/prefix}/index/sitelinks-newest-action">{intl Newest Links}</a> + {end if} + {if appconf ('user_ratings')} +     + <a href="{site/prefix}/index/sitelinks-top-action">{intl Top Listings}</a> + {end if} + {if appconf ('browse_by_type')} +     + <a href="{site/prefix}/index/sitelinks-types-action">{intl Browse By Type}</a> + {end if} +</p> +{end if} + +<ul> +{loop obj[categories]} + <li><a href="{site/prefix}/index/sitelinks-app/category.{loop/category}">{loop/category} ({loop/items})</a></li> +{end loop} +</ul> diff --git a/inc/app/sitelinks/html/category.spt b/inc/app/sitelinks/html/category.spt new file mode 100644 index 00000000..3d735487 --- /dev/null +++ b/inc/app/sitelinks/html/category.spt @@ -0,0 +1,30 @@ +{if not empty (obj[category])} +<h1>{category}</h1> + +<p> + <a href="{site/prefix}/index/sitelinks-app">{appconf/sitelinks_name}</a> / + {category} +</p> +{end if} +{if else} +<h1>{appconf/sitelinks_name}</h1> +{end if} + +{box cms/buttons/add?collection=sitelinks_item&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ loop.category]} + +<ul> +{loop obj[list]} + {if appconf ('item_pages')} + <li> + {box cms/buttons?collection=sitelinks_item&id=[loop/id]&status=[loop/sitellite_status]&access=[loop/sitellite_access]&float=true&add=false&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ loop.category]} + <a href="{site/prefix}/index/sitelinks-app/item.{loop/id}">{loop/title}</a> + </li> + {end if} + {if else} + <li> + {box cms/buttons?collection=sitelinks_item&id=[loop/id]&status=[loop/sitellite_status]&access=[loop/sitellite_access]&float=true&add=false&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ loop.category]} + <a href="{site/prefix}/index/sitelinks-app/forward.{loop/id}">{loop/title}</a> + </li> + {end if} +{end loop} +</ul> diff --git a/inc/app/sitelinks/html/category_selector.spt b/inc/app/sitelinks/html/category_selector.spt new file mode 100644 index 00000000..70568d7c --- /dev/null +++ b/inc/app/sitelinks/html/category_selector.spt @@ -0,0 +1,16 @@ +<p>{intl Please select a category}:</p> + +<form> + <p> + <select name="category" onchange="this.form.submit ()"> + <option value="">- {intl SELECT} -</option> + {loop obj} + <option value="{loop/id}">{loop/id}</option> + {end loop} + </select> + </p> + + <p> + <input type="submit" value="{intl Next}" /> + </p> +</form> diff --git a/inc/app/sitelinks/html/category_top.spt b/inc/app/sitelinks/html/category_top.spt new file mode 100644 index 00000000..4cb8d743 --- /dev/null +++ b/inc/app/sitelinks/html/category_top.spt @@ -0,0 +1,43 @@ +{if not empty (obj[category])} +<h1>{category}</h1> + +<p> + <a href="{site/prefix}/index/sitelinks-app">{appconf/sitelinks_name}</a> / + {category} +</p> +{end if} +{if else} +<h1>{appconf/sitelinks_name}</h1> +{end if} + +{if obj[sitesearch] or appconf ('user_submissions')} +<p> + {if obj[sitesearch]} + <a href="{site/prefix}/index/sitesearch-app?ctype=sitelinks_item&show_types=yes">{intl Search}</a> +     + {end if} + {if appconf ('user_submissions')} + <a href="{site/prefix}/index/sitelinks-mylinks-submit-action?category={category}">{intl Add} {appconf/sitelinks_name_singular}</a> +     + <a href="{site/prefix}/index/sitelinks-mylinks-action">{intl My} {appconf/sitelinks_name}</a> + {end if} + {if appconf ('rss_links')} +     + <a href="{site/prefix}/index/sitelinks-rss-action/category.{category}">{intl Syndicated Feed (RSS)}</a> + {end if} +</p> +{end if} + +{box cms/buttons/add?collection=sitelinks_item&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ cgi.category]} + +{if obj[pager]} +<div id="sitelinks-pager"> + <span style="float: left"> + {spt PAGER_TEMPLATE_FROM_TO} + </span> + <span style="float: right; text-align: right"> + {if pager.total}{spt PAGER_TEMPLATE_PREV_PAGE_LIST_NEXT}{end if} + </span> + <br style="clear: both" /> +</div> +{end if} diff --git a/inc/app/sitelinks/html/full/default.spt b/inc/app/sitelinks/html/full/default.spt new file mode 100644 index 00000000..683be320 --- /dev/null +++ b/inc/app/sitelinks/html/full/default.spt @@ -0,0 +1,42 @@ +<div class="sitelinks-item"> + {box cms/buttons?collection=sitelinks_item&id=[id]&status=[sitellite_status]&access=[sitellite_access]&float=true&return=[php site_prefix () _ '/index/sitelinks-app/item.' _ obj.id]&team=none} + <h1><a href="{site/prefix}/index/sitelinks-app/forward.{id}">{title}</a></h1> + + <p> + <a href="{site/prefix}/index/sitelinks-app">{appconf/sitelinks_name}</a> / + <a href="{site/prefix}/index/sitelinks-app/category.{category}">{category}</a> / + {title} + </p> + + {if obj.sitesearch} + {if not empty (obj.search_bar)} + {filter none}{search_bar}{end filter} + {end if} + {end if} + + {if obj.sitesearch or appconf ('user_submissions')} + <p> + {if obj.sitesearch} + <a href="{site/prefix}/index/sitesearch-app?ctype=sitelinks_item&show_types=yes">{intl Search}</a> +     + {end if} + {if appconf ('user_submissions')} + {if session_username () eq obj.user_id} + <a href="{site/prefix}/index/sitelinks-mylinks-update-action?id={id}">{intl Update This} {appconf/sitelinks_name_singular}</a> +     + {end if} + <a href="{site/prefix}/index/sitelinks-mylinks-submit-action?category={category}">{intl Add} {appconf/sitelinks_name_singular}</a> +     + <a href="{site/prefix}/index/sitelinks-mylinks-action">{intl My} {appconf/sitelinks_name}</a> + {end if} + </p> + {end if} + + <p class="sitelinks-summary">{filter none}{summary}{end filter}</p> + + <ul> + <li><strong>{intl Last Updated}:</strong> {filter sitelinks_filter_ts}{ts}{end filter}</li> + <li><strong>{intl Views}:</strong> {views}</li> + <li><strong>{intl Hits}:</strong> {hits}</li> + </ul> +</div> diff --git a/inc/app/sitelinks/html/full/music.spt b/inc/app/sitelinks/html/full/music.spt new file mode 100644 index 00000000..6fbdf740 --- /dev/null +++ b/inc/app/sitelinks/html/full/music.spt @@ -0,0 +1,43 @@ +<div class="sitelinks-item"> + {box cms/buttons?collection=sitelinks_item&id=[id]&status=[sitellite_status]&access=[sitellite_access]&float=true&return=[php site_prefix () _ '/index/sitelinks-app/item.' _ obj.id]&team=none} + <h1><a href="{site/prefix}/index/sitelinks-app/forward.{id}">{title}</a></h1> + + <p> + <a href="{site/prefix}/index/sitelinks-app">{appconf/sitelinks_name}</a> / + <a href="{site/prefix}/index/sitelinks-app/category.{category}">{category}</a> / + {title} + </p> + + {if obj.sitesearch} + {if not empty (obj.search_bar)} + {filter none}{search_bar}{end filter} + {end if} + {end if} + + {if obj.sitesearch or appconf ('user_submissions')} + <p> + {if obj.sitesearch} + <a href="{site/prefix}/index/sitesearch-app?ctype=sitelinks_item&show_types=yes">{intl Search}</a> +     + {end if} + {if appconf ('user_submissions')} + {if session_username () eq obj.user_id} + <a href="{site/prefix}/index/sitelinks-mylinks-update-action?id={id}">{intl Update This} {appconf/sitelinks_name_singular}</a> +     + {end if} + <a href="{site/prefix}/index/sitelinks-mylinks-submit-action?category={category}">{intl Add} {appconf/sitelinks_name_singular}</a> +     + <a href="{site/prefix}/index/sitelinks-mylinks-action">{intl My} {appconf/sitelinks_name}</a> + {end if} + </p> + {end if} + + <p class="sitelinks-summary">{filter none}{summary}{end filter}</p> + + <ul> + <li><strong>{intl Genre}:</strong> {genre}</strong></li> + <li><strong>{intl Last Updated}:</strong> {filter sitelinks_filter_ts}{ts}{end filter}</li> + <li><strong>{intl Views}:</strong> {views}</li> + <li><strong>{intl Hits}:</strong> {hits}</li> + </ul> +</div> diff --git a/inc/app/sitelinks/html/full/software.spt b/inc/app/sitelinks/html/full/software.spt new file mode 100644 index 00000000..3e876c3c --- /dev/null +++ b/inc/app/sitelinks/html/full/software.spt @@ -0,0 +1,45 @@ +<div class="sitelinks-item"> + {box cms/buttons?collection=sitelinks_item&id=[id]&status=[sitellite_status]&access=[sitellite_access]&float=true&return=[php site_prefix () _ '/index/sitelinks-app/item.' _ obj.id]&team=none} + <h1><a href="{site/prefix}/index/sitelinks-app/forward.{id}">{title}</a></h1> + + <p> + <a href="{site/prefix}/index/sitelinks-app">{appconf/sitelinks_name}</a> / + <a href="{site/prefix}/index/sitelinks-app/category.{category}">{category}</a> / + {title} + </p> + + {if obj.sitesearch} + {if not empty (obj.search_bar)} + {filter none}{search_bar}{end filter} + {end if} + {end if} + + {if obj.sitesearch or appconf ('user_submissions')} + <p> + {if obj.sitesearch} + <a href="{site/prefix}/index/sitesearch-app?ctype=sitelinks_item&show_types=yes">{intl Search}</a> +     + {end if} + {if appconf ('user_submissions')} + {if session_username () eq obj.user_id} + <a href="{site/prefix}/index/sitelinks-mylinks-update-action?id={id}">{intl Update This} {appconf/sitelinks_name_singular}</a> +     + {end if} + <a href="{site/prefix}/index/sitelinks-mylinks-submit-action?category={category}">{intl Add} {appconf/sitelinks_name_singular}</a> +     + <a href="{site/prefix}/index/sitelinks-mylinks-action">{intl My} {appconf/sitelinks_name}</a> + {end if} + </p> + {end if} + + <p class="sitelinks-summary">{filter none}{summary}{end filter}</p> + + <ul> + <li><strong>{intl Cost}:</strong> {cost}</strong></li> + <li><strong>{intl Platform}:</strong> {platform}</strong></li> + <li><strong>{intl Version}:</strong> {version}</strong></li> + <li><strong>{intl Last Updated}:</strong> {filter sitelinks_filter_ts}{ts}{end filter}</li> + <li><strong>{intl Views}:</strong> {views}</li> + <li><strong>{intl Hits}:</strong> {hits}</li> + </ul> +</div> diff --git a/inc/app/sitelinks/html/mylinks/default.spt b/inc/app/sitelinks/html/mylinks/default.spt new file mode 100644 index 00000000..a81a9aa3 --- /dev/null +++ b/inc/app/sitelinks/html/mylinks/default.spt @@ -0,0 +1,18 @@ +<div class="sitelinks-item-summary"> + {box cms/buttons?collection=sitelinks_item&id=[id]&status=[sitellite_status]&access=[sitellite_access]&float=true&add=false&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ obj.category]&team=none} + <h2> + <a href="{site/prefix}/index/sitelinks-app/item.{id}">{title}{if obj.sitelinks_top} ({intl Rating}: {rating}){end if}</a> + </h2> + + <p class="sitelinks-status"> + <strong>{intl Status}: {filter sitelinks_filter_status}{sitellite_status}{end filter}</strong> +     + <a href="{site/prefix}/index/sitelinks-mylinks-update-action?id={id}">{intl Update}</a> +     + <a href="{site/prefix}/index/sitelinks-mylinks-remove-action?id={id}" onclick="return sitelinks_confirm_delete ('{title}')">{intl Remove}</a> + </p> + + <p class="sitelinks-summary">{filter none}{summary}{end filter}</p> + + <p>{intl Last Updated}: {filter sitelinks_filter_ts}{ts}{end filter}</p> +</div> diff --git a/inc/app/sitelinks/html/mylinks/music.spt b/inc/app/sitelinks/html/mylinks/music.spt new file mode 100644 index 00000000..4731ee18 --- /dev/null +++ b/inc/app/sitelinks/html/mylinks/music.spt @@ -0,0 +1,26 @@ +<div class="sitelinks-item-summary"> + {box cms/buttons?collection=sitelinks_item&id=[id]&status=[sitellite_status]&access=[sitellite_access]&float=true&add=false&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ obj.category]&team=none} + <h2> + <a href="{site/prefix}/index/sitelinks-app/item.{id}">{title}{if obj.sitelinks_top} ({intl Rating}: {rating}){end if}</a> + </h2> + + <p class="sitelinks-status"> + <strong>{intl Status}: {filter sitelinks_filter_status}{sitellite_status}{end filter}</strong> +     + <a href="{site/prefix}/index/sitelinks-mylinks-update-action?id={id}">{intl Update}</a> +     + <a href="{site/prefix}/index/sitelinks-mylinks-remove-action?id={id}" onclick="return sitelinks_confirm_delete ('{title}')">{intl Remove}</a> + </p> + + <p class="sitelinks-summary">{filter none}{summary}{end filter}</p> + + <p> + <span style="float: left"> + {intl Genre}: {genre} + </span> + <span style="float: right"> + {intl Last Updated}: {filter sitelinks_filter_ts}{ts}{end filter} + </span> + <br style="clear: both" /> + </p> +</div> diff --git a/inc/app/sitelinks/html/mylinks/software.spt b/inc/app/sitelinks/html/mylinks/software.spt new file mode 100644 index 00000000..f2870188 --- /dev/null +++ b/inc/app/sitelinks/html/mylinks/software.spt @@ -0,0 +1,26 @@ +<div class="sitelinks-item-summary"> + {box cms/buttons?collection=sitelinks_item&id=[id]&status=[sitellite_status]&access=[sitellite_access]&float=true&add=false&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ obj.category]&team=none} + <h2> + <a href="{site/prefix}/index/sitelinks-app/item.{id}">{title}{if obj.sitelinks_top} ({intl Rating}: {rating}){end if}</a> + </h2> + + <p class="sitelinks-status"> + <strong>{intl Status}: {filter sitelinks_filter_status}{sitellite_status}{end filter}</strong> +     + <a href="{site/prefix}/index/sitelinks-mylinks-update-action?id={id}">{intl Update}</a> +     + <a href="{site/prefix}/index/sitelinks-mylinks-remove-action?id={id}" onclick="return sitelinks_confirm_delete ('{title}')">{intl Remove}</a> + </p> + + <p class="sitelinks-summary">{filter none}{summary}{end filter}</p> + + <p> + <span style="float: left"> + {intl Cost}: {cost} + </span> + <span style="float: right"> + {intl Platform}: {platform} + </span> + <br style="clear: both" /> + </p> +</div> diff --git a/inc/app/sitelinks/html/mylinks_none.spt b/inc/app/sitelinks/html/mylinks_none.spt new file mode 100644 index 00000000..9ad236a5 --- /dev/null +++ b/inc/app/sitelinks/html/mylinks_none.spt @@ -0,0 +1,12 @@ +{if obj[context] eq 'action'} +<h1>{intl My} {appconf/sitelinks_name}</h1> + +<p> + <a href="{site/prefix}/index/sitelinks-app">{appconf/sitelinks_name}</a> / + {intl My} {appconf/sitelinks_name} +</p> +{end if} + +<p>{intl You have not submitted any} {filter strtolower}{appconf/sitelinks_name}{end filter} {intl yet.}</p> + +<p><a href="{site/prefix}/index/sitelinks-mylinks-submit-action">{intl Add} {appconf/sitelinks_name_singular}</a></p> diff --git a/inc/app/sitelinks/html/mylinks_profile.spt b/inc/app/sitelinks/html/mylinks_profile.spt new file mode 100644 index 00000000..2360eec4 --- /dev/null +++ b/inc/app/sitelinks/html/mylinks_profile.spt @@ -0,0 +1,5 @@ +<ul> + {loop obj[list]} + <li><a href="{url}{loop/id}">{loop/title}</a> - {loop/category}</li> + {end loop} +</ul> diff --git a/inc/app/sitelinks/html/mylinks_short.spt b/inc/app/sitelinks/html/mylinks_short.spt new file mode 100644 index 00000000..e77c0f94 --- /dev/null +++ b/inc/app/sitelinks/html/mylinks_short.spt @@ -0,0 +1,47 @@ +{if obj[context] eq 'action'} +<h1>{intl My} {appconf/sitelinks_name}</h1> + +<p> + <a href="{site/prefix}/index/sitelinks-app">{appconf/sitelinks_name}</a> / + {intl My} {appconf/sitelinks_name} +</p> +{end if} + +{if obj[sitesearch] or appconf ('user_submissions')} +<p> + {if obj[sitesearch]} + <a href="{site/prefix}/index/sitesearch-app?ctype=sitelinks_item&show_types=yes">{intl Search}</a> +     + {end if} + {if appconf ('user_submissions')} + <a href="{site/prefix}/index/sitelinks-mylinks-submit-action">{intl Add} {appconf/sitelinks_name_singular}</a> + {end if} +</p> +{end if} + +{box cms/buttons/add?collection=sitelinks_item&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ cgi.category]} + +<script language="javascript" type="text/javascript"> + +function sitelinks_confirm_delete (title) { + return confirm ('{intl Are you sure you want to remove this listing?} ' + title); +} + +</script> + +<ul> +{loop obj[list]} + {if appconf ('item_pages')} + <li> + {box cms/buttons?collection=sitelinks_item&id=[loop/id]&status=[loop/sitellite_status]&access=[loop/sitellite_access]&float=true&add=false&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ loop.category]} + <a href="{site/prefix}/index/sitelinks-app/item.{loop/id}">{loop/title}</a> ({intl Status}: {filter ucwords}{loop/sitellite_status}{end filter}) + </li> + {end if} + {if else} + <li> + {box cms/buttons?collection=sitelinks_item&id=[loop/id]&status=[loop/sitellite_status]&access=[loop/sitellite_access]&float=true&add=false&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ loop.category]} + <a href="{site/prefix}/index/sitelinks-app/forward.{loop/id}">{loop/title}</a> ({intl Status}: {filter ucwords}{loop/sitellite_status}{end filter}) + </li> + {end if} +{end loop} +</ul> diff --git a/inc/app/sitelinks/html/mylinks_top.spt b/inc/app/sitelinks/html/mylinks_top.spt new file mode 100644 index 00000000..78700e11 --- /dev/null +++ b/inc/app/sitelinks/html/mylinks_top.spt @@ -0,0 +1,30 @@ +{if obj[context] eq 'action'} +<h1>{intl My} {appconf/sitelinks_name}</h1> + +<p> + <a href="{site/prefix}/index/sitelinks-app">{appconf/sitelinks_name}</a> / + {intl My} {appconf/sitelinks_name} +</p> +{end if} + +{if obj[sitesearch] or appconf ('user_submissions')} +<p> + {if obj[sitesearch]} + <a href="{site/prefix}/index/sitesearch-app?ctype=sitelinks_item&show_types=yes">{intl Search}</a> +     + {end if} + {if appconf ('user_submissions')} + <a href="{site/prefix}/index/sitelinks-mylinks-submit-action">{intl Add} {appconf/sitelinks_name_singular}</a> + {end if} +</p> +{end if} + +{box cms/buttons/add?collection=sitelinks_item&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ cgi.category]} + +<script language="javascript" type="text/javascript"> + +function sitelinks_confirm_delete (title) { + return confirm ('{intl Are you sure you want to remove this listing?} ' + title); +} + +</script> diff --git a/inc/app/sitelinks/html/not_registered.spt b/inc/app/sitelinks/html/not_registered.spt new file mode 100644 index 00000000..3b4cf4f0 --- /dev/null +++ b/inc/app/sitelinks/html/not_registered.spt @@ -0,0 +1,22 @@ +{if not empty (obj.username)} +<p>{intl Invalid username or password. Please try again.}</p> +{end if} +{if else} +<p>{intl If you are already a member, you may sign in here.}</p> +{end if} + +<form method="post"> + +<p>{intl Username}<br /> +<input type="text" name="username" /></p> + +<p>{intl Password}<br /> +<input type="password" name="password" /></p> + +<p><input type="submit" value="{intl Enter}" /></p> + +</form> + +<p><a href="{site/prefix}/index/sitellite-user-passrecover-action">{intl Forgot your password?}</a></p> + +<p>{intl Not a member?} <a href="{site/prefix}/index/org-memberReg-form">{intl Click here to register.}</a></p> diff --git a/inc/app/sitelinks/html/ratings.spt b/inc/app/sitelinks/html/ratings.spt new file mode 100644 index 00000000..1bd67b17 --- /dev/null +++ b/inc/app/sitelinks/html/ratings.spt @@ -0,0 +1,34 @@ +<div class="sitelinks-ratings"> + <h2>{intl User Ratings}</h2> + + {if obj[ratings] gt 0} + <p><strong>{intl Average Rating}:</strong> {ratings}</p> + + <p><strong>{intl Total Votes}:</strong> {votes}</p> + {end if} + {if else} + <p><strong>{intl No Votes Yet}</strong></p> + {end if} + + {if not obj[has_voted]} + + <h3>{intl Add Your Vote}</h3> + + <form method="post" action="{site/prefix}/index/sitelinks-ratings-action"> + <input type="hidden" name="item" value="{item}" /> + <p> + <select name="rating"> + <option value="" selected="selected">{intl Select Your Rating}</option> + <option value="5">{intl Excellent}!</option> + <option value="4">{intl Very Good}</option> + <option value="3">{intl Good}</option> + <option value="2">{intl Fair}</option> + <option value="1">{intl Poor}</option> + </select> +   + <input type="submit" value="{intl Vote}!" /> + </p> + </form> + + {end if} +</div> diff --git a/inc/app/sitelinks/html/ratings_thanks.spt b/inc/app/sitelinks/html/ratings_thanks.spt new file mode 100644 index 00000000..9b6e89d4 --- /dev/null +++ b/inc/app/sitelinks/html/ratings_thanks.spt @@ -0,0 +1 @@ +<p>{intl Your vote has been added.} <a href="{site/prefix}/index/sitelinks-app/item.{item}">{intl Click here to continue.}</a></p> diff --git a/inc/app/sitelinks/html/related.spt b/inc/app/sitelinks/html/related.spt new file mode 100644 index 00000000..6ace57ee --- /dev/null +++ b/inc/app/sitelinks/html/related.spt @@ -0,0 +1,7 @@ +<h2>{intl Related Links}</h2> + +<ul> + {loop obj} + <li><a href="{site/prefix}/index/sitelinks-app/item.{loop/id}">{loop/title}</a></li> + {end loop} +</ul> diff --git a/inc/app/sitelinks/html/rss_category.spt b/inc/app/sitelinks/html/rss_category.spt new file mode 100644 index 00000000..eb13d94a --- /dev/null +++ b/inc/app/sitelinks/html/rss_category.spt @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="iso-8859-1"?> + +<rdf:RDF + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" + xmlns:admin="http://webns.net/mvcb/" + xmlns="http://purl.org/rss/1.0/" +> + +<channel rdf:about="{site/url}/index/sitelinks-app/category.{cgi/category}"> + + <title>{rss_title} + {site/url}/index/sitelinks-app/category.{cgi/category} + {rss_description} + + {if not empty (intl_locale ())}{intl/locale}-{end if}{intl/language} + {rss_date} + + hourly + 1 + 1970-01-01T00:00+00:00 + + + + + +{loop obj[list]}{if loop._type ne 'date'} + +{end if}{end loop} + + + + + +{loop obj[list]}{if loop._type ne 'date'} + + {loop/title} + {site/url}/index/sitelinks-app/item.{loop/id} + {if empty (loop.summary)}{loop/body}{end if}{if else}{loop/summary}{end if} + {loop/category} + + +{end if}{end loop} + diff --git a/inc/app/sitelinks/html/sidebar.spt b/inc/app/sitelinks/html/sidebar.spt new file mode 100644 index 00000000..b7c28873 --- /dev/null +++ b/inc/app/sitelinks/html/sidebar.spt @@ -0,0 +1,5 @@ + diff --git a/inc/app/sitelinks/html/submission_notice.spt b/inc/app/sitelinks/html/submission_notice.spt new file mode 100644 index 00000000..5278cc5d --- /dev/null +++ b/inc/app/sitelinks/html/submission_notice.spt @@ -0,0 +1,9 @@ +You have received the following SiteLinks submission: + +Title: {title} +URL: {url} +User ID: {session/username} +Category: {category} +Summary: + +{summary} diff --git a/inc/app/sitelinks/html/submission_received.spt b/inc/app/sitelinks/html/submission_received.spt new file mode 100644 index 00000000..00f89e71 --- /dev/null +++ b/inc/app/sitelinks/html/submission_received.spt @@ -0,0 +1,3 @@ +

{intl Your submission has been received. Please allow some time for the administrator to review your submission before it appears on our web site.}

+ +

{intl Click here to continue.}

diff --git a/inc/app/sitelinks/html/summary/default.spt b/inc/app/sitelinks/html/summary/default.spt new file mode 100644 index 00000000..c159a0a1 --- /dev/null +++ b/inc/app/sitelinks/html/summary/default.spt @@ -0,0 +1,10 @@ + diff --git a/inc/app/sitelinks/html/summary/music.spt b/inc/app/sitelinks/html/summary/music.spt new file mode 100644 index 00000000..56ee9db7 --- /dev/null +++ b/inc/app/sitelinks/html/summary/music.spt @@ -0,0 +1,18 @@ + diff --git a/inc/app/sitelinks/html/summary/software.spt b/inc/app/sitelinks/html/summary/software.spt new file mode 100644 index 00000000..4d3fe508 --- /dev/null +++ b/inc/app/sitelinks/html/summary/software.spt @@ -0,0 +1,18 @@ + diff --git a/inc/app/sitelinks/html/top.spt b/inc/app/sitelinks/html/top.spt new file mode 100644 index 00000000..953230ba --- /dev/null +++ b/inc/app/sitelinks/html/top.spt @@ -0,0 +1,22 @@ +{if not empty (obj[category])} +

{category}

+ +

+ {appconf/sitelinks_name} / + {category} +

+{end if} +{if else} +

{appconf/sitelinks_name}

+{end if} + + diff --git a/inc/app/sitelinks/html/type.spt b/inc/app/sitelinks/html/type.spt new file mode 100644 index 00000000..e893fb8d --- /dev/null +++ b/inc/app/sitelinks/html/type.spt @@ -0,0 +1,30 @@ +{if not empty (obj[type])} +

{filter ucwords}{type}{end filter}

+ +

+ {appconf/sitelinks_name} / + {filter ucwords}{type}{end filter} +

+{end if} +{if else} +

{appconf/sitelinks_name}

+{end if} + +{box cms/buttons/add?collection=sitelinks_item&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ loop.category]} + +
    +{loop obj[list]} + {if appconf ('item_pages')} +
  • + {box cms/buttons?collection=sitelinks_item&id=[loop/id]&status=[loop/sitellite_status]&access=[loop/sitellite_access]&float=true&add=false&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ loop.category]} + {loop/title} +
  • + {end if} + {if else} +
  • + {box cms/buttons?collection=sitelinks_item&id=[loop/id]&status=[loop/sitellite_status]&access=[loop/sitellite_access]&float=true&add=false&return=[php site_prefix () _ '/index/sitelinks-app/category.' _ loop.category]} + {loop/title} +
  • + {end if} +{end loop} +
diff --git a/inc/app/sitelinks/html/type_top.spt b/inc/app/sitelinks/html/type_top.spt new file mode 100644 index 00000000..e56dc2d5 --- /dev/null +++ b/inc/app/sitelinks/html/type_top.spt @@ -0,0 +1,43 @@ +{if not empty (obj[type])} +

{filter ucwords}{type}{end filter}

+ +

+ {appconf/sitelinks_name} / + {filter ucwords}{type}{end filter} +

+{end if} +{if else} +

{appconf/sitelinks_name}

+{end if} + +{if obj[sitesearch] or appconf ('user_submissions')} +

+ {if obj[sitesearch]} + {intl Search} +     + {end if} + {if appconf ('user_submissions')} + {intl Add} {appconf/sitelinks_name_singular} +     + {intl My} {appconf/sitelinks_name} + {end if} + {if appconf ('rss_links')} +     + {intl Syndicated Feed (RSS)} + {end if} +

+{end if} + +{box cms/buttons/add?collection=sitelinks_item&return=[php site_prefix () _ '/index/sitelinks-app/type.' _ cgi.type]} + +{if obj[pager]} + +{end if} diff --git a/inc/app/sitelinks/html/types.spt b/inc/app/sitelinks/html/types.spt new file mode 100644 index 00000000..c07815a5 --- /dev/null +++ b/inc/app/sitelinks/html/types.spt @@ -0,0 +1,25 @@ +

{appconf/sitelinks_name}

+ +{if obj[sitesearch]} +

+ {intl Search} + {if appconf ('user_submissions')} +     + {intl My} {appconf/sitelinks_name} +     + {intl Newest Links} + {end if} + {if appconf ('user_ratings')} +     + {intl Top Listings} + {end if} +     + {intl Browse By Category} +

+{end if} + + diff --git a/inc/app/sitelinks/install/INSTALL b/inc/app/sitelinks/install/INSTALL new file mode 100644 index 00000000..83e53c83 --- /dev/null +++ b/inc/app/sitelinks/install/INSTALL @@ -0,0 +1 @@ +Your installation instructions go here diff --git a/inc/app/sitelinks/install/changes.txt b/inc/app/sitelinks/install/changes.txt new file mode 100644 index 00000000..2cf45848 --- /dev/null +++ b/inc/app/sitelinks/install/changes.txt @@ -0,0 +1,19 @@ +Changes in 1.0.4 + +- Database schema update to comply with Sitellite 4.2.7 -- see the file + install/upgrade-1.0.3-1.0.4.sql + +Changes in 1.0.3 + +- mylinks box now hides

and breadcrumb if embedded into another page, + making it more suitable for use with SiteMember now. +- Added sitelinks/mylinks/profile box for use with SiteMember for profile + pages. + +Changes in 1.0.2 + +- Browse by type. + +Changes in 1.0.1 + +- Added sitellite_owner and sitellite_team columns to the sitelinks_item table. diff --git a/inc/app/sitelinks/install/install-mysql.sql b/inc/app/sitelinks/install/install-mysql.sql new file mode 100644 index 00000000..da2ae8fd --- /dev/null +++ b/inc/app/sitelinks/install/install-mysql.sql @@ -0,0 +1,77 @@ +# Your database schema goes here + +create table sitelinks_item ( + id int not null auto_increment primary key, + title char(128) not null, + url char(255) not null, + user_id char(32) not null, + rank int not null, + user_rating decimal(3,2) not null, + category char(48) not null, + ctype char(48) not null, + ts datetime not null, + summary text not null, + sitellite_status char(16) not null, + sitellite_access char(16) not null, + sitellite_owner char(48) not null, + sitellite_team char(48) not null, + index (user_id,rank,user_rating,category,ctype,ts,sitellite_status,sitellite_access,sitellite_owner,sitellite_team) +); + +create table sitelinks_item_sv ( + sv_autoid int(11) NOT NULL auto_increment primary key, + sv_author varchar(16) NOT NULL default '', + sv_action enum('created','modified','republished','replaced','restored','deleted','updated') NOT NULL default 'created', + sv_revision datetime NOT NULL, + sv_changelog text NOT NULL, + sv_deleted enum('yes','no') NOT NULL default 'no', + sv_current enum('yes','no') NOT NULL default 'yes', + id int not null, + title char(128) not null, + url char(255) not null, + user_id char(32) not null, + rank int not null, + user_rating decimal(3,2) not null, + category char(48) not null, + ctype char(48) not null, + ts datetime not null, + summary text not null, + sitellite_status char(16) not null, + sitellite_access char(16) not null, + sitellite_owner char(48) not null, + sitellite_team char(48) not null, + index sv_author (sv_author,sv_action,sv_revision,sv_deleted,sv_current), + index (user_id,rank,user_rating,category,ctype,ts,sitellite_status,sitellite_access,sitellite_owner,sitellite_team) +); + +create table sitelinks_category ( + id char(48) not null primary key +); + +create table sitelinks_hit ( + id int not null auto_increment primary key, + item_id int not null, + ts datetime not null, + ip char(15) not null, + ua char(128) not null, + index (item_id,ts,ip,ua) +); + +create table sitelinks_view ( + id int not null auto_increment primary key, + item_id int not null, + ts datetime not null, + ip char(15) not null, + ua char(128) not null, + index (item_id,ts,ip,ua) +); + +create table sitelinks_rating ( + id int not null auto_increment primary key, + item_id int not null, + rating int not null, + ts datetime not null, + ip char(15) not null, + ua char(128) not null, + index (item_id,rating,ts,ip,ua) +); diff --git a/inc/app/sitelinks/install/sitelinks_item.php b/inc/app/sitelinks/install/sitelinks_item.php new file mode 100644 index 00000000..ae272680 --- /dev/null +++ b/inc/app/sitelinks/install/sitelinks_item.php @@ -0,0 +1,163 @@ +; \ No newline at end of file diff --git a/inc/app/sitelinks/install/update-1.0.0-1.0.1.sql b/inc/app/sitelinks/install/update-1.0.0-1.0.1.sql new file mode 100644 index 00000000..c524fb7c --- /dev/null +++ b/inc/app/sitelinks/install/update-1.0.0-1.0.1.sql @@ -0,0 +1,6 @@ +alter table sitelinks_item add column sitellite_owner char(48) not null; +alter table sitelinks_item add column sitellite_team char(48) not null; +alter table sitelinks_item add index (sitellite_owner, sitellite_team); +alter table sitelinks_item_sv add column sitellite_owner char(48) not null; +alter table sitelinks_item_sv add column sitellite_team char(48) not null; +alter table sitelinks_item_sv add index (sitellite_owner, sitellite_team); diff --git a/inc/app/sitelinks/install/upgrade-1.0.3-1.0.4.sql b/inc/app/sitelinks/install/upgrade-1.0.3-1.0.4.sql new file mode 100644 index 00000000..2bb48b76 --- /dev/null +++ b/inc/app/sitelinks/install/upgrade-1.0.3-1.0.4.sql @@ -0,0 +1 @@ +alter table sitelinks_item_sv modify sv_action enum('created','modified','republished','replaced','restored','deleted','updated') not null default 'created'; diff --git a/inc/app/sitelinks/lib/Filters.php b/inc/app/sitelinks/lib/Filters.php new file mode 100644 index 00000000..4465cc91 --- /dev/null +++ b/inc/app/sitelinks/lib/Filters.php @@ -0,0 +1,41 @@ +top_range) { + case 'day': + $format = appconf ('admin_date_short'); + break; + case 'month': + $format = appconf ('admin_date_month'); + break; + case 'year': + $format = appconf ('admin_date_year'); + break; + } + + return Date::format ($date, $format); +} + +function sitelinks_filter_status ($status) { + if ($status == 'approved') { + return intl_get ('Live'); + } elseif ($status == 'rejected') { + return intl_get ('Rejected'); + } + return intl_get ('Pending'); +} + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/lib/Functions.php b/inc/app/sitelinks/lib/Functions.php new file mode 100644 index 00000000..7566ab17 --- /dev/null +++ b/inc/app/sitelinks/lib/Functions.php @@ -0,0 +1,59 @@ + \ No newline at end of file diff --git a/inc/app/sitelinks/lib/Item.php b/inc/app/sitelinks/lib/Item.php new file mode 100644 index 00000000..775f8457 --- /dev/null +++ b/inc/app/sitelinks/lib/Item.php @@ -0,0 +1,330 @@ +usePermissions = true; + if (session_admin ()) { + $this->perms = session_allowed_sql (); + } elseif (session_valid ()) { + $this->perms = '((' . session_approved_sql () . ') or user_id = "' . session_username () . '")'; + } else { + $this->perms = session_approved_sql (); + } + //die ($this->perms); + } + + function get ($id) { + $item = db_single ('select * from sitelinks_item where id = ? and ' . $this->perms, $id); + if (! $item) { + return $item; + } + + $ps = new PropertySet ('sitelinks_item', $id); + foreach ($ps->get () as $k => $v) { + $item->{$k} = $v; + } + + $item->views = $this->views ($id); + $item->hits = $this->hits ($id); + $rating = $this->rating ($id); + $item->votes = $rating->votes; + $item->rating = $rating->rating; + return $item; + } + + /** + * Returns the number of views of the specified item. + */ + function views ($item) { + return db_shift ('select count(*) from sitelinks_view where item_id = ?', $item); + } + + /** + * Returns the number of hits of the specified item. + */ + function hits ($item) { + return db_shift ('select count(*) from sitelinks_hit where item_id = ?', $item); + } + + /** + * Returns an object with the properties $obj->rating and $obj->votes, + * where the rating is the average of all the votes for this item, + * and votes is the number of votes placed. + */ + function rating ($item) { + $res = db_single ( + 'select avg(rating) as rating, count(*) as votes from sitelinks_rating where item_id = ?', + $item + ); + $res->rating = number_format ($res->rating, 2); + return $res; + } + + /** + * Increases the number of views of the specified item. + */ + function addView ($item) { + $res = db_shift ( + 'select count(*) from sitelinks_view where item_id = ? and ts > date_sub(now(), interval 1 day) and ip = ? and ua = ?', + $item, + $_SERVER['REMOTE_ADDR'], + $_SERVER['HTTP_USER_AGENT'] + ); + if ($res > 0) { + return false; + } + + $res = db_execute ( + 'insert into sitelinks_view (id, item_id, ts, ip, ua) values (null, ?, now(), ?, ?)', + $item, + $_SERVER['REMOTE_ADDR'], + $_SERVER['HTTP_USER_AGENT'] + ); + if (! $res) { + $this->error = db_error (); + return false; + } + return true; + } + + /** + * Increases the number of hits (aka "click throughs") of the specified item. + */ + function addHit ($item) { + $res = db_shift ( + 'select count(*) from sitelinks_hit where item_id = ? and ts > date_sub(now(), interval 1 day) and ip = ? and ua = ?', + $item, + $_SERVER['REMOTE_ADDR'], + $_SERVER['HTTP_USER_AGENT'] + ); + if ($res > 0) { + return false; + } + + $res = db_execute ( + 'insert into sitelinks_hit (id, item_id, ts, ip, ua) values (null, ?, now(), ?, ?)', + $item, + $_SERVER['REMOTE_ADDR'], + $_SERVER['HTTP_USER_AGENT'] + ); + if (! $res) { + $this->error = db_error (); + return false; + } + return true; + } + + /** + * Determines whether the current visitor has voted for the specified item within the + * past month. + */ + function hasVoted ($item) { + return db_shift ( + 'select count(*) from sitelinks_rating where item_id = ? and ip = ? and ua = ? and ts > date_sub(now(), interval 1 month)', + $item, + $_SERVER['REMOTE_ADDR'], + $_SERVER['HTTP_USER_AGENT'] + ); + } + + /** + * Makes a rating on the specified item. $rating should be from 0 to 5. + */ + function addRating ($item, $rating) { + if ($this->hasVoted ($item)) { + return false; + } + + $res = db_execute ( + 'insert into sitelinks_rating (id, item_id, rating, ts, ip, ua) values (null, ?, ?, now(), ?, ?)', + $item, + $rating, + $_SERVER['REMOTE_ADDR'], + $_SERVER['HTTP_USER_AGENT'] + ); + if (! $res) { + $this->error = db_error (); + return false; + } + + $r = $this->rating ($item); + loader_import ('cms.Versioning.Rex'); + $rex = new Rex ('sitelinks_item'); + if (! $rex->collection) { + $this->error = 'SiteLinks collection is not installed. Please copy install/sitelinks_item.php into inc/app/cms/conf/collections.'; + return false; + } + $rex->modify ($item, array ('user_rating' => $r->rating)); + + return true; + } + + function getCategories () { + return db_fetch_array ('select category, count(*) as items from sitelinks_item where category != "" and ' . $this->perms . ' group by category asc'); + } + + function getTypes () { + return db_fetch_array ('select ctype, count(*) as items from sitelinks_item where ctype != "" and ' . $this->perms . ' group by ctype asc'); + } + + function getCategory ($cat = false, $limit = false, $offset = false) { + if (! $limit) { + if ($cat) { + $res = db_fetch_array ( + 'select * from sitelinks_item where category = ? and ' . $this->perms . ' order by rank desc, user_rating desc, ts desc', + $cat + ); + } else { + $res = db_fetch_array ( + 'select * from sitelinks_item where ' . $this->perms . ' order by rank desc, user_rating desc, ts desc' + ); + } + } else { + if ($cat) { + $q = db_query ( + 'select * from sitelinks_item where category = ? and ' . $this->perms . ' order by rank desc, user_rating desc, ts desc' + ); + $b = array ($cat); + } else { + $q = db_query ( + 'select * from sitelinks_item where ' . $this->perms . ' order by rank desc, user_rating desc, ts desc' + ); + $b = array (); + } + + if ($q->execute ($b)) { + $res = $q->fetch ($offset, $limit); + $this->total = $q->rows (); + $q->free (); + } else { + $this->error = $q->error (); + return false; + } + } + + $ps = new PropertySet ('sitelinks_item', false); + foreach (array_keys ($res) as $key) { + $ps->entity = $res[$key]->id; + foreach ($ps->get () as $k => $v) { + $res[$key]->{$k} = $v; + } + } + + return $res; + } + + function getByType ($type = false, $limit = false, $offset = false) { + if (! $limit) { + if ($type) { + $res = db_fetch_array ( + 'select * from sitelinks_item where ctype = ? and ' . $this->perms . ' order by rank desc, user_rating desc, ts desc', + $type + ); + } else { + $res = db_fetch_array ( + 'select * from sitelinks_item where ' . $this->perms . ' order by rank desc, user_rating desc, ts desc' + ); + } + } else { + if ($type) { + $q = db_query ( + 'select * from sitelinks_item where ctype = ? and ' . $this->perms . ' order by rank desc, user_rating desc, ts desc' + ); + $b = array ($type); + } else { + $q = db_query ( + 'select * from sitelinks_item where ' . $this->perms . ' order by rank desc, user_rating desc, ts desc' + ); + $b = array (); + } + + if ($q->execute ($b)) { + $res = $q->fetch ($offset, $limit); + $this->total = $q->rows (); + $q->free (); + } else { + $this->error = $q->error (); + return false; + } + } + + $ps = new PropertySet ('sitelinks_item', false); + foreach (array_keys ($res) as $key) { + $ps->entity = $res[$key]->id; + foreach ($ps->get () as $k => $v) { + $res[$key]->{$k} = $v; + } + } + + return $res; + } + + function myLinks ($user = false) { + if (! $user) { + $user = session_username (); + } + + $res = db_fetch_array ( + 'select * from sitelinks_item where user_id = ? order by title asc', + $user + ); + + $ps = new PropertySet ('sitelinks_item', false); + foreach (array_keys ($res) as $key) { + $ps->entity = $res[$key]->id; + foreach ($ps->get () as $k => $v) { + $res[$key]->{$k} = $v; + } + } + + return $res; + } + + function getNewest ($limit = 10) { + $res = db_fetch_array ( + 'select * from sitelinks_item where ' . $this->perms . ' order by ts desc limit ' . $limit + ); + + $ps = new PropertySet ('sitelinks_item', false); + foreach (array_keys ($res) as $key) { + $ps->entity = $res[$key]->id; + foreach ($ps->get () as $k => $v) { + $res[$key]->{$k} = $v; + } + } + + return $res; + } + + function getTop ($limit = 10) { + $res = db_fetch_array ( + 'select * from sitelinks_item where ' . $this->perms . ' order by user_rating desc limit ' . $limit + ); + + $ps = new PropertySet ('sitelinks_item', false); + foreach (array_keys ($res) as $key) { + $r = $this->rating ($res[$key]->id); + $res[$key]->rating = $r->rating; + $ps->entity = $res[$key]->id; + foreach ($ps->get () as $k => $v) { + $res[$key]->{$k} = $v; + } + } + + return $res; + } + + function getRelated ($item) { + $uid = db_shift ('select user_id from sitelinks_item where id = ?', $item); + return db_fetch_array ('select id, title from sitelinks_item where user_id = ? and id != ? and ' . $this->perms . ' order by title asc limit 5', $uid, $item); + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitelinks/lib/Widget/Linktype.php b/inc/app/sitelinks/lib/Widget/Linktype.php new file mode 100644 index 00000000..4cbad808 --- /dev/null +++ b/inc/app/sitelinks/lib/Widget/Linktype.php @@ -0,0 +1,146 @@ + | +// +----------------------------------------------------------------------+ +// | Authors: John Luxford | +// +----------------------------------------------------------------------+ +// +// Linktype widget. Displays an HTML form field containing a + * list of types from inc/app/sitelinks/html/types. + * + * + * validation ('is "foo"'); + * $widget->setValue ('foo'); + * $widget->error_message = 'Oops! This widget is being unruly!'; + * + * ? > + * + * + * @package SiteLinks + * @author John Luxford + * @copyright Copyright (C) 2001-2003, Simian Systems Inc. + * @license http://www.sitellite.org/index/license Simian Open Software License + * @version 1.0, 2001-11-28, $Id: Linktype.php,v 1.1.1.1 2004/06/14 17:44:22 lux Exp $ + * @access public + * + */ + +class MF_Widget_linktype extends MF_Widget { + /** + * A way to pass extra parameters to the HTML form tag, for + * example 'enctype="multipart/formdata"'. + * + * @access public + * + */ + var $extra = ''; + + /** + * This is the short name for this widget. The short name is + * the class name minus the 'MF_Widget_' prefix. + * + * @access public + * + */ + var $type = 'linktype'; + + function getTypes ($path = false) { + if (! $path) { + $path = site_docroot () . '/inc/app/sitelinks/html/full'; + } + + $types = array ('default' => 'Default'); + + loader_import ('saf.File.Directory'); + $dir = new Dir; + if (! $dir->open ($path)) { + return $types; + } + + foreach ($dir->read_all () as $file) { + if (strpos ($file, '.') === 0 || @is_dir ($path . '/' . $file)) { + continue; + } + if (preg_match ('/^([^\.]+)\.spt$/', $file, $regs)) { + $types[$regs[1]] = ucfirst ($regs[1]); + } + } + + return $types; + } + + /** + * Returns the display HTML for this widget. The optional + * parameter determines whether or not to automatically display the widget + * nicely, or whether to simply return the widget (for use in a template). + * + * @access public + * @param boolean $generate_html + * @return string + * + */ + function display ($generate_html = 0) { + global $intl, $simple; + if (! isset ($this->data_value)) { + $this->data_value = $this->default_value; + } + + $this->value = $this->getTypes (); + + $attrstr = $this->getAttrs (); + if ($generate_html) { + $data = "\t" . '' . "\n\t\t" . '' . "\n\t\t" . + ''; + $data .= '' . "\n\t" . '' . "\n"; + return $data; + + } else { + $data = ''; + } + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/access.php b/inc/app/sitemailer2/boxes/access.php new file mode 100644 index 00000000..a49d9f5a --- /dev/null +++ b/inc/app/sitemailer2/boxes/access.php @@ -0,0 +1,5 @@ +sitellite_access = private +sitellite_status = approved +sitellite_action = on +sitellite_goto = sitemailer2-app +sitellite_template_set = admin diff --git a/inc/app/sitemailer2/boxes/archive/index.php b/inc/app/sitemailer2/boxes/archive/index.php new file mode 100644 index 00000000..e2ff041c --- /dev/null +++ b/inc/app/sitemailer2/boxes/archive/index.php @@ -0,0 +1,97 @@ +offset)) { + $cgi->offset = 0; +} + +page_title ('SiteMailer 2'); + +$data = array (); + +$clause = ' where '; +$bind = array (); + +if (! empty ($cgi->_newsletter)) { + $message_ids = db_shift_array ('select message from sitemailer2_message_newsletter where newsletter = ?', $cgi->_newsletter); + + if (count ($message_ids) > 0) { + $message_ids = 'in(' . implode (', ', $message_ids) . ')'; + + $sql .= $clause . ' id ' . $message_ids; + $clause = ' and '; + } + + $bind[] = $cgi->_newsletter; +} + +if (! empty ($cgi->status)) { + $sql .= $clause . 'status = ?'; + $bind[] = $cgi->status; + $clause = ' and '; +} else { + $sql .= $clause . 'status in("running", "done")'; + $clause = ' and '; +} + + +$total = db_shift ('select count(*) from sitemailer2_message ' . $sql); + + + +$q = db_query ('select * from sitemailer2_message ' . $sql . ' order by date desc'); + + +if ($q->execute ($bind)) { + $res = $q->fetch ($cgi->offset, $limit); + $q->free (); + + +} else { + die ($q->error ()); +} + +foreach (array_keys ($res) as $k) { + $res[$k]->bounced = 0; + if ($res[$k]->status != 'done') { + $res[$k]->numsent .= ' (' . round (($res[$k]->numsent / ($res[$k]->numsent + db_shift ('select count(*) from sitemailer2_q where message = ?', $res[$k]->id))) * 100) . '%)'; + } +} + +$data['list'] =& $res; + +$rex = new Rex (false); + +$rex->facets['subject'] = new rTextFacet ('subject', array ('display' => intl_get ('Text'), 'type' => 'text')); +$rex->facets['subject']->preserve = array ('offset'); +$rex->facets['subject']->fields = array ('id', 'subject', 'mbody'); + +$rex->facets['newsletter'] = new rSelectFacet ('newsletter', array ('display' => intl_get ('Newsletter'), 'type' => 'select')); +$rex->facets['newsletter']->preserve = array ('offset'); +$rex->facets['newsletter']->options = db_pairs ('select id, name from sitemailer2_newsletter order by name asc'); +$rex->facets['newsletter']->count = false; + +$rex->facets['status'] = new rSelectFacet ('status', array ('display' => intl_get ('Status'), 'type' => 'select')); +$rex->facets['status']->preserve = array ('offset'); +$rex->facets['status']->options = array ('running' => 'Running', 'done' => 'Done'); +$rex->facets['status']->count = false; + +$data['facets'] = $rex->renderFacets (); + +$pg = new Pager ($cgi->offset, $limit, $total); +$pg->url = site_prefix () . '/index/sitemailer2-archive-action?_newsletter=' . urlencode ($cgi->_newsletter) . '&_status=' . urlencode ($cgi->_status) . '&_subject=' . urlencode ($cgi->_subject); +$pg->setData ($res); +$pg->update (); + +template_simple_register ('pager', $pg); +echo template_simple ('archive.spt', $data); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/bouncer/access.php b/inc/app/sitemailer2/boxes/bouncer/access.php new file mode 100644 index 00000000..23ba4d45 --- /dev/null +++ b/inc/app/sitemailer2/boxes/bouncer/access.php @@ -0,0 +1,4 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on + diff --git a/inc/app/sitemailer2/boxes/bouncer/index.php b/inc/app/sitemailer2/boxes/bouncer/index.php new file mode 100644 index 00000000..0883040f --- /dev/null +++ b/inc/app/sitemailer2/boxes/bouncer/index.php @@ -0,0 +1,244 @@ +parseUri (); +array_shift ($args); + +$testing = false; +$quiet = false; + +foreach ($args as $a) { + if ($a == 'testing') { + $testing = true; + echo "Running in test mode...\n"; + } if ($a == 'quiet') { + $quiet = true; + } +} + +if (! $quiet) echo "Loading Packages...\n"; + +loader_import ('sitemailer2.Bouncer'); +loader_import ('saf.Mail.Pop3'); +loader_import ('pear.Mail.mimeDecode'); +loader_import ('cms.Workspace.Message'); +loader_import ('saf.File.Store'); + +if ($testing) { + + loader_import ('saf.File.Directory'); + + $folder = 'inc/app/sitemailer2/tests'; + + foreach (Dir::find ('*.txt', $folder) as $file) { + $messages[$file]['message'] = join ('', file ($file)); + } + +} else { + + $settings = parse_ini_file ('inc/app/sitemailer2/conf/settings2.ini.php'); + + if ($settings['email_id'] == "ENTER_YOUR_EMAIL_ID") { + echo "You must configure your server settings under the settings tab in the sitemailer web interface!\n"; + exit; + } + + $pop3 = new Pop3 ($settings['email_server'], $settings['email_port']); + + if (! $quiet) echo "Connecting to mail server...\n"; + + if (! $pop3->connect ()) { + echo $pop3->error . "\n"; + return; + } + + if (! $quiet) echo "Authenicating...\n"; + + if (! $pop3->authenticate ($settings['email_id'], $settings['email_password'])) { + echo $pop3->error . "\n"; + return; + } + + if (! $quiet) echo "Getting message list...\n"; + + $messages = $pop3->listMessages (); + +} + +$wmsg = new WorkspaceMessage (); + +$total = count ($messages); +$sofar = 0; + +echo 'Found ' . $total . " messages.\n"; + +if ($total == 0) exit; + +foreach ($messages as $number => $message) { + + $sofar++; + + if (! $quiet) echo 'Downloading message ' . $sofar . '/' . $total . "...\n"; + + if (! $testing) { + + set_time_limit (1000); + + $messages[$number]['message'] = $pop3->getMessage ($number); + if ($messages[$number]['message'] === false) { + echo $pop3->error . "\n"; + } + + } + + if (! $quiet) echo "Processing message...\n"; + + // parse message and send to system + $md = new Mail_mimeDecode ($messages[$number]['message']); + $decoded = $md->decode (array ( + 'include_bodies' => true, + 'decode_bodies' => true, + 'decode_headers' => true, + )); + + //parse the from line + $from_email = getEmailFromAddress ($decoded->headers['from']); + $fname = getFirstNameFromAddress ($decoded->headers['from']); + $lname = getLastNameFromAddress ($decoded->headers['from']); + + /*if (strcasecmp ($from_email, $settings['email_address']) == 0) { + $pop3->removeMessage ($number); + continue; + }*/ + + // determine priority + if (preg_match ("/^[0-9]$/", $decoded->headers['x-priority'])) { + $priority = $decoded->headers['x-priority']; + } else { + $priority = 3; + } + + $body = ''; + + //parse the body + if (! empty ($decoded->body)) { + if ($decoded->ctype_secondary == 'plain') { + $body = $wmsg->formatBody ($decoded->body); + } else { + $body = $decoded->body; + } + $attachments = array (); + } else { + $body = ''; + $attachments = array (); + foreach ($decoded->parts as $part) { + if ($part->disposition == 'attachment' || $part->ctype_primary != 'text') { + + $a = array ( + 'type' => 'document', + ); + $a['name'] = $part->d_parameters['filename']; + $a['body'] = $part->body; + $a['mime'] = $part->ctype_primary . '/' . $part->ctype_secondary; + $a['summary'] = ''; + $attachments[] = $a; + } else { + if ($part->ctype_secondary == 'plain') { + $body .= $wmsg->formatBody ($part->body); + } else { + $body .= $part->body; + } + } + } + } + + //parse timestamp + $ts; + $unixtime = strtotime ($decoded->headers['date']); + $ts = date ('Y-m-d H:i:s', $unixtime); + + //bounce detection begins + if (! $quiet) echo "Bounce detection begins...\n"; + + //rules to scan for + $rules = array ( + 'DSN', + 'Qmail', + 'Postfix', + 'Yahoo', + 'Caiwireless', + 'Exchange', + 'Exim', + 'Netscape', + 'Compuserve', + 'Microsoft', + 'GroupWise', + 'SMTP32', + 'SimpleMatch', + 'Yale', + 'LLNL',); + + $found_bounce = false; + $done_rules = false; + foreach ($rules as $r) { + + $f = 'bouncer_' . strtolower ($r); + + //if true, then message is bounced + if ($res = call_user_func ($f, $decoded)) { + if (! $quiet) echo 'Bounced message detected from mailer ' . $r . "\n"; + + if ($res === true) { + if (! $quiet) echo "No recipient found, continuing bounce detection.\n"; + $found_bounce = true; + continue; + } + + if (! $quiet) echo 'Recipient(s) found: ' . implode (', ', $res) . "\n"; + + unsub($res); + count_bounce(count($res)); + + $done_rules = true; + break; + } + } + + //count bounced messages even if a recipient wasn't found + if ($found_bounce) { + count_bounce(1); + } + + if (! $done_rules && $testing) { + echo "Message not a bounced message: " . $number . "\n"; + } + + //$pop3->removeMessage ($number); +} + +if (! $testing) { + $pop3->disconnect (); +} + +echo "\n"; + +exit; + +?> diff --git a/inc/app/sitemailer2/boxes/bouncer/summary.txt b/inc/app/sitemailer2/boxes/bouncer/summary.txt new file mode 100644 index 00000000..41b4e016 --- /dev/null +++ b/inc/app/sitemailer2/boxes/bouncer/summary.txt @@ -0,0 +1,111 @@ + 'DSN', delivery status notification + header action != failed or failure + 'Qmail', + introtag = 'Hi. This is the' + acre = re.compile(r'<(?P[^>]*)>:') + 'Postfix', + pcre = re.compile(r'[ \t]*the\s*(bns)?\s*(postfix|keftamail|smtp_gateway)', re.IGNORECASE) + rcre = re.compile(r'failure reason:$', re.IGNORECASE) + acre = re.compile(r'<(?P[^>]*)>:') + 'Yahoo', + tcre = re.compile(r'message\s+from\s+yahoo\.\S+', re.IGNORECASE) + acre = re.compile(r'<(?P[^>]*)>:') + ecre = re.compile(r'--- Original message follows') + if not sender.startswith('mailer-daemon@yahoo'): + 'Caiwireless', + tcre = re.compile(r'the following recipients did not receive this message:', re.IGNORECASE) + acre = re.compile(r'<(?P[^>]*)>') + 'Exchange', + scre = re.compile('did not reach the following recipient') + ecre = re.compile('MSEXCH:') + a1cre = re.compile('SMTP=(?P[^;]+); on ') + a2cre = re.compile('(?P[^ ]+) on ') + 'Exim', + header 'x-failed-recipients' + 'Netscape', + pcre = re.compile(r'This Message was undeliverable due to the following reason:', + re.IGNORECASE) + acre = re.compile(r'(?Pplease reply to)?.*<(?P[^>]*)>', re.IGNORECASE) + 'Compuserve', + dcre = re.compile(r'your message could not be delivered', re.IGNORECASE) + acre = re.compile(r'Invalid receiver address: (?P.*)') + 'Microsoft', + scre = re.compile(r'transcript of session follows', re.IGNORECASE) + 'GroupWise', + X-Mailer: Novell GroupWise Internet Agent 5.5.3.1 + X-Mailer: NTMail v4.30.0012 + X-Mailer: Internet Mail Service (5.5.2653.19) + ??? + 'SMTP32', + ecre = re.compile('original message follows', re.IGNORECASE) + acre = re.compile(r''' + ( # several different prefixes + user\ mailbox[^:]*: # have been spotted in the + |delivery\ failed[^:]*: # wild... + |undeliverable\ to + ) + \s* # space separator + (?P.*) # and finally, the address + ''', re.IGNORECASE | re.VERBOSE) + 'SimpleMatch', + PATTERNS = [ + # sdm.de + (_c('here is your list of failed recipients'), + _c('here is your returned mail'), + _c(r'<(?P[^>]*)>')), + # sz-sb.de, corridor.com, nfg.nl + (_c('the following addresses had'), + _c('transcript of session follows'), + _c(r'<(?P[^>]*)>|\(expanded from: [^>)]*)>?\)')), + # robanal.demon.co.uk + (_c('this message was created automatically by mail delivery software'), + _c('original message follows'), + _c('rcpt to:\s*<(?P[^>]*)>')), + # s1.com (InterScan E-Mail VirusWall NT ???) + (_c('message from interscan e-mail viruswall nt'), + _c('end of message'), + _c('rcpt to:\s*<(?P[^>]*)>')), + # Smail + (_c('failed addresses follow:'), + _c('message text follows:'), + _c(r'\s*(?P\S+@\S+)')), + # newmail.ru + (_c('This is the machine generated message from mail service.'), + _c('--- Below the next line is a copy of the message.'), + _c('<(?P[^>]*)>')), + # turbosport.com runs something called `MDaemon 3.5.2' ??? + (_c('The following addresses did NOT receive a copy of your message:'), + _c('--- Session Transcript ---'), + _c('[>]\s*(?P.*)$')), + # usa.net + (_c('Intended recipient:\s*(?P.*)$'), + _c('--------RETURNED MAIL FOLLOWS--------'), + _c('Intended recipient:\s*(?P.*)$')), + # hotpop.com + (_c('Undeliverable Address:\s*(?P.*)$'), + _c('Original message attached'), + _c('Undeliverable Address:\s*(?P.*)$')), + # Another demon.co.uk format + (_c('This message was created automatically by mail delivery'), + _c('^---- START OF RETURNED MESSAGE ----'), + _c("addressed to '(?P[^']*)'")), + # Next one goes here... + ] + 'SimpleWarning', + patterns = [ + # pop3.pta.lia.net + (_c('The address to which the message has not yet been delivered is'), + _c('No action is required on your part'), + _c(r'\s*(?P\S+@\S+)\s*')), + # Next one goes here... + ] + 'Yale', + scre = re.compile(r'Message not delivered to the following', re.IGNORECASE) + ecre = re.compile(r'Error Detail', re.IGNORECASE) + acre = re.compile(r'\s+(?P\S+)\s+') + addrs.append(name + '@yale.edu') + addrs.append(name + '@cs.yale.edu') + 'LLNL', + acre = re.compile(r',\s*(?P\S+@[^,]+),', re.IGNORECASE) + + diff --git a/inc/app/sitemailer2/boxes/campaigns/delete/index.php b/inc/app/sitemailer2/boxes/campaigns/delete/index.php new file mode 100644 index 00000000..fe3bccd4 --- /dev/null +++ b/inc/app/sitemailer2/boxes/campaigns/delete/index.php @@ -0,0 +1,12 @@ +uncomment ' . $camp . '

'; + db_execute ('delete from sitemailer2_campaign where id = ?', $camp); + +} + +header ('Location: ' . site_prefix () . '/index/sitemailer2-campaigns-action'); +exit; +?> diff --git a/inc/app/sitemailer2/boxes/campaigns/index.php b/inc/app/sitemailer2/boxes/campaigns/index.php new file mode 100644 index 00000000..b1a6ccbb --- /dev/null +++ b/inc/app/sitemailer2/boxes/campaigns/index.php @@ -0,0 +1,60 @@ +id] = $camp; +} + +$camps = $temp; + +foreach ($tracker as $track) { + $camps[$track->campaign]->clicks++; +} + +if ($camps) { +foreach ($camps as $k=>$v) { + if (empty ($camps[$k]->clicks)) { + $camps[$k]->clicks = '0'; + } +}} + +page_title ('Campaigns'); + +echo template_simple ('campaign.spt', array ('list' => $camps)); + +/* +echo '
'; + +foreach ($camps as $camp) { + + echo '

' . $camp->title . '  

'; + echo '
    '; + echo '
  • ID: ' . $camp->id . '
  • '; + echo '
  • URL: ' . $camp->forward_url . '
  • '; + echo '
  • Views:
  • '; + echo '
      '; + + if (empty ($camp->messages)) { + + echo '
    • No confirmed views.
    • '; + + } else { + foreach ($camp->messages as $k=>$v) { + + echo '
    • Message ' . $k . ': ' . $v . '
    • '; + + } + } + + echo '
    '; + echo '
'; + +}*/ + + +?> diff --git a/inc/app/sitemailer2/boxes/campaigns/stats/index.php b/inc/app/sitemailer2/boxes/campaigns/stats/index.php new file mode 100644 index 00000000..2c457085 --- /dev/null +++ b/inc/app/sitemailer2/boxes/campaigns/stats/index.php @@ -0,0 +1,65 @@ +title); + +// Message, Newsletter, Date, Impressions, Impressions, Clicks, % + +$messages = array (); + +foreach ($stats as $stat) { + $messages[$stat->message]['clicks']++; +} + +$data = array ('forward_url' => $res->forward_url); + +foreach ($messages as $k=>$message) { + $res = db_single ('select * from sitemailer2_message where id = ?', $k); + + if ($res->subject) { + $messages[$k]['subject'] = $res->subject; + } else { + $messages[$k]['subject'] = 'Nonexistent Message'; + } + $messages[$k]['date'] = $res->date; + if ($res->confirmed_views) { + $messages[$k]['impressions'] = $res->confirmed_views; + } else { + $messages[$k]['impressions'] = '0'; + } + $messages[$k]['message_id'] = $k; + + //get newsletter + + $res1 = db_shift ('select t2.name from sitemailer2_message_newsletter as t1, sitemailer2_newsletter as t2 where t1.message = ? and t2.id = t1.newsletter limit 1', $k); + + if ($res1) { + $messages[$k]['newsletter'] = $res1; + } else { + $messages[$k]['newsletter'] = 'NA'; + } + + + if ($res->confirmed_views != 0) { + $messages[$k]['percent'] = round (($message['clicks'] / $res->confirmed_views) * 100, 1) . '%'; + } else { + $messages[$k]['percent'] = 'NA'; + } +} + +$data['list'] = $messages; + +echo template_simple ('campstats.spt', $data); + +//organize stats + +?> diff --git a/inc/app/sitemailer2/boxes/drafts/index.php b/inc/app/sitemailer2/boxes/drafts/index.php new file mode 100644 index 00000000..1aaacbe8 --- /dev/null +++ b/inc/app/sitemailer2/boxes/drafts/index.php @@ -0,0 +1,31 @@ +id) as $id) { + $n[] = db_shift ('select name from sitemailer2_newsletter where id = ?', $id); + } + $res[$k]->newsletter = join (', ', $n); +} + +$data['list'] =& $res; + +global $cgi; + +$msg_list = appconf ('msg'); + +if (isset ($msg_list[$cgi->_msg])) { + page_onload ('alert (\'' . $msg_list[$cgi->_msg] . '\')'); +} + +echo template_simple ('drafts.spt', $data); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/index/access.php b/inc/app/sitemailer2/boxes/index/access.php new file mode 100644 index 00000000..67d9a345 --- /dev/null +++ b/inc/app/sitemailer2/boxes/index/access.php @@ -0,0 +1,4 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on +sitellite_template_set = admin diff --git a/inc/app/sitemailer2/boxes/index/index.php b/inc/app/sitemailer2/boxes/index/index.php new file mode 100644 index 00000000..f8fc2e1b --- /dev/null +++ b/inc/app/sitemailer2/boxes/index/index.php @@ -0,0 +1,71 @@ +username)) { + echo '

Invalid password. Please try again.

'; + } else { + echo '

Please enter your username and password to enter.

'; + } + + echo template_simple ('
+ + + + + + + + + + + + + + +
Username
Password
 
+
' + ); + + return; +} + +page_title ('SiteMailer'); + +$data = array ( + 'groups' => array (), + 'total' => 0, +); + +$res = db_fetch ( + 'select * from sitemailer2_category order by name asc' +); +if (! $res) { + $res = array (); +} elseif (is_object ($res)) { + $res = array ($res); +} + +foreach ($res as $key => $row) { + $res[$key]->subscribers = db_shift ('select count(*) from sitemailer2_subscriber_category where category = ?', $row->id); + if (! $res[$key]->subscribers) { + $res[$key]->subscribers = '0'; + } +} + +$data['groups'] = $res; +if (! $data['total']) { + $data['total'] = '0'; +} + +$data['total'] = db_shift ('select count(*) from sitemailer2_subscriber'); +if (! $data['total']) { + $data['total'] = '0'; +} + +echo template_simple ('index.spt', $data); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/mailer/access.php b/inc/app/sitemailer2/boxes/mailer/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/mailer/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/mailer/index.php b/inc/app/sitemailer2/boxes/mailer/index.php new file mode 100644 index 00000000..cd98a819 --- /dev/null +++ b/inc/app/sitemailer2/boxes/mailer/index.php @@ -0,0 +1,264 @@ +IsSMTP (); + foreach (appconf ('mta_smtp') as $k => $v) { + $msg->{$k} = $v; + } + break; + case 'sendmail': + $msg->IsSendmail (); + foreach (appconf ('mta_sendmail') as $k => $v) { + $msg->{$k} = $v; + } + break; + case 'qmail': + $msg->IsQmail (); + foreach (appconf ('mta_qmail') as $k => $v) { + $msg->{$k} = $v; + } + break; + case 'mail': + default: + $msg->IsMail (); + foreach (appconf ('mta_mail') as $k => $v) { + $msg->{$k} = $v; + } +} + +//we need to check if messages are done, do this while sleeping or every 1000 message sends +$checkfordone = 0; +$lastmessage; + +//loop forever +while (1) { + + $checkdonecount++; + + if ($checkdonecount == 1000) { + checkfordone (); + } + + //get the next message + $res = db_single ('select * from sitemailer2_q where next_attempt <= now() order by next_attempt asc limit 1'); + + //info ($res, true);exit; + + + //if there's no msgs sleep + if (! $res) { + //might as well check for messages that need to be marked done + checkfordone (); + echo "Sleeping...\n"; + sleep (10); + continue; + } + +//compose the message + + if (! empty ($lastmessage)) { + if ($res->message == $lastmessage->id) { + $template = $lastmessage; + } else { + //grab the template + $template = db_single ('select * from sitemailer2_template t2, sitemailer2_message as + t1 where t1.id = ? and t1.template = t2.id', $res->message); + } + } else { + + //grab the template + $template = db_single ('select * from sitemailer2_template t2, sitemailer2_message as t1 + where t1.id = ? and t1.template = t2.id', $res->message); + + $lastmessage = $template; + } + + //grab the recipient info + $recipient = db_single ('select * from sitemailer2_recipient where id = ?', $res->recipient); + + //info ($template, true);exit; + + + //generate the message + + //we need the newsletter id + $newsletter = db_shift_array ('select newsletter from sitemailer2_message_newsletter where message = ?', $res->message); + + //this needs a better solution, maybe keep track of the newsletter in the queued items + $newsletter = $newsletter[0]; + + //info ($newsletter);exit; + + //prepare the data + $data = array ( + 'subject' => $template->subject, + 'email' => $recipient->email, + 'fullname' => $recipient->firstname . ' ' . $recipient->lastname, + 'firstname' => $recipient->firstname, + 'lastname' => $recipient->lastname, + 'organization' => $recipient->organization, + 'website' => $recipient->website, + 'date' => date ('F j, Y'), + 'unsubscribe' => '[[[unsub]]]', + 'tracker' => '[[[tracker]]]', + ); + + $unsub = 'Unsubscribe'; + + $tracker = ''; + + //make the html version of the message + + //add body to template + $data['body'] = template_simple ($template->mbody, $data); + $template->body = str_replace ('{body}', '{filter none}{body}{end filter}', $template->body); + + + //info ($template); + //info ($data, true);exit; + + //generate the final html + $html = template_simple ($template->body, $data); + + $html = str_replace ('[[[unsub]]]', $unsub, $html); + $html = str_replace ('[[[tracker]]]', $tracker, $html); + + //search for [[[campain_link=#]]] and replace it with a proper link + + $pos = 0; + $last_pos = 0; + + $offset = strlen ('[[[campaign_link='); + + while ($pos = strpos ($html, '[[[campaign_link=')) { + + //find the end + $end = strpos ($html, ']]]', $pos); + + $camp_id = substr ($html, $pos + $offset, $end - $pos - $offset); + + $html = str_replace ('[[[campaign_link=' . $camp_id . ']]]', 'http://' . $settings['mailer_domain'] . '/index/sitemailer2-public-link-action?c=' . $camp_id . '&m=' . $res->message . '&r=' . $res->recipient, $html); + } + + //info ($html);exit; + + $html = preg_replace ('/
([^\n])/i", "
\n\$1", $html); + + //create the text only version of the email + $text_body = preg_replace ( + array ("/^[\r\n]+/", "/[\r\n]+$/", "/[\r\n][\r\n]+/", ), + array ("", "", "\n\n", ), + strip_tags ( str_replace ( + array ('
', '
', ' ', '©', '<', '>', ), + array ('--', '--', ' ', '(c)', '<', '>', ), + $html ) + ) + ); + +//ready to send off the message + + //give $msg the content of the email + $msg->Body = $html; + $msg->AltBody = $text_body; + $msg->AddAddress ($recipient->email, $recipient->firstname . ' ' . $recipient->lastname); + $msg->From = $template->fromemail; + $msg->FromName = $template->fromname; + $msg->Subject = $template->subject; + + //info ($msg);exit; + + echo "Sending message " . $res->id . "\n"; + + if ($msg->Send()) { + //echo "Sent Message \n"; + db_execute ('delete from sitemailer2_q where id = ?', $res->id); + db_execute ('update sitemailer2_message set numsent = numsent + 1 where id = ?', $res->message); + } else { + + //check how many times message sending has been attempted + if (($res->attempts + 1) >= appconf ('max_attempts')) { + + if (empty ($msg->ErrorInfo)){ + $msg->ErrorInfo = "Unknown Error. Check server configuration."; + } + + db_execute ('delete from sitemailer2_q where id = ?', $res->id); + + if (! db_execute ('insert into sitemailer2_failed_q (id, recipient, message, attempts, created, + last_attempt, last_error) values (NULL, ?, ?, ?, ?, now(), ?)', $res->recipient, $res->message , $res->attempts + 1, $res->created, $msg->ErrorInfo)) { + echo "Failed to update failed q.\n"; + } + } else { + //update q'ed element, $res holds the info + + $next_attempt = date ('Y-m-d H:i:s', mktime (date('H'), date('i')+1, date('s'), date('m'), date('d'), date('Y'))); + + if (! db_execute ('update sitemailer2_q set attempts=?, next_attempt = ? where id = ?', ($res->attempts+1), $next_attempt, $res->id)) { + echo "Failed to increment attempts q.\n"; + } + + exit; + } + } + + //clean up + $msg->ClearAddresses(); + +} + +function checkfordone () { + + loader_import ('cms.Versioning.Rex'); + $rex = new Rex('sitemailer2_message'); + + $res1 = db_fetch_array ('select * from sitemailer2_message where status = "running"'); + foreach ($res1 as $r1) { + + $q = db_shift ('select count(id) from sitemailer2_q where message = ?', $r1->id); + $fq = db_shift ('select count(id) from sitemailer2_failed_q where message = ?', + $r1->id); + + if ($q == 0) { + + //calc num sent + if (! $fq) { + $numsent = $r1->numrec; + } else { + $numsent = $r1->numrec - $fq; + } + + $method = $rex->determineAction ($r1->id); + $rex->{$method} ($r1->id, array ('status' => 'done', + 'numsent' => $numsent)); + + db_execute ('delete from sitemailer2_q_failed where message = ?', $r1->id); + } + } + + $checkdonecount=0; +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/massunsub/index.php b/inc/app/sitemailer2/boxes/massunsub/index.php new file mode 100644 index 00000000..f8610047 --- /dev/null +++ b/inc/app/sitemailer2/boxes/massunsub/index.php @@ -0,0 +1,275 @@ +submit)) { + + $data = $cgi; + + unset ($data['files']); + unset ($data['param']); + unset ($data['error']); + unset ($data['submit']); + unset ($data['csvfile']); + unset ($data['page']); + unset ($data['mode']); + unset ($data['rc']); + + $struct = array (); + + foreach ($data as $k=>$d) { + //$k is of the form c# where # is the number of the column + $col = substr ($k, 1); + $struct[$d] = $col-1; + } + + //info ($struct);exit; + + //at the very least the email field must be set + if (! isset ($struct['email'])) { + header ('Location: ' . site_prefix () . '/index/sitemailer2-massunsub-action?error=noemail'); + exit; + } + + $file = site_docroot () . '/inc/app/sitemailer2/data/tmp/_' . session_username (); + + + //make sure the file still exists + if (! file_exists ($file)) { + echo '
No file to import.
'; + exit; + } + + //now parse the csv file based on the col order + $table = get_csv ($file, 0); + + foreach ($table as $row) { + + $zero = 0; + + //ready to insert new addresses now + //echo 'Adding email: ' . getEmailFromAddress ($row[$struct['email']]) . '
'; + $email = getEmailFromAddress ($row[$struct['email']]); + + //get all recipients with this email address + + $recipients = db_shift_array ('select id from sitemailer2_recipient where email = ?', $email); + + $recipients = implode ($recipients, ','); + + if (! db_execute ( + 'update sitemailer2_recipient_in_newsletter set status_change_time = now(), status = "unsubscribed" where + recipient in('. $recipients . ') and newsletter in(' . $cgi->rc . ')')) { + echo db_error(); + exit; + } + + + } + + page_title ('SiteMailer 2 - Importer'); + echo '

Finished unsubscribing.

'; + echo '

Return to subscriber list

'; + return; +} + +if (! file_exists (site_docroot () . '/inc/app/sitemailer2/data/tmp/_' . session_username ())) { + echo '
No file to import.
'; + exit; +} + +if (! empty ($cgi->error)) { + echo '
You must select one field as the email source.
'; +} + +$table = get_csv (site_docroot () . '/inc/app/sitemailer2/data/tmp/_' . session_username (), 3); + +//how many columns are there? +$cols = 0; + +if (! empty ($table)) { + foreach($table[0] as $col) { + $cols++; + } +} + +echo '

Please map the data to the correct fields below.

'; + +echo '
'; +$sels = '"; + +echo "\n"; +echo ''; + +loader_import ('saf.Misc.Alt'); + +$alt = new Alt ('#fff', '#eee'); + +for ($i = 0; $i < $cols; $i++) { + echo ''; +} +echo ''; + +foreach ($table as $row) { + $alt->reset (); + echo ""; + foreach ($row as $data) { + if (strlen ($data) > 20) { + $data = substr ($data, 0, 17) . '...'; + } + echo ''; + } + echo "\n"; +} +echo ''; +echo "
' . $sels . ($i + 1) . $sele . '
' . $data . '
...
\n"; +echo ''; +echo '

'; +echo '
'; + + +function get_csv($filename, $maxlines=0, $delim=',') + { + $row = 0; + $dump = array(); + $f = fopen ($filename,"r"); + $size = filesize($filename)+1; + while ($data = fgetcsv($f, $size, $delim)) { + $dump[$row] = $data; + $row++; + if ($maxlines != 0 && $row >= $maxlines) break; + } + fclose ($f); + + return $dump; +} + +function getFirstNameFromAddress ($x) { + + //possible formats + //1. Name + //2. email + //3. "Name@domain" + //4. + + //return empty string if no name + + $x = trim ($x); + + $s = strpos ($x, '<'); + $e = strpos ($x, '>'); + $q = strpos($x, "\""); + + $name = ''; + $fname = ''; //covers 2 and 4 + + if ($e) { //check for 1 or 3 + if ($q) { //3 + $q2 = strpos ($x, "\"", $q+1); + if ($q2) { + $name = substr ($x, $q, $q2-$q1); + } else { //erroneous address???, look for '<' + $name = trim (substr ($x, $q, $q-$s)); + } + } else { //1 + $name = trim (substr ($x, 0, $s)); + } + //break up name if theres a space in it; + $s = strpos ($name, ' '); + if($s) { + $fname = substr ($name, 0, $s); + } else { + $fname = $name; + } + } + + return $fname; +} + +function getLastNameFromAddress ($x) { + + //possible formats + //1. Name + //2. email + //3. "Name@domain" + //4. + + //return empty string if no name + + $x = trim ($x); + + $s = strpos ($x, '<'); + $e = strpos ($x, '>'); + $q = strpos($x, "\""); + + $name = ''; + $lname = ''; //covers 2 and 4 + + if ($e) { //check for 1 or 3 + if ($q) { //3 + $q2 = strpos ($x, "\"", $q+1); + if ($q2) { + $name = substr ($x, $q, $q2-$q1); + } else { //erroneous address???, look for '<' + $name = trim (substr ($x, $q, $q-$s)); + } + } else { //1 + $name = trim (substr ($x, 0, $s)); + } + //break up name if theres a space in it; + $s = strpos ($name, ' '); + if($s) { + $lname = substr ($name, $s, $e-$s); + } else { + $lname = ''; + } + } + + return trim ($lname); +} + +function getEmailFromAddress ($x) { + + //possible formats + //1. Name + //2. email + //3. "Name@domain" + //4. + + //return empty string if no name + + $x = trim ($x); + + $s = strpos ($x, '<'); + $e = strpos ($x, '>'); + + $addy = ''; + + if ($e) { //1, 3 and 4 + $addy = substr ($x, $s+1, $e-$s-1); + } else { //2 + $addy = $x; + } + + return strtolower (trim ($addy)); +} + +?> + diff --git a/inc/app/sitemailer2/boxes/message/index.php b/inc/app/sitemailer2/boxes/message/index.php new file mode 100644 index 00000000..cc8e3f0e --- /dev/null +++ b/inc/app/sitemailer2/boxes/message/index.php @@ -0,0 +1,42 @@ +id); + +$msg->template_body = db_shift ('select body from sitemailer2_template where id = ?', $msg->template); +if (! $msg->template_body) { + $msg->template_body = '{body}'; +} + +$data = array ( + 'body' => $msg->mbody, + 'date' => Date::format ($msg->date, 'F jS, Y'), + 'email' => 'joe@example.com', + 'firstname' => 'Joe', + 'fullname' => 'Joe Smith', + 'lastname' => 'Smith', + 'organization' => 'Example Inc.', + 'tracker' => '', + 'unsubscribe' => site_prefix () . '/index/sitemailer2-unsubscribe-action?email=joe@example.com', + 'website' => 'http://www.example.com/', +); + +$msg->template_body = str_replace ('{body}', '{filter none}{body}{end filter}', $msg->template_body); + +page_title ('SiteMailer 2 - View Message'); + +echo template_simple ( + 'view_message.spt', + array ( + 'body' => template_simple ($msg->template_body, $data), + 'subject' => $msg->subject, + 'fromname' => $msg->fromname, + 'fromemail' => $msg->fromemail, + 'date' => $data['date'], + ) +); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/newsletter/delete/index.php b/inc/app/sitemailer2/boxes/newsletter/delete/index.php new file mode 100644 index 00000000..eccda74a --- /dev/null +++ b/inc/app/sitemailer2/boxes/newsletter/delete/index.php @@ -0,0 +1,21 @@ +delete as $id) { + db_execute ('delete from sitemailer2_newsletter where id = ?', $id); + db_execute ('delete from sitemailer2_recipient_in_newsletter where newsletter = ?', $id); + db_execute ('delete from sitemailer2_message where newsletter = ?', $id); + db_execute ('delete from sitemailer2_message_sv where newsletter = ?', $id); +} + +if (count ($cgi->delete) > 1) { + $msg = 'deletes'; +} else { + $msg = 'deleted'; +} +header ('Location: ' . site_prefix () . '/index/sitemailer2-app?msg=' . $msg); + +exit; + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/newsletters/access.php b/inc/app/sitemailer2/boxes/newsletters/access.php new file mode 100644 index 00000000..67d9a345 --- /dev/null +++ b/inc/app/sitemailer2/boxes/newsletters/access.php @@ -0,0 +1,4 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on +sitellite_template_set = admin diff --git a/inc/app/sitemailer2/boxes/newsletters/index.php b/inc/app/sitemailer2/boxes/newsletters/index.php new file mode 100644 index 00000000..eba59aa5 --- /dev/null +++ b/inc/app/sitemailer2/boxes/newsletters/index.php @@ -0,0 +1,71 @@ +username)) { + echo '

Invalid password. Please try again.

'; + } else { + echo '

Please enter your username and password to enter.

'; + } + + echo template_simple ('
+ + + + + + + + + + + + + + +
Username
Password
 
+
' + ); + + return; +} + +loader_import ('sitemailer2.Filters'); + +page_title ('SiteMailer 2'); + +$data = array (); + +$res = db_fetch_array ( + 'select * from sitemailer2_newsletter order by name asc' +); + +foreach (array_keys ($res) as $key) { + $res[$key]->subscribers = db_shift ('select count(*) from sitemailer2_recipient_in_newsletter where newsletter = ?', $res[$key]->id); + $res[$key]->last_sent = db_shift ('select date from sitemailer2_message where newsletter = ? and status != "draft" order by date desc limit 1', $res[$key]->id); + if (! $res[$key]->subscribers) { + $res[$key]->subscribers = '0'; + } +} + +$data['list'] =& $res; + +$data['total'] = db_shift ('select count(*) from sitemailer2_recipient'); +if (! $data['total']) { + $data['total'] = '0'; +} + +global $cgi; + +$msg_list = appconf ('msg'); + +if (isset ($msg_list[$cgi->msg])) { + page_onload ('alert (\'' . $msg_list[$cgi->msg] . '\')'); +} + +echo template_simple ('newsletters.spt', $data); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/preview/index.php b/inc/app/sitemailer2/boxes/preview/index.php new file mode 100644 index 00000000..0778fb6d --- /dev/null +++ b/inc/app/sitemailer2/boxes/preview/index.php @@ -0,0 +1,32 @@ +message) || empty ($cgi->message)) { + header ('Location: ' . site_prefix() . '/index/sitemailer2-app'); + exit; +} + +$tpll = db_single ('select * from sitemailer2_template t2, sitemailer2_message as t1 + where t1.id = ? and t1.template = t2.id', $cgi->message); + +$data = array ('subject' => 'Quisque quis dui quis massa eleifend dignissim', + 'email' => 'email@domain.com', + 'recipient_name' => 'Jon Doe', + 'recipient_firstname' => 'Jon', + 'recipient_lastname' => 'Doe', + 'recipient_organization' => 'Doe Inc.', + 'recipient_website' => 'www.jondoe.com'); + +$subject = template_simple ($tpll->subject, $data); + +echo '

Subject: ' . $subject . '

' . "\n"; + +$data['body'] = template_simple ($tpll->mbody, $data); + +$tpll->body = str_replace ('{body}', '{filter none}{body}{end filter}', $tpll->body); + +echo template_simple ($tpll->body, $data); + +?> diff --git a/inc/app/sitemailer2/boxes/preview/template/index.php b/inc/app/sitemailer2/boxes/preview/template/index.php new file mode 100644 index 00000000..1a4a301a --- /dev/null +++ b/inc/app/sitemailer2/boxes/preview/template/index.php @@ -0,0 +1,25 @@ + '

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut enim. In dictum. Curabitur fermentum. Nullam neque diam, bibendum at, semper vel, euismod vitae, erat. Sed velit neque, iaculis id, tincidunt et, rhoncus at, sapien. Curabitur ultricies. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum dictum bibendum neque. Aliquam erat volutpat. Pellentesque accumsan suscipit lectus. Nullam mi ipsum, dictum eu, auctor ac, sagittis nec, wisi. Praesent pharetra tortor vel metus. Vivamus et sapien vitae turpis vestibulum luctus. Phasellus aliquet risus id felis. Praesent vel metus. Fusce faucibus nisl vitae ante euismod pharetra.

In hac habitasse platea dictumst. Suspendisse potenti. Duis viverra dui. Praesent scelerisque. Proin eget est sed urna tempor vehicula. Praesent eget magna at tellus bibendum consequat. Curabitur dignissim. Donec pulvinar interdum ante. Cras semper vehicula justo. Integer nec sem eu orci rutrum vehicula. Aliquam gravida. Sed aliquam arcu a nibh. Aenean eu mauris non nulla convallis ultrices.

', + 'date' => date ('F j, Y'), + 'email' => 'joe@example.com', + 'firstname' => 'Joe', + 'fullname' => 'Joe Smith', + 'lastname' => 'Smith', + 'organization' => 'Example Inc.', + 'tracker' => '', + 'unsubscribe' => site_prefix () . '/index/sitemailer2-unsubscribe-action?email=joe@example.com', + 'website' => 'http://www.example.com/', +); + +$parameters['body'] = str_replace ('{body}', '{filter none}{body}{end filter}', $parameters['body']); + +page_title ('SiteMailer 2 - Preview Template'); + +echo template_simple ( + 'preview_template.spt', + array ('body' => template_simple ($parameters['body'], $data)) +); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/public/access.php b/inc/app/sitemailer2/boxes/public/access.php new file mode 100644 index 00000000..71255c6a --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/access.php @@ -0,0 +1,4 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on +sitellite_inline = on diff --git a/inc/app/sitemailer2/boxes/public/archive/access.php b/inc/app/sitemailer2/boxes/public/archive/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/archive/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/public/archive/index.php b/inc/app/sitemailer2/boxes/public/archive/index.php new file mode 100644 index 00000000..09518b38 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/archive/index.php @@ -0,0 +1,32 @@ +date = Date::format ($items[$k]->date, 'M j, Y'); +} + +page_title ($name . ' - ' . intl_get ('Archive')); + +echo template_simple ( + 'public_archive.spt', + array ( + 'name' => $name, + 'items' => $items, + ) +); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/public/checkboxes/access.php b/inc/app/sitemailer2/boxes/public/checkboxes/access.php new file mode 100644 index 00000000..71255c6a --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/checkboxes/access.php @@ -0,0 +1,4 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on +sitellite_inline = on diff --git a/inc/app/sitemailer2/boxes/public/checkboxes/index.php b/inc/app/sitemailer2/boxes/public/checkboxes/index.php new file mode 100644 index 00000000..e8e29f77 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/checkboxes/index.php @@ -0,0 +1,74 @@ +Error, this should not be called.

'; + return; +} + +if ($box['context'] == 'action') { + page_title (intl_get ('Newsletters')); +} + +$u = session_user_get (session_username ()); +$u->recipient_id = db_shift ('select id from sitemailer2_recipient where email = ?', $u->email); +if (! $u->recipient_id) { + db_execute ( + 'insert into sitemailer2_recipient values (null, ?, ?, ?, ?, ?, now(), "active")', + $u->email, + $u->firstname, + $u->lastname, + $u->company, + $u->website + ); + $u->recipient_id = db_lastid (); +} + +if (isset ($parameters['submit_button']) && ! is_array ($parameters['newsletters'])) { + $parameters['newsletters'] = array (); +} + +$lists = db_fetch_array ('select id, name from sitemailer2_newsletter where public = "yes" order by name asc'); + +foreach ($lists as $k => $v) { + $lists[$k]->subscribed = db_shift ( + 'select count(*) from sitemailer2_recipient_in_newsletter where recipient = ? and newsletter = ?', + $u->recipient_id, + $v->id + ); + if (isset ($parameters['submit_button'])) { + if ($lists[$k]->subscribed && ! in_array ($v->id, $parameters['newsletters'])) { + db_execute ( + 'delete from sitemailer2_recipient_in_newsletter where recipient = ? and newsletter = ?', + $u->recipient_id, + $v->id + ); + $lists[$k]->subscribed = 0; + } elseif (! $lists[$k]->subscribed && in_array ($v->id, $parameters['newsletters'])) { + db_execute ( + 'insert into sitemailer2_recipient_in_newsletter values (?, ?, now(), "subscribed")', + $u->recipient_id, + $v->id + ); + $lists[$k]->subscribed = 1; + } + } +} + +//only require the email, which we should have now +echo template_simple ('public_checkboxes.spt', + array ( + 'lists' => $lists, + 'updated' => isset ($parameters['submit_button']), + ) +); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/public/checkboxes/settings.php b/inc/app/sitemailer2/boxes/public/checkboxes/settings.php new file mode 100644 index 00000000..388bd27a --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/checkboxes/settings.php @@ -0,0 +1,4 @@ +[Meta] + +name = Newsletter Checkboxes +description = Checkboxes for registered site members to manage their subscriptions with. diff --git a/inc/app/sitemailer2/boxes/public/index.php b/inc/app/sitemailer2/boxes/public/index.php new file mode 100644 index 00000000..23223c23 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/index.php @@ -0,0 +1,31 @@ +Error, this should not be called.

'; + return; + +} else if ($settings['subscriber_registration'] == 'email') { + //only require the email, which we should have now + echo template_simple ('publicemail.spt', $lists); + +} else if ($settings['subscriber_registration'] == 'full') { + //only require the email, but allow user to enter all info + echo template_simple ('publicfull.spt', $lists); + +} else if ($settings['subscriber_registration'] == 'req') { + //require all settings + echo template_simple ('publicreq.spt', $lists); + +} + + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/public/link/access.php b/inc/app/sitemailer2/boxes/public/link/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/link/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/public/link/index.php b/inc/app/sitemailer2/boxes/public/link/index.php new file mode 100644 index 00000000..7da4b769 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/link/index.php @@ -0,0 +1,35 @@ +m) && ! isset ($cgi->m)) { $fail = true; } +if (empty ($cgi->r) && ! isset ($cgi->r)) { $fail = true; } +if (empty ($cgi->c) && ! isset ($cgi->c)) { $fail = true; } + +if (! $fail) { + + //has this m/r/c combinations been counted? + $counted = db_shift ('select count(id) from sitemailer2_link_tracker where campaign = ? and message = ? and recipient = ?', $cgi->c, $cgi->m, $cgi->r); + + if ($counted == "0") { + + if (! db_execute ('insert into sitemailer2_link_tracker (id, campaign, message, created, recipient) values (NULL, ?, ?, now(), ?)', $cgi->c, $cgi->m, $cgi->r)) { + echo 'Failed to update tracker.'; + return; + } + } +} + +$camp = db_single ('select * from sitemailer2_campaign where id = ?', $cgi->c); + +if (is_int (strpos (strtolower ($camp->forward_url), 'http://'))) { +} else { + $camp->forward_url = 'http://' . $camp->forward_url; +} + +header ('Location: ' . $camp->forward_url); +exit; + +?> diff --git a/inc/app/sitemailer2/boxes/public/message/access.php b/inc/app/sitemailer2/boxes/public/message/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/message/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/public/message/index.php b/inc/app/sitemailer2/boxes/public/message/index.php new file mode 100644 index 00000000..bfa2373a --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/message/index.php @@ -0,0 +1,31 @@ + $msg->mbody, + 'date' => Date::format ($msg->date, 'F jS, Y'), + 'email' => '', + 'firstname' => '', + 'fullname' => '', + 'lastname' => '', + 'organization' => '', + 'tracker' => '', + 'unsubscribe' => '', + 'website' => '', +); + +$t = db_single ('select * from sitemailer2_template where id = ?', $msg->template); + +$t->body = str_replace ('{body}', '{filter none}{body}{end filter}', $t->body); + +echo template_simple ($t->body, $data); + +exit; + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/public/rss/access.php b/inc/app/sitemailer2/boxes/public/rss/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/rss/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/public/rss/index.php b/inc/app/sitemailer2/boxes/public/rss/index.php new file mode 100644 index 00000000..2f05f0b3 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/rss/index.php @@ -0,0 +1,45 @@ +click) { + //track subscription + db_execute ('update sitemailer2_newsletter set rss_subs=rss_subs+1 where id = ?', $parameters['list']); +} + +$name = db_shift ( + 'select name from sitemailer2_newsletter where id = ? and public = "yes"', + $parameters['list'] +); +if (! $name) { + die ('Unknown list'); +} + +$items = db_fetch_array ( + 'select id, title, date from sitemailer2_message where newsletter = ? and status != "draft" order by date desc limit 10', + $parameters['list'] +); + +loader_import ('sitemailer2.Functions'); +loader_import ('saf.Date'); + +$z = sitemailer2_rss_timezone (date ('Z')); + +foreach (array_keys ($items) as $k) { + $items[$k]->date = Date::format ($items[$k]->date, 'Y-m-d\TH:i:s') . $z; +} + +header ('Content-Type: text/xml'); + +echo template_simple ( + 'public_rss.spt', + array ( + 'name' => $name, + 'items' => $items, + 'date' => date ('Y-m-d\TH:i:s') . $z, + ) +); + +exit; + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/public/settings.php b/inc/app/sitemailer2/boxes/public/settings.php new file mode 100644 index 00000000..2281dc79 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/settings.php @@ -0,0 +1,4 @@ +[Meta] + +name = All Newsletters +description = A public list of newsletters visitors can subscribe to and view the archives of. diff --git a/inc/app/sitemailer2/boxes/public/subscribe/access.php b/inc/app/sitemailer2/boxes/public/subscribe/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/subscribe/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/public/subscribe/delete/index.php b/inc/app/sitemailer2/boxes/public/subscribe/delete/index.php new file mode 100755 index 00000000..401c29f1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/subscribe/delete/index.php @@ -0,0 +1,19 @@ +_key as $id) { + db_execute ('delete from sitemailer2_recipient where id = ?', $id); + db_execute ('delete from sitemailer2_recipient_in_newsletter where recipient = ?', $id); +} + +if (count ($cgi->_key) > 1) { + $msg = 'subsdel'; +} else { + $msg = 'subdel'; +} +header ('Location: ' . site_prefix () . '/index/sitemailer2-subscribers-action?_msg=' . $msg); + +exit; + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/public/subscribe/index.php b/inc/app/sitemailer2/boxes/public/subscribe/index.php new file mode 100755 index 00000000..e83275af --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/subscribe/index.php @@ -0,0 +1,118 @@ +email)) { + echo '

Invalid request: no email address found.

'; + return; +} + + +if (empty ($cgi->newsletter)) { + if (empty ($cgi->list)) { + echo '

Invalid request: no newsletter found.

'; + return; + } else { + $cgi->newsletter = $cgi->list; + } +} + +//set some default values if needed +if (empty ($cgi->fname)) { $cgi->fname = ""; }; +if (empty ($cgi->lname)) { $cgi->lname = ""; }; +if (empty ($cgi->organization)) { $cgi->organization = ""; }; +if (empty ($cgi->website)) { $cgi->website = ""; }; + +$settings = @parse_ini_file ('inc/app/sitemailer2/conf/settings2.ini.php'); + +//see if recipient already exists +//recipient exists, simply subscribe +if ($recipient = db_shift_array ('select id from sitemailer2_recipient where email = ?', + $cgi->email)) { + $recipient = $recipient[0]; + +//recipient doesnt exist, create recipient and subscribe +} else { + + if (! db_execute ('insert into sitemailer2_recipient (id, email, firstname, lastname, + organization, website, created, status) values (NULL, ?, ?, ?, ?, ?, + now(), "unverified")', + $cgi->email, $cgi->fname, $cgi->lname, $cgi->organization, $cgi->website)) { + echo '

Error adding recipient.

'; + info ($cgi); + } + + $recipient = db_lastid (); +} + +//if we don't have a recipient yet, quit! +if (empty ($recipient)) { + echo '

Unable to add recipient and recipient doesn\'t exists

'; +} + +//make sure the recipient is not already subscribed +if (db_shift ('select count(recipient) from sitemailer2_recipient_in_newsletter where recipient = ? and newsletter = ? and status = "subscribed"', $recipient, $cgi->list)) { + echo '

Your email address is already subscribed to this list.

'; + return; +} + +//check if we only need to change the recipients status +if (db_shift ('select count(recipient) from sitemailer2_recipient_in_newsletter where recipient = ? and newsletter = ? and status = "unsubscribed"', $recipient, $cgi->list)) { + +} else { + + //add recipient to newsletter + if (! db_execute ('insert into sitemailer2_recipient_in_newsletter (recipient, newsletter, status_change_time, status) values (?, ?, now(), "unsubscribed")', $recipient, $cgi->newsletter)) { + echo '

Error adding recipient to newsletter

'; + } +} + +if ($settings['subscriber_email_verification'] == 1) { + + echo '

Your subscription will not be complete until you receive a confirmation email.

'; + + $data['firstname'] = $cgi->fname; + $data['lastname'] = $cgi->lname; + $data['email'] = $cgi->email; + $data['organization'] = $cgi->organization; + $data['website'] = $cgi->website; + $created = db_shift ('select created from sitemailer2_recipient where id = ?', $recipient); + $data['key'] = md5($recipient . $cgi->email . $created); + $data['nl'] = $cgi->newsletter; + + //send out the request + //import the mailer package + loader_import ('ext.phpmailer'); + //initialize the mailer package + $msg = new PHPMailer(); + $msg->Body = template_simple ('responses/email_confirmation.spt', $data); + $msg->AltBody = template_simple ('responses/email_confirmation.spt', $data); + $msg->AddAddress ($cgi->email, $cgi->fname . ' ' . $cgi->lname); + $msg->From = $settings['confirmation_email_domain']; + $msg->FromName = $settings['confirmation_from']; + $msg->Subject = $settings['confirmation_subject']; + + echo "

Sending message...

"; + + if (! $msg->Send()) { + echo '

Failed to send verification email. Are you sure the email address "' . $cgi->email . '" is valid? Click back to try again.

'; + } else { + echo "

Message Sent Successfully!

"; + } + +} else { + + $created = db_shift ('select created from sitemailer2_recipient where id = ?', $recipient); + //just subscribe + + header('Location: ' . site_prefix() . '/index/sitemailer2-public-subscribe-verify-action?email=' . $cgi->email . '&nl=' . $cgi->newsletter . '&key=' . md5($recipient . $cgi->email . $created)); + exit; + +} + + + +?> diff --git a/inc/app/sitemailer2/boxes/public/subscribe/verify/index.php b/inc/app/sitemailer2/boxes/public/subscribe/verify/index.php new file mode 100755 index 00000000..88c74998 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/subscribe/verify/index.php @@ -0,0 +1,59 @@ +email)) { + show_error ('no email address specified, cannot continue'); + return; +} + +if (empty ($cgi->nl)) { + show_error ('no newsletter specified, cannot continue'); + return; +} + +if (empty ($cgi->key)) { + show_error ('no key specified, cannot continue'); + return; +} + +//make sure the recipient exists +if ($recipient = db_shift_array ('select id from sitemailer2_recipient where email = ?', + $cgi->email)) { + $recipient = $recipient[0]; +} else { + show_error ('the email address to be confirmed has not requested to be subscribed'); + return; +} + +//verify key + +$created = db_shift ('select created from sitemailer2_recipient where id = ?', $recipient); + +if ($cgi->key === md5($recipient . $cgi->email . $created)) { + + //activate recipient and recipient in newsletter + if (! db_execute ('update sitemailer2_recipient set status="active" where id = ?', $recipient)) { + show_error ('failed to activate email address'); + return; + } + + if (! db_execute ('update sitemailer2_recipient_in_newsletter set status="subscribed" where recipient = ? and newsletter = ?', $recipient, $cgi->nl)) { + show_error ('failed to subscribe email address'); + return; + } + + echo '

You are now successfully subscribed!

'; + +} else { + show_error ('the key is incorrect'); + return; +} + +function show_error ($str) { + $str = trim ($str); + echo '

Subscription failed: ' . $str . '. +

Visit here to try again.

'; +} + +?> diff --git a/inc/app/sitemailer2/boxes/public/subscriber/access.php b/inc/app/sitemailer2/boxes/public/subscriber/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/subscriber/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/public/tracker/access.php b/inc/app/sitemailer2/boxes/public/tracker/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/tracker/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/public/tracker/index.php b/inc/app/sitemailer2/boxes/public/tracker/index.php new file mode 100644 index 00000000..ac3fef0e Binary files /dev/null and b/inc/app/sitemailer2/boxes/public/tracker/index.php differ diff --git a/inc/app/sitemailer2/boxes/public/unsubscribe/access.php b/inc/app/sitemailer2/boxes/public/unsubscribe/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/unsubscribe/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/public/unsubscribe/index.php b/inc/app/sitemailer2/boxes/public/unsubscribe/index.php new file mode 100755 index 00000000..0f16852c --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/unsubscribe/index.php @@ -0,0 +1,83 @@ +email)) { + echo '

Invalid request: no email address found.

'; + return; +} + +if (empty ($cgi->list)) { + echo '

Invalid request: no newsletter found.

'; + return; +} + +$cgi->newsletter = $cgi->list; + +$settings = @parse_ini_file ('inc/app/sitemailer2/conf/settings2.ini.php'); + +//see if recipient already exists +if ($recipient = db_shift_array ('select id from sitemailer2_recipient where email = ?', + $cgi->email)) { + $recipient = $recipient[0]; + +//recipient doesnt exist, create recipient and subscribe +} else { + echo '

That email address is not in our database, click back to try again

'; + return; +} + +//if we don't have a recipient yet, quit! +if (empty ($recipient)) { + echo '

Unable to unsubscribe, email address doesn\'t exists

'; + return; +} + +$full_recipient = db_single ('select * from sitemailer2_recipient where id = ?', $recipient); + +if ($settings['unsubscribe_email_verification'] == 1) { + + echo '

Your subscription cancellation will not be complete until you receive a confirmation email.

'; + + $data['firstname'] = $full_recipient->fname; + $data['lastname'] = $full_recipient->lname; + $data['email'] = $cgi->email; + $data['organization'] = $full_recipient->organization; + $data['website'] = $full_recipient->website; + $created = db_shift ('select created from sitemailer2_recipient where id = ?', $recipient); + $data['key'] = md5($recipient . $cgi->email . $created); + $data['nl'] = $cgi->newsletter; + + //send out the request + //import the mailer package + loader_import ('ext.phpmailer'); + //initialize the mailer package + $msg = new PHPMailer(); + $msg->Body = template_simple ('responses/email_unsub_confirmation.spt', $data); + $msg->AltBody = template_simple ('responses/email_unsub_confirmation.spt', $data); + $msg->AddAddress ($cgi->email, $cgi->fname . ' ' . $cgi->lname); + $msg->From = $settings['confirmation_email_domain']; + $msg->FromName = $settings['confirmation_from']; + $msg->Subject = 'Subscription Cancellation'; + + echo "

Sending message...

"; + + if (! $msg->Send()) { + echo '

Failed to send cancellation email. Are you sure the email address "' . $cgi->email . '" is valid? Click back to try again.

'; + } else { + echo "

Message Sent Successfully!

"; + } +} else { + + //just unsubscribe + $created = db_shift ('select created from sitemailer2_recipient where id = ?', $recipient); + + header('Location: ' . site_prefix() . '/index/sitemailer2-public-unsubscribe-verify-action?email=' . $cgi->email . '&nl=' . $cgi->newsletter . '&key=' . md5($recipient . $cgi->email . $created)); + exit; + +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/public/unsubscribe/verify/index.php b/inc/app/sitemailer2/boxes/public/unsubscribe/verify/index.php new file mode 100755 index 00000000..8a88582c --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/unsubscribe/verify/index.php @@ -0,0 +1,53 @@ +email)) { + show_error ('no email address specified, cannot continue'); + return; +} + +if (empty ($cgi->nl)) { + show_error ('no newsletter specified, cannot continue'); + return; +} + +if (empty ($cgi->key)) { + show_error ('no key specified, cannot continue'); + return; +} + +//make sure the recipient exists +if ($recipient = db_shift_array ('select id from sitemailer2_recipient where email = ?', + $cgi->email)) { + $recipient = $recipient[0]; +} else { + show_error ('the email address to be unsubscribed doesn\'t exist'); + return; +} + +//verify key + +$created = db_shift ('select created from sitemailer2_recipient where id = ?', $recipient); + +if ($cgi->key === md5($recipient . $cgi->email . $created)) { + + if (! db_execute ('update sitemailer2_recipient_in_newsletter set status="unsubscribed" where recipient = ? and newsletter = ?', $recipient, $cgi->nl)) { + show_error ('failed to unsubscribe email address'); + return; + } + db_execute ('delete from sitemailer2_recipient_in_newsletter where recipient = ? and newsletter = ?', $recipient, $cgi->nl); + echo '

You are now successfully unsubscribed!

'; + +} else { + show_error ('the key is incorrect'); + return; +} + +function show_error ($str) { + $str = trim ($str); + echo '

Subscription failed: ' . $str . '. +

Visit here to try again.

'; +} + +?> diff --git a/inc/app/sitemailer2/boxes/public/verify/access.php b/inc/app/sitemailer2/boxes/public/verify/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/public/verify/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/recurring/access.php b/inc/app/sitemailer2/boxes/recurring/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/recurring/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/recurring/index.php b/inc/app/sitemailer2/boxes/recurring/index.php new file mode 100755 index 00000000..0d7887af --- /dev/null +++ b/inc/app/sitemailer2/boxes/recurring/index.php @@ -0,0 +1,86 @@ +next_recurrence); + $added++; + } + + list ($date, $time) = explode (' ', $message->next_recurrence); + + list ($year, $month, $day) = explode ('-', $date); + + list ($hour, $minute, $second) = explode (':', $time); + + // 1. daily + // 2. weekly + // 3. twice-monthly + // 4. monthly + + //set next send time + if ($message->recurring == 'daily') { + $day += 1; + } else if ($message->recurring == 'weekly') { + $day += 7; + } else if ($message->recurring == 'twice-monthly') { + $day += 15; + } else if ($message->recurring == 'monthly') { + $month += 1; + } else { + echo 'form error! invalid recurrence type:' . $message->recurring;exit; + } + + $next_recurrence = date ('Y-m-d H:i:s', mktime ($hour, $minute, $second, $month, $day, $year)); + + + if (! db_execute ('update sitemailer2_message set next_recurrence=?, numrec=? where id=?', $next_recurrence, $message->numrec + $added, $mid)) { + echo 'update of next_recurrence failed'; + } + } +} + +?> diff --git a/inc/app/sitemailer2/boxes/stats/index.php b/inc/app/sitemailer2/boxes/stats/index.php new file mode 100644 index 00000000..c2b0bd45 --- /dev/null +++ b/inc/app/sitemailer2/boxes/stats/index.php @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/subscriber/delete/index.php b/inc/app/sitemailer2/boxes/subscriber/delete/index.php new file mode 100644 index 00000000..401c29f1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/subscriber/delete/index.php @@ -0,0 +1,19 @@ +_key as $id) { + db_execute ('delete from sitemailer2_recipient where id = ?', $id); + db_execute ('delete from sitemailer2_recipient_in_newsletter where recipient = ?', $id); +} + +if (count ($cgi->_key) > 1) { + $msg = 'subsdel'; +} else { + $msg = 'subdel'; +} +header ('Location: ' . site_prefix () . '/index/sitemailer2-subscribers-action?_msg=' . $msg); + +exit; + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/subscribers/index.php b/inc/app/sitemailer2/boxes/subscribers/index.php new file mode 100644 index 00000000..8e204f2e --- /dev/null +++ b/inc/app/sitemailer2/boxes/subscribers/index.php @@ -0,0 +1,190 @@ +offset)) { + $cgi->offset = 0; +} + +$cgi->collection = 'sitemailer2_recipient'; + +$data = array ('collection' => $cgi->collection); + +$rex = new Rex ($cgi->collection); + +if (! $rex->collection) { + header ('Location: ' . site_prefix () . '/index/cms-cpanel-action'); + exit; +} + +if (session_is_resource ($cgi->collection) && ! session_allowed ($cgi->collection, 'r', 'resource')) { + header ('Location: ' . site_prefix () . '/index/cms-cpanel-action'); + exit; +} + +if (! isset ($cgi->orderBy)) { + if (isset ($rex->info['Collection']['order_by'])) { + $cgi->orderBy = $rex->info['Collection']['order_by']; + } else { + $cgi->orderBy = $rex->info['Collection']['title_field']; + } +} + +if (! isset ($cgi->sort)) { + if (isset ($rex->info['Collection']['sorting_order'])) { + $cgi->sort = $rex->info['Collection']['sorting_order']; + } else { + $cgi->sort = 'asc'; + } +} + +$pg = new Pager ($cgi->offset, $limit); +$pg->url = site_current () . '?collection=' . urlencode ($cgi->collection) . '&orderBy=' . urlencode ($cgi->orderBy) . '&sort=' . urlencode ($cgi->sort); +$data['facet_url'] = ''; +foreach ($cgi->param as $p) { + if (strpos ($p, '_') === 0 && $p != '_msg') { + $data['facet_url'] .= '&' . $p . '=' . urlencode ($cgi->{$p}); + } +} +$pg->url .= $data['facet_url']; +$data['return'] = $pg->url; + +// build column headers + +$struct = array_keys ($rex->getStruct ()); + +$acl = array (); +if (! $struct) { + $struct = array (); +} else { + $acl_list = session_allowed_access_list (); + if (! in_array ('all', $acl_list)) { + foreach ($struct as $k) { + if ($k == 'sitellite_access') { + $acl = array ( + 'sitellite_access' => new rList ( + 'sitellite_access', + session_allowed_access_list () + ) + ); + break; + } + } + } + $team_list = session_allowed_teams_list (); + if (! in_array ('all', $team_list)) { + $team_list[] = ''; + foreach ($struct as $k) { + if ($k == 'sitellite_team') { + $acl['sitellite_team'] = new rList ( + 'sitellite_team', + $team_list + ); + break; + } + } + } +} + +foreach ($rex->info as $key => $vals) { + if (strpos ($key, 'browse:') === 0) { + $key = substr ($key, 7); + $data['headers'][] = new TableHeader ($key, $vals['header']); + $data['fields'][$key] = $vals; + if (isset ($vals['filter_import'])) { + loader_import ($vals['filter_import']); + } + } +} + +if ($rex->isVersioned) { + $res = $rex->getStoreList ($acl, $limit, $cgi->offset, $cgi->orderBy, $cgi->sort); +} else { + $res = $rex->getList ($acl, $limit, $cgi->offset, $cgi->orderBy, $cgi->sort); +} + +if (! $res) { + $res = array (); + $rex->total = 0; +} +$pg->total = $rex->total; + +$rex->ignore (array ('_msg')); + +if (count ($rex->facets) > 0) { + $data['facets'] = $rex->renderFacets (); +} else { + $data['facets'] = ''; +} +$data['is_versioned'] = $rex->isVersioned; + +$res2 = array (); +$locks = array (); +$editable = array (); +$align = array (); +$width = array (); + +foreach ($res as $key => $row) { + $row = $rex->getCurrent ($row->{$rex->key}); + if (empty ($row->{$rex->info['Collection']['title_field']})) { + $row->{$rex->info['Collection']['title_field']} = $row->{$rex->key}; + } + $tmp = new StdClass; + foreach ($data['headers'] as $field) { + $tmp->{$field->name} = $row->{$field->name}; + if ($data['fields'][$field->name]['filter']) { + $filter = $data['fields'][$field->name]['filter']; + $tmp->{$field->name} = $filter ($tmp->{$field->name}); + } elseif ($data['fields'][$field->name]['virtual']) { + $virtual = $data['fields'][$field->name]['virtual']; + $tmp->{$field->name} = $virtual ($row); + } else { + $tmp->{$field->name} = htmlentities_compat ($tmp->{$field->name}); + } + $align[$field->name] = ($data['fields'][$field->name]['align']) ? $data['fields'][$field->name]['align'] : 'left'; + $width[$field->name] = ($data['fields'][$field->name]['width']) ? $data['fields'][$field->name]['width'] : 'auto'; + if (isset ($rex->info['browse:' . $field->name]['length']) && strlen ($tmp->{$field->name}) > $rex->info['browse:' . $field->name]['length']) { + $tmp->{$field->name} = rtrim (substr ($tmp->{$field->name}, 0, $rex->info['browse:' . $field->name]['length'] - 3)) . '...'; + } + } + + $res2[$row->{$rex->key}] = $tmp; + //$locks[$row->{$rex->key}] = lock_exists ($cgi->collection, $row->{$rex->key}); + if (isset ($row->sitellite_access) && ! session_allowed ($row->sitellite_access, 'w', 'access')) { + $editable[$row->{$rex->key}] = false; + } else { + $editable[$row->{$rex->key}] = true; + } +} + +$pg->setData ($res2); +$pg->update (); + +//page_title (intl_get ('Browsing') . ': ' . $rex->info['Collection']['display']); +$data['collection_name'] = $rex->info['Collection']['display']; +$data['title_field'] = $rex->info['Collection']['title_field']; +$data['key_field'] = $rex->info['Collection']['key_field']; + +$msg_list = appconf ('msg'); + +if (isset ($msg_list[$cgi->_msg])) { + page_onload ('alert (\'' . $msg_list[$cgi->_msg] . '\')'); +} + +page_title ('SiteMailer 2'); + +template_simple_register ('pager', $pg); +template_simple_register ('editable', $editable); +template_simple_register ('align', $align); +template_simple_register ('width', $width); + +echo template_simple ('subscribers.spt', $data); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/template/delete/index.php b/inc/app/sitemailer2/boxes/template/delete/index.php new file mode 100644 index 00000000..c356a9c8 --- /dev/null +++ b/inc/app/sitemailer2/boxes/template/delete/index.php @@ -0,0 +1,18 @@ +delete as $id) { + db_execute ('delete from sitemailer2_template where id = ?', $id); +} + +if (count ($cgi->delete) > 1) { + $msg = 'tpldeletes'; +} else { + $msg = 'tpldeleted'; +} +header ('Location: ' . site_prefix () . '/index/sitemailer2-templates-action?msg=' . $msg); + +exit; + +?> diff --git a/inc/app/sitemailer2/boxes/templates/index.php b/inc/app/sitemailer2/boxes/templates/index.php new file mode 100644 index 00000000..26b335c3 --- /dev/null +++ b/inc/app/sitemailer2/boxes/templates/index.php @@ -0,0 +1,33 @@ +subscribers = db_shift ('select count(*) from sitemailer2_subscriber_category where category = ?', $res[$key]->id); + $res[$key]->last_sent = db_shift ('select date from sitemailer2_message where newsletter = ? order by date desc limit 1', $res[$key]->id); + if (! $res[$key]->subscribers) { + $res[$key]->subscribers = '0'; + } +} + +$data['list'] =& $res; + +global $cgi; + +$msg_list = appconf ('msg'); + +if (isset ($msg_list[$cgi->msg])) { + page_onload ('alert (\'' . $msg_list[$cgi->msg] . '\')'); +} + +echo template_simple ('templates.spt', $data); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/testemail/index.php b/inc/app/sitemailer2/boxes/testemail/index.php new file mode 100644 index 00000000..d8ce5f5a --- /dev/null +++ b/inc/app/sitemailer2/boxes/testemail/index.php @@ -0,0 +1,137 @@ +IsSMTP (); + foreach (appconf ('mta_smtp') as $k => $v) { + $msg->{$k} = $v; + } + break; + case 'sendmail': + $msg->IsSendmail (); + foreach (appconf ('mta_sendmail') as $k => $v) { + $msg->{$k} = $v; + } + break; + case 'qmail': + $msg->IsQmail (); + foreach (appconf ('mta_qmail') as $k => $v) { + $msg->{$k} = $v; + } + break; + case 'mail': + default: + $msg->IsMail (); + foreach (appconf ('mta_mail') as $k => $v) { + $msg->{$k} = $v; + } +} + +//compose the message +if (empty ($parameters['template'])) { + $template = '{body}'; +} else { + $template = db_shift ('select body from sitemailer2_template where id = ?', $parameters['template']); +} + +//generate the message + +//we need the newsletter id +$newsletter = $parameters ['newsletter']; + +//this needs a better solution, maybe keep track of the newsletter in the queued items +$newsletter = $newsletter[0]; + +//prepare the data +$data = array ('subject' => $parameters['subject'], 'email' => $parameters['test_email'], + 'fullname' => 'Test_Full_Name', + 'firstname' => 'Test_First_Name', + 'lastname' => 'Test_Last_Name', + 'organization' => 'Test_Organization', + 'website' => 'Test_URL', + 'date' => date('Y-m-d'), + 'unsubscribe' => '[[[unsub]]]', + 'tracker' => '[[[tracker]]]'); + + +$unsub = 'Unsubscribe'; + +$tracker = ''; + +//make the html version of the message + + +//add body to template +$data['body'] = template_simple ($parameters['body'], $data); + +$template = str_replace ('{body}', '{filter none}{body}{end filter}', $template); + +//generate the final html +$html = template_simple ($template, $data); + +$html = str_replace ('[[[unsub]]]', $unsub, $html); +$html = str_replace ('[[[tracker]]]', $tracker, $html); + +$pos = 0; +$last_pos = 0; + +$offset = strlen ('[[[campaign_link='); + +while ($pos = strpos ($html, '[[[campaign_link=')) { + + //find the end + $end = strpos ($html, ']]]', $pos); + + $camp_id = substr ($html, $pos + $offset, $end - $pos - $offset); + + $html = str_replace ('[[[campaign_link=' . $camp_id . ']]]', 'http://' . $settings['mailer_domain'] . '/index/sitemailer2-public-link-action?c=' . $camp_id . '&m=' . $res->message, $html); +} + +//create the text only version of the email +$html_body = preg_replace ('/
([^\n])/i", "
\n\$1", $html); + +$text_body = preg_replace ( + array ("/^[\r\n]+/", "/[\r\n]+$/", "/[\r\n][\r\n]+/", ), + array ("", "", "\n\n", ), + strip_tags ( str_replace ( + array ('
', '
', ' ', '©', '<', '>', ), + array ('--', '--', ' ', '(c)', '<', '>', ), + $html_body ) + ) + ); + +//ready to send off the message + +//give $msg the content of the email +$msg->Body = $html_body; +$msg->AltBody = $text_body; +$msg->AddAddress ($parameters['test_email'], 'Test_First_Name Test_Last_Name'); +$msg->From = $parameters['from_email']; +$msg->FromName = $parameters['from_name']; +$msg->Subject = $parameters['subject']; + +if ($msg->Send()) { + echo "

Message Sent Successfully

"; +} else { + echo "

Message Failed to Send

"; +} + +//clean up +$msg->ClearAddresses(); + +echo ('Close Window'); + +?> diff --git a/inc/app/sitemailer2/boxes/unsubscribe/access.php b/inc/app/sitemailer2/boxes/unsubscribe/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/boxes/unsubscribe/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/boxes/unsubscribe/index.php b/inc/app/sitemailer2/boxes/unsubscribe/index.php new file mode 100644 index 00000000..20dd9940 --- /dev/null +++ b/inc/app/sitemailer2/boxes/unsubscribe/index.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/unsubscribe/verify/index.php b/inc/app/sitemailer2/boxes/unsubscribe/verify/index.php new file mode 100644 index 00000000..cec34091 --- /dev/null +++ b/inc/app/sitemailer2/boxes/unsubscribe/verify/index.php @@ -0,0 +1,34 @@ +\n" + . "\n404 Not Found\n\n

Not Found

\n" + . "The requested URL " . $_SERVER['PHP_SELF'] . " was not found on this server.

\n


\n" + . $_SERVER['SERVER_SIGNATURE'] . ""; + exit; +} + +if (empty ($email)) { + fail (); +} + +$res = db_single ('select * from sitemailer2_subscriber where email = ?', $email); +if (! $res) { + fail (); +} + +if (md5 ($res->email . $res->registered) != $key) { + fail (); +} + +// valid + +db_execute ('update sitemailer2_subscriber set status = ? where email = ?', 'unsubscribed', $email); +page_title (intl_get ('Thank You!')); +echo template_simple ('responses/verified_unsubscribed.spt', $parameters); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/boxes/verifycsv/index.php b/inc/app/sitemailer2/boxes/verifycsv/index.php new file mode 100644 index 00000000..17d72adc --- /dev/null +++ b/inc/app/sitemailer2/boxes/verifycsv/index.php @@ -0,0 +1,373 @@ +submit)) { + + $data = $cgi; + + unset ($data['files']); + unset ($data['param']); + unset ($data['error']); + unset ($data['submit']); + unset ($data['csvfile']); + unset ($data['page']); + unset ($data['mode']); + unset ($data['rc']); + + $struct = array (); + + foreach ($data as $k=>$d) { + //$k is of the form c# where # is the number of the column + $col = substr ($k, 1); + $struct[$d] = $col-1; + } + + //info ($struct);exit; + + //at the very least the email field must be set + if (! isset ($struct['email'])) { + header ('Location: ' . site_prefix () . '/index/sitemailer2-verifycsv-action?error=noemail'); + exit; + } + + //make sure the file still exists + if (! file_exists (site_docroot () . '/inc/app/sitemailer2/data/tmp/' . session_username ())) { + echo '
No file to import.
'; + exit; + } + + //now parse the csv file based on the col order + $table = get_csv (site_docroot () . '/inc/app/sitemailer2/data/tmp/' . session_username (), 0); + + //there are many ways to get the name + + $fname; $lname; $email; $organization; $url; + + //if the user selected first name or last name, only use those fields + + //option 0 -> omit names, try to get names from email address, see below for more options + $name = 0; + + if (isset ($struct['firstname'])) $fname = $struct['firstname']; + if (isset ($struct['lastname'])) $lname = $struct['lastname']; + + //use first name, last name as is + $name = 1; + + //other name source are determined while looping through data + + if (empty ($fname) && empty ($lname)) { + if (isset ($struct['name'])) { + //full name in one field + $name = 2; + } else if (! empty ($struct['lfname'])) { + $name = 3; + } + } + + $ids = array (); + $user_count = 0; + $dupes = 0; + + foreach ($table as $row) { + + $insfn = ""; $insln = ""; $org = ""; $url = ""; + + $zero = 0; + + if (isset ($struct['organization'])) $org = $row[$struct['organization']]; + if (isset ($struct['www'])) $url = $row[$struct['www']]; + + //first name, last name are ready + if ($name == 1) { + if (! empty ($fname) || $fname == 0) $insfn = $row[$fname]; + if (! empty ($lname) || $lname == 0) $insln = $row[$lname]; + // full name in one field + } elseif ($name == 2) { + $tname = explode (" ", $row[$struct['name']]); + if (count ($tname) > 1) { + $insfn = $tname[0]; + $insln = $tname[1]; + } else if (count ($tname) == 1) { + $insfn = $tname[0]; + } + //lastname, firstname + } elseif ($name == 3) { + $tname = preg_split ('/, ?/', $row[$struct['lfname']]); + if (count ($tname) > 1) { + $insfn = $tname[1]; + $insln = $tname[0]; + } else if (count ($tname) == 1) { + $insfn = $tname[0]; + } + //try to find names from email addresses + } else { + $insfn = getFirstNameFromAddress($row[$struct['email']]); + $insln = getLastNameFromAddress($row[$struct['email']]); + } + + //ready to insert new addresses now + //echo 'Adding email: ' . getEmailFromAddress ($row[$struct['email']]) . '
'; + $email = getEmailFromAddress ($row[$struct['email']]); + if (db_shift ('select count(*) from sitemailer2_recipient where email = ?', $email)) { + $dupes++; + continue; + } + + if (empty ($insfn)) $insfn = ''; + if (empty ($insln)) $insln = ''; + if (empty ($org)) $org = ''; + if (empty ($url)) $url = ''; + + if (! db_execute ( + 'insert into sitemailer2_recipient + (id, email, firstname, lastname, organization, website, created) + values + (null, ?, ?, ?, ?, ?, now())', + $email, + $insfn, + $insln, + $org, + $url + )) { + // unknown error + echo db_error (); + continue; + } + + $user_count++; + + //keep track of the id's added + + $ids[] = db_lastid(); + + $lastid = db_lastid (); + $groups = preg_split ('/, ?/', $cgi->rc); + + foreach ($groups as $group) { + db_execute ( + 'insert into sitemailer2_recipient_in_newsletter + (recipient, newsletter, status_change_time, status) + values + (?, ?, now(), "subscribed")', + $lastid, + $group + ); + } + } + + if (count ($dupes) == 1) { + $dupes = ' with ' . $dupes . ' duplicate not imported'; + } elseif (count ($dupes) > 1) { + $dupes = ' with ' . $dupes . ' duplicates not imported'; + } else { + $dupes = ''; + } + + page_title ('SiteMailer 2 - Importer'); + echo '

Successfully imported ' . $user_count . ' users' . $dupes . '.

'; + echo '

Return to subscriber list

'; + return; +} + +if (! file_exists (site_docroot () . '/inc/app/sitemailer2/data/tmp/' . session_username ())) { + echo '
No file to import.
'; + exit; +} + +if (! empty ($cgi->error)) { + echo '
You must select one field as the email source.
'; +} + +$table = get_csv (site_docroot () . '/inc/app/sitemailer2/data/tmp/' . session_username (), 3); + +//how many columns are there? +$cols = 0; + +if (! empty ($table)) { + foreach($table[0] as $col) { + $cols++; + } +} + +echo '

Please map the data to the correct fields below.

'; + +echo '
'; +$sels = '"; + +echo "\n"; +echo ''; + +loader_import ('saf.Misc.Alt'); + +$alt = new Alt ('#fff', '#eee'); + +for ($i = 0; $i < $cols; $i++) { + echo ''; +} +echo ''; + +foreach ($table as $row) { + $alt->reset (); + echo ""; + foreach ($row as $data) { + if (strlen ($data) > 20) { + $data = substr ($data, 0, 17) . '...'; + } + echo ''; + } + echo "\n"; +} +echo ''; +echo "
' . $sels . ($i + 1) . $sele . '
' . $data . '
...
\n"; +echo ''; +echo '

'; +echo '
'; + + +function get_csv($filename, $maxlines=0, $delim=',') + { + $row = 0; + $dump = array(); + $f = fopen ($filename,"r"); + $size = filesize($filename)+1; + while ($data = fgetcsv($f, $size, $delim)) { + $dump[$row] = $data; + $row++; + if ($maxlines != 0 && $row >= $maxlines) break; + } + fclose ($f); + + return $dump; +} + +function getFirstNameFromAddress ($x) { + + //possible formats + //1. Name + //2. email + //3. "Name@domain" + //4. + + //return empty string if no name + + $x = trim ($x); + + $s = strpos ($x, '<'); + $e = strpos ($x, '>'); + $q = strpos($x, "\""); + + $name = ''; + $fname = ''; //covers 2 and 4 + + if ($e) { //check for 1 or 3 + if ($q) { //3 + $q2 = strpos ($x, "\"", $q+1); + if ($q2) { + $name = substr ($x, $q, $q2-$q1); + } else { //erroneous address???, look for '<' + $name = trim (substr ($x, $q, $q-$s)); + } + } else { //1 + $name = trim (substr ($x, 0, $s)); + } + //break up name if theres a space in it; + $s = strpos ($name, ' '); + if($s) { + $fname = substr ($name, 0, $s); + } else { + $fname = $name; + } + } + + return $fname; +} + +function getLastNameFromAddress ($x) { + + //possible formats + //1. Name + //2. email + //3. "Name@domain" + //4. + + //return empty string if no name + + $x = trim ($x); + + $s = strpos ($x, '<'); + $e = strpos ($x, '>'); + $q = strpos($x, "\""); + + $name = ''; + $lname = ''; //covers 2 and 4 + + if ($e) { //check for 1 or 3 + if ($q) { //3 + $q2 = strpos ($x, "\"", $q+1); + if ($q2) { + $name = substr ($x, $q, $q2-$q1); + } else { //erroneous address???, look for '<' + $name = trim (substr ($x, $q, $q-$s)); + } + } else { //1 + $name = trim (substr ($x, 0, $s)); + } + //break up name if theres a space in it; + $s = strpos ($name, ' '); + if($s) { + $lname = substr ($name, $s, $e-$s); + } else { + $lname = ''; + } + } + + return trim ($lname); +} + +function getEmailFromAddress ($x) { + + //possible formats + //1. Name + //2. email + //3. "Name@domain" + //4. + + //return empty string if no name + + $x = trim ($x); + + $s = strpos ($x, '<'); + $e = strpos ($x, '>'); + + $addy = ''; + + if ($e) { //1, 3 and 4 + $addy = substr ($x, $s+1, $e-$s-1); + } else { //2 + $addy = $x; + } + + return strtolower (trim ($addy)); +} + +?> + diff --git a/inc/app/sitemailer2/boxes/verifycsv/settings.php b/inc/app/sitemailer2/boxes/verifycsv/settings.php new file mode 100644 index 00000000..621345cf --- /dev/null +++ b/inc/app/sitemailer2/boxes/verifycsv/settings.php @@ -0,0 +1,16 @@ +; +copyright = "Copyright (C) 2004, Me Inc." +license = "http://www.opensource.org/licenses/index.php#PICK ONE!!!" +version = 0.1 + +; your form definition goes here + + + +; */ ?> diff --git a/inc/app/sitemailer2/conf/config.ini.php b/inc/app/sitemailer2/conf/config.ini.php new file mode 100755 index 00000000..43f53b93 --- /dev/null +++ b/inc/app/sitemailer2/conf/config.ini.php @@ -0,0 +1,12 @@ +; \ No newline at end of file diff --git a/inc/app/sitemailer2/conf/properties.php b/inc/app/sitemailer2/conf/properties.php new file mode 100755 index 00000000..f07ae662 --- /dev/null +++ b/inc/app/sitemailer2/conf/properties.php @@ -0,0 +1,252 @@ + 'YOUR_SMTP_SERVER', + 'Port' => 25, + 'SMTPAuth' => false, + 'Username' => '', + 'Password' => '', + ) +); + +appconf_set ( + 'mta_sendmail', + array ( + // path to sendmail program + 'Sendmail' => '/usr/sbin/sendmail', + ) +); + +appconf_set ( + 'mta_qmail', + array () +); + +/* Do not make changes below this point. */ + +appconf_set ('from', appconf ('from_name') . ' <' . appconf ('from_email') . '>'); + +appconf_set ( + 'msg', + array ( + 'SENT' => intl_get ('Your message has been sent.'), + 'GROUP_DEL' => intl_get ('Your group has been deleted.'), + 'created' => intl_get ('Your newsletter has been created.'), + 'saved' => intl_get ('Your newsletter has been saved.'), + 'deleted' => intl_get ('Your newsletter has been deleted.'), + 'deletes' => intl_get ('Your newsletters have been deleted.'), + 'subcreated' => intl_get ('Your subscriber has been created.'), + 'subsaved' => intl_get ('Your subscriber has been saved.'), + 'subdel' => intl_get ('Your subscriber has been deleted.'), + 'subsdel' => intl_get ('Your subscribers have been deleted.'), + 'stopped' => intl_get ('Your message has been stopped.'), + 'sending' => intl_get ('Your message will begin sending shortly.'), + 'draft' => intl_get ('Your message has been saved to draft.'), + 'draftdel' => intl_get ('Your message has been deleted.'), + 'tplcreated' => intl_get ('Your template has been created.'), + 'tplsaved' => intl_get ('Your template has been saved.'), + 'tpldeleted' => intl_get ('Your template has been deleted.'), + 'tpldeletes' => intl_get ('Your templates have been deleted.'), + 'settings' => intl_get ('Your settings have been saved.'), + ) +); + +foreach (parse_ini_file ('inc/app/sitemailer2/conf/settings2.ini.php') as $k => $v) { + appconf_set ($k, $v); +} + +appconf_set ('max_attempts', 2); + +if ($context == 'action' && strpos ($_SERVER['REQUEST_URI'], 'public') === false) { +page_add_style (' +h1 { + background-image: url(\'' . site_prefix () . '/inc/app/sitemailer2/pix/icon.gif\'); + background-repeat: no-repeat; + background-position: 0, 50%; + padding-left: 42px; + padding-top: 5px; + padding-bottom: 12px; + margin-bottom: 0px; +} + +table.navbar { + margin-top: 10px; + width: 100%; +} + +table.navbar td { + padding-left: 5px; + padding-right: 5px; + border-bottom: 3px solid #eaeaea; +} + +table.navbar span { + display: block; + float: left; + padding: 0px; + margin: 0px; + background: #ccc; +} + +table.navbar span.current { + background-color: #eaeaea; +} + +table.navbar a { + display: block; + float: left; + padding: 5px; + padding-left: 20px; + margin: 0px; + padding-right: 20px; + border-right: 1px solid #fff; + background-image: url(' . site_prefix () . '/inc/app/sitemailer2/pix/corner.gif); + background-repeat: no-repeat; + background-position: 0px 0px; + color: #000; +} + +table.navbar a.current { + background-image: url(' . site_prefix () . '/inc/app/sitemailer2/pix/corner.gif); + background-repeat: no-repeat; + background-position: 0px 0px; + color: #0081d6; + font-weight: bold; +} + +table.navbar a:hover { + text-decoration: underline; + background-image: url(' . site_prefix () . '/inc/app/sitemailer2/pix/corner.gif); + background-repeat: no-repeat; + background-position: 0px 0px; +} + +tr.odd { + background-color: #fff; +} + +tr.even { + background-color: #eee; +} +'); +} + +define ('CMS_JS_DELETE_CONFIRM', ''); + +define ('CMS_JS_SELECT_ALL', ''); + +formdata_set ( + 'hours', + array ( + '00:00:00' => 'Midnight', + '00:30:00' => ' 0:30 AM', + '01:00:00' => ' 1:00 AM', + '01:30:00' => ' 1:30 AM', + '02:00:00' => ' 2:00 AM', + '02:30:00' => ' 2:30 AM', + '03:00:00' => ' 3:00 AM', + '03:30:00' => ' 3:30 AM', + '04:00:00' => ' 4:00 AM', + '04:30:00' => ' 4:30 AM', + '05:00:00' => ' 5:00 AM', + '05:30:00' => ' 5:30 AM', + '06:00:00' => ' 6:00 AM', + '06:30:00' => ' 6:30 AM', + '07:00:00' => ' 7:00 AM', + '07:30:00' => ' 7:30 AM', + '08:00:00' => ' 8:00 AM', + '08:30:00' => ' 8:30 AM', + '09:00:00' => ' 9:00 AM', + '09:30:00' => ' 9:30 AM', + '10:00:00' => '10:00 AM', + '10:30:00' => '10:30 AM', + '11:00:00' => '11:00 AM', + '11:30:00' => '11:30 AM', + '12:00:00' => '12:00 PM', + '12:30:00' => '12:30 PM', + '13:00:00' => ' 1:00 PM', + '13:30:00' => ' 1:30 PM', + '14:00:00' => ' 2:00 PM', + '14:30:00' => ' 2:30 PM', + '15:00:00' => ' 3:00 PM', + '15:30:00' => ' 3:30 PM', + '16:00:00' => ' 4:00 PM', + '16:30:00' => ' 4:30 PM', + '17:00:00' => ' 5:00 PM', + '17:30:00' => ' 5:30 PM', + '18:00:00' => ' 6:00 PM', + '18:30:00' => ' 6:30 PM', + '19:00:00' => ' 7:00 PM', + '19:30:00' => ' 7:30 PM', + '20:00:00' => ' 8:00 PM', + '20:30:00' => ' 8:30 PM', + '21:00:00' => ' 9:00 PM', + '21:30:00' => ' 9:30 PM', + '22:00:00' => '10:00 PM', + '22:30:00' => '10:30 PM', + '23:00:00' => '11:00 PM', + '23:30:00' => '11:30 PM', + ) +); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/conf/server.ini.php b/inc/app/sitemailer2/conf/server.ini.php new file mode 100755 index 00000000..81854a9a --- /dev/null +++ b/inc/app/sitemailer2/conf/server.ini.php @@ -0,0 +1,24 @@ +; \ No newline at end of file diff --git a/inc/app/sitemailer2/conf/settings2.ini.php b/inc/app/sitemailer2/conf/settings2.ini.php new file mode 100755 index 00000000..d3cb52bf --- /dev/null +++ b/inc/app/sitemailer2/conf/settings2.ini.php @@ -0,0 +1,42 @@ +; \ No newline at end of file diff --git a/inc/app/sitemailer2/data/.htaccess b/inc/app/sitemailer2/data/.htaccess new file mode 100755 index 00000000..4566ff0f --- /dev/null +++ b/inc/app/sitemailer2/data/.htaccess @@ -0,0 +1,3 @@ +Order allow,deny +Deny from all + diff --git a/inc/app/sitemailer2/docs/en/001-about-sitemailer.html b/inc/app/sitemailer2/docs/en/001-about-sitemailer.html new file mode 100644 index 00000000..4c9ef48b --- /dev/null +++ b/inc/app/sitemailer2/docs/en/001-about-sitemailer.html @@ -0,0 +1,14 @@ +

About SiteMailer

+ +

SiteMailer is a complete email marketing add-on to the Sitellite CMS. Some of its features include:

+ +
    +
  • Easily create multiple subscriber lists to improve target marketing based on different interest groups.
  • +
  • Integrate subscribe and unsubscribe forms into your web site with a single line of code inserted into your site template.
  • +
  • Create message templates to maintain consistent branding and formatting across all your messages.
  • +
  • Compose messages using a browser-based Word-like editor. It couldn't get any easier than that!
  • +
  • Rich HTML formatting distinguishes your messages from the sea of plain-text email.
  • +
  • Integrates with the SiteTracker add-on to track responses from email campaigns.
  • +
  • Import subscribers from Outlook or PDA's through a built-in VCF file importer.
  • +
  • And much more!
  • +
diff --git a/inc/app/sitemailer2/docs/en/002-installation.html b/inc/app/sitemailer2/docs/en/002-installation.html new file mode 100644 index 00000000..494f163b --- /dev/null +++ b/inc/app/sitemailer2/docs/en/002-installation.html @@ -0,0 +1,24 @@ +

Installation

+ +

From the Unix command-line, enter the following:

+ +

+mysql -p -u USER DBNAME < inc/app/sitemailer/install/install-mysql.sql
+
+ +

Then enter your password when prompted. You may also use an alternate MySQL client, such as phpMyAdmin, if you prefer. This will create the necessary database tables that SiteMailer needs to store your subscriber lists.

+ +

Edit your configuration file

+ +

SiteMailer contains two configuration files that specify the behaviour of the application. The first is called config.ini.php, which tells the Sitellite Content Server how to load SiteMailer and how to interact with it. The second, which is called properties.php, tells SiteMailer how you want it to behave. Both of these files live in the inc/app/sitemailer/conf folder.

+ +

The only two options that everyone needs to adjust in the properties.php file are the following lines:

+ +

+appconf_set ('from_email', 'you@yourWebSite.com');
+appconf_set ('from_name', 'SiteMailer');
+
+ +

The first line tells SiteMailer to send messages “from” the specified email address, and the second tells SiteMailer to give the the “from” line an actual name.

+ +

The rest of the options are for advanced users only, and instructions for each of them are contained inside the properties.php file.

diff --git a/inc/app/sitemailer2/docs/en/003-logging-in.html b/inc/app/sitemailer2/docs/en/003-logging-in.html new file mode 100644 index 00000000..9a3e726e --- /dev/null +++ b/inc/app/sitemailer2/docs/en/003-logging-in.html @@ -0,0 +1,11 @@ +

Logging into SiteMailer

+ +

Once you have successfully installed SiteMailer, you will see the SiteMailer icon as well as its name in the Add-Ons list in Sitellite's Control Panel view.

+ +

Alternatively, you can log into the SiteMailer administrative area directly by going to the following URL:

+ +

+http://www.YourWebSite.com/index/sitemailer-app
+
+ +

Then simply enter your username and password to begin creating subscriber groups, managing subscribers, and sending messages to them.

diff --git a/inc/app/sitemailer2/docs/en/004-message-templates.html b/inc/app/sitemailer2/docs/en/004-message-templates.html new file mode 100644 index 00000000..5f193c90 --- /dev/null +++ b/inc/app/sitemailer2/docs/en/004-message-templates.html @@ -0,0 +1,9 @@ +

SiteMailer Message Templates

+ +

SiteMailer allows you to use templates to add branding to your messages. These templates live in the inc/app/sitemailer/html/templates folder, and can be selected when you are composing a message.

+ +

Templates are written in the SimpleTemplate language. A default template, named default.spt, is provided as an example.

+ +

Once you have created a new template and saved it to the inc/app/sitemailer/html/templates folder, it will automatically appear in the list of available templates when composing messages in SiteMailer.

+ +

Please note that the templates are generated only once ahead of time, and so they cannot contain any personalized information for each subscriber. This is functionality slated for SiteMailer 2.

diff --git a/inc/app/sitemailer2/docs/en/005-site-integration.html b/inc/app/sitemailer2/docs/en/005-site-integration.html new file mode 100644 index 00000000..6819330d --- /dev/null +++ b/inc/app/sitemailer2/docs/en/005-site-integration.html @@ -0,0 +1,14 @@ +

Insert SiteMailer into your Web Site

+ +

To insert SiteMailer’s subscribe and unsubscribe forms into your web site, simply include the following code into your templates somewhere:

+ +

+<xt:form name="sitemailer/subscribe" />
+
+ +

And for the unsubscribe form:

+ +

+<xt:form name="sitemailer/unsubscribe" />
+
+ diff --git a/inc/app/sitemailer2/docs/en/index.html b/inc/app/sitemailer2/docs/en/index.html new file mode 100644 index 00000000..63cb1250 --- /dev/null +++ b/inc/app/sitemailer2/docs/en/index.html @@ -0,0 +1,11 @@ +

SiteMailer Help

+ +

Table of Contents

+ +
    +
  1. About SiteMailer
  2. +
  3. Installation
  4. +
  5. Logging Into SiteMailer
  6. +
  7. Message Templates
  8. +
  9. Insert SiteMailer into your Web Site
  10. +
diff --git a/inc/app/sitemailer2/forms/access.php b/inc/app/sitemailer2/forms/access.php new file mode 100644 index 00000000..a83a1fbe --- /dev/null +++ b/inc/app/sitemailer2/forms/access.php @@ -0,0 +1,5 @@ +sitellite_access = private +sitellite_status = approved +sitellite_action = on +sitellite_goto = sitemailer2-app +sitellite_template_set = admin diff --git a/inc/app/sitemailer2/forms/campaign/add/index.php b/inc/app/sitemailer2/forms/campaign/add/index.php new file mode 100644 index 00000000..bc52fec4 --- /dev/null +++ b/inc/app/sitemailer2/forms/campaign/add/index.php @@ -0,0 +1,34 @@ +parseSettings ('inc/app/sitemailer2/forms/campaign/settings.php'); + + page_title ('Add a Campaign'); + + $this->widgets['url']->setValue ('http://'); + + $cancel = site_prefix () . '/index/sitemailer2-campaigns-action'; + + foreach ($this->widgets['done']->buttons as $k=>$button) { + if ($button->value == "Cancel") { + $this->widgets['done']->buttons[$k]->extra = 'onclick="window.location.href=\'' . $cancel . '\'; return false"'; + } + + } + } + + function onSubmit ($vals) { + // your handler code goes here + + if (! db_execute ('insert into sitemailer2_campaign (id, title, forward_url, created) values (NULL, ?, ?, now())', $vals['title'], $vals['url'])) { + echo 'Failed to create campain'; + } else { + header ('Location: ' . site_prefix () . '/index/sitemailer2-campaigns-action'); + } + } +} + +?> diff --git a/inc/app/sitemailer2/forms/campaign/edit/index.php b/inc/app/sitemailer2/forms/campaign/edit/index.php new file mode 100644 index 00000000..31a77ac8 --- /dev/null +++ b/inc/app/sitemailer2/forms/campaign/edit/index.php @@ -0,0 +1,35 @@ +parseSettings ('inc/app/sitemailer2/forms/campaign/settings.php'); + + page_title ('Edit a Campaign'); + + $this->widgets['id']->setValue ($cgi->id); + + $res = db_single ('select * from sitemailer2_campaign where id = ?', $cgi->id); + + //info ($res); + + $this->widgets['title']->setValue ($res->title); + $this->widgets['url']->setValue ($res->forward_url); + + } + + function onSubmit ($vals) { + // your handler code goes here + + if (! db_execute ('update sitemailer2_campaign set title = ?, forward_url = ? where id = ?', $vals['title'], $vals['url'], $vals['id'])) { + echo 'Failed to update campain'; + } else { + header ('Location: ' . site_prefix () . '/index/sitemailer2-campaigns-action'); + } + } +} + +?> diff --git a/inc/app/sitemailer2/forms/campaign/settings.php b/inc/app/sitemailer2/forms/campaign/settings.php new file mode 100644 index 00000000..2a4a5a85 --- /dev/null +++ b/inc/app/sitemailer2/forms/campaign/settings.php @@ -0,0 +1,35 @@ +; +copyright = "Copyright (C) 2004, Me Inc." +license = "http://www.opensource.org/licenses/index.php#PICK ONE!!!" +version = 0.1 + +; your form definition goes here + +[title] + +type = text +rule 1 = "not empty, You must enter a title." + +[url] + +type = text +alt = URL to forward to +rule 1 = "not empty, You must enter a URL to forward to." + +[id] + +type = hidden + +[done] + +type = msubmit +button 1 = Submit +button 2 = Cancel + +; */ ?> diff --git a/inc/app/sitemailer2/forms/import/submissions/index.php b/inc/app/sitemailer2/forms/import/submissions/index.php new file mode 100644 index 00000000..f0148cf1 --- /dev/null +++ b/inc/app/sitemailer2/forms/import/submissions/index.php @@ -0,0 +1,55 @@ + '- All -'); + foreach (db_pairs ('select id, name from sitellite_form_type order by name asc') as $k => $v) { + $groups[$k] = $v; + } + $this->widgets['group']->setValues ($groups); + $this->widgets['newsletter']->setValues (db_pairs ('select id, name from sitemailer2_newsletter order by name asc')); + page_title (intl_get ('Add to Newsletter')); + } + + function onSubmit ($vals) { + if (! $vals['group']) { + $res = db_fetch_array ( + 'select distinct first_name, last_name, email_address, company from sitellite_form_submission' + ); + } else { + $res = db_fetch_array ( + 'select distinct first_name, last_name, email_address, company from sitellite_form_submission where form_type = ?', + $vals['group'] + ); + } + + foreach ($res as $row) { + $id = db_shift ('select id from sitemailer2_recipient where email = ?', $row->email_address); + if (! $id) { + $row->first_name = (is_null ($row->first_name)) ? '' : $row->first_name; + $row->last_name = (is_null ($row->last_name)) ? '' : $row->last_name; + $row->company = (is_null ($row->company)) ? '' : $row->company; + db_execute ( + 'insert into sitemailer2_recipient values (null, ?, ?, ?, ?, "", now(), "active")', + $row->email_address, + $row->first_name, + $row->last_name, + $row->company + ); + $id = db_lastid (); + } + db_execute ( + 'insert into sitemailer2_recipient_in_newsletter values (?, ?, now(), "subscribed")', + $id, + $vals['newsletter'] + ); + } + + page_title (intl_get ('Contacts Added')); + echo '

' . intl_get ('The selected users have been added to your newsletter.') . ' ' . intl_get ('Back') . '

'; + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/import/submissions/settings.php b/inc/app/sitemailer2/forms/import/submissions/settings.php new file mode 100644 index 00000000..faab2084 --- /dev/null +++ b/inc/app/sitemailer2/forms/import/submissions/settings.php @@ -0,0 +1,20 @@ +[Form] + +method = post +message = "Add form submission contacts from the selected group to the selected newsletter. Back" + +[group] + +type = select +alt = Form Submission Group + +[newsletter] + +type = select +alt = Add to Newsletter + +[submit_button] + +type = submit +setValues = Save +extra = "onclick=`this.value = 'Please wait...'`" diff --git a/inc/app/sitemailer2/forms/import/users/index.php b/inc/app/sitemailer2/forms/import/users/index.php new file mode 100644 index 00000000..0066ef84 --- /dev/null +++ b/inc/app/sitemailer2/forms/import/users/index.php @@ -0,0 +1,71 @@ + '- SELECT -'); + foreach (array_keys ($snm->role->getList ()) as $role) { + $list[$role] = ucwords ($role); + } + return $list; +} + +function sitemailer2_get_teams () { + $snm =& session_get_manager (); + $list = array ('' => '- SELECT -'); + foreach (array_keys ($snm->team->getList ()) as $role) { + $list[$role] = ucwords ($role); + } + return $list; +} + +class Sitemailer2ImportUsersForm extends MailForm { + function Sitemailer2ImportUsersForm () { + parent::MailForm (__FILE__); + $this->widgets['newsletter']->setValues (db_pairs ('select id, name from sitemailer2_newsletter order by name asc')); + page_title (intl_get ('Add to Newsletter')); + } + + function onSubmit ($vals) { + $sql = 'select email, firstname, lastname, company, website from sitellite_user'; + $clause = ' where '; + $bind = array (); + + if (! empty ($vals['team'])) { + $sql .= $clause . 'team = ?'; + $clause = ' and '; + $bind[] = $vals['team']; + } + + if (! empty ($vals['role'])) { + $sql .= $clause . 'role = ?'; + $bind[] = $vals['role']; + } + + $res = db_fetch_array ($sql, $bind); + + foreach ($res as $row) { + $id = db_shift ('select id from sitemailer2_recipient where email = ?', $row->email); + if (! $id) { + db_execute ( + 'insert into sitemailer2_recipient values (null, ?, ?, ?, ?, ?, now(), "active")', + $row->email, + $row->firstname, + $row->lastname, + $row->company, + $row->website + ); + $id = db_lastid (); + } + db_execute ( + 'insert into sitemailer2_recipient_in_newsletter values (?, ?, now(), "subscribed")', + $id, + $vals['newsletter'] + ); + } + + page_title (intl_get ('Users Added')); + echo '

' . intl_get ('The selected users have been added to your newsletter.') . ' ' . intl_get ('Back') . '

'; + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/import/users/settings.php b/inc/app/sitemailer2/forms/import/users/settings.php new file mode 100644 index 00000000..df4b652a --- /dev/null +++ b/inc/app/sitemailer2/forms/import/users/settings.php @@ -0,0 +1,27 @@ +[Form] + +method = post +message = "Add users from the selected team and role to the selected newsletter. Back" + +[team] + +type = select +alt = Team +setValues = "eval: sitemailer2_get_teams ()" + +[role] + +type = select +alt = Role +setValues = "eval: sitemailer2_get_roles ()" + +[newsletter] + +type = select +alt = Add to Newsletter + +[submit_button] + +type = submit +setValues = Save +extra = "onclick=`this.value = 'Please wait...'`" diff --git a/inc/app/sitemailer2/forms/massunsub/index.php b/inc/app/sitemailer2/forms/massunsub/index.php new file mode 100644 index 00000000..e590e7b7 --- /dev/null +++ b/inc/app/sitemailer2/forms/massunsub/index.php @@ -0,0 +1,40 @@ +parseSettings ('inc/app/sitemailer2/forms/massunsub/settings.php'); + } + + function onSubmit ($vals) { + + if (! empty ($vals['file_csv'])) { + + //move the file somewhere temporary that can be controlled + //move the file to /inc/app/sitemailer2/data/tmp + //call the filename username + + $newfile = '_' . session_username (); + + //check if it exists + if (file_exists (site_docroot () . '/inc/app/sitemailer2/data/tmp/' . $newfile)) { + //delete it if it exists + unlink ('inc/app/sitemailer2/data/tmp/' . $newfile); + } + + //move the file + rename ($vals['file_csv']->tmp_name, site_docroot () . '/inc/app/sitemailer2/data/tmp/' . $newfile); + //header off to verification + header ('Location: ' . site_prefix () . '/index/sitemailer2-massunsub-action?rc=' . $vals['newsletter']); + exit; + } else { + echo 'Error importing recipients.'; + } + } +} + +page_title ('SiteMailer 2 - ' . intl_get ('Mass Unsubscriber')); +$form = new MassunsubForm; +echo $form->run (false); // false tells it not to save the uploaded file + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/massunsub/settings.php b/inc/app/sitemailer2/forms/massunsub/settings.php new file mode 100644 index 00000000..a9e4c976 --- /dev/null +++ b/inc/app/sitemailer2/forms/massunsub/settings.php @@ -0,0 +1,42 @@ +; \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/msg/index.php b/inc/app/sitemailer2/forms/msg/index.php new file mode 100755 index 00000000..6af805e2 --- /dev/null +++ b/inc/app/sitemailer2/forms/msg/index.php @@ -0,0 +1,347 @@ +_key) && ! empty($cgi->_key)) { + $add = false; + } + + //this message already exists + if (! $add) { + + $document = db_single ('select * from sitemailer2_message where id = ?', $cgi->_key); + + //special display + if ($document->status == 'done' || $document->status == 'running') { + + $this->parseSettings ('inc/app/sitemailer2/forms/msg/settingsstatic.php'); + + $newsletter = db_shift ('select name from sitemailer2_newsletter where id = ?', $document->newsletter); + + $this->widgets['recur']->setValue ($document->recurring); + + $this->widgets['newsletter']->setValue ($newsletter); + + $tpl = db_single ('select title from sitemailer2_template where id = ?' , $document->template); + $this->widgets['template']->setValue ($tpl->title); + + $this->widgets['start']->setValues ($document->start); + + $cancel = site_prefix () . '/index/cms-browse-action?collection=sitemailer2_message'; + + $this->widgets['submit_button']->buttons[1]->extra = 'onclick="window.location.href=\'' . $cancel . '\'; return false"'; + + if ($document != 'running') unset ($this->widgets['submit_button']->buttons[0]); + + //standard display + } else { + + $this->parseSettings ('inc/app/sitemailer2/forms/msg/settings.php'); + $this->widgets['template']->setValue ($document->template); + + $settings = @parse_ini_file ('inc/app/sitemailer2/conf/settings2.ini.php'); + $this->widgets['test_email']->setValue ($settings['test_email']); + + $dt = explode (' ', $document->start); + + $this->widgets['date']->setValue ($dt[0]); + $this->widgets['time']->setValue ($dt[1]); + + $newsletters = db_shift_array ('select newsletter from sitemailer2_message_newsletter where message = ?', $cgi->_key); + + $this->widgets['newsletter']->setValue ($newsletters); + + $this->widgets['recur']->setValues (assocify (array ('no', 'weekly', 'twice-montly', 'monthly'))); + + $this->widgets['recur']->setValue ($document->recurring); + + } + + //display for all cases + page_title ('SiteMailer 2 - ' . intl_get ('Edit Message')); + + $this->widgets['title']->setValue ($document->title); + $this->widgets['status']->setValue (ucfirst ($document->status)); + $this->widgets['from_name']->setValue ($document->fromname); + $this->widgets['from_email']->setValue ($document->fromemail); + $this->widgets['body']->setValue ($document->mbody); + $this->widgets['subject']->setValue ($document->subject); + + //how many messages are queued? + if ($document->numrec != 0 && $document->status == 'running') { + $total = db_shift ('select count(id) from sitemailer2_q where message = ?', $cgi->_key); + $total = $document->numrec - $total; + + $this->widgets['complete']->setValue ($total . '/' . $document->numrec . ' (' . $total/$document->numrec*100 . "%)"); + + } elseif ($document->numrec != 0 && $document->status == 'done') { + + $this->widgets['complete']->setValue ($document->numsent . '/' . $document->numrec . ' (' . $document->numsent/$document->numrec*100 . "%)"); + + } else { + + $this->widgets['complete']->setValue ('0' . '/' . $document->numrec . ' (0%)'); + } + + //else this message is new + } else { + + $this->parseSettings ('inc/app/sitemailer2/forms/msg/settings.php'); + + $settings = @parse_ini_file ('inc/app/sitemailer2/conf/settings2.ini.php'); + $this->widgets['test_email']->setValue ($settings['test_email']); + + page_title ('SiteMailer 2 - ' . intl_get ('New Message')); + $this->widgets['status']->setValue ('Draft'); + unset ($this->widgets['complete']); + + $this->widgets['recur']->setValues (assocify (array ('no', 'weekly', 'twice-monthly', 'monthly'))); + + loader_import ('saf.Date'); + + $this->widgets['date']->setValue (date('Y-m-d')); + $this->widgets['time']->setValue (Date::roundTime(date('H:i:s'), 30)); + + if (is_array ($cgi->newsletter) && count ($cgi->newsletter) == 1) { + $res = db_single ('select * from sitemailer2_newsletter where id = ?', $cgi->newsletter[0]); + $this->widgets['from_name']->setValue ($res->from_name); + $this->widgets['from_email']->setValue ($res->from_email); + $this->widgets['template']->setValue ($res->template); + $this->widgets['subject']->setValue ($res->subject); + } + } + + //unset buttons based on context + if ($document->status != 'done' && $document->status != 'running') { + //done only has a back button + + unset ($this->widgets['submit_button']->buttons[2]); + + if ($document->status == 'draft' || $add) { + unset ($this->widgets['complete']); + } + } + + $cancel = site_prefix () . '/index/sitemailer2-app'; + + foreach ($this->widgets['submit_button']->buttons as $k=>$button) { + if ($button->value == intl_get ('Send Test Message')) { + $this->widgets['submit_button']->buttons[$k]->extra = 'onclick="return sm2_prompt(this.form)"'; + } + + if ($button->value == intl_get ('Cancel')) { + $this->widgets['submit_button']->buttons[$k]->extra = 'onclick="window.location.href=\'' . $cancel . '\'; return false"'; + } + + } + } + + function onSubmit ($vals) { + + //info ($vals);exit; + + $id = $vals['_key']; + + $newsletters = explode (',', $vals['newsletter']); + + if($vals['submit_button'] == intl_get ('Stop Sending')) { + + //untested + $sent = db_shift ('select count(id) from sitemailer2_q where message = ?', $id); + + $curr = db_single ('select * from sitemailer2_message where id = ?', $id); + + $sent = $curr->numrec - $sent; + + db_execute ('delete from sitemailer2_q where message = ?', $id); + + db_execute ('update sitemailer2_message set status = "done", numsent = ? where id = ?', $sent, $id); + + header ('Location: ' . site_prefix () . '/index/sitemailer2-app?msg=stopped'); + exit; + } + + if (empty ($vals['_key'])) { //create + + db_execute ('insert into sitemailer2_message + (id, title, date, template, status, fromname, fromemail, mbody, subject, numrec, numsent, confirmed_views, start, recurring) + values (null, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + $vals['title'], //title + date ('Y-m-d H:i:s'), //date + $vals['template'], //template + 'draft', //status + $vals['from_name'], //fromname + $vals['from_email'], //fromemail + $vals['body'], //mbody + $vals['subject'], //subject + 0, 0, 0, //numrec, numsent, confirmed_views + $vals['date'] . ' ' . $vals['time'],//start + $vals['recur']); + + $id = db_lastid (); + + foreach ($newsletters as $n) { + db_execute ('insert into sitemailer2_message_newsletter (id, message, newsletter) values (null, ?, ?)', $id, $n); + } + + } else { //update + + db_execute ('update sitemailer2_message set + title=?, template=?, status=?, fromname=?, fromemail=?, mbody=?, subject=?, start=?, recurring=? where id = ?', + $vals['title'], //title + $vals['template'], //template + 'draft', //status + $vals['from_name'], //fromname + $vals['from_email'], //fromemail + $vals['body'], //mbody + $vals['subject'], //subject + $vals['date'] . ' ' . $vals['time'], + $vals['recur'], + $id); //start + + db_execute ('delete from sitemailer2_message_newsletter where message = ?', $id); + + foreach ($newsletters as $n) { + db_execute ('insert into sitemailer2_message_newsletter (id, message, newsletter) values (null, ?, ?)', $id, $n); + } + } + + //sending messages to q + if ($vals['submit_button'] == intl_get ('Send Message')) { //run the mailing list + + set_time_limit (0); + $added = 0; + + if ($vals['date'] == 'SITEEVENT_TODAY') { + $date = date ('Y-m-d'); + } else { + $date = $vals['date']; + } + + //get a list of recipients + $q = db_query ('select distinct recipient from sitemailer2_recipient_in_newsletter + where newsletter in(' . $vals['newsletter'] . ') and status="subscribed"'); + if ($q->execute ()) { + while ($r = $q->fetch ()) { + if (! db_execute ('insert into sitemailer2_q (id, recipient, message, attempts, created, last_attempt, last_error, next_attempt) values (null, ?, ?, 0, now(), "", "", ?)', $r->recipient, $id, $date . ' ' . $vals['time'])) { + echo '

Error adding recipient to the queue.

'; + exit; + } else { + $added++; + } + } + } else { + echo '

No recipients found.

'; + exit; + } + + /* + $res = db_shift_array ('select distinct recipient from sitemailer2_recipient_in_newsletter + where newsletter in(' . $vals['newsletter'] . ') and status="subscribed"'); + + //add all emails in $res to the q with the neccesary info + $added = 0; + + if ($vals['date'] == 'SITEEVENT_TODAY') { + $date = date ('Y-m-d'); + } else { + $date = $vals['date']; + } + + foreach ($res as $r) { + + if (! db_execute ('insert into sitemailer2_q (id, recipient, message, attempts, created, last_attempt, last_error, next_attempt) values (null, ?, ?, 0, now(), "", "", ?)', $r, $id, $date . ' ' . $vals['time'])) { + echo '

Error adding message to q.

'; + exit; + } else { + $added++; + } + } + */ + + db_execute ('update sitemailer2_message set numrec='. $added . ', status="running" where id = ?', $id); + + //set up recurrences, if needed + if ($vals['recur'] != 'no') { + //find year, month, day + //hour, minute, second + + list ($year, $month, $day) = explode ('-', $date); + + list ($hour, $minute, $second) = explode (':', $time); + + //set next send time + if ($vals['recur'] == 'daily') { + $day += 1; + } else if ($vals['recur'] == 'weekly') { + $day += 7; + } else if ($vals['recur'] == 'twice-monthly') { + $day += 15; + } else if ($vals['recur'] == 'monthly') { + $month += 1; + } else { + echo 'form error! invalid recurrence type';exit; + } + + $next_recurrence = date ('Y-m-d H:i:s', mktime ($hour, $minute, $second, $month, $day, $year)); + + if (! db_execute ('update sitemailer2_message set next_recurrence=? where id=?', $next_recurrence, $id)) { + echo 'update of next_recurrence failed'; + exit; + } + } + + header ('Location: ' . site_prefix () . '/index/sitemailer2-app?msg=sending'); + exit; + } else { + header ('Location: ' . site_prefix () . '/index/sitemailer2-app?msg=draft'); + exit; + } + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/msg/settings.php b/inc/app/sitemailer2/forms/msg/settings.php new file mode 100755 index 00000000..35f9f6f3 --- /dev/null +++ b/inc/app/sitemailer2/forms/msg/settings.php @@ -0,0 +1,108 @@ +; '- SELECT -') + db_pairs ('select id,title from sitemailer2_template order by title asc')" +rule 1 = "not empty, You must specify a template." + +[recur] + +type = select +alt = Re-occurring + +[date] + +type = calendar +data_value = SITEEVENT_TODAY +rule 1 = "not empty, You must set a day and time. If you set the message for a time in the past, it will have a priority over messages set for a later date and time." + + +[time] + +type = select +setValues = "eval: formdata_get ('hours')" +extra = "id=`time` style=`font-family: monospace; padding-top: 2px`" +rule 1 = "not empty, You must set a day and time. If you set the message for a time in the past, it will have a priority over messages set for a later date and time." + +;newsletter +[newsletter] + +alt = Newsletters +;type = selector +type = multiple +size = 5 +;table = sitemailer2_newsletter +setValues = "eval: db_pairs ('select id, name from sitemailer2_newsletter')" +;extra = "onfocus=`formhelp_show(this,'blah')` onblur=`formhelp_hide()`" +;key = id +;title = name + +[subject] + +alt = Subject +type = text +size = 40 + +[body] + +type = xed.Widget.Xeditor +; clean = off + +[test_email] + +type = hidden + +[submit_button] + +type = msubmit +button 1 = Send Message +button 2 = Save as Draft +button 3 = Stop Sending +button 4 = Send Test Message +button 5 = Cancel + +; */ ?> diff --git a/inc/app/sitemailer2/forms/msg/settingsstatic.php b/inc/app/sitemailer2/forms/msg/settingsstatic.php new file mode 100755 index 00000000..63ab9797 --- /dev/null +++ b/inc/app/sitemailer2/forms/msg/settingsstatic.php @@ -0,0 +1,79 @@ +; +copyright = "Copyright (C) 2004, Me Inc." +license = "http://www.opensource.org/licenses/index.php#PICK ONE!!!" +version = 0.1 +error_mode = all +extra = "onsubmit=`xed_copy_value (this, 'body')`" + +[collection] + +type = hidden + +[_collection] + +type = hidden + +[_key] + +type = hidden + +[title] + +type = info + +[status] + +type = info + +[recur] + +type = info + +[complete] + +type = info + +[from_name] + +type = info + +[from_email] + +type = info +rule 1 = "not empty, You must specify a reply email address." + +[template] + +type = info + +;newsletter +[newsletter] + +type = info + +[start] + +type = info + +[subject] + +type = info + +[body] + +type = textarea +; clean = off + +[submit_button] + +type = msubmit +button 1 = Stop Sending +button 2 = Cancel + +; */ ?> diff --git a/inc/app/sitemailer2/forms/newsletter/add/index.php b/inc/app/sitemailer2/forms/newsletter/add/index.php new file mode 100644 index 00000000..c1a5c422 --- /dev/null +++ b/inc/app/sitemailer2/forms/newsletter/add/index.php @@ -0,0 +1,57 @@ +parseSettings ('inc/app/sitemailer2/forms/newsletter/add/settings.php'); + $this->widgets['submit_button']->buttons[1]->extra = 'onclick="window.location.href = \'' . site_prefix () . '/index/sitemailer2-app\'; return false"'; + + $settings = @parse_ini_file ('inc/app/sitemailer2/conf/settings2.ini.php'); + + $this->widgets['from_email']->setValue($settings['email_id']); + + $list = array (); + $list = db_pairs ('select id, title from sitemailer2_template order by title asc'); + $list[''] = '- SELECT -'; + + ksort ($list); + $this->widgets['template']->setValues ($list); + } + + function onSubmit ($vals) { + if (! $vals['template']) { + $vals['template'] = ''; + } + + + if(! db_execute ( + 'insert into sitemailer2_newsletter (id, name, from_name, from_email, template, subject, public, rss_subs) values (null, ?, ?, ?, ?, ?, ?, 0)', + $vals['name'], + $vals['from_name'], + $vals['from_email'], + $vals['template'], + $vals['subject'], + $vals['public'] + )) { echo "

Failed to add newsletter\n

";exit; } + + if (! empty ($vals['newsletters'])) { + $id = db_lastid (); + $res = db_pairs ('select distinct recipient, status from sitemailer2_recipient_in_newsletter where newsletter in(' . $vals['newsletters'] . ')'); + foreach ($res as $recip => $status) { + db_execute ( + 'insert into sitemailer2_recipient_in_newsletter (recipient, newsletter, status_change_time, status) values (?, ?, now(), ?)', + $recip, $id, $status + ); + } + } + + header ('Location: ' . site_prefix () . '/index/sitemailer2-app?msg=created'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/newsletter/add/settings.php b/inc/app/sitemailer2/forms/newsletter/add/settings.php new file mode 100644 index 00000000..220365d4 --- /dev/null +++ b/inc/app/sitemailer2/forms/newsletter/add/settings.php @@ -0,0 +1,45 @@ +[Form] + +[name] + +type = text +alt = Newsletter Name + +[from_name] + +type = text +alt = From Name + +[from_email] + +type = text +alt = From Email +extra = "onfocus=`formhelp_show (this, 'Please Note: Changing this from the global default value will prevent the bounced message checker from checking this newsletter.')` onblur=`formhelp_hide ()`" + +[template] + +type = select + +[subject] + +type = text +alt = Subject + +[public] + +type = select +alt = Public +setValues = "eval: assocify (array ('yes', 'no'))" + +[newsletters] + +type = multiple +size = 5 +alt = Import Subscribers From +setValues = "eval: db_pairs ('select id, name from sitemailer2_newsletter order by name asc')" + +[submit_button] + +type = msubmit +button 1 = Create +button 2 = Cancel diff --git a/inc/app/sitemailer2/forms/newsletter/edit/index.php b/inc/app/sitemailer2/forms/newsletter/edit/index.php new file mode 100644 index 00000000..8f4b4e68 --- /dev/null +++ b/inc/app/sitemailer2/forms/newsletter/edit/index.php @@ -0,0 +1,51 @@ +parseSettings ('inc/app/sitemailer2/forms/newsletter/edit/settings.php'); + $this->widgets['submit_button']->buttons[1]->extra = 'onclick="window.location.href = \'' . site_prefix () . '/index/sitemailer2-app\'; return false"'; + + $list = array (); + $list = db_pairs ('select id, title from sitemailer2_template order by title asc'); + $list[''] = '- SELECT -'; + + ksort ($list); + + $this->widgets['template']->setValues ($list); + + global $cgi; + $this->widgets['id']->setValue ($cgi->id); + + $res = db_single ('select * from sitemailer2_newsletter where id = ?', $cgi->id); + + $this->widgets['name']->setValue ($res->name); + $this->widgets['from_name']->setValue ($res->from_name); + $this->widgets['from_email']->setValue ($res->from_email); + $this->widgets['template']->setValue ($res->template); + $this->widgets['subject']->setValue ($res->subject); + $this->widgets['public']->setValue ($res->public); + } + + function onSubmit ($vals) { + if (! $vals['template']) { + $vals['template'] = ''; + } + db_execute ( + 'update sitemailer2_newsletter set name = ?, from_name = ?, from_email = ?, template = ?, subject = ?, public = ? where id = ?', + $vals['name'], + $vals['from_name'], + $vals['from_email'], + $vals['template'], + $vals['subject'], + $vals['public'], + $vals['id'] + ); + header ('Location: ' . site_prefix () . '/index/sitemailer2-app?msg=saved'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/newsletter/edit/settings.php b/inc/app/sitemailer2/forms/newsletter/edit/settings.php new file mode 100644 index 00000000..6ca5cd7f --- /dev/null +++ b/inc/app/sitemailer2/forms/newsletter/edit/settings.php @@ -0,0 +1,41 @@ +[Form] + +[id] + +type = hidden + +[name] + +type = text +alt = Newsletter Name + +[from_name] + +type = text +alt = From Name + +[from_email] + +type = text +alt = From Email + +[template] + +type = select + +[subject] + +type = text +alt = Subject + +[public] + +type = select +alt = Public +setValues = "eval: assocify (array ('yes', 'no'))" + +[submit_button] + +type = msubmit +button 1 = Save +button 2 = Cancel diff --git a/inc/app/sitemailer2/forms/settings/access.php b/inc/app/sitemailer2/forms/settings/access.php new file mode 100644 index 00000000..a83a1fbe --- /dev/null +++ b/inc/app/sitemailer2/forms/settings/access.php @@ -0,0 +1,5 @@ +sitellite_access = private +sitellite_status = approved +sitellite_action = on +sitellite_goto = sitemailer2-app +sitellite_template_set = admin diff --git a/inc/app/sitemailer2/forms/settings/index.php b/inc/app/sitemailer2/forms/settings/index.php new file mode 100644 index 00000000..06b013c5 --- /dev/null +++ b/inc/app/sitemailer2/forms/settings/index.php @@ -0,0 +1,107 @@ +parseSettings ('inc/app/sitemailer2/forms/settings/settings.php'); + page_title ('SiteMailer 2 - Settings'); + + $settings = @parse_ini_file ('inc/app/sitemailer2/conf/settings2.ini.php'); + + $this->widgets['bounces']->setValue ($settings['disable_subscriber_after_bounces']); + $this->widgets['registration']->setValue ($settings['subscriber_registration']); + + if ($settings['subscriber_email_verification']) { + $this->widgets['verification']->setValue ('yes'); + } else { + $this->widgets['verification']->setValue ('no'); + } + + if ($settings['unsubscribe_email_verification']) { + $this->widgets['unsubscribe_email_verification']->setValue ('yes'); + } else { + $this->widgets['unsubscribe_email_verification']->setValue ('no'); + } + + if ($settings['public_archive_of_messages']) { + $this->widgets['archive']->setValue ('yes'); + } else { + $this->widgets['archive']->setValue ('no'); + } + + if ($settings['rss_subscribers']) { + $this->widgets['rss']->setValue ('yes'); + } else { + $this->widgets['rss']->setValue ('no'); + } + + if ($settings['confirmation_email_domain']) { + $this->widgets['confirmation_email_domain']->setValue ($settings['confirmation_email_domain']); + } + + if ($settings['confirmation_from']) { + $this->widgets['confirmation_from']->setValue ($settings['confirmation_from']); + } + + if ($settings['confirmation_subject']) { + $this->widgets['confirmation_subject']->setValue ($settings['confirmation_subject']); + } + + if ($settings['mailer_domain']) { + $this->widgets['mailer_domain']->setValue ($settings['mailer_domain']); + } else { + $this->widgets['mailer_domain']->setValue (site_domain ()); + } + + if ($settings['email_id']) { + $this->widgets['email_id']->setValue ($settings['email_id']); + } + if ($settings['email_password']) { + $this->widgets['email_password']->setValue ($settings['email_password']); + } + if ($settings['email_port']) { + $this->widgets['email_port']->setValue ($settings['email_port']); + } + if ($settings['email_server']) { + $this->widgets['email_server']->setValue ($settings['email_server']); + } + } + + function onSubmit ($vals) { + + loader_import ('saf.File'); + loader_import ('saf.Misc.Ini'); + + $settings = array(); + $settings['disable_subscriber_after_bounces'] = $vals ['bounces']; + $settings['subscriber_registration'] = $vals ['registration']; + $settings['subscriber_email_verification'] = $vals ['verification']; + $settings['public_archive_of_messages'] = $vals ['archive']; + $settings['rss_subscribers'] = $vals ['rss']; + $settings['confirmation_email_domain'] = $vals ['confirmation_email_domain']; + $settings['confirmation_from'] = $vals ['confirmation_from']; + $settings['confirmation_subject'] = $vals ['confirmation_subject']; + $settings['unsubscribe_email_verification'] = $vals ['unsubscribe_email_verification']; + $settings['mailer_domain'] = $vals ['mailer_domain']; + $settings['email_id'] = $vals ['email_id']; + $settings['email_password'] = $vals ['email_password']; + $settings['email_port'] = $vals ['email_port']; + $settings['email_server'] = $vals ['email_server']; + + $r = file_overwrite ('inc/app/sitemailer2/conf/settings2.ini.php', ini_write ($settings)); + + if (! $r) { + echo '

Error: the settings file is not writable, exiting.

'; + exit; + } + + header ('Location: ' . site_prefix () . '/index/sitemailer2-app?msg=settings'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/settings/settings.php b/inc/app/sitemailer2/forms/settings/settings.php new file mode 100644 index 00000000..412eeada --- /dev/null +++ b/inc/app/sitemailer2/forms/settings/settings.php @@ -0,0 +1,98 @@ +[Form] + +error_mode = all + + + +[registration] + +type = select +alt = "Subscriber registration" +setValues = "eval: array ('none' => 'None', 'email' => 'Email-only', 'full' => 'Collect all data', 'req' => 'All data required')" +setDefault = email + +[verification] + +type = select +alt = "Subscribe email verification" +setValues = "eval: array ('yes' => 'Yes', 'no' => 'No')" +setDefault = yes + +[unsubscribe_email_verification] + +type = select +alt = "Unsubscribe email verification" +setValues = "eval: array ('yes' => 'Yes', 'no' => 'No')" +setDefault = yes + +[archive] + +type = select +alt = "Public archive of messages" +setValues = "eval: array ('yes' => 'Yes', 'no' => 'No')" +setDefault = yes + +[rss] + +type = select +alt = "RSS subscribers" +setValues = "eval: array ('yes' => 'Yes', 'no' => 'No')" +setDefault = yes + +[confirmation_email_domain] + +type = text +alt = Confirmation Email Address +rule 1 = "not empty, Please specify a confirmation email domain." + +[confirmation_from] +type = text +alt = The name to appear in a confirmation email +rule 1 = "not empty, Please specify a confirmation email name." + +[confirmation_subject] +type = text +alt = The subject line of a confirmation email +rule 1 = "not empty, Please specify a confirmation email subject." + +[mailer_domain] + +type = text +alt = The Domain SiteMailer2 Resides On + +[bounced] + +type = info +alt = Bounced Message Detection Settings + +[bounces] + +type = select +alt = "Disable subscriber after bounces" +setValues = "eval: array (0 => 'Disabled', 1, 2, 3, 4, 5)" +setDefault = 2 + +[email_id] + +type = text +alt = Email ID For Bounced Messages + +[email_password] +type = text +alt = Email Password For Bounced Messages + +[email_server] +type = text +alt = Server For Bounced Messages + +[email_port] +type = text +alt = Port For Server For Bounced Messages + + + +[submit_button] + +type = msubmit +button 1 = Save +button 2 = "Cancel, onclick=`window.location.href = 'sitemailer2-app'; return false`" diff --git a/inc/app/sitemailer2/forms/subscribe/access.php b/inc/app/sitemailer2/forms/subscribe/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/forms/subscribe/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/forms/subscribe/full/index.php b/inc/app/sitemailer2/forms/subscribe/full/index.php new file mode 100755 index 00000000..f148effd --- /dev/null +++ b/inc/app/sitemailer2/forms/subscribe/full/index.php @@ -0,0 +1,25 @@ +parseSettings ('inc/app/sitemailer2/forms/subscribe/full/settings.php'); + + $this->widgets['email']->setValue($cgi->email); + + } + + function onSubmit ($vals) { + + return loader_box ('sitemailer2/public/subscribe', $vals); + + } +} + +?> diff --git a/inc/app/sitemailer2/forms/subscribe/full/settings.php b/inc/app/sitemailer2/forms/subscribe/full/settings.php new file mode 100755 index 00000000..0a072f61 --- /dev/null +++ b/inc/app/sitemailer2/forms/subscribe/full/settings.php @@ -0,0 +1,55 @@ +; +copyright = "Copyright (C) 2004, Me Inc." +license = "http://www.opensource.org/licenses/index.php#PICK ONE!!!" +version = 0.1 + +[Required] + +alt = * Denotes a required field. +type = info +;setValue = "* Denotes a required field." + +[email] + +alt = Email Address* +type = text +rule 1= "not empty, You must enter an email address." + +[fname] + +alt = First Name +type = text + +[lname] + +alt = Last Name +type = text + +[organization] + +alt = Your Organization +type = text + +[website] + +alt = Website URL +type = text + +[newsletter] + +type = hidden + +[done] + +type = submit +setValues = Subscribe + +; your form definition goes here + +; */ ?> diff --git a/inc/app/sitemailer2/forms/subscribe/index.php b/inc/app/sitemailer2/forms/subscribe/index.php new file mode 100644 index 00000000..cb7d96fd --- /dev/null +++ b/inc/app/sitemailer2/forms/subscribe/index.php @@ -0,0 +1,127 @@ +addWidget ('text', 'email'); + $w->alt = intl_get ('Email Address'); + $w->addRule ('contains "@"', 'Your email address does not appear to be valid.'); + $w->addRule ('func "sitemailer_unique_check"', 'The email address specified is already a subscriber.'); + + if (appconf ('collect_info')) { + // gather firstname, lastname, organization, website + + $w =& $this->addWidget ('text', 'firstname'); + $w->alt = intl_get ('First Name'); + $w->addRule ('not empty', 'You must enter your first name.'); + + $w =& $this->addWidget ('text', 'lastname'); + $w->alt = intl_get ('Last Name'); + $w->addRule ('not empty', 'You must enter your last name.'); + + $w =& $this->addWidget ('text', 'organization'); + $w->alt = intl_get ('Organization'); + $w->addRule ('not empty', 'You must enter your organization name.'); + + $w =& $this->addWidget ('text', 'website'); + $w->alt = intl_get ('Web Site'); + $w->setDefault ('http://'); + $w->addRule ('not empty', 'You must enter your web site address.'); + $w->addRule ('not is "http://"', 'You must enter your web site address.'); + + } else { + $this->addWidget ('hidden', 'firstname'); + $this->addWidget ('hidden', 'lastname'); + $this->addWidget ('hidden', 'organization'); + $this->addWidget ('hidden', 'website'); + } + + $w =& $this->addWidget ('hidden', 'group'); + if (empty ($cgi->group)) { + $cgi->group = '1'; + $w->setValue ('1'); + } + + $w =& $this->addWidget ('submit', 'submit_button'); + $w->setValues (intl_get ('Subscribe')); + + } + + function onSubmit ($vals) { + if (sitemailer_subscriber_exists ($vals['email'])) { + // subscriber is being added to a second group + db_execute ('update sitemailer_subscriber set status = ? where email = ?', 'subscribed', $vals['email']); + db_execute ('insert into sitemailer_subscriber_category (id, subscriber, category) values (null, ?, ?)', $vals['email'], $vals['group']); + + // say thank you, johnny + page_title (intl_get ('Thank You!')); + echo template_simple ('responses/subscribed.spt'); + + } else { + // add user and subscribe them + $res = db_execute ( + 'insert into sitemailer_subscriber + (email, firstname, lastname, organization, website, registered, status) + values + (?, ?, ?, ?, ?, now(), ?)', + $vals['email'], + $vals['firstname'], + $vals['lastname'], + $vals['organization'], + $vals['website'], + 'unverified' // first timers need to verify their email address + ); + + $res = db_execute ( + 'insert into sitemailer_subscriber_category + (id, subscriber, category) + values + (null, ?, ?)', + $vals['email'], + $vals['group'] + ); + + // make validation key (md5 of email.registered) + $vals['key'] = sitemailer_make_verification_key ($vals['email']); + $vals['from_name'] = appconf ('from_name'); + $vals['from_email'] = appconf ('from_email'); + + // send email with validation link + mail ($vals['email'], intl_get ('Subscription Verification'), template_simple ('responses/email_confirmation.spt', $vals), 'From: ' . $vals['from_email']); + + // say 'check your email' + page_title (intl_get ('Thank You!')); + echo template_simple ('responses/checkyouremail.spt', $vals); + } + } +} + +function sitemailer_make_verification_key ($email) { + $reg = db_shift ('select registered from sitemailer_subscriber where email = ?', $email); + return md5 ($email . $reg); +} + +function sitemailer_subscriber_exists ($email) { + return db_shift ('select count(*) from sitemailer_subscriber where email = ?', $email); +} + +function sitemailer_unique_check ($vals) { + global $cgi; + + // check for uniqueness of email address in the specified group + $res = db_shift ('select count(*) from sitemailer_subscriber s, sitemailer_subscriber_category c where s.email = c.subscriber and s.email = ? and c.category = ? and s.status = ?', $cgi->email, $cgi->group, 'subscribed'); + if (! $res || $res === 0) { + return true; + } + return false; +} + +page_title (intl_get ('Subscribe')); +$form = new SubscribeForm (); +echo $form->run (); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/subscribe/req/index.php b/inc/app/sitemailer2/forms/subscribe/req/index.php new file mode 100755 index 00000000..690ac12c --- /dev/null +++ b/inc/app/sitemailer2/forms/subscribe/req/index.php @@ -0,0 +1,28 @@ +parseSettings ('inc/app/sitemailer2/forms/subscribe/req/settings.php'); + + $this->widgets['newsletter']->setValue ($cgi->nl); + + } + + function onSubmit ($vals) { + // your handler code goes here + + return loader_box ('sitemailer2/public/subscribe', $vals); + + } +} + +?> diff --git a/inc/app/sitemailer2/forms/subscribe/req/settings.php b/inc/app/sitemailer2/forms/subscribe/req/settings.php new file mode 100755 index 00000000..96d97373 --- /dev/null +++ b/inc/app/sitemailer2/forms/subscribe/req/settings.php @@ -0,0 +1,59 @@ +; +copyright = "Copyright (C) 2004, Me Inc." +license = "http://www.opensource.org/licenses/index.php#PICK ONE!!!" +version = 0.1 + +[Required] + +alt = * Denotes a required field. +type = info +;setValue = "* Denotes a required field." + +[email] + +alt = Email Address* +type = text +rule 1= "not empty, You must enter an email address." + +[fname] + +alt = First Name* +type = text +rule 1= "not empty, You must enter a first name." + +[lname] + +alt = Last Name* +type = text +rule 1= "not empty, You must enter a last name." + +[organization] + +alt = Your Organization* +type = text +rule 1= "not empty, You must enter your organization name." + +[website] + +alt = Website URL* +type = text +rule 1= "not empty, You must enter your website." + +[newsletter] + +type = hidden + +[done] + +type = submit +setValues = Subscribe + +; your form definition goes here + +; */ ?> diff --git a/inc/app/sitemailer2/forms/subscriber/add/index.php b/inc/app/sitemailer2/forms/subscriber/add/index.php new file mode 100644 index 00000000..18f57a6d --- /dev/null +++ b/inc/app/sitemailer2/forms/subscriber/add/index.php @@ -0,0 +1,46 @@ +parseSettings ('inc/app/sitemailer2/forms/subscriber/add/settings.php'); + page_title ('SiteMailer 2 - Add Subscriber'); + $this->widgets['submit_button']->buttons[1]->extra = 'onclick="window.location.href = \'' . site_prefix () . '/index/sitemailer2-subscribers-action\'; return false"'; + } + + function onSubmit ($vals) { + if ($vals['website'] == 'http://') { + $vals['website'] = ''; + } + + db_execute ( + 'insert into sitemailer2_recipient + (id, email, firstname, lastname, organization, website, created, status) + values + (null, ?, ?, ?, ?, ?, now(), "active")', + $vals['email'], + $vals['firstname'], + $vals['lastname'], + $vals['organization'], + $vals['website'] + ); + + $id = db_lastid (); + + foreach (explode (',', $vals['newsletters']) as $newsletter) { + db_execute ( + 'insert into sitemailer2_recipient_in_newsletter + (recipient, newsletter, status_change_time, status) + values + (?, ?, now(), "subscribed")', + $id, + $newsletter + ); + } + + header ('Location: ' . site_prefix () . '/index/sitemailer2-subscribers-action?_msg=subcreated'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/subscriber/add/settings.php b/inc/app/sitemailer2/forms/subscriber/add/settings.php new file mode 100644 index 00000000..6968b131 --- /dev/null +++ b/inc/app/sitemailer2/forms/subscriber/add/settings.php @@ -0,0 +1,45 @@ +[Form] + +error_mode = all + +[email] + +type = text +alt = Email Address +rule 1 = "not empty, You must enter an email address for your subscriber." +rule 2 = "contains '@', Your email address does not appear to be valid." +rule 3 = "unique 'sitemailer2_recipient.email', There is already an account for this email address." + +[firstname] + +type = text +alt = First Name + +[lastname] + +type = text +alt = Last Name + +[organization] + +type = text +alt = Organization + +[website] + +type = text +alt = Web Site +setDefault = "http://" + +[newsletters] + +type = multiple +size = 5 +alt = Newsletters +setValues = "eval: db_pairs ('select id, name from sitemailer2_newsletter order by name asc')" + +[submit_button] + +type = msubmit +button 1 = Create +button 2 = Cancel diff --git a/inc/app/sitemailer2/forms/subscriber/edit/index.php b/inc/app/sitemailer2/forms/subscriber/edit/index.php new file mode 100644 index 00000000..dca43207 --- /dev/null +++ b/inc/app/sitemailer2/forms/subscriber/edit/index.php @@ -0,0 +1,63 @@ +parseSettings ('inc/app/sitemailer2/forms/subscriber/edit/settings.php'); + page_title ('SiteMailer 2 - Edit Subscriber'); + $this->widgets['submit_button']->buttons[1]->extra = 'onclick="window.location.href = \'' . site_prefix () . '/index/sitemailer2-subscribers-action\'; return false"'; + + global $cgi; + + $res = db_single ('select * from sitemailer2_recipient where id = ?', $cgi->_key); + $this->widgets['email']->setValue ($res->email); + $this->widgets['firstname']->setValue ($res->firstname); + $this->widgets['lastname']->setValue ($res->lastname); + $this->widgets['organization']->setValue ($res->organization); + $this->widgets['website']->setValue ($res->website); + $this->widgets['status']->setValue ($res->status); + + $res = db_shift_array ('select newsletter from sitemailer2_recipient_in_newsletter where recipient = ?', $cgi->_key); + $this->widgets['newsletters']->setValue ($res); + } + + function onSubmit ($vals) { + if ($vals['website'] == 'http://') { + $vals['website'] = ''; + } + + db_execute ( + 'update sitemailer2_recipient + set email = ?, firstname = ?, lastname = ?, organization = ?, website = ?, status = ? + where id = ?', + $vals['email'], + $vals['firstname'], + $vals['lastname'], + $vals['organization'], + $vals['website'], + $vals['status'], + $vals['_key'] + ); + + $res = db_shift_array ('select newsletter from sitemailer2_recipient_in_newsletter where recipient = ?', $vals['_key']); + db_execute ('delete from sitemailer2_recipient_in_newsletter where recipient = ? and newsletter not in(' . $vals['newsletters'] . ')', $vals['_key']); + foreach (explode (',', $vals['newsletters']) as $newsletter) { + if (in_array ($newsletter, $res)) { + continue; + } + db_execute ( + 'insert into sitemailer2_recipient_in_newsletter + (recipient, newsletter, status_change_time, status) + values + (?, ?, now(), "subscribed")', + $vals['_key'], + $newsletter + ); + } + + header ('Location: ' . site_prefix () . '/index/sitemailer2-subscribers-action?_msg=subsaved'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/subscriber/edit/settings.php b/inc/app/sitemailer2/forms/subscriber/edit/settings.php new file mode 100644 index 00000000..de518f85 --- /dev/null +++ b/inc/app/sitemailer2/forms/subscriber/edit/settings.php @@ -0,0 +1,55 @@ +[Form] + +error_mode = all + +[_key] + +type = hidden + +[email] + +type = info +alt = Email Address +;rule 1 = "not empty, You must enter an email address for your subscriber." +;rule 2 = "contains '@', Your email address does not appear to be valid." +;rule 3 = "unique 'sitemailer2_recipient.email', There is already an account for this email address." + +[firstname] + +type = text +alt = First Name + +[lastname] + +type = text +alt = Last Name + +[organization] + +type = text +alt = Organization + +[website] + +type = text +alt = Web Site +setDefault = "http://" + +[status] + +type = select +alt = Status +setValues = "eval: array ('active' => 'Active', 'disabled' => 'Disabled', 'unverified' => 'Unverified')" + +[newsletters] + +type = multiple +size = 5 +alt = Newsletters +setValues = "eval: db_pairs ('select id, name from sitemailer2_newsletter order by name asc')" + +[submit_button] + +type = msubmit +button 1 = Save +button 2 = Cancel diff --git a/inc/app/sitemailer2/forms/template/index.php b/inc/app/sitemailer2/forms/template/index.php new file mode 100644 index 00000000..8a6bbb0c --- /dev/null +++ b/inc/app/sitemailer2/forms/template/index.php @@ -0,0 +1,73 @@ +_key) && ! empty ($cgi->_key)) { + $add = false; + } + + $this->parseSettings ('inc/app/sitemailer2/forms/template/settings.php'); + + if (! $add) { + $rex = new Rex ('sitemailer2_template'); + $document = $rex->getCurrent ($cgi->_key); + page_title ('SiteMailer 2 - ' . intl_get ('Edit Template')); + + } else { + list ($set, $tpl) = explode ('/', $cgi->path); + list ($mode, $name, $ext) = preg_split ('|\.|', basename ($cgi->path)); + page_title ('SiteMailer 2 - ' . intl_get ('New Template')); + } + + + $this->widgets['top']->data = array ('title' => $document->title, + //'subject' => $document->subject, + 'body' => $document->body, + ); + + //needs {} selector + } + + function onSubmit ($vals) { + + page_onload (false); + page_onclick (false); + page_onfocus (false); + + loader_import ('cms.Versioning.Rex'); + + global $cgi; + + $rex = new Rex ('sitemailer2_template'); + + $data = array ( 'title' => $cgi->title, + //'subject' => $cgi->subject, + 'body' => $cgi->body, + 'date' => date ('Y-m-d H:i:s'), + ); + + + if (isset ($cgi->_key) && ! empty ($cgi->_key)) { + $rex->modify ($cgi->_key, $data, 'Updated via template collection...'); + header ('Location: ' . site_prefix () . '/index/sitemailer2-templates-action?msg=tplsaved'); + } else { + $rex->create ($data); + header ('Location: ' . site_prefix () . '/index/sitemailer2-templates-action?msg=tplcreated'); + } + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/template/settings.php b/inc/app/sitemailer2/forms/template/settings.php new file mode 100644 index 00000000..602465fd --- /dev/null +++ b/inc/app/sitemailer2/forms/template/settings.php @@ -0,0 +1,40 @@ +; +copyright = "Copyright (C) 2004, Me Inc." +license = "http://www.opensource.org/licenses/index.php#PICK ONE!!!" +version = 0.1 + +; your form definition goes here + +extra = "id='sitemailer2-editor'" +error_mode = all + +[collection] + +type = hidden + +[_collection] + +type = hidden + +[_key] + +type = hidden + +[_return] + +type = hidden + +[top] + +type = template +template = tpl_top.spt +submitButtons = submit_button + + +; */ ?> diff --git a/inc/app/sitemailer2/forms/unsubscribe/access.php b/inc/app/sitemailer2/forms/unsubscribe/access.php new file mode 100644 index 00000000..d793a6d1 --- /dev/null +++ b/inc/app/sitemailer2/forms/unsubscribe/access.php @@ -0,0 +1,3 @@ +sitellite_access = public +sitellite_status = approved +sitellite_action = on diff --git a/inc/app/sitemailer2/forms/unsubscribe/index.php b/inc/app/sitemailer2/forms/unsubscribe/index.php new file mode 100644 index 00000000..870f4df5 --- /dev/null +++ b/inc/app/sitemailer2/forms/unsubscribe/index.php @@ -0,0 +1,24 @@ +parseSettings ('inc/app/sitemailer2/forms/unsubscribe/settings.php'); + + $this->widgets['newsletter']->setValue ($cgi->nl); + + } + + function onSubmit ($vals) { + // your handler code goes here + + return loader_box ('sitemailer2/public/unsubscribe', $vals); + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/unsubscribe/settings.php b/inc/app/sitemailer2/forms/unsubscribe/settings.php new file mode 100644 index 00000000..0bd57b4d --- /dev/null +++ b/inc/app/sitemailer2/forms/unsubscribe/settings.php @@ -0,0 +1,28 @@ +; +copyright = "Copyright (C) 2004, Me Inc." +license = "http://www.opensource.org/licenses/index.php#PICK ONE!!!" +version = 0.1 + +[email] + +alt = Email Address +type = text +rule 1= "not empty, You must enter an email address." + +[newsletter] + +type = hidden +rule 1 = "not empty, A form error occurred, click back to start over." + +[done] + +type = submit +setValues = Unsubscribe + +; */ ?> diff --git a/inc/app/sitemailer2/forms/verifyvcf/index.php b/inc/app/sitemailer2/forms/verifyvcf/index.php new file mode 100644 index 00000000..753955e6 --- /dev/null +++ b/inc/app/sitemailer2/forms/verifyvcf/index.php @@ -0,0 +1,72 @@ +parseSettings ('inc/app/sitemailer2/forms/verifyvcf/settings.php'); + + $res = db_fetch ('select * from sitemailer2_newsletter'); + if (! $res) { + $res = array (); + } elseif (is_object ($res)) { + $res = array ($res); + } + + global $cgi; + + // info ($cgi); + + // info ($cgi->group, true); + $this->widgets['group']->setValue ($cgi->group); + $this->widgets['firstname']->setValue ($cgi->firstname); + $this->widgets['lastname']->setValue ($cgi->lastname); + $this->widgets['organization']->setValue ($cgi->organization); + if (strstr ($cgi->website, 'http://')) { + $this->widgets['website']->setValue ($cgi->website); + } else { + $this->widgets['website']->setValue ('http://' . $cgi->website); + } + $this->widgets['email']->setValue ($cgi->email); + } + + function onSubmit ($vals) { + + db_execute ( + 'insert into sitemailer2_recipient + (id, email, firstname, lastname, organization, website, created) + values + (null, ?, ?, ?, ?, ?, now())', + $vals['email'], + $vals['firstname'], + $vals['lastname'], + $vals['organization'], + $vals['website'] + ); + + $lastid = db_lastid (); + $vals['group'] = explode (',', $vals['group']); + + foreach ($vals['group'] as $group) { + db_execute ( + 'insert into sitemailer2_recipient_in_newsletter + (recipient, newsletter, status, status_change_time) + values + (?, ?, "subscribed", now())', + $lastid, + $group + ); + } + + //header ('Location: ' . site_prefix () . '/index/sitemailer2-subscribers-action?_msg=subcreated'); + //exit; + page_title ('SiteMailer 2 - Importer'); + echo '

Subscriber successfully imported.

'; + echo '

Return to subscriber list

'; + } +} + +page_title ('SiteMailer 2 - ' . intl_get ('Importer')); +$form = new VerifyvcfForm (); +echo $form->run (); + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/forms/verifyvcf/settings.php b/inc/app/sitemailer2/forms/verifyvcf/settings.php new file mode 100644 index 00000000..e92ee4ab --- /dev/null +++ b/inc/app/sitemailer2/forms/verifyvcf/settings.php @@ -0,0 +1,42 @@ +[Form] + +action = sitemailer2-verifyvcf-form +message = Please verify the import data. +method = post + +[email] + +type = text +rule 1 = "not empty, You must enter an email address for your subscriber." +rule 2 = "contains '@', Your email address does not appear to be valid." +rule 3 = "unique 'sitemailer2_recipient.email', There is already an account for this email address." + +[firstname] + +type = text +alt = First Name + +[lastname] + +type = text +alt = Last Name + +[organization] + +type = text + +[website] + +type = text +alt = Web Site +default_value = "http://" + +[group] + +type = hidden + +[submit] + +type = msubmit +button 1 = "Import" +button 2 = "Cancel, onclick=`window.location.href = 'sitemailer-app'; return false`" diff --git a/inc/app/sitemailer2/html/archive.spt b/inc/app/sitemailer2/html/archive.spt new file mode 100644 index 00000000..1d98cda4 --- /dev/null +++ b/inc/app/sitemailer2/html/archive.spt @@ -0,0 +1,63 @@ +{filter none} +{CMS_JS_DELETE_CONFIRM} +{CMS_JS_SELECT_ALL} +{end filter} + +{alt even odd} + + + + + + + +
+ +

+ {intl Newsletters} / {intl Archive} +

+ +

+ {filter none}{facets}{end filter} +

+ +

+ + + + + +
{spt PAGER_TEMPLATE_FROM_TO}{if pager.total}{spt PAGER_TEMPLATE_PREV_PAGE_LIST_NEXT}{end if}
+ + + + + + + + + + + {loop obj[list]} + + + + + + + + + {end loop} +
{intl Subject}{intl Date}{intl Status}{intl Sent}{intl Viewed}{intl Bounced}
+ {loop/subject} + {filter sitemailer2_filter_last_sent}{loop/date}{end filter}{filter ucfirst}{loop/status}{end filter}{loop/numsent}{loop/confirmed_views}{loop/bounced}
+

diff --git a/inc/app/sitemailer2/html/campaign.spt b/inc/app/sitemailer2/html/campaign.spt new file mode 100644 index 00000000..f74f37f7 --- /dev/null +++ b/inc/app/sitemailer2/html/campaign.spt @@ -0,0 +1,55 @@ +{filter none} +{CMS_JS_DELETE_CONFIRM} +{CMS_JS_SELECT_ALL} +{end filter} + +{alt even odd} + + + + + + + +
+ +

{intl Add Campaign}

+ +{-- spt facets.spt --} + +
+ + + + + + + + + {loop obj[list]} + + + + + + + + {end loop} +
+   + + {intl Campaign}{intl Address}{intl Clicks}{intl Created}
+ + + {loop/title} + {loop/forward_url}{loop/clicks}{filter sitemailer2_filter_date}{loop/created}{end filter}
+
diff --git a/inc/app/sitemailer2/html/campstats.spt b/inc/app/sitemailer2/html/campstats.spt new file mode 100644 index 00000000..e7178af2 --- /dev/null +++ b/inc/app/sitemailer2/html/campstats.spt @@ -0,0 +1,41 @@ +{alt even odd} + + + + + + +
+{intl Back}       {intl Visit}
+ +
+ + + + + + + + + + + {loop obj[list]} + + + + + + + + + {end loop} +
{intl Message}{intl Newsletter}{intl Date}{intl Impressions}{intl Clicks}%
{loop/subject}{loop/newsletter}{filter sitemailer2_filter_date}{loop/date}{end filter}{loop/impressions}{loop/clicks}{loop/percent}
diff --git a/inc/app/sitemailer2/html/delete.spt b/inc/app/sitemailer2/html/delete.spt new file mode 100644 index 00000000..83108eb0 --- /dev/null +++ b/inc/app/sitemailer2/html/delete.spt @@ -0,0 +1,9 @@ +

{intl Are you sure you want to delete} {file}?

+ +    {intl No} +    {intl Yes} + +{if obj[err]} +

{err}

+{end if} + diff --git a/inc/app/sitemailer2/html/drafts.spt b/inc/app/sitemailer2/html/drafts.spt new file mode 100644 index 00000000..f67d3812 --- /dev/null +++ b/inc/app/sitemailer2/html/drafts.spt @@ -0,0 +1,55 @@ +{filter none} +{CMS_JS_DELETE_CONFIRM} +{CMS_JS_SELECT_ALL} +{end filter} + +{alt even odd} + + + + + + + +
+ +

+ {intl Compose Message} +

+ +
+ + + + + + + + + + {loop obj[list]} + + + + + + + {end loop} +
+   + + {intl Subject}{intl Newsletter}{intl Date}
+ + + {loop/subject} + {loop/newsletter}{filter sitemailer2_filter_last_sent}{loop/date}{end filter}
+
\ No newline at end of file diff --git a/inc/app/sitemailer2/html/facets.spt b/inc/app/sitemailer2/html/facets.spt new file mode 100644 index 00000000..c6e355b4 --- /dev/null +++ b/inc/app/sitemailer2/html/facets.spt @@ -0,0 +1,42 @@ + + + + + + + + + {loop obj[facets]} + + {loop loop} + + {end loop} + + {end loop} + + {if count (obj[selected]) gt 0} + + + + + {loop obj[selected]} + + {loop loop} + + {end loop} + + {end loop} + + {end if} +
+

{intl Search Parameters}

+
+ {if obj[bookmark]}{box cms/bookmarks/button}{end if} + {if not obj[bookmark]} {end if} +
+ {filter none}{loop/_value}{end filter} +
+ {intl You have chosen}: +
+ {filter none}{loop/_value}{end filter} +
diff --git a/inc/app/sitemailer2/html/group.spt b/inc/app/sitemailer2/html/group.spt new file mode 100644 index 00000000..d3b9ad2a --- /dev/null +++ b/inc/app/sitemailer2/html/group.spt @@ -0,0 +1,13 @@ +

+ {intl Back}     + {intl Send Message}     + {intl Add Subscriber}     + {intl Import vCard}     +

+ +{form sitemailer/group/edit} + + diff --git a/inc/app/sitemailer2/html/js.spt b/inc/app/sitemailer2/html/js.spt new file mode 100644 index 00000000..3c568b84 --- /dev/null +++ b/inc/app/sitemailer2/html/js.spt @@ -0,0 +1,66 @@ + +var templatechooser_form = false; +var templatechooser_element = false; +var templatechooser_attrs = false; +dialogWin.scrollbars = 'yes'; +dialogWin.resizable = 'yes'; + +function templatechooser () { + openDGDialog ( + '{site/prefix}/index/templatechooser-app?attrs=' + templatechooser_attrs, + 400, + 300, + templatechooser_handler + ); +} + +function templatechooser_get_file (f, e) { + templatechooser_form = f; + templatechooser_element = e; + templatechooser (); + return false; +} + +function templatechooser_view (file) { + if (! file) { + return false; + } + + win = window.open ( + file, + 'TemplateChooser', + 'top=50,left=50' + ); + return false; +} + +function templatechooser_select (f) { // alt and flt are optional parameters + if (arguments.length > 1) { + alt = arguments[1]; + flt = arguments[2]; + h = arguments[3]; + w = arguments[4]; + } else { + alt = false; + h = false; + } + if (opener && ! opener.closed) { + if (h != false) { + opener.dialogWin.returnedValue = new Array (); + opener.dialogWin.returnedValue['src'] = f; + opener.dialogWin.returnedValue['alt'] = alt; + opener.dialogWin.returnedValue['float'] = flt; + opener.dialogWin.returnedValue['height'] = h; + opener.dialogWin.returnedValue['width'] = w; + } else { + opener.dialogWin.returnedValue = f; + } + opener.dialogWin.returnFunc (); + } else { + alert ('Hey, where did my parent go?'); + } + window.close (); + if (h != false) { + return false; + } +} diff --git a/inc/app/sitemailer2/html/message_preview.spt b/inc/app/sitemailer2/html/message_preview.spt new file mode 100644 index 00000000..c9897b39 --- /dev/null +++ b/inc/app/sitemailer2/html/message_preview.spt @@ -0,0 +1,26 @@ +

{intl Close Preview Window}

+ + + + + + + + + + + + + + + + + + + + +
{intl Subject}{subject}
{intl From}{from}
{intl Send to Groups} + {loop obj[groups]} + {loop/name}
+ {end loop} +
{intl Message Body}
{filter none}{body}{end filter}
diff --git a/inc/app/sitemailer2/html/message_view.spt b/inc/app/sitemailer2/html/message_view.spt new file mode 100644 index 00000000..2e95eb37 --- /dev/null +++ b/inc/app/sitemailer2/html/message_view.spt @@ -0,0 +1,30 @@ +

{intl Back}

+ + + + + + + + + + + + + + + + + + + + + + + + +
{intl Subject}{subject}
{intl From}{from}
{intl Sent on}{filter sitemailer_date}{date}{end filter}
{intl Send to Groups} + {loop obj.groups} + {loop/name}
+ {end loop} +
{intl Message Body}
{filter none}{body}{end filter}
diff --git a/inc/app/sitemailer2/html/messages.spt b/inc/app/sitemailer2/html/messages.spt new file mode 100644 index 00000000..d91294e7 --- /dev/null +++ b/inc/app/sitemailer2/html/messages.spt @@ -0,0 +1,42 @@ +{alt #fff #eee} + +

+ {intl Back}     + {intl Send Message} +

+ +

+{if count (pager.results) gt 0} + + + + + +
{spt PAGER_TEMPLATE_FROM_TO}{spt PAGER_TEMPLATE_PREV_PAGE_LIST_NEXT}
+{end if} +{if count (pager.results) eq 0} + {intl No messages}. +{end if} +

+ +

+ + + {loop obj[headers]} + + {end loop} + + {loop pager.results} + + + + + {end loop} +
{php intl_get (loop.fullname)} + {if loop.isCurrent ()} + {cgi/sort} + {end if} +
{loop/subject}{filter sitemailer_date}{loop/date}{end filter}
+

+ +
diff --git a/inc/app/sitemailer2/html/newimage.spt b/inc/app/sitemailer2/html/newimage.spt new file mode 100644 index 00000000..a89e875f --- /dev/null +++ b/inc/app/sitemailer2/html/newimage.spt @@ -0,0 +1,27 @@ +

+ {intl Back} +

+ +{if obj[err]} +

{err}

+{end if} + +
+ + + + + + + + + + + + + +
{intl Find the file}
{intl Save as}
({intl leave blank for current name})
 
+ + + +
\ No newline at end of file diff --git a/inc/app/sitemailer2/html/newsletters.spt b/inc/app/sitemailer2/html/newsletters.spt new file mode 100644 index 00000000..52d25861 --- /dev/null +++ b/inc/app/sitemailer2/html/newsletters.spt @@ -0,0 +1,86 @@ +{filter none} +{CMS_JS_DELETE_CONFIRM} +{CMS_JS_SELECT_ALL} +{end filter} + +{alt even odd} + + + + + + + +
+ +

{intl Add Newsletter}

+ +{-- spt facets.spt --} + +
+ + + + + + + + + {loop obj[list]} + + + + + + + + {end loop} + + + + + + + +
+   + +  {intl Newsletter}{intl Last Sent}{intl Subscribers}
+ + + {intl Compose Message} +  {intl Subscribers} +  {intl Sent Messages} +  {intl Edit} + + {loop/name} + {filter sitemailer2_filter_last_sent}{loop/last_sent}{end filter}{loop/subscribers}
  {intl Total Subscribers} {total}
+
+ + + \ No newline at end of file diff --git a/inc/app/sitemailer2/html/newtpl.spt b/inc/app/sitemailer2/html/newtpl.spt new file mode 100644 index 00000000..0d9355f8 --- /dev/null +++ b/inc/app/sitemailer2/html/newtpl.spt @@ -0,0 +1,20 @@ +

+ {intl Back} +

+ +{if obj[err]} +

{err}

+{end if} + +
+ + + + + + + + + +
{intl Choose a template set name}
 
+
diff --git a/inc/app/sitemailer2/html/preview_template.spt b/inc/app/sitemailer2/html/preview_template.spt new file mode 100644 index 00000000..1570aad5 --- /dev/null +++ b/inc/app/sitemailer2/html/preview_template.spt @@ -0,0 +1,32 @@ + + +

{intl Close Preview Window}

+ +
+ +{filter none}{body}{end filter} + +
diff --git a/inc/app/sitemailer2/html/public.spt b/inc/app/sitemailer2/html/public.spt new file mode 100644 index 00000000..5724222c --- /dev/null +++ b/inc/app/sitemailer2/html/public.spt @@ -0,0 +1,13 @@ +{loop obj} +
+

{loop/name}

+
+ + +
+
+{end loop} diff --git a/inc/app/sitemailer2/html/public_archive.spt b/inc/app/sitemailer2/html/public_archive.spt new file mode 100644 index 00000000..ff70f816 --- /dev/null +++ b/inc/app/sitemailer2/html/public_archive.spt @@ -0,0 +1,5 @@ + diff --git a/inc/app/sitemailer2/html/public_checkboxes.spt b/inc/app/sitemailer2/html/public_checkboxes.spt new file mode 100755 index 00000000..0946a7bc --- /dev/null +++ b/inc/app/sitemailer2/html/public_checkboxes.spt @@ -0,0 +1,18 @@ +
+ +{if obj[updated]} +

{intl Your subscription preferences have been saved!}

+{end if} +{if else} +

{intl Select which newsletters you would like to receive}:

+{end if} + +

+{loop obj[lists]} + {loop/name} – {intl Archive}{intl RSS}
+{end loop} +

+ +

+ +
\ No newline at end of file diff --git a/inc/app/sitemailer2/html/public_rss.spt b/inc/app/sitemailer2/html/public_rss.spt new file mode 100644 index 00000000..b428c33c --- /dev/null +++ b/inc/app/sitemailer2/html/public_rss.spt @@ -0,0 +1,43 @@ + + + + + + + {name} + {site/url}/index/sitemailer2-public-action + + {if intl_locale ()}{intl/locale}-{end if}{intl/language} + {date} + + hourly + 1 + 1970-01-01T00:00+00:00 + + + + + +{loop obj[items]} + +{end loop} + + + + + +{loop obj[items]} + + {loop/title} + {site/url}/index/sitemailer2-public-message-action/id.{loop/id} + {loop/date} + + +{end loop} + diff --git a/inc/app/sitemailer2/html/publicemail.spt b/inc/app/sitemailer2/html/publicemail.spt new file mode 100755 index 00000000..53b0b40c --- /dev/null +++ b/inc/app/sitemailer2/html/publicemail.spt @@ -0,0 +1,26 @@ +{loop obj} +
+

{loop/name}

+ + +
+{end loop} diff --git a/inc/app/sitemailer2/html/publicfull.spt b/inc/app/sitemailer2/html/publicfull.spt new file mode 100755 index 00000000..a5ab16f1 --- /dev/null +++ b/inc/app/sitemailer2/html/publicfull.spt @@ -0,0 +1,14 @@ +{loop obj} + +{end loop} diff --git a/inc/app/sitemailer2/html/publicnone.spt b/inc/app/sitemailer2/html/publicnone.spt new file mode 100755 index 00000000..5724222c --- /dev/null +++ b/inc/app/sitemailer2/html/publicnone.spt @@ -0,0 +1,13 @@ +{loop obj} +
+

{loop/name}

+
+ + +
+
+{end loop} diff --git a/inc/app/sitemailer2/html/publicreq.spt b/inc/app/sitemailer2/html/publicreq.spt new file mode 100755 index 00000000..50f916fb --- /dev/null +++ b/inc/app/sitemailer2/html/publicreq.spt @@ -0,0 +1,14 @@ +{loop obj} + +{end loop} diff --git a/inc/app/sitemailer2/html/responses/checkyouremail.spt b/inc/app/sitemailer2/html/responses/checkyouremail.spt new file mode 100644 index 00000000..e5bc8cbf --- /dev/null +++ b/inc/app/sitemailer2/html/responses/checkyouremail.spt @@ -0,0 +1 @@ +

{intl An email has been sent to the specified email address containing information you need in order to verify your account information.}

diff --git a/inc/app/sitemailer2/html/responses/checkyouremail_unsubscribe.spt b/inc/app/sitemailer2/html/responses/checkyouremail_unsubscribe.spt new file mode 100644 index 00000000..6893ced4 --- /dev/null +++ b/inc/app/sitemailer2/html/responses/checkyouremail_unsubscribe.spt @@ -0,0 +1 @@ +

{intl An email has been sent to the specified email address containing information you need in order to verify your unsubscription request.}

diff --git a/inc/app/sitemailer2/html/responses/email_confirmation.spt b/inc/app/sitemailer2/html/responses/email_confirmation.spt new file mode 100644 index 00000000..f5dcf39e --- /dev/null +++ b/inc/app/sitemailer2/html/responses/email_confirmation.spt @@ -0,0 +1,22 @@ +

{intl Hello} {firstname} {lastname},

+ +

{intl This email has been sent so that you may confirm your subscription request.}

+ +

{intl Subscription Info}:

+ +

{intl Name}: {firstname} {lastname}
+{intl Email}: {email}
+{intl Organization}: {organization}
+{intl Web Site}: {website}

+ +

{intl To confirm your email address and activate your subscription, either click on the following link, or paste it into your web browser.}

+ +

{site/url}/index/sitemailer2-public-subscribe-verify-action?email={email}&nl={nl}&key={key}

+ +

{intl Thank you}

+ +

--

+ +

{from_name} +{from_email} +{site/url}

diff --git a/inc/app/sitemailer2/html/responses/email_confirmation_unsubscribe.spt b/inc/app/sitemailer2/html/responses/email_confirmation_unsubscribe.spt new file mode 100644 index 00000000..075405c3 --- /dev/null +++ b/inc/app/sitemailer2/html/responses/email_confirmation_unsubscribe.spt @@ -0,0 +1,22 @@ +

{intl Hello} {firstname} {lastname},

+ +

{intl This email has been sent so that you may confirm your subscription cancellation request.}

+ +

{intl Subscription Info}:

+ +

{intl Name}: {firstname} {lastname}
+{intl Email}: {email}
+{intl Organization}: {organization}
+{intl Web Site}: {website}

+ +

{intl To confirm your email address and cancel your subscription, either click on the following link, or paste it into your web browser.}

+ +

{site/url}/index/sitemailer2-public-unsubscribe-verify-action?email={email}&nl={nl}&key={key}

+ +

{intl Thank you},

+ +

--

+ +

{from_name} +{from_email} +{site/url}

diff --git a/inc/app/sitemailer2/html/responses/email_unsub_confirmation.spt b/inc/app/sitemailer2/html/responses/email_unsub_confirmation.spt new file mode 100755 index 00000000..0c12e19b --- /dev/null +++ b/inc/app/sitemailer2/html/responses/email_unsub_confirmation.spt @@ -0,0 +1,22 @@ +

{intl Hello} {firstname} {lastname},

+ +

{intl This email has been sent so that you may confirm your subscription cancellation request.}

+ +

{intl Subscription Info}:

+ +

{intl Name}: {firstname} {lastname}
+{intl Email}: {email}
+{intl Organization}: {organization}
+{intl Web Site}: {website}

+ +

{intl To confirm your email address and cancel your subscription, either click on the following link, or paste it into your web browser.}

+ +

{site/url}/index/sitemailer2-public-unsubscribe-verify-action?email={email}&nl={nl}&key={key}

+ +

{intl Thank you}

+ +

--

+ +

{from_name} +{from_email} +{site/url}

diff --git a/inc/app/sitemailer2/html/responses/subscribed.spt b/inc/app/sitemailer2/html/responses/subscribed.spt new file mode 100644 index 00000000..91e30fd8 --- /dev/null +++ b/inc/app/sitemailer2/html/responses/subscribed.spt @@ -0,0 +1,3 @@ +

{intl Your subscription has been completed.}

+ +

{intl Continue browsing.}

diff --git a/inc/app/sitemailer2/html/responses/verified_subscribed.spt b/inc/app/sitemailer2/html/responses/verified_subscribed.spt new file mode 100644 index 00000000..478ad79d --- /dev/null +++ b/inc/app/sitemailer2/html/responses/verified_subscribed.spt @@ -0,0 +1,3 @@ +

{intl Your subscription has been activated.}

+ +

{intl Continue browsing.}

\ No newline at end of file diff --git a/inc/app/sitemailer2/html/responses/verified_unsubscribed.spt b/inc/app/sitemailer2/html/responses/verified_unsubscribed.spt new file mode 100644 index 00000000..9a74a6a2 --- /dev/null +++ b/inc/app/sitemailer2/html/responses/verified_unsubscribed.spt @@ -0,0 +1,3 @@ +

{intl You have been unsubscribed.}

+ +

{intl Continue browsing.}

\ No newline at end of file diff --git a/inc/app/sitemailer2/html/settings.spt b/inc/app/sitemailer2/html/settings.spt new file mode 100644 index 00000000..3c459589 --- /dev/null +++ b/inc/app/sitemailer2/html/settings.spt @@ -0,0 +1,15 @@ + + + + + +
diff --git a/inc/app/sitemailer2/html/stats.spt b/inc/app/sitemailer2/html/stats.spt new file mode 100644 index 00000000..00df0956 --- /dev/null +++ b/inc/app/sitemailer2/html/stats.spt @@ -0,0 +1,38 @@ +{filter none} +{CMS_JS_DELETE_CONFIRM} +{CMS_JS_SELECT_ALL} +{end filter} + +{alt even odd} + + + + + + + +
+ +

{intl Subscribers}

+ + + + + + + {loop obj[subscribers]} + + + + + {end loop} +
{intl Status}{intl Subscribers}
{filter ucfirst}{loop/_key}{end filter}{loop/_value}
diff --git a/inc/app/sitemailer2/html/subscriber.spt b/inc/app/sitemailer2/html/subscriber.spt new file mode 100644 index 00000000..7f6c7c79 --- /dev/null +++ b/inc/app/sitemailer2/html/subscriber.spt @@ -0,0 +1,55 @@ +{alt #fff #eee} + +

+ {intl Back}     + {intl Send Message}     + {intl Add Subscriber}     + {intl Import vCard}     +

+ +

+{if count (pager.results) gt 0} + + + + + +
{spt PAGER_TEMPLATE_FROM_TO}{spt PAGER_TEMPLATE_PREV_PAGE_LIST_NEXT}
+{end if} +{if count (pager.results) eq 0} + {intl No subscribers}. +{end if} +

+ +

+ + + {loop obj[headers]} + + {end loop} + + {loop pager.results} + + + + + + + + {end loop} +
{php intl_get (loop.fullname)} + {if loop.isCurrent ()} + {cgi/sort} + {end if} +
{loop/email}{loop/firstname} {loop/lastname} + {if not empty (loop.website)}{loop/organization}{end if} + {if empty (loop.website)}{loop/organization}{end if} + {filter sitemailer_date}{loop/registered}{end filter}{loop/status}
+

+ +
+ + +

{intl Add Subscriber}

+ +{form sitemailer/subscriber/add} diff --git a/inc/app/sitemailer2/html/subscribers.spt b/inc/app/sitemailer2/html/subscribers.spt new file mode 100644 index 00000000..dbc72a68 --- /dev/null +++ b/inc/app/sitemailer2/html/subscribers.spt @@ -0,0 +1,85 @@ +{filter none} +{CMS_JS_DELETE_CONFIRM} +{CMS_JS_SELECT_ALL} +{end filter} + +{alt even odd} + + + + + + + +
+ +

+ {intl Add Subscriber} +       {intl Import Subscribers}      {intl Mass Unsubscribe} +

+ + +

+{filter none}{facets}{end filter} +

+ + + + + + +
{spt PAGER_TEMPLATE_FROM_TO}{if pager.total}{spt PAGER_TEMPLATE_PREV_PAGE_LIST_NEXT}{end if}
+ +
+ + + + {if obj[is_versioned]} + + {end if} + {loop obj[headers]} + + {end loop} + + {loop pager.results} + + + {loop loop._properties} + {if strpos (loop._key, '_') !== 0} + {if loop._key eq obj[title_field]} + {if locks[ parent._key ] or not editable[ parent._key ]} + + {end if} + {if not locks[ parent._key ] and editable[ parent._key ]} + + {end if} + {end if} + {if loop._key ne obj[title_field]} + + {end if} + {end if} + {end loop} + + {end loop} +
+   + + +   + {php intl_get (loop.fullname)} + {if loop.isCurrent ()} + {cgi/sort} + {end if} +
+ + {filter none}{loop/_value}{end filter}{filter none}{loop/_value}{end filter}{filter none}{loop/_value}{end filter}
+
diff --git a/inc/app/sitemailer2/html/t.html b/inc/app/sitemailer2/html/t.html new file mode 100644 index 00000000..738546e6 --- /dev/null +++ b/inc/app/sitemailer2/html/t.html @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + +
asdfasdfasdf
asdfasdf
asdfasdf
asdfasdf
\ No newline at end of file diff --git a/inc/app/sitemailer2/html/tabs.spt b/inc/app/sitemailer2/html/tabs.spt new file mode 100644 index 00000000..964d3156 --- /dev/null +++ b/inc/app/sitemailer2/html/tabs.spt @@ -0,0 +1,42 @@ + + + + + +
+{intl Back}    {intl View}
+ + + + + + + + + + {loop obj[list]} + + + + + + + + {end loop} +
+   + + {intl Campaign}{intl Address}{intl Clicks}{intl Created}
+ + + {loop/title} + {loop/forward_url}{loop/clicks}{filter sitemailer2_filter_date}{loop/created}{end filter}
diff --git a/inc/app/sitemailer2/html/templates.spt b/inc/app/sitemailer2/html/templates.spt new file mode 100644 index 00000000..81b03ae0 --- /dev/null +++ b/inc/app/sitemailer2/html/templates.spt @@ -0,0 +1,51 @@ +{filter none} +{CMS_JS_DELETE_CONFIRM} +{CMS_JS_SELECT_ALL} +{end filter} + +{alt even odd} + + + + + + + +
+ +

{intl Add Template}

+ +{-- spt facets.spt --} + +
+ + + + + + + {loop obj[list]} + + + + + + {end loop} +
+   + + {intl Template}{intl Last Modified}
+ + + {loop/title} + {filter sitemailer2_filter_last_sent}{loop/date}{end filter}
+
diff --git a/inc/app/sitemailer2/html/templates/default.spt b/inc/app/sitemailer2/html/templates/default.spt new file mode 100644 index 00000000..6afb5d27 --- /dev/null +++ b/inc/app/sitemailer2/html/templates/default.spt @@ -0,0 +1,11 @@ +

+ YourWebSite.com +

+ +{-- message body goes here -- do NOT change this line --} +{filter none}{body}{end filter} +{-- end message body --} + +
+ +

Copyright © {php date ('Y')}, Your Company Inc.

diff --git a/inc/app/sitemailer2/html/templateselect.spt b/inc/app/sitemailer2/html/templateselect.spt new file mode 100644 index 00000000..8853eeec --- /dev/null +++ b/inc/app/sitemailer2/html/templateselect.spt @@ -0,0 +1,112 @@ + + + + +

{intl Template Set}: {name}

+ +

+ {intl Back}     + {intl New Template}     + {intl New Stylesheet}     + {intl New Image}     + {intl Edit Properties}     +

+ +

{intl Templates}

+ +{alt even odd} + +{loop obj[templates]} +

{filter strtoupper}{loop/_key}{end filter}

+ {alt/reset} + + {loop loop} + + + + + {end loop} +
+ {if loop[file] eq 'html.default.tpl'} +   + {end if} + {if else} + {intl Delete} + {end if} + + {filter ucfirst}{loop/name}{end filter} +
+{end loop} + +

{intl Styles}

+ +{alt/reset} + + + {loop obj[styles]} + + + + + {end loop} +
+ {if loop[file] eq 'site.css'} +   + {end if} + {if else} + {intl Delete} + {end if} + + {filter ucfirst}{loop/name}{end filter} +
+ +

{intl Images}

+ +{alt/reset} + + + {loop obj[images]} + + + + + {end loop} +
+ {intl Delete} + + {filter ucfirst}{loop/file}{end filter} +
diff --git a/inc/app/sitemailer2/html/tpl_bottom.spt b/inc/app/sitemailer2/html/tpl_bottom.spt new file mode 100644 index 00000000..6cb8f893 --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_bottom.spt @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/inc/app/sitemailer2/html/tpl_cssfeatures.spt b/inc/app/sitemailer2/html/tpl_cssfeatures.spt new file mode 100644 index 00000000..263dda7e --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_cssfeatures.spt @@ -0,0 +1,39 @@ + + + + + {intl Stylesheet} + + + {name} + + + + + + + + + + +
+   + +   + + {intl Help} +   +
+ + \ No newline at end of file diff --git a/inc/app/sitemailer2/html/tpl_csssubmit.spt b/inc/app/sitemailer2/html/tpl_csssubmit.spt new file mode 100644 index 00000000..863165ca --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_csssubmit.spt @@ -0,0 +1,57 @@ + + + + + + + + + +
+ +   + + + {intl Validate:} + + +
+ + diff --git a/inc/app/sitemailer2/html/tpl_features.spt b/inc/app/sitemailer2/html/tpl_features.spt new file mode 100644 index 00000000..f7a629e4 --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_features.spt @@ -0,0 +1,128 @@ + + + + + {intl Output Mode} + + + {mode} + + + + + + {intl Template Name} + + + {name} + + + + + + + + + + +
+ {intl Insert a box tag} +   + {intl Insert a doctype definition tag} +   + {intl Insert a if/else condition block} +   + {intl Insert an intl tag} +   + {intl Insert a loop tag} +   + {intl Insert a var tag} +   + {intl Insert an XML declaration} + + {intl Help} +
+ + diff --git a/inc/app/sitemailer2/html/tpl_newcsssubmit.spt b/inc/app/sitemailer2/html/tpl_newcsssubmit.spt new file mode 100644 index 00000000..863165ca --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_newcsssubmit.spt @@ -0,0 +1,57 @@ + + + + + + + + + +
+ +   + + + {intl Validate:} + + +
+ + diff --git a/inc/app/sitemailer2/html/tpl_newfeatures.spt b/inc/app/sitemailer2/html/tpl_newfeatures.spt new file mode 100644 index 00000000..d1c13499 --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_newfeatures.spt @@ -0,0 +1,110 @@ + + + + + + + + + +
+ {intl Insert a box tag} +   + {intl Insert a doctype definition tag} +   + {intl Insert a if/else condition block} +   + {intl Insert an intl tag} +   + {intl Insert a loop tag} +   + {intl Insert a var tag} +   + {intl Insert an XML declaration} + + {intl Help} +
+ + diff --git a/inc/app/sitemailer2/html/tpl_newsubmit.spt b/inc/app/sitemailer2/html/tpl_newsubmit.spt new file mode 100644 index 00000000..d581f86e --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_newsubmit.spt @@ -0,0 +1,110 @@ + + + + + + + + + +
+ +   + +   + + + {intl Validate:} + + +
+ + diff --git a/inc/app/sitemailer2/html/tpl_save_buttons.spt b/inc/app/sitemailer2/html/tpl_save_buttons.spt new file mode 100644 index 00000000..ed1e7d9a --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_save_buttons.spt @@ -0,0 +1,13 @@ + + + + + +
+ + +   +   + + +
\ No newline at end of file diff --git a/inc/app/sitemailer2/html/tpl_submit.spt b/inc/app/sitemailer2/html/tpl_submit.spt new file mode 100644 index 00000000..5aa10f5c --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_submit.spt @@ -0,0 +1,92 @@ + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +   +   + + +
+
+ +
+ +
+
+ + diff --git a/inc/app/sitemailer2/html/tpl_top.spt b/inc/app/sitemailer2/html/tpl_top.spt new file mode 100644 index 00000000..42579f4d --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_top.spt @@ -0,0 +1,122 @@ + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ +
+ +
+ + +   +   + + +
+ + diff --git a/inc/app/sitemailer2/html/tpl_validate.spt b/inc/app/sitemailer2/html/tpl_validate.spt new file mode 100644 index 00000000..e6a7425f --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_validate.spt @@ -0,0 +1,7 @@ + +

+ {intl Close}     +

+ +

{error} ({intl Line} {err_ln}, {intl Column} + {err_cl})

diff --git a/inc/app/sitemailer2/html/tpl_validate_noerr.spt b/inc/app/sitemailer2/html/tpl_validate_noerr.spt new file mode 100644 index 00000000..f39250d6 --- /dev/null +++ b/inc/app/sitemailer2/html/tpl_validate_noerr.spt @@ -0,0 +1,3 @@ +

+ {intl Close}     +

diff --git a/inc/app/sitemailer2/html/view_message.spt b/inc/app/sitemailer2/html/view_message.spt new file mode 100644 index 00000000..7fc79a52 --- /dev/null +++ b/inc/app/sitemailer2/html/view_message.spt @@ -0,0 +1,49 @@ + + +

{intl Close Window}

+ +

+ + + + + + + + + + + + + +
{intl Subject}{subject}
{intl From}{fromname} <{fromemail}>
{intl Date}{date}
+

+ +
+ +{filter none}{body}{end filter} + +
diff --git a/inc/app/sitemailer2/html/xhtml_forwarder.spt b/inc/app/sitemailer2/html/xhtml_forwarder.spt new file mode 100644 index 00000000..daaa7aa6 --- /dev/null +++ b/inc/app/sitemailer2/html/xhtml_forwarder.spt @@ -0,0 +1,10 @@ + + +
+ + + + +
+ + diff --git a/inc/app/sitemailer2/install/INSTALL b/inc/app/sitemailer2/install/INSTALL new file mode 100644 index 00000000..e647967f --- /dev/null +++ b/inc/app/sitemailer2/install/INSTALL @@ -0,0 +1,69 @@ +1. Install the Database Schema: + + cd /path/to/sitellite + cd inc/app/sitemailer2/install + mysql -u DB_USERNAME -p SITELLITE_DB_NAME < install-mysql.sql + (enter password when prompted) + +2. Install the Collections: + + cd /path/to/sitellite + cd inc/app/sitemailer2/install + cp *.php ../../cms/conf/collections/ + cp html.settings.tpl ../../../html// + + Note: If you do not know your template set specify "default". + +3. Make 2 Files Writable By Apache: + + cd /path/to/sitellite + cd inc/app/sitemailer2/ + chmod 777 data/tmp + chmod 777 conf/settings2.ini.php + +4. Configure Your Outgoing Mail Server: + + cd /path/to/sitellite + cd inc/app/sitemailer2/conf + vi properties.php + + Then find the line: "appconf_set ('mta', 'smtp');" + + If you want to use an smtp server leave this line and make the appropriate changes to the line: + "appconf_set ( + 'mta_smtp'," + +5. Verify The Settings Tab in the Sitemailer2 Web Interface + + Visit http:///index/sitemailer2-settings-form + +6. Edit 2 Scripts: + + cd /path/to/sitellite + cd inc/app/sitemailer2/script + vi start.sh + + Make sure the line "export PATH=" has the path to your php binary. If you don't + know the path to your php binary, you can find out using the which command. + + vi start_bouncer.sh + + Make the same change here. + +7. Start SiteMailer2: + + cd /path/to/sitellite + cd inc/app/sitemailer2/script + ./start + +8. Install the Following Cron Job: + + 0,10,20,30,40,50 * * * * /path/to/sitellite/inc/app/sitemailer2/script/running.sh + + Note: make sure to replace /path/to/sitellite with the actual path to sitellite + +9. Start Using Sitemailer2: + + Verify The Settings Tab in the Sitemailer2 Web Interface. The default username/password is admin/admin. + + Visit http:///index/sitemailer2-app diff --git a/inc/app/sitemailer2/install/changes.txt b/inc/app/sitemailer2/install/changes.txt new file mode 100644 index 00000000..51b19e50 --- /dev/null +++ b/inc/app/sitemailer2/install/changes.txt @@ -0,0 +1,38 @@ +2.0.6: + +- Added box chooser support. +- Content types are now hidden, access through Tools > SiteMailer 2. + +2.0.5: + +- Updated the settings so they don't conflict with Sitellite's new app + settings editor. + +2.0.4: + +- Fixed a bug causing changes to drafts not to be saved + +2.0.3: + +- Fixed many i18n issues throughout the templates +- Fixed an i18n issue where code logic relied on default submit button + values + +2.0.2: + +- Improved shell scripts + +2.0.1: + +- Sending one message doesn't send all drafts now +- Newsletter column was blank in draft list +- Settings form shows with wrong template set +- Fixed default paths in shell scripts +- Added data directory to CVS, needed for pid files +- Fixed a memory problem with sending to large numbers of subscribers +- Fixed a problem causing messages to occassionally get marked 'done' + prematurely. +- Fixed a bug in mailer causing Sent # in archive not to update while + mail was in progress. +- Added a percent value to running messages in the archive. +- Increased the memory usage of the message form from 8 to 24 MB. diff --git a/inc/app/sitemailer2/install/html.settings.tpl b/inc/app/sitemailer2/install/html.settings.tpl new file mode 100755 index 00000000..98eb7a5a --- /dev/null +++ b/inc/app/sitemailer2/install/html.settings.tpl @@ -0,0 +1,62 @@ + + + SITELLITE content server 4 + + + + + + +
+ + + + + + +
+ + + + + + + +

Title

+ + + + + + + +
+ +

body here

+ +

[ top ]

+ +
+
+ +
+ +

+ Copyright , SIMIAN systems Inc.
+ All rights reserved.
+ Click here to read the software license agreement. +

+ + + \ No newline at end of file diff --git a/inc/app/sitemailer2/install/install-mysql.sql b/inc/app/sitemailer2/install/install-mysql.sql new file mode 100755 index 00000000..cc3e0d82 --- /dev/null +++ b/inc/app/sitemailer2/install/install-mysql.sql @@ -0,0 +1,142 @@ +# Your database schema goes here + +create table sitemailer2_recipient ( + id int auto_increment primary key, + email char(72) not null, + firstname char(24) not null, + lastname char(24) not null, + organization char(72) not null, + website char(72) not null, + created datetime not null, + status enum('active','unverified','disabled') not null, + index (email, status, created) +); + +-- table storing newsletters a recipient belongs to +create table sitemailer2_recipient_in_newsletter ( + recipient int not null, + newsletter int not null, + status_change_time datetime, + status enum('subscribed','unsubscribed') not null, + primary key (recipient, newsletter) +); + +-- list of message categories +create table sitemailer2_newsletter ( + id int not null auto_increment primary key, + name char(48) not null, + from_name char(128) not null, + from_email char(128) not null, + template int not null, + subject char(128) not null, + rss_subs int not null, + public enum('yes','no') not null default 'yes', + index (name, public) +); + +insert into sitemailer2_newsletter (id, name) values (1, 'Default'); + +-- table for messages +create table sitemailer2_message ( + id int not null auto_increment primary key, + title char (128) not null, + date datetime not null, + mbody text not null, + subject char(72) not null, + template int not null, + start datetime not null, + status enum('draft', 'running', 'done') not null, + recurring enum ('no', 'daily', 'weekly', 'twice-monthly', 'monthly') not null, + next_recurrence datetime not null, + fromname char (128) not null, + fromemail char (128) not null, + numrec int not null, + numsent int not null, + confirmed_views int not null, + num_bounced int not null, + index (date, status) +); + +create table sitemailer2_message_newsletter ( + id int not null auto_increment primary key, + message int not null, + newsletter int not null +); + +--table for templates +create table sitemailer2_template ( + id int not null auto_increment primary key, + title char (128) not null, + date datetime not null, + body text not null, + index (date) +); + +insert into sitemailer2_template (id, title, date, body) values (NULL, "Default", now(), "{body}"); + +--table for mail to be sent +create table sitemailer2_q ( + id int not null auto_increment primary key, + recipient int not null, + message int not null, + attempts int not null, + created datetime not null, + last_attempt datetime not null, + last_error char(128) not null, + next_attempt datetime not null, + index (message) +); + +--table for mail that failed to send +create table sitemailer2_failed_q ( + id int not null auto_increment primary key, + recipient int not null, + message int not null, + attempts int not null, + created datetime not null, + last_attempt datetime not null, + last_error char(128) not null, + index (message) +); + +--subscription confirmation url table +create table sitemailer2_email_tracker ( + id int not null auto_increment primary key, + url char (128) not null, + recipient int not null, + newsletter int not null, + message int not null, + count int not null, + index (newsletter, message) +); + +--create table sitemailer2_rss_tracker ( + +--); + +--bounce tracker +create table sitemailer2_bounces ( + id int not null auto_increment primary key, + recipient int not null, + message int not null, + occurred datetime not null +); + +--campains + +create table sitemailer2_campaign ( + id int not null auto_increment primary key, + title text not null, + forward_url text not null, + created datetime not null +); + +--alter table sitemailer2_link_tracker add recipient int not null; + +create table sitemailer2_link_tracker ( + id int not null auto_increment primary key, + campaign int not null, + created datetime not null, + message int not null, + recipient int not null +); diff --git a/inc/app/sitemailer2/install/sitemailer2_message.php b/inc/app/sitemailer2/install/sitemailer2_message.php new file mode 100755 index 00000000..4076c1c0 --- /dev/null +++ b/inc/app/sitemailer2/install/sitemailer2_message.php @@ -0,0 +1,80 @@ +; diff --git a/inc/app/sitemailer2/install/sitemailer2_recipient.php b/inc/app/sitemailer2/install/sitemailer2_recipient.php new file mode 100755 index 00000000..3f659de5 --- /dev/null +++ b/inc/app/sitemailer2/install/sitemailer2_recipient.php @@ -0,0 +1,106 @@ +; 'Active', 'unverified' => 'Unverified', 'disabled' => 'Disabled')" +count = off + +; */ ?> \ No newline at end of file diff --git a/inc/app/sitemailer2/install/sitemailer2_template.php b/inc/app/sitemailer2/install/sitemailer2_template.php new file mode 100644 index 00000000..eed27884 --- /dev/null +++ b/inc/app/sitemailer2/install/sitemailer2_template.php @@ -0,0 +1,72 @@ +; diff --git a/inc/app/sitemailer2/install/test-data.sql b/inc/app/sitemailer2/install/test-data.sql new file mode 100644 index 00000000..1b5666d0 --- /dev/null +++ b/inc/app/sitemailer2/install/test-data.sql @@ -0,0 +1,75 @@ +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 1, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 2, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 3, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "", "", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 4, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 5, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 6, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 7, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 8, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 9, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 10, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 11, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 12, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 13, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 14, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 15, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 16, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 17, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "jd@localhost", "jon", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 18, 1); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 19, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 20, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 21, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "", "", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 22, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 23, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 24, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 25, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 26, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 27, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 28, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 29, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 30, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 31, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 32, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 33, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 34, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 35, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 36, 2); +insert into sitemailer2_recipient (id, email, firstname, lastname, organization, website, created) values (null, "ian@localhost", "ian", "dart", "", "", ""); +insert into sitemailer2_recipient_belongs_to_category (id, recipient, category) values (null, 37, 2); + diff --git a/inc/app/sitemailer2/lib/Bouncer.php b/inc/app/sitemailer2/lib/Bouncer.php new file mode 100644 index 00000000..b36cca04 --- /dev/null +++ b/inc/app/sitemailer2/lib/Bouncer.php @@ -0,0 +1,724 @@ +parts)) { + return false; + } + + foreach ($m->parts as $part) { + + if (strpos (strtolower($part->headers['content-type']), 'message') || + (strpos (strtolower($part->headers['content-type']), 'delivery-status'))) { + + # Each message/delivery-status contains a list of Message objects + # which are the header blocks. Iterate over those too. + # We try to dig out the Original-Recipient (which is optional) and + # Final-Recipient (which is mandatory, but may not exactly match + # an address on our list). Some MTA's also use X-Actual-Recipient + # as a synonym for Original-Recipient, but some apparently use + # that for other purposes :( + # + # Also grok out Action so we can do something with that too. + + $body = strtolower($part->body); + + $action = findPostFix ('action:', $body); + + if ($action == 'delayed') { + return false; + } elseif ($action == 'failed' || $action == 'failure') { + //find recipient, this is a bounced message + $bounce = true; + + // ; removed from 'rfc822;' because findPostFix removes ';' + $recipient = findPostFix ('original-recipient:', $body); + $recipient = findPostFix ('rfc822', $recipient); + + if (! empty ($recipient)) $recipients[] = $recipient; + + $recipient = findPostFix ('final-recipient:', $body); + $recipient = findPostFix ('rfc822', $recipient); + if (! empty ($recipient)) $recipients[] = $recipient; + + } + } + } + + if ($bounce) { + if (! empty ($recipients)) { + return $recipients; + } else { + return true; + } + } else { + return false; + } +} + +/*Parse bounce messages generated by qmail. + +Qmail actually has a standard, called QSBMF (qmail-send bounce message +format), as described in + + http://cr.yp.to/proto/qsbmf.txt +*/ +function bouncer_qmail ($m) { + + $s = strpos ($m->body, 'Hi. This is the qmail'); + + //$s should equal 0, be careful + + if (! is_int ($s)) return false; + + //find addresses after pos $s + $len = strlen($m->body); + + $lt = strpos ($m->body, '<', $s) + 1; + $gt = strpos ($m->body, '>', $lt); + + $addr = substr ($m->body, $lt, $gt-$lt); + + if (! empty ($addr)) return array ($addr); + else return array(); +} + +/*Parse bounce messages generated by Postfix. + +This also matches something called `Keftamail' which looks just like Postfix +bounces with the word Postfix scratched out and the word `Keftamail' written +in in crayon. + +It also matches something claiming to be `The BNS Postfix program', and +`SMTP_Gateway'. Everybody's gotta be different, huh? +*/ +function bouncer_postfix ($m) { + + $bounce = false; + + if (empty ($m->parts)) return false; + + foreach ($m->parts as $part) { + + $part->body = strtolower ($part->body); + + $s = strpos ($part->body, 'the postfix program'); + if (! $s) $s = strpos ($part->body, 'the smtp_gateway program'); + if (! $s) $s = strpos ($part->body, 'the keftamail program'); + if (! $s) $s = strpos ($part->body, 'the bns postfix program'); + if (! $s) { + //some postfixes have more os information too... regexp + $s = preg_match ("'the postfix.*program'", $part->body); + + if ($s === 0) continue; + + $s = strpos ($part->body, 'program'); + } + + if (is_int ($s)) { + $bounce = true; + + //now find the (second) email addy + $lt = strpos ($part->body, '<', $s) + 1; + $lt = strpos ($part->body, '<', $lt) + 1; + $gt = strpos ($part->body, '>', $lt); + $addr = substr ($part->body, $lt, $gt-$lt); + + //we're done + if (! empty ($addr)) return array ($addr); + break; + } + } + + return false; +} + +function bouncer_yahoo ($m) { + + if (! is_int (strpos (strtolower($m->headers['from']), 'mailer-daemon@yahoo'))) { + return false; + } + + $m->body = strtolower ($m->body); + + $s = strpos ($m->body, 'to the following address'); + + //now find the email addy + $lt = strpos ($m->body, '<', $s) + 1; + $gt = strpos ($m->body, '>', $lt); + $addr = substr ($m->body, $lt, $gt-$lt); + + //we're done + if (! empty ($addr)) return array ($addr); + else return false; +} + +function bouncer_caiwireless ($m) { + + if (empty ($m->parts)) return false; + + $bounce = false; + + foreach ($m->parts as $part) { + + $part->body = strtolower ($part->body); + $s = strpos ($part->body, 'the following recipients did not receive this message'); + + if (is_int ($s)) { + $bounce = true; + + //now find the email addy + $lt = strpos ($part->body, '<', $s) + 1; + $gt = strpos ($part->body, '>', $lt); + $addr = substr ($part->body, $lt, $gt-$lt); + + //we're done + if (! empty ($addr)) return array ($addr); + else return false; + } + } + + return $bounce; +} + +//Recognizes (some) Microsoft Exchange formats. +function bouncer_exchange ($m) { + + $bounce = false; + + if (empty ($m->parts)) return false; + + foreach ($m->parts as $part) { + + $part->body = strtolower ($part->body); + $s = strpos ($part->body, 'did not reach the following recipient'); + + if (is_int ($s)) { + + $bounce = true; + + //now find the email addy + $email = findPostFix ('smtp=', $part->body); + if (! empty ($email)) { + return array ($email); + } + } + } + + return $bounce; +} + +/*Parse bounce messages generated by Exim. + +Exim adds an X-Failed-Recipients: header to bounce messages containing +an `addresslist' of failed addresses. + +*/ +function bouncer_exim ($m) { + + if (empty ($m->headers['x-failed-recipients'])) return false; + + return array ($m->headers['x-failed-recipients']); + +} + +/*Netscape Messaging Server bounce formats. + +I've seen at least one NMS server version 3.6 (envy.gmp.usyd.edu.au) bounce +messages of this format. Bounces come in DSN MIME format, but don't include +any -Recipient: headers. Gotta just parse the text :( + +NMS 4.1 (dfw-smtpin1.email.verio.net) seems even worse, but we'll try to +decipher the format here too. + +*/ +function bouncer_netscape ($m) { + + if (empty ($m->parts)) return false; + + $bounce = false; + + $addr = array (); + + foreach ($m->parts as $part) { + + //can be multiple failures per email + + $part->body = strtolower ($part->body); + + $s = strpos ($part->body, 'this message was undeliverable due to the following reason:'); + + if (is_int ($s)) { + + $bounce = true; + + $email = findPostFix ('<', substr ($part->body, $s)); + + if (!empty ($email)) { + $addr[] = $email; + } + } + + } + + if (empty($addr)) return $bounce; + else return $addr; +} + +//Compuserve has its own weird format for bounces. +function bouncer_compuserve ($m) { + + if (! empty ($m->parts)) return false; + + $m->body = strtolower ($m->body); + + $s = strpos ($m->body, 'your message could not be delivered'); + + if (is_int ($s)) { + //now find the email addy + $email = findPostFix ('invalid receiver address:', $m->body); + //we're done + } + + if (! empty ($email)) return array ($email); + else return false; +} + +function bouncer_microsoft ($m) { + + if (empty ($m->parts)) return false; + + foreach ($m->parts as $part) { + + if (empty ($part->body)) continue; + + $part->body = strtolower ($part->body); + + $s = strpos ('transcript of session follow', $part->body); + + if (is_int ($s)) { + //there should be a line with only the email address in it + + foreach (explode ("\n", $part->body) as $line) { + $t = strpos ('@', $line); + + if (is_int ($t)) + return array (trim ($t)); + } + } else { + + //try one other format + $s = strpos ('did not reach the following recipient(s):', $part->body); + + if (! is_int($s)) continue; + + $res = findPostFix ('did not reach the following recipient(s):', $part->body); + + if (! empty ($res)) return array ($res); + } + } + + return false; +} + +/*This appears to be the format for Novell GroupWise and NTMail + +X-Mailer: Novell GroupWise Internet Agent 5.5.3.1 +X-Mailer: NTMail v4.30.0012 +X-Mailer: Internet Mail Service (5.5.2653.19) +*/ +function bouncer_groupwise ($m) { + + if (empty ($m->headers['x-mailer'])) return false; + if (empty ($m->parts)) return false; + + //find a plain/text + foreach ($m->parts as $part) { + + + $s = strpos ($part->headers['content-type'], 'text/plain'); + + if (is_int ($s)) { + //return addy should be here somewhere + $part->body = strtolower ($part->body); + $email = findPostFix ("did not reach the following recipient(s):", $part->body); + if (! empty ($email)) return array ($email); + } else { + + //probably mime/html type... look for the same after removing some html tags + $part->body = str_replace ('
', ' ', $part->body); + $email = findPostFix ("did not reach the following recipient(s):", $part->body); + if (! empty ($email)) return array ($email); + } + + + } + + return false; +} + +/*Something which claims +X-Mailer: + +What the heck is this thing? Here's a recent host: + +% telnet 207.51.255.218 smtp +Trying 207.51.255.218... +Connected to 207.51.255.218. +Escape character is '^]'. +220 X1 NT-ESMTP Server 208.24.118.205 (IMail 6.00 45595-15) + +*/ +function bouncer_smtp32 ($m) { + + if (empty ($m->headers['x-mailer'])) return false; + + $s = strpos ($m->headers['x-mailer'], 'body); + if (! $mail) $mail = findPostFix ('undeliverable to', $m->body); + if (! $mail) $mail = findPostFix ('delivery failed:', $m->body); + if (! $mail) $mail = findPostFix ('attempts: ', $m->body); + + if ($mail) return array ($mail); + else return false; +} + +//Recognizes simple heuristically delimited bounces. +function bouncer_simplematch ($m) { + + if (empty ($m->parts)) $body = $m->body; + else $body = $m->parts[0]->body; + + $tuples = array ( + # sdm.de + array ('here is your list of failed recipients', + 'here is your returned mail', + '<>'), + # sz-sb.de, corridor.com, nfg.nl + array ('(expanded from: ', + 'transcript of session follows', + 'expanded from:'), + # robanal.demon.co.uk + array ('this message was created automatically by mail delivery software', + 'original message follows', + 'rcpt to:'), + # s1.com (InterScan E-Mail VirusWall NT ???) + array ('message from interscan e-mail viruswall nt', + 'end of message', + 'rcpt to:'), + # Smail + array ("failed addresses follow: ", + 'message text follows:', + "failed addresses follow: ---------------------|"), + # newmail.ru + array ('This is the machine generated message from mail service.', + '--- Below the next line is a copy of the message.', + '<>'), + # turbosport.com runs something called `MDaemon 3.5.2' ??? + array ('The following addresses did NOT receive a copy of your message:', + '--- Session Transcript ---', + '>'), + # usa.net + array ('Intended recipient:', + '--------RETURNED MAIL FOLLOWS--------', + 'Intended recipient:'), + # hotpop.com + array ('Undeliverable Address:', + 'Original message attached', + 'Undeliverable Address:'), + # Another demon.co.uk format + array ('This message was created automatically by mail delivery', + '---- START OF RETURNED MESSAGE ----', + "addressed to "), + array ('------ Failed Recipients ------', + '-------- Returned Mail --------', + '<>'), + ); + + $body = strtolower ($body); + + foreach ($tuples as $t) { + $t[0] = strtolower ($t[0]); + $t[1] = strtolower ($t[1]); + $t[2] = strtolower ($t[2]); + + $s = strpos ($body, $t[0]); + if (! is_int ($s)) continue; + $e = strpos ($body, $t[1]); + if (! is_int ($e)) continue; + + if ($t[2] == '<>') { + //email is surround by <> + $haystack = substr ($body, $s, $e-$s); + $open = strpos ($haystack, '<') + 1; + $close = strpos ($haystack, '>', $open); + $email = trim (substr ($haystack, $open, $close-$open)); + break; + } elseif ($t[2] == '>') { + $haystack = substr ($body, $s, $e-$s); + $open = strpos ($haystack, '>') + 1; + $close = strpos ($haystack, "\n", $open); + $email = trim (substr ($haystack, $open, $close-$open)); + break; + } else { + $haystack = substr ($body, $s, $e-$s); + $email = findPostFix ($t[2], $haystack); + break; + + } + } + + if (empty ($email)) return false; + else return array ($email); +} + + +/*Yale's mail server is pretty dumb. + +Its reports include the end user's name, but not the full domain. I think we +can usually guess it right anyway. This is completely based on examination of +the corpse, and is subject to failure whenever Yale even slightly changes +their MTA. :( + +*/ +function bouncer_yale ($m) { + //check if from has mailer-daemon and yale.edu + + $s = strpos (strtolower ($m->headers['from']), 'mailer-daemon'); + if (! is_int ($s)) return false; + $s = strpos (strtolower ($m->headers['from']), 'yale.edu'); + if (! is_int ($s)) return false; + + $email = findPostFix ('--------Message not delivered to the following:', $m->body); + + if (! $email) return false; + else return array ($email . '@yale.edu', $email . '@yale.cs.edu'); +} + +function bouncer_llnl ($m) { + + if (! is_int (strpos ($m->headers['from'], 'postmaster@llnl.gov'))) return false; + + $email = findPostFix ('which your message was addressed,', $m->body); + + if (! $email) return false; + else return array( $email); + +} + +function new_is_int ($x) { + return (is_numeric($x) ? intval($x) == $x : false); +} + +function getFirstNameFromAddress ($x) { + + //possible formats + //1. Name + //2. email + //3. "Name@domain" + //4. + + //return empty string if no name + + $x = trim ($x); + + $s = strpos ($x, '<'); + $e = strpos ($x, '>'); + $q = strpos($x, "\""); + + $name = ''; + $fname = ''; //covers 2 and 4 + + if ($e) { //check for 1 or 3 + if ($q) { //3 + $q2 = strpos ($x, "\"", $q+1); + if ($q2) { + $name = substr ($x, $q, $q2-$q1); + } else { //erroneous address???, look for '<' + $name = trim (substr ($x, $q, $q-$s)); + } + } else { //1 + $name = trim (substr ($x, 0, $s)); + } + //break up name if theres a space in it; + $s = strpos ($name, ' '); + if($s) { + $fname = substr ($name, 0, $s); + } else { + $fname = $name; + } + } + + return $fname; +} + +function getLastNameFromAddress ($x) { + + //possible formats + //1. Name + //2. email + //3. "Name@domain" + //4. + + //return empty string if no name + + $x = trim ($x); + + $s = strpos ($x, '<'); + $e = strpos ($x, '>'); + $q = strpos($x, "\""); + + $name = ''; + $lname = ''; //covers 2 and 4 + + if ($e) { //check for 1 or 3 + if ($q) { //3 + $q2 = strpos ($x, "\"", $q+1); + if ($q2) { + $name = substr ($x, $q, $q2-$q1); + } else { //erroneous address???, look for '<' + $name = trim (substr ($x, $q, $q-$s)); + } + } else { //1 + $name = trim (substr ($x, 0, $s)); + } + //break up name if theres a space in it; + $s = strpos ($name, ' '); + if($s) { + $lname = substr ($name, $s, $e-$s); + } else { + $lname = ''; + } + } + + return trim ($lname); +} + +function getEmailFromAddress ($x) { + + //possible formats + //1. Name + //2. email + //3. "Name@domain" + //4. + + //return empty string if no name + + $x = trim ($x); + + $s = strpos ($x, '<'); + $e = strpos ($x, '>'); + + $addy = ''; + + if ($e) { //1, 3 and 4 + $addy = substr ($x, $s+1, $e-$s-1); + } else { //2 + $addy = $x; + } + + return strtolower (trim ($addy)); +} + +function findPostfix ($needle, $haystack) { + + $haystack = str_replace ("\n", ' ', $haystack); + + $s = strpos ($haystack, $needle); + + if (! is_int($s)) return false; + + $s += strlen ($needle); + + //find the next non space char + for ($i = $s; $i < strlen($haystack); $i++) { + if (substr ($haystack, $i, 1) == ' ') { + // + } else { + $s = $i; + break; + } + } + + for ($i = $s; $i < strlen($haystack); $i++) { + + if ($i == strlen($haystack) - 1) { + $e = strlen ($haystack); + } else if (substr ($haystack, $i, 1) == "," || //chars that shouldnt be in an email address + substr ($haystack, $i, 1) == ' ' || //and often end an email address + substr ($haystack, $i, 1) == ')' || + substr ($haystack, $i, 1) == '>') { + $e = $i; + break; + } + } + + //hack + $final = trim (substr ($haystack, $s, $e-$s)); + $final = str_replace ("'", '', $final); + $final = str_replace (";", '', $final); + $final = str_replace ("<", '', $final); + return $final; +} + + +//takes an array of email address to unsub +function unsub ($addrs) { + + foreach ($addrs as $email) { + + //get the recipient id(s) for the email address + $recipients = db_shift_array ('select id from sitemailer2_recipient where email=?', $email); + + //see if we need to unsub + $max_bounces = appconf ('disable_subscriber_after_bounces'); + + //only consider bounces younger than 3 months + list ($date, $time) = explode (' ', date('Y-m-d-H-i-s')); + list ($year, $month, $day, $hour, $minute, $second) = explode ('-', $date); + $max_date = date ('Y-m-d H:i:s', mktime ($hour, $minute, $second, $month-3, $day, $year)); + + //we need to find out how many times each recipient id has been bounced + foreach ($recipients as $r) { + + $count = db_shift ('select count(id) from sitemailer2_bounces where recipient=? and occurred > ?', $r, $max_date); + + if ($count >= $max_bounces) { + + //need to unsub + db_execute ('update sitemailer2_recipient_in_newsletter set status="unsubscribed" where recipient=?', $r); + db_execute ('update sitemailer2_recipient set status="disabled" where id=?', $r); + } else { + + //count this bounce + if (! db_execute ('insert into sitemailer2_bounces (id, recipient, message, + occurred) values (null, ?, "", now())', $r)) { + echo "Failed to updates bounces\n"; + } + } + } + } +} + +function count_bounce ($num) { + + //make a best guess of what message this bounce comes from + //base the guess on proximity to message start date + //assume message was bounced now + + $best_guess = db_shift ('select id from sitemailer2_message where start < now() and status in("running", "done") order by start desc limit 1'); + + if ($best_guess) { + db_execute ('update sitemailer2_message set num_bounced=num_bounced+? where id = ?', $num, $best_guess); + } else { + echo "Failed to determine what message resulted in bounce \n"; + } +} + +?> diff --git a/inc/app/sitemailer2/lib/Facet/Join.php b/inc/app/sitemailer2/lib/Facet/Join.php new file mode 100644 index 00000000..ba6d888d --- /dev/null +++ b/inc/app/sitemailer2/lib/Facet/Join.php @@ -0,0 +1,65 @@ +{'_' . $this->field}) { + return new rList ( + 'id', + db_shift_array ('select ' . $this->key1 . ' from ' . $this->join_table . ' where ' . $this->key2 . ' = ?', $cgi->{'_' . $this->field}) + ); + } else { + return false; + } + } + + function render () { + global $cgi; + + $out = '
' . NEWLINE; + + foreach ($this->preserve as $name) { + $out .= '' . NEWLINE; + } + + foreach ($cgi->param as $k) { + if ($k != $this->field && strpos ($k, '_') === 0 && ! in_array ($k, $this->ignore)) { + // assume it's a facet + $out .= '' . NEWLINE; + } + } + + $out .= '' . intl_get ($this->display) . ':' . NEWLINE + . TAB . '' . NEWLINE . '
' . NEWLINE; + + return $out; + } +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/lib/Filters.php b/inc/app/sitemailer2/lib/Filters.php new file mode 100644 index 00000000..1f6f387c --- /dev/null +++ b/inc/app/sitemailer2/lib/Filters.php @@ -0,0 +1,60 @@ + '\T\o\d\a\y - g:i A', + 'yesterday' => '\Y\e\s\t\e\r\d\a\y - g:i A', + 'tomorrow' => '\T\o\m\o\r\r\o\w - g:i A', + 'this week' => 'l, F j, Y - g:i A', + 'other' => 'F j, Y - g:i A', + ) + ); +} + +function sitemailer2_filter_date ($date) { + + return Date::timestamp ( + $date, + array ( + 'today' => '\T\o\d\a\y', + 'yesterday' => '\Y\e\s\t\e\r\d\a\y', + 'tomorrow' => '\T\o\m\o\r\r\o\w', + 'this week' => 'M j, Y', + 'other' => 'M j, Y', + ) + ); +} + +function sitemailer2_filter_org_link ($item) { + if (strlen ($item->organization) > 20) { + $item->organization = substr ($item->organization, 0, 17) . '...'; + } + return '' . $item->organization . ''; +} + +function sitemailer2_filter_newsletter ($id) { + return db_shift ('select name from sitemailer2_newsletter where id = ?', $id); +} + +function sitemailer2_filter_newsletters ($id) { + + //get the newsletters this recipient belongs to + $nls = db_pairs ('select distinct t1.newsletter, t2.name from sitemailer2_recipient_in_newsletter as t1, sitemailer2_newsletter as t2 where t1.recipient = ? and t2.id = t1.newsletter', $id->id); + + $nls = implode (", ", $nls); + + return $nls; +} + +?> \ No newline at end of file diff --git a/inc/app/sitemailer2/lib/Functions.php b/inc/app/sitemailer2/lib/Functions.php new file mode 100644 index 00000000..5cde7923 --- /dev/null +++ b/inc/app/sitemailer2/lib/Functions.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/inc/app/sitemailer2/pix/arrow.asc.gif b/inc/app/sitemailer2/pix/arrow.asc.gif new file mode 100644 index 00000000..703c0c5e Binary files /dev/null and b/inc/app/sitemailer2/pix/arrow.asc.gif differ diff --git a/inc/app/sitemailer2/pix/arrow.desc.gif b/inc/app/sitemailer2/pix/arrow.desc.gif new file mode 100644 index 00000000..b7d72f46 Binary files /dev/null and b/inc/app/sitemailer2/pix/arrow.desc.gif differ diff --git a/inc/app/sitemailer2/pix/corner.gif b/inc/app/sitemailer2/pix/corner.gif new file mode 100755 index 00000000..bc111c2a Binary files /dev/null and b/inc/app/sitemailer2/pix/corner.gif differ diff --git a/inc/app/sitemailer2/pix/icon.gif b/inc/app/sitemailer2/pix/icon.gif new file mode 100644 index 00000000..5eec80ae Binary files /dev/null and b/inc/app/sitemailer2/pix/icon.gif differ diff --git a/inc/app/sitemailer2/pix/icons/archive.gif b/inc/app/sitemailer2/pix/icons/archive.gif new file mode 100644 index 00000000..1c1871d8 Binary files /dev/null and b/inc/app/sitemailer2/pix/icons/archive.gif differ diff --git a/inc/app/sitemailer2/pix/icons/compose.gif b/inc/app/sitemailer2/pix/icons/compose.gif new file mode 100644 index 00000000..bc22b174 Binary files /dev/null and b/inc/app/sitemailer2/pix/icons/compose.gif differ diff --git a/inc/app/sitemailer2/pix/icons/subscribers.gif b/inc/app/sitemailer2/pix/icons/subscribers.gif new file mode 100644 index 00000000..259e2e8d Binary files /dev/null and b/inc/app/sitemailer2/pix/icons/subscribers.gif differ diff --git a/inc/app/sitemailer2/pix/invisible.gif b/inc/app/sitemailer2/pix/invisible.gif new file mode 100644 index 00000000..e565824a Binary files /dev/null and b/inc/app/sitemailer2/pix/invisible.gif differ diff --git a/inc/app/sitemailer2/pix/tab.gif b/inc/app/sitemailer2/pix/tab.gif new file mode 100644 index 00000000..aa5c8bcd Binary files /dev/null and b/inc/app/sitemailer2/pix/tab.gif differ diff --git a/inc/app/sitemailer2/script/running.sh b/inc/app/sitemailer2/script/running.sh new file mode 100755 index 00000000..cfd4d149 --- /dev/null +++ b/inc/app/sitemailer2/script/running.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +# To check for sitemailer's wellbeing every 10 minutes (recommended), +# put the following line in your crontab: +# 0,10,20,30,40,50 * * * * /path/to/sitellite/inc/app/sitemailer2/script/running.sh +# And if you don't want to get email from crontab put the following +# in your crontab: +# 0,10,20,30,40,50 * * * * /path/to/sitellite/inc/app/sitemailer2/script/running.sh +# + +export PATH=/bin:/usr/bin:/usr/local/bin + +script_dir=`dirname $0` +cd $script_dir + +pid_file=../data/mailer.pid +mailer_pid=`ps wux | grep 'php -f index sitemailer2-mailer-action' | grep -v grep | awk '{ print $2; exit }'` + +if test -s "$pid_file" +then + real_pid=`ps wux | grep 'php -f index sitemailer2-mailer-action' | grep -v grep | awk '{ print $2; exit }'` + + if [ $real_pid ] + then + # SiteSearch is running + echo "Mailer is Running." + else + echo "No Mailer daemon found. Attempting to start Mailer daemon..." + ./stop.sh + ./start.sh + fi +else + echo "No Mailer pid file found. Looked for $pid_file" + echo "Attempting to start Mailer daemon..." + ./stop.sh + ./start.sh +fi + +pid_file=../data/recurring.pid +recurring_pid=`ps wux | grep 'php -f index sitemailer2-recurring-action' | grep -v grep | awk '{ print $2; exit }'` + +if test -s "$pid_file" +then + real_pid=`ps wux | grep 'php -f index sitemailer2-recurring-action' | grep -v grep | awk '{ print $2; exit }'` + + if [ $real_pid ] + then + # SiteSearch is running + echo "Recurring is Running." + else + echo "No Recurring daemon found. Attempting to start Recurring daemon..." + ./stop.sh + ./start.sh + fi +else + echo "No Recurring pid file found. Looked for $pid_file" + echo "Attempting to start Recurring daemon..." + ./stop.sh + ./start.sh +fi + +pid_file=../data/bouncer.pid +bouncer_pid=`ps wux | grep 'php -f index sitemailer2-bouncer-action' | grep -v grep | awk '{ print $2; exit }'` + +if test -s "$pid_file" +then + real_pid=`ps wux | grep 'php -f index sitemailer2-bouncer-action' | grep -v grep | awk '{ print $2; exit }'` + + if [ $real_pid ] + then + # SiteSearch is running + echo "Bouncer Running." + else + echo "No Bouncer found. Attempting to start Bouncer..." + ./start_bouncer.sh + fi +else + echo "No Bouncer pid file found. Looked for $pid_file" + echo "Attempting to start Bouncer..." + ./start_bouncer.sh +fi diff --git a/inc/app/sitemailer2/script/start.sh b/inc/app/sitemailer2/script/start.sh new file mode 100755 index 00000000..f68dfbb9 --- /dev/null +++ b/inc/app/sitemailer2/script/start.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# start the server in the background + +export PATH=/usr/local/bin:/usr/bin:/bin + +script_dir=`dirname $0` +cd $script_dir + +cd ../../../../ + +php -f index sitemailer2-mailer-action & + +sleep 2 +mailer_pid=`ps wux | grep 'php -f index sitemailer2-mailer-action' | grep -v grep | awk '{ print $2; exit }'` + +echo $mailer_pid > inc/app/sitemailer2/data/mailer.pid + +php -f index sitemailer2-recurring-action & + +sleep 2 +recurring_pid=`ps wux | grep 'php -f index sitemailer2-recurring-action' | grep -v grep | awk '{ print $2; exit }'` + +echo $recurring_pid > inc/app/sitemailer2/data/recurring.pid diff --git a/inc/app/sitemailer2/script/start_bouncer.sh b/inc/app/sitemailer2/script/start_bouncer.sh new file mode 100755 index 00000000..059c23af --- /dev/null +++ b/inc/app/sitemailer2/script/start_bouncer.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +export PATH=/usr/local/bin:/usr/bin:/bin + +script_dir=`dirname $0` +cd $script_dir + +cd ../../../../ + +php -f index sitemailer2-bouncer-action & + +sleep 2 +bouncer_pid=`ps wux | grep 'php -f index sitemailer2-bouncer-action' | grep -v grep | awk '{ print $2; exit }'` + +echo $bouncer_pid > inc/app/sitemailer2/data/bouncer.pid diff --git a/inc/app/sitemailer2/script/stop.sh b/inc/app/sitemailer2/script/stop.sh new file mode 100755 index 00000000..8b9da6fb --- /dev/null +++ b/inc/app/sitemailer2/script/stop.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +script_dir=`dirname $0` +cd $script_dir + +pid_file=../data/mailer.pid + +if test -s "$pid_file" +then + mailer_pid=`cat $pid_file` + echo "Killing Mailer with pid $mailer_pid" + kill $mailer_pid + + sleep 1 + rm $pid_file +else + echo "No Mailer pid file found. Looked for $pid_file" +fi + +pid_file=../data/recurring.pid + +if test -s "$pid_file" +then + recurring_pid=`cat $pid_file` + echo "Killing Recurring with pid $recurring_pid" + kill $recurring_pid + + sleep 1 + rm $pid_file +else + echo "No Recurring pid file found. Looked for $pid_file" +fi diff --git a/inc/app/sitemailer2/tests/Makefile.in b/inc/app/sitemailer2/tests/Makefile.in new file mode 100644 index 00000000..1aaa9ff9 --- /dev/null +++ b/inc/app/sitemailer2/tests/Makefile.in @@ -0,0 +1,69 @@ +# Copyright (C) 2001-2003 by the Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public Licenseo +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# NOTE: Makefile.in is converted into Makefile by the configure script +# in the parent directory. Once configure has run, you can recreate +# the Makefile by running just config.status. + +# Variables set by configure + +VPATH= @srcdir@ +srcdir= @srcdir@ +bindir= @bindir@ +prefix= @prefix@ +exec_prefix= @exec_prefix@ +DESTDIR= + +CC= @CC@ +CHMOD= @CHMOD@ +INSTALL= @INSTALL@ + +DEFS= @DEFS@ + +# Customizable but not set by configure + +OPT= @OPT@ +CFLAGS= $(OPT) $(DEFS) +BOUNCEDIR= $(prefix)/tests/bounces +SHELL= /bin/sh + +BOUNCE_FILES= $(srcdir)/*.txt + + +# Modes for directories and executables created by the install +# process. Default to group-writable directories but +# user-only-writable for executables. +DIRMODE= 775 +EXEMODE= 755 +FILEMODE= 644 +INSTALL_PROGRAM=$(INSTALL) -m $(EXEMODE) + +# Rules +all: + +install: + for f in $(BOUNCE_FILES); \ + do \ + $(INSTALL) -m $(FILEMODE) $$f $(DESTDIR)$(BOUNCEDIR); \ + done + +finish: + +clean: + +distclean: + -rm *.pyc + -rm Makefile diff --git a/inc/app/sitemailer2/tests/bounce_01.txt b/inc/app/sitemailer2/tests/bounce_01.txt new file mode 100644 index 00000000..ab7f45d4 --- /dev/null +++ b/inc/app/sitemailer2/tests/bounce_01.txt @@ -0,0 +1,95 @@ +From VM Wed Feb 7 14:01:33 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "" "6" "February" "2001" "14:41:27" "GMT" "\"Jetmail System\" <>" "\"Jetmail System\" <>" nil "48" "Mail Error" "^From:" nil nil "2" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: bwarsaw@wooz.org +Received: from digicool.com (host15.digitalcreations.d.subnet.rcn.com [208.59.6.15]) + by mail.wooz.org (Postfix) with ESMTP id 1AE74D37AC + for ; Tue, 6 Feb 2001 01:41:50 -0500 (EST) +Received: from + by digicool.com (CommuniGate Pro RULES 3.3.2) + with RULES id 1443386; Tue, 06 Feb 2001 01:43:53 -0500 +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.3.2) + with ESMTP id 1443385 for barry@mail.digicool.com; Tue, 06 Feb 2001 01:43:53 -0500 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id BAA24701 + for ; Tue, 6 Feb 2001 01:42:30 -0500 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14Q1pg-0006hx-00 + for barry@digicool.com; Tue, 06 Feb 2001 01:42:32 -0500 +Received: from host2.btamail.net.cn ([202.106.196.72] helo=btamail.net.cn) + by mail.python.org with smtp (Exim 3.21 #1) + id 14Q1oj-0006ek-00 + for python-list-admin@python.org; Tue, 06 Feb 2001 01:41:33 -0500 +Message-Id: +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: "Jetmail System" <> +Sender: python-list-owner@python.org +To: python-list-admin@python.org +Subject: Mail Error +Date: 06 Feb 2001 14:41:27 GMT +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.1 (101270) + +Your mail cannot be delivered to the following address(es): + + dylan "(0), ErrMsg=mail box space not enough, account=dylan " + +Please check the above address(es) and then try again. + +---- Header of the source mail attached ---- + +Received: from bjmx2.163.net([202.108.255.253]) by btamail.net.cn(JetMail 2.5.3.0) + with SMTP id jmb3a800bb6; Tue, 6 Feb 2001 06:41:26 -0000 +Received: by bjmx2.163.net (Postfix) + id ; Tue, 6 Feb 2001 06:31:28 +0800 (CST) +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by bjmx2.163.net (Postfix) with ESMTP id A468F1CB4210C + for ; Tue, 6 Feb 2001 06:31:27 +0800 (CST) +Received: from mail.python.org (localhost.localdomain [127.0.0.1]) + by mail.python.org (Postfix) with ESMTP + id 1B087E827; Mon, 5 Feb 2001 17:31:27 -0500 (EST) +Delivered-To: mm+python-list@python.org +Received: from onca.catsden.net (unknown [216.218.194.20]) + by mail.python.org (Postfix) with ESMTP id F004BE72E + for ; Mon, 5 Feb 2001 17:30:44 -0500 (EST) +Received: from localhost (chris@localhost) + by onca.catsden.net (8.9.3/8.9.3) with ESMTP id OAA28446; + Mon, 5 Feb 2001 14:23:15 -0800 +From: +To: Sam Wun +Cc: +Subject: Re: sorting on IP addresses +In-Reply-To: <3A7F26CB.BE85C96F@esec.com.au> +Message-ID: +MIME-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +Sender: python-list-admin@python.org +Errors-To: python-list-admin@python.org +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.1 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +Date: Mon, 5 Feb 2001 14:23:15 -0800 (PST) + + diff --git a/inc/app/sitemailer2/tests/bounce_02.txt b/inc/app/sitemailer2/tests/bounce_02.txt new file mode 100644 index 00000000..2d1d80c9 --- /dev/null +++ b/inc/app/sitemailer2/tests/bounce_02.txt @@ -0,0 +1,36 @@ +From: E500_SMTP_Mail_Service@lerctr.org +To: +Subject: Returned Mail - Error During Delivery +Date: Wed, 20 Nov 2002 19:58:47 -0500 (EST) +X-Virus-Scanned: by amavisd-milter (http://amavis.org/) + +------ Failed Recipients ------ + +: Requested action not taken: mailbox unavailable. [SMTP Error Code 550] +-------- Returned Mail -------- + +Received: from tnmx01.mgw.rr.com(24.165.200.11) by tnav01.midsouth.rr.com via csmap + id 26013; Wed, 20 Nov 2002 19:58:47 -0500 (EST) +Received: from lerami.lerctr.org (lerami.lerctr.org [207.158.72.11]) + by tnmx01.mgw.rr.com (8.12.5/8.12.5) with ESMTP id gAL0wLBM020447 + for ; Wed, 20 Nov 2002 19:58:21 -0500 (EST) +Received: from lerami.lerctr.org (localhost [127.0.0.1]) + by lerami.lerctr.org (8.12.6/8.12.6/20020902/$Revision: 1.1.1.1 $) with ESMTP id gAL0wHwV016400 + for ; Wed, 20 Nov 2002 18:58:18 -0600 (CST) +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +Subject: You have been unsubscribed from the MacArthur1975 mailing list +From: macarthur1975-bounces@lerctr.org +To: acinsp1@midsouth.rr.com +Message-ID: +Date: Wed, 20 Nov 2002 18:58:16 -0600 +Precedence: bulk +X-BeenThere: macarthur1975@lerctr.org +X-Mailman-Version: 2.1b4 +List-Id: MacArthur Class of 1975 Discussion +X-List-Administrivia: yes +Sender: macarthur1975-bounces@lerctr.org +Errors-To: macarthur1975-bounces@lerctr.org +X-Virus-Scanned: by amavisd-milter (http://amavis.org/) + diff --git a/inc/app/sitemailer2/tests/bounce_03.txt b/inc/app/sitemailer2/tests/bounce_03.txt new file mode 100644 index 00000000..fc62dcab --- /dev/null +++ b/inc/app/sitemailer2/tests/bounce_03.txt @@ -0,0 +1,109 @@ +Received: from tele-punt-22.mail.demon.net ([194.217.242.7]) + by mail.python.org with esmtp (Exim 4.05) + id 18GwM4-0000D4-00 + for mailman-users-admin@python.org; Wed, 27 Nov 2002 02:11:28 -0500 +Received: from root by tele-punt-22.mail.demon.net with local (Exim 2.12 #1) + id 18GwLf-0003ka-00 + for mailman-users-admin@python.org; Wed, 27 Nov 2002 07:11:03 +0000 +Subject: Mail delivery failure +Message-Id: +From: Mail Delivery System +To: mailman-users-admin@python.org +Date: Wed, 27 Nov 2002 07:11:03 +0000 +X-Spam-Status: No, hits=-2.5 required=5.0 + tests=FROM_MAILER_DAEMON,MAILER_DAEMON,MAILTO_WITH_SUBJ,SPAM_PHRASE_03_05 +X-Spam-Level: + +This message was created automatically by mail delivery +software. A message that you sent could not be delivered +to all of its recipients. + +The following message, addressed to 'james@jeborall.demon.co.uk', +failed because it has not been collected after 30 days + +Here is a copy of the first part of the message, including +all headers. + +---- START OF RETURNED MESSAGE ---- +Received: from punt-2.mail.demon.net by mailstore for james@jeborall.demon.co.uk + id 1035738253:20:01723:229; Sun, 27 Oct 2002 17:04:13 GMT +Received: from mail.python.org ([12.155.117.29]) by punt-2.mail.demon.net + id aa2004462; 27 Oct 2002 17:02 GMT +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 4.05) + id 185qn2-0007ru-00; Sun, 27 Oct 2002 12:01:28 -0500 +Date: Sun, 27 Oct 2002 12:00:04 -0500 +Message-ID: <20021027170004.27298.9909.Mailman@mail.python.org> +From: mailman-users-request@python.org +Subject: Mailman-Users digest, Vol 1 #2344 - 14 msgs +Reply-to: mailman-users@python.org +X-Mailer: Mailman v2.0.13 (101270) +MIME-version: 1.0 +Content-type: multipart/mixed; boundary=10.0.11.1.506.27298.1035738004.364.17787 +To: mailman-users@python.org +Sender: mailman-users-admin@python.org +Errors-To: mailman-users-admin@python.org +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0.13 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: + +--10.0.11.1.506.27298.1035738004.364.17787 +Content-type: text/plain; charset=us-ascii +Content-description: Masthead (Mailman-Users digest, Vol 1 #2344) + +Send Mailman-Users mailing list submissions to + mailman-users@python.org + +To subscribe or unsubscribe via the World Wide Web, visit + http://mail.python.org/mailman/listinfo/mailman-users +or, via email, send a message with subject or body 'help' to + mailman-users-request@python.org + +You can reach the person managing the list at + mailman-users-admin@python.org + +When replying, please edit your Subject line so it is more specific +than "Re: Contents of Mailman-Users digest..." + + +--10.0.11.1.506.27298.1035738004.364.17787 +Content-type: text/plain; charset=us-ascii +Content-description: Today's Topics (14 msgs) + +Today's Topics: + + 1. RELEASED Mailman 2.1 beta 4 (Barry A. Warsaw) + 2. bin/arch not working (Aparajita Fishman) + 3. Can't receive mail (Aparajita Fishman) + 4. I have the same problem with the list not sending mail..but + getting confirmations... (jared sanders) + 5. Re: RELEASED Mailman 2.1 beta 4 (Jeremy Portzer) + 6. Re: I have the same problem with the list not sending mail..but getting confirmations... (Aparajita Fishman) + 7. 2.1b4 problem (Fuzzy) + 8. inetd doesn't start mailman...? (Nick Arnett) + 9. Re: rejecting non-subscriber postings (G. Armour Van Horn) + 10. Re: No public lists? (Armando Soto Baeza) + 11. Re: No public lists? (Armando Soto Baeza) + 12. Re: I have the same problem with the list not sending mail..but getting confirmations... (Armando Soto Baeza) + 13. Re: Can't subscribe via web (Armando Soto Baeza) + +--10.0.11.1.506.27298.1035738004.364.17787 +Content-type: multipart/digest; boundary="__--__--" + +--__--__-- + +Message: 1 +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +Message-ID: <15802.52753.139705.927733@gargle.gargle.HOWL> +---- MESSAGE TRUNCATED ---- + diff --git a/inc/app/sitemailer2/tests/dsn_01.txt b/inc/app/sitemailer2/tests/dsn_01.txt new file mode 100644 index 00000000..d09768c6 --- /dev/null +++ b/inc/app/sitemailer2/tests/dsn_01.txt @@ -0,0 +1,217 @@ +From VM Wed Oct 4 02:03:34 2000 +Return-Path: +Delivered-To: zzzzz@mail.wooz.org +Received: from ns1.beopen.com (unknown [208.185.174.104]) + by mail.wooz.org (Postfix) with ESMTP id 0E701D37D5 + for ; Tue, 3 Oct 2000 18:33:46 -0400 (EDT) +Received: from dinsdale.python.org (dinsdale.cnri.reston.va.us [132.151.1.21]) + by ns1.beopen.com (8.9.3/8.9.3) with ESMTP id PAA65588 + for ; Tue, 3 Oct 2000 15:34:07 -0700 (PDT) + (envelope-from jpython-interest-admin@python.org) +Received: from dinsdale.python.org (localhost [127.0.0.1]) + by dinsdale.python.org (Postfix) with ESMTP id D2E691CC09 + for ; Tue, 3 Oct 2000 18:32:02 -0400 (EDT) +Delivered-To: jpython-interest-admin@python.org +Received: from mta01f.seamail.go.com (mta01f.seamail.go.com [204.202.140.193]) + by dinsdale.python.org (Postfix) with ESMTP id D33DA1CD8E + for ; Tue, 3 Oct 2000 18:31:09 -0400 (EDT) +Received: from msg00.seamail.go.com (msg00.seamail.go.com [10.212.0.32]) + by mta01.seamail.go.com + (Sun Internet Mail Server sims.4.0.2000.05.17.04.13.p6) with ESMTP id + <0G1V0040VJN3RY@mta01.seamail.go.com> for jpython-interest-admin@python.org; + Tue, 3 Oct 2000 14:57:04 -0700 (PDT) +Received: from process-daemon by msg00.seamail.go.com + (Sun Internet Mail Server sims.4.0.2000.05.17.04.13.p6) + id <0G1V00701JN2C7@msg00.seamail.go.com> for + jpython-interest-admin@python.org; Tue, 03 Oct 2000 14:57:02 -0700 (PDT) +Received: from msg00.seamail.go.com + (Sun Internet Mail Server sims.4.0.2000.05.17.04.13.p6) + id <0G1V00703JN1C6@msg00.seamail.go.com>; Tue, 03 Oct 2000 14:57:02 -0700 (PDT) +Message-id: <0G1V0070AJN2C6@msg00.seamail.go.com> +MIME-version: 1.0 +Content-type: MULTIPART/REPORT; + BOUNDARY="Boundary_(ID_+h6gzBCYzjhP3wCVCkWTrg)"; REPORT-TYPE=DELIVERY-STATUS +Errors-To: jpython-interest-owner@python.org +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , +List-Id: Python for the JavaTM Platform +List-Unsubscribe: , +List-Archive: +From: Internet Mail Delivery +Sender: jpython-interest-owner@python.org +To: jpython-interest-admin@python.org +Subject: Delivery Notification: Delivery has failed +Date: Tue, 03 Oct 2000 14:57:02 -0700 (PDT) +X-BeenThere: jpython-interest@python.org +X-Mailman-Version: 2.0beta6 + + +--Boundary_(ID_+h6gzBCYzjhP3wCVCkWTrg) +Content-type: text/plain; charset=ISO-8859-1 +Content-transfer-encoding: 7BIT + +This report relates to a message you sent with the following header fields: + + Message-id: + Date: Tue, 03 Oct 2000 19:28:29 +0000 (GMT) + From: heiho1@hotmail.com + To: thaank@nl.packardbell.org, jpython-interest@python.org + Subject: [JPython] Re: JPython testing framework + +Your message cannot be delivered to the following recipients: + + Recipient address: JimmyMcEgypt@sims-ms-daemon + Original address: JimmyMcEgypt@go.com + Reason: recipient reached disk quota + + +--Boundary_(ID_+h6gzBCYzjhP3wCVCkWTrg) +Content-type: message/DELIVERY-STATUS + +Reporting-MTA: dns;msg00.seamail.go.com + +Action: failed +Status: 5.0.0 (recipient reached disk quota) +Original-recipient: rfc822;JimmyMcEgypt@go.com +Final-recipient: rfc822;JimmyMcEgypt@sims-ms-daemon + +--Boundary_(ID_+h6gzBCYzjhP3wCVCkWTrg) +Content-type: MESSAGE/RFC822 + +Return-path: jpython-interest-admin@python.org +Received: from sims-ms-daemon by msg00.seamail.go.com + (Sun Internet Mail Server sims.4.0.2000.05.17.04.13.p6) + id <0G1V00703JN1C6@msg00.seamail.go.com>; Tue, 03 Oct 2000 14:57:01 -0700 (PDT) +Received: from mta01.seamail.go.com (mta01.seamail.go.com [10.212.0.193]) + by msg00.seamail.go.com + (Sun Internet Mail Server sims.4.0.2000.05.17.04.13.p6) with ESMTP id + <0G1V00L69JG1BD@msg00.seamail.go.com> for JimmyMcEgypt@sims-ms-daemon + (ORCPT rfc822;JimmyMcEgypt@go.com); Tue, 03 Oct 2000 14:56:57 -0700 (PDT) +Received: from dinsdale.python.org (dinsdale.cnri.reston.va.us [132.151.1.21]) + by mta01.seamail.go.com + (Sun Internet Mail Server sims.4.0.2000.05.17.04.13.p6) with ESMTP id + <0G1V004NTCTFPX@mta01.seamail.go.com> for JimmyMcEgypt@msg00.seamail.go.com + (ORCPT rfc822;JimmyMcEgypt@go.com); Tue, 03 Oct 2000 12:29:39 -0700 (PDT) +Received: from dinsdale.python.org (localhost [127.0.0.1]) + by dinsdale.python.org (Postfix) with ESMTP id 76FC61CF28; Tue, + 03 Oct 2000 15:29:27 -0400 (EDT) +Received: from hotmail.com (f121.pav1.hotmail.com [64.4.31.121]) + by dinsdale.python.org (Postfix) with ESMTP id AFF4D1CD11 for + ; Tue, 03 Oct 2000 15:28:28 -0400 (EDT) +Received: from mail pickup service by hotmail.com with Microsoft SMTPSVC; Tue, + 03 Oct 2000 12:28:29 -0700 +Received: from 206.41.27.49 by pv1fd.pav1.hotmail.msn.com with HTTP; Tue, + 03 Oct 2000 19:28:29 +0000 (GMT) +Date: Tue, 03 Oct 2000 19:28:29 +0000 (GMT) +From: heiho1@hotmail.com +Subject: [JPython] Re: JPython testing framework +X-Originating-IP: [206.41.27.49] +Sender: jpython-interest-admin@python.org +To: thaank@nl.packardbell.org, jpython-interest@python.org +Errors-to: jpython-interest-admin@python.org +Message-id: +MIME-version: 1.0 +Content-type: text/plain; format=flowed +Content-transfer-encoding: 7BIT +Precedence: bulk +Delivered-to: jpython-interest@python.org +X-BeenThere: jpython-interest@python.org +X-Mailman-Version: 2.0beta6 +List-Post: +List-Subscribe: , + +List-Unsubscribe: , + +List-Archive: +List-Help: +List-Id: Python for the JavaTM Platform + +X-OriginalArrivalTime: 03 Oct 2000 19:28:29.0320 (UTC) + FILETIME=[1BD98080:01C02D70] + +Otto, + +Thanks for the reply. I remembered hearing of this PyUnit but had lost +track of it for a while. I just visited the sourceforge homepage: + +http://pyunit.sourceforge.net/pyunit.html + +I'm pretty sure that PyUnit [as its coded to Python 1.5.2] should be +workable with JPython, but the web page says: + +""" +PyUnit cannot be used with JPython, the users of which should probably use +JUnit and create JPython subclasses of its TestCase class. I haven't tried +doing this. +""" + +Now, I don't see why this would be the case, so I'm going to download PyUnit +and sniff around. Are any of these modifications you mentioned to get +PyUnit running under JPython published on the Web anywhere? I'd like to +take a look, as they would probably save me some time. + +Thanks again, + +James + +> +>James, +> +>I'm using PyUnit from within JPython to drive unit tests that test a Java +>applications. Some minor changes had to be made to PyUnit to make it work +>with JPython, and the testrunner only works textually. But nevertheless, +>it's a much better option than using JUnit from within JPython. +> +>-Otto Perdeck +> +> +>Hello all, +> +>I've used JPython for close to two years and I find the language to be +>indispensable. The recent, protracted silence regarding the "official" +>status of JPython has concerned me quite a bit as I didn't want this +>language to die out when it shows such promise. +> +>I hope that BeOpen and CNRI can come to an agreement that will benefit the +>community as a whole. +> +>Regardless, my major use of JPython [due to the status of the 1.1 release +>and its errata (not an attack on Finn Bock, just an engineer not willing to +>deploy certain software on "unofficial" patches)] has been to facilitate +>prototyping and [almost ;)] XP style repetitive testing. My interest is if +>a JPython testing framework exists? Something that is a JUnit for JPython, +>but with functional level testing as well [similar to what Inline-Standard +>provides: http://www.inline-software.com/products/datasheet.html but not +>restricted to EJBs]. +> +>If not, what is the interest of the JPython mailing list on collaborating +>to +>produce such an entity [maybe sourceforge.net]? +> +>Also, has anybody played around with AspectJ [ www.aspectj.org very cool +>stuff ;)] and JPython? It seems that AOP and JPython could be a pretty +>good +>one-two punch for knocking out larger scale Java problems. +> +>James Richards +>Java Software Engineer +> +> +>- Tjitske Haank & Otto Perdeck + +_________________________________________________________________________ +Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com. + +Share information about yourself, create your own public profile at +http://profiles.msn.com. + + +_______________________________________________ +JPython-Interest maillist - JPython-Interest@python.org +http://www.python.org/mailman/listinfo/jpython-interest + +--Boundary_(ID_+h6gzBCYzjhP3wCVCkWTrg)-- + + diff --git a/inc/app/sitemailer2/tests/dsn_02.txt b/inc/app/sitemailer2/tests/dsn_02.txt new file mode 100644 index 00000000..3525605f --- /dev/null +++ b/inc/app/sitemailer2/tests/dsn_02.txt @@ -0,0 +1,187 @@ +From VM Tue Dec 26 18:03:42 2000 +Return-Path: +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.3.1) + with ESMTP id 399952 for xxxxx@mail.digicool.com; Tue, 26 Dec 2000 16:49:08 -0500 +Received: from mail.python.org (starship.python.net [63.102.49.30]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id QAA00928 + for ; Tue, 26 Dec 2000 16:49:01 -0500 +Received: from ns1.zope.org (localhost.localdomain [127.0.0.1]) + by mail.python.org (Postfix) with ESMTP id 0CE1CE9B2 + for ; Tue, 26 Dec 2000 16:48:01 -0500 (EST) +Delivered-To: mm+python-list-admin@python.org +Received: from cata.hud.ac.uk (cata.hud.ac.uk [161.112.232.16]) + by mail.python.org (Postfix) with ESMTP id 5398EE9B2 + for ; Tue, 26 Dec 2000 16:47:33 -0500 (EST) +Received: from hud.ac.uk by cata.hud.ac.uk id <13167-0@cata.hud.ac.uk>; + Tue, 26 Dec 2000 21:47:28 +0000 +Message-Type: Delivery Report +X400-Received: by /PRMD=UK.AC/ADMD= /C=GB/; Relayed; + Tue, 26 Dec 2000 21:47:27 +0000 +X400-Received: by mta cata.hud.ac.uk in /PRMD=UK.AC/ADMD= /C=GB/; Relayed; + Tue, 26 Dec 2000 21:47:27 +0000 +X400-MTS-Identifier: [/PRMD=UK.AC/ADMD= /C=GB/;cata.hud.a:131600:20001226214727] +Message-ID: <"cata.hud.a:131600:20001226214727"@hud.ac.uk> +Content-Identifier: RE: A Q conce... +MIME-Version: 1.0 +Content-Type: multipart/report; boundary="---Multi-Part-Report-Level-1-1-13166" +Errors-To: python-list-owner@python.org +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: postmaster@hud.ac.uk +Sender: python-list-owner@python.org +To: python-list-admin@python.org +Subject: Delivery Report (failure) for zzzzz@zeus.hud.ac.uk +Date: Tue, 26 Dec 2000 21:47:28 +0000 +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0 + + +-----Multi-Part-Report-Level-1-1-13166 + +This report relates to your message: +Subject: RE: A Q concerning map (a comparison to Maple V), + Message-ID: , + To: + +of Tue, 26 Dec 2000 21:47:27 +0000 + +Your message was not delivered to: + zzzzz@zeus.hud.ac.uk +for the following reason: +Diagnostic was Unable to transfer, Message timed out +Information Message timed out + +The Original Message follows: + +-----Multi-Part-Report-Level-1-1-13166 +Content-Type: message/delivery-status + +Reporting-MTA: x400; mta cata.hud.ac.uk in /PRMD=UK.AC/ADMD= /C=GB/ +Arrival-Date: Sat, 23 Dec 2000 21:44:56 +0000 +DSN-Gateway: dns; cata.hud.ac.uk +X400-Conversion-Date: Tue, 26 Dec 2000 21:47:28 +0000 +Original-Envelope-Id: [/PRMD=UK.AC/ADMD= /C=GB/;, + To: + +Original-Recipient: rfc822; zzzzz@zeus.hud.ac.uk +Final-Recipient: x400; /S=zzzzz/OU=zeus/O=hud/PRMD=UK.AC/ADMD= /C=GB/ +X400-Originally-Specified-Recipient-Number: 1 +Action: failed +Diagnostic-Code: Reason 1 (Unable-To-Transfer); Diagnostic 5 (Maximum-Time-Expired) +Status: 4.4.7 +X400-Supplementary-Info: "Message timed out" +X400-Last-Trace: Sat, 23 Dec 2000 21:44:56 +0000 + +-----Multi-Part-Report-Level-1-1-13166 +Content-Type: message/rfc822 + +Received: from mail.python.org (actually host starship.python.net) + by cata.hud.ac.uk with SMTP (Mailer); Sat, 23 Dec 2000 21:44:56 +0000 +Received: from ns1.zope.org (localhost.localdomain [127.0.0.1]) + by mail.python.org (Postfix) with ESMTP id 9200FEB18; + Sat, 23 Dec 2000 13:10:09 -0500 (EST) +Delivered-To: mm+python-list@python.org +Received: from mail.rdc1.md.home.com (ha1.rdc1.md.home.com [24.2.2.66]) + by mail.python.org (Postfix) with ESMTP id 9FA2AEC45 + for ; Sat, 23 Dec 2000 12:35:46 -0500 (EST) +Received: from cj569191b ([65.1.136.53]) + by mail.rdc1.md.home.com (InterMail vM.4.01.03.00 201-229-121) + with SMTP + id <20001223173546.KSYS10139.mail.rdc1.md.home.com@cj569191b> + for ; Sat, 23 Dec 2000 09:35:46 -0800 +From: Tim Peters +To: python-list +Subject: RE: A Q concerning map (a comparison to Maple V) +Message-ID: +MIME-Version: 1.0 +Content-Type: text/plain; charset="iso-8859-1" +Content-Transfer-Encoding: 7bit +X-Priority: 3 (Normal) +X-MSMail-Priority: Normal +X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2911.0) +X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4522.1200 +In-Reply-To: <3A448735.4DF3C95C@schneider-kamp.de> +Importance: Normal +Sender: python-list-admin@python.org +Errors-To: python-list-admin@python.org +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language + +List-Unsubscribe: , + +List-Archive: +Date: Sat, 23 Dec 2000 12:35:50 -0500 + +[Franz GEIGER] +> > map(replace, ["abc", "cde"], "c", "C"); +> > instead of having to create a lambda function. +> > Wouldn't it make sense to have that in Python too? Do there come +> > more such opportunities into your mind? + +[Peter Schneider-Kamp] +> If I get you right you intend this to mean: +> +> map(replace, ["abc", "cde"], ["c"]*2, ["C"]*2) +> +> So basically your proposal is to reuse map parameters +> which are no sequences in every iteration over the +> parameters who are, + +It's hard to tell for sure, but that was my guess too. In array languages, +this kind of thing is ubiquitous and is often called "scalar broadcast" +(where a scalar is any atomic value (as opposed to an array), and is +"broadcast" to every position of the arrays in which it's combined via some +operation). + +There was a long debate about this a few years ago on c.l.py, where I +championed scalar broadcast in map specifically. It collapsed under its own +hideous weight when-- as such things always do --that originally +modest goal got hijacked by people seeking to extend the semantics to every +corner of the language. That won't happen. + +> ... +> But how would you decide if "abc" is a sequence parameter +> or not? + +That is a problem! Kinda. Mostly people want to broadcast numbers (as in +Franz's original example), and there's no problem there. A cheap workaround +for sequences that are desired to be treated as scalars would have been to +introduce a new builtin scalar() function, that simply hid the +"sequenceness" of its argument from map. + +Note that the listcomps in 2.0 make scalar broadcast much easier to spell; +e.g. + + [replace(x, "c", "C") for x in ("abc", "cde")] + [x**2 + 5 for x in L] + +So the better solution is not to extend map, but to forget it <0.9 wink>. + +a-life-strategy-of-universal-applicability-ly y'rs - tim + + +-- +http://www.python.org/mailman/listinfo/python-list + +-----Multi-Part-Report-Level-1-1-13166-- + + diff --git a/inc/app/sitemailer2/tests/dsn_03.txt b/inc/app/sitemailer2/tests/dsn_03.txt new file mode 100644 index 00000000..4e4fef05 --- /dev/null +++ b/inc/app/sitemailer2/tests/dsn_03.txt @@ -0,0 +1,144 @@ +From VM Fri Feb 9 13:30:37 2001 +Return-Path: +Delivered-To: zzzzz@wwwww.org +Received: from digicool.com (host15.digitalcreations.d.subnet.rcn.com [208.59.6.15]) + by mail.wwwww.org (Postfix) with ESMTP id 1E50CD37AC + for ; Thu, 8 Feb 2001 07:31:12 -0500 (EST) +Received: from + by digicool.com (CommuniGate Pro RULES 3.3.2) + with RULES id 1450363; Thu, 08 Feb 2001 07:33:30 -0500 +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.3.2) + with ESMTP id 1450362 for yyyyy@mail.digicool.com; Thu, 08 Feb 2001 07:33:30 -0500 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id HAA17520 + for ; Thu, 8 Feb 2001 07:32:00 -0500 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14QqF1-0002hJ-00 + for yyyyy@digicool.com; Thu, 08 Feb 2001 07:32:03 -0500 +Received: from [194.78.23.194] (helo=pigeon.advalvas.be) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14QqCJ-0002UN-00 + for python-list-admin@python.org; Thu, 08 Feb 2001 07:29:15 -0500 +Message-Id: <12334670553230@pigeon.advalvas.be> +Mime-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; boundary="==_12334670553231@pigeon.advalvas.be==_" +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: "postmaster@advalvas.be" +Sender: python-list-owner@python.org +To: "python-list-admin@python.org" +Subject: Failed mail: exceeded maximum incoming message size +Date: Thu, 8 Feb 2001 13:33:46 +0100 +X-Autogenerated: Mirror +X-Mirrored-by: +X-Mailer: NTMail v5.06.0014 +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.1 (101270) + +This is a MIME-encapsulated message + +--==_12334670553231@pigeon.advalvas.be==_ +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +Content-Disposition: inline + +Your message was not delivered to + + ddd.kkk@advalvas.be + +This mail message has exceeded the maximum incoming message size. + + +--==_12334670553231@pigeon.advalvas.be==_ +Content-Type: message/delivery-status +Content-Transfer-Encoding: 7bit +Content-Disposition: inline + +Reporting-MTA: dns;pigeon.net7.be + +Final-Recipient: rfc822;ddd.kkk@advalvas.be +Action: failure +Status: 553 Exceeded maximum inbound message size + + +--==_12334670553231@pigeon.advalvas.be==_ +Content-Type: message/rfc822 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline + +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14Qq5S-0001zk-00; Thu, 08 Feb 2001 07:22:10 -0500 +Received: from [193.123.0.194] (helo=intrepid.trisystems.co.uk) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14Qq2n-0001kA-00 + for python-list@python.org; Thu, 08 Feb 2001 07:19:25 -0500 +Received: by intrepid with Internet Mail Service (5.5.2650.21) + id <11PN1RRB>; Thu, 8 Feb 2001 12:21:16 -0000 +Message-ID: <31575A892FF6D1118F5800600846864D5B17D1@intrepid> +From: Simon Brunning +To: 'Ggggg Wwwww' , Python Mailling list + +Subject: RE: None assigment +MIME-Version: 1.0 +X-Mailer: Internet Mail Service (5.5.2650.21) +Content-Type: text/plain +Sender: python-list-admin@python.org +Errors-To: python-list-admin@python.org +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.1 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +Date: Thu, 8 Feb 2001 12:20:27 -0000 + +> From: Ggggg Wwwww [SMTP:ggg@pppeval.be] +> While playing a bit with python 2.0, I found that I can assign some value +> to None +(snip) +> If it is a feature (I suppose it is not a bug :), what is the interest of +> this ? + +Feature. 'None' is just a label, and just like any other label, you can +always assign to it. I'm not aware of any way of preventing a label from +being assigned to. + +Doesn't make it a good idea, though... + +Cheers, +TriSystems Ltd. +sssss@trisystems.co.uk + + + + + +----------------------------------------------------------------------- +The information in this email is confidential and may be legally privileged. +It is intended solely for the addressee. Access to this email by anyone else +is unauthorised. If you are not the intended recipient, any disclosure, +copying, distribution, or any action taken or omitted to be taken in +reliance on it, is prohibited and may be unlawful. TriSystems Ltd. cannot +accept liability for statements made which are clearly the senders own. + +-- +http://mail.python.org/mailman/listinfo/python-list + +--==_12334670553231@pigeon.advalvas.be==_-- + + diff --git a/inc/app/sitemailer2/tests/dsn_04.txt b/inc/app/sitemailer2/tests/dsn_04.txt new file mode 100644 index 00000000..9bea9758 --- /dev/null +++ b/inc/app/sitemailer2/tests/dsn_04.txt @@ -0,0 +1,202 @@ +From VM Sat Jun 30 11:29:01 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Saturday" "30" "June" "2001" "00:21:42" "+0200" "PMDF e-Mail Interconnect" "postmaster@yogi.urz.unibas.ch" nil "147" "Delivery Notification: Delivery has failed" "^From:" nil nil "6" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: barry@wooz.org +Received: from digicool.com (unknown [63.100.190.15]) + by mail.wooz.org (Postfix) with ESMTP id 2852FD36EC + for ; Fri, 29 Jun 2001 18:21:58 -0400 (EDT) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 2122693; Fri, 29 Jun 2001 18:23:52 -0400 +Received: from ns2.digicool.com ([63.100.190.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 2122692 for barry@mail.digicool.com; Fri, 29 Jun 2001 18:23:52 -0400 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id SAA15102 + for ; Fri, 29 Jun 2001 18:22:00 -0400 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15G6eH-0006NJ-00 + for barry@digicool.com; Fri, 29 Jun 2001 18:22:01 -0400 +Received: from [131.152.1.4] (helo=yogi.urz.unibas.ch) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15G6d4-0006Lg-00 + for python-list-admin@python.org; Fri, 29 Jun 2001 18:20:46 -0400 +Received: from PROCESS-DAEMON by yogi.urz.unibas.ch (PMDF V5.2-29 #33343) + id <01K5CWRKUM2O8X1X1D@yogi.urz.unibas.ch> for python-list-admin@python.org; + Sat, 30 Jun 2001 00:21:44 +0200 +Received: from yogi.urz.unibas.ch (PMDF V5.2-29 #33343) + id <01K5CWRINUF48X46F4@yogi.urz.unibas.ch>; Sat, 30 Jun 2001 00:21:42 +0200 +Message-id: <01K5CWRJIDYU8X46F4@yogi.urz.unibas.ch> +MIME-version: 1.0 +Content-type: MULTIPART/REPORT; + BOUNDARY="Boundary_(ID_MUSA353qRe9PeqtdeP14tg)"; REPORT-TYPE=DELIVERY-STATUS +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: PMDF e-Mail Interconnect +Sender: python-list-owner@python.org +To: python-list-admin@python.org +Subject: Delivery Notification: Delivery has failed +Date: Sat, 30 Jun 2001 00:21:42 +0200 +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.5 (101270) + + +--Boundary_(ID_MUSA353qRe9PeqtdeP14tg) +Content-type: text/plain; charset=us-ascii +Content-language: EN-US + +This report relates to a message you sent with the following header fields: + + Message-id: + Date: Sat, 30 Jun 2001 00:18:49 +0200 (CEST) + From: Carsten Geckeler + To: Python + Subject: Re: Augmented Assignement (was: Re: PEP scepticism) + +Your message cannot be delivered to the following recipients: + + Recipient address: HAASM@yogi.urz.unibas.ch + Original address: max.haas@unibas.ch +%MAIL-E-OPENOUT, error opening !AS as output +-RMS-E-CRE, ACP file create failed +-SYSTEM-F-EXDISKQUOTA, disk quota exceeded + + +--Boundary_(ID_MUSA353qRe9PeqtdeP14tg) +Content-type: message/DELIVERY-STATUS + +Original-envelope-id: 0GFP00202Q2DR3@mailhub.unibas.ch +Reporting-MTA: dns;yogi.urz.unibas.ch + +Action: failed +Status: 5.0.0 +Original-recipient: rfc822;max.haas@unibas.ch +Final-recipient: rfc822;HAASM@yogi.urz.unibas.ch + +--Boundary_(ID_MUSA353qRe9PeqtdeP14tg) +Content-type: MESSAGE/RFC822 + +Return-path: python-list-admin@python.org +Received: from yogi.urz.unibas.ch by yogi.urz.unibas.ch (PMDF V5.2-29 #33343) + id <01K5CWRINUF48X46F4@yogi.urz.unibas.ch> + (original mail from python-list-admin@python.org); Sat, + 30 Jun 2001 00:21:42 +0200 +Received: from maser.urz.unibas.ch ([131.152.1.5]) + by yogi.urz.unibas.ch (PMDF V5.2-29 #33343) + with ESMTP id <01K5CWRGK0V68X4CRC@yogi.urz.unibas.ch> for + HAASM@yogi.urz.unibas.ch (ORCPT rfc822;max.haas@unibas.ch); Sat, + 30 Jun 2001 00:21:38 +0200 +Received: from DIRECTORY-DAEMON.mailhub.unibas.ch by mailhub.unibas.ch + (PMDF V6.0-24 #41480) id <0GFP00201Q2DR3@mailhub.unibas.ch> for + HAASM@yogi.urz.unibas.ch (ORCPT max.haas@unibas.ch); Sat, + 30 Jun 2001 00:20:37 +0200 (MET DST) +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by mailhub.unibas.ch (PMDF V6.0-24 #41480) + with ESMTP id <0GFP00BEAQ2C5Y@mailhub.unibas.ch> for max.haas@unibas.ch; Sat, + 30 Jun 2001 00:20:37 +0200 (MET DST) +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) id 15G6bK-0006HW-00; Fri, + 29 Jun 2001 18:18:58 -0400 +Received: from [134.2.34.92] (helo=nemesis.jura.uni-tuebingen.de ident=qmailr) + by mail.python.org with smtp (Exim 3.21 #1) + id 15G6Zp-0006Ee-00 for python-list@python.org; Fri, 29 Jun 2001 18:17:25 -0400 +Received: (qmail 31643 invoked from network); Fri, 29 Jun 2001 22:17:24 +0000 +Received: from justitia.jura.uni-tuebingen.de (mail@134.2.34.12) + by nemesis.jura.uni-tuebingen.de with SMTP; Fri, 29 Jun 2001 22:17:24 +0000 +Received: from s-gec3 by justitia.jura.uni-tuebingen.de with local + (Exim 3.12 #1 (Debian)) id 15G6Zo-0002Zx-00 for ; Sat, + 30 Jun 2001 00:17:24 +0200 +Date: Sat, 30 Jun 2001 00:18:49 +0200 (CEST) +From: Carsten Geckeler +Subject: Re: Augmented Assignement (was: Re: PEP scepticism) +In-reply-to: +Sender: python-list-admin@python.org +To: Python +Errors-to: python-list-admin@python.org +Message-id: +MIME-version: 1.0 +Content-type: TEXT/PLAIN; charset=US-ASCII +Precedence: bulk +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.5 (101270) +List-Post: +List-Subscribe: , + +List-Unsubscribe: , + +List-Archive: +List-Help: +List-Id: General discussion list for the Python programming language + + +On 29 Jun 2001, David Bolen wrote: + +> Carsten Geckeler writes: +> +> > The problem which some people have with augmented assignment is not that +> > they exist, but that they do not work as they expect (at least from the +> > POV of some readers). I expect that +> > ident op= expr +> > works like +> > ident = ident op expr +> > +> > At least that's what I'd have expectd comming from other programming +> > languages. +> +> Of course, one interesting point is that while you may think the above +> if coming from, say, C, what "ident = ident op expr" means in C is not +> what "ident = ident op expr" means in Python. + +Yes, that's completely true. I can accept, that Python work differently +in many cases. Actually I love Python's object stuff. That's something +more natural that in many other languages. And I can accept, that objects +(which are bound to different variable names) can be changed (like with +l.extend). + +The point is not that Python differs from C (or other languages), but that +the two statements above work differently. I can accept that, of course +(well I have to, I thing ;) ). But, when I write the following three +statements, + l = l + [3, 4] + l += [3, 4] + l.extend([3,4]) +it seems more logical to me, that the first two do the same than the last +two. I know, of course, that the last two do the same. But anyway, the +first two just _look_ more the same. + +> In C it has the result of changing data (in either case) that is +> stored in a named location ident, in Python the long form just rebinds +> the reference ident to a new object and doesn't touch the original +> object. The short form can actually get closer to the C idiom if the +> object is mutable. +> +> So I wonder if some of the confusion is people familiar with other +> language's augmented assignment trying to extrapolate that into Python +> and then running into the pre-existing differences in assignment +> versus binding? + +No, that's at least no problem for me (see above). + +Cheers, Carsten +-- +Carsten Geckeler + + +-- +http://mail.python.org/mailman/listinfo/python-list + +--Boundary_(ID_MUSA353qRe9PeqtdeP14tg)-- + + diff --git a/inc/app/sitemailer2/tests/dsn_05.txt b/inc/app/sitemailer2/tests/dsn_05.txt new file mode 100644 index 00000000..73331578 --- /dev/null +++ b/inc/app/sitemailer2/tests/dsn_05.txt @@ -0,0 +1,125 @@ +From VM Wed Mar 21 22:20:23 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Thursday" "22" "March" "2001" "02:52:34" "+0100" "postmaster@relay.atlas.cz" "postmaster@relay.atlas.cz" nil "76" "Message delayed (pkocmid@atlas.cz)" "^From:" nil nil "3" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: bwarsaw@wooz.org +Received: from digicool.com (host15.digitalcreations.d.subnet.rcn.com [208.59.6.15]) + by mail.wooz.org (Postfix) with ESMTP id 97D9ED37AC + for ; Wed, 21 Mar 2001 21:34:33 -0500 (EST) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 1706776; Wed, 21 Mar 2001 21:39:26 -0500 +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 1706775 for barry@mail.digicool.com; Wed, 21 Mar 2001 21:39:26 -0500 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id VAA12152 + for ; Wed, 21 Mar 2001 21:36:03 -0500 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14fuxH-0002AK-00 + for barry@digicool.com; Wed, 21 Mar 2001 21:36:03 -0500 +Received: from [195.119.187.242] (helo=cuk.atlas.cz) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14fuwk-00028x-00 + for python-list-admin@python.org; Wed, 21 Mar 2001 21:35:31 -0500 +Message-Id: +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; boundary="45817/808/985225954/VOPmail/cuk.atlas.cz" +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: postmaster@relay.atlas.cz +Sender: python-list-owner@python.org +To: python-list-admin@python.org +Subject: Message delayed (pkocmid@atlas.cz) +Date: Thu, 22 Mar 2001 02:52:34 +0100 +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.3 (101270) + +--45817/808/985225954/VOPmail/cuk.atlas.cz +Content-Type: text/plain + +Your message has been delayed and is still awaiting delivery +to the following recipient(s): + +pkocmid@atlas.cz +Message delayed + + +Your message is delayed +Message for domain atlas.cz delayed at relay.atlas.cz. +Unable to deliver to domain for 12 hours. +Will continue trying for 96 hours. +No action is required on your part. +Last attempt failed because: +Can't connect to host + + +--45817/808/985225954/VOPmail/cuk.atlas.cz +Content-Type: message/delivery-status + +Reporting-MTA: dns; cuk.atlas.cz +Received-From-MTA: dns; mail.python.org (unverified [63.102.49.29]) +Arrival-Date: Wed, 21 Mar 2001 15:08:54 +0100 + +Final-Recipient: rfc822; pkocmid@atlas.cz +Action: delayed +Status: 4.4.1 (Persistent transient failure - routing/network: no answer from host) +Will-Retry-Until: Mon, 26 Mar 2001 03:42:45 +0100 + +--45817/808/985225954/VOPmail/cuk.atlas.cz +Content-Type: message/rfc822-headers + +Received: from mail.python.org (unverified [63.102.49.29]) by cuk.atlas.cz + (Vircom SMTPRS 4.5.186) with ESMTP id for ; + Wed, 21 Mar 2001 15:08:54 +0100 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14fjGM-0007PZ-00; Wed, 21 Mar 2001 09:06:58 -0500 +Path: news.baymountain.net!uunet!ash.uu.net!sac.uu.net!newsfeed.attap.net!enews.sgi.com!feeder.via.net!news.he.net!typhoon.aracnet.com!not-for-mail +From: Daniel Klein +Newsgroups: comp.lang.python +Subject: Re: Pick Systems D3 Database +Message-ID: +References: +X-Newsreader: Forte Agent 1.8/32.548 +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +Lines: 25 +NNTP-Posting-Host: 216.99.212.46 +X-Complaints-To: news@aracnet.com +X-Trace: typhoon.aracnet.com 985183028 216.99.212.46 (Wed, 21 Mar 2001 05:57:08 PST) +NNTP-Posting-Date: Wed, 21 Mar 2001 05:57:08 PST +Organization: Aracnet Internet +Xref: news.baymountain.net comp.lang.python:93719 +To: python-list@python.org +Sender: python-list-admin@python.org +Errors-To: python-list-admin@python.org +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.3 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +Date: Wed, 21 Mar 2001 06:05:14 -0800 + +--45817/808/985225954/VOPmail/cuk.atlas.cz-- + + + diff --git a/inc/app/sitemailer2/tests/dsn_06.txt b/inc/app/sitemailer2/tests/dsn_06.txt new file mode 100644 index 00000000..22f69760 --- /dev/null +++ b/inc/app/sitemailer2/tests/dsn_06.txt @@ -0,0 +1,122 @@ +From VM Mon Jul 2 04:05:06 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Sunday" "1" "July" "2001" "16:07:50" "+0200" "Mail Delivery Service" "mailadm@thales-is.com" nil "72" "Delivery Status Notification (Mail Delivery Delayed)" "^From:" nil nil "7" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: barry@wooz.org +Received: from digicool.com (unknown [63.100.190.15]) + by mail.wooz.org (Postfix) with ESMTP id 1F5FED36EC + for ; Sun, 1 Jul 2001 10:07:00 -0400 (EDT) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 2125237; Sun, 01 Jul 2001 10:08:57 -0400 +Received: from ns2.digicool.com ([63.100.190.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 2125244 for barry@mail.digicool.com; Sun, 01 Jul 2001 10:08:57 -0400 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id KAA26383 + for ; Sun, 1 Jul 2001 10:07:00 -0400 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15GhsL-0001Ey-00 + for barry@digicool.com; Sun, 01 Jul 2001 10:07:01 -0400 +Received: from [195.101.39.226] (helo=gwsmtp.thomson-csf.com) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15GhrZ-0001D4-00 + for python-list-admin@python.org; Sun, 01 Jul 2001 10:06:13 -0400 +Received: by gwsmtp.thomson-csf.com (NPlex 5.1.053) id 3B3CE20D00005041 for python-list-admin@python.org; Sun, 1 Jul 2001 16:07:50 +0200 +Message-ID: <3B3CE20D0000503F@gwsmtp.thomson-csf.com> +MIME-Version: 1.0 +Content-Type: Multipart/Report; report-type=delivery-status; boundary="=========3B3CE20D00004815/gwsmtp.thomson-csf.com" +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: Mail Delivery Service +Sender: python-list-owner@python.org +To: python-list-admin@python.org +Subject: Delivery Status Notification (Mail Delivery Delayed) +Date: Sun, 1 Jul 2001 16:07:50 +0200 +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.5 (101270) + +This multi-part MIME message contains a Delivery Status Notification. +If you can see this text, your mail client may not be able to understand MIME +formatted messages or DSNs (see RFC 2045 through 2049 for general MIME +information and RFC 1891 through 1894 for DSN specific information). + +--=========3B3CE20D00004815/gwsmtp.thomson-csf.com +Content-Type: text/plain; charset=us-ascii + + - This is only a notification about a delay in the delivery of your message. + - There is no need to resend your message at this time. + - The following recipients have not yet received your message: + +hao-nghi.au@fr.thalesgroup.com; Action: Delayed + + - The server will continue trying for up to 21 hours. + + +--=========3B3CE20D00004815/gwsmtp.thomson-csf.com +Content-Type: Message/Delivery-Status + +Reporting-MTA: dns; gwsmtp.thomson-csf.com +Received-from-MTA: dns; mail.python.org (63.102.49.29) +Arrival-Date: Sun, 1 Jul 2001 13:07:44 +0200 + +Final-Recipient: rfc822; hao-nghi.au@fr.thalesgroup.com +Action: Delayed +Status: 4.4.0 (other or undefined network or routing status) +Will-Retry-Until: Mon, 2 Jul 2001 13:07:44 +0200 + +--=========3B3CE20D00004815/gwsmtp.thomson-csf.com +Content-Type: Text/RFC822-headers + +Return-Path: +Received: from mail.python.org (63.102.49.29) by gwsmtp.thomson-csf.com (NPlex 5.1.053) + id 3B3CE20D00004815 for hao-nghi.au@fr.thalesgroup.com; Sun, 1 Jul 2001 13:07:44 +0200 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15Gf3C-0005ft-00; Sun, 01 Jul 2001 07:06:02 -0400 +Path: news.baymountain.net!uunet!ash.uu.net!dca.uu.net!feed2.onemain.com!feed1.onemain.com!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!fu-berlin.de!hahn.informatik.hu-berlin.de!not-for-mail +From: Martin von Loewis +Newsgroups: comp.lang.python +Subject: Re: GCC 3.0, Standard ABI & C++/Python Integration +Organization: Humboldt University Berlin, Department of Computer Science +Lines: 8 +Message-ID: +References: +NNTP-Posting-Host: pandora.informatik.hu-berlin.de +X-Trace: hahn.informatik.hu-berlin.de 993984634 26083 141.20.23.176 (1 Jul 2001 10:50:34 GMT) +X-Complaints-To: news@hahn.informatik.hu-berlin.de +NNTP-Posting-Date: 1 Jul 2001 10:50:34 GMT +X-Newsreader: Gnus v5.7/Emacs 20.7 +Xref: news.baymountain.net comp.lang.python:110477 +To: python-list@python.org +Sender: python-list-admin@python.org +Errors-To: python-list-admin@python.org +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.5 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +Date: 01 Jul 2001 12:50:34 +0200 + + +--=========3B3CE20D00004815/gwsmtp.thomson-csf.com-- + + + diff --git a/inc/app/sitemailer2/tests/dsn_07.txt b/inc/app/sitemailer2/tests/dsn_07.txt new file mode 100644 index 00000000..2e5a0e5d --- /dev/null +++ b/inc/app/sitemailer2/tests/dsn_07.txt @@ -0,0 +1,121 @@ +From VM Wed Aug 1 17:56:11 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Thursday" "2" "August" "2001" "08:02:07" "+1200" "postmaster@Parliament.govt.nz" "postmaster@Parliament.govt.nz" nil "73" "Message delayed (david.farrar@parliament.govt.nz)" "^From:" "mailman-users-admin@python.org" "mailman-users-admin@python.org" "8" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: barry@wooz.org +Received: from digicool.com (unknown [63.100.190.15]) + by mail.wooz.org (Postfix) with ESMTP id D431ED35F0 + for ; Wed, 1 Aug 2001 16:26:59 -0400 (EDT) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 2462291; Wed, 01 Aug 2001 16:27:02 -0400 +Received: from smtp.zope.com ([63.100.190.10] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 2462289 for barry@mail.zope.com; Wed, 01 Aug 2001 16:27:02 -0400 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by smtp.zope.com (8.11.2/8.11.2) with ESMTP id f71KR2X19854 + for ; Wed, 1 Aug 2001 16:27:02 -0400 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15S2a4-0003D5-00; Wed, 01 Aug 2001 16:27:00 -0400 +Received: from [203.97.232.93] (helo=ns1.parliament.govt.nz) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15S2Z4-0003Bh-00 + for mailman-users-admin@python.org; Wed, 01 Aug 2001 16:25:59 -0400 +Message-Id: +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; boundary="23/89/996696127/MAILsweeper/ns1.parliament.govt.nz" +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +From: postmaster@Parliament.govt.nz +Sender: mailman-users-owner@python.org +To: mailman-users-admin@python.org +Subject: Message delayed (david.farrar@parliament.govt.nz) +Date: Thu, 2 Aug 2001 08:02:07 +1200 +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0.6 (101270) + +--23/89/996696127/MAILsweeper/ns1.parliament.govt.nz +Content-Type: text/plain + +Your message has been delayed and is still awaiting delivery +to the following recipient(s): + +david.farrar@Parliament.govt.nz +(Was addressed to david.farrar@parliament.govt.nz) +Message delayed + + +Your message is delayed +Message for domain parliament.govt.nz delayed at Parliament.govt.nz. +Unable to deliver to domain for 6 hours. +Will continue trying for 66 hours. +No action is required on your part. +Last attempt failed because: +Can't connect to host + + +--23/89/996696127/MAILsweeper/ns1.parliament.govt.nz +Content-Type: message/delivery-status + +Reporting-MTA: dns; ns1.parliament.govt.nz +Received-From-MTA: dns; mail.python.org (unverified [63.102.49.29]) +Arrival-Date: Thu, 2 Aug 2001 02:00:22 +1200 + +Final-Recipient: rfc822; david.farrar@parliament.govt.nz +Action: delayed +Status: 4.4.1 (Persistent transient failure - routing/network: no answer from host) +Will-Retry-Until: Sun, 5 Aug 2001 02:02:05 +1200 + +--23/89/996696127/MAILsweeper/ns1.parliament.govt.nz +Content-Type: message/rfc822-headers + +Received: from mail.python.org (unverified) by ns1.parliament.govt.nz + (Content Technologies SMTPRS 4.1.5) with ESMTP id for ; + Thu, 2 Aug 2001 02:00:22 +1200 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15RvjO-00089v-00; Wed, 01 Aug 2001 09:08:10 -0400 +Received: from [144.122.169.16] (helo=robot.metu.edu.tr) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15Rvie-00086Z-00 + for mailman-users@python.org; Wed, 01 Aug 2001 09:07:26 -0400 +Received: from localhost (ceyhun@localhost) + by robot.metu.edu.tr (8.11.2/8.11.2) with ESMTP id f71DBH312336 + for ; Wed, 1 Aug 2001 16:11:18 +0300 +From: +To: +Message-ID: +MIME-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +Subject: [Mailman-Users] Hi there, +Sender: mailman-users-admin@python.org +Errors-To: mailman-users-admin@python.org +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0.6 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +Date: Wed, 1 Aug 2001 16:11:17 +0300 (EEST) +X-Mime-Type: Plain + +--23/89/996696127/MAILsweeper/ns1.parliament.govt.nz-- + + + diff --git a/inc/app/sitemailer2/tests/dsn_08.txt b/inc/app/sitemailer2/tests/dsn_08.txt new file mode 100644 index 00000000..8d4d3b8b --- /dev/null +++ b/inc/app/sitemailer2/tests/dsn_08.txt @@ -0,0 +1,131 @@ +Return-Path: +Received: from smtp.zope.com ([63.100.190.10] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 2769384 for mj@mail.zope.com; Thu, 04 Oct 2001 04:48:48 -0400 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by smtp.zope.com (8.11.2/8.11.2) with ESMTP id f948k0X28835 + for ; Thu, 4 Oct 2001 04:46:00 -0400 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15p48n-0001n2-00 + for mj@zope.com; Thu, 04 Oct 2001 04:46:01 -0400 +Received: from [212.84.234.29] (helo=daswort.innominate.com) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15p48K-0001ku-00 + for zope-admin@zope.org; Thu, 04 Oct 2001 04:45:32 -0400 +Received: from mate.bln.innominate.de (cerberus.berlin.innominate.de [212.84.234.251]) + by daswort.innominate.com (Postfix) with ESMTP id BC8F2272F7 + for ; Thu, 4 Oct 2001 09:45:26 +0000 (GMT) +Received: by mate.bln.innominate.de (Postfix) + id 27AD62CB3A; Thu, 4 Oct 2001 10:45:28 +0200 (CEST) +Date: Thu, 4 Oct 2001 10:45:28 +0200 (CEST) +From: MAILER-DAEMON@innominate.de (Mail Delivery System) +Subject: Delayed Mail (still being retried) +To: zope-admin@zope.org +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; + boundary="A216D2D16B.1002185128/mate.bln.innominate.de" +Message-Id: <20011004084528.27AD62CB3A@mate.bln.innominate.de> +Sender: zope-owner@zope.org +Errors-To: zope-owner@zope.org +X-BeenThere: zope@zope.org +X-Mailman-Version: 2.0.6 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Users of the Z Object Publishing Environment +List-Unsubscribe: , + +List-Archive: + +This is a MIME-encapsulated message. + +--A216D2D16B.1002185128/mate.bln.innominate.de +Content-Description: Notification +Content-Type: text/plain + +This is the Postfix program at host mate.bln.innominate.de. + +#################################################################### +# THIS IS A WARNING ONLY. YOU DO NOT NEED TO RESEND YOUR MESSAGE. # +#################################################################### + +Your message could not be delivered for 0.2 hours. +It will be retried until it is 5.0 days old. + +For further assistance, please send mail to + + The Postfix program + +: temporary failure. Command + output: avpcheck: unable to connect to avp daemon: Connection refused + +--A216D2D16B.1002185128/mate.bln.innominate.de +Content-Description: Delivery error report +Content-Type: message/delivery-status + +Reporting-MTA: dns; mate.bln.innominate.de +Arrival-Date: Thu, 4 Oct 2001 10:20:46 +0200 (CEST) + +Final-Recipient: rfc822; news-list.zope@localhost.bln.innominate.de +Action: delayed +Status: 4.0.0 +Diagnostic-Code: X-Postfix; temporary failure. Command output: avpcheck: unable + to connect to avp daemon: Connection refused +Will-Retry-Until: Tue, 9 Oct 2001 10:20:46 +0200 (CEST) + +--A216D2D16B.1002185128/mate.bln.innominate.de +Content-Description: Undelivered Message Headers +Content-Type: text/rfc822-headers + +Received: from daswort.innominate.com (daswort.innominate.com [212.84.234.29]) + by mate.bln.innominate.de (Postfix) with ESMTP id A216D2D16B + for ; Thu, 4 Oct 2001 10:20:46 +0200 (CEST) +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by daswort.innominate.com (Postfix) with ESMTP id 8106A284DD + for ; Thu, 4 Oct 2001 04:42:06 +0000 (GMT) +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15ozMj-000236-00; Wed, 03 Oct 2001 23:40:05 -0400 +Received: from [65.32.1.43] (helo=smtp-server6.tampabay.rr.com) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15ozMQ-00021c-00 + for zope@zope.org; Wed, 03 Oct 2001 23:39:46 -0400 +Received: from tlc2 (242850hfc162.tampabay.rr.com [24.28.50.162]) + by smtp-server6.tampabay.rr.com (8.11.2/8.11.2) with SMTP id f943dcd28305; + Wed, 3 Oct 2001 23:39:42 -0400 (EDT) +From: "Trevor Toenjes" +To: "Martijn Pieters" , + "Trevor Toenjes" +Cc: +Subject: RE: [Zope] what is error_message and how do I alter it?? +Message-ID: +MIME-Version: 1.0 +Content-Type: text/plain; + charset="iso-8859-1" +Content-Transfer-Encoding: 7bit +X-Priority: 3 (Normal) +X-MSMail-Priority: Normal +X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) +Importance: Normal +X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2314.1300 +In-Reply-To: <20011003223154.D27261@zope.com> +Sender: zope-admin@zope.org +Errors-To: zope-admin@zope.org +X-BeenThere: zope@zope.org +X-Mailman-Version: 2.0.6 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Users of the Z Object Publishing Environment +List-Unsubscribe: , + +List-Archive: +Date: Wed, 3 Oct 2001 23:41:18 -0400 + +--A216D2D16B.1002185128/mate.bln.innominate.de-- + diff --git a/inc/app/sitemailer2/tests/dsn_09.txt b/inc/app/sitemailer2/tests/dsn_09.txt new file mode 100644 index 00000000..c24fc14d --- /dev/null +++ b/inc/app/sitemailer2/tests/dsn_09.txt @@ -0,0 +1,89 @@ +Received: by main.nlenet.net (mbox bob) + (with Cubic Circle's cucipop (v1.31 1998/05/13) Sun Nov 4 02:46:01 2001) +X-From_: postmaster@btconnect.com Sun Nov 4 02:45:50 2001 +>From bob Sun Nov 4 02:45:50 2001 +Return-Path: +Delivered-To: bob@nlenet.net +Received: from c2bapps1.btconnect.com (c2bapps1.btconnect.com [193.113.209.21]) + by main.nlenet.net (Postfix) with SMTP id ED8D113D126 + for ; Sun, 4 Nov 2001 02:45:49 -0500 (EST) +Received: from btconnect.com by c2bapps1.btconnect.com id ; Sun, 4 Nov 2001 07:45:32 +0000 +Message-Type: Delivery Report +X400-Received: by /ADMD= /C=WW/; Relayed; Sun, 4 Nov 2001 07:45:31 +0000 +X400-Received: by mta c2bapps1-hme1 in /ADMD= /C=WW/; Relayed; Sun, 4 Nov 2001 07:45:31 +0000 +X400-MTS-Identifier: [/ADMD= /C=WW/;c2bapps1.b:026710:20011104074531] +From: postmaster@btconnect.com +To: bob@nleaudio.com +Subject: Delivery Report (failure) for pr@allen-heath.com +Date: Sun, 4 Nov 2001 07:45:32 +0000 +Message-ID: <"c2bapps1.b:026710:20011104074531"@btconnect.com> +Content-Identifier: test +MIME-Version: 1.0 +Content-Type: multipart/report; boundary="---Multi-Part-Report-Level-1-1-2672" +X-Mozilla-Status: 8001 +X-Mozilla-Status2: 00000000 +X-UIDL: 34456246710d0000 + + +-----Multi-Part-Report-Level-1-1-2672 + +This report relates to your message: +Subject: test, + Message-ID: <3BE4F1EC.8306C281@nleaudio.com>, + To: pr@allen-heath.com + +of Sun, 4 Nov 2001 07:45:31 +0000 + +Your message was not delivered to: + pr@allen-heath.com +for the following reason: +Diagnostic was Unable to transfer, -1 +Information MTA '62.6.150.133' gives error message 5.7.1 Unable to relay for pr@allen-heath.com + +The Original Message follows: + +-----Multi-Part-Report-Level-1-1-2672 +Content-Type: message/delivery-status + +Reporting-MTA: x400; mta c2bapps1-hme1 in /ADMD= /C=WW/ +Arrival-Date: Sun, 4 Nov 2001 07:45:00 +0000 +DSN-Gateway: dns; c2bapps1.btconnect.com +X400-Conversion-Date: Sun, 4 Nov 2001 07:45:32 +0000 +Original-Envelope-Id: [/ADMD= /C=WW/;<3BE4F1EC.8306C281@nleaudio.com>] +X400-Content-Identifier: test +X400-Encoded-Info: ia5-text +X400-Content-Correlator: Subject: test, + Message-ID: <3BE4F1EC.8306C281@nleaudio.com>, + To: pr@allen-heath.com + +Original-Recipient: rfc822; pr@allen-heath.com +Final-Recipient: x400; /RFC-822=pr(a)allen-heath.com/ADMD= /C=WW/ +X400-Originally-Specified-Recipient-Number: 1 +Action: failed +Diagnostic-Code: Reason 1 (Unable-To-Transfer); Diagnostic -1 (Unknown) +Status: 5.0.0 +X400-Supplementary-Info: "MTA '62.6.150.133' gives error message 5.7.1 Unable to relay for pr(a)allen-heath.com" +X400-Last-Trace: Sun, 4 Nov 2001 07:45:00 +0000 + +-----Multi-Part-Report-Level-1-1-2672 +Content-Type: message/rfc822 + +Received: from ns.nlenet.net by c2bapps1 with SMTP (XT-PP); Sun, 4 Nov 2001 07:45:00 +0000 +Received: from nleaudio.com (66-133-142-213.roc.frontiernet.net [66.133.142.213]) + by ns.nlenet.net (Postfix) with ESMTP id E354A770C + for ; Sun, 4 Nov 2001 02:44:57 -0500 (EST) +Message-ID: <3BE4F1EC.8306C281@nleaudio.com> +Date: Sun, 04 Nov 2001 02:44:44 -0500 +From: "Bob Puff@NLE" +X-Mailer: Mozilla 4.78 [en] (Win95; U) +X-Accept-Language: en +MIME-Version: 1.0 +To: pr@allen-heath.com +Subject: test +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit + +test, please disregard. + +-----Multi-Part-Report-Level-1-1-2672-- + diff --git a/inc/app/sitemailer2/tests/dsn_10.txt b/inc/app/sitemailer2/tests/dsn_10.txt new file mode 100644 index 00000000..d37aa174 --- /dev/null +++ b/inc/app/sitemailer2/tests/dsn_10.txt @@ -0,0 +1,66 @@ +Return-Path: <> +From: MAILER-DAEMON@example.com (Mail Delivery System) +Message-ID: <20021021152058.7A58560E24@brainy.example.com> +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; + boundary="AA0C160E1D.1035213658/brainy.example.com" +Content-Transfer-Encoding: 8bit +Subject: Undelivered Mail Returned to Sender +Date: 21 Oct 2002 15:20:58 GMT +To: somelist-bounces@listi.example.com + +This is a MIME-encapsulated message. + +--AA0C160E1D.1035213658/brainy.example.com +Content-Description: Notification +Content-Type: text/plain + +This is the Postfix program at host brainy.example.com. + +I'm sorry to have to inform you that the message returned +below could not be delivered to one or more destinations. + +For further assistance, please send mail to + +If you do so, please include this problem report. You can +delete your own text from the message returned below. + + The Postfix program + +: host mx.dom.ain[192.168.1.100] said: 550 {mx001-rz3} + ... User unknown or not available - Empfaenger + unbekannt oder nicht erreichbar (in reply to RCPT TO command) + +--AA0C160E1D.1035213658/brainy.example.com +Content-Description: Delivery error report +Content-Type: message/delivery-status + +Reporting-MTA: dns; brainy.example.com +Arrival-Date: Mon, 21 Oct 2002 17:20:56 +0200 (CEST) + +Final-Recipient: rfc822; anne.person@dom.ain +Action: failed +Status: 5.0.0 +Diagnostic-Code: X-Postfix; host mx.dom.ain[192.168.1.100] said: 550 + {mx001-rz3} ... User unknown or not available - + Empfaenger unbekannt oder nicht erreichbar (in reply to RCPT TO command) + +--AA0C160E1D.1035213658/brainy.example.com +Content-Description: Undelivered Message +Content-Type: message/rfc822 +Content-Transfer-Encoding: 8bit + +From: b.a.dude@example.com (Peer Heinlein) +Message-ID: <200210211625.12753.b.a.dude@example.com> +X-Gateway: ZCONNECT UU example.com [DUUCP vom 25.09.2000], RFC1036/822 UU + example.com [DUUCP vom 25.09.2000] +MIME-Version: 1.0 +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: 8bit +Subject: [lb] Probleme =?iso-8859-15?q?gel=F6st?=, Bugs gefunden +Date: 21 Oct 2002 14:25:12 GMT +To: people@example.com + +A message about stuff. + +--AA0C160E1D.1035213658/brainy.example.com-- diff --git a/inc/app/sitemailer2/tests/dsn_11.txt b/inc/app/sitemailer2/tests/dsn_11.txt new file mode 100644 index 00000000..f3e8acaa --- /dev/null +++ b/inc/app/sitemailer2/tests/dsn_11.txt @@ -0,0 +1,176 @@ +Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) +From: Mail Delivery Subsystem +Message-Id: <200210261300.WAA27079@example.com> +To: +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; + boundary="WAA27079.1035637226/example.com" +Subject: Returned mail: User unknown +Auto-Submitted: auto-generated (failure) +X-Scanned-By: MIMEDefang 2.16 (www . roaringpenguin . com / mimedefang) +X-Spam-Status: No, hits=-4.0 required=5.0 + tests=ATTACH_DS,FAILURE_NOTICE_1,FAILURE_NOTICE_2,FROM_MAILER_DAEMON,MAILER_DAEMON,RCVD_IN_RFCI,SPAM_PHRASE_00_01 +X-Spam-Level: + +This is a MIME-encapsulated message + +--WAA27079.1035637226/example.com + +The original message was received at Sat, 26 Oct 2002 22:00:24 +0900 (JST) +from mailhub-nyc3-hme0.ny.ssmb.com [162.124.148.17] + + ----- The following addresses had permanent fatal errors ----- + +joem@example.com + (expanded from: ) +joem@example.com + (expanded from: joem@example.com) +joem@example.com + (expanded from: joem@example.com) +joem@example.com + (expanded from: joem@example.com) +joem@example.com + (expanded from: joem@example.com) +joem@example.com + (expanded from: joem@example.com) +joem@example.com + (expanded from: joem@example.com) +joem@example.com + (expanded from: joem@example.com) +joem@example.com + (expanded from: joem@example.com) +joem@example.com + (expanded from: joem@example.com) + + ----- Transcript of session follows ----- +554 joem@example.com... aliasing/forwarding loop broken (11 aliases deep; 10 max) +550 joem@example.com... User unknown +550 joem@example.com... User unknown +550 joem@example.com... User unknown +550 joem@example.com... User unknown +550 joem@example.com... User unknown +550 joem@example.com... User unknown +550 joem@example.com... User unknown +550 joem@example.com... User unknown +550 joem@example.com... User unknown +550 joem@example.com... User unknown +550 ... User unknown + +--WAA27079.1035637226/example.com +Content-Type: message/delivery-status + +Reporting-MTA: dns; example.com +Received-From-MTA: DNS; mailhub-nyc3-hme0.ny.ssmb.com +Arrival-Date: Sat, 26 Oct 2002 22:00:24 +0900 (JST) + +Final-Recipient: RFC822; +Action: failed +Status: 5.1.1 +Last-Attempt-Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) + +Final-Recipient: RFC822; +X-Actual-Recipient: RFC822; joem@example.com +Action: failed +Status: 5.1.1 +Last-Attempt-Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) + +Final-Recipient: RFC822; +X-Actual-Recipient: RFC822; joem@example.com +Action: failed +Status: 5.1.1 +Last-Attempt-Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) + +Final-Recipient: RFC822; +X-Actual-Recipient: RFC822; joem@example.com +Action: failed +Status: 5.1.1 +Last-Attempt-Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) + +Final-Recipient: RFC822; +X-Actual-Recipient: RFC822; joem@example.com +Action: failed +Status: 5.1.1 +Last-Attempt-Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) + +Final-Recipient: RFC822; +X-Actual-Recipient: RFC822; joem@example.com +Action: failed +Status: 5.1.1 +Last-Attempt-Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) + +Final-Recipient: RFC822; +X-Actual-Recipient: RFC822; joem@example.com +Action: failed +Status: 5.1.1 +Last-Attempt-Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) + +Final-Recipient: RFC822; +X-Actual-Recipient: RFC822; joem@example.com +Action: failed +Status: 5.1.1 +Last-Attempt-Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) + +Final-Recipient: RFC822; +X-Actual-Recipient: RFC822; joem@example.com +Action: failed +Status: 5.1.1 +Last-Attempt-Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) + +Final-Recipient: RFC822; +X-Actual-Recipient: RFC822; joem@example.com +Action: failed +Status: 5.1.1 +Last-Attempt-Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) + +Final-Recipient: RFC822; +X-Actual-Recipient: RFC822; joem@example.com +Action: failed +Status: 5.1.1 +Last-Attempt-Date: Sat, 26 Oct 2002 22:00:26 +0900 (JST) + +--WAA27079.1035637226/example.com +Content-Type: text/rfc822-headers + +Return-Path: +Received: from mailhub-nyc3.ny.ssmb.com (mailhub-nyc3-hme0.ny.ssmb.com [162.124.148.17]) + by example.com (8.8.8+Sun/8.8.8) with ESMTP id WAA27077 + for ; Sat, 26 Oct 2002 22:00:24 +0900 (JST) +Received: from imbarc-nj01.nj.ssmb.com (imbarc-nj01-1.nj.ssmb.com [150.110.115.169]) + by mailhub-nyc3.ny.ssmb.com (8.9.3/8.9.3/SSMB-HUB) with ESMTP id JAA01226 + for ; Sat, 26 Oct 2002 09:00:23 -0400 (EDT) +Received: from imbavirus-nj02.nj.ssmb.com (imbavirus-nj02-1.nj.ssmb.com [150.110.235.232]) + by imbarc-nj01.nj.ssmb.com (8.12.4/8.12.4/SSMB_QQQ_IN/1.1) with ESMTP id g9QD0ZtR020988 + for ; Sat, 26 Oct 2002 09:00:35 -0400 (EDT) +Received: (from uucp@localhost) + by imbavirus-nj02.nj.ssmb.com (8.11.0/8.11.0/SSMB_AV/1.1) id g9QD0GF15020 + for ; Sat, 26 Oct 2002 09:00:16 -0400 (EDT) +Received: from nodnsquery(199.67.177.248) by imbavirus-nj02.nj.ssmb.com via csmap (V4.1) + id srcAAA5gaqvD; Sat, 26 Oct 02 09:00:15 -0400 +Received: from mail.python.org (mail.python.org [12.155.117.29]) + by imbaspam-nj04.iplex.ssmb.com (8.12.5/8.12.5/SSMB_EXT/evision: 1.13 $) with ESMTP id g9QD0FnI008045 + for ; Sat, 26 Oct 2002 09:00:15 -0400 (EDT) +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 4.05) + id 185QXq-0004y2-00 + for joem@example.com; Sat, 26 Oct 2002 09:00:02 -0400 +MIME-Version: 1.0 +Content-Type: text/plain; charset="us-ascii" +Content-Transfer-Encoding: 7bit +From: mailman-developers-request@python.org +To: joem@example.com +Subject: confirm e70bc3961da9f415027185c8634596f7b226815a +Message-ID: +Date: Sat, 26 Oct 2002 09:00:01 -0400 +Precedence: bulk +X-BeenThere: mailman-developers@python.org +X-Mailman-Version: 2.1b4 +X-List-Administrivia: yes +List-Id: GNU Mailman developers +Sender: mailman-developers-bounces@python.org +Errors-To: mailman-developers-bounces@python.org +X-Spam-Score: -1.1 () NO_REAL_NAME +X-Scanned-By: MIMEDefang 2.16 (www . roaringpenguin . com / mimedefang) + +--WAA27079.1035637226/example.com-- + + diff --git a/inc/app/sitemailer2/tests/dumbass_01.txt b/inc/app/sitemailer2/tests/dumbass_01.txt new file mode 100644 index 00000000..c4e40d4b --- /dev/null +++ b/inc/app/sitemailer2/tests/dumbass_01.txt @@ -0,0 +1,109 @@ +From VM Tue Dec 26 22:41:02 2000 +Return-Path: +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.3.1) + with ESMTP id 400019 for xxxxx@mail.digicool.com; Tue, 26 Dec 2000 18:02:35 -0500 +Received: from mail.python.org (starship.python.net [63.102.49.30]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id SAA02602 + for ; Tue, 26 Dec 2000 18:02:28 -0500 +Received: from ns1.zope.org (localhost.localdomain [127.0.0.1]) + by mail.python.org (Postfix) with ESMTP id 9D20DE71C + for ; Tue, 26 Dec 2000 12:47:01 -0500 (EST) +Delivered-To: mm+python-list-admin@python.org +Received: from mail1.microsoft.com (mail1.microsoft.com [131.107.3.125]) + by mail.python.org (Postfix) with SMTP id 23085E950 + for ; Tue, 26 Dec 2000 12:46:03 -0500 (EST) +Received: from 157.54.9.101 by mail1.microsoft.com (InterScan E-Mail VirusWall NT); Tue, 26 Dec 2000 09:43:37 -0800 (Pacific Standard Time) +Received: from inet-imc-01.redmond.corp.microsoft.com ([157.54.9.101]) by inet-imc-01.redmond.corp.microsoft.com with Microsoft SMTPSVC(5.0.2195.1600); + Tue, 26 Dec 2000 09:44:45 -0800 +Received: from mail1.microsoft.com ([157.54.7.20]) by inet-imc-01.redmond.corp.microsoft.com with Microsoft SMTPSVC(5.0.2195.1600); + Tue, 26 Dec 2000 09:44:44 -0800 +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="------------InterScan_NT_MIME_Boundary" +Message-ID: +Errors-To: python-list-owner@python.org +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: inetgw1@microsoft.com +Sender: python-list-owner@python.org +To: +Subject: Mail could not be delivered +Date: 26 Dec 2000 09:44:44 -0800 +X-OriginalArrivalTime: 26 Dec 2000 17:44:44.0596 (UTC) FILETIME=[8852FF40:01C06F63] +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0 + + +--------------InterScan_NT_MIME_Boundary +Content-type: text/plain + +****** Message from InterScan E-Mail VirusWall NT ****** + +The following mail could not be delivered. +Reason: Exceeded Maximum Delivery Attempts. Verify that the recipient address is correct. + +***************** End of message *************** + +--------------InterScan_NT_MIME_Boundary +Content-type: message/rfc822 + +Received: from 63.102.49.30 by mail1.microsoft.com (InterScan E-Mail VirusWall NT); Mon, 25 Dec 2000 08:40:09 -0800 (Pacific Standard Time) +Received: from ns1.zope.org (localhost.localdomain [127.0.0.1]) + by mail.python.org (Postfix) with ESMTP + id 80C4BE86C; Mon, 25 Dec 2000 11:41:09 -0500 (EST) +Path: news.baymountain.net!uunet!ash.uu.net!news.netins.net!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!howland.erols.net!panix!news.panix.com!panix2.panix.com!not-for-mail +From: aahz@panix.com (Aahz Maruch) +Newsgroups: comp.lang.python +Subject: Season's greetings (was Re: Some Python 2.1 ideas) +Organization: The Cat & Dragon +Lines: 13 +Message-ID: <927suu$r5l$1@panix2.panix.com> +References: <925tl301ub0@news1.newsguy.com> <20001225150250.6FA06A84F@darjeeling.zadka.site.co.il> +NNTP-Posting-Host: panix2.panix.com +X-Trace: news.panix.com 977762079 17648 166.84.0.227 (25 Dec 2000 16:34:39 GMT) +X-Complaints-To: abuse@panix.com +NNTP-Posting-Date: 25 Dec 2000 16:34:39 GMT +Xref: news.baymountain.net comp.lang.python:81985 +To: python-list@python.org +Sender: python-list-admin@python.org +Errors-To: python-list-admin@python.org +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +Date: 25 Dec 2000 08:34:38 -0800 + +In article , +Bob Alexander wrote: +> +>P.S. Merry Christmas! + +Bah, humbug. +-- + --- Aahz (Copyright 2000 by aahz@pobox.com) + +Androgynous poly kinky vanilla queer het <*> http://www.rahul.net/aahz/ +Hugs and backrubs -- I break Rule 6 + +'"Crisp" is a good quality for crackers; less so for pot roast.' --pnh +-- +http://www.python.org/mailman/listinfo/python-list + +--------------InterScan_NT_MIME_Boundary-- + + diff --git a/inc/app/sitemailer2/tests/exim_01.txt b/inc/app/sitemailer2/tests/exim_01.txt new file mode 100644 index 00000000..42ceb0b0 --- /dev/null +++ b/inc/app/sitemailer2/tests/exim_01.txt @@ -0,0 +1,58 @@ +Received: from localhost (k298r.balpol.tudelft.nl) [127.0.0.1] + by stereo.rotzorg.org with esmtp (Exim 2.05 #1 (Debian)) + id 11SrFm-000595-00; Mon, 20 Sep 1999 02:24:22 +0200 +Received: from mail by stereo.rotzorg.org with local (Exim 2.05 #1 (Debian)) + id 11SrFM-00058o-00; Mon, 20 Sep 1999 02:23:56 +0200 +X-Failed-Recipients: delangen@its.tudelft.nl +From: Mail Delivery System +To: lanparty-helden-admin@rotzorg.org +Subject: Mail delivery failed: returning message to sender +Message-Id: +Date: Mon, 20 Sep 1999 02:23:56 +0200 +Status: RO +Content-Length: 1544 +Lines: 42 + +This message was created automatically by mail delivery software. + +A message that you sent could not be delivered to all of its recipients. The +following address(es) failed: + + delangen@its.tudelft.nl: + SMTP error from remote mailer after RCPT TO: + : + host mailhost1.et.tudelft.nl [130.161.33.163]: + 553 5.1.1 unknown or illegal user: + delangen@its.tudelft.nl + +----- This is a copy of the message, including all the headers. ------ + +Return-path: +Received: from localhost (k298r.balpol.tudelft.nl) [127.0.0.1] + by stereo.rotzorg.org with esmtp (Exim 2.05 #1 (Debian)) + id 11SrFJ-00058j-00; Mon, 20 Sep 1999 02:23:53 +0200 +Received: from sgr by stereo.rotzorg.org with local (Exim 2.05 #1 (Debian)) + id 11SrEp-00058U-00; Mon, 20 Sep 1999 02:23:23 +0200 +Date: Mon, 20 Sep 1999 02:23:22 +0200 +From: Sendy +To: lanparty-helden@rotzorg.org +Message-ID: <19990920022322.A19735@stereo.rotzorg.org> +Reply-To: sendy@dds.nl +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +X-Mailer: Mutt 0.95.3i +Subject: [Lanparty-helden] test +Sender: lanparty-helden-admin@rotzorg.org +Errors-To: lanparty-helden-admin@rotzorg.org +X-Mailman-Version: 1.0rc2 +Precedence: bulk +List-Id: Mailinglist voor de KB Lanparty organisatoren +X-BeenThere: lanparty-helden@rotzorg.org + + + +_______________________________________________ +Lanparty-helden mailing list - Lanparty-helden@rotzorg.org +http://rotzorg.org/mailman/listinfo/lanparty-helden + diff --git a/inc/app/sitemailer2/tests/groupwise_01.txt b/inc/app/sitemailer2/tests/groupwise_01.txt new file mode 100644 index 00000000..68101ba0 --- /dev/null +++ b/inc/app/sitemailer2/tests/groupwise_01.txt @@ -0,0 +1,151 @@ +From VM Fri Jul 20 14:14:47 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Friday" "20" "July" "2001" "11:09:00" "-0700" "System Administrator" "postmaster@mainex1.asu.edu" nil "93" "Undeliverable: [Mailman-Users] [ alexandria-Bugs-442987 ] mailman bug" "^From:" "mailman-users-admin@python.org" "mailman-users-admin@python.org" "7" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: barry@wooz.org +Received: from digicool.com (unknown [63.100.190.15]) + by mail.wooz.org (Postfix) with ESMTP id 2193BD35F0 + for ; Fri, 20 Jul 2001 14:11:42 -0400 (EDT) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 2267275; Fri, 20 Jul 2001 14:11:10 -0400 +Received: from ns2.digicool.com ([63.100.190.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 2267274 for barry@mail.digicool.com; Fri, 20 Jul 2001 14:11:10 -0400 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id OAA18755 + for ; Fri, 20 Jul 2001 14:11:40 -0400 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15NekX-00065F-00; Fri, 20 Jul 2001 14:11:41 -0400 +Received: from [129.219.110.73] (helo=post2.inre.asu.edu) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15Nejg-0005zp-00 + for mailman-users-admin@python.org; Fri, 20 Jul 2001 14:10:48 -0400 +Received: from conversion.post2.inre.asu.edu by asu.edu (PMDF V6.0-24 #47347) + id <0GGS00E01AF3DP@asu.edu> for mailman-users-admin@python.org; Fri, + 20 Jul 2001 11:09:03 -0700 (MST) +Received: from mainex1.asu.edu (mainex1.asu.edu [129.219.10.200]) + by asu.edu (PMDF V6.0-24 #47347) with ESMTP id <0GGS00E5WAF396@asu.edu> for + mailman-users-admin@python.org; Fri, 20 Jul 2001 11:09:03 -0700 (MST) +Received: by mainex1.asu.edu with Internet Mail Service (5.5.2653.19) + id <3MQDQNK7>; Fri, 20 Jul 2001 11:09:02 -0700 +Message-id: <803148826976D411ADA600B0D03D6E2806F867BF@mainex1.asu.edu> +MIME-version: 1.0 +Content-type: multipart/mixed; boundary="Boundary_(ID_T1d1xFzw5I4c8zjm3AkzoA)" +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +From: System Administrator +Sender: mailman-users-owner@python.org +To: mailman-users-admin@python.org +Subject: Undeliverable: [Mailman-Users] [ alexandria-Bugs-442987 ] mailman bug +Date: Fri, 20 Jul 2001 11:09:00 -0700 +X-Autogenerated: Mirror +X-Mirrored-by: +X-Mailer: Internet Mail Service (5.5.2653.19) +X-MS-Embedded-Report: +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0.5 (101270) + +This message is in MIME format. Since your mail reader does not understand +this format, some or all of this message may not be legible. + +--Boundary_(ID_T1d1xFzw5I4c8zjm3AkzoA) +Content-type: text/plain + +Your message + + To: mailman-users@python.org + Subject: [Mailman-Users] [ alexandria-Bugs-442987 ] mailman bug + Sent: Fri, 20 Jul 2001 08:53:08 -0700 + +did not reach the following recipient(s): + +thoff@MAINEX1.ASU.EDU on Fri, 20 Jul 2001 11:08:59 -0700 + The recipient name is not recognized + The MTS-ID of the original message is: c=us;a= ;p=arizona state +un;l=MAINEX101072018083MQDQNKX + MSEXCH:IMS:Arizona State University:MAIN:MAINEX1 0 (000C05A6) Unknown +Recipient + + + +--Boundary_(ID_T1d1xFzw5I4c8zjm3AkzoA) +Content-type: message/rfc822 + +Date: Fri, 20 Jul 2001 08:53:08 -0700 +From: Marc MERLIN +Subject: [Mailman-Users] [ alexandria-Bugs-442987 ] mailman bug +To: mailman-users@python.org +Message-id: <20010720085308.H17468@magic.merlins.org> +MIME-version: 1.0 +X-Mailer: Internet Mail Service (5.5.2653.19) +Content-type: text/plain +X-MS-Embedded-Report: +List-Subscribe: , + +List-Unsubscribe: , + +List-Help: + +Anyone has a clue about this error? + +----- Forwarded message from noreply@sourceforge.net ----- + +To: noreply@sourceforge.net +From: noreply@sourceforge.net +Subject: [ alexandria-Bugs-442987 ] mailman bug +Date: Fri, 20 Jul 2001 07:47:39 -0700 + +Initial Comment: +-----Forwarded Message----- +From: rtfs-project-admin@lists.sourceforge.net +To: rtfs-project-admin@lists.sourceforge.net +Subject: Unexpected Mailman error + + +An unexpected Mailman error has occurred in +MailCommandHandler.ParseMailCommands(). Here is the +traceback: + +Traceback (innermost last): + File +"/var/local/mailman/Mailman/MailCommandHandler.py", +line 221, in ParseMailCommands + self.__dispatch[cmd](args, line, msg) + File +"/var/local/mailman/Mailman/MailCommandHandler.py", +line 362, in ProcessSetCmd + self.ConfirmUserPassword(sender, args[2]) + File "/var/local/mailman/Mailman/SecurityManager.py", +line 140, in ConfirmUserPassword + raise Errors.MMBadUserError +MMBadUserError + +---------------------------------------------------------------------- + +----- End forwarded message ----- + +-- +Microsoft is to operating systems & security .... + .... what McDonalds is to gourmet +cooking + +Home page: http://marc.merlins.org/ | Finger marc_f@merlins.org for PGP +key + +------------------------------------------------------ +Mailman-Users maillist - Mailman-Users@python.org +http://mail.python.org/mailman/listinfo/mailman-users + +--Boundary_(ID_T1d1xFzw5I4c8zjm3AkzoA)-- + + diff --git a/inc/app/sitemailer2/tests/groupwise_02.txt b/inc/app/sitemailer2/tests/groupwise_02.txt new file mode 100644 index 00000000..3abfdf86 --- /dev/null +++ b/inc/app/sitemailer2/tests/groupwise_02.txt @@ -0,0 +1,186 @@ +From MAILER-DAEMON Thu Jul 11 15:53:40 2002 +Envelope-to: mailman-developers-bounces@python.org +Received: from [200.61.188.243] (helo=m3srv02) + by mail.python.org with esmtp (Exim 4.05) + id 17Sk0S-0004e9-00 + for mailman-developers-bounces@python.org; Thu, 11 Jul 2002 15:53:40 -0400 +Received: from thedc02.thebas.com ([10.1.1.3]) by m3srv02 with Microsoft + SMTPSVC(5.0.2195.4905); + Thu, 11 Jul 2002 17:00:06 -0300 +Received: by thedc02.thebas.com with Internet Mail Service (5.5.2653.19) + id ; Thu, 11 Jul 2002 16:55:03 -0300 +Message-ID: <1E774123429CC84995E7DA78FED5F49D408FEF@thedc02.thebas.com> +From: System Administrator +To: mailman-developers-bounces@python.org +Subject: Undeliverable: [Mailman-Developers] RELEASED Mailman 2.0.12 +Date: Thu, 11 Jul 2002 16:55:03 -0300 +MIME-Version: 1.0 +X-Mailer: Internet Mail Service (5.5.2653.19) +X-MS-Embedded-Report: +Content-Type: multipart/mixed; + boundary="----_=_NextPart_000_01C22914.D8CBF488" +X-OriginalArrivalTime: 11 Jul 2002 20:00:06.0562 (UTC) + FILETIME=[8D8C2820:01C22915] + +This message is in MIME format. Since your mail reader does not understand +this format, some or all of this message may not be legible. + +------_=_NextPart_000_01C22914.D8CBF488 +Content-Type: text/html; + charset="iso-8859-1" + + + + + + +Undeliverable: [Mailman-Developers] RELEASED Mailman 2.0.12 + + + +

Your message
+
+  To:      mailman-announce@python.org
+  Cc:      mailman-developers@python.org; mailman-users@python.org
+  Subject: [Mailman-Developers] RELEASED Mailman 2.0.12
+  Sent:    Thu, 11 Jul 2002 16:52:33 -0300
+
+did not reach the following recipient(s):
+
+omarmo@thebas.com on Thu, 11 Jul 2002 16:54:54 -0300
+    The recipient name is not recognized
+        The MTS-ID of the original message is: c=us;a= ;p=thebas sa;l=THEDC020207111954NZ5X2T9P
+    MSEXCH:IMS:Thebas sa:CENTRAL:THEDC02 0 (000C05A6) Unknown Recipient
+
+

+ +

  + + + +------_=_NextPart_000_01C22914.D8CBF488 +Content-Type: message/rfc822 + +Message-ID: <15661.57857.753290.942668@anthem.wooz.org> +From: barry@zope.com +To: mailman-announce@python.org +Cc: mailman-developers@python.org, mailman-users@python.org +Subject: [Mailman-Developers] RELEASED Mailman 2.0.12 +Date: Thu, 11 Jul 2002 16:52:33 -0300 +MIME-Version: 1.0 +X-Mailer: Internet Mail Service (5.5.2653.19) +X-MS-Embedded-Report: +List-Help: +List-Subscribe: , +List-Unsubscribe: , +Content-Type: text/html; + charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable + + + + + + +[Mailman-Developers] RELEASED Mailman 2.0.12 + + +
+ +

I' released Mailman 2.0.12 which fixes a cross-site = +scripting +
vulnerability, among other changes.  I = +recommend that folks upgrade +
their 2.0.x systems to this new version.  See = +below for a NEWS file +
excerpt. +

+ +

As usual, I've made both full source tarballs and = +patches available. +
See +

+ +

    http://sourceforge.net/project/showfiles.php?group_id=3D= +103 +

+ +

for links to download all the patches and the source = +tarball.  If you +
decide to install the patches, please do read the = +release notes first: +

+ +

    http://sourceforge.net/project/shownotes.php?release_i= +d=3D97760 +

+ +

See also: +

+ +

    http://www.gnu.org/software/mailman +
    http://www.list.org +
    http://mailman.sf.net +

+ +

Cheers, +
-Barry +

+ +

-------------------- snip snip = +-------------------- +
2.0.12 (02-Jul-2002) +

+ +

    - Implemented a guard against some = +reply loops and 'bot +
      subscription = +attacks.  Specifically, if a message to -request +
      has a Precedence: = +bulk (or list, or junk) header, the command is +
      ignored.  = +Well-behaved 'bots should always include such a +
      header. +

+ +

    - Changes to the configure script = +so that you can pass in the mail +
      host and web host by = +setting the environment variables MAILHOST +
      and WWWHOST = +respectively.  configure will also exit if it can't +
      figure out these = +values (usually due to broken dns). +

+ +

    - Closed another minor cross-site = +scripting vulnerability. +

+
+ +

_______________________________________________ +
Mailman-Developers mailing list +
Mailman-Developers@python.org +
http://mail.python.org/mailman-21/listinfo/mailman-dev= +elopers +

+ + + +------_=_NextPart_000_01C22914.D8CBF488-- + + diff --git a/inc/app/sitemailer2/tests/hotpop_01.txt b/inc/app/sitemailer2/tests/hotpop_01.txt new file mode 100644 index 00000000..970c3998 --- /dev/null +++ b/inc/app/sitemailer2/tests/hotpop_01.txt @@ -0,0 +1,181 @@ +>From daemon Tue Nov 13 13:43:50 2001 +Return-Path: +Received: from westmail2.West.Sun.COM (westmail2.West.Sun.COM [129.153.100.30]) + by angus.west.sun.com (8.11.4+Sun/8.11.4) with ESMTP id fADLhna07541 + for ; Tue, 13 Nov 2001 13:43:49 -0800 (PST) +Received: from pheriche.sun.com (pheriche.Central.Sun.COM [129.147.5.34]) + by westmail2.West.Sun.COM (8.9.3+Sun/8.9.3/ENSMAIL,v2.1p1) with ESMTP id NAA21411 + for ; Tue, 13 Nov 2001 13:43:49 -0800 (PST) +Received: from babylon.socal-raves.org (ip-209-85-222-117.dreamhost.com [209.85.222.117]) + by pheriche.sun.com (8.9.3+Sun/8.9.3) with ESMTP id OAA24699 + for ; Tue, 13 Nov 2001 14:43:44 -0700 (MST) +Received: by babylon.socal-raves.org (Postfix) + id 7153B51D5B; Tue, 13 Nov 2001 13:42:35 -0800 (PST) +Delivered-To: dmick-lm@babylon.socal-raves.org +Received: from babylon.socal-raves.org (localhost [127.0.0.1]) + by babylon.socal-raves.org (Postfix) with ESMTP id 5E63D51B8A + for ; Tue, 13 Nov 2001 13:42:35 -0800 (PST) +Delivered-To: scr-admin@socal-raves.org +Received: from kitkat.hotpop.com (kitkat.hotpop.com [204.57.55.30]) + by babylon.socal-raves.org (Postfix) with ESMTP id DEC4D51B8A + for ; Tue, 13 Nov 2001 13:42:32 -0800 (PST) +Received: from hotpop.com (unknown [204.57.55.31]) + by kitkat.hotpop.com (Postfix) with SMTP id 53D27324D3 + for ; Tue, 13 Nov 2001 21:43:27 +0000 (UTC) +From: MAILER-DAEMON@HotPOP.com (Mail Delivery System) +Subject: Undelivered Mail Returned to Sender +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="------------1903.1005687801/HotPOP.com" +Message-Id: <20011113214327.53D27324D3@kitkat.hotpop.com> +Date: Tue, 13 Nov 2001 21:43:27 +0000 (UTC) +To: undisclosed-recipients: ; +Sender: scr-owner@socal-raves.org +Errors-To: scr-owner@socal-raves.org +X-BeenThere: scr@socal-raves.org +X-Mailman-Version: 2.1a3+ +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: SoCal-Raves +List-Unsubscribe: , + +List-Archive: +Content-Length: 5470 +Status: O +X-Status: $$$$ +X-UID: 0000014497 + +This is a MIME-encapsulated message. + +--------------1903.1005687801/HotPOP.com +Content-Description: Notification +Content-Type: text/plain + +Undeliverable Address: allensmithee@hotpop.com + +Reason: The email you sent to the address specified +above has been returned because the recipient is over disk quota. This +account will not be able to receive any email until the account owner +removes some email from the server. + + +System Contact: postmaster@HotPOP.com + + +Original message attached (Max 5k) + +--------------1903.1005687801/HotPOP.com +Content-Description: Undelivered Message +Content-Type: message/rfc822 + +Received: from babylon.socal-raves.org (ip-209-85-222-117.dreamhost.com + [209.85.222.117]) + by mx1.hotpop.com (Postfix) with ESMTP + id 3F802249091; + Tue, 13 Nov 2001 20:48:57 +0000 (UTC) +Received: from babylon.socal-raves.org (localhost [127.0.0.1]) + by babylon.socal-raves.org (Postfix) with ESMTP + id 62A6E51D4C; Tue, 13 Nov 2001 12:47:47 -0800 (PST) +Delivered-To: scr-post@babylon.socal-raves.org +Received: by babylon.socal-raves.org (Postfix, from userid 60001) + id D4A4551D4C; Tue, 13 Nov 2001 12:47:43 -0800 (PST) +Delivered-To: scr@socal-raves.org +Received: from mail24.bigmailbox.com (mail24.bigmailbox.com + [209.132.220.207]) by babylon.socal-raves.org (Postfix) with ESMTP id + 0750D51B8A for ; Tue, 13 Nov 2001 12:47:43 -0800 + (PST) +Received: (from www@localhost) by mail24.bigmailbox.com (8.10.0/8.10.0) + id fADKmeG21560; Tue, 13 Nov 2001 12:48:40 -0800 +Date: Tue, 13 Nov 2001 12:48:40 -0800 +Message-Id: <200111132048.fADKmeG21560@mail24.bigmailbox.com> +Content-Type: text/plain +Content-Disposition: inline +Content-Transfer-Encoding: 8bit +X-Mailer: MIME-tools 4.104 (Entity 4.116) +Mime-Version: 1.0 +X-Originating-Ip: [192.76.84.68] +From: "Jim C" +To: scr@socal-raves.org, fitrhaper@aol.com, pbrock@odin.ac.hmc.edu +Subject: RE: Re: [scr] scary +Sender: scr-admin@socal-raves.org +Errors-To: scr-admin@socal-raves.org +X-BeenThere: scr@socal-raves.org +X-Mailman-Version: 2.1a3+ +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: SoCal-Raves +List-Unsubscribe: , + +List-Archive: + +[demime could not interpret encoding binary - treating as plain text] +Hi New to the List. Just curious. What would you have the government do instead? I see alot of passion over this topic so I assume you have an alternative to Ashcroft. These are tough times, and call for quick and concise thinking, Gov is doing its best, Do we have anything better in mind that can be implemented in a short amount of time like this is.? + +> FitRhapER@aol.comDate: Tue, 13 Nov 2001 00:39:20 EST +> Re: [scr] scary pbrock@odin.ac.hmc.edu, scr@socal-raves.org +>argh! That makes me so angry. Every time i see another people happily not +>questioning anything and going along with the government for some idiotic +>reason (i cant really figure out why people happily go along with things, i +>guess just less stress or something) it just disheartens me further. Why +>don't these people see just a bit further. I mean it's not hard to see how +>this could be misused is it? And alot of these people wont be convinced +>otherwise. You tell them the facts. They give you the obivious retort (the +>one they've been spoon fed), you show them how that could be side stepped to +>hurt the innocent, they give you another answer (usually one they thought up +>themselves, oo how clever), you again show em how this is +>wrong/unconstitutional/gonna fuck everything up. They give you a "yeah well, +>the government needs to stop terrorism somehow!" kind of answer. +> +>grrrr. *slap* WAKE UP BITCH!!! then they ask you why your eyes are all glazed +>over and you're smiling funny. +> +>peace +>olly the limey +> +>> i know many mudders who think the goverenment is being perfectly +>> reasonable and that everything about the war and the new laws is +>> correct. one girl lives like a few doors down from me and it just cracks +>> me up.... +>> +>> jesus i can understand not hating everyth9ing, but being happy with every +>> action the government is taking now just boggles my mind +>> +>> on an unrelated note./...... +>> +>> i like buffy songs...yay buffy songs +>> +>> ,tricia +>> +>> AIM amphitrite27 +>> +>> http://www.geocities.com/amphitrite27/index.html +>> +>> I wanted a perfect ending. Now I've learned, the hard way, that some poems +>> don't rhyme, and some stories don't have a clear beginning, middle, and +>> end. Life is about not knowing, having to change, taking the moment and +>> making the best of it without knowing what's going to happen next. +>> ~Gilda Radner +>_______________________________________________ +>For event info, list questions, or to unsubscribe, see http://www.socal-raves.org/ + + + + +------------------------------------------------------------ +House music all night long... +http://www.housemusic.com +_______________________________________________ +For event info, list questions, or to unsubscribe, see http://www.socal-raves.org/ + + + +--------------1903.1005687801/HotPOP.com-- + + + diff --git a/inc/app/sitemailer2/tests/llnl_01.txt b/inc/app/sitemailer2/tests/llnl_01.txt new file mode 100644 index 00000000..9a6de7f9 --- /dev/null +++ b/inc/app/sitemailer2/tests/llnl_01.txt @@ -0,0 +1,203 @@ +From VM Mon May 28 12:27:07 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Sunday" "27" "May" "2001" "14:25:17" "-0700" "Automated response from LLNL postmaster" "postmaster@llnl.gov" nil "153" "FAILED MAIL to \"trotts1\" regarding \"[ANNOUNCE] wxPython 2.3.0\"" "^From:" nil nil "5" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: barry@wooz.org +Received: from digicool.com (unknown [63.100.190.15]) + by mail.wooz.org (Postfix) with ESMTP id 307A8D38E0 + for ; Sun, 27 May 2001 17:26:43 -0400 (EDT) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 1985528; Sun, 27 May 2001 17:27:06 -0400 +Received: from ns2.digicool.com ([63.100.190.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 1985527 for barry@mail.digicool.com; Sun, 27 May 2001 17:27:06 -0400 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id RAA21782 + for ; Sun, 27 May 2001 17:26:42 -0400 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15483f-000890-00 + for barry@digicool.com; Sun, 27 May 2001 17:26:43 -0400 +Received: from [128.115.41.100] (helo=pierce.llnl.gov) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15482m-00086w-00 + for python-announce-list-admin@python.org; Sun, 27 May 2001 17:25:48 -0400 +Received: (from postmaster@localhost) + by pierce.llnl.gov (8.8.8/LLNL-3.0.2/llnl.gov-5.1) + id OAA03843; Sun, 27 May 2001 14:25:17 -0700 (PDT) +Message-Id: <200105272125.OAA03843@pierce.llnl.gov> +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Announcement-only list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: postmaster@llnl.gov (Automated response from LLNL postmaster) +Sender: python-announce-list-owner@python.org +To: python-announce-list-admin@python.org +Subject: FAILED MAIL to "trotts1" regarding "[ANNOUNCE] wxPython 2.3.0" +Date: Sun, 27 May 2001 14:25:17 -0700 (PDT) +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: python-announce-list@python.org +X-Mailman-Version: 2.0.5 (101270) + +The standard form of email address at LLNL is lastnameNumber@llnl.gov +although individuals may choose an alternate email address. The address to +which your message was addressed, trotts1@llnl.gov, did not exactly match an +LLNL email address. + +The following locator information may be of help in finding another means +of contacting "trotts1": + + Judy L. Trotter +1 925-423-5635 trotter4@llnl.gov + L-149 + + +Original message as received is as follows: +======================================================================== +>Return-Path: +>Received: from smtp-in-2.llnl.gov (smtp-in-2.llnl.gov [128.115.249.72]) by pierce.llnl.gov (8.8.8/LLNL-3.0.2/llnl.gov-5.1) with ESMTP id OAA03514 for ; Sun, 27 May 2001 14:21:25 -0700 (PDT) +>Received: from mail.python.org (localhost [127.0.0.1]) by smtp-in-2.llnl.gov (8.9.3/8.9.3/LLNL-gateway-1.0) with ESMTP id OAA20597 for ; Sun, 27 May 2001 14:21:23 -0700 (PDT) +>Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) by mail.python.org with esmtp (Exim 3.21 #1) id 1547yA-0007w7-00; Sun, 27 May 2001 17:21:02 -0400 +>Path: news.baymountain.net!not-for-mail +>From: "Robin Dunn" +>Newsgroups: comp.lang.python.announce +>Subject: [ANNOUNCE] wxPython 2.3.0 +>Organization: Baymountain +>Lines: 150 +>Message-ID: +>NNTP-Posting-Host: mail.python.org +>X-Trace: news.baymountain.net 990998285 26598 63.102.49.29 (27 May 2001 21:18:05 GMT) +>X-Complaints-To: abuse@baymountain.net +>NNTP-Posting-Date: 27 May 2001 21:18:05 GMT +>X-Priority: 3 +>X-MSMail-Priority: Normal +>X-Mailer: Microsoft Outlook Express 5.50.4133.2400 +>X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400 +>X-BeenThere: clpa-moderators@python.org +>X-Mailman-Version: 2.0.5 (101270) +>Precedence: bulk +>X-BeenThere: clpa-moderators@python.org +>Xref: news.baymountain.net comp.lang.python.announce:1064 +>X-Originally-To: , , +>To: python-announce-list@python.org +>Sender: python-announce-list-admin@python.org +>Errors-To: python-announce-list-admin@python.org +>X-BeenThere: python-announce-list@python.org +>List-Help: +>List-Post: +>List-Subscribe: , +>List-Id: Announcement-only list for the Python programming language +>List-Unsubscribe: , +>List-Archive: +>Date: Fri, 25 May 2001 10:24:51 -0700 +> +>wxPython 2.3.0 is now available for download. Unfortunately the shell +>server at sourceforge is down for a few days and so I can't update the +>wxPython.org web page, but in the meantime you can get the files directly +>from +> +>http://sourceforge.net/project/showfiles.php?group_id=10718. +> +>Sources and binaries for win32 and Linux for Python 1.5.2, 2.0 and 2.1 are +>available. (The win32 binaries with "-hybrid" in the name are built with +>extra debugging code enabled so some things that caused mysterious problems +>before will now pop-up a slightly less mysterious message dialog.) +> +>There have been a large number of changes for this release. I'll include +>the relevant portion of CHANGES.txt here: +> +> +> +>Removed initial startup dependency on the OpenGL DLLs so only the +>glcanvasc.pyd depends on them, (on wxMSW.) +> +>Changed wxFont, wxPen, wxBrush to not implicitly use the +>wxThe[Font|Pen|Brush]List objects behind the scenes, but to use normal +>ctor and dtors. +> +>Exposed the wxThe[Font|Pen|Brush]List to wxPython. +> +>Also added wxTheColourDatabase and added a library module (in the +>wxPython.lib.colourdb module) to load LOTS more colour names into the +>colour database. +> +>Added wxWakeUpMainThread, wxMutexGuiEnter, wxMutexGuiLeave, +>wxMutexGuiLocker and wxThread_IsMain to assist with dealing with GUI +>access from non-GUI threads. +> +>wxPyOnDemandOutputWindow is now (more) thread safe if non-GUI threads +>use print, sys.stdout.write, etc. +> +>Added CreateTextSizer and CreateButtonSizer to wxDialog +> +>Added wxPython/lib/infoframe.py from Chris Fama. It contains a class +>that can be used in place of wxPyOnDemandOutputWindow. +> +>Added colourselect.py, imagebrowser.py and an updated calendar.py to +>wxPython/lib from Lorne White. +> +>Added patch to wxPoint_LIST_helper from Tim Hochberg that should make +>it gobs faster in certain situations. +> +>Added tools that will take an image file in a wx supported format and +>convert it to data embedded in a Python source file. The image is +>converted to XPM format which is essentially a list of strings +>containing info about each pixel. The image's transparency mask is +>included, if there is one, or a mask can be added if a mask colour is +>specified on the command line. It is then pickled and optionally +>compressed and written to a Python source file along with functions to +>convert it to either a wxBitmap or a wxImage. See +>wxPython/demo/images.py for examples, and wxPython/Tools/img2py.py for +>the implementation. +> +>Fixed wxStyledTextCtrl to be much faster on wxGTK. There was some +>experimental code that got left in place that ended up causing way too +>many refreshes. +> +>A couple more hacks in my_distutils.py so wxPython can be built with +>the distutils that comes with Python 2.1. +> +>Added a ton of missing methods for wxPrintData. +> +>Switched to InnoSetup for MSW distributions. +> +>Added wxToggleButton. +> +>Fixed bug that prevented wxTreeCtrl.OnCompareItems from being called. +> +>Added some methods to wxGrid: +> GetCellHighlightPenWidth +> GetCellHighlightROPenWidth +> SetCellHighlightPenWidth +> SetCellHighlightROPenWidth +> GetGridWindow +> GetGridRowLabelWindow +> GetGridColLabelWindow +> GetGridCornerLabelWindow +> +>Added wxGetClientDisplayRect which on wxMSW returns a wxRect +>representing the area on screen not occupied by the taskbar and such. +>On other platforms it is equivallent to wxGetDisplaySize. +> +> +>***---***---***---***---***---***---***---***---***---***---***--- +> Implemented the first phase of OOR (Original Object Return). See +> the text in the demo for more details of what this means, but in a +> nutshell methods such as wxWindow.GetParent or FindWindowById will +> now return a shadow object of the proper type if it can. By +> "proper type" I mean that if the wxWindow pointer returned from +> FindWindowById really points to a wxButton then the Python object +> constructed will be of a wxButtonPtr class instead of wxWindowPtr +> as before. This should reduce or eliminiate the need for +> wxPyTypeCast. (Woo Hoo!) The objects returned are still not the +> original Python object, but that is the next step. (Although it + + + diff --git a/inc/app/sitemailer2/tests/microsoft_01.txt b/inc/app/sitemailer2/tests/microsoft_01.txt new file mode 100644 index 00000000..92465f78 --- /dev/null +++ b/inc/app/sitemailer2/tests/microsoft_01.txt @@ -0,0 +1,108 @@ +Return-Path: +Received: from bkb01-ims-01.ikon.com (bkb01-ims-01.ikon.com [205.145.1.251]) + by plaidworks.com (8.12.2/8.12.2) with ESMTP id g94LJbkw021463 + for ; Fri, 4 Oct 2002 14:19:37 -0700 (PDT) +Received: by bkb01-ims-01.ikon.com with Internet Mail Service (5.5.2656.59) + id <4C3HZXG8>; Fri, 4 Oct 2002 17:12:36 -0400 +Message-ID: <44136F3E78E1C44EB52A3F95C986EAED09DB0AAB@BKB02-IMS-01.ikon.org> +From: System Administrator +To: pit-penguins-bounces@plaidworks.com +Subject: Undeliverable: RE: Waiver draft results explained +Date: Fri, 4 Oct 2002 17:12:35 -0400 +MIME-Version: 1.0 +X-Mailer: Internet Mail Service (5.5.2656.59) +X-MS-Embedded-Report: +Content-Type: multipart/mixed; + boundary="----_=_NextPart_000_01C26BEA.C2970D56" + +This message is in MIME format. Since your mail reader does not understand +this format, some or all of this message may not be legible. + +------_=_NextPart_000_01C26BEA.C2970D56 +Content-Type: text/plain; + charset="iso-8859-1" + +Your message + + To: pit-penguins@plaidworks.com + Subject: RE: Waiver draft results explained + Sent: Fri, 4 Oct 2002 17:10:56 -0400 + +did not reach the following recipient(s): + +c=US;a= ;p=IKON;o=Nexus2;dda:SMTP=DJBENNETT@IKON.COM; on Fri, 4 Oct 2002 +17:12:28 -0400 + The recipient name is not recognized + The MTS-ID of the original message is: c=us;a= +;p=ikon;l=BKB02-IMS-010210042112TX06SNVK + MSEXCH:IMS:IKON:Nexus2:BKB02-IMS-01 0 (000C05A6) Unknown Recipient + + + +------_=_NextPart_000_01C26BEA.C2970D56 +Content-Type: message/rfc822 + +Message-ID: <5.1.1.5.2.20021004224506.00bd9ff8@mail.chello.se> +From: Mikael Hedberg +To: pit-penguins@plaidworks.com +Subject: RE: Waiver draft results explained +Date: Fri, 4 Oct 2002 17:10:56 -0400 +MIME-Version: 1.0 +X-Mailer: Internet Mail Service (5.5.2656.59) +X-MS-Embedded-Report: +List-Help: +List-Subscribe: , +List-Unsubscribe: , +Content-Type: text/plain; + charset="iso-8859-1" + + +OK, one more time...slowly: + +Youngsters like Berry, Meloche and TK are no longer exempt from regular +season waivers. Hence, they'd have to pass through waivers to be sent down +to WBS. + +Now, during the waiver draft, to claim a player you must also unprotect one +of your own players. This is different from the regular waivers, where any +team can claim any player without giving up anything but the waiver fee. +This means teams are more reluctant to claim guys, since they run the risk +of losing one of their own players. + +However, if a player was to pass through the waiver draft *unclaimed*, he +would also count as having passed regular waivers -- and then be allowed to +be sent down immidiately. This was most definitely Patrick's reasoning for +Meloche and TK -- he said as much yesterday -- and probably also for Berry; +ie. management wanted them playing in the minors, and this was the best +chance of getting them there. The only other option would be to keep them +on the big team for the entire season. + +Also, if Washington ever wants to send Berry down, they must put him +through waivers, where the Pens have the option of claiming him back -- and +would then, as the original owning team, be free to send him down to THEIR +minor club without putting him on waivers (NHL CBA, article 13.20, I +believe). + +Personally, I think this whole Rick Berry issue has been totally blown out +of proportion. It's not like he's the second coming of Ray Bourque or even +Scott Stevens. He's a borderline NHL:er who probably would've played out +most of the season in the minors anyway (seeing as how Penguins management +weren't too high on him after camp). While I can't say I feel content to +lose one asset of the Kasparaitis trade already, the reasoning behind this +move is sound, and all you Pittsburgh/Mario/CP-bashers are really making a +chicken out of a feather here. + +__________________________________________________________________ + Mikael Hedberg mhedberg@chello.se + + "It does not do to leave a live dragon out of your calculations, + if you live near one." ---J.R.R. Tolkien + +_______________________________________________ +Do not post admin requests to the list. They will be ignored. +pit-penguins mailing list +pit-penguins@plaidworks.com +http://plaidworks.com/mailman/listinfo/pit-penguins + +------_=_NextPart_000_01C26BEA.C2970D56-- + diff --git a/inc/app/sitemailer2/tests/microsoft_02.txt b/inc/app/sitemailer2/tests/microsoft_02.txt new file mode 100644 index 00000000..3c6c5416 --- /dev/null +++ b/inc/app/sitemailer2/tests/microsoft_02.txt @@ -0,0 +1,119 @@ +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +From: System Administrator +Sender: mailman-users-owner@python.org +To: mailman-users-admin@python.org +Subject: Undeliverable: [Mailman-Users] Virus in ma mail ... these are the + headers.... +Date: Fri, 18 Oct 2002 09:13:31 -0600 +X-Mailer: Internet Mail Service (5.5.2653.19) +X-MS-Embedded-Report: +X-Spam-Status: No, hits=-5.0 required=5.0 tests=FROM_MAILER_DAEMON,MIME_NULL_BLOCK,ATTACH_RFC822 +X-Spam-Level: +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0.13 (101270) + +This message is in MIME format. Since your mail reader does not understand +this format, some or all of this message may not be legible. + +------_=_NextPart_000_01C276B8.EB5EB90E +Content-Type: text/plain; + charset="iso-8859-1" + +Your message + + To: K12 + Cc: Mailman; RedHat Mail List + Subject: [Mailman-Users] Virus in ma mail ... these are the headers.... + Sent: Fri, 18 Oct 2002 09:25:07 -0600 + +did not reach the following recipient(s): + +MDMOORE@BALL.COM on Fri, 18 Oct 2002 09:13:24 -0600 + The recipient name is not recognized + The MTS-ID of the original message is: c=us;a= +;p=ball;l=AEROMSG2021018151347W14KQ9 + MSEXCH:IMS:BALL:AEROSPACE:AEROMSG2 0 (000C05A6) Unknown Recipient + + + + +------_=_NextPart_000_01C276B8.EB5EB90E +Content-Type: message/rfc822 + +Message-ID: +From: Angel Gabriel +To: K12 +Cc: Mailman , RedHat Mail List + +Subject: [Mailman-Users] Virus in ma mail ... these are the headers.... +Date: Fri, 18 Oct 2002 09:25:07 -0600 +MIME-Version: 1.0 +X-Mailer: Internet Mail Service (5.5.2653.19) +X-MS-Embedded-Report: +List-Help: +List-Subscribe: , +List-Unsubscribe: , +Content-Type: text/plain; + charset="iso-8859-1" + +This is a continuation of my viral problem.... I'm guessing that this person +was either infected by my, or infected me.... but how do I notify them?? +These are the headers of one of the problem mails. Is there anything I can +do? + +Return-Path: +Received: from smtp.lycos.co.uk (croy-gw1.homechoice.co.uk [212.187.250.18]) + + by mailbox-8.st1.spray.net (Postfix) with SMTP id 7E1E3252DF + for ; Fri, 18 Oct 2002 17:01:29 +0200 +(DST) +From: werfriends +To: badmangabriel@lycos.co.uk +Subject: Bullshit Screensaver to ur friends !! +Date: Fri,18 Oct 2002 16:03:06 PM +X-Mailer: Microsoft Outlook Express 5.50.4133.2400 +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary=simqlgr +Message-Id: <20021018150129.7E1E3252DF@mailbox-8.st1.spray.net> + + + +*** + +Not everyone is touched by an Angel......and those that are, never forget +the experience. + +*** + +If you want guest list for bare club nights..... +http://raw-talent.hopto.org/mailman/clubnights + + +*** + +Can you sing, dance, MC, DJ, do you have talent? Send an email to +sign-me@raw-talent.hopto.org + +*** + + +--- +Outgoing mail is certified Virus Free. +Checked by AVG anti-virus system ( http://www.grisoft.com + ). +Version: 6.0.394 / Virus Database: 224 - Release Date: 10/3/02 + + + +------_=_NextPart_000_01C276B8.EB5EB90E-- + + diff --git a/inc/app/sitemailer2/tests/netscape_01.txt b/inc/app/sitemailer2/tests/netscape_01.txt new file mode 100644 index 00000000..adcde15b --- /dev/null +++ b/inc/app/sitemailer2/tests/netscape_01.txt @@ -0,0 +1,123 @@ +Received: by master.kde.org id ; + Fri, 26 May 2000 23:16:18 +0200 +Received: from nmail.corel.com ([209.167.40.11]:48557 "EHLO nsmail.corel.com") + by master.kde.org with ESMTP id ; + Fri, 26 May 2000 23:15:58 +0200 +To: kde-core-devel-admin@master.kde.org +From: Mail Administrator +Reply-To: Mail Administrator +Subject: Mail System Error - Returned Mail +Date: Fri, 26 May 2000 17:14:07 -0400 +Message-ID: <20000526211407.AAB24445@nsmail.corel.com> +MIME-Version: 1.0 +Content-Type: multipart/report; report-type=delivery-status; + Boundary="===========================_ _= 461730(24445)" +Sender: kde-core-devel-admin@master.kde.org +Resent-Sender: kde-core-devel-admin@master.kde.org +Resent-From: kde-core-devel@master.kde.org +X-Mailing-List: +Errors-To: kde-core-devel-admin@master.kde.org +X-BeenThere: kde-core-devel@master.kde.org +X-Mailman-Version: 2.0beta2 +Precedence: bulk +List-Id: KDE's core development crew +Resent-Date: Fri, 26 May 2000 23:16:18 +0200 +Return-Path: +X-Orcpt: rfc822;coolo@kde.org +X-Mozilla-Status: 8001 +X-Mozilla-Status2: 00000000 + +--===========================_ _= 461730(24445) +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit + +This Message was undeliverable due to the following reason: + +Your message was not delivered because the destination computer was +not reachable within the allowed queue period. The amount of time +a message is queued before it is returned depends on local configura- +tion parameters. + +Most likely there is a network problem that prevented delivery, but +it is also possible that the computer is turned off, or does not +have a mail system running right now. + +Your message was not delivered within 2 days. +Host corel.com is not responding. + +The following recipients did not receive your message: + + +The following recipients did not receive your message: + + + +Please reply to Postmaster@nsmail.corel.com +if you feel this message to be in error. + + +--===========================_ _= 461730(24445) +Content-Type: message/delivery-status +Content-Disposition: inline +Content-Transfer-Encoding: 7bit + + +Reporting-MTA: dns; nsmail.corel.com +Received-From-MTA: dns; [120.2.1.9] [120.2.1.9] +Arrival-Date: Wed, 24 May 2000 16:50:34 -0400 + +--===========================_ _= 461730(24445) +Content-Type: message/rfc822 +Content-Disposition: inline +Content-Transfer-Encoding: 7bit + +Received: from fwsb1 ([120.2.1.9]) by nsmail.corel.com + (Netscape Messaging Server 3.61) with SMTP id AAA41D0 + for ; Wed, 24 May 2000 16:50:34 -0400 +Received: by master.kde.org id ; + Wed, 24 May 2000 22:50:08 +0200 +Received: from smtp.mail.yahoo.com ([128.11.68.32]:5906 "HELO + smtp.mail.yahoo.com") by master.kde.org with SMTP + id ; Wed, 24 May 2000 22:49:41 +0200 +Received: from pec-151-5.tnt7.b2.uunet.de (HELO yahoo.com) (149.225.151.5) + by smtp.mail.yahoo.com with SMTP; 24 May 2000 12:29:34 -0700 +X-Apparently-From: +Message-ID: <392C2D67.C072CDA8@yahoo.com> +Date: Wed, 24 May 2000 21:28:39 +0200 +From: Falk Brettschneider +Organization: FBI (Falk Brettschneider International) +X-Mailer: Mozilla 4.7 [de] (X11; I; Linux 2.2.13 i686) +X-Accept-Language: en +MIME-Version: 1.0 +To: kde-core-devel@kde.org +Subject: private classes in KDE +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +Sender: kde-core-devel-admin@master.kde.org +Resent-Sender: kde-core-devel-admin@master.kde.org +Resent-From: kde-core-devel@master.kde.org +X-Mailing-List: +Errors-To: kde-core-devel-admin@master.kde.org +X-BeenThere: kde-core-devel@master.kde.org +X-Mailman-Version: 2.0beta2 +Precedence: bulk +Reply-To: kde-core-devel@master.kde.org +List-Id: KDE's core development crew +Resent-Date: Wed, 24 May 2000 22:50:08 +0200 + +Hi, + +Can I move a class away from the public classes of KDE to a private +header/source file of KDE when one of the public classes declares this +private candidate as friend class? + +Thanks + Bye, + F@lk + + + +__________________________________________________ +Do You Yahoo!? +Talk to your friends online with Yahoo! Messenger. +http://im.yahoo.com +--===========================_ _= 461730(24445)-- diff --git a/inc/app/sitemailer2/tests/newmailru_01.txt b/inc/app/sitemailer2/tests/newmailru_01.txt new file mode 100644 index 00000000..7802c151 --- /dev/null +++ b/inc/app/sitemailer2/tests/newmailru_01.txt @@ -0,0 +1,112 @@ +From VM Thu Dec 7 15:07:27 2000 +Return-Path: +Delivered-To: bxxxxx@mail.wooz.org +Received: from dinsdale.python.org (dinsdale.python.org [132.151.1.21]) + by mail.wooz.org (Postfix) with ESMTP id 276A9D37DB + for ; Thu, 7 Dec 2000 15:03:20 -0500 (EST) +Received: from dinsdale.python.org (localhost [127.0.0.1]) + by dinsdale.python.org (Postfix) with ESMTP id 13CF11CFD2 + for ; Thu, 7 Dec 2000 14:58:02 -0500 (EST) +Delivered-To: python-list-admin@python.org +Received: from grif.newmail.ru (grif.newmail.ru [212.48.140.154]) + by dinsdale.python.org (Postfix) with SMTP id D9F021CFD2 + for ; Thu, 7 Dec 2000 14:57:26 -0500 (EST) +Received: (qmail 1933 invoked for bounce); 7 Dec 2000 19:57:26 -0000 +Content-Type: text/plain; charset=koi8-r +Message-Id: <20001207195726.D9F021CFD2@dinsdale.python.org> +Errors-To: python-list-owner@python.org +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: MAILER-DAEMON@grif.newmail.ru +Sender: python-list-owner@python.org +To: python-list-admin@python.org +Subject: failure notice +Date: 7 Dec 2000 19:57:26 -0000 +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0 + +This is the machine generated message from mail service. +Unfortunately, we were not able to deliver your message to the following address(es): + +üÔÏ ÓÏÏÂÝÅÎÉÅ ÓÏÚÄÁÎÏ Á×ÔÏÍÁÔÉÞÅÓËÉ mail-ÓÅÒ×ÉÓÏÍ. +ë ÓÏÖÁÌÅÎÉÀ, ÎÅ×ÏÚÍÏÖÎÏ ÄÏÓÔÁ×ÉÔØ ÓÏÏÂÝÅÎÉÅ ÐÏ ÓÌÅÄÕÀÝÅÍÕ ÁÄÒÅÓÕ: + +: +This person's account is exceeding their quota. + +--- Below the next line is a copy of the message. +--- îÉÖÅ ÜÔÏÊ ÌÉÎÉÉ ÎÁÈÏÄÉÔÓÑ ËÏÐÉÑ ÓÏÏÂÝÅÎÉÑ. + +Return-Path: +Received: (qmail 1924 invoked from network); 7 Dec 2000 19:57:26 -0000 +Received: from unknown (HELO dinsdale.python.org) (132.151.1.21) + by grif.newmail.ru with SMTP; 7 Dec 2000 19:57:26 -0000 +Received: from dinsdale.python.org (localhost [127.0.0.1]) + by dinsdale.python.org (Postfix) with ESMTP + id 8E2A81CD7A; Thu, 7 Dec 2000 14:56:18 -0500 (EST) +Message-ID: <3A2FEB05.5E9531C4@san.rr.com> +From: Darren New +Organization: Bookshelves and file cabinets? +X-Mailer: Mozilla 4.06 [en] (WinNT; U) +MIME-Version: 1.0 +Newsgroups: comp.lang.python +Subject: Re: Python Origins +References: <90k3pq$50p$1@nnrp1.deja.com> <3A2DD2CA.14A5D7E2@engcorp.com> <90l3j9$4bn$1@kapsel.intranet> +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +Lines: 22 +NNTP-Posting-Host: 204.210.39.121 +X-Complaints-To: abuse@rr.com +X-Trace: typhoon.san.rr.com 976218885 204.210.39.121 (Thu, 07 Dec 2000 11:54:45 PST) +NNTP-Posting-Date: Thu, 07 Dec 2000 11:54:45 PST +Path: news!uunet!ash.uu.net!hermes.visi.com!news-out.visi.com!cyclone-sjo1.usenetserver.com!news-out.usenetserver.com!cyclone-west.rr.com!news.rr.com!news-west.rr.com!lsnws01.we.mediaone.net!cyclone-LA3.rr.com!typhoon.san.rr.com.POSTED!not-for-mail +Xref: news comp.lang.python:121135 +To: python-list@python.org +Sender: python-list-admin@python.org +Errors-To: python-list-admin@python.org +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +Date: Thu, 07 Dec 2000 19:54:45 GMT + +Grant Edwards wrote: +> If a person who speaks two languages is "bilingual" and a +> person who speaks three languages is "trilingual", then what do +> you call a person who only speaks one langage? +> +> American! + +Yah. We just export our culture to y'all. ;-) + +Actually, we don't all speak the same language. We can just all understand +each other. + +The traveling salesman saw "grits" on the menu. He asked the waitress "What +are grits?" She said "They're extra." "But what *are* they?" he asked +again. "They're fifty cents" she answered. "Yes, I'll have the grits, +please." + +-- +Darren New / Senior MTS & Free Radical / Invisible Worlds Inc. +San Diego, CA, USA (PST). Cryptokeys on demand. +Personal malapropism generator free with purchase! +Steganography: The manual is hidden in the source code. +-- +http://www.python.org/mailman/listinfo/python-list + + diff --git a/inc/app/sitemailer2/tests/postfix_01.txt b/inc/app/sitemailer2/tests/postfix_01.txt new file mode 100644 index 00000000..186cc763 --- /dev/null +++ b/inc/app/sitemailer2/tests/postfix_01.txt @@ -0,0 +1,123 @@ +From VM Tue Oct 3 18:16:48 2000 +Return-Path: +Delivered-To: zzzzz@mail.wooz.org +Received: from ns1.beopen.com (unknown [208.185.174.104]) + by mail.wooz.org (Postfix) with ESMTP id 0C841D37D5 + for ; Tue, 3 Oct 2000 18:08:44 -0400 (EDT) +Received: from dinsdale.python.org (dinsdale.cnri.reston.va.us [132.151.1.21]) + by ns1.beopen.com (8.9.3/8.9.3) with ESMTP id PAA65355 + for ; Tue, 3 Oct 2000 15:09:08 -0700 (PDT) + (envelope-from mailman-developers-admin@python.org) +Received: from dinsdale.python.org (localhost [127.0.0.1]) + by dinsdale.python.org (Postfix) with ESMTP id 2EF421CDC9 + for ; Tue, 3 Oct 2000 18:07:03 -0400 (EDT) +Delivered-To: mailman-developers-admin@python.org +Received: by dinsdale.python.org (Postfix) via BOUNCE + id 7CE611CE55; Tue, 3 Oct 2000 18:06:58 -0400 (EDT) +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="BDD021CF6B.970610818/dinsdale.python.org" +Message-Id: <20001003220658.7CE611CE55@dinsdale.python.org> +Errors-To: mailman-developers-owner@python.org +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , +List-Id: Mailman mailing list developers +List-Unsubscribe: , +List-Archive: +From: MAILER-DAEMON@python.org (Mail Delivery System) +Sender: mailman-developers-owner@python.org +To: mailman-developers-admin@python.org +Subject: Undelivered Mail Returned to Sender +Date: Tue, 3 Oct 2000 18:06:58 -0400 (EDT) +X-BeenThere: mailman-developers@python.org +X-Mailman-Version: 2.0beta6 + +This is a MIME-encapsulated message. + +--BDD021CF6B.970610818/dinsdale.python.org +Content-Description: Notification +Content-Type: text/plain + +This is the Postfix program at host dinsdale.python.org. + +I'm sorry to have to inform you that the message returned +below could not be delivered to one or more destinations. + +For further assistance, please contact + +If you do so, please include this problem report. You can +delete your own text from the message returned below. + + The Postfix program + +: host mail.local.ie[195.7.46.14] said: 550 5.1.1 + ... User unknown + + +--BDD021CF6B.970610818/dinsdale.python.org +Content-Description: Undelivered Message +Content-Type: message/rfc822 + +Received: from dinsdale.python.org (localhost [127.0.0.1]) + by dinsdale.python.org (Postfix) with ESMTP + id BDD021CF6B; Tue, 3 Oct 2000 18:03:05 -0400 (EDT) +Delivered-To: mailman-developers@python.org +Received: from public.lists.apple.com (public.lists.apple.com [17.254.0.151]) + by dinsdale.python.org (Postfix) with ESMTP id D05861CDC9 + for ; Tue, 3 Oct 2000 18:02:10 -0400 (EDT) +Received: from [17.216.27.250] (A17-216-27-250.apple.com [17.216.27.250]) + by public.lists.apple.com (8.9.1a/8.9.1) with ESMTP id PAA50322 + ; Tue, 3 Oct 2000 15:09:09 -0700 +Mime-Version: 1.0 +Message-Id: +To: mailman-developers@python.org +From: Chuq Von Rospach +Content-Type: text/plain; charset="us-ascii" ; format="flowed" +Subject: [Mailman-Developers] broken CVS! +Sender: mailman-developers-admin@python.org +Errors-To: mailman-developers-admin@python.org +X-BeenThere: mailman-developers@python.org +X-Mailman-Version: 2.0beta6 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , +List-Id: Mailman mailing list developers +List-Unsubscribe: , +List-Archive: +Date: Tue, 3 Oct 2000 15:01:50 -0700 + + +I just updated to the current CVS, and it's broken: + +Traceback (innermost last): + File "/home/mailman/cron/qrunner", line 85, in ? + from Mailman import MailList + File "/home/mailman/Mailman/MailList.py", line 45, in ? + from Mailman.Archiver import Archiver + File "/home/mailman/Mailman/Archiver/__init__.py", line 17, in ? + from Archiver import * + File "/home/mailman/Mailman/Archiver/Archiver.py", line 33, in ? + from Mailman import Mailbox + File "/home/mailman/Mailman/Mailbox.py", line 43 + <<<<<<< Mailbox.py + ^ +SyntaxError: invalid syntax + + +-- +Chuq Von Rospach - Plaidworks Consulting (mailto:chuqui@plaidworks.com) +Apple Mail List Gnome (mailto:chuq@apple.com) + +You seem a decent fellow. I hate to die. + +_______________________________________________ +Mailman-Developers mailing list +Mailman-Developers@python.org +http://www.python.org/mailman/listinfo/mailman-developers + +--BDD021CF6B.970610818/dinsdale.python.org-- + + diff --git a/inc/app/sitemailer2/tests/postfix_02.txt b/inc/app/sitemailer2/tests/postfix_02.txt new file mode 100644 index 00000000..c4065816 --- /dev/null +++ b/inc/app/sitemailer2/tests/postfix_02.txt @@ -0,0 +1,60 @@ +From VM Wed Dec 27 22:11:47 2000 +Return-Path: <> +Delivered-To: xxxxx@mail.wooz.org +Received: by mail.wooz.org (Postfix) via BOUNCE + id 68CBFD37E7; Wed, 27 Dec 2000 20:42:55 -0500 (EST) +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="17E1DD37E0.977967775/mail.wooz.org" +Message-Id: <20001228014255.68CBFD37E7@mail.wooz.org> +From: MAILER-DAEMON@mail.wooz.org (Mail Delivery System) +To: xxxxx@mail.wooz.org +Subject: Undelivered Mail Returned to Sender +Date: Wed, 27 Dec 2000 20:42:55 -0500 (EST) + +This is a MIME-encapsulated message. + +--17E1DD37E0.977967775/mail.wooz.org +Content-Description: Notification +Content-Type: text/plain + +This is the Postfix program at host mail.wooz.org. + +I'm sorry to have to inform you that the message returned +below could not be delivered to one or more destinations. + +For further assistance, please contact + +If you do so, please include this problem report. You can +delete your own text from the message returned below. + + The Postfix program + +: Name service error for domain digicool.com: Host not + found, try again + + +--17E1DD37E0.977967775/mail.wooz.org +Content-Description: Undelivered Message +Content-Type: message/rfc822 + +Received: by mail.wooz.org (Postfix, from userid 889) + id 17E1DD37E0; Fri, 22 Dec 2000 20:06:42 -0500 (EST) +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +Message-ID: <14915.64162.965657.699956@anthem.concentric.net> +Date: Fri, 22 Dec 2000 20:06:42 -0500 +To: yyyyy@digicool.com +Subject: testing to yyyyy +X-Mailer: VM 6.84 under 21.1 (patch 12) "Channel Islands" XEmacs Lucid +X-Attribution: BAW +X-Oblique-Strategy: You don't have to be ashamed of using your own ideas +X-Url: http://www.wooz.org/yyyyy +From: yyyyy@digicool.com (Yyyyy A. Zzzzz) + + +hello yyyyy + +--17E1DD37E0.977967775/mail.wooz.org-- + diff --git a/inc/app/sitemailer2/tests/postfix_03.txt b/inc/app/sitemailer2/tests/postfix_03.txt new file mode 100644 index 00000000..5204712c --- /dev/null +++ b/inc/app/sitemailer2/tests/postfix_03.txt @@ -0,0 +1,145 @@ +From VM Fri Feb 9 13:30:31 2001 +Return-Path: +Delivered-To: xxxxxx@zzzz.org +Received: from digicool.com (host15.digitalcreations.d.subnet.rcn.com [208.59.6.15]) + by mail.zzzz.org (Postfix) with ESMTP id 3B39FD37AC + for ; Thu, 8 Feb 2001 06:57:08 -0500 (EST) +Received: from + by digicool.com (CommuniGate Pro RULES 3.3.2) + with RULES id 1450267; Thu, 08 Feb 2001 06:59:26 -0500 +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.3.2) + with ESMTP id 1450266 for yyyyy@mail.digicool.com; Thu, 08 Feb 2001 06:59:21 -0500 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id GAA16165 + for ; Thu, 8 Feb 2001 06:57:51 -0500 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14Qphy-0000Sk-00 + for yyyyy@digicool.com; Thu, 08 Feb 2001 06:57:54 -0500 +Received: from [212.55.105.23] (helo=proxy.ggggg.com) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14Qpgv-0000O4-00 + for python-list-admin@python.org; Thu, 08 Feb 2001 06:56:49 -0500 +Received: by proxy.ggggg.com (Postfix on SuSE Linux 6.4 (i386)) via BOUNCE + id 7EA84D1046; Thu, 8 Feb 2001 14:00:07 +0100 (CET) +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="11D14D1045.981637207/proxy.ggggg.com" +Message-Id: <20010208130007.7EA84D1046@proxy.ggggg.com> +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: MAILER-DAEMON@proxy.ggggg.com (Mail Delivery System) +Sender: python-list-owner@python.org +To: python-list-admin@python.org +Subject: Undelivered Mail Returned to Sender +Date: Thu, 8 Feb 2001 14:00:07 +0100 (CET) +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.1 (101270) + +This is a MIME-encapsulated message. + +--11D14D1045.981637207/proxy.ggggg.com +Content-Description: Notification +Content-Type: text/plain + +This is the Postfix on SuSE Linux 6.4 (i386) program at host proxy.ggggg.com. + +I'm sorry to have to inform you that the message returned +below could not be delivered to one or more destinations. + +For further assistance, please contact + +If you do so, please include this problem report. You can +delete your own text from the message returned below. + + The Postfix on SuSE Linux 6.4 (i386) program + +: Command died with status 17: "/usr/sbin/amavis". Command + output: Can't use an undefined value as a symbol reference at + /usr/sbin/amavis line 1178. + + +--11D14D1045.981637207/proxy.ggggg.com +Content-Description: Undelivered Message +Content-Type: message/rfc822 + +Received: from mail.i-s-o.net (mail.i-s-o.net [212.55.96.66]) + by proxy.ggggg.com (Postfix on SuSE Linux 6.4 (i386)) with SMTP id 11D14D1045 + for ; Thu, 8 Feb 2001 14:00:06 +0100 (CET) +Received: (qmail 14297 invoked by uid 0); 8 Feb 2001 11:56:43 -0000 +Received: from mail.python.org (63.102.49.29) + by mail.i-s-o.net with SMTP; 8 Feb 2001 11:56:43 -0000 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14QpgG-0000Lg-00; Thu, 08 Feb 2001 06:56:08 -0500 +Received: from [194.183.224.20] (helo=relay.ppppp.net) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14QpeE-0000DS-00 + for python-list@python.org; Thu, 08 Feb 2001 06:54:03 -0500 +Received: from hercule.ppppp.be (hercule.ppppp.be [194.183.229.151]) + by relay.ppppp.net (8.11.0/8.11.0) with ESMTP id f18Bruv05655 + for ; Thu, 8 Feb 2001 12:53:56 +0100 (MET) +From: Gregoire Welraeds +X-Sender: gwelr@localhost +To: Python Mailling list +Subject: None assigment +Message-ID: +MIME-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=US-ASCII +Sender: python-list-admin@python.org +Errors-To: python-list-admin@python.org +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.1 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +Date: Thu, 8 Feb 2001 12:54:00 +0100 (CET) + + +While playing a bit with python 2.0, I found that I can assign some value +to None + +EG: None= 2 + +which I found to be very pernicious because then the following, for +example, won't work any more: + +>>> b= filter(None, [1,2,'',3]) + +Bug or feature ? + +If it is a feature (I suppose it is not a bug :), what is the interest of +this ? + +Ppppp Development team +------------------------------------------------------------------------------- +Ppppp Technologies sa/nv Tel: +32-2-6409194 +Rue Tenbosch, 9 Fax: +32-2-6403154 +B-1000 Brussels general information: info@ppppp.net +BELGIUM technical information: helpdesk@ppppp.net +URL: http://www.ppppp.be/ +------------------------------------------------------------------------------- + + +-- +http://mail.python.org/mailman/listinfo/python-list + +--11D14D1045.981637207/proxy.ggggg.com-- + + diff --git a/inc/app/sitemailer2/tests/postfix_04.txt b/inc/app/sitemailer2/tests/postfix_04.txt new file mode 100644 index 00000000..86a60ea8 --- /dev/null +++ b/inc/app/sitemailer2/tests/postfix_04.txt @@ -0,0 +1,240 @@ +From VM Wed Mar 7 11:06:03 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Tuesday" "6" "March" "2001" "09:29:58" "-0800" "Mail Delivery System" "MAILER-DAEMON@keftamail.com" nil "185" "Undelivered Mail Returned to Sender" "^From:" nil nil "3" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: bwarsaw@wooz.org +Received: from digicool.com (host15.digitalcreations.d.subnet.rcn.com [208.59.6.15]) + by mail.wooz.org (Postfix) with ESMTP id 6C2DCD37AC + for ; Tue, 6 Mar 2001 12:30:35 -0500 (EST) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 1650903; Tue, 06 Mar 2001 12:33:44 -0500 +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 1650896 for barry@mail.digicool.com; Tue, 06 Mar 2001 12:33:44 -0500 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id MAA08939 + for ; Tue, 6 Mar 2001 12:31:02 -0500 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14aLIc-0001Wp-00 + for barry@digicool.com; Tue, 06 Mar 2001 12:31:02 -0500 +Received: from [64.75.1.85] (helo=postal-worker1.kefta.com) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14aLIB-0001VP-00 + for mailman-announce-admin@python.org; Tue, 06 Mar 2001 12:30:35 -0500 +Received: from mail1.kefta.com (mail1.kefta.com [10.0.2.1]) + by postal-worker1.kefta.com (Keftamail) with ESMTP id E57BC4081 + for ; Tue, 6 Mar 2001 09:24:31 -0800 (PST) +Received: by mail1.kefta.com (Keftamail) via BOUNCE + id 438064082; Tue, 6 Mar 2001 09:29:58 -0800 (PST) +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="1EDF14081.983899798/mail1.kefta.com" +Message-Id: <20010306172958.438064082@mail1.kefta.com> +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Announce-only list for Mailman releases and news +List-Unsubscribe: , + +List-Archive: +From: MAILER-DAEMON@keftamail.com (Mail Delivery System) +Sender: mailman-announce-owner@python.org +To: mailman-announce-admin@python.org +Subject: Undelivered Mail Returned to Sender +Date: Tue, 6 Mar 2001 09:29:58 -0800 (PST) +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: mailman-announce@python.org +X-Mailman-Version: 2.0.2 (101270) + +This is a MIME-encapsulated message. + +--1EDF14081.983899798/mail1.kefta.com +Content-Description: Notification +Content-Type: text/plain + +This is the Keftamail program at host mail1.kefta.com. + +I'm sorry to have to inform you that the message returned +below could not be delivered to one or more destinations. + +For further assistance, please contact + +If you do so, please include this problem report. You can +delete your own text from the message returned below. + + The Keftamail program + +: permission denied. Command output: Mail quota + exceeded. + + +--1EDF14081.983899798/mail1.kefta.com +Content-Description: Undelivered Message +Content-Type: message/rfc822 + +Received: from postal-worker2.kefta.com (postal-worker2.kefta.com [10.0.2.4]) + by mail1.kefta.com (Keftamail) with ESMTP id 1EDF14081 + for ; Tue, 6 Mar 2001 09:29:58 -0800 (PST) +Received: by postal-worker2.kefta.com (Keftamail) + id F089940C9; Tue, 6 Mar 2001 09:29:37 -0800 (PST) +Delivered-To: davidlowie@keftamail.com +Received: from lists.securityfocus.com (lists.securityfocus.com [66.38.151.7]) + by postal-worker2.kefta.com (Keftamail) with ESMTP id BA59D40C0 + for ; Tue, 6 Mar 2001 09:29:37 -0800 (PST) +Received: from lists.securityfocus.com (lists.securityfocus.com [66.38.151.7]) + by lists.securityfocus.com (Postfix) with ESMTP + id 3A1C024CF8C; Tue, 6 Mar 2001 10:04:43 -0700 (MST) +Received: from LISTS.SECURITYFOCUS.COM by LISTS.SECURITYFOCUS.COM + (LISTSERV-TCP/IP release 1.8d) with spool id 27825191 for + BUGTRAQ@LISTS.SECURITYFOCUS.COM; Tue, 6 Mar 2001 10:03:25 -0700 +Approved-By: aleph1@SECURITYFOCUS.COM +Delivered-To: bugtraq@lists.securityfocus.com +Received: from firewall.osb.hu (unknown [193.224.234.1]) by + lists.securityfocus.com (Postfix) with ESMTP id 48CD624C646 for + ; Tue, 6 Mar 2001 00:49:55 -0700 + (MST) +Received: from pimpa.intranet.osb.hu (IDENT:root@pimpa.intranet.osb.hu + [192.168.0.8]) by firewall.osb.hu (8.9.3/8.9.3/Debian 8.9.3-21) with + ESMTP id IAA11531 for ; Tue, 6 Mar + 2001 08:53:08 +0100 +Received: from localhost (sp@localhost) by pimpa.intranet.osb.hu (8.9.3/8.9.3) + with ESMTP id IAA05518 for ; Tue, 6 + Mar 2001 08:53:08 +0100 +X-Authentication-Warning: pimpa.intranet.osb.hu: sp owned process doing -bs +X-Received: from firewall.osb.hu (fw.intranet.osb.hu [192.168.0.1]) by + pimpa.intranet.osb.hu (8.9.3/8.9.3) with ESMTP id JAA18698 for + ; Sat, 3 Mar 2001 09:41:17 +0100 +X-Received: from pax.intranet.osb.hu (IDENT:root@pax.intranet.osb.hu + [192.168.0.2]) by firewall.osb.hu (8.9.3/8.9.3/Debian 8.9.3-21) + with ESMTP id JAA24373 for ; Sat, 3 Mar + 2001 09:41:17 +0100 +X-Received: from firewall.osb.hu (fw.intranet.osb.hu [192.168.0.1]) by + pax.intranet.osb.hu (8.9.3/8.9.3) with ESMTP id JAA09389 for + ; Sat, 3 Mar 2001 09:41:16 +0100 +X-Received: from mail.python.org (mail.python.org [63.102.49.29]) by + firewall.osb.hu (8.9.3/8.9.3/Debian 8.9.3-21) with ESMTP id + JAA24367 for ; Sat, 3 Mar 2001 09:41:07 +0100 +X-Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) by + mail.python.org with esmtp (Exim 3.21 #1) id 14Z7OV-0000vs-00; Sat, + 03 Mar 2001 03:28:03 -0500 +X-Received: from [216.27.134.141] (helo=mail.wooz.org) by mail.python.org with + esmtp (Exim 3.21 #1) id 14Z7Nq-0000tq-00; Sat, 03 Mar 2001 03:27:22 + -0500 +X-Received: by mail.wooz.org (Postfix, from userid 889) id BE7B0D37AC; Sat, 3 + Mar 2001 03:26:35 -0500 (EST) +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +X-Mailer: VM 6.84 under 21.1 (patch 12) "Channel Islands" XEmacs Lucid +X-Attribution: BAW +X-Oblique-Strategy: Subvert your original idea +X-Url: http://www.wooz.org/barry +Errors-To: mailman-announce-admin@python.org +X-BeenThere: mailman-announce@python.org +X-Mailman-Version: 2.0.2 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Announce-only list for Mailman releases and news + +List-Unsubscribe: , + +List-Archive: +X-AntiVirus: scanned for viruses by AMaViS 0.2.1 (http://amavis.org/) +ReSent-Subject: [Mailman-Announce] ANNOUNCE Mailman 2.0.2 (important privacy + patch) +Message-ID: +Date: Tue, 6 Mar 2001 08:53:01 +0100 +Reply-To: mailman-developers@python.org +Sender: Bugtraq List +Comments: RFC822 error: CC field duplicated. Last occurrence was + retained. +Comments: Resent-From: Soos Peter +Comments: Originally-From: barry@digicool.com (Barry A. Warsaw) +From: Soos Peter +Subject: [Mailman-Announce] ANNOUNCE Mailman 2.0.2 (important privacy + patch) +X-cc: mailman-developers@python.org +To: BUGTRAQ@SECURITYFOCUS.COM + +I've just uploaded the Mailman 2.0.2 release to SourceForge. This is +a bug fix release that also fixes a potential privacy hole, which +could allow a list administrator to get access to user passwords. +Even with those passwords, I believe there's little additional harm +that a list admin could do, but still they probably shouldn't have +access to those passwords. + +There are a few other important fixes in this release, so I recommend +that all sites running Mailman 2.0 or 2.0.1 should upgrade. + +As usual I'm releasing this as both a complete tarball and as a patch +against Mailman 2.0.1. If you grab the patchfile, you'll want to cd +into your 2.0 source, and apply it like so: + + % patch -p1 < mailman-2.0.1-2.0.2.diff + +Currently only http://mailman.sourceforge.net is updated, but the +list.org and gnu.org sites should be updated soon. The release +information on SF is at + + http://sourceforge.net/project/shownotes.php?release_id=25955 + +My thanks to Thomas Wouters for his help! + +Enjoy, +-Barry + +P.S. I'm not sure if I'll have time to release a 2.1 alpha of the I18N +stuff before I leave for the Python9 conference. If we get the +expected foot of snow between Sunday and Monday, it's a +possibility. ;) + + +[From the NEWS file] + +2.0.2 (03-Mar-2001) + + Security fix: + + - A fix for a potential privacy exploit where a clever list + administrator could gain access to user passwords. This doesn't + allow them to do much more harm to the user then they normally + could, but they still shouldn't have access to the passwords. + + Bug fixes: + + - In the admindb page, don't complain when approving a + subscription of someone who's already on the list (SF bug + #222409 - Thomas Wouters). + + Also, quote for HTML the Subject: text printed for held + messages, otherwise messages with e.g. "Subject: " could + royally screw page formatting. + + - In Netscape.py bounce processor, don't bomb out on ill-formed + messages (no semi-colon separating parameters), otherwise mail + delivery could grind to a halt. Bug reported by Kambiz + Aghaiepour. + + - Docstring fix bin/newlist to remove mention of "immediate" + argument (Thomas Wouters). + + - Fix for bin/update when PREFIX != VAR_PREFIX (SF bug #229794 -- + Thomas Wouters). + +_______________________________________________ +Mailman-announce mailing list +Mailman-announce@python.org +http://mail.python.org/mailman/listinfo/mailman-announce + +--1EDF14081.983899798/mail1.kefta.com-- + + diff --git a/inc/app/sitemailer2/tests/postfix_05.txt b/inc/app/sitemailer2/tests/postfix_05.txt new file mode 100644 index 00000000..4bd56d60 --- /dev/null +++ b/inc/app/sitemailer2/tests/postfix_05.txt @@ -0,0 +1,231 @@ +From VM Wed Mar 7 11:08:33 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Tuesday" "6" "March" "2001" "19:02:13" "+0000" "Mail Delivery System" "MAILER-DAEMON@bucks.net" nil "179" "Undelivered Mail Returned to Sender" "^From:" nil nil "3" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: bwarsaw@wooz.org +Received: from digicool.com (host15.digitalcreations.d.subnet.rcn.com [208.59.6.15]) + by mail.wooz.org (Postfix) with ESMTP id 590BFD37AC + for ; Tue, 6 Mar 2001 14:02:37 -0500 (EST) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 1651377; Tue, 06 Mar 2001 14:05:47 -0500 +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 1651376 for barry@mail.digicool.com; Tue, 06 Mar 2001 14:05:46 -0500 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id OAA13908 + for ; Tue, 6 Mar 2001 14:03:04 -0500 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14aMje-0005oS-00 + for barry@digicool.com; Tue, 06 Mar 2001 14:03:02 -0500 +Received: from [195.112.37.162] (helo=babylon.bucks.net ident=postfix) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14aMix-0005nQ-00 + for mailman-announce-admin@python.org; Tue, 06 Mar 2001 14:02:19 -0500 +Received: by babylon.bucks.net (BNS Postfix) via BOUNCE + id 59B9747B9E; Tue, 6 Mar 2001 19:02:13 +0000 (GMT) +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="41A6B47B9D.983905333/babylon.bucks.net" +Message-Id: <20010306190213.59B9747B9E@babylon.bucks.net> +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Announce-only list for Mailman releases and news +List-Unsubscribe: , + +List-Archive: +From: MAILER-DAEMON@bucks.net (Mail Delivery System) +Sender: mailman-announce-owner@python.org +To: mailman-announce-admin@python.org +Subject: Undelivered Mail Returned to Sender +Date: Tue, 6 Mar 2001 19:02:13 +0000 (GMT) +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: mailman-announce@python.org +X-Mailman-Version: 2.0.2 (101270) + +This is a MIME-encapsulated message. + +--41A6B47B9D.983905333/babylon.bucks.net +Content-Description: Notification +Content-Type: text/plain + +This is the BNS Postfix program at host babylon.bucks.net. + +I'm sorry to have to inform you that the message returned +below could not be delivered to one or more destinations. + +For further assistance, please contact + +If you do so, please include this problem report. You can +delete your own text from the message returned below. + + The BNS Postfix program + +: host mail.btconnect.com[193.113.154.2] said: 554 No + Resent-From field given + + +--41A6B47B9D.983905333/babylon.bucks.net +Content-Description: Undelivered Message +Content-Type: message/rfc822 + +Received: from lists.securityfocus.com (lists.securityfocus.com [66.38.151.7]) + by babylon.bucks.net (BNS Postfix) with ESMTP id 41A6B47B9D + for ; Tue, 6 Mar 2001 19:02:11 +0000 (GMT) +Received: from lists.securityfocus.com (lists.securityfocus.com [66.38.151.7]) + by lists.securityfocus.com (Postfix) with ESMTP + id C8A0024C93F; Tue, 6 Mar 2001 10:05:17 -0700 (MST) +Received: from LISTS.SECURITYFOCUS.COM by LISTS.SECURITYFOCUS.COM + (LISTSERV-TCP/IP release 1.8d) with spool id 27825191 for + BUGTRAQ@LISTS.SECURITYFOCUS.COM; Tue, 6 Mar 2001 10:03:25 -0700 +Approved-By: aleph1@SECURITYFOCUS.COM +Delivered-To: bugtraq@lists.securityfocus.com +Received: from firewall.osb.hu (unknown [193.224.234.1]) by + lists.securityfocus.com (Postfix) with ESMTP id 48CD624C646 for + ; Tue, 6 Mar 2001 00:49:55 -0700 + (MST) +Received: from pimpa.intranet.osb.hu (IDENT:root@pimpa.intranet.osb.hu + [192.168.0.8]) by firewall.osb.hu (8.9.3/8.9.3/Debian 8.9.3-21) with + ESMTP id IAA11531 for ; Tue, 6 Mar + 2001 08:53:08 +0100 +Received: from localhost (sp@localhost) by pimpa.intranet.osb.hu (8.9.3/8.9.3) + with ESMTP id IAA05518 for ; Tue, 6 + Mar 2001 08:53:08 +0100 +X-Authentication-Warning: pimpa.intranet.osb.hu: sp owned process doing -bs +X-Received: from firewall.osb.hu (fw.intranet.osb.hu [192.168.0.1]) by + pimpa.intranet.osb.hu (8.9.3/8.9.3) with ESMTP id JAA18698 for + ; Sat, 3 Mar 2001 09:41:17 +0100 +X-Received: from pax.intranet.osb.hu (IDENT:root@pax.intranet.osb.hu + [192.168.0.2]) by firewall.osb.hu (8.9.3/8.9.3/Debian 8.9.3-21) + with ESMTP id JAA24373 for ; Sat, 3 Mar + 2001 09:41:17 +0100 +X-Received: from firewall.osb.hu (fw.intranet.osb.hu [192.168.0.1]) by + pax.intranet.osb.hu (8.9.3/8.9.3) with ESMTP id JAA09389 for + ; Sat, 3 Mar 2001 09:41:16 +0100 +X-Received: from mail.python.org (mail.python.org [63.102.49.29]) by + firewall.osb.hu (8.9.3/8.9.3/Debian 8.9.3-21) with ESMTP id + JAA24367 for ; Sat, 3 Mar 2001 09:41:07 +0100 +X-Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) by + mail.python.org with esmtp (Exim 3.21 #1) id 14Z7OV-0000vs-00; Sat, + 03 Mar 2001 03:28:03 -0500 +X-Received: from [216.27.134.141] (helo=mail.wooz.org) by mail.python.org with + esmtp (Exim 3.21 #1) id 14Z7Nq-0000tq-00; Sat, 03 Mar 2001 03:27:22 + -0500 +X-Received: by mail.wooz.org (Postfix, from userid 889) id BE7B0D37AC; Sat, 3 + Mar 2001 03:26:35 -0500 (EST) +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +X-Mailer: VM 6.84 under 21.1 (patch 12) "Channel Islands" XEmacs Lucid +X-Attribution: BAW +X-Oblique-Strategy: Subvert your original idea +X-Url: http://www.wooz.org/barry +Errors-To: mailman-announce-admin@python.org +X-BeenThere: mailman-announce@python.org +X-Mailman-Version: 2.0.2 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Announce-only list for Mailman releases and news + +List-Unsubscribe: , + +List-Archive: +X-AntiVirus: scanned for viruses by AMaViS 0.2.1 (http://amavis.org/) +ReSent-Subject: [Mailman-Announce] ANNOUNCE Mailman 2.0.2 (important privacy + patch) +Message-ID: +Date: Tue, 6 Mar 2001 08:53:01 +0100 +Reply-To: mailman-developers@python.org +Sender: Bugtraq List +Comments: RFC822 error: CC field duplicated. Last occurrence was + retained. +Comments: Resent-From: Soos Peter +Comments: Originally-From: barry@digicool.com (Barry A. Warsaw) +From: Soos Peter +Subject: [Mailman-Announce] ANNOUNCE Mailman 2.0.2 (important privacy + patch) +X-cc: mailman-developers@python.org +To: BUGTRAQ@SECURITYFOCUS.COM + +I've just uploaded the Mailman 2.0.2 release to SourceForge. This is +a bug fix release that also fixes a potential privacy hole, which +could allow a list administrator to get access to user passwords. +Even with those passwords, I believe there's little additional harm +that a list admin could do, but still they probably shouldn't have +access to those passwords. + +There are a few other important fixes in this release, so I recommend +that all sites running Mailman 2.0 or 2.0.1 should upgrade. + +As usual I'm releasing this as both a complete tarball and as a patch +against Mailman 2.0.1. If you grab the patchfile, you'll want to cd +into your 2.0 source, and apply it like so: + + % patch -p1 < mailman-2.0.1-2.0.2.diff + +Currently only http://mailman.sourceforge.net is updated, but the +list.org and gnu.org sites should be updated soon. The release +information on SF is at + + http://sourceforge.net/project/shownotes.php?release_id=25955 + +My thanks to Thomas Wouters for his help! + +Enjoy, +-Barry + +P.S. I'm not sure if I'll have time to release a 2.1 alpha of the I18N +stuff before I leave for the Python9 conference. If we get the +expected foot of snow between Sunday and Monday, it's a +possibility. ;) + + +[From the NEWS file] + +2.0.2 (03-Mar-2001) + + Security fix: + + - A fix for a potential privacy exploit where a clever list + administrator could gain access to user passwords. This doesn't + allow them to do much more harm to the user then they normally + could, but they still shouldn't have access to the passwords. + + Bug fixes: + + - In the admindb page, don't complain when approving a + subscription of someone who's already on the list (SF bug + #222409 - Thomas Wouters). + + Also, quote for HTML the Subject: text printed for held + messages, otherwise messages with e.g. "Subject: " could + royally screw page formatting. + + - In Netscape.py bounce processor, don't bomb out on ill-formed + messages (no semi-colon separating parameters), otherwise mail + delivery could grind to a halt. Bug reported by Kambiz + Aghaiepour. + + - Docstring fix bin/newlist to remove mention of "immediate" + argument (Thomas Wouters). + + - Fix for bin/update when PREFIX != VAR_PREFIX (SF bug #229794 -- + Thomas Wouters). + +_______________________________________________ +Mailman-announce mailing list +Mailman-announce@python.org +http://mail.python.org/mailman/listinfo/mailman-announce + +--41A6B47B9D.983905333/babylon.bucks.net-- + + diff --git a/inc/app/sitemailer2/tests/qmail_01.txt b/inc/app/sitemailer2/tests/qmail_01.txt new file mode 100644 index 00000000..dbe6f435 --- /dev/null +++ b/inc/app/sitemailer2/tests/qmail_01.txt @@ -0,0 +1,103 @@ +From VM Thu Oct 4 15:25:26 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "" "4" "November" "1999" "21:42:45" "-0000" "MAILER-DAEMON@gate0.n-h.net" "MAILER-DAEMON@gate0.n-h.net" nil "89" "failure notice" "^From:" nil nil "11" nil nil nil nil nil] + nil) +Message-Id: <199911042119.QAA21584@python.org> +Content-Length: 3215 +MIME-Version: 1.0 +From: MAILER-DAEMON@gate0.n-h.net +To: psa-members-admin@python.org +Subject: failure notice +Date: 4 Nov 1999 21:42:45 -0000 +X-Digest: Mailman bounce lack-of-detection + +Hi. This is the qmail-send program at gate0.n-h.net. +I'm afraid I wasn't able to deliver your message to the following addresses. +This is a permanent error; I've given up. Sorry it didn't work out. + +: + +--- Below this line is a copy of the message. + +Return-Path: +Received: (qmail 23042 invoked from network); 4 Nov 1999 21:42:35 -0000 +Received: from one.n-h.net (HELO n-h.net) (root@195.254.4.1) + by wwwmail.n-h.de with SMTP; 4 Nov 1999 21:42:35 -0000 +Received: from python.org (parrot.python.org [132.151.1.90]) + by n-h.net (8.8.5/8.8.5) with ESMTP id WAA00074 + for ; Thu, 4 Nov 1999 22:45:15 +0100 +Received: from python.org (localhost [127.0.0.1]) + by python.org (8.9.1a/8.9.1) with ESMTP id QAA20872; + Thu, 4 Nov 1999 16:10:19 -0500 (EST) +Received: from origin.ea.com (hidden-user@gnat6.owo.com [208.12.170.6]) + by python.org (8.9.1a/8.9.1) with ESMTP id QAA20823 + for ; Thu, 4 Nov 1999 16:09:48 -0500 (EST) +Received: from forest.origin.ea.com (molach.origin.ea.com [159.153.98.2]) + by origin.ea.com (8.8.8/8.8.8PJ) with ESMTP id PAA19774; + Thu, 4 Nov 1999 15:26:35 -0600 (CST) +Received: by molach.origin.ea.com with Internet Mail Service (5.5.2448.0) + id ; Thu, 4 Nov 1999 15:00:30 -0600 +Message-ID: <11A17AA2B9EAD111BCEA00A0C9B4179303385B62@molach.origin.ea.com> +From: "Asbahr, Jason" +To: "'beazley@cs.uchicago.edu'" , chriss@dnastar.com +Cc: psa-members@python.org +Subject: RE: [PSA MEMBERS] ObjC.py ? +Date: Thu, 4 Nov 1999 15:00:29 -0600 +MIME-Version: 1.0 +X-Mailer: Internet Mail Service (5.5.2448.0) +Content-Type: text/plain; + charset="iso-8859-1" +Sender: psa-members-admin@python.org +Errors-To: psa-members-admin@python.org +X-Mailman-Version: 1.0.2 +Precedence: bulk +List-Id: Python Software Activity members discussion list +X-BeenThere: psa-members@python.org + +I had the impression that SWIG supported the relatively recent +versions of GNU ObjC, but not earlier versions, such as NeXT's +original ObjC extensions to GCC. True? + +Cheers, + +Jason Asbahr +Origin Systems, Inc. +jasbahr@origin.ea.com + +-----Original Message----- +From: David Beazley [mailto:beazley@cs.uchicago.edu] +Sent: Wednesday, November 03, 1999 11:13 PM +To: chriss@dnastar.com +Cc: psa-members@python.org +Subject: Re: [PSA MEMBERS] ObjC.py ? + + +chriss@dnastar.com writes: +> Does anyone know what is left of the effort to interface +Python/ObjectiveC? +> E.g. is there a module, bits of code ... ? +> + +Well, it's not widely known, but SWIG has some support for ObjectiveC. +I haven't used this feature of SWIG in quite awhile, but I did use it +to build some Python interfaces to some simple ObjectiveC programs I +wrote about 3 years ago. I can't think of any reason why it wouldn't +work (unless there has been some sort of bit-rot that I'm not aware +of). + +Cheers, + +Dave + + +_______________________________________________ +PSA-members mailing list +PSA-members@python.org +http://www.python.org/mailman/listinfo/psa-members + +_______________________________________________ +PSA-members mailing list +PSA-members@python.org +http://www.python.org/mailman/listinfo/psa-members + + diff --git a/inc/app/sitemailer2/tests/sendmail_01.txt b/inc/app/sitemailer2/tests/sendmail_01.txt new file mode 100644 index 00000000..cfea95a2 --- /dev/null +++ b/inc/app/sitemailer2/tests/sendmail_01.txt @@ -0,0 +1,146 @@ +From VM Sat Oct 14 00:29:43 2000 +Return-Path: +Delivered-To: bxxxxx@mail.wooz.org +Received: from ns1.beopen.com (unknown [208.185.174.104]) + by mail.wooz.org (Postfix) with ESMTP id DF2B1D38CD + for ; Sat, 14 Oct 2000 00:16:04 -0400 (EDT) +Received: from dinsdale.python.org (dinsdale.cnri.reston.va.us [132.151.1.21]) + by ns1.beopen.com (8.9.3/8.9.3) with ESMTP id VAA04124 + for ; Fri, 13 Oct 2000 21:17:08 -0700 (PDT) + (envelope-from mailman-users-admin@python.org) +Received: from dinsdale.python.org (localhost [127.0.0.1]) + by dinsdale.python.org (Postfix) with ESMTP id 46F711D08C + for ; Sat, 14 Oct 2000 00:15:15 -0400 (EDT) +Delivered-To: mailman-users-admin@python.org +Received: from banzai.nfg.nl (banzai.nfg.nl [194.109.206.156]) + by dinsdale.python.org (Postfix) with ESMTP id 201661D08C + for ; Sat, 14 Oct 2000 00:14:45 -0400 (EDT) +Received: from localhost (localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with internal id GAB17388; + Sat, 14 Oct 2000 06:14:45 +0200 +Message-Id: <200010140414.GAB17388@banzai.nfg.nl> +Auto-Submitted: auto-generated (failure) +Errors-To: mailman-users-owner@python.org +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +From: Mail Delivery Subsystem +Sender: mailman-users-owner@python.org +To: mailman-users-admin@python.org +To: postmaster@banzai.nfg.nl +Subject: Returned mail: Too many hops 26 (25 max): from mailman-users-admin@python.org via localhost, to zzzzz@nfg.nl +Date: Sat, 14 Oct 2000 06:14:45 +0200 +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0beta6 + +The original message was received at Sat, 14 Oct 2000 06:14:45 +0200 +from uucp@localhost + + ----- The following addresses had permanent fatal errors ----- +zzzzz@shaft.coal.nl + (expanded from: zzzzz@nfg.nl) + + ----- Transcript of session follows ----- +554 Too many hops 26 (25 max): from mailman-users-admin@python.org via localhost, to zzzzz@nfg.nl + + ----- Message header follows ----- + +Return-Path: +Received: (from uucp@localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with UUCP id GAA17388 + for zzzzz@nfg.nl; Sat, 14 Oct 2000 06:14:45 +0200 +Received: by shaft.coal.nl (Postfix, from userid 10) + id A9BAE1B30B; Sat, 14 Oct 2000 06:06:08 +0200 (CEST) +Received: (from uucp@localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with UUCP id XAA25085 + for zzzzz@nfg.nl; Fri, 13 Oct 2000 23:55:54 +0200 +Received: by shaft.coal.nl (Postfix, from userid 10) + id 62E251B307; Fri, 13 Oct 2000 23:46:43 +0200 (CEST) +Received: (from uucp@localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with UUCP id XAA20156 + for zzzzz@nfg.nl; Fri, 13 Oct 2000 23:35:01 +0200 +Received: by shaft.coal.nl (Postfix, from userid 10) + id 247881B308; Fri, 13 Oct 2000 23:26:09 +0200 (CEST) +Received: (from uucp@localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with UUCP id XAA15152 + for zzzzz@nfg.nl; Fri, 13 Oct 2000 23:15:47 +0200 +Received: by shaft.coal.nl (Postfix, from userid 10) + id E91F81B308; Fri, 13 Oct 2000 23:06:29 +0200 (CEST) +Received: (from uucp@localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with UUCP id WAA09896 + for zzzzz@nfg.nl; Fri, 13 Oct 2000 22:54:42 +0200 +Received: by shaft.coal.nl (Postfix, from userid 10) + id 51CA11B308; Fri, 13 Oct 2000 22:45:24 +0200 (CEST) +Received: (from uucp@localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with UUCP id WAA04651 + for zzzzz@nfg.nl; Fri, 13 Oct 2000 22:34:41 +0200 +Received: by shaft.coal.nl (Postfix, from userid 10) + id 6C48F1B308; Fri, 13 Oct 2000 22:25:19 +0200 (CEST) +Received: (from uucp@localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with UUCP id WAA31892 + for zzzzz@nfg.nl; Fri, 13 Oct 2000 22:14:14 +0200 +Received: by shaft.coal.nl (Postfix, from userid 10) + id 8ABF91B308; Fri, 13 Oct 2000 22:04:33 +0200 (CEST) +Received: (from uucp@localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with UUCP id VAA26727 + for zzzzz@nfg.nl; Fri, 13 Oct 2000 21:54:10 +0200 +Received: by shaft.coal.nl (Postfix, from userid 10) + id A44BC1B308; Fri, 13 Oct 2000 21:44:57 +0200 (CEST) +Received: (from uucp@localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with UUCP id VAA21600 + for zzzzz@nfg.nl; Fri, 13 Oct 2000 21:33:40 +0200 +Received: by shaft.coal.nl (Postfix, from userid 10) + id 56B311B308; Fri, 13 Oct 2000 21:24:00 +0200 (CEST) +Received: (from uucp@localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with UUCP id VAA16279 + for zzzzz@nfg.nl; Fri, 13 Oct 2000 21:13:21 +0200 +Received: by shaft.coal.nl (Postfix, from userid 10) + id 409701B308; Fri, 13 Oct 2000 21:04:32 +0200 (CEST) +Received: (from uucp@localhost) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with UUCP id UAA11084 + for zzzzz@nfg.nl; Fri, 13 Oct 2000 20:53:53 +0200 +Received: by shaft.coal.nl (Postfix, from userid 10) + id 05A9E1B307; Fri, 13 Oct 2000 20:44:14 +0200 (CEST) +Received: from dinsdale.python.org (dinsdale.cnri.reston.va.us [132.151.1.21]) + by banzai.nfg.nl (8.9.3/8.9.3/Debian 8.9.3-21) with ESMTP id UAA08474 + for ; Fri, 13 Oct 2000 20:41:13 +0200 +X-Authentication-Warning: banzai.nfg.nl: Host dinsdale.cnri.reston.va.us [132.151.1.21] claimed to be dinsdale.python.org +Received: from dinsdale.python.org (localhost [127.0.0.1]) + by dinsdale.python.org (Postfix) with ESMTP + id A1F631CFCC; Fri, 13 Oct 2000 14:38:00 -0400 (EDT) +Delivered-To: mailman-users@python.org +Received: from raptor.ebuilt.net (unknown [216.237.34.38]) + by dinsdale.python.org (Postfix) with ESMTP id 7D3B21CDB9 + for ; Fri, 13 Oct 2000 14:35:02 -0400 (EDT) +Received: by raptor.ebuilt.net with Internet Mail Service (5.5.2650.21) + id <4V699WRN>; Fri, 13 Oct 2000 11:35:00 -0700 +Message-ID: +From: "Young, Roger" +To: mailman-users@python.org +X-Mailer: Internet Mail Service (5.5.2650.21) +Subject: [Mailman-Users] auto responder +Sender: mailman-users-admin@python.org +Errors-To: mailman-users-admin@python.org +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0beta6 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +Date: Fri, 13 Oct 2000 11:34:51 -0700 + + ----- Message body suppressed ----- + + + diff --git a/inc/app/sitemailer2/tests/simple_01.txt b/inc/app/sitemailer2/tests/simple_01.txt new file mode 100644 index 00000000..f2d2669f --- /dev/null +++ b/inc/app/sitemailer2/tests/simple_01.txt @@ -0,0 +1,153 @@ +From VM Tue Feb 20 10:32:44 2001 +Return-Path: +Delivered-To: zzzzz@wwww.org +Received: from digicool.com (host15.digitalcreations.d.subnet.rcn.com [208.59.6.15]) + by mail.wwww.org (Postfix) with ESMTP id 06EA8D37AC + for ; Sun, 18 Feb 2001 03:26:37 -0500 (EST) +Received: from + by digicool.com (CommuniGate Pro RULES 3.3.2) + with RULES id 1483250; Sun, 18 Feb 2001 03:27:53 -0500 +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.3.2) + with ESMTP id 1483249 for yyyyy@mail.digicool.com; Sun, 18 Feb 2001 03:27:53 -0500 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id DAA13272 + for ; Sun, 18 Feb 2001 03:25:56 -0500 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14UPAP-0001ei-00 + for yyyyy@digicool.com; Sun, 18 Feb 2001 03:26:01 -0500 +Received: from [63.118.43.131] (helo=receive.turbosport.com) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14UP9j-0001c7-00 + for jpython-interest-admin@python.org; Sun, 18 Feb 2001 03:25:19 -0500 +Received: from receive.turbosport.com [63.118.43.131] by receive.turbosport.com [63.118.43.131] + with RAW (MDaemon.v3.5.2.R) + for ; Sun, 18 Feb 2001 02:26:12 -0600 +Message-ID: +Mime-Version: 1.0 +Content-Type: multipart/mixed; boundary="0218-0226-12-PART-BREAK" +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Python for the JavaTM Platform +List-Unsubscribe: , + +List-Archive: +From: MDaemon@receive.turbosport.com +Sender: jpython-interest-owner@python.org +To: jpython-interest-admin@python.org +Subject: Permanent Delivery Failure +Date: Sun, 18 Feb 2001 02:26:12 -0600 +X-Autogenerated: Mirror +X-Mirrored-by: +X-MDSend-Notifications-To: [trash] +X-MDaemon-Deliver-To: jpython-interest-admin@python.org +X-Actual-From: MDaemon@receive.turbosport.com +X-BeenThere: jpython-interest@python.org +X-Mailman-Version: 2.0.1 (101270) +Reply-To: BadMsgQ@receive.turbosport.com + + The following data may contain sections which represent BASE64 encoded + file attachments. These sections will be unreadable without MIME aware + tools. Seek your system administrator if you need help extracting any + files which may be embedded within this message. + +--0218-0226-12-PART-BREAK +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: 7bit + +The attached message had PERMANENT fatal delivery errors! + +After one or more unsuccessful delivery attempts the attached message has +been removed from the mail queue on this server. The number and frequency +of delivery attempts are determined by local configuration parameters. + +YOUR MESSAGE WAS NOT DELIVERED! + +The following addresses did NOT receive a copy of your message: + +> bbbsss@turbosport.com + +--- Session Transcript --- + Attempting SMTP connection to [63.118.43.130 : 25] + Waiting for socket connection... + Socket connection established + Waiting for protocol initiation... + 220 turbosport.com ESMTP MDaemon 3.5.2 ready + EHLO receive.turbosport.com + 250-turbosport.com Hello receive.turbosport.com, ESMTP hello! + 250-VRFY + 250-EXPN + 250-ETRN + 250-AUTH LOGIN CRAM-MD5 + 250-8BITMIME + 250 SIZE 40000000 + MAIL From: SIZE=1861 + 250 , Sender ok + RCPT To: + 552 Message for would exceed mailbox quota + QUIT +--- End Transcript --- + +: Message contains [1] file attachments + +--0218-0226-12-PART-BREAK +Content-Type: message/rfc822; charset=US-ASCII; name="md50002271709.md" +Content-Transfer-Encoding: 7bit +Content-ID: +Content-Description: + +Return-path: +Received: from mta540.mail.yahoo.com [216.136.131.22] by receive.turbosport.com [63.118.43.131] + with SMTP (MDaemon.v3.5.2.R) + for ; Sun, 18 Feb 2001 02:25:20 -0600 +Message-ID: <20010218082300.42071.qmail@mta540.mail.yahoo.com> +Received: from mta540.mail.yahoo.com for bbbsss@turbosport.com; Feb 18 00:23:00 2001 -0800 +Received: from smtp015.mail.yahoo.com (216.136.173.59) +X-Yahoo-Forwarded: from aaaaa_20@yahoo.com to bbbsss@turbosport.com + by mta540.mail.yahoo.com with SMTP; 18 Feb 2001 00:23:00 -0800 (PST) +Date: 18 Feb 2001 08:22:57 -0000 +From: MAILER-DAEMON@yahoo.com +To: aaaaa@yahoo.com +Subject: failure delivery +X-MDRcpt-To: bbbsss@turbosport.com +X-MDRemoteIP: 216.136.131.22 +X-Return-Path: jpython-interest-admin@python.org +X-MDaemon-Deliver-To: bbbsss@turbosport.com + +Message from yahoo.com. +Unable to deliver message to the following address(es). + +: +Sorry, I wasn't able to establish an SMTP connection. (#4.4.1) +I'm not going to try again; this message has been in the queue too long. + +--- Original message follows. + +Return-Path: +Received: from c58148.upc-c.chello.nl (HELO localhost) (212.187.58.148) + by smtp.mail.vip.sc5.yahoo.com with SMTP; 11 Feb 2001 01:15:27 -0000 +X-Apparently-From: +X-Sender: aaaaa@yahoo.com +From: Albert Ttttt +To: subscribe.motorcycles@listsociety.com +Date: Sun, 11 Feb 2001 02:14:40 +0100 +Subject: Subscribe +Reply-To: aaaaa@yahoo.com +MIME-Version: 1.0 +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: 7bit + + + +_________________________________________________________ +Do You Yahoo!? +Get your free @yahoo.com address at http://mail.yahoo.com + +--0218-0226-12-PART-BREAK-- + + + diff --git a/inc/app/sitemailer2/tests/simple_02.txt b/inc/app/sitemailer2/tests/simple_02.txt new file mode 100644 index 00000000..f017fa25 --- /dev/null +++ b/inc/app/sitemailer2/tests/simple_02.txt @@ -0,0 +1,118 @@ +From VM Thu Feb 22 16:05:17 2001 +Return-Path: +Delivered-To: zzzzz@wwww.org +Received: from digicool.com (host15.digitalcreations.d.subnet.rcn.com [208.59.6.15]) + by mail.wwww.org (Postfix) with ESMTP id AD081D37AC + for ; Thu, 22 Feb 2001 04:54:37 -0500 (EST) +Received: from + by digicool.com (CommuniGate Pro RULES 3.3.2) + with RULES id 1498944; Thu, 22 Feb 2001 04:56:22 -0500 +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.3.2) + with ESMTP id 1498943 for zzzzz@mail.digicool.com; Thu, 22 Feb 2001 04:56:22 -0500 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id EAA15538 + for ; Thu, 22 Feb 2001 04:54:14 -0500 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14VsRz-0002Md-00 + for zzzzz@digicool.com; Thu, 22 Feb 2001 04:54:15 -0500 +Received: from [204.68.24.95] (helo=nm195.netaddress.usa.net) + by mail.python.org with smtp (Exim 3.21 #1) + id 14VsRh-0002K2-00 + for python-list-admin@python.org; Thu, 22 Feb 2001 04:53:57 -0500 +Received: (qmail 1169 invoked by uid 0); 22 Feb 2001 09:51:46 -0000 +Message-ID: <20010222095146.1166.qmail@nm195.netaddress.usa.net> +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: MAILER-DAEMON@usa.net +Sender: python-list-owner@python.org +To: python-list-admin@python.org +Subject: Processing Error +Date: 22 Feb 2001 09:51:46 -0000 +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.1 (101270) + +Intended recipient: chris.ggggmmmm@usa.net + +The following mail has been returned because it encountered an error +while being processed. Please try to resend this message. + +A notice of this error has been reported to the POSTMASTER at USA.NET +which will attempt to contact the intended recipient. + +--------RETURNED MAIL FOLLOWS-------- +Received: from mail.python.org [63.102.49.29] by nm195 via mtad (34FM.0700.12.01) + with ESMTP id 167FBVJzI0889M19; Thu, 22 Feb 2001 09:51:43 GMT +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14Vs49-0000n4-00; Thu, 22 Feb 2001 04:29:37 -0500 +Path: news.baymountain.net!uunet!ash.uu.net!npeer.kpnqwest.net!news.tele.dk!130.133.1.3!fu-berlin.de!uni-berlin.de!adsl-138-89-39-3.nnj.adsl.bellatlantic.NET!not-for-mail +From: ccccc@meezon.com (Ccccc Mmmmm) +Newsgroups: comp.lang.python +Subject: Re: import statement is case sensitive +Lines: 28 +Message-ID: <3a947ac4.802440@News.CIS.DFN.DE> +References: <3a943bea.525315589@News.CIS.DFN.DE> +NNTP-Posting-Host: adsl-138-89-39-3.nnj.adsl.bellatlantic.net (138.89.39.3) +X-Trace: fu-berlin.de 982810722 24108160 138.89.39.3 (16 [57226]) +X-Newsreader: Forte Free Agent 1.1/32.230 +Xref: news.baymountain.net comp.lang.python:89820 +To: python-list@python.org +Sender: python-list-admin@python.org +Errors-To: python-list-admin@python.org +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.1 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +Date: Thu, 22 Feb 2001 02:58:29 GMT + +"Lyle" wrote: + +>> Also what is the purpose of even having it case sensitive. I've yet to +>> see a file system that has case sensitive filenames.... +> +>There is an operating system called "Unix" that has case-sensitive file +>names. There is a slight chance that others on this newsgroup have also +>heard of this obscure operating system. +> + +Well given the fact that Linux and Windows is beating it to death I +can see why Unix is becoming obscure :) + +Actually I would consider this a shortcoming of Unix. Shipping a +product that depends on the directory names and files being in the +right case must cause all sorts of headaches. + +I am trying to run an an application under Windows and now I have to +worry if my directory name is in the correct case. I use PythonWin (a +fantastic product) to run and test it. There is no option for telling +it to ignore the case of the import filenames that I could see. + +And renaming directories and files is not an easy option.. But anyway, +this is should automatically be handled in Python depending on the OS. + + +Why would asnyone make the same filenames with different cases? Is +there a good use? +-- +http://mail.python.org/mailman/listinfo/python-list +---------END OF RETURNED MAIL-------- + + diff --git a/inc/app/sitemailer2/tests/simple_03.txt b/inc/app/sitemailer2/tests/simple_03.txt new file mode 100644 index 00000000..16fc04d6 --- /dev/null +++ b/inc/app/sitemailer2/tests/simple_03.txt @@ -0,0 +1,68 @@ +From VM Mon Apr 2 02:29:26 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil t nil nil] + [nil "Monday" "2" "April" "2001" "08:27:16" "+0200" "Mail Delivery System" "Mailer-Daemon@pop3.pta.lia.net" nil "18" "Warning: message 14jRTi-0007jE-00 delayed 24 hours" "^From:" "python-list-admin@python.org" "python-list-admin@python.org" "4" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: bwarsaw@wooz.org +Received: from digicool.com (host15.digitalcreations.d.subnet.rcn.com [208.59.6.15]) + by mail.wooz.org (Postfix) with ESMTP id 458FAD3757 + for ; Mon, 2 Apr 2001 02:25:41 -0400 (EDT) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 1746501; Mon, 02 Apr 2001 02:27:54 -0400 +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 1746500 for barry@mail.digicool.com; Mon, 02 Apr 2001 02:27:54 -0400 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id CAA09080 + for ; Mon, 2 Apr 2001 02:28:02 -0400 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14jxoo-0003mt-00 + for barry@digicool.com; Mon, 02 Apr 2001 02:28:02 -0400 +Received: from [196.22.216.11] (helo=pop3.pta.lia.net ident=root) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14jxo8-0003hg-00 + for python-list-admin@python.org; Mon, 02 Apr 2001 02:27:23 -0400 +Received: from root by pop3.pta.lia.net with local (Exim 1.92 #1) + for python-list-admin@python.org + id 14jxo4-00007H-00; Mon, 2 Apr 2001 08:27:16 +0200 +Message-Id: +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: Mail Delivery System +Sender: python-list-owner@python.org +To: python-list-admin@python.org +Subject: Warning: message 14jRTi-0007jE-00 delayed 24 hours +Date: Mon, 2 Apr 2001 08:27:16 +0200 +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.3 (101270) + +This message was created automatically by mail delivery software. + +A message that you sent has not yet been delivered to all its recipients +after more than 24 hours on the queue on pop3.pta.lia.net. + +The message identifier is: 14jRTi-0007jE-00 +The subject of the message is: I want to learn PYTHON! +The date of the message is: Sat, 31 Mar 2001 14:33:06 -0500 + +The address to which the message has not yet been delivered is: + + jacobus@geo.co.za + +No action is required on your part. Delivery attempts will continue for +some time, and this warning may be repeated at intervals if the message +remains undelivered. Eventually the mail delivery software will give up, +and when that happens, the message will be returned to you. + + diff --git a/inc/app/sitemailer2/tests/simple_04.txt b/inc/app/sitemailer2/tests/simple_04.txt new file mode 100644 index 00000000..022a3198 --- /dev/null +++ b/inc/app/sitemailer2/tests/simple_04.txt @@ -0,0 +1,105 @@ +From VM Sat Aug 4 01:17:43 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Friday" "3" "August" "2001" "23:59:56" "-0500" "MAILER-DAEMON@airmail.net" "MAILER-DAEMON@airmail.net" nil "51" "mail failed, returning to sender" "^From:" nil nil "8" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: barry@wooz.org +Received: from digicool.com (unknown [63.100.190.15]) + by mail.wooz.org (Postfix) with ESMTP id D0258D3738 + for ; Sat, 4 Aug 2001 01:00:57 -0400 (EDT) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 2491440; Sat, 04 Aug 2001 01:01:04 -0400 +Received: from smtp.zope.com ([63.100.190.10] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 2491439 for barry@mail.zope.com; Sat, 04 Aug 2001 01:01:04 -0400 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by smtp.zope.com (8.11.2/8.11.2) with ESMTP id f74511X29279 + for ; Sat, 4 Aug 2001 01:01:01 -0400 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15StYa-0005er-00; Sat, 04 Aug 2001 01:01:00 -0400 +Received: from [209.196.77.104] (helo=mx7.airmail.net) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15StYG-0005ec-00 + for mailman-users-admin@python.org; Sat, 04 Aug 2001 01:00:40 -0400 +Received: from mail3.iadfw.net ([209.196.123.3]) + by mx7.airmail.net with smtp (Exim 3.16 #10) + id 15StY6-000E5t-00 + for mailman-users-admin@python.org; Sat, 04 Aug 2001 00:00:30 -0500 +Received: from mail3.iadfw.net by mail3.iadfw.net + (/\##/\ Smail3.1.30.16 #30.25) with bsmtp for sender: + id ; Fri, 3 Aug 2001 23:59:56 -0500 (CDT) +Message-Id: +Reference: +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +From: +Sender: mailman-users-owner@python.org +To: mailman-users-admin@python.org +Subject: mail failed, returning to sender +Date: Fri, 3 Aug 2001 23:59:56 -0500 (CDT) +X-Autogenerated: Mirror +X-Mirrored-by: +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0.6 (101270) + +|------------------------- Message log follows: -------------------------| + no valid recipients were found for this message +|------------------------- Failed addresses follow: ---------------------| + claird@starbase.neosoft.com ... unknown host +|------------------------- Message text follows: ------------------------| +Received: from mx1.airmail.net from [209.196.77.98] by mail3.iadfw.net + (/\##/\ Smail3.1.30.16 #30.25) with esmtp sender: + id ; Fri, 3 Aug 2001 23:59:49 -0500 (CDT) +Received: from mail.python.org ([63.102.49.29]) + by mx1.airmail.net with esmtp (Exim 3.16 #10) + id 15StVY-000P3g-00 + for claird@neosoft.com; Fri, 03 Aug 2001 23:57:52 -0500 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15StSp-0005bx-00; Sat, 04 Aug 2001 00:55:03 -0400 +Received: from [206.81.192.3] (helo=sttlpop3.sttl.uswest.net) + by mail.python.org with smtp (Exim 3.21 #1) + id 15StRq-0005bS-00 + for mailman-users@python.org; Sat, 04 Aug 2001 00:54:02 -0400 +Received: (qmail 14391 invoked by alias); 4 Aug 2001 04:53:49 -0000 +Delivered-To: fixup-mailman-users@python.org@fixme +Received: (qmail 14361 invoked by uid 0); 4 Aug 2001 04:53:48 -0000 +Received: from sttldslgw14poola186.sttl.uswest.net (HELO first-last.ocentrix.com) (63.229.16.186) + by sttlpop3.sttl.uswest.net with SMTP; 4 Aug 2001 04:53:48 -0000 +Message-Id: <5.0.2.1.0.20010803211707.04770ce0@mail.ocentrix.com> +X-Sender: benwa@mail.ocentrix.com +X-Mailer: QUALCOMM Windows Eudora Version 5.0.2 +To: runaway@rahul.net (Colin Andrews) +From: Ben Burnett +Subject: Re: [Mailman-Users] Excessive headers and Eudora +Cc: mailman-users@python.org +In-Reply-To: <20010803190718.3389699D03@waltz.rahul.net> +Mime-Version: 1.0 +Content-Type: text/plain; charset="us-ascii"; format=flowed +Sender: mailman-users-admin@python.org +Errors-To: mailman-users-admin@python.org +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0.6 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +Date: Fri, 03 Aug 2001 21:54:02 -0700 + +[low-priority message, body not included] + + diff --git a/inc/app/sitemailer2/tests/sina_01.txt b/inc/app/sitemailer2/tests/sina_01.txt new file mode 100644 index 00000000..366500a9 --- /dev/null +++ b/inc/app/sitemailer2/tests/sina_01.txt @@ -0,0 +1,128 @@ +Return-Path: +Received: from mx04.mrf.mail.rcn.net ([207.172.4.53] [207.172.4.53]) + by mta05.mrf.mail.rcn.net with ESMTP + id <20020403160608.EQZZ19155.mta05.mrf.mail.rcn.net@mx04.mrf.mail.rcn.net>; + Wed, 3 Apr 2002 11:06:08 -0500 +Received: from milliways.osl.iu.edu ([129.79.245.239]) + by mx04.mrf.mail.rcn.net with esmtp (Exim 3.35 #5) + id 16snGx-0005F0-00 + for david.abrahams@rcn.com; Wed, 03 Apr 2002 11:06:07 -0500 +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33G61A24861; + Wed, 3 Apr 2002 11:06:01 -0500 +Received: from sina.com ([202.106.187.178]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with SMTP id g33G5CA24792 + for ; Wed, 3 Apr 2002 11:05:13 -0500 +Message-Id: <200204031605.g33G5CA24792@milliways.osl.iu.edu> +Received: (qmail 53818 invoked for bounce); 3 Apr 2002 15:55:44 -0000 +Date: 3 Apr 2002 15:55:44 -0000 +From: MAILER-DAEMON@sina.com +To: boost-admin@lists.boost.org +Subject: Óʼþ´«Êäʧ°Ü£¡ +MIME-Version: 1.0 +X-Priority: 3 +X-Mailer: SinaMail 3.0 +Content-Type: multipart/mixed; + boundary="----------101784934443375SINAEMAIL---" +Sender: boost-owner@lists.boost.org +Errors-To: boost-owner@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: + +This is a multi-part message in MIME format. + +------------101784934443375SINAEMAIL--- +Content-Type: text/plain; + charset="gb2312" +Content-Transfer-Encoding: binary + +sina.com. +ÓʼþÎÞ·¨·¢Ë͵½ÄúÖ¸¶¨µÄµØÖ·ÖС£ +ÔÚÓʼþ´«Êä¹ý³ÌÖÐÓÉÓÚÍⲿµÄÎÞ·¨±ÜÃâµÄ´íÎóµ¼ÖÂÓʼþÎÞ·¨ËÍ´ï¡£ + +: + +: + +--- ¸½¼þÖеÄÄÚÈÝÊÇÔ­ÐżþµÄÒ»·Ý¿½±´ + +------------101784934443375SINAEMAIL--- +Content-Type: message/rfc822; + name="original message.eml" +Content-Transfer-Encoding: binary +Content-Disposition: attachment; + filename="original message.eml" + +Return-Path: +Received: (qmail 31910 invoked from network); 3 Apr 2002 15:42:31 -0000 +Received: from unknown (HELO milliways.osl.iu.edu) (129.79.245.239) + by 202.106.187.178 with SMTP; 3 Apr 2002 15:42:31 -0000 +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33FaGA24120; + Wed, 3 Apr 2002 10:36:16 -0500 +Received: from hotmail.com (f128.law10.hotmail.com [64.4.15.128]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33FYUA24076 + for ; Wed, 3 Apr 2002 10:34:31 -0500 +Received: from mail pickup service by hotmail.com with Microsoft SMTPSVC; + Wed, 3 Apr 2002 07:34:23 -0800 +Received: from 194.100.118.234 by lw10fd.law10.hotmail.msn.com with HTTP; + Wed, 03 Apr 2002 15:34:23 GMT +X-Originating-IP: [194.100.118.234] +From: "Vesa Karvonen" +To: boost@lists.boost.org +Subject: Re: [boost] [Type Traits] Patch for type_with_alignment +Mime-Version: 1.0 +Content-Type: text/plain; format=flowed +Message-ID: +X-OriginalArrivalTime: 03 Apr 2002 15:34:23.0543 (UTC) FILETIME=[07DF4470:01C1DB25] +Sender: boost-admin@lists.boost.org +Errors-To: boost-admin@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +Reply-To: boost@lists.boost.org +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: +Date: Wed, 03 Apr 2002 18:34:23 +0300 + +Douglas Gregor: +>type_with_alignment<> is available in CVS. + +hmm... You are right, but it is in the compiler_supported_error_messages +branch. Is this intentional? + +>I'm guessing we should also add aligned_storage somewhere, because I'm +>sure quite a few of us will use it: + +Good idea. + +>Maybe this belongs in utility/aligned_storage.hpp? + +I have a feeling that something like this should probably go somewhere +closer to rather than . + + +_________________________________________________________________ +Send and receive Hotmail on your mobile device: http://mobile.msn.com + +_______________________________________________ +Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost + + + +------------101784934443375SINAEMAIL----- \ No newline at end of file diff --git a/inc/app/sitemailer2/tests/smtp32_01.txt b/inc/app/sitemailer2/tests/smtp32_01.txt new file mode 100644 index 00000000..decf0ddc --- /dev/null +++ b/inc/app/sitemailer2/tests/smtp32_01.txt @@ -0,0 +1,97 @@ +From VM Mon Apr 2 10:02:42 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Monday" "2" "April" "101" "04:20:10" "CST" "Postmaster" "postmaster@208.24.118.205" nil "48" "Undeliverable Mail" "^From:" nil nil "4" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: bwarsaw@wooz.org +Received: from digicool.com (host15.digitalcreations.d.subnet.rcn.com [208.59.6.15]) + by mail.wooz.org (Postfix) with ESMTP id B42DFD3757 + for ; Mon, 2 Apr 2001 06:21:39 -0400 (EDT) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 1746977; Mon, 02 Apr 2001 06:23:54 -0400 +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 1746976 for barry@mail.digicool.com; Mon, 02 Apr 2001 06:23:54 -0400 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id GAA19223 + for ; Mon, 2 Apr 2001 06:24:01 -0400 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14k1VB-0006KC-00 + for barry@digicool.com; Mon, 02 Apr 2001 06:24:01 -0400 +Received: from [207.51.255.218] (helo=208.24.118.205) + by mail.python.org with smtp (Exim 3.21 #1) + id 14k1UG-0006Ia-00 + for mailman-users-admin@python.org; Mon, 02 Apr 2001 06:23:04 -0400 +Message-Id: <10104020420.AA00477@208.24.118.205> +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +From: "Postmaster" +Sender: mailman-users-owner@python.org +To: +Subject: Undeliverable Mail +Date: Mon, 2 Apr 101 04:20:10 CST +X-Autogenerated: Mirror +X-Mirrored-by: +X-Mailer: +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0.3 (101270) +Reply-To: + +Delivery failed 20 attempts: oliver@pcworld.com.ph + + +Original message follows. + +Received: from SMTP32-FWD by the-pentagon.com + (SMTP32) id A00000199; Sun, 1 Apr 101 09:53:32 CST +Received: from mail.python.org [63.102.49.29] by 208.24.118.205 with ESMTP + (SMTPD32-6.00) id AEF8223011C; Sun, 01 Apr 2001 10:53:31 -0500 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14jk6B-0005u4-00; Sun, 01 Apr 2001 11:49:03 -0400 +Received: from [195.3.3.14] (helo=ibis.worldnet.net) + by mail.python.org with esmtp (Exim 3.21 #1) + id 14jk5s-0005t5-00 + for mailman-users@python.org; Sun, 01 Apr 2001 11:48:45 -0400 +Received: from m3.worldnet.net (m2.worldnet.net [195.3.3.6]) + by ibis.worldnet.net (8.11.3/8.11.1) with ESMTP id f31Fmgv23795 + for ; Sun, 1 Apr 2001 17:48:42 +0200 (CEST) + (envelope-from bootc@worldnet.fr) +Received: from [195.3.46.106] (i46-106.province.worldnet.fr [195.3.46.106]) + by m3.worldnet.net (8.11.2/8.11.1) with ESMTP id f31FnIY00581 + for ; Sun, 1 Apr 2001 17:49:18 +0200 (CEST) + (envelope-from bootc@worldnet.fr) +User-Agent: Microsoft-Outlook-Express-Macintosh-Edition/5.02.2022 +Subject: Re: [Mailman-Users] List Info page showing wrong e-mail address +From: Chris Boot +To: Mailman Users +Message-ID: +In-Reply-To: +Mime-version: 1.0 +Content-type: text/plain; charset="US-ASCII" +Content-transfer-encoding: 7bit +Sender: mailman-users-admin@python.org +Errors-To: mailman-users-admin@python.org +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0.3 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + + +[message truncated] + + diff --git a/inc/app/sitemailer2/tests/smtp32_02.txt b/inc/app/sitemailer2/tests/smtp32_02.txt new file mode 100644 index 00000000..3336a28d --- /dev/null +++ b/inc/app/sitemailer2/tests/smtp32_02.txt @@ -0,0 +1,96 @@ +From VM Wed May 30 01:59:29 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Tuesday" "29" "May" "2001" "20:19:37" "-0700" "Postmaster" "postmaster@launchpoint.net" nil "48" "Undeliverable Mail" "^From:" nil nil "5" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: barry@wooz.org +Received: from digicool.com (unknown [63.100.190.15]) + by mail.wooz.org (Postfix) with ESMTP id 5BA95D35D7 + for ; Tue, 29 May 2001 23:48:06 -0400 (EDT) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 1993021; Tue, 29 May 2001 23:48:38 -0400 +Received: from ns2.digicool.com ([63.100.190.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 1993014 for barry@mail.digicool.com; Tue, 29 May 2001 23:47:17 -0400 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id XAA05200 + for ; Tue, 29 May 2001 23:46:46 -0400 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 154wwZ-0007Jf-00 + for barry@digicool.com; Tue, 29 May 2001 23:46:47 -0400 +Received: from [65.200.12.28] (helo=launchpoint.net) + by mail.python.org with esmtp (Exim 3.21 #1) + id 154wv7-0007H3-00 + for python-list-admin@python.org; Tue, 29 May 2001 23:45:17 -0400 +Message-Id: <10105292019.AA00136@launchpoint.net> +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +From: "Postmaster" +Sender: python-list-owner@python.org +To: +Subject: Undeliverable Mail +Date: Tue, 29 May 2001 20:19:37 -0700 +X-Autogenerated: Mirror +X-Mirrored-by: +X-Mailer: +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.5 (101270) + +Delivery failed 20 attempts: lists@mail.spicynoodles.com + + +Original message follows. + +Received: from mail.python.org [63.102.49.29] by launchpoint.net with ESMTP + (SMTPD32-6.06) id ACB127960212; Tue, 29 May 2001 09:22:09 -0700 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 154mEf-0002VG-00; Tue, 29 May 2001 12:20:45 -0400 +Received: from [194.109.0.100] (helo=centurion.xs4all.nl) + by mail.python.org with esmtp (Exim 3.21 #1) + id 154mDK-0002Te-00 + for python-list@python.org; Tue, 29 May 2001 12:19:22 -0400 +Received: by centurion.xs4all.nl (Postfix, from userid 1000) + id 14716147; Tue, 29 May 2001 18:18:49 +0200 (CEST) +From: Thomas Wouters +To: Jim Abrams +Cc: python-list@python.org +Subject: Re: Active State and the PSF +Message-ID: <20010529181849.U690@xs4all.nl> +References: +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +User-Agent: Mutt/1.3.17i +In-Reply-To: ; from jim@publishingresources.com on Tue, May 29, 2001 at 03:43:08PM +0000 +Sender: python-list-admin@python.org +Errors-To: python-list-admin@python.org +X-BeenThere: python-list@python.org +X-Mailman-Version: 2.0.5 (101270) +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: General discussion list for the Python programming language +List-Unsubscribe: , + +List-Archive: +Date: Tue, 29 May 2001 18:18:49 +0200 + +On Tue, May 29, 2001 at 03:43:08PM +0000, Jim Abrams wrote: + +> Forgive my lazyiness in not deciphering the GPL, but does the GPL put some + +[message truncated] + + diff --git a/inc/app/sitemailer2/tests/smtp32_03.txt b/inc/app/sitemailer2/tests/smtp32_03.txt new file mode 100644 index 00000000..0c284afc --- /dev/null +++ b/inc/app/sitemailer2/tests/smtp32_03.txt @@ -0,0 +1,92 @@ +From VM Wed Aug 1 17:39:21 2001 +X-VM-v5-Data: ([nil nil nil nil nil nil nil nil nil] + [nil "Wednesday" "1" "August" "2001" "12:02:47" "-0700" "Postmaster" "postmaster@mgw.xraymedia.com" nil "43" "Undeliverable Mail" "^From:" "mailman-users-admin@python.org" "mailman-users-admin@python.org" "8" nil nil nil nil nil] + nil) +Return-Path: +Delivered-To: barry@wooz.org +Received: from digicool.com (unknown [63.100.190.15]) + by mail.wooz.org (Postfix) with ESMTP id 012AFD35F4 + for ; Wed, 1 Aug 2001 15:24:04 -0400 (EDT) +Received: from + by digicool.com (CommuniGate Pro RULES 3.4) + with RULES id 2461696; Wed, 01 Aug 2001 15:24:06 -0400 +Received: from smtp.zope.com ([63.100.190.10] verified) + by digicool.com (CommuniGate Pro SMTP 3.4) + with ESMTP id 2461695 for barry@mail.zope.com; Wed, 01 Aug 2001 15:24:06 -0400 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by smtp.zope.com (8.11.2/8.11.2) with ESMTP id f71JO6X18645 + for ; Wed, 1 Aug 2001 15:24:06 -0400 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15S1bB-0001XU-00; Wed, 01 Aug 2001 15:24:05 -0400 +Received: from [209.17.153.132] (helo=mgw.xraymedia.com) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15S1aM-0001Wb-00 + for mailman-users-admin@python.org; Wed, 01 Aug 2001 15:23:14 -0400 +Message-Id: <10108011202.AA00462@mgw.xraymedia.com> +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +From: "Postmaster" +Sender: mailman-users-owner@python.org +To: mailman-users-admin@python.org +Subject: Undeliverable Mail +Date: Wed, 1 Aug 2001 12:02:47 -0700 +X-Autogenerated: Mirror +X-Mirrored-by: +X-Mailer: +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0.6 (101270) + +undeliverable to borisk@gw.xraymedia.com + + +Original message follows. + +Received: from mgw.xraymedia.com [209.17.153.132] by mgw.xraymedia.com with ESMTP + (SMTPD32-7.00 EVAL) id A2541501BA; Wed, 01 Aug 2001 12:02:47 -0700 +Received: from mgw.xraymedia.com [209.17.153.132] by mgw.xraymedia.com with ESMTP + (SMTPD32-7.00 EVAL) id A2534501B6; Wed, 01 Aug 2001 12:02:46 -0700 +Received: from mgw.xraymedia.com [209.17.153.132] by mgw.xraymedia.com with ESMTP + (SMTPD32-7.00 EVAL) id A24D3A01B6; Wed, 01 Aug 2001 12:02:46 -0700 +Received: from mgw.xraymedia.com [209.17.153.132] by mgw.xraymedia.com with ESMTP + (SMTPD32-7.00 EVAL) id A2533401B6; Wed, 01 Aug 2001 12:02:46 -0700 +Received: from hercules.xraymedia.com [64.69.69.18] by mgw.xraymedia.com with ESMTP + (SMTPD32-7.00 EVAL) id A2553201B6; Wed, 01 Aug 2001 12:02:45 -0700 +Received: from mail.python.org (mail.python.org [63.102.49.29]) + by hercules.xraymedia.com (8.11.0/8.11.0) with ESMTP id f71IEQb00859 + for ; Wed, 1 Aug 2001 11:14:26 -0700 +Received: from localhost.localdomain ([127.0.0.1] helo=mail.python.org) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15S13G-0008Mi-00; Wed, 01 Aug 2001 14:49:02 -0400 +Received: from [24.201.245.36] (helo=VL-MS-MR002.sc1.videotron.ca) + by mail.python.org with esmtp (Exim 3.21 #1) + id 15S12G-0008IE-00 + for mailman-users@python.org; Wed, 01 Aug 2001 14:48:00 -0400 +Received: from cthulhu.gerg.ca ([24.203.122.44]) by + VL-MS-MR002.sc1.videotron.ca (Netscape Messaging Server 4.15) + with ESMTP id GHEK7K02.QG7 for ; Wed, + 1 Aug 2001 14:47:44 -0400 +Received: from gward by cthulhu.gerg.ca with local (Exim 3.22 #1 (Debian)) + id 15S11y-0000ip-00 + for ; Wed, 01 Aug 2001 14:47:42 -0400 +To: mailman-users@python.org +Subject: Re: [Mailman-Users] pls HELP!!! +Message-ID: <20010801144742.B2759@mems-exchange.org> +Mail-Followup-To: mailman-users@python.org +References: +Mime-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline + +[message truncated] + + diff --git a/inc/app/sitemailer2/tests/yahoo_01.txt b/inc/app/sitemailer2/tests/yahoo_01.txt new file mode 100644 index 00000000..0758957f --- /dev/null +++ b/inc/app/sitemailer2/tests/yahoo_01.txt @@ -0,0 +1,47 @@ +Return-path: +Received: from mta540.mail.yahoo.com [216.136.131.22] by receive.turbosport.com [63.118.43.131] + with SMTP (MDaemon.v3.5.2.R) + for ; Sun, 18 Feb 2001 02:25:20 -0600 +Message-ID: <20010218082300.42071.qmail@mta540.mail.yahoo.com> +Received: from mta540.mail.yahoo.com for bbbsss@turbosport.com; Feb 18 00:23:00 2001 -0800 +Received: from smtp015.mail.yahoo.com (216.136.173.59) +X-Yahoo-Forwarded: from aaaaa_20@yahoo.com to bbbsss@turbosport.com + by mta540.mail.yahoo.com with SMTP; 18 Feb 2001 00:23:00 -0800 (PST) +Date: 18 Feb 2001 08:22:57 -0000 +From: MAILER-DAEMON@yahoo.com +To: aaaaa@yahoo.com +Subject: failure delivery +X-MDRcpt-To: bbbsss@turbosport.com +X-MDRemoteIP: 216.136.131.22 +X-Return-Path: jpython-interest-admin@python.org +X-MDaemon-Deliver-To: bbbsss@turbosport.com + +Message from yahoo.com. +Unable to deliver message to the following address(es). + +: +Sorry, I wasn't able to establish an SMTP connection. (#4.4.1) +I'm not going to try again; this message has been in the queue too long. + +--- Original message follows. + +Return-Path: +Received: from c58148.upc-c.chello.nl (HELO localhost) (212.187.58.148) + by smtp.mail.vip.sc5.yahoo.com with SMTP; 11 Feb 2001 01:15:27 -0000 +X-Apparently-From: +X-Sender: aaaaa@yahoo.com +From: Albert Ttttt +To: subscribe.motorcycles@listsociety.com +Date: Sun, 11 Feb 2001 02:14:40 +0100 +Subject: Subscribe +Reply-To: aaaaa@yahoo.com +MIME-Version: 1.0 +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: 7bit + + + +_________________________________________________________ +Do You Yahoo!? +Get your free @yahoo.com address at http://mail.yahoo.com + diff --git a/inc/app/sitemailer2/tests/yahoo_02.txt b/inc/app/sitemailer2/tests/yahoo_02.txt new file mode 100644 index 00000000..f0c4b3d9 Binary files /dev/null and b/inc/app/sitemailer2/tests/yahoo_02.txt differ diff --git a/inc/app/sitemailer2/tests/yahoo_03.txt b/inc/app/sitemailer2/tests/yahoo_03.txt new file mode 100644 index 00000000..eef9a9a7 --- /dev/null +++ b/inc/app/sitemailer2/tests/yahoo_03.txt @@ -0,0 +1,98 @@ +Return-Path: +Received: from mx04.mrf.mail.rcn.net ([207.172.4.53] [207.172.4.53]) + by mta02.mrf.mail.rcn.net with ESMTP + id <20020403141004.PXBK1795.mta02.mrf.mail.rcn.net@mx04.mrf.mail.rcn.net>; + Wed, 3 Apr 2002 09:10:04 -0500 +Received: from milliways.osl.iu.edu ([129.79.245.239]) + by mx04.mrf.mail.rcn.net with esmtp (Exim 3.35 #5) + id 16slSd-0006Tx-00 + for david.abrahams@rcn.com; Wed, 03 Apr 2002 09:10:04 -0500 +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33EA0A22345; + Wed, 3 Apr 2002 09:10:00 -0500 +Received: from mta545.mail.yahoo.com (mta545.mail.yahoo.com [216.136.131.27]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with SMTP id g33E9DA22332 + for ; Wed, 3 Apr 2002 09:09:13 -0500 +Date: Wed, 3 Apr 2002 09:09:13 -0500 +Message-Id: <200204031409.g33E9DA22332@milliways.osl.iu.edu> +From: MAILER-DAEMON@yahoo.com +To: boost-admin@lists.boost.org +X-Loop: MAILER-DAEMON@yahoo.com +Subject: Delivery failure +Sender: boost-owner@lists.boost.org +Errors-To: boost-owner@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: + +Message from yahoo.com. +Unable to deliver message to the following address(es). + +: +Sorry your message to cresus22@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +--- Original message follows. + +X-Rocket-Spam: 129.79.245.239 +X-YahooFilteredBulk: 129.79.245.239 +X-Track: 111: 20 +Return-Path: +Received: from milliways.osl.iu.edu (129.79.245.239) + by mta545.mail.yahoo.com with SMTP; 03 Apr 2002 06:09:04 -0800 (PST) +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33D6PA21151; + Wed, 3 Apr 2002 08:06:25 -0500 +Received: from exchsrv.uttc-utc.com ([63.80.119.4]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33D42A21076 + for ; Wed, 3 Apr 2002 08:04:03 -0500 +Received: by EXCHSRV with Internet Mail Service (5.5.2653.19) + id ; Wed, 3 Apr 2002 08:03:59 -0500 +Message-ID: <2FE8C75C7A06D4118BB50008C7F7E83103D5DF@EXCHSRV> +From: "Moore, Dave" +To: "'boost@lists.boost.org'" +MIME-Version: 1.0 +X-Mailer: Internet Mail Service (5.5.2653.19) +Content-Type: text/plain; + charset="iso-8859-1" +Subject: [boost] OT(?) Top Posting, Discussion Threads, and Outlook/Exchange +Sender: boost-admin@lists.boost.org +Errors-To: boost-admin@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +Reply-To: boost@lists.boost.org +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: +Date: Wed, 3 Apr 2002 08:03:58 -0500 + +Since the recent discussion-discussion, I just tried to reply the "right" +way in "RE: [boost] Thread locals", only to see my efforts cheerfully +ignored by the Mailing List archive. +(http://lists.boost.org/MailArchives/boost/) + +I am stuck with Outlook 2000 + Exchange 5.5 here at work, but have some +considerable pull with the Exchange Admin. + +I notice that my replies have the "References:" field stripped off. Any +Boosters successfully using this email combination, preserving the +references field? + +Thanks, and sorry for the noise. +Dave +_______________________________________________ +Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost +. diff --git a/inc/app/sitemailer2/tests/yahoo_04.txt b/inc/app/sitemailer2/tests/yahoo_04.txt new file mode 100644 index 00000000..73b7b466 --- /dev/null +++ b/inc/app/sitemailer2/tests/yahoo_04.txt @@ -0,0 +1,150 @@ +Return-Path: +Received: from mx04.mrf.mail.rcn.net ([207.172.4.53] [207.172.4.53]) + by mta05.mrf.mail.rcn.net with ESMTP + id <20020403144504.BXMM19155.mta05.mrf.mail.rcn.net@mx04.mrf.mail.rcn.net>; + Wed, 3 Apr 2002 09:45:04 -0500 +Received: from milliways.osl.iu.edu ([129.79.245.239]) + by mx04.mrf.mail.rcn.net with esmtp (Exim 3.35 #5) + id 16sm0V-0007O8-00 + for david.abrahams@rcn.com; Wed, 03 Apr 2002 09:45:04 -0500 +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33Ej1A23023; + Wed, 3 Apr 2002 09:45:01 -0500 +Received: from mta468.mail.yahoo.com (mta468.mail.yahoo.com [216.136.130.133]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with SMTP id g33EibA23012 + for ; Wed, 3 Apr 2002 09:44:37 -0500 +Date: Wed, 3 Apr 2002 09:44:37 -0500 +Message-Id: <200204031444.g33EibA23012@milliways.osl.iu.edu> +From: MAILER-DAEMON@yahoo.com +To: boost-admin@lists.boost.org +X-Loop: MAILER-DAEMON@yahoo.com +Subject: Delivery failure +Sender: boost-owner@lists.boost.org +Errors-To: boost-owner@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: + +Message from yahoo.com. +Unable to deliver message to the following address(es). + +: +Sorry, your message to agarciamartiartu@yahoo.es cannot be delivered. This account is over quota. + +: +Sorry, your message to open00now@yahoo.co.uk cannot be delivered. This account is over quota. + +--- Original message follows. + +X-Track: 0: 100 +Return-Path: +Received: from milliways.osl.iu.edu (129.79.245.239) + by mta468.mail.yahoo.com with SMTP; 03 Apr 2002 06:44:13 -0800 (PST) +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33EgcA22988; + Wed, 3 Apr 2002 09:42:38 -0500 +Received: from mail2.commerzbank.com (mail2.commerzbank.com [212.149.48.101]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33EciA22890 + for ; Wed, 3 Apr 2002 09:38:44 -0500 +Received: from sv016317.exchange.commerzbank.com (sendmail.commerzbank.com [172.16.71.150]) + by mail2.commerzbank.com (Commerzbank Mail-System) with ESMTP id 38105116C + for ; Wed, 3 Apr 2002 16:35:15 +0200 (CEST) +Received: by sv016317.exchange.commerzbank.com with Internet Mail Service (5.5.2653.19) + id <2GBLGLD2>; Wed, 3 Apr 2002 16:37:33 +0200 +Message-ID: +From: "Hoeffner, Detlef" +To: "'boost@lists.boost.org'" +Subject: RE: [boost] Thread locals +MIME-Version: 1.0 +X-Mailer: Internet Mail Service (5.5.2653.19) +Content-Type: text/plain; + charset="iso-8859-1" +Sender: boost-admin@lists.boost.org +Errors-To: boost-admin@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +Reply-To: boost@lists.boost.org +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: +Date: Wed, 3 Apr 2002 16:37:41 +0200 + + +> As a substitute, try using the comparison operator for the boost::thread +> class. This can fill the gap in many (but not all) cases where you are +> managing the set of threads yourself. + +I need this mainly for tracing purposes in spots where I have no knowledge +of the current instance of thread. This does not seem to help me in that +case. + +> On some platforms (i.e. pthreads), the "thread_id" is actually an opaque +> type (pthread_t) rather than a numeric value, and I think that is why no +> such operation is exposed in the current version of the library. + +It is however possible to provide a class threadid, that has dependent on +the +platform different members but provides operations as ==, !=, +operator<<(ostream&, ), ... That would be fine to solve the problem. + +Regards + +Detlef + +-----Original Message----- +From: Moore, Dave [mailto:dmoore@ashtontechgroup.com] +Sent: Mittwoch, 3. April 2002 14:33 +To: 'boost@lists.boost.org' +Subject: RE: [boost] Thread locals + + +> -----Original Message----- +> From: Hoeffner, Detlef +> [mailto:Detlef.Hoeffner@partner.commerzbank.com] +> Sent: Wednesday, April 03, 2002 6:59 AM +> To: 'boost@lists.boost.org' +> Subject: [boost] Thread locals +> +> +> Hello all, +> +> I am replacing my thread abstraction with the thread package +> from boost. It +> is very nice but I am missing two things. +> +> The first is the possibility to get an identifier for the +> current thread, a +> thread id. + +As a substitute, try using the comparison operator for the boost::thread +class. This can fill the gap in many (but not all) cases where you are +managing the set of threads yourself. + +On some platforms (i.e. pthreads), the "thread_id" is actually an opaque +type (pthread_t) rather than a numeric value, and I think that is why no +such operation is exposed in the current version of the library. + +Regards, +Dave + + +_______________________________________________ +Unsubscribe & other changes: +http://lists.boost.org/mailman/listinfo.cgi/boost +_______________________________________________ +Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost +. diff --git a/inc/app/sitemailer2/tests/yahoo_05.txt b/inc/app/sitemailer2/tests/yahoo_05.txt new file mode 100644 index 00000000..b33dc78b --- /dev/null +++ b/inc/app/sitemailer2/tests/yahoo_05.txt @@ -0,0 +1,150 @@ +Return-Path: +Received: from mx04.mrf.mail.rcn.net ([207.172.4.53] [207.172.4.53]) + by mta05.mrf.mail.rcn.net with ESMTP + id <20020403160106.EMCB19155.mta05.mrf.mail.rcn.net@mx04.mrf.mail.rcn.net>; + Wed, 3 Apr 2002 11:01:06 -0500 +Received: from milliways.osl.iu.edu ([129.79.245.239]) + by mx04.mrf.mail.rcn.net with esmtp (Exim 3.35 #5) + id 16snC5-0003g7-00 + for david.abrahams@rcn.com; Wed, 03 Apr 2002 11:01:06 -0500 +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33G10A24726; + Wed, 3 Apr 2002 11:01:00 -0500 +Received: from mta414.mail.yahoo.com (mta414.mail.yahoo.com [216.136.128.66]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with SMTP id g33G02A24708 + for ; Wed, 3 Apr 2002 11:00:03 -0500 +Date: Wed, 3 Apr 2002 11:00:03 -0500 +Message-Id: <200204031600.g33G02A24708@milliways.osl.iu.edu> +From: MAILER-DAEMON@yahoo.com +To: boost-admin@lists.boost.org +X-Loop: MAILER-DAEMON@yahoo.com +Subject: Delivery failure +Sender: boost-owner@lists.boost.org +Errors-To: boost-owner@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: + +Message from yahoo.com. +Unable to deliver message to the following address(es). + +: +Sorry your message to cresus22@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to jjb700@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +--- Original message follows. + +X-Track: 1: 40 +Return-Path: +Received: from milliways.osl.iu.edu (129.79.245.239) + by mta414.mail.yahoo.com with SMTP; 03 Apr 2002 07:59:49 -0800 (PST) +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33EduA22960; + Wed, 3 Apr 2002 09:39:56 -0500 +Received: from mail2.commerzbank.com (mail2.commerzbank.com [212.149.48.101]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33EciA22890 + for ; Wed, 3 Apr 2002 09:38:44 -0500 +Received: from sv016317.exchange.commerzbank.com (sendmail.commerzbank.com [172.16.71.150]) + by mail2.commerzbank.com (Commerzbank Mail-System) with ESMTP id 38105116C + for ; Wed, 3 Apr 2002 16:35:15 +0200 (CEST) +Received: by sv016317.exchange.commerzbank.com with Internet Mail Service (5.5.2653.19) + id <2GBLGLD2>; Wed, 3 Apr 2002 16:37:33 +0200 +Message-ID: +From: "Hoeffner, Detlef" +To: "'boost@lists.boost.org'" +Subject: RE: [boost] Thread locals +MIME-Version: 1.0 +X-Mailer: Internet Mail Service (5.5.2653.19) +Content-Type: text/plain; + charset="iso-8859-1" +Sender: boost-admin@lists.boost.org +Errors-To: boost-admin@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +Reply-To: boost@lists.boost.org +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: +Date: Wed, 3 Apr 2002 16:37:41 +0200 + + +> As a substitute, try using the comparison operator for the boost::thread +> class. This can fill the gap in many (but not all) cases where you are +> managing the set of threads yourself. + +I need this mainly for tracing purposes in spots where I have no knowledge +of the current instance of thread. This does not seem to help me in that +case. + +> On some platforms (i.e. pthreads), the "thread_id" is actually an opaque +> type (pthread_t) rather than a numeric value, and I think that is why no +> such operation is exposed in the current version of the library. + +It is however possible to provide a class threadid, that has dependent on +the +platform different members but provides operations as ==, !=, +operator<<(ostream&, ), ... That would be fine to solve the problem. + +Regards + +Detlef + +-----Original Message----- +From: Moore, Dave [mailto:dmoore@ashtontechgroup.com] +Sent: Mittwoch, 3. April 2002 14:33 +To: 'boost@lists.boost.org' +Subject: RE: [boost] Thread locals + + +> -----Original Message----- +> From: Hoeffner, Detlef +> [mailto:Detlef.Hoeffner@partner.commerzbank.com] +> Sent: Wednesday, April 03, 2002 6:59 AM +> To: 'boost@lists.boost.org' +> Subject: [boost] Thread locals +> +> +> Hello all, +> +> I am replacing my thread abstraction with the thread package +> from boost. It +> is very nice but I am missing two things. +> +> The first is the possibility to get an identifier for the +> current thread, a +> thread id. + +As a substitute, try using the comparison operator for the boost::thread +class. This can fill the gap in many (but not all) cases where you are +managing the set of threads yourself. + +On some platforms (i.e. pthreads), the "thread_id" is actually an opaque +type (pthread_t) rather than a numeric value, and I think that is why no +such operation is exposed in the current version of the library. + +Regards, +Dave + + +_______________________________________________ +Unsubscribe & other changes: +http://lists.boost.org/mailman/listinfo.cgi/boost +_______________________________________________ +Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost +. diff --git a/inc/app/sitemailer2/tests/yahoo_06.txt b/inc/app/sitemailer2/tests/yahoo_06.txt new file mode 100644 index 00000000..5baa4f58 --- /dev/null +++ b/inc/app/sitemailer2/tests/yahoo_06.txt @@ -0,0 +1,105 @@ +Return-Path: +Received: from mx04.mrf.mail.rcn.net ([207.172.4.53] [207.172.4.53]) + by mta03.mrf.mail.rcn.net with ESMTP + id <20020403160604.WVKA16695.mta03.mrf.mail.rcn.net@mx04.mrf.mail.rcn.net>; + Wed, 3 Apr 2002 11:06:04 -0500 +Received: from milliways.osl.iu.edu ([129.79.245.239]) + by mx04.mrf.mail.rcn.net with esmtp (Exim 3.35 #5) + id 16snGt-0005FB-00 + for david.abrahams@rcn.com; Wed, 03 Apr 2002 11:06:04 -0500 +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33G61A24869; + Wed, 3 Apr 2002 11:06:01 -0500 +Received: from mta593.mail.yahoo.com (mta593.mail.yahoo.com [216.136.224.181]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with SMTP id g33G5lA24845 + for ; Wed, 3 Apr 2002 11:05:47 -0500 +Date: Wed, 3 Apr 2002 11:05:47 -0500 +Message-Id: <200204031605.g33G5lA24845@milliways.osl.iu.edu> +From: MAILER-DAEMON@yahoo.com +To: boost-admin@lists.boost.org +X-Loop: MAILER-DAEMON@yahoo.com +Subject: Delivery failure +Sender: boost-owner@lists.boost.org +Errors-To: boost-owner@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: + +Message from yahoo.com. +Unable to deliver message to the following address(es). + +: +Sorry your message to andrew_polevoy@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to baruch_sterin@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to rjhoeks@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to tritonrugger91@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +--- Original message follows. + +X-Track: 1: 40 +Return-Path: +Received: from milliways.osl.iu.edu (129.79.245.239) + by mta593.mail.yahoo.com with SMTP; 03 Apr 2002 08:03:49 -0800 (PST) +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33D6PA21151; + Wed, 3 Apr 2002 08:06:25 -0500 +Received: from exchsrv.uttc-utc.com ([63.80.119.4]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33D42A21076 + for ; Wed, 3 Apr 2002 08:04:03 -0500 +Received: by EXCHSRV with Internet Mail Service (5.5.2653.19) + id ; Wed, 3 Apr 2002 08:03:59 -0500 +Message-ID: <2FE8C75C7A06D4118BB50008C7F7E83103D5DF@EXCHSRV> +From: "Moore, Dave" +To: "'boost@lists.boost.org'" +MIME-Version: 1.0 +X-Mailer: Internet Mail Service (5.5.2653.19) +Content-Type: text/plain; + charset="iso-8859-1" +Subject: [boost] OT(?) Top Posting, Discussion Threads, and Outlook/Exchange +Sender: boost-admin@lists.boost.org +Errors-To: boost-admin@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +Reply-To: boost@lists.boost.org +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: +Date: Wed, 3 Apr 2002 08:03:58 -0500 + +Since the recent discussion-discussion, I just tried to reply the "right" +way in "RE: [boost] Thread locals", only to see my efforts cheerfully +ignored by the Mailing List archive. +(http://lists.boost.org/MailArchives/boost/) + +I am stuck with Outlook 2000 + Exchange 5.5 here at work, but have some +considerable pull with the Exchange Admin. + +I notice that my replies have the "References:" field stripped off. Any +Boosters successfully using this email combination, preserving the +references field? + +Thanks, and sorry for the noise. +Dave +_______________________________________________ +Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost +. diff --git a/inc/app/sitemailer2/tests/yahoo_07.txt b/inc/app/sitemailer2/tests/yahoo_07.txt new file mode 100644 index 00000000..36df3fa0 --- /dev/null +++ b/inc/app/sitemailer2/tests/yahoo_07.txt @@ -0,0 +1,112 @@ +Return-Path: +Received: from mx04.mrf.mail.rcn.net ([207.172.4.53] [207.172.4.53]) + by mta05.mrf.mail.rcn.net with ESMTP + id <20020403160902.ETVB19155.mta05.mrf.mail.rcn.net@mx04.mrf.mail.rcn.net>; + Wed, 3 Apr 2002 11:09:02 -0500 +Received: from milliways.osl.iu.edu ([129.79.245.239]) + by mx04.mrf.mail.rcn.net with esmtp (Exim 3.35 #5) + id 16snJm-00067W-00 + for david.abrahams@rcn.com; Wed, 03 Apr 2002 11:09:02 -0500 +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33G90A24959; + Wed, 3 Apr 2002 11:09:00 -0500 +Received: from mta532.mail.yahoo.com (mta532.mail.yahoo.com [216.136.129.204]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with SMTP id g33G84A24927 + for ; Wed, 3 Apr 2002 11:08:05 -0500 +Date: Wed, 3 Apr 2002 11:08:05 -0500 +Message-Id: <200204031608.g33G84A24927@milliways.osl.iu.edu> +From: MAILER-DAEMON@yahoo.com +To: boost-admin@lists.boost.org +X-Loop: MAILER-DAEMON@yahoo.com +Subject: Delivery failure +Sender: boost-owner@lists.boost.org +Errors-To: boost-owner@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: + +Message from yahoo.com. +Unable to deliver message to the following address(es). + +: +Sorry your message to mark1960_1998@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to ovchenkov@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to tsa412@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to vaxheadroom@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +--- Original message follows. + +X-Track: 1: 40 +Return-Path: +Received: from 129.79.245.239 (EHLO milliways.osl.iu.edu) (129.79.245.239) + by mta532.mail.yahoo.com with SMTP; 03 Apr 2002 08:06:35 -0800 (PST) +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33DItA21480; + Wed, 3 Apr 2002 08:18:55 -0500 +Received: from hotmail.com (f110.law10.hotmail.com [64.4.15.110]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33DH7A21450 + for ; Wed, 3 Apr 2002 08:17:07 -0500 +Received: from mail pickup service by hotmail.com with Microsoft SMTPSVC; + Wed, 3 Apr 2002 05:16:59 -0800 +Received: from 194.100.118.234 by lw10fd.law10.hotmail.msn.com with HTTP; + Wed, 03 Apr 2002 13:16:59 GMT +X-Originating-IP: [194.100.118.234] +From: "Vesa Karvonen" +To: boost@lists.boost.org +Subject: Re: [boost] [Type Traits] Patch for type_with_alignment +Mime-Version: 1.0 +Content-Type: text/plain; format=flowed +Message-ID: +X-OriginalArrivalTime: 03 Apr 2002 13:16:59.0830 (UTC) FILETIME=[D63C7D60:01C1DB11] +Sender: boost-admin@lists.boost.org +Errors-To: boost-admin@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +Reply-To: boost@lists.boost.org +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: +Date: Wed, 03 Apr 2002 16:16:59 +0300 + +>On Fri, 29 Mar 2002, David Abrahams wrote: +>>Are you planning to apply this patch? +>> +>>-Dave +> +>Yes, but I can't right now. I'll apply it tomorrow if it hasn't already +>been done. +> +> Doug + +How is the patch coming up (or did I miss some post on this subject)? + +I'm also working on something that could use type_with_alignment<>. + + +_________________________________________________________________ +Join the world’s largest e-mail service with MSN Hotmail. +http://www.hotmail.com + +_______________________________________________ +Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost +. diff --git a/inc/app/sitemailer2/tests/yahoo_08.txt b/inc/app/sitemailer2/tests/yahoo_08.txt new file mode 100644 index 00000000..91b09f3f --- /dev/null +++ b/inc/app/sitemailer2/tests/yahoo_08.txt @@ -0,0 +1,129 @@ +Return-Path: +Received: from mx04.mrf.mail.rcn.net ([207.172.4.53] [207.172.4.53]) + by mta05.mrf.mail.rcn.net with ESMTP + id <20020403162905.FMNL19155.mta05.mrf.mail.rcn.net@mx04.mrf.mail.rcn.net>; + Wed, 3 Apr 2002 11:29:05 -0500 +Received: from milliways.osl.iu.edu ([129.79.245.239]) + by mx04.mrf.mail.rcn.net with esmtp (Exim 3.35 #5) + id 16snd9-0004Fd-00 + for david.abrahams@rcn.com; Wed, 03 Apr 2002 11:29:04 -0500 +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33GT1A25554; + Wed, 3 Apr 2002 11:29:01 -0500 +Received: from mta551.mail.yahoo.com (mta551.mail.yahoo.com [216.136.172.80]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with SMTP id g33GSmA25536 + for ; Wed, 3 Apr 2002 11:28:49 -0500 +Date: Wed, 3 Apr 2002 11:28:49 -0500 +Message-Id: <200204031628.g33GSmA25536@milliways.osl.iu.edu> +From: MAILER-DAEMON@yahoo.com +To: boost-admin@lists.boost.org +X-Loop: MAILER-DAEMON@yahoo.com +Subject: Delivery failure +Sender: boost-owner@lists.boost.org +Errors-To: boost-owner@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: + +Message from yahoo.com. +Unable to deliver message to the following address(es). + +: +Sorry your message to chatrathis@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to crownjules01@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to cwl_999@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to eichaiwiu@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to rjhoeks@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to yuli_kolesnikov@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +--- Original message follows. + +X-Track: 1: 40 +Return-Path: +Received: from milliways.osl.iu.edu (129.79.245.239) + by mta551.mail.yahoo.com with SMTP; 03 Apr 2002 08:22:08 -0800 (PST) +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33GJwA25252; + Wed, 3 Apr 2002 11:19:58 -0500 +Received: from mailout6-0.nyroc.rr.com (mailout6-0.nyroc.rr.com [24.92.226.125]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33GInA25230 + for ; Wed, 3 Apr 2002 11:18:49 -0500 +Received: from there (alb-66-24-181-181.nycap.rr.com [66.24.181.181]) + by mailout6-0.nyroc.rr.com (8.11.6/Road Runner 1.12) with SMTP id g33GIko18895 + for ; Wed, 3 Apr 2002 11:18:46 -0500 (EST) +Message-Id: <200204031618.g33GIko18895@mailout6-0.nyroc.rr.com> +Content-Type: text/plain; + charset="iso-8859-1" +From: Douglas Gregor +Organization: Rensselaer Polytechnic Institute +To: boost@lists.boost.org +Subject: Re: [boost] [Type Traits] Patch for type_with_alignment +X-Mailer: KMail [version 1.3.2] +References: +In-Reply-To: +MIME-Version: 1.0 +Content-Transfer-Encoding: 8bit +Sender: boost-admin@lists.boost.org +Errors-To: boost-admin@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +Reply-To: boost@lists.boost.org +X-Reply-To: gregod@cs.rpi.edu +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: +Date: Wed, 3 Apr 2002 11:21:18 -0500 + +On Wednesday 03 April 2002 10:34 am, you wrote: +> Douglas Gregor: +> >type_with_alignment<> is available in CVS. +> +> hmm... You are right, but it is in the compiler_supported_error_messages +> branch. Is this intentional? + +It was a rogue sticky tag... type_with_alignment<> is now on the CVS main +trunk, where it was supposed to be in the first place. + +> >I'm guessing we should also add aligned_storage somewhere, because I'm +> >sure quite a few of us will use it: +> +> Good idea. +> +> >Maybe this belongs in utility/aligned_storage.hpp? +> +> I have a feeling that something like this should probably go somewhere +> closer to rather than . + +? I'd really like to have more than 6 lines in it, but we +can do that. That'd probably be a good place for the small-string +optimization allocator as well. + + Doug +_______________________________________________ +Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost +. + diff --git a/inc/app/sitemailer2/tests/yahoo_09.txt b/inc/app/sitemailer2/tests/yahoo_09.txt new file mode 100644 index 00000000..e3886730 --- /dev/null +++ b/inc/app/sitemailer2/tests/yahoo_09.txt @@ -0,0 +1,165 @@ +Return-Path: +Received: from mx04.mrf.mail.rcn.net ([207.172.4.53] [207.172.4.53]) + by mta01.mrf.mail.rcn.net with ESMTP + id <20020403190104.CHE29566.mta01.mrf.mail.rcn.net@mx04.mrf.mail.rcn.net>; + Wed, 3 Apr 2002 14:01:04 -0500 +Received: from milliways.osl.iu.edu ([129.79.245.239]) + by mx04.mrf.mail.rcn.net with esmtp (Exim 3.35 #5) + id 16sq0F-0005l5-00 + for david.abrahams@rcn.com; Wed, 03 Apr 2002 14:01:03 -0500 +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33J11A07189; + Wed, 3 Apr 2002 14:01:01 -0500 +Received: from mta446.mail.yahoo.com (mta446.mail.yahoo.com [216.136.129.101]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with SMTP id g33J04A07150 + for ; Wed, 3 Apr 2002 14:00:05 -0500 +Date: Wed, 3 Apr 2002 14:00:05 -0500 +Message-Id: <200204031900.g33J04A07150@milliways.osl.iu.edu> +From: MAILER-DAEMON@yahoo.com +To: boost-admin@lists.boost.org +X-Loop: MAILER-DAEMON@yahoo.com +Subject: Delivery failure +Sender: boost-owner@lists.boost.org +Errors-To: boost-owner@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: + +Message from yahoo.com. +Unable to deliver message to the following address(es). + +: +Sorry your message to hankel_o_fung@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +: +Sorry your message to ultravirus2001@yahoo.com cannot be delivered. This account has been disabled or discontinued. + +--- Original message follows. + +The original message is over 5K. Message truncated. + +X-Track: 1: 100 +Return-Path: +Received: from milliways.osl.iu.edu (129.79.245.239) + by mta446.mail.yahoo.com with SMTP; 03 Apr 2002 10:59:57 -0800 (PST) +Received: from milliways.osl.iu.edu (localhost [127.0.0.1]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with ESMTP id g33HexA27227; + Wed, 3 Apr 2002 12:40:59 -0500 +Received: from smtp016.mail.yahoo.com (smtp016.mail.yahoo.com [216.136.174.113]) + by milliways.osl.iu.edu (8.11.6/8.11.6/IUCS_2.44) with SMTP id g33HcwA27186 + for ; Wed, 3 Apr 2002 12:38:58 -0500 +Received: from ppp-1-53.chel-5800-8.access.uk.tiscali.com (HELO albert) (RaoulGough@212.159.169.53 with login) + by smtp.mail.vip.sc5.yahoo.com with SMTP; 3 Apr 2002 17:38:54 -0000 +Message-ID: <001601c1db36$6da28950$0100a8c0@albert> +From: "Raoul Gough" +To: +References: <200204011702.g31H2eA04494@milliways.osl.iu.edu> +MIME-Version: 1.0 +Content-Type: text/plain; + charset="iso-8859-1" +Content-Transfer-Encoding: 7bit +X-Priority: 3 +X-MSMail-Priority: Normal +X-Mailer: Microsoft Outlook Express 6.00.2600.0000 +X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000 +Subject: [boost] Re: boost::weak_ptr suggestions +Sender: boost-admin@lists.boost.org +Errors-To: boost-admin@lists.boost.org +X-BeenThere: boost@lists.boost.org +X-Mailman-Version: 2.0.8 +Precedence: bulk +Reply-To: boost@lists.boost.org +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Boost mailing list +List-Unsubscribe: , + +List-Archive: +Date: Wed, 3 Apr 2002 18:37:55 +0100 + +> From: "Peter Dimov" +> To: +> Subject: Re: [boost] boost::weak_ptr suggestions +> Date: Mon, 1 Apr 2002 17:31:05 +0300 +> Organization: Multi Media Ltd. +> Reply-To: boost@lists.boost.org +> +> From: "Raoul Gough" +[snip] +> > Secondly, I believe it would be better for the get() method to throw or +> > assert when called on an invalidated pointer, instead of transparently +> > returning 0. In my opinion, there is a fundamental difference between +the +> > two states (null and invalid) which is not observable with the current +> > interface. The addition of a member function like "bool is_valid() +const;" +> > would also allow the user code to decide how to deal with an invalid +> > pointer, instead of merging the two distinct states into the one (null) +> > state. +> +> Right again. However, the primary methods of accessing a weak_ptr are (1) +> constructing a shared_ptr (which does throw) and (2) make_shared. get() +has +> been retained for efficiency but is not recommended (in multithreaded +> programs.) + +So why the difference in error semantics between the single and +multi-threaded idioms? For example, if I converted single-threaded code that +uses get() to thread-safe code using make_shared, I also get changed +semantics for the invalid pointer case. + +Incidentally, it looks like the use_count member function can determine +indirectly whether the target still exists or not. It seems a bit obscure +though, seeing as the reference count is really an implementation detail and +distinct from the concept of null/valid/invalid. + +> +> > The big advantage of considering invalid.get() an error is that code +which +> > then works without error using weak_ptr would have *exactly* unchanged +> > semantics using a plain pointer replacement. This allows (for example) a +> > debug build/release build choice between weak_ptr and T* for +> performance +> > reasons. If weak_ptr silently returns null on invalid pointers, then +> this +> > guarantee cannot be made - what would be undefined use on a plain +pointer +> is +> > not detected by the weak_ptr. +> +> Interesting point. You can write your own get() that does what you want: +> +> T * get(weak_ptr const & p) +> { +> return shared_ptr(p).get(); +> } +> +> but it's not as efficient as a throwing get(). Most people seem to prefer +> the current get() semantics, though, where 0 is returned. + +Well, I can understand that point of view as well - either the weak pointer +has a valid target object or not (in which case null or deleted doesn't +really matter). However, my use of a smart weak pointer is really as a +debugging aid, so I would like the error to be detected as soon as possible +(and distinguished from a null-pointer assertion or SEGV). Short of adding a +policy class template parameter, it would be easy to add a new member +function which does get() with severe checking - along the lines of +vector.at versus vector.operator[]. Just an idea. + +BTW, am I right in thinking that sharede_ptr always maintains an extra weak +reference counter? I mean, even if my code doesn't use weak_ptr, shared_ptr +still has to maintain the extra counter, right? That, combined with the +*** MESSAGE TRUNCATED *** + + +. diff --git a/inc/app/sitemailer2/tests/yale_01.txt b/inc/app/sitemailer2/tests/yale_01.txt new file mode 100644 index 00000000..7be4754e --- /dev/null +++ b/inc/app/sitemailer2/tests/yale_01.txt @@ -0,0 +1,422 @@ +From VM Tue Dec 26 22:41:08 2000 +Return-Path: +Received: from ns2.digicool.com ([216.164.72.2] verified) + by digicool.com (CommuniGate Pro SMTP 3.3.1) + with ESMTP id 400038 for xxxxx@mail.digicool.com; Tue, 26 Dec 2000 18:41:55 -0500 +Received: from mail.python.org (starship.python.net [63.102.49.30]) + by ns2.digicool.com (8.9.3/8.9.3) with ESMTP id SAA03359 + for ; Tue, 26 Dec 2000 18:41:47 -0500 +Received: from ns1.zope.org (localhost.localdomain [127.0.0.1]) + by mail.python.org (Postfix) with ESMTP id DC80BE904 + for ; Tue, 26 Dec 2000 13:27:01 -0500 (EST) +Delivered-To: mm+mailman-users-admin@python.org +Received: from mr2.its.yale.edu (mr2.its.yale.edu [130.132.21.43]) + by mail.python.org (Postfix) with ESMTP id E27E8E904 + for ; Tue, 26 Dec 2000 13:26:19 -0500 (EST) +Received: (from mailnull@localhost) + by mr2.its.yale.edu (8.8.8/8.8.8) id NAA14658; + Tue, 26 Dec 2000 13:26:18 -0500 (EST) +Message-Id: <200012261826.NAA14658@mr2.its.yale.edu> +Errors-To: mailman-users-owner@python.org +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +From: MAILER-DAEMON@mr2.its.yale.edu +Sender: mailman-users-owner@python.org +To: mailman-users-admin@python.org +Subject: Returned mail - nameserver error report +Date: Tue, 26 Dec 2000 13:26:18 -0500 (EST) +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0 + + --------Message not delivered to the following: + + thomas.dtankengine No matches to nameserver query + + --------Error Detail (phquery V4.1): + + The message, "No matches to nameserver query," is generated whenever + Yale's on-line directory fails to locate either a ph alias, name or + nickname field that matches the supplied name. The usual causes are + typographical errors. Recommended action is to query the Yale on-line + directory prior to mailing using the ``ph -s directory.yale.edu NAME'', + ``finger NAME@directory.yale.edu'', or equivalent commands, or by + querying the Yale Directory within YaleInfo, where NAME is your party's + name, email alias, or nickname. If no lookup tools are available to + you, try sending to the most explicit form of the name, e.g., if + mike.fox@yale.edu fails, try michael.j.fox@yale.edu. + + To reach a party that was formerly reachable by emailing NAME@yale.edu, + try emailing to NAME@cs.yale.edu instead. + + + --------Unsent Message below: + +Received: from mail.python.org ([63.102.49.30]) + by mr2.its.yale.edu (8.8.8/8.8.8) with ESMTP id NAA14654 + for ; Tue, 26 Dec 2000 13:26:17 -0500 (EST) +Received: from ns1.zope.org (localhost.localdomain [127.0.0.1]) + by mail.python.org (Postfix) with ESMTP + id 3DFEDE904; Tue, 26 Dec 2000 12:01:13 -0500 (EST) +From: mailman-users-request@python.org +Subject: Mailman-Users digest, Vol 1 #948 - 11 msgs +Reply-To: mailman-users@python.org +X-Mailer: Mailman v2.0 +MIME-version: 1.0 +Content-type: text/plain +To: mailman-users@python.org +Sender: mailman-users-admin@python.org +Errors-To: mailman-users-admin@python.org +X-BeenThere: mailman-users@python.org +X-Mailman-Version: 2.0 +Precedence: bulk +List-Help: +List-Post: +List-Subscribe: , + +List-Id: Mailman mailing list management users +List-Unsubscribe: , + +List-Archive: +Message-Id: <20001226170113.3DFEDE904@mail.python.org> +Date: Tue, 26 Dec 2000 12:01:13 -0500 (EST) + +Send Mailman-Users mailing list submissions to + mailman-users@python.org + +To subscribe or unsubscribe via the World Wide Web, visit + http://www.python.org/mailman/listinfo/mailman-users +or, via email, send a message with subject or body 'help' to + mailman-users-request@python.org + +You can reach the person managing the list at + mailman-users-admin@python.org + +When replying, please edit your Subject line so it is more specific +than "Re: Contents of Mailman-Users digest..." + + +Today's Topics: + + 1. Re: GID error (Bradley Leonard) + 2. Password bug in Mailman 2.0 (Juan Eliseo Carrasco Diaz) + 3. Re: Password bug in Mailman 2.0 (Bek Oberin) + 4. Re: Password bug in Mailman 2.0 (Juan Eliseo Carrasco Diaz) + 5. Re: Password bug in Mailman 2.0 (Bek Oberin) + 6. Re: Is this a bug, or just because I called it from an + unpriveledged account? (Dan Mick) + 7. Re: Re: Password bug in Mailman 2.0 (Dan Mick) + 8. Mailman 2.0 with Python 2.0 (Leonard Jacobs) + 9. Recovering/resetting a list admin password (Jim Trigg) + 10. (no subject) (Michael Albert) + +--__--__-- + +Message: 1 +Date: Mon, 25 Dec 2000 14:05:42 -0500 (EST) +Subject: Re: [Mailman-Users] GID error +From: "Bradley Leonard" +To: jaym@opensourcedirectory.com +Cc: mailman-users@python.org +Reply-To: bradley@stygianresearch.com + +If the rpm was compiled for RH 7 then its probably set to apache. If not, +you need to find the src rpm and rebuild it using the --rebuilddb option. +You'll need to pass in new options or change the spec file. + +Brad + + +0> How would I set the GID for the cgi to execute. If I installed mailman +> via rpm(on a slackware system)? +> +> +> ------------------------------------------------------ +> Mailman-Users maillist - Mailman-Users@python.org +> http://www.python.org/mailman/listinfo/mailman-users + + +-- +Bradley Leonard (bradley@stygianresearch.com) +Stygian Research (http://stygianresearch.com) + +Life is simple. We make it complicated. + + + + +--__--__-- + +Message: 2 +Date: Mon, 25 Dec 2000 22:48:07 -0500 +From: Juan Eliseo Carrasco Diaz +To: mailman-users@python.org +Subject: [Mailman-Users] Password bug in Mailman 2.0 + + The Administrator name can be used as password to go into and change +administrative and users options in theirs respective html pages. + + It's this a bug? + + + +--__--__-- + +Message: 3 +Date: Tue, 26 Dec 2000 11:49:21 +1100 +From: Bek Oberin +To: Juan Eliseo Carrasco Diaz +Cc: mailman-users@python.org +Subject: [Mailman-Users] Re: Password bug in Mailman 2.0 + +Juan Eliseo Carrasco Diaz wrote: +> The Administrator name can be used as password to go into and change +> administrative and users options in theirs respective html pages. + +It's a feature. + + +bekj + +-- +: --Hacker-Neophile-Eclectic-Geek-Grrl-Queer-Disabled-Boychick-- +: gossamer@tertius.net.au http://www.tertius.net.au/~gossamer/ +: Artificial Intelligence: the art of making computers that behave +: like the ones in movies. -- Bill Bulko + + +--__--__-- + +Message: 4 +Date: Tue, 26 Dec 2000 01:21:42 -0500 +From: Juan Eliseo Carrasco Diaz +To: Bek Oberin +Cc: mailman-users@python.org +Subject: [Mailman-Users] Re: Password bug in Mailman 2.0 + +Bek Oberin wrote: + +> Juan Eliseo Carrasco Diaz wrote: +> > The Administrator name can be used as password to go into and change +> > administrative and users options in theirs respective html pages. +> +> It's a feature. +> +> bekj +> +> -- +> : --Hacker-Neophile-Eclectic-Geek-Grrl-Queer-Disabled-Boychick-- +> : gossamer@tertius.net.au http://www.tertius.net.au/~gossamer/ +> : Artificial Intelligence: the art of making computers that behave +> : like the ones in movies. -- Bill Bulko + +Ok, but It can be used by anyone, so a list member can modify the +administrative options. + + If it's a feature, I don't understand it. + + + +--__--__-- + +Message: 5 +Date: Tue, 26 Dec 2000 12:23:42 +1100 +From: Bek Oberin +To: Juan Eliseo Carrasco Diaz +Cc: mailman-users@python.org +Subject: [Mailman-Users] Re: Password bug in Mailman 2.0 + +Juan Eliseo Carrasco Diaz wrote: +> Bek Oberin wrote: +> > Juan Eliseo Carrasco Diaz wrote: +> > > The Administrator name can be used as password to go into and change +> > > administrative and users options in theirs respective html pages. +> > It's a feature. +> Ok, but It can be used by anyone, so a list member can modify the +> administrative options. + +Hang on, I mis-read that as "The Administrator password ...". +Their -name-? You mean their email address? There isn't +anywhere in mailman that their name is used .... + +bekj + +-- +: --Hacker-Neophile-Eclectic-Geek-Grrl-Queer-Disabled-Boychick-- +: gossamer@tertius.net.au http://www.tertius.net.au/~gossamer/ +: Uptime DSW's are the highest form of geek competition. +: -- Mike Whitaker + + +--__--__-- + +Message: 6 +Date: Mon, 25 Dec 2000 21:00:25 -0800 +From: Dan Mick +To: scott-brown@home.com +Cc: mailman-users@python.org +Subject: Re: [Mailman-Users] Is this a bug, or just because I called it from an + unpriveledged account? + + + +> If it's trying to delete a lock file, it's no doubt due to the fact that it +> (thought that it) created a lock file. Since no lock file is present... why +> did it get as far as it did without producing an error? + +I believe the underlying code is trying to clean up any possibly pre-existing lock file +as part of the "taking care" section when creating a list. There's no known live lock +file for the list because the list is being created now, and this code is just a +prophylactic measure to try to make newlist more bulletproof. The fact +that you didn't have permission would be a fatal error for either creating or +removing a lock, so dying if it happens is not unreasonable. + +It is a bit confusing, but it's part of trying to make the filesystem persistence +less of a problem. + + +--__--__-- + +Message: 7 +Date: Mon, 25 Dec 2000 21:06:48 -0800 +From: Dan Mick +To: Juan Eliseo Carrasco Diaz , + mailman-users@python.org +Subject: Re: [Mailman-Users] Re: Password bug in Mailman 2.0 + + + +Juan Eliseo Carrasco Diaz wrote: +> +> Bek Oberin wrote: +> +> > Juan Eliseo Carrasco Diaz wrote: +> > > The Administrator name can be used as password to go into and change +> > > administrative and users options in theirs respective html pages. +> > +> > It's a feature. +> > +> > bekj +> > +> > -- +> > : --Hacker-Neophile-Eclectic-Geek-Grrl-Queer-Disabled-Boychick-- +> > : gossamer@tertius.net.au http://www.tertius.net.au/~gossamer/ +> > : Artificial Intelligence: the art of making computers that behave +> > : like the ones in movies. -- Bill Bulko +> +> Ok, but It can be used by anyone, so a list member can modify the +> administrative options. + +?? You said, correctly, the administrator password can be used as password to go +change users' options. That's not at all true in the reverse; user passwords don't +get you admin privileges. + +Think of the admin password like the "root" user password; you can do more with it. +And the site password works for even more things (for admin privs on any list, +for example). + + +--__--__-- + +Message: 8 +From: "Leonard Jacobs" +To: mailman-users@python.org +Date: Tue, 26 Dec 2000 01:31:17 -0500 +Reply-To: lj@mandala-designs.com +Subject: [Mailman-Users] Mailman 2.0 with Python 2.0 + +Mailman seems to be continually retrying sending mail to hosts +which can't be resolved via the DNS. Is this correct? + +Also why is it that Mailman seems to invoke sendmail in such a +way that it causes sendmail to return a failure on hostnames that +can't be resolved (presumably a temporary condition) rather than +just passing the message to sendmail and letting sendmail do all +the retries itself (which is how most mailers invoke sendmail). I +imagine this must relate to the program's needing more detailed +info about the state of each message to be sent, but when you tie +this in with the default frequency of its retries, it's very strange. + +------------------ + + Leonard Jacobs + www.mandala-designs.com + (508) 359-5473 + + + +--__--__-- + +Message: 9 +Date: Tue, 26 Dec 2000 09:08:39 -0500 +To: mailman-users@python.org +From: Jim Trigg +Subject: [Mailman-Users] Recovering/resetting a list admin password + +I lost the email giving me my list admin password for one list. The site +admin claims that there is no way to either recover or reset that password, +and that I have to recreate the list. Is that true, or can he use the site +admin password to get access to the list administrative page and reset the +password that way? It looks to me from the documentation that he should be +able to. + +Thanks, +Jim Trigg + + + +--__--__-- + +Message: 10 +From: "Michael Albert" +To: +Date: Tue, 26 Dec 2000 10:03:03 -0800 +Subject: [Mailman-Users] (no subject) + +There is a list about ethiopia maintained or adminstered or otherwise +related to your operations. + +People are being added to this list without having any knowledge of it. They +are given passwords they don't know. They cannot, therefore, remove +themsleves. I am such a person. + +Perhaps this is ignorance, more likely a stupid but venal undertaking, At +any rate, you should immediately shut down this list and inform those +attempting to create it of proper procedures. + +Thank you. + +The list is + +Pol.ethiopia mailing list +Pol.ethiopia@lists.sn.apc.org +http://lists.sn.apc.org/mailman/listinfo/pol.ethiopia + + + +Michael Albert +Z Magazine / ZNet +sysop@zmag.org +www.zmag.org + + + + +--__--__-- + +------------------------------------------------------ +Mailman-Users maillist - Mailman-Users@python.org +http://www.python.org/mailman/listinfo/mailman-users + + +End of Mailman-Users Digest + + --------End of Unsent Message + + diff --git a/inc/app/siteshop/boxes/admin/access.php b/inc/app/siteshop/boxes/admin/access.php new file mode 100644 index 00000000..7d1c0358 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/access.php @@ -0,0 +1,9 @@ +; diff --git a/inc/app/siteshop/boxes/admin/categories/add/index.php b/inc/app/siteshop/boxes/admin/categories/add/index.php new file mode 100644 index 00000000..e88a3c70 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/categories/add/index.php @@ -0,0 +1,8 @@ + $parameters['name'])); + +header ('Location: ' . site_prefix () . '/index/siteshop-admin-categories-action'); +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/categories/delete/index.php b/inc/app/siteshop/boxes/admin/categories/delete/index.php new file mode 100644 index 00000000..d115f343 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/categories/delete/index.php @@ -0,0 +1,10 @@ +remove ($parameters['_key']); + +header ('Location: ' . site_prefix () . '/index/siteshop-admin-categories-action'); +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/categories/index.php b/inc/app/siteshop/boxes/admin/categories/index.php new file mode 100644 index 00000000..986b8107 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/categories/index.php @@ -0,0 +1,15 @@ + 'categories')); + +$s = new Category (); +$s->orderBy ('weight desc, name asc'); +$parameters['list'] = $s->find (array ()); + +echo template_simple ('admin_categories.spt', $parameters); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/categories/weight/index.php b/inc/app/siteshop/boxes/admin/categories/weight/index.php new file mode 100644 index 00000000..67f611be --- /dev/null +++ b/inc/app/siteshop/boxes/admin/categories/weight/index.php @@ -0,0 +1,16 @@ +val ('weight') + 1; +} else { + $weight = $s->val ('weight') - 1; +} + +$s->modify ($parameters['_key'], array ('weight' => $weight)); + +header ('Location: ' . site_prefix () . '/index/siteshop-admin-categories-action'); +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/index.php b/inc/app/siteshop/boxes/admin/index.php new file mode 100644 index 00000000..a0d92c6b --- /dev/null +++ b/inc/app/siteshop/boxes/admin/index.php @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/index/access.php b/inc/app/siteshop/boxes/admin/index/access.php new file mode 100644 index 00000000..f34a5359 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/index/access.php @@ -0,0 +1,8 @@ +; diff --git a/inc/app/siteshop/boxes/admin/index/index.php b/inc/app/siteshop/boxes/admin/index/index.php new file mode 100644 index 00000000..652c66a4 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/index/index.php @@ -0,0 +1,43 @@ +username)) { + echo '

Invalid password. Please try again.

'; + } else { + echo '

Please enter your username and password to enter.

'; + } + + echo template_simple ('
+ + + + + + + + + + + + + +
Username
Password
 
+
' + ); + + return; +} + +page_title ('SiteShop 2 - ' . intl_get ('Overview')); + +echo loader_box ('siteshop/admin/nav', array ('current' => 'overview')); + +echo template_simple ('admin_index.spt', Order::overview ()); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/nav/index.php b/inc/app/siteshop/boxes/admin/nav/index.php new file mode 100644 index 00000000..382b5cdd --- /dev/null +++ b/inc/app/siteshop/boxes/admin/nav/index.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/offers/delete/index.php b/inc/app/siteshop/boxes/admin/offers/delete/index.php new file mode 100644 index 00000000..21944d4f --- /dev/null +++ b/inc/app/siteshop/boxes/admin/offers/delete/index.php @@ -0,0 +1,10 @@ +remove ($parameters['_key']); + +header ('Location: ' . site_prefix () . '/index/siteshop-admin-offers-action'); +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/offers/index.php b/inc/app/siteshop/boxes/admin/offers/index.php new file mode 100644 index 00000000..f87c0f2a --- /dev/null +++ b/inc/app/siteshop/boxes/admin/offers/index.php @@ -0,0 +1,13 @@ + 'offers')); + +$s = new CheckoutOffer (); +$s->orderBy ('offer_number asc'); +$parameters['list'] = $s->find (array ()); + +echo template_simple ('admin_offers.spt', $parameters); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/options/index.php b/inc/app/siteshop/boxes/admin/options/index.php new file mode 100755 index 00000000..bfac3adc --- /dev/null +++ b/inc/app/siteshop/boxes/admin/options/index.php @@ -0,0 +1,15 @@ + 'products')); +loader_import('siteshop.Objects'); + +$o = new Option; +$o->orderBy ('type asc, name asc'); + +$parameters['list'] = $o->find (array()); + +echo template_simple ('admin_options.spt', $parameters); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/options/removeone/index.php b/inc/app/siteshop/boxes/admin/options/removeone/index.php new file mode 100755 index 00000000..14bd7a50 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/options/removeone/index.php @@ -0,0 +1,12 @@ +id); +db_execute ('delete from siteshop_option where id = ?', $cgi->id); + +header ('Location: ' . site_prefix() . '/index/siteshop-admin-options-action'); + +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/orders/delete/index.php b/inc/app/siteshop/boxes/admin/orders/delete/index.php new file mode 100644 index 00000000..4c455380 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/orders/delete/index.php @@ -0,0 +1,12 @@ +remove ($id); +} + +header ('Location: ' . site_prefix () . '/index/siteshop-admin-orders-action'); +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/orders/export/index.php b/inc/app/siteshop/boxes/admin/orders/export/index.php new file mode 100644 index 00000000..20c6413f --- /dev/null +++ b/inc/app/siteshop/boxes/admin/orders/export/index.php @@ -0,0 +1,33 @@ +orderBy ('ts desc'); +$p = array (); +if (! empty ($parameters['status'])) { + $p['status'] = $parameters['status']; +} +$list = $o->find ($p); + +header ('Cache-control: private'); +header ('Content-Type: text/plain'); +header ('Content-Disposition: attachment; filename=Orders-' . date ('Y-m-d') . '.csv'); + +echo "Order #,Customer Name,Status,Date/Time,Subtotal,Shipping,Taxes,Total\n"; + +foreach ($list as $item) { + printf ( + "%d,%s,%s,%s,%s,%s,%s,%s\n", + $item->id, + $item->bill_to, + ucwords ($item->status), + $item->ts, + $item->subtotal, + $item->shipping, + $item->taxes, + $item->total + ); +} + +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/orders/index.php b/inc/app/siteshop/boxes/admin/orders/index.php new file mode 100644 index 00000000..e3434fdf --- /dev/null +++ b/inc/app/siteshop/boxes/admin/orders/index.php @@ -0,0 +1,52 @@ + 'orders')); + +if (! $parameters['offset']) { + $parameters['offset'] = 0; +} + +if (! $parameters['orderBy']) { + $parameters['orderBy'] = 'ts'; +} + +if (! $parameters['sort']) { + $parameters['sort'] = 'desc'; +} + +loader_import ('cms.Versioning.Rex'); + +$r = new Rex (false); +$r->preserve = array ('orderBy', 'sort'); +$r->addFacet ('id', array ('type' => 'text', 'display' => intl_get ('Text'), 'fields' => 'id, name, description, body')); +$r->addFacet ('status', array ('type' => 'select', 'display' => intl_get ('Status'), 'values' => array ('new' => intl_get ('New'), 'partly-shipped' => intl_get ('Partly-Shipped'), 'shipped' => intl_get ('Shipped'), 'cancelled' => intl_get ('Cancelled')), 'count' => false)); +$parameters['facets'] = $r->renderFacets (); + +$search_params = array (); +foreach ($parameters as $k => $v) { + if ($k == '_id') { + $search_params[] = '(id = "' . $v . '" or ship_to like "%' . $v . '%" or bill_to like "%' . $v . '%")'; + } elseif ($k == '_status') { + // exact matches + $search_params[substr ($k, 1)] = $v; + } +} + +$o = new Order (); +$o->orderBy ($parameters['orderBy'] . ' ' . $parameters['sort']); +$o->offset ($parameters['offset']); +$o->limit (20); +$parameters['list'] = $o->find ($search_params); +$parameters['total'] = $o->total; + +loader_import ('saf.GUI.Pager'); +$pg = new Pager ($parameters['offset'], 20, $parameters['total']); +$pg->setUrl (site_prefix () . '/index/siteshop-admin-orders-action?'); +$pg->getInfo (); +template_simple_register ('pager', $pg); + +echo template_simple ('admin_orders.spt', $parameters); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/orders/update/index.php b/inc/app/siteshop/boxes/admin/orders/update/index.php new file mode 100644 index 00000000..a36ef562 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/orders/update/index.php @@ -0,0 +1,20 @@ +set ('status', $parameters['status']); +$o->set ('tracking', $parameters['tracking']); +$o->save (); + +$o->recordStatus (); + +@mail ( + $o->val ('email'), + intl_get ('Order') . ' #' . $parameters['id'] . ' - ' . intl_get ('Status Updated'), + template_simple ('admin_orders_update_email.spt', $o->makeObj ()), + 'From: ' . appconf ('order_notices') +); + +header ('Location: ' . site_prefix () . '/index/siteshop-admin-orders-view-action?id=' . $parameters['id']); +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/orders/view/index.php b/inc/app/siteshop/boxes/admin/orders/view/index.php new file mode 100644 index 00000000..f39edce5 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/orders/view/index.php @@ -0,0 +1,20 @@ + 'orders')); + +$o = new Order ($parameters['id']); + +$ord = $o->makeObj (); + +$ord->products = $o->getDetails (); +$ord->history = $o->getHistory (); + +if (@file_exists ('inc/app/siteshop/html/admin_orders_print_header.spt')) { + echo ''; +} + +echo template_simple ('admin_orders_view.spt', $ord); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/productoptions/index.php b/inc/app/siteshop/boxes/admin/productoptions/index.php new file mode 100755 index 00000000..ccd74a2d --- /dev/null +++ b/inc/app/siteshop/boxes/admin/productoptions/index.php @@ -0,0 +1,72 @@ +submit_button)) { + + $p = new Product($cgi->p); + $options = $p->getAllOptions(); + + foreach ($cgi->param as $to) { + if (strpos($to, 'po-') === 0) { + list($ignore, $id, $option) = explode ('-',$to); + + foreach ($options as $k=>$o) { + if ($o->id == $id && $option == 'yes') { + echo 'yes'; + $options[$k]->yes = true; + } elseif ($o->id == $id && $option == 'no') { + echo 'no'; + $options[$k]->no = true; + } + } + } + } + + foreach ($options as $o) { + //unavailable + if (isset ($o->no)) { + $p->setOptionC ($o->id, 'no'); + //available + } elseif (isset ($o->yes)) { + $p->setOptionC ($o->id, 'yes'); + //unlisted + } else { + $p->setOptionC ($o->id, null); + } + } + + header ('Location: ' . site_prefix() . '/index/siteshop-admin-products-action'); + exit; +} + +page_title ('SiteShop 2 - ' . intl_get ('Product Options')); + +echo loader_box ('siteshop/admin/nav', array ('current' => 'products')); +global $cgi; +$p = new Product($cgi->p); +$options = $p->getAllOptions(); +$parameters['name'] = $p->val('name'); +$parameters['product_id'] = $cgi->p; + +echo template_simple ('admin_productoptions1.spt', $parameters); + +$previous_type = $options[0]->type; +$data = array (); +foreach ($options as $o) { + if ($o->type != $previous_type) { + echo template_simple ('admin_productoptions2.spt', array ('options' => $data, 'type' => $previous_type)); + $previous_type = $o->type; + $data = array (); + $data[] = $o; + } else { + $data[] = $o; + } +} + +echo template_simple ('admin_productoptions2.spt', array ('options' => $data, 'type' => $previous_type)); + +echo template_simple ('admin_productoptions3.spt'); +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/products/delete/index.php b/inc/app/siteshop/boxes/admin/products/delete/index.php new file mode 100644 index 00000000..402d4dc2 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/products/delete/index.php @@ -0,0 +1,12 @@ +remove ($id); +} + +header ('Location: ' . site_prefix () . '/index/siteshop-admin-products-action'); +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/products/index.php b/inc/app/siteshop/boxes/admin/products/index.php new file mode 100644 index 00000000..8b1dc4e1 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/products/index.php @@ -0,0 +1,59 @@ + 'products')); + +if (! $parameters['offset']) { + $parameters['offset'] = 0; +} + +if (! $parameters['orderBy']) { + $parameters['orderBy'] = 'name'; +} + +if (! $parameters['sort']) { + $parameters['sort'] = 'asc'; +} + +loader_import ('cms.Versioning.Rex'); + +$r = new Rex (false); +$r->preserve = array ('orderBy', 'sort'); +$r->addFacet ('sku', array ('type' => 'text', 'display' => intl_get ('Text'), 'fields' => 'sku, name, description, body')); +$r->addFacet ('category', array ('type' => 'select', 'display' => intl_get ('Category'), 'values' => db_pairs ('select * from siteshop_category order by name asc'), 'count' => false)); +$r->addFacet ('availability', array ('type' => 'select', 'display' => intl_get ('Availability'), 'values' => appconf ('availability'), 'count' => false)); +$r->addFacet ('weight', array ('type' => 'select', 'display' => intl_get ('Sorting Weight'), 'values' => appconf ('weight'), 'count' => false)); +$r->addFacet ('sitellite_status', array ('type' => 'select', 'display' => intl_get ('Status'), 'values' => assocify (session_get_statuses ()), 'count' => false)); +$r->addFacet ('sitellite_access', array ('type' => 'select', 'display' => intl_get ('Access Level'), 'values' => assocify (session_get_access_levels ()), 'count' => false)); +$parameters['facets'] = $r->renderFacets (); + +$search_params = array (); +foreach ($parameters as $k => $v) { + if ($k == '_category') { + $list = db_shift_array ('select product_id from siteshop_product_category where category_id = ?', $v); + $search_params[] = 'id in(' . join (', ', $list) . ')'; + } elseif ($k == '_sku') { + $search_params[] = '(sku like "%' . $v . '%" or name like "%' . $v . '%" or description like "%' . $v . '%" or body like "%' . $v . '%")'; + } elseif (in_array ($k, array ('_availability', '_weight', '_sitellite_status', '_sitellite_access'))) { + // exact matches + $search_params[substr ($k, 1)] = $v; + } +} + +$p = new Product (); +$p->orderBy ($parameters['orderBy'] . ' ' . $parameters['sort']); +$p->offset ($parameters['offset']); +$p->limit (20); +$parameters['list'] = $p->find ($search_params); +$parameters['total'] = $p->total; + +loader_import ('saf.GUI.Pager'); +$pg = new Pager ($parameters['offset'], 20, $parameters['total']); +$pg->setUrl (site_prefix () . '/index/siteshop-admin-products-action?'); +$pg->getInfo (); +template_simple_register ('pager', $pg); + +echo template_simple ('admin_products.spt', $parameters); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/promo/delete/index.php b/inc/app/siteshop/boxes/admin/promo/delete/index.php new file mode 100644 index 00000000..8e5d4cf9 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/promo/delete/index.php @@ -0,0 +1,10 @@ +remove ($parameters['_key']); + +header ('Location: ' . site_prefix () . '/index/siteshop-admin-promo-action'); +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/promo/index.php b/inc/app/siteshop/boxes/admin/promo/index.php new file mode 100644 index 00000000..74b16b97 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/promo/index.php @@ -0,0 +1,13 @@ + 'promo')); + +$s = new Promo (); +$s->orderBy ('expires desc'); +$parameters['list'] = $s->find (array ()); + +echo template_simple ('admin_promo.spt', $parameters); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/sales/delete/index.php b/inc/app/siteshop/boxes/admin/sales/delete/index.php new file mode 100644 index 00000000..bb665a0e --- /dev/null +++ b/inc/app/siteshop/boxes/admin/sales/delete/index.php @@ -0,0 +1,10 @@ +remove ($parameters['_key']); + +header ('Location: ' . site_prefix () . '/index/siteshop-admin-sales-action'); +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/admin/sales/index.php b/inc/app/siteshop/boxes/admin/sales/index.php new file mode 100644 index 00000000..d3176924 --- /dev/null +++ b/inc/app/siteshop/boxes/admin/sales/index.php @@ -0,0 +1,13 @@ + 'sales')); + +$s = new Sale (); +$s->orderBy ('start_date desc, until_date desc'); +$parameters['list'] = $s->find (array ()); + +echo template_simple ('admin_sales.spt', $parameters); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/cart/access.php b/inc/app/siteshop/boxes/cart/access.php new file mode 100644 index 00000000..13777b5d --- /dev/null +++ b/inc/app/siteshop/boxes/cart/access.php @@ -0,0 +1,7 @@ +; diff --git a/inc/app/siteshop/boxes/cart/add/index.php b/inc/app/siteshop/boxes/cart/add/index.php new file mode 100644 index 00000000..e2b8925c --- /dev/null +++ b/inc/app/siteshop/boxes/cart/add/index.php @@ -0,0 +1,16 @@ +$p) { + if (strpos ($k, 'optiontype_') === 0) { + $options[] = $p; + } +} + +Cart::add ($parameters['pid'], false, $options); + +header ('Location: ' . site_prefix () . '/index/siteshop-cart-action'); +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/cart/index.php b/inc/app/siteshop/boxes/cart/index.php new file mode 100644 index 00000000..5104eaaa --- /dev/null +++ b/inc/app/siteshop/boxes/cart/index.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/inc/app/siteshop/boxes/cart/remove/index.php b/inc/app/siteshop/boxes/cart/remove/index.php new file mode 100644 index 00000000..8180549a --- /dev/null +++ b/inc/app/siteshop/boxes/cart/remove/index.php @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/inc/app/siteshop/boxes/cart/sidebar/access.php b/inc/app/siteshop/boxes/cart/sidebar/access.php new file mode 100644 index 00000000..fec3b1c7 --- /dev/null +++ b/inc/app/siteshop/boxes/cart/sidebar/access.php @@ -0,0 +1,8 @@ +; diff --git a/inc/app/siteshop/boxes/cart/sidebar/index.php b/inc/app/siteshop/boxes/cart/sidebar/index.php new file mode 100644 index 00000000..0d8dc043 --- /dev/null +++ b/inc/app/siteshop/boxes/cart/sidebar/index.php @@ -0,0 +1,10 @@ + Cart::items (), + 'total' => Cart::subtotal (), +); + +echo template_simple ('cart_sidebar.spt', $data); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/cart/sidebar/settings.php b/inc/app/siteshop/boxes/cart/sidebar/settings.php new file mode 100644 index 00000000..bd6cebca --- /dev/null +++ b/inc/app/siteshop/boxes/cart/sidebar/settings.php @@ -0,0 +1,3 @@ +[Meta] + +name = Cart Sidebar diff --git a/inc/app/siteshop/boxes/cart/update/index.php b/inc/app/siteshop/boxes/cart/update/index.php new file mode 100644 index 00000000..11286f40 --- /dev/null +++ b/inc/app/siteshop/boxes/cart/update/index.php @@ -0,0 +1,22 @@ + $qty) { + Cart::qty ($id, $qty); +} + +if (isset ($parameters['promo'])) { + $promo = Promo::code ($parameters['promo']); + if ($promo) { + Cart::addPromo ($promo); + } +} + +if (isset ($parameters['checkout'])) { + header ('Location: ' . site_prefix () . '/index/siteshop-checkout-action'); + exit; +} + +header ('Location: ' . $_SERVER['HTTP_REFERER']); +exit; + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/categories/access.php b/inc/app/siteshop/boxes/categories/access.php new file mode 100644 index 00000000..fec3b1c7 --- /dev/null +++ b/inc/app/siteshop/boxes/categories/access.php @@ -0,0 +1,8 @@ +; diff --git a/inc/app/siteshop/boxes/categories/index.php b/inc/app/siteshop/boxes/categories/index.php new file mode 100644 index 00000000..f710817d --- /dev/null +++ b/inc/app/siteshop/boxes/categories/index.php @@ -0,0 +1,9 @@ +orderBy ('weight desc, name asc'); +$list = $c->find (array ()); + +echo template_simple ('categories.spt', $list); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/categories/settings.php b/inc/app/siteshop/boxes/categories/settings.php new file mode 100644 index 00000000..e1985571 --- /dev/null +++ b/inc/app/siteshop/boxes/categories/settings.php @@ -0,0 +1,3 @@ +[Meta] + +name = Categories diff --git a/inc/app/siteshop/boxes/checkout/access.php b/inc/app/siteshop/boxes/checkout/access.php new file mode 100644 index 00000000..13777b5d --- /dev/null +++ b/inc/app/siteshop/boxes/checkout/access.php @@ -0,0 +1,7 @@ +; diff --git a/inc/app/siteshop/boxes/checkout/index.php b/inc/app/siteshop/boxes/checkout/index.php new file mode 100644 index 00000000..14083470 --- /dev/null +++ b/inc/app/siteshop/boxes/checkout/index.php @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/inc/app/siteshop/boxes/checkout/paypal/index.php b/inc/app/siteshop/boxes/checkout/paypal/index.php new file mode 100644 index 00000000..6169f696 --- /dev/null +++ b/inc/app/siteshop/boxes/checkout/paypal/index.php @@ -0,0 +1,191 @@ + $parameters['email'], + 'password' => better_crypt ($parameters['password_new_customer']), + 'firstname' => $parameters ['bill_to'], + 'country' => $parameters['bill_country'], + 'province' => $parameters['bill_state'], + 'address1' => $parameters['bill_address'], + 'address2' => $parameters['bill_address2'], + 'phone' => $parameters['phone'], + 'city' => $parameters['bill_city'], + 'email' => $parameters['email'], + 'postal_code' => $parameters['bill_zip'], + 'session_id' => null, + 'role' => 'member', + 'team' => 'none', + 'public' => 'no', + 'registered' => date ('Y-m-d H:i:s'), + 'modified' => date ('Y-m-d H:i:s'), + ) + ); + + if (empty ($res)) { + + $parameters['new_user_error'] = '1'; + + page_title (intl_get ('Customer Information')); + echo template_simple ('checkout1_registered.spt', $parameters); + return; + } + + // 2. email confirmation + @mail ($parameters['email'], 'Customer Confirmation', template_simple ('register_confirmation.spt', $parameters), 'From: ' . appconf ('customer_registration_return_email')); + + global $session; + $session->username = $parameters['email']; + $session->password = $parameters['password_new_customer']; + $session->start (); + + } + + // 1. handle customer information + $info = $parameters; + unset ($info['password_new_customer']); + unset ($info['password_new_customer_verify']); + unset ($info['_rewrite_sticky']); + unset ($info['param']); + unset ($info['files']); + unset ($info['error']); + unset ($info['step']); + unset ($info['page']); + unset ($info['mode']); + + if ($info['ship_same'] == 'yes') { + $info['ship_to'] = $info['bill_to']; + $info['ship_address'] = $info['bill_address']; + $info['ship_address2'] = $info['bill_address2']; + $info['ship_city'] = $info['bill_city']; + $info['ship_state'] = $info['bill_state']; + $info['ship_country'] = $info['bill_country']; + $info['ship_zip'] = $info['bill_zip']; + } + unset ($info['ship_same']); + $_SESSION['siteshop_customer_info'] = $info; + + // 2. show checkout offers + $tcart_prods = array_keys (Cart::view ()); + $cart_prods = array (); + foreach ($tcart_prods as $prod) { + $tarr = explode ('_', $prod); + $cart_prods[] = $tarr[0]; + } + + $o = new CheckoutOffer (); + $o->orderBy ('offer_number asc'); + $list = $o->find (array ('product_id not in(' . join (',', $cart_prods) . ')')); + + if (count ($list) > 0) { + foreach (array_keys ($list) as $k) { + $p = new Product ($list[$k]->product_id); + $list[$k]->price = $p->val ('price'); + } + page_title (intl_get ('Special Offers')); + echo template_simple ('checkout2.spt', $list); + } else { + header ('Location: ' . site_prefix () . '/index/siteshop-checkout-action?step=3'); + exit; + } + break; + case 3: + // 1. handle checkout offers + if (is_array ($parameters['add'])) { + foreach ($parameters['add'] as $id) { + // should this be add? + Cart::changePrice ($id, db_shift ('select sale_price from siteshop_checkout_offer where product_id = ?', $id)); + } + } + + // 2. redirect to paypal + page_title (intl_get ('Verify Your Order')); + $info = $_SESSION['siteshop_customer_info']; + $info['cart'] = Cart::view (); + echo template_simple ('checkout3.spt', $info); + break; + case 'success': + $username = ''; + if (session_valid ()) { + $username = session_username (); + } + // 1. save order to database + $info = $_SESSION['siteshop_customer_info']; + $info['user_id'] = $username; + $info['status'] = 'new'; + $info['ts'] = date ('Y-m-d H:i:s'); + $info['subtotal'] = Cart::subtotal (); + $info['shipping'] = Cart::shipping (); + $info['taxes'] = Cart::tax (); + $info['promo_code'] = Cart::promoCode (); + $info['promo_discount'] = Cart::promo (); + $info['total'] = Cart::total (); + $info['tracking'] = ''; + + $o = new Order ($info); + + $info['id'] = $o->val ('id'); + $info['cart'] = Cart::view (); + + foreach ($info['cart'] as $k => $item) { + $item->options = serialize ($item->options); + $o->addProduct ($item); + Product::updateQuantity ($k, $item->qty); + } + + $o->recordStatus (); + + Cart::clear (); + + // 2. email receipt + mail ( + $info['email'], + intl_get ('Order Receipt'), + template_simple ('order_receipt_email.spt', $info), + 'From: ' . appconf ('order_notices') + ); + + // 3. email notice + mail ( + appconf ('order_notices'), + intl_get ('Order Notification'), + template_simple ('order_notice_email.spt', $info), + 'From: ' . appconf ('order_notices') + ); + + page_title (intl_get ('Thank You')); + echo template_simple ('checkout4.spt'); + break; + case 'cancelled': + // cancellation + page_title (intl_get ('Order Cancelled')); + echo template_simple ('checkout5.spt'); + break; + default: + $user = session_get_user (); + + $data = array ( + 'bill_to' => $user->firstname, + 'bill_country' => $user->country, + 'bill_state' => $user->province, + 'bill_address' => $user->address1, + 'bill_address2' => $user->address2, + 'phone' => $user->phone, + 'bill_city' => $user->city, + 'email' => $user->email, + 'bill_zip' => $user->postal_code + ); + //info ($user); + page_title (intl_get ('Customer Information')); + echo template_simple ('checkout1_registered.spt', $data); + break; +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/index/access.php b/inc/app/siteshop/boxes/index/access.php new file mode 100644 index 00000000..13777b5d --- /dev/null +++ b/inc/app/siteshop/boxes/index/access.php @@ -0,0 +1,7 @@ +; diff --git a/inc/app/siteshop/boxes/index/index.php b/inc/app/siteshop/boxes/index/index.php new file mode 100644 index 00000000..86cfe203 --- /dev/null +++ b/inc/app/siteshop/boxes/index/index.php @@ -0,0 +1,70 @@ +val ('name')); + echo template_simple ('category.spt', $c); + //info ($c->getSortedProducts ()); +} elseif (isset ($parameters['pid'])) { + $alt = appconf ('alternate_product'); + if (! empty ($alt)) { + echo loader_box ($alt, $parameters, $context); + return; + } + + // single product detail page + page_add_script (site_prefix () . '/inc/app/siteshop/pix/addtocart.js'); + $p = new Product ($parameters['pid']); + if (! $p->val ('id')) { + page_title (intl_get ('Not Found')); + echo '

' . intl_get ('The product you have requests could not be found.') . '

'; + return; + } + $prod = $p->makeObj (); + $price = $p->getPrice (); + if ($price != $prod->price) { + $prod->sale = true; + $prod->sale_price = $price; + } + $prod->addtocartform = $p->getAddToCartForm (); + page_title ($p->val ('name')); + page_description ($p->val ('description')); + page_keywords ($p->val ('keywords')); + page_add_script (site_prefix () . '/inc/app/siteshop/js/prototype.js'); + page_add_script (site_prefix () . '/inc/app/siteshop/js/scriptaculous.js?load=effects'); + page_add_script (site_prefix () . '/inc/app/siteshop/js/lightbox.js'); + page_add_style (site_prefix () . '/inc/app/siteshop/html/lightbox.css'); + echo template_simple ('product.spt', $prod); +} else { + $alt = appconf ('alternate_index'); + if (! empty ($alt)) { + echo loader_box ($alt, $parameters, $context); + return; + } + + // sales and top products by weight + if (appconf ('page_title')) { + page_title (appconf ('page_title')); + } + $data = array (); + $s = new Sale (); + if ($s->loadCurrent ()) { + $data['sale_name'] = $s->val ('name'); + $data['sale_items'] = $s->top (3); + $data['featured_items'] = Product::featured (3); + } else { + $data['sale_name'] = ''; + $data['featured_items'] = Product::featured (6); + } + echo template_simple ('index.spt', $data); +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/boxes/sale/access.php b/inc/app/siteshop/boxes/sale/access.php new file mode 100644 index 00000000..13777b5d --- /dev/null +++ b/inc/app/siteshop/boxes/sale/access.php @@ -0,0 +1,7 @@ +; diff --git a/inc/app/siteshop/boxes/sale/index.php b/inc/app/siteshop/boxes/sale/index.php new file mode 100644 index 00000000..67eebbb7 --- /dev/null +++ b/inc/app/siteshop/boxes/sale/index.php @@ -0,0 +1,17 @@ +loadCurrent ()) { + header ('Location: ' . site_prefix () . '/index/siteshop-app'); + exit; +} + +$data = array (); +$data['start'] = $s->val ('start_date'); +$data['until'] = $s->val ('until_date'); +$data['list'] = $s->all (); + +page_title ($s->val ('name') . ' ' . intl_get ('Sale') . '!'); +echo template_simple ('sale.spt', $data); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/conf/config.ini.php b/inc/app/siteshop/conf/config.ini.php new file mode 100755 index 00000000..2d60e73d --- /dev/null +++ b/inc/app/siteshop/conf/config.ini.php @@ -0,0 +1,23 @@ +; diff --git a/inc/app/siteshop/conf/properties.php b/inc/app/siteshop/conf/properties.php new file mode 100755 index 00000000..83464ce7 --- /dev/null +++ b/inc/app/siteshop/conf/properties.php @@ -0,0 +1,74 @@ + intl_get ('Usually Ships Within 24 Hours'), + 2 => intl_get ('Usually Ships in 1-2 Business Days'), + 3 => intl_get ('Usually Ships in 2-3 Days'), + 4 => intl_get ('Usually Ships in 1-2 Weeks'), + 5 => intl_get ('Usually Ships in 2-3 Weeks'), + 6 => intl_get ('Back-Ordered'), + 7 => intl_get ('Temporarily Unavailable'), + 8 => intl_get ('Unavailable'), +)); + +appconf_set ('weight', array ( + 0 => intl_get ('Normal'), + 1 => intl_get ('Special'), + 2 => intl_get ('On Sale'), + 3 => intl_get ('Hot Seller'), + 4 => intl_get ('Featured Product'), +)); + +loader_import ('siteshop.Objects'); +loader_import ('siteshop.Functions'); +loader_import ('siteshop.Cart'); + +?> \ No newline at end of file diff --git a/inc/app/siteshop/conf/settings.php b/inc/app/siteshop/conf/settings.php new file mode 100755 index 00000000..1320b5e8 --- /dev/null +++ b/inc/app/siteshop/conf/settings.php @@ -0,0 +1,66 @@ +; \ No newline at end of file diff --git a/inc/app/siteshop/conf/translate.ini.php b/inc/app/siteshop/conf/translate.ini.php new file mode 100755 index 00000000..7280fd35 --- /dev/null +++ b/inc/app/siteshop/conf/translate.ini.php @@ -0,0 +1,12 @@ +; \ No newline at end of file diff --git a/inc/app/siteshop/data/default_thumbnail.gif b/inc/app/siteshop/data/default_thumbnail.gif new file mode 100644 index 00000000..39bbcc66 Binary files /dev/null and b/inc/app/siteshop/data/default_thumbnail.gif differ diff --git a/inc/app/siteshop/docs/en/001-introduction.html b/inc/app/siteshop/docs/en/001-introduction.html new file mode 100644 index 00000000..f9e6ae9e --- /dev/null +++ b/inc/app/siteshop/docs/en/001-introduction.html @@ -0,0 +1,4 @@ +

Introduction

+ +SiteShop 2 is an easy-to-use but feature-full shopping cart and ecommerce engine for Sitellite. SiteShop's unique selling points are its tight integration with Sitellite and its extensibility through the use of the SiteShop API. Using this, sites can extend SiteShop to do new things, and integrate SiteShop's product management or payment interface directly into your own custom Sitellite apps.
+ diff --git a/inc/app/siteshop/docs/en/002-configuration.html b/inc/app/siteshop/docs/en/002-configuration.html new file mode 100644 index 00000000..b538e178 --- /dev/null +++ b/inc/app/siteshop/docs/en/002-configuration.html @@ -0,0 +1,28 @@ +

Configuration

+ +Configuring SiteShop is easy. Simply select SiteShop from the Tools menu of Sitellite's Control Panel and click on the Settings tab. Here you can configure the following aspects of SiteShop:
+ +
  • Shopping cart name
  • + +
  • Paypal seller ID
  • + +
  • Taxes
  • + +
  • Notification email address
  • + +
  • Currency
  • + +
  • Shipping
  • + +
    • Base amount for any product
    • + +
    • Maximum amount of shipping (optional)
    • + +
    • Purchase amount over which shipping is free (optional)
    • + +
    + +
+ +You can also control sales and promoted items, as well as checkout specials, through their own SiteShop tabs.
+ diff --git a/inc/app/siteshop/docs/en/003-goal-tracking.html b/inc/app/siteshop/docs/en/003-goal-tracking.html new file mode 100644 index 00000000..61ab715b --- /dev/null +++ b/inc/app/siteshop/docs/en/003-goal-tracking.html @@ -0,0 +1,7 @@ +

Goal Tracking

+ +For goal tracking using the Google Analytics goals and conversion tracking or another similar tracking package, simply copy and paste the following addresses that belong to the SiteShop checkout process:
+
  • View Cart: http://www.yourWebSite.com/siteshop-cart-action
  • +
  • Order Confirmation: http://www.yourWebSite.com/siteshop-thankyou-action
    +
  • +
diff --git a/inc/app/siteshop/docs/en/004-siteshop-api.html b/inc/app/siteshop/docs/en/004-siteshop-api.html new file mode 100644 index 00000000..2aa13473 --- /dev/null +++ b/inc/app/siteshop/docs/en/004-siteshop-api.html @@ -0,0 +1,4 @@ +

SiteShop API

+ +SiteShop can be extended or integrated into your own Sitellite applications using the SiteShop API. API documentation is still in progress.
+ diff --git a/inc/app/siteshop/docs/en/005-settings.html b/inc/app/siteshop/docs/en/005-settings.html new file mode 100644 index 00000000..19378c74 --- /dev/null +++ b/inc/app/siteshop/docs/en/005-settings.html @@ -0,0 +1,146 @@ +

Settings

+ +

General Settings

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Store Name
+ +
The name of the store, displayed as the title of the main page of the store.
+ +
Paypal ID
+ +
The email address registered to your Paypal account that payments should be made to.
+ +
Email Order Notices
+ +
The email address to send new order notices to and order updates to customers from.
+ +
Local Currency Code
+ +
Used to tell Paypal what currency to bill people under. A currency code is an abbreviation instead of a country name, e.g., CAD for Canadian, USD for American.
+ +
+ +

Shipping

+ + + + + + + + + + + + + + + + + + + + + +
Base Shipping For All Items
+ +
This is the default shipping amount to set for any new items created.
+ +
Max Shipping On Orders
+ +
This is an optional setting that allows you to set a maximum shipping fee a customer can pay, regardless of how large their order is.
+ +
Free Shipping On Orders Over
+ +
This is an optional setting that allows you to set an amount that a customer can spend to receive free shipping.
+ +
+ +

Taxes

+ +

To enter multiple taxes to charge, set the tax names one per line in the taxes box. Beside each tax enter one space and then the amount to multiply the order by for that tax. For example, if the tax is 6% then you would enter 0.06.

+ +

Display

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Default Thumbnail Image
+ +
The location of an image on the server which should be used as a default when no image has been uploaded for an item.
+ +
Default CSS Stylesheet
+ +
The location of a CSS stylesheet file on the server which should be used to style the look and feel of the shopping cart elements in the website.
+ +
Page Alias (Page ID)The ID of a page that SiteShop should act as an alias of in the site structure.
Below Page (Page ID)The ID of a page that SiteShop should act as if it's directly below in the site structure.
Page TemplateThe page template to use to display SiteShop.
Alternate Index (Box)The name of a Sitellite box to use to display the SiteShop homepage, allowing you to completely change the look of it.
Alternate Product Page (Box)The name of a Sitellite box to use to display the SiteShop product pages, allowing you to completely change the look of it.
+ +
+ diff --git a/inc/app/siteshop/docs/en/006-future.html b/inc/app/siteshop/docs/en/006-future.html new file mode 100644 index 00000000..103913e6 --- /dev/null +++ b/inc/app/siteshop/docs/en/006-future.html @@ -0,0 +1,13 @@ +

Future Features

+ +Some of the features we plan on adding in future versions of SiteShop include:
+ +
  • Purchase history page for registered customers
  • + +
  • Wish lists
  • + +
  • Reporting on orders and performance of products, sales and checkout offers
  • + +
  • Digital media sales, i.e., the ability to sell files for download such as software, ebooks, movies or audio
  • + +
diff --git a/inc/app/siteshop/forms/add/access.php b/inc/app/siteshop/forms/add/access.php new file mode 100644 index 00000000..fc3b876a --- /dev/null +++ b/inc/app/siteshop/forms/add/access.php @@ -0,0 +1,5 @@ +sitellite_access = private +sitellite_status = approved +sitellite_action = on +sitellite_template_set = admin +sitellite_goto = siteshop-admin-index-action diff --git a/inc/app/siteshop/forms/add/index.php b/inc/app/siteshop/forms/add/index.php new file mode 100644 index 00000000..253a3946 --- /dev/null +++ b/inc/app/siteshop/forms/add/index.php @@ -0,0 +1,59 @@ +parseSettings ('inc/app/siteshop/forms/add/settings.php'); + page_title (intl_get ('Add a Product')); + } + + function onSubmit ($vals) { + unset ($vals['tab1']); + unset ($vals['tab2']); + unset ($vals['tab3']); + unset ($vals['tab4']); + unset ($vals['tab-end']); + unset ($vals['submit_button']); + + $images = array (); + $images[] = $vals['image1']; + $images[] = $vals['image2']; + $images[] = $vals['image3']; + $images[] = $vals['image4']; + $images[] = $vals['image5']; + $images[] = $vals['image6']; + unset ($vals['image1']); + unset ($vals['image2']); + unset ($vals['image3']); + unset ($vals['image4']); + unset ($vals['image5']); + unset ($vals['image6']); + + $categories = array (); + $categories[] = $vals['category1']; + $categories[] = $vals['category2']; + $categories[] = $vals['category3']; + unset ($vals['category1']); + unset ($vals['category2']); + unset ($vals['category3']); + + $p = new Product ($vals); + + foreach ($categories as $cat) { + if ($cat) { + $p->setCategory (new Category ($cat)); + } + } + + foreach ($images as $n => $image) { + if (is_object ($image) && preg_match ('/\.jpg$/i', $image->name)) { + $image->move ('inc/app/siteshop/data', $p->val ('id') . '-' . ($n + 1) . '.jpg'); + } + } + + header ('Location: ' . site_prefix () . '/index/siteshop-admin-products-action'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/forms/add/offer/index.php b/inc/app/siteshop/forms/add/offer/index.php new file mode 100644 index 00000000..bb743db8 --- /dev/null +++ b/inc/app/siteshop/forms/add/offer/index.php @@ -0,0 +1,23 @@ +parseSettings ('inc/app/siteshop/forms/add/offer/settings.php'); + page_title (intl_get ('Add a Checkout Offer')); + } + + function onSubmit ($vals) { + unset ($vals['submit_button']); + + $n = db_shift ('select offer_number from siteshop_checkout_offer order by offer_number desc limit 1'); + $vals['offer_number'] = $n + 1; + + $s = new CheckoutOffer ($vals); + + header ('Location: ' . site_prefix () . '/index/siteshop-admin-offers-action'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/forms/add/offer/settings.php b/inc/app/siteshop/forms/add/offer/settings.php new file mode 100644 index 00000000..e56f79ca --- /dev/null +++ b/inc/app/siteshop/forms/add/offer/settings.php @@ -0,0 +1,26 @@ +[Form] + +error_mode = all + +[offer_text] + +type = text +alt = Offer Text +extra = "size=`60`" + +[product_id] + +type = select +alt = Product +setValues = "eval: Product::selectAll ()" + +[sale_price] + +type = text +alt = "Sale Price ($)" + +[submit_button] + +type = msubmit +button 0 = Create +button 1 = "Cancel, onclick=`history.go (-1); return false`" diff --git a/inc/app/siteshop/forms/add/option/index.php b/inc/app/siteshop/forms/add/option/index.php new file mode 100755 index 00000000..81cea322 --- /dev/null +++ b/inc/app/siteshop/forms/add/option/index.php @@ -0,0 +1,31 @@ +parseSettings ('inc/app/siteshop/forms/add/option/settings.php'); + page_title (intl_get ('Add an Option')); + } + + function onSubmit ($vals) { + + unset ($vals['submit_button']); + + $image = $vals['image']; + unset ($vals['image']); + + $o = new Option; + $res = $o->add($vals); + + if (is_object ($image) && preg_match ('/\.jpg$/i', $image->name)) { + $image->move ('inc/app/siteshop/pix/options', $res . '.jpg'); + } + + header ('Location: ' . site_prefix () . '/index/siteshop-admin-options-action'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/forms/add/option/settings.php b/inc/app/siteshop/forms/add/option/settings.php new file mode 100755 index 00000000..fc84234f --- /dev/null +++ b/inc/app/siteshop/forms/add/option/settings.php @@ -0,0 +1,40 @@ +[Form] + +error_mode = all +extra = "enctype=`multipart/form-data`" +uploadFiles = false + +[name] +alt = Option Name +type = text +rule 1 = "not empty, You must enter an option name." + +[type] + +type = selector +alt = Option Group +table = siteshop_option_type +key = name +rule 1 = "not empty, You must enter an option group." + +[value] + +type = text +alt = Extra Info + +[image] + +alt = "Image (Optional)" +type = file + +[weight] +type = text +alt = "Sorting Weight" +rule 1 = "numeric, The weight must be an integer 1-100" +default_value = 5 + +[submit_button] + +type = msubmit +button 0 = Create +button 1 = "Cancel, onclick=`history.go (-1); return false`" diff --git a/inc/app/siteshop/forms/add/promo/index.php b/inc/app/siteshop/forms/add/promo/index.php new file mode 100644 index 00000000..5418dff5 --- /dev/null +++ b/inc/app/siteshop/forms/add/promo/index.php @@ -0,0 +1,20 @@ +parseSettings ('inc/app/siteshop/forms/add/promo/settings.php'); + page_title (intl_get ('Add a Promo Code')); + } + + function onSubmit ($vals) { + unset ($vals['submit_button']); + + $s = new Promo ($vals); + + header ('Location: ' . site_prefix () . '/index/siteshop-admin-promo-action'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/forms/add/promo/settings.php b/inc/app/siteshop/forms/add/promo/settings.php new file mode 100644 index 00000000..ce26939a --- /dev/null +++ b/inc/app/siteshop/forms/add/promo/settings.php @@ -0,0 +1,32 @@ +[Form] + +error_mode = all + +[code] + +type = text +alt = Promo Code + +[discount_type] + +type = select +alt = Discount Type +setValues = "eval: array ('percent' => 'Percent', 'dollars' => 'Dollars')" + +[discount] + +type = text +alt = Discount + +[expires] + +type = calendar +alt = "Expires (Last Day)" +format = "%Y-%m-%d" +displayFormat = "%a, %e %b, %Y" + +[submit_button] + +type = msubmit +button 0 = Create +button 1 = "Cancel, onclick=`history.go (-1); return false`" diff --git a/inc/app/siteshop/forms/add/sale/index.php b/inc/app/siteshop/forms/add/sale/index.php new file mode 100644 index 00000000..1c66e4fb --- /dev/null +++ b/inc/app/siteshop/forms/add/sale/index.php @@ -0,0 +1,38 @@ +parseSettings ('inc/app/siteshop/forms/add/sale/settings.php'); + page_title (intl_get ('Add a Sale')); + } + + function onSubmit ($vals) { + $products = trim ($vals['product_id']); + unset ($vals['product_id']); + unset ($vals['submit_button']); + + // adjust dates + $vals['start_date'] = array_shift (explode (' ', $vals['start_date'])) . ' 00:00:00'; + $vals['until_date'] = array_shift (explode (' ', $vals['until_date'])) . ' 23:59:59'; + + $s = new Sale ($vals); + + // set all products on sale + db_execute ('delete from siteshop_sale_product where sale_id = ?', $s->val ('id')); + parse_str ($products, $prods); + foreach ($prods as $k => $v) { + db_execute ( + 'insert into siteshop_sale_product values (?, ?, ?)', + $s->val ('id'), + $k, + $v + ); + } + + header ('Location: ' . site_prefix () . '/index/siteshop-admin-sales-action'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/forms/add/sale/settings.php b/inc/app/siteshop/forms/add/sale/settings.php new file mode 100644 index 00000000..bb61f061 --- /dev/null +++ b/inc/app/siteshop/forms/add/sale/settings.php @@ -0,0 +1,34 @@ +[Form] + +error_mode = all + +[name] + +type = text +alt = Sale Name +extra = "size=`60`" + +[start_date] + +type = calendar +alt = "Sale Starts (First Day)" +format = "%Y-%m-%d" +displayFormat = "%a, %e %b, %Y" + +[until_date] + +type = calendar +alt = "Sale Ends (Last Day)" +format = "%Y-%m-%d" +displayFormat = "%a, %e %b, %Y" + +[product_id] + +type = siteshop.Widget.Products +alt = Products + +[submit_button] + +type = msubmit +button 0 = Create +button 1 = "Cancel, onclick=`history.go (-1); return false`" diff --git a/inc/app/siteshop/forms/add/settings.php b/inc/app/siteshop/forms/add/settings.php new file mode 100644 index 00000000..4a719e21 --- /dev/null +++ b/inc/app/siteshop/forms/add/settings.php @@ -0,0 +1,190 @@ +[Form] + +error_mode = all +extra = "onsubmit=`xed_copy_value (this, 'body')` enctype=`multipart/form-data`" +uploadFiles = false + +[tab1] + +type = tab +title = Edit + +[sku] + +type = text +alt = SKU + +[name] + +type = text +alt = Product Name +extra = "size=`60`" + +[price] + +type = text +alt = "Price ($)" + +[category1] + +type = select +alt = Category 1 +setValues = "eval: Category::listAssoc ()" + +[category2] + +type = select +alt = Category 2 +setValues = "eval: Category::listAssoc ()" + +[category3] + +type = select +alt = Category 3 +setValues = "eval: Category::listAssoc ()" + +[body] + +type = xed.Widget.Xeditor + +[tab2] + +type = tab +title = Properties + +[shipping] + +type = text +alt = "Shipping ($)" +setDefault = "eval: appconf ('shipping_base')" + +[availability] + +type = select +alt = Availability +setValues = "eval: appconf ('availability')" + +[quantity] + +type = text +alt = "Quantity (-1 for unlimited)" +setDefault = "-1" + +[weight] + +type = select +alt = Sorting Weight +setValues = "eval: appconf ('weight')" + +[taxable] + +type = select +alt = Taxable +setValues = "eval: array ('yes' => 'Yes', 'no' => 'No')" + +[keywords] + +type = cms.Widget.Keywords +alt = Keywords + +[description] + +type = textarea +alt = Description +rows = 3 +labelPosition = left + +[tab3] + +type = tab +title = Images + +[image1] + +type = file +alt = "Image 1 (.jpg)" + +[image2] + +type = file +alt = "Image 2 (.jpg)" + +[image3] + +type = file +alt = "Image 3 (.jpg)" + +[image4] + +type = file +alt = "Image 4 (.jpg)" + +[image5] + +type = file +alt = "Image 5 (.jpg)" + +[image6] + +type = file +alt = "Image 6 (.jpg)" + +[tab4] + +type = tab +title = State + +[sitellite_status] + +type = status +alt = Status +setValue = draft +extra = "id=`sitellite_status` onfocus=`formhelp_show (this, 'The status determines what stage of its lifecycle that your document is in. Only Approved pages can be viewed on the live site. Queued pages are set to be approved on the specified Publish On date (below) by the scheduler.')` onblur=`formhelp_hide ()`" + +[sitellite_access] + +type = access +alt = Access Level +setValue = public +extra = "id=`sitellite_access` onfocus=`formhelp_show (this, 'The access level of a document determines who is allowed to view it. This allows you to make portions of your site completely private, or only available to specific user roles (ie. members-only).')` onblur=`formhelp_hide ()`" + +[sitellite_startdate] + +type = calendar +alt = "Publish On (If Status is `Queued`)" +nullable = true +showsTime = true +format = "%Y-%m-%d %H:%M:%S" +displayFormat = "%a, %e %b, %Y - %l:%M%P" + +[sitellite_expirydate] + +type = calendar +alt = "Archive On (If Status is `Approved`)" +nullable = true +showsTime = true +format = "%Y-%m-%d %H:%M:%S" +displayFormat = "%a, %e %b, %Y - %l:%M%P" + +[sitellite_owner] + +type = owner +alt = Created By +advanced = yes + +[sitellite_team] + +type = team +alt = Owned by Team +extra = "id=`sitellite_team`" +advanced = yes + +[tab-end] + +type = tab + +[submit_button] + +type = msubmit +button 0 = Create +button 1 = "Cancel, onclick=`history.go (-1); return false`" diff --git a/inc/app/siteshop/forms/edit/access.php b/inc/app/siteshop/forms/edit/access.php new file mode 100644 index 00000000..fc3b876a --- /dev/null +++ b/inc/app/siteshop/forms/edit/access.php @@ -0,0 +1,5 @@ +sitellite_access = private +sitellite_status = approved +sitellite_action = on +sitellite_template_set = admin +sitellite_goto = siteshop-admin-index-action diff --git a/inc/app/siteshop/forms/edit/index.php b/inc/app/siteshop/forms/edit/index.php new file mode 100644 index 00000000..4132607c --- /dev/null +++ b/inc/app/siteshop/forms/edit/index.php @@ -0,0 +1,87 @@ +parseSettings ('inc/app/siteshop/forms/edit/settings.php'); + global $cgi; + $p = new Product ($cgi->id); + page_title (intl_get ('Editing Product') . ': ' . $p->val ('name')); + $data = (array) $p->makeObj (); + foreach ($data as $k => $v) { + $this->widgets[$k]->setValue ($v); + } + $cats = $p->getCategories (); + foreach ($cats as $i => $cat) { + if ($i > 2) { + break; + } + $this->widgets['category' . ($i + 1)]->setValue ($cat->id); + } + $images = $p->getImages (); + foreach ($images as $i => $image) { + if ($image == site_prefix () . '/' . appconf ('default_thumbnail')) { + continue; + } + if ($i > 5) { + break; + } + + $this->widgets['image' . ($i + 1)]->setValue ($image); + } + } + + function onSubmit ($vals) { + unset ($vals['tab1']); + unset ($vals['tab2']); + unset ($vals['tab3']); + unset ($vals['tab4']); + unset ($vals['tab-end']); + unset ($vals['submit_button']); + + $images = array (); + $images[] = $vals['image1']; + $images[] = $vals['image2']; + $images[] = $vals['image3']; + $images[] = $vals['image4']; + $images[] = $vals['image5']; + $images[] = $vals['image6']; + unset ($vals['image1']); + unset ($vals['image2']); + unset ($vals['image3']); + unset ($vals['image4']); + unset ($vals['image5']); + unset ($vals['image6']); + + $categories = array (); + $categories[] = $vals['category1']; + $categories[] = $vals['category2']; + $categories[] = $vals['category3']; + unset ($vals['category1']); + unset ($vals['category2']); + unset ($vals['category3']); + + $p = new Product ($vals['id']); + $vals = (object) $vals; + $p->setCurrent ($vals); + $p->save (); + + foreach ($categories as $cat) { + if ($cat) { + $p->setCategory (new Category ($cat)); + } + } + + foreach ($images as $n => $image) { + if (is_object ($image) && preg_match ('/\.jpg$/i', $image->name)) { + unlink ('inc/app/siteshop/data/'. $p->val ('id') . '-' . ($n + 1) . '.jpg'); + $image->move ('inc/app/siteshop/data', $p->val ('id') . '-' . ($n + 1) . '.jpg'); + } + } + + header ('Location: ' . site_prefix () . '/index/siteshop-admin-products-action'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/forms/edit/offer/index.php b/inc/app/siteshop/forms/edit/offer/index.php new file mode 100644 index 00000000..a6331d16 --- /dev/null +++ b/inc/app/siteshop/forms/edit/offer/index.php @@ -0,0 +1,30 @@ +parseSettings ('inc/app/siteshop/forms/edit/offer/settings.php'); + global $cgi; + $s = new CheckoutOffer ($cgi->id); + $this->widgets['id']->setValue ($cgi->id); + $this->widgets['offer_number']->setValue ($s->val ('offer_number')); + $this->widgets['offer_text']->setValue ($s->val ('offer_text')); + $this->widgets['product_id']->setValue ($s->val ('product_id')); + $this->widgets['sale_price']->setValue ($s->val ('sale_price')); + page_title (intl_get ('Editing Checkout Offer') . ': ' . $s->val ('offer_number')); + } + + function onSubmit ($vals) { + unset ($vals['submit_button']); + + $s = new CheckoutOffer ($vals['id']); + $vals = (object) $vals; + $s->setCurrent ($vals); + $s->save (); + + header ('Location: ' . site_prefix () . '/index/siteshop-admin-offers-action'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/forms/edit/offer/settings.php b/inc/app/siteshop/forms/edit/offer/settings.php new file mode 100644 index 00000000..d8e9d9c3 --- /dev/null +++ b/inc/app/siteshop/forms/edit/offer/settings.php @@ -0,0 +1,35 @@ +[Form] + +error_mode = all + +[id] + +type = hidden + +[offer_number] + +type = info +alt = Offer Number + +[offer_text] + +type = text +alt = Offer Text +extra = "size=`60`" + +[product_id] + +type = select +alt = Product +setValues = "eval: Product::selectAll ()" + +[sale_price] + +type = text +alt = "Sale Price ($)" + +[submit_button] + +type = msubmit +button 0 = Save +button 1 = "Cancel, onclick=`history.go (-1); return false`" diff --git a/inc/app/siteshop/forms/edit/option/index.php b/inc/app/siteshop/forms/edit/option/index.php new file mode 100755 index 00000000..cc3e0b4b --- /dev/null +++ b/inc/app/siteshop/forms/edit/option/index.php @@ -0,0 +1,51 @@ +parseSettings ('inc/app/siteshop/forms/edit/option/settings.php'); + page_title (intl_get ('Edit an Option')); + + global $cgi; + $o = new Option($cgi->o); + $this->action = site_prefix() . '/index/siteshop-edit-option-form?o=' . $cgi->o; + + //$this->widgets['type']->setValue($o->val ('type')); + $this->widgets['name']->setValue($o->val ('name')); + $this->widgets['weight']->setValue($o->val ('weight')); + $this->widgets['value']->setValue($o->val('value')); + $this->widgets['type']->setValue($o->val('type')); + $this->widgets['image']->setValue($o->getImage()); + } + + function onSubmit ($vals) { + + global $cgi; + + unset ($vals['submit_button']); + $vals['id'] = $cgi->o; + + $image = $vals['image']; + unset ($vals['image']); + + $o = new Option($cgi->o); + $vals = (object) $vals; + + + //info ($vals);exit; + $o->setCurrent ($vals); + $o->save(); + + if (is_object ($image) && preg_match ('/\.jpg$/i', $image->name)) { + unlink ('inc/app/siteshop/pix/options/' . $o->val ('id') . '.jpg'); + $image->move ('inc/app/siteshop/pix/options', $o->val ('id') . '.jpg'); + } + + header ('Location: ' . site_prefix () . '/index/siteshop-admin-options-action'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/forms/edit/option/settings.php b/inc/app/siteshop/forms/edit/option/settings.php new file mode 100755 index 00000000..b04c637e --- /dev/null +++ b/inc/app/siteshop/forms/edit/option/settings.php @@ -0,0 +1,40 @@ +[Form] + +error_mode = all +extra = "enctype=`multipart/form-data`" +uploadFiles = false + +[name] +alt = Option Name +type = text +rule 1 = "not empty, You must enter an option name" + +[type] + +type = selector +alt = Option Group +table = siteshop_option_type +key = name +rule 1 = "not empty, You must enter an option group." + +[value] + +type = text +alt = Extra Info + +[image] + +alt = "Image (Optional)" +type = file + +[weight] +type = text +alt = "Sorting Weight" +rule 1 = "numeric, The weight must be an integer 1-100" +default_value = 5 + +[submit_button] + +type = msubmit +button 0 = Save +button 1 = "Cancel, onclick=`history.go (-1); return false`" diff --git a/inc/app/siteshop/forms/edit/promo/index.php b/inc/app/siteshop/forms/edit/promo/index.php new file mode 100644 index 00000000..6cbafe09 --- /dev/null +++ b/inc/app/siteshop/forms/edit/promo/index.php @@ -0,0 +1,30 @@ +parseSettings ('inc/app/siteshop/forms/edit/promo/settings.php'); + global $cgi; + $s = new Promo ($cgi->id); + page_title (intl_get ('Editing Promo Code') . ': ' . $s->val ('code')); + $this->widgets['id']->setValue ($s->val ('id')); + $this->widgets['code']->setValue ($s->val ('code')); + $this->widgets['discount_type']->setValue ($s->val ('discount_type')); + $this->widgets['discount']->setValue ($s->val ('discount')); + $this->widgets['expires']->setValue ($s->val ('expires')); + } + + function onSubmit ($vals) { + unset ($vals['submit_button']); + + $s = new Promo ($vals['id']); + $vals = (object) $vals; + $s->setCurrent ($vals); + $s->save (); + + header ('Location: ' . site_prefix () . '/index/siteshop-admin-promo-action'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/forms/edit/promo/settings.php b/inc/app/siteshop/forms/edit/promo/settings.php new file mode 100644 index 00000000..ee4fa544 --- /dev/null +++ b/inc/app/siteshop/forms/edit/promo/settings.php @@ -0,0 +1,36 @@ +[Form] + +error_mode = all + +[id] + +type = hidden + +[code] + +type = text +alt = Promo Code + +[discount_type] + +type = select +alt = Discount Type +setValues = "eval: array ('percent' => 'Percent', 'dollars' => 'Dollars')" + +[discount] + +type = text +alt = Discount + +[expires] + +type = calendar +alt = "Expires (Last Day)" +format = "%Y-%m-%d" +displayFormat = "%a, %e %b, %Y" + +[submit_button] + +type = msubmit +button 0 = Save +button 1 = "Cancel, onclick=`history.go (-1); return false`" diff --git a/inc/app/siteshop/forms/edit/sale/index.php b/inc/app/siteshop/forms/edit/sale/index.php new file mode 100644 index 00000000..f85203c8 --- /dev/null +++ b/inc/app/siteshop/forms/edit/sale/index.php @@ -0,0 +1,47 @@ +parseSettings ('inc/app/siteshop/forms/edit/sale/settings.php'); + global $cgi; + $s = new Sale ($cgi->id); + page_title (intl_get ('Editing Sale') . ': ' . $s->val ('name')); + $this->widgets['id']->setValue ($s->val ('id')); + $this->widgets['name']->setValue ($s->val ('name')); + $this->widgets['start_date']->setValue ($s->val ('start_date')); + $this->widgets['until_date']->setValue ($s->val ('until_date')); + } + + function onSubmit ($vals) { + $products = trim ($vals['product_id']); + unset ($vals['product_id']); + unset ($vals['submit_button']); + + // adjust dates + $vals['start_date'] = array_shift (explode (' ', $vals['start_date'])) . ' 00:00:00'; + $vals['until_date'] = array_shift (explode (' ', $vals['until_date'])) . ' 23:59:59'; + + $s = new Sale ($vals['id']); + $vals = (object) $vals; + $s->setCurrent ($vals); + $s->save (); + + // set all products on sale + db_execute ('delete from siteshop_sale_product where sale_id = ?', $vals->id); + parse_str ($products, $prods); + foreach ($prods as $k => $v) { + db_execute ( + 'insert into siteshop_sale_product values (?, ?, ?)', + $vals->id, + $k, + $v + ); + } + + header ('Location: ' . site_prefix () . '/index/siteshop-admin-sales-action'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/forms/edit/sale/settings.php b/inc/app/siteshop/forms/edit/sale/settings.php new file mode 100644 index 00000000..ec715a18 --- /dev/null +++ b/inc/app/siteshop/forms/edit/sale/settings.php @@ -0,0 +1,38 @@ +[Form] + +error_mode = all + +[id] + +type = hidden + +[name] + +type = text +alt = Sale Name +extra = "size=`60`" + +[start_date] + +type = calendar +alt = "Sale Starts (First Day)" +format = "%Y-%m-%d" +displayFormat = "%a, %e %b, %Y" + +[until_date] + +type = calendar +alt = "Sale Ends (Last Day)" +format = "%Y-%m-%d" +displayFormat = "%a, %e %b, %Y" + +[product_id] + +type = siteshop.Widget.Products +alt = Products + +[submit_button] + +type = msubmit +button 0 = Save +button 1 = "Cancel, onclick=`history.go (-1); return false`" diff --git a/inc/app/siteshop/forms/edit/settings.php b/inc/app/siteshop/forms/edit/settings.php new file mode 100644 index 00000000..e5cf4b8f --- /dev/null +++ b/inc/app/siteshop/forms/edit/settings.php @@ -0,0 +1,194 @@ +[Form] + +error_mode = all +extra = "onsubmit=`xed_copy_value (this, 'body')` enctype=`multipart/form-data`" +uploadFiles = false + +[id] + +type = hidden + +[tab1] + +type = tab +title = Edit + +[sku] + +type = text +alt = SKU + +[name] + +type = text +alt = Product Name +extra = "size=`60`" + +[price] + +type = text +alt = "Price ($)" + +[category1] + +type = select +alt = Category 1 +setValues = "eval: Category::listAssoc ()" + +[category2] + +type = select +alt = Category 2 +setValues = "eval: Category::listAssoc ()" + +[category3] + +type = select +alt = Category 3 +setValues = "eval: Category::listAssoc ()" + +[body] + +type = xed.Widget.Xeditor + +[tab2] + +type = tab +title = Properties + +[shipping] + +type = text +alt = "Shipping ($)" +setDefault = "eval: appconf ('shipping_base')" + +[availability] + +type = select +alt = Availability +setValues = "eval: appconf ('availability')" + +[quantity] + +type = text +alt = "Quantity (-1 for unlimited)" +setDefault = "-1" + +[weight] + +type = select +alt = Sorting Weight +setValues = "eval: appconf ('weight')" + +[taxable] + +type = select +alt = Taxable +setValues = "eval: array ('yes' => 'Yes', 'no' => 'No')" + +[keywords] + +type = cms.Widget.Keywords +alt = Keywords + +[description] + +type = textarea +alt = Description +rows = 3 +labelPosition = left + +[tab3] + +type = tab +title = Images + +[image1] + +type = file +alt = "Image 1 (.jpg)" + +[image2] + +type = file +alt = "Image 2 (.jpg)" + +[image3] + +type = file +alt = "Image 3 (.jpg)" + +[image4] + +type = file +alt = "Image 4 (.jpg)" + +[image5] + +type = file +alt = "Image 5 (.jpg)" + +[image6] + +type = file +alt = "Image 6 (.jpg)" + +[tab4] + +type = tab +title = State + +[sitellite_status] + +type = status +alt = Status +setValue = draft +extra = "id=`sitellite_status` onfocus=`formhelp_show (this, 'The status determines what stage of its lifecycle that your document is in. Only Approved pages can be viewed on the live site. Queued pages are set to be approved on the specified Publish On date (below) by the scheduler.')` onblur=`formhelp_hide ()`" + +[sitellite_access] + +type = access +alt = Access Level +setValue = public +extra = "id=`sitellite_access` onfocus=`formhelp_show (this, 'The access level of a document determines who is allowed to view it. This allows you to make portions of your site completely private, or only available to specific user roles (ie. members-only).')` onblur=`formhelp_hide ()`" + +[sitellite_startdate] + +type = calendar +alt = "Publish On (If Status is `Queued`)" +nullable = true +showsTime = true +format = "%Y-%m-%d %H:%M:%S" +displayFormat = "%a, %e %b, %Y - %l:%M%P" + +[sitellite_expirydate] + +type = calendar +alt = "Archive On (If Status is `Approved`)" +nullable = true +showsTime = true +format = "%Y-%m-%d %H:%M:%S" +displayFormat = "%a, %e %b, %Y - %l:%M%P" + +[sitellite_owner] + +type = owner +alt = Created By +advanced = yes + +[sitellite_team] + +type = team +alt = Owned by Team +extra = "id=`sitellite_team`" +advanced = yes + +[tab-end] + +type = tab + +[submit_button] + +type = msubmit +button 0 = Save +button 1 = "Cancel, onclick=`history.go (-1); return false`" diff --git a/inc/app/siteshop/forms/settings/access.php b/inc/app/siteshop/forms/settings/access.php new file mode 100755 index 00000000..fc3b876a --- /dev/null +++ b/inc/app/siteshop/forms/settings/access.php @@ -0,0 +1,5 @@ +sitellite_access = private +sitellite_status = approved +sitellite_action = on +sitellite_template_set = admin +sitellite_goto = siteshop-admin-index-action diff --git a/inc/app/siteshop/forms/settings/index.php b/inc/app/siteshop/forms/settings/index.php new file mode 100755 index 00000000..35511945 --- /dev/null +++ b/inc/app/siteshop/forms/settings/index.php @@ -0,0 +1,59 @@ +' . intl_get ('Can\'t write to the settings file, please check your server permissions and try again.') . '

'; + return; +} + +class SiteshopSettingsForm extends MailForm { + function SiteshopSettingsForm () { + parent::MailForm (); + $this->parseSettings ('inc/app/siteshop/forms/settings/settings.php'); + page_title (intl_get ('Settings')); + $conf = ini_parse ('inc/app/siteshop/conf/settings.php'); + foreach ($conf as $section => $settings) { + if ($section == 'Taxes') { + $o = ''; + $sep = ''; + foreach ($settings as $k => $v) { + $o .= $sep . $k . ' ' . $v; + $sep = "\n"; + } + $this->widgets['tax_input']->setValue ($o); + } else { + foreach ($settings as $k => $v) { + $this->widgets[$k]->setValue ($v); + } + } + } + } + + function onSubmit ($vals) { + $conf = ini_parse ('inc/app/siteshop/conf/settings.php'); + foreach ($conf as $section => $settings) { + if ($section == 'Taxes') { + $new_taxes = array (); + foreach (explode ("\n", $vals['tax_input']) as $line) { + $line = trim ($line); + list ($k, $v) = explode (' ', $line, 2); + $new_taxes[$k] = $v; + } + $conf[$section] = $new_taxes; + } else { + foreach ($settings as $k => $v) { + $conf[$section][$k] = $vals[$k]; + } + } + } + + $fp = fopen ('inc/app/siteshop/conf/settings.php', 'w'); + fwrite ($fp, ini_write ($conf)); + fclose ($fp); + + header ('Location: ' . site_prefix () . '/index/siteshop-admin-index-action'); + exit; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/forms/settings/settings.php b/inc/app/siteshop/forms/settings/settings.php new file mode 100755 index 00000000..b66bb0ca --- /dev/null +++ b/inc/app/siteshop/forms/settings/settings.php @@ -0,0 +1,151 @@ +[Form] + +error_mode = all + +[general] + +type = section +title = General + +[page_title] + +type = text +alt = Store Name +extra = "size=`30`" + +[paypal_id] + +type = text +alt = Paypal ID +extra = "size=`30`" + +[order_notices] + +type = text +alt = Email Order Notices +extra = "size=`30`" + +[currency_code] + +type = text +alt = Local Currency Code +extra = "size=`10`" + +[shipping] + +type = section +title = Shipping + +[base] + +type = text +alt = Base Shipping For All Items +extra = "size=`10`" + +[max] + +type = text +alt = "Max Shipping On Orders (Optional)" +extra = "size=`10`" + +[free] + +type = text +alt = "Free Shipping On Orders Over (Optional)" +extra = "size=`10`" + +[taxes] + +type = section +title = Taxes + +[tax_input] + +type = textarea +label_template = "{filter none}{display_value}{end filter}" +alt = "One per line, e.g.,
GST 0.06
PST 0.07
" +labelPosition = left +cols = 20 +rows = 3 + +[display] + +type = section +title = Display + +[default_thumbnail] + +type = text +alt = Default Thumbnail Image +extra = "size=`50`" + +[default_style] + +type = text +alt = Default CSS Stylesheet +extra = "size=`50`" + +[page_alias] + +type = text +alt = "Page Alias (Page ID)" + +[below_page] + +type = text +alt = "Below Page (Page ID)" + +[page_template] + +type = text +label_template = "{filter none}{display_value}{end filter}" +alt = "Page Template
For html.default.tpl enter 'default'
" + +[checkout_template] + +type = text +label_template = "{filter none}{display_value}{end filter}" +alt = "Checkout Template
For html.default.tpl enter 'default'
" + +[checkout_handler] + +type = text +alt = "Checkout Handler" + +[alternate_index] + +type = text +alt = "Alternate Index (Box)" + +[alternate_product] + +type = text +alt = "Alternate Product Page (Box)" + +[alternate_category] + +type = text +alt = "Alternate Product Category Page (Box)" + +[customer_registration_return_email] + +type = text +alt = "Customer Registration Return Email Address" + +[product_comments] + +type = select +alt = "Enable product comments" +setValues = "eval: array ('0' => intl_get ('No'), '1' => intl_get ('Yes'))" + +[product_ratings] + +type = select +alt = "Enable product ratings" +setValues = "eval: array ('0' => intl_get ('No'), '1' => intl_get ('Yes'))" + +[submit_button] + +type = msubmit +button 0 = Save +button 1 = "Cancel, onclick=`history.go (-1); return false`" diff --git a/inc/app/siteshop/html/addtocartform1.spt b/inc/app/siteshop/html/addtocartform1.spt new file mode 100755 index 00000000..e249ff2c --- /dev/null +++ b/inc/app/siteshop/html/addtocartform1.spt @@ -0,0 +1,2 @@ +
+ diff --git a/inc/app/siteshop/html/addtocartform2.spt b/inc/app/siteshop/html/addtocartform2.spt new file mode 100755 index 00000000..59ac344a --- /dev/null +++ b/inc/app/siteshop/html/addtocartform2.spt @@ -0,0 +1,28 @@ + + + +{loop obj[options]} + + + + +{end loop} + diff --git a/inc/app/siteshop/html/addtocartform3.spt b/inc/app/siteshop/html/addtocartform3.spt new file mode 100755 index 00000000..a2aae27b --- /dev/null +++ b/inc/app/siteshop/html/addtocartform3.spt @@ -0,0 +1,8 @@ +
+

{type}:

+
+ + + {if loop.available eq 'yes'} + {loop/name}
+ {end if} + {if loop.available eq 'no'} + {loop/name} - Sold Out
+ {end if} +
+
+

+ +{intl Add to Cart} + +

+
\ No newline at end of file diff --git a/inc/app/siteshop/html/addtocartform_nooptions.spt b/inc/app/siteshop/html/addtocartform_nooptions.spt new file mode 100755 index 00000000..5c5aa6e1 --- /dev/null +++ b/inc/app/siteshop/html/addtocartform_nooptions.spt @@ -0,0 +1,7 @@ +
+

+ +{intl Add to Cart} + +

+
diff --git a/inc/app/siteshop/html/admin_categories.spt b/inc/app/siteshop/html/admin_categories.spt new file mode 100644 index 00000000..c280db25 --- /dev/null +++ b/inc/app/siteshop/html/admin_categories.spt @@ -0,0 +1,62 @@ + + +

{intl Add Category}

+ +{alt #fff #eee} + +

+ + + + + + + +{loop obj[list]} + + + + + + +{end loop} +
+   + + {intl Name} + + {intl Sorting Weight} + + {intl Products} +
+ {intl Delete} + + {loop/name} + + {loop/weight} +  {intl Increase} +  {intl Decrease} + + {filter siteshop_filter_category_products}{loop/id}{end filter} +
+

diff --git a/inc/app/siteshop/html/admin_index.spt b/inc/app/siteshop/html/admin_index.spt new file mode 100644 index 00000000..e7953ad6 --- /dev/null +++ b/inc/app/siteshop/html/admin_index.spt @@ -0,0 +1,65 @@ +

+ + + + + +
+ +

{intl Orders} ({orders_total})

+ + + +

{intl Statistics}

+ + + + + + +
+{intl Total Sales Today}:
+{intl Total Sales This Month}:
+{intl Total Sales This Year}:
+{intl Orders Today}:
+{intl Orders This Month}:
+{intl Orders This Year}: +
+${sales_today}
+${sales_month}
+${sales_year}
+{orders_today}
+{orders_month}
+{orders_year} +
+ +
+ +

Quick Links

+ + + + + + +
+Products ({products})
+Checkout Offers ({offers})
+Sales ({sales})
+Categories ({categories})
+Orders ({orders_total}) +
+Add | View
+Add | View
+Add | View
+Add | View
+View
+
+ +
+

diff --git a/inc/app/siteshop/html/admin_nav.spt b/inc/app/siteshop/html/admin_nav.spt new file mode 100644 index 00000000..bb9f67af --- /dev/null +++ b/inc/app/siteshop/html/admin_nav.spt @@ -0,0 +1,136 @@ + + + + + + +

+ + + + + +

diff --git a/inc/app/siteshop/html/admin_offers.spt b/inc/app/siteshop/html/admin_offers.spt new file mode 100644 index 00000000..8bfd0808 --- /dev/null +++ b/inc/app/siteshop/html/admin_offers.spt @@ -0,0 +1,45 @@ +

{intl Add Checkout Offer}

+ +{alt #fff #eee} + +

+ + + + + + + + +{loop obj[list]} + + + + + + + +{end loop} +
+   + + # + + {intl Offer Text} + + {intl Product} + + {intl Sale Price} +
+ {intl Delete} + + {loop/offer_number} + + {loop/offer_text} + + {filter siteshop_filter_product_name}{loop/product_id}{end filter} + + ${loop/sale_price} +
+

diff --git a/inc/app/siteshop/html/admin_options.spt b/inc/app/siteshop/html/admin_options.spt new file mode 100755 index 00000000..c29ce9f9 --- /dev/null +++ b/inc/app/siteshop/html/admin_options.spt @@ -0,0 +1,39 @@ +

{intl Add Option}    {intl Products}

+ +{alt #fff #eee} + +

+ + + + + + + +{loop obj[list]} + + + + + + +{end loop} +
+   + + {intl Type} + + {intl Option} + + {intl Extra Info} +
+ {intl Delete} + + {loop/type} + + {loop/name} + + {loop/value} +
+

diff --git a/inc/app/siteshop/html/admin_orders.spt b/inc/app/siteshop/html/admin_orders.spt new file mode 100644 index 00000000..5ab53337 --- /dev/null +++ b/inc/app/siteshop/html/admin_orders.spt @@ -0,0 +1,94 @@ +

+{filter none}{facets}{end filter} +

+ +

+ + + + + +
{spt PAGER_TEMPLATE_FROM_TO}{if pager.total}{spt PAGER_TEMPLATE_PREV_PAGE_LIST_NEXT}{end if}
+

+ +{alt #fff #eee} + +
+ + + + + + + + + + + + +{loop obj[list]} + + + + + + + + + + + +{end loop} +
+   + {intl Order} # + {if obj[orderBy] eq 'id'} + {cgi/sort} + {end if} + {intl Customer Name} + {if obj[orderBy] eq 'bill_to'} + {cgi/sort} + {end if} + {intl Status} + {if obj[orderBy] eq 'status'} + {cgi/sort} + {end if} + {intl Date/Time} + {if obj[orderBy] eq 'ts'} + {cgi/sort} + {end if} + {intl Subtotal} + {if obj[orderBy] eq 'subtotal'} + {cgi/sort} + {end if} + {intl Shipping} + {if obj[orderBy] eq 'shipping'} + {cgi/sort} + {end if} + {intl Taxes} + {if obj[orderBy] eq 'taxes'} + {cgi/sort} + {end if} + {intl Total} + {if obj[orderBy] eq 'total'} + {cgi/sort} + {end if} +
+ + {loop/id}{loop/bill_to}{filter ucwords}{loop/status}{end filter}{filter siteshop_filter_date_time}{loop/ts}{end filter}${loop/subtotal}${loop/shipping}${loop/taxes}${loop/total}
+
+ +
+

{intl Export Orders (CSV)}

+

{intl Status}:  +   + +

+
+ diff --git a/inc/app/siteshop/html/admin_orders_update_email.spt b/inc/app/siteshop/html/admin_orders_update_email.spt new file mode 100644 index 00000000..da62ddd5 --- /dev/null +++ b/inc/app/siteshop/html/admin_orders_update_email.spt @@ -0,0 +1,12 @@ +Hello, + +This is an automatic notice sent to let you know that the status of your +order #{id} has been changed to {filter ucwords}{status}{end filter}. +{if not empty (obj.tracking)} +You can track the shipment status of this order here: + +{tracking}{end if} + +If you have any questions, please let us know. + +{site/domain} diff --git a/inc/app/siteshop/html/admin_orders_view.spt b/inc/app/siteshop/html/admin_orders_view.spt new file mode 100644 index 00000000..6c4a6c74 --- /dev/null +++ b/inc/app/siteshop/html/admin_orders_view.spt @@ -0,0 +1,150 @@ + + +

{intl Order} #{id}

+ +

+ {intl Back} +     + {intl Print Order} +

+ +

+ + + + + +
+

{intl Ship To}

+

{ship_to}
{ship_address}{if not empty (obj.ship_address2)}
{ship_address2}{end if}
{ship_city}, {filter strtoupper}{ship_state}{end filter}
{filter siteshop_filter_country}{ship_country}{end filter}
{ship_zip}

+

+

+ + + + + + + + + + + + + + +
{intl Status}
{intl Tracking Link}
 
+
+

+
+

{intl Billed To}

+

{bill_to}
{bill_address}{if not empty (obj.bill_address2)}
{bill_address2}{end if}
{bill_city}, {filter strtoupper}{bill_state}{end filter}
{filter siteshop_filter_country}{bill_country}{end filter}
{bill_zip}

+

{phone}
{email}

+
+

+ +
+

{intl Status History}

+ +

+ + + + + +{loop obj.history} + + + + +{end loop} +
DateStatus
{filter siteshop_filter_date_time}{loop/ts}{end filter}{filter ucwords}{loop/status}{end filter}
+

+
+ +

{intl Items}

+ +{alt #fff #eee} + +

+ + + + + + + + + +{loop obj.products} + + + + + + + +{end loop} + + + + + + + + + + + + + + + +{if not empty (obj.promo_code)} + + + + + +{end if} + + + + + +
SKU{intl Product Name}{intl Product Options}{intl Price}{intl Quantity}{intl Total}
{loop/sku}{loop/name} + {loop loop.options} + {loop/type}: {loop/name}{if loop[_total] eq loop[_index]}{end if}{if else},{end if} + {end loop} + ${loop/price}{loop/quantity}${filter siteshop_filter_money}{php loop.price x loop.quantity}{end filter}
 {intl Subtotal}${subtotal}
 {intl Shipping}${shipping}
 {intl Tax}${taxes}
 {intl Promo Code}: {promo_code}${promo_discount}
 {intl Total}${total}
+

diff --git a/inc/app/siteshop/html/admin_productoptions1.spt b/inc/app/siteshop/html/admin_productoptions1.spt new file mode 100755 index 00000000..bfcdd643 --- /dev/null +++ b/inc/app/siteshop/html/admin_productoptions1.spt @@ -0,0 +1,5 @@ +

Options For: {name}

+ +
+ + diff --git a/inc/app/siteshop/html/admin_productoptions2.spt b/inc/app/siteshop/html/admin_productoptions2.spt new file mode 100755 index 00000000..e1bbdb8f --- /dev/null +++ b/inc/app/siteshop/html/admin_productoptions2.spt @@ -0,0 +1,17 @@ + + + + + +{loop obj[options]} + + + + + + +{end loop} + + diff --git a/inc/app/siteshop/html/admin_productoptions3.spt b/inc/app/siteshop/html/admin_productoptions3.spt new file mode 100755 index 00000000..5ef4b25f --- /dev/null +++ b/inc/app/siteshop/html/admin_productoptions3.spt @@ -0,0 +1,9 @@ + + + +
+

{type}

+
+ +   + +
+
\ No newline at end of file diff --git a/inc/app/siteshop/html/admin_products.spt b/inc/app/siteshop/html/admin_products.spt new file mode 100644 index 00000000..84002cd8 --- /dev/null +++ b/inc/app/siteshop/html/admin_products.spt @@ -0,0 +1,73 @@ +

{intl Add Product}    {intl Product Options}

+ +

+{filter none}{facets}{end filter} +

+ +

+ + + + + +
{spt PAGER_TEMPLATE_FROM_TO}{if pager.total}{spt PAGER_TEMPLATE_PREV_PAGE_LIST_NEXT}{end if}
+

+ +{alt #fff #eee} + +
+ + + + + + + + + + + + +{loop obj[list]} + + + + + + + + + + + +{end loop} +
+   + SKU + {if obj[orderBy] eq 'sku'} + {cgi/sort} + {end if} + {intl Product Name} + {if obj[orderBy] eq 'name'} + {cgi/sort} + {end if} + {intl Price} + {if obj[orderBy] eq 'price'} + {cgi/sort} + {end if} + {intl Shipping} + {if obj[orderBy] eq 'shipping'} + {cgi/sort} + {end if} + {intl Quantity} + {if obj[orderBy] eq 'quantity'} + {cgi/sort} + {end if} + {intl Sorting Weight} + {if obj[orderBy] eq 'weight'} + {cgi/sort} + {end if} + {intl Categories}
+ + Product Options{loop/sku}{loop/name}${loop/price}${loop/shipping}{if loop.quantity eq -1}{intl Unlimited}{end if}{if else}{loop/quantity}{end if}{filter siteshop_filter_weight}{loop/weight}{end filter}{filter siteshop_filter_categories}{loop/id}{end filter}
+
diff --git a/inc/app/siteshop/html/admin_promo.spt b/inc/app/siteshop/html/admin_promo.spt new file mode 100644 index 00000000..199c40e0 --- /dev/null +++ b/inc/app/siteshop/html/admin_promo.spt @@ -0,0 +1,45 @@ +

{intl Add Promo Code}

+ +{alt #fff #eee} + +

+ + + + + + + + +{loop obj[list]} + + + + + + + +{end loop} +
+   + + {intl Code} + + {intl Type} + + {intl Discount} + + {intl Expires} +
+ {intl Delete} + + {loop/code} + + {filter ucfirst}{loop/discount_type}{end filter} + + {loop/discount} + + {filter siteshop_filter_date}{loop/expires}{end filter} +
+

diff --git a/inc/app/siteshop/html/admin_sales.spt b/inc/app/siteshop/html/admin_sales.spt new file mode 100644 index 00000000..7e2c0f37 --- /dev/null +++ b/inc/app/siteshop/html/admin_sales.spt @@ -0,0 +1,45 @@ +

{intl Add Sale}

+ +{alt #fff #eee} + +

+ + + + + + + + +{loop obj[list]} + + + + + + + +{end loop} +
+   + + {intl Name} + + {intl From} + + {intl To} + + {intl Products} +
+ {intl Delete} + + {loop/name} + + {filter siteshop_filter_date}{loop/start_date}{end filter} + + {filter siteshop_filter_date}{loop/until_date}{end filter} + + {filter siteshop_filter_sale_products}{loop/id}{end filter} +
+

diff --git a/inc/app/siteshop/html/cart.spt b/inc/app/siteshop/html/cart.spt new file mode 100644 index 00000000..1948269c --- /dev/null +++ b/inc/app/siteshop/html/cart.spt @@ -0,0 +1,78 @@ +{alt #fff #eee} + +

{intl Continue Shopping}

+ +
+ +

+ + + + + + + + + +{loop obj} + + + + + + + + +{end loop} + + + + + + + + + + + + + + + + + + +{if Cart::hasPromo ()} + + + + + + +{end if} + + + + + + +
 {intl Product Name}{intl Options}{intl Price}{intl Qty}{intl Total}
{intl Remove}{loop/name} + {loop loop.options} + {loop/type}: {loop/name}{if loop[_total] eq loop[_index]}{end if}{if else},{end if} + {end loop} + ${loop/price}${php Cart::subtotal (loop._key)}
  {intl Subtotal}${php Cart::subtotal ()}
  {intl Shipping}{if Cart::shipping () eq 0}{intl FREE!}{end if}{if else}${php Cart::shipping ()}{end if}
  {intl Tax}${php Cart::tax ()}
  {intl Promo}: {php Cart::promoName ()}${php Cart::promo ()}
  {intl Total}${php Cart::total ()}
+

+ +

+ {if not Cart::hasPromo ()} + + {intl Promo Code}:   + + + {end if} + +   + +

+ +
diff --git a/inc/app/siteshop/html/cart_sidebar.spt b/inc/app/siteshop/html/cart_sidebar.spt new file mode 100644 index 00000000..bdaed77d --- /dev/null +++ b/inc/app/siteshop/html/cart_sidebar.spt @@ -0,0 +1,8 @@ +{if obj[items] eq 0} +

{intl Your shopping cart is empty.}

+{end if} +{if else} +

{items} {intl Item(s)}
+{intl Total}: ${total}

+

{intl View Cart}

+{end if} diff --git a/inc/app/siteshop/html/categories.spt b/inc/app/siteshop/html/categories.spt new file mode 100644 index 00000000..c5ad8357 --- /dev/null +++ b/inc/app/siteshop/html/categories.spt @@ -0,0 +1,5 @@ + diff --git a/inc/app/siteshop/html/category.spt b/inc/app/siteshop/html/category.spt new file mode 100644 index 00000000..488f6027 --- /dev/null +++ b/inc/app/siteshop/html/category.spt @@ -0,0 +1,49 @@ +{alt 1 2 3} + +{loop obj.getSortedProducts ()} +
+

{loop/name}

+

{loop/name}

+

{loop/description}

+ {if loop.sale} +

+ + + + + +
+ {intl On Sale}: {intl Only} ${loop/sale_price}!
+ ({intl Reg.} ${loop/price}) +
+ {if appconf ('product_ratings')} +
+ + {end if} +
+

+ {end if} + {if else} +

+ + + + + +
+ ${loop/price} + {if loop.weight gt 0}
{filter siteshop_filter_weight}{loop/weight}{end filter}!{end if} +
+ {if appconf ('product_ratings')} +
+ + {end if} +
+

+ {end if} +

+ + {intl More Info} +

+
+{end loop} diff --git a/inc/app/siteshop/html/checkout1.spt b/inc/app/siteshop/html/checkout1.spt new file mode 100644 index 00000000..03b1c925 --- /dev/null +++ b/inc/app/siteshop/html/checkout1.spt @@ -0,0 +1,183 @@ + + +

{intl All fields are required.}

+ +
+ + +

+ + + + + +
+ +

{intl Billing Address}

+ +

{intl Full Name}:
+

+ +

{intl Phone Number}:
+

+ +

{intl Email Address}:
+

+ +

{intl Address}:
+
+

+ +

{intl City}:
+

+ +

{intl State/Province}:
+

+ +

{intl Country}:
+

+ +

{intl Zip/Postal Code}:
+

+ +
+ +

{intl Shipping Address}

+ +

{intl Same as billing address.}

+ +

{intl Full Name}:
+

+ +

{intl Address}:
+
+

+ +

{intl City}:
+

+ +

{intl State/Province}:
+

+ +

{intl Country}:
+

+ +

{intl Zip/Postal Code}:
+

+ +

 

+ +

+ +
+

+ +
\ No newline at end of file diff --git a/inc/app/siteshop/html/checkout1_registered.spt b/inc/app/siteshop/html/checkout1_registered.spt new file mode 100755 index 00000000..01e3a673 --- /dev/null +++ b/inc/app/siteshop/html/checkout1_registered.spt @@ -0,0 +1,240 @@ + + +{if not session_valid()} +
+

Existing Customer?

+ +{if not empty (obj[username])} +

{intl Invalid username or password. Please try again.}

+{end if} + +
+ + + + + + + + + + +
+ {intl Email}: + + {intl Password}: + + +{intl Forgot your password?}
+
+
+
+{end if} +

+{if obj[new_user_error] eq 1} + + {intl Please correct the following to continue}:
+ That email address has already been registered. Either login with it above, or don't specify a password below.
+{end if} +{if else} + {intl All fields below are required.} +{end if} +

+ +
+ + + + + + + +
+ +

{intl Billing Address}

+ +

{intl Full Name}:
+

+ +

{intl Phone Number}:
+

+ +

{intl Email Address}:
+

+ +

{intl Address}:
+
+

+ +

{intl City}:
+

+ +

{intl State/Province}:
+

+ +

{intl Country}:
+

+ +

{intl Zip/Postal Code}:
+

+ +
+ +

{intl Shipping Address}

+ +

{intl Same as billing address.}

+ +

{intl Full Name}:
+

+ +

{intl Address}:
+
+

+ +

{intl City}:
+

+ +

{intl State/Province}:
+

+ +

{intl Country}:
+

+ +

{intl Zip/Postal Code}:
+

+ +
+{if not session_valid()} +
+

New Customer?

+

Enter a password to create an account, which will store your contact +information for future purchases (optional).

+
{intl Password}: + +{intl Verify Password}: + +
+
+{end if} +

+
\ No newline at end of file diff --git a/inc/app/siteshop/html/checkout2.spt b/inc/app/siteshop/html/checkout2.spt new file mode 100644 index 00000000..9fa6c3eb --- /dev/null +++ b/inc/app/siteshop/html/checkout2.spt @@ -0,0 +1,27 @@ +

{intl Check each item you would like to add to your order then click continue. To continue without these special offers, simply leave them all unchecked.}

+ +
+ + +{loop obj} +
+

{loop/offer_text}

+ + + + + +
+

{loop/offer_text}

+
+

{loop/description}

+

{intl Only} ${loop/sale_price}!
+ ({intl Reg.} ${loop/price})

+

{intl Add to my order}

+
+
+{end loop} + +

+ +
diff --git a/inc/app/siteshop/html/checkout3.spt b/inc/app/siteshop/html/checkout3.spt new file mode 100644 index 00000000..54f310ac --- /dev/null +++ b/inc/app/siteshop/html/checkout3.spt @@ -0,0 +1,90 @@ +

{intl Please review your order one more time to ensure all of the information is correct. When you are ready, please click continue.}

+ +

+ + + + + +
+

{intl Billing Address}

+

{bill_to}
{bill_address}{if not empty (obj[bill_address2])}
{bill_address2}{end if}
{bill_city}, {filter strtoupper}{bill_state}{end filter}
{filter siteshop_filter_country}{bill_country}{end filter}
{bill_zip}

+

{phone}
{email}

+
+

{intl Shipping Address}

+

{ship_to}
{ship_address}{if not empty (obj[ship_address2])}
{ship_address2}{end if}
{ship_city}, {filter strtoupper}{ship_state}{end filter}
{filter siteshop_filter_country}{ship_country}{end filter}
{ship_zip}

+
+

+ +

{intl Cart Contents}

+ +

+ + + + + + + + +{loop obj[cart]} + + + + + + + +{end loop} + + + + + + + + + + + + + + + +{if Cart::hasPromo ()} + + + + + +{end if} + + + + + +
{intl Product Name}{intl Options}{intl Price}{intl Qty}{intl Total}
{loop/name} + {loop loop.options} + {loop/type}: {loop/name}{if loop[_total] eq loop[_index]}{end if}{if else},{end if} + {end loop}${loop/price}{loop/qty}${php Cart::subtotal (loop._key)}
 {intl Subtotal}${php Cart::subtotal ()}
 {intl Shipping}{if Cart::shipping () eq 0}{intl FREE!}{end if}{if else}${php Cart::shipping ()}{end if}
 {intl Tax}${php Cart::tax ()}
 {intl Promo}: {php Cart::promoName ()}${php Cart::promo ()}
 {intl Total}${php Cart::total ()}
+

+ +

{intl Redirecting to Paypal}

+ +

{intl If everything looks correct, please click continue. You will then be redirected to Paypal to make your payment. Paypal is the largest online payment processing service and ensures your payment information is secure.}

+ +

{intl Once you have completed the payment with Paypal, you will be redirected back to the order confirmation screen on our website.}

+ +
+ + + + + + + + +{if Cart::shipping () ne 0}{end if} + +

+
diff --git a/inc/app/siteshop/html/checkout4.spt b/inc/app/siteshop/html/checkout4.spt new file mode 100644 index 00000000..ecbcd283 --- /dev/null +++ b/inc/app/siteshop/html/checkout4.spt @@ -0,0 +1,3 @@ +

{intl Your order has been submitted. You will receive an email receipt in your inbox shortly.}

+ +

{intl Continue}

diff --git a/inc/app/siteshop/html/checkout5.spt b/inc/app/siteshop/html/checkout5.spt new file mode 100644 index 00000000..e7a69bf1 --- /dev/null +++ b/inc/app/siteshop/html/checkout5.spt @@ -0,0 +1,3 @@ +

{intl Your order has been cancelled. Feel free to browse around the website, everything is still in your shopping cart in case you change your mind.}

+ +

{intl Continue Shopping}

diff --git a/inc/app/siteshop/html/facets.spt b/inc/app/siteshop/html/facets.spt new file mode 100755 index 00000000..c6e355b4 --- /dev/null +++ b/inc/app/siteshop/html/facets.spt @@ -0,0 +1,42 @@ + + + + + + + + + {loop obj[facets]} + + {loop loop} + + {end loop} + + {end loop} + + {if count (obj[selected]) gt 0} + + + + + {loop obj[selected]} + + {loop loop} + + {end loop} + + {end loop} + + {end if} +
+

{intl Search Parameters}

+
+ {if obj[bookmark]}{box cms/bookmarks/button}{end if} + {if not obj[bookmark]} {end if} +
+ {filter none}{loop/_value}{end filter} +
+ {intl You have chosen}: +
+ {filter none}{loop/_value}{end filter} +
diff --git a/inc/app/siteshop/html/index.spt b/inc/app/siteshop/html/index.spt new file mode 100644 index 00000000..2d7765bb --- /dev/null +++ b/inc/app/siteshop/html/index.spt @@ -0,0 +1,69 @@ +{alt 1 2 3} + +{if not empty (obj[sale_name])} +
+

{sale_name} {intl Sale}!

+ +{loop obj[sale_items]} +
+

{loop/name}

+

{loop/name}

+

{loop/description}

+

+ + + + + +
+ {intl ONLY} ${loop/sale_price}!
+ ({intl REG.} ${loop/price}) +
+ {if appconf ('product_ratings')} +
+ + {end if} +
+

+

+ + {intl More Info} +

+
+{end loop} + +

{intl More} {sale_name} {intl Sales}!

+
+{end if} + +{alt/reset} + +

{intl Featured Products}

+ +{loop obj[featured_items]} +
+

{loop/name}

+

{loop/name}

+

{loop/description}

+

+ + + + + +
+ ${loop/price} + {if loop.weight gt 0}
{filter siteshop_filter_weight}{loop/weight}{end filter}!{end if} +
+ {if appconf ('product_ratings')} +
+ + {end if} +
+

+

+ + {intl More Info} +

+
+{end loop} diff --git a/inc/app/siteshop/html/lightbox.css b/inc/app/siteshop/html/lightbox.css new file mode 100755 index 00000000..e981db42 --- /dev/null +++ b/inc/app/siteshop/html/lightbox.css @@ -0,0 +1,135 @@ +#lightbox{ + position: absolute; + top: 20px; + left: 0; + width: 100%; + z-index: 100; + text-align: center; + line-height: 0; + color:#151410; + } + +#lightbox a, #lightbox a:hover { + border-bottom:none; + color:#151410; + text-decoration:underline; +} + +#lightbox a img{ border: none; } + +#outerImageContainer{ + position: relative; + background-color: #fff; + width: 250px; + height: 250px; + margin: 0 auto; + } + +#imageContainer{ + padding: 10px; + } + +#loading{ + position: absolute; + top: 40%; + left: 0%; + height: 25%; + width: 100%; + text-align: center; + line-height: 0; + } +#loadingLink { + display:block; + margin:0 auto; + padding:0; + width:32px; + height:32px; + background:url("../pix/loading.gif") center center no-repeat; + text-indent:-9999px; +} +#hoverNav{ + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 10; + } +#imageContainer>#hoverNav{ left: 0;} +#hoverNav a{ outline: none;} + +#prevLinkImg, #nextLinkImg{ + width: 49%; + height: 100%; + background: transparent url("../pix/blank.gif") no-repeat; /* Trick IE into showing hover */ + display: block; + text-indent:-9999px; + } +#prevLinkImg { left: 0; float: left;} +#nextLinkImg { right: 0; float: right;} +#prevLinkImg:hover, #prevLinkImg:visited:hover { background: url("../pix/prevlabel.gif") left 15% no-repeat; } +#nextLinkImg:hover, #nextLinkImg:visited:hover { background: url("../pix/nextlabel.gif") right 15% no-repeat; } + + +#imageDataContainer{ + font: 10px Verdana, Helvetica, sans-serif; + background-color: #fff; + margin: 0 auto; + line-height: 1.4em; + } + +#imageData{ + padding:0 10px; + } +#imageDetails{ width: 70%; float: left; text-align: left; } +#caption{ font-weight: bold; } +#numberDisplay{ display: block; clear: left; } +#detailsNav{ display: block; clear: left; padding:0 0 10px 0; } +#prevLinkDetails { margin:0 8px 0 0; } +#nextLinkDetails { margin:0 8px 0 0; } +#closeLink { + display:block; + margin:0; + padding:0 0 10px 0; + text-decoration:none; + float:right; + width:66px; + height:28px; + background:url("../pix/closelabel.gif") no-repeat; + text-indent:-9999px; + overflow:hidden; +} + +#overlay{ + position: absolute; + top: 0; + left: 0; + z-index: 90; + width: 100%; + height: 500px; + background-color: #151410; + filter:alpha(opacity=60); + -moz-opacity: 0.6; + opacity: 0.6; + } + + +.clearfix:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; + } + +* html>body .clearfix { + display: inline-block; + width: 100%; + } + +* html .clearfix { + /* Hides from IE-mac \*/ + height: 1%; + /* End hide from IE-mac */ + } + \ No newline at end of file diff --git a/inc/app/siteshop/html/order_notice_email.spt b/inc/app/siteshop/html/order_notice_email.spt new file mode 100644 index 00000000..1c85f7e5 --- /dev/null +++ b/inc/app/siteshop/html/order_notice_email.spt @@ -0,0 +1,12 @@ +An order has been submitted at {site/domain}. + +Order summary: + +{loop obj[cart]} +{php str_pad (loop.sku, 11)}{php str_pad (substr (loop.name, 0, 45), 50)}{php str_pad (substr (loop.options_str, 0, 30), 35)}{php str_pad (loop.qty, 3)} {loop/price} +{end loop} + +Subtotal ${subtotal} +Shipping ${shipping} +Tax ${taxes} +Total ${total} diff --git a/inc/app/siteshop/html/order_receipt_email.spt b/inc/app/siteshop/html/order_receipt_email.spt new file mode 100644 index 00000000..8ab199e1 --- /dev/null +++ b/inc/app/siteshop/html/order_receipt_email.spt @@ -0,0 +1,21 @@ +Your order #{id} has been submitted and is being processed. Here is a summary +of your order: + +{loop obj[cart]} +{php str_pad (loop.sku, 11)}{php str_pad (substr (loop.name, 0, 55), 50)}{php str_pad (substr (loop.options_str, 0, 30), 35)}{php str_pad (loop.qty, 3)}{loop/price} +{end loop} + +Subtotal ${subtotal} +Shipping ${shipping} +Tax ${taxes}{if not empty obj[promo_code]} +Promo ${promo_discount}{end if} +Total ${total} + +This order will ship to the following address: + +{ship_to} +{ship_address}{if not empty (obj[ship_address2])} +{ship_address2}{end if} +{ship_city}, {filter strtoupper}{ship_state}{end filter} +{filter siteshop_filter_country}{ship_country}{end filter} +{ship_zip} diff --git a/inc/app/siteshop/html/product.spt b/inc/app/siteshop/html/product.spt new file mode 100644 index 00000000..afeef722 --- /dev/null +++ b/inc/app/siteshop/html/product.spt @@ -0,0 +1,60 @@ +
+ + +{loop Product::getImages (obj.id)} + +{end loop} +
+ +{if obj.sale} +

+ + + + + +
+ {intl On Sale}: {intl Only} ${sale_price}!
+ ({intl Reg.} ${price}) +
+ {if appconf ('product_ratings')} +
+ + {end if} +
+

+{end if} +{if else} +

+ + + + + +
+ {intl Price}: ${price} + {if obj.weight gt 0} {filter siteshop_filter_weight}{weight}{end filter}!{end if} + + {if appconf ('product_ratings')} +
+ + {end if} +
+

+{end if} + +

+ {intl Availability}: {filter siteshop_filter_availability}{availability}{end filter} +

+ +{filter none}{addtocartform}{end filter} + +

{intl Details}

+ +
{filter none}{body}{end filter}
+ +{if appconf ('product_comments')} +

{intl Comments}

+
+ +{end if} diff --git a/inc/app/siteshop/html/sale.spt b/inc/app/siteshop/html/sale.spt new file mode 100644 index 00000000..602f6537 --- /dev/null +++ b/inc/app/siteshop/html/sale.spt @@ -0,0 +1,31 @@ +{alt 1 2 3} + +

{intl From} {filter siteshop_filter_date}{start}{end filter} {intl until} {filter siteshop_filter_date}{until}{end filter}

+ +{loop obj[list]} +
+

{loop/name}

+

{loop/name}

+

{loop/description}

+

+ + + + + +
+ {intl ONLY} ${loop/sale_price}!
+ ({intl REG.} ${loop/price}) +
+ {if appconf ('product_ratings')} +
+ + {end if} +
+

+

+ {intl Add to Cart} | + {intl More Info} +

+
+{end loop} diff --git a/inc/app/siteshop/html/style.css b/inc/app/siteshop/html/style.css new file mode 100644 index 00000000..b5aadbae --- /dev/null +++ b/inc/app/siteshop/html/style.css @@ -0,0 +1,96 @@ +div.siteshop-product-listing { + width: 150px; + margin-right: 20px; + margin-bottom: 10px; + float: left; +} + +div.siteshop-product-listing img { + width: 125px; + height: 87px; +} + +div.siteshop-checkout-product img { + width: 125px; + height: 87px; + margin-right: 15px; +} + +div.siteshop-product-matrix-1 { + /* this causes the product category screen to display properly */ + clear: both; +} + +div.siteshop-product-matrix-3 { + /* this causes the product category screen to display properly */ + margin-right: 0px !important; +} + +.siteshop-product-price { + font-weight: bold; +} + +p.siteshop-product-availability { + color: #666; +} + +p.siteshop-product-add-to-cart { + margin: 20px 0px 20px 0px; +} + +p.siteshop-product-add-to-cart a { + font-weight: bold; + font-size: 13px; + background: #eee; + border: 1px solid #666; + border-left: 1px solid #999; + border-top: 1px solid #999; + padding: 7px 7px 5px 7px; +} + +p.siteshop-product-add-to-cart a:hover { + text-decoration: none; +} + +span.siteshop-weight { + font-size: 9px; + font-weight: bold; + color: #900; + text-transform: uppercase; +} + +span.siteshop-reg { + font-size: 9px; + font-weight: bold; + color: #666; + text-transform: uppercase; +} + +p.siteshop-notice { + font-weight: bold; + color: #900; +} + +div.siteshop-sale-area { + /* style sales block here */ +} + +div.siteshop-sale-area h2 { + color: #900; +} + +div.siteshop-product-weight-1 { + /* style special products here */ +} + +div.siteshop-product-weight-2 { + /* style on sale products here */ +} + +div.siteshop-product-weight-3 { + /* style hot seller products here */ +} + +div.siteshop-product-weight-4 { + /* style featured products here */ +} diff --git a/inc/app/siteshop/install/INSTALL b/inc/app/siteshop/install/INSTALL new file mode 100644 index 00000000..83e53c83 --- /dev/null +++ b/inc/app/siteshop/install/INSTALL @@ -0,0 +1 @@ +Your installation instructions go here diff --git a/inc/app/siteshop/install/changes.txt b/inc/app/siteshop/install/changes.txt new file mode 100644 index 00000000..00f35c63 --- /dev/null +++ b/inc/app/siteshop/install/changes.txt @@ -0,0 +1,8 @@ +New in 2.0.1: + +- Added customer registration/accounts +- Added product options (colours, sizes) +- Added more template settings +- Added customizable category screens +- Begun adding multilingual support +- Added lightbox effect instead of product image popups diff --git a/inc/app/siteshop/install/install-mysql.sql b/inc/app/siteshop/install/install-mysql.sql new file mode 100644 index 00000000..0e463d8e --- /dev/null +++ b/inc/app/siteshop/install/install-mysql.sql @@ -0,0 +1,493 @@ +create table siteshop_product ( + id int not null auto_increment primary key, + sku char(24) not null, + name char(72) not null, + price decimal(9,2) not null, + body text not null, + shipping decimal(9,2) not null, + availability int not null default 1, + quantity int not null default -1, + weight int not null, + taxable enum('yes','no') not null default 'yes', + keywords text not null, + description text not null, + sitellite_status varchar(48) NOT NULL default '', + sitellite_access varchar(48) NOT NULL default '', + sitellite_startdate datetime default NULL, + sitellite_expirydate datetime default NULL, + sitellite_owner varchar(48) NOT NULL default '', + sitellite_team varchar(48) NOT NULL default '', + index (name, weight, price, availability, sitellite_status, sitellite_access) +); + +create table siteshop_category ( + id int not null auto_increment primary key, + name char(72) not null, + weight tinyint not null default 0, + index (name, weight) +); + +# product-category join table +create table siteshop_product_category ( + product_id int not null, + category_id int not null, + primary key (product_id, category_id) +); + +create table siteshop_option_type ( + id int unsigned not null auto_increment primary key, + name varchar(72) not null unique, + index (name) +); + +create table siteshop_option ( + id int unsigned not null auto_increment primary key, + name varchar(72) not null, + type varchar(72) not null, -- e.g., colour, size, etc. + value varchar(72) not null, + weight int not null default 1, + unique (name, type), + index (name, type) +); + +create table siteshop_product_option ( + id int unsigned not null unique auto_increment, #for generic + option_id int unsigned not null, + product_id int not null, + available enum('yes','no') not null default 'yes', + primary key (option_id, product_id), + index (available) +); + +create table siteshop_order ( + id int not null auto_increment primary key, + user_id char(72) not null, + status enum('new','partly-shipped','shipped','cancelled') not null default 'new', + tracking char(128) not null, + ts datetime not null, + ship_to char(72) not null, + ship_address char(72) not null, + ship_address2 char(72) not null, + ship_city char(72) not null, + ship_state char(2) not null, + ship_country char(2) not null, + ship_zip char(15) not null, + bill_to char(72) not null, + bill_address char(72) not null, + bill_address2 char(72) not null, + bill_city char(72) not null, + bill_state char(2) not null, + bill_country char(2) not null, + bill_zip char(15) not null, + phone char(24) not null, + email char(72) not null, + subtotal decimal(9,2) not null, + shipping decimal(9,2) not null, + taxes decimal(9,2) not null, + promo_code char(16) not null, + promo_discount decimal(9,2) not null, + total decimal(9,2) not null, + index (ts, status, user_id) +); + +#alter table siteshop_order add column promo_code char(16) not null; +#alter table siteshop_order add column promo_discount decimal(9,2) not null; + +# order-product join table +create table siteshop_order_product ( + order_id int not null, + product_id int not null, + product_sku char(24) not null, + product_name char(72) not null, + product_options blob not null, + price decimal(9,2) not null, + shipping decimal(9,2) not null, + quantity int not null, + primary key (order_id, product_id) +); + +create table siteshop_order_status ( + order_id int not null, + ts datetime not null, + status enum('new','partly-shipped','shipped','cancelled') not null default 'new', + index (order_id, ts) +); + +create table siteshop_wishlist ( + id int not null auto_increment primary key, + user_id char(72) not null, + index (user_id) +); + +# wishlist-product join table +create table siteshop_wishlist_product ( + wishlist_id int not null, + product_id int not null, + primary key (wishlist_id, product_id) +); + +create table siteshop_sale ( + id int not null auto_increment primary key, + name char(78) not null, + start_date datetime not null, + until_date datetime not null, + index (start_date, until_date) +); + +# sale-product join table +create table siteshop_sale_product ( + sale_id int not null, + product_id int not null, + sale_price decimal(9,2) not null, + primary key (sale_id, product_id, sale_price) +); + +create table siteshop_tax ( + id int not null auto_increment primary key, + name char(72) not null, + rate decimal(2,2) default '0.0', + province char(2), + country char(2), + unique (province, country) +); + +create table siteshop_checkout_offer ( + id int not null auto_increment primary key, + offer_text char(128) not null, + offer_number int not null, + product_id int not null, + sale_price decimal(9,2) not null, + index (offer_number) +); + +create table siteshop_promo_code ( + id int not null auto_increment primary key, + code char(16) not null, + discount_type enum('percent','dollars') not null, + discount decimal(9,2) not null, + expires date not null, + unique (code), + index (expires) +); + +create table siteshop_country ( + code char(2) not null, + country char(72) not null, + active enum('yes','no') not null default 'yes', + primary key (code), + index (country) +); + +INSERT INTO siteshop_country (code, country, active) VALUES ('af', 'Afghanistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('al', 'Albania', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dz', 'Algeria', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('as', 'American Samoa', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ad', 'Andorra', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ao', 'Angola', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ai', 'Anguilla', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('aq', 'Antarctica', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ag', 'Antigua and Barbuda', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ar', 'Argentina', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('am', 'Armenia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('aw', 'Aruba', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('au', 'Australia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('at', 'Austria', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('az', 'Azerbaijan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bs', 'Bahamas', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bh', 'Bahrain', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bd', 'Bangladesh', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bb', 'Barbados', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('by', 'Belarus', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('be', 'Belgium', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bz', 'Belize', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bj', 'Benin', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bm', 'Bermuda', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bt', 'Bhutan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bo', 'Bolivia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ba', 'Bosnia and Herzegovina', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bw', 'Botswana', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bv', 'Bouvet Island', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('br', 'Brazil', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('io', 'British Indian Ocean Territory', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bn', 'Brunei Darussalam', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bg', 'Bulgaria', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bf', 'Burkina Faso', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bi', 'Burundi', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kh', 'Cambodia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cm', 'Cameroon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ca', 'Canada', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cv', 'Cape Verde', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ky', 'Cayman Islands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cf', 'Central African Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('td', 'Chad', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cl', 'Chile', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cn', 'China', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cx', 'Christmas Island', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cc', 'Cocos (keeling) Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('co', 'Colombia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('km', 'Comoros', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cg', 'Congo', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cd', 'Congo, The Democratic Republic of the', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ck', 'Cook Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cr', 'Costa Rica', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ci', 'Cote D\'ivoire', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hr', 'Croatia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cu', 'Cuba', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cy', 'Cyprus', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cz', 'Czech Republic', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dk', 'Denmark', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dj', 'Djibouti', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dm', 'Dominica', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('do', 'Dominican Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ec', 'Ecuador', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('eg', 'Egypt', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sv', 'El Salvador', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gq', 'Equatorial Guinea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('er', 'Eritrea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ee', 'Estonia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('et', 'Ethiopia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fk', 'Falkland Islands (malvinas)', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fo', 'Faroe Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fj', 'Fiji', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fi', 'Finland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fr', 'France', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gf', 'French Guiana', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pf', 'French Polynesia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tf', 'French Southern Territories', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ga', 'Gabon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gm', 'Gambia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ge', 'Georgia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('de', 'Germany', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gh', 'Ghana', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gi', 'Gibraltar', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gr', 'Greece', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gl', 'Greenland', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gd', 'Grenada', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gp', 'Guadeloupe', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gu', 'Guam', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gt', 'Guatemala', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gn', 'Guinea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gw', 'Guinea-bissau', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gy', 'Guyana', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ht', 'Haiti', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hm', 'Heard Island and Mcdonald Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('va', 'Holy See (Vatican City State)', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hn', 'Honduras', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hk', 'Hong Kong', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hu', 'Hungary', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('is', 'Iceland', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('in', 'India', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('id', 'Indonesia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ir', 'Iran, Islamic Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('iq', 'Iraq', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ie', 'Ireland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('il', 'Israel', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('it', 'Italy', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('jm', 'Jamaica', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('jp', 'Japan', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('jo', 'Jordan', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kz', 'Kazakhstan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ke', 'Kenya', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ki', 'Kiribati', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kp', 'Korea, Democratic People\'s Republic of', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kr', 'Korea, Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kw', 'Kuwait', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kg', 'Kyrgyzstan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('la', 'Lao People\'s Democratic Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lv', 'Latvia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lb', 'Lebanon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ls', 'Lesotho', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lr', 'Liberia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ly', 'Libyan Arab Jamahiriya', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('li', 'Liechtenstein', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lt', 'Lithuania', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lu', 'Luxembourg', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mo', 'Macao', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mk', 'Macedonia, The Former Yugoslav Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mg', 'Madagascar', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mw', 'Malawi', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('my', 'Malaysia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mv', 'Maldives', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ml', 'Mali', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mt', 'Malta', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mh', 'Marshall Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mq', 'Martinique', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mr', 'Mauritania', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mu', 'Mauritius', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('yt', 'Mayotte', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mx', 'Mexico', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fm', 'Micronesia, Federated States of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('md', 'Moldova, Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mc', 'Monaco', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mn', 'Mongolia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ms', 'Montserrat', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ma', 'Morocco', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mz', 'Mozambique', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mm', 'Myanmar', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('na', 'Namibia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nr', 'Nauru', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('np', 'Nepal', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nl', 'Netherlands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('an', 'Netherlands Antilles', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nc', 'New Caledonia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nz', 'New Zealand', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ni', 'Nicaragua', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ne', 'Niger', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ng', 'Nigeria', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nu', 'Niue', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nf', 'Norfolk Island', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mp', 'Northern Mariana Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('no', 'Norway', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('om', 'Oman', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pk', 'Pakistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pw', 'Palau', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ps', 'Palestinian Territory, Occupied', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pa', 'Panama', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pg', 'Papua New Guinea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('py', 'Paraguay', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pe', 'Peru', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ph', 'Philippines', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pn', 'Pitcairn', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pl', 'Poland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pt', 'Portugal', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pr', 'Puerto Rico', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('qa', 'Qatar', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('re', 'Reunion', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ro', 'Romania', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ru', 'Russia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('rw', 'Rwanda', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sh', 'Saint Helena', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kn', 'Saint Kitts and Nevis', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lc', 'Saint Lucia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pm', 'Saint Pierre and Miquelon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vc', 'Saint Vincent and the Grenadines', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ws', 'Samoa', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sm', 'San Marino', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('st', 'Sao Tome and Principe', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sa', 'Saudi Arabia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sn', 'Senegal', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cs', 'Serbia and Montenegro', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sc', 'Seychelles', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sl', 'Sierra Leone', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sg', 'Singapore', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sk', 'Slovakia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('si', 'Slovenia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sb', 'Solomon Islands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('so', 'Somalia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('za', 'South Africa', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gs', 'South Georgia and the South Sandwich Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('es', 'Spain', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lk', 'Sri Lanka', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sd', 'Sudan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sr', 'Suriname', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sj', 'Svalbard and Jan Mayen', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sz', 'Swaziland', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('se', 'Sweden', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ch', 'Switzerland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sy', 'Syrian Arab Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tw', 'Taiwan', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tj', 'Tajikistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tz', 'Tanzania, United Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('th', 'Thailand', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tl', 'Timor-leste', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tg', 'Togo', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tk', 'Tokelau', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('to', 'Tonga', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tt', 'Trinidad and Tobago', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tn', 'Tunisia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tr', 'Turkey', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tm', 'Turkmenistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tc', 'Turks and Caicos Islands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tv', 'Tuvalu', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ug', 'Uganda', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ua', 'Ukraine', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ae', 'United Arab Emirates', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gb', 'United Kingdom', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('us', 'United States', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('um', 'United States Minor Outlying Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('uy', 'Uruguay', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('uz', 'Uzbekistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vu', 'Vanuatu', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ve', 'Venezuela', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vn', 'Vietnam', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vg', 'Virgin Islands, British', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vi', 'Virgin Islands, U.S.', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('wf', 'Wallis and Futuna', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('eh', 'Western Sahara', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ye', 'Yemen', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('zm', 'Zambia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('zw', 'Zimbabwe', 'no'); + +create table siteshop_province ( + code char(2) not null, + country_code char(2) not null, + province char(72) not null, + active enum('yes','no') not null default 'yes', + primary key (code, country_code), + index (province) +); + +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ab', 'ca', 'Alberta'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('bc', 'ca', 'British Columbia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mb', 'ca', 'Manitoba'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nb', 'ca', 'New Brunswick'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nl', 'ca', 'Newfoundland and Labrador'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ns', 'ca', 'Nova Scotia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nt', 'ca', 'Northwest Territories'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nu', 'ca', 'Nunavut'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('on', 'ca', 'Ontario'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('pe', 'ca', 'Prince Edward Island'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('qc', 'ca', 'Quebec'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('sk', 'ca', 'Saskatchewan'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('yt', 'ca', 'Yukon'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('al', 'us', 'Alabama'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ak', 'us', 'Alaska'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('az', 'us', 'Arizona'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ar', 'us', 'Arkansas'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ca', 'us', 'California'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('co', 'us', 'Colorado'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ct', 'us', 'Connecticut'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('dc', 'us', 'District of Columbia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('de', 'us', 'Delaware'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('fl', 'us', 'Florida'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ga', 'us', 'Georgia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('hi', 'us', 'Hawaii'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('id', 'us', 'Idaho'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('il', 'us', 'Illinois'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('in', 'us', 'Indiana'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ia', 'us', 'Iowa'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ks', 'us', 'Kansas'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ky', 'us', 'Kentucky'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('la', 'us', 'Louisiana'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('me', 'us', 'Maine'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('md', 'us', 'Maryland'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ma', 'us', 'Massachusetts'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mi', 'us', 'Michigan'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mn', 'us', 'Minnesota'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ms', 'us', 'Mississippi'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mo', 'us', 'Missouri'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mt', 'us', 'Montana'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ne', 'us', 'Nebraska'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nv', 'us', 'Nevada'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nh', 'us', 'New Hampshire'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nj', 'us', 'New Jersey'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nm', 'us', 'New Mexico'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ny', 'us', 'New York'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nc', 'us', 'North Carolina'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nd', 'us', 'North Dakota'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('oh', 'us', 'Ohio'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ok', 'us', 'Oklahoma'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('or', 'us', 'Oregon'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('pa', 'us', 'Pennsylvania'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ri', 'us', 'Rhode Island'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('sc', 'us', 'South Carolina'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('sd', 'us', 'South Dakota'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('tn', 'us', 'Tennessee'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('tx', 'us', 'Texas'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ut', 'us', 'Utah'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('vt', 'us', 'Vermont'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('va', 'us', 'Virginia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wa', 'us', 'Washington'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wv', 'us', 'West Virginia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wi', 'us', 'Wisconsin'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wy', 'us', 'Wyoming'); diff --git a/inc/app/siteshop/install/siteshop_product.php b/inc/app/siteshop/install/siteshop_product.php new file mode 100644 index 00000000..d9561c81 --- /dev/null +++ b/inc/app/siteshop/install/siteshop_product.php @@ -0,0 +1,81 @@ +; \ No newline at end of file diff --git a/inc/app/siteshop/install/upgrade-2.0.0-2.0.1.sql b/inc/app/siteshop/install/upgrade-2.0.0-2.0.1.sql new file mode 100644 index 00000000..45a6ac26 --- /dev/null +++ b/inc/app/siteshop/install/upgrade-2.0.0-2.0.1.sql @@ -0,0 +1,27 @@ +create table siteshop_option_type ( + id int unsigned not null auto_increment primary key, + name varchar(72) not null unique, + index (name) +); + +create table siteshop_product_option ( + id int unsigned not null unique auto_increment, #for generic + option_id int unsigned not null, + product_id int not null, + available enum('yes','no') not null default 'yes', + primary key (option_id, product_id), + index (available) +); + +drop table siteshop_option; +create table siteshop_option ( + id int unsigned not null auto_increment primary key, + name varchar(72) not null, + type varchar(72) not null, -- e.g., colour, size, etc. + value varchar(72) not null, + weight int not null default 1, + unique (name, type), + index (name, type) +); + +alter table siteshop_order_product add column product_options blob not null; diff --git a/inc/app/siteshop/install/upgrade-2.0.1-2.0.2.sql b/inc/app/siteshop/install/upgrade-2.0.1-2.0.2.sql new file mode 100644 index 00000000..75f508da --- /dev/null +++ b/inc/app/siteshop/install/upgrade-2.0.1-2.0.2.sql @@ -0,0 +1 @@ +alter table siteshop_category add column weight tinyint not null default 0; diff --git a/inc/app/siteshop/js/effects.js b/inc/app/siteshop/js/effects.js new file mode 100755 index 00000000..70d07526 --- /dev/null +++ b/inc/app/siteshop/js/effects.js @@ -0,0 +1,1094 @@ +// script.aculo.us effects.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007 + +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Contributors: +// Justin Palmer (http://encytemedia.com/) +// Mark Pilgrim (http://diveintomark.org/) +// Martin Bialasinki +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// converts rgb() and #xxx to #xxxxxx format, +// returns self (or first argument) if not convertable +String.prototype.parseColor = function() { + var color = '#'; + if(this.slice(0,4) == 'rgb(') { + var cols = this.slice(4,this.length-1).split(','); + var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); + } else { + if(this.slice(0,1) == '#') { + if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); + if(this.length==7) color = this.toLowerCase(); + } + } + return(color.length==7 ? color : (arguments[0] || this)); +} + +/*--------------------------------------------------------------------------*/ + +Element.collectTextNodes = function(element) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); + }).flatten().join(''); +} + +Element.collectTextNodesIgnoreClass = function(element, className) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? + Element.collectTextNodesIgnoreClass(node, className) : '')); + }).flatten().join(''); +} + +Element.setContentZoom = function(element, percent) { + element = $(element); + element.setStyle({fontSize: (percent/100) + 'em'}); + if(Prototype.Browser.WebKit) window.scrollBy(0,0); + return element; +} + +Element.getInlineOpacity = function(element){ + return $(element).style.opacity || ''; +} + +Element.forceRerendering = function(element) { + try { + element = $(element); + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch(e) { } +}; + +/*--------------------------------------------------------------------------*/ + +Array.prototype.call = function() { + var args = arguments; + this.each(function(f){ f.apply(this, args) }); +} + +/*--------------------------------------------------------------------------*/ + +var Effect = { + _elementDoesNotExistError: { + name: 'ElementDoesNotExistError', + message: 'The specified DOM element does not exist, but is required for this effect to operate' + }, + tagifyText: function(element) { + if(typeof Builder == 'undefined') + throw("Effect.tagifyText requires including script.aculo.us' builder.js library"); + + var tagifyStyle = 'position:relative'; + if(Prototype.Browser.IE) tagifyStyle += ';zoom:1'; + + element = $(element); + $A(element.childNodes).each( function(child) { + if(child.nodeType==3) { + child.nodeValue.toArray().each( function(character) { + element.insertBefore( + Builder.node('span',{style: tagifyStyle}, + character == ' ' ? String.fromCharCode(160) : character), + child); + }); + Element.remove(child); + } + }); + }, + multiple: function(element, effect) { + var elements; + if(((typeof element == 'object') || + (typeof element == 'function')) && + (element.length)) + elements = element; + else + elements = $(element).childNodes; + + var options = Object.extend({ + speed: 0.1, + delay: 0.0 + }, arguments[2] || {}); + var masterDelay = options.delay; + + $A(elements).each( function(element, index) { + new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); + }); + }, + PAIRS: { + 'slide': ['SlideDown','SlideUp'], + 'blind': ['BlindDown','BlindUp'], + 'appear': ['Appear','Fade'] + }, + toggle: function(element, effect) { + element = $(element); + effect = (effect || 'appear').toLowerCase(); + var options = Object.extend({ + queue: { position:'end', scope:(element.id || 'global'), limit: 1 } + }, arguments[2] || {}); + Effect[element.visible() ? + Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + } +}; + +var Effect2 = Effect; // deprecated + +/* ------------- transitions ------------- */ + +Effect.Transitions = { + linear: Prototype.K, + sinoidal: function(pos) { + return (-Math.cos(pos*Math.PI)/2) + 0.5; + }, + reverse: function(pos) { + return 1-pos; + }, + flicker: function(pos) { + var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; + return (pos > 1 ? 1 : pos); + }, + wobble: function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; + }, + pulse: function(pos, pulses) { + pulses = pulses || 5; + return ( + Math.round((pos % (1/pulses)) * pulses) == 0 ? + ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) : + 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) + ); + }, + none: function(pos) { + return 0; + }, + full: function(pos) { + return 1; + } +}; + +/* ------------- core effects ------------- */ + +Effect.ScopedQueue = Class.create(); +Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { + initialize: function() { + this.effects = []; + this.interval = null; + }, + _each: function(iterator) { + this.effects._each(iterator); + }, + add: function(effect) { + var timestamp = new Date().getTime(); + + var position = (typeof effect.options.queue == 'string') ? + effect.options.queue : effect.options.queue.position; + + switch(position) { + case 'front': + // move unstarted effects after this effect + this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { + e.startOn += effect.finishOn; + e.finishOn += effect.finishOn; + }); + break; + case 'with-last': + timestamp = this.effects.pluck('startOn').max() || timestamp; + break; + case 'end': + // start effect after last queued effect has finished + timestamp = this.effects.pluck('finishOn').max() || timestamp; + break; + } + + effect.startOn += timestamp; + effect.finishOn += timestamp; + + if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) + this.effects.push(effect); + + if(!this.interval) + this.interval = setInterval(this.loop.bind(this), 15); + }, + remove: function(effect) { + this.effects = this.effects.reject(function(e) { return e==effect }); + if(this.effects.length == 0) { + clearInterval(this.interval); + this.interval = null; + } + }, + loop: function() { + var timePos = new Date().getTime(); + for(var i=0, len=this.effects.length;i= this.startOn) { + if(timePos >= this.finishOn) { + this.render(1.0); + this.cancel(); + this.event('beforeFinish'); + if(this.finish) this.finish(); + this.event('afterFinish'); + return; + } + var pos = (timePos - this.startOn) / this.totalTime, + frame = Math.round(pos * this.totalFrames); + if(frame > this.currentFrame) { + this.render(pos); + this.currentFrame = frame; + } + } + }, + cancel: function() { + if(!this.options.sync) + Effect.Queues.get(typeof this.options.queue == 'string' ? + 'global' : this.options.queue.scope).remove(this); + this.state = 'finished'; + }, + event: function(eventName) { + if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); + if(this.options[eventName]) this.options[eventName](this); + }, + inspect: function() { + var data = $H(); + for(property in this) + if(typeof this[property] != 'function') data[property] = this[property]; + return '#'; + } +} + +Effect.Parallel = Class.create(); +Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), { + initialize: function(effects) { + this.effects = effects || []; + this.start(arguments[1]); + }, + update: function(position) { + this.effects.invoke('render', position); + }, + finish: function(position) { + this.effects.each( function(effect) { + effect.render(1.0); + effect.cancel(); + effect.event('beforeFinish'); + if(effect.finish) effect.finish(position); + effect.event('afterFinish'); + }); + } +}); + +Effect.Event = Class.create(); +Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), { + initialize: function() { + var options = Object.extend({ + duration: 0 + }, arguments[0] || {}); + this.start(options); + }, + update: Prototype.emptyFunction +}); + +Effect.Opacity = Class.create(); +Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); + // make this work on IE on elements without 'layout' + if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + var options = Object.extend({ + from: this.element.getOpacity() || 0.0, + to: 1.0 + }, arguments[1] || {}); + this.start(options); + }, + update: function(position) { + this.element.setOpacity(position); + } +}); + +Effect.Move = Class.create(); +Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + x: 0, + y: 0, + mode: 'relative' + }, arguments[1] || {}); + this.start(options); + }, + setup: function() { + // Bug in Opera: Opera returns the "real" position of a static element or + // relative element that does not have top/left explicitly set. + // ==> Always set top and left for position relative elements in your stylesheets + // (to 0 if you do not need them) + this.element.makePositioned(); + this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); + this.originalTop = parseFloat(this.element.getStyle('top') || '0'); + if(this.options.mode == 'absolute') { + // absolute movement, so we need to calc deltaX and deltaY + this.options.x = this.options.x - this.originalLeft; + this.options.y = this.options.y - this.originalTop; + } + }, + update: function(position) { + this.element.setStyle({ + left: Math.round(this.options.x * position + this.originalLeft) + 'px', + top: Math.round(this.options.y * position + this.originalTop) + 'px' + }); + } +}); + +// for backwards compatibility +Effect.MoveBy = function(element, toTop, toLeft) { + return new Effect.Move(element, + Object.extend({ x: toLeft, y: toTop }, arguments[3] || {})); +}; + +Effect.Scale = Class.create(); +Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), { + initialize: function(element, percent) { + this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + scaleX: true, + scaleY: true, + scaleContent: true, + scaleFromCenter: false, + scaleMode: 'box', // 'box' or 'contents' or {} with provided values + scaleFrom: 100.0, + scaleTo: percent + }, arguments[2] || {}); + this.start(options); + }, + setup: function() { + this.restoreAfterFinish = this.options.restoreAfterFinish || false; + this.elementPositioning = this.element.getStyle('position'); + + this.originalStyle = {}; + ['top','left','width','height','fontSize'].each( function(k) { + this.originalStyle[k] = this.element.style[k]; + }.bind(this)); + + this.originalTop = this.element.offsetTop; + this.originalLeft = this.element.offsetLeft; + + var fontSize = this.element.getStyle('font-size') || '100%'; + ['em','px','%','pt'].each( function(fontSizeType) { + if(fontSize.indexOf(fontSizeType)>0) { + this.fontSize = parseFloat(fontSize); + this.fontSizeType = fontSizeType; + } + }.bind(this)); + + this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; + + this.dims = null; + if(this.options.scaleMode=='box') + this.dims = [this.element.offsetHeight, this.element.offsetWidth]; + if(/^content/.test(this.options.scaleMode)) + this.dims = [this.element.scrollHeight, this.element.scrollWidth]; + if(!this.dims) + this.dims = [this.options.scaleMode.originalHeight, + this.options.scaleMode.originalWidth]; + }, + update: function(position) { + var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); + if(this.options.scaleContent && this.fontSize) + this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); + this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); + }, + finish: function(position) { + if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + }, + setDimensions: function(height, width) { + var d = {}; + if(this.options.scaleX) d.width = Math.round(width) + 'px'; + if(this.options.scaleY) d.height = Math.round(height) + 'px'; + if(this.options.scaleFromCenter) { + var topd = (height - this.dims[0])/2; + var leftd = (width - this.dims[1])/2; + if(this.elementPositioning == 'absolute') { + if(this.options.scaleY) d.top = this.originalTop-topd + 'px'; + if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; + } else { + if(this.options.scaleY) d.top = -topd + 'px'; + if(this.options.scaleX) d.left = -leftd + 'px'; + } + } + this.element.setStyle(d); + } +}); + +Effect.Highlight = Class.create(); +Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {}); + this.start(options); + }, + setup: function() { + // Prevent executing on elements not in the layout flow + if(this.element.getStyle('display')=='none') { this.cancel(); return; } + // Disable background image during the effect + this.oldStyle = {}; + if (!this.options.keepBackgroundImage) { + this.oldStyle.backgroundImage = this.element.getStyle('background-image'); + this.element.setStyle({backgroundImage: 'none'}); + } + if(!this.options.endcolor) + this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); + if(!this.options.restorecolor) + this.options.restorecolor = this.element.getStyle('background-color'); + // init color calculations + this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); + this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); + }, + update: function(position) { + this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ + return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) }); + }, + finish: function() { + this.element.setStyle(Object.extend(this.oldStyle, { + backgroundColor: this.options.restorecolor + })); + } +}); + +Effect.ScrollTo = Class.create(); +Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + this.start(arguments[1] || {}); + }, + setup: function() { + Position.prepare(); + var offsets = Position.cumulativeOffset(this.element); + if(this.options.offset) offsets[1] += this.options.offset; + var max = window.innerHeight ? + window.height - window.innerHeight : + document.body.scrollHeight - + (document.documentElement.clientHeight ? + document.documentElement.clientHeight : document.body.clientHeight); + this.scrollStart = Position.deltaY; + this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart; + }, + update: function(position) { + Position.prepare(); + window.scrollTo(Position.deltaX, + this.scrollStart + (position*this.delta)); + } +}); + +/* ------------- combination effects ------------- */ + +Effect.Fade = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + var options = Object.extend({ + from: element.getOpacity() || 1.0, + to: 0.0, + afterFinishInternal: function(effect) { + if(effect.options.to!=0) return; + effect.element.hide().setStyle({opacity: oldOpacity}); + }}, arguments[1] || {}); + return new Effect.Opacity(element,options); +} + +Effect.Appear = function(element) { + element = $(element); + var options = Object.extend({ + from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), + to: 1.0, + // force Safari to render floated elements properly + afterFinishInternal: function(effect) { + effect.element.forceRerendering(); + }, + beforeSetup: function(effect) { + effect.element.setOpacity(effect.options.from).show(); + }}, arguments[1] || {}); + return new Effect.Opacity(element,options); +} + +Effect.Puff = function(element) { + element = $(element); + var oldStyle = { + opacity: element.getInlineOpacity(), + position: element.getStyle('position'), + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height + }; + return new Effect.Parallel( + [ new Effect.Scale(element, 200, + { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], + Object.extend({ duration: 1.0, + beforeSetupInternal: function(effect) { + Position.absolutize(effect.effects[0].element) + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().setStyle(oldStyle); } + }, arguments[1] || {}) + ); +} + +Effect.BlindUp = function(element) { + element = $(element); + element.makeClipping(); + return new Effect.Scale(element, 0, + Object.extend({ scaleContent: false, + scaleX: false, + restoreAfterFinish: true, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }, arguments[1] || {}) + ); +} + +Effect.BlindDown = function(element) { + element = $(element); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || {})); +} + +Effect.SwitchOff = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + return new Effect.Appear(element, Object.extend({ + duration: 0.4, + from: 0, + transition: Effect.Transitions.flicker, + afterFinishInternal: function(effect) { + new Effect.Scale(effect.element, 1, { + duration: 0.3, scaleFromCenter: true, + scaleX: false, scaleContent: false, restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); + } + }) + } + }, arguments[1] || {})); +} + +Effect.DropOut = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left'), + opacity: element.getInlineOpacity() }; + return new Effect.Parallel( + [ new Effect.Move(element, {x: 0, y: 100, sync: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 }) ], + Object.extend( + { duration: 0.5, + beforeSetup: function(effect) { + effect.effects[0].element.makePositioned(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); + } + }, arguments[1] || {})); +} + +Effect.Shake = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left') }; + return new Effect.Move(element, + { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) { + effect.element.undoPositioned().setStyle(oldStyle); + }}) }}) }}) }}) }}) }}); +} + +Effect.SlideDown = function(element) { + element = $(element).cleanWhitespace(); + // SlideDown need to have the content of the element wrapped in a container element with fixed height! + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: window.opera ? 0 : 1, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if(window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || {}) + ); +} + +Effect.SlideUp = function(element) { + element = $(element).cleanWhitespace(); + var oldInnerBottom = element.down().getStyle('bottom'); + return new Effect.Scale(element, window.opera ? 0 : 1, + Object.extend({ scaleContent: false, + scaleX: false, + scaleMode: 'box', + scaleFrom: 100, + restoreAfterFinish: true, + beforeStartInternal: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if(window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom}); + effect.element.down().undoPositioned(); + } + }, arguments[1] || {}) + ); +} + +// Bug in opera makes the TD containing this element expand for a instance after finish +Effect.Squish = function(element) { + return new Effect.Scale(element, window.opera ? 1 : 0, { + restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }); +} + +Effect.Grow = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.full + }, arguments[1] || {}); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var initialMoveX, initialMoveY; + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + initialMoveX = initialMoveY = moveX = moveY = 0; + break; + case 'top-right': + initialMoveX = dims.width; + initialMoveY = moveY = 0; + moveX = -dims.width; + break; + case 'bottom-left': + initialMoveX = moveX = 0; + initialMoveY = dims.height; + moveY = -dims.height; + break; + case 'bottom-right': + initialMoveX = dims.width; + initialMoveY = dims.height; + moveX = -dims.width; + moveY = -dims.height; + break; + case 'center': + initialMoveX = dims.width / 2; + initialMoveY = dims.height / 2; + moveX = -dims.width / 2; + moveY = -dims.height / 2; + break; + } + + return new Effect.Move(element, { + x: initialMoveX, + y: initialMoveY, + duration: 0.01, + beforeSetup: function(effect) { + effect.element.hide().makeClipping().makePositioned(); + }, + afterFinishInternal: function(effect) { + new Effect.Parallel( + [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), + new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), + new Effect.Scale(effect.element, 100, { + scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, + sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) + ], Object.extend({ + beforeSetup: function(effect) { + effect.effects[0].element.setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); + } + }, options) + ) + } + }); +} + +Effect.Shrink = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.none + }, arguments[1] || {}); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + moveX = moveY = 0; + break; + case 'top-right': + moveX = dims.width; + moveY = 0; + break; + case 'bottom-left': + moveX = 0; + moveY = dims.height; + break; + case 'bottom-right': + moveX = dims.width; + moveY = dims.height; + break; + case 'center': + moveX = dims.width / 2; + moveY = dims.height / 2; + break; + } + + return new Effect.Parallel( + [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), + new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), + new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) + ], Object.extend({ + beforeStartInternal: function(effect) { + effect.effects[0].element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } + }, options) + ); +} + +Effect.Pulsate = function(element) { + element = $(element); + var options = arguments[1] || {}; + var oldOpacity = element.getInlineOpacity(); + var transition = options.transition || Effect.Transitions.sinoidal; + var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) }; + reverser.bind(transition); + return new Effect.Opacity(element, + Object.extend(Object.extend({ duration: 2.0, from: 0, + afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } + }, options), {transition: reverser})); +} + +Effect.Fold = function(element) { + element = $(element); + var oldStyle = { + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height }; + element.makeClipping(); + return new Effect.Scale(element, 5, Object.extend({ + scaleContent: false, + scaleX: false, + afterFinishInternal: function(effect) { + new Effect.Scale(element, 1, { + scaleContent: false, + scaleY: false, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().setStyle(oldStyle); + } }); + }}, arguments[1] || {})); +}; + +Effect.Morph = Class.create(); +Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), { + initialize: function(element) { + this.element = $(element); + if(!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + style: {} + }, arguments[1] || {}); + if (typeof options.style == 'string') { + if(options.style.indexOf(':') == -1) { + var cssText = '', selector = '.' + options.style; + $A(document.styleSheets).reverse().each(function(styleSheet) { + if (styleSheet.cssRules) cssRules = styleSheet.cssRules; + else if (styleSheet.rules) cssRules = styleSheet.rules; + $A(cssRules).reverse().each(function(rule) { + if (selector == rule.selectorText) { + cssText = rule.style.cssText; + throw $break; + } + }); + if (cssText) throw $break; + }); + this.style = cssText.parseStyle(); + options.afterFinishInternal = function(effect){ + effect.element.addClassName(effect.options.style); + effect.transforms.each(function(transform) { + if(transform.style != 'opacity') + effect.element.style[transform.style] = ''; + }); + } + } else this.style = options.style.parseStyle(); + } else this.style = $H(options.style) + this.start(options); + }, + setup: function(){ + function parseColor(color){ + if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; + color = color.parseColor(); + return $R(0,2).map(function(i){ + return parseInt( color.slice(i*2+1,i*2+3), 16 ) + }); + } + this.transforms = this.style.map(function(pair){ + var property = pair[0], value = pair[1], unit = null; + + if(value.parseColor('#zzzzzz') != '#zzzzzz') { + value = value.parseColor(); + unit = 'color'; + } else if(property == 'opacity') { + value = parseFloat(value); + if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + } else if(Element.CSS_LENGTH.test(value)) { + var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); + value = parseFloat(components[1]); + unit = (components.length == 3) ? components[2] : null; + } + + var originalValue = this.element.getStyle(property); + return { + style: property.camelize(), + originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), + targetValue: unit=='color' ? parseColor(value) : value, + unit: unit + }; + }.bind(this)).reject(function(transform){ + return ( + (transform.originalValue == transform.targetValue) || + ( + transform.unit != 'color' && + (isNaN(transform.originalValue) || isNaN(transform.targetValue)) + ) + ) + }); + }, + update: function(position) { + var style = {}, transform, i = this.transforms.length; + while(i--) + style[(transform = this.transforms[i]).style] = + transform.unit=='color' ? '#'+ + (Math.round(transform.originalValue[0]+ + (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + + (Math.round(transform.originalValue[1]+ + (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + + (Math.round(transform.originalValue[2]+ + (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : + transform.originalValue + Math.round( + ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit; + this.element.setStyle(style, true); + } +}); + +Effect.Transform = Class.create(); +Object.extend(Effect.Transform.prototype, { + initialize: function(tracks){ + this.tracks = []; + this.options = arguments[1] || {}; + this.addTracks(tracks); + }, + addTracks: function(tracks){ + tracks.each(function(track){ + var data = $H(track).values().first(); + this.tracks.push($H({ + ids: $H(track).keys().first(), + effect: Effect.Morph, + options: { style: data } + })); + }.bind(this)); + return this; + }, + play: function(){ + return new Effect.Parallel( + this.tracks.map(function(track){ + var elements = [$(track.ids) || $$(track.ids)].flatten(); + return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) }); + }).flatten(), + this.options + ); + } +}); + +Element.CSS_PROPERTIES = $w( + 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + + 'fontSize fontWeight height left letterSpacing lineHeight ' + + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ + 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + + 'right textIndent top width wordSpacing zIndex'); + +Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; + +String.prototype.parseStyle = function(){ + var element = document.createElement('div'); + element.innerHTML = '
'; + var style = element.childNodes[0].style, styleRules = $H(); + + Element.CSS_PROPERTIES.each(function(property){ + if(style[property]) styleRules[property] = style[property]; + }); + if(Prototype.Browser.IE && this.indexOf('opacity') > -1) { + styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]; + } + return styleRules; +}; + +Element.morph = function(element, style) { + new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {})); + return element; +}; + +['getInlineOpacity','forceRerendering','setContentZoom', + 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each( + function(f) { Element.Methods[f] = Element[f]; } +); + +Element.Methods.visualEffect = function(element, effect, options) { + s = effect.dasherize().camelize(); + effect_class = s.charAt(0).toUpperCase() + s.substring(1); + new Effect[effect_class](element, options); + return $(element); +}; + +Element.addMethods(); \ No newline at end of file diff --git a/inc/app/siteshop/js/fade.js b/inc/app/siteshop/js/fade.js new file mode 100644 index 00000000..e4649770 --- /dev/null +++ b/inc/app/siteshop/js/fade.js @@ -0,0 +1,74 @@ +// cross-browser fade-out, fade-in, and fade-between effects + +var fade_o = 100; +var fade_i = 0; +var fade_d = 0; +var fade_agent = navigator.userAgent.toLowerCase(); +var fade_moz = ((fade_agent.indexOf ('gecko') != -1) && (fade_agent.indexOf ('khtml') == -1));; + +function _fade_out (id) { + e = document.getElementById (id); + + if (fade_o > 0) { + e.style.filter = 'alpha(opacity=' + fade_o + ')'; + e.style.mozOpacity = fade_o / 100; + e.style.opacity = fade_o / 100; + fade_o -= 10; + setTimeout ('_fade_out (\'' + id + '\')', fade_d) + } else if (fade_o <= 0) { + e.style.filter = 'alpha(opacity=' + 0 + ')'; + e.style.mozOpacity = 0; + e.style.opacity = 0; + e.style.visibility = 'hidden'; + } + + return false; +} + +function fade_out (id) { + fade_o = 100; + setTimeout ('_fade_out (\'' + id + '\')', fade_d); + return false; +} + +function _fade_in (id) { + e = document.getElementById (id); + + if (fade_i == 0) { + e.style.filter = 'alpha(opacity=' + fade_i + ')'; + e.style.mozOpacity = 0; + e.style.opacity = 0; + fade_i += 10; + setTimeout ('_fade_in (\'' + id + '\')', fade_d); + } else if (fade_i <= 100) { + e.style.filter = 'alpha(opacity=' + fade_i + ')'; + e.style.mozOpacity = fade_i / 100; + e.style.opacity = fade_i / 100; + fade_i += 10; + setTimeout ('_fade_in (\'' + id + '\')', fade_d); + } + + return false; +} + +function fade_in (id) { + fade_i = 0; + fade (id); + document.getElementById (id).style.visibility = 'visible'; + setTimeout ('_fade_in (\'' + id + '\')', fade_d); + return false; +} + +function fade (id) { + e = document.getElementById (id); + e.style.filter = 'alpha(opacity=' + 0 + ')'; + e.style.mozOpacity = 0; + e.style.opacity = 0; + return false; +} + +function fade_between (out_id, in_id) { + fade_out (out_id); + fade_in (in_id); + return false; +} diff --git a/inc/app/siteshop/js/lightbox.js b/inc/app/siteshop/js/lightbox.js new file mode 100755 index 00000000..777a5a6f --- /dev/null +++ b/inc/app/siteshop/js/lightbox.js @@ -0,0 +1,705 @@ +// ----------------------------------------------------------------------------------- +// +// Lightbox Slideshow v1.1 +// by Justin Barkhuff - http://www.justinbarkhuff.com/lab/lightbox_slideshow/ +// Updated: 2007-08-15 +// +// Largely based on Lightbox v2.02 +// by Lokesh Dhakar - http://huddletogether.com/projects/lightbox2/ +// 3/31/06 +// +// Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/ +// +// The code inserts html at the bottom of the page that looks similar to this: +// +//
+// +// +// ----------------------------------------------------------------------------------- + +// +// Lightbox Object +// + +var Lightbox = { + activeImage : null, + badObjects : ['select','object','embed'], + container : null, + enableSlideshow : null, + groupName : null, + imageArray : [], + options : null, + overlayDuration : null, + overlayOpacity : null, + playSlides : null, + refTags : ['a','area'], + relAttribute : null, + resizeDuration : null, + slideShowTimer : null, + startImage : null, + + // + // initialize() + // Constructor sets class properties and configuration options and + // inserts html at the bottom of the page which is used to display the shadow + // overlay and the image container. + // + initialize: function(options) { + if (!document.getElementsByTagName){ return; } + + this.options = $H({ + animate : true, // resizing animations + autoPlay : true, // should slideshow start automatically + borderSize : 10, // if you adjust the padding in the CSS, you will need to update this variable + containerID : document, // lightbox container object + enableSlideshow : true, // enable slideshow feature + googleAnalytics : false, // track individual image views using Google Analytics + imageDataLocation : 'south', // location of image caption information + initImage : '', // ID of image link to automatically launch when upon script initialization + loop : true, // whether to continuously loop slideshow images + overlayDuration : .2, // time to fade in shadow overlay + overlayOpacity : .8, // transparency of shadow overlay + prefix : '', // ID prefix for all dynamically created html elements + relAttribute : 'lightbox', // specifies the rel attribute value that triggers lightbox + resizeSpeed : 7, // controls the speed of the image resizing (1=slowest and 10=fastest) + showGroupName : false, // show group name of images in image details + slideTime : 4, // time to display images during slideshow + strings : { // allows for localization + closeLink : 'close', + loadingMsg : 'loading', + nextLink : 'next »', + prevLink : '« prev', + startSlideshow : 'start slideshow', + stopSlideshow : 'stop slideshow', + numDisplayPrefix : 'Image', + numDisplaySeparator : 'of' + } + }).merge(options); + + if(this.options.animate){ + this.overlayDuration = Math.max(this.options.overlayDuration,0); + this.options.resizeSpeed = Math.max(Math.min(this.options.resizeSpeed,10),1); + this.resizeDuration = (11 - this.options.resizeSpeed) * 0.15; + }else{ + this.overlayDuration = 0; + this.resizeDuration = 0; + } + + this.enableSlideshow = this.options.enableSlideshow; + this.overlayOpacity = Math.max(Math.min(this.options.overlayOpacity,1),0); + this.playSlides = this.options.autoPlay; + this.container = $(this.options.containerID); + this.relAttribute = this.options.relAttribute; + this.updateImageList(); + + var objBody = this.container != document ? this.container : document.getElementsByTagName('body').item(0); + + var objOverlay = document.createElement('div'); + objOverlay.setAttribute('id',this.getID('overlay')); + objOverlay.style.display = 'none'; + objBody.appendChild(objOverlay); + Event.observe(objOverlay,'click',this.end.bindAsEventListener(this)); + + var objLightbox = document.createElement('div'); + objLightbox.setAttribute('id',this.getID('lightbox')); + objLightbox.style.display = 'none'; + objBody.appendChild(objLightbox); + + var objImageDataContainer = document.createElement('div'); + objImageDataContainer.setAttribute('id',this.getID('imageDataContainer')); + objImageDataContainer.className = this.getID('clearfix'); + + var objImageData = document.createElement('div'); + objImageData.setAttribute('id',this.getID('imageData')); + objImageDataContainer.appendChild(objImageData); + + var objImageDetails = document.createElement('div'); + objImageDetails.setAttribute('id',this.getID('imageDetails')); + objImageData.appendChild(objImageDetails); + + var objCaption = document.createElement('span'); + objCaption.setAttribute('id',this.getID('caption')); + objImageDetails.appendChild(objCaption); + + var objNumberDisplay = document.createElement('span'); + objNumberDisplay.setAttribute('id',this.getID('numberDisplay')); + objImageDetails.appendChild(objNumberDisplay); + + var objDetailsNav = document.createElement('span'); + objDetailsNav.setAttribute('id',this.getID('detailsNav')); + objImageDetails.appendChild(objDetailsNav); + + var objPrevLink = document.createElement('a'); + objPrevLink.setAttribute('id',this.getID('prevLinkDetails')); + objPrevLink.setAttribute('href','javascript:void(0);'); + objPrevLink.innerHTML = this.options.strings.prevLink; + objDetailsNav.appendChild(objPrevLink); + Event.observe(objPrevLink,'click',this.showPrev.bindAsEventListener(this)); + + var objNextLink = document.createElement('a'); + objNextLink.setAttribute('id',this.getID('nextLinkDetails')); + objNextLink.setAttribute('href','javascript:void(0);'); + objNextLink.innerHTML = this.options.strings.nextLink; + objDetailsNav.appendChild(objNextLink); + Event.observe(objNextLink,'click',this.showNext.bindAsEventListener(this)); + + var objSlideShowControl = document.createElement('a'); + objSlideShowControl.setAttribute('id',this.getID('slideShowControl')); + objSlideShowControl.setAttribute('href','javascript:void(0);'); + objDetailsNav.appendChild(objSlideShowControl); + Event.observe(objSlideShowControl,'click',this.toggleSlideShow.bindAsEventListener(this)); + + var objClose = document.createElement('div'); + objClose.setAttribute('id',this.getID('close')); + objImageData.appendChild(objClose); + + var objCloseLink = document.createElement('a'); + objCloseLink.setAttribute('id',this.getID('closeLink')); + objCloseLink.setAttribute('href','javascript:void(0);'); + objCloseLink.innerHTML = this.options.strings.closeLink; + objClose.appendChild(objCloseLink); + Event.observe(objCloseLink,'click',this.end.bindAsEventListener(this)); + + if(this.options.imageDataLocation == 'north'){ + objLightbox.appendChild(objImageDataContainer); + } + + var objOuterImageContainer = document.createElement('div'); + objOuterImageContainer.setAttribute('id',this.getID('outerImageContainer')); + objLightbox.appendChild(objOuterImageContainer); + + var objImageContainer = document.createElement('div'); + objImageContainer.setAttribute('id',this.getID('imageContainer')); + objOuterImageContainer.appendChild(objImageContainer); + + var objLightboxImage = document.createElement('img'); + objLightboxImage.setAttribute('id',this.getID('lightboxImage')); + objImageContainer.appendChild(objLightboxImage); + + var objHoverNav = document.createElement('div'); + objHoverNav.setAttribute('id',this.getID('hoverNav')); + objImageContainer.appendChild(objHoverNav); + + var objPrevLinkImg = document.createElement('a'); + objPrevLinkImg.setAttribute('id',this.getID('prevLinkImg')); + objPrevLinkImg.setAttribute('href','javascript:void(0);'); + objHoverNav.appendChild(objPrevLinkImg); + Event.observe(objPrevLinkImg,'click',this.showPrev.bindAsEventListener(this)); + + var objNextLinkImg = document.createElement('a'); + objNextLinkImg.setAttribute('id',this.getID('nextLinkImg')); + objNextLinkImg.setAttribute('href','javascript:void(0);'); + objHoverNav.appendChild(objNextLinkImg); + Event.observe(objNextLinkImg,'click',this.showNext.bindAsEventListener(this)); + + var objLoading = document.createElement('div'); + objLoading.setAttribute('id',this.getID('loading')); + objImageContainer.appendChild(objLoading); + + var objLoadingLink = document.createElement('a'); + objLoadingLink.setAttribute('id',this.getID('loadingLink')); + objLoadingLink.setAttribute('href','javascript:void(0);'); + objLoadingLink.innerHTML = this.options.strings.loadingMsg; + objLoading.appendChild(objLoadingLink); + Event.observe(objLoadingLink,'click',this.end.bindAsEventListener(this)); + + if(this.options.imageDataLocation != 'north'){ + objLightbox.appendChild(objImageDataContainer); + } + + if(this.options.initImage != ''){ + this.start($(this.options.initImage)); + } + }, + + // + // updateImageList() + // Loops through specific tags within 'container' looking for + // 'lightbox' references and applies onclick events to them. + // + updateImageList: function(){ + var el, els, rel; + for(var i=0; i < this.refTags.length; i++){ + els = this.container.getElementsByTagName(this.refTags[i]); + for(var j=0; j < els.length; j++){ + el = els[j]; + rel = String(el.getAttribute('rel')); + if (el.getAttribute('href') && (rel.toLowerCase().match(this.relAttribute))){ + el.onclick = function(){Lightbox.start(this); return false;} + } + } + } + }, + + // + // start() + // Display overlay and lightbox. If image is part of a set, add siblings to imageArray. + // + start: function(imageLink) { + + this.hideBadObjects(); + + // stretch overlay to fill page and fade in + var pageSize = this.getPageSize(); + $(this.getID('overlay')).setStyle({height:pageSize.pageHeight+'px'}); + new Effect.Appear(this.getID('overlay'), { duration: this.overlayDuration, from: 0, to: this.overlayOpacity }); + + this.imageArray = []; + this.groupName = null; + + var rel = imageLink.getAttribute('rel'); + var imageTitle = ''; + + // if image is NOT part of a group.. + if(rel == this.relAttribute){ + // add single image to imageArray + imageTitle = imageLink.getAttribute('title') ? imageLink.getAttribute('title') : ''; + this.imageArray.push({'link':imageLink.getAttribute('href'), 'title':imageTitle}); + this.startImage = 0; + } else { + // if image is part of a group.. + var els = this.container.getElementsByTagName(imageLink.tagName); + // loop through anchors, find other images in group, and add them to imageArray + for (var i=0; i 1){ + var num_display = this.options.strings.numDisplayPrefix + ' ' + eval(this.activeImage + 1) + ' ' + this.options.strings.numDisplaySeparator + ' ' + this.imageArray.length; + if(this.options.showGroupName && this.groupName != ''){ + num_display += ' '+this.options.strings.numDisplaySeparator+' '+this.groupName; + } + $(this.getID('numberDisplay')).update(num_display).show(); + if(!this.enableSlideshow){ + $(this.getID('slideShowControl')).hide(); + } + $(this.getID('detailsNav')).show(); + } + + new Effect.Parallel( + [ new Effect.SlideDown( this.getID('imageDataContainer'), { sync: true }), + new Effect.Appear(this.getID('imageDataContainer'), { sync: true }) ], + { duration:.65, afterFinish: function() { Lightbox.updateNav();} } + ); + }, + + // + // updateNav() + // Display appropriate previous and next hover navigation. + // + updateNav: function() { + if(this.imageArray.length > 1){ + $(this.getID('hoverNav')).show(); + if(this.enableSlideshow){ + if(this.playSlides){ + this.startSlideShow(); + } else { + this.stopSlideShow(); + } + } + } + this.enableKeyboardNav(); + }, + // + // startSlideShow() + // Starts the slide show + // + startSlideShow: function(){ + this.playSlides = true; + this.slideShowTimer = new PeriodicalExecuter(function(pe){ Lightbox.showNext(); pe.stop(); },this.options.slideTime); + $(this.getID('slideShowControl')).update(this.options.strings.stopSlideshow); + }, + + // + // stopSlideShow() + // Stops the slide show + // + stopSlideShow: function(){ + this.playSlides = false; + if(this.slideShowTimer){ + this.slideShowTimer.stop(); + } + $(this.getID('slideShowControl')).update(this.options.strings.startSlideshow); + }, + + // + // stopSlideShow() + // Stops the slide show + // + toggleSlideShow: function(){ + if(this.playSlides){ + this.stopSlideShow(); + }else{ + this.startSlideShow(); + } + }, + + // + // pauseSlideShow() + // Pauses the slide show (doesn't change the value of this.playSlides) + // + pauseSlideShow: function(){ + if(this.slideShowTimer){ + this.slideShowTimer.stop(); + } + }, + + // + // showNext() + // Display the next image in a group + // + showNext : function(){ + if(this.imageArray.length > 1){ + if(!this.options.loop && ((this.activeImage == this.imageArray.length - 1 && this.startImage == 0) || (this.activeImage+1 == this.startImage))){ + return this.end(); + } + if(this.activeImage == this.imageArray.length - 1){ + this.changeImage(0); + }else{ + this.changeImage(this.activeImage+1); + } + } + }, + + // + // showPrev() + // Display the next image in a group + // + showPrev : function(){ + if(this.imageArray.length > 1){ + if(this.activeImage == 0){ + this.changeImage(this.imageArray.length - 1); + }else{ + this.changeImage(this.activeImage-1); + } + } + }, + + // + // showFirst() + // Display the first image in a group + // + showFirst : function(){ + if(this.imageArray.length > 1){ + this.changeImage(0); + } + }, + + // + // showFirst() + // Display the first image in a group + // + showLast : function(){ + if(this.imageArray.length > 1){ + this.changeImage(this.imageArray.length - 1); + } + }, + + // + // enableKeyboardNav() + // + enableKeyboardNav: function() { + document.onkeydown = this.keyboardAction; + }, + + // + // disableKeyboardNav() + // + disableKeyboardNav: function() { + document.onkeydown = ''; + }, + + // + // keyboardAction() + // + keyboardAction: function(e) { + if (e == null) { // ie + keycode = event.keyCode; + } else { // mozilla + keycode = e.which; + } + + key = String.fromCharCode(keycode).toLowerCase(); + + if(key == 'x' || key == 'o' || key == 'c'){ // close lightbox + Lightbox.end(); + } else if(key == 'p' || key == '%'){ // display previous image + Lightbox.showPrev(); + } else if(key == 'n' || key =='\''){ // display next image + Lightbox.showNext(); + } else if(key == 'f'){ // display first image + Lightbox.showFirst(); + } else if(key == 'l'){ // display last image + Lightbox.showLast(); + } else if(key == 's'){ // toggle slideshow + if(Lightbox.imageArray.length > 0 && Lightbox.options.enableSlideshow){ + Lightbox.toggleSlideShow(); + } + } + }, + + // + // preloadNeighborImages() + // Preload previous and next images. + // + preloadNeighborImages: function(){ + var nextImageID = this.imageArray.length - 1 == this.activeImage ? 0 : this.activeImage + 1; + nextImage = new Image(); + nextImage.src = this.imageArray[nextImageID].link + + var prevImageID = this.activeImage == 0 ? this.imageArray.length - 1 : this.activeImage - 1; + prevImage = new Image(); + prevImage.src = this.imageArray[prevImageID].link; + }, + + // + // end() + // + end: function() { + this.disableKeyboardNav(); + this.pauseSlideShow(); + $(this.getID('lightbox')).hide(); + new Effect.Fade(this.getID('overlay'), { duration:this.overlayDuration }); + this.showBadObjects(); + }, + + // + // showBadObjects() + // + showBadObjects: function (){ + var els; + var tags = Lightbox.badObjects; + for(var i=0; i exitTime) + return; + } + }, + + // + // getPageScroll() + // Returns array with x,y page scroll values. + // Core code from - quirksmode.org + // + getPageScroll: function(){ + var x,y; + if (self.pageYOffset) { + x = self.pageXOffset; + y = self.pageYOffset; + } else if (document.documentElement && document.documentElement.scrollTop){ // Explorer 6 Strict + x = document.documentElement.scrollLeft; + y = document.documentElement.scrollTop; + } else if (document.body) {// all other Explorers + x = document.body.scrollLeft; + y = document.body.scrollTop; + } + return {x:x,y:y}; + }, + + // + // getPageSize() + // Returns array with page width, height and window width, height + // Core code from - quirksmode.org + // Edit for Firefox by pHaez + // + getPageSize: function(){ + var scrollX,scrollY,windowX,windowY,pageX,pageY; + if (window.innerHeight && window.scrollMaxY) { + scrollX = document.body.scrollWidth; + scrollY = window.innerHeight + window.scrollMaxY; + } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac + scrollX = document.body.scrollWidth; + scrollY = document.body.scrollHeight; + } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari + scrollX = document.body.offsetWidth; + scrollY = document.body.offsetHeight; + } + + if (self.innerHeight) { // all except Explorer + windowX = self.innerWidth; + windowY = self.innerHeight; + } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode + windowX = document.documentElement.clientWidth; + windowY = document.documentElement.clientHeight; + } else if (document.body) { // other Explorers + windowX = document.body.clientWidth; + windowY = document.body.clientHeight; + } + + pageY = (scrollY < windowY) ? windowY : scrollY; // for small pages with total height less then height of the viewport + pageX = (scrollX < windowX) ? windowX : scrollX; // for small pages with total width less then width of the viewport + + return {pageWidth:pageX,pageHeight:pageY,winWidth:windowX,winHeight:windowY}; + }, + + // + // getID() + // Returns formatted Lightbox element ID + // + getID: function(id){ + return this.options.prefix+id; + } +} + +// ----------------------------------------------------------------------------------- + +Event.observe(window,'load',function(){ Lightbox.initialize(); }); \ No newline at end of file diff --git a/inc/app/siteshop/js/prototype.js b/inc/app/siteshop/js/prototype.js new file mode 100755 index 00000000..69e29e23 --- /dev/null +++ b/inc/app/siteshop/js/prototype.js @@ -0,0 +1,3271 @@ +/* Prototype JavaScript framework, version 1.5.1 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.1', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) + }, + + ScriptFragment: ']*>([\u0001-\uFFFF]*?)', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(//g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (typeof element == 'string') + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(query.snapshotItem(i)); + return results; + }; + + document.getElementsByClassName = function(className, parentElement) { + var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; + return document._getElementsByXPath(q, parentElement); + } + +} else document.getElementsByClassName = function(className, parentElement) { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) var Element = {}; + +Element.extend = function(element) { + var F = Prototype.BrowserFeatures; + if (!element || !element.tagName || element.nodeType == 3 || + element._extended || F.SpecificElementExtensions || element == window) + return element; + + var methods = {}, tagName = element.tagName, cache = Element.extend.cache, + T = Element.Methods.ByTag; + + // extend methods for all tags (Safari doesn't need this) + if (!F.ElementExtensions) { + Object.extend(methods, Element.Methods), + Object.extend(methods, Element.Methods.Simulated); + } + + // extend methods for specific tags + if (T[tagName]) Object.extend(methods, T[tagName]); + + for (var property in methods) { + var value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = cache.findOrStore(value); + } + + element._extended = Prototype.emptyFunction; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + hide: function(element) { + $(element).style.display = 'none'; + return element; + }, + + show: function(element) { + $(element).style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: function(element, html) { + html = typeof html == 'undefined' ? '' : html.toString(); + $(element).innerHTML = html.stripScripts(); + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + replace: function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNodeContents(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + setTimeout(function() {html.evalScripts()}, 10); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (typeof selector == 'string') + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = element.ancestors(); + return expression ? Selector.findElement(ancestors, expression, index) : + ancestors[index || 0]; + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + var descendants = element.descendants(); + return expression ? Selector.findElement(descendants, expression, index) : + descendants[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = element.previousSiblings(); + return expression ? Selector.findElement(previousSiblings, expression, index) : + previousSiblings[index || 0]; + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = element.nextSiblings(); + return expression ? Selector.findElement(nextSiblings, expression, index) : + nextSiblings[index || 0]; + }, + + getElementsBySelector: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + getElementsByClassName: function(element, className) { + return document.getElementsByClassName(className, element); + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + if (!element.attributes) return null; + var t = Element._attributeTranslations; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + var attribute = element.attributes[name]; + return attribute ? attribute.nodeValue : null; + } + return element.getAttribute(name); + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + if (elementClassName.length == 0) return false; + if (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) + return true; + return false; + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).add(className); + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element).remove(className); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className); + return element; + }, + + observe: function() { + Event.observe.apply(Event, arguments); + return $A(arguments).first(); + }, + + stopObserving: function() { + Event.stopObserving.apply(Event, arguments); + return $A(arguments).first(); + }, + + // removes whitespace-only text node children + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + while (element = element.parentNode) + if (element == ancestor) return true; + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Position.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles, camelized) { + element = $(element); + var elementStyle = element.style; + + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]) + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : + (camelized ? property : property.camelize())] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = $(element).getStyle('display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + // All *Width and *Height properties give 0 on elements with display none, + // so enable the element temporarily + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + // Opera returns the offset relative to the positioning context, when an + // element is position relative but top and left have not been defined + if (window.opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = element.style.overflow || 'auto'; + if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + } +}; + +Object.extend(Element.Methods, { + childOf: Element.Methods.descendantOf, + childElements: Element.Methods.immediateDescendants +}); + +if (Prototype.Browser.Opera) { + Element.Methods._getStyle = Element.Methods.getStyle; + Element.Methods.getStyle = function(element, style) { + switch(style) { + case 'left': + case 'top': + case 'right': + case 'bottom': + if (Element._getStyle(element, 'position') == 'static') return null; + default: return Element._getStyle(element, style); + } + }; +} +else if (Prototype.Browser.IE) { + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset'+style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + element = $(element); + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + style.filter = filter.replace(/alpha\([^\)]*\)/gi,''); + return element; + } else if (value < 0.00001) value = 0; + style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + // IE is missing .innerHTML support for TABLE-related elements + Element.Methods.update = function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + var tagName = element.tagName.toUpperCase(); + if (['THEAD','TBODY','TR','TD'].include(tagName)) { + var div = document.createElement('div'); + switch (tagName) { + case 'THEAD': + case 'TBODY': + div.innerHTML = '' + html.stripScripts() + '
'; + depth = 2; + break; + case 'TR': + div.innerHTML = '' + html.stripScripts() + '
'; + depth = 3; + break; + case 'TD': + div.innerHTML = '
' + html.stripScripts() + '
'; + depth = 4; + } + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + depth.times(function() { div = div.firstChild }); + $A(div.childNodes).each(function(node) { element.appendChild(node) }); + } else { + element.innerHTML = html.stripScripts(); + } + setTimeout(function() { html.evalScripts() }, 10); + return element; + } +} +else if (Prototype.Browser.Gecko) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } +}; + +(function() { + Object.extend(this, { + href: this._getAttr, + src: this._getAttr, + type: this._getAttr, + disabled: this._flag, + checked: this._flag, + readonly: this._flag, + multiple: this._flag + }); +}).call(Element._attributeTranslations.values); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations, node; + attribute = t.names[attribute] || attribute; + node = $(element).getAttributeNode(attribute); + return node && node.specified; + } +}; + +Element.Methods.ByTag = {}; + +Object.extend(Element, Element.Methods); + +if (!Prototype.BrowserFeatures.ElementExtensions && + document.createElement('div').__proto__) { + window.HTMLElement = {}; + window.HTMLElement.prototype = document.createElement('div').__proto__; + Prototype.BrowserFeatures.ElementExtensions = true; +} + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || {}); + else { + if (tagName.constructor == Array) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = {}; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + var cache = Element.extend.cache; + for (var property in methods) { + var value = methods[property]; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = cache.findOrStore(value); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + window[klass] = {}; + window[klass].prototype = document.createElement(tagName).__proto__; + return window[klass]; + } + + if (F.ElementExtensions) { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (typeof klass == "undefined") continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; +}; + +var Toggle = { display: Element.toggle }; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +Abstract.Insertion.prototype = { + initialize: function(element, content) { + this.element = $(element); + this.content = content.stripScripts(); + + if (this.adjacency && this.element.insertAdjacentHTML) { + try { + this.element.insertAdjacentHTML(this.adjacency, this.content); + } catch (e) { + var tagName = this.element.tagName.toUpperCase(); + if (['TBODY', 'TR'].include(tagName)) { + this.insertContent(this.contentFromAnonymousTable()); + } else { + throw e; + } + } + } else { + this.range = this.element.ownerDocument.createRange(); + if (this.initializeRange) this.initializeRange(); + this.insertContent([this.range.createContextualFragment(this.content)]); + } + + setTimeout(function() {content.evalScripts()}, 10); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
'; + return $A(div.childNodes[0].childNodes[0].childNodes); + } +} + +var Insertion = new Object(); + +Insertion.Before = Class.create(); +Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { + initializeRange: function() { + this.range.setStartBefore(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, this.element); + }).bind(this)); + } +}); + +Insertion.Top = Class.create(); +Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(true); + }, + + insertContent: function(fragments) { + fragments.reverse(false).each((function(fragment) { + this.element.insertBefore(fragment, this.element.firstChild); + }).bind(this)); + } +}); + +Insertion.Bottom = Class.create(); +Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { + initializeRange: function() { + this.range.selectNodeContents(this.element); + this.range.collapse(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.appendChild(fragment); + }).bind(this)); + } +}); + +Insertion.After = Class.create(); +Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { + initializeRange: function() { + this.range.setStartAfter(this.element); + }, + + insertContent: function(fragments) { + fragments.each((function(fragment) { + this.element.parentNode.insertBefore(fragment, + this.element.nextSibling); + }).bind(this)); + } +}); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type))) + element.select(); + } catch (e) {} + return element; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (Prototype.Browser.WebKit) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/inc/app/siteshop/js/scriptaculous.js b/inc/app/siteshop/js/scriptaculous.js new file mode 100755 index 00000000..7c472a60 --- /dev/null +++ b/inc/app/siteshop/js/scriptaculous.js @@ -0,0 +1,58 @@ +// script.aculo.us scriptaculous.js v1.7.1_beta3, Fri May 25 17:19:41 +0200 2007 + +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +var Scriptaculous = { + Version: '1.7.1_beta3', + require: function(libraryName) { + // inserting via DOM fails in Safari 2.0, so brute force approach + document.write(''); + }, + REQUIRED_PROTOTYPE: '1.5.1', + load: function() { + function convertVersionString(versionString){ + var r = versionString.split('.'); + return parseInt(r[0])*100000 + parseInt(r[1])*1000 + parseInt(r[2]); + } + + if((typeof Prototype=='undefined') || + (typeof Element == 'undefined') || + (typeof Element.Methods=='undefined') || + (convertVersionString(Prototype.Version) < + convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE))) + throw("script.aculo.us requires the Prototype JavaScript framework >= " + + Scriptaculous.REQUIRED_PROTOTYPE); + + $A(document.getElementsByTagName("script")).findAll( function(s) { + return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/)) + }).each( function(s) { + var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,''); + var includes = s.src.match(/\?.*load=([a-z,]*)/); + (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each( + function(include) { Scriptaculous.require(path+include+'.js') }); + }); + } +} + +Scriptaculous.load(); \ No newline at end of file diff --git a/inc/app/siteshop/lib/Cart.php b/inc/app/siteshop/lib/Cart.php new file mode 100644 index 00000000..80bae524 --- /dev/null +++ b/inc/app/siteshop/lib/Cart.php @@ -0,0 +1,205 @@ +init (); + } + + function init () { + if (! is_array ($_SESSION['siteshop_cart'])) { + $_SESSION['siteshop_cart'] = array (); + } + } + + function addPromo ($p) { + if (Cart::hasPromo ()) { + // only allow one + return false; + } + $_SESSION['siteshop_promo'] = $p->code; + } + + function hasPromo () { + if (isset ($_SESSION['siteshop_promo'])) { + return true; + } + return false; + } + + function add ($id, $price = false, $options) { + if (! $price) { + $price = Product::getPrice ($id); + } + + if (empty ($options)) { + $_SESSION['siteshop_cart'][$id . '_'] = array (1, $price, $options, $id); + } else { + $_SESSION['siteshop_cart'][$id . '_' . implode ('_', $options)] = array (1, $price, $options, $id); + } + } + + function changePrice ($id, $price = false) { + if (! $price) { + $price = Product::getPrice ($id); + } + + foreach ($_SESSION['siteshop_cart'] as $k => $v) { + if (strpos($k, $id.'_') === 0) { + $_SESSION['siteshop_cart'][$k][1] = $price; + } + } + + if (empty ($options)) { + $_SESSION['siteshop_cart'][$id . '_'] = array (1, $price, $options, $id); + } else { + $_SESSION['siteshop_cart'][$id . '_' . implode ('_',$options)] = array (1, $price, $options, $id); + } + } + + function remove ($id) { + unset ($_SESSION['siteshop_cart'][$id]); + } + + function qty ($id, $qty) { + $_SESSION['siteshop_cart'][$id][0] = $qty; + } + + function view () { + $cart = array (); + foreach ($_SESSION['siteshop_cart'] as $k => $info) { + $qty = $info[0]; + $price = $info[1]; + $options = $info[2]; + $id = $info[3]; + $p = new Product ($id); + + $index = $id.'_'; + if (! empty ($options)) { + $index = $id . '_' . implode ('_', $options); + } + + $cart[$index] = $p->makeObj (); + $cart[$index]->qty = $qty; + $cart[$index]->price = $price; + $cart[$index]->options = array (); + $cart[$index]->id = $id; + $cart[$index]->options_str = ''; + if (! empty ($options)) { + foreach ($options as $o) { + $to = new Option ($o); + $cart[$index]->options[$to->val ('id')] = array ( + 'id' => $to->val('id'), + 'name' => $to->val('name'), + 'type' => $to->val('type'), + ); + $cart[$index]->option_str .= ucwords ($to->val ('type')) . ': ' . ucwords ($to->val ('name')) . ', '; + } + $cart[$index]->options_str = substr ($cart[$index]->option_str, 0, -2); + } + } + return $cart; + } + + function items () { + return count ($_SESSION['siteshop_cart']); + } + + function subtotal ($id = false) { + Cart::init (); + + if ($id) { + return money_format ('%^!n', $_SESSION['siteshop_cart'][$id][0] * $_SESSION['siteshop_cart'][$id][1]); + } + $t = 0; + foreach ($_SESSION['siteshop_cart'] as $id => $info) { + $qty = $info[0]; + $price = $info[1]; + $t += $price * $qty; + } + return money_format ('%^!n', $t); + } + + function shipping () { + $t = 0; + $sub = 0; + foreach ($_SESSION['siteshop_cart'] as $id => $info) { + $qty = $info[0]; + $price = $info[1]; + $p = new Product ($id); + $sub += $price * $qty; + $ship = $p->val ('shipping'); + if ($ship == 0) { + $ship = appconf ('shipping_base'); + } + $t += $ship * $qty; + } + if (appconf ('shipping_max') && $t > appconf ('shipping_max')) { + $t = appconf ('shipping_max'); + } + if (appconf ('shipping_free') && $sub > appconf ('shipping_free')) { + $t = 0; + } + return money_format ('%^!n', $t); + } + + function tax () { + $sub = Cart::shipping (); + foreach ($_SESSION['siteshop_cart'] as $id => $info) { + if (Product::taxable ($id)) { + $qty = $info[0]; + $price = $info[1]; + $sub += $price * $qty; + } + } + $t = 0; + foreach (appconf ('taxes') as $tax => $amt) { + $t += $sub * $amt; + } + return money_format ('%^!n', $t); + } + + function promoCode () { + if (Cart::hasPromo ()) { + return $_SESSION['siteshop_promo']; + } + return ''; + } + + function promoName () { + if (Cart::hasPromo ()) { + $promo = Promo::code ($_SESSION['siteshop_promo']); + if ($promo->discount_type == 'dollars') { + return '$' . money_format ('%^!n', $promo->discount) . ' off'; + } else { + return round ($promo->discount) . '% off'; + } + } + return false; + } + + function promo () { + if (Cart::hasPromo ()) { + $promo = Promo::code ($_SESSION['siteshop_promo']); + if ($promo->discount_type == 'dollars') { + return '-' . money_format ('%^!n', $promo->discount); + } else { + return '-' . money_format ('%^!n', ($promo->discount * Cart::subtotal ()) / 100); + } + } + return 0; + } + + function pptotal () { + return money_format ('%^!n', Cart::subtotal () + Cart::promo ()); + } + + function total () { + return money_format ('%^!n', Cart::subtotal () + Cart::shipping () + Cart::tax () + Cart::promo ()); + } + + function clear () { + $_SESSION['siteshop_cart'] = array (); + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/lib/CustomCategory.php b/inc/app/siteshop/lib/CustomCategory.php new file mode 100644 index 00000000..05697e01 --- /dev/null +++ b/inc/app/siteshop/lib/CustomCategory.php @@ -0,0 +1,54 @@ +val ('id'); + } elseif (is_object ($id)) { + $id = $id->id; + } + + if (session_admin ()) { + $sql = session_allowed_sql (); + } else { + $sql = session_approved_sql (); + } + + $list = db_fetch_array ( + 'select b.* from siteshop_category a, siteshop_product_category j, siteshop_product b + where a.id = ? and a.id = j.category_id and b.id = j.product_id and b.availability != 8 and + (b.quantity = -1 or b.quantity > 0) and ' . $sql . ' order by b.weight desc', + $id + ); + + foreach (array_keys ($list) as $k) { + $p = new Product ($list[$k]->id); + $price = $p->getPrice (); + if ($price != $p->val ('price')) { + $list[$k]->sale = true; + $list[$k]->sale_price = $price; + } + } + + return $list; + } + + function listAssoc () { + $c = new Category (); + $c->orderBy ('name asc'); + $list = $c->find (array ()); + $out = array ('' => '- SELECT -'); + if (empty ($list)) { + return $out; + } + foreach ($list as $item) { + $out[$item->id] = $item->name; + } + return $out; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/lib/CustomOption.php b/inc/app/siteshop/lib/CustomOption.php new file mode 100755 index 00000000..90fccb1c --- /dev/null +++ b/inc/app/siteshop/lib/CustomOption.php @@ -0,0 +1,14 @@ +val ('id') . '.jpg')) { + return site_prefix() . '/inc/app/siteshop/pix/options/' . $this->val ('id') . '.jpg'; + } + else return false; + } +} + +?> diff --git a/inc/app/siteshop/lib/CustomOrder.php b/inc/app/siteshop/lib/CustomOrder.php new file mode 100644 index 00000000..c76a703f --- /dev/null +++ b/inc/app/siteshop/lib/CustomOrder.php @@ -0,0 +1,119 @@ += ? and ts <= ?', + date ('Y-m-d 00:00:00'), + date ('Y-m-d 23:59:59') + )); + + $out['sales_month'] = money_format ('%!n', db_shift ( + 'select sum(total) from siteshop_order where ts >= ? and ts <= ?', + date ('Y-m-01 00:00:00'), + date ('Y-m-t 23:59:59') + )); + + $out['sales_year'] = money_format ('%!n', db_shift ( + 'select sum(total) from siteshop_order where ts >= ? and ts <= ?', + date ('Y-01-01 00:00:00'), + date ('Y-12-31 23:59:59') + )); + + $out['orders_today'] = db_shift ( + 'select count(*) from siteshop_order where ts >= ? and ts <= ?', + date ('Y-m-d 00:00:00'), + date ('Y-m-d 23:59:59') + ); + + $out['orders_month'] = db_shift ( + 'select count(*) from siteshop_order where ts >= ? and ts <= ?', + date ('Y-m-01 00:00:00'), + date ('Y-m-t 23:59:59') + ); + + $out['orders_year'] = db_shift ( + 'select count(*) from siteshop_order where ts >= ? and ts <= ?', + date ('Y-01-01 00:00:00'), + date ('Y-12-31 23:59:59') + ); + + $out['products'] = db_shift ('select count(*) from siteshop_product'); + $out['offers'] = db_shift ('select count(*) from siteshop_checkout_offer'); + $out['sales'] = db_shift ('select count(*) from siteshop_sale'); + $out['categories'] = db_shift ('select count(*) from siteshop_category'); + + return $out; + } + + function addProduct ($p) { + $prod = new Product ($p->id); + $p->sku = $prod->val ('sku'); + $p->name = $prod->val ('name'); + return db_execute ( + 'insert into siteshop_order_product + (order_id, product_id, product_sku, product_name, price, shipping, quantity, product_options) + values (?, ?, ?, ?, ?, ?, ?, ?)', + $this->val ('id'), + $p->id, + $p->sku, + $p->name, + $p->price, + $p->shipping, + $p->qty, + $p->options + ); + } + + function recordStatus () { + return db_execute ( + 'insert into siteshop_order_status values (?, now(), ?)', + $this->val ('id'), + $this->val ('status') + ); + } + + function getHistory () { + return db_fetch_array ( + 'select * from siteshop_order_status where order_id = ? order by ts asc', + $this->val ('id') + ); + } + + function getDetails ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } elseif (is_object ($id)) { + $id = $id->id; + } + + $res = db_fetch_array ( + 'select order_id, product_id, product_sku as sku, product_name as name, price, shipping, quantity, product_options from siteshop_order_product + where order_id = ?', + $id + ); + foreach ($res as $k => $v) { + if (empty ($v->sku) || empty ($v->name)) { + $p = new Product ($v->product_id); + $res[$k]->sku = $p->val ('sku'); + $res[$k]->name = $p->val ('name'); + } + $res[$k]->options = unserialize ($v->product_options); + } + return $res; + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/lib/CustomProduct.php b/inc/app/siteshop/lib/CustomProduct.php new file mode 100644 index 00000000..6fbfc0a4 --- /dev/null +++ b/inc/app/siteshop/lib/CustomProduct.php @@ -0,0 +1,201 @@ +val ('id'); + } + if (@file_exists ('inc/app/siteshop/data/' . $id . '-1.jpg')) { + return site_prefix () . '/inc/app/siteshop/data/' . $id . '-1.jpg'; + } + return site_prefix () . '/' . appconf ('default_thumbnail'); + } + + function getImages ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } + $images = array (); + $i = 1; + while (@file_exists ('inc/app/siteshop/data/' . $id . '-' . $i . '.jpg')) { + $images[] = site_prefix () . '/inc/app/siteshop/data/' . $id . '-' . $i . '.jpg'; + $i++; + } + if (count ($images) == 0) { + $images[] = site_prefix () . '/' . appconf ('default_thumbnail'); + } + return $images; + } + + function selectAll () { + return db_pairs ( + 'select id, concat(name, \' ($\', price, \')\') from siteshop_product order by name asc' + ); + } + + function featured ($n) { + if (session_admin ()) { + $sql = session_allowed_sql (); + } else { + $sql = session_approved_sql (); + } + + return db_fetch_array ( + 'select * from siteshop_product + where availability != 8 and (quantity = -1 or quantity > 0) + and ' . $sql . ' order by weight desc + limit ' . $n + ); + } + + function getPrice ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } + + $p = new Product ($id); + + $price = $p->val ('price'); + + // check for sale + $s = new Sale (); + if ($s->loadCurrent ()) { + $sale_price = db_shift ( + 'select sale_price from siteshop_sale_product where sale_id = ? and product_id = ?', + $s->val ('id'), + $id + ); + if ($sale_price) { + $price = $sale_price; + } + } + + return $price; + } + + function updateQuantity ($id = false, $qty = 1) { + if (! $id) { + $id = $this->val ('id'); + } + + $p = new Product ($id); + if ($p->val ('quantity') == -1) { + return true; + } elseif ($p->val ('quantity') == 0) { + return false; + } + $p->set ('quantity', $p->val ('quantity') - $qty); + $p->save (); + return true; + } + + function taxable ($id = false) { + if ($id) { + $p = new Product ($id); + if ($p->val ('taxable') == 'yes') { + return true; + } + return false; + } + if ($this->val ('taxable') == 'yes') { + return true; + } + return false; + } + + function getAllOptions () { + $options = db_fetch_array (' + select distinct o.id, o.name, po.available, o.type from + (select * from siteshop_option) as o + left outer join + (select * from siteshop_product_option where product_id = ?) as po + on + o.id = po.option_id order by o.type asc, o.weight, o.name asc', + $this->val('id') + ); + + return $options; + } + + function setOptionC ($option_id, $available = 'no') { + if (empty ($option_id)) { + return false; + } + if (! is_numeric ($option_id)) { + return false; + } + + db_execute ('delete from siteshop_product_option where product_id = ? and option_id = ?', $this->val ('id'), $option_id); + + if (empty ($available)) { + return true; + } + + db_execute ('insert into siteshop_product_option (product_id, option_id, available) values (?, ?, ?)', $this->val ('id'), $option_id, $available); + //db_execute ('update siteshop_product_option set available = ? where product_id = ? and option_id = ?', $available, $this->val('id'), $option_id); + + return true; + } + + function getVisibleOptions () { + $options = db_fetch_array ( + 'select * from siteshop_product_option as po, siteshop_option as o where po.product_id = ? and po.option_id = o.id order by o.type asc, o.weight, o.name asc', + $this->val ('id') + ); + + foreach ($options as $k => $o) { + if (file_exists ('inc/app/siteshop/pix/options/' . $o->id . '.jpg')) { + $options[$k]->has_thumbnail = 'yes'; + $options[$k]->thumbnail = 'inc/app/siteshop/pix/options/' . $o->id . '.jpg'; + } else { + $options[$k]->has_thumbnail = 'no'; + } + } + + return $options; + } + + function getAddToCartForm () { + + $beginning = template_simple ('addtocartform1.spt', array ('id' => $this->val ('id'))); + $middle = ''; + $end = ''; + + $options = $this->getVisibleOptions (); + + if (empty($options)) { + return template_simple ('addtocartform_nooptions.spt', array ('id' => $this->val ('id'))); + } + + $previous_type = $options[0]->type; + $data = array (); + $first_enabled_found = false; + foreach ($options as $o) { + if ($o->type != $previous_type) { + $middle .= template_simple ('addtocartform2.spt', array ('options' => $data, 'type' => $previous_type)); + $previous_type = $o->type; + $first_enabled_found = false; + $data = array (); + $data[$o->id] = $o; + } else { + $data[$o->id] = $o; + } + + if ($o->available == 'yes' && ! $first_enabled_found) { + $data[$o->id]->selected = true; + $first_enabled_found = true; + } + } + + $middle .= template_simple ('addtocartform2.spt', array ('options' => $data, 'type' => $previous_type)); + + $end .= template_simple ('addtocartform3.spt'); + + return $beginning . $middle . $end; + } + +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/lib/CustomPromo.php b/inc/app/siteshop/lib/CustomPromo.php new file mode 100644 index 00000000..02878784 --- /dev/null +++ b/inc/app/siteshop/lib/CustomPromo.php @@ -0,0 +1,16 @@ +find (array ('code' => $code, 'expires > ' . date ('Y-m-d'))); + if (! $list) { + return false; + } + return array_shift ($list); + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/lib/CustomSale.php b/inc/app/siteshop/lib/CustomSale.php new file mode 100644 index 00000000..cfab0bc5 --- /dev/null +++ b/inc/app/siteshop/lib/CustomSale.php @@ -0,0 +1,51 @@ += ? limit 1', + date ('Y-m-d H:i:s'), + date ('Y-m-d H:i:s') + ); + if (is_object ($c)) { + $this->setCurrent ($c); + return true; + } + return false; + } + + function top ($n) { + if (session_admin ()) { + $sql = session_allowed_sql (); + } else { + $sql = session_approved_sql (); + } + + return db_fetch_array ( + 'select b.*, j.* from siteshop_sale a, siteshop_sale_product j, siteshop_product b + where a.id = ? and a.id = j.sale_id and b.id = j.product_id and b.availability != 8 and + (b.quantity = -1 or b.quantity > 0) and ' . $sql . ' order by b.weight desc + limit ' . $n, + $this->val ('id') + ); + } + + function all () { + if (session_admin ()) { + $sql = session_allowed_sql (); + } else { + $sql = session_approved_sql (); + } + + return db_fetch_array ( + 'select b.*, j.* from siteshop_sale a, siteshop_sale_product j, siteshop_product b + where a.id = ? and a.id = j.sale_id and b.id = j.product_id and b.availability != 8 and + (b.quantity = -1 or b.quantity > 0) and ' . $sql . ' order by b.weight desc', + $this->val ('id') + ); + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/lib/Functions.php b/inc/app/siteshop/lib/Functions.php new file mode 100644 index 00000000..9cfdf132 --- /dev/null +++ b/inc/app/siteshop/lib/Functions.php @@ -0,0 +1,150 @@ +getCategories (); + $o = ''; + $sep = ''; + foreach ($cats as $cat) { + $o .= $sep . $cat->name; + $sep = ', '; + } + return $o; +} + +function siteshop_filter_sale_products ($id) { + $prods = db_fetch_array ( + 'select s.product_id, s.sale_price, p.name from siteshop_sale_product s, siteshop_product p where s.sale_id = ? and s.product_id = p.id', + $id + ); + $o = ''; + foreach ($prods as $p) { + $o .= $p->name . ' ($' . $p->sale_price . ')
'; + } + return $o; +} + +function siteshop_filter_category_products ($id) { + return db_shift ( + 'select count(*) from siteshop_product_category where category_id = ?', + $id + ); +} + +function siteshop_filter_date ($d) { + return date ('F j, Y', strtotime ($d)); +} + +function siteshop_filter_date_time ($d) { + return date ('F j, Y - g:ia', strtotime ($d)); +} + +function siteshop_filter_money ($d) { + return money_format ('%^!n', $d); +} + +function siteshop_filter_province ($c) { + $n = db_shift ('select province from siteshop_province where code = ?', $c); + if (! empty ($n)) { + return $n; + } + return $c; +} + +function siteshop_filter_country ($c) { + $n = db_shift ('select country from siteshop_country where code = ?', $c); + if (! empty ($n)) { + return $n; + } + return $c; +} + +function siteshop_filter_product_name ($id) { + return db_shift ( + 'select name from siteshop_product where id = ?', + $id + ); +} + + +function siteshop_filter_option_type_options ($t) { + $res = db_fetch_array ('select id, name from siteshop_option where type = ? order by weight asc, name asc', $t); + + $oa = array(); + $o = ''; + foreach ($res as $r) { + $oa[] = '' . $r->name . '' . intl_get('Delete Selected') . ''; + } + + return implode (', ', $oa); +} + + +function siteshop_get_states ($s = '') { + + $out = array ('' => '- ' . intl_get ('SELECT') . '-'); + $list = db_pairs ('select code, province from siteshop_province where active = "yes"'); + foreach ($list as $k => $v) { + $out[$k] = $v; + } + $options = ''; + + foreach ($out as $k => $v) { + if ($s == $k) { + $options .= '\n"; + } else { + $options .= '\n"; + } + } + return $options; +} + +function siteshop_get_countries ($s = '') { + $out = array ('' => '- ' . intl_get ('SELECT') . '-'); + $list = db_pairs ('select code, country from siteshop_country where active = "yes"'); + foreach ($list as $k => $v) { + $out[$k] = $v; + } + $options = ''; + foreach ($out as $k => $v) { + if ($s == $k) { + $options .= '\n"; + } else { + $options .= '\n"; + } + } + + return $options; +} + + +?> \ No newline at end of file diff --git a/inc/app/siteshop/lib/Objects.ini.php b/inc/app/siteshop/lib/Objects.ini.php new file mode 100644 index 00000000..c743b25f --- /dev/null +++ b/inc/app/siteshop/lib/Objects.ini.php @@ -0,0 +1,94 @@ +; \ No newline at end of file diff --git a/inc/app/siteshop/lib/Widget/Products.php b/inc/app/siteshop/lib/Widget/Products.php new file mode 100644 index 00000000..0e381c3c --- /dev/null +++ b/inc/app/siteshop/lib/Widget/Products.php @@ -0,0 +1,199 @@ + | +// +----------------------------------------------------------------------+ +// | Authors: John Luxford | +// +----------------------------------------------------------------------+ +// +// Prodcuts widget. Displays a list of products to assign to something. +// + +/** + * Products widget. Displays a list of products to assign to something. + * + * + * validation ('is "foo"'); + * $widget->setValue ('foo'); + * $widget->error_message = 'Oops! This widget is being unruly!'; + * + * ? > + * + * + * @package MailForm + * @author John Luxford + * @copyright Copyright (C) 2001-2003, Simian Systems Inc. + * @license http://www.sitellite.org/index/license Simian Open Software License + * @version 1.2, 2002-05-03, $Id: Products.php,v 1.1.1.1 2007/03/13 07:40:26 lux Exp $ + * @access public + * + */ + +class MF_Widget_products extends MF_Widget { + /** + * A way to pass extra parameters to the HTML form tag, for + * example 'enctype="multipart/formdata"'. + * + * @access public + * + */ + var $extra = ''; + + /** + * This is the short name for this widget. The short name is + * the class name minus the 'MF_Widget_' prefix. + * + * @access public + * + */ + var $type = 'products'; + + var $ignoreEmpty = true; + + var $js = ' +'; + + /** + * Returns the display HTML for this widget. The optional + * parameter determines whether or not to automatically display the widget + * nicely, or whether to simply return the widget (for use in a template). + * + * @access public + * @param boolean $generate_html + * @return string + * + */ + function display ($generate_html = 0) { + parent::display ($generate_html); + global $intl, $simple; + $attrstr = $this->getAttrs (); + + return template_simple ($this->js, $this) . "\t" . '' . "\n\t\t" . '' . "\n\t\t" . + '' . + '
    ' . $this->getProducts ('li') . '
' . + '

' . + '

' . intl_get ('Sale Price') . ':   ' . + '

' . + '' . "\n\t" . '' . "\n"; + } + + function getProducts ($out_type = 'option') { + global $cgi; + if ($out_type == 'option') { + $out = Product::selectAll (); + $o = ''; + foreach ($out as $k => $v) { + $o .= '\n"; + } + return $o; + } elseif ($out_type == 'li') { + $s = new Sale ($cgi->id); + $list = $s->getProducts (); + $out = array (); + foreach ($list as $item) { + $id = $item->id; + $out[$id] = $item->name . ' - $' . $item->sale_price . ''; + } + $o = ''; + foreach ($out as $k => $v) { + $o .= '
  • Remove - ' . $v . "
  • \n"; + } + return $o; + } elseif ($out_type == 'hidden') { + $s = new Sale ($cgi->id); + $list = $s->getProducts (); + $out = ''; + foreach ($list as $item) { + $out .= '&' . $item->id . '=' . $item->sale_price; + } + return $out; + } + } +} + + + +?> \ No newline at end of file diff --git a/inc/app/siteshop/lib/_Objects.php b/inc/app/siteshop/lib/_Objects.php new file mode 100755 index 00000000..bbc87a51 --- /dev/null +++ b/inc/app/siteshop/lib/_Objects.php @@ -0,0 +1,705 @@ +usePermissions = true; + $this->multilingual = true; + + if (is_array ($id)) { + $newkey = $this->add ($id); + if (is_numeric ($newkey)) { + $this->setCurrent ($this->get ($newkey)); + } else { + $this->setCurrent ($this->get ($id['id'])); + } + } elseif (is_object ($id)) { + $this->setCurrent ($id); + } elseif ($id) { + $this->setCurrent ($this->get ($id)); + } + + + $this->_cascade[] = array ('siteshop_product_option', 'product_id'); + $this->_cascade[] = array ('siteshop_product_category', 'product_id'); + } + + function &setOption (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'insert into siteshop_product_option (product_id, option_id) values (?, ?)', + $this->pkey (), + $k + )) { + $this->error = db_error (); + return false; + } + return $o; + } + + function unsetOption (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'delete from siteshop_product_option where product_id = ? and option_id = ?', + $this->val ('id'), + $k + )) { + $this->error = db_error (); + return false; + } + return true; + } + + function getOptions ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } elseif (is_object ($id)) { + $id = $id->id; + } + + return db_fetch_array ( + 'select b.*, j.* from siteshop_product a, siteshop_product_option j, siteshop_option b + where a.id = ? and a.id = j.product_id and b.id = j.option_id', + $id + ); + } + + function &setCategory (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'insert into siteshop_product_category (product_id, category_id) values (?, ?)', + $this->pkey (), + $k + )) { + $this->error = db_error (); + return false; + } + return $o; + } + + function unsetCategory (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'delete from siteshop_product_category where product_id = ? and category_id = ?', + $this->val ('id'), + $k + )) { + $this->error = db_error (); + return false; + } + return true; + } + + function getCategories ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } elseif (is_object ($id)) { + $id = $id->id; + } + + return db_fetch_array ( + 'select b.*, j.* from siteshop_product a, siteshop_product_category j, siteshop_category b + where a.id = ? and a.id = j.product_id and b.id = j.category_id', + $id + ); + } + + function &setOrder (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'insert into siteshop_order_product (product_id, order_id) values (?, ?)', + $this->pkey (), + $k + )) { + $this->error = db_error (); + return false; + } + return $o; + } + + function unsetOrder (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'delete from siteshop_order_product where product_id = ? and order_id = ?', + $this->val ('id'), + $k + )) { + $this->error = db_error (); + return false; + } + return true; + } + + function getOrders ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } elseif (is_object ($id)) { + $id = $id->id; + } + + return db_fetch_array ( + 'select b.*, j.* from siteshop_product a, siteshop_order_product j, siteshop_order b + where a.id = ? and a.id = j.product_id and b.id = j.order_id', + $id + ); + } + + function &setSale (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'insert into siteshop_sale_product (product_id, sale_id) values (?, ?)', + $this->pkey (), + $k + )) { + $this->error = db_error (); + return false; + } + return $o; + } + + function unsetSale (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'delete from siteshop_sale_product where product_id = ? and sale_id = ?', + $this->val ('id'), + $k + )) { + $this->error = db_error (); + return false; + } + return true; + } + + function getSales ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } elseif (is_object ($id)) { + $id = $id->id; + } + + return db_fetch_array ( + 'select b.*, j.* from siteshop_product a, siteshop_sale_product j, siteshop_sale b + where a.id = ? and a.id = j.product_id and b.id = j.sale_id', + $id + ); + } +} + +loader_import ('siteshop.CustomCategory'); + +class Category extends CustomCategory { + function Category ($id = false) { + parent::CustomCategory ('siteshop_category', 'id'); + + + + if (is_array ($id)) { + $newkey = $this->add ($id); + if (is_numeric ($newkey)) { + $this->setCurrent ($this->get ($newkey)); + } else { + $this->setCurrent ($this->get ($id['id'])); + } + } elseif (is_object ($id)) { + $this->setCurrent ($id); + } elseif ($id) { + $this->setCurrent ($this->get ($id)); + } + + // Category cascade + } + + function &setProduct (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'insert into siteshop_product_category (category_id, product_id) values (?, ?)', + $this->pkey (), + $k + )) { + $this->error = db_error (); + return false; + } + return $o; + } + + function unsetProduct (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'delete from siteshop_product_category where category_id = ? and product_id = ?', + $this->val ('id'), + $k + )) { + $this->error = db_error (); + return false; + } + return true; + } + + function getProducts ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } elseif (is_object ($id)) { + $id = $id->id; + } + + return db_fetch_array ( + 'select b.*, j.* from siteshop_category a, siteshop_product_category j, siteshop_product b + where a.id = ? and a.id = j.category_id and b.id = j.product_id', + $id + ); + } +} + +loader_import ('siteshop.CustomOrder'); + +class Order extends CustomOrder { + function Order ($id = false) { + parent::CustomOrder ('siteshop_order', 'id'); + + + + if (is_array ($id)) { + $newkey = $this->add ($id); + if (is_numeric ($newkey)) { + $this->setCurrent ($this->get ($newkey)); + } else { + $this->setCurrent ($this->get ($id['id'])); + } + } elseif (is_object ($id)) { + $this->setCurrent ($id); + } elseif ($id) { + $this->setCurrent ($this->get ($id)); + } + + + $this->_cascade[] = array ('siteshop_order_product', 'order_id'); + } + + function &setProduct (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'insert into siteshop_order_product (order_id, product_id) values (?, ?)', + $this->pkey (), + $k + )) { + $this->error = db_error (); + return false; + } + return $o; + } + + function unsetProduct (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'delete from siteshop_order_product where order_id = ? and product_id = ?', + $this->val ('id'), + $k + )) { + $this->error = db_error (); + return false; + } + return true; + } + + function getProducts ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } elseif (is_object ($id)) { + $id = $id->id; + } + + return db_fetch_array ( + 'select b.*, j.* from siteshop_order a, siteshop_order_product j, siteshop_product b + where a.id = ? and a.id = j.order_id and b.id = j.product_id', + $id + ); + } +} + +loader_import ('siteshop.CustomOption'); + +class Option extends CustomOption { + function Option ($id = false) { + parent::CustomOption ('siteshop_option', 'id'); + + + + if (is_array ($id)) { + $newkey = $this->add ($id); + if (is_numeric ($newkey)) { + $this->setCurrent ($this->get ($newkey)); + } else { + $this->setCurrent ($this->get ($id['id'])); + } + } elseif (is_object ($id)) { + $this->setCurrent ($id); + } elseif ($id) { + $this->setCurrent ($this->get ($id)); + } + + + $this->_cascade['ProductOption'] = 'option_id'; + } + + function &setProductOption (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + $o->_current->option_id = $this->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'update siteshop_product_option set option_id = ? where id = ?', + $this->pkey (), + $k + )) { + $this->error = db_error (); + return false; + } + return $o; + } + + function unsetProductOption (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + $o->_current->option_id = 0; + } else { + $k = $o->id; + } + if (! db_execute ( + 'update siteshop_product_option set option_id = ? where id = ?', + 0, + $k + )) { + $this->error = db_error (); + return false; + } + return true; + } + + function getProductOptions ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } elseif (is_object ($id)) { + $id = $id->id; + } + + return db_fetch_array ( + 'select * from siteshop_product_option + where option_id = ?', + $id + ); + } + + function &setProduct (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'insert into siteshop_product_option (option_id, product_id) values (?, ?)', + $this->pkey (), + $k + )) { + $this->error = db_error (); + return false; + } + return $o; + } + + function unsetProduct (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'delete from siteshop_product_option where option_id = ? and product_id = ?', + $this->val ('id'), + $k + )) { + $this->error = db_error (); + return false; + } + return true; + } + + function getProducts ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } elseif (is_object ($id)) { + $id = $id->id; + } + + return db_fetch_array ( + 'select b.*, j.* from siteshop_option a, siteshop_product_option j, siteshop_product b + where a.id = ? and a.id = j.option_id and b.id = j.product_id', + $id + ); + } +} + +class ProductOption extends Generic { + function ProductOption ($id = false) { + parent::Generic ('siteshop_product_option', 'id'); + + + + if (is_array ($id)) { + $newkey = $this->add ($id); + if (is_numeric ($newkey)) { + $this->setCurrent ($this->get ($newkey)); + } else { + $this->setCurrent ($this->get ($id['id'])); + } + } elseif (is_object ($id)) { + $this->setCurrent ($id); + } elseif ($id) { + $this->setCurrent ($this->get ($id)); + } + + // ProductOption cascade + } + + function &setOption (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'update siteshop_product_option set option_id = ? where id = ?', + $k, + $this->pkey () + )) { + $this->error = db_error (); + return false; + } + $this->_current->option_id = $k; + return $o; + } + + function unsetOption (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'update siteshop_product_option set option_id = ? where id = ?', + 0, + $this->pkey () + )) { + $this->error = db_error (); + return false; + } + $this->_current->option_id = 0; + return true; + } + + function getOption () { + return db_single ( + 'select * from siteshop_option + where id = ?', + $this->val ('option_id') + ); + } +} + +class OptionType extends Generic { + function OptionType ($id = false) { + parent::Generic ('siteshop_option_type', 'id'); + + + + if (is_array ($id)) { + $newkey = $this->add ($id); + if (is_numeric ($newkey)) { + $this->setCurrent ($this->get ($newkey)); + } else { + $this->setCurrent ($this->get ($id['id'])); + } + } elseif (is_object ($id)) { + $this->setCurrent ($id); + } elseif ($id) { + $this->setCurrent ($this->get ($id)); + } + + // OptionType cascade + } +} + +loader_import ('siteshop.CustomSale'); + +class Sale extends CustomSale { + function Sale ($id = false) { + parent::CustomSale ('siteshop_sale', 'id'); + + + + if (is_array ($id)) { + $newkey = $this->add ($id); + if (is_numeric ($newkey)) { + $this->setCurrent ($this->get ($newkey)); + } else { + $this->setCurrent ($this->get ($id['id'])); + } + } elseif (is_object ($id)) { + $this->setCurrent ($id); + } elseif ($id) { + $this->setCurrent ($this->get ($id)); + } + + + $this->_cascade[] = array ('siteshop_sale_product', 'sale_id'); + } + + function &setProduct (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'insert into siteshop_sale_product (sale_id, product_id) values (?, ?)', + $this->pkey (), + $k + )) { + $this->error = db_error (); + return false; + } + return $o; + } + + function unsetProduct (&$o) { + if (is_subclass_of ($o, 'Generic')) { + $k = $o->pkey (); + } else { + $k = $o->id; + } + if (! db_execute ( + 'delete from siteshop_sale_product where sale_id = ? and product_id = ?', + $this->val ('id'), + $k + )) { + $this->error = db_error (); + return false; + } + return true; + } + + function getProducts ($id = false) { + if (! $id) { + $id = $this->val ('id'); + } elseif (is_object ($id)) { + $id = $id->id; + } + + return db_fetch_array ( + 'select b.*, j.* from siteshop_sale a, siteshop_sale_product j, siteshop_product b + where a.id = ? and a.id = j.sale_id and b.id = j.product_id', + $id + ); + } +} + +loader_import ('siteshop.CustomPromo'); + +class Promo extends CustomPromo { + function Promo ($id = false) { + parent::CustomPromo ('siteshop_promo_code', 'id'); + + + + if (is_array ($id)) { + $newkey = $this->add ($id); + if (is_numeric ($newkey)) { + $this->setCurrent ($this->get ($newkey)); + } else { + $this->setCurrent ($this->get ($id['id'])); + } + } elseif (is_object ($id)) { + $this->setCurrent ($id); + } elseif ($id) { + $this->setCurrent ($this->get ($id)); + } + + // Promo cascade + } +} + +class CheckoutOffer extends Generic { + function CheckoutOffer ($id = false) { + parent::Generic ('siteshop_checkout_offer', 'id'); + + + + if (is_array ($id)) { + $newkey = $this->add ($id); + if (is_numeric ($newkey)) { + $this->setCurrent ($this->get ($newkey)); + } else { + $this->setCurrent ($this->get ($id['id'])); + } + } elseif (is_object ($id)) { + $this->setCurrent ($id); + } elseif ($id) { + $this->setCurrent ($this->get ($id)); + } + + // CheckoutOffer cascade + } +} + +?> \ No newline at end of file diff --git a/inc/app/siteshop/pix/addtocart.js b/inc/app/siteshop/pix/addtocart.js new file mode 100755 index 00000000..245a2187 --- /dev/null +++ b/inc/app/siteshop/pix/addtocart.js @@ -0,0 +1,4 @@ +function addtocart () +{ + document.addtocartform.submit() ; +} diff --git a/inc/app/siteshop/pix/blank.gif b/inc/app/siteshop/pix/blank.gif new file mode 100755 index 00000000..1d11fa9a Binary files /dev/null and b/inc/app/siteshop/pix/blank.gif differ diff --git a/inc/app/siteshop/pix/closelabel.gif b/inc/app/siteshop/pix/closelabel.gif new file mode 100755 index 00000000..2adcfd62 Binary files /dev/null and b/inc/app/siteshop/pix/closelabel.gif differ diff --git a/inc/app/siteshop/pix/corner.gif b/inc/app/siteshop/pix/corner.gif new file mode 100755 index 00000000..bc111c2a Binary files /dev/null and b/inc/app/siteshop/pix/corner.gif differ diff --git a/inc/app/siteshop/pix/default_thumbnail.gif b/inc/app/siteshop/pix/default_thumbnail.gif new file mode 100644 index 00000000..39bbcc66 Binary files /dev/null and b/inc/app/siteshop/pix/default_thumbnail.gif differ diff --git a/inc/app/siteshop/pix/delete.gif b/inc/app/siteshop/pix/delete.gif new file mode 100644 index 00000000..5dd5e715 Binary files /dev/null and b/inc/app/siteshop/pix/delete.gif differ diff --git a/inc/app/siteshop/pix/icon.gif b/inc/app/siteshop/pix/icon.gif new file mode 100644 index 00000000..393e1500 Binary files /dev/null and b/inc/app/siteshop/pix/icon.gif differ diff --git a/inc/app/siteshop/pix/loading.gif b/inc/app/siteshop/pix/loading.gif new file mode 100755 index 00000000..f864d5fd Binary files /dev/null and b/inc/app/siteshop/pix/loading.gif differ diff --git a/inc/app/siteshop/pix/nextlabel.gif b/inc/app/siteshop/pix/nextlabel.gif new file mode 100755 index 00000000..1e81b308 Binary files /dev/null and b/inc/app/siteshop/pix/nextlabel.gif differ diff --git a/inc/app/siteshop/pix/prevlabel.gif b/inc/app/siteshop/pix/prevlabel.gif new file mode 100755 index 00000000..ab715a9f Binary files /dev/null and b/inc/app/siteshop/pix/prevlabel.gif differ diff --git a/inc/app/siteshop/pix/product-option-trans.gif b/inc/app/siteshop/pix/product-option-trans.gif new file mode 100755 index 00000000..5c5d72e8 Binary files /dev/null and b/inc/app/siteshop/pix/product-option-trans.gif differ diff --git a/inc/app/usradm/boxes/browse/_users.php b/inc/app/usradm/boxes/browse/_users.php index 529bf3f1..fb7fb018 100755 --- a/inc/app/usradm/boxes/browse/_users.php +++ b/inc/app/usradm/boxes/browse/_users.php @@ -49,7 +49,7 @@ function confirmDelete (list, key) { {intl Add User}     Export Users

    '); + echo template_simple ('

    {intl Add User}     Export Users     Add to Newsletter

    '); $snm =& session_get_manager (); $users = $snm->user->getList ($cgi->offset, $limit, $cgi->orderBy, $cgi->sort, $cgi->_role, $cgi->_team, $cgi->_lastname, $cgi->_disabled, $cgi->_public, $cgi->_teams); diff --git a/inc/conf/auth/applications/index.php b/inc/conf/auth/applications/index.php index 79ce6373..ffa2d286 100755 --- a/inc/conf/auth/applications/index.php +++ b/inc/conf/auth/applications/index.php @@ -104,6 +104,10 @@ realty = Off +sitebanner = Off + +sitelinks = Off + ; ; THE END ; diff --git a/inc/conf/auth/resources/index.php b/inc/conf/auth/resources/index.php index b88ca147..170af133 100755 --- a/inc/conf/auth/resources/index.php +++ b/inc/conf/auth/resources/index.php @@ -50,6 +50,54 @@ app_sitetemplate = Off +app_sitefaq = Off + +app_siteforum = Off + +app_siteglossary = Off + +app_sitepoll = Off + +app_sitequotes = Off + +app_sitesearch = Off + +app_sitewiki = Off + +app_siteblog = Off + +app_sitegallery = Off + +app_sitestreamer = Off + +app_sitestudy = Off + +app_deadlines = Off + +app_timetracker = Off + +app_todo = Off + +app_sitepresenter = Off + +app_devtools = Off + +app_sitebanner = Off + +app_siteevent = Off + +app_sitelinks = Off + +app_sitemailer = Off + +app_sitetracker = Off + +app_sitemailer2 = Off + +app_sitepublisher = Off + +app_pbadmin = Off + ; ; THE END ; diff --git a/inc/conf/auth/roles/editor.php b/inc/conf/auth/roles/editor.php index c92a8b2f..22ebf2c7 100755 --- a/inc/conf/auth/roles/editor.php +++ b/inc/conf/auth/roles/editor.php @@ -18,10 +18,14 @@ [allow:resources] +add = rw + app_boxchooser = rw delete = rw +sitellite_form_submission= rw + imagechooser_delete = rw sitellite_news = rw diff --git a/inc/conf/auth/status/index.php b/inc/conf/auth/status/index.php index 22e0ad8d..573f067d 100755 --- a/inc/conf/auth/status/index.php +++ b/inc/conf/auth/status/index.php @@ -14,6 +14,8 @@ draft = Off +parallel = Off + pending = Off queued = Off diff --git a/inc/conf/product.php b/inc/conf/product.php new file mode 100755 index 00000000..7e4a6f97 --- /dev/null +++ b/inc/conf/product.php @@ -0,0 +1,21 @@ +; \ No newline at end of file diff --git a/install/changes.txt b/install/changes.txt index 81a98506..3ec437f0 100755 --- a/install/changes.txt +++ b/install/changes.txt @@ -101,6 +101,7 @@ Changes in 5.0.3-stable - Fixed additional PHP 5.3 compatibility issues and warnings. - Fixed Xed box chooser output to be compatible with Firefox 3.6 - Added script to fix existing boxes for Firefox 3.6 compatibility. +- Merged Professional Edition features into the main codebase. Changes in 5.0.2-stable diff --git a/install/install-mysql.sql b/install/install-mysql.sql index 26f620e0..909955c9 100755 --- a/install/install-mysql.sql +++ b/install/install-mysql.sql @@ -870,6 +870,761 @@ create table sitellite_translation_sv ( index (sv_author, sv_action, sv_revision, sv_deleted, sv_current), index (id) ); + +# Your database schema goes here + +CREATE TABLE sitebanner_ad ( + id int not null auto_increment primary key, + name char(72) not null, + description char(255) not null, + client char(48) not null, + purchased int not null, + impressions int not null, + display_url char(128) not null, + url char(255) not null, + target enum('parent','self','top','blank') not null default 'top', + format enum('image','html','text','external','adsense') not null default 'image', + file text not null, + section char(200) not null, + position char(48) not null, + active enum('yes','no') not null default 'yes', + index (purchased, impressions, section, position, active, client, format) +); + +CREATE TABLE sitebanner_position ( + name char(48) not null primary key +); + +CREATE TABLE sitebanner_view ( + id int not null auto_increment primary key, + campaign int not null, + ip char(15) not null, + ts datetime not null, + ua char(128) not null, + index (campaign, ip, ts, ua) +); + +CREATE TABLE sitebanner_click ( + id int not null auto_increment primary key, + campaign int not null, + ip char(15) not null, + ts datetime not null, + ua char(128) not null, + index (campaign, ip, ts, ua) +); +# Your database schema goes here + +create table sitelinks_item ( + id int not null auto_increment primary key, + title char(128) not null, + url char(255) not null, + user_id char(32) not null, + rank int not null, + user_rating decimal(3,2) not null, + category char(48) not null, + ctype char(48) not null, + ts datetime not null, + summary text not null, + sitellite_status char(32) not null, + sitellite_access char(32) not null, + sitellite_owner char(48) not null, + sitellite_team char(48) not null, + index (user_id,rank,user_rating,category,ctype,ts,sitellite_status,sitellite_access,sitellite_owner,sitellite_team) +); + +create table sitelinks_item_sv ( + sv_autoid int(11) NOT NULL auto_increment primary key, + sv_author varchar(16) NOT NULL default '', + sv_action enum('created','modified','republished','replaced','restored','deleted','updated') NOT NULL default 'created', + sv_revision datetime NOT NULL, + sv_changelog text NOT NULL, + sv_deleted enum('yes','no') NOT NULL default 'no', + sv_current enum('yes','no') NOT NULL default 'yes', + id int not null, + title char(128) not null, + url char(255) not null, + user_id char(32) not null, + rank int not null, + user_rating decimal(3,2) not null, + category char(48) not null, + ctype char(48) not null, + ts datetime not null, + summary text not null, + sitellite_status char(32) not null, + sitellite_access char(32) not null, + sitellite_owner char(48) not null, + sitellite_team char(48) not null, + index sv_author (sv_author,sv_action,sv_revision,sv_deleted,sv_current), + index (user_id,rank,user_rating,category,ctype,ts,sitellite_status,sitellite_access,sitellite_owner,sitellite_team) +); + +create table sitelinks_category ( + id char(48) not null primary key +); + +create table sitelinks_hit ( + id int not null auto_increment primary key, + item_id int not null, + ts datetime not null, + ip char(15) not null, + ua char(128) not null, + index (item_id,ts,ip,ua) +); + +create table sitelinks_view ( + id int not null auto_increment primary key, + item_id int not null, + ts datetime not null, + ip char(15) not null, + ua char(128) not null, + index (item_id,ts,ip,ua) +); + +create table sitelinks_rating ( + id int not null auto_increment primary key, + item_id int not null, + rating int not null, + ts datetime not null, + ip char(15) not null, + ua char(128) not null, + index (item_id,rating,ts,ip,ua) +); +# Your database schema goes here + +create table sitemailer2_recipient ( + id int auto_increment primary key, + email char(72) not null, + firstname char(24) not null, + lastname char(24) not null, + organization char(72) not null, + website char(72) not null, + created datetime not null, + status enum('active','unverified','disabled') not null, + index (email, status, created) +); + +-- table storing newsletters a recipient belongs to +create table sitemailer2_recipient_in_newsletter ( + recipient int not null, + newsletter int not null, + status_change_time datetime, + status enum('subscribed','unsubscribed') not null, + primary key (recipient, newsletter) +); + +-- list of message categories +create table sitemailer2_newsletter ( + id int not null auto_increment primary key, + name char(48) not null, + from_name char(128) not null, + from_email char(128) not null, + template int not null, + subject char(128) not null, + rss_subs int not null, + public enum('yes','no') not null default 'yes', + index (name, public) +); + +insert into sitemailer2_newsletter (id, name) values (1, 'Default'); + +-- table for messages +create table sitemailer2_message ( + id int not null auto_increment primary key, + title char (128) not null, + date datetime not null, + mbody text not null, + subject char(72) not null, + template int not null, + start datetime not null, + status enum('draft', 'running', 'done') not null, + recurring enum ('no', 'daily', 'weekly', 'twice-monthly', 'monthly') not null, + next_recurrence datetime not null, + fromname char (128) not null, + fromemail char (128) not null, + numrec int not null, + numsent int not null, + confirmed_views int not null, + num_bounced int not null, + index (date, status) +); + +create table sitemailer2_message_newsletter ( + id int not null auto_increment primary key, + message int not null, + newsletter int not null +); + +--table for templates +create table sitemailer2_template ( + id int not null auto_increment primary key, + title char (128) not null, + date datetime not null, + body text not null, + index (date) +); + +insert into sitemailer2_template (id, title, date, body) values (NULL, "Default", now(), "{body}"); + +--table for mail to be sent +create table sitemailer2_q ( + id int not null auto_increment primary key, + recipient int not null, + message int not null, + attempts int not null, + created datetime not null, + last_attempt datetime not null, + last_error char(128) not null, + next_attempt datetime not null, + index (message) +); + +--table for mail that failed to send +create table sitemailer2_failed_q ( + id int not null auto_increment primary key, + recipient int not null, + message int not null, + attempts int not null, + created datetime not null, + last_attempt datetime not null, + last_error char(128) not null, + index (message) +); + +--subscription confirmation url table +create table sitemailer2_email_tracker ( + id int not null auto_increment primary key, + url char (128) not null, + recipient int not null, + newsletter int not null, + message int not null, + count int not null, + index (newsletter, message) +); + +--create table sitemailer2_rss_tracker ( + +--); + +--bounce tracker +create table sitemailer2_bounces ( + id int not null auto_increment primary key, + recipient int not null, + message int not null, + occurred datetime not null +); + +--campains + +create table sitemailer2_campaign ( + id int not null auto_increment primary key, + title text not null, + forward_url text not null, + created datetime not null +); + +--alter table sitemailer2_link_tracker add recipient int not null; + +create table sitemailer2_link_tracker ( + id int not null auto_increment primary key, + campaign int not null, + created datetime not null, + message int not null, + recipient int not null +); +create table siteshop_product ( + id int not null auto_increment primary key, + sku char(24) not null, + name char(72) not null, + price decimal(9,2) not null, + body text not null, + shipping decimal(9,2) not null, + availability int not null default 1, + quantity int not null default -1, + weight int not null, + taxable enum('yes','no') not null default 'yes', + keywords text not null, + description text not null, + sitellite_status varchar(48) NOT NULL default '', + sitellite_access varchar(48) NOT NULL default '', + sitellite_startdate datetime default NULL, + sitellite_expirydate datetime default NULL, + sitellite_owner varchar(48) NOT NULL default '', + sitellite_team varchar(48) NOT NULL default '', + index (name, weight, price, availability, sitellite_status, sitellite_access) +); + +create table siteshop_category ( + id int not null auto_increment primary key, + name char(72) not null, + weight tinyint not null default 0, + index (name, weight) +); + +# product-category join table +create table siteshop_product_category ( + product_id int not null, + category_id int not null, + primary key (product_id, category_id) +); + +create table siteshop_option_type ( + id int unsigned not null auto_increment primary key, + name varchar(72) not null unique, + index (name) +); + +create table siteshop_option ( + id int unsigned not null auto_increment primary key, + name varchar(72) not null, + type varchar(72) not null, -- e.g., colour, size, etc. + value varchar(72) not null, + weight int not null default 1, + unique (name, type), + index (name, type) +); + +create table siteshop_product_option ( + id int unsigned not null unique auto_increment, #for generic + option_id int unsigned not null, + product_id int not null, + available enum('yes','no') not null default 'yes', + primary key (option_id, product_id), + index (available) +); + +create table siteshop_order ( + id int not null auto_increment primary key, + user_id char(72) not null, + status enum('new','partly-shipped','shipped','cancelled') not null default 'new', + tracking char(128) not null, + ts datetime not null, + ship_to char(72) not null, + ship_address char(72) not null, + ship_address2 char(72) not null, + ship_city char(72) not null, + ship_state char(2) not null, + ship_country char(2) not null, + ship_zip char(15) not null, + bill_to char(72) not null, + bill_address char(72) not null, + bill_address2 char(72) not null, + bill_city char(72) not null, + bill_state char(2) not null, + bill_country char(2) not null, + bill_zip char(15) not null, + phone char(24) not null, + email char(72) not null, + subtotal decimal(9,2) not null, + shipping decimal(9,2) not null, + taxes decimal(9,2) not null, + promo_code char(16) not null, + promo_discount decimal(9,2) not null, + total decimal(9,2) not null, + index (ts, status, user_id) +); + +#alter table siteshop_order add column promo_code char(16) not null; +#alter table siteshop_order add column promo_discount decimal(9,2) not null; + +# order-product join table +create table siteshop_order_product ( + order_id int not null, + product_id int not null, + product_sku char(24) not null, + product_name char(72) not null, + product_options blob not null, + price decimal(9,2) not null, + shipping decimal(9,2) not null, + quantity int not null, + primary key (order_id, product_id) +); + +create table siteshop_order_status ( + order_id int not null, + ts datetime not null, + status enum('new','partly-shipped','shipped','cancelled') not null default 'new', + index (order_id, ts) +); + +create table siteshop_wishlist ( + id int not null auto_increment primary key, + user_id char(72) not null, + index (user_id) +); + +# wishlist-product join table +create table siteshop_wishlist_product ( + wishlist_id int not null, + product_id int not null, + primary key (wishlist_id, product_id) +); + +create table siteshop_sale ( + id int not null auto_increment primary key, + name char(78) not null, + start_date datetime not null, + until_date datetime not null, + index (start_date, until_date) +); + +# sale-product join table +create table siteshop_sale_product ( + sale_id int not null, + product_id int not null, + sale_price decimal(9,2) not null, + primary key (sale_id, product_id, sale_price) +); + +create table siteshop_tax ( + id int not null auto_increment primary key, + name char(72) not null, + rate decimal(2,2) default '0.0', + province char(2), + country char(2), + unique (province, country) +); + +create table siteshop_checkout_offer ( + id int not null auto_increment primary key, + offer_text char(128) not null, + offer_number int not null, + product_id int not null, + sale_price decimal(9,2) not null, + index (offer_number) +); + +create table siteshop_promo_code ( + id int not null auto_increment primary key, + code char(16) not null, + discount_type enum('percent','dollars') not null, + discount decimal(9,2) not null, + expires date not null, + unique (code), + index (expires) +); + +create table siteshop_country ( + code char(2) not null, + country char(72) not null, + active enum('yes','no') not null default 'yes', + primary key (code), + index (country) +); + +INSERT INTO siteshop_country (code, country, active) VALUES ('af', 'Afghanistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('al', 'Albania', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dz', 'Algeria', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('as', 'American Samoa', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ad', 'Andorra', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ao', 'Angola', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ai', 'Anguilla', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('aq', 'Antarctica', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ag', 'Antigua and Barbuda', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ar', 'Argentina', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('am', 'Armenia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('aw', 'Aruba', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('au', 'Australia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('at', 'Austria', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('az', 'Azerbaijan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bs', 'Bahamas', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bh', 'Bahrain', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bd', 'Bangladesh', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bb', 'Barbados', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('by', 'Belarus', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('be', 'Belgium', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bz', 'Belize', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bj', 'Benin', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bm', 'Bermuda', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bt', 'Bhutan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bo', 'Bolivia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ba', 'Bosnia and Herzegovina', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bw', 'Botswana', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bv', 'Bouvet Island', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('br', 'Brazil', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('io', 'British Indian Ocean Territory', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bn', 'Brunei Darussalam', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bg', 'Bulgaria', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bf', 'Burkina Faso', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bi', 'Burundi', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kh', 'Cambodia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cm', 'Cameroon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ca', 'Canada', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cv', 'Cape Verde', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ky', 'Cayman Islands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cf', 'Central African Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('td', 'Chad', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cl', 'Chile', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cn', 'China', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cx', 'Christmas Island', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cc', 'Cocos (keeling) Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('co', 'Colombia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('km', 'Comoros', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cg', 'Congo', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cd', 'Congo, The Democratic Republic of the', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ck', 'Cook Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cr', 'Costa Rica', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ci', 'Cote D\'ivoire', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hr', 'Croatia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cu', 'Cuba', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cy', 'Cyprus', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cz', 'Czech Republic', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dk', 'Denmark', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dj', 'Djibouti', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dm', 'Dominica', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('do', 'Dominican Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ec', 'Ecuador', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('eg', 'Egypt', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sv', 'El Salvador', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gq', 'Equatorial Guinea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('er', 'Eritrea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ee', 'Estonia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('et', 'Ethiopia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fk', 'Falkland Islands (malvinas)', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fo', 'Faroe Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fj', 'Fiji', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fi', 'Finland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fr', 'France', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gf', 'French Guiana', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pf', 'French Polynesia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tf', 'French Southern Territories', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ga', 'Gabon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gm', 'Gambia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ge', 'Georgia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('de', 'Germany', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gh', 'Ghana', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gi', 'Gibraltar', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gr', 'Greece', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gl', 'Greenland', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gd', 'Grenada', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gp', 'Guadeloupe', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gu', 'Guam', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gt', 'Guatemala', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gn', 'Guinea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gw', 'Guinea-bissau', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gy', 'Guyana', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ht', 'Haiti', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hm', 'Heard Island and Mcdonald Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('va', 'Holy See (Vatican City State)', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hn', 'Honduras', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hk', 'Hong Kong', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hu', 'Hungary', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('is', 'Iceland', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('in', 'India', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('id', 'Indonesia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ir', 'Iran, Islamic Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('iq', 'Iraq', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ie', 'Ireland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('il', 'Israel', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('it', 'Italy', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('jm', 'Jamaica', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('jp', 'Japan', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('jo', 'Jordan', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kz', 'Kazakhstan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ke', 'Kenya', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ki', 'Kiribati', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kp', 'Korea, Democratic People\'s Republic of', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kr', 'Korea, Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kw', 'Kuwait', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kg', 'Kyrgyzstan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('la', 'Lao People\'s Democratic Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lv', 'Latvia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lb', 'Lebanon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ls', 'Lesotho', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lr', 'Liberia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ly', 'Libyan Arab Jamahiriya', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('li', 'Liechtenstein', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lt', 'Lithuania', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lu', 'Luxembourg', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mo', 'Macao', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mk', 'Macedonia, The Former Yugoslav Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mg', 'Madagascar', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mw', 'Malawi', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('my', 'Malaysia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mv', 'Maldives', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ml', 'Mali', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mt', 'Malta', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mh', 'Marshall Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mq', 'Martinique', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mr', 'Mauritania', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mu', 'Mauritius', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('yt', 'Mayotte', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mx', 'Mexico', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fm', 'Micronesia, Federated States of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('md', 'Moldova, Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mc', 'Monaco', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mn', 'Mongolia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ms', 'Montserrat', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ma', 'Morocco', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mz', 'Mozambique', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mm', 'Myanmar', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('na', 'Namibia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nr', 'Nauru', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('np', 'Nepal', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nl', 'Netherlands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('an', 'Netherlands Antilles', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nc', 'New Caledonia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nz', 'New Zealand', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ni', 'Nicaragua', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ne', 'Niger', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ng', 'Nigeria', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nu', 'Niue', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nf', 'Norfolk Island', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mp', 'Northern Mariana Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('no', 'Norway', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('om', 'Oman', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pk', 'Pakistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pw', 'Palau', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ps', 'Palestinian Territory, Occupied', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pa', 'Panama', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pg', 'Papua New Guinea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('py', 'Paraguay', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pe', 'Peru', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ph', 'Philippines', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pn', 'Pitcairn', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pl', 'Poland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pt', 'Portugal', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pr', 'Puerto Rico', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('qa', 'Qatar', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('re', 'Reunion', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ro', 'Romania', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ru', 'Russia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('rw', 'Rwanda', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sh', 'Saint Helena', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kn', 'Saint Kitts and Nevis', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lc', 'Saint Lucia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pm', 'Saint Pierre and Miquelon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vc', 'Saint Vincent and the Grenadines', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ws', 'Samoa', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sm', 'San Marino', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('st', 'Sao Tome and Principe', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sa', 'Saudi Arabia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sn', 'Senegal', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cs', 'Serbia and Montenegro', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sc', 'Seychelles', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sl', 'Sierra Leone', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sg', 'Singapore', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sk', 'Slovakia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('si', 'Slovenia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sb', 'Solomon Islands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('so', 'Somalia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('za', 'South Africa', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gs', 'South Georgia and the South Sandwich Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('es', 'Spain', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lk', 'Sri Lanka', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sd', 'Sudan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sr', 'Suriname', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sj', 'Svalbard and Jan Mayen', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sz', 'Swaziland', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('se', 'Sweden', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ch', 'Switzerland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sy', 'Syrian Arab Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tw', 'Taiwan', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tj', 'Tajikistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tz', 'Tanzania, United Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('th', 'Thailand', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tl', 'Timor-leste', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tg', 'Togo', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tk', 'Tokelau', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('to', 'Tonga', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tt', 'Trinidad and Tobago', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tn', 'Tunisia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tr', 'Turkey', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tm', 'Turkmenistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tc', 'Turks and Caicos Islands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tv', 'Tuvalu', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ug', 'Uganda', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ua', 'Ukraine', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ae', 'United Arab Emirates', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gb', 'United Kingdom', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('us', 'United States', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('um', 'United States Minor Outlying Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('uy', 'Uruguay', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('uz', 'Uzbekistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vu', 'Vanuatu', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ve', 'Venezuela', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vn', 'Vietnam', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vg', 'Virgin Islands, British', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vi', 'Virgin Islands, U.S.', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('wf', 'Wallis and Futuna', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('eh', 'Western Sahara', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ye', 'Yemen', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('zm', 'Zambia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('zw', 'Zimbabwe', 'no'); + +create table siteshop_province ( + code char(2) not null, + country_code char(2) not null, + province char(72) not null, + active enum('yes','no') not null default 'yes', + primary key (code, country_code), + index (province) +); + +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ab', 'ca', 'Alberta'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('bc', 'ca', 'British Columbia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mb', 'ca', 'Manitoba'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nb', 'ca', 'New Brunswick'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nl', 'ca', 'Newfoundland and Labrador'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ns', 'ca', 'Nova Scotia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nt', 'ca', 'Northwest Territories'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nu', 'ca', 'Nunavut'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('on', 'ca', 'Ontario'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('pe', 'ca', 'Prince Edward Island'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('qc', 'ca', 'Quebec'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('sk', 'ca', 'Saskatchewan'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('yt', 'ca', 'Yukon'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('al', 'us', 'Alabama'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ak', 'us', 'Alaska'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('az', 'us', 'Arizona'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ar', 'us', 'Arkansas'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ca', 'us', 'California'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('co', 'us', 'Colorado'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ct', 'us', 'Connecticut'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('dc', 'us', 'District of Columbia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('de', 'us', 'Delaware'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('fl', 'us', 'Florida'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ga', 'us', 'Georgia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('hi', 'us', 'Hawaii'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('id', 'us', 'Idaho'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('il', 'us', 'Illinois'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('in', 'us', 'Indiana'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ia', 'us', 'Iowa'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ks', 'us', 'Kansas'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ky', 'us', 'Kentucky'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('la', 'us', 'Louisiana'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('me', 'us', 'Maine'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('md', 'us', 'Maryland'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ma', 'us', 'Massachusetts'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mi', 'us', 'Michigan'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mn', 'us', 'Minnesota'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ms', 'us', 'Mississippi'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mo', 'us', 'Missouri'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mt', 'us', 'Montana'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ne', 'us', 'Nebraska'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nv', 'us', 'Nevada'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nh', 'us', 'New Hampshire'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nj', 'us', 'New Jersey'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nm', 'us', 'New Mexico'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ny', 'us', 'New York'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nc', 'us', 'North Carolina'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nd', 'us', 'North Dakota'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('oh', 'us', 'Ohio'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ok', 'us', 'Oklahoma'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('or', 'us', 'Oregon'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('pa', 'us', 'Pennsylvania'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ri', 'us', 'Rhode Island'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('sc', 'us', 'South Carolina'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('sd', 'us', 'South Dakota'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('tn', 'us', 'Tennessee'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('tx', 'us', 'Texas'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ut', 'us', 'Utah'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('vt', 'us', 'Vermont'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('va', 'us', 'Virginia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wa', 'us', 'Washington'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wv', 'us', 'West Virginia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wi', 'us', 'Wisconsin'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wy', 'us', 'Wyoming'); + create table deadlines ( id int not null auto_increment primary key, title char(72) not null, diff --git a/install/install-old.sql b/install/install-old.sql index e0da846c..2c7b2964 100755 --- a/install/install-old.sql +++ b/install/install-old.sql @@ -869,6 +869,761 @@ create table sitellite_translation_sv ( index (sv_author, sv_action, sv_revision, sv_deleted, sv_current), index (id) ); + +# Your database schema goes here + +CREATE TABLE sitebanner_ad ( + id int not null auto_increment primary key, + name char(72) not null, + description char(255) not null, + client char(48) not null, + purchased int not null, + impressions int not null, + display_url char(128) not null, + url char(255) not null, + target enum('parent','self','top','blank') not null default 'top', + format enum('image','html','text','external','adsense') not null default 'image', + file text not null, + section char(200) not null, + position char(48) not null, + active enum('yes','no') not null default 'yes', + index (purchased, impressions, section, position, active, client, format) +); + +CREATE TABLE sitebanner_position ( + name char(48) not null primary key +); + +CREATE TABLE sitebanner_view ( + id int not null auto_increment primary key, + campaign int not null, + ip char(15) not null, + ts datetime not null, + ua char(128) not null, + index (campaign, ip, ts, ua) +); + +CREATE TABLE sitebanner_click ( + id int not null auto_increment primary key, + campaign int not null, + ip char(15) not null, + ts datetime not null, + ua char(128) not null, + index (campaign, ip, ts, ua) +); +# Your database schema goes here + +create table sitelinks_item ( + id int not null auto_increment primary key, + title char(128) not null, + url char(255) not null, + user_id char(32) not null, + rank int not null, + user_rating decimal(3,2) not null, + category char(48) not null, + ctype char(48) not null, + ts datetime not null, + summary text not null, + sitellite_status char(32) not null, + sitellite_access char(32) not null, + sitellite_owner char(48) not null, + sitellite_team char(48) not null, + index (user_id,rank,user_rating,category,ctype,ts,sitellite_status,sitellite_access,sitellite_owner,sitellite_team) +); + +create table sitelinks_item_sv ( + sv_autoid int(11) NOT NULL auto_increment primary key, + sv_author varchar(16) NOT NULL default '', + sv_action enum('created','modified','republished','replaced','restored','deleted','updated') NOT NULL default 'created', + sv_revision datetime NOT NULL, + sv_changelog text NOT NULL, + sv_deleted enum('yes','no') NOT NULL default 'no', + sv_current enum('yes','no') NOT NULL default 'yes', + id int not null, + title char(128) not null, + url char(255) not null, + user_id char(32) not null, + rank int not null, + user_rating decimal(3,2) not null, + category char(48) not null, + ctype char(48) not null, + ts datetime not null, + summary text not null, + sitellite_status char(32) not null, + sitellite_access char(32) not null, + sitellite_owner char(48) not null, + sitellite_team char(48) not null, + index sv_author (sv_author,sv_action,sv_revision,sv_deleted,sv_current), + index (user_id,rank,user_rating,category,ctype,ts,sitellite_status,sitellite_access,sitellite_owner,sitellite_team) +); + +create table sitelinks_category ( + id char(48) not null primary key +); + +create table sitelinks_hit ( + id int not null auto_increment primary key, + item_id int not null, + ts datetime not null, + ip char(15) not null, + ua char(128) not null, + index (item_id,ts,ip,ua) +); + +create table sitelinks_view ( + id int not null auto_increment primary key, + item_id int not null, + ts datetime not null, + ip char(15) not null, + ua char(128) not null, + index (item_id,ts,ip,ua) +); + +create table sitelinks_rating ( + id int not null auto_increment primary key, + item_id int not null, + rating int not null, + ts datetime not null, + ip char(15) not null, + ua char(128) not null, + index (item_id,rating,ts,ip,ua) +); +# Your database schema goes here + +create table sitemailer2_recipient ( + id int auto_increment primary key, + email char(72) not null, + firstname char(24) not null, + lastname char(24) not null, + organization char(72) not null, + website char(72) not null, + created datetime not null, + status enum('active','unverified','disabled') not null, + index (email, status, created) +); + +-- table storing newsletters a recipient belongs to +create table sitemailer2_recipient_in_newsletter ( + recipient int not null, + newsletter int not null, + status_change_time datetime, + status enum('subscribed','unsubscribed') not null, + primary key (recipient, newsletter) +); + +-- list of message categories +create table sitemailer2_newsletter ( + id int not null auto_increment primary key, + name char(48) not null, + from_name char(128) not null, + from_email char(128) not null, + template int not null, + subject char(128) not null, + rss_subs int not null, + public enum('yes','no') not null default 'yes', + index (name, public) +); + +insert into sitemailer2_newsletter (id, name) values (1, 'Default'); + +-- table for messages +create table sitemailer2_message ( + id int not null auto_increment primary key, + title char (128) not null, + date datetime not null, + mbody text not null, + subject char(72) not null, + template int not null, + start datetime not null, + status enum('draft', 'running', 'done') not null, + recurring enum ('no', 'daily', 'weekly', 'twice-monthly', 'monthly') not null, + next_recurrence datetime not null, + fromname char (128) not null, + fromemail char (128) not null, + numrec int not null, + numsent int not null, + confirmed_views int not null, + num_bounced int not null, + index (date, status) +); + +create table sitemailer2_message_newsletter ( + id int not null auto_increment primary key, + message int not null, + newsletter int not null +); + +--table for templates +create table sitemailer2_template ( + id int not null auto_increment primary key, + title char (128) not null, + date datetime not null, + body text not null, + index (date) +); + +insert into sitemailer2_template (id, title, date, body) values (NULL, "Default", now(), "{body}"); + +--table for mail to be sent +create table sitemailer2_q ( + id int not null auto_increment primary key, + recipient int not null, + message int not null, + attempts int not null, + created datetime not null, + last_attempt datetime not null, + last_error char(128) not null, + next_attempt datetime not null, + index (message) +); + +--table for mail that failed to send +create table sitemailer2_failed_q ( + id int not null auto_increment primary key, + recipient int not null, + message int not null, + attempts int not null, + created datetime not null, + last_attempt datetime not null, + last_error char(128) not null, + index (message) +); + +--subscription confirmation url table +create table sitemailer2_email_tracker ( + id int not null auto_increment primary key, + url char (128) not null, + recipient int not null, + newsletter int not null, + message int not null, + count int not null, + index (newsletter, message) +); + +--create table sitemailer2_rss_tracker ( + +--); + +--bounce tracker +create table sitemailer2_bounces ( + id int not null auto_increment primary key, + recipient int not null, + message int not null, + occurred datetime not null +); + +--campains + +create table sitemailer2_campaign ( + id int not null auto_increment primary key, + title text not null, + forward_url text not null, + created datetime not null +); + +--alter table sitemailer2_link_tracker add recipient int not null; + +create table sitemailer2_link_tracker ( + id int not null auto_increment primary key, + campaign int not null, + created datetime not null, + message int not null, + recipient int not null +); +create table siteshop_product ( + id int not null auto_increment primary key, + sku char(24) not null, + name char(72) not null, + price decimal(9,2) not null, + body text not null, + shipping decimal(9,2) not null, + availability int not null default 1, + quantity int not null default -1, + weight int not null, + taxable enum('yes','no') not null default 'yes', + keywords text not null, + description text not null, + sitellite_status varchar(48) NOT NULL default '', + sitellite_access varchar(48) NOT NULL default '', + sitellite_startdate datetime default NULL, + sitellite_expirydate datetime default NULL, + sitellite_owner varchar(48) NOT NULL default '', + sitellite_team varchar(48) NOT NULL default '', + index (name, weight, price, availability, sitellite_status, sitellite_access) +); + +create table siteshop_category ( + id int not null auto_increment primary key, + name char(72) not null, + weight tinyint not null default 0, + index (name, weight) +); + +# product-category join table +create table siteshop_product_category ( + product_id int not null, + category_id int not null, + primary key (product_id, category_id) +); + +create table siteshop_option_type ( + id int unsigned not null auto_increment primary key, + name varchar(72) not null unique, + index (name) +); + +create table siteshop_option ( + id int unsigned not null auto_increment primary key, + name varchar(72) not null, + type varchar(72) not null, -- e.g., colour, size, etc. + value varchar(72) not null, + weight int not null default 1, + unique (name, type), + index (name, type) +); + +create table siteshop_product_option ( + id int unsigned not null unique auto_increment, #for generic + option_id int unsigned not null, + product_id int not null, + available enum('yes','no') not null default 'yes', + primary key (option_id, product_id), + index (available) +); + +create table siteshop_order ( + id int not null auto_increment primary key, + user_id char(72) not null, + status enum('new','partly-shipped','shipped','cancelled') not null default 'new', + tracking char(128) not null, + ts datetime not null, + ship_to char(72) not null, + ship_address char(72) not null, + ship_address2 char(72) not null, + ship_city char(72) not null, + ship_state char(2) not null, + ship_country char(2) not null, + ship_zip char(15) not null, + bill_to char(72) not null, + bill_address char(72) not null, + bill_address2 char(72) not null, + bill_city char(72) not null, + bill_state char(2) not null, + bill_country char(2) not null, + bill_zip char(15) not null, + phone char(24) not null, + email char(72) not null, + subtotal decimal(9,2) not null, + shipping decimal(9,2) not null, + taxes decimal(9,2) not null, + promo_code char(16) not null, + promo_discount decimal(9,2) not null, + total decimal(9,2) not null, + index (ts, status, user_id) +); + +#alter table siteshop_order add column promo_code char(16) not null; +#alter table siteshop_order add column promo_discount decimal(9,2) not null; + +# order-product join table +create table siteshop_order_product ( + order_id int not null, + product_id int not null, + product_sku char(24) not null, + product_name char(72) not null, + product_options blob not null, + price decimal(9,2) not null, + shipping decimal(9,2) not null, + quantity int not null, + primary key (order_id, product_id) +); + +create table siteshop_order_status ( + order_id int not null, + ts datetime not null, + status enum('new','partly-shipped','shipped','cancelled') not null default 'new', + index (order_id, ts) +); + +create table siteshop_wishlist ( + id int not null auto_increment primary key, + user_id char(72) not null, + index (user_id) +); + +# wishlist-product join table +create table siteshop_wishlist_product ( + wishlist_id int not null, + product_id int not null, + primary key (wishlist_id, product_id) +); + +create table siteshop_sale ( + id int not null auto_increment primary key, + name char(78) not null, + start_date datetime not null, + until_date datetime not null, + index (start_date, until_date) +); + +# sale-product join table +create table siteshop_sale_product ( + sale_id int not null, + product_id int not null, + sale_price decimal(9,2) not null, + primary key (sale_id, product_id, sale_price) +); + +create table siteshop_tax ( + id int not null auto_increment primary key, + name char(72) not null, + rate decimal(2,2) default '0.0', + province char(2), + country char(2), + unique (province, country) +); + +create table siteshop_checkout_offer ( + id int not null auto_increment primary key, + offer_text char(128) not null, + offer_number int not null, + product_id int not null, + sale_price decimal(9,2) not null, + index (offer_number) +); + +create table siteshop_promo_code ( + id int not null auto_increment primary key, + code char(16) not null, + discount_type enum('percent','dollars') not null, + discount decimal(9,2) not null, + expires date not null, + unique (code), + index (expires) +); + +create table siteshop_country ( + code char(2) not null, + country char(72) not null, + active enum('yes','no') not null default 'yes', + primary key (code), + index (country) +); + +INSERT INTO siteshop_country (code, country, active) VALUES ('af', 'Afghanistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('al', 'Albania', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dz', 'Algeria', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('as', 'American Samoa', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ad', 'Andorra', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ao', 'Angola', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ai', 'Anguilla', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('aq', 'Antarctica', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ag', 'Antigua and Barbuda', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ar', 'Argentina', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('am', 'Armenia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('aw', 'Aruba', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('au', 'Australia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('at', 'Austria', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('az', 'Azerbaijan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bs', 'Bahamas', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bh', 'Bahrain', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bd', 'Bangladesh', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bb', 'Barbados', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('by', 'Belarus', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('be', 'Belgium', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bz', 'Belize', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bj', 'Benin', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bm', 'Bermuda', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bt', 'Bhutan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bo', 'Bolivia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ba', 'Bosnia and Herzegovina', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bw', 'Botswana', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bv', 'Bouvet Island', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('br', 'Brazil', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('io', 'British Indian Ocean Territory', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bn', 'Brunei Darussalam', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bg', 'Bulgaria', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bf', 'Burkina Faso', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('bi', 'Burundi', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kh', 'Cambodia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cm', 'Cameroon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ca', 'Canada', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cv', 'Cape Verde', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ky', 'Cayman Islands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cf', 'Central African Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('td', 'Chad', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cl', 'Chile', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cn', 'China', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cx', 'Christmas Island', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cc', 'Cocos (keeling) Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('co', 'Colombia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('km', 'Comoros', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cg', 'Congo', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cd', 'Congo, The Democratic Republic of the', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ck', 'Cook Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cr', 'Costa Rica', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ci', 'Cote D\'ivoire', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hr', 'Croatia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cu', 'Cuba', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cy', 'Cyprus', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cz', 'Czech Republic', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dk', 'Denmark', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dj', 'Djibouti', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('dm', 'Dominica', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('do', 'Dominican Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ec', 'Ecuador', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('eg', 'Egypt', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sv', 'El Salvador', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gq', 'Equatorial Guinea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('er', 'Eritrea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ee', 'Estonia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('et', 'Ethiopia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fk', 'Falkland Islands (malvinas)', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fo', 'Faroe Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fj', 'Fiji', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fi', 'Finland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fr', 'France', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gf', 'French Guiana', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pf', 'French Polynesia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tf', 'French Southern Territories', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ga', 'Gabon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gm', 'Gambia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ge', 'Georgia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('de', 'Germany', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gh', 'Ghana', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gi', 'Gibraltar', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gr', 'Greece', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gl', 'Greenland', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gd', 'Grenada', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gp', 'Guadeloupe', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gu', 'Guam', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gt', 'Guatemala', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gn', 'Guinea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gw', 'Guinea-bissau', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gy', 'Guyana', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ht', 'Haiti', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hm', 'Heard Island and Mcdonald Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('va', 'Holy See (Vatican City State)', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hn', 'Honduras', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hk', 'Hong Kong', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('hu', 'Hungary', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('is', 'Iceland', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('in', 'India', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('id', 'Indonesia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ir', 'Iran, Islamic Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('iq', 'Iraq', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ie', 'Ireland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('il', 'Israel', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('it', 'Italy', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('jm', 'Jamaica', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('jp', 'Japan', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('jo', 'Jordan', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kz', 'Kazakhstan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ke', 'Kenya', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ki', 'Kiribati', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kp', 'Korea, Democratic People\'s Republic of', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kr', 'Korea, Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kw', 'Kuwait', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kg', 'Kyrgyzstan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('la', 'Lao People\'s Democratic Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lv', 'Latvia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lb', 'Lebanon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ls', 'Lesotho', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lr', 'Liberia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ly', 'Libyan Arab Jamahiriya', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('li', 'Liechtenstein', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lt', 'Lithuania', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lu', 'Luxembourg', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mo', 'Macao', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mk', 'Macedonia, The Former Yugoslav Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mg', 'Madagascar', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mw', 'Malawi', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('my', 'Malaysia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mv', 'Maldives', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ml', 'Mali', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mt', 'Malta', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mh', 'Marshall Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mq', 'Martinique', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mr', 'Mauritania', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mu', 'Mauritius', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('yt', 'Mayotte', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mx', 'Mexico', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('fm', 'Micronesia, Federated States of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('md', 'Moldova, Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mc', 'Monaco', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mn', 'Mongolia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ms', 'Montserrat', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ma', 'Morocco', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mz', 'Mozambique', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mm', 'Myanmar', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('na', 'Namibia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nr', 'Nauru', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('np', 'Nepal', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nl', 'Netherlands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('an', 'Netherlands Antilles', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nc', 'New Caledonia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nz', 'New Zealand', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ni', 'Nicaragua', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ne', 'Niger', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ng', 'Nigeria', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nu', 'Niue', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('nf', 'Norfolk Island', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('mp', 'Northern Mariana Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('no', 'Norway', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('om', 'Oman', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pk', 'Pakistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pw', 'Palau', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ps', 'Palestinian Territory, Occupied', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pa', 'Panama', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pg', 'Papua New Guinea', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('py', 'Paraguay', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pe', 'Peru', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ph', 'Philippines', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pn', 'Pitcairn', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pl', 'Poland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pt', 'Portugal', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pr', 'Puerto Rico', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('qa', 'Qatar', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('re', 'Reunion', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ro', 'Romania', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ru', 'Russia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('rw', 'Rwanda', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sh', 'Saint Helena', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('kn', 'Saint Kitts and Nevis', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lc', 'Saint Lucia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('pm', 'Saint Pierre and Miquelon', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vc', 'Saint Vincent and the Grenadines', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ws', 'Samoa', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sm', 'San Marino', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('st', 'Sao Tome and Principe', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sa', 'Saudi Arabia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sn', 'Senegal', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('cs', 'Serbia and Montenegro', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sc', 'Seychelles', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sl', 'Sierra Leone', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sg', 'Singapore', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sk', 'Slovakia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('si', 'Slovenia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sb', 'Solomon Islands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('so', 'Somalia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('za', 'South Africa', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gs', 'South Georgia and the South Sandwich Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('es', 'Spain', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('lk', 'Sri Lanka', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sd', 'Sudan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sr', 'Suriname', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sj', 'Svalbard and Jan Mayen', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sz', 'Swaziland', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('se', 'Sweden', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ch', 'Switzerland', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('sy', 'Syrian Arab Republic', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tw', 'Taiwan', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tj', 'Tajikistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tz', 'Tanzania, United Republic of', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('th', 'Thailand', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tl', 'Timor-leste', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tg', 'Togo', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tk', 'Tokelau', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('to', 'Tonga', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tt', 'Trinidad and Tobago', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tn', 'Tunisia', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tr', 'Turkey', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tm', 'Turkmenistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tc', 'Turks and Caicos Islands', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('tv', 'Tuvalu', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ug', 'Uganda', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ua', 'Ukraine', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ae', 'United Arab Emirates', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('gb', 'United Kingdom', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('us', 'United States', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('um', 'United States Minor Outlying Islands', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('uy', 'Uruguay', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('uz', 'Uzbekistan', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vu', 'Vanuatu', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ve', 'Venezuela', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vn', 'Vietnam', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vg', 'Virgin Islands, British', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('vi', 'Virgin Islands, U.S.', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('wf', 'Wallis and Futuna', 'yes'); +INSERT INTO siteshop_country (code, country, active) VALUES ('eh', 'Western Sahara', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('ye', 'Yemen', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('zm', 'Zambia', 'no'); +INSERT INTO siteshop_country (code, country, active) VALUES ('zw', 'Zimbabwe', 'no'); + +create table siteshop_province ( + code char(2) not null, + country_code char(2) not null, + province char(72) not null, + active enum('yes','no') not null default 'yes', + primary key (code, country_code), + index (province) +); + +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ab', 'ca', 'Alberta'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('bc', 'ca', 'British Columbia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mb', 'ca', 'Manitoba'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nb', 'ca', 'New Brunswick'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nl', 'ca', 'Newfoundland and Labrador'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ns', 'ca', 'Nova Scotia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nt', 'ca', 'Northwest Territories'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nu', 'ca', 'Nunavut'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('on', 'ca', 'Ontario'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('pe', 'ca', 'Prince Edward Island'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('qc', 'ca', 'Quebec'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('sk', 'ca', 'Saskatchewan'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('yt', 'ca', 'Yukon'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('al', 'us', 'Alabama'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ak', 'us', 'Alaska'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('az', 'us', 'Arizona'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ar', 'us', 'Arkansas'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ca', 'us', 'California'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('co', 'us', 'Colorado'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ct', 'us', 'Connecticut'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('dc', 'us', 'District of Columbia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('de', 'us', 'Delaware'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('fl', 'us', 'Florida'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ga', 'us', 'Georgia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('hi', 'us', 'Hawaii'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('id', 'us', 'Idaho'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('il', 'us', 'Illinois'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('in', 'us', 'Indiana'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ia', 'us', 'Iowa'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ks', 'us', 'Kansas'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ky', 'us', 'Kentucky'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('la', 'us', 'Louisiana'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('me', 'us', 'Maine'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('md', 'us', 'Maryland'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ma', 'us', 'Massachusetts'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mi', 'us', 'Michigan'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mn', 'us', 'Minnesota'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ms', 'us', 'Mississippi'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mo', 'us', 'Missouri'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('mt', 'us', 'Montana'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ne', 'us', 'Nebraska'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nv', 'us', 'Nevada'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nh', 'us', 'New Hampshire'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nj', 'us', 'New Jersey'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nm', 'us', 'New Mexico'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ny', 'us', 'New York'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nc', 'us', 'North Carolina'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('nd', 'us', 'North Dakota'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('oh', 'us', 'Ohio'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ok', 'us', 'Oklahoma'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('or', 'us', 'Oregon'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('pa', 'us', 'Pennsylvania'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ri', 'us', 'Rhode Island'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('sc', 'us', 'South Carolina'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('sd', 'us', 'South Dakota'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('tn', 'us', 'Tennessee'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('tx', 'us', 'Texas'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('ut', 'us', 'Utah'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('vt', 'us', 'Vermont'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('va', 'us', 'Virginia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wa', 'us', 'Washington'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wv', 'us', 'West Virginia'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wi', 'us', 'Wisconsin'); +INSERT INTO siteshop_province (code, country_code, province) VALUES ('wy', 'us', 'Wyoming'); + create table deadlines ( id int not null auto_increment primary key, title char(72) not null, diff --git a/js/parallel.js b/js/parallel.js new file mode 100644 index 00000000..e4ae116a --- /dev/null +++ b/js/parallel.js @@ -0,0 +1,58 @@ +var parallel_script_url = false; +var parallel_page_id = false; +var parallel_revision_id = false; +var parallel_goal_url = false; +var parallel_rpc = new rpc (); + +// silence potential errors +parallel_rpc.setErrorHandler ( + function (error) { + return true; + } +); + +var parallel = { + url: '', + action: parallel_rpc.action, + + init: function (url) { + this.url = url; + if (parallel_goal_url != false && parallel_goal_url.length > 0) { + links = document.getElementsByTagName ('a'); + for (i = 0; i < links.length; i++) { + if (links[i].href == parallel_goal_url) { + links[i].oldClick = (links[i].onclick) ? links[i].onclick : function () {}; + links[i].onclick = function () { return (parallel.click () && this.oldClick ()); }; + } + } + } + }, + + click: function () { + parallel_rpc.call ( + this.action ('click', [parallel_page_id, parallel_revision_id]), + function (request) { + return true; + } + ); + return true; + } +} + +function parallel_onload (func) { + var oldonload = window.onload; + if (typeof window.onload != 'function') { + window.onload = func; + } else { + window.onload = function () { + if (oldonload) { + oldonload (); + } + func (); + } + } +} + +parallel_onload (function () { + parallel.init (parallel_script_url); +}); diff --git a/upgrade/5.0.1-5.0.2.sql b/upgrade/5.0.1-5.0.2.sql index 9085bde6..de9cc8f5 100644 --- a/upgrade/5.0.1-5.0.2.sql +++ b/upgrade/5.0.1-5.0.2.sql @@ -88,4 +88,6 @@ create table myadm_report_results ( alter table petition_signature change column province province char(2) not null; alter table petition_signature add column country char(2) not null after province; -alter table petition_signature change column postal_code postal_code char(10) not null; \ No newline at end of file +alter table petition_signature change column postal_code postal_code char(10) not null; + +alter table siteshop_category add column weight tinyint not null default 0;