| PrayMind documentation | Contained in the PrayMind distribution. |
Religion::Islam::PrayMind - a Perl module that is a client for PrayerMinder server
use Religion::Islam::PrayMind; $p1 = new PMConnect(ClientID => "xxxx"); #where xxxx is the client web site's ID at the PrayerMinder server. $p1->GetList(<listtype> [, <parentID>); $p1->GetPrayerTimes(<cityID>);
This module provides ways to obtain data from the PrayerMinder server. It is built on top of XML::Parser. Each call to GetList or GetPrayerTimes methods opens a socket connection to the PrayerMinder server, and creates a new instance of XML::Parser which is then used to parse the data received through the socket.
Example
The following files show example usage of the PrayMind module:
Exported constants and variables
This is a class method, the constructor for PMConnect. Client ID for the caller's PrayerMinder account is passed as keyword value pair.
This method retrieves a list of locations.
PARAMETERS
Specifies type of list desired. The properties and elementes of the list can be retrieved using relevant methods listed later. GetError and GetErrorText must be called before calling any other methods to make sure no errors occurred. Possible values for LIST_TYPE are listed below:
Not needed if LIST_TYPE is eContinentsList, required otherwise. Specifies the parent whose children are to be listed.
Returns integer
Called after GetList to obtain the number of locations in the list.
Returns integer
Called after GetList to obtain the number of locations in the list.
Returns string
Called after GetList to obtain the number of locations in the list.
Returns true if successful, false for no more elements.
Called after GetList to obtain the number of locations in the list.
This method retrieves prayer times for the requested city. CITY_ID specifies the ID of the city requested. GetError and GetErrorText must be called before calling any other methods to make sure no errors occurred.
Returns integer
Called after GetPrayerTimes to obtain the ID for the city.
Returns string
Called after GetPrayerTimes to obtain the title for the city.
Returns string (floating point decimal number)
Called after GetPrayerTimes to obtain the time zone for the city.
Returns string
Called after GetPrayerTimes to obtain today's Islamic date for the city.
Returns string
Called after GetPrayerTimes to obtain today's Gregorian date for the city.
Returns string
Called after GetPrayerTimes to obtain the default Asr fiqh method for the city.
Returns string
Called after GetPrayerTimes to obtain the requested prayer time for the city.
PARAMETERS
Specifies prayer whose time is desired. Possible values for PRAYER_NAME are listed below:
Returns Error_ID
Called after GetPrayerTimes or GetList to obtain the error ID. Returns values indicates error ID or IDS_NoError if no errors occurred.
Returns string
Called after GetError to obtain the text description of the last error.
Tasmin Ahmad, <support@prayerminder.com>
Web site: http://www.prayerminder.com/
| PrayMind documentation | Contained in the PrayMind distribution. |
package Religion::Islam::PrayMind; # # Copyright (c) 2002 Tasmin Ahmad # All rights reserved. # # Implements Class to connect and retrieve data from the PrayerMinder server # # This library is free software; you can redistribute it and/or modify # it under the "Artistic License", as described in the accompanying # License.txt file. # # # DISCLAIMER # THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # Acknowledgement # The following people have contributed to the development of # this tool, in addition to the copyright owner: # # 1. Mr. Tariq Chaudhary # 2. Allied Software Corporation Islamabad, Pakistan; particularly the # following folks: # 2.1 Mr. S. Taimur Hassan # 2.2 Ms. Shaista Rashid # 2.3 Mr. Ijaz Rashid # use IO::Socket; use XML::Parser; use 5.006; use strict; use warnings; require Exporter; our @ISA = qw(Exporter); # Items to export into callers namespace by default. Note: do not export # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. # This allows declaration use Religion::Islam::PrayMind ':all'; # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK # will save memory. our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw($VERSION eContinentsList eCountriesList eStatesList eCitiesListForState eCitiesListForCountry ePrayerTimes ePrayerTimeTable IDS_NO_Error IDS_ERROR_OpenNotCalled IDS_ERROR_ClientIDNotSpecified IDS_ERROR_EmptyString IDS_ERROR_GetListNotCalled IDS_ERROR_GetPrayerTimesNotCalled IDS_ERROR_EmptyList ); our $VERSION = '1.01'; #define constant values for type of listing requested by caller use constant eContinentsList => 0; use constant eCountriesList => 1; use constant eStatesList => 2; use constant eCitiesListForState => 3; use constant eCitiesListForCountry => 4; use constant eCitiesSearchList => 5; use constant ePrayerTimes => 6; use constant ePrayerTimeTable => 7; #define constant values for error codes use constant IDS_NO_Error => 0; use constant IDS_ERROR_OpenNotCalled => 1; use constant IDS_ERROR_ClientIDNotSpecified => 2; use constant IDS_ERROR_EmptyString => 3; use constant IDS_ERROR_GetListNotCalled => 4; use constant IDS_ERROR_GetPrayerTimesNotCalled => 5; use constant IDS_ERROR_EmptyList => 6; #define local constant values used to know type of listing obtained use constant eNoData => 0; use constant eLocationsList => 1; use constant ePrayerTimings => 2; use constant host => "www.prayerminder.com"; #use constant host => "209.185.200.148"; use constant EOL => "\015\012"; use constant BLANK => EOL x 2; #class private global member variable declaration #our ($host, $EOL, $BLANK); #Hash to store error codes and their corresponding text our @PMErrors = ( "No Errors", "Open function not called", "Client ID not specified", "Host returned an empty string please check that you have passed correct parameters", "Call GetList function first", "Call GetPrayerTimes function first", "List does not contain elements" ); #function that will return class reference sub new { my ($class, %args) = @_; my $self = bless \%args, $_[0]; if(!defined($args{ClientID})) { $args{ErrorCode} = IDS_ERROR_ClientIDNotSpecified; } else { $args{ErrorCode} = IDS_NO_Error; $args{_DataType} = eNoData; $args{_TimesData} = { nCityID => 0, nCountryId => 0, nStateID => 0, sCityTitle => '', sCityTimeZone => '', sCityIslamicDate => '', sCityGregorianDate => '', sCityAsrFiqh => '', CityPrayerTimes => {Fajr => "", Shurooq => "", Zuhr => "", AsrHanafi => "", AsrShafei => "", Maghrib => "", Isha => ""} }; $args{_LocationsList} = { LocNames => [], LocIDs => [], nCurrItem => 0 }; } $self; } # Preloaded methods go here. # Autoload methods go after =cut, and are processed by the autosplit program. #sends HTTP query to obtain the list required and saves the result in run time structure sub GetList { #store parameters received to functions local variables my ($self, $ListType, $nParentID) = @_; my ($document, $nListType); $nListType = eNoData; #implementing error when GetList called before making a call to new function if(!defined($self->{ErrorCode})) { $self->{ErrorCode} = IDS_ERROR_OpenNotCalled; } if($self->{ErrorCode} != IDS_NO_Error) { return; } $document = "/cgi-bin/PMCalc.cgi?F=X&I=" . $self->{ClientID} . "&R="; #Get the required list if Open function called before calling it if($self->{ErrorCode} != IDS_ERROR_OpenNotCalled) { #now it depends upon $ListType which list to obtain #make the query string that will be passed to get continent, countrie and city listing #asked for continents list if($ListType == eContinentsList) { $document = $document . "LCN"; } #asked for countries list elsif($ListType == eCountriesList) { $document = $document . "LCY&CN="; $document = $document . $nParentID; } #asked for cities list elsif($ListType == eCitiesListForCountry) { $document = $document . "LCT&CY="; $document = $document . $nParentID; } #print " in GetList 1<BR>\n"; #establish the connection to the host my ($remote, $StartData, $aline); $remote = IO::Socket::INET->new( Proto => "tcp", PeerAddr => host, PeerPort => "http(80)", ); #print " in GetList , doc=" . $document . "<BR>\n"; #error message to report if connection is not established with host unless($remote) { die "Cannot connect to http daemon on host " . host; } print $remote "GET $document HTTP/1.0" . BLANK; $StartData = 0; #$DesiredString = ""; #while remote is returning cetain text while(($StartData < 1) && (defined ($aline = <$remote>))) { #print " > " . $aline . "<br>\n"; #check if line is a blank line, after which the XML document follows if($aline eq "\r\n") { $StartData = 1; } } # If we got any data, parse it if($StartData == 1) { # Make a call to function that will xml data returned by server # the XML data will be parsed by XML parser and information will be # stored in class member variables ParseXMLFile($self, $remote, eLocationsList); } close $remote; #print " *** GetList ErrorCode: " . $self->{ErrorCode} . " ErrorText: " . $self->{ErrorText} . "<BR>\n"; #you get the required text from host # if($self->{_DataType} != eLocationsList) # { #discard errors previously set #Error Code IDS_ERROR_GetListNotCalled "Call GetList function first"; #Error Code IDS_ERROR_GetPrayerTimesNotCalled "Call GetPrayerTimes function first"; #Error Code IDS_ERROR_EmptyList "Empty List"; # $self->{ErrorCode} = IDS_NO_Error # if($self->{ErrorCode} == IDS_ERROR_GetListNotCalled || $self->{ErrorCode} == IDS_ERROR_GetPrayerTimesNotCalled || # $self->{ErrorCode} == IDS_ERROR_EmptyList); # } #check whether some string is returned by host # if($self->{_DataType} != eLocationsList) # { # $self->{ErrorCode} = IDS_ERROR_EmptyString # if($self->{ErrorCode}) == IDS_NO_Error; # } #discard error that was set that empty string returned by host # elsif($self->{ErrorCode} == IDS_ERROR_EmptyString) # { # $self->{ErrorCode} = IDS_NO_Error; # } } } #functions that are called when asked for listing of continents, countries and cities #returns number of elements in the list retreived by GetList sub GetListSize { #store parameters received to functions local variables my $self = shift; #$nListType is set to eLocationsList when asked for continents, countries or city listing if($self->{_DataType} != eLocationsList) { $self->{ErrorCode} = IDS_ERROR_GetListNotCalled; return -1; } else { #check for empty list if($#{$self->{_LocationsList}->{LocNames}} < 0) { $self->{ErrorCode} = IDS_ERROR_EmptyList; } return $#{$self->{_LocationsList}->{LocNames}} + 1; } } #returns parent element's ID, to which this list belongs #sub GetParentID #{ # #$nListType is set to eLocationsList when asked for continents, countries or city listing # if($nListType != eLocationsList) # { # $ErrorCode = IDS_ERROR_GetListNotCalled; # return -1; # } # else # { # return $ParentID; # } #} #returns ID of the current element from the list sub GetElementID { my $self = shift; #$nListType is set to eLocationsList when asked for continents, countries or city listing if($self->{_DataType} != eLocationsList) { $self->{ErrorCode} = IDS_ERROR_GetListNotCalled; return -1; } else { return $self->{_LocationsList}->{LocIDs}->[$self->{_LocationsList}->{nCurrItem}]; } } #returns the name of the current element from the list sub GetElementName { my $self = shift; #$nListType is set to eLocationsList when asked for continents, countries or city listing if($self->{_DataType} != eLocationsList) { $self->{ErrorCode} = IDS_ERROR_GetListNotCalled; return -1; } else { return $self->{_LocationsList}->{LocNames}->[$self->{_LocationsList}->{nCurrItem}]; } } #moves to next element in the list sub NextElement { my $self = shift; #$nListType is set to eLocationsList when asked for continents, countries or city listing if($self->{_DataType} != eLocationsList) { $self->{ErrorCode} = IDS_ERROR_GetListNotCalled; return -1; } else { if($self->{_LocationsList}->{nCurrItem} >= $#{$self->{_LocationsList}->{LocNames}}) { return -1; } elsif($self->{_LocationsList}->{nCurrItem} < $#{$self->{_LocationsList}->{LocNames}}) { $self->{_LocationsList}->{nCurrItem}++; return 0; } } } #sends HTTP query to obtain prayer times for the required city and saves the #results in run time structure sub GetPrayerTimes { my ($self, $CityID) = @_; my($nListType, $document, $remote, $StartData, $aline); $nListType = eNoData; #implementing error when GetPrayerTimes called before making a call to Open function unless (host ne "") { $self->{ErrorCode} = IDS_ERROR_OpenNotCalled; } $document = "/cgi-bin/PMCalc.cgi?F=X&I=" . $self->{ClientID} . "&R="; #Get the required list if Open function called before calling it if($self->{ErrorCode} != IDS_ERROR_OpenNotCalled) { #store parameters received to functions local variables #document is query string that will be passed to host $document = $document . "GD&CT="; $document = $document . $CityID; #establish the connection to the host $remote = IO::Socket::INET->new( Proto => "tcp", PeerAddr => host, PeerPort => "http(80)", ); #report an error if connection to host is not established unless($remote) { die "cannot connect to http daemon on host ". host; } print $remote "GET $document HTTP/1.0" . BLANK; $StartData = 0; #while remote is returning cetain text while(($StartData < 1) && (defined ($aline = <$remote>))) { #print " > " . $aline . "\n"; #check if line is a blank line, after which the XML document follows if($aline eq "\r\n") { $StartData = 1; } } #make a call to function that will write response returned by host to file #file will be parsed by XML parser and desired information will be stored in class member variables ParseXMLFile($self, $remote, ePrayerTimings); #close the connection established to host close $remote; #print " *** GetPrayerTimes ErrorCode: " . $self->{ErrorCode} . " ErrorText: " . $self->{ErrorText} . "<BR>\n"; # if($self->{_DataType} == ePrayerTimings) # { #discard previously set errors #Error Code IDS_ERROR_GetListNotCalled "Call GetList function first"; #Error Code IDS_ERROR_GetPrayerTimesNotCalled "Call GetPrayerTimes function first"; #Error Code IDS_ERROR_EmptyList "Empty List"; # $self->{ErrorCode} = IDS_NO_Error # if($self->{ErrorCode} == IDS_ERROR_GetListNotCalled || $self->{ErrorCode} == IDS_ERROR_GetPrayerTimesNotCalled || # $self->{ErrorCode} == IDS_ERROR_EmptyList); # } #check whether some string is returned by host # if($self->{_DataType} != ePrayerTimings) # { # $self->{ErrorCode} = IDS_ERROR_EmptyString # if($self->{ErrorCode}) == IDS_NO_Error; # } #discard error that was set that empty string returned by host # elsif($self->{ErrorCode} == IDS_ERROR_EmptyString) # { # $self->{ErrorCode} = IDS_NO_Error; # } } } #functions that will be called when asked for prayer timings #returns parent element(Country's ID) to which this city belongs sub GetCountryID { my $self = shift; #$nListType is set to ePrayerTimings when asked for prayer timings if($self->{_DataType} != ePrayerTimings) { $self->{ErrorCode} = IDS_ERROR_GetPrayerTimesNotCalled; return -1; } else { return $self->{_TimesData}->{nCountryID}; } } #returns ID of the city sub CityID { my $self = shift; #$nListType is set to ePrayerTimings when asked for prayer timings if($self->{_DataType} != ePrayerTimings) { $self->{ErrorCode} = IDS_ERROR_GetPrayerTimesNotCalled; return -1; } else { return $self->{_TimesData}->{nCityID}; } } #returns Title of the city sub CityTitle { my $self = shift; #$nListType is set to ePrayerTimings when asked for prayer timings if($self->{_DataType} != ePrayerTimings) { $self->{ErrorCode} = IDS_ERROR_GetPrayerTimesNotCalled; return -1; } else { return $self->{_TimesData}->{sCityTitle}; } } #returns time zone of the city sub CityTimeZone { my $self = shift; #$nListType is set to ePrayerTimings when asked for prayer timings if($self->{_DataType} != ePrayerTimings) { $self->{ErrorCode} = IDS_ERROR_GetPrayerTimesNotCalled; return -1; } else { return $self->{_TimesData}->{sCityTimeZone}; } } #returns Islamic date for city sub CityIslamicDate { my $self = shift; #$nListType is set to ePrayerTimings when asked for prayer timings if($self->{_DataType} != ePrayerTimings) { $self->{ErrorCode} = IDS_ERROR_GetPrayerTimesNotCalled; return -1; } else { return $self->{_TimesData}->{sCityIslamicDate}; } } #returns Gregorian date for city sub CityGregorianDate { my $self = shift; #$nListType is set to ePrayerTimings when asked for prayer timings if($self->{_DataType} != ePrayerTimings) { $self->{ErrorCode} = IDS_ERROR_GetPrayerTimesNotCalled; return -1; } else { return $self->{_TimesData}->{sCityGregorianDate}; } } #returns default/official Asr Fiqh for city sub CityAsrFiqh { my $self = shift; #$nListType is set to ePrayerTimings when asked for prayer timings if($self->{_DataType} != ePrayerTimings) { $self->{ErrorCode} = IDS_ERROR_GetPrayerTimesNotCalled; return -1; } else { return $self->{_TimesData}->{sCityAsrFiqh}; } } #returns requested prayer time for city sub CityPrayerTime { my ($self, $PrayerName) = @_; #$nListType is set to ePrayerTimings when asked for prayer timings if($self->{_DataType} != ePrayerTimings) { $self->{ErrorCode} = IDS_ERROR_GetPrayerTimesNotCalled; return -1; } else { return $self->{_TimesData}->{CityPrayerTimes}->{$PrayerName}; } } #returns 0 for no error and non zero error code for error sub GetError { my $self = shift; return $self->{ErrorCode}; } #returns error string if error function will return non zero sub GetErrorText { my $self = shift; my $err = $self->{ErrorCode}; if(($err >= IDS_NO_Error) && ($err <= IDS_ERROR_EmptyList)) { return $PMErrors[$err]; } else { if(defined($self->{ErrorText})) { return $self->{ErrorText} } else { return "Error text not received from server."; } } } #Function that will parse XML file sub ParseXMLFile { #access arguments passed my ($self, $xmlstream, $List) = @_; #discard all element names previously stored in an array $#{$self->{_LocationsList}->{LocNames}} = -1; #discard all element IDs previously stored in an array $#{$self->{_LocationsList}->{LocIDs}} = -1; $self->{_LocationsList}->{nCurrItem} = 0; #declare parser object my $Parser = new XML::Parser(Style=>'Stream'); #variable that will hold the text appearing within start and end tag that is country name #my ($csText); $Parser->{PMText} = ''; $Parser->{PMListType} = $List; $Parser->{PMObj} = $self; #socket having response from the server $Parser->parse($xmlstream); $self->{_LocationsList}->{nCurrItem} = 0; #Parser calls StartTag sub when it reads opening tag from XML file sub StartTag { #first argument is reference to parser object and second is string containing element type name my ($expat,$elementtype) = @_; #print " -- StartTag: elementtype = " . $elementtype . "<br>\n"; if($elementtype eq "PMxml") { my $datatype = %_->{datatype}; #print " -- StartTag: datatype = " . $datatype . "<br>\n"; if($datatype eq "Error") { $expat->{PMObj}->{_DataType} = eNoData; } elsif($datatype eq "Errors") { $expat->{PMObj}->{_DataType} = eNoData; } elsif($datatype eq "PrayerTimes") { $expat->{PMObj}->{_DataType} = ePrayerTimings; } else { $expat->{PMObj}->{_DataType} = eLocationsList; } } } #Parser calls Text sub when it sees characters. $_ contains text up to next tag, end tag, # processing instruction, or comment sub Text { my($expat) = @_; #print " -- expat = $expat, text= " . $_ . "<br>\n"; #translate new line to single space tr/\n/ /; #discard all leading white space characters s/^\s+//; #discard all trailing white space characters s/\s+$//; #return empty string if nothing found as text return if $_ eq ""; #if there is found some text within start and end tag then store it to $parabuf $expat->{PMText} = $_; #print "text= " . $_ . "<br>\n"; } #Parser calls EndTag sub when it reads end tag from XML file sub EndTag { #first argument is reference to parser object and second is string containing element type name my ($expat,$elementtype) = @_; my $self = $expat->{PMObj}; my $nX = $self->{_LocationsList}->{nCurrItem}; #print " -- End: index = " . $nX . ", element type = " . $elementtype . ", value =" . $expat->{PMText} . "<br>\n"; #print " > EndTag: DataType = " . $self->{_DataType} . "<BR>\n"; #get name and ID from XML file when asked for continents, countries or cities listing if($self->{_DataType} == eLocationsList) { if ($elementtype eq "LocID") { #Storing element ID accessed, to an array $self->{_LocationsList}->{LocIDs}->[$nX] = $expat->{PMText}; } if ($elementtype eq "Name") { #Storing name accessed, to an array $self->{_LocationsList}->{LocNames}->[$nX] = $expat->{PMText}; $self->{_LocationsList}->{nCurrItem} = $nX + 1; } } #asked for prayer times elsif($self->{_DataType} == ePrayerTimings) { #get city local id if ($elementtype eq "LocID") { $self->{_TimesData}->{nCityID} = $expat->{PMText}; } #get city title if ($elementtype eq "LocTitle") { $self->{_TimesData}->{sCityTitle} = $expat->{PMText}; } #get Country ID if ($elementtype eq "CountryID") { $self->{_TimesData}->{nCountryID} = $expat->{PMText}; } #get State ID if ($elementtype eq "StateID") { $self->{_TimesData}->{nStateID} = $expat->{PMText}; } #get city title if ($elementtype eq "LocTitle") { $self->{_TimesData}->{sCityTitle} = $expat->{PMText}; } #get city time zone if ($elementtype eq "LocTimeZone") { $self->{_TimesData}->{sCityTimeZone} = $expat->{PMText}; } #get city islamic date if ($elementtype eq "IDate") { $self->{_TimesData}->{sCityIslamicDate} = $expat->{PMText}; } #get city gregorian date if ($elementtype eq "GDate") { $self->{_TimesData}->{sCityGregorianDate} = $expat->{PMText}; } #get city As Fiqh if ($elementtype eq "AsrFiqh") { $self->{_TimesData}->{sCityAsrFiqh} = $expat->{PMText}; } #get fajr timing if ($elementtype eq "Fajr") { $self->{_TimesData}->{CityPrayerTimes}->{$elementtype} = $expat->{PMText}; } #get Shurooq timing if ($elementtype eq "Shurooq") { $self->{_TimesData}->{CityPrayerTimes}->{$elementtype} = $expat->{PMText}; } #get Zuhr timing if ($elementtype eq "Zuhr") { $self->{_TimesData}->{CityPrayerTimes}->{$elementtype} = $expat->{PMText}; } #get AsrHanafi timing if ($elementtype eq "AsrHanafi") { $self->{_TimesData}->{CityPrayerTimes}->{$elementtype} = $expat->{PMText}; } #get AsrShafei timing if ($elementtype eq "AsrShafei") { $self->{_TimesData}->{CityPrayerTimes}->{$elementtype} = $expat->{PMText}; } #get Maghrib timing if ($elementtype eq "Maghrib") { $self->{_TimesData}->{CityPrayerTimes}->{$elementtype} = $expat->{PMText}; } #get Isha timing if ($elementtype eq "Isha") { $self->{_TimesData}->{CityPrayerTimes}->{$elementtype} = $expat->{PMText}; } } else { #get error code if ($elementtype eq "ErrorCode") { $self->{ErrorCode} = $expat->{PMText}; $self->{ErrorCode} += 500 if $self->{ErrorCode} < 500; } #get error text if ($elementtype eq "ErrorText") { $self->{ErrorText} = $expat->{PMText}; } } $expat->{PMText} = ''; } } 1; __END__ # Below is stub documentation for your module. You better edit it!