Overview

Packages

  • admin
  • classes
    • media
  • CodeIgniter
    • Libraries
  • core
  • functions
  • JSMin
  • None
  • OpenID
  • PHP
  • PHPMailer
  • plugins
    • admin
    • development
    • feed
    • mail
    • media
    • misc
    • seo
    • spam
    • uploader
    • users
    • zenpage
    • zenphoto
      • news
  • Services
    • JSON

Classes

  • _zp_captcha
  • _zp_HTML_cache
  • admin_approval
  • Album
  • AlbumBase
  • AlbumZip
  • AMFReader
  • AMFStream
  • AnyFile
  • AnyFile_Options
  • Auth_OpenID
  • Auth_OpenID_AlreadySigned
  • Auth_OpenID_AssociateRequest
  • Auth_OpenID_Association
  • Auth_OpenID_AuthRequest
  • Auth_OpenID_AX
  • Auth_OpenID_AX_AttrInfo
  • Auth_OpenID_AX_Error
  • Auth_OpenID_AX_FetchRequest
  • Auth_OpenID_AX_FetchResponse
  • Auth_OpenID_AX_KeyValueMessage
  • Auth_OpenID_AX_Message
  • Auth_OpenID_AX_StoreRequest
  • Auth_OpenID_AX_StoreResponse
  • Auth_OpenID_BcMathWrapper
  • Auth_OpenID_CancelResponse
  • Auth_OpenID_CheckAuthRequest
  • Auth_OpenID_CheckIDRequest
  • Auth_OpenID_Consumer
  • Auth_OpenID_ConsumerResponse
  • Auth_OpenID_CryptUtil
  • Auth_OpenID_DatabaseConnection
  • Auth_OpenID_Decoder
  • Auth_OpenID_DiffieHellman
  • Auth_OpenID_DiffieHellmanSHA1ConsumerSession
  • Auth_OpenID_DiffieHellmanSHA1ServerSession
  • Auth_OpenID_DiffieHellmanSHA256ConsumerSession
  • Auth_OpenID_DiffieHellmanSHA256ServerSession
  • Auth_OpenID_DumbStore
  • Auth_OpenID_Encoder
  • Auth_OpenID_EncodingError
  • Auth_OpenID_Extension
  • Auth_OpenID_FailureResponse
  • Auth_OpenID_FileStore
  • Auth_OpenID_GenericConsumer
  • Auth_OpenID_GmpMathWrapper
  • Auth_OpenID_KVForm
  • Auth_OpenID_MalformedReturnURL
  • Auth_OpenID_MalformedTrustRoot
  • Auth_OpenID_Mapping
  • Auth_OpenID_MathLibrary
  • Auth_OpenID_MDB2Store
  • Auth_OpenID_MemcachedStore
  • Auth_OpenID_Message
  • Auth_OpenID_MySQLStore
  • Auth_OpenID_NamespaceMap
  • Auth_OpenID_NoReturnToError
  • Auth_OpenID_OpenIDStore
  • Auth_OpenID_PAPE_Request
  • Auth_OpenID_PAPE_Response
  • Auth_OpenID_Parse
  • Auth_OpenID_PlainTextConsumerSession
  • Auth_OpenID_PlainTextServerSession
  • Auth_OpenID_PostgreSQLStore
  • Auth_OpenID_Request
  • Auth_OpenID_Server
  • Auth_OpenID_ServerError
  • Auth_OpenID_ServerErrorContainer
  • Auth_OpenID_ServerRequest
  • Auth_OpenID_ServerResponse
  • Auth_OpenID_ServiceEndpoint
  • Auth_OpenID_ServiceEndpointLoader
  • Auth_OpenID_SessionNegotiator
  • Auth_OpenID_SetupNeededResponse
  • Auth_OpenID_Signatory
  • Auth_OpenID_SigningEncoder
  • Auth_OpenID_SQLiteStore
  • Auth_OpenID_SQLStore
  • Auth_OpenID_SRegBase
  • Auth_OpenID_SRegRequest
  • Auth_OpenID_SRegResponse
  • Auth_OpenID_SuccessResponse
  • Auth_OpenID_TrustRoot
  • Auth_OpenID_TypeURIMismatch
  • Auth_OpenID_UntrustedReturnURL
  • Auth_OpenID_WebResponse
  • Auth_Yadis_Discovery
  • Auth_Yadis_DiscoveryResult
  • Auth_Yadis_dom
  • Auth_Yadis_domxml
  • Auth_Yadis_HTTPFetcher
  • Auth_Yadis_HTTPResponse
  • Auth_Yadis_Manager
  • Auth_Yadis_ManagerLoader
  • Auth_Yadis_ParanoidHTTPFetcher
  • Auth_Yadis_ParseHTML
  • Auth_Yadis_PHPSession
  • Auth_Yadis_PlainHTTPFetcher
  • Auth_Yadis_ProxyResolver
  • Auth_Yadis_Service
  • Auth_Yadis_SessionLoader
  • Auth_Yadis_XMLParser
  • Auth_Yadis_XRDS
  • Auth_Yadis_Yadis
  • auto_backup
  • AVCSequenceParameterSetReader
  • bxslider
  • cacheManager
  • cacheManagerFeed
  • CI_jsmin
  • CI_load
  • cloneZenphoto
  • codeIgniter_kludge
  • colorbox
  • Comment
  • comment_form
  • contactformOptions
  • crop_image
  • cycle
  • defaultCodeblocks
  • deprecated_functions
  • DownloadList
  • dynamic_locale
  • dynamicAlbum
  • elFinder_options
  • email_new_user
  • exampleMacros
  • external_auth
  • ExternalFeed
  • externalFeed_options
  • favorites
  • favoritesOptions
  • federated_logon
  • feed
  • fieldExtender
  • flag_thumbnail
  • Gallery
  • galleryArticles
  • getID3
  • getid3_aac
  • getid3_apetag
  • getid3_flv
  • getid3_handler
  • getid3_id3v1
  • getid3_id3v2
  • getid3_lib
  • getid3_lyrics3
  • getid3_mp3
  • getid3_mpeg
  • getid3_quicktime
  • getid3_swf
  • GoogleMap
  • Googlemaps
  • googleVerifyOptions
  • hitcounter
  • HTML
  • htmlmetatags
  • http_auth
  • Image
  • image_effects
  • internal_deprecations
  • ipBlocker
  • jcarousel
  • jPlayer
  • jplayer_options
  • jquery_rating
  • JSMin
  • lib_GD_Options
  • lib_Imagick_Options
  • lib_NoGraphics
  • MediaObject
  • menu_manager
  • MergedRSS
  • MergedRSSOptions
  • mobile
  • Mobile_Detect
  • mobileTheme
  • multipleLayoutOptions
  • null_seo
  • OAuthConsumer
  • OAuthDataStore
  • OAuthRequest
  • OAuthServer
  • OAuthSignatureMethod
  • OAuthSignatureMethod_HMAC_SHA1
  • OAuthSignatureMethod_PLAINTEXT
  • OAuthSignatureMethod_RSA_SHA1
  • OAuthToken
  • OAuthUtil
  • pagedThumbsNav
  • pagedthumbsOptions
  • PclZip
  • PersistentObject
  • PHPMailer
  • PlainText
  • POP3
  • print_album_menu
  • pseudoPlayer
  • publishContent
  • quota_manager
  • reCaptcha
  • ReCaptchaResponse
  • register_user
  • rewriteRules
  • rewriteTokens
  • RSS
  • RSS_internal_deprecations
  • rss_options
  • search_statistics
  • SearchEngine
  • security_logger
  • seo_locale
  • Services_JSON
  • Services_JSON_Error
  • setupexternalFeed
  • setupRSS
  • show_not_loggedin
  • sitemap
  • slideshow
  • SMTP
  • static_html_cache
  • tagsuggest
  • TextObject
  • TextObject_internal_deprecations
  • TextObject_Options
  • ThemeObject
  • themeSwitcher
  • tinymce4Options
  • tinyURL
  • Transientimage
  • tweet
  • TwitterOAuth
  • UploadHandler
  • user_expiry
  • user_groups
  • user_logout_options
  • userAddressFields
  • utf8
  • Video
  • Video_internal_deprecations
  • VideoObject_Options
  • viewer_size_image_options
  • WEBdocs
  • WEBdocs_Options
  • xmpMetadata
  • Zenpage
  • Zenpage_internal_deprecations
  • ZenpageCategory
  • zenpagecms
  • ZenpageItems
  • ZenpageNews
  • ZenpagePage
  • ZenpageRoot
  • Zenphoto_Administrator
  • Zenphoto_Authority
  • zenphoto_org_news
  • zenphoto_seo
  • zenphotoDonate
  • ZipStream
  • zp_PHPMailer
  • zpCaptcha
  • zpFunctions
  • zpLegacySpam
  • zpMutex
  • zpSimpleSpam
  • zpTrivialSpam

Exceptions

  • BadFunctionCallException
  • BadMethodCallException
  • Exception
  • getid3_exception
  • JSMin_UnterminatedCommentException
  • JSMin_UnterminatedRegExpException
  • JSMin_UnterminatedStringException
  • LogicException
  • OAuthExcept
  • phpmailerException

Functions

  • __autoload
  • _escape_xref
  • _recaptcha_aes_encrypt
  • _recaptcha_aes_pad
  • _recaptcha_http_post
  • _recaptcha_mailhide_email_parts
  • _recaptcha_mailhide_urlbase64
  • _recaptcha_qsencode
  • accessAllAlbums
  • add_context
  • addalbumsToDatabase
  • addCategoriesToDatabase
  • addGeoCoord
  • addItem
  • addPagesToDatabase
  • addPluginScript
  • addPluginType
  • addSubalbumMenus
  • admin_album_list
  • admin_securityChecks
  • admin_showupdate
  • adminPageNav
  • adminToolbox
  • albumNumber
  • applyMacros
  • Auth_OpenID_arrangeByType
  • Auth_OpenID_AX_checkAlias
  • Auth_OpenID_AX_toTypeURIs
  • Auth_OpenID_bestMatchingService
  • Auth_OpenID_checkFieldName
  • Auth_OpenID_checkSessionType
  • Auth_OpenID_checkTimestamp
  • Auth_OpenID_detectMathLibrary
  • Auth_OpenID_discover
  • Auth_OpenID_discoverURI
  • Auth_OpenID_discoverWithoutYadis
  • Auth_OpenID_discoverWithYadis
  • Auth_OpenID_discoverXRI
  • Auth_OpenID_extractReturnURL
  • Auth_OpenID_findOPLocalIdentifier
  • Auth_OpenID_getAllAssociationTypes
  • Auth_OpenID_getAllowedReturnURLs
  • Auth_OpenID_getAuthorityPattern
  • Auth_OpenID_getAvailableSessionTypes
  • Auth_OpenID_getDefaultAssociationOrder
  • Auth_OpenID_getDefaultGen
  • Auth_OpenID_getDefaultMod
  • Auth_OpenID_getDefaultNegotiator
  • Auth_OpenID_getEncodedPattern
  • Auth_OpenID_getEncryptedNegotiator
  • Auth_OpenID_getEscapeRE
  • Auth_OpenID_getMathLib
  • Auth_OpenID_getOnlyEncryptedOrder
  • Auth_OpenID_getOpenIDConsumerTypeURIs
  • Auth_OpenID_getOpenIDTypeName
  • Auth_OpenID_getOpenIDTypeURIs
  • Auth_OpenID_getOPOrUserServices
  • Auth_OpenID_getSecretSize
  • Auth_OpenID_getSessionTypes
  • Auth_OpenID_getSupportedAssociationTypes
  • Auth_OpenID_getUnreserved
  • Auth_OpenID_getURIPattern
  • Auth_OpenID_getURLIllegalCharRE
  • Auth_OpenID_HMACSHA1
  • Auth_OpenID_HMACSHA256
  • Auth_OpenID_include_init
  • Auth_OpenID_isError
  • Auth_OpenID_isOpenID1
  • Auth_OpenID_legacy_discover
  • Auth_OpenID_makeOpenIDEndpoints
  • Auth_OpenID_math_extensions
  • Auth_OpenID_mkNonce
  • Auth_OpenID_noMathSupport
  • Auth_OpenID_pct_encoded_replace
  • Auth_OpenID_pct_encoded_replace_unreserved
  • Auth_OpenID_registerNamespaceAlias
  • Auth_OpenID_remove_dot_segments
  • Auth_OpenID_removeNamespaceAlias
  • Auth_OpenID_returnToMatches
  • Auth_OpenID_setNoMathSupport
  • Auth_OpenID_SHA1
  • Auth_OpenID_SHA256
  • Auth_OpenID_splitNonce
  • Auth_OpenID_supportsSReg
  • Auth_OpenID_urinorm
  • Auth_OpenID_verifyReturnTo
  • Auth_Yadis_array_scramble
  • Auth_Yadis_escapeForIRI
  • Auth_Yadis_getCanonicalID
  • Auth_Yadis_getDefaultProxy
  • Auth_Yadis_getEscapeRE
  • Auth_Yadis_getIPrivateChars
  • Auth_Yadis_getNSMap
  • Auth_Yadis_getServiceEndpoints
  • Auth_Yadis_getSupportedExtensions
  • Auth_Yadis_getUCSChars
  • Auth_Yadis_getXMLParser
  • Auth_Yadis_getXRDExpiration
  • Auth_Yadis_getXrefRE
  • Auth_Yadis_getXRIAuthorities
  • Auth_Yadis_identifierScheme
  • Auth_Yadis_iriToURI
  • Auth_Yadis_pct_escape_unicode
  • Auth_Yadis_providerIsAuthoritative
  • Auth_Yadis_rootAuthority
  • Auth_Yadis_setDefaultParser
  • Auth_Yadis_startswith
  • Auth_Yadis_toIRINormal
  • Auth_Yadis_toURINormal
  • Auth_Yadis_XRI
  • Auth_Yadis_XRIAppendArgs
  • authorSelector
  • build_query
  • build_url
  • bulkActionRedirect
  • bulkTags
  • byteConvert
  • cacheImage
  • checkAccess
  • checkAlbumimagesort
  • checkAlbumParentid
  • checkAlbumPassword
  • checkChosenItemStatus
  • checkChosenMenuset
  • checked
  • checkFolder
  • checkForEmptyTitle
  • checkForGuest
  • checkForPage
  • checkForPassword
  • checkForUpdate
  • checkHitcounterDisplay
  • checkIfChecked
  • checkIfLockedNews
  • checkIfLockedPage
  • checkIfNew
  • checkInstall
  • checkLayoutUseForImages
  • checkNewsAccess
  • checkNewsCategoryPassword
  • checkObjectsThumb
  • checkPagePassword
  • checkPageValidity
  • checkParentLayouts
  • checkPublishDates
  • checkRequiredField
  • checkSelectedAlbum
  • checkSignature
  • cleanAlbum
  • cleanHTML
  • clearSitemapCache
  • clonedFrom
  • codeblocktabsJS
  • comment_form_addComment
  • comment_form_handle_comment
  • comment_form_PaginationJS
  • comment_form_postcomment
  • comment_form_print10Most
  • comment_form_visualEditor
  • commentFormUseCaptcha
  • commentReply
  • commentsAllowed
  • consolidatedEditMessages
  • copyLayoutSelection
  • copyThemeDirectory
  • countArticles
  • countCombiNews
  • createMenuIfNotExists
  • createRelatedItemsResultArray
  • cron_starter
  • currentRelativeURL
  • customOptions
  • dateDiff
  • datepickerJS
  • dateTimeConvert
  • db_affected_rows
  • db_close
  • db_collation
  • db_connect
  • db_count
  • db_create
  • db_create_table
  • db_error
  • db_fetch_assoc
  • db_fetch_row
  • db_free_result
  • db_getSQLmode
  • db_insert_id
  • db_LIKE_escape
  • db_list_fields
  • db_name
  • db_num_rows
  • db_permissions
  • db_quote
  • db_setSQLmode
  • db_show
  • db_software
  • db_table_update
  • db_truncate_table
  • debug404
  • debugLog
  • debugLogBacktrace
  • debugLogVar
  • defaultCodeblocks_codebox
  • deleteArticle
  • deleteCategory
  • deleteItem
  • deleteLayoutSelection
  • deletePage
  • deleteThemeDirectory
  • detect_fetcher
  • detect_math
  • detect_query_corruption
  • detect_random
  • detect_stores
  • detect_xml
  • dircopy
  • displayError
  • doIncludes
  • elFinder_admin_tabs
  • elFinder_tinymce
  • enableExtension
  • escape
  • executeRSS
  • exitZP
  • exposeZenPhotoInformations
  • extensionEnabled
  • fetchComments
  • filesystemToInternal
  • filter_extractReturnURL
  • filter_MatchesAnyOpenIDConsumerType
  • filter_MatchesAnyOpenIDType
  • filterImageQuery
  • fix_path_redirect
  • formatList
  • fullText
  • galleryAlbumsPerPage
  • genAlbumList
  • generateCaptcha
  • generateLanguageList
  • generateListFromArray
  • generateListFromFiles
  • generateRadiobuttonsFromArray
  • generateSitemapCacheFile
  • generateSitemapIndexCacheFile
  • generateUnorderedListFromArray
  • get_AnyFile_suffixes
  • get_context
  • get_filterScript
  • get_instance
  • get_language_string
  • getAdminThumb
  • getAlbumArray
  • getAlbumBreadcrumb
  • getAlbumBreadcrumbAdmin
  • getAlbumCustomData
  • getAlbumData
  • getAlbumDate
  • getAlbumDesc
  • getAlbumFolder
  • getAlbumGeodata
  • getAlbumId
  • getAlbumInherited
  • getAlbumLinkURL
  • getAlbumLocation
  • getAlbumPage
  • getAlbumPlace
  • getAlbumStatistic
  • getAlbumThumb
  • getAlbumTitle
  • getAlbumURL
  • getAllAccessibleAlbums
  • getAllAlbums
  • getAllArticleDates
  • getAllCategories
  • getAllDates
  • getAllowedTags
  • getAllSubAlbumIDs
  • getAllSubalbums
  • getAllTagsCount
  • getAllTagsFromAlbum
  • getAllTagsFromAlbum_multi_unique
  • getAllTagsFromZenpage
  • getAllTagsUnique
  • getAllTranslations
  • getAnnotatedAlbumTitle
  • getAnnotatedImageTitle
  • getArticles
  • getAuthor
  • getBare
  • getBareAlbumDesc
  • getBareAlbumTitle
  • getBareGalleryDesc
  • getBareGalleryTitle
  • getBareImageDesc
  • getBareImageTitle
  • getBareNewsAlbumTitle
  • getBareNewsTitle
  • getBarePageTitle
  • getCategory
  • getCategoryID
  • getCategoryLink
  • getCategoryParentID
  • getCategorySortOrder
  • getCategoryTitle
  • getCheckboxState
  • getCodeblock
  • getCombiNews
  • getCommentAddress
  • getCommentAuthorEmail
  • getCommentAuthorLink
  • getCommentAuthorName
  • getCommentAuthorSite
  • getCommentBody
  • getCommentCount
  • getCommentDate
  • getCommentDateTime
  • getCommentErrors
  • getCommentsAllowed
  • getCommentStored
  • getCommentTime
  • getConsumer
  • getContentShorten
  • getCurrentMenuItem
  • getCurrentNewsArchive
  • getCurrentNewsCategory
  • getCurrentNewsCategoryID
  • getCurrentNewsCategoryParentID
  • getCurrentNewsPage
  • getCurrentPage
  • getCurrentTheme
  • getCustomAlbumThumb
  • getCustomAlbumThumbMaxSpace
  • getCustomImageURL
  • getCustomPageURL
  • getCustomSizedImageMaxSpace
  • getCustomSizedImageThumbMaxSpace
  • getDefaultHeight
  • getDefaultSizedImage
  • getDefaultWidth
  • getDownloadLink
  • getdownloadList
  • getDownloadURL
  • getE
  • getEnabledPlugins
  • getExpiryDatePost
  • getFavoritesURL
  • getField
  • getFirstImageURL
  • getFullHeight
  • getFullImageURL
  • getFullNewsImage
  • getFullWidth
  • getGalleryDesc
  • getGalleryIndexURL
  • getGalleryTitle
  • getGeoCoord
  • getHeadTitle
  • getHitcounter
  • getImageArgs
  • getImageCacheFilename
  • getImageCachePostfix
  • getImageCity
  • getImageCountry
  • getImageCustomData
  • getImageData
  • getImageDate
  • getImageDesc
  • getImageEXIFData
  • getImageGeodata
  • getImageID
  • getImageLinkURL
  • getImageLocation
  • getImageMetaData
  • getImageParameters
  • getImageProcessorURI
  • getImageProcessorURIFromCacheName
  • getImageRotation
  • getImageSortOrder
  • getImageState
  • getImageStatistic
  • getImageThumb
  • getImageTitle
  • getImageURI
  • getImageURL
  • getItem
  • getItemByID
  • getItemTitleAndURL
  • getjPlayerSkinCSS
  • getjPlayerSkins
  • getLanguageArray
  • getLanguageFlag
  • getLastImageURL
  • getLatestComments
  • getLatestNews
  • getLatestZenpageComments
  • getLayout
  • getLayoutSelector
  • getLink
  • getLinkHTML
  • getLogTabs
  • getMacros
  • getMainSiteName
  • getMainSiteURL
  • getManagedAlbumList
  • getMaxSpaceContainer
  • getMenuFromLink
  • getMenuItemChilds
  • getMenuItems
  • getMenumanagerPredicessor
  • getMenumanagerSuccessor
  • getMenuSetSelector
  • getMenuVisibility
  • getMimeString
  • getNestedAlbumList
  • getNewsAdminOption
  • getNewsAdminOptionPath
  • getNewsAlbumName
  • getNewsAlbumTitle
  • getNewsAlbumURL
  • getNewsArchivePath
  • getNewsArchiveURL
  • getNewsAuthor
  • getNewsCategories
  • getNewsCategoryCustomData
  • getNewsCategoryDesc
  • getNewsCategoryPath
  • getNewsCategoryURL
  • getNewsContent
  • getNewsContentShorten
  • getNewsCustomData
  • getNewsDate
  • getNewsExtraContent
  • getNewsID
  • getNewsImageTags
  • getNewsIndexURL
  • getNewsLink
  • getNewsPagesStatistic
  • getNewsPathNav
  • getNewsReadMore
  • getNewsTitle
  • getNewsTitleLink
  • getNewsTitlePath
  • getNewsType
  • getNewsURL
  • getNewsVideoContent
  • getNextAlbum
  • getNextAlbumURL
  • getNextImageThumb
  • getNextImageURL
  • getNextNewsPageURL
  • getNextNewsURL
  • getNextPageURL
  • getNextPrevNews
  • getNotViewableAlbums
  • getNotViewableImages
  • getNumAlbums
  • getNumAllSubalbums
  • getNumImages
  • getNumNews
  • getNumPages
  • getNumSubalbums
  • getOpenIDURL
  • getOption
  • getOptionFromDB
  • getOptionList
  • getPageAuthor
  • getPageContent
  • getPageCustomData
  • getPageDate
  • getPageExtraContent
  • getPageID
  • getPageLastChangeDate
  • getPageLinkPath
  • getPageLinkURL
  • getPageNavList
  • getPageNumURL
  • getPageParentID
  • getPageRedirect
  • getPages
  • getPageSelector
  • getPageSortorder
  • getPageTitle
  • getPageTitleLink
  • getPageURL
  • getParentAlbums
  • getParentAlbumsAdmin
  • getParentBreadcrumb
  • getParentItems
  • getParentMenuItems
  • getParentNewsCategories
  • getParentPages
  • getPasswordProtectImage
  • getPHPFiles
  • getPlugin
  • getPluginFiles
  • getPluginTabs
  • getPrevAlbum
  • getPrevAlbumURL
  • getPrevImageThumb
  • getPrevImageURL
  • getPrevNewsPageURL
  • getPrevNewsURL
  • getPrevPageURL
  • getProtectedImageURL
  • getRandomImages
  • getRandomImagesAlbum
  • getRating
  • getRelatedItems
  • getRequestURI
  • getReturnTo
  • getRSSHeaderLink
  • getRSSLink
  • getScheme
  • getSearchDate
  • getSearchURL
  • getSearchWords
  • getSelectedLayout
  • getSerializedArray
  • getSetClause
  • getSiteHomeURL
  • getSitemapAlbumList
  • getSitemapAlbums
  • getSitemapGoogleImageVideoExtras
  • getSitemapGoogleLoopIndex
  • getSitemapImages
  • getSitemapIndexLinks
  • getSitemapZenpageNewsArticles
  • getSitemapZenpageNewsCategories
  • getSitemapZenpageNewsIndex
  • getSitemapZenpagePages
  • getSizeCustomImage
  • getSizeDefaultImage
  • getSizeDefaultThumb
  • getSizedImageURL
  • getSizeFullImage
  • getStore
  • getSubCategories
  • getSubtabs
  • getSuffix
  • getTagCountByAccess
  • getTagOrder
  • getTags
  • gettext_pl
  • gettext_th
  • getTheme
  • getThemeFiles
  • getThemeOption
  • getTimezones
  • getTinyMCE4ConfigFiles
  • getTitle
  • getTotalArticles
  • getTotalImagesIn
  • getTotalNewsPages
  • getTotalPages
  • getTrustRoot
  • getUnprotectedImageURL
  • getUrAlbum
  • getURL
  • getUserIP
  • getUserLocale
  • getVersion
  • getViewerImageSize
  • getWatermarkParam
  • getWatermarkPath
  • getWatermarks
  • getWhereClause
  • getXSRFToken
  • getZenpageHitcounter
  • getZenpageRSSHeaderLink
  • getZenpageRSSLink
  • getZenpageStatistic
  • googleVerifyHead
  • handleSearchParms
  • hasDynamicAlbumSuffix
  • hasNextImage
  • hasNextPage
  • hasPrevImage
  • hasPrevPage
  • hitcounter
  • html_decode
  • html_encode
  • html_encodeTagged
  • httpsRedirect
  • httpUploadHandler
  • httpUploadHandler_admin_tabs
  • i18nSetLocale
  • imageBlurGD
  • imageDebug
  • imageError
  • imageNumber
  • imgSrcURI
  • in_context
  • inNewsCategory
  • inProtectedNewsCategory
  • installSignature
  • instrument
  • inSubNewsCategoryOf
  • internalToFilesystem
  • inventMenuItem
  • iptc_make_tag
  • is_AdminEditPage
  • is_connected
  • is_GalleryNewsType
  • is_News
  • is_NewsArchive
  • is_NewsArticle
  • is_NewsCategory
  • is_NewsPage
  • is_NewsType
  • is_Pages
  • is_valid_email_zp
  • is_valid_image
  • is_valid_other_type
  • is_zip
  • isAlbumClass
  • isAlbumPage
  • isArchive
  • isHandledAlbum
  • isImageClass
  • isImagePage
  • isImagePhoto
  • isImageVideo
  • isLandscape
  • isMyAlbum
  • isMyNews
  • isMyPage
  • isolate
  • isProtectedAlbum
  • isProtectedNewsCategory
  • isProtectedPage
  • isSubNewsCategoryOf
  • isValidURL
  • jQueryUpload_head
  • jQueryUpload_headers
  • jQueryUploadHandler
  • jQueryUploadHandler_admin_tabs
  • js_encode
  • json_decode
  • json_encode
  • kses
  • kses_array_lc
  • kses_attr
  • kses_bad_protocol
  • kses_bad_protocol_once
  • kses_bad_protocol_once2
  • kses_check_attr_val
  • kses_decode_entities
  • kses_hair
  • kses_hook
  • kses_html_error
  • kses_js_entities
  • kses_no_null
  • kses_normalize_entities
  • kses_normalize_entities2
  • kses_split
  • kses_split2
  • kses_stripslashes
  • kses_version
  • ksesProcess
  • layoutSelector
  • layoutSelector_album
  • listDBUses
  • listDirectoryFiles
  • listUses
  • load_zenpage_news
  • load_zenpage_pages
  • loadLocalOptions
  • log_message
  • lookupSortKey
  • macro_admin_tabs
  • macroList_show
  • makeAlbumCurrent
  • makeImageCurrent
  • makeSpecialImageName
  • markRelease_button
  • mb_strlen
  • mb_strpos
  • mb_strrpos
  • mb_strtolower
  • mb_strtoupper
  • mb_substr
  • mb_substr_count
  • menu_admin_toolbox_global
  • menu_tabs
  • minDiff
  • mkdir_recursive
  • my_truncate_string
  • myts_date
  • newAlbum
  • newImage
  • next_album
  • next_comment
  • next_image
  • next_news
  • next_page
  • ngettext_pl
  • ngettext_th
  • normalizeColumns
  • omsAdditions
  • openedForComments
  • parse_query
  • parse_size
  • parseAllowedTags
  • parseHttpAcceptLanguage
  • passAlbums
  • passImages
  • pathurlencode
  • PclZipUtilCopyBlock
  • PclZipUtilOptionText
  • PclZipUtilPathInclusion
  • PclZipUtilPathReduction
  • PclZipUtilRename
  • PclZipUtilTranslateWinPath
  • PHPMailerAutoload
  • populateManagedObjectsList
  • postAlbumSort
  • postIndexDecode
  • postIndexEncode
  • prefix
  • prepareAlbumPage
  • prepareCustomPage
  • prepareImagePage
  • prepareIndexPage
  • print404status
  • print_language_string_list
  • printAddToFavorites
  • printAdminFooter
  • printAdminHeader
  • printAdminRightsTable
  • printAdminToolbox
  • printAlbumBreadcrumb
  • printAlbumButtons
  • printAlbumCustomData
  • printAlbumData
  • printAlbumDate
  • printAlbumDesc
  • printAlbumEditForm
  • printAlbumEditRow
  • printAlbumLegend
  • printAlbumLink
  • printAlbumLocation
  • printAlbumMap
  • printAlbumMenu
  • printAlbumMenuJump
  • printAlbumMenuList
  • printAlbumMenuListAlbum
  • printAlbumPlace
  • printAlbumRating
  • printAlbumsSelector
  • printAlbumStatistic
  • printAlbumStatisticItem
  • printAlbumThumbImage
  • printAlbumTitle
  • printAlbumURL
  • printAlbumZip
  • printAllDates
  • printAllNewsCategories
  • printAllTags
  • printAllTagsAs
  • printAllTagsFromAlbum
  • printAllTagsFromZenpage
  • printAnnotatedAlbumTitle
  • printAnnotatedImageTitle
  • printArticleCategories
  • printArticleDatesDropdown
  • printArticlesPerPageDropdown
  • printBareAlbumDesc
  • printBareAlbumTitle
  • printBareGalleryDesc
  • printBareGalleryTitle
  • printBareImageDesc
  • printBareImageTitle
  • printBareNewsTitle
  • printBarePageTitle
  • printBulkActions
  • printCaptcha
  • printCategoriesStatistic
  • printCategoryCheckboxListEntry
  • printCategoryDropdown
  • printCategoryListSortableTable
  • printCategorySelection
  • printCodeblock
  • printCodeblockEdit
  • printCommentAuthorLink
  • printCommentErrors
  • printCommentForm
  • printContactForm
  • printCurrentNewsArchive
  • printCurrentNewsCategory
  • printCustomAlbumThumbImage
  • printCustomAlbumThumbMaxSpace
  • printCustomMenu
  • printCustomPageSelector
  • printCustomPageURL
  • printCustomSizedImage
  • printCustomSizedImageMaxHeight
  • printCustomSizedImageMaxSpace
  • printCustomSizedImageThumbMaxSpace
  • printDefaultSizedImage
  • printDownloadAlbumZipURL
  • printDownloadLink
  • printDownloadLinkAlbumZip
  • printdownloadList
  • printDownloadURL
  • printEditable
  • printEditCommentLink
  • printEditDropdown
  • printExpired
  • printFavoritesLink
  • printFavoritesURL
  • printField
  • printGalleryDesc
  • printGalleryIndexURL
  • printGalleryTitle
  • printGoogleMap
  • printHeadTitle
  • printHomeLink
  • printImageCustomData
  • printImageData
  • printImageDate
  • printImageDesc
  • printImageDiv
  • printImageEXIFData
  • printImageID
  • printImageLink
  • printImageMap
  • printImageMetadata
  • printImageRating
  • printImageSortOrder
  • printImageStatistic
  • printImageThumb
  • printImageTitle
  • printImageURL
  • printItemEditLink
  • printItemsList
  • printItemsListTable
  • printItemStatusDropdown
  • printjCarouselThumbNav
  • printjPlayerPlaylist
  • printLanguageSelector
  • printLatestAlbums
  • printLatestComments
  • printLatestImages
  • printLatestImagesByDate
  • printLatestImagesByMtime
  • printLatestNews
  • printLatestUpdatedAlbums
  • printLatestZenpageComments
  • printLink
  • printLinkHTML
  • printLogoAndLinks
  • printManagedObjects
  • printMenuemanagerPageList
  • printMenuemanagerPageListWithNav
  • printMenumanagerBreadcrumb
  • printMenumanagerNextLink
  • printMenumanagerPrevLink
  • printMostPopularItems
  • printMostRatedAlbums
  • printMostRatedImages
  • printMostRatedItems
  • printNestedAlbumsList
  • printNestedItemsList
  • printNestedMenu
  • printNews
  • printNewsArchive
  • printNewsAuthor
  • printNewsCategories
  • printNewsCategoryCustomData
  • printNewsCategoryDesc
  • printNewsCategoryURL
  • printNewsContent
  • printNewsCustomData
  • printNewsDate
  • printNewsExtraContent
  • printNewsImageTags
  • printNewsIndexURL
  • printNewsLink
  • printNewsPageList
  • printNewsPageListWithNav
  • printNewsReadMoreLink
  • printNewsStatistic
  • printNewsTitle
  • printNewsTitleLink
  • printNewsURL
  • printNextNewsLink
  • printNextNewsPageLink
  • printNextPageLink
  • printNextPageURL
  • printPageArticleTags
  • printPageAuthor
  • printPageContent
  • printPageCustomData
  • printPageDate
  • printPagedThumbsNav
  • printPageExtraContent
  • printPageID
  • printPageLastChangeDate
  • printPageLinkURL
  • printPageList
  • printPageListWithNav
  • printPageMenu
  • printPageNav
  • printPageSelector
  • printPagesListTable
  • printPagesStatistic
  • printPageTitle
  • printPageTitleLink
  • printPageURL
  • printParentBreadcrumb
  • printParentPagesBreadcrumb
  • printPasswordForm
  • printPopularAlbums
  • printPopularImages
  • printPreloadScript
  • printPrevNewsLink
  • printPrevNewsPageLink
  • printPrevPageLink
  • printPrevPageURL
  • printPublished
  • printPublishIconLink
  • printRandomImages
  • printRating
  • printRegisterURL
  • printRegistrationForm
  • printRelatedItems
  • printRSSHeaderLink
  • printRSSLink
  • printSearchBreadcrumb
  • printSearchForm
  • printSiteHomeURL
  • printSizedImageLink
  • printSizedImageURL
  • printSlideShow
  • printSlideShowJS
  • printSlideShowLink
  • printSortableHead
  • printSortOrderDropdown
  • printSubPagesExcerpts
  • printSubtabs
  • printTabs
  • printTags
  • printThumbNav
  • printTopRatedAlbums
  • printTopRatedImages
  • printTopRatedItems
  • printUnpublishedDropdown
  • printUserLogin_out
  • printUserSizeImage
  • printUserSizeSelector
  • printVersion
  • printZenJavascripts
  • printZenpageIconLegend
  • printZenpageItemsBreadcrumb
  • printZenpageNewsCategorySelector
  • printZenpagePagesSelector
  • printZenpageRSSHeaderLink
  • printZenpageRSSLink
  • printZenpageStatistic
  • printZenphotoLink
  • process_language_string_save
  • processAlbumBulkActions
  • processAlbumEdit
  • processCodeblockSave
  • processCommentBulkActions
  • processCredentials
  • processCustomOptionSave
  • processEditSelection
  • processExpired
  • processImageBulkActions
  • processImageEdit
  • processManagedObjects
  • processMenuBulkActions
  • processOrder
  • processRights
  • processTags
  • processZenpageBulkActions
  • propSizes
  • publishItem
  • purgeOption
  • query
  • query_full_array
  • query_single_row
  • rc4
  • read_exif_data_protected
  • readTags
  • recaptcha_check_answer
  • recaptcha_get_html
  • recaptcha_get_signup_url
  • recaptcha_mailhide_html
  • recaptcha_mailhide_url
  • reconfigureAction
  • reconfigureCS
  • reconfigurePage
  • recordMissing
  • rem_context
  • removeParentAlbumNames
  • resetCurrentAlbum
  • restore_context
  • reveal
  • rewrite_get_album_image
  • rewrite_path
  • rewrite_path_zenpage
  • RSS_Channel
  • RSS_Retrieve
  • RSS_Tags
  • rulesList
  • run
  • safe_fnmatch
  • safe_glob
  • sanitize
  • sanitize_numeric
  • sanitize_path
  • sanitize_script
  • sanitize_string
  • sanitizeRedirect
  • save_context
  • saveLayoutSelection
  • saveZenphotoLayoutSelection
  • search_quote
  • secureServer
  • seo_cleanup_button
  • seoFriendly
  • seoFriendlyJS
  • set_context
  • setAlbumCustomData
  • setAlbumSubtabs
  • setImageCustomData
  • setMainDomain
  • setOption
  • setOptionDefault
  • setPluginDomain
  • setThemeColumns
  • setThemeDomain
  • setThemeOption
  • setThemeOptionDefault
  • setupAllowedMaps
  • setupCurrentLocale
  • setupDomain
  • setupTheme
  • shortenContent
  • showOrNotShowField
  • shuffle_assoc
  • signatureChange
  • site_upgrade_button
  • site_upgrade_status
  • sitemap_echonl
  • sitemap_getChangefreq
  • sitemap_getDateformat
  • sitemap_getDBLimit
  • sitemap_getISO8601Date
  • skipScheduledPublishing
  • sortByKey
  • sortByMultilingual
  • sortMultiArray
  • standardScripts
  • standardThemeOptions
  • stickyNews
  • storeConfig
  • storeTags
  • stripSuffix
  • submenuOf
  • switchLog
  • tagSelector
  • tagSuggestJS
  • tagSuggestJS_admin
  • tagSuggestJS_frontend
  • themeIsEditable
  • themeSetup
  • timezoneDiff
  • tinymce4ConfigJS
  • truncate_string
  • unpublishedZenphotoItemCheck
  • unpublishSubalbums
  • unQuote
  • unzip
  • updateArticle
  • updateCacheName
  • updateCategory
  • updateConfigItem
  • updateItemSortorder
  • updateItemsSortorder
  • updateMenuItem
  • updatePage
  • upload_extra
  • upload_form
  • upload_head
  • user_mailing_list_button
  • validateLocale
  • wordpress_import_button
  • wp_prefix
  • wp_query_full_array
  • wpimport_TryAgainError
  • XSRFdefender
  • XSRFToken
  • zenJavascript
  • zenpageAlbumImage
  • zenpageBulkActionMessage
  • zenpageHitcounter
  • zenpageJSCSS
  • zenpageOpenedForComments
  • zenpagePublish
  • zenphoto_PHPMailer
  • zenphoto_sendmail
  • zenPhotoTheme
  • zp_apply_filter
  • zp_clearCookie
  • zp_colorAllocate
  • zp_cookieEncode
  • zp_copyCanvas
  • zp_createImage
  • zp_drawRectangle
  • zp_error
  • zp_filter_slot
  • zp_filter_unique_id
  • zp_getCookie
  • zp_getFonts
  • zp_graphicsLibInfo
  • zp_handle_password
  • zp_handle_password_single
  • zp_has_filter
  • zp_image_types
  • zp_imageCanRotate
  • zp_imageColorTransparent
  • zp_imageDims
  • zp_imageFill
  • zp_imageFontHeight
  • zp_imageFontWidth
  • zp_imageFromString
  • zp_imageGet
  • zp_imageGray
  • zp_imageHeight
  • zp_imageIPTC
  • zp_imageKill
  • zp_imageLoadFont
  • zp_imageMerge
  • zp_imageOutput
  • zp_imageResizeAlpha
  • zp_imageUnsharpMask
  • zp_imageWidth
  • zp_load_album
  • zp_load_gallery
  • zp_load_image
  • zp_load_page
  • zp_load_request
  • zp_load_search
  • zp_loggedin
  • zp_mail
  • zp_register_filter
  • zp_remove_filter
  • zp_resampleImage
  • zp_rotateImage
  • zp_session_start
  • zp_setCookie
  • zp_writeString
  • zpErrorHandler
  • zpFormattedDate
  • zpRewriteURL
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
   1: <?php
   2: 
   3: /**
   4:  * search class
   5:  * @package classes
   6:  */
   7: // force UTF-8 Ø
   8: //*************************************************************
   9: //*ZENPHOTO SEARCH ENGINE CLASS *******************************
  10: //*************************************************************
  11: 
  12: define('EXACT_TAG_MATCH', getOption('exact_tag_match'));
  13: define('SEARCH_DURATION', 3000);
  14: define('SEARCH_CACHE_DURATION', getOption('search_cache_duration'));
  15: 
  16: class SearchEngine {
  17: 
  18:     var $fieldList = NULL;
  19:     var $page = 1;
  20:     var $images = NULL;
  21:     var $albums = NULL;
  22:     var $articles = NULL;
  23:     var $pages = NULL;
  24:     var $pattern;
  25:     var $tagPattern;
  26:     private $exact = false;
  27:     protected $dynalbumname = NULL;
  28:     protected $album = NULL;
  29:     protected $words;
  30:     protected $dates;
  31:     protected $whichdates = 'date'; // for zenpage date searches, which date field to search
  32:     protected $search_no_albums = false; // omit albums
  33:     protected $search_no_images = false; // omit images
  34:     protected $search_no_pages = false; // omit pages
  35:     protected $search_no_news = false; // omit news
  36:     protected $search_unpublished = false; // will override the loggedin checks with respect to unpublished items
  37:     protected $search_structure; // relates translatable names to search fields
  38:     protected $iteration = 0; // used by apply_filter('search_statistics') to indicate sequential searches of different objects
  39:     protected $processed_search = NULL;
  40:     protected $album_list = NULL; // list of albums to search
  41:     protected $category_list = NULL; // list of categories for a news search
  42:     protected $searches = NULL; // remember the criteria for past searches
  43:     protected $extraparams = array(); // allow plugins to add to search parameters
  44: //  mimic album object
  45:     var $loaded = false;
  46:     var $table = 'albums';
  47:     var $transient = true;
  48: 
  49:     /**
  50:      * Constuctor
  51:      *
  52:      * @param bool $dynamic_album set true for dynamic albums (limits the search fields)
  53:      * @return SearchEngine
  54:      */
  55:     function __construct($dynamic_album = false) {
  56:         global $_zp_exifvars, $_zp_gallery;
  57:         switch ((int) getOption('exact_tag_match')) {
  58:             case 0:
  59:                 // partial
  60:                 $this->tagPattern = array('type' => 'like', 'open' => '%', 'close' => '%');
  61:                 break;
  62:             case 1:
  63:                 // exact
  64:                 $this->tagPattern = array('type' => '=', 'open' => '', 'close' => '');
  65:                 break;
  66:             case 2:
  67:                 //word
  68:                 $this->tagPattern = array('type' => 'regexp', 'open' => '[[:<:]]', 'close' => '[[:>:]]');
  69:                 break;
  70:         }
  71: 
  72:         switch ((int) getOption('exact_string_match')) {
  73:             case 0:
  74:                 // pattern
  75:                 $this->pattern = array('type' => 'like', 'open' => '%', 'close' => '%');
  76:                 break;
  77:             case 1:
  78:                 // partial start
  79:                 $this->pattern = array('type' => 'regexp', 'open' => '[[:<:]]', 'close' => '');
  80:                 break;
  81:             case 2:
  82:                 //word
  83:                 $this->pattern = array('type' => 'regexp', 'open' => '[[:<:]]', 'close' => '[[:>:]]');
  84:                 break;
  85:         }
  86: 
  87:         $this->extraparams['albumssorttype'] = getOption('search_album_sort_type');
  88:         $this->extraparams['albumssortdirection'] = getOption('search_album_sort_direction') ? 'DESC' : '';
  89:         $this->extraparams['imagessorttype'] = getOption('search_image_sort_type');
  90:         $this->extraparams['imagessortdirection'] = getOption('search_image_sort_direction') ? 'DESC' : '';
  91:         $this->extraparams['newssorttype'] = 'date';
  92:         $this->extraparams['newssortdirection'] = 'DESC';
  93:         $this->extraparams['pagesssorttype'] = 'title';
  94:         $this->extraparams['pagessortdirection'] = '';
  95: 
  96: //image/album fields
  97:         $this->search_structure['title'] = gettext('Title');
  98:         $this->search_structure['desc'] = gettext('Description');
  99:         $this->search_structure['tags'] = gettext('Tags');
 100:         $this->search_structure['tags_exact'] = ''; //  internal use only field
 101:         $this->search_structure['filename'] = gettext('File/Folder name');
 102:         $this->search_structure['date'] = gettext('Date');
 103:         $this->search_structure['custom_data'] = gettext('Custom data');
 104:         $this->search_structure['location'] = gettext('Location/Place');
 105:         $this->search_structure['city'] = gettext('City');
 106:         $this->search_structure['state'] = gettext('State');
 107:         $this->search_structure['country'] = gettext('Country');
 108:         $this->search_structure['copyright'] = gettext('Copyright');
 109:         $this->search_structure['owner'] = gettext('Owner');
 110:         $this->search_structure['credit'] = gettext('Credit');
 111:         if (extensionEnabled('zenpage') && !$dynamic_album) {
 112: //zenpage fields
 113:             $this->search_structure['content'] = gettext('Content');
 114:             $this->search_structure['extracontent'] = gettext('ExtraContent');
 115:             $this->search_structure['author'] = gettext('Author');
 116:             $this->search_structure['lastchangeauthor'] = gettext('Last Editor');
 117:             $this->search_structure['titlelink'] = gettext('TitleLink');
 118:             $this->search_structure['news_categories'] = gettext('Categories');
 119:         }
 120: //metadata fields
 121:         foreach ($_zp_exifvars as $field => $row) {
 122:             if ($row[4] && $row[5]) { //    only those that are "real" and "processed"
 123:                 $this->search_structure[strtolower($field)] = $row[2];
 124:             }
 125:         }
 126:         $this->search_structure = zp_apply_filter('searchable_fields', $this->search_structure);
 127:         if (isset($_REQUEST['words'])) {
 128:             $this->words = zpFunctions::removeTrailingSlash(strtr(sanitize($_REQUEST['words'], 4), array('__23__' => '#', '__25__' => '%', '__26__' => '&', '__2F__' => '/')));
 129:         } else {
 130:             $this->words = NULL;
 131:             if (isset($_REQUEST['date'])) { // words & dates are mutually exclusive
 132:                 $this->dates = zpFunctions::removeTrailingSlash(sanitize($_REQUEST['date'], 3));
 133:                 if (isset($_REQUEST['whichdate'])) {
 134:                     $this->whichdates = sanitize($_REQUEST['whichdate']);
 135:                 }
 136:             } else {
 137:                 $this->dates = NULL;
 138:             }
 139:         }
 140:         $this->fieldList = $this->parseQueryFields();
 141:         if (isset($_REQUEST['inalbums'])) {
 142:             $list = trim(sanitize($_REQUEST['inalbums'], 3));
 143:             if (strlen($list) > 0) {
 144:                 switch ($list) {
 145:                     case "0":
 146:                         $this->search_no_albums = true;
 147:                         setOption('search_no_albums', 1, false);
 148:                         break;
 149:                     case "1":
 150:                         $this->search_no_albums = false;
 151:                         setOption('search_no_albums', 0, false);
 152:                         break;
 153:                     default:
 154:                         $this->album_list = explode(',', $list);
 155:                         break;
 156:                 }
 157:             }
 158:         }
 159:         if (isset($_REQUEST['inimages'])) {
 160:             $list = trim(sanitize($_REQUEST['inimages'], 3));
 161:             if (strlen($list) > 0) {
 162:                 switch ($list) {
 163:                     case "0":
 164:                         $this->search_no_images = true;
 165:                         setOption('search_no_images', 1, false);
 166:                         break;
 167:                     case "1":
 168:                         $this->search_no_images = false;
 169:                         setOption('search_no_images', 0, false);
 170:                         break;
 171:                 }
 172:             }
 173:         }
 174:         if (isset($_REQUEST['inpages'])) {
 175:             $list = trim(sanitize($_REQUEST['inpages'], 3));
 176:             if (strlen($list) > 0) {
 177:                 switch ($list) {
 178:                     case "0":
 179:                         $this->search_no_pages = true;
 180:                         setOption('search_no_pages', 1, false);
 181:                         break;
 182:                 }
 183:             }
 184:         }
 185:         if (isset($_REQUEST['innews'])) {
 186:             $list = trim(sanitize($_REQUEST['innews'], 3));
 187:             if (strlen($list) > 0) {
 188:                 switch ($list) {
 189:                     case "0":
 190:                         $this->search_no_news = true;
 191:                         setOption('search_no_news', 1, false);
 192:                         break;
 193:                     case "1":
 194:                         break;
 195:                     default:
 196:                         $this->category_list = explode(',', $list);
 197:                         break;
 198:                 }
 199:             }
 200:         }
 201:         $this->images = NULL;
 202:         $this->albums = NULL;
 203:         $this->searches = array('images' => NULL, 'albums' => NULL, 'pages' => NULL, 'news' => NULL);
 204:         zp_apply_filter('search_instantiate', $this);
 205:     }
 206: 
 207:     /**
 208:      * mimic an album object
 209:      * @return number
 210:      */
 211:     function getID() {
 212:         return 0;
 213:     }
 214: 
 215:     /**
 216:      * Returns a list of search fields display names indexed by the search mask
 217:      *
 218:      * @return array
 219:      */
 220:     function getSearchFieldList() {
 221:         $list = array();
 222:         foreach ($this->search_structure as $key => $display) {
 223:             if ($display) {
 224:                 $list[$display] = $key;
 225:             }
 226:         }
 227:         return $list;
 228:     }
 229: 
 230:     /**
 231:      * Returns an array of the enabled search fields
 232:      *
 233:      * @return array
 234:      */
 235:     function allowedSearchFields() {
 236:         $setlist = array();
 237:         $fields = strtolower(getOption('search_fields'));
 238:         if (is_numeric($fields)) {
 239:             $setlist = $this->numericFields($fields);
 240:         } else {
 241:             $list = explode(',', $fields);
 242:             foreach ($this->search_structure as $key => $display) {
 243:                 if (in_array($key, $list)) {
 244:                     $setlist[$display] = $key;
 245:                 }
 246:             }
 247:         }
 248:         return $setlist;
 249:     }
 250: 
 251:     /**
 252:      * converts old style bitmask field spec into field list array
 253:      *
 254:      * @param bit $fields
 255:      * @return array
 256:      */
 257:     protected function numericFields($fields) {
 258:         if ($fields == 0)
 259:             $fields = 0x0fff;
 260:         if ($fields & 0x01)
 261:             $list[$this->search_structure['title']] = 'title';
 262:         if ($fields & 0x02)
 263:             $list[$this->search_structure['desc']] = 'desc';
 264:         if ($fields & 0x04)
 265:             $list[$this->search_structure['tags']] = 'tags';
 266:         if ($fields & 0x08)
 267:             $list[$this->search_structure['filename']] = 'filename';
 268:         return $list;
 269:     }
 270: 
 271:     /**
 272:      * creates a search query from the search words
 273:      *
 274:      * @param bool $long set to false to omit albumname and page parts
 275:      *
 276:      * @return string
 277:      */
 278:     function getSearchParams($long = true) {
 279:         global $_zp_page;
 280:         $r = '';
 281:         $w = urlencode(trim($this->codifySearchString()));
 282:         if (!empty($w)) {
 283:             $r .= '&words=' . $w;
 284:         }
 285:         $d = trim($this->dates);
 286:         if (!empty($d)) {
 287:             $r .= '&date=' . $d;
 288:             $d = trim($this->whichdates);
 289:             if ($d != 'date') {
 290:                 $r.= '&whichdates=' . $d;
 291:             }
 292:         }
 293:         $r .= $this->getSearchFieldsText($this->fieldList);
 294:         if ($long) {
 295:             $a = $this->dynalbumname;
 296:             if ($a) {
 297:                 $r .= '&albumname=' . $a;
 298:             }
 299:             if (empty($this->album_list)) {
 300:                 if ($this->search_no_albums) {
 301:                     $r .= '&inalbums=0';
 302:                 }
 303:             } else {
 304:                 $r .= '&inalbums=' . implode(',', $this->album_list);
 305:             }
 306:             if ($this->search_no_images) {
 307:                 $r .= '&inimages=0';
 308:             }
 309:             if ($this->search_no_pages) {
 310:                 $r .= '&inpages=0';
 311:             }
 312:             if (empty($this->categories)) {
 313:                 if ($this->search_no_news) {
 314:                     $r .= '&innews=0';
 315:                 }
 316:             } else {
 317:                 $r .= '&innews=' . implode(',', $this->categories);
 318:             }
 319:             if ($_zp_page > 1) {
 320:                 $this->page = $_zp_page;
 321:                 $r .= '&page=' . $_zp_page;
 322:             }
 323:         }
 324:         foreach ($this->extraparams as $p => $v) {
 325:             $r .= '&' . $p . '=' . $v;
 326:         }
 327:         return $r;
 328:     }
 329: 
 330:     /**
 331:      *
 332:      * Retrieves search extra parameters
 333:      * @return array
 334:      */
 335:     function getSearchExtra() {
 336:         return $this->extraparams;
 337:     }
 338: 
 339:     /**
 340:      *
 341:      * Stores extra search params for plugin use
 342:      * @param array $extra
 343:      */
 344:     function setSearchExtra($extra) {
 345:         $this->extraparams = $extra;
 346:     }
 347: 
 348:     /**
 349:      * sets sort directions
 350:      *
 351:      * @param bool $val the direction
 352:      * @param string $what 'images' if you want the image direction,
 353:      *        'albums' if you want it for the album
 354:      */
 355:     function setSortDirection($val, $what = 'images') {
 356:         if ($val) {
 357:             $this->extraparams[$what . 'sortdirection'] = 'DESC';
 358:         } else {
 359:             $this->extraparams[$what . 'sortdirection'] = 'ASC';
 360:         }
 361:     }
 362: 
 363:     /**
 364:      * Stores the sort type
 365:      *
 366:      * @param string $sorttype the sort type
 367:      * @param string $what 'images' or 'albums'
 368:      */
 369:     function setSortType($sorttype, $what = 'images') {
 370:         $this->extraparams[$what . 'sorttype'] = $sorttype;
 371:     }
 372: 
 373:     /**
 374:      * Returns the "searchstring" element of a query parameter set
 375:      *
 376:      * @param array $fields the fields required
 377:      * @param string $param the query parameter (possibly with the intro character
 378:      * @return string
 379:      */
 380:     function getSearchFieldsText($fields, $param = '&searchfields=') {
 381:         $default = $this->allowedSearchFields();
 382:         $diff = array_diff($default, $fields);
 383:         if (count($diff) > 0) {
 384:             foreach ($fields as $field) {
 385:                 $param .= $field . ',';
 386:             }
 387:             return substr($param, 0, -1);
 388:         }
 389:         return '';
 390:     }
 391: 
 392:     /**
 393:      * Parses and stores a search string
 394:      * NOTE!! this function assumes that the 'words' part of the list has been urlencoded!!!
 395:      *
 396:      * @param string $paramstr the string containing the search words
 397:      */
 398:     function setSearchParams($paramstr) {
 399:         $params = explode('&', $paramstr);
 400:         foreach ($params as $param) {
 401:             $e = strpos($param, '=');
 402:             $p = substr($param, 0, $e);
 403:             $v = substr($param, $e + 1);
 404:             switch ($p) {
 405:                 case 'words':
 406:                     $this->words = urldecode($v);
 407:                     break;
 408:                 case 'date':
 409:                     $this->dates = $v;
 410:                     break;
 411:                 case 'whichdates':
 412:                     $this->whichdates = $v;
 413:                     break;
 414:                 case 'searchfields':
 415:                     if (is_numeric($v)) {
 416:                         $this->fieldList = $this->numericFields($v);
 417:                     } else {
 418:                         $this->fieldList = array();
 419:                         $list = explode(',', strtolower($v));
 420:                         foreach ($this->search_structure as $key => $row) {
 421:                             if (in_array(strtolower($key), $list)) {
 422:                                 $this->fieldList[] = $key;
 423:                             }
 424:                         }
 425:                     }
 426:                     break;
 427:                 case 'page':
 428:                     $this->page = $v;
 429:                     break;
 430:                 case 'albumname':
 431:                     $alb = newAlbum($v, true, true);
 432:                     if ($alb->loaded) {
 433:                         $this->album = $alb;
 434:                         $this->dynalbumname = $v;
 435:                         $this->setSortType($this->album->getSortType('album'), 'albums');
 436:                         $this->setSortDirection($this->album->getSortDirection('album'), 'albums');
 437:                         $this->setSortType($this->album->getSortType(), 'images');
 438:                         $this->setSortDirection($this->album->getSortDirection('image'), 'images');
 439:                     }
 440:                     break;
 441:                 case 'inimages':
 442:                     if (strlen($v) > 0) {
 443:                         switch ($v) {
 444:                             case "0":
 445:                                 $this->search_no_images = true;
 446:                                 setOption('search_no_images', 1, false);
 447:                                 break;
 448:                             case "1":
 449:                                 $this->search_no_images = false;
 450:                                 setOption('search_no_images', 0, false);
 451:                                 break;
 452:                         }
 453:                     }
 454:                     break;
 455:                 case 'inalbums':
 456:                     if (strlen($v) > 0) {
 457:                         switch ($v) {
 458:                             case "0":
 459:                                 $this->search_no_albums = true;
 460:                                 setOption('search_no_albums', 1, false);
 461:                                 break;
 462:                             case "1":
 463:                                 $this->search_no_albums = false;
 464:                                 setOption('search_no_albums', 0, false);
 465:                                 break;
 466:                             default:
 467:                                 $this->album_list = explode(',', $v);
 468:                                 break;
 469:                         }
 470:                     }
 471:                     break;
 472:                 case 'unpublished':
 473:                     $this->search_unpublished = (bool) $v;
 474:                     break;
 475:                 default:
 476:                     $this->extraparams[$p] = $v;
 477:                     break;
 478:             }
 479:         }
 480:         if (!empty($this->words)) {
 481:             $this->dates = ''; // words and dates are mutually exclusive
 482:         }
 483:     }
 484: 
 485: // call to always return unpublished items
 486:     function setSearchUnpublished() {
 487:         $this->search_unpublished = true;
 488:     }
 489: 
 490:     /**
 491:      * Returns the search words variable
 492:      *
 493:      * @return string
 494:      */
 495:     function getSearchWords() {
 496:         return $this->words;
 497:     }
 498: 
 499:     /**
 500:      * Returns the search dates variable
 501:      *
 502:      * @return string
 503:      */
 504:     function getSearchDate() {
 505:         return $this->dates;
 506:     }
 507: 
 508:     /**
 509:      * Returns the search fields variable
 510:      *
 511:      * @param bool $array set to true to return the fields as array elements. Otherwise
 512:      * a comma delimited string is returned
 513:      *
 514:      * @return mixed
 515:      */
 516:     function getSearchFields($array = false) {
 517:         if ($array)
 518:             return $this->fieldList;
 519:         return implode(',', $this->fieldList);
 520:     }
 521: 
 522:     /**
 523:      * Parses a search string
 524:      * Items within quotations are treated as atomic
 525:      * AND, OR and NOT are converted to &, |, and !
 526:      *
 527:      * Returns an array of search elements
 528:      *
 529:      * @return array
 530:      */
 531:     function getSearchString() {
 532:         if ($this->processed_search) {
 533:             return $this->processed_search;
 534:         }
 535:         $searchstring = trim($this->words);
 536:         $space_is = getOption('search_space_is');
 537:         $opChars = array('&' => 1, '|' => 1, '!' => 1, ',' => 1, '(' => 2);
 538:         if ($space_is) {
 539:             $opChars[' '] = 1;
 540:         }
 541:         $c1 = ' ';
 542:         $result = array();
 543:         $target = "";
 544:         $i = 0;
 545:         do {
 546:             $c = substr($searchstring, $i, 1);
 547:             $op = '';
 548:             switch ($c) {
 549:                 case "'":
 550:                 case '"':
 551:                 case '`':
 552:                     $j = strpos(str_replace('\\' . $c, '__', $searchstring), $c, $i + 1);
 553:                     if ($j !== false) {
 554:                         $target .= stripcslashes(substr($searchstring, $i + 1, $j - $i - 1));
 555:                         $i = $j;
 556:                     } else {
 557:                         $target .= $c;
 558:                     }
 559:                     $c1 = $c;
 560:                     break;
 561:                 case ' ':
 562:                     $j = $i + 1;
 563:                     while ($j < strlen($searchstring) && $searchstring{$j} == ' ') {
 564:                         $j++;
 565:                     }
 566:                     switch ($space_is) {
 567:                         case 'OR':
 568:                         case 'AND':
 569:                             if ($j < strlen($searchstring)) {
 570:                                 $c3 = $searchstring{$j};
 571:                                 if (array_key_exists($c3, $opChars) && $opChars[$c3] == 1) {
 572:                                     $nextop = $c3 != '!';
 573:                                 } else if (substr($searchstring . ' ', $j, 4) == 'AND ') {
 574:                                     $nextop = true;
 575:                                 } else if (substr($searchstring . ' ', $j, 3) == 'OR ') {
 576:                                     $nextop = true;
 577:                                 } else {
 578:                                     $nextop = false;
 579:                                 }
 580:                             }
 581:                             if (!$nextop) {
 582:                                 if (!empty($target)) {
 583:                                     $r = trim($target);
 584:                                     if (!empty($r)) {
 585:                                         $last = $result[] = $r;
 586:                                         $target = '';
 587:                                     }
 588:                                 }
 589:                                 if ($space_is == 'AND') {
 590:                                     $c1 = '&';
 591:                                 } else {
 592:                                     $c1 = '|';
 593:                                 }
 594:                                 $target = '';
 595:                                 $last = $result[] = $c1;
 596:                             }
 597:                             break;
 598:                         default:
 599:                             $c1 = $c;
 600:                             $target .= str_pad('', $j - $i);
 601:                             break;
 602:                     }
 603:                     $i = $j - 1;
 604:                     break;
 605:                 case ',':
 606:                     if (!empty($target)) {
 607:                         $r = trim($target);
 608:                         if (!empty($r)) {
 609:                             switch ($r) {
 610:                                 case 'AND':
 611:                                     $r = '&';
 612:                                     break;
 613:                                 case 'OR':
 614:                                     $r = '|';
 615:                                     break;
 616:                                 case 'NOT':
 617:                                     $r = '!';
 618:                                     break;
 619:                             }
 620:                             $last = $result[] = $r;
 621:                             $target = '';
 622:                         }
 623:                     }
 624:                     $c2 = substr($searchstring, $i + 1, 1);
 625:                     switch ($c2) {
 626:                         case 'A':
 627:                             if (substr($searchstring . ' ', $i + 1, 4) == 'AND ')
 628:                                 $c2 = '&';
 629:                             break;
 630:                         case 'O':
 631:                             if (substr($searchstring . ' ', $i + 1, 3) == 'OR ')
 632:                                 $c2 = '|';
 633:                             break;
 634:                         case 'N':
 635:                             if (substr($searchstring . ' ', $i + 1, 4) == 'NOT ')
 636:                                 $c2 = '!';
 637:                             break;
 638:                     }
 639:                     if (!((isset($opChars[$c2]) && $opChars[$c2] == 1) || (isset($opChars[$last]) && $opChars[$last] == 1))) {
 640:                         $last = $result[] = '|';
 641:                         $c1 = $c;
 642:                     }
 643:                     break;
 644:                 case '!':
 645:                 case '&':
 646:                 case '|':
 647:                 case '(':
 648:                 case ')':
 649:                     if (!empty($target)) {
 650:                         $r = trim($target);
 651:                         if (!empty($r)) {
 652:                             $last = $result[] = $r;
 653:                             $target = '';
 654:                         }
 655:                     }
 656:                     $c1 = $c;
 657:                     $target = '';
 658:                     $last = $result[] = $c;
 659:                     $j = $i + 1;
 660:                     break;
 661:                 case 'A':
 662:                     if (substr($searchstring . ' ', $i, 4) == 'AND ') {
 663:                         $op = '&';
 664:                         $skip = 3;
 665:                     }
 666:                 case 'O':
 667:                     if (substr($searchstring . ' ', $i, 3) == 'OR ') {
 668:                         $op = '|';
 669:                         $skip = 2;
 670:                     }
 671:                 case 'N':
 672:                     if (substr($searchstring . ' ', $i, 4) == 'NOT ') {
 673:                         $op = '!';
 674:                         $skip = 3;
 675:                     }
 676:                     if ($op) {
 677:                         if (!empty($target)) {
 678:                             $r = trim($target);
 679:                             if (!empty($r)) {
 680:                                 $last = $result[] = $r;
 681:                                 $target = '';
 682:                             }
 683:                         }
 684:                         $c1 = $op;
 685:                         $target = '';
 686:                         $last = $result[] = $op;
 687:                         $j = $i + $skip;
 688:                         while ($j < strlen($searchstring) && substr($searchstring, $j, 1) == ' ') {
 689:                             $j++;
 690:                         }
 691:                         $i = $j - 1;
 692:                     } else {
 693:                         $c1 = $c;
 694:                         $target .= $c;
 695:                     }
 696:                     break;
 697: 
 698:                 default:
 699:                     $c1 = $c;
 700:                     $target .= $c;
 701:                     break;
 702:             }
 703:         } while ($i++ < strlen($searchstring));
 704:         if (!empty($target)) {
 705:             $last = $result[] = trim($target);
 706:         }
 707:         $lasttoken = '';
 708:         foreach ($result as $key => $token) {
 709:             if ($token == '|' && $lasttoken == '|') { // remove redundant OR ops
 710:                 unset($result[$key]);
 711:             }
 712:             $lasttoken = $token;
 713:         }
 714:         if (array_key_exists($lasttoken, $opChars) && $opChars[$lasttoken] == 1) {
 715:             array_pop($result);
 716:         }
 717: 
 718:         $this->processed_search = zp_apply_filter('search_criteria', $result);
 719:         return $this->processed_search;
 720:     }
 721: 
 722:     /**
 723:      * recodes the search words replacing the boolean operators with text versions
 724:      *
 725:      * @param string $quote how to represent quoted strings
 726:      *
 727:      * @return string
 728:      *
 729:      */
 730:     function codifySearchString() {
 731:         $searchstring = $this->getSearchString();
 732:         $sanitizedwords = '';
 733:         if (is_array($searchstring)) {
 734:             foreach ($searchstring as $singlesearchstring) {
 735:                 switch ($singlesearchstring) {
 736:                     case '&':
 737:                         $sanitizedwords .= " AND ";
 738:                         break;
 739:                     case '|':
 740:                         $sanitizedwords .= " OR ";
 741:                         break;
 742:                     case '!':
 743:                         $sanitizedwords .= " NOT ";
 744:                         break;
 745:                     case '(':
 746:                     case ')':
 747:                         $sanitizedwords .= $singlesearchstring;
 748:                         break;
 749:                     default:
 750:                         $sanitizedwords .= search_quote(sanitize($singlesearchstring, 3));
 751:                         break;
 752:                 }
 753:             }
 754:         }
 755: 
 756:         $sanitizedwords = trim(str_replace(array('   ', '  ',), ' ', $sanitizedwords));
 757:         $sanitizedwords = trim(str_replace('( ', '(', $sanitizedwords));
 758:         $sanitizedwords = trim(str_replace(' )', ')', $sanitizedwords));
 759:         return $sanitizedwords;
 760:     }
 761: 
 762:     /**
 763:      * Returns the number of albums found in a search
 764:      *
 765:      * @return int
 766:      */
 767:     function getNumAlbums() {
 768:         if (is_null($this->albums)) {
 769:             $this->getAlbums(0, NULL, NULL, false);
 770:         }
 771:         return count($this->albums);
 772:     }
 773: 
 774:     /**
 775:      * Returns the set of fields from the url query/post
 776:      * @return int
 777:      * @since 1.1.3
 778:      */
 779:     function parseQueryFields() {
 780:         $fields = array();
 781:         if (isset($_REQUEST['searchfields'])) {
 782:             $fs = sanitize($_REQUEST['searchfields']);
 783:             if (is_numeric($fs)) {
 784:                 $fields = array_flip($this->numericFields($fs));
 785:             } else {
 786:                 $fields = explode(',', $fs);
 787:             }
 788:         } else {
 789:             foreach ($_REQUEST as $key => $value) {
 790:                 if (strpos($key, 'SEARCH_') !== false) {
 791:                     $fields[substr($key, 7)] = $value;
 792:                 }
 793:             }
 794:         }
 795:         return $fields;
 796:     }
 797: 
 798:     /**
 799:      *
 800:      * Returns an array of News article IDs belonging to the search categories
 801:      */
 802:     protected function subsetNewsCategories() {
 803:         global $_zp_zenpage;
 804:         if (!is_array($this->category_list))
 805:             return false;
 806:         $cat = '';
 807:         $list = $_zp_zenpage->getAllCategories();
 808:         if (!empty($list)) {
 809:             foreach ($list as $category) {
 810:                 if (in_array($category['title'], $this->category_list)) {
 811:                     $catobj = new ZenpageCategory($category['titlelink']);
 812:                     $cat .= ' `cat_id`=' . $catobj->getID() . ' OR';
 813:                     $subcats = $catobj->getSubCategories();
 814:                     if ($subcats) {
 815:                         foreach ($subcats as $subcat) {
 816:                             $catobj = new ZenpageCategory($subcat);
 817:                             $cat .= ' `cat_id`=' . $catobj->getID() . ' OR';
 818:                         }
 819:                     }
 820:                 }
 821:             }
 822:             if ($cat) {
 823:                 $cat = ' WHERE ' . substr($cat, 0, -3);
 824:             }
 825:         }
 826:         $sql = 'SELECT DISTINCT `news_id` FROM ' . prefix('news2cat') . $cat;
 827:         $result = query($sql);
 828:         $list = array();
 829:         if ($result) {
 830:             while ($row = db_fetch_assoc($result)) {
 831:                 $list[] = $row['news_id'];
 832:             }
 833:             db_free_result($result);
 834:         }
 835:         return $list;
 836:     }
 837: 
 838:     /**
 839:      * Takes a list of IDs and makes a where clause
 840:      *
 841:      * @param array $idlist list of IDs for a where clause
 842:      */
 843:     protected static function compressedIDList($idlist) {
 844:         $idlist = array_unique($idlist);
 845:         asort($idlist);
 846:         return '`id` IN (' . implode(',', $idlist) . ')';
 847:     }
 848: 
 849:     /**
 850:      * get connical sort key and direction parameters.
 851:      * @param type $sorttype sort field desired
 852:      * @param type $sortdirection DESC or ASC
 853:      * @param type $defaulttype if no sort type otherwise selected use this one
 854:      * @param type $table the database table being searched
 855:      * @return array
 856:      */
 857:     protected function sortKey($sorttype, $sortdirection, $defaulttype, $table) {
 858:         if (is_null($sorttype)) {
 859:             if (array_key_exists($table . 'sorttype', $this->extraparams)) {
 860:                 $sorttype = $this->extraparams[$table . 'sorttype'];
 861:             } else if (array_key_exists('sorttype', $this->extraparams)) {
 862:                 $sorttype = $this->extraparams['sorttype'];
 863:             }
 864:         }
 865:         $sorttype = lookupSortKey($sorttype, $defaulttype, $table);
 866:         if (is_null($sortdirection)) {
 867:             if (array_key_exists($table . 'sortdirection', $this->extraparams)) {
 868:                 $sortdirection = $this->extraparams[$table . 'sortdirection'];
 869:             } else if (array_key_exists('sortdirection', $this->extraparams)) {
 870:                 $sortdirection = $this->extraparams['sortdirection'];
 871:             }
 872:         }
 873:         return array($sorttype, $sortdirection);
 874:     }
 875: 
 876:     /**
 877:      * returns the results of a date search
 878:      * @param string $searchstring the search target
 879:      * @param string $searchdate the date target
 880:      * @param string $tbl the database table to search
 881:      * @param string $sorttype what to sort on
 882:      * @param string $sortdirection what direction
 883:      * @return string
 884:      * @since 1.1.3
 885:      */
 886:     function searchDate($searchstring, $searchdate, $tbl, $sorttype, $sortdirection, $whichdate = 'date') {
 887:         global $_zp_current_album, $_zp_gallery;
 888:         $sql = 'SELECT DISTINCT `id`, `show`,`title`';
 889:         switch ($tbl) {
 890:             case 'pages':
 891:             case 'news':
 892:                 $sql .= ',`titlelink` ';
 893:                 break;
 894:             case 'albums':
 895:                 $sql .= ",`desc`,`folder` ";
 896:                 break;
 897:             default:
 898:                 $sql .= ",`desc`,`albumid`,`filename`,`location`,`city`,`state`,`country` ";
 899:                 break;
 900:         }
 901:         $sql .= "FROM " . prefix($tbl) . " WHERE ";
 902:         if (!zp_loggedin()) {
 903:             $sql .= "`show` = 1 AND (";
 904:         }
 905: 
 906:         if (!empty($searchdate)) {
 907:             if ($searchdate == "0000-00") {
 908:                 $sql .= "`$whichdate`=\"0000-00-00 00:00:00\"";
 909:             } else {
 910:                 $datesize = sizeof(explode('-', $searchdate));
 911: // search by day
 912:                 if ($datesize == 3) {
 913:                     $d1 = $searchdate . " 00:00:00";
 914:                     $d2 = $searchdate . " 23:59:59";
 915:                     $sql .= "`$whichdate` >= \"$d1\" AND `$whichdate` < \"$d2\"";
 916:                 }
 917: // search by month
 918:                 else if ($datesize == 2) {
 919:                     $d1 = $searchdate . "-01 00:00:00";
 920:                     $d = strtotime($d1);
 921:                     $d = strtotime('+ 1 month', $d);
 922:                     $d2 = substr(date('Y-m-d H:m:s', $d), 0, 7) . "-01 00:00:00";
 923:                     $sql .= "`$whichdate` >= \"$d1\" AND `$whichdate` < \"$d2\"";
 924:                 } else {
 925:                     $sql .= "`$whichdate`<\"0000-00-00 00:00:00\"";
 926:                 }
 927:             }
 928:         }
 929:         if (!zp_loggedin()) {
 930:             $sql .= ")";
 931:         }
 932: 
 933:         switch ($tbl) {
 934:             case 'news':
 935:                 if (empty($sorttype)) {
 936:                     $key = '`date` DESC';
 937:                 } else {
 938:                     $key = trim($sorttype . ' ' . $sortdirection);
 939:                 }
 940:                 break;
 941:             case 'pages':
 942:                 $key = '`sort_order`';
 943:                 break;
 944:             case 'albums':
 945:                 if (is_null($sorttype)) {
 946:                     if (empty($this->album)) {
 947:                         list($key, $sortdirection) = $this->sortKey($_zp_gallery->getSortType(), $sortdirection, 'title', 'albums');
 948:                         if ($key != '`sort_order`') {
 949:                             if ($_zp_gallery->getSortDirection()) {
 950:                                 $key .= " DESC";
 951:                             }
 952:                         }
 953:                     } else {
 954:                         $key = $this->album->getAlbumSortKey();
 955:                         if ($key != '`sort_order`' && $key != 'RAND()') {
 956:                             if ($this->album->getSortDirection('album')) {
 957:                                 $key .= " DESC";
 958:                             }
 959:                         }
 960:                     }
 961:                 } else {
 962:                     list($key, $sortdirection) = $this->sortKey($sorttype, $sortdirection, 'title', 'albums');
 963:                     $key = trim($key . ' ' . $sortdirection);
 964:                 }
 965:                 break;
 966:             default:
 967:                 $hidealbums = getNotViewableAlbums();
 968:                 if (!is_null($hidealbums)) {
 969:                     foreach ($hidealbums as $id) {
 970:                         $sql .= ' AND `albumid`!=' . $id;
 971:                     }
 972:                 }
 973:                 if (is_null($sorttype)) {
 974:                     if (empty($this->album)) {
 975:                         list($key, $sortdirection) = $this->sortKey(IMAGE_SORT_TYPE, $sortdirection, 'title', 'images');
 976:                         if ($key != '`sort_order`') {
 977:                             if (IMAGE_SORT_DIRECTION) {
 978:                                 $key .= " DESC";
 979:                             }
 980:                         }
 981:                     } else {
 982:                         $key = $thie->album->getImageSortKey();
 983:                         if ($key != '`sort_order`' && $key != 'RAND()') {
 984:                             if ($this->album->getSortDirection('image')) {
 985:                                 $key .= " DESC";
 986:                             }
 987:                         }
 988:                     }
 989:                 } else {
 990:                     list($key, $sortdirection) = $this->sortKey($sorttype, $sortdirection, 'title', 'images');
 991:                     $key = trim($key . ' ' . $sortdirection);
 992:                 }
 993:                 break;
 994:         }
 995:         $sql .= " ORDER BY " . $key;
 996:         return $sql;
 997:     }
 998: 
 999:     /**
1000:      * Searches the table for tags
1001:      * Returns an array of database records.
1002:      *
1003:      * @param array $searchstring
1004:      * @param string $tbl set DB table name to be searched
1005:      * @param string $sorttype what to sort on
1006:      * @param string $sortdirection what direction
1007:      * @return array
1008:      */
1009:     protected function searchFieldsAndTags($searchstring, $tbl, $sorttype, $sortdirection) {
1010:         global $_zp_gallery;
1011:         $weights = $idlist = array();
1012:         $sql = $allIDs = NULL;
1013:         $tagPattern = $this->tagPattern;
1014: // create an array of [tag, objectid] pairs for tags
1015:         $tag_objects = array();
1016:         $fields = $this->fieldList;
1017:         if (count($fields) == 0) { // then use the default ones
1018:             $fields = $this->allowedSearchFields();
1019:         }
1020:         foreach ($fields as $key => $field) {
1021:             switch ($field) {
1022:                 case 'news_categories':
1023:                     if ($tbl != 'news') {
1024:                         break;
1025:                     }
1026:                     unset($fields[$key]);
1027:                     query('SET @serachfield="news_categories"');
1028:                     $tagsql = 'SELECT @serachfield AS field, t.`title` AS name, o.`news_id` AS `objectid` FROM ' . prefix('news_categories') . ' AS t, ' . prefix('news2cat') . ' AS o WHERE t.`id`=o.`cat_id` AND (';
1029:                     foreach ($searchstring as $singlesearchstring) {
1030:                         switch ($singlesearchstring) {
1031:                             case '&':
1032:                             case '!':
1033:                             case '|':
1034:                             case '(':
1035:                             case ')':
1036:                                 break;
1037:                             case '*':
1038:                                 $targetfound = true;
1039:                                 $tagsql .= "COALESCE(title, '') != '' OR ";
1040:                                 break;
1041:                             default:
1042:                                 $targetfound = true;
1043:                                 $tagsql .= '`title` = ' . db_quote($singlesearchstring) . ' OR ';
1044:                         }
1045:                     }
1046:                     $tagsql = substr($tagsql, 0, strlen($tagsql) - 4) . ') ORDER BY t.`id`';
1047:                     $objects = query_full_array($tagsql, false);
1048:                     if (is_array($objects)) {
1049:                         $tag_objects = $objects;
1050:                     }
1051:                     break;
1052:                 case 'tags_exact':
1053:                     $tagPattern = array('type' => '=', 'open' => '', 'close' => '');
1054:                 case 'tags':
1055:                     unset($fields[$key]);
1056:                     query('SET @serachfield="tags"');
1057:                     $tagsql = 'SELECT @serachfield AS field, t.`name`, o.`objectid` FROM ' . prefix('tags') . ' AS t, ' . prefix('obj_to_tag') . ' AS o WHERE t.`id`=o.`tagid` AND o.`type`="' . $tbl . '" AND (';
1058:                     foreach ($searchstring as $singlesearchstring) {
1059:                         switch ($singlesearchstring) {
1060:                             case '&':
1061:                             case '!':
1062:                             case '|':
1063:                             case '(':
1064:                             case ')':
1065:                                 break;
1066:                             case '*':
1067:                                 query('SET @emptyfield="*"');
1068:                                 $tagsql = str_replace('t.`name`', '@emptyfield as name', $tagsql);
1069:                                 $tagsql .= "t.`name` IS NOT NULL OR ";
1070:                                 break;
1071:                             default:
1072:                                 $targetfound = true;
1073:                                 if ($tagPattern['type'] == 'like') {
1074:                                     $target = db_LIKE_escape($singlesearchstring);
1075:                                 } else {
1076:                                     $target = $singlesearchstring;
1077:                                 }
1078:                                 $tagsql .= 't.`name` ' . strtoupper($tagPattern['type']) . ' ' . db_quote($tagPattern['open'] . $target . $tagPattern['close']) . ' OR ';
1079:                         }
1080:                     }
1081:                     $tagsql = substr($tagsql, 0, strlen($tagsql) - 4) . ') ORDER BY t.`id`';
1082:                     $objects = query_full_array($tagsql, false);
1083:                     if (is_array($objects)) {
1084:                         $tag_objects = array_merge($tag_objects, $objects);
1085:                     }
1086:                     break;
1087:                 default:
1088:                     break;
1089:             }
1090:         }
1091: 
1092: 
1093: // create an array of [name, objectid] pairs for the search fields.
1094:         $field_objects = array();
1095:         if (count($fields) > 0) {
1096:             $columns = array();
1097:             $dbfields = db_list_fields($tbl);
1098:             if (is_array($dbfields)) {
1099:                 foreach ($dbfields as $row) {
1100:                     $columns[] = strtolower($row['Field']);
1101:                 }
1102:             }
1103:             foreach ($searchstring as $singlesearchstring) {
1104:                 switch ($singlesearchstring) {
1105:                     case '!':
1106:                     case '&':
1107:                     case '|':
1108:                     case '(':
1109:                     case ')':
1110:                         break;
1111:                     default:
1112:                         $targetfound = true;
1113:                         query('SET @serachtarget=' . db_quote($singlesearchstring));
1114:                         foreach ($fields as $fieldname) {
1115:                             if ($tbl == 'albums' && strtolower($fieldname) == 'filename') {
1116:                                 $fieldname = 'folder';
1117:                             } else {
1118:                                 $fieldname = strtolower($fieldname);
1119:                             }
1120:                             if ($fieldname && in_array($fieldname, $columns)) {
1121:                                 query('SET @serachfield=' . db_quote($fieldname));
1122:                                 switch ($singlesearchstring) {
1123:                                     case '*':
1124:                                         $sql = 'SELECT @serachtarget AS name, @serachfield AS field, `id` AS `objectid` FROM ' . prefix($tbl) . ' WHERE (' . "COALESCE(`$fieldname`, '') != ''" . ') ORDER BY `id`';
1125:                                         break;
1126:                                     default:
1127:                                         if ($this->pattern['type'] == 'like') {
1128:                                             $target = db_LIKE_escape($singlesearchstring);
1129:                                         } else {
1130:                                             $target = $singlesearchstring;
1131:                                         }
1132:                                         $fieldsql = ' `' . $fieldname . '` ' . strtoupper($this->pattern['type']) . ' ' . db_quote($this->pattern['open'] . $target . $this->pattern['close']);
1133:                                         $sql = 'SELECT @serachtarget AS name, @serachfield AS field, `id` AS `objectid` FROM ' . prefix($tbl) . ' WHERE (' . $fieldsql . ') ORDER BY `id`';
1134:                                 }
1135:                                 $objects = query_full_array($sql, false);
1136:                                 if (is_array($objects)) {
1137:                                     $field_objects = array_merge($field_objects, $objects);
1138:                                 }
1139:                             }
1140:                         }
1141:                 }
1142:             }
1143:         }
1144: 
1145: // now do the boolean logic of the search string
1146:         $exact = $tagPattern['type'] == '=';
1147:         $objects = array_merge($tag_objects, $field_objects);
1148:         if (count($objects) != 0) {
1149:             $tagid = '';
1150:             $taglist = array();
1151: 
1152:             foreach ($objects as $object) {
1153:                 $tagid = strtolower($object['name']);
1154:                 if (!isset($taglist[$tagid]) || !is_array($taglist[$tagid])) {
1155:                     $taglist[$tagid] = array();
1156:                 }
1157:                 $taglist[$tagid][] = $object['objectid'];
1158:             }
1159:             $op = '';
1160:             $idstack = array();
1161:             $opstack = array();
1162:             while (count($searchstring) > 0) {
1163:                 $singlesearchstring = array_shift($searchstring);
1164:                 switch ($singlesearchstring) {
1165:                     case '&':
1166:                     case '!':
1167:                     case '|':
1168:                         $op = $op . $singlesearchstring;
1169:                         break;
1170:                     case '(':
1171:                         array_push($idstack, $idlist);
1172:                         array_push($opstack, $op);
1173:                         $idlist = array();
1174:                         $op = '';
1175:                         break;
1176:                     case ')':
1177:                         $objectid = $idlist;
1178:                         $idlist = array_pop($idstack);
1179:                         $op = array_pop($opstack);
1180:                         switch ($op) {
1181:                             case '&':
1182:                                 if (is_array($objectid)) {
1183:                                     $idlist = array_intersect($idlist, $objectid);
1184:                                 } else {
1185:                                     $idlist = array();
1186:                                 }
1187:                                 break;
1188:                             case '!':
1189:                                 break; // Paren followed by NOT is nonsensical?
1190:                             case '&!':
1191:                                 if (is_array($objectid)) {
1192:                                     $idlist = array_diff($idlist, $objectid);
1193:                                 }
1194:                                 break;
1195:                             case '';
1196:                             case '|':
1197:                                 if (is_array($objectid)) {
1198:                                     $idlist = array_merge($idlist, $objectid);
1199:                                 }
1200:                                 break;
1201:                         }
1202:                         $op = '';
1203:                         break;
1204:                     default:
1205:                         $lookfor = strtolower($singlesearchstring);
1206:                         $objectid = NULL;
1207:                         foreach ($taglist as $key => $objlist) {
1208:                             if (($exact && $lookfor == $key) || (!$exact && preg_match('|' . preg_quote($lookfor) . '|', $key))) {
1209:                                 if (is_array($objectid)) {
1210:                                     $objectid = array_merge($objectid, $objlist);
1211:                                 } else {
1212:                                     $objectid = $objlist;
1213:                                 }
1214:                             }
1215:                         }
1216:                         switch ($op) {
1217:                             case '&':
1218:                                 if (is_array($objectid)) {
1219:                                     $idlist = array_intersect($idlist, $objectid);
1220:                                 } else {
1221:                                     $idlist = array();
1222:                                 }
1223:                                 break;
1224:                             case '!':
1225:                                 if (is_null($allIDs)) {
1226:                                     $allIDs = array();
1227:                                     $result = query("SELECT `id` FROM " . prefix($tbl));
1228:                                     if ($result) {
1229:                                         while ($row = db_fetch_assoc($result)) {
1230:                                             $allIDs[] = $row['id'];
1231:                                         }
1232:                                         db_free_result($result);
1233:                                     }
1234:                                 }
1235:                                 if (is_array($objectid)) {
1236:                                     $idlist = array_merge($idlist, array_diff($allIDs, $objectid));
1237:                                 }
1238:                                 break;
1239:                             case '&!':
1240:                                 if (is_array($objectid)) {
1241:                                     $idlist = array_diff($idlist, $objectid);
1242:                                 }
1243:                                 break;
1244:                             case '';
1245:                             case '|':
1246:                                 if (is_array($objectid)) {
1247:                                     $idlist = array_merge($idlist, $objectid);
1248:                                 }
1249:                                 break;
1250:                         }
1251:                         $op = '';
1252:                         break;
1253:                 }
1254:             }
1255:         }
1256: 
1257: // we now have an id list of the items that were found and will create the SQL Search to retrieve their records
1258:         if (count($idlist) > 0) {
1259:             $weights = array_count_values($idlist);
1260:             arsort($weights, SORT_NUMERIC);
1261:             $sql = 'SELECT DISTINCT `id`,`show`,';
1262: 
1263:             switch ($tbl) {
1264:                 case 'news':
1265:                     if ($this->search_unpublished || zp_loggedin(MANAGE_ALL_NEWS_RIGHTS)) {
1266:                         $show = '';
1267:                     } else {
1268:                         $show = "`show` = 1 AND ";
1269:                     }
1270:                     $sql .= '`titlelink` ';
1271:                     if (is_array($this->category_list)) {
1272:                         $news_list = $this->subsetNewsCategories();
1273:                         $idlist = array_intersect($news_list, $idlist);
1274:                         if (count($idlist) == 0) {
1275:                             return array(false, array());
1276:                         }
1277:                     }
1278:                     if (empty($sorttype)) {
1279:                         $key = '`date` DESC';
1280:                     } else {
1281:                         $key = trim($sorttype . $sortdirection);
1282:                     }
1283:                     if ($show) {
1284:                         $show .= '`date`<=' . db_quote(date('Y-m-d H:i:s')) . ' AND ';
1285:                     }
1286:                     break;
1287:                 case 'pages':
1288:                     if (zp_loggedin(MANAGE_ALL_PAGES_RIGHTS)) {
1289:                         $show = '';
1290:                     } else {
1291:                         $show = "`show` = 1 AND ";
1292:                     }
1293:                     $sql .= '`titlelink` ';
1294:                     if ($show) {
1295:                         $show .= '`date`<=' . db_quote(date('Y-m-d H:i:s')) . ' AND ';
1296:                     }
1297:                     $key = '`sort_order`';
1298:                     break;
1299:                 case 'albums':
1300:                     if ($this->search_unpublished || zp_loggedin()) {
1301:                         $show = '';
1302:                     } else {
1303:                         $show = "`show` = 1 AND ";
1304:                     }
1305:                     $sql .= "`folder`, `title` ";
1306:                     if (is_null($sorttype)) {
1307:                         if (empty($this->album)) {
1308:                             list($key, $sortdirection) = $this->sortKey($_zp_gallery->getSortType(), $sortdirection, 'title', 'albums');
1309:                             if ($_zp_gallery->getSortDirection()) {
1310:                                 $key .= " DESC";
1311:                             }
1312:                         } else {
1313:                             $key = $this->album->getAlbumSortKey();
1314:                             if ($key != '`sort_order`' && $key != 'RAND()') {
1315:                                 if ($this->album->getSortDirection('album')) {
1316:                                     $key .= " DESC";
1317:                                 }
1318:                             }
1319:                         }
1320:                     } else {
1321:                         list($key, $sortdirection) = $this->sortKey($sorttype, $sortdirection, 'title', 'albums');
1322:                         $key = trim($key . ' ' . $sortdirection);
1323:                     }
1324:                     break;
1325:                 default: // images
1326:                     if ($this->search_unpublished || zp_loggedin()) {
1327:                         $show = '';
1328:                     } else {
1329:                         $show = "`show` = 1 AND ";
1330:                     }
1331:                     $sql .= "`albumid`, `filename`, `title` ";
1332:                     if (is_null($sorttype)) {
1333:                         if (empty($this->album)) {
1334:                             list($key, $sortdirection) = $this->sortKey($sorttype, $sortdirection, 'title', 'images');
1335:                             if ($sortdirection) {
1336:                                 $key .= " DESC";
1337:                             }
1338:                         } else {
1339:                             $key = $this->album->getImageSortKey();
1340:                             if ($key != '`sort_order`') {
1341:                                 if ($this->album->getSortDirection('image')) {
1342:                                     $key .= " DESC";
1343:                                 }
1344:                             }
1345:                         }
1346:                     } else {
1347:                         list($key, $sortdirection) = $this->sortKey($sorttype, $sortdirection, 'title', 'images');
1348:                         $key = trim($key . ' ' . $sortdirection);
1349:                     }
1350:                     break;
1351:             }
1352:             $sql .= "FROM " . prefix($tbl) . " WHERE " . $show;
1353:             $sql .= '(' . self::compressedIDList($idlist) . ')';
1354:             $sql .= " ORDER BY " . $key;
1355:             return array($sql, $weights);
1356:         }
1357:         return array(false, array());
1358:     }
1359: 
1360:     /**
1361:      * Returns an array of albums found in the search
1362:      * @param string $sorttype what to sort on
1363:      * @param string $sortdirection what direction
1364:      * @param bool $mine set true/false to override ownership
1365:      *
1366:      * @return array
1367:      */
1368:     private function getSearchAlbums($sorttype, $sortdirection, $mine = NULL) {
1369:         if (getOption('search_no_albums') || $this->search_no_albums) {
1370:             return array();
1371:         }
1372:         list($sorttype, $sortdirection) = $this->sortKey($sorttype, $sortdirection, 'title', 'albums');
1373:         $albums = array();
1374:         $searchstring = $this->getSearchString();
1375:         if (empty($searchstring)) {
1376:             return array();
1377:         } // nothing to find
1378:         $criteria = $this->getCacheTag('albums', serialize($searchstring), $sorttype . ' ' . $sortdirection . ' '. $mine);
1379:         if ($this->albums && $criteria == $this->searches['albums']) {
1380:             return $this->albums;
1381:         }
1382:         $albums = $this->getCachedSearch($criteria);
1383:         if (is_null($albums)) {
1384:             if (is_null($mine) && zp_loggedin(MANAGE_ALL_ALBUM_RIGHTS)) {
1385:                 $mine = true;
1386:             }
1387:             $result = $albums = array();
1388:             list ($search_query, $weights) = $this->searchFieldsAndTags($searchstring, 'albums', $sorttype, $sortdirection);
1389:             if (!empty($search_query)) {
1390:                 $search_result = query($search_query);
1391:                 if ($search_result) {
1392:                     while ($row = db_fetch_assoc($search_result)) {
1393:                         $albumname = $row['folder'];
1394:                         if ($albumname != $this->dynalbumname) {
1395:                             if (file_exists(ALBUM_FOLDER_SERVERPATH . internalToFilesystem($albumname))) {
1396:                                 $album = newAlbum($albumname);
1397:                                 $uralbum = getUrAlbum($album);
1398:                                 $viewUnpublished = ($this->search_unpublished || zp_loggedin() && $uralbum->albumSubRights() & (MANAGED_OBJECT_RIGHTS_EDIT | MANAGED_OBJECT_RIGHTS_VIEW));
1399:                                 switch (checkPublishDates($row)) {
1400:                                     case 1:
1401:                                         $album->setShow(0);
1402:                                         $album->save();
1403:                                     case 2:
1404:                                         $row['show'] = 0;
1405:                                 }
1406:                                 if ($mine || (is_null($mine) && $album->isMyItem(LIST_RIGHTS)) || (checkAlbumPassword($albumname) && ($row['show'] || $viewUnpublished))) {
1407:                                     if (empty($this->album_list) || in_array($albumname, $this->album_list)) {
1408:                                         $result[] = array('title' => $row['title'], 'name' => $albumname, 'weight' => $weights[$row['id']]);
1409:                                     }
1410:                                 }
1411:                             }
1412:                         }
1413:                     }
1414:                     db_free_result($search_result);
1415:                     if (is_null($sorttype)) {
1416:                         $result = sortMultiArray($result, 'weight', true, true, false, false, array('weight'));
1417:                     }
1418:                     if ($sorttype == '`title`') {
1419:                         $result = sortByMultilingual($result, 'title', $sortdirection);
1420:                     }
1421:                     foreach ($result as $album) {
1422:                         $albums[] = $album['name'];
1423:                     }
1424:                 }
1425:             }
1426:             zp_apply_filter('search_statistics', $searchstring, 'albums', !empty($albums), $this->dynalbumname, $this->iteration++);
1427:             $this->cacheSearch($criteria, $albums);
1428:         }
1429:         $this->albums = $albums;
1430:         $this->searches['albums'] = $criteria;
1431:         
1432:         return $albums;
1433:     }
1434: 
1435:     /**
1436:      * Returns an array of album names found in the search.
1437:      * If $page is not zero, it returns the current page's albums
1438:      *
1439:      * @param int $page the page number we are on
1440:      * @param string $sorttype what to sort on
1441:      * @param string $sortdirection what direction
1442:      * @param bool $care set to false if the order of the albums does not matter
1443:      * @param bool $mine set true/false to override ownership
1444:      *
1445:      * @return array
1446:      */
1447:     function getAlbums($page = 0, $sorttype = NULL, $sortdirection = NULL, $care = true, $mine = NULL) {
1448:         $this->albums = $this->getSearchAlbums($sorttype, $sortdirection, $mine);
1449:         if ($page == 0) {
1450:             return $this->albums;
1451:         } else {
1452:             $albums_per_page = max(1, getOption('albums_per_page'));
1453:             return array_slice($this->albums, $albums_per_page * ($page - 1), $albums_per_page);
1454:         }
1455:     }
1456: 
1457:     /**
1458:      * Returns the index of the album within the search albums
1459:      *
1460:      * @param string $curalbum The album sought
1461:      * @return int
1462:      */
1463:     function getAlbumIndex($curalbum) {
1464:         $albums = $this->getAlbums(0);
1465:         return array_search($curalbum, $albums);
1466:     }
1467: 
1468:     /**
1469:      * Returns the album following the current one
1470:      *
1471:      * @param string $curalbum the name of the current album
1472:      * @return object
1473:      */
1474:     function getNextAlbum($curalbum) {
1475:         global $_zp_gallery;
1476:         $albums = $this->getAlbums(0);
1477:         $inx = array_search($curalbum, $albums) + 1;
1478:         if ($inx >= 0 && $inx < count($albums)) {
1479:             return newAlbum($albums[$inx]);
1480:         }
1481:         return null;
1482:     }
1483: 
1484:     /**
1485:      * Returns the album preceding the current one
1486:      *
1487:      * @param string $curalbum the name of the current album
1488:      * @return object
1489:      */
1490:     function getPrevAlbum($curalbum) {
1491:         global $_zp_gallery;
1492:         $albums = $this->getAlbums(0);
1493:         $inx = array_search($curalbum, $albums) - 1;
1494:         if ($inx >= 0 && $inx < count($albums)) {
1495:             return newAlbum($albums[$inx]);
1496:         }
1497:         return null;
1498:     }
1499: 
1500:     /**
1501:      * Returns the number of images found in the search
1502:      *
1503:      * @return int
1504:      */
1505:     function getNumImages() {
1506:         if (is_null($this->images)) {
1507:             $this->getImages(0);
1508:         }
1509:         return count($this->images);
1510:     }
1511: 
1512:     /**
1513:      * Returns an array of image names found in the search
1514:      *
1515:      * @param string $sorttype what to sort on
1516:      * @param string $sortdirection what direction
1517:      * @param bool $mine set true/false to overried ownership
1518:      * @return array
1519:      */
1520:     private function getSearchImages($sorttype, $sortdirection, $mine = NULL) {
1521:         
1522:         if (getOption('search_no_images') || $this->search_no_images) {
1523:             return array();
1524:         }
1525:         list($sorttype, $sortdirection) = $this->sortKey($sorttype, $sortdirection, 'title', 'images');
1526:         if (is_null($mine) && zp_loggedin(MANAGE_ALL_ALBUM_RIGHTS)) {
1527:             $mine = true;
1528:         }
1529:         $searchstring = $this->getSearchString();
1530:         $searchdate = $this->dates;
1531:         if (empty($searchstring) && empty($searchdate)) {
1532:             return array();
1533:         } // nothing to find
1534: 
1535:         $criteria = $this->getCacheTag('images', serialize($searchstring) . ' ' . $searchdate, $sorttype . ' ' . $sortdirection . ' '.$mine);
1536:         if ($criteria == $this->searches['images']) {
1537:             return $this->images;
1538:         }
1539:         $images = $this->getCachedSearch($criteria);
1540:         if (is_null($images)) {
1541:             if (empty($searchdate)) {
1542:                 list ($search_query, $weights) = $this->searchFieldsAndTags($searchstring, 'images', $sorttype, $sortdirection);
1543:             } else {
1544:                 $search_query = $this->searchDate($searchstring, $searchdate, 'images', $sorttype, $sortdirection);
1545:             }
1546:             if (empty($search_query)) {
1547:                 $search_result = false;
1548:             } else {
1549:                 $search_result = query($search_query);
1550:             }
1551:             $albums_seen = $images = array();
1552:             if ($search_result) {
1553:                 while ($row = db_fetch_assoc($search_result)) {
1554:                     $albumid = $row['albumid'];
1555:                     if (array_key_exists($albumid, $albums_seen)) {
1556:                         $albumrow = $albums_seen[$albumid];
1557:                     } else {
1558:                         $query = "SELECT folder, `show` FROM " . prefix('albums') . " WHERE id = $albumid";
1559:                         $row2 = query_single_row($query); // id is unique
1560:                         if ($row2) {
1561:                             $albumname = $row2['folder'];
1562:                             $allow = false;
1563:                             $album = newAlbum($albumname);
1564:                             $uralbum = getUrAlbum($album);
1565:                             $viewUnpublished = ($this->search_unpublished || zp_loggedin() && $uralbum->albumSubRights() & (MANAGED_OBJECT_RIGHTS_EDIT | MANAGED_OBJECT_RIGHTS_VIEW));
1566:                             switch (checkPublishDates($row)) {
1567:                                 case 1:
1568:                                     $imageobj = newImage($this, $row['filename']);
1569:                                     $imageobj->setShow(0);
1570:                                     $imageobj->save();
1571:                                 case 2:
1572:                                     $row['show'] = 0;
1573:                                     break;
1574:                             }
1575:                             if ($mine || is_null($mine) && ($album->isMyItem(LIST_RIGHTS) || checkAlbumPassword($albumname) && ($album->getShow() || $viewUnpublished))) {
1576:                                 $allow = empty($this->album_list) || in_array($albumname, $this->album_list);
1577:                             }
1578:                             $albums_seen[$albumid] = $albumrow = array('allow' => $allow, 'viewUnpublished' => $viewUnpublished, 'folder' => $albumname, 'localpath' => ALBUM_FOLDER_SERVERPATH . internalToFilesystem($albumname) . '/');
1579:                         } else {
1580:                             $albums_seen[$albumid] = $albumrow = array('allow' => false, 'viewUnpublished' => false, 'folder' => '', 'localpath' => '');
1581:                         }
1582:                     }
1583:                     if ($albumrow['allow'] && ($row['show'] || $albumrow['viewUnpublished'])) {
1584:                         if (file_exists($albumrow['localpath'] . internalToFilesystem($row['filename']))) { //  still exists
1585:                             $data = array('title' => $row['title'], 'filename' => $row['filename'], 'folder' => $albumrow['folder']);
1586:                             if (isset($weights)) {
1587:                                 $data['weight'] = $weights[$row['id']];
1588:                             }
1589:                             $images[] = $data;
1590:                         }
1591:                     }
1592:                 }
1593:                 db_free_result($search_result);
1594:                 if (is_null($sorttype) && isset($weights)) {
1595:                     $images = sortMultiArray($images, 'weight', true, true, false, false, array('weight'));
1596:                 }
1597:                 if ($sorttype == '`title`') {
1598:                     $images = sortByMultilingual($images, 'title', $sortdirection);
1599:                 }
1600:             }
1601:             if (empty($searchdate)) {
1602:                 zp_apply_filter('search_statistics', $searchstring, 'images', !empty($images), $this->dynalbumname, $this->iteration++);
1603:             }
1604:             $this->cacheSearch($criteria, $images);
1605:         }
1606:         $this->searches['images'] = $criteria;
1607:         return $images;
1608:     }
1609: 
1610:     /**
1611:      * Returns an array of images found in the search
1612:      * It will return a "page's worth" if $page is non zero
1613:      *
1614:      * @param int $page the page number desired
1615:      * @param int $firstPageCount count of images that go on the album/image transition page
1616:      * @param string $sorttype what to sort on
1617:      * @param string $sortdirection what direction
1618:      * @param bool $care placeholder to make the getImages methods all the same.
1619:      * @param bool $mine set true/false to overried ownership
1620:      * @return array
1621:      */
1622:     function getImages($page = 0, $firstPageCount = 0, $sorttype = NULL, $sortdirection = NULL, $care = true, $mine = NULL) {
1623:         $this->images = $this->getSearchImages($sorttype, $sortdirection, $mine);
1624:         if ($page == 0) {
1625:             return $this->images;
1626:         } else {
1627:             if (empty($this->images)) {
1628:                 return array();
1629:             }
1630:             // Only return $firstPageCount images if we are on the first page and $firstPageCount > 0
1631:             if (($page == 1) && ($firstPageCount > 0)) {
1632:                 $pageStart = 0;
1633:                 $images_per_page = $firstPageCount;
1634:             } else {
1635:                 if ($firstPageCount > 0) {
1636:                     $fetchPage = $page - 2;
1637:                 } else {
1638:                     $fetchPage = $page - 1;
1639:                 }
1640:                 $images_per_page = max(1, getOption('images_per_page'));
1641:                 $pageStart = $firstPageCount + $images_per_page * $fetchPage;
1642:             }
1643:             $slice = array_slice($this->images, $pageStart, $images_per_page);
1644:             return $slice;
1645:         }
1646:     }
1647: 
1648:     /**
1649:      * Returns the index of this image in the search images
1650:      *
1651:      * @param string $album The folder name of the image
1652:      * @param string $filename the filename of the image
1653:      * @return int
1654:      */
1655:     function getImageIndex($album, $filename) {
1656:         $images = $this->getImages();
1657:         $c = 0;
1658:         foreach ($images as $image) {
1659:             if (($album == $image['folder']) && ($filename == $image['filename'])) {
1660:                 return $c;
1661:             }
1662:             $c++;
1663:         }
1664:         return false;
1665:     }
1666: 
1667:     /**
1668:      * Returns a specific image
1669:      *
1670:      * @param int $index the index of the image desired
1671:      * @return object
1672:      */
1673:     function getImage($index) {
1674:         global $_zp_gallery;
1675:         if (!is_null($this->images)) {
1676:             $this->getImages();
1677:         }
1678:         if ($index >= 0 && $index < $this->getNumImages()) {
1679:             $img = $this->images[$index];
1680:             return newImage(newAlbum($img['folder']), $img['filename']);
1681:         }
1682:         return false;
1683:     }
1684: 
1685:     function getDynamicAlbum() {
1686:         return $this->album;
1687:     }
1688: 
1689:     /**
1690:      *
1691:      * return the list of albums found
1692:      */
1693:     function getAlbumList() {
1694:         return $this->album_list;
1695:     }
1696: 
1697:     /**
1698:      *
1699:      * return the list of categories found
1700:      */
1701:     function getCategoryList() {
1702:         return $this->category_list;
1703:     }
1704: 
1705:     /**
1706:      *
1707:      * Returns pages from a search
1708:      * @param bool $published ignored, left for parameter compatibility
1709:      * @param bool $toplevel ignored, left for parameter compatibility
1710:      * @param int $number ignored, left for parameter compatibility
1711:      * @param string $sorttype the sort key
1712:      * @param strng $sortdirection the sort order
1713:      *
1714:      * @return array
1715:      */
1716:     function getPages($published = NULL, $toplevel = false, $number = NULL, $sorttype = NULL, $sortdirection = NULL) {
1717:         return $this->getSearchPages($sorttype, $sortdirection);
1718:     }
1719: 
1720:     /**
1721:      * Returns a list of Pages Titlelinks found in the search
1722:      *
1723:      * @parm string $sorttype optional sort field
1724:      * @param string $sortdirection optional ordering
1725:      *
1726:      * @return array
1727:      */
1728:     private function getSearchPages($sorttype, $sortdirection) {
1729:         if (!extensionEnabled('zenpage') || getOption('search_no_pages') || $this->search_no_pages)
1730:             return array();
1731:         list($sorttype, $sortdirection) = $this->sortKey($sorttype, $sortdirection, 'title', 'pages');
1732:         $searchstring = $this->getSearchString();
1733:         $searchdate = $this->dates;
1734:         if (empty($searchstring) && empty($searchdate)) {
1735:             return array();
1736:         } // nothing to find
1737:         $criteria = $this->getCacheTag('news', serialize($searchstring), $sorttype . ' ' . $sortdirection);
1738:         if ($this->pages && $criteria == $this->searches['pages']) {
1739:             return $this->pages;
1740:         }
1741:         if (is_null($this->pages)) {
1742:             $pages = $result = array();
1743:             if (empty($searchdate)) {
1744:                 list ($search_query, $weights) = $this->searchFieldsAndTags($searchstring, 'pages', $sorttype, $sortdirection);
1745:                 if (empty($search_query)) {
1746:                     $search_result = false;
1747:                 } else {
1748:                     $search_result = query($search_query);
1749:                 }
1750:                 zp_apply_filter('search_statistics', $searchstring, 'pages', !$search_result, false, $this->iteration++);
1751:             } else {
1752:                 $search_query = $this->searchDate($searchstring, $searchdate, 'pages', NULL, NULL);
1753:                 $search_result = query($search_query);
1754:             }
1755:             if ($search_result) {
1756:                 while ($row = db_fetch_assoc($search_result)) {
1757:                     $data = array('titlelink' => $row['titlelink']);
1758:                     if (isset($weights)) {
1759:                         $data['weight'] = $weights[$row['id']];
1760:                     }
1761:                     $result[] = $data;
1762:                 }
1763:                 db_free_result($search_result);
1764:             }
1765:             if (isset($weights)) {
1766:                 $result = sortMultiArray($result, 'weight', true, true, false, false, array('weight'));
1767:             }
1768: 
1769: 
1770:             foreach ($result as $page) {
1771:                 $pages[] = $page['titlelink'];
1772:             }
1773:             $this->pages = $pages;
1774:         }
1775:         $this->searches['pages'] = $criteria;
1776:         return $this->pages;
1777:     }
1778: 
1779:     /**
1780:      * Returns a list of News Titlelinks found in the search
1781:      *
1782:      * @param int $articles_per_page The number of articles to get
1783:      * @param bool $published placeholder for consistent parameter list
1784:      * @param bool $ignorepagination ignore pagination
1785:      * @param string $sorttype field to sort on
1786:      * @param string $sortdirection sort order
1787:      *
1788:      * @return array
1789:      */
1790:     function getArticles($articles_per_page = 0, $published = NULL, $ignorepagination = false, $sorttype = NULL, $sortdirection = NULL) {
1791: 
1792:         $articles = $this->getSearchArticles($sorttype, $sortdirection);
1793:         if (empty($articles)) {
1794:             return array();
1795:         } else {
1796:             if ($ignorepagination || !$articles_per_page) {
1797:                 return $articles;
1798:             }
1799:             return array_slice($articles, Zenpage::getOffset($articles_per_page), $articles_per_page);
1800:         }
1801:     }
1802: 
1803:     /**
1804:      * Returns a list of News Titlelinks found in the search
1805:      *
1806:      * @param string $sorttype field to sort on
1807:      * @param string $sortdirection sort order
1808:      *
1809:      * @return array
1810:      */
1811:     private function getSearchArticles($sorttype, $sortdirection) {
1812:         if (!extensionEnabled('zenpage') || getOption('search_no_news') || $this->search_no_news) {
1813:             return array();
1814:         }
1815:         list($sorttype, $sortdirection) = $this->sortKey($sorttype, $sortdirection, 'title', 'news');
1816:         $searchstring = $this->getSearchString();
1817:         $searchdate = $this->dates;
1818:         if (empty($searchstring) && empty($searchdate)) {
1819:             return array();
1820:         } // nothing to find
1821:         $criteria = $this->getCacheTag('news', serialize($searchstring), $sorttype . ' ' . $sortdirection);
1822:         if ($this->articles && $criteria == $this->searches['news']) {
1823:             return $this->articles;
1824:         }
1825:         $result = $this->getCachedSearch($criteria);
1826:         if (is_null($result)) {
1827:             $result = array();
1828:             if (empty($searchdate)) {
1829:                 list ($search_query, $weights) = $this->searchFieldsAndTags($searchstring, 'news', $sorttype, $sortdirection);
1830:             } else {
1831:                 $search_query = $this->searchDate($searchstring, $searchdate, 'news', $sorttype, $sortdirection, $this->whichdates);
1832:             }
1833:             if (empty($search_query)) {
1834:                 $search_result = false;
1835:             } else {
1836:                 $search_result = query($search_query);
1837:             }
1838:             zp_apply_filter('search_statistics', $searchstring, 'news', !empty($search_result), false, $this->iteration++);
1839:             if ($search_result) {
1840:                 while ($row = db_fetch_assoc($search_result)) {
1841:                     $data = array('titlelink' => $row['titlelink']);
1842:                     if (isset($weights)) {
1843:                         $data['weight'] = $weights[$row['id']];
1844:                     }
1845:                     $result[] = $data;
1846:                 }
1847:                 db_free_result($search_result);
1848:             }
1849:             if (isset($weights)) {
1850:                 $result = sortMultiArray($result, 'weight', true, true, false, false, array('weight'));
1851:             }
1852:             $this->cacheSearch($criteria, $result);
1853:         }
1854:         $this->articles = $result;
1855:         $this->searches['news'] = $criteria;
1856:         return $this->articles;
1857:     }
1858: 
1859:     function clearSearchWords() {
1860:         $this->processed_search = '';
1861:         $this->words = '';
1862:     }
1863: 
1864:     /**
1865:      *
1866:      * creates a unique id for a search
1867:      * @param string $table Database table
1868:      * @param string $search    Search string
1869:      * @param string $sort  Sort criteria
1870:      */
1871:     protected function getCacheTag($table, $search, $sort) {
1872:         $user = 'guest';
1873:         $authCookies = Zenphoto_Authority::getAuthCookies();
1874:         if (!empty($authCookies)) { // some sort of password exists, play it safe and make the tag unique
1875:             $user = getUserIP();
1876:         }
1877:         return array('item' => $table, 'fields' => implode(', ', $this->fieldList), 'search' => $search, 'sort' => $sort, 'user' => $user);
1878:     }
1879: 
1880:     /**
1881:      *
1882:      * Caches a search
1883:      * @param string $criteria
1884:      * @param string $found reslts of the search
1885:      */
1886:     private function cacheSearch($criteria, $found) {
1887:         if (SEARCH_CACHE_DURATION) {
1888:             $criteria = serialize($criteria);
1889:             $sql = 'SELECT `id`, `data`, `date` FROM ' . prefix('search_cache') . ' WHERE `criteria` = ' . db_quote($criteria);
1890:             $result = query_single_row($sql);
1891:             if ($result) {
1892:                 $sql = 'UPDATE ' . prefix('search_cache') . ' SET `data` = ' . db_quote(serialize($found)) . ', `date` = ' . db_quote(date('Y-m-d H:m:s')) . ' WHERE `id` = ' . $result['id'];
1893:                 query($sql);
1894:             } else {
1895:                 $sql = 'INSERT INTO ' . prefix('search_cache') . ' (criteria, data, date) VALUES (' . db_quote($criteria) . ', ' . db_quote(serialize($found)) . ', ' . db_quote(date('Y-m-d H:m:s')) . ')';
1896:                 query($sql);
1897:             }
1898:         }
1899:     }
1900: 
1901:     /**
1902:      *
1903:      * Fetches a search from the cache if it exists and has not expired
1904:      * @param string $criteria
1905:      */
1906:     private function getCachedSearch($criteria) {
1907:         if (SEARCH_CACHE_DURATION) {
1908:             $sql = 'SELECT `id`, `date`, `data` FROM ' . prefix('search_cache') . ' WHERE `criteria` = ' . db_quote(serialize($criteria));
1909:             $result = query_single_row($sql);
1910:             if ($result) {
1911:                 if ((time() - strtotime($result['date'])) > SEARCH_CACHE_DURATION * 60) {
1912:                     query('DELETE FROM ' . prefix('search_cache') . ' WHERE `id` = ' . $result['id']);
1913:                 } else {
1914:                     if ($result = getSerializedArray($result['data'])) {
1915:                         return $result;
1916:                     }
1917:                 }
1918:             }
1919:         }
1920:         return NULL;
1921:     }
1922: 
1923:     /**
1924:      * Clears the entire search cache table
1925:      */
1926:     static function clearSearchCache() {
1927:         $check = query_single_row('SELECT id FROM ' . prefix('search_cache'). ' LIMIT 1');
1928:         if($check) {
1929:             query('TRUNCATE TABLE ' . prefix('search_cache'));
1930:         }
1931:     }
1932: 
1933: }
1934: 
1935: // search class end
1936: 
1937: /**
1938:  *
1939:  * encloses search word in quotes if needed
1940:  * @param string $word
1941:  * @return string
1942:  */
1943: function search_quote($word) {
1944:     if (is_numeric($word) || preg_match("/[ &|!'\"`,()]/", $word)) {
1945:         $word = '"' . str_replace("\\'", "'", addslashes($word)) . '"';
1946:     }
1947:     return $word;
1948: }
1949: 
1950: ?>
Zenphoto doc API documentation generated by ApiGen