Overview

Namespaces

  • MatthiasMullie
    • Minify
      • Exceptions
    • PathConverter
  • None
  • ReCaptcha
    • RequestMethod
  • TOTP

Classes

  • apc_cache
  • apcu_cache
  • ApprovePost_Notify_Background
  • ApproveReply_Notify_Background
  • Attachments
  • Birthday_Notify_Background
  • browser_detector
  • Buddy_Notify_Background
  • cache_api
  • CreateAttachment_Notify_Background
  • CreatePost_Notify_Background
  • curl_fetch_web_data
  • custom_search
  • EventNew_Notify_Background
  • ftp_connection
  • fulltext_search
  • gif_color_table
  • gif_file
  • gif_file_header
  • gif_image
  • gif_image_header
  • gif_lzw_compression
  • GroupAct_Notify_Background
  • GroupReq_Notify_Background
  • Likes
  • Likes_Notify_Background
  • MatthiasMullie\Minify\CSS
  • MatthiasMullie\Minify\JS
  • MatthiasMullie\Minify\Minify
  • MatthiasMullie\PathConverter\Converter
  • MemberReport_Notify_Background
  • MemberReportReply_Notify_Background
  • memcache_cache
  • memcached_cache
  • Mentions
  • MsgReport_Notify_Background
  • MsgReportReply_Notify_Background
  • paypal_display
  • paypal_payment
  • postgres_cache
  • ProxyServer
  • Punycode
  • ReCaptcha\ReCaptcha
  • ReCaptcha\RequestMethod\Curl
  • ReCaptcha\RequestMethod\CurlPost
  • ReCaptcha\RequestMethod\Post
  • ReCaptcha\RequestMethod\Socket
  • ReCaptcha\RequestMethod\SocketPost
  • ReCaptcha\RequestParameters
  • ReCaptcha\Response
  • Register_Notify_Background
  • search_api
  • SMF_BackgroundTask
  • smf_cache
  • sqlite_cache
  • standard_search
  • TOTP\Auth
  • TypeError
  • Update_TLD_Regex
  • xcache_cache
  • xmlArray
  • zend_cache

Interfaces

  • cache_api_interface
  • ReCaptcha\RequestMethod
  • search_api_interface

Exceptions

  • Error
  • MatthiasMullie\Minify\Exception
  • MatthiasMullie\Minify\Exceptions\BasicException
  • MatthiasMullie\Minify\Exceptions\FileImportException
  • MatthiasMullie\Minify\Exceptions\IOException

