📄 atomserver.pm
字号:
my $app = shift; $app->authenticate || return; if (my $svc = $app->{param}{svc}) { if ($svc eq 'upload') { return $app->handle_upload; } elsif ($svc eq 'categories') { return $app->get_categories; } } my $method = $app->request_method; if ($method eq 'POST') { return $app->new_post; } elsif ($method eq 'PUT') { return $app->edit_post; } elsif ($method eq 'DELETE') { return $app->delete_post; } elsif ($method eq 'GET') { if ($app->{param}{entry_id}) { return $app->get_post; } elsif ($app->{param}{blog_id}) { return $app->get_posts; } else { return $app->get_weblogs; } }}sub authenticate { my $app = shift; $app->SUPER::authenticate or return; if (my $blog_id = $app->{param}{blog_id}) { $app->{blog} = MT::Blog->load($blog_id) or return $app->error(400, "Invalid blog ID '$blog_id'"); $app->{user} or return $app->error(403, "Authenticate"); my $perms = $app->{perms} = MT::Permission->load({ author_id => $app->{user}->id, blog_id => $app->{blog}->id }); return $app->error(403) unless $perms && $perms->can_post; } 1;}sub publish { my $app = shift; my($entry, $no_ping) = @_; my $blog = MT::Blog->load($entry->blog_id); $app->rebuild_entry( Entry => $entry, Blog => $blog, BuildDependencies => 1 ) or return; unless ($no_ping) { $app->ping_and_save( Entry => $entry, Blog => $blog ) or return; } 1;}sub get_weblogs { my $app = shift; my $user = $app->{user}; my $iter = MT::Permission->load_iter({ author_id => $user->id }); my $feed = XML::Atom::Feed->new; my $base = $app->base . $app->uri; while (my $perms = $iter->()) { next unless $perms->can_post; my $blog = MT::Blog->load($perms->blog_id); my $uri = $base . '/blog_id=' . $blog->id; $feed->add_link({ rel => 'service.post', title => $blog->name, href => $uri, type => 'application/x.atom+xml' }); $feed->add_link({ rel => 'service.feed', title => $blog->name, href => $uri, type => 'application/x.atom+xml' }); $feed->add_link({ rel => 'service.upload', title => $blog->name, href => $uri . '/svc=upload', type => 'application/x.atom+xml' }); $feed->add_link({ rel => 'service.categories', title => $blog->name, href => $uri . '/svc=categories', type => 'application/x.atom+xml' }); } $app->response_code(200); $app->response_content_type('application/x.atom+xml'); $feed->as_xml;}sub new_post { my $app = shift; my $atom = $app->atom_body or return $app->errpr(500, "No body!"); my $blog = $app->{blog}; my $user = $app->{user}; ## Check for category in dc:subject. We will save it later if ## it's present, but we want to give an error now if necessary. my($cat); if (my $label = $atom->get(NS_DC, 'subject')) { $cat = MT::Category->load({ blog_id => $blog->id, label => $label }) or return $app->error(400, "Invalid category '$label'"); } my $entry = MT::Entry->new; $entry->blog_id($blog->id); $entry->author_id($user->id); $entry->status(MT::Entry::RELEASE()); $entry->allow_comments($blog->allow_comments_default); $entry->allow_pings($blog->allow_pings_default); $entry->convert_breaks($blog->convert_paras); $entry->title($atom->title); $entry->text($atom->content()->body()); $entry->excerpt($atom->summary); if (my $iso = $atom->issued) { $entry->created_on(MT::Util::iso2ts($blog, $iso)); }## xxx mt/typepad-specific fields $entry->save or return $app->error(500, $entry->errstr); ## Save category, if present. if ($cat) { my $place = MT::Placement->new; $place->is_primary(1); $place->entry_id($entry->id); $place->blog_id($blog->id); $place->category_id($cat->id); $place->save or return $app->error(500, $place->errstr); } $app->publish($entry); $app->response_code(201); $app->response_content_type('application/xml'); $app->set_header('Location', $app->base . $app->uri . '/blog_id=' . $entry->blog_id . '/entry_id=' . $entry->id); $atom = MT::Atom::Entry->new_with_entry($entry); $atom->as_xml;}sub edit_post { my $app = shift; my $atom = $app->atom_body or return; my $blog = $app->{blog}; my $entry_id = $app->{param}{entry_id} or return $app->error(400, "No entry_id"); my $entry = MT::Entry->load($entry_id) or return $app->error(400, "Invalid entry_id"); return $app->error(403, "Access denied") unless $app->{perms}->can_edit_entry($entry, $app->{user}); $entry->title($atom->title); $entry->text($atom->content()->body()); $entry->excerpt($atom->summary); if (my $iso = $atom->issued) { $entry->created_on($app->iso2ts($iso, $blog->server_offset())); }## xxx mt/typepad-specific fields $entry->save or return $app->error(500, $entry->errstr); $app->publish($entry) or return $app->error(500, $app->errstr); $app->response_code(200); $app->response_content_type('application/xml'); $atom = MT::Atom::Entry->new_with_entry($entry); $atom->as_xml;}sub get_posts { my $app = shift; my $blog = $app->{blog}; my %terms = (blog_id => $blog->id); my %arg = (sort => 'created_on', direction => 'descend'); my $Limit = 20; $arg{limit} = $Limit + 1; $arg{offset} = $app->{param}{offset} || 0; my $iter = MT::Entry->load_iter(\%terms, \%arg); my $feed = XML::Atom::Feed->new; my $uri = $app->base . $app->uri . '/blog_id=' . $blog->id; $feed->add_link({ rel => 'alternate', type => 'text/html', href => $blog->site_url }); $feed->title($blog->name); $feed->add_link({ rel => 'service.post', type => 'application/x.atom+xml', href => $uri, title => $blog->name }); $uri .= '/entry_id='; while (my $entry = $iter->()) { my $e = MT::Atom::Entry->new_with_entry($entry); $e->add_link({ rel => 'service.edit', type => 'application/x.atom+xml', href => ($uri . $entry->id), title => $entry->title }); $feed->add_entry($e); } ## xxx add next/prev links $app->response_content_type('application/xml'); $feed->as_xml;}sub get_post { my $app = shift; my $blog = $app->{blog}; my $entry_id = $app->{param}{entry_id} or return $app->error(400, "No entry_id"); my $entry = MT::Entry->load($entry_id) or return $app->error(400, "Invalid entry_id"); return $app->error(403, "Access denied") unless $app->{perms}->can_edit_entry($entry, $app->{user}); my $co = sprintf "%04d-%02d-%02dT%02d:%02d:%02d", unpack 'A4A2A2A2A2A2', $entry->created_on; $blog = MT::Blog->load($entry->blog_id); my $so = $blog->server_offset; $so = sprintf "%s%02d00", $so < 0 ? '-' : '+', abs($so); $app->response_content_type('application/xml'); my $atom = MT::Atom::Entry->new_with_entry($entry); $atom->as_xml;}sub delete_post { my $app = shift; my $blog = $app->{blog}; my $entry_id = $app->{param}{entry_id} or return $app->error(400, "No entry_id"); my $entry = MT::Entry->load($entry_id) or return $app->error(400, "Invalid entry_id"); return $app->error(403, "Access denied") unless $app->{perms}->can_edit_entry($entry, $app->{user}); $entry->remove or return $app->error(500, $entry->errstr); $app->publish($entry, 1) or return $app->error(500, $app->errstr); '';}sub handle_upload { my $app = shift; my $atom = $app->atom_body or return; my $blog = $app->{blog}; my $user = $app->{user}; return $app->error(403, "Access denied") unless $app->{perms}->can_upload; my $content = $atom->content; my $type = $content->type or return $app->error(400, "content \@type is required"); my $fname = $atom->title or return $app->error(400, "title is required"); $fname = basename($fname); return $app->error(400, "Invalid or empty filename") if $fname =~ m!/|\.\.|\0|\|!; my $local = File::Spec->catfile($blog->site_path, $fname); my $fmgr = $blog->file_mgr; my($base, $path, $ext) = File::Basename::fileparse($local, '\.[^\.]*'); my $base_copy = $base; my $i = 1; while ($fmgr->exists($path . $base . $ext)) { $base = $base_copy . '_' . $i++; } $local = $path . $base . $ext; my $data = $content->body; $atom = XML::Atom::Entry->new; $atom->title($base . $ext); defined(my $bytes = $fmgr->put_data($data, $local, 'upload')) or return $app->error(500, "Error writing uploaded file"); my $link = XML::Atom::Link->new; $link->type($type); $link->rel('alternate'); $link->href($blog->site_url . $base . $ext); $atom->add_link($link); $app->response_code(201); $app->response_content_type('application/x.atom+xml'); $atom->as_xml;}sub get_categories { my $app = shift; my $blog = $app->{blog}; my $iter = MT::Category->load_iter({ blog_id => $blog->id }); my $doc; if (LIBXML) { $doc = XML::LibXML::Document->createDocument('1.0', 'utf-8'); my $root = $doc->createElementNS(NS_CATEGORY, 'categories'); $doc->setDocumentElement($root); } else { $doc = XML::XPath::Node::Element->new('categories'); my $ns = XML::XPath::Node::Namespace->new('#default' => NS_CATEGORY); $doc->appendNamespace($ns); } while (my $cat = $iter->()) { if (LIBXML) { my $elem = $doc->createElementNS(NS_DC, 'subject'); $doc->getDocumentElement->appendChild($elem); $elem->appendChild(XML::LibXML::Text->new($cat->label)); } else { my $elem = XML::XPath::Node::Element->new('subject'); my $ns = XML::XPath::Node::Namespace->new('#default' => NS_DC); $elem->appendNamespace($ns); $doc->appendChild($elem); $elem->appendChild(XML::XPath::Node::Text->new($cat->label)); } } $app->response_code(200); $app->response_content_type('application/x.atom+xml'); if (LIBXML) { $doc->toString(1); } else { return '<?xml version="1.0" encoding="utf-8"?>' . "\n" . $doc->toString; }}1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -