root/trunk/htdocs/talkpost_do.bml @ 994

Revision 994, 31.7 KB (checked in by bradfitz, 11 years ago)

<lj user=avva>:
This patch does two things:

1. Correctly encodes Subject: fields in emails as per RFC2047.
Note it uses MIME::Words , which should be on all our servers (I think
it's part of the standard distribution, but it's better to check).
2. Inserts a meta tag with encoding information in the beginning of
the HTML part of the email (some mail readers aren't smart enough to
apply the Content-type: information already there in the MIME header
to HTML attachments, so this gives them a clue).

Tested.

<lj user=bradfitz>:
the lj-bml-init/INSTALL changes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1(=PAGE
2TITLE=>Post Comment
3BODY<=
4
5(=_CODE
6
7 use strict;
8 use vars qw(%FORM);
9
10 foreach my $re (@LJ::TALKSPAM) {
11     return if ($FORM{'body'} =~ /$re/);
12 }
13
14 return LJ::server_down_html() if ($LJ::SERVER_DOWN);
15
16 # as an exception, we do NOT call LJ::text_in() to check for bad
17 # input, since it may be not in UTF-8 in replies coming from mail
18 # clients. We call it later.
19
20
21 $Text::Wrap::columns = 76;
22 my $dbs = LJ::get_dbs();
23 my $dbh = $dbs->{'dbh'};
24 my $dbr = $dbs->{'reader'};
25 my $sth;
26
27 my $remote = LJ::get_remote($dbs);
28
29 my $init = LJ::Talk::init($dbs, \%FORM);
30 my $u = $init->{'journalu'};
31
32 return "(=H1 Error H1=)(=P $init->{'error'} P=)" if $init->{'error'};
33 return "Error: couldn't determine journal from arguments." unless $u;
34 return $LJ::MSG_READONLY_USER if LJ::get_cap($u, "readonly");
35
36 my $pics = LJ::Talk::get_subjecticons();
37 my $clustered = $init->{'clustered'};
38
39 my ($dbcs, $dbcm, $dbcr) = ($dbs, $dbh, $dbr);
40 if ($clustered) {
41     $dbcs = LJ::get_cluster_set($u);
42     $dbcm = $dbcs->{'dbh'};
43     $dbcr = $dbcs->{'reader'};
44 }
45
46 return $LJ::MSG_READONLY_USER unless $dbcm && $dbh;
47 return "Database temporarily unavailable" unless $dbcr && $dbr;
48
49 my $jarg = $clustered ? "journal=$u->{'user'}&" : "";
50 my $jargent = $clustered ? "journal=$u->{'user'}&amp;" : "";
51
52 my $ret = "";
53 my @errors = ();
54
55 my ($DEBUG, $debug) = (0, "");  # flag, data
56
57 # start quoting shit to insert
58 my $itemid = $init->{'itemid'}+0;
59
60 my $item = LJ::Talk::get_journal_item($dbs, $dbcs, $u, $itemid);
61
62 if ($init->{'oldurl'} && $item) {
63     $init->{'anum'} = $item->{'anum'};
64     $init->{'ditemid'} = $init->{'itemid'}*256 + $item->{'anum'};
65 }
66
67 unless ($item && $item->{'anum'} == $init->{'anum'}) {
68     return "(=H1 Error H1=)(=P No such entry. P=)";
69 }
70
71 my %logprops = %{$item->{'logprops'}};
72 my $ditemid = $init->{'ditemid'}+0;
73
74 ### load users
75 my $ujp;                 # poster of item
76 LJ::load_userids_multiple($dbs, [
77                                  $item->{'posterid'} => \$ujp,
78                                  ], [ $u ]);
79 my ($quser, $qjpuser) = map { $dbr->quote($_) } ($u->{'user'}, $ujp->{'user'});
80 LJ::load_user_props($dbs, $u, "opt_logcommentips");
81
82 if ($FORM{'userpost'} && $FORM{'usertype'} ne "user") {
83     push @errors, "You entered a username, but selected to post anonymously or as the currently logged in user.  Go back and decide which you really want to do.";
84 }
85
86 my $cookie_auth;
87 if ($FORM{'usertype'} eq "cookieuser") {
88     push @errors, "Your login cookie seems to have disappeared?"
89         unless ($remote && $remote->{'user'} eq $FORM{'cookieuser'});
90     return LJ::bad_input(@errors) if @errors;
91     
92     $cookie_auth = 1;
93     $FORM{'userpost'} = $remote->{'user'};
94     $FORM{'usertype'} = "user";
95 }
96
97 if ((grep { $FORM{'userpost'} eq $_ } @LJ::TESTACCTS) && !
98     (grep { $u->{'user'}      eq $_ } @LJ::TESTACCTS))
99 {
100     push @errors, "Test accounts can only be used in test account journals.";
101 }
102
103 my $userpost = lc($FORM{'userpost'});
104 my $up;
105 my $didlogin = 0;      # true if user logged in while commenting
106
107 if ($FORM{'usertype'} eq "user") {
108     if ($FORM{'userpost'}) {
109         $up = LJ::load_user($dbs, $FORM{'userpost'});
110         if ($up)
111         {
112             ### see if the user is banned from posting here
113             if (LJ::is_banned($dbr, $up, $u)) {
114                 push @errors, "You are not allowed to post in this user's journal.";
115             }
116
117             if ($up->{'journaltype'} ne "P") {
118                 push @errors, "You can't post as a shared or community account.  ".
119                     "Shared accounts represent groups of people, not individual people.";
120             }
121
122             unless ($cookie_auth ||
123                     LJ::auth_okay($up, $FORM{'password'}, $FORM{'hpassword'}) ||
124                     ecphash($itemid, $FORM{'parenttalkid'},
125                             $up->{'password'}) eq $FORM{'ecphash'} )
126             {
127                 push @errors, "Incorrect password given for the username ".
128                     " specified.  You can recover your password <a href=\"/lostinfo.bml\">here</a> ".
129                     "if you've forgotten it.";
130             }
131
132             # if the user chooses to log in, do so (patch by: lucretio)
133             if ($FORM{'do_login'} && ! @errors) {
134                 my $hp = $FORM{'hpassword'} || LJ::hash_password($FORM{'password'});
135                 my $etime = 0;
136                 BMLClient::set_cookie("ljuser", $up->{'user'}, $etime, $LJ::COOKIE_PATH, $LJ::COOKIE_DOMAIN);
137                 BMLClient::set_cookie("ljhpass", "$up->{'user'}:$hp", $etime, $LJ::COOKIE_PATH, $LJ::COOKIE_DOMAIN);
138
139                 LJ::run_hooks("post_login", {
140                     "u" => $up,
141                     "form" => \%FORM,
142                     "expiretime" => $etime,
143                 });
144
145                 $BMLClient::COOKIE{"ljuser"} = $up->{'user'};
146                 $BMLClient::COOKIE{"ljhpass"} = "$up->{'user'}:$hp";
147
148                 $didlogin = 1;
149             }
150
151         } else {
152             push @errors, "The LiveJournal username you specified does not exist.  You can recover your username <a href=\"/lostinfo.bml\">here</a> if you've forgotten it, or you may post as \"Anonymous\" instead.";
153         }
154     } else {
155         push @errors, "You did not enter your LiveJournal username.  You can choose to post as \"Anonymous\" if you don't have a LiveJournal user account.";
156     }
157 }
158
159 # check that user can even view this post, which is required
160 # to reply to it
161 ####  Check security before viewing this post
162 unless (LJ::can_view($dbs, $up, $item)) {
163     push @errors, "You must be logged in or using a username/password to reply to this protected entry."
164         unless (defined $up);
165     push @errors, "You are not authorized to reply to this protected entry.";
166     return LJ::bad_input(@errors);     
167 }
168
169 if ($FORM{'usertype'} ne "user" && $u->{'opt_whocanreply'} ne "all") {
170     push @errors, "You can't post anonymously in this person's journal.";
171 }
172
173 if ($logprops{$itemid}->{'opt_nocomments'}) {
174     push @errors, "User has disabled commenting on this journal entry.";
175 }
176
177 if ($up && $up->{'status'} eq "N") {
178     push @errors, "Sorry, you aren't allowed to post comments in other people's journals until your email address has been verified.  If you've lost the confirmation email to do this, you can have it resent from the <a href=\"/lostinfo.bml\">lost information page</a>.";
179 }
180
181 if ($up && $up->{'statusvis'} eq "D") {
182     push @errors, "Your journal has been deleted.  You can't post messages.";
183 }
184 if ($up && $up->{'statusvis'} eq "S") {
185     push @errors, "Your journal has been suspended.  You can't post messages.";
186 }
187
188 if ($u->{'opt_whocanreply'} eq "friends") {
189     if ($up) {
190         if ($up->{'userid'} != $u->{'userid'})
191         {
192             unless (LJ::is_friend($dbs, $u, $up)) {
193                 push @errors, "Sorry, user <B>$u->{'user'}</B> does not list you as a friend, and they've set the \"friends only\" option for who can reply to their journal.";
194             }
195         }
196     } else {
197         push @errors, "Only friends of <B>$u->{'user'}</B> may post in this journal.";
198     }
199 }
200
201 unless ($FORM{'body'} =~ /\S/) {
202     push @errors, "Your message was blank.  Please type at least something in the message field.";
203 }
204
205 # in case this post comes directly from the user's mail client, it
206 # may have an encoding field for us.
207 if ($FORM{'encoding'}) {
208     $FORM{'body'} = Unicode::MapUTF8::to_utf8({-string=>$FORM{'body'}, -charset=>$FORM{'encoding'}});
209     $FORM{'subject'} = Unicode::MapUTF8::to_utf8({-string=>$FORM{'subject'}, -charset=>$FORM{'encoding'}});
210 }
211 
212 # now check for UTF-8 correctness, it must hold
213
214 return "(=BADINPUT=)" unless LJ::text_in(\%FORM);
215
216 my $unknown8bit = 0;
217 unless (LJ::is_ascii($FORM{'body'}) && LJ::is_ascii($FORM{'subject'})) {
218     if ($LJ::UNICODE) {
219         # no need to check if they're well-formed, we did that above
220     } else {
221         # so rest of site can change chars to ? marks until
222         # default user's encoding is set.  (legacy support)
223         $unknown8bit = 1;
224     }
225 }
226
227 my $max_length = 2000;
228 my $length = length($FORM{'body'});
229 if ($userpost) { $max_length = 4000; }
230 if ($length > $max_length) {
231     push @errors, "Sorry, but your comment of length $length exceeds the maximum allowed length of $max_length.  Please go back, shorten it, and try posting it again.";
232 }
233
234 return LJ::bad_input(@errors) if @errors;
235
236 ###################################################3
237
238 my $textsubject = $FORM{'subject'};
239 LJ::CleanHTML::clean_subject_all(\$textsubject);
240 my $cleansubject = $FORM{'subject'};
241 LJ::CleanHTML::clean_subject(\$cleansubject);
242
243 ## preview
244
245 if ($FORM{'submitpreview'}) {
246     $ret .= "(=H1 Preview H1=)(=P Below is how your post will look.  Press your browser's back button to make changes. Or, submit it. P=)(=HR=)";
247
248     my $event = $FORM{'body'};
249     LJ::CleanHTML::clean_comment(\$event, $FORM{'prop_opt_preformatted'});
250
251     $ret .= "<b>Subject: </b> $cleansubject<hr>\n";
252     $ret .= $event;
253
254     $ret .= "<hr />";
255     $ret .= "<form method='post'>\n";
256     # change mode:
257     delete $FORM{'submitpreview'}; $FORM{'submitpost'} = 1;
258     if ($cookie_auth) {
259         $FORM{'usertype'} = "cookieuser";
260         delete $FORM{'userpost'};
261     }
262     foreach (keys %FORM) {
263         $ret .= "<input type='hidden' name=\"$_\" value=\"" . LJ::ehtml($FORM{$_}) . "\">\n";
264     }
265
266     $ret .= "<input type='submit' value='Submit'>\n";
267     $ret .= "</form>";
268     return $ret;
269 }
270
271 ## insertion
272
273 $FORM{'subject'} = LJ::text_trim($FORM{'subject'}, 100, 100);
274 $FORM{'body'} = LJ::text_trim($FORM{'body'}, $LJ::BMAX_COMMENT, $LJ::CMAX_COMMENT);
275
276 my $partid = $FORM{'parenttalkid'};
277 my $qpartid = $dbh->quote($partid);
278 my $qsubject = $dbh->quote($FORM{'subject'});
279 my $subjecticon = ($FORM{'subjecticon'} eq "none" || $FORM{'subjecticon'} eq "") ? "" : LJ::trim(lc($FORM{'subjecticon'}));
280 my $qbody = $dbh->quote($FORM{'body'});
281 my $datepost = LJ::mysql_time();
282 my $qdatepost = $dbh->quote($datepost);
283 my $icon = LJ::Talk::show_image($pics, $subjecticon);
284
285 my $insertid;
286 my $dtalkid;
287 my $md5_body = md5_hex($FORM{'body'});
288 
289 ### check for duplicate entry (double submission)
290 my $posterid = $up ? $up->{'userid'} : 0;
291 if ($clustered)
292 {
293     $insertid = $dbcm->selectrow_array
294         (
295          "SELECT t.jtalkid FROM talk2 t, talktext2 tt WHERE ".
296          "t.journalid=$u->{'userid'} AND tt.journalid=$u->{'userid'} ".
297          "AND t.jtalkid=tt.jtalkid ".
298          "AND t.nodetype='L' AND t.nodeid=$itemid ".
299          "AND t.posterid=$posterid AND tt.subject=$qsubject AND MD5(tt.body)='$md5_body' ".
300          "AND t.parenttalkid=$qpartid"
301          );
302 } else {
303     $insertid = $dbh->selectrow_array
304         (
305          "SELECT t.talkid FROM talk t, talktext tt WHERE t.talkid=tt.talkid ".
306          "AND t.journalid=$u->{'userid'} AND t.nodetype='L' AND t.nodeid=$itemid ".
307          "AND t.posterid=$posterid AND tt.subject=$qsubject AND MD5(tt.body)='$md5_body' ".
308          "AND t.parenttalkid=$qpartid"
309          );
310 }
311 
312 # they don't have a duplicate...
313 unless ($insertid)
314 {
315     # insert the comment
316     my $table = $clustered ? "talk2" : "talk";
317     my $now = $dbcm->selectrow_array("SELECT NOW()");
318     $sth = $dbcm->prepare("INSERT INTO $table (nodetype, nodeid, parenttalkid, ".
319                           "journalid, posterid, datepost) ".
320                           "VALUES ('L', $itemid, $qpartid, ".
321                           "$u->{'userid'}, $posterid, '$now')");
322     $sth->execute;
323     
324     # uh oh?  is there an error?  show them if there is.
325     if ($dbcm->err) {
326         return "<h2>Database Error</h2>There was an error posting your comment to the database.  Please report this to <b>$LJ::SUPPORT_EMAIL</b>.  The error is: <b>" . $dbcm->errstr . "</b>";
327     }
328     
329     # what's the tid of the newly inserted message?
330     $insertid = $sth->{'mysql_insertid'};
331
332     # add to poster's talkleft table, or the xfer place
333     if ($posterid && $clustered) {
334         my ($db, $table) = ($dbh, "talkleft_xfp");
335         if ($up->{'clusterid'}) {
336             $db = LJ::get_cluster_master($up);
337             if ($db) {
338                 # remote's cluster is writable
339                 $table = "talkleft";
340             } else {
341                 # do it later, as if user was not yet clustered
342                 $db = $dbh;
343             }
344         }
345         my $pub  = $item->{'security'} eq "public" ? 1 : 0;
346         $db->do("INSERT INTO $table (userid, posttime, journalid, nodetype, ".
347                 "nodeid, jtalkid, publicitem) VALUES ($posterid, UNIX_TIMESTAMP('$now'), ".
348                 "$u->{'userid'}, 'L', $init->{'itemid'}, $insertid, '$pub')");
349     }
350
351     if ($clustered) {
352         $dbcm->do("INSERT INTO talktext2 (journalid, jtalkid, subject, body) ".
353                   "VALUES ($u->{'userid'}, $insertid, $qsubject, $qbody)");
354         die $dbcm->errstr if $dbcm->err;
355     } else {
356         my @prefix = ("");
357         if ($LJ::USE_RECENT_TABLES) { push @prefix, "recent_"; }
358         foreach my $pfx (@prefix) {
359             $dbh->do("INSERT INTO ${pfx}talktext (talkid, subject, body) ".
360                      "VALUES ($insertid, $qsubject, $qbody)");
361         }
362     }
363
364     # dudata
365     if ($clustered) {
366         my $bytes = length($FORM{'subject'}) + length($FORM{'body'});
367         LJ::dudata_set($dbcm, $u->{'userid'}, 'T', $insertid, $bytes);
368     }
369
370     my %talkprop;   # propname -> value
371
372
373     # meta-data
374     $talkprop{'unknown8bit'} = 1 if $unknown8bit;
375     $talkprop{'subjecticon'} = $subjecticon;
376     $talkprop{'picture_keyword'} = $FORM{'prop_picture_keyword'};
377     $talkprop{'opt_preformatted'} = $FORM{'prop_opt_preformatted'} ? 1 : 0;
378     if ($u->{'opt_logcommentips'} eq "A" ||
379         ($u->{'opt_logcommentips'} eq "S" && $FORM{'usertype'} ne "user"))
380     {
381         my $ip = $ENV{'REMOTE_ADDR'};
382         if ($ENV{'HTTP_X_FORWARDED_FOR'}) { $ip = "$ENV{'HTTP_X_FORWARDED_FOR'}, via $ip"; }
383         $talkprop{'poster_ip'} = $ip;
384
385     }
386
387     # remove blank/0 values (defaults)
388     foreach (keys %talkprop) { delete $talkprop{$_} unless $talkprop{$_}; }
389
390     LJ::load_props($dbs, "talk");
391     if (%talkprop) {
392         my $values;
393         foreach (keys %talkprop) {
394             my $p = LJ::get_prop("talk", $_);
395             next unless $p;
396             my $tpropid = $p->{'tpropid'};
397             my $qv = $dbh->quote($talkprop{$_});
398             if ($clustered) {
399                 $values .= "($u->{'userid'}, $insertid, $tpropid, $qv),";
400             } else {
401                 $values .= "($insertid, $tpropid, $qv),";
402             }
403         }
404         if ($values) {
405             chop $values;
406             if ($clustered) {
407                 $dbcm->do("INSERT INTO talkprop2 (journalid, jtalkid, tpropid, value) ".
408                           "VALUES $values");
409             } else {
410                 $dbcm->do("INSERT INTO talkprop (talkid, tpropid, value) ".
411                           "VALUES $values");
412             }
413             die $dbcm->errstr if $dbcm->err;
414         }
415     }
416     
417     # update the "replycount" summary field of the log table
418     if ($clustered) {
419         $dbcm->do("UPDATE log2 SET replycount=replycount+1 WHERE ".
420                   "journalid=$u->{'userid'} AND jitemid=$itemid");
421     } else {
422         LJ::query_buffer_add($dbh, "log", "UPDATE log SET replycount=replycount+1 WHERE itemid=$itemid");     
423     }
424
425     # log the event
426     if ($clustered) {
427         LJ::event_register($dbs, $dbcm, "R", $u->{'userid'}, $ditemid);
428         # FUTURE: log events type 'T' (thread) up to root
429     }
430     
431     # send some emails
432     my $who = $up->{'name'} || "Somebody";
433     my $whouser = $up->{'user'} ? " ($up->{'user'})" : "";
434     my $whouserhtml = $up->{'user'} ? " (<a href=\"$LJ::SITEROOT/userinfo.bml?user=$up->{'user'}\">$up->{'user'}</a>)" : "";
435     my $whopic;
436     if ($up->{'defaultpicid'} || $FORM{'prop_picture_keyword'}) {
437         my $picid;
438         if ($FORM{'prop_picture_keyword'}) {
439             my $qkw = $dbr->quote($FORM{'prop_picture_keyword'});
440             $picid = $dbr->selectrow_array("SELECT m.picid FROM userpicmap m, keywords k ".
441                                            "WHERE m.userid=$up->{'userid'} AND m.kwid=k.kwid ".
442                                            "AND k.keyword=$qkw");
443         }
444         $picid ||= $up->{'defaultpicid'};
445         if ($picid) {
446             my %pics;
447             LJ::load_userpics($dbs, \%pics, [ $picid ]);
448             $whopic = "<img src=\"$LJ::SITEROOT/userpic/$picid\" align='absmiddle' ".
449                 "width='$pics{$picid}->{'width'}' height='$pics{$picid}->{'height'}' ".
450                 "hspace='1' vspace='2'> ";
451         }
452     }
453
454     # check to see if parent post is from a registerd livejournal user, and
455     # mail them the response
456     my $parentcomment = "";
457     my $parentmailed = "";  # who if anybody was just mailed
458
459     if ($partid)
460     { 
461         if ($clustered) {
462             $sth = $dbcm->prepare("SELECT t.posterid, tt.body FROM talk2 t, talktext2 tt ".
463                                   "WHERE t.journalid=$u->{'userid'} AND tt.journalid=$u->{'userid'} ".
464                                   "AND t.jtalkid=$qpartid AND tt.jtalkid=$qpartid");
465         } else {
466             $sth = $dbh->prepare("SELECT t.posterid, tt.body FROM talk t, talktext tt ".
467                                  "WHERE t.talkid=$qpartid AND tt.talkid=$qpartid");
468         }
469         $sth->execute;
470         my ($paruserid, $parbody) = $sth->fetchrow_array;
471         $parentcomment = $parbody;
472
473         # convert to UTF-8 if necessary
474         if ($LJ::UNICODE) {
475             my %props = ($partid => {});
476
477             if ($clustered) {
478                 LJ::load_props($dbs, "talk");
479                 LJ::load_talk_props2($dbcr, $u->{'userid'}, [$partid], \%props);
480             } else {
481                 LJ::load_talk_props($dbs, [$partid], \%props);
482             }
483             if ($props{$partid}->{'unknown8bit'}) {
484                 LJ::item_toutf8($dbs, $u, \$textsubject, \$parentcomment, {});
485                 LJ::item_toutf8($dbs, $u, \$cleansubject, undef, {});
486             }
487         }
488
489       
490         if ($paruserid) {
491             my $qparuserid = $dbr->quote($paruserid);
492             $sth = $dbr->prepare("SELECT user, email, opt_htmlemail, password, status, ".
493                                  "opt_gettalkemail FROM user WHERE userid=$qparuserid");
494             $sth->execute;
495             my $paru = $sth->fetchrow_hashref;
496             LJ::load_user_props($dbs, $paru, 'mailencoding');
497             LJ::load_codes($dbs, { "encoding" => \%LJ::CACHE_ENCODINGS } )
498                 unless %LJ::CACHE_ENCODINGS;
499             
500             if ($paru->{'opt_gettalkemail'} eq "Y" &&
501                 $paru->{'email'} ne $up->{'email'} &&
502                 $paru->{'status'} eq "A")
503             {
504                 if ($DEBUG) {
505                     $debug .= "Parent mailed ($paru->{'user'}, $paru->{'email'})<br>\n";
506                 }
507                 $parentmailed = $paru->{'email'};
508                 my $encoding = $paru->{'mailencoding'} ? $LJ::CACHE_ENCODINGS{$paru->{'mailencoding'}} : "UTF-8";
509                 my $part;
510
511                 my $headersubject = $textsubject;
512                 if ($LJ::UNICODE && $encoding ne "UTF-8") {
513                     $headersubject = Unicode::MapUTF8::from_utf8({-string=>$textsubject, -charset=>$encoding});
514                 }
515
516                 if ($headersubject) {
517                     $headersubject = encode_mimewords($headersubject,
518                                          ('Charset'=>$encoding));
519                 }
520
521                 my $fromname = $up->{'user'} ? "$up->{'user'} - LJ Comment" : "LiveJournal Comment";
522                 my $msg =  new MIME::Lite ('From' => "$LJ::BOGUS_EMAIL ($fromname)",
523                                            'To' => $paru->{'email'},
524                                            'Subject' => ($headersubject || "Reply to your comment..."),
525                                            'Type' => 'multipart/alternative');
526                 
527                 my $text = "";
528                 $text .= "$who$whouser replied to your LiveJournal comment in which you said:\n\n";
529                 $text .= &indent($parentcomment, ">");
530                 $text .= "\n\nTheir reply was:\n\n";
531                 $text .= &indent("Subject: $cleansubject\n\n$FORM{'body'}");
532                 $text .= "\n\nYou can view the discussion and reply here:\n\n";
533                 $text .= "     $LJ::SITEROOT/talkread.bml?${jarg}itemid=$ditemid\n\n";
534                 $text .= "-- $LJ::SITENAME\n\n";
535
536                 if ($LJ::UNICODE && $encoding ne "UTF-8") {
537                     $text = Unicode::MapUTF8::from_utf8({-string=>$text, -charset=>$encoding});
538                 }
539                 $part = $msg->attach('Type' => 'TEXT',
540                              'Data' => $text,
541                              'Encoding' => 'quoted-printable',
542                              );
543                 $part->attr("content-type.charset" => $encoding)
544                     if $LJ::UNICODE;
545
546                 my $html = "";
547                 $html .= "<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=$encoding\"></head><BODY BGCOLOR=#EFEFFF TEXT=#000000 LINK=#0000FF VLINK=#A000C0>";
548                 $html .= "<TABLE><TR VALIGN=TOP><TD>$whopic</TD><TD WIDTH=100%><B>$who</B>$whouserhtml replied to <A HREF=\"$LJ::SITEROOT/talkread.bml?${jargent}itemid=$ditemid\">your LiveJournal comment</A> in which you said:</TD></TR></TABLE>\n\n";
549                 my $htmlbody = $parentcomment;
550                 LJ::CleanHTML::clean_comment(\$htmlbody);
551                 $html .= &blockquote($htmlbody);
552                 
553                 $html .= "\n\nTheir reply was:\n\n";
554                 my $cleanbody = $FORM{'body'};
555                 LJ::CleanHTML::clean_comment(\$cleanbody, $FORM{'prop_opt_preformatted'});
556                 $html .= &blockquote("<TT><B>Subject:</B> $cleansubject</TT> $icon<P>$cleanbody");
557
558                 $html .= "You can reply at the webpage, or here...";
559                 $html .= "<BLOCKQUOTE><FORM METHOD=POST TARGET=ljreply ACTION=\"$LJ::SITEROOT/talkpost_do.bml\">\n";
560                 $html .= "<INPUT TYPE=HIDDEN NAME=usertype VALUE=user>";
561                 $html .= "<INPUT TYPE=HIDDEN NAME=parenttalkid VALUE=$insertid>";
562                 $html .= "<INPUT TYPE=HIDDEN NAME=journal VALUE='$u->{'user'}'>" if $clustered;
563                 $html .= "<INPUT TYPE=HIDDEN NAME=itemid VALUE=$ditemid>";
564                 $html .= "<INPUT TYPE=HIDDEN NAME=userpost VALUE=\"$paru->{'user'}\">";
565                 $html .= "<INPUT TYPE=HIDDEN NAME=ecphash VALUE=\"" . LJ::ehtml(ecphash($itemid, $insertid, $paru->{'password'})) . "\">";
566                 $html .= "<input type=hidden name=encoding value=$encoding>" unless $encoding eq "UTF-8";
567                 my $newsub = $FORM{'subject'};
568                 unless ($FORM{'subject'} =~ /^Re:/) { $newsub = "Re: $newsub"; }
569                 $html .= "<B>Subject: </B> <INPUT NAME=subject SIZE=40 VALUE=\"" . LJ::ehtml($newsub) . "\">";
570                 $html .= "<P><B>Message</B><BR><TEXTAREA ROWS=10 COLS=50 WRAP=SOFT NAME=body></TEXTAREA>";
571                 $html .= "<BR><INPUT TYPE=SUBMIT VALUE=\"Post Reply\">";
572                 $html .= "</FORM></BLOCKQUOTE>\n";
573                 $html .= "<FONT SIZE=-1>(if you'd prefer to not get these updates, go to <A HREF=\"$LJ::SITEROOT/editinfo.bml\">your user profile page</A> and turn off the relevant options)</FONT>\n";
574                 $html .= "</BODY>\n";
575
576                 if ($LJ::UNICODE && $encoding ne "UTF-8") {
577                     $html = Unicode::MapUTF8::from_utf8({-string=>$html, -charset=>$encoding});
578                 }
579
580                 if ($paru->{'opt_htmlemail'} eq "Y")
581                 {
582
583                     $part = $msg->attach('Type' => 'text/html',
584                                  'Data' => $html,
585                                  'Encoding' => 'quoted-printable',
586                                  );
587                     $part->attr("content-type.charset" => $encoding)
588                         if $LJ::UNICODE;
589
590                 }
591
592                 open(MAIL, "|$LJ::SENDMAIL");
593                 $msg->print(\*MAIL);
594                 close MAIL;
595             } else {
596                 if ($DEBUG) {
597                     $debug .= "Parent not mailed<br>\n";
598                 }
599             }
600         }
601     }
602
603     # send mail to journal owner
604     if ($ujp->{'opt_gettalkemail'} eq "Y" &&
605         $userpost ne $ujp->{'user'} &&
606         $ujp->{'email'} ne $parentmailed &&
607         $ujp->{'status'} eq "A")
608     {
609         if ($DEBUG) {
610             $debug .= "send mail to journal owner. (to $ujp->{'email'})<br>\n";
611         }
612
613         LJ::load_user_props($dbs, $ujp, 'mailencoding');
614         LJ::load_codes($dbs, { "encoding" => \%LJ::CACHE_ENCODINGS } )
615             unless %LJ::CACHE_ENCODINGS;
616         my $encoding = $ujp->{'mailencoding'} ? $LJ::CACHE_ENCODINGS{$ujp->{'mailencoding'}} : "UTF-8";
617         my $part;
618
619         my $headersubject = $textsubject;
620         if ($LJ::UNICODE && $encoding ne "UTF-8") {
621             $headersubject = Unicode::MapUTF8::from_utf8({-string=>$textsubject, -charset=>$encoding});
622         }
623
624         if ($headersubject) {
625             $headersubject = encode_mimewords($headersubject,
626                                  ('Charset'=>$encoding));
627         }
628
629
630         my $fromname = $up->{'user'} ? "$up->{'user'} - LJ Comment" : "LiveJournal Comment";
631         my $msg =  new MIME::Lite ('From' => "$LJ::BOGUS_EMAIL ($fromname)",
632                                    'To' => $ujp->{'email'},
633                                    'Subject' => ($headersubject || "Reply to your post..."),
634                                    'Type' => 'multipart/alternative');
635         my $text = "";
636         if ($parentcomment)  {
637             $text .= "$who$whouser replied to another comment somebody left in your LiveJournal post.  The comment they replied to was:\n\n";
638             $text .= &indent($parentcomment, ">");
639         } else {
640             $text .= "$who$whouser replied to your LiveJournal post in which you said:\n\n";
641             $text .= &indent($item->{'event'}, ">");
642         }
643         $text .= "\n\nTheir reply was:\n\n";
644         $text .= &indent("Subject: $textsubject\n\n$FORM{'body'}");
645         $text .= "\n\nYou can view the discussion and reply here:\n\n";
646         $text .= "     $LJ::SITEROOT/talkread.bml?${jarg}itemid=$ditemid\n\n";
647         $text .= "-- $LJ::SITENAME\n\n";
648         $text .= "(if you'd prefer to not get these updates, go to $LJ::SITEROOT/editinfo.bml and turn off the relevant options)\n";
649
650         if ($LJ::UNICODE && $encoding ne "UTF-8") {
651             $text = Unicode::MapUTF8::from_utf8({-string=>$text, -charset=>$encoding});
652         }
653         $part = $msg->attach('Type' => 'TEXT',
654                      'Data' => $text,
655                      'Encoding' => 'quoted-printable',
656                      );
657         $part->attr("content-type.charset" => $encoding)
658             if $LJ::UNICODE;
659
660         
661         my $html = "";
662         $html .= "<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=$encoding\"></head><BODY BGCOLOR=#EFEFFF TEXT=#000000 LINK=#0000FF VLINK=#A000C0>";
663         if ($parentcomment)  {
664             $html .= "<TABLE><TR VALIGN=TOP><TD>$whopic</TD><TD WIDTH=100%><B>$who</B>$whouserhtml replied to another comment somebody left in <A HREF=\"$LJ::SITEROOT/talkread.bml?${jargent}itemid=$ditemid\">your LiveJournal post</A>.  The comment they replied to was:</TD></TR></TABLE>\n";
665             my $cleancom = $parentcomment;
666             LJ::CleanHTML::clean_comment(\$cleancom);
667             $html .= &blockquote($cleancom);
668         } else {
669             $html .= "<TABLE><TR VALIGN=TOP><TD>$whopic</TD><TD WIDTH=100%><B>$who</B>$whouserhtml replied to <A HREF=\"$LJ::SITEROOT/talkread.bml?${jargent}itemid=$ditemid\">your LiveJournal post</A> in which you said:</TD></TR></TABLE>\n";
670             my $clean = $item->{'event'};
671             LJ::CleanHTML::clean_event(\$clean);
672             $html .= &blockquote($clean);
673         }
674         $html .= "\n\nTheir reply was:\n\n";
675         my $clean = $FORM{'body'};
676         LJ::CleanHTML::clean_comment(\$clean, $FORM{'prop_opt_preformatted'});
677         $html .= &blockquote("<TT><B>Subject: </B> $textsubject</TT> $icon<HR>$clean");
678
679         # begin form
680         $html .= "You can reply at the webpage, or here...";
681         $html .= "<BLOCKQUOTE><FORM METHOD=POST TARGET=ljreply ACTION=\"$LJ::SITEROOT/talkpost_do.bml\">\n";
682         $html .= "<INPUT TYPE=HIDDEN NAME=usertype VALUE=user>";
683         $html .= "<INPUT TYPE=HIDDEN NAME=parenttalkid VALUE=$insertid>";
684         $html .= "<INPUT TYPE=HIDDEN NAME=itemid VALUE=$ditemid>";
685         $html .= "<INPUT TYPE=HIDDEN NAME=journal VALUE='$u->{'user'}'>" if $clustered;
686         $html .= "<INPUT TYPE=HIDDEN NAME=userpost VALUE=\"$ujp->{'user'}\">";
687         $html .= "<INPUT TYPE=HIDDEN NAME=ecphash VALUE=\"" . LJ::ehtml(ecphash($itemid, $insertid, $ujp->{'password'})) . "\">";
688         $html .= "<input type=hidden name=encoding value=$encoding>" unless $encoding eq "UTF-8";
689
690         my $newsub = $FORM{'subject'};
691         unless ($FORM{'subject'} =~ /^Re:/) { $newsub = "Re: $newsub"; }
692         $html .= "<B>Subject: </B> <INPUT NAME=subject SIZE=40 VALUE=\"" . LJ::ehtml($newsub) . "\">";
693         $html .= "<P><B>Message</B><BR><TEXTAREA ROWS=10 COLS=50 WRAP=SOFT NAME=body></TEXTAREA>";
694         $html .= "<BR><INPUT TYPE=SUBMIT VALUE=\"Post Reply\">";
695         $html .= "</FORM></BLOCKQUOTE>\n";
696         # end form
697
698         $html .= "<FONT SIZE=-1>(if you'd prefer to not get these updates, go to <A HREF=\"$LJ::SITEROOT/editinfo.bml\">your user profile page</A> and turn off the relevant options)</FONT>\n";
699         $html .= "</BODY>\n";
700
701         if ($LJ::UNICODE && $encoding ne "UTF-8") {
702             $html = Unicode::MapUTF8::from_utf8({-string=>$html, -charset=>$encoding});
703         }
704
705         if ($ujp->{'opt_htmlemail'} eq "Y")
706         {
707             $part = $msg->attach('Type' => 'text/html',
708                          'Data' => $html,
709                          'Encoding' => 'quoted-printable',
710                          );
711             $part->attr("content-type.charset" => $encoding)
712                 if $LJ::UNICODE;
713         }
714         
715         open(MAIL, "|$LJ::SENDMAIL");
716         $msg->print(\*MAIL);
717         close MAIL;
718     } else {
719         $debug .= "don't send mail to journal owner.<ul>\n";
720         $debug .= "<li>ujp--opt_gettalkemail = $ujp->{'opt_gettalkemail'}\n";
721         $debug .= "<li>userpost = $userpost\n";
722         $debug .= "<li>ujp--user = $ujp->{'user'}\n";
723         $debug .= "<li>ujp--email = $ujp->{'email'}\n";
724         $debug .= "<li>parentmailed = $parentmailed\n";
725         $debug .= "<li>ujp--status = $ujp->{'status'}\n";
726         $debug .= "</ul>\n";
727
728     }
729 }
730
731 $dtalkid = $clustered ? $insertid * 256 + $item->{'anum'} : $insertid;
732 
733 # Yeah, we're done.
734 my $commentlink = "<a href='talkread.bml?${jargent}itemid=$ditemid&amp;view=$dtalkid#t$dtalkid'>here</a>";
735 $ret .= "(=H1 Success H1=)(=P Your comment has been added.  You can view it $commentlink. P=)";
736
737 if ($didlogin) {
738     $ret .= "(=P You are now logged in. P=)";
739 }
740
741 if ($DEBUG) {
742     $ret .= "<p>$debug</p>";
743 }
744 return $ret;
745
746 # entryid-commentid-password hash
747 sub ecphash {
748     my ($itemid, $talkid, $password) = @_;
749     return "ecph-" . md5_hex($itemid . $talkid . $password);
750 }
751
752 sub indent {
753     my $a = shift;
754     my $leadchar = shift || " ";
755     return Text::Wrap::fill("$leadchar  ", "$leadchar  ", $a);
756 }
757
758sub blockquote {
759     my $a = shift;
760     return "<blockquote style='BORDER-LEFT: #000040 2px solid; MARGIN-LEFT: 0px; MARGIN-RIGHT: 0px; PADDING-LEFT: 15px; PADDING-RIGHT: 0px'>$a</blockquote>";
761}
762
763_CODE=)
764
765
766
767<=BODY
768PAGE=)(=_C <LJDEP>
769link: htdocs/lostinfo.bml, htdocs/userinfo.bml, htdocs/talkread.bml, htdocs/editinfo.bml
770post: htdocs/talkpost_do.bml
771</LJDEP> _C=)
Note: See TracBrowser for help on using the browser.