# ODP::Editors::Category - An ODP editor-side category parsing and handling class (Version 0.01) # Copyright (C) 2002 - 2004 Richard P. Fuller # Significant contributions to this module by dlugan # 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 License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA package ODP::Editors::Category; our @ISA="ODP::Category"; use strict; use ODP::Category; use ODP::Editors::HTTP; use UNIVERSAL qw(isa); use URI::Escape; $ODP::Error::No_Error = 0; $ODP::Error::Unknown_Error = 1; $ODP::Error::Not_Authorised = 2; $ODP::Error::Invalid_Category = 4; $ODP::Error::Category_Exists = 8; $ODP::Error::Category_Not_Empty = 16; $ODP::Error::CGI_Moved = 32; $ODP::Error::Symlink_Exists = 64; $ODP::Error::Invalid_Destination = 128; $ODP::Error::Login_Incorrect = 256; $ODP::Editors::ServerURL = "http://editors.dmoz.org"; # new - Initialises a new ODP::Editors::Category object # Parameters: your username, your password, category # Returns: ODP::Editors::Category object sub new ($$$) { my $object = {}; if (!$_[3]) { die 'No category supplied.'; } $object->{'e_name'} = $_[1]; $object->{'e_pass'} = $_[2]; $object->{'category'} = ODP::Category::normalise($_[3]); return bless $object; } # fetch - Fetches the edit-side page and stores the source in the object # Parameters: # Returns: sub fetch { my $self = shift; my $ua = new ODP::Editors::HTTP('POST', "$ODP::Editors::ServerURL/editors/editcat.cgi", $self->{'e_name'}, $self->{'e_pass'}, [ cat=>uri_unescape($self->{'category'}), ]); my $response = $ua->execute(); $self->{'editcontent'} = $response; if ($response =~ m|^\n.*?New Category Request|) { return $ODP::Error::Not_Authorised; } if ($response =~ m|^\n.*?No such category|) { return $ODP::Error::Invalid_Category; } return 0; } # set_exostring - Sets the search string used for external search engines # Parameters: public string, search string # Returns: sub set_exosearch($$) { my $self = shift; my $ua = new ODP::Editors::HTTP('POST',"$ODP::Editors::ServerURL/editors/exosearch2.cgi",$self->{'e_name'},$self->{'e_pass'}, [ cat=>$self->{'category'}, exosearchname=>$_[0], exosearch=>$_[1] ]); my $response = $ua->execute(); if ($response =~ m|^\n.*? - No permission|) { return $ODP::Error::Not_Authorised; } elsif ($response =~ m|^\n.*?Error|) { if ($response =~ m|Unknown directory category|) { return $ODP::Error::Invalid_Category; } return $ODP::Error::Unknown_Error; } # Since we just got an updated edit page back, update our copy $self->{'editcontent'} = $response; return 0; } # add_symlink - Adds an @link to the category # Parameters: target category (scalar or ODP::Category), name of link # Returns: 0 on success; non-zero on failure sub add_symlink($$) { my $self = shift; my ($linkcat, $linkname) = @_; if (isa($linkcat, 'ODP::Category')) { $linkcat = $linkcat->{'category'}; } else { $linkcat = ODP::Category::normalise($linkcat); } $linkname = ODP::Category::normalise($linkname); my $ua = new ODP::Editors::HTTP('POST', "$ODP::Editors::ServerURL/editors/link2.cgi", $self->{'e_name'}, $self->{'e_pass'}, [ cat=>$self->{'category'}, linkcat=>$linkcat, linkname=>$linkname, ]); my $response = $ua->execute(); if ($response =~ m|^\n\n.*?No permission|) { return $ODP::Error::Not_Authorised; } elsif ($response =~ m|^\n\n.*?Directory already exists|) { return $ODP::Error::Category_Exists; } elsif ($response =~ m|^\n\n.*?Link already exists|) { return $ODP::Error::Symlink_Exists; } elsif ($response =~ m|^\n\n.*?Bad category|) { return $ODP::Error::Invalid_Category; } elsif ($response =~ m|^\n\n.*?Error|) { if ($response =~ m|Unknown directory category|) { return $ODP::Error::Invalid_Destination; } return $ODP::Error::Unknown_Error; } elsif ($response =~ m|^\n\n.*?302 Found|) { return $ODP::Error::CGI_Moved; } # Since we just got an updated edit page back, update our copy $self->{'editcontent'} = $response; return 0; } # relcats - Returns a list of related categories (from the edit side) # Parameters: # Returns: Array of related categories (as ODP::Category objects) sub relcats { my $self = shift; if (!$self->{'editcontent'}) { my $response = $self->fetch(); # Handle errors here? } my $page = $self->{'editcontent'}; my @relcats = (); while ($page =~ m|
  • Open Directory |g) { push @relcats, new ODP::Category(uri_unescape($1)); } return @relcats; } # set_relcats - Sets the related categories to those supplied as parameters # Parameters: array of categories (scalars or ODP::Category objects) # Returns: non-zero on failure; 0 on success sub set_relcats(@) { my $self = shift; my $relcats = join "\n", map { isa($_, 'ODP::Category') ? $_->{'category'} : ODP::Category::normalise($_); } @_; my $ua = new ODP::Editors::HTTP('POST', "$ODP::Editors::ServerURL/editors/related2.cgi", $self->{'e_name'}, $self->{'e_pass'}, [ cat=>$self->{'category'}, Newcat=>$relcats, ]); my $response = $ua->execute(); if ($response =~ m|^\n.*?No permission|) { return $ODP::Error::Not_Authorised; } # Since we just got an updated edit page back, update our copy $self->{'editcontent'} = $response; return 0; } # add_relcats - Adds the specified related categories supplied as parameters to the existing ones - duplicates are filtered out by dmoz # Parameters: array of categories (scalars or ODP::Category objects) # Returns: non-zero on failure; 0 on success sub add_relcats(@) { my $self = shift; my @existing_relcats = $self->relcats(); my $relcats = join "\n", map { isa($_, 'ODP::Category') ? $_->{'category'} : ODP::Category::normalise($_); } (@_, @existing_relcats); my $ua = new ODP::Editors::HTTP('POST', "$ODP::Editors::ServerURL/editors/related2.cgi", $self->{'e_name'}, $self->{'e_pass'}, [ cat=>$self->{'category'}, Newcat=>$relcats, ]); my $response = $ua->execute(); if ($response =~ m|^\n\n.*?No permission|) { return $ODP::Error::Not_Authorised; } elsif ($response =~ m|^\n\n.*?Bad form arguments|) { return $ODP::Error::Invalid_Category; } elsif ($response =~ m|^\n\n.*?Error|) { if ($response =~ m|Unknown Open Directory category|) { return $ODP::Error::Invalid_Destination; } return $ODP::Error::Unknown_Error; } # Since we just got an updated edit page back, update our copy $self->{'editcontent'} = $response; return 0; } # moveto - Moves a category someplace else # Parameters: destination # Returns: non-zero on failure; 0 on success sub moveto(@) { my $self = shift; my $destination = shift; if (isa($destination, 'ODP::Category')) { $destination = $destination->{'category'}; } else { $destination = ODP::Category::normalise($destination); } my $ua = new ODP::Editors::HTTP('POST', "$ODP::Editors::ServerURL/editors/catmv3.cgi", $self->{'e_name'}, $self->{'e_pass'}, [ cat=>$self->{'category'}, target=>$destination, ]); my $response = $ua->execute(); my $standard_error = _checkstandarderrors($response); if ($standard_error) { return $standard_error; } if ($response =~ m|(.*?)Error(.*?)|s) { if ($response =~ m!Target parent category does not exist!) { return $ODP::Error::Invalid_Destination; } elsif ($response =~ m!Target category already exists!s) { return $ODP::Error::Category_Exists; } return $ODP::Error::Unknown_Error; } # Since we just got an updated edit page back, update our copy $self->{'editcontent'} = $response; return 0; } sub _checkstandarderrors($content) { my $content = shift; if ($content =~ m!^(.*?)Login Incorrect!s) { return $ODP::Error::Login_Incorrect; } elsif ($content =~ m!(.*?)Bad category(.*?)!s) { return $ODP::Error::Invalid_Category; } elsif ($content =~ m|(.*?)Not authorized(.*?)|s) { return $ODP::Error::Not_Authorised; } } 1;