Functions

  • _safe_serialize
  • _safe_unserialize
  • account
  • Activate
  • activateAccount
  • add_integration_function
  • addData
  • addInlineCss
  • addInlineJavaScript
  • addJavaScriptVar
  • AddLanguage
  • AddMailQueue
  • AddMembergroup
  • addMembersToGroup
  • addSeparator
  • AddSmiley
  • addSubscription
  • addTriggers
  • AdminAccount
  • AdminApprove
  • AdminBoardRecount
  • AdminEndSession
  • AdminHome
  • adminLogin
  • adminLogin_outputPostVars
  • AdminLogs
  • AdminMain
  • adminNotify
  • AdminRegister
  • AdminSearch
  • AdminSearchInternal
  • AdminSearchMember
  • AdminSearchOM
  • alert_configuration
  • alert_count
  • alert_delete
  • alert_mark
  • alert_markread
  • alert_notifications_boards
  • alert_notifications_topics
  • alert_purge
  • alerts_popup
  • AlignURLsWithSSLSetting
  • allowedTo
  • AnnouncementSelectMembergroup
  • AnnouncementSend
  • AnnounceTopic
  • ApplyRules
  • approveAllData
  • ApproveAttach
  • ApproveAttachments
  • ApproveMessage
  • approveMessages
  • approvePosts
  • approveTopics
  • array_column
  • array_length
  • assignAttachments
  • attachDirStatus
  • attachmentChecks
  • attachments_init_dir
  • automanage_attachments_by_space
  • automanage_attachments_check_directory
  • automanage_attachments_create_directory
  • AutoSuggest_Search_Member
  • AutoSuggest_Search_MemberGroups
  • AutoSuggest_Search_SMFVersions
  • AutoSuggestHandler
  • AutoTask
  • BackupDatabase
  • backupTable
  • Ban
  • BanBrowseTriggers
  • BanEdit
  • banEdit2
  • BanEditTrigger
  • BanList
  • banLoadAdditionalIPs
  • banLoadAdditionalIPsError
  • banLoadAdditionalIPsMember
  • BanLog
  • banPermissions
  • bbc_to_html
  • BoardIndex
  • BoardNotify
  • BoardPermissionsReport
  • BoardReport
  • boardsAllowedTo
  • BoardurlMatch
  • BookOfUnknown
  • BrowseFiles
  • BrowseMailQueue
  • BuddyListToggle
  • build_query_board
  • build_regex
  • buildEventDatetimes
  • cache_get_data
  • cache_getLastPosts
  • cache_getMembergroupList
  • cache_getOffsetIndependentEvents
  • cache_getRecentEvents
  • cache_put_data
  • cache_quick_get
  • CalculateNextTrigger
  • CalendarMain
  • CalendarPost
  • call_helper
  • call_integration_hook
  • canLinkEvent
  • canPickTheme
  • cdata_parse
  • censorText
  • check_cron
  • checkActivation
  • checkChange
  • checkConfirm
  • checkExistingTriggerIP
  • CheckFilesWritable
  • checkGD
  • checkImageContents
  • checkImagick
  • checkLogin
  • checkMagickWand
  • checkSession
  • checkSubmitOnce
  • clean_cache
  • cleanLangString
  • cleanRequest
  • cleanRequest_cron
  • cleanTokens
  • cleanXml
  • ClearMailQueue
  • cli_scheduled_fetchSMfiles
  • clock
  • cmdStep0
  • comma_format
  • compareVersions
  • ComposeMailing
  • consolidateSpiderStats
  • construct_query_string
  • constructPageIndex
  • ConvertEntities
  • ConvertMsgBody
  • convertSettingstoOptions
  • convertSettingsToTheme
  • ConvertUtf8
  • CoppaForm
  • CopyTemplate
  • copytree
  • countReports
  • create_button
  • create_chmod_control
  • create_control_richedit
  • create_control_verification
  • createAttachment
  • createBoard
  • createCategory
  • createList
  • createMenu
  • CreateMessageIndex
  • createPost
  • createSalvageArea
  • createThumbnail
  • createToken
  • createWaveFile
  • Credits
  • custFieldsMaxOrder
  • custMinify
  • DatabaseChanges
  • DatabasePopulation
  • DatabaseSettings
  • db_extend
  • db_extra_init
  • db_fix_prefix
  • db_packages_init
  • db_search_init
  • db_version_check
  • debugPrint
  • deleteAccount
  • deleteAccount2
  • deleteAllMinified
  • deleteBoards
  • deleteCategories
  • DeleteDraft
  • deleteErrors
  • DeleteInstall
  • DeleteMembergroup
  • deleteMembergroups
  • deleteMembers
  • DeleteMessage
  • deleteMessages
  • deleteModComment
  • deleteNotifyPrefs
  • DeleteUpgrade
  • deltree
  • Destroy
  • destroyMenu
  • detectBrowser
  • detectFulltextIndex
  • determineActions
  • Display
  • display_db_error
  • display_loadavg_error
  • display_maintenance_message
  • DisplayAdminFile
  • displayDebug
  • DisplayStats
  • DoLogin
  • Download
  • downloadAvatar
  • DownloadLanguage
  • dumpTags
  • EditAgreement
  • EditBoard
  • EditBoard2
  • EditBoardSettings
  • editBuddies
  • editBuddyIgnoreLists
  • EditCategory
  • EditCategory2
  • EditComment
  • EditCustomProfiles
  • EditHoliday
  • editIgnoreList
  • EditMembergroup
  • EditMessageIcons
  • editModComment
  • EditNews
  • EditPermissionProfiles
  • EditPoll
  • EditPoll2
  • EditSearchMethod
  • EditSearchSettings
  • EditSmileyOrder
  • EditSmileys
  • EditSmileySets
  • EditSmileySettings
  • EditSpider
  • EditTask
  • EditTheme
  • EditWeights
  • emailAdmins
  • EnableTheme
  • entity_fix__callback
  • escapestring__recursive
  • ExamineFile
  • expandIPv6
  • fatal_error
  • fatal_lang_error
  • fetch_alerts
  • fetch_task
  • fetch_web_data
  • fetchPerms__recursive
  • fetchTagAttributes
  • find_gpg
  • find_signed_off
  • find_signed_off_parents
  • findForumErrors
  • findMembers
  • findSearchAPI
  • finishTables
  • fix_possible_url
  • fix_serialized_data
  • fixchar__callback
  • fixchardb__callback
  • fixChildren
  • fixModSecurity
  • fixRelativePath
  • fixTag
  • fixTags
  • forum_time
  • forumProfile
  • ForumSettings
  • frameOptionsHeader
  • GeneralPermissionSettings
  • generateSubscriptionError
  • generateValidationCode
  • get_all_themes
  • get_current_settings
  • get_date_or_time_format
  • get_directory_tree_elements
  • get_file_listing
  • get_files_recursive
  • get_gravatar_url
  • get_hook_info_from_raw
  • get_installed_themes
  • get_integration_hooks
  • get_integration_hooks_count
  • get_integration_hooks_data
  • get_proxied_url
  • get_single_theme
  • get_theme_info
  • getAttachmentFilename
  • getAttachMsgInfo
  • getAvatars
  • getBirthdayRange
  • getBoardIndex
  • getBoardList
  • getBoardModeratorGroups
  • getBoardModerators
  • getBoardParents
  • getBoardTree
  • getCalendarGrid
  • getCalendarList
  • getCalendarWeek
  • getCommentModDetails
  • getCustFieldsMList
  • getDailyStats
  • getEventPoster
  • getEventProperties
  • getEventRange
  • getFileVersions
  • getHolidayRange
  • GetJumpTo
  • getLanguages
  • getLastPost
  • getLastPosts
  • GetMemberActivationCounts
  • getMemberData
  • getMemberGroups
  • getMembersOnlineStats
  • getMessageIcons
  • getMsgMemberID
  • getNewEventDatetimes
  • getNotifyPrefs
  • getPackageInfo
  • getRawAttachInfo
  • getReportComments
  • getReportDetails
  • getReports
  • getServerVersions
  • getTodayInfo
  • getTopic
  • getTreeOrder
  • getUserTimezone
  • getXmlMembers
  • getXmlNews
  • getXmlProfile
  • getXmlRecent
  • gif_outputAsPng
  • GroupList
  • groupMembership
  • groupMembership2
  • GroupPermissionsReport
  • GroupRequests
  • Groups
  • groupsAllowedTo
  • HandleComment
  • HandleReport
  • hash_benchmark
  • hash_length
  • hash_password
  • hash_salt
  • hash_verify_password
  • HelpIndex
  • HelpRules
  • highlight
  • highlight_php_code
  • host_from_ip
  • html_to_bbc
  • htmlspecialchars__recursive
  • htmltrim__recursive
  • https_redirect_active
  • httpsOn
  • iCalDownload
  • ignoreboards
  • imagecopyresamplebicubic
  • imagecreatefrombmp
  • imageMemoryCheck
  • ImportSmileys
  • inet_dtop
  • inet_ptod
  • initialize_inputs
  • InMaintenance
  • insertBanGroup
  • insertEvent
  • InstallCopy
  • InstallDir
  • installer_updateSettingsFile
  • installExit
  • InstallFile
  • InstallSmileySet
  • ip2range
  • iri_to_url
  • is_not_banned
  • is_not_guest
  • isAccessiblePM
  • isAllowedTo
  • isBannedEmail
  • isBrowser
  • isChildOf
  • isReservedName
  • issueWarning
  • isValidIP
  • isValidIPv6
  • JavaScriptEscape
  • JavaScriptModify
  • jeffsdatediff
  • JSMembers
  • KickGuest
  • legalise_bbc
  • list_getAttachDirs
  • list_getAttachments
  • list_getBanItems
  • list_getBanLogEntries
  • list_getBans
  • list_getBanTriggers
  • list_getBaseDirs
  • list_getBoardNotifications
  • list_getFiles
  • list_getGroupRequestCount
  • list_getGroupRequests
  • list_getGroupRequestsCount
  • list_getHolidays
  • list_getIPMessageCount
  • list_getIPMessages
  • list_getLanguages
  • list_getLanguagesList
  • list_getLoginCount
  • list_getLogins
  • list_getMailQueue
  • list_getMailQueueSize
  • list_getMembergroups
  • list_getMembers
  • list_getMessageIcons
  • list_getModLogEntries
  • list_getModLogEntryCount
  • list_getNews
  • list_getNumAttachments
  • list_getNumBanItems
  • list_getNumBanLogEntries
  • list_getNumBans
  • list_getNumBanTriggers
  • list_getNumFiles
  • list_getNumHolidays
  • list_getNumLanguages
  • list_getNumMembers
  • list_getNumSmileys
  • list_getNumSmileySets
  • list_getNumSpiderLogs
  • list_getNumSpiders
  • list_getNumSpiderStats
  • list_getNumTaskLogEntries
  • list_getNumUnapprovedAttachments
  • list_getNumUnwatched
  • list_getPackages
  • list_getProfileEditCount
  • list_getProfileEdits
  • list_getProfileFields
  • list_getProfileFieldSize
  • list_getScheduledTasks
  • list_getSmileys
  • list_getSmileySets
  • list_getSpiderLogs
  • list_getSpiders
  • list_getSpiderStats
  • list_getSubscribedUserCount
  • list_getSubscribedUsers
  • list_getTaskLogEntries
  • list_getTopicNotificationCount
  • list_getTopicNotifications
  • list_getUnapprovedAttachments
  • list_getUnwatched
  • list_getUserErrorCount
  • list_getUserErrors
  • list_getUserWarningCount
  • list_getUserWarnings
  • list_getWarningCount
  • list_getWarnings
  • list_getWarningTemplateCount
  • list_getWarningTemplates
  • list_getWatchedUserCount
  • list_getWatchedUserPosts
  • list_getWatchedUserPostsCount
  • list_getWatchedUsers
  • list_integration_hooks
  • listMembergroupMembers_Href
  • ListMessageIcons
  • listtree
  • load_database
  • load_file
  • load_lang_file
  • loadAttachmentContext
  • loadBoard
  • loadCacheAccelerator
  • loadCacheAPIs
  • loadCSSFile
  • loadCustomFields
  • loadDatabase
  • loadDatePair
  • loadDatePicker
  • loadEmailTemplate
  • loadEssentialData
  • loadEssentialThemeData
  • loadForumTests
  • loadGeneralSettingParameters
  • loadIllegalBBCHtmlGroups
  • loadIllegalGuestPermissions
  • loadIllegalPermissions
  • loadInstalledPackages
  • loadJavaScriptFile
  • loadLanguage
  • loadLocale
  • loadMemberContext
  • loadMemberCustomFields
  • loadMemberData
  • loadPaymentGateways
  • loadPermissionProfiles
  • loadPermissions
  • loadProfileFields
  • LoadRules
  • loadSearchAPIs
  • loadSession
  • loadSubscriptions
  • loadSubTemplate
  • loadTemplate
  • loadTheme
  • loadThemeOptions
  • loadTimePicker
  • loadUserSettings
  • LockTopic
  • LockVoting
  • log_ban
  • log_error
  • log_error_online
  • logAction
  • logActions
  • Login
  • Login2
  • LoginTFA
  • logLastDatabaseError
  • Logout
  • logSpider
  • logTriggersUpdates
  • MaintainCleanCache
  • MaintainDatabase
  • MaintainEmptyUnimportantLogs
  • MaintainFiles
  • MaintainFindFixErrors
  • MaintainMassMoveTopics
  • MaintainMembers
  • MaintainPurgeInactiveMembers
  • MaintainReattributePosts
  • MaintainRecountPosts
  • MaintainRemoveOldDrafts
  • MaintainRemoveOldPosts
  • MaintainRoutine
  • MaintainTopics
  • makeCustomFieldChanges
  • makeFilesWritable
  • makeNotificationChanges
  • makeThemeChanges
  • ManageAttachmentPaths
  • ManageAttachments
  • ManageAttachmentSettings
  • ManageAvatarSettings
  • ManageBoards
  • ManageBoardsMain
  • ManageCalendar
  • ManageLabels
  • ManageLanguages
  • ManageMail
  • ManageMaintenance
  • ManageNews
  • ManagePaidSubscriptions
  • ManagePostSettings
  • ManageRules
  • ManageScheduledTasks
  • ManageSearch
  • ManageSearchEngineSettings
  • ManageSmileys
  • markBoardsRead
  • markMessages
  • MarkRead
  • matchHighestPackageVersion
  • matchIPtoCIDR
  • matchPackageVersion
  • md5_hmac
  • MembergroupIndex
  • MembergroupMembers
  • MemberGroupsReport
  • Memberlist
  • membersAllowedTo
  • MembersAwaitingActivation
  • memoryReturnBytes
  • MergeDone
  • MergeExecute
  • MergeIndex
  • mergePosts
  • MergeTopics
  • MessageActionsApply
  • MessageDrafts
  • MessageFolder
  • MessageIndex
  • messageIndexBar
  • MessageKillAll
  • MessageMain
  • MessagePopup
  • MessagePost
  • MessagePost2
  • messagePostError
  • MessagePrune
  • MessageSearch
  • MessageSearch2
  • MessageSettings
  • mimespecialchars
  • mktree
  • MLAll
  • MLSearch
  • ModBlockGroupRequests
  • ModBlockNotes
  • ModBlockReportedMembers
  • ModBlockReportedPosts
  • ModBlockWatchedUsers
  • ModEndSession
  • ModerateGroups
  • ModerationHome
  • ModerationMain
  • ModerationSettings
  • ModifyAlertsSettings
  • ModifyAntispamSettings
  • ModifyBasicSettings
  • ModifyBBCSettings
  • modifyBoard
  • ModifyCacheSettings
  • ModifyCalendarSettings
  • ModifyCat
  • modifyCategory
  • ModifyCookieSettings
  • ModifyDatabaseSettings
  • ModifyDraftSettings
  • modifyEvent
  • ModifyFeatureSettings
  • ModifyGeneralModSettings
  • ModifyGeneralSecuritySettings
  • ModifyGeneralSettings
  • ModifyHolidays
  • ModifyLanguage
  • ModifyLanguages
  • ModifyLanguageSettings
  • ModifyLayoutSettings
  • ModifyLikesSettings
  • ModifyLoadBalancingSettings
  • ModifyLogSettings
  • ModifyMailSettings
  • ModifyMembergroup
  • ModifyMembergroup2
  • ModifyMembergroups
  • ModifyMembergroupsettings
  • ModifyMentionsSettings
  • ModifyModSettings
  • ModifyNewsSettings
  • ModifyPermissions
  • modifyPost
  • ModifyPostModeration
  • ModifyPostSettings
  • ModifyProfile
  • ModifyRegistrationSettings
  • ModifySettings
  • ModifySignatureSettings
  • ModifySubscription
  • ModifySubscriptionSettings
  • ModifyTopicSettings
  • ModifyUserSubscription
  • ModifyWarningSettings
  • ModifyWarningTemplate
  • MoveTopic
  • MoveTopic2
  • moveTopicConcurrence
  • moveTopics
  • MySQLConvertOldIp
  • newsletterpreview
  • newspreview
  • newTable
  • next_time
  • nextSubstep
  • notification
  • ob_sessrewrite
  • obExit
  • obExit_cron
  • OptimizeTables
  • package_chmod
  • package_create_backup
  • package_crypt
  • package_flush_cache
  • package_get_contents
  • package_put_contents
  • PackageBrowse
  • PackageDownload
  • PackageFTPTest
  • PackageGBrowse
  • PackageGet
  • PackageInstall
  • PackageInstallTest
  • PackageList
  • PackageOptions
  • PackagePermissions
  • PackagePermissionsAction
  • PackageRemove
  • packageRequireFTP
  • Packages
  • PackageServerAdd
  • PackageServerRemove
  • PackageServers
  • PackageUpload
  • parse_bbc
  • parse_path
  • parse_sql
  • parseAttachBBC
  • parseBoardMod
  • parseModification
  • parsePackageInfo
  • parsesmileys
  • password_get_info
  • password_hash
  • password_needs_rehash
  • password_verify
  • pauseAttachmentMaintenance
  • pauseMailQueueClear
  • pauseRepairProcess
  • pauseSignatureApplySettings
  • perform_task
  • PermissionByBoard
  • PermissionIndex
  • permute
  • php_version_check
  • phpBB3_password_check
  • PickTheme
  • PlushSearch1
  • PlushSearch2
  • populateDuplicateMembers
  • Post
  • Post2
  • PostModerationMain
  • prepareAttachsByMsg
  • prepareCLIhandler
  • prepareDBSettingContext
  • prepareDisplayContext
  • prepareLikesContext
  • prepareMailingForPreview
  • prepareMessageContext
  • prepareSearchContext
  • prepareServerSettingsContext
  • preparsecode
  • print_error
  • printMemberListRows
  • PrintTopic
  • processAttachments
  • profile_popup
  • profileLoadAvatarData
  • profileLoadGroups
  • profileLoadLanguages
  • profileLoadSignatureData
  • profileReloadUser
  • profileSaveAvatarData
  • profileSaveGroups
  • profileSendActivation
  • profileValidateEmail
  • profileValidateSignature
  • protected_alter
  • quickFileWritable
  • QuickInTopicModeration
  • QuickModeration
  • QuoteFast
  • random_bytes
  • random_int
  • RandomCompat_intval
  • RandomCompat_strlen
  • RandomCompat_substr
  • range2ip
  • read_tgz_data
  • read_tgz_file
  • read_zip_data
  • read_zip_file
  • ReadDraft
  • reapplySubscriptions
  • reattributePosts
  • rebuildModCache
  • recacheSpiderNames
  • RecentPosts
  • recountOpenReports
  • recursiveBoards
  • redirectexit
  • redirectLocation
  • ReduceMailQueue
  • reencodeImage
  • RegCenter
  • Register
  • Register2
  • RegisterCheckUsername
  • registerMember
  • registerSMStats
  • reloadSettings
  • RemindMe
  • RemindPick
  • remove_dir
  • remove_integration_function
  • remove_theme
  • RemoveAllAttachments
  • RemoveAttachment
  • RemoveAttachmentByAge
  • RemoveAttachmentBySize
  • removeBanGroups
  • removeBanLogs
  • removeBanTriggers
  • removeDeleteConcurrence
  • removeEvent
  • removeHolidays
  • removeIllegalBBCHtmlPermission
  • removeMembersFromGroups
  • removeMessage
  • removeMessages
  • RemoveOldTopics2
  • RemovePoll
  • removeSubscription
  • RemoveTheme
  • RemoveTopic2
  • removeTopics
  • reorderBoards
  • RepairAttachments
  • RepairBoards
  • replaceEntities__callback
  • ReportDetails
  • ReportedContent
  • ReportedMembers
  • ReportMessage
  • reportPost
  • ReportsMain
  • ReportToModerator
  • ReportToModerator2
  • reportUser
  • RequestMembers
  • resetPassword
  • resizeImage
  • resizeImageFile
  • RestoreTopic
  • RetrievePreview
  • safe_file_write
  • safe_serialize
  • safe_unserialize
  • sanitize_iri
  • sanitizeMSCutPaste
  • saveDBSettings
  • SaveDraft
  • saveModComment
  • SavePMDraft
  • saveProfileChanges
  • saveProfileFields
  • saveSettings
  • saveTriggers
  • scheduled_birthdayemails
  • scheduled_daily_digest
  • scheduled_daily_maintenance
  • scheduled_fetchSMfiles
  • scheduled_paid_subscriptions
  • scheduled_remove_old_drafts
  • scheduled_remove_temp_attachments
  • scheduled_remove_topic_redirect
  • scheduled_weekly_digest
  • scheduled_weekly_maintenance
  • ScheduledTasks
  • SearchEngines
  • SearchMembers
  • searchSort
  • SecretAnswer2
  • SecretAnswerInput
  • secureDirectory
  • SelectMailingMembers
  • send_http_status
  • SendActivation
  • sendmail
  • SendMailing
  • sendNotifications
  • sendpm
  • sentence_list
  • serialize_to_json
  • sessionClose
  • sessionDestroy
  • sessionGC
  • sessionOpen
  • sessionRead
  • sessionWrite
  • set_alert_icon
  • set_avatar_data
  • set_fatal_error_headers
  • set_tld_regex
  • SetCensor
  • setEventStartEnd
  • SetJavaScript
  • setKeys
  • setLoginCookie
  • setMemoryLimit
  • setNotifyPrefs
  • setPassword
  • setPassword2
  • SetQuickGroups
  • SetReserved
  • setSqlMode
  • setTFACookie
  • SetThemeOptions
  • SetThemeSettings
  • setup_fatal_error_context
  • setupMenuContext
  • setupProfileContext
  • setupThemeContext
  • sha1_core
  • sha1_ft
  • sha1_kt
  • sha1_raw
  • sha1_rol
  • sha1_smf
  • shorten_subject
  • ShowAdminHelp
  • showAlerts
  • showAttachment
  • showAttachments
  • ShowClosedReports
  • showCodeImage
  • ShowCustomProfiles
  • ShowDrafts
  • ShowHelp
  • showLetterImage
  • ShowNotice
  • showPermissions
  • ShowPHPinfoSettings
  • showPMDrafts
  • showPosts
  • showProfileDrafts
  • ShowReports
  • showUnwatched
  • ShowXmlFeed
  • sig_preview
  • smf_chmod
  • smf_crc32
  • smf_db_add_column
  • smf_db_add_index
  • smf_db_affected_rows
  • smf_db_allow_persistent
  • smf_db_backup_table
  • smf_db_calculate_type
  • smf_db_change_column
  • smf_db_create_query_column
  • smf_db_create_table
  • smf_db_create_word_search
  • smf_db_cte_support
  • smf_db_custom_order
  • smf_db_drop_table
  • smf_db_error
  • smf_db_error_backtrace
  • smf_db_error_insert
  • smf_db_escape_string
  • smf_db_escape_wildcard_string
  • smf_db_fetch_all
  • smf_db_get_server_info
  • smf_db_get_vendor
  • smf_db_get_version
  • smf_db_initiate
  • smf_db_insert
  • smf_db_insert_id
  • smf_db_list_columns
  • smf_db_list_indexes
  • smf_db_list_tables
  • smf_db_native_replace
  • smf_db_optimize_table
  • smf_db_query
  • smf_db_quote
  • smf_db_remove_column
  • smf_db_remove_index
  • smf_db_replacement__callback
  • smf_db_search_language
  • smf_db_search_query
  • smf_db_search_support
  • smf_db_select
  • smf_db_select_db
  • smf_db_table_sql
  • smf_db_table_structure
  • smf_db_transaction
  • smf_db_version
  • smf_error_handler
  • smf_error_handler_cron
  • smf_is_resource
  • smf_json_decode
  • smf_list_timezones
  • smf_main
  • smf_mysql_fetch_assoc
  • smf_mysql_fetch_row
  • smf_mysql_free_result
  • smf_mysql_insert_id
  • smf_mysql_num_rows
  • smf_mysql_real_escape_string
  • smf_seed_generator
  • smf_serverResponse
  • smf_setcookie
  • smf_strtolower
  • smf_var_export
  • SMStats
  • sortBoards
  • sortCategories
  • spamProtection
  • spell_check
  • spell_init
  • spell_suggest
  • SpellCheck
  • SpiderCheck
  • SpiderLogs
  • SpiderStats
  • SplitExecute
  • SplitIndex
  • SplitSelectionExecute
  • SplitSelectTopics
  • splitTopic
  • SplitTopics
  • ssi_boardNews
  • ssi_boardStats
  • ssi_checkPassword
  • ssi_copyright
  • ssi_fetchGroupMembers
  • ssi_fetchMember
  • ssi_fetchPosts
  • ssi_full_version
  • ssi_latestMember
  • ssi_login
  • ssi_logOnline
  • ssi_logout
  • ssi_menubar
  • ssi_news
  • ssi_pollVote
  • ssi_queryMembers
  • ssi_queryPosts
  • ssi_quickSearch
  • ssi_randomMember
  • ssi_recentAttachments
  • ssi_recentEvents
  • ssi_recentPoll
  • ssi_recentPosts
  • ssi_recentTopics
  • ssi_showPoll
  • ssi_shutdown
  • ssi_software_year
  • ssi_todaysBirthdays
  • ssi_todaysCalendar
  • ssi_todaysEvents
  • ssi_todaysHolidays
  • ssi_topBoards
  • ssi_topPoll
  • ssi_topPoster
  • ssi_topTopics
  • ssi_topTopicsReplies
  • ssi_topTopicsViews
  • ssi_version
  • ssi_welcome
  • ssi_whosOnline
  • ssl_cert_found
  • StaffReport
  • statPanel
  • Sticky
  • strip_php_comments
  • stripslashes__recursive
  • subscriptions
  • summary
  • TaskLog
  • TaskSettings
  • template_action_permissions
  • template_add_edit_group_boards_list
  • template_add_language
  • template_add_rule
  • template_additional_rows
  • template_addsmiley
  • template_admin
  • template_admin_account
  • template_admin_browse
  • template_admin_login
  • template_admin_quick_search
  • template_admin_register
  • template_admin_search_results
  • template_after
  • template_alert_configuration
  • template_alert_notifications_boards
  • template_alert_notifications_topics
  • template_alerts_all_read
  • template_alerts_popup
  • template_announce
  • template_announcement_send
  • template_ask
  • template_ask_delete
  • template_attachment_errors
  • template_attachment_paths
  • template_attachment_repair
  • template_avatar_settings_above
  • template_avatar_settings_below
  • template_backup_database
  • template_backup_xml
  • template_ban_edit
  • template_ban_edit_trigger
  • template_bcd
  • template_bi_board_children
  • template_bi_board_icon
  • template_bi_board_info
  • template_bi_board_lastpost
  • template_bi_board_stats
  • template_bi_redirect_icon
  • template_bi_redirect_stats
  • template_boardindex_outer_above
  • template_boardindex_outer_below
  • template_body_above
  • template_body_below
  • template_browse
  • template_button_strip
  • template_by_board
  • template_calendar_top
  • template_callback_question_answer_list
  • template_check_username
  • template_chmod
  • template_chmod_files
  • template_choose_payment
  • template_clean_cache_button_above
  • template_clean_cache_button_below
  • template_confirm_board_delete
  • template_confirm_category_delete
  • template_control_chmod
  • template_control_richedit
  • template_control_richedit_buttons
  • template_control_verification
  • template_convert_entities
  • template_convert_msgbody
  • template_convert_utf8
  • template_convert_xml
  • template_coppa
  • template_coppa_form
  • template_copy_template
  • template_create_index
  • template_create_index_done
  • template_create_index_progress
  • template_create_list_menu
  • template_credits
  • template_css
  • template_database_changes
  • template_database_settings
  • template_database_xml
  • template_delete_install
  • template_delete_subscription
  • template_deleteAccount
  • template_download_language
  • template_downloaded
  • template_edit_agreement
  • template_edit_browse
  • template_edit_censored
  • template_edit_comment
  • template_edit_file
  • template_edit_group
  • template_edit_holiday
  • template_edit_list
  • template_edit_options
  • template_edit_profile_field
  • template_edit_profiles
  • template_edit_reserved_words
  • template_edit_scheduled_tasks
  • template_edit_style
  • template_edit_template
  • template_editBuddies
  • template_editicon
  • template_editicons
  • template_editIgnoreList
  • template_editsets
  • template_email_members
  • template_email_members_compose
  • template_email_members_send
  • template_error_log
  • template_error_message
  • template_event_post
  • template_examine
  • template_extract_package
  • template_fatal_error
  • template_file_permissions
  • template_find_members
  • template_folder
  • template_footer
  • template_forum_settings
  • template_ftp_required
  • template_generic
  • template_generic_menu
  • template_generic_menu_dropdown_above
  • template_generic_menu_dropdown_below
  • template_generic_menu_tabs
  • template_generic_xml
  • template_generic_xml_recursive
  • template_group_members
  • template_group_request_reason
  • template_group_requests_block
  • template_groupMembership
  • template_header
  • template_hms
  • template_homepage_sample1
  • template_homepage_sample1_html
  • template_homepage_sample1_php
  • template_html_above
  • template_html_below
  • template_ic_block_calendar
  • template_ic_block_online
  • template_ic_block_recent
  • template_ic_block_stats
  • template_ignoreboards
  • template_include
  • template_info_center
  • template_init
  • template_inline_permissions
  • template_install_above
  • template_install_below
  • template_install_options
  • template_installed
  • template_issueWarning
  • template_javascript
  • template_jump_to
  • template_kick_guest
  • template_labels
  • template_like
  • template_list
  • template_list_themes
  • template_load_warning_variables
  • template_login
  • template_login_tfa
  • template_mailtest
  • template_main
  • template_maint_warning_above
  • template_maint_warning_below
  • template_maintain_database
  • template_maintain_members
  • template_maintain_routine
  • template_maintain_topics
  • template_maintenance
  • template_manual
  • template_max_size
  • template_menu
  • template_merge
  • template_merge_done
  • template_merge_extra_options
  • template_message_icons
  • template_moderation_center
  • template_moderation_settings
  • template_modify_board
  • template_modify_category
  • template_modify_group
  • template_modify_group_display
  • template_modify_language_entries
  • template_modify_subscription
  • template_modify_user_subscription
  • template_modify_weights
  • template_modifydone
  • template_modifyfast
  • template_modifyset
  • template_modifysmiley
  • template_modifytopicdone
  • template_move
  • template_new_group
  • template_news_lists
  • template_newsfader
  • template_not_done
  • template_notes
  • template_notify_board
  • template_omfg
  • template_optimize
  • template_options
  • template_package_confirm
  • template_package_list
  • template_paid_done
  • template_permission_index
  • template_permission_show_contents
  • template_php_info
  • template_pick
  • template_pm
  • template_pm_above
  • template_pm_below
  • template_pm_popup
  • template_populate_database
  • template_popup
  • template_post
  • template_post_header
  • template_postmod_permissions
  • template_print
  • template_print_above
  • template_print_below
  • template_print_options
  • template_profile_above
  • template_profile_avatar_select
  • template_profile_below
  • template_profile_birthdate
  • template_profile_group_manage
  • template_profile_pm_settings
  • template_profile_popup
  • template_profile_save
  • template_profile_signature_modify
  • template_profile_smiley_pick
  • template_profile_tfa
  • template_profile_theme_pick
  • template_profile_theme_settings
  • template_profile_timeformat_modify
  • template_prune
  • template_quickbuttons
  • template_quickreply
  • template_quotefast
  • template_recent
  • template_redirect_options
  • template_registration_agreement
  • template_registration_form
  • template_reminder_pick
  • template_repair_boards
  • template_replies
  • template_report_message
  • template_report_message_complete
  • template_report_type
  • template_reported_members
  • template_reported_members_block
  • template_reported_posts
  • template_reported_posts_block
  • template_reported_users_block
  • template_resend
  • template_reset_list
  • template_results
  • template_retry_activate
  • template_rules
  • template_search
  • template_search_members
  • template_search_results
  • template_select
  • template_select_search_method
  • template_send
  • template_sendbody
  • template_sent
  • template_serialize_json
  • template_serialize_json_xml
  • template_servers
  • template_set_options
  • template_set_password
  • template_set_settings
  • template_setorder
  • template_settings
  • template_show_backtrace
  • template_show_custom_profile
  • template_show_file
  • template_show_list
  • template_show_month_grid
  • template_show_notice
  • template_show_settings
  • template_show_spider_logs
  • template_show_spider_stats
  • template_show_upcoming_list
  • template_show_week_grid
  • template_showAlerts
  • template_showDrafts
  • template_showPermissions
  • template_showPMDrafts
  • template_showPosts
  • template_single_pm
  • template_single_post
  • template_spellcheck
  • template_spider_edit
  • template_split
  • template_ssi_above
  • template_ssi_below
  • template_statPanel
  • template_stats
  • template_subject_list
  • template_summary
  • template_terms
  • template_tfadisable
  • template_tfasetup
  • template_tfasetup_backup
  • template_thetime
  • template_topic_legend
  • template_trackActivity
  • template_trackIP
  • template_unapproved_posts
  • template_unread
  • template_upgrade_above
  • template_upgrade_below
  • template_upgrade_complete
  • template_upgrade_options
  • template_user_subscription
  • template_user_watch_post_callback
  • template_verification_sound
  • template_view_operations
  • template_view_package
  • template_view_scheduled_tasks
  • template_view_versions
  • template_viewmemberreport
  • template_viewmodreport
  • template_viewWarning
  • template_warn_template
  • template_warning
  • template_warning_divs
  • template_watched_users
  • template_welcome_message
  • template_xml_above
  • template_xml_below
  • TestMailSend
  • text2words
  • textfield_alter
  • tfadisable
  • tfasetup
  • theme
  • theme_copyright
  • theme_inline_permissions
  • theme_install
  • theme_linktree
  • ThemeAdmin
  • ThemeInstall
  • ThemeList
  • ThemesMain
  • throw_error
  • time_since
  • timeformat
  • TopicNotify
  • trackActivity
  • trackEdits
  • trackGroupReq
  • tracking
  • TrackIP
  • TrackLogins
  • trackStats
  • trackStatsUsersOnline
  • TransferAttachments
  • truncate_array
  • un_htmlspecialchars
  • un_preparsecode
  • UnapprovedAttachments
  • UnapprovedPosts
  • unescapestring__recursive
  • UnreadTopics
  • updateAdminPreferences
  • updateBanGroup
  • updateBanMembers
  • updateBoardManagers
  • updateChildPermissions
  • updateDbLastError
  • updateLastMessages
  • updateMemberData
  • updateReport
  • updateSettings
  • updateSettingsFile
  • updateStats
  • updateTriggers
  • upgrade_clean_cache
  • upgrade_query
  • upgradeExit
  • upgradeGetColumnInfo
  • UpgradeOptions
  • url_exists
  • url_image_size
  • url_parts
  • url_to_iri
  • urldecode__recursive
  • user_info_callback
  • utf8_strtolower
  • utf8_strtoupper
  • validate_iri
  • validateEventPost
  • validatePassword
  • validatePasswordFlood
  • validateSession
  • validateToken
  • validateTriggers
  • validateUsername
  • VerificationCode
  • VersionDetail
  • ViewBacktrace
  • ViewErrorLog
  • ViewFile
  • ViewMemberlist
  • ViewMembers
  • ViewModlog
  • ViewOperations
  • ViewQuery
  • ViewSpiders
  • ViewSubscribedUsers
  • ViewSubscriptions
  • viewWarning
  • ViewWarningLog
  • ViewWarnings
  • ViewWarningTemplates
  • ViewWatchedUsers
  • Vote
  • warning_preview
  • Welcome
  • WelcomeLogin
  • Who
  • WrapAction
  • writeLog
  • XmlDraft
  • XMLhttpMain
  • Overview
  • Namespace
  • Class
  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: 
<?php

/**
 * This file has functions in it to do with authentication, user handling, and the like.
 *
 * Simple Machines Forum (SMF)
 *
 * @package SMF
 * @author Simple Machines https://www.simplemachines.org
 * @copyright 2020 Simple Machines and individual contributors
 * @license https://www.simplemachines.org/about/smf/license.php BSD
 *
 * @version 2.1 RC2
 */

if (!defined('SMF'))
    die('No direct access...');

/**
 * Sets the SMF-style login cookie and session based on the id_member and password passed.
 * - password should be already encrypted with the cookie salt.
 * - logs the user out if id_member is zero.
 * - sets the cookie and session to last the number of seconds specified by cookie_length, or
 *   ends them if cookie_length is less than 0.
 * - when logging out, if the globalCookies setting is enabled, attempts to clear the subdomain's
 *   cookie too.
 *
 * @param int $cookie_length How many seconds the cookie should last. If negative, forces logout.
 * @param int $id The ID of the member to set the cookie for
 * @param string $password The hashed password
 */
function setLoginCookie($cookie_length, $id, $password = '')
{
    global $smcFunc, $cookiename, $boardurl, $modSettings, $sourcedir;

    $id = (int) $id;

    $expiry_time = ($cookie_length >= 0 ? time() + $cookie_length : 1);

    // If changing state force them to re-address some permission caching.
    $_SESSION['mc']['time'] = 0;

    // Extract our cookie domain and path from $boardurl
    $cookie_url = url_parts(!empty($modSettings['localCookies']), !empty($modSettings['globalCookies']));

    // The cookie may already exist, and have been set with different options.
    if (isset($_COOKIE[$cookiename]))
    {
        // First check for 2.1 json-format cookie
        if (preg_match('~^{"0":\d+,"1":"[0-9a-f]*","2":\d+,"3":"[^"]+","4":"[^"]+"~', $_COOKIE[$cookiename]) === 1)
            list(,,, $old_domain, $old_path) = $smcFunc['json_decode']($_COOKIE[$cookiename], true);

        // Legacy format (for recent 2.0 --> 2.1 upgrades)
        elseif (preg_match('~^a:[34]:\{i:0;i:\d+;i:1;s:(0|128):"([a-fA-F0-9]{128})?";i:2;[id]:\d+;(i:3;i:\d;)?~', $_COOKIE[$cookiename]) === 1)
        {
            list(,,, $old_state) = safe_unserialize($_COOKIE[$cookiename]);

            $cookie_state = (empty($modSettings['localCookies']) ? 0 : 1) | (empty($modSettings['globalCookies']) ? 0 : 2);

            // Maybe we need to temporarily pretend to be using local cookies
            if ($cookie_state == 0 && $old_state == 1)
                list($old_domain, $old_path) = url_parts(true, false);
            else
                list($old_domain, $old_path) = url_parts($old_state & 1 > 0, $old_state & 2 > 0);
        }

        // Out with the old, in with the new!
        if (isset($old_domain) && $old_domain != $cookie_url[0] || isset($old_path) && $old_path != $cookie_url[1])
            smf_setcookie($cookiename, $smcFunc['json_encode'](array(0, '', 0, $old_domain, $old_path), JSON_FORCE_OBJECT), 1, $old_path, $old_domain);
    }

    // Get the data and path to set it on.
    $data = empty($id) ? array(0, '', 0, $cookie_url[0], $cookie_url[1]) : array($id, $password, $expiry_time, $cookie_url[0], $cookie_url[1]);

    // Allow mods to add custom info to the cookie
    $custom_data = array();
    call_integration_hook('integrate_cookie_data', array($data, &$custom_data));

    $data = $smcFunc['json_encode'](array_merge($data, $custom_data), JSON_FORCE_OBJECT);

    // Set the cookie, $_COOKIE, and session variable.
    smf_setcookie($cookiename, $data, $expiry_time, $cookie_url[1], $cookie_url[0]);

    // If subdomain-independent cookies are on, unset the subdomain-dependent cookie too.
    if (empty($id) && !empty($modSettings['globalCookies']))
        smf_setcookie($cookiename, $data, $expiry_time, $cookie_url[1], '');

    // Any alias URLs?  This is mainly for use with frames, etc.
    if (!empty($modSettings['forum_alias_urls']))
    {
        $aliases = explode(',', $modSettings['forum_alias_urls']);

        $temp = $boardurl;
        foreach ($aliases as $alias)
        {
            // Fake the $boardurl so we can set a different cookie.
            $alias = strtr(trim($alias), array('http://' => '', 'https://' => ''));
            $boardurl = 'http://' . $alias;

            $cookie_url = url_parts(!empty($modSettings['localCookies']), !empty($modSettings['globalCookies']));

            if ($cookie_url[0] == '')
                $cookie_url[0] = strtok($alias, '/');

            $alias_data = $smcFunc['json_decode']($data, true);
            $alias_data[3] = $cookie_url[0];
            $alias_data[4] = $cookie_url[1];
            $alias_data = $smcFunc['json_encode']($alias_data, JSON_FORCE_OBJECT);

            smf_setcookie($cookiename, $alias_data, $expiry_time, $cookie_url[1], $cookie_url[0]);
        }

        $boardurl = $temp;
    }

    $_COOKIE[$cookiename] = $data;

    // Make sure the user logs in with a new session ID.
    if (!isset($_SESSION['login_' . $cookiename]) || $_SESSION['login_' . $cookiename] !== $data)
    {
        // We need to meddle with the session.
        require_once($sourcedir . '/Session.php');

        // Backup and remove the old session.
        $oldSessionData = $_SESSION;
        $_SESSION = array();
        session_destroy();

        // Recreate and restore the new session.
        loadSession();
        // @todo should we use session_regenerate_id(true); now that we are 5.1+
        session_regenerate_id();
        $_SESSION = $oldSessionData;

        $_SESSION['login_' . $cookiename] = $data;
    }
}

/**
 * Sets Two Factor Auth cookie
 *
 * @param int $cookie_length How long the cookie should last, in seconds
 * @param int $id The ID of the member
 * @param string $secret Should be a salted secret using hash_salt
 */
function setTFACookie($cookie_length, $id, $secret)
{
    global $smcFunc, $modSettings, $cookiename;

    $expiry_time = ($cookie_length >= 0 ? time() + $cookie_length : 1);

    $identifier = $cookiename . '_tfa';
    $cookie_url = url_parts(!empty($modSettings['localCookies']), !empty($modSettings['globalCookies']));

    // Get the data and path to set it on.
    $data = $smcFunc['json_encode'](empty($id) ? array(0, '', 0, $cookie_url[0], $cookie_url[1], false) : array($id, $secret, $expiry_time, $cookie_url[0], $cookie_url[1]), JSON_FORCE_OBJECT);

    // Set the cookie, $_COOKIE, and session variable.
    smf_setcookie($identifier, $data, $expiry_time, $cookie_url[1], $cookie_url[0]);

    // If subdomain-independent cookies are on, unset the subdomain-dependent cookie too.
    if (empty($id) && !empty($modSettings['globalCookies']))
        smf_setcookie($identifier, $data, $expiry_time, $cookie_url[1], '');

    $_COOKIE[$identifier] = $data;
}

/**
 * Get the domain and path for the cookie
 * - normally, local and global should be the localCookies and globalCookies settings, respectively.
 * - uses boardurl to determine these two things.
 *
 * @param bool $local Whether we want local cookies
 * @param bool $global Whether we want global cookies
 * @return array An array to set the cookie on with domain and path in it, in that order
 */
function url_parts($local, $global)
{
    global $boardurl, $modSettings;

    // Parse the URL with PHP to make life easier.
    $parsed_url = parse_url($boardurl);

    // Is local cookies off?
    if (empty($parsed_url['path']) || !$local)
        $parsed_url['path'] = '';

    if (!empty($modSettings['globalCookiesDomain']) && strpos($boardurl, $modSettings['globalCookiesDomain']) !== false)
        $parsed_url['host'] = $modSettings['globalCookiesDomain'];

    // Globalize cookies across domains (filter out IP-addresses)?
    elseif ($global && preg_match('~^\d{1,3}(\.\d{1,3}){3}$~', $parsed_url['host']) == 0 && preg_match('~(?:[^\.]+\.)?([^\.]{2,}\..+)\z~i', $parsed_url['host'], $parts) == 1)
        $parsed_url['host'] = '.' . $parts[1];

    // We shouldn't use a host at all if both options are off.
    elseif (!$local && !$global)
        $parsed_url['host'] = '';

    // The host also shouldn't be set if there aren't any dots in it.
    elseif (!isset($parsed_url['host']) || strpos($parsed_url['host'], '.') === false)
        $parsed_url['host'] = '';

    return array($parsed_url['host'], $parsed_url['path'] . '/');
}

/**
 * Throws guests out to the login screen when guest access is off.
 * - sets $_SESSION['login_url'] to $_SERVER['REQUEST_URL'].
 * - uses the 'kick_guest' sub template found in Login.template.php.
 */
function KickGuest()
{
    global $txt, $context;

    loadLanguage('Login');
    loadTemplate('Login');
    createToken('login');

    // Never redirect to an attachment
    if (strpos($_SERVER['REQUEST_URL'], 'dlattach') === false)
        $_SESSION['login_url'] = $_SERVER['REQUEST_URL'];

    $context['sub_template'] = 'kick_guest';
    $context['page_title'] = $txt['login'];
}

/**
 * Display a message about the forum being in maintenance mode.
 * - display a login screen with sub template 'maintenance'.
 * - sends a 503 header, so search engines don't bother indexing while we're in maintenance mode.
 */
function InMaintenance()
{
    global $txt, $mtitle, $mmessage, $context, $smcFunc;

    loadLanguage('Login');
    loadTemplate('Login');
    createToken('login');

    // Send a 503 header, so search engines don't bother indexing while we're in maintenance mode.
    send_http_status(503, 'Service Temporarily Unavailable');

    // Basic template stuff..
    $context['sub_template'] = 'maintenance';
    $context['title'] = $smcFunc['htmlspecialchars']($mtitle);
    $context['description'] = &$mmessage;
    $context['page_title'] = $txt['maintain_mode'];
}

/**
 * Question the verity of the admin by asking for his or her password.
 * - loads Login.template.php and uses the admin_login sub template.
 * - sends data to template so the admin is sent on to the page they
 *   wanted if their password is correct, otherwise they can try again.
 *
 * @param string $type What login type is this - can be 'admin' or 'moderate'
 */
function adminLogin($type = 'admin')
{
    global $context, $txt, $user_info;

    loadLanguage('Admin');
    loadTemplate('Login');

    // Validate what type of session check this is.
    $types = array();
    call_integration_hook('integrate_validateSession', array(&$types));
    $type = in_array($type, $types) || $type == 'moderate' ? $type : 'admin';

    // They used a wrong password, log it and unset that.
    if (isset($_POST[$type . '_hash_pass']) || isset($_POST[$type . '_pass']))
    {
        $txt['security_wrong'] = sprintf($txt['security_wrong'], isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : $txt['unknown'], $_SERVER['HTTP_USER_AGENT'], $user_info['ip']);
        log_error($txt['security_wrong'], 'critical');

        if (isset($_POST[$type . '_hash_pass']))
            unset($_POST[$type . '_hash_pass']);
        if (isset($_POST[$type . '_pass']))
            unset($_POST[$type . '_pass']);

        $context['incorrect_password'] = true;
    }

    createToken('admin-login');

    // Figure out the get data and post data.
    $context['get_data'] = '?' . construct_query_string($_GET);
    $context['post_data'] = '';

    // Now go through $_POST.  Make sure the session hash is sent.
    $_POST[$context['session_var']] = $context['session_id'];
    foreach ($_POST as $k => $v)
        $context['post_data'] .= adminLogin_outputPostVars($k, $v);

    // Now we'll use the admin_login sub template of the Login template.
    $context['sub_template'] = 'admin_login';

    // And title the page something like "Login".
    if (!isset($context['page_title']))
        $context['page_title'] = $txt['login'];

    // The type of action.
    $context['sessionCheckType'] = $type;

    obExit();

    // We MUST exit at this point, because otherwise we CANNOT KNOW that the user is privileged.
    trigger_error('Hacking attempt...', E_USER_ERROR);
}

/**
 * Used by the adminLogin() function.
 * if 'value' is an array, the function is called recursively.
 *
 * @param string $k The keys
 * @param string $v The values
 * @return string 'hidden' HTML form fields, containing key-value-pairs
 */
function adminLogin_outputPostVars($k, $v)
{
    global $smcFunc;

    if (!is_array($v))
        return '
<input type="hidden" name="' . $smcFunc['htmlspecialchars']($k) . '" value="' . strtr($v, array('"' => '&quot;', '<' => '&lt;', '>' => '&gt;')) . '">';
    else
    {
        $ret = '';
        foreach ($v as $k2 => $v2)
            $ret .= adminLogin_outputPostVars($k . '[' . $k2 . ']', $v2);

        return $ret;
    }
}

/**
 * Properly urlencodes a string to be used in a query
 *
 * @param string $get
 * @return string Our query string
 */
function construct_query_string($get)
{
    global $scripturl;

    $query_string = '';

    // Awww, darn.  The $scripturl contains GET stuff!
    $q = strpos($scripturl, '?');
    if ($q !== false)
    {
        parse_str(preg_replace('/&(\w+)(?=&|$)/', '&$1=', strtr(substr($scripturl, $q + 1), ';', '&')), $temp);

        foreach ($get as $k => $v)
        {
            // Only if it's not already in the $scripturl!
            if (!isset($temp[$k]))
                $query_string .= urlencode($k) . '=' . urlencode($v) . ';';
            // If it changed, put it out there, but with an ampersand.
            elseif ($temp[$k] != $get[$k])
                $query_string .= urlencode($k) . '=' . urlencode($v) . '&amp;';
        }
    }
    else
    {
        // Add up all the data from $_GET into get_data.
        foreach ($get as $k => $v)
            $query_string .= urlencode($k) . '=' . urlencode($v) . ';';
    }

    $query_string = substr($query_string, 0, -1);
    return $query_string;
}

/**
 * Finds members by email address, username, or real name.
 * - searches for members whose username, display name, or e-mail address match the given pattern of array names.
 * - searches only buddies if buddies_only is set.
 *
 * @param array $names The names of members to search for
 * @param bool $use_wildcards Whether to use wildcards. Accepts wildcards ? and * in the pattern if true
 * @param bool $buddies_only Whether to only search for the user's buddies
 * @param int $max The maximum number of results
 * @return array An array containing information about the matching members
 */
function findMembers($names, $use_wildcards = false, $buddies_only = false, $max = 500)
{
    global $scripturl, $user_info, $smcFunc;

    // If it's not already an array, make it one.
    if (!is_array($names))
        $names = explode(',', $names);

    $maybe_email = false;
    $names_list = array();
    foreach ($names as $i => $name)
    {
        // Trim, and fix wildcards for each name.
        $names[$i] = trim($smcFunc['strtolower']($name));

        $maybe_email |= strpos($name, '@') !== false;

        // Make it so standard wildcards will work. (* and ?)
        if ($use_wildcards)
            $names[$i] = strtr($names[$i], array('%' => '\%', '_' => '\_', '*' => '%', '?' => '_', '\'' => '&#039;'));
        else
            $names[$i] = strtr($names[$i], array('\'' => '&#039;'));

        $names_list[] = '{string:lookup_name_' . $i . '}';
        $where_params['lookup_name_' . $i] = $names[$i];
    }

    // What are we using to compare?
    $comparison = $use_wildcards ? 'LIKE' : '=';

    // Nothing found yet.
    $results = array();

    // This ensures you can't search someones email address if you can't see it.
    if (($use_wildcards || $maybe_email) && allowedTo('moderate_forum'))
        $email_condition = '
            OR (email_address ' . $comparison . ' \'' . implode('\') OR (email_address ' . $comparison . ' \'', $names) . '\')';
    else
        $email_condition = '';

    // Get the case of the columns right - but only if we need to as things like MySQL will go slow needlessly otherwise.
    $member_name = $smcFunc['db_case_sensitive'] ? 'LOWER(member_name)' : 'member_name';
    $real_name = $smcFunc['db_case_sensitive'] ? 'LOWER(real_name)' : 'real_name';

    // Searches.
    $member_name_search = $member_name . ' ' . $comparison . ' ' . implode(' OR ' . $member_name . ' ' . $comparison . ' ', $names_list);
    $real_name_search = $real_name . ' ' . $comparison . ' ' . implode(' OR ' . $real_name . ' ' . $comparison . ' ', $names_list);

    // Search by username, display name, and email address.
    $request = $smcFunc['db_query']('', '
        SELECT id_member, member_name, real_name, email_address
        FROM {db_prefix}members
        WHERE (' . $member_name_search . '
            OR ' . $real_name_search . ' ' . $email_condition . ')
            ' . ($buddies_only ? 'AND id_member IN ({array_int:buddy_list})' : '') . '
            AND is_activated IN (1, 11)
        LIMIT {int:limit}',
        array_merge($where_params, array(
            'buddy_list' => $user_info['buddies'],
            'limit' => $max,
        ))
    );
    while ($row = $smcFunc['db_fetch_assoc']($request))
    {
        $results[$row['id_member']] = array(
            'id' => $row['id_member'],
            'name' => $row['real_name'],
            'username' => $row['member_name'],
            'email' => allowedTo('moderate_forum') ? $row['email_address'] : '',
            'href' => $scripturl . '?action=profile;u=' . $row['id_member'],
            'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>'
        );
    }
    $smcFunc['db_free_result']($request);

    // Return all the results.
    return $results;
}

/**
 * Called by index.php?action=findmember.
 * - is used as a popup for searching members.
 * - uses sub template find_members of the Help template.
 * - also used to add members for PM's sent using wap2/imode protocol.
 */
function JSMembers()
{
    global $context, $scripturl, $user_info, $smcFunc;

    checkSession('get');

    // Why is this in the Help template, you ask?  Well, erm... it helps you.  Does that work?
    loadTemplate('Help');

    $context['template_layers'] = array();
    $context['sub_template'] = 'find_members';

    if (isset($_REQUEST['search']))
        $context['last_search'] = $smcFunc['htmlspecialchars']($_REQUEST['search'], ENT_QUOTES);
    else
        $_REQUEST['start'] = 0;

    // Allow the user to pass the input to be added to to the box.
    $context['input_box_name'] = isset($_REQUEST['input']) && preg_match('~^[\w-]+$~', $_REQUEST['input']) === 1 ? $_REQUEST['input'] : 'to';

    // Take the delimiter over GET in case it's \n or something.
    $context['delimiter'] = isset($_REQUEST['delim']) ? ($_REQUEST['delim'] == 'LB' ? "\n" : $_REQUEST['delim']) : ', ';
    $context['quote_results'] = !empty($_REQUEST['quote']);

    // List all the results.
    $context['results'] = array();

    // Some buddy related settings ;)
    $context['show_buddies'] = !empty($user_info['buddies']);
    $context['buddy_search'] = isset($_REQUEST['buddies']);

    // If the user has done a search, well - search.
    if (isset($_REQUEST['search']))
    {
        $_REQUEST['search'] = $smcFunc['htmlspecialchars']($_REQUEST['search'], ENT_QUOTES);

        $context['results'] = findMembers(array($_REQUEST['search']), true, $context['buddy_search']);
        $total_results = count($context['results']);

        $context['page_index'] = constructPageIndex($scripturl . '?action=findmember;search=' . $context['last_search'] . ';' . $context['session_var'] . '=' . $context['session_id'] . ';input=' . $context['input_box_name'] . ($context['quote_results'] ? ';quote=1' : '') . ($context['buddy_search'] ? ';buddies' : ''), $_REQUEST['start'], $total_results, 7);

        // Determine the navigation context.
        $base_url = $scripturl . '?action=findmember;search=' . urlencode($context['last_search']) . (empty($_REQUEST['u']) ? '' : ';u=' . $_REQUEST['u']) . ';' . $context['session_var'] . '=' . $context['session_id'];
        $context['links'] = array(
            'first' => $_REQUEST['start'] >= 7 ? $base_url . ';start=0' : '',
            'prev' => $_REQUEST['start'] >= 7 ? $base_url . ';start=' . ($_REQUEST['start'] - 7) : '',
            'next' => $_REQUEST['start'] + 7 < $total_results ? $base_url . ';start=' . ($_REQUEST['start'] + 7) : '',
            'last' => $_REQUEST['start'] + 7 < $total_results ? $base_url . ';start=' . (floor(($total_results - 1) / 7) * 7) : '',
            'up' => $scripturl . '?action=pm;sa=send' . (empty($_REQUEST['u']) ? '' : ';u=' . $_REQUEST['u']),
        );
        $context['page_info'] = array(
            'current_page' => $_REQUEST['start'] / 7 + 1,
            'num_pages' => floor(($total_results - 1) / 7) + 1
        );

        $context['results'] = array_slice($context['results'], $_REQUEST['start'], 7);
    }
    else
        $context['links']['up'] = $scripturl . '?action=pm;sa=send' . (empty($_REQUEST['u']) ? '' : ';u=' . $_REQUEST['u']);
}

/**
 * Outputs each member name on its own line.
 * - used by javascript to find members matching the request.
 */
function RequestMembers()
{
    global $user_info, $txt, $smcFunc;

    checkSession('get');

    $_REQUEST['search'] = $smcFunc['htmlspecialchars']($_REQUEST['search']) . '*';
    $_REQUEST['search'] = trim($smcFunc['strtolower']($_REQUEST['search']));
    $_REQUEST['search'] = strtr($_REQUEST['search'], array('%' => '\%', '_' => '\_', '*' => '%', '?' => '_', '&#038;' => '&amp;'));

    if (function_exists('iconv'))
        header('content-type: text/plain; charset=UTF-8');

    $request = $smcFunc['db_query']('', '
        SELECT real_name
        FROM {db_prefix}members
        WHERE {raw:real_name} LIKE {string:search}' . (isset($_REQUEST['buddies']) ? '
            AND id_member IN ({array_int:buddy_list})' : '') . '
            AND is_activated IN (1, 11)
        LIMIT ' . ($smcFunc['strlen']($_REQUEST['search']) <= 2 ? '100' : '800'),
        array(
            'real_name' => $smcFunc['db_case_sensitive'] ? 'LOWER(real_name)' : 'real_name',
            'buddy_list' => $user_info['buddies'],
            'search' => $_REQUEST['search'],
        )
    );
    while ($row = $smcFunc['db_fetch_assoc']($request))
    {
        if (function_exists('iconv'))
        {
            $utf8 = iconv($txt['lang_character_set'], 'UTF-8', $row['real_name']);
            if ($utf8)
                $row['real_name'] = $utf8;
        }

        $row['real_name'] = strtr($row['real_name'], array('&amp;' => '&#038;', '&lt;' => '&#060;', '&gt;' => '&#062;', '&quot;' => '&#034;'));

        if (preg_match('~&#\d+;~', $row['real_name']) != 0)
            $row['real_name'] = preg_replace_callback('~&#(\d+);~', 'fixchar__callback', $row['real_name']);

        echo $row['real_name'], "\n";
    }
    $smcFunc['db_free_result']($request);

    obExit(false);
}

/**
 * Generates a random password for a user and emails it to them.
 * - called by Profile.php when changing someone's username.
 * - checks the validity of the new username.
 * - generates and sets a new password for the given user.
 * - mails the new password to the email address of the user.
 * - if username is not set, only a new password is generated and sent.
 *
 * @param int $memID The ID of the member
 * @param string $username The new username. If set, also checks the validity of the username
 */
function resetPassword($memID, $username = null)
{
    global $sourcedir, $modSettings, $smcFunc, $language;

    // Language... and a required file.
    loadLanguage('Login');
    require_once($sourcedir . '/Subs-Post.php');

    // Get some important details.
    $request = $smcFunc['db_query']('', '
        SELECT member_name, email_address, lngfile
        FROM {db_prefix}members
        WHERE id_member = {int:id_member}',
        array(
            'id_member' => $memID,
        )
    );
    list ($user, $email, $lngfile) = $smcFunc['db_fetch_row']($request);
    $smcFunc['db_free_result']($request);

    if ($username !== null)
    {
        $old_user = $user;
        $user = trim($username);
    }

    // Generate a random password.
    $newPassword = substr(preg_replace('/\W/', '', md5($smcFunc['random_int']())), 0, 10);
    $newPassword_sha1 = hash_password($user, $newPassword);

    // Do some checks on the username if needed.
    if ($username !== null)
    {
        validateUsername($memID, $user);

        // Update the database...
        updateMemberData($memID, array('member_name' => $user, 'passwd' => $newPassword_sha1));
    }
    else
        updateMemberData($memID, array('passwd' => $newPassword_sha1));

    call_integration_hook('integrate_reset_pass', array($old_user, $user, $newPassword));

    $replacements = array(
        'USERNAME' => $user,
        'PASSWORD' => $newPassword,
    );

    $emaildata = loadEmailTemplate('change_password', $replacements, empty($lngfile) || empty($modSettings['userLanguage']) ? $language : $lngfile);

    // Send them the email informing them of the change - then we're done!
    sendmail($email, $emaildata['subject'], $emaildata['body'], null, 'chgpass' . $memID, $emaildata['is_html'], 0);
}

/**
 * Checks a username obeys a load of rules
 *
 * @param int $memID The ID of the member
 * @param string $username The username to validate
 * @param boolean $return_error Whether to return errors
 * @param boolean $check_reserved_name Whether to check this against the list of reserved names
 * @return array|null Null if there are no errors, otherwise an array of errors if return_error is true
 */
function validateUsername($memID, $username, $return_error = false, $check_reserved_name = true)
{
    global $sourcedir, $txt, $smcFunc, $user_info;

    $errors = array();

    // Don't use too long a name.
    if ($smcFunc['strlen']($username) > 25)
        $errors[] = array('lang', 'error_long_name');

    // No name?!  How can you register with no name?
    if ($username == '')
        $errors[] = array('lang', 'need_username');

    // Only these characters are permitted.
    if (in_array($username, array('_', '|')) || preg_match('~[<>&"\'=\\\\]~', preg_replace('~&#(?:\\d{1,7}|x[0-9a-fA-F]{1,6});~', '', $username)) != 0 || strpos($username, '[code') !== false || strpos($username, '[/code') !== false)
        $errors[] = array('lang', 'error_invalid_characters_username');

    if (stristr($username, $txt['guest_title']) !== false)
        $errors[] = array('lang', 'username_reserved', 'general', array($txt['guest_title']));

    if ($check_reserved_name)
    {
        require_once($sourcedir . '/Subs-Members.php');
        if (isReservedName($username, $memID, false))
            $errors[] = array('done', '(' . $smcFunc['htmlspecialchars']($username) . ') ' . $txt['name_in_use']);
    }

    if ($return_error)
        return $errors;
    elseif (empty($errors))
        return null;

    loadLanguage('Errors');
    $error = $errors[0];

    $message = $error[0] == 'lang' ? (empty($error[3]) ? $txt[$error[1]] : vsprintf($txt[$error[1]], $error[3])) : $error[1];
    fatal_error($message, empty($error[2]) || $user_info['is_admin'] ? false : $error[2]);
}

/**
 * Checks whether a password meets the current forum rules
 * - called when registering/choosing a password.
 * - checks the password obeys the current forum settings for password strength.
 * - if password checking is enabled, will check that none of the words in restrict_in appear in the password.
 * - returns an error identifier if the password is invalid, or null.
 *
 * @param string $password The desired password
 * @param string $username The username
 * @param array $restrict_in An array of restricted strings that cannot be part of the password (email address, username, etc.)
 * @return null|string Null if valid or a string indicating what the problem was
 */
function validatePassword($password, $username, $restrict_in = array())
{
    global $modSettings, $smcFunc;

    // Perform basic requirements first.
    if ($smcFunc['strlen']($password) < (empty($modSettings['password_strength']) ? 4 : 8))
        return 'short';

    // Is this enough?
    if (empty($modSettings['password_strength']))
        return null;

    // Otherwise, perform the medium strength test - checking if password appears in the restricted string.
    if (preg_match('~\b' . preg_quote($password, '~') . '\b~', implode(' ', $restrict_in)) != 0)
        return 'restricted_words';
    elseif ($smcFunc['strpos']($password, $username) !== false)
        return 'restricted_words';

    // If just medium, we're done.
    if ($modSettings['password_strength'] == 1)
        return null;

    // Otherwise, hard test next, check for numbers and letters, uppercase too.
    $good = preg_match('~(\D\d|\d\D)~', $password) != 0;
    $good &= $smcFunc['strtolower']($password) != $password;

    return $good ? null : 'chars';
}

/**
 * Quickly find out what moderation authority this user has
 * - builds the moderator, group and board level querys for the user
 * - stores the information on the current users moderation powers in $user_info['mod_cache'] and $_SESSION['mc']
 */
function rebuildModCache()
{
    global $user_info, $smcFunc;

    // What groups can they moderate?
    $group_query = allowedTo('manage_membergroups') ? '1=1' : '0=1';

    if ($group_query == '0=1' && !$user_info['is_guest'])
    {
        $request = $smcFunc['db_query']('', '
            SELECT id_group
            FROM {db_prefix}group_moderators
            WHERE id_member = {int:current_member}',
            array(
                'current_member' => $user_info['id'],
            )
        );
        $groups = array();
        while ($row = $smcFunc['db_fetch_assoc']($request))
            $groups[] = $row['id_group'];
        $smcFunc['db_free_result']($request);

        if (empty($groups))
            $group_query = '0=1';
        else
            $group_query = 'id_group IN (' . implode(',', $groups) . ')';
    }

    // Then, same again, just the boards this time!
    $board_query = allowedTo('moderate_forum') ? '1=1' : '0=1';

    if ($board_query == '0=1' && !$user_info['is_guest'])
    {
        $boards = boardsAllowedTo('moderate_board', true);

        if (empty($boards))
            $board_query = '0=1';
        else
            $board_query = 'id_board IN (' . implode(',', $boards) . ')';
    }

    // What boards are they the moderator of?
    $boards_mod = array();
    if (!$user_info['is_guest'])
    {
        $request = $smcFunc['db_query']('', '
            SELECT id_board
            FROM {db_prefix}moderators
            WHERE id_member = {int:current_member}',
            array(
                'current_member' => $user_info['id'],
            )
        );
        while ($row = $smcFunc['db_fetch_assoc']($request))
            $boards_mod[] = $row['id_board'];
        $smcFunc['db_free_result']($request);

        // Can any of the groups they're in moderate any of the boards?
        $request = $smcFunc['db_query']('', '
            SELECT id_board
            FROM {db_prefix}moderator_groups
            WHERE id_group IN({array_int:groups})',
            array(
                'groups' => $user_info['groups'],
            )
        );
        while ($row = $smcFunc['db_fetch_assoc']($request))
            $boards_mod[] = $row['id_board'];
        $smcFunc['db_free_result']($request);

        // Just in case we've got duplicates here...
        $boards_mod = array_unique($boards_mod);
    }

    $mod_query = empty($boards_mod) ? '0=1' : 'b.id_board IN (' . implode(',', $boards_mod) . ')';

    $_SESSION['mc'] = array(
        'time' => time(),
        // This looks a bit funny but protects against the login redirect.
        'id' => $user_info['id'] && $user_info['name'] ? $user_info['id'] : 0,
        // If you change the format of 'gq' and/or 'bq' make sure to adjust 'can_mod' in Load.php.
        'gq' => $group_query,
        'bq' => $board_query,
        'ap' => boardsAllowedTo('approve_posts'),
        'mb' => $boards_mod,
        'mq' => $mod_query,
    );
    call_integration_hook('integrate_mod_cache');

    $user_info['mod_cache'] = $_SESSION['mc'];

    // Might as well clean up some tokens while we are at it.
    cleanTokens();
}

/**
 * A wrapper for setcookie that gives integration hook access to it
 *
 * @param string $name
 * @param string $value = ''
 * @param int $expire = 0
 * @param string $path = ''
 * @param string $domain = ''
 * @param bool $secure = false
 * @param bool $httponly = true
 */
function smf_setcookie($name, $value = '', $expire = 0, $path = '', $domain = '', $secure = null, $httponly = true)
{
    global $modSettings;

    // In case a customization wants to override the default settings
    if ($httponly === null)
        $httponly = !empty($modSettings['httponlyCookies']);
    if ($secure === null)
        $secure = !empty($modSettings['secureCookies']);

    // Intercept cookie?
    call_integration_hook('integrate_cookie', array($name, $value, $expire, $path, $domain, $secure, $httponly));

    return setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
}

/**
 * Hashes username with password
 *
 * @param string $username The username
 * @param string $password The unhashed password
 * @param int $cost The cost
 * @return string The hashed password
 */
function hash_password($username, $password, $cost = null)
{
    global $sourcedir, $smcFunc, $modSettings;
    if (!function_exists('password_hash'))
        require_once($sourcedir . '/Subs-Password.php');

    $cost = empty($cost) ? (empty($modSettings['bcrypt_hash_cost']) ? 10 : $modSettings['bcrypt_hash_cost']) : $cost;

    return password_hash($smcFunc['strtolower']($username) . $password, PASSWORD_BCRYPT, array(
        'cost' => $cost,
    ));
}

/**
 * Hashes password with salt, this is solely used for cookies.
 *
 * @param string $password The password
 * @param string $salt The salt
 * @return string The hashed password
 */
function hash_salt($password, $salt)
{
    return hash('sha512', $password . $salt);
}

/**
 * Verifies a raw SMF password against the bcrypt'd string
 *
 * @param string $username The username
 * @param string $password The password
 * @param string $hash The hashed string
 * @return bool Whether the hashed password matches the string
 */
function hash_verify_password($username, $password, $hash)
{
    global $sourcedir, $smcFunc;
    if (!function_exists('password_verify'))
        require_once($sourcedir . '/Subs-Password.php');

    return password_verify($smcFunc['strtolower']($username) . $password, $hash);
}

/**
 * Returns the length for current hash
 *
 * @return int The length for the current hash
 */
function hash_length()
{
    return 60;
}

/**
 * Benchmarks the server to figure out an appropriate cost factor (minimum 9)
 *
 * @param float $hashTime Time to target, in seconds
 * @return int The cost
 */
function hash_benchmark($hashTime = 0.2)
{
    $cost = 9;
    do
    {
        $timeStart = microtime(true);
        hash_password('test', 'thisisatestpassword', $cost);
        $timeTaken = microtime(true) - $timeStart;
        $cost++;
    }
    while ($timeTaken < $hashTime);

    return $cost;
}

?>
API documentation generated by ApiGen