Overview

Classes

  • _zp_captcha
  • _zp_HTML_cache
  • admin_approval
  • Album
  • AlbumBase
  • AlbumZip
  • AMFReader
  • AMFStream
  • AnyFile
  • AnyFile_Options
  • auto_backup
  • AVCSequenceParameterSetReader
  • bxslider
  • cacheManager
  • cachemanager_internal_deprecations
  • cacheManagerFeed
  • CI_jsmin
  • CI_load
  • cloneZenphoto
  • codeIgniter_kludge
  • colorbox
  • Combi
  • Comment
  • comment_form
  • contactformOptions
  • cookieConsent
  • crop_image
  • cycle
  • defaultCodeblocks
  • deprecated_functions
  • DownloadList
  • dynamic_locale
  • dynamicAlbum
  • elFinder
  • elFinder_options
  • elFinderConnector
  • elFinderEditor
  • elFinderEditorOnlineConvert
  • elFinderEditorZipArchive
  • elFinderEditorZohoOffice
  • elFinderLibGdBmp
  • elFinderPlugin
  • elFinderPluginAutoResize
  • elFinderPluginAutoRotate
  • elFinderPluginNormalizer
  • elFinderPluginSanitizer
  • elFinderPluginWatermark
  • elFinderSession
  • elFinderVolumeBox
  • elFinderVolumeDriver
  • elFinderVolumeDropbox
  • elFinderVolumeDropbox2
  • elFinderVolumeFlysystemGoogleDriveCache
  • elFinderVolumeFlysystemGoogleDriveNetmount
  • elFinderVolumeFTP
  • elFinderVolumeGoogleDrive
  • elFinderVolumeGroup
  • elFinderVolumeLocalFileSystem
  • elFinderVolumeMySQL
  • elFinderVolumeOneDrive
  • elFinderVolumeTrash
  • elFinderVolumeTrashMySQL
  • email_new_user
  • exampleMacros
  • external_auth
  • favorites
  • favoritesOptions
  • 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
  • hitcounter
  • htmlmetatags
  • Image
  • internal_deprecations
  • ipBlocker
  • jPlayer
  • jplayer_options
  • jquery_rating
  • JSMin
  • lazyload
  • lib_GD_Options
  • lib_Imagick_Options
  • lib_NoGraphics
  • matomoStats
  • 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
  • openStreetMap
  • openStreetMapOptions
  • pagedThumbsNav
  • pagedthumbsOptions
  • PersistentObject
  • PHPMailer\PHPMailer\PHPMailer
  • PHPMailer\PHPMailer\POP3
  • PHPMailer\PHPMailer\SMTP
  • print_album_menu
  • pseudoPlayer
  • publishContent
  • quota_manager
  • reCaptcha
  • RecursiveCallbackFilterIterator
  • redirector
  • redirectorOptions
  • register_user
  • rewriteRules
  • rewriteTokens
  • RSS
  • rss_options
  • scriptlessSocialsharing
  • scriptlessSocialsharingOptions
  • search_statistics
  • SearchEngine
  • security_logger
  • securityHeaders
  • securityheadersOptions
  • seo_locale
  • Services_JSON
  • Services_JSON_Error
  • setup
  • setupMutex
  • setupRSS
  • show_not_loggedin
  • sitemap
  • sitemapOptions
  • static_html_cache
  • staticHTMLCacheOptions
  • tagsuggest
  • TextObject
  • TextObject_Options
  • ThemeObject
  • themeSwitcher
  • tinymce4Options
  • tinyURL
  • Transientimage
  • UploadHandler
  • user_expiry
  • user_groups
  • user_logout_options
  • userAddressFields
  • userDataExport
  • utf8
  • Video
  • VideoObject_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
  • zpFunctions
  • zpMutex
  • zpSimpleSpam
  • zpTrivialSpam

Interfaces

  • elFinderSessionInterface

Exceptions

  • elFinderAbortException
  • elFinderTriggerException
  • getid3_exception
  • JSMin_UnterminatedCommentException
  • JSMin_UnterminatedRegExpException
  • JSMin_UnterminatedStringException
  • OAuthExcept
  • PHPMailer\PHPMailer\Exception

Functions

  • access
  • accessAlbums
  • accessAllAlbums
  • accessImage
  • add_context
  • addalbumsToDatabase
  • addCategoriesToDatabase
  • addDateToTitlelink
  • addGeoCoord
  • addItem
  • addMissingDefaultRewriteTokens
  • addPagesToDatabase
  • addReconfigureNote
  • addSubalbumMenus
  • addWatermark
  • admin_album_list
  • admin_securityChecks
  • admin_showupdate
  • adminPageNav
  • adminToolbox
  • albumNumber
  • applyMacros
  • authorSelector
  • bind_textdomain_codeset
  • bindtextdomain
  • build_query
  • build_url
  • bulkActionRedirect
  • bulkTags
  • byteConvert
  • cacheImage
  • checkAccess
  • checkAlbumForImages
  • checkAlbumimagesort
  • checkAlbumParentid
  • checkAlbumPassword
  • checkChosenItemStatus
  • checkChosenMenuset
  • checked
  • checkFolder
  • checkForEmptyTitle
  • checkForGuest
  • checkForPage
  • checkForUpdate
  • checkHitcounterDisplay
  • checkIfChecked
  • checkIfLockedNews
  • checkIfLockedPage
  • checkIfNew
  • checkInstall
  • checkLayoutUseForImages
  • checkObjectsThumb
  • checkPageValidity
  • checkParentLayouts
  • checkPublishDates
  • checkRequiredField
  • checkSchedulePublishingNotes
  • checkSelectedAlbum
  • checkSignature
  • checkTitlelinkDuplicate
  • cleanAlbum
  • cleanHTML
  • clonedFrom
  • codeblocktabsJS
  • comment_form_addComment
  • comment_form_handle_comment
  • comment_form_PaginationJS
  • comment_form_postcomment
  • comment_form_print10Most
  • comment_form_visualEditor
  • commentFormUseCaptcha
  • commentReply
  • commentsAllowed
  • compressRow
  • consolidatedEditMessages
  • copyLayoutSelection
  • copyThemeDirectory
  • createMenuIfNotExists
  • createRelatedItemsResultArray
  • createTitlelink
  • cron_starter
  • curlRequest
  • 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_getClientInfo
  • db_getServerInfo
  • db_getSQLmode
  • db_getVersion
  • db_insert_id
  • db_isMariaDB
  • 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
  • debuglogReconfigureNote
  • debugLogVar
  • decompressField
  • decompressRow
  • defaultCodeblocks_codebox
  • deleteArticle
  • deleteCategory
  • deleteItem
  • deleteLayoutSelection
  • deletePage
  • deleteThemeDirectory
  • dircopy
  • disableExtension
  • elFinder_admin_tabs
  • elFinder_tinymce
  • elFinderAutoloader
  • enableExtension
  • executeRSS
  • exitZP
  • exposeZenPhotoInformations
  • extendExecution
  • extensionEnabled
  • fetchComments
  • filesystemToInternal
  • fillbuffer
  • filterImageQuery
  • fix_path_redirect
  • formatList
  • fullText
  • galleryAlbumsPerPage
  • gallerystats_filesize_r
  • genAlbumList
  • generateAttributesFromArray
  • generateImageCacheFile
  • generateLanguageList
  • generateListFromArray
  • generateListFromFiles
  • generateRadiobuttonsFromArray
  • generateUnorderedListFromArray
  • get_AnyFile_suffixes
  • get_context
  • get_filterScript
  • get_instance
  • get_language_string
  • getAdminstratorsOptionsArray
  • getAdminThumb
  • getAdminThumbHTML
  • getAlbumArray
  • getAlbumBreadcrumb
  • getAlbumBreadcrumbAdmin
  • getAlbumCustomData
  • getAlbumData
  • getAlbumDate
  • getAlbumDesc
  • getAlbumFolder
  • getAlbumGeodata
  • getAlbumInherited
  • getAlbumLocation
  • getAlbumPage
  • getAlbumStatistic
  • getAlbumThumb
  • getAlbumTitle
  • getAlbumURL
  • getAllAccessibleAlbums
  • getAllAlbums
  • getAllDates
  • getAllowedTags
  • getAllSubAlbumIDs
  • getAllTagsCount
  • getAllTagsFromAlbum
  • getAllTagsFromAlbum_multi_unique
  • getAllTagsFromZenpage
  • getAllTagsUnique
  • getAllTranslations
  • getAnnotatedAlbumTitle
  • getAnnotatedImageTitle
  • getAnonymIP
  • getAuthor
  • getBare
  • getBareAlbumDesc
  • getBareAlbumTitle
  • getBareGalleryDesc
  • getBareGalleryTitle
  • getBareImageDesc
  • getBareImageTitle
  • getBareNewsTitle
  • getBarePageTitle
  • getCheckboxState
  • getCodeblock
  • getCommentAddress
  • getCommentAuthorEmail
  • getCommentAuthorLink
  • getCommentAuthorName
  • getCommentAuthorSite
  • getCommentBody
  • getCommentCount
  • getCommentDateTime
  • getCommentErrors
  • getCommentStored
  • getContactFormMacros
  • getContentShorten
  • getCookieInfoData
  • getCookieInfoHTML
  • getCookieInfoMacro
  • getCurrentMenuItem
  • getCurrentNewsArchive
  • getCurrentPage
  • getCurrentTheme
  • getCustomAlbumThumb
  • getCustomAlbumThumbMaxSpace
  • getCustomGalleryIndexPage
  • getCustomGalleryIndexURL
  • getCustomImageURL
  • getCustomPageURL
  • getCustomSizedImageMaxSpace
  • getCustomSizedImageThumbMaxSpace
  • getDataUsageNotice
  • getDefaultHeight
  • getDefaultRewriteTokens
  • getDefaultSizedImage
  • getDefaultWidth
  • getdownloadList
  • getDownloadURL
  • getE
  • getEnabledPlugins
  • getExpiryDatePost
  • getFavoritesURL
  • getField
  • getFullHeight
  • getFullImageFilesize
  • getFullImageURL
  • getFullWidth
  • getGalleryDesc
  • getGalleryIndexURL
  • getGalleryTitle
  • getGeoCoord
  • getHeadTitle
  • getHitcounter
  • getImageArgs
  • getImageCacheFilename
  • getImageCachePostfix
  • getImageCity
  • getImageCountry
  • getImageCustomData
  • getImageData
  • getImageDate
  • getImageDesc
  • getImageGeodata
  • getImageLocation
  • getImageMetaData
  • getImageParameters
  • getImageProcessorURI
  • getImageProcessorURIFromCacheName
  • getImageRotation
  • getImageState
  • getImageStatistic
  • getImageThumb
  • getImageTitle
  • getImageType
  • getImageURI
  • getImageURL
  • getItem
  • getItemByID
  • getItemTitleAndURL
  • getjPlayerSkinCSS
  • getjPlayerSkins
  • getLangAttributeLocale
  • getLanguageArray
  • getLanguageDisplayName
  • getLanguageFlag
  • getLanguageSubdomains
  • getLanguageText
  • getLatestComments
  • getLatestNews
  • getLatestZenpageComments
  • getLayout
  • getLayoutSelector
  • getLinkHTML
  • getLogTabs
  • getMacros
  • getMainSiteName
  • getMainSiteURL
  • getManagedAlbumList
  • getMaxSpaceContainer
  • getMenuFromLink
  • getMenuItemChilds
  • getMenuItems
  • getMenumanagerPredicessor
  • getMenumanagerSuccessor
  • getMenuSetSelector
  • getMenuVisibility
  • getMimeString
  • getNestedAlbumList
  • getNewsAdminOption
  • getNewsAdminOptionPath
  • getNewsArchivePath
  • getNewsArchiveURL
  • getNewsAuthor
  • getNewsCategories
  • getNewsCategoryCustomData
  • getNewsCategoryDesc
  • getNewsCategoryURL
  • getNewsContent
  • getNewsCustomData
  • getNewsDate
  • getNewsExtraContent
  • getNewsID
  • getNewsIndexURL
  • getNewsPagesStatistic
  • getNewsPathNav
  • getNewsReadMore
  • getNewsTitle
  • getNewsURL
  • getNextAlbum
  • getNextAlbumURL
  • getNextImageThumb
  • getNextImageURL
  • getNextNewsPageURL
  • getNextNewsURL
  • getNextPageURL
  • getNextPrevNews
  • getNotViewableAlbums
  • getNotViewableImages
  • getNumAlbums
  • getNumAllSubalbums
  • getNumImages
  • getNumNews
  • getNumPages
  • getOption
  • getOptionFromDB
  • getOptionList
  • getOwnerAuthor
  • getOwnerAuthorURL
  • getPageAuthor
  • getPageContent
  • getPageCustomData
  • getPageDate
  • getPageExtraContent
  • getPageID
  • getPageLastChangeDate
  • getPageNavList
  • getPageNumURL
  • getPageParentID
  • getPageRedirect
  • getPageSelector
  • getPageSortorder
  • getPageTitle
  • getPageTitleLink
  • getPageURL
  • getParentAlbums
  • getParentAlbumsAdmin
  • getParentBreadcrumb
  • getParentMenuItems
  • getPasswordProtectImage
  • getPHPFiles
  • getPictureOfTheDay
  • getPlugin
  • getPluginFiles
  • getPluginTabs
  • getPrevAlbum
  • getPrevAlbumURL
  • getPrevImageThumb
  • getPrevImageURL
  • getPrevNewsPageURL
  • getPrevNewsURL
  • getPrevPageURL
  • getProtectedImageURL
  • getRandomImages
  • getRandomImagesAlbum
  • getRating
  • getReconfigureNote
  • getRelatedItems
  • getRequestURI
  • getrow
  • getRSSLink
  • getRules
  • getSearchDate
  • getSearchURL
  • getSearchWords
  • getSelectedLayout
  • getSerializedArray
  • getSetClause
  • getSiteHomeURL
  • getSizeCustomImage
  • getSizeDefaultImage
  • getSizeDefaultThumb
  • getSizedImageURL
  • getSizeFullImage
  • getSortByOptions
  • getSortByStatusOptions
  • getStandardGalleryIndexURL
  • getSubtabs
  • getSuffix
  • getSystemLocales
  • getTagCountByAccess
  • getTagOrder
  • getTags
  • gettext
  • gettext_pl
  • gettext_th
  • getThemeFiles
  • getThemeOption
  • getTimezones
  • getTinyMCE4ConfigFiles
  • getTitle
  • getTotalHitcounter
  • getTotalImagesIn
  • getTotalNewsPages
  • getTotalPages
  • getUnprotectedImageURL
  • getUrAlbum
  • getUserIP
  • getUserLocale
  • getUserURL
  • getVersion
  • getWatermarkParam
  • getWatermarkPath
  • getWatermarks
  • getWhereClause
  • getXSRFToken
  • getZenpagePagesOptionsArray
  • getZenpageStatistic
  • handleSearchParms
  • hasDynamicAlbumSuffix
  • hasNextImage
  • hasNextNewsPage
  • hasNextPage
  • hasPrevImage
  • hasPrevNewsPage
  • hasPrevPage
  • hasPrimaryScripts
  • hl_attrval
  • hl_bal
  • hl_cmtcd
  • hl_ent
  • hl_prot
  • hl_regex
  • hl_spec
  • hl_tag
  • hl_tag2
  • hl_tidy
  • hl_version
  • html_decode
  • html_encode
  • html_encodeTagged
  • html_pathurlencode
  • htmLawed
  • httpsRedirect
  • httpUploadHandler
  • httpUploadHandler_admin_tabs
  • i18nSetLocale
  • ignoreSetupRunRequest
  • imageBlurGD
  • imagecreatefrombmp
  • imageDebug
  • imageError
  • imageNumber
  • imgSrcURI
  • in_context
  • installSignature
  • instrument
  • internalToFilesystem
  • inventMenuItem
  • iptc_make_tag
  • is_AdminEditPage
  • is_connected
  • is_News
  • is_NewsArchive
  • is_NewsArticle
  • is_NewsCategory
  • is_NewsPage
  • is_Pages
  • is_valid_email_zp
  • is_zip
  • isAlbumClass
  • isAlbumPage
  • isArchive
  • isCurrentitemParent
  • isHandledAlbum
  • isImageClass
  • isImagePage
  • isImagePhoto
  • isImageVideo
  • isIncompatibleExtension
  • isLandscape
  • isolate
  • isSetupProtected
  • isValidEmail
  • 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
  • myts_date
  • newAlbum
  • newImage
  • next_album
  • next_comment
  • next_image
  • next_news
  • next_page
  • ngettext
  • ngettext_pl
  • ngettext_th
  • omsAdditions
  • parse_query
  • parse_size
  • parseAllowedTags
  • parseHttpAcceptLanguage
  • pathurlencode
  • pluginDebug
  • populateManagedObjectsList
  • postAlbumSort
  • postIndexDecode
  • postIndexEncode
  • prefix
  • prepareAlbumPage
  • prepareCustomPage
  • prepareImagePage
  • prepareIndexPage
  • print404status
  • print_language_string_list
  • printAddToFavorites
  • printAdminFooter
  • printAdminHeader
  • printAdminRightsTable
  • printAdminThumb
  • printAlbumBreadcrumb
  • printAlbumButtons
  • printAlbumCustomData
  • printAlbumData
  • printAlbumDate
  • printAlbumDesc
  • printAlbumEditForm
  • printAlbumEditRow
  • printAlbumLegend
  • printAlbumLocation
  • printAlbumMenu
  • printAlbumMenuJump
  • printAlbumMenuList
  • printAlbumMenuListAlbum
  • printAlbumsSelector
  • printAlbumStatistic
  • printAlbumStatisticItem
  • printAlbumThumbImage
  • printAlbumTitle
  • printAlbumURL
  • printAllDates
  • printAllNestedList
  • printAllNewsCategories
  • printAllTags
  • printAllTagsAs
  • printAllTagsFromAlbum
  • printAllTagsFromZenpage
  • printAnnotatedAlbumTitle
  • printAnnotatedImageTitle
  • printArticleCategories
  • printArticleDatesDropdown
  • printArticlesPerPageDropdown
  • printAuthorDropdown
  • printBareAlbumDesc
  • printBareAlbumTitle
  • printBareGalleryDesc
  • printBareGalleryTitle
  • printBareImageDesc
  • printBareImageTitle
  • printBareNewsTitle
  • printBarePageTitle
  • printBarGraph
  • printBulkActions
  • printCategoriesStatistic
  • printCategoryCheckboxListEntry
  • printCategoryDropdown
  • printCategoryListSortableTable
  • printCategorySelection
  • printCodeblock
  • printCodeblockEdit
  • printCommentAuthorLink
  • printCommentErrors
  • printCommentForm
  • printContactForm
  • printContactFormMacro
  • printCookieInfo
  • printCopyrightNotice
  • printCurrentNewsArchive
  • printCurrentNewsCategory
  • printCustomAlbumThumbImage
  • printCustomAlbumThumbMaxSpace
  • printCustomMenu
  • printCustomPageSelector
  • printCustomPageURL
  • printCustomSizedImage
  • printCustomSizedImageMaxSpace
  • printCustomSizedImageThumbMaxSpace
  • printDataUsageNotice
  • printDefaultSizedImage
  • printDownloadAlbumZipURL
  • printdownloadList
  • printDownloadURL
  • printEditCommentLink
  • printEditDropdown
  • printExpired
  • printFavoritesURL
  • printFullAlbumsList
  • printFullImageDownloadURL
  • printGalleryDesc
  • printGalleryIndexURL
  • printGalleryTitle
  • printGoogleMap
  • printHeadTitle
  • printHomeLink
  • printImageCustomData
  • printImageData
  • printImageDate
  • printImageDesc
  • printImageMetadata
  • printImageslist
  • printImageStatistic
  • printImageThumb
  • printImageTitle
  • printImageURL
  • printItemEditLink
  • printItemsList
  • printItemsListTable
  • printItemStatusDropdown
  • printjPlayerPlaylist
  • printLangAttribute
  • printLanguageSelector
  • printLastChangeInfo
  • printLatestAlbums
  • printLatestComments
  • printLatestImages
  • printLatestImagesByDate
  • printLatestImagesByMtime
  • printLatestNews
  • printLatestUpdatedAlbums
  • printLinkHTML
  • printLogoAndLinks
  • printManagedObjects
  • printMenuemanagerPageList
  • printMenuemanagerPageListWithNav
  • printMenumanagerBreadcrumb
  • printMenumanagerNextLink
  • printMenumanagerPrevLink
  • printMostPopularItems
  • printMostRatedAlbums
  • printMostRatedImages
  • printMostRatedItems
  • printNestedAlbumsList
  • printNestedItemsList
  • printNestedMenu
  • printNews
  • printNewsArchive
  • printNewsArticlesList
  • printNewsAuthor
  • printNewsCategories
  • printNewsCategoryCustomData
  • printNewsCategoryDesc
  • printNewsCategoryURL
  • printNewsContent
  • printNewsCustomData
  • printNewsDate
  • printNewsExtraContent
  • printNewsIndexURL
  • printNewsPageList
  • printNewsPageListWithNav
  • printNewsStatistic
  • printNewsTitle
  • printNewsURL
  • printNextNewsLink
  • printNextNewsPageLink
  • printNextPageURL
  • printOpenStreetMap
  • printOwnerAuthor
  • printOwnerAuthorURL
  • printPageArticleTags
  • printPageAuthor
  • printPageContent
  • printPageCustomData
  • printPageDate
  • printPagedThumbsNav
  • printPageExtraContent
  • printPageID
  • printPageLastChangeDate
  • printPageList
  • printPageListWithNav
  • printPageMenu
  • printPageNav
  • printPageSelector
  • printPagesListTable
  • printPagesStatistic
  • printPageTitle
  • printPageTitleLink
  • printPageURL
  • printParentBreadcrumb
  • printPasswordForm
  • printPopularAlbums
  • printPopularImages
  • printPrevNewsLink
  • printPrevNewsPageLink
  • printPrevPageURL
  • printPrivacyPageLink
  • printPublished
  • printPublishIconLink
  • printPublishIconLinkGallery
  • printRandomImages
  • printRating
  • printReconfigureError
  • printReconfigureNote
  • printRegisterURL
  • printRegistrationForm
  • printRelatedItems
  • printRSSHeaderLink
  • printRSSLink
  • printScheduledPublishingNotes
  • printSearchBreadcrumb
  • printSearchForm
  • printSelectorWithCustomField
  • printSiteHomeURL
  • printSizedImageURL
  • printSlideShow
  • printSlideShowLink
  • printSortableHead
  • printSortOrderDropdown
  • printSubLevelAlbums
  • printSubPagesExcerpts
  • printSubtabs
  • printTabs
  • printTags
  • printThumbNav
  • printTinyPageNav
  • printTinyZenpageCategorySelector
  • printTopRatedAlbums
  • printTopRatedImages
  • printTopRatedItems
  • printUnpublishedDropdown
  • printUserLogin_out
  • printUserSelector
  • printUserURL
  • printVersion
  • printZenJavascripts
  • printZenpageIconLegend
  • printZenpageItems
  • printZenpageItemsBreadcrumb
  • printZenpageNewsCategorySelector
  • printZenpagePageSelector
  • printZenpagePagesSelector
  • printZenpageStatistic
  • printZenphotoLink
  • process_language_string_save
  • processAlbumBulkActions
  • processAlbumEdit
  • processCodeblockSave
  • processCommentBulkActions
  • processCredentials
  • processCustomOptionSave
  • processEditSelection
  • processExtensionVariable
  • processImageBulkActions
  • processImageEdit
  • processManagedObjects
  • processMenuBulkActions
  • processOrder
  • processRights
  • processTags
  • processZenpageBulkActions
  • propSizes
  • protectSetupFiles
  • publishItem
  • purgeOption
  • purgeThemeOption
  • query
  • query_full_array
  • query_single_row
  • rc4
  • read_exif_data_protected
  • readTags
  • reconfigureAction
  • reconfigureCSS
  • recordMissing
  • redirectionHandler
  • redirectURL
  • rem_context
  • removeDir
  • removeParentAlbumNames
  • removeTrailingSlash
  • renameOption
  • replaceOption
  • replaceThemeOption
  • restore_context
  • reveal
  • rewrite_get_album_image
  • rewrite_path
  • rewriteHandler
  • RSS_Channel
  • RSS_Retrieve
  • RSS_Tags
  • rulesList
  • 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
  • setAlbumSubtabs
  • setexifvars
  • setMainDomain
  • setOption
  • setOptionDefault
  • setSiteState
  • setThemeColumns
  • setThemeOption
  • setThemeOptionDefault
  • setTinyZenpageLocale
  • setupCurrentLocale
  • setupDomain
  • setupTheme
  • shortenContent
  • shortentitle
  • showOrNotShowField
  • showZenphotoOptions
  • shuffle_assoc
  • signatureChange
  • site_upgrade_button
  • site_upgrade_status
  • skipScheduledPublishing
  • sortArray
  • sortByKey
  • sortByMultilingual
  • sortMultiArray
  • standardScripts
  • standardThemeOptions
  • stickyNews
  • storeConfig
  • storeTags
  • stripSuffix
  • submenuOf
  • switchLog
  • tagSelector
  • tagSuggestJS
  • tagSuggestJS_admin
  • tagSuggestJS_frontend
  • tagURLs
  • textdomain
  • themeIsEditable
  • themeSetup
  • tidyHTML
  • timezoneDiff
  • tinymce4ConfigJS
  • truncate_string
  • unprotectSetupFiles
  • unpublishedZenpageItemCheck
  • unpublishedZenphotoItemCheck
  • unpublishSubalbums
  • unQuote
  • unTagURLs
  • unzip
  • updateArticle
  • updateCacheName
  • updateCategory
  • updateConfigItem
  • updateImageProcessorLink
  • updateItemSortorder
  • updateItemsSortorder
  • updateMenuItem
  • updatePage
  • upload_extra
  • upload_form
  • upload_head
  • user_mailing_list_button
  • validateLocale
  • writeHeader
  • XSRFdefender
  • XSRFToken
  • zenpageAlbumImage
  • zenpageBulkActionMessage
  • zenpageJSCSS
  • 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_imageResizeTransparent
  • 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_destroy
  • zp_session_start
  • zp_setCookie
  • zp_writeString
  • zpErrorHandler
  • zpFormattedDate
  • zpRewriteURL
  • Overview
  • Class
  • Tree
  • Package
  • Deprecated
   1:    2:    3:    4:    5:    6:    7:    8:    9:   10:   11:   12:   13:   14:   15:   16:   17:   18:   19:   20:   21:   22:   23:   24:   25:   26:   27:   28:   29:   30:   31:   32:   33:   34:   35:   36:   37:   38:   39:   40:   41:   42:   43:   44:   45:   46:   47:   48:   49:   50:   51:   52:   53:   54:   55:   56:   57:   58:   59:   60:   61:   62:   63:   64:   65:   66:   67:   68:   69:   70:   71:   72:   73:   74:   75:   76:   77:   78:   79:   80:   81:   82:   83:   84:   85:   86:   87:   88:   89:   90:   91:   92:   93:   94:   95:   96:   97:   98:   99:  100:  101:  102:  103:  104:  105:  106:  107:  108:  109:  110:  111:  112:  113:  114:  115:  116:  117:  118:  119:  120:  121:  122:  123:  124:  125:  126:  127:  128:  129:  130:  131:  132:  133:  134:  135:  136:  137:  138:  139:  140:  141:  142:  143:  144:  145:  146:  147:  148:  149:  150:  151:  152:  153:  154:  155:  156:  157:  158:  159:  160:  161:  162:  163:  164:  165:  166:  167:  168:  169:  170:  171:  172:  173:  174:  175:  176:  177:  178:  179:  180:  181:  182:  183:  184:  185:  186:  187:  188:  189:  190:  191:  192:  193:  194:  195:  196:  197:  198:  199:  200:  201:  202:  203:  204:  205:  206:  207:  208:  209:  210:  211:  212:  213:  214:  215:  216:  217:  218:  219:  220:  221:  222:  223:  224:  225:  226:  227:  228:  229:  230:  231:  232:  233:  234:  235:  236:  237:  238:  239:  240:  241:  242:  243:  244:  245:  246:  247:  248:  249:  250:  251:  252:  253:  254:  255:  256:  257:  258:  259:  260:  261:  262:  263:  264:  265:  266:  267:  268:  269:  270:  271:  272:  273:  274:  275:  276:  277:  278:  279:  280:  281:  282:  283:  284:  285:  286:  287:  288:  289:  290:  291:  292:  293:  294:  295:  296:  297:  298:  299:  300:  301:  302:  303:  304:  305:  306:  307:  308:  309:  310:  311:  312:  313:  314:  315:  316:  317:  318:  319:  320:  321:  322:  323:  324:  325:  326:  327:  328:  329:  330:  331:  332:  333:  334:  335:  336:  337:  338:  339:  340:  341:  342:  343:  344:  345:  346:  347:  348:  349:  350:  351:  352:  353:  354:  355:  356:  357:  358:  359:  360:  361:  362:  363:  364:  365:  366:  367:  368:  369:  370:  371:  372:  373:  374:  375:  376:  377:  378:  379:  380:  381:  382:  383:  384:  385:  386:  387:  388:  389:  390:  391:  392:  393:  394:  395:  396:  397:  398:  399:  400:  401:  402:  403:  404:  405:  406:  407:  408:  409:  410:  411:  412:  413:  414:  415:  416:  417:  418:  419:  420:  421:  422:  423:  424:  425:  426:  427:  428:  429:  430:  431:  432:  433:  434:  435:  436:  437:  438:  439:  440:  441:  442:  443:  444:  445:  446:  447:  448:  449:  450:  451:  452:  453:  454:  455:  456:  457:  458:  459:  460:  461:  462:  463:  464:  465:  466:  467:  468:  469:  470:  471:  472:  473:  474:  475:  476:  477:  478:  479:  480:  481:  482:  483:  484:  485:  486:  487:  488:  489:  490:  491:  492:  493:  494:  495:  496:  497:  498:  499:  500:  501:  502:  503:  504:  505:  506:  507:  508:  509:  510:  511:  512:  513:  514:  515:  516:  517:  518:  519:  520:  521:  522:  523:  524:  525:  526:  527:  528:  529:  530:  531:  532:  533:  534:  535:  536:  537:  538:  539:  540:  541:  542:  543:  544:  545:  546:  547:  548:  549:  550:  551:  552:  553:  554:  555:  556:  557:  558:  559:  560:  561:  562:  563:  564:  565:  566:  567:  568:  569:  570:  571:  572:  573:  574:  575:  576:  577:  578:  579:  580:  581:  582:  583:  584:  585:  586:  587:  588:  589:  590:  591:  592:  593:  594:  595:  596:  597:  598:  599:  600:  601:  602:  603:  604:  605:  606:  607:  608:  609:  610:  611:  612:  613:  614:  615:  616:  617:  618:  619:  620:  621:  622:  623:  624:  625:  626:  627:  628:  629:  630:  631:  632:  633:  634:  635:  636:  637:  638:  639:  640:  641:  642:  643:  644:  645:  646:  647:  648:  649:  650:  651:  652:  653:  654:  655:  656:  657:  658:  659:  660:  661:  662:  663:  664:  665:  666:  667:  668:  669:  670:  671:  672:  673:  674:  675:  676:  677:  678:  679:  680:  681:  682:  683:  684:  685:  686:  687:  688:  689:  690:  691:  692:  693:  694:  695:  696:  697:  698:  699:  700:  701:  702:  703:  704:  705:  706:  707:  708:  709:  710:  711:  712:  713:  714:  715:  716:  717:  718:  719:  720:  721:  722:  723:  724:  725:  726:  727:  728:  729:  730:  731:  732:  733:  734:  735:  736:  737:  738:  739:  740:  741:  742:  743:  744:  745:  746:  747:  748:  749:  750:  751:  752:  753:  754:  755:  756:  757:  758:  759:  760:  761:  762:  763:  764:  765:  766:  767:  768:  769:  770:  771:  772:  773:  774:  775:  776:  777:  778:  779:  780:  781:  782:  783:  784:  785:  786:  787:  788:  789:  790:  791:  792:  793:  794:  795:  796:  797:  798:  799:  800:  801:  802:  803:  804:  805:  806:  807:  808:  809:  810:  811:  812:  813:  814:  815:  816:  817:  818:  819:  820:  821:  822:  823:  824:  825:  826:  827:  828:  829:  830:  831:  832:  833:  834:  835:  836:  837:  838:  839:  840:  841:  842:  843:  844:  845:  846:  847:  848:  849:  850:  851:  852:  853:  854:  855:  856:  857:  858:  859:  860:  861:  862:  863:  864:  865:  866:  867:  868:  869:  870:  871:  872:  873:  874:  875:  876:  877:  878:  879:  880:  881:  882:  883:  884:  885:  886:  887:  888:  889:  890:  891:  892:  893:  894:  895:  896:  897:  898:  899:  900:  901:  902:  903:  904:  905:  906:  907:  908:  909:  910:  911:  912:  913:  914:  915:  916:  917:  918:  919:  920:  921:  922:  923:  924:  925:  926:  927:  928:  929:  930:  931:  932:  933:  934:  935:  936:  937:  938:  939:  940:  941:  942:  943:  944:  945:  946:  947:  948:  949:  950:  951:  952:  953:  954:  955:  956:  957:  958:  959:  960:  961:  962:  963:  964:  965:  966:  967:  968:  969:  970:  971:  972:  973:  974:  975:  976:  977:  978:  979:  980:  981:  982:  983:  984:  985:  986:  987:  988:  989:  990:  991:  992:  993:  994:  995:  996:  997:  998:  999: 1000: 1001: 1002: 1003: 1004: 1005: 1006: 1007: 1008: 1009: 1010: 1011: 1012: 1013: 1014: 1015: 1016: 1017: 1018: 1019: 1020: 1021: 1022: 1023: 1024: 1025: 1026: 1027: 1028: 1029: 1030: 1031: 1032: 1033: 1034: 1035: 1036: 1037: 1038: 1039: 1040: 1041: 1042: 1043: 1044: 1045: 1046: 1047: 1048: 1049: 1050: 1051: 1052: 1053: 1054: 1055: 1056: 1057: 1058: 1059: 1060: 1061: 1062: 1063: 1064: 1065: 1066: 1067: 1068: 1069: 1070: 1071: 1072: 1073: 1074: 1075: 1076: 1077: 1078: 1079: 1080: 1081: 1082: 1083: 1084: 1085: 1086: 1087: 1088: 1089: 1090: 1091: 1092: 1093: 1094: 1095: 1096: 1097: 1098: 1099: 1100: 1101: 1102: 1103: 1104: 1105: 1106: 1107: 1108: 1109: 1110: 1111: 1112: 1113: 1114: 1115: 1116: 1117: 1118: 1119: 1120: 1121: 1122: 1123: 1124: 1125: 1126: 1127: 1128: 1129: 1130: 1131: 1132: 1133: 1134: 1135: 1136: 1137: 1138: 1139: 1140: 1141: 1142: 1143: 1144: 1145: 1146: 1147: 1148: 1149: 1150: 1151: 1152: 1153: 1154: 1155: 1156: 1157: 1158: 1159: 1160: 1161: 1162: 1163: 1164: 1165: 1166: 1167: 1168: 1169: 1170: 1171: 1172: 1173: 1174: 1175: 1176: 1177: 1178: 1179: 1180: 1181: 1182: 1183: 1184: 1185: 1186: 1187: 1188: 1189: 1190: 1191: 1192: 1193: 1194: 1195: 1196: 1197: 1198: 1199: 1200: 1201: 1202: 1203: 1204: 1205: 1206: 1207: 1208: 1209: 1210: 1211: 1212: 1213: 1214: 1215: 1216: 1217: 1218: 1219: 1220: 1221: 1222: 1223: 1224: 1225: 1226: 1227: 1228: 1229: 1230: 1231: 1232: 1233: 1234: 1235: 1236: 1237: 1238: 1239: 1240: 1241: 1242: 1243: 1244: 1245: 1246: 1247: 1248: 1249: 1250: 1251: 1252: 1253: 1254: 1255: 1256: 1257: 1258: 1259: 1260: 1261: 1262: 1263: 1264: 1265: 1266: 1267: 1268: 1269: 1270: 1271: 1272: 1273: 1274: 1275: 1276: 1277: 1278: 1279: 1280: 1281: 1282: 1283: 1284: 1285: 1286: 1287: 1288: 1289: 1290: 1291: 1292: 1293: 1294: 1295: 1296: 1297: 1298: 1299: 1300: 1301: 1302: 1303: 1304: 1305: 1306: 1307: 1308: 1309: 1310: 1311: 1312: 1313: 1314: 1315: 1316: 1317: 1318: 1319: 1320: 1321: 1322: 1323: 1324: 1325: 1326: 1327: 1328: 1329: 1330: 1331: 1332: 1333: 1334: 1335: 1336: 1337: 1338: 1339: 1340: 1341: 1342: 1343: 1344: 1345: 1346: 1347: 1348: 1349: 1350: 1351: 1352: 1353: 1354: 1355: 1356: 1357: 1358: 1359: 1360: 1361: 1362: 1363: 1364: 1365: 1366: 1367: 1368: 1369: 1370: 1371: 1372: 1373: 1374: 1375: 1376: 1377: 1378: 1379: 1380: 1381: 1382: 1383: 1384: 1385: 1386: 1387: 1388: 1389: 1390: 1391: 1392: 1393: 1394: 1395: 1396: 1397: 1398: 1399: 1400: 1401: 1402: 1403: 1404: 1405: 1406: 1407: 1408: 1409: 1410: 1411: 1412: 1413: 1414: 1415: 1416: 1417: 1418: 1419: 1420: 1421: 1422: 1423: 1424: 1425: 1426: 1427: 1428: 1429: 1430: 1431: 1432: 1433: 1434: 1435: 1436: 1437: 1438: 1439: 1440: 1441: 1442: 1443: 1444: 1445: 1446: 1447: 1448: 1449: 1450: 1451: 1452: 1453: 1454: 1455: 1456: 1457: 1458: 1459: 1460: 1461: 1462: 1463: 1464: 1465: 1466: 1467: 1468: 1469: 1470: 1471: 1472: 1473: 1474: 1475: 1476: 1477: 1478: 1479: 1480: 1481: 1482: 1483: 1484: 1485: 1486: 1487: 1488: 1489: 1490: 1491: 1492: 1493: 1494: 1495: 1496: 1497: 1498: 1499: 1500: 1501: 1502: 1503: 1504: 1505: 1506: 1507: 1508: 1509: 1510: 1511: 1512: 1513: 1514: 1515: 1516: 1517: 1518: 1519: 1520: 1521: 1522: 1523: 1524: 1525: 1526: 1527: 1528: 1529: 1530: 1531: 1532: 1533: 1534: 1535: 1536: 1537: 1538: 1539: 1540: 1541: 1542: 1543: 1544: 1545: 1546: 1547: 1548: 1549: 1550: 1551: 1552: 1553: 1554: 1555: 1556: 1557: 1558: 1559: 1560: 1561: 1562: 1563: 1564: 1565: 1566: 1567: 1568: 1569: 1570: 1571: 1572: 1573: 1574: 1575: 1576: 1577: 1578: 1579: 1580: 1581: 1582: 1583: 1584: 1585: 1586: 1587: 1588: 1589: 1590: 1591: 1592: 1593: 1594: 1595: 1596: 1597: 1598: 1599: 1600: 1601: 1602: 1603: 1604: 1605: 1606: 1607: 1608: 1609: 1610: 1611: 1612: 1613: 1614: 1615: 1616: 1617: 1618: 1619: 1620: 1621: 1622: 1623: 1624: 1625: 1626: 1627: 1628: 1629: 1630: 1631: 1632: 1633: 1634: 1635: 1636: 1637: 1638: 1639: 1640: 1641: 1642: 1643: 1644: 1645: 1646: 1647: 1648: 1649: 1650: 1651: 1652: 1653: 1654: 1655: 1656: 1657: 1658: 1659: 1660: 1661: 1662: 1663: 1664: 1665: 1666: 1667: 1668: 1669: 1670: 1671: 1672: 1673: 1674: 1675: 1676: 1677: 1678: 1679: 1680: 1681: 1682: 1683: 1684: 1685: 1686: 1687: 1688: 1689: 1690: 1691: 1692: 1693: 1694: 1695: 1696: 1697: 1698: 1699: 1700: 1701: 1702: 1703: 1704: 1705: 1706: 1707: 1708: 1709: 1710: 1711: 1712: 1713: 1714: 1715: 1716: 1717: 1718: 1719: 1720: 1721: 1722: 1723: 1724: 1725: 1726: 1727: 1728: 1729: 1730: 1731: 1732: 1733: 1734: 1735: 1736: 1737: 1738: 1739: 1740: 1741: 1742: 1743: 1744: 1745: 1746: 1747: 1748: 1749: 1750: 1751: 1752: 1753: 1754: 1755: 1756: 1757: 1758: 1759: 1760: 1761: 1762: 1763: 1764: 1765: 1766: 1767: 1768: 1769: 1770: 1771: 1772: 1773: 1774: 1775: 1776: 1777: 1778: 1779: 1780: 1781: 1782: 1783: 1784: 1785: 1786: 1787: 1788: 1789: 1790: 1791: 1792: 1793: 1794: 1795: 1796: 1797: 1798: 1799: 1800: 1801: 1802: 1803: 1804: 1805: 1806: 1807: 1808: 1809: 1810: 1811: 1812: 1813: 1814: 1815: 1816: 1817: 1818: 1819: 1820: 1821: 1822: 1823: 1824: 1825: 1826: 1827: 1828: 1829: 1830: 1831: 1832: 1833: 1834: 1835: 1836: 1837: 1838: 1839: 1840: 1841: 1842: 1843: 1844: 1845: 1846: 1847: 1848: 1849: 1850: 1851: 1852: 1853: 1854: 1855: 1856: 1857: 1858: 1859: 1860: 1861: 1862: 1863: 1864: 1865: 1866: 1867: 1868: 1869: 1870: 1871: 1872: 1873: 1874: 1875: 1876: 1877: 1878: 1879: 1880: 1881: 1882: 1883: 1884: 1885: 
<?php
/**
 * Zenphoto USER credentials handlers
 *
 * An alternate authorization script may be provided to override this script. To do so, make a script that
 * implements the classes declared below. Place the new script inthe <ZENFOLDER>/plugins/alt/ folder. Zenphoto
 * will then will be automatically loaded the alternate script in place of this one.
 *
 * Replacement libraries must implement two classes:
 *      "Authority" class: Provides the methods used for user authorization and management
 *          store an instantiation of this class in $_zp_authority.
 *
 *      Administrator: supports the basic Zenphoto needs for object manipulation of administrators.
 * (You can include this script and extend the classes if that suits your needs.)
 *
 * The global $_zp_current_admin_obj represents the current admin with.
 * The library must instantiate its authority class and store the object in the global $_zp_authority
 * (Note, this library does instantiate the object as described. This is so its classes can
 * be used as parent classes for lib-auth implementations. If auth_zp.php decides to use this
 * library it will instantiate the class and store it into $_zp_authority.
 *
 * The following elements need to be present in any alternate implementation in the
 * array returned by getAdministrators().
 *
 *      In particular, there should be array elements for:
 *              'id' (unique), 'user' (unique), 'pass', 'name', 'email', 'rights', 'valid',
 *              'group', and 'custom_data'
 *
 *      So long as all these indices are populated it should not matter when and where
 *      the data is stored.
 *
 *      Administrator class methods are required for these elements as well.
 *
 *      The getRights() method must define at least the rights defined by the method in
 *      this library.
 *
 *      The checkAuthorization() method should promote the "most privileged" Admin to
 *      ADMIN_RIGHTS to insure that there is some user capable of adding users or
 *      modifying user rights.
 *
 * @package core
 * @subpackage classes\authorization
 */
// force UTF-8 Ø
require_once(dirname(__FILE__) . '/classes.php');

/**
 * Provides the methods used for user authorization and management
 * store an instantiation of this class in `$_zp_authority`.
 *
 * @package core
 * @subpackage classes\authorization
 */
class Zenphoto_Authority {

    public $admin_users = NULL;
    public $admin_groups = NULL;
    public $admin_other = NULL;
    public $admin_all = NULL;
    public $rightsset = NULL;
    protected $master_user = NULL;
    static $preferred_version = 4;
    static $supports_version = 4;
    static $hashList = array('pbkdf2' => 3, 'pbkdf2*' => 2, 'sha1' => 1, 'md5' => 0);

    /**
     * class instantiation function
     *
     * @return lib_auth_options
     */
    function __construct() {
        setOptionDefault('admin_lastvisit_timeframe', 600);
        setOptionDefault('admin_lastvisit', true);
        $this->admin_all = $this->admin_groups = $this->admin_users = $this->admin_other = array();
        $sql = 'SELECT * FROM ' . prefix('administrators') . ' ORDER BY `rights` DESC, `id`';
        $admins = query($sql, false);
        if ($admins) {
            while ($user = db_fetch_assoc($admins)) {
                $this->admin_all[$user['id']] = $user;
                switch ($user['valid']) {
                    case 1:
                        $this->admin_users[$user['id']] = $user;
                        if (empty($this->master_user))
                            $this->master_user = $user['user'];
                        break;
                    case 0:
                        $this->admin_groups[$user['id']] = $user;
                        break;
                    default:
                        $this->admin_other[$user['id']] = $user;
                        break;
                }
            }
            db_free_result($admins);
        }
    }

    function getMasterUser() {
        return new Zenphoto_Administrator($this->master_user, 1);
    }

    function isMasterUser($user) {
        return $user == $this->master_user;
    }

    /**
     * Declares options used by lib-auth
     *
     * @return array
     */
    function getOptionsSupported() {
        $encodings = self::$hashList;
        unset($encodings['pbkdf2*']); // don't use this one any more
        if (!function_exists('hash')) {
            unset($encodings['pbkdf2']);
        }
        return array(gettext('Primary album edit') =>
                array('key' => 'user_album_edit_default',
                        'type' => OPTION_TYPE_CHECKBOX,
                        'desc' => gettext('Check if you want <em>edit rights</em> automatically assigned when a user <em>primary album</em> is created.')),
                gettext('Minimum password strength') => array(
                        'key' => 'password_strength',
                        'type' => OPTION_TYPE_CUSTOM,
                        'desc' => sprintf(gettext('Users must provide passwords a strength of at least %s. The repeat password field will be disabled until this floor is met.'), '<span id="password_strength_display">' . getOption('password_strength') . '</span>')),
                gettext('Password hash algorithm') => array(
                        'key' => 'strong_hash',
                        'type' => OPTION_TYPE_SELECTOR,
                        'selections' => $encodings,
                        'desc' => sprintf(gettext('The hashing algorithm used by Zenphoto. In order of robustness the choices are %s'), '<code>' . implode('</code> > <code>', array_flip($encodings)) . '</code>')),
                gettext('User last visit - store') => array(
                        'key' => 'admin_lastvisit',
                        'type' => OPTION_TYPE_CHECKBOX,
                        'desc' => gettext('Enable if you like to store visits of logged-in users in the database.')),
                gettext('User last visit - time frame') => array(
                        'key' => 'admin_lastvisit_timeframe',
                        'type' => OPTION_TYPE_TEXTBOX,
                        'desc' => gettext('Time in seconds before the last visit of logged-in users is updated in the database. Default is 600 seconds (10 minutes)'))
        );
    }

    /**
     * Dummy for object inheritance purposes
     */
    function handleOption($option, $currentValue) {
        global $_zp_current_admin_obj;
        switch ($option) {
            case 'password_strength':
                ?>
                <input type="hidden" size="3" id="password_strength" name="password_strength" value="<?php echo getOption('password_strength'); ?>" />
                <script type="text/javascript">
                    // <!-- <![CDATA[
                    function sliderColor(strength) {
                        var url = 'url(<?php echo WEBPATH . '/' . ZENFOLDER; ?>/images/strengths/strength' + strength + '.png)';
                        $('#slider-password_strength').css('background-image', url);
                    }
                    $(function() {
                        $("#slider-password_strength").slider({
                <?php $v = getOption('password_strength'); ?>
                            startValue: <?php echo $v; ?>,
                            value: <?php echo $v; ?>,
                            min: 1,
                            max: 30,
                            slide: function(event, ui) {
                                $("#password_strength").val(ui.value);
                                $('#password_strength_display').html(ui.value);
                                sliderColor(ui.value);
                            }
                        });
                        var strength = $("#slider-password_strength").slider("value");
                        $("#password_strength").val(strength);
                        $('#password_strength_display').html(strength);
                        sliderColor(strength);
                    });
                    // ]]> -->
                </script>
                <div id="slider-password_strength"></div>
                <?php
                break;
        }
    }

    static function getVersion() {
        $v = getOption('libauth_version');
        if (empty($v)) {
            return self::$preferred_version;
        } else {
            return $v;
        }
    }

    /**
     * Returns the hash of the zenphoto password
     *
     * @param string $user
     * @param string $pass
     * @return string
     */
    static function passwordHash($user, $pass, $hash_type = NULL) {
        if (is_null($hash_type)) {
            $hash_type = getOption('strong_hash');
        }
        switch ($hash_type) {
            case 1:
                $hash = sha1($user . $pass . HASH_SEED);
                break;
            case 2:
                //  deprecated beause of possible "+" in the text
                $hash = base64_encode(self::pbkdf2($pass, $user . HASH_SEED));
                break;
            case 3:
                $hash = str_replace('+', '-', base64_encode(self::pbkdf2($pass, $user . HASH_SEED)));
                break;
            default:
                $hash = md5($user . $pass . HASH_SEED);
                break;
        }
        if (DEBUG_LOGIN) {
            debugLog("passwordHash($user, $pass, $hash_type)[ " . HASH_SEED . " ]:$hash");
        }
        return $hash;
    }

    /**
     * Returns an array of admin users, indexed by the userid and ordered by "privileges"
     *
     * The array contains the id, hashed password, user's name, email, and admin privileges
     *
     * @param string $what: 'all' for everything, 'users' for just users 'groups' for groups and templates
     * @return array
     */
    function getAdministrators($what = 'users') {
        switch ($what) {
            case 'users':
                return $this->admin_users;
            case 'groups':
                return $this->admin_groups;
            case 'allusers':
                return array_merge($this->admin_users, $this->admin_other);
            default:
                return $this->admin_all;
        }
    }

    /**
     * Returns an admin object from the $pat:$criteria
     * @param array $criteria [ match => criteria ]
     * @return Zenphoto_Administrator
     */
    static function getAnAdmin($criteria) {
        $selector = array();
        foreach ($criteria as $match => $value) {
            if (is_numeric($value)) {
                $selector[] = $match . $value;
            } else {
                $selector[] = $match . db_quote($value);
            }
        }
        $sql = 'SELECT * FROM ' . prefix('administrators') . ' WHERE ' . implode(' AND ', $selector) . ' LIMIT 1';
        $admin = query_single_row($sql, false);
        if ($admin) {
            return self::newAdministrator($admin['user'], $admin['valid']);
        } else {
            return NULL;
        }
    }

    /**
     * Retuns the administration rights of a saved authorization code
     * Will promote an admin to ADMIN_RIGHTS if he is the most privileged admin
     *
     * @param string $authCode the hash code to check
     * @param int $id whom we think this is
     *
     * @return bit
     */
    function checkAuthorization($authCode, $id) {
        global $_zp_current_admin_obj;
        if (DEBUG_LOGIN) {
            debugLogBacktrace("checkAuthorization($authCode, $id)");
        }


        $admins = $this->getAdministrators();
        if (count($admins) == 0) {
            if (DEBUG_LOGIN) {
                debugLog("checkAuthorization: no admins");
            }
            $_zp_current_admin_obj = new Zenphoto_Administrator('', 1);
            $_zp_current_admin_obj->set('id', 0);
            $_zp_current_admin_obj->reset = true;
            return ADMIN_RIGHTS;
        }
        if (is_object($_zp_current_admin_obj) && $_zp_current_admin_obj->reset) {
            if (DEBUG_LOGIN) {
                debugLog("checkAuthorization: reset request");
            }
            return $_zp_current_admin_obj->getRights();
        }


        $_zp_current_admin_obj = NULL;
        if (empty($authCode))
            return 0; //  so we don't "match" with an empty password
        if (DEBUG_LOGIN) {
            debugLogVar("checkAuthorization: admins", $admins);
        }
        $rights = 0;
        $criteria = array('`pass`=' => $authCode, '`valid`=' => 1);
        if (!empty($id)) {
            $criteria['`id`='] = $id;
        }
        $user = self::getAnAdmin($criteria);
        if (is_object($user)) {
            $_zp_current_admin_obj = $user;
            $rights = $user->getRights();
            if (DEBUG_LOGIN) {
                debugLog(sprintf('checkAuthorization: from %1$s->%2$X', $authCode, $rights));
            }
            return $rights;
        }
        $_zp_current_admin_obj = NULL;
        if (DEBUG_LOGIN) {
            debugLog("checkAuthorization: no match");
        }
        return 0; // no rights
    }

    /**
     * Checks a logon user/password against admins
     *
     * Returns the user object if there is a match
     *
     * @param string $user
     * @param string $pass
     * @return object
     */
    function checkLogon($user, $pass) {
        $userobj = self::getAnAdmin(array('`user`=' => $user, '`valid`=' => 1));
        if ($userobj) {
            $hash = self::passwordHash($user, $pass, $userobj->get('passhash'));
            if ($hash != $userobj->getPass()) {
                //  maybe not yet updated passhash field
                foreach (self::$hashList as $hashv) {
                    $hash = self::passwordHash($user, $pass, $hashv);
                    if ($hash == $userobj->getPass()) {
                        break;
                    } else {
                        $hash = -1;
                    }
                }
                if ($hash === -1) {
                    $userobj = NULL;
                }
            }
        } else {
            $hash = -1;
        }

        if (DEBUG_LOGIN) {
            if ($userobj) {
                $rights = sprintf('%X', $userobj->getRights());
            } else {
                $rights = false;
            }
            debugLog(sprintf('checkLogon(%1$s, %2$s)->%3$s', $user, $hash, $rights));
        }
        return $userobj;
    }

    /**
     * Returns the email addresses of the Admin with ADMIN_USERS rights
     *
     * @param bit $rights what kind of admins to retrieve
     * @return array
     */
    function getAdminEmail($rights = NULL) {
        if (is_null($rights)) {
            $rights = ADMIN_RIGHTS;
        }
        $emails = array();
        $admins = $this->getAdministrators();
        foreach ($admins as $user) {
            if (($user['rights'] & $rights) && isValidEmail($user['email'])) {
                $name = $user['name'];
                if (empty($name)) {
                    $name = $user['user'];
                }
                $emails[$name] = $user['email'];
            }
        }
        return $emails;
    }

    /**
     * Migrates credentials
     *
     * @param int $oldversion
     */
    function migrateAuth($to) {
        if ($to > self::$supports_version || $to < self::$preferred_version - 1) {
            trigger_error(sprintf(gettext('Cannot migrate rights to version %1$s (Zenphoto_Authority supports only %2$s and %3$s.)'), $to, self::$supports_version, self::$preferred_version), E_USER_NOTICE);
            return false;
        }
        $success = true;
        $oldversion = self::getVersion();
        setOption('libauth_version', $to);
        $this->admin_users = array();
        $sql = "SELECT * FROM " . prefix('administrators') . "ORDER BY `rights` DESC, `id`";
        $admins = query($sql, false);
        if ($admins) { // something to migrate
            $oldrights = array();
            foreach (self::getRights($oldversion) as $key => $right) {
                $oldrights[$key] = $right['value'];
            }
            $currentrights = self::getRights($to);
            while ($user = db_fetch_assoc($admins)) {
                $update = false;
                $rights = $user['rights'];
                $newrights = $currentrights['NO_RIGHTS']['value'];
                foreach ($currentrights as $key => $right) {
                    if ($right['display']) {
                        if (array_key_exists($key, $oldrights) && $rights & $oldrights[$key]) {
                            $newrights = $newrights | $right['value'];
                        }
                    }
                }
                if ($oldversion < 4) {
                    $newrights = $newrights | $currentrights['USER_RIGHTS']['value'];
                }
                if ($to >= 3 && $oldversion < 3) {
                    if ($rights & $oldrights['VIEW_ALL_RIGHTS']) {
                        $updaterights = $currentrights['ALL_ALBUMS_RIGHTS']['value'] | $currentrights['ALL_PAGES_RIGHTS']['value'] |
                                        $currentrights['ALL_NEWS_RIGHTS']['value'] | $currentrights['VIEW_SEARCH_RIGHTS']['value'] |
                                        $currentrights['VIEW_GALLERY_RIGHTS']['value'] | $currentrights['VIEW_FULLIMAGE_RIGHTS']['value'];
                        $newrights = $newrights | $updaterights;
                    }
                }
                if ($oldversion >= 3 && $to < 3) {
                    if ($oldrights['ALL_ALBUMS_RIGHTS'] || $oldrights['ALL_PAGES_RIGHTS'] || $oldrights['ALL_NEWS_RIGHTS']) {
                        $newrights = $newrights | $currentrights['VIEW_ALL_RIGHTS']['value'];
                    }
                }
                if ($oldversion == 1) { // need to migrate zenpage rights
                    if ($rights & $oldrights['ZENPAGE_RIGHTS']) {
                        $newrights = $newrights | $currentrights['ZENPAGE_PAGES_RIGHTS'] | $currentrights['ZENPAGE_NEWS_RIGHTS'] | $currentrights['FILES_RIGHTS'];
                    }
                }
                if ($to >= 3) {
                    if ($newrights & $currentrights['ADMIN_RIGHTS']['value']) {
                        $newrights = $currentrights['ALL_RIGHTS']['value'];
                    } else {
                        if ($newrights & $currentrights['MANAGE_ALL_ALBUM_RIGHTS']['value']) {
                            // these are lock-step linked!
                            $newrights = $newrights | $currentrights['ALBUM_RIGHTS']['value'];
                        }
                        if ($newrights & $currentrights['MANAGE_ALL_NEWS_RIGHTS']['value']) {
                            // these are lock-step linked!
                            $newrights = $newrights | $currentrights['ZENPAGE_NEWS_RIGHTS']['value'];
                        }
                        if ($newrights & $currentrights['MANAGE_ALL_PAGES_RIGHTS']['value']) {
                            // these are lock-step linked!
                            $newrights = $newrights | $currentrights['ZENPAGE_PAGES_RIGHTS']['value'];
                        }
                    }
                }

                $sql = 'UPDATE ' . prefix('administrators') . ' SET `rights`=' . $newrights . ' WHERE `id`=' . $user['id'];
                $success = $success && query($sql);
            } // end loop
            db_free_result($admins);
        }
        return $success;
    }

    /**
     * Updates a field in admin record(s)
     *
     * @param string $update name of the field
     * @param mixed $value what to store
     * @param array $constraints on the update [ field<op>,value ]
     * @return mixed Query result
     */
    static function updateAdminField($update, $value, $constraints) {
        $where = '';
        foreach ($constraints as $field => $clause) {
            if (!empty($where))
                $where .= ' AND ';
            if (is_numeric($clause)) {
                $where .= $field . $clause;
            } else {
                $where .= $field . db_quote($clause);
            }
        }
        if (is_null($value)) {
            $value = 'NULL';
        } else {
            $value = db_quote($value);
        }
        $sql = 'UPDATE ' . prefix('administrators') . ' SET `' . $update . '`=' . $value . ' WHERE ' . $where;
        $result = query($sql);
        return $result;
    }

    /**
     * Instantiates and returns administrator object
     * @param $name
     * @param $valid
     * @return object
     */
    static function newAdministrator($name, $valid = 1) {
        $user = new Zenphoto_Administrator($name, $valid);
        return $user;
    }

    /**
     * Returns an array of the rights definitions for $version (default returns current version rights)
     *
     * @param $version
     */
    static function getRights($version = NULL) {
        if (empty($version)) {
            $v = self::getVersion();
        } else {
            $v = $version;
        }
        switch ($v) {
            case 1:
                $rightsset = array('NO_RIGHTS'                               => array('value' => 2, 'name' => gettext('No rights'), 'set' => '', 'display' => false, 'hint' => ''),
                                'OVERVIEW_RIGHTS'                    => array('value' => 4, 'name' => gettext('Overview'), 'set' => '', 'display' => true, 'hint' => ''),
                                'VIEW_ALL_RIGHTS'                    => array('value' => 8, 'name' => gettext('View all'), 'set' => '', 'display' => true, 'hint' => ''),
                                'UPLOAD_RIGHTS'                      => array('value' => 16, 'name' => gettext('Upload'), 'set' => '', 'display' => true, 'hint' => ''),
                                'POST_COMMENT_RIGHTS'            => array('value' => 32, 'name' => gettext('Post comments'), 'set' => '', 'display' => true, 'hint' => ''),
                                'COMMENT_RIGHTS'                     => array('value' => 64, 'name' => gettext('Comments'), 'set' => '', 'display' => true, 'hint' => ''),
                                'ALBUM_RIGHTS'                       => array('value' => 256, 'name' => gettext('Album'), 'set' => '', 'display' => true, 'hint' => ''),
                                'MANAGE_ALL_ALBUM_RIGHTS'    => array('value' => 512, 'name' => gettext('Manage all albums'), 'set' => '', 'display' => true, 'hint' => ''),
                                'THEMES_RIGHTS'                      => array('value' => 1024, 'name' => gettext('Themes'), 'set' => '', 'display' => true, 'hint' => ''),
                                'ZENPAGE_RIGHTS'                     => array('value' => 2049, 'name' => gettext('Zenpage'), 'set' => '', 'display' => true, 'hint' => ''),
                                'TAGS_RIGHTS'                            => array('value' => 4096, 'name' => gettext('Tags'), 'set' => '', 'display' => true, 'hint' => ''),
                                'OPTIONS_RIGHTS'                     => array('value' => 8192, 'name' => gettext('Options'), 'set' => '', 'display' => true, 'hint' => ''),
                                'ADMIN_RIGHTS'                       => array('value' => 65536, 'name' => gettext('Full admin rights'), 'set' => '', 'display' => true, 'hint' => ''));
                break;
            case 2:
                $rightsset = array('NO_RIGHTS'                               => array('value' => 1, 'name' => gettext('No rights'), 'set' => '', 'display' => false, 'hint' => ''),
                                'OVERVIEW_RIGHTS'                    => array('value' => pow(2, 2), 'name' => gettext('Overview'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may view the admin overview page.')),
                                'VIEW_ALL_RIGHTS'                    => array('value' => pow(2, 4), 'name' => gettext('View all'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may view all of the gallery regardless of protection of the page. Without this right, the user can view only public ones and those checked in his managed object lists or as granted by View Search or View Gallery.')),
                                'UPLOAD_RIGHTS'                      => array('value' => pow(2, 6), 'name' => gettext('Upload'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may upload to the albums for which they have management rights.')),
                                'POST_COMMENT_RIGHTS'            => array('value' => pow(2, 8), 'name' => gettext('Post comments'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('When the comment_form plugin is used for comments and its "Only members can comment" option is set, only users with this right may post comments.')),
                                'COMMENT_RIGHTS'                     => array('value' => pow(2, 10), 'name' => gettext('Comments'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may make comments tab changes.')),
                                'ALBUM_RIGHTS'                       => array('value' => pow(2, 12), 'name' => gettext('Albums'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users with this right may access the “albums” tab to make changes.')),
                                'ZENPAGE_PAGES_RIGHTS'       => array('value' => pow(2, 14), 'name' => gettext('Pages'), 'set' => gettext('Pages'), 'display' => true, 'hint' => gettext('Users with this right may edit and manage Zenpage pages.')),
                                'ZENPAGE_NEWS_RIGHTS'            => array('value' => pow(2, 16), 'name' => gettext('News'), 'set' => gettext('News'), 'display' => true, 'hint' => gettext('Users with this right may edit and manage Zenpage articles and categories.')),
                                'FILES_RIGHTS'                       => array('value' => pow(2, 18), 'name' => gettext('Files'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Allows the user access to the “filemanager” located on the upload: files sub-tab.')),
                                'MANAGE_ALL_PAGES_RIGHTS'    => array('value' => pow(2, 20), 'name' => gettext('Manage all pages'), 'set' => gettext('Pages'), 'display' => true, 'hint' => gettext('Users who do not have “Admin” rights normally are restricted to manage only objects to which they have been assigned. This right allows them to manage any Zenpage page.')),
                                'MANAGE_ALL_NEWS_RIGHTS'     => array('value' => pow(2, 22), 'name' => gettext('Manage all news'), 'set' => gettext('News'), 'display' => true, 'hint' => gettext('Users who do not have “Admin” rights normally are restricted to manage only objects to which they have been assigned. This right allows them to manage any Zenpage news article or category.')),
                                'MANAGE_ALL_ALBUM_RIGHTS'    => array('value' => pow(2, 24), 'name' => gettext('Manage all albums'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users who do not have “Admin” rights normally are restricted to manage only objects to which they have been assigned. This right allows them to manage any album in the gallery.')),
                                'THEMES_RIGHTS'                      => array('value' => pow(2, 26), 'name' => gettext('Themes'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may make themes related changes. These are limited to the themes associated with albums checked in their managed albums list.')),
                                'TAGS_RIGHTS'                            => array('value' => pow(2, 28), 'name' => gettext('Tags'), 'set' => gettext('General'), 'display' => true, 'hint' => gettext('Users with this right may make additions and changes to the set of tags.')),
                                'OPTIONS_RIGHTS'                     => array('value' => pow(2, 29), 'name' => gettext('Options'), 'set' => gettext('General'), 'display' => true, 'hint' => gettext('Users with this right may make changes on the options tabs.')),
                                'ADMIN_RIGHTS'                       => array('value' => pow(2, 30), 'name' => gettext('Full admin rights'), 'set' => gettext('General'), 'display' => true, 'hint' => gettext('The master privilege. A user with "Admin" can do anything. (No matter what his other rights might indicate!)')));
                break;
            case 3:
                $rightsset = array('NO_RIGHTS'                               => array('value' => 1, 'name' => gettext('No rights'), 'set' => '', 'display' => false, 'hint' => ''),
                                'OVERVIEW_RIGHTS'                    => array('value' => pow(2, 2), 'name' => gettext('Overview'), 'set' => gettext('General'), 'display' => true, 'hint' => gettext('Users with this right may view the admin overview page.')),
                                'VIEW_GALLERY_RIGHTS'            => array('value' => pow(2, 4), 'name' => gettext('View gallery'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may view otherwise protected generic gallery pages.')),
                                'VIEW_SEARCH_RIGHTS'             => array('value' => pow(2, 5), 'name' => gettext('View search'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may view search pages even if password protected.')),
                                'VIEW_FULLIMAGE_RIGHTS'      => array('value' => pow(2, 6), 'name' => gettext('View fullimage'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users with this right may view all full sized (raw) images.')),
                                'ALL_NEWS_RIGHTS'                    => array('value' => pow(2, 7), 'name' => gettext('Access all'), 'set' => gettext('News'), 'display' => true, 'hint' => gettext('Users with this right have access to all zenpage news articles.')),
                                'ALL_PAGES_RIGHTS'               => array('value' => pow(2, 8), 'name' => gettext('Access all'), 'set' => gettext('Pages'), 'display' => true, 'hint' => gettext('Users with this right have access to all zenpage pages.')),
                                'ALL_ALBUMS_RIGHTS'              => array('value' => pow(2, 9), 'name' => gettext('Access all'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users with this right have access to all albums.')),
                                'VIEW_UNPUBLISHED_RIGHTS'    => array('value' => pow(2, 10), 'name' => gettext('View unpublished'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users with this right will see all unpublished items.')),
                                'POST_COMMENT_RIGHTS'            => array('value' => pow(2, 11), 'name' => gettext('Post comments'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('When the comment_form plugin is used for comments and its "Only members can comment" option is set, only users with this right may post comments.')),
                                'COMMENT_RIGHTS'                     => array('value' => pow(2, 12), 'name' => gettext('Comments'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may make comments tab changes.')),
                                'UPLOAD_RIGHTS'                      => array('value' => pow(2, 13), 'name' => gettext('Upload'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users with this right may upload to the albums for which they have management rights.')),
                                'ZENPAGE_NEWS_RIGHTS'            => array('value' => pow(2, 15), 'name' => gettext('News'), 'set' => gettext('News'), 'display' => false, 'hint' => gettext('Users with this right may edit and manage Zenpage articles and categories.')),
                                'ZENPAGE_PAGES_RIGHTS'       => array('value' => pow(2, 16), 'name' => gettext('Pages'), 'set' => gettext('Pages'), 'display' => false, 'hint' => gettext('Users with this right may edit and manage Zenpage pages.')),
                                'FILES_RIGHTS'                       => array('value' => pow(2, 17), 'name' => gettext('Files'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Allows the user access to the “filemanager” located on the upload: files sub-tab.')),
                                'ALBUM_RIGHTS'                       => array('value' => pow(2, 18), 'name' => gettext('Albums'), 'set' => gettext('Albums'), 'display' => false, 'hint' => gettext('Users with this right may access the “albums” tab to make changes.')),
                                'MANAGE_ALL_NEWS_RIGHTS'     => array('value' => pow(2, 21), 'name' => gettext('Manage all'), 'set' => gettext('News'), 'display' => true, 'hint' => gettext('Users who do not have “Admin” rights normally are restricted to manage only objects to which they have been assigned. This right allows them to manage any Zenpage news article or category.')),
                                'MANAGE_ALL_PAGES_RIGHTS'    => array('value' => pow(2, 22), 'name' => gettext('Manage all'), 'set' => gettext('Pages'), 'display' => true, 'hint' => gettext('Users who do not have “Admin” rights normally are restricted to manage only objects to which they have been assigned. This right allows them to manage any Zenpage page.')),
                                'MANAGE_ALL_ALBUM_RIGHTS'    => array('value' => pow(2, 23), 'name' => gettext('Manage all'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users who do not have “Admin” rights normally are restricted to manage only objects to which they have been assigned. This right allows them to manage any album in the gallery.')),
                                'THEMES_RIGHTS'                      => array('value' => pow(2, 26), 'name' => gettext('Themes'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may make themes related changes. These are limited to the themes associated with albums checked in their managed albums list.')),
                                'TAGS_RIGHTS'                            => array('value' => pow(2, 28), 'name' => gettext('Tags'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may make additions and changes to the set of tags.')),
                                'OPTIONS_RIGHTS'                     => array('value' => pow(2, 29), 'name' => gettext('Options'), 'set' => gettext('General'), 'display' => true, 'hint' => gettext('Users with this right may make changes on the options tabs.')),
                                'ADMIN_RIGHTS'                       => array('value' => pow(2, 30), 'name' => gettext('Full admin rights'), 'set' => gettext('General'), 'display' => true, 'hint' => gettext('The master privilege. A user with "Admin" can do anything. (No matter what his other rights might indicate!)')));
                break;
            case 4:
                $rightsset = array('NO_RIGHTS'                               => array('value' => 1, 'name' => gettext('No rights'), 'set' => '', 'display' => false, 'hint' => ''),
                                'OVERVIEW_RIGHTS'                    => array('value' => pow(2, 2), 'name' => gettext('Overview'), 'set' => gettext('General'), 'display' => true, 'hint' => gettext('Users with this right may view the admin overview page.')),
                                'USER_RIGHTS'                            => array('value' => pow(2, 3), 'name' => gettext('User'), 'set' => gettext('General'), 'display' => true, 'hint' => gettext('Users must have this right to change their credentials.')),
                                'VIEW_GALLERY_RIGHTS'            => array('value' => pow(2, 5), 'name' => gettext('View gallery'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may view otherwise protected generic gallery pages.')),
                                'VIEW_SEARCH_RIGHTS'             => array('value' => pow(2, 6), 'name' => gettext('View search'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may view search pages even if password protected.')),
                                'VIEW_FULLIMAGE_RIGHTS'      => array('value' => pow(2, 7), 'name' => gettext('View fullimage'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users with this right may view all full sized (raw) images.')),
                                'ALL_NEWS_RIGHTS'                    => array('value' => pow(2, 8), 'name' => gettext('Access all'), 'set' => gettext('News'), 'display' => true, 'hint' => gettext('Users with this right have access to all zenpage news articles.')),
                                'ALL_PAGES_RIGHTS'               => array('value' => pow(2, 9), 'name' => gettext('Access all'), 'set' => gettext('Pages'), 'display' => true, 'hint' => gettext('Users with this right have access to all zenpage pages.')),
                                'ALL_ALBUMS_RIGHTS'              => array('value' => pow(2, 10), 'name' => gettext('Access all'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users with this right have access to all albums.')),
                                'VIEW_UNPUBLISHED_RIGHTS'    => array('value' => pow(2, 11), 'name' => gettext('View unpublished'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users with this right will see all unpublished items.')),
                                'POST_COMMENT_RIGHTS'            => array('value' => pow(2, 13), 'name' => gettext('Post comments'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('When the comment_form plugin is used for comments and its "Only members can comment" option is set, only users with this right may post comments.')),
                                'COMMENT_RIGHTS'                     => array('value' => pow(2, 14), 'name' => gettext('Comments'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may make comments tab changes.')),
                                'UPLOAD_RIGHTS'                      => array('value' => pow(2, 15), 'name' => gettext('Upload'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users with this right may upload to the albums for which they have management rights.')),
                                'ZENPAGE_NEWS_RIGHTS'            => array('value' => pow(2, 17), 'name' => gettext('News'), 'set' => gettext('News'), 'display' => false, 'hint' => gettext('Users with this right may edit and manage Zenpage articles and categories.')),
                                'ZENPAGE_PAGES_RIGHTS'       => array('value' => pow(2, 18), 'name' => gettext('Pages'), 'set' => gettext('Pages'), 'display' => false, 'hint' => gettext('Users with this right may edit and manage Zenpage pages.')),
                                'FILES_RIGHTS'                       => array('value' => pow(2, 19), 'name' => gettext('Files'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Allows the user access to the “filemanager” located on the upload: files sub-tab.')),
                                'ALBUM_RIGHTS'                       => array('value' => pow(2, 20), 'name' => gettext('Albums'), 'set' => gettext('Albums'), 'display' => false, 'hint' => gettext('Users with this right may access the “albums” tab to make changes.')),
                                'MANAGE_ALL_NEWS_RIGHTS'     => array('value' => pow(2, 21), 'name' => gettext('Manage all'), 'set' => gettext('News'), 'display' => true, 'hint' => gettext('Users who do not have “Admin” rights normally are restricted to manage only objects to which they have been assigned. This right allows them to manage any Zenpage news article or category.')),
                                'MANAGE_ALL_PAGES_RIGHTS'    => array('value' => pow(2, 22), 'name' => gettext('Manage all'), 'set' => gettext('Pages'), 'display' => true, 'hint' => gettext('Users who do not have “Admin” rights normally are restricted to manage only objects to which they have been assigned. This right allows them to manage any Zenpage page.')),
                                'MANAGE_ALL_ALBUM_RIGHTS'    => array('value' => pow(2, 23), 'name' => gettext('Manage all'), 'set' => gettext('Albums'), 'display' => true, 'hint' => gettext('Users who do not have “Admin” rights normally are restricted to manage only objects to which they have been assigned. This right allows them to manage any album in the gallery.')),
                                'CODEBLOCK_RIGHTS'               => array('value' => pow(2, 25), 'name' => gettext('Codeblock'), 'set' => gettext('General'), 'display' => true, 'hint' => gettext('Users with this right may edit Codeblocks.')),
                                'THEMES_RIGHTS'                      => array('value' => pow(2, 26), 'name' => gettext('Themes'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may make themes related changes. These are limited to the themes associated with albums checked in their managed albums list.')),
                                'TAGS_RIGHTS'                            => array('value' => pow(2, 28), 'name' => gettext('Tags'), 'set' => gettext('Gallery'), 'display' => true, 'hint' => gettext('Users with this right may make additions and changes to the set of tags.')),
                                'OPTIONS_RIGHTS'                     => array('value' => pow(2, 29), 'name' => gettext('Options'), 'set' => gettext('General'), 'display' => true, 'hint' => gettext('Users with this right may make changes on the options tabs.')),
                                'ADMIN_RIGHTS'                       => array('value' => pow(2, 30), 'name' => gettext('Full admin rights'), 'set' => gettext('General'), 'display' => true, 'hint' => gettext('The master privilege. A user with "Admin" can do anything. (No matter what his other rights might indicate!)')));
                break;
        }
        
        $allrights = 0;
        foreach ($rightsset as $key => $right) {
            $allrights = $allrights | $right['value'];
        }
        $rightsset['ALL_RIGHTS'] = array('value' => $allrights, 'name' => gettext('All rights'), 'display' => false);
        $rightsset['DEFAULT_RIGHTS'] = array('value' => $rightsset['OVERVIEW_RIGHTS']['value'] + $rightsset['POST_COMMENT_RIGHTS']['value'], 'name' => gettext('Default rights'), 'display' => false);
        if (isset($rightsset['VIEW_ALL_RIGHTS']['value'])) {        
            $rightsset['DEFAULT_RIGHTS']['value'] = $rightsset['DEFAULT_RIGHTS']['value'] | $rightsset['VIEW_ALL_RIGHTS']['value'];
        } else {
            $rightsset['DEFAULT_RIGHTS']['value'] = $rightsset['DEFAULT_RIGHTS']['value'] | $rightsset['ALL_ALBUMS_RIGHTS']['value'] |
                            $rightsset['ALL_PAGES_RIGHTS']['value'] | $rightsset['ALL_NEWS_RIGHTS']['value'] |
                            $rightsset['VIEW_SEARCH_RIGHTS']['value'] | $rightsset['VIEW_GALLERY_RIGHTS']['value'];
        }
        
        $rightsset = sortMultiArray($rightsset, 'value', true, false, false);
        return $rightsset;
    }

    static function getResetTicket($user, $pass) {
        $req = time();
        $ref = sha1($req . $user . $pass);
        $time = bin2hex(rc4('ticket' . HASH_SEED, $req));
        return $time . $ref;
    }

    function validateTicket($ticket, $user) {
        global $_zp_current_admin_obj;
        $admins = $this->getAdministrators();
        foreach ($admins as $tuser) {
            if ($tuser['user'] == $user) {
                if ($tuser['rights'] & USER_RIGHTS) {
                    $request_date = rc4('ticket' . HASH_SEED, pack("H*", $time = substr($ticket, 0, 20)));
                    $ticket = substr($ticket, 20);
                    $ref = sha1($request_date . $user . $tuser['pass']);
                    if ($ref === $ticket) {
                        if (time() <= ($request_date + (3 * 24 * 60 * 60))) {
                            // limited time offer
                            $_zp_current_admin_obj = new Zenphoto_Administrator($user, 1);
                            $_zp_current_admin_obj->reset = true;
                        }
                    }
                    break;
                }
            }
        }
    }

    /**
     * Set log-in cookie for a user
     * @param object $user
     */
    static function logUser($user) {
        $user->set('lastloggedin', $user->get('loggedin'));
        $user->set('loggedin', date('Y-m-d H:i:s'));
        $user->save();
        zp_setCookie('zpcms_auth_user', $user->getPass() . '.' . $user->getID(), NULL, NULL, secureServer(), true);
    }

    /**
     * User authentication support
     */
    function handleLogon() {
        global $_zp_current_admin_obj, $_zp_login_error, $_zp_captcha, $_zp_loggedin;
        if (isset($_POST['login'])) {
            $post_user = sanitize(@$_POST['user']);
            $post_pass = sanitize(@$_POST['pass'], 0);
            $_zp_loggedin = false;

            switch (@$_POST['password']) {
                default:
                    $user = self::checkLogon($post_user, $post_pass);
                    if ($user) {
                        $_zp_loggedin = $user->getRights();
                    }
                    $_zp_loggedin = zp_apply_filter('admin_login_attempt', $_zp_loggedin, $post_user, $post_pass);
                    if ($_zp_loggedin) {
                        self::logUser($user);
                        $_zp_current_admin_obj = $user;
                    } else {
                        zp_clearCookie('zpcms_auth_user', null, secureServer(), true ); // Clear the cookie, just in case
                        $_zp_login_error = 1;
                    }
                    break;
                case 'challenge':
                    $user = self::getAnAdmin(array('`user`=' => $post_user, '`valid`=' => 1));
                    if (is_object($user)) {
                        $info = $user->getChallengePhraseInfo();
                        if ($post_pass && $info['response'] == $post_pass) {
                            $ref = self::getResetTicket($post_user, $user->getPass());
                            redirectURL(FULLWEBPATH . '/' . ZENFOLDER . '/admin-users.php?ticket=' . $ref . '&user=' . $post_user);
                        }
                    }
                    if ( !empty($info['challenge']) && !empty($_POST['pass'])) { $_zp_login_error = gettext('Sorry, that is not the answer.'); }
                    $_REQUEST['logon_step'] = 'challenge';
                    break;
                case 'captcha':
                    if ($_zp_captcha->checkCaptcha(trim(@$_POST['code']), sanitize(@$_POST['code_h'], 3))) {
                        require_once(dirname(__FILE__) . '/load_objectClasses.php'); // be sure that the plugins are loaded for the mail handler
                        if (empty($post_user)) {
                            $requestor = gettext('You are receiving this e-mail because of a password reset request on your Zenphoto gallery.');
                        } else {
                            $requestor = sprintf(gettext("You are receiving this e-mail because of a password reset request on your Zenphoto gallery from a user who tried to log in as %s."), $post_user);
                        }
                        $admins = $this->getAdministrators();
                        $mails = array();
                        $user = NULL;
                        foreach ($admins as $key => $tuser) {
                            if (!empty($tuser['email'])) {
                                if (!empty($post_user) && ($tuser['user'] == $post_user || $tuser['email'] == $post_user)) {
                                    $name = $tuser['name'];
                                    if (empty($name)) {
                                        $name = $tuser['user'];
                                    }
                                    $mails[$name] = $tuser['email'];
                                    $user = $tuser;
                                    unset($admins[$key]); // drop him from alternate list.
                                } else {
                                    if (!($tuser['rights'] & ADMIN_RIGHTS)) {
                                        unset($admins[$key]); // eliminate any peons from the list
                                    }
                                }
                            } else {
                                unset($admins[$key]); // we want to ignore groups and users with no email address here!
                            }
                        }

                        $cclist = array();
                        foreach ($admins as $tuser) {
                            $name = $tuser['name'];
                            if (empty($name)) {
                                $name = $tuser['user'];
                            }
                            if (is_null($user)) {
                                $user = $tuser;
                                $mails[$name] = $tuser['email'];
                            } else {
                                $cclist[$name] = $tuser['email'];
                            }
                        }
                        if (is_null($user)) {
                            $_zp_login_error = gettext('There was no one to which to send the reset request.');
                        } else {
                            $ref = self::getResetTicket($user['user'], $user['pass']);
                            $msg = "\n" . $requestor .
                                            "\n" . sprintf(gettext("To reset your Zenphoto Admin passwords visit: %s"), FULLWEBPATH . "/" . ZENFOLDER . "/admin-users.php?ticket=$ref&user=" . $user['user']) .
                                            "\n" . gettext("If you do not wish to reset your passwords just ignore this message. This ticket will automatically expire in 3 days.");
                            $err_msg = zp_mail(gettext("The Zenphoto information you requested"), $msg, $mails, $cclist);
                            if (empty($err_msg)) {
                                $_zp_login_error = 2;
                            } else {
                                $_zp_login_error = $err_msg;
                            }
                        }
                    } else {
                        $_zp_login_error = gettext('Your input did not match the captcha');
                        $_REQUEST['logon_step'] = 'captcha';
                    }
                    break;
            }
        }
        return $_zp_loggedin;
    }

    /**
     *
     * returns an array of the active "password" cookies
     *
     * NOTE: this presumes the general form of an authrization cookie is:
     * zp_xxxxx_auth{_dddd) where xxxxx is the authority (e.g. gallery, image, search, ...)
     * and dddd if present is the object id.
     *
     */
    static function getAuthCookies() {
        $candidates = array();
        if (isset($_COOKIE)) {
            $candidates = $_COOKIE;
        }
        if (isset($_SESSION)) {
            $candidates = array_merge($candidates, $_SESSION);
        }
        foreach ($candidates as $key => $candidate) {
            if (strpos($key, '_auth') === false) {
                unset($candidates[$key]);
            }
        }
        return $candidates;
    }

    /**
     * Cleans up on logout
     *
     */
    static function handleLogout() {
        global $_zp_loggedin, $_zp_pre_authorization, $_zp_current_admin_obj;
        foreach (self::getAuthCookies() as $cookie => $value) {
            zp_clearCookie($cookie, null, secureServer(), true);
        }
        $_zp_loggedin = false;
        $_zp_pre_authorization = array();
        zp_session_destroy();
        header('Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"');
        return zp_apply_filter('zp_logout', NULL, $_zp_current_admin_obj);
    }

    /**
     * Checks saved cookies to see if a user is logged in
     */
    function checkCookieCredentials() {
        list($auth, $id) = explode('.', zp_getCookie('zpcms_auth_user') . '.');
        $loggedin = $this->checkAuthorization($auth, $id);
        $loggedin = zp_apply_filter('authorization_cookie', $loggedin, $auth, $id);
        if ($loggedin) {
            return $loggedin;
        } else {
            zp_clearCookie('zpcms_auth_user', null, secureServer(), true);
            return NULL;
        }
    }

    /**
     * Print the login form for ZP. This will take into account whether mod_rewrite is enabled or not.
     *
     * @param string $redirect URL to return to after login
     * @param bool $logo set to true to display the ADMIN zenphoto logo.
     * @param bool $showUserField set to true to display the user input
     * @param bool $showCaptcha set to false to not display the forgot password captcha.
     * @param string $hint optional hint for the password
     *
     */
    function printLoginForm($redirect = null, $logo = true, $showUserField = true, $showCaptcha = true, $hint = '') {
        global $_zp_login_error, $_zp_captcha, $_zp_gallery;
        if (is_null($redirect)) {
            $redirect = getRequestURI();
        }
        $redirect = sanitizeRedirect($redirect);
        if (isset($_POST['user'])) {
            $requestor = sanitize($_POST['user'], 3);
        } else {
            $requestor = '';
        }
        if (empty($requestor)) {
            if (isset($_GET['ref'])) {
                $requestor = sanitize($_GET['ref']);
            }
        }
        $alt_handlers = zp_apply_filter('alt_login_handler', array());
        $star = false;
        $mails = array();
        $info = array('challenge' => '', 'response' => '');
        $username_is_valid = false;
        if (!empty($requestor)) {
            $admin = self::getAnAdmin(array('`user`=' => $requestor, '`valid`=' => 1));
            if (is_object($admin)) {
                if ($admin->getEmail()) {
                    $star = $showCaptcha;
                }
                $info = $admin->getChallengePhraseInfo();
                $username_is_valid = true;
            }
        }
        if (!$star) {
            $admins = $this->getAdministrators();
            while (count($admins) > 0) {
                $user = array_shift($admins);
                if ($user['email']) {
                    $star = $showCaptcha;
                }
            }
        }
        $whichForm = sanitize(@$_REQUEST['logon_step']);
        ?>
        <div id="loginform">
            <?php
            if ($logo) {
                ?>
                <p>
                    <img src="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/images/zen-logo.png" title="ZenPhoto" alt="ZenPhoto" />
                </p>
                <?php
            }
            switch ($_zp_login_error) {
                case 1:
                    ?>
                    <div class="errorbox" id="message"><h2><?php echo gettext("There was an error logging in."); ?></h2>
                        <?php
                        if ($showUserField) {
                            echo gettext("Check your username and password and try again.");
                        } else {
                            echo gettext("Check password and try again.");
                        }
                        ?>
                    </div>
                    <?php
                    break;
                case 2:
                    ?>
                    <div class="messagebox fade-message">
                        <h2><?php echo gettext("A reset request has been sent."); ?></h2>
                    </div>
                    <?php
                    break;
                default:
                    if (!empty($_zp_login_error)) {
                        ?>
                        <div class="errorbox fade-message">
                            <h2><?php echo $_zp_login_error; ?></h2>
                        </div>
                        <?php
                    }
                    break;
            }
            switch ($whichForm) {
                case 'challenge':
                    ?>
                    <form name="login" action="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/admin.php" method="post">
                        <fieldset id="logon_box">
                            <input type="hidden" name="login" value="1" />
                            <input type="hidden" name="password" value="challenge" />
                            <input type="hidden" name="redirect" value="<?php echo html_encode(pathurlencode($redirect)); ?>" />
                            <fieldset>
                                <legend><?php echo gettext('User') ?></legend>
                                <input class="textfield" name="user" id="user" type="text" size="35" value="<?php echo html_encode($requestor); ?>" />
                            </fieldset>
                            <?php
                            if ($requestor && $admin) {
                            if (!empty($info['challenge'])) {
                                ?>
                                <p class="logon_form_text"><?php echo gettext('Supply the correct response to the question below and you will be directed to a page where you can change your password.'); ?>
                                <?php if ( $admin->getEmail() ) { echo gettext('<br />You may also use the link below to request a reset by e-mail.'); } ?>
                                </p>
                                <fieldset><legend><?php echo gettext('Challenge question:') ?></legend>
                                    <?php
                                    echo html_encode($info['challenge']);
                                    ?>
                                </fieldset>
                                <fieldset><legend><?php echo gettext('Your response') ?></legend>
                                    <input class="textfield" name="pass" id="pass" type="text" size="35" />
                                </fieldset>
                                <br />
                                <?php } else {
                                        if ( $username_is_valid && !$admin->getEmail() ) { ?>
                                            <fieldset><p class="logon_form_text errorbox"><?php echo gettext('A password reset is not possible.'); ?></p></fieldset>
                                    <?php } else { ?>
                                            <p class="logon_form_text"><?php echo gettext('Please request a reset by e-mail by clicking the link below.'); ?></p>
                                <?php
                                    }
                                }
                            } else {
                                ?>
                                <p class="logon_form_text">
                                    <?php
                                    echo gettext('Enter your User ID and press <code>Refresh</code> to get your challenge question and/or get a link to request a reset by e-mail.');
                                    ?>
                                </p>
                                <?php
                            }
                            ?>
                            <div class="buttons">
                                <button type="submit" value="<?php echo gettext("Submit"); ?>"<?php if (!$info['challenge']) echo ' disabled="disabled"'; ?> >
                                    <img src="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/images/pass.png" alt="" /><?php echo gettext("Submit"); ?>
                                </button>
                                <a id="logonstep_challenge_js" class="button" title="<?php echo gettext("Refresh"); ?>" href="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/admin.php?logon_step=challenge&amp;ref=">
                                    <img src="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/images/refresh.png" alt="" /><?php echo gettext("Refresh"); ?>
                                </a>
                                <a id="logonstep_return_js" class="button" title="<?php echo gettext("Return"); ?>" href="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/admin.php?logon_step=&amp;ref=">
                                    <img src="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/images/refresh.png" alt="" /><?php echo gettext("Return"); ?>
                                </a>
                            </div>
                            <br class="clearall" />
                        </fieldset>
                        <br />
                        <?php
                        if ( $star && (!empty($requestor) && $username_is_valid && $admin->getEmail()) ) {
                            ?>
                            <p class="logon_link">
                                <a id="logonstep_captcha_js" class="button" href="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/admin.php?logon_step=captcha&amp;ref=">
                                    <?php echo gettext('Request reset by e-mail'); ?>
                                </a>
                            </p>
                            <?php
                        }
                        ?>
                    </form>
                    <?php
                    break;
                case 'captcha':
                    $captcha = $_zp_captcha->getCaptcha(NULL);
                    ?>
                    <form name="login" action="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/admin.php" method="post">
                        <?php if (isset($captcha['hidden'])) echo $captcha['hidden']; ?>
                        <input type="hidden" name="login" value="1" />
                        <input type="hidden" name="password" value="captcha" />
                        <input type="hidden" name="redirect" value="<?php echo html_encode(pathurlencode($redirect)); ?>" />
                        <fieldset id="logon_box">
                            <fieldset><legend><?php echo gettext('User'); ?></legend>
                                <input class="textfield" name="user" id="user" type="text" value="<?php echo html_encode($requestor); ?>" />
                            </fieldset>
                            <?php if (isset($captcha['html'])) echo $captcha['html']; ?>
                            <?php
                            if (isset($captcha['input'])) {
                                ?>
                                <fieldset><legend><?php echo gettext("Enter CAPTCHA"); ?></legend>
                                    <?php echo $captcha['input']; ?>
                                </fieldset>
                                <?php
                            }
                            ?>
                            <br />
                            <div class="buttons">
                                <button type="submit" value="<?php echo gettext("Request"); ?>" ><img src="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/images/pass.png" alt="" />
                                    <?php echo gettext("Request password reset"); ?>
                                </button>
                                <a id="logonstep_return_js" class="button" title="<?php echo gettext("Return"); ?>" href="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/admin.php?logon_step=&amp;ref=">
                                    <img src="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/images/refresh.png" alt="" /><?php echo gettext("Return"); ?>
                                </a>
                            </div>
                            <br class="clearall" />
                        </fieldset>
                    </form>
                    <?php
                    break;
                default:
                    if (empty($alt_handlers)) {
                        $legend = gettext('Login');
                    } else {
                        ?>
                        <script type="text/javascript">
                            // <!-- <![CDATA[
                            var handlers = [];
                    <?php
                    $list = '<select id="logon_choices" onchange="changeHandler(handlers[$(this).val()]);">' .
                                    '<option value="0">' . html_encode(get_language_string($_zp_gallery->getTitle())) . '</option>';
                    $c = 0;
                    foreach ($alt_handlers as $handler => $details) {
                        $c++;
                        $details['params'][] = 'redirect=' . $redirect;
                        if (!empty($requestor)) {
                            $details['params'][] = 'requestor=' . $requestor;
                        }
                        echo "handlers[" . $c . "]=['" . $details['script'] . "','" . implode("','", $details['params']) . "'];";

                        $list .= '<option value="' . $c . '">' . $handler . '</option>';
                    }
                    $list .= '</select>';
                    $legend = sprintf(gettext('Logon using:%s'), $list);
                    ?>
                            function changeHandler(handler) {
                                handler.push('user=' + $('#user').val());
                                var script = handler.shift();
                                window.location = script+'?'+handler.join('&');
                            }
                            // ]]> -->
                        </script>
                        <?php
                    }
                    $redirect = zp_apply_filter('login_redirect_link', $redirect);
                    ?>
                    <form name="login" action="<?php echo html_encode(pathurlencode($redirect)); ?>" method="post">
                        <input type="hidden" name="login" value="1" />
                        <input type="hidden" name="password" value="1" />
                        <input type="hidden" name="redirect" value="<?php echo html_encode(pathurlencode($redirect)); ?>" />
                        <fieldset id="logon_box"><legend><?php echo $legend; ?></legend>
                            <?php
                            if ($showUserField) { //    requires a "user" field
                                ?>
                                <fieldset><legend><?php echo gettext("User"); ?></legend>
                                    <input class="textfield" name="user" id="user" type="text" size="35" value="<?php echo html_encode($requestor); ?>" />
                                </fieldset>
                                <?php
                            }
                            ?>
                            <fieldset><legend><?php echo gettext("Password"); ?></legend>
                                <input class="textfield" name="pass" id="pass" type="password" size="35" /><br />
                                <label><input type="checkbox" name="disclose_password" id="disclose_password" onclick="togglePassword('');" /><?php echo gettext('Show password') ?></label>
                            </fieldset>
                            <br />
                            <div class="buttons">
                                <button type="submit" value="<?php echo gettext("Log in"); ?>" ><img src="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/images/pass.png" alt="" /><?php echo gettext("Log in"); ?></button>
                                <button type="reset" value="<?php echo gettext("Reset"); ?>" ><img src="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/images/reset.png" alt="" /><?php echo gettext("Reset"); ?></button>
                            </div>
                            <br class="clearall" />
                        </fieldset>
                    </form>
                    <?php
                    if ($hint) {
                        echo '<p>' . $hint . '</p>';
                    }
                    if ($showUserField && OFFSET_PATH != 2) {
                        ?>
                        <p class="logon_link">
                            <a id="logonstep_challenge_js" class="button" href="<?php echo WEBPATH . '/' . ZENFOLDER; ?>/admin.php?logon_step=challenge&amp;ref=">
                                <?php echo gettext('I forgot my <strong>User ID</strong>/<strong>Password</strong>'); ?>
                            </a>
                        </p>
                        <?php
                    }
                    break;

            }
            Zenphoto_Authority::printPasswordFormJS()
            ?>
        </div>

        <?php
    }

    /**
     *
     * Javascript for password change input handling
     */
    static function printPasswordFormJS() {
        ?>
        <script type="text/javascript">
            // <!-- <![CDATA[
            function passwordStrength(id) {
                var inputa = '#pass' + id;
                var inputb = '#pass_r' + id;
                var displaym = '#match' + id;
                var displays = '#strength' + id;
                var numeric = 0;
                var special = 0;
                var upper = 0;
                var lower = 0;
                var str = $(inputa).val();
                var len = str.length;
                var strength = 0;
                for (c = 0; c < len; c++) {
                    if (str[c].match(/[0-9]/)) {
                        numeric++;
                    } else if (str[c].match(/[^A-Za-z0-9]/)) {
                        special++;
                    } else if (str[c].toUpperCase() == str[c]) {
                        upper++;
                    } else {
                        lower++;
                    }
                }
                if (upper != len) {
                    upper = upper * 2;
                }
                if (lower == len) {
                    lower = lower * 0.75;
                }
                if (numeric != len) {
                    numeric = numeric * 4;
                }
                if (special != len) {
                    special = special * 5;
                }
                len = Math.max(0, (len - 6) * .35);
                strength = Math.min(30, Math.round(upper + lower + numeric + special + len));
                if (str.length == 0) {
                    $(displays).css('color', 'black');
                    $(displays).html('<?php echo gettext('Password'); ?>');
                    $(inputa).css('background-image', 'none');
                } else {
                    if (strength < 15) {
                        $(displays).css('color', '#ff0000');
                        $(displays).html('<?php echo gettext('password strength weak'); ?>');
                    } else if (strength < 25) {
                        $(displays).css('color', '#ff0000');
                        $(displays).html('<?php echo gettext('password strength good'); ?>');
                    } else {
                        $(displays).css('color', '#008000');
                        $(displays).html('<?php echo gettext('password strength strong'); ?>');
                    }
                    if (strength < <?php echo (int) getOption('password_strength'); ?>) {
                        $(inputb).prop('disabled',true);
                        $(displays).css('color', '#ff0000');
                        $(displays).html('<?php echo gettext('password strength too weak'); ?>');
                    } else {
      $(inputb).parent().removeClass('ui-state-disabled');
      $(inputb).prop('disabled',false);
                        passwordMatch(id);
                    }
                    var url = 'url(<?php echo WEBPATH . '/' . ZENFOLDER; ?>/images/strengths/strength' + strength + '.png)';
                    $(inputa).css('background-image', url);
                    $(inputa).css('background-size', '100%');
                }
            }

            function passwordMatch(id) {
                var inputa = '#pass' + id;
                var inputb = '#pass_r' + id;
                var display = '#match' + id;
                if ($('#disclose_password' + id).prop('checked')) {
                    if ($(inputa).val() === $(inputb).val()) {
                        if ($(inputa).val().trim() !== '') {
                            $(display).css('color', '#008000');
                            $(display).html('<?php echo gettext('passwords match'); ?>');
                        }
                    } else {
                        $(display).css('color', '#ff0000');
                        $(display).html('<?php echo gettext('passwords do not match'); ?>');
                    }
                }
            }

            function passwordClear(id) {
                var inputa = '#pass' + id;
                var inputb = '#pass_r' + id;
                if ($(inputa).val().trim() === '') {
                    $(inputa).val('');
                }
                if ($(inputb).val().trim() === '') {
                    $(inputb).val('');
                }
            }
            function togglePassword(id) {
                if ($('#pass' + id).attr('type') == 'password') {
                    var oldp = $('#pass' + id);
                    var newp = oldp.clone();
                    newp.attr('type', 'text');
                    newp.insertAfter(oldp);
                    oldp.remove();
                    $('.password_field_' + id).hide();
                } else {
                    var oldp = $('#pass' + id);
                    var newp = oldp.clone();
                    newp.attr('type', 'password');
                    newp.insertAfter(oldp);
                    oldp.remove();
                    $('.password_field_' + id).show();
                }
            }

            var logonsteps = {
                'logonstep_challenge_js' : $('#logonstep_challenge_js').attr('href'),
                'logonstep_captcha_js' : $('#logonstep_captcha_js').attr('href'),
                'logonstep_return_js' : $('#logonstep_return_js').attr('href')
            };
            setLogonStepURL(logonsteps)
            $( "#user" ).keyup(function() {
                setLogonStepURL(logonsteps);
            });

            function setLogonStepURL(logonsteps) {
                var user = $('#user').val();
                $.each( logonsteps, function( key, value ) {
                    if($('#'+key).length) {
                        $('#'+key).attr('href', value + user);
                    }
                });
            }
            // ]]> -->
        </script>
        <?php
    }

    static function printPasswordForm($id = '', $pad = false, $disable = NULL, $required = false, $flag = '') {
        if ($pad) {
            $x = '          ';
        } else {
            $x = '';
        }
        ?>
        <input type="hidden" name="passrequired<?php echo $id; ?>" id="passrequired-<?php echo $id; ?>" value="<?php echo (int) $required; ?>" />
        <p>
            <label for="pass<?php echo $id; ?>" id="strength<?php echo $id; ?>"><?php echo gettext("Password") . $flag; ?></label>
            <input type="password" size="<?php echo TEXT_INPUT_SIZE; ?>"
                         name="pass<?php echo $id ?>" value="<?php echo $x; ?>"
                         id="pass<?php echo $id; ?>"
                         onchange="$('#passrequired-<?php echo $id; ?>').val(1);"
                         onclick="passwordClear('<?php echo $id; ?>');"
                         onkeyup="passwordStrength('<?php echo $id; ?>');"
                         <?php echo $disable; ?> />
        </p>
        <p>
            <label for="disclose_password<?php echo $id; ?>"><?php echo gettext('Show password'); ?></label>
            <input type="checkbox" name="disclose_password<?php echo $id; ?>" id="disclose_password<?php echo $id; ?>" onclick="passwordClear('<?php echo $id; ?>');
                    togglePassword('<?php echo $id; ?>');">
        </p>
        <p class="password_field_<?php echo $id; ?>">
            <label for="pass_r<?php echo $id; ?>" id="match<?php echo $id; ?>"><?php echo gettext("Repeat password") . $flag; ?></label>
            <input type="password" size="<?php echo TEXT_INPUT_SIZE; ?>"
                         name="pass_r<?php echo $id ?>" value="<?php echo $x; ?>"
                         id="pass_r<?php echo $id; ?>" disabled="disabled"
                         onchange="$('#passrequired-<?php echo $id; ?>').val(1);"
                         onkeydown="passwordClear('<?php echo $id; ?>');"
                         onkeyup="passwordMatch('<?php echo $id; ?>');" />
        </p>
        <?php
    }

    /** PBKDF2 Implementation (described in RFC 2898)
     *
     *  @param string p password
     *  @param string s salt
     *  @param int c iteration count (use 1000 or higher)
     *  @param int kl derived key length
     *  @param string a hash algorithm
     *
     *  @return string derived key
     */
    static function pbkdf2($p, $s, $c = 1000, $kl = 32, $a = 'sha256') {
        $hl = strlen(hash($a, null, true)); # Hash length
        $kb = ceil($kl / $hl); # Key blocks to compute
        $dk = ''; # Derived key
        # Create key
        for ($block = 1; $block <= $kb; $block++) {
            # Initial hash for this block
            $ib = $b = hash_hmac($a, $s . pack('N', $block), $p, true);
            # Perform block iterations
            for ($i = 1; $i < $c; $i++)
            # XOR each iterate
                $ib ^= ($b = hash_hmac($a, $b, $p, true));
            $dk .= $ib; # Append iterated block
        }
        # Return derived key of correct length
        return substr($dk, 0, $kl);
    }

    /**
     * Checks if the email address being set is already used by another user
     * Returns true if it is, false if not
     *
     * @param string $email_to_check email address to check
     * @param type $current_user user id of the user trying to set this email address
     * @return boolean
     */
    function checkUniqueMailaddress($email_to_check, $current_user) {
        if (!empty($email_to_check) && isValidEmail($email_to_check)) {
            $all_users = $this->getAdministrators('users');
            foreach ($all_users as $user) {
                if ($user['user'] != $current_user && !empty($user['email']) && $user['email'] == $email_to_check) {
                    return false;
                }
            }
            return true;
        } else {
            return false;
        }
    }

}
/**
 * This is a simple class so that we have a convienient "handle" for manipulating Administrators.
 *
 * NOTE: one should use the Zenphoto_Authority newAdministrator() method rather than directly instantiating
 * an administrator object
 * @package core
 * @subpackage classes\authorization
 */
class Zenphoto_Administrator extends PersistentObject {

    public $objects = NULL;
    public $master = false; //  will be set to true if this is the inherited master user
    public $msg = NULL; //  a means of storing error messages from filter processing
    public $logout_link = true; // for a Zenphoto logout
    public $reset = false; // if true the user was setup by a "reset password" event
    public $passhash; // the hash algorithm used in creating the password

    /**
     * Constructor for an Administrator
     *
     * @param string $user.
     * @param int $valid used to signal kind of admin object
     * @return Administrator
     */
    function __construct($user, $valid) {
        global $_zp_authority;
        $this->passhash = (int) getOption('strong_hash');
        $this->instantiate('administrators', array('user' => $user, 'valid' => $valid), NULL, false, empty($user));
        if (empty($user)) {
            $this->set('id', -1);
        }
        if ($valid) {
            $rights = $this->getRights();
            $new_rights = 0;
            if ($_zp_authority->isMasterUser($user)) {
                $new_rights = ALL_RIGHTS;
                $this->master = true;
            } else {
                // make sure that the "hidden" gateway rights are set for managing objects
                if ($rights & MANAGE_ALL_ALBUM_RIGHTS) {
                    $new_rights = $new_rights | ALBUM_RIGHTS;
                }
                if ($rights & MANAGE_ALL_NEWS_RIGHTS) {
                    $new_rights = $new_rights | ZENPAGE_PAGES_RIGHTS;
                }
                if ($rights & MANAGE_ALL_PAGES_RIGHTS) {
                    $new_rights = $new_rights | ZENPAGE_NEWS_RIGHTS;
                }
                $this->getObjects();
                foreach ($this->objects as $object) {
                    switch ($object['type']) {
                        case 'album':
                            if ($object['edit'] && MANAGED_OBJECT_RIGHTS_EDIT) {
                                $new_rights = $new_rights | ALBUM_RIGHTS;
                            }
                            break;
                        case 'pages':
                            $new_rights = $new_rights | ZENPAGE_PAGES_RIGHTS;
                            break;
                        case 'news':
                            $new_rights = $new_rights | ZENPAGE_NEWS_RIGHTS;
                            break;
                    }
                }
            }
            if($this->getGroup()) {
                $this->preservePrimeAlbum();
            }
            if ($new_rights) {
                $this->setRights($rights | $new_rights);
            }
        }
    }

    /**
     * Returns the unformatted date
     *
     * @return date
     */
    function getDateTime() {
        return $this->get('date');
    }

    /**
     * Stores the date
     *
     * @param string $datetime formatted date
     */
    function setDateTime($datetime) {
        $this->set('date', $datetime);
    }

    function getID() {
        return $this->get('id');
    }

    /**
     * Hashes and stores the password
     * @param $pwd
     */
    function setPass($pwd) {
        $hash_type = getOption('strong_hash');
        $pwd = Zenphoto_Authority::passwordHash($this->getUser(), $pwd, $hash_type);
        $this->set('pass', $pwd);
        $this->set('passupdate', date('Y-m-d H:i:s'));
        $this->set('passhash', $hash_type);
        return $this->get('pass');
    }

    /**
     * Returns stored password hash
     */
    function getPass() {
        return $this->get('pass');
    }

    /**
     * Stores the user name
     */
    function setName($admin_n) {
        $this->set('name', $admin_n);
    }

    /**
     * Returns the user name
     */
    function getName() {
        return $this->get('name');
    }
    
    /**
     * Gets the full name if set 
     * 
     * @since ZenphotoCNS 1.5.8
     * 
     * @param string $user User id 
     * @return string
     */
    static function getNameByUser($user) {
        $admin = Zenphoto_Authority::getAnAdmin(array('`user`=' => $user, '`valid`=' => 1));
        if (is_object($admin) && $admin->getName()) {
            return $admin->getName();
        }
        return $user;
    }

    /**
     * Stores the user email
     */
    function setEmail($admin_e) {
        $this->set('email', $admin_e);
    }

    /**
     * Returns the user email
     */
    function getEmail() {
        return $this->get('email');
    }

    /**
     * Stores user rights
     */
    function setRights($rights) {
        $this->set('rights', $rights);
    }

    /**
     * Returns user rights
     */
    function getRights() {
        return $this->get('rights');
    }

    /**
     * Returns local copy of managed objects.
     */
    function setObjects($objects) {
        $this->objects = $objects;
    }

    /**
     * Saves local copy of managed objects.
     * NOTE: The database is NOT updated by this, the user object MUST be saved to
     * cause an update
     */
    function getObjects($what = NULL) {
        if (is_null($this->objects)) {
            if ($this->transient) {
                $this->objects = array();
            } else {
                $this->objects = populateManagedObjectsList(NULL, $this->getID());
            }
        }
        if (empty($what)) {
            return $this->objects;
        }
        $result = array();
        foreach ($this->objects as $object) {
            if ($object['type'] == $what) {
                $result[get_language_string($object['name'])] = $object['data'];
            }
        }
        return $result;
    }

    /**
     * Stores custom data
     */
    function setCustomData($custom_data) {
        $this->set('custom_data', $custom_data);
    }

    /**
     * Returns custom data
     */
    function getCustomData() {
        return $this->get('custom_data');
    }

    /**
     * Sets the "valid" flag. Valid is 1 for users, 0 for groups and templates
     */
    function setValid($valid) {
        $this->set('valid', $valid);
    }

    /**
     * Returns the valid flag
     */
    function getValid() {
        return $this->get('valid');
    }

    /**
     * Sets the user's group.
     * NOTE this does NOT set rights, etc. that must be done separately
     */
    function setGroup($group) {
        $this->set('group', $group);
    }

    /**
     * Returns user's group
     */
    function getGroup() {
        return $this->get('group');
    }

    /**
     * Sets the user's user id
     */
    function setUser($user) {
        $this->set('user', $user);
    }

    /**
     * Returns user's user id
     */
    function getUser() {
        return $this->get('user');
    }

    /**
     * Sets the users quota
     */
    function setQuota($v) {
        $this->set('quota', $v);
    }

    /**
     * Returns the users quota
     */
    function getQuota() {
        return $this->get('quota');
    }

    /**
     * Returns the user's prefered language
     */
    function getLanguage() {
        return $this->get('language');
    }

    /**
     * Sets the user's preferec language
     */
    function setLanguage($locale) {
        $this->set('language', $locale);
    }

    /**
     * Uptates the database with all changes
     * 
     * @param bool $checkupdates Default false. If true the internal $updates property is checked for actual changes so unnecessary saving is skipped. Applies to already existing objects only.
     */
    function save($checkupdates = false) {
        global $_zp_gallery;
        if (DEBUG_LOGIN) {
            debugLogVar("Zenphoto_Administrator->save()", $this);
        }
        $objects = $this->getObjects();
        if (is_null($this->get('date'))) {
            $this->set('date', date('Y-m-d H:i:s'));
        }
        parent::save($checkupdates);
        $id = $this->getID();
        if (is_array($objects)) {
            $sql = "DELETE FROM " . prefix('admin_to_object') . ' WHERE `adminid`=' . $id;
            $result = query($sql, false);
            foreach ($objects as $object) {
                if (array_key_exists('edit', $object)) {
                    $edit = $object['edit'] | 32767 & ~(MANAGED_OBJECT_RIGHTS_EDIT | MANAGED_OBJECT_RIGHTS_UPLOAD | MANAGED_OBJECT_RIGHTS_VIEW);
                } else {
                    $edit = 32767;
                }
                switch ($object['type']) {
                    case 'album':
                        $album = newAlbum($object['data']);
                        $albumid = $album->getID();
                        $sql = "INSERT INTO " . prefix('admin_to_object') . " (adminid, objectid, type, edit) VALUES ($id, $albumid, 'albums', $edit)";
                        $result = query($sql);
                        break;
                    case 'pages':
                        $sql = 'SELECT * FROM ' . prefix('pages') . ' WHERE `titlelink`=' . db_quote($object['data']);
                        $result = query_single_row($sql);
                        if (is_array($result)) {
                            $objectid = $result['id'];
                            $sql = "INSERT INTO " . prefix('admin_to_object') . " (adminid, objectid, type, edit) VALUES ($id, $objectid, 'pages', $edit)";
                            $result = query($sql);
                        }
                        break;
                    case 'news':
                        $sql = 'SELECT * FROM ' . prefix('news_categories') . ' WHERE `titlelink`=' . db_quote($object['data']);
                        $result = query_single_row($sql);
                        if (is_array($result)) {
                            $objectid = $result['id'];
                            $sql = "INSERT INTO " . prefix('admin_to_object') . " (adminid, objectid, type, edit) VALUES ($id, $objectid, 'news', $edit)";
                            $result = query($sql);
                        }
                        break;
                }
            }
        }
    }

    /**
     * Removes a user from the system
     */
    function remove() {
        zp_apply_filter('remove_user', $this);
        $album = $this->getAlbum();
        $id = $this->getID();
        if (parent::remove()) {
            if (!empty($album)) { //    Remove users album as well
                $album->remove();
            }
            $sql = "DELETE FROM " . prefix('admin_to_object') . " WHERE `adminid`=$id";
            $result = query($sql);
        } else {
            return false;
        }
        return $result;
    }

    /**
     * Returns the user's "prime" album. See setAlbum().
     */
    function getAlbum() {
        $id = $this->get('prime_album');
        if (!empty($id)) {
            $sql = 'SELECT `folder` FROM ' . prefix('albums') . ' WHERE `id`=' . $id;
            $result = query_single_row($sql);
            if ($result) {
                $album = newAlbum($result['folder']);
                return $album;
            }
        }
        return false;
    }

    /**
     * Records the "prime album" of a user. Prime albums are linked to the user and
     * removed if the user is removed.
     */
    function setAlbum($album) {
        if ($album) {
            $this->set('prime_album', $album->getID());
        } else {
            $this->set('prime_album', NULL);
        }
    }

    /**
     * Data to support other credential systems integration
     */
    function getCredentials() {
        return getSerializedArray($this->get('other_credentials'));
    }

    function setCredentials($cred) {
        $this->set('other_credentials', serialize($cred));
    }

    /**
     * Creates a "prime" album for the user. Album name is based on the userid
     */
    function createPrimealbum($new = true, $name = NULL) {
        //  create his album
        $t = 0;
        $ext = '';
        if (is_null($name)) {
            $filename = internalToFilesystem(str_replace(array('<', '>', ':', '"' . '/' . '\\', '|', '?', '*'), '_', seoFriendly($this->getUser())));
        } else {
            $filename = internalToFilesystem(str_replace(array('<', '>', ':', '"' . '/' . '\\', '|', '?', '*'), '_', $name));
        }
        while ($new && file_exists(ALBUM_FOLDER_SERVERPATH . $filename . $ext)) {
            $t++;
            $ext = '-' . $t;
        }
        $path = ALBUM_FOLDER_SERVERPATH . $filename . $ext;
        $albumname = filesystemToInternal($filename . $ext);
        if (@mkdir_recursive($path, FOLDER_MOD)) {
            $album = newAlbum($albumname);
            if ($title = $this->getName()) {
                $album->setTitle($title);
            }
            $album->setOwner($this->getUser());
            $album->save();
            $this->setAlbum($album);
            $this->setRights($this->getRights() | ALBUM_RIGHTS);
            if (getOption('user_album_edit_default')) {
                $subrights = MANAGED_OBJECT_RIGHTS_EDIT;
            } else {
                $subrights = 0;
            }
            if ($this->getRights() & UPLOAD_RIGHTS) {
                $subrights = $subrights | MANAGED_OBJECT_RIGHTS_UPLOAD;
            }
            $objects = $this->getObjects();
            $objects[] = array('data' => $albumname, 'name' => $albumname, 'type' => 'album', 'edit' => $subrights);
            $this->setObjects($objects);
        }
    }

    function getChallengePhraseInfo() {
        $info = $this->get('challenge_phrase');
        if ($info) {
            return getSerializedArray($info);
        } else {
            return array('challenge' => '', 'response' => '');
        }
    }

    function setChallengePhraseInfo($challenge, $response) {
        $this->set('challenge_phrase', serialize(array('challenge' => $challenge, 'response' => $response)));
    }

    /**
     *
     * returns the last time the user has logged on
     */
    function getLastLogon() {
        return $this->get('lastloggedin');
    }
    
    /**
     * Returns the last time the user visited the site being loggedin
     * 
     * @since ZenphotoCMS 1.5.8
     * @return strig
     */
    function getLastVisit() {
        return $this->get('lastvisit');
    }
    
    /**
     * Sets the last time the user visited the site being loggedin
     * 
     * @since ZenphotoCMS 1.5.8
     */
    function setLastVisit($datetime = '') {
        if(empty($datetime)) {
            $datetime = date('Y-m-d H:i:s');
        }
        $this->set('lastvisit', $datetime);
    }
    
    /**
     * Updates the last visit date if enabled on the options and the time frame defined has passed.
     * @since ZenphotoCMS 1.5.8
     */
    function updateLastVisit() {
        if (getOption('admin_lastvisit')) {
            $lastvisit = strtotime($this->getLastVisit());
            $lastvisit_timeframe = getOption('admin_lastvisit_timeframe');
            if (empty($lastvisit_timeframe)) {
                $lastvisit_timeframe = 600;
            }
            if (empty($lastvisit) || (time() - $lastvisit) > $lastvisit_timeframe) {
                $this->setLastVisit();
                $this->save();
            }
        }
    }

    /**
     * Preserves the user's prime album as managed album even if he is in a group the album is actually set as managed
     */
    function preservePrimeAlbum() {
        $primeAlbum = $this->getAlbum();
        if (is_object($primeAlbum)) {
            $primealbum_name = $primeAlbum->name;
            $objects = $this->getObjects();
            $primealbum_managed = false;
            foreach ($objects as $key => $val) {
                if ($val['type'] == 'album' && $val['name'] == $primealbum_name) {
                    $primealbum_managed = true;
                    break;
                }
            }
            if (!$primealbum_managed) {
                $objects[] = array(
                        'data' => $primealbum_name,
                        'name' => $primealbum_name,
                        'type' => 'album',
                        'edit' => 32765
                );
            }
            $this->setObjects($objects);
        }
    }

}
?>
ZenphotoCMS 1.5.x API documentation generated by ApiGen