7 my $remote = LJ::get_remote();
8 return "<?needlogin?>" unless $remote;
10 my $authas = $GET{'authas'} || $remote->{'user'};
12 my $can_view = LJ::check_priv($remote, "siteadmin", "commentview") && ($mode ne 'comment_body');
13 my $u = $can_view ? LJ::load_user($authas) : LJ::get_authas_user($authas);
14 return LJ::bad_input($ML{'error.invalidauth'}) unless $u;
18 my $dbcr = LJ::get_cluster_reader($u);
19 push @errors, $ML{'error.nodb'} unless $dbcr;
21 # don't let people hit us with silly GET attacks
22 push @errors, "This page can't be viewed except via POST."
23 if BML::get_client_header('Referer') && !LJ::did_post();
26 push @errors, "Invalid mode."
27 unless $mode =~ m/^comment_(?:meta|body)$/;
30 return LJ::bad_input(@errors) if @errors;
32 # from now on, we manage our own output
33 BML::suppress_headers();
34 BML::suppress_content();
37 LJ::Request->content_type("text/xml; charset=utf-8");
38 LJ::Request->send_http_header();
39 LJ::Request->print("<?xml version=\"1.0\" encoding='utf-8'?>\n<livejournal>\n");
42 my $maxitems = $mode eq 'comment_meta' ? 10000 : 1000;
43 my $numitems = $GET{numitems};
46 if ( defined $numitems && ($numitems > 0) && ($numitems <= $maxitems) ) {
53 my $startid = $GET{startid}+0;
54 my $endid = $startid + $gather;
57 my $rows = $dbcr->selectall_arrayref('
65 WHERE nodetype = \'L\'
75 # now let's gather them all together while making a list of posterids
76 my ( %posterids, %comments );
78 foreach my $r ( @{$rows || []} ) {
79 $comments{$r->[0]} = {
81 parenttalkid => $r->[2],
86 $posterids{$r->[3]} = 1 if $r->[3]; # don't include 0 (anonymous)
89 # now we have two choices: comments themselves or metadata
90 if ( $mode eq 'comment_meta' ) {
91 # meta data is easy :)
92 my $max = $dbcr->selectrow_array('
96 AND nodetype = \'L\'',
101 LJ::Request->print("<maxid>$max</maxid>\n");
102 my $nextid = $startid + $gather;
103 LJ::Request->print("<nextid>$nextid</nextid>\n") unless ($nextid > $max);
106 my $us = LJ::load_userids(keys %posterids);
108 # now spit out the metadata
109 LJ::Request->print("<comments>\n");
111 while (my ($id, $data) = each %comments) {
112 my $ret = "<comment id='$id'";
113 $ret .= " posterid='$data->{posterid}'" if $data->{posterid};
114 $ret .= " state='$data->{state}'" if $data->{state} ne 'A';
115 $ret .= " jitemid='$data->{nodeid}'";
117 LJ::Request->print($ret);
120 LJ::Request->print("</comments>\n<usermaps>\n");
122 # now spit out usermap
125 while (my ($id, $user) = each %$us) {
126 $ret .= "<usermap id='$id' user='$user->{user}' />\n";
129 LJ::Request->print($ret);
130 LJ::Request->print("</usermaps>\n");
132 # comment data also presented in glorious XML:
133 elsif ($mode eq 'comment_body') {
134 # get real comments from startid to a limit of 10k data, however far that takes us
135 my @ids = sort { $a <=> $b } keys %comments;
137 # call a load to get comment text
138 my $texts = LJ::get_talktext2($u, @ids);
140 # get props if we need to
143 LJ::load_talk_props2($u->{userid}, \@ids, $props);
146 # now start spitting out data
147 LJ::Request->print("<comments>\n");
148 foreach my $id (@ids) {
149 # get text for this comment
150 my $data = $comments{$id};
151 my $text = $texts->{$id};
152 my ($subject, $body) = @{$text || []};
154 # only spit out valid UTF8, and make sure it fits in XML, and uncompress it
155 LJ::text_uncompress(\$body);
156 LJ::text_out(\$subject);
157 LJ::text_out(\$body);
158 $subject = LJ::exml($subject);
159 $body = LJ::exml($body);
161 # setup the date to be GMT and formatted per W3C specs
162 my $date = LJ::TimeUtil->mysqldate_to_time($data->{datepost});
163 $date = LJ::TimeUtil->time_to_w3c($date, 'Z');
166 my $ret = "<comment id='$id' jitemid='$data->{nodeid}'";
167 $ret .= " posterid='$data->{posterid}'" if $data->{posterid};
168 $ret .= " state='$data->{state}'" if $data->{state} ne 'A';
169 $ret .= " parentid='$data->{parenttalkid}'" if $data->{parenttalkid};
170 if ($data->{state} eq 'D') {
174 $ret .= "<subject>$subject</subject>\n" if $subject;
175 $ret .= "<body>$body</body>\n" if $body;
176 $ret .= "<date>$date</date>\n";
177 foreach my $propkey (keys %{$props->{$id} || {}}) {
178 $ret .= "<property name='$propkey'>";
179 $ret .= LJ::exml($props->{$id}->{$propkey});
180 $ret .= "</property>\n";
182 $ret .= "</comment>\n";
184 LJ::Request->print($ret);
186 LJ::Request->print("</comments>\n");
190 LJ::Request->print("</livejournal>\n");