[interchange-cvs] interchange - heins modified 5 files
interchange-core@icdevgroup.org
interchange-core@icdevgroup.org
Wed Aug 14 01:31:01 2002
User: heins
Date: 2002-08-14 05:30:09 GMT
Modified: . MANIFEST
Modified: dist/foundation/products variable.txt
Modified: dist/lib/UI/pages/include/menus Customers.txt
Added: dist/foundation/pages/query unsub.html
Added: dist/lib/UI/pages/admin customer_mailing.html
Log:
* Add cheesy mail list manager, a common thing to ask. Supported by unsubsc=
ribe
function and a batch download mode for large mailings....probably should
create some online help.
Revision Changes Path
2.51 +4 -0 interchange/MANIFEST
rev 2.51, prev_rev 2.50
Index: MANIFEST
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /var/cvs/interchange/MANIFEST,v
retrieving revision 2.50
retrieving revision 2.51
diff -u -r2.50 -r2.51
--- MANIFEST 7 Aug 2002 08:10:59 -0000 2.50
+++ MANIFEST 14 Aug 2002 05:30:08 -0000 2.51
@@ -443,6 +443,7 @@
dist/foundation/pages/query/get_password.html
dist/foundation/pages/query/order_detail.html
dist/foundation/pages/query/order_return.html
+dist/foundation/pages/query/unsub.html
dist/foundation/pages/results.html
dist/foundation/pages/results_big.html
dist/foundation/pages/returns.html
@@ -687,6 +688,7 @@
dist/lib/UI/pages/admin/customer_bill.html
dist/lib/UI/pages/admin/customer_change_pass.html
dist/lib/UI/pages/admin/customer_comments.html
+dist/lib/UI/pages/admin/customer_mailing.html
dist/lib/UI/pages/admin/customer_pref.html
dist/lib/UI/pages/admin/customer_select.html
dist/lib/UI/pages/admin/customer_ship.html
@@ -828,6 +830,7 @@
dist/lib/UI/pages/include/item_option_simple
dist/lib/UI/pages/include/menus/Accounting.txt
dist/lib/UI/pages/include/menus/Admin.txt
+dist/lib/UI/pages/include/menus/Bottom.txt
dist/lib/UI/pages/include/menus/Content.txt
dist/lib/UI/pages/include/menus/Customers.txt
dist/lib/UI/pages/include/menus/Design.txt
@@ -985,6 +988,7 @@
scripts/dump.PL
scripts/expire.PL
scripts/expireall.PL
+scripts/findtags.PL
scripts/ic_mod_perl.PL
scripts/interchange.PL
scripts/localize.PL
1.1 interchange/dist/foundation/pages/query/unsub.html
rev 1.1, prev_rev 1.0
Index: unsub.html
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
[comment]
ui_template: Yes
ui_template_name: leftonly
[/comment]
[tmp page_title]Trying to unsub....[/tmp]
[control reset=3D1]
[control-set]
[component]search_box_small[/component]
[/control-set]
[control-set]
[component]category_vertical[/component]
[/control-set]
[control reset=3D1]
@_LEFTONLY_TOP_@
<!-- BEGIN CONTENT -->
<table width=3D"95%">
<tr>
<td>
<p> </P>
<blockquote>
<H2>Trying to unsub you from the <b>[filter interpolate=3D1 op=3Dentities][=
cgi list][/filter]</b> list....</H2>
[flag type=3Dwrite table=3Duserdb]
[perl userdb]
my $db =3D $Db{userdb};
$Config->{NoSearch} =3D '';
my $who =3D $CGI->{who};
my $what =3D $CGI->{what};
$what =3D~ s/'/''/;
my $s_email =3D $Tag->filter('entities', $what);
$who =3D~ s/'/''/;
my $list =3D $CGI->{list};
my $s_list =3D $Tag->filter('entities', $list);
my $q =3D qq{
SELECT username,email,mail_list
FROM userdb
WHERE username =3D '$who'
AND email =3D '$what'
};
Debug("unsub query is : $q");
my $ary =3D $db->query($q);
if(! $ary) {
$who =3D $Tag->filter('entities', $who);
return "Sorry, error unsubscribing $s_email from list '$s_list'.";
}
elsif(! scalar(@$ary) ) {
return "Sorry, $s_email is not in our database under that user at all.";
}
my @out;
for(@$ary) {
my ($uname, $email, $lists) =3D @$_;
my @l =3D grep /\S/, split /[\s,\0]+/, $lists;
my $origlist =3D join " ", @l;
@l =3D grep $_ ne $list, @l;
my $newlist =3D join " ", @l;=20
if($newlist eq $origlist) {
push @out, "Sorry, $s_email is not on the '$s_list' list.";
next;
}
$db->set_field($uname, 'mail_list', $newlist);=20
push @out, "Removed $s_email from $s_list. Thanks for your time.";
}
return "<UL><LI>" . join("<LI>", @out) . "</UL>";
[/perl]
<!-- END CONTENT -->
@_LEFTONLY_BOTTOM_@
2.11 +3 -0 interchange/dist/foundation/products/variable.txt
rev 2.11, prev_rev 2.10
Index: variable.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /var/cvs/interchange/dist/foundation/products/variable.txt,v
retrieving revision 2.10
retrieving revision 2.11
diff -u -r2.10 -r2.11
--- variable.txt 12 Aug 2002 01:12:54 -0000 2.10
+++ variable.txt 14 Aug 2002 05:30:09 -0000 2.11
@@ -45,6 +45,9 @@
LINKHOVERDECO underline Catalog Colors and Style
LOGGED_STATIC 1 Static pages
LOGO __MVC_LOGO__ Template
+MAILING_MAX_DIRECT 50 Mailings
+MAILING_FROM __MVC_COMPANY__ <__MVC_EMAILSERVICE__> Mailings
+MAILING_TO {FNAME} {LNAME} <{EMAIL}> Mailings
MAINCONTENT_TEXT #000000 Catalog Colors and Style
MAINCONTENT_BG #FFFFFF Catalog Colors and Style
MAINCONTENT_FONT Helvetica Catalog Colors and Style
1.1 interchange/dist/lib/UI/pages/admin/customer_mailing.h=
tml
rev 1.1, prev_rev 1.0
Index: customer_mailing.html
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
@_UI_STD_INIT_@
[value name=3Dmv_data_table set=3Duserdb hide=3D1]
[if-mm !tables]
[set ui_error]
[L]Not authorized for customer administration. Contact administrator?[/L]
[/set]
[bounce page=3D"__UI_BASE__/error"]
[/if-mm]
[set ui_class]Customers[/set]
[set page_perm]mailing[/set]
@_UI_STD_HEAD_@
<!-- ----- BEGIN REAL STUFF ----- -->
<script>
function selfit (form, hide) {
if(hide =3D=3D undefined)
hide =3D 0;
form.hide_textarea.value =3D hide;
form.show_close.value =3D 0;
form.target =3D '_self';
return;
}
function blanktarg (form) {
form.hide_textarea.value =3D 1;
form.show_close.value =3D 1;
form.target =3D '_blank';
return;
}
function clearform (form) {
if(form =3D=3D undefined)
return;
selfit(form);
form.mail_to.value =3D '';
form.mail_subject.value =3D '';
form.mail_template.value =3D '';
form.mail_from.value =3D '';
form.mail_reply.value =3D '';
return true;
}
</script>
[calc]
my @actions =3D qw/
direct_send
download_batch
show_email
/;
my $die =3D sub {
my $msg =3D shift;
$msg =3D errmsg($msg, @_);
for(@actions) {
delete $CGI->{$_};
}
return "<blockquote class=3Dcerror>$msg</blockquote>";
};
if($CGI->{mv_action} and ! $Values->{mail_to}) {
return $die->("Reset to default.");
}
if($Values->{mail_subject} !~ /\w/) {
return $die->("No subject, cannot send.");
}
elsif ($Values->{mail_template} !~ /\w+.*\w+.*\n.*\w+/s) {
return $die->("No suitable message to send.");
}
return;
[/calc]
<form action=3D"[process download_name=3D"@@MV_PAGE@@.sh"]" method=3DPOST n=
ame=3Dmailform>
<INPUT TYPE=3Dhidden NAME=3Dmv_nextpage VALUE=3D"@@MV_PAGE@@">
<INPUT TYPE=3Dhidden NAME=3Dmv_session_id VALUE=3D"[data session id]">
<INPUT TYPE=3Dhidden NAME=3Dmv_action VALUE=3Dgo>
<INPUT TYPE=3Dhidden NAME=3Dhide_textarea VALUE=3D"">
<INPUT TYPE=3Dhidden NAME=3Dshow_close VALUE=3D"">
[perl tables=3D"userdb __UI_META_TABLE__"]
$Config->{NoSearch} =3D '';
my $ary =3D $Db{userdb}->query("select distinct mail_list from userdb");
my @lists;
for(@$ary) {
push @lists, split /[\s,\0]+/, $_->[0];
}
my %seen;
@lists =3D sort @lists;
@lists =3D grep !$seen{$_}++ && /\S/, @lists;
my $meta =3D $Tag->meta_record('userdb::mail_list');
my $options;
if($meta) {
$options =3D $meta->{options};
}
my @out;
$options =3D get_option_hash($options);
for(@lists) {
next if exists $options->{$_};
$options->{$_} =3D "$_ (???)";
$options->{$_} =3D~ s/,/)/g;
}
@lists =3D sort { $options->{$a} cmp $options->{$b} } @lists;
for(@lists) {
push @out, "$_=3D$options->{$_}";
}
$Scratch->{mail_list_options} =3D join ",", @out;
return;
[/perl]
[if cgi hide_textarea]
[if cgi show_close]
<input type=3Dbutton onClick=3D"window.close()" Value=3D"Close window">
[/if]
[else]
[calc]
$Values->{mail_to} ||=3D $Variable->{MAILING_TO}
|| "{FNAME} {LNAME} <{EMAIL}>";
$Values->{mail_from} ||=3D $Variable->{MAILING_FROM}
|| q{__COMPANY__ <__EMAIL_SERVICE__>};
my $burl =3D $Config->{VendURL};
my $unsub =3D "{MV_BASE_URL}?list=3D{MV_LIST}&what=3D{MV_EMAIL}&who=3D{US=
ERNAME}";
$Values->{mail_template} =3D~ s/\s+$//;
$Values->{mail_template} =3D~ s/\r\n/\n/g;
$Values->{mail_template} ||=3D $Variable->{MAILING_TEMPLATE}
|| qq{Dear {FNAME} {LNAME},
=09=09
<replace with body of message>
Best Regards,
__COMPANY__ Customer Service
Note: You subscribed to this list ({MV_LIST}) when you placed an order at
our web site at $burl. You can unubscribe at any time with the
URL:
$unsub
Thanks for your business!
};
return;
[/calc]
<table>
<tr>
<td>
From:
</td>
<td>
<input
name=3Dmail_from
type=3Dtext
size=3D50
maxlength=3D"70"
value=3D"[value name=3Dmail_from filter=3Dentities]"
>
</td>
</tr>
<tr>
<td>
To:
</td>
<td>
<input
name=3Dmail_to
type=3Dtext
size=3D40
maxlength=3D"70"
value=3D"[value name=3Dmail_to filter=3Dentities]"
>
</td>
</tr>
<tr>
<td>
Subject:
</td>
<td>
<input
name=3Dmail_subject
type=3Dtext
size=3D50
maxlength=3D"70"
value=3D"[value name=3Dmail_subject filter=3Dentities]"
>
</td>
</tr>
<tr>
<td>
Reply-To:
</td>
<td>
<input
name=3Dmail_reply
type=3Dtext
size=3D40
maxlength=3D"70"
value=3D"[value name=3Dmail_reply filter=3Dentities]"
> <I>(blank is same as From)</i>
</td>
</tr>
<tr>
<td colspan=3D2>
<TEXTAREA name=3Dmail_template cols=3D80 rows=3D15>[value name=3Dmail_templ=
ate filter=3Dentities]</textarea>
</p>
<b><u>Mailing List</u>:</b><br>
[display default=3D"[cgi target_list]" name=3Dtarget_list type=3Dselect opt=
ions=3D"[scratch mail_list_options]"]
<input
type=3Dsubmit
name=3Dshow_members
onClick=3D"selfit(this.form)"
value=3D"Show list members and select"
>
<input
type=3Dbutton
onClick=3D"confirm('Reset to defaults?') && clearform(this.form) && this=
form.submit()"
value=3D"Clear form"
>
</td>
</tr>
</table>
[/else]
[/if]
</td>
</tr>
</table>
<br>
[if cgi mail_template]<!-- update: [update values]-->[/if]
[if cgi show_members]
<div style=3D"
Height: 100px;
Margin-left: 5%;
Width: 600px;
Overflow: auto;
">[tmpn tmp_seen][/tmpn]
[loop search=3D"
fi=3Duserdb
st=3Ddb
co=3Dyes
op=3Drm
ml=3D1000
sf=3Dmail_list
tf=3Dlname
se=3D[cgi target_list]
rf=3Dusername,fname,lname,company,email,mail_list
"]=20
[loop-sub sent_check]
$tmp_url ||=3D $Tag->area({
href =3D> '__UI_BASE__/customer_view',
form =3D> "view=3D1",
});
$tmp_struct ||=3D $Scratch->{sent_ids} ||=3D {};
my $stuff =3D shift;
my $row =3D shift;
my $list =3D $CGI->{target_list};
my $user =3D $row->[0];
if (my $s =3D $tmp_struct->{$user}) {
return if $s =3D~ /\s$list\s/;
}
$Scratch->{tmp_seen}++;
my $url =3D $tmp_url . '&' . "customer=3D$user";
$stuff =3D~ s/HREF=3D""/href=3D"$url"/;
return $stuff;
[/loop-sub][loop-exec sent_check]
<input type=3Dcheckbox name=3Dproduce value=3D"[loop-code]" CHECKED><A href=
=3D"mailto:[loop-param email]">[loop-param email]</A> -- [loop-param fname]=
[loop-param lname][if-loop-param company], [loop-param company][/if-loop-p=
aram] (<A HREF=3D"">[loop-code]</A>)<br>
[/loop-exec][/loop]
[if !scratch tmp_seen]
<blockquote style=3D"font-size: larger">
You have already sent email to all users on this list. You should not send =
more
than one message per day at the very top! Once a month is more appropriate.=
Imagine
if someone sent you mail every day!
<P>
You will have to turn off your browser or cancel your session to send
mail to this list again. And it be on your head...
</blockquote>
[/if]
</div>
<div style=3D"margin-left: 5%">
<P>
<A HREF=3D"javascript:checkAll(document.mailform, 'produce', 0)"><img src=
=3D"__UI_IMG__box_checked.gif" border=3D0>Check all</A> &n=
bsp;
<A HREF=3D"javascript:checkAll(document.mailform, 'produce', 1)"><img src=
=3D"__UI_IMG__box_empty.gif" border=3D0>Uncheck all</A>
</p>
<p>
<input type=3Dsubmit name=3Dshow onClick=3D"blanktarg(this.form)" value=3D"=
Preview email">
<input type=3Dsubmit name=3Ddownload_batch onClick=3D"selfit(this.form, 1)"=
value=3D"Download Mail Batch">
[if value mv_search_match_count > 50]
(too many matches to send directly)
[else]
<input type=3Dsubmit name=3D"direct_send" onClick=3D"selfit(this.form, 1)" =
value=3D"Send now">
[/else]
[/if]
</div>
[elsif cgi produce]
<div style=3D"margin-left: 5%">
[perl]
my @list =3D grep /\S/, split /[\s,\0]+/, $CGI->{produce};
my @messages;
my @out;
my $list =3D $CGI->{target_list};
my $opt =3D { table =3D> 'userdb', hash =3D> 1};
my $body =3D $Values->{mail_template};
$body =3D~ s/\r\n/\n/g;
$body =3D~ s/\r/\n/g;
$template =3D "From: $Values->{mail_from}\n";
$template .=3D "To: $Values->{mail_to}\n";
$template .=3D "Subject: $Values->{mail_subject}\n";
$template .=3D "Reply-To: $Values->{mail_reply}\n"
if $Values->{mail_reply} =3D~ /\w\w+/;
$template .=3D "\n$body";
my $burl =3D $Variable->{MAILING_UNSUB} || "$Config->{VendURL}/query/unsu=
b";
for my $user (@list) {
$opt->{key} =3D $user;
my $record =3D $Tag->data($opt);
next unless $record;
$record->{mv_base_url} =3D $burl;
$record->{mv_email} =3D $Tag->filter('urlencode', $record->{email});
$record->{mv_list} =3D $list;
my $msg =3D $Tag->uc_attr_list($record, $template);
$msg =3D~ s/\s*$/\n/;
push @messages, [ $user, $msg ];
}
my $out;
return if ! @messages;
if($CGI->{direct_send}) {
my $max =3D $Variable->{MAIL_MAX_DIRECT} || 5;
if( scalar(@out) > $max ) {
my $msg =3D errmsg("Too many addresses for direct send, max %s!", $max);
return "<blockquote class=3Dcerror>$max</blockquote>";
}
my $s =3D $Scratch->{sent_ids} ||=3D {};
for(@messages) {
my ($u, $b) =3D @$_;
if( $s->{$u} =3D~ /\s$list\s/) {
push @out, errmsg("Already sent %s email to %s", $list, $u);
}
else {
my $msg =3D errmsg("Send to %s: ", $u);
my $opt =3D { raw =3D> 1, body =3D> $b };
if( $Tag->email_raw({}, $b) ) {
$msg .=3D errmsg('success');
$s->{$u} ||=3D '';
$s->{$u} .=3D " $list ";
}
else {
$msg .=3D errmsg('FAILED');
}
push @out, $msg;
}
}
$out =3D join "<br>\n", @out;
$Tag->log({
type =3D> 'text',
file =3D> 'logs/mailing',
body =3D> join("\n",
$Tag->time({format =3D> '%c'}),
"Sent mailing to list '$list':\n",
$template,
"\nResults:\n",
@out,
'####END MAILING ####',
''),
});
}
elsif($CGI->{download_batch}) {
@out =3D map { $_->[1] } @messages;
$out =3D "#!/bin/sh\n\ncat <<EOF | sendmail -t\n";
$out .=3D join "EOF\n\ncat <<EOF | sendmail -t\n", @out;
$out .=3D "EOF\n\n";
$Tag->deliver( { body =3D> \$out } );
$Tag->tmpn('delivered_mail_batch');
$Scratch->{delivered_mail_batch} =3D 1;
return;
}
else {
@out =3D map { $_->[1] } @messages;
my $divintro =3D q{<div style=3D"width: 80%; border: 2pt gray solid; bac=
kground: #EEEEEE; "><xmp>};
my $divend =3D qq{</xmp></div>\n};
$out =3D $divintro;
$out .=3D join "$divend$divintro", @out;
$out .=3D $divend;
}
return $out;
[/perl]
</div>
[/elsif]
[/if]
[if cgi show_close]
<p>
<input type=3Dbutton onClick=3D"window.close()" Value=3D"Close window">
[/if]
</form>
<!-- ----- END REAL STUFF ----- -->
@_UI_STD_FOOTER_@
<!-- page: @@MV_PAGE@@ -->
1.2 +8 -7 interchange/dist/lib/UI/pages/include/menus/Customers.=
txt
rev 1.2, prev_rev 1.1
Index: Customers.txt
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /var/cvs/interchange/dist/lib/UI/pages/include/menus/Customers.tx=
t,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Customers.txt 7 Aug 2002 08:11:00 -0000 1.1
+++ Customers.txt 14 Aug 2002 05:30:09 -0000 1.2
@@ -2,10 +2,11 @@
001 Customers x001 showactive! admin/customer showactive=3D1 Active Cus=
tomers 0 1
002 Customers x002 showinactive! admin/customer showinactive=3D1 Inacti=
ve Customers 0 1
003 Customers x003 admin/flex_editor page_title=3DCreate new customer&=
mv_data_table=3Duserdb&help_name=3Dcreate.new.customer&ui_new_item=3D1&ui_r=
eturn_to=3Dadmin/customer Create new customer 0=09=09=09=09=09=09=09=09
-004 Customers x004 1 deletecustomer customer admin/customer_view customer=
=3D[cgi customer] View 0=09=09=09=09=09=09=09=09
-005 Customers x005 deletecustomer customer admin/customer_ship customer=
=3D[cgi customer] Shipping 0=09=09=09=09=09=09=09=09
-006 Customers x006 deletecustomer customer admin/customer_bill customer=
=3D[cgi customer] Billing 0=09=09=09=09=09=09=09=09
-007 Customers x007 deletecustomer customer admin/customer_comments custo=
mer=3D[cgi customer] Feedback 0=09=09=09=09=09=09=09=09
-008 Customers x008 deletecustomer customer admin/customer_all customer=
=3D[cgi customer] All 0=09=09=09=09=09=09=09=09
-009 Customers x009 deletecustomer customer admin/customer_pref customer=
=3D[cgi customer] Preferences 0=09=09=09=09=09=09=09=09
-010 Customers x010 deletecustomer customer admin/entry customer=3D[cgi c=
ustomer] Enter Order 0=09=09=09=09=09=09=09=09
+004 x004 admin/customer_mailing Customer Mailing 0 Send mail to all=
customers on a list=09=09=09=09=09=09=09
+005 Customers x005 1 deletecustomer customer admin/customer_view customer=
=3D[cgi customer] View 0=09=09=09=09=09=09=09=09
+006 Customers x006 deletecustomer customer admin/customer_ship customer=
=3D[cgi customer] Shipping 0=09=09=09=09=09=09=09=09
+007 Customers x007 deletecustomer customer admin/customer_bill customer=
=3D[cgi customer] Billing 0=09=09=09=09=09=09=09=09
+008 Customers x008 deletecustomer customer admin/customer_comments custo=
mer=3D[cgi customer] Feedback 0=09=09=09=09=09=09=09=09
+009 Customers x009 deletecustomer customer admin/customer_all customer=
=3D[cgi customer] All 0=09=09=09=09=09=09=09=09
+010 Customers x010 deletecustomer customer admin/customer_pref customer=
=3D[cgi customer] Preferences 0=09=09=09=09=09=09=09=09
+011 Customers x011 deletecustomer customer admin/entry customer=3D[cgi c=
ustomer] Enter Order 0=09=09=09=09=09=09=09=09