Repository: rathena/FluxCP Branch: master Commit: 98cd4b8fd832 Files: 559 Total size: 1.7 MB Directory structure: gitextract_z0fge0vx/ ├── .deepsource.toml ├── .editorconfig ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ ├── config.yml │ │ └── enhancement_request.yml │ ├── PULL_REQUEST_TEMPLATE/ │ │ └── pull_request_template.md │ ├── pull_request_template.md │ └── workflows/ │ └── codeql.yml ├── .gitignore ├── .htaccess ├── LICENSE ├── README.md ├── addons/ │ └── helloworld/ │ ├── config/ │ │ ├── access.php │ │ └── addon.php │ ├── lang/ │ │ ├── en_us.php │ │ └── ko_kr.php │ ├── modules/ │ │ └── helloworld/ │ │ └── index.php │ └── themes/ │ └── default/ │ └── helloworld/ │ └── index.php ├── config/ │ ├── .htaccess │ ├── access.php │ ├── application.php │ ├── attributes.php │ ├── cashshopcategories.php │ ├── castlenames.php │ ├── elements.php │ ├── equip_jobs.php │ ├── equip_location_combinations.php │ ├── equip_locations.php │ ├── equip_upper.php │ ├── error.php │ ├── feedingtypes.php │ ├── groups.php │ ├── homunculus.php │ ├── item_randoptions.php │ ├── itemsflags.php │ ├── itemsubtypes.php │ ├── itemtypes.php │ ├── jobs.php │ ├── jobs_alchemist.php │ ├── jobs_blacksmith.php │ ├── jobs_gender_linked.php │ ├── loginerrors.php │ ├── monster_ai.php │ ├── monstermode.php │ ├── picktypes.php │ ├── races.php │ ├── servers.php │ ├── shopcategories.php │ ├── sizes.php │ └── trade_restrictions.php ├── data/ │ ├── captcha/ │ │ ├── fonts/ │ │ │ └── index.html │ │ └── index.html │ ├── emblem/ │ │ └── index.html │ ├── index.html │ ├── items/ │ │ ├── icons/ │ │ │ └── index.html │ │ ├── images/ │ │ │ └── index.html │ │ └── index.html │ ├── itemshop/ │ │ └── index.html │ ├── jobs/ │ │ ├── images/ │ │ │ ├── F/ │ │ │ │ └── index.html │ │ │ ├── M/ │ │ │ │ └── index.html │ │ │ └── index.html │ │ └── index.html │ ├── logs/ │ │ └── index.html │ ├── monsters/ │ │ └── index.html │ ├── npc/ │ │ ├── DonationNPC.txt │ │ ├── PeakNPC.txt │ │ ├── index.html │ │ ├── support_cmd.txt │ │ └── web_commands.txt │ ├── paypal/ │ │ ├── button.php │ │ └── index.html │ ├── schemas/ │ │ ├── charmapdb/ │ │ │ ├── cp_charprefs.20080929191525.sql │ │ │ ├── cp_charprefs.20081109093448.sql │ │ │ ├── cp_charprefs.20120816150540.sql │ │ │ ├── cp_commands.20160608065501.sql │ │ │ ├── cp_itemdesc.20170210033400.sql │ │ │ ├── cp_itemshop.20080928225124.sql │ │ │ ├── cp_itemshop.20081109093448.sql │ │ │ ├── cp_itemshop.20081128093449.sql │ │ │ ├── cp_itemshop.20090104190020.sql │ │ │ ├── cp_onlinepeak.20131120120201.sql │ │ │ ├── cp_redeemlog.20080928225124.sql │ │ │ ├── cp_redeemlog.20081001054354.sql │ │ │ ├── cp_redeemlog.20081109093448.sql │ │ │ ├── cp_xferlog.20080928225124.sql │ │ │ ├── cp_xferlog.20081109093448.sql │ │ │ └── index.html │ │ ├── index.html │ │ └── logindb/ │ │ ├── cp_banlog.20131213174201.sql │ │ ├── cp_cmsnews.20131120145701.sql │ │ ├── cp_cmspages.20131120161901.sql │ │ ├── cp_cmssettings.20131120145801.sql │ │ ├── cp_createlog.20131213174201.sql │ │ ├── cp_createlog.20170720151901.sql │ │ ├── cp_createlog.20250614124331.sql │ │ ├── cp_credits.20131213174201.sql │ │ ├── cp_emailchange.20131213174201.sql │ │ ├── cp_emailchange.20250609133400.sql │ │ ├── cp_ipbanlog.20120816150540.sql │ │ ├── cp_ipbanlog.20250609133400.sql │ │ ├── cp_loginlog.20131213174201.sql │ │ ├── cp_loginlog.20250609133400.sql │ │ ├── cp_loginprefs.20131213174201.sql │ │ ├── cp_pwchange.20131213174201.sql │ │ ├── cp_pwchange.20250609133400.sql │ │ ├── cp_resetpass.20131213174201.sql │ │ ├── cp_resetpass.20250609133400.sql │ │ ├── cp_servicedesk.20131122010001.sql │ │ ├── cp_servicedesk.20250609133400.sql │ │ ├── cp_servicedeska.20131122010001.sql │ │ ├── cp_servicedeska.20250609133400.sql │ │ ├── cp_servicedeskcat.20131122010001.sql │ │ ├── cp_servicedesksettings.20131122010001.sql │ │ ├── cp_trusted.20131213174201.sql │ │ ├── cp_txnlog.20131213174201.sql │ │ ├── cp_txnlog.20170217073601.sql │ │ ├── cp_txnlog.20170221184601.sql │ │ └── index.html │ ├── templates/ │ │ ├── changemail.php │ │ ├── confirm.php │ │ ├── contactform.php │ │ ├── index.html │ │ ├── marketing1.php │ │ ├── newpass.php │ │ ├── newticket.php │ │ ├── resetpass.php │ │ └── ticketreply.php │ └── tmp/ │ ├── index.html │ └── transactions/ │ ├── Refunded/ │ │ └── index.html │ ├── Reversed/ │ │ └── index.html │ └── web_accept/ │ ├── Completed/ │ │ └── index.html │ ├── Denied/ │ │ └── index.html │ └── Pending/ │ └── index.html ├── doc/ │ ├── user_lang.md │ └── user_theme.md ├── error.php ├── index.php ├── lang/ │ ├── en_us.php │ ├── es_es.php │ ├── id_id.php │ └── pt_br.php ├── lib/ │ ├── Flux/ │ │ ├── Addon.php │ │ ├── Athena.php │ │ ├── Authorization.php │ │ ├── BaseServer.php │ │ ├── Captcha.php │ │ ├── CharServer.php │ │ ├── Config.php │ │ ├── Connection/ │ │ │ ├── Statement.php │ │ │ └── index.html │ │ ├── Connection.php │ │ ├── DataObject.php │ │ ├── Dispatcher.php │ │ ├── EmblemExporter.php │ │ ├── Error.php │ │ ├── FileLoad.php │ │ ├── Installer/ │ │ │ ├── CharMapServer.php │ │ │ ├── MainServer.php │ │ │ ├── Schema.php │ │ │ ├── SchemaPermissionError.php │ │ │ └── index.html │ │ ├── Installer.php │ │ ├── ItemExistsError.php │ │ ├── ItemShop/ │ │ │ ├── Cart.php │ │ │ └── index.html │ │ ├── ItemShop.php │ │ ├── LogFile.php │ │ ├── LoginAthenaGroup.php │ │ ├── LoginError.php │ │ ├── LoginServer.php │ │ ├── Mailer.php │ │ ├── MapServer.php │ │ ├── Paginator.php │ │ ├── PaymentNotifyRequest.php │ │ ├── PermissionError.php │ │ ├── RegisterError.php │ │ ├── SessionData.php │ │ ├── Template.php │ │ ├── TemporaryTable.php │ │ └── index.html │ ├── Flux.php │ ├── functions/ │ │ ├── discordwebhook.php │ │ ├── getReposVersion.php │ │ ├── imagecreatefrombmpstring.php │ │ └── index.html │ ├── index.html │ └── phpmailer/ │ ├── LICENSE │ ├── PHPMailerAutoload.php │ ├── VERSION │ ├── class.phpmailer.php │ ├── class.pop3.php │ ├── class.smtp.php │ ├── extras/ │ │ ├── EasyPeasyICS.php │ │ ├── README.md │ │ ├── htmlfilter.php │ │ └── ntlm_sasl_client.php │ ├── index.html │ └── language/ │ ├── index.html │ ├── phpmailer.lang-am.php │ ├── phpmailer.lang-ar.php │ ├── phpmailer.lang-az.php │ ├── phpmailer.lang-be.php │ ├── phpmailer.lang-bg.php │ ├── phpmailer.lang-br.php │ ├── phpmailer.lang-ca.php │ ├── phpmailer.lang-ch.php │ ├── phpmailer.lang-cs.php │ ├── phpmailer.lang-cz.php │ ├── phpmailer.lang-da.php │ ├── phpmailer.lang-de.php │ ├── phpmailer.lang-dk.php │ ├── phpmailer.lang-el.php │ ├── phpmailer.lang-eo.php │ ├── phpmailer.lang-es.php │ ├── phpmailer.lang-et.php │ ├── phpmailer.lang-fa.php │ ├── phpmailer.lang-fi.php │ ├── phpmailer.lang-fo.php │ ├── phpmailer.lang-fr.php │ ├── phpmailer.lang-gl.php │ ├── phpmailer.lang-he.php │ ├── phpmailer.lang-hr.php │ ├── phpmailer.lang-hu.php │ ├── phpmailer.lang-id.php │ ├── phpmailer.lang-it.php │ ├── phpmailer.lang-ja.php │ ├── phpmailer.lang-ka.php │ ├── phpmailer.lang-ko.php │ ├── phpmailer.lang-lt.php │ ├── phpmailer.lang-lv.php │ ├── phpmailer.lang-ms.php │ ├── phpmailer.lang-nb.php │ ├── phpmailer.lang-nl.php │ ├── phpmailer.lang-no.php │ ├── phpmailer.lang-pl.php │ ├── phpmailer.lang-pt.php │ ├── phpmailer.lang-pt_br.php │ ├── phpmailer.lang-ro.php │ ├── phpmailer.lang-ru.php │ ├── phpmailer.lang-se.php │ ├── phpmailer.lang-sk.php │ ├── phpmailer.lang-sl.php │ ├── phpmailer.lang-sr.php │ ├── phpmailer.lang-sv.php │ ├── phpmailer.lang-tr.php │ ├── phpmailer.lang-uk.php │ ├── phpmailer.lang-vi.php │ ├── phpmailer.lang-zh.php │ └── phpmailer.lang-zh_cn.php ├── modules/ │ ├── .htaccess │ ├── account/ │ │ ├── cart.php │ │ ├── changemail.php │ │ ├── changepass.php │ │ ├── changesex.php │ │ ├── confirm.php │ │ ├── confirmemail.php │ │ ├── create.php │ │ ├── edit.php │ │ ├── index.php │ │ ├── login.php │ │ ├── logout.php │ │ ├── pagemenu/ │ │ │ └── view.php │ │ ├── prune.php │ │ ├── resend.php │ │ ├── resetpass.php │ │ ├── resetpw.php │ │ ├── transfer.php │ │ ├── view.php │ │ └── xferlog.php │ ├── auction/ │ │ └── index.php │ ├── buyingstore/ │ │ ├── index.php │ │ └── viewshop.php │ ├── captcha/ │ │ └── index.php │ ├── castle/ │ │ └── index.php │ ├── character/ │ │ ├── changeslot.php │ │ ├── divorce.php │ │ ├── index.php │ │ ├── mapstats.php │ │ ├── online.php │ │ ├── pagemenu/ │ │ │ └── view.php │ │ ├── prefs.php │ │ ├── resetlook.php │ │ ├── resetpos.php │ │ └── view.php │ ├── cplog/ │ │ ├── ban.php │ │ ├── changemail.php │ │ ├── changepass.php │ │ ├── create.php │ │ ├── index.php │ │ ├── ipban.php │ │ ├── login.php │ │ ├── paypal.php │ │ ├── resetpass.php │ │ └── txnview.php │ ├── donate/ │ │ ├── complete.php │ │ ├── history.php │ │ ├── index.php │ │ ├── notify.php │ │ ├── trusted.php │ │ └── update.php │ ├── economy/ │ │ └── index.php │ ├── errors/ │ │ ├── missing_action.php │ │ └── missing_view.php │ ├── forum/ │ │ └── index.php │ ├── guild/ │ │ ├── emblem.php │ │ ├── export.php │ │ ├── index.php │ │ └── view.php │ ├── history/ │ │ ├── cplogin.php │ │ ├── emailchange.php │ │ ├── gamelogin.php │ │ ├── index.php │ │ ├── passchange.php │ │ └── passreset.php │ ├── install/ │ │ ├── index.php │ │ └── reinstall.php │ ├── ipban/ │ │ ├── add.php │ │ ├── edit.php │ │ ├── index.php │ │ ├── remove.php │ │ └── unban.php │ ├── item/ │ │ ├── index.php │ │ ├── iteminfo.php │ │ ├── pagemenu/ │ │ │ └── view.php │ │ └── view.php │ ├── itemshop/ │ │ ├── add.php │ │ ├── delete.php │ │ ├── edit.php │ │ └── imagedel.php │ ├── logdata/ │ │ ├── branch.php │ │ ├── cashpoints.php │ │ ├── char.php │ │ ├── chat.php │ │ ├── command.php │ │ ├── feeding.php │ │ ├── index.php │ │ ├── inter.php │ │ ├── login.php │ │ ├── mvp.php │ │ ├── npc.php │ │ ├── pick.php │ │ └── zeny.php │ ├── mail/ │ │ └── index.php │ ├── main/ │ │ ├── index.php │ │ ├── page_not_found.php │ │ └── preprocess.php │ ├── monster/ │ │ ├── index.php │ │ └── view.php │ ├── news/ │ │ ├── add.php │ │ ├── delete.php │ │ ├── edit.php │ │ ├── index.php │ │ ├── manage.php │ │ └── view.php │ ├── pages/ │ │ ├── add.php │ │ ├── content.php │ │ ├── delete.php │ │ ├── edit.php │ │ └── index.php │ ├── purchase/ │ │ ├── add.php │ │ ├── cart.php │ │ ├── checkout.php │ │ ├── clear.php │ │ ├── index.php │ │ ├── pending.php │ │ └── remove.php │ ├── ranking/ │ │ ├── alchemist.php │ │ ├── blacksmith.php │ │ ├── character.php │ │ ├── death.php │ │ ├── guild.php │ │ ├── homunculus.php │ │ ├── mvp.php │ │ └── zeny.php │ ├── server/ │ │ ├── info.php │ │ ├── status-xml.php │ │ └── status.php │ ├── service/ │ │ └── tos.php │ ├── servicedesk/ │ │ ├── catcontrol.php │ │ ├── create.php │ │ ├── index.php │ │ ├── staffindex.php │ │ ├── staffsettings.php │ │ ├── staffview.php │ │ ├── staffviewclosed.php │ │ └── view.php │ ├── unauthorized/ │ │ └── index.php │ ├── vending/ │ │ ├── index.php │ │ └── viewshop.php │ ├── webcommands/ │ │ └── index.php │ └── woe/ │ ├── custom.php │ └── index.php ├── robots.txt └── themes/ ├── bootstrap/ │ ├── css/ │ │ ├── flux/ │ │ │ ├── ie.css │ │ │ └── unitip.css │ │ ├── flux.css │ │ └── sticky-footer-navbar.css │ ├── footer.php │ ├── header.php │ ├── js/ │ │ └── ie9.js │ ├── main/ │ │ └── navbar.php │ └── manifest.php ├── default/ │ ├── account/ │ │ ├── cart.php │ │ ├── changemail.php │ │ ├── changepass.php │ │ ├── changesex.php │ │ ├── confirm.php │ │ ├── confirmemail.php │ │ ├── create.php │ │ ├── edit.php │ │ ├── index.php │ │ ├── login.php │ │ ├── logout.php │ │ ├── prune.php │ │ ├── resend.php │ │ ├── resetpass.php │ │ ├── resetpw.php │ │ ├── transfer.php │ │ ├── view.php │ │ └── xferlog.php │ ├── auction/ │ │ └── index.php │ ├── buyingstore/ │ │ ├── index.php │ │ └── viewshop.php │ ├── captcha/ │ │ └── index.php │ ├── castle/ │ │ └── index.php │ ├── character/ │ │ ├── changeslot.php │ │ ├── divorce.php │ │ ├── index.php │ │ ├── mapstats.php │ │ ├── online.php │ │ ├── prefs.php │ │ ├── resetlook.php │ │ ├── resetpos.php │ │ └── view.php │ ├── cplog/ │ │ ├── ban.php │ │ ├── changemail.php │ │ ├── changepass.php │ │ ├── create.php │ │ ├── index.php │ │ ├── ipban.php │ │ ├── login.php │ │ ├── paypal.php │ │ ├── resetpass.php │ │ └── txnview.php │ ├── css/ │ │ ├── flux/ │ │ │ ├── ie.css │ │ │ ├── recaptcha.css │ │ │ └── unitip.css │ │ └── flux.css │ ├── data/ │ │ └── FluxDefaultTheme.psd │ ├── donate/ │ │ ├── complete.php │ │ ├── history.php │ │ ├── index.php │ │ ├── notify.php │ │ ├── trusted.php │ │ └── update.php │ ├── economy/ │ │ └── index.php │ ├── errors/ │ │ ├── missing_action.php │ │ └── missing_view.php │ ├── footer.php │ ├── forum/ │ │ └── index.php │ ├── guild/ │ │ ├── emblem.php │ │ ├── export.php │ │ ├── index.php │ │ └── view.php │ ├── header.php │ ├── history/ │ │ ├── cplogin.php │ │ ├── emailchange.php │ │ ├── gamelogin.php │ │ ├── index.php │ │ ├── passchange.php │ │ └── passreset.php │ ├── install/ │ │ └── reinstall.php │ ├── ipban/ │ │ ├── add.php │ │ ├── edit.php │ │ ├── index.php │ │ ├── remove.php │ │ └── unban.php │ ├── item/ │ │ ├── index.php │ │ ├── iteminfo.php │ │ └── view.php │ ├── itemshop/ │ │ ├── add.php │ │ ├── delete.php │ │ ├── edit.php │ │ └── imagedel.php │ ├── js/ │ │ ├── flux.datefields.js │ │ ├── flux.unitip.js │ │ ├── flux.unitpngfix.js │ │ ├── ie9.js │ │ └── jquery-1.8.3.min.js │ ├── logdata/ │ │ ├── branch.php │ │ ├── cashpoints.php │ │ ├── char.php │ │ ├── chat.php │ │ ├── command.php │ │ ├── feeding.php │ │ ├── index.php │ │ ├── inter.php │ │ ├── login.php │ │ ├── mvp.php │ │ ├── npc.php │ │ ├── pick.php │ │ └── zeny.php │ ├── mail/ │ │ └── index.php │ ├── main/ │ │ ├── balance.php │ │ ├── index.php │ │ ├── loginbox.php │ │ ├── page_not_found.php │ │ ├── pagemenu.php │ │ ├── sidebar.php │ │ └── submenu.php │ ├── monster/ │ │ ├── index.php │ │ └── view.php │ ├── news/ │ │ ├── add.php │ │ ├── delete.php │ │ ├── edit.php │ │ ├── index.php │ │ ├── manage.php │ │ └── view.php │ ├── pages/ │ │ ├── add.php │ │ ├── content.php │ │ ├── delete.php │ │ ├── edit.php │ │ └── index.php │ ├── purchase/ │ │ ├── add.php │ │ ├── cart.php │ │ ├── checkout.php │ │ ├── clear.php │ │ ├── index.php │ │ ├── pending.php │ │ └── remove.php │ ├── ranking/ │ │ ├── alchemist.php │ │ ├── blacksmith.php │ │ ├── character.php │ │ ├── death.php │ │ ├── guild.php │ │ ├── homunculus.php │ │ ├── mvp.php │ │ └── zeny.php │ ├── server/ │ │ ├── info.php │ │ ├── status-xml.php │ │ └── status.php │ ├── service/ │ │ └── tos.php │ ├── servicedesk/ │ │ ├── catcontrol.php │ │ ├── create.php │ │ ├── index.php │ │ ├── staffindex.php │ │ ├── staffsettings.php │ │ ├── staffview.php │ │ ├── staffviewclosed.php │ │ └── view.php │ ├── unauthorized/ │ │ └── index.php │ ├── vending/ │ │ ├── index.php │ │ └── viewshop.php │ ├── webcommands/ │ │ └── index.php │ └── woe/ │ ├── custom.php │ └── index.php └── installer/ ├── footer.php ├── header.php └── install/ └── index.php ================================================ FILE CONTENTS ================================================ ================================================ FILE: .deepsource.toml ================================================ version = 1 [[analyzers]] name = "php" [[analyzers]] name = "javascript" [[analyzers]] name = "sql" exclude_files = [ "lib/phpmailer/**", ] ================================================ FILE: .editorconfig ================================================ # rAthena FluxCP EditorConfig file # EditorConfig is awesome: https://EditorConfig.org root = true [*] insert_final_newline = true trim_trailing_whitespace = true [*.php] charset = utf-8 end_of_line = lf indent_style = space indent_size = 4 [*.json] indent_style = space indent_size = 2 [*.yml] indent_style = space indent_size = 2 ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yml ================================================ name: Bug Report description: Create an Issue that details broken or unexpected behaviour labels: [Bug Report] body: - type: textarea attributes: label: Environment description: | examples: - **PHP**: 8.1 - **MySQL**: MariaDB 10 value: | - PHP: - MySQL: render: Markdown validations: required: true - type: textarea attributes: label: Current Behavior description: A concise description of what you're experiencing. validations: required: true - type: textarea attributes: label: Expected Behavior description: A concise description of what you expected to happen. validations: required: false - type: textarea attributes: label: Steps To Reproduce description: Steps to reproduce the behavior. placeholder: | 1. In this environment... 2. With this config... 3. Open page '...' 4. See error... validations: required: true - type: textarea attributes: label: Anything else? description: | Links? References? Anything that will give us more context about the issue you are encountering! Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. validations: required: false ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: Forum Support url: https://rathena.org/board/forum/21-web-support/ about: You can obtain support for FluxCP on our forum. - name: Discord Support url: https://discord.gg/kMeMXWEvSV about: Chat with others in our fluxcp-support channel. ================================================ FILE: .github/ISSUE_TEMPLATE/enhancement_request.yml ================================================ name: Enhancement Request description: Submit your request for changes to existing code to provide more functionality or QoL changes. title: "Enhancement Request" labels: [Enhancement Request] body: - type: textarea attributes: label: Provide Details description: Give as much information as possible in order to get the discussion going. validations: required: true ================================================ FILE: .github/PULL_REQUEST_TEMPLATE/pull_request_template.md ================================================ Fixes # . Changes proposed in this Pull Request: * ? * ? * ? ================================================ FILE: .github/pull_request_template.md ================================================ Fixes # . Changes proposed in this Pull Request: * ? * ? * ? ================================================ FILE: .github/workflows/codeql.yml ================================================ name: "CodeQL" on: push: branches: [ "master" ] pull_request: branches: [ "master" ] schedule: - cron: "36 3 * * 3" jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: language: [ javascript ] steps: - name: Checkout uses: actions/checkout@v3 - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} queries: +security-and-quality - name: Autobuild uses: github/codeql-action/autobuild@v2 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 with: category: "/language:${{ matrix.language }}" ================================================ FILE: .gitignore ================================================ # Images /data/items/icons/*.png /data/items/images/*.png /data/jobs/images/F/*.gif /data/jobs/images/M/*.gif /data/monsters/*.png /data/monsters/*.gif # Logs /data/logs/errors /data/logs/mail /data/logs/mysql /data/logs/schemas /data/logs/transactions # Caches /data/tmp/*.php /data/tmp/*.cache /data/tmp/emblems # Non-Default Themes /themes/* !/themes/default !/themes/bootstrap !/themes/installer # Import Configs /config/import ================================================ FILE: .htaccess ================================================ #RewriteEngine On #RewriteBase / #RewriteCond %{REQUEST_FILENAME} !-f #RewriteCond %{REQUEST_FILENAME} !-d #RewriteRule !\.(js|ico|gif|jpg|png|css|pdf|swf|flv)$ index.php [QSA] ================================================ FILE: LICENSE ================================================ GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ================================================ FILE: README.md ================================================ FluxCP ====== [![DeepSource](https://app.deepsource.com/gh/rathena/FluxCP.svg/?label=active+issues&show_trend=true&token=nhkIfid6qRIZxl2INWaaV4Qb)](https://app.deepsource.com/gh/rathena/FluxCP/?ref=repository-badge) [![Open Issues](https://img.shields.io/github/issues/rathena/FluxCP.svg?logo=github&logoWidth=18&color=yellow)](https://lgtm.com/projects/g/rathena/FluxCP/alerts/) [![Open PRs](https://img.shields.io/github/issues-pr/rathena/FluxCP.svg?logo=github&logoWidth=18&color=blue)](https://lgtm.com/projects/g/rathena/FluxCP/alerts/) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/4d1c0a43c0864764b3d3dc5ed2d93192)](https://www.codacy.com/gh/rathena/FluxCP/dashboard?utm_source=github.com&utm_medium=referral&utm_content=rathena/FluxCP&utm_campaign=Badge_Grade) Flux Control Panel (FluxCP) for rAthena servers. Requirements --------- * PHP 7.3 or newer * PDO and PDO-MYSQL extensions for PHP (including PHP_MYSQL support) * MySQL 5 or newer * Optional: GD2 (for guild emblems and registration CAPTCHA) * Optional: Tidy (for cleaner HTML output) * Optional: mod_rewrite support for UseCleanUrls feature * Optional: [Item images](http://rathena.org/board/files/file/2509-item-images/) What's New? --------- * The description files are kept upto-date with each new commit from rAthena. * Pre-integrated themes: - default - Bootstrap * Built-In: - News and Pages CMS with integrated TinyMCE - Service Desk (ITIL Incident Management style support ticket system) - Additional Logs - More Ranking Lists - Discord Integration - Google ReCaptcha - Remote AtCommand functionality How To ... ? --------- We have a small doc library that covers: * Basic User Documentation - Installation - [Themes](https://github.com/rathena/FluxCP/blob/master/doc/user_theme.md) - [Languages](https://github.com/rathena/FluxCP/blob/master/doc/user_lang.md) - Installing Addons - Updating FluxCP * Developer Documentation - Creating an Addon - Providing Addon updates - Creating a custom Theme Join the Discussion --------- We have a discord server separate from rAthena just for FluxCP stuff! The channels there can be used to obtain help, discuss testing, view anonymous feedback log, Github commits, etc. https://discord.gg/kMeMXWEvSV Extra Credits --------- Original FluxCP created by Paradox924X and Byteflux with additional contributions from Xantara. Some works from other users have been integrated into this project. ================================================ FILE: addons/helloworld/config/access.php ================================================ array( 'helloworld' => array( 'index' => AccountLevel::ADMIN ) ), 'features' => array( // None. ) ) ?> ================================================ FILE: addons/helloworld/config/addon.php ================================================ array( //'Hello World' => array('module' => 'helloworld') ) ) ?> ================================================ FILE: addons/helloworld/lang/en_us.php ================================================ 'Hello, World!', 'HelloInfoText' => 'This is a “Hello World” sample from an add-on!', 'HelloVersionText' => 'Your Flux Control Panel version is %s' ); ?> ================================================ FILE: addons/helloworld/lang/ko_kr.php ================================================ '안녕하세요!', 'HelloInfoText' => '현제보고계시는건 샘플 애드온 프로그램입니다!', 'HelloVersionText' => '지금 사용하고계시는 플럭스 버젼은 %s입니다.' ); ?> ================================================ FILE: addons/helloworld/modules/helloworld/index.php ================================================ ================================================ FILE: addons/helloworld/themes/default/helloworld/index.php ================================================

================================================ FILE: config/.htaccess ================================================ Order deny,allow Deny from all ================================================ FILE: config/access.php ================================================ array( 'main' => array( '*' => AccountLevel::ANYONE ), 'donate' => array( 'index' => AccountLevel::ANYONE, 'notify' => AccountLevel::ANYONE, 'update' => AccountLevel::ANYONE, 'complete' => AccountLevel::ANYONE, 'history' => AccountLevel::NORMAL, 'trusted' => AccountLevel::NORMAL ), 'purchase' => array( 'index' => AccountLevel::ANYONE, 'add' => AccountLevel::ANYONE, 'clear' => AccountLevel::NORMAL, 'cart' => AccountLevel::NORMAL, 'checkout' => AccountLevel::NORMAL, 'remove' => AccountLevel::NORMAL, 'pending' => AccountLevel::NORMAL ), 'itemshop' => array( 'add' => AccountLevel::ADMIN, 'edit' => AccountLevel::ADMIN, 'delete' => AccountLevel::ADMIN, 'imagedel' => AccountLevel::ADMIN ), 'account' => array( 'index' => AccountLevel::LOWGM, 'view' => AccountLevel::NORMAL, 'create' => AccountLevel::UNAUTH, 'login' => AccountLevel::UNAUTH, 'logout' => AccountLevel::NORMAL, 'transfer' => AccountLevel::NORMAL, 'xferlog' => AccountLevel::NORMAL, 'cart' => AccountLevel::NORMAL, 'changepass' => AccountLevel::NORMAL, 'edit' => AccountLevel::ADMIN, 'changesex' => AccountLevel::NORMAL, 'confirm' => AccountLevel::UNAUTH, 'resend' => AccountLevel::UNAUTH, 'resetpass' => AccountLevel::UNAUTH, 'resetpw' => AccountLevel::UNAUTH, 'changemail' => AccountLevel::NORMAL, 'confirmemail' => AccountLevel::NORMAL, 'prune' => AccountLevel::ANYONE ), 'character' => array( 'index' => AccountLevel::LOWGM, 'view' => AccountLevel::NORMAL, 'online' => AccountLevel::ANYONE, 'prefs' => AccountLevel::NORMAL, 'changeslot' => AccountLevel::NORMAL, 'resetlook' => AccountLevel::NORMAL, 'resetpos' => AccountLevel::NORMAL, 'mapstats' => AccountLevel::ANYONE, 'divorce' => AccountLevel::NORMAL ), 'guild' => array( 'emblem' => AccountLevel::ANYONE, 'index' => AccountLevel::LOWGM, 'export' => AccountLevel::ADMIN, 'view' => AccountLevel::NORMAL ), 'castle' => array( 'index' => AccountLevel::ANYONE ), 'economy' => array( 'index' => AccountLevel::NORMAL ), 'auction' => array( 'index' => AccountLevel::LOWGM ), 'ranking' => array( 'character' => AccountLevel::ANYONE, 'guild' => AccountLevel::ANYONE, 'zeny' => AccountLevel::ANYONE, 'death' => AccountLevel::ANYONE, 'homun' => AccountLevel::ANYONE, 'swordman' => AccountLevel::ANYONE, 'bowman' => AccountLevel::ANYONE, 'spearman' => AccountLevel::ANYONE, 'mvp' => AccountLevel::ANYONE, ), 'item' => array( 'index' => AccountLevel::ANYONE, 'view' => AccountLevel::ANYONE, 'iteminfo' => AccountLevel::ADMIN ), 'monster' => array( 'index' => AccountLevel::ANYONE, 'view' => AccountLevel::ANYONE ), 'server' => array( 'status' => AccountLevel::ANYONE, 'status-xml' => AccountLevel::ANYONE, 'info' => AccountLevel::ANYONE ), 'logdata' => array( 'index' => AccountLevel::ADMIN, 'char' => AccountLevel::ADMIN, 'cashpoints' => AccountLevel::ADMIN, 'feeding' => AccountLevel::ADMIN, 'inter' => AccountLevel::ADMIN, 'command' => AccountLevel::ADMIN, 'branch' => AccountLevel::ADMIN, 'chat' => AccountLevel::ADMIN, 'login' => AccountLevel::ADMIN, 'mvp' => AccountLevel::ADMIN, 'npc' => AccountLevel::ADMIN, 'pick' => AccountLevel::ADMIN, 'zeny' => AccountLevel::ADMIN ), 'cplog' => array( 'index' => AccountLevel::ADMIN, 'create' => AccountLevel::ADMIN, 'paypal' => AccountLevel::ADMIN, 'login' => AccountLevel::ADMIN, 'resetpass' => AccountLevel::ADMIN, 'changepass' => AccountLevel::ADMIN, 'changemail' => AccountLevel::ADMIN, 'ban' => AccountLevel::ADMIN, 'ipban' => AccountLevel::ADMIN, 'txnview' => AccountLevel::ADMIN ), 'ipban' => array( 'index' => AccountLevel::ADMIN, 'add' => AccountLevel::ADMIN, 'unban' => AccountLevel::ADMIN, 'edit' => AccountLevel::ADMIN, 'remove' => AccountLevel::ADMIN ), 'service' => array( 'tos' => AccountLevel::ANYONE ), 'captcha' => array( 'index' => AccountLevel::ANYONE ), 'install' => array( 'index' => AccountLevel::ANYONE, 'reinstall' => AccountLevel::ADMIN ), 'test' => array( '*' => AccountLevel::ANYONE ), 'woe' => array( 'index' => AccountLevel::ANYONE ), 'mail' => array( 'index' => AccountLevel::ADMIN ), 'history' => array( 'index' => AccountLevel::NORMAL, 'cplogin' => AccountLevel::NORMAL, 'gamelogin' => AccountLevel::NORMAL, 'emailchange' => AccountLevel::NORMAL, 'passchange' => AccountLevel::NORMAL, 'passreset' => AccountLevel::NORMAL ), 'pages' => array( 'index' => AccountLevel::ADMIN, 'add' => AccountLevel::ADMIN, 'delete' => AccountLevel::ADMIN, 'edit' => AccountLevel::ADMIN, 'content' => AccountLevel::ANYONE, ), 'news' => array( 'index' => AccountLevel::ANYONE, 'view' => AccountLevel::ANYONE, 'manage' => AccountLevel::ADMIN, 'add' => AccountLevel::ADMIN, 'edit' => AccountLevel::ADMIN, 'delete' => AccountLevel::ADMIN, ), 'servicedesk'=> array( 'index' => AccountLevel::NORMAL, 'create' => AccountLevel::NORMAL, 'view' => AccountLevel::NORMAL, 'staffindex' => AccountLevel::LOWGM, 'staffview' => AccountLevel::LOWGM, 'staffviewclosed'=> AccountLevel::LOWGM, 'staffsettings' => AccountLevel::LOWGM, 'catcontrol' => AccountLevel::HIGHGM ), 'vending' => array( 'index' => AccountLevel::ANYONE, 'viewshop' => AccountLevel::ANYONE, ), 'webcommands' => array( 'index' => AccountLevel::ADMIN, ), ), // General feature permissions, handled by the modules themselves. 'features' => array( 'ViewAccount' => AccountLevel::HIGHGM, // View another person's account details. 'ViewAccountBanLog' => AccountLevel::HIGHGM, // View another person's account ban log. 'DeleteAccount' => AccountLevel::ADMIN, // (not yet implemented) 'DeleteCharacter' => AccountLevel::ADMIN, // (not yet implemented) 'SeeAccountPassword' => AccountLevel::NOONE, // If not using MD5, view another person's password in list. 'TempBanAccount' => AccountLevel::LOWGM, // Has ability to temporarily ban an account. 'TempUnbanAccount' => AccountLevel::LOWGM, // Has ability to remove a temporary ban on an account. 'PermBanAccount' => AccountLevel::HIGHGM, // Has ability to permanently ban an account. 'PermUnbanAccount' => AccountLevel::HIGHGM, // Has ability to remove a permanent ban on an account. 'SearchMD5Passwords' => AccountLevel::NOONE, // Ability to search MD5'd passwords in list. 'ViewCharacter' => AccountLevel::HIGHGM, // View another person's character details. 'DivorceCharacter' => AccountLevel::LOWGM, // Divorce another character. 'AddShopItem' => AccountLevel::ADMIN, // Ability to add an item to the shop. 'EditShopItem' => AccountLevel::ADMIN, // Ability to modify a shop item's details. 'DeleteShopItem' => AccountLevel::ADMIN, // Ability to remove an item for sale on the shop. 'ViewGuild' => AccountLevel::ADMIN, // Ability to view another guild's details. 'SearchWhosOnline' => AccountLevel::ANYONE, // Ability to search the "Who's Online" page. 'ViewOnlinePosition' => AccountLevel::LOWGM, // Ability to see a character's current map on "Who's Online" page. 'EditAccountGroupID' => AccountLevel::ADMIN, // Ability to edit another person's account group ID. 'EditAccountBalance' => AccountLevel::ADMIN, // Ability to edit another person's account balance. 'ModifyAccountPrefs' => AccountLevel::ADMIN, // Ability to modify another person's account preferences. 'ModifyCharPrefs' => AccountLevel::ADMIN, // Ability to modify another person's character preferences. 'IgnoreHiddenPref' => AccountLevel::LOWGM, // Ability to see users on "Who's Online" page, hidden or not. 'IgnoreHiddenPref2' => AccountLevel::LOWGM, // Ability to see users on "Who's Online" page, hidden by app config or not. 'SeeHiddenMapStats' => AccountLevel::LOWGM, // Ability to see hidden map statistics. 'ChangeSlot' => AccountLevel::LOWGM, // Minimum group level required to change another character's slot. 'ModifyIpBan' => AccountLevel::ADMIN, // Minimum group level required to modify an existing IP ban. 'RemoveIpBan' => AccountLevel::ADMIN, // Minimum group level required to remove an existing IP ban. 'HideFromZenyRank' => AccountLevel::NORMAL, // Ability to set "Hide from zeny ranking" pref. 'SeeItemDbScripts' => AccountLevel::ANYONE, // Ability to see item_db scripts in view page. 'SeeItemDb2Scripts' => AccountLevel::ADMIN, // Ability to see item_db2 scripts in view page. 'ViewRawTxnLogData' => AccountLevel::ADMIN, // Minimum group level required to view Raw Transaction Log in txnview page. 'ResetLook' => AccountLevel::LOWGM, // Minimum group level required to reset another character's look. 'ResetPosition' => AccountLevel::LOWGM, // Minimum group level required to reset another character's position. 'ViewWoeDisallowed' => AccountLevel::LOWGM, // Minimum group level required to bypass WoE-disabled page security check. 'SeeCpLoginLogPass' => AccountLevel::NOONE, // Minimum group level required to see password in CP login log (also requires CpLoginLogShowPassword in application.php) 'SearchCpLoginLogPw' => AccountLevel::NOONE, // Minimum group level required to search through passwords in the CP login log. 'SeeCpResetPass' => AccountLevel::NOONE, // Minimum group level required to see passwords in CP log's "password resets" page. 'SearchCpResetPass' => AccountLevel::NOONE, // Minimum group level required to search passwords in CP log's "password resets" page. 'SeeCpChangePass' => AccountLevel::NOONE, // Minimum group level required to see passwords in CP log's "password changes" page. 'SearchCpChangePass' => AccountLevel::NOONE, // Minimum group level required to search passwords in CP log's "password changes" page. 'SeeAccountID' => AccountLevel::LOWGM, // Minimum group level required to see Account ID on account view and character view pages. 'SeeUnknownItems' => AccountLevel::LOWGM, // Minimum group level required to see unidentified items as identified. 'AvoidSexChangeCost' => AccountLevel::LOWGM, // Avoid paying cost (if any) for sex changes. 'EditHigherPower' => AccountLevel::NOONE, 'BanHigherPower' => AccountLevel::NOONE ) ); ?> ================================================ FILE: config/application.php ================================================ 'localhost', // This value is the hostname:port under which Flux runs. (e.g., example.com or example.com:80) 'BaseURI' => 'fluxcp', // The base URI is the base web root on which your application lies. 'ForceHTTPS' => true, // By default use HTTPS, you should only use HTTP, if you have no certificate available (Note: You may want to visit https://letsencrypt.org) 'InstallerPassword' => 'secretpassword', // Installer/updater password. 'RequireOwnership' => true, // Require the executing user to be owner of the FLUX_ROOT/data/ directory tree? (Better for security) // WARNING: This will be mostly IGNORED on non-POSIX-compliant OSes (e.g. Windows). 'DefaultLoginGroup' => null, 'DefaultCharMapServer' => null, 'DefaultLanguage' => 'en_us', // Specify the default control panel language (see FLUX_ROOT/lang/ directory for available languages.) 'SiteTitle' => 'Flux Control Panel', // This value is only used if the theme decides to use it. 'ThemeName' => array('default', 'bootstrap'), // Names of the themes you would like list for use in the footer. Themes are in FLUX_ROOT/themes. 'ScriptTimeLimit' => 0, // Script execution time limit. Specifies (in seconds) how long a page should run before timing out. (0 means forever) 'MissingEmblemBMP' => 'empty.bmp', // 'ItemIconNameFormat' => '%d.png', // The filename format for item icons (defaults to {itemid}.png). 'ItemImageNameFormat' => '%d.png', // The filename format for item images (defaults to {itemid}.png). 'MonsterImageNameFormat' => '%d.gif', // The filename format for monster images (defaults to {monsterid}.gif). 'JobImageNameFormat' => '%d.gif', // The filename format for job images (defaults to {jobid}.gif). 'DivinePrideIntegration' => true, // Dowload monsters and items images from https://www.divine-pride.net if it's not exist. 'ForceEmptyEmblem' => false, // Forcefully display empty guild emblems, helpful when you don't have GD2 installed. 'EmblemCacheInterval' => 12, // Hourly interval to re-cache guild emblems (set to 0 to disable emblem cache). 'EmblemUseWebservice' => true, // Load emblems from WebService? 'SessionCookieExpire' => 48, // Duration in hours. 'AdminMenuGroupLevel' => AccountLevel::LOWGM, // The starting group ID for which module actions are moved into the admin menu for display. 'DateDefaultTimezone' => 'UTC', // The default timezone, consult the PHP manual for valid timezones: http://php.net/timezones (null for defaut system TZ) 'DateFormat' => 'Y-m-d', // Default DATE format to be displayed in pages. 'DateTimeFormat' => 'Y-m-d H:i:s', // Default DATETIME format to be displayed in pages. 'ShowSinglePage' => true, // Whether or not to show the page numbers even if there's only one page. 'ResultsPerPage' => 20, // The number of results to display in a paged set, per page. 'PagesToShow' => 10, // The number of page numbers to display at once. 'PageJumpMinimumPages' => 1, // Minimum number of required pages before page jump box is shown. (0 to always show!) 'ShowPageJump' => true, // Whether or not to show the "Page Jump" box. 'SingleMatchRedirect' => true, // Whether or not to redirect to view action from index page if only one match is returned (and action is allowed). 'SingleMatchRedirectItem' => false, // Same as above, for item module. 'SingleMatchRedirectMobs' => false, // Same as above, for monster module. 'UsernameAllowedChars' => 'a-zA-Z0-9_', // PCRE Format Pattern. default: 'a-zA-Z0-9_' (alphanumeric and underscore) // WARNING: This string isn't escaped so be careful which chars you use! // PCRE Pattern Ref: http://php.net/manual/en/pcre.pattern.php 'MinUsernameLength' => 4, // Minimum username length. 'MaxUsernameLength' => 23, // Maximum username length. 'MinPasswordLength' => 8, // Minimum password length. 'MaxPasswordLength' => 31, // Maximum password length. 'PasswordMinUpper' => 1, // Number of upper-case letters to require in passwords. 'PasswordMinLower' => 1, // Number of lower-case letters to require in passwords. 'PasswordMinNumber' => 1, // Number of numbers to require in passwords. 'PasswordMinSymbol' => 0, // Number of symbols to require in passwords. 'GMMinPasswordLength' => 8, // Minimum password length for GM accounts. 'GMPasswordMinUpper' => 1, // Number of upper-case letters to require in passwords for GM accounts. 'GMPasswordMinLower' => 1, // Number of lower-case letters to require in passwords for GM accounts. 'GMPasswordMinNumber' => 1, // Number of numbers to require in passwords for GM accounts. 'GMPasswordMinSymbol' => 1, // Number of symbols to require in passwords for GM accounts. 'RandomPasswordLength' => 16, // This is the length of the random password generated by the "Reset Password" feature. (NOTE: Hardcoded minimum value of 8) 'AllowUserInPassword' => false, // Whether or not to allow the password to contain the username. (NOTE: A case-insensitive search is performed) 'AllowDuplicateEmails' => false, // Whether or not to allow duplicate e-mails to be used in registration. (See Mailer config options) 'RequireEmailConfirm' => false, // Require e-mail confirmation during registration. 'RequireChangeConfirm' => false, // Require confirmation when changing e-mail addresses. 'EmailConfirmExpire' => 48, // E-mail confirmations expire hours. Unconfirmed accounts will expire after this period of time. 'PincodeEnabled' => true, // Whether or not the pincode system is enabled in your server. (Check your char_athena.conf file. Enabled by default.) 'MailerFromAddress' => 'noreply@localhost', // The e-mail address displayed in the From field. 'MailerFromName' => 'MailerName', // The name displayed with the From e-mail address. 'MailerUseSMTP' => false, // Whether or not to use a separate SMTP server for sending mail. 'MailerSMTPUseSSL' => false, // Whether or not mailer should connect using SSL (yes for GMail). 'MailerSMTPUseTLS' => false, // Same as above SSL setting, but for TLS. This setting will override the SSL setting. 'MailerSMTPPort' => null, // When MailerUseSMTP is true: SMTP server port (mailer will default to 25). 'MailerSMTPHosts' => null, // When MailerUseSMTP is true: A string host or array of hosts (e.g., 'host1' or array('host1', 'backuphost')). 'MailerSMTPUsername' => null, // When MailerUseSMTP is true: Authorized username for SMTP server. 'MailerSMTPPassword' => null, // When MailerUseSMTP is true: Authorized password for SMTP server (for above user). 'ServerStatusCache' => 2, // Store a cached server status and refresh every X minutes. Default: 2 minutes (value is measured in minutes). 'ServerStatusTimeout' => 2, // For each server, spend X amount of seconds to determine whether it's up or not. 'SessionKey' => 'fluxSessionData', // Shouldn't be changed, just specifies the session key to be used for session data. 'DefaultModule' => 'main', // This is the module to execute when none has been specified. 'DefaultAction' => 'index', // This is the default action for any module, probably should leave this alone. (Deprecated) 'GzipCompressOutput' => false, // Whether or not to compress output using zlib. 'GzipCompressionLevel' => 9, // zlib compression level. (1~9) 'OutputCleanHTML' => true, // Use this if you have Tidy installed to clean your HTML output when serving pages. 'ShowCopyright' => true, // Whether or not to show the copyright footer. 'ShowRenderDetails' => true, // Shows the "page rendered in X seconds" and "number of queries executed: X" in the default theme. 'UseCleanUrls' => false, // Set to true if you're running Apache and it supports mod_rewrite and .htaccess files. 'DebugMode' => false, // Set to false to minimize technical details from being output by Flux. WARNING: DO NOT USE THIS OPTION ON A PUBLICALLY-ACCESSIBLE CP. 'UseCaptcha' => false, // Use CAPTCHA image for account registration to prevent automated account creations. (Requires GD2/FreeType2) 'UseLoginCaptcha' => false, // Use CAPTCHA image for account logins. (Requires GD2/FreeType2) 'EnableReCaptcha' => false, // Enables the use of reCAPTCHA instead of Flux's native GD2 library (http://www.google.com/recaptcha) 'ReCaptchaPublicKey' => '...', // This is your reCAPTCHA public key [REQUIRED FOR RECAPTCHA] (sign up at http://www.google.com/recaptcha) 'ReCaptchaPrivateKey' => '...', // This is your reCAPTCHA private key [REQUIRED FOR RECAPTCHA] (sign up at http://www.google.com/recaptcha) 'ReCaptchaTheme' => 'light', // ReCaptcha theme to use (Value: dark or light) (see: https://developers.google.com/recaptcha/docs/display#render_param) 'DisplaySinglePages' => true, // Whether or not to display paging for single page results. 'ForwardYears' => 15, // (Visual) The number of years to display ahead of the current year in date inputs. 'BackwardYears' => 60, // (Visual) The number of years to display behind the current year in date inputs. 'ColumnSortAscending' => ' ▲', // (Visual) Text displayed for ascending sorted column names. 'ColumnSortDescending' => ' ▼', // (Visual) Text displayed for descending sorted column names. 'DisplayCashPoints' => false, // Whether or not to display "Cash Points" instead of the player's "Credits" in the control panel. 'CreditExchangeRate' => 1.0, // The rate at which credits are exchanged for dollars. 'MinDonationAmount' => 2.0, // Minimum donation amount. (NOTE: Actual donations made that are less than this account won't be exchanged) 'DonationCurrency' => 'USD', // Preferred donation currency. Only donations made in this currency will be processed for credit deposits. 'MoneyDecimalPlaces' => 2, // (Visual) Number of decimal places to display in amount. 'MoneyThousandsSymbol' => ',', // (Visual) Thousandths place separator (a period in European currencies). 'MoneyDecimalSymbol' => '.', // (Visual) Decimal separator (a comma in European currencies). 'AcceptDonations' => true, // Whether or not to accept donations. 'PayPalIpnUrl' => 'www.paypal.com', // The ipnpb.paypal.com and ipnpb.sandbox.paypal.com endpoints only accept HTTPS connections. If you currently use www.paypal.com, you should move to ipnpb.paypal.com when you update your code to use HTTPS. 'PayPalBusinessEmail' => 'admin@localhost', // Enter the e-mail under which you have registered your business account. 'PayPalReceiverEmails' => array( // These are the receiver e-mail addresses who are allowed to receive payment. //'admin2@localhost', // -- This array may be empty if you only use one e-mail //'admin3@localhost' // -- because your Business Email is also checked. ), 'PaypalHackNotify' => true, // Send email notification if hack attempt detected (Notification will be send for each address in list PayPalBusinessEmail and PayPalReceiverEmails) 'PayPalAllowedHosts' => array( // PayPal IP list https://www.paypal.com/fm/smarthelp/article/what-are-the-ip-addresses-for-live-paypal-servers-ts1056 'ipn.sandbox.paypal.com', 'notify.paypal.com', '66.211.170.66', '173.0.81.1', '173.0.81.0/24', '173.0.81.33', '173.0.81.65', '173.0.81.140', '64.4.240.0/21', '64.4.248.0/22', '6.211.168.0/22', '173.0.80.0/20', '91.243.72.0/23' ), 'GStorageLeaderOnly' => false, // Only allow guild leader to view guild storage rather than all members? 'DivorceKeepChild' => false, // Keep child after divorce? 'DivorceKeepRings' => false, // Keep wedding rings after divorce? 'IpWhitelistPattern' => // PCRE Format Pattern. It's recommended you add your gameserver, webserver and server owner's IPs here. '(127\.0\.0\.1|0(\.[0\*]){3})', // WARNING: This string isn't escaped so be careful which chars you use! // By default, whitelists 127.0.0.1 (localhost) and 0.0.0.0 (all interfaces; whitelists all wildcard bans that can achive this too) 'AllowIpBanLogin' => false, // Allow logging into account from banned IP. 'AllowTempBanLogin' => false, // Allow logging in of temporarily banned accounts. 'AllowPermBanLogin' => false, // Allow logging in of permanently banned accounts. 'AutoRemoveTempBans' => true, // Automatically remove expired temporary bans on certain pages. 'ItemShopMaxCost' => 99, // Max price an item can be sold for. 'ItemShopMaxQuantity' => 99, // Max quantity the item may be sold at once for. 'ItemShopItemPerPage' => 5, // The number of items to display per page in the "Item Shop" page. 'ShowItemDesc' => false, // Displays generated item descs from parsed itemInfo.lua 'HideFromWhosOnline' => AccountLevel::LOWGM, // Levels greater than or equal to this will be hidden from the "Who's Online" page. 'HideFromMapStats' => AccountLevel::LOWGM, // Levels greater than or equal to this will be hidden from the "Map Stats" page. 'EnableGMPassSecurity' => AccountLevel::LOWGM, // Levels greater than or equal to this will be required to use passwords that meet the earlier GM Password settings. 'ChargeGenderChange' => 0, // You can specify this as the number of credits to charge for gender change. Can be 0 for free change. 'BanPaymentStatuses' => array( // Payment statuses that will automatically ban the account owner if received. 'Cancelled_Reversal', // -- 'Cancelled_Reversal' 'Reversed', // -- 'Reversed' ), 'HoldUntrustedAccount' => 0, // This is the time in hours to hold a donation crediting process for, if the account // isn't a trusted account. Specify 0 or false to disable this feature. 'AutoUnholdAccount' => false, // Enable this to auto-unhold an account and credit it if the transaction is still // valid. This only applies if you are using the HoldUnstrustedAccount feature. // If you want to run a cron job instead, you can make a request to the '/donate/update' // module/action with the InstallerPassword as the password to run the update task. // With clean URLs: http:////donate/update?password= // Without clean URLs: http:///?module=donate&action=update&password= // NOTE: This option is HIGHLY inefficient, it's recommended to run a cron job instead. 'AutoPruneAccounts' => false, // Enable this to automatically prune expired accounts. Enabling this is a performance // performance killer. See 'AutoUnholdAccount' for running this task as a cron job, // the module is 'account' and the action is 'prune'. // With clean URLs: http:////account/prune?password= // Without clean URLs: http:///?module=account&action=prune&password= 'ShopImageExtensions' => array( // These are the image extensions allowed for uploading in the item shop. 'png', 'jpg', 'gif', 'bmp', 'jpeg' ), 'NoResetPassGroupLevel' => AccountLevel::LOWGM, // Minimum group level of account to prevent password reset using control panel. 'CharRankingLimit' => 20, // 'GuildRankingLimit' => 20, // 'ZenyRankingLimit' => 20, // 'DeathRankingLimit' => 20, // 'AlchemistRankingLimit' => 20, // 'BlacksmithRankingLimit' => 20, // 'HomunRankingLimit' => 20, // 'MVPRankingLimit' => 20, // 'RankingHideGroupLevel' => AccountLevel::LOWGM, // 'InfoHideZenyGroupLevel' => AccountLevel::LOWGM, // Minimum group level of account to hide zeny from in server information page. 'CharRankingThreshold' => 0, // Number of days the character must have logged in within to be listed in character ranking. (0 = disabled) 'ZenyRankingThreshold' => 0, // Number of days the character must have logged in within to be listed in zeny ranking. (0 = disabled) 'DeathRankingThreshold' => 0, // Number of days the character must have logged in within to be listed in death ranking. (0 = disabled) 'AlchemistRankingThreshold' => 0, // Number of days the character must have logged in within to be listed in death ranking. (0 = disabled) 'HomunRankingThreshold' => 0, // Number of days the character must have logged in within to be listed in homunculus ranking. (0 = disabled) 'HideTempBannedCharRank' => false, // Hide temporarily banned characters from ranking. 'HidePermBannedCharRank' => true, // Hide permanently banned characters from ranking. 'HideTempBannedZenyRank' => false, // Hide temporarily banned characters from ranking. 'HidePermBannedZenyRank' => true, // Hide permanently banned characters from ranking. 'HideTempBannedDeathRank' => false, // Hide temporarily banned characters from ranking. 'HidePermBannedDeathRank' => true, // Hide permanently banned characters from ranking. 'HideTempBannedAlcheRank' => false, // Hide temporarily banned characters from ranking. 'HidePermBannedAlcheRank' => true, // Hide permanently banned characters from ranking. 'HideTempBannedSmithRank' => false, // Hide temporarily banned characters from ranking. 'HidePermBannedSmithRank' => true, // Hide permanently banned characters from ranking. 'HideTempBannedStats' => false, // Hide temporarily banned accounts from statistics. 'HidePermBannedStats' => true, // Hide permanently banned accounts from statistics. 'HideTempBannedHomunRank' => false, // Hide temporarily banned characters from ranking. 'HidePermBannedHomunRank' => true, // Hide permanently banned characters from ranking. 'SortJobsByAmount' => false, // Sort job class information on statistics page by descending quantity (false = Sort by Job ID). 'CpLoginLogShowPassword' => false, // Show password in CP login log (also see access.php's SeeCpLoginLogPass). 'CpResetLogShowPassword' => false, // Show password in CP "password resets" log (also see access.php's SeeCpResetPass). 'CpChangeLogShowPassword' => false, // Show password in CP "password changes" log (also see access.php's SeeCpChangePass). 'AdminMenuNewStyle' => true, // Use new-style admin menu; Applies to 'default' theme. 'EnablePeakDisplay' => true, // Display Peak User count on Server Status page. // News Options 'CMSNewsOnHomepage' => true, // Display News on Home Page instead of "You've Just Installed FluxCP" message? 'CMSNewsType' => 1, // Type = source of news feed: // 1 = Built-in news page // 2 = RSS Import 'CMSNewsRSS' => 'https://rathena.org/board/rss/1-latest-community-announcements.xml/', // Use if CMSNewsType = 2 'CMSNewsLimit' => 4, // Number of news items to display 'CMSDisplayModifiedBy' => false, // If a news item has been modified, display modified date under news item? // Service Desk 'StaffReplyColour' => 'brown', 'FontResolvedColour' => 'green', 'FontPendingColour' => 'orange', 'FontClosedColour' => 'darkgrey', 'SDEnableCreditRewards' => true, // Show option in Service Desk to reward player X credits for reporting bugs/abuse/etc. 'SDCreditReward' => 10, // Number of credits to award account. // Discord Webhooks 'DiscordUseWebhook' => false, 'DiscordWebhookURL' => 'enter_webhook_url_from_discord_here', 'DiscordSendOnRegister' => true, // Sends a channel message when someone registers 'DiscordSendOnNewTicket' => true, // Sends a channel message when someone submits a new ticket to the Service Desk 'DiscordSendOnWebCommand' => true, // Sends a channel message when someone uses the Web Command feature in FluxCP 'DiscordSendOnMarketing' => true, // Sends a channel message when someone uses the Send Email feature in FluxCP 'DiscordSendOnErrorException' => true, // Sends a channel message when an exception is thrown 'TinyMCEKey' => 'no-key', // Register for a key at https://www.tiny.cloud/my-account/dashboard/ // These are the main menu items that should be displayed by themes. // They route to modules and actions. Whether they are displayed or // not at any given time depends on the user's account group level and/or // their login status. 'MenuItems' => array( 'MainMenuLabel' => array( 'HomeLabel' => array('module' => 'main'), //'ForumLabel' => array('exturl' => 'http://www.fluxro.com/community'), // External forum link //'ForumLabel' => array('module' => 'forums'), // Built-in forum link 'NewsLabel' => array('module' => 'news'), // Sample items for pages function. 'DownloadsLabel' => array('module' => 'pages','action'=>'content','param'=>array('path'=>'downloads')), 'RulesLabel' => array('module' => 'pages','action'=>'content','param'=>array('path'=>'rules')), // End sample items for pages function. ), 'AccountLabel' => array( 'AccountCreateHeading' => array('module' => 'account', 'action' => 'create'), 'LoginTitle' => array('module' => 'account', 'action' => 'login'), 'MyAccountLabel' => array('module' => 'account', 'action' => 'view'), 'HistoryLabel' => array('module' => 'history'), 'ServiceDeskLabel' => array('module' => 'servicedesk'), 'LogoutTitle' => array('module' => 'account', 'action' => 'logout'), ), 'DonationsLabel' => array( 'PurchaseLabel' => array('module' => 'purchase'), 'DonateLabel' => array('module' => 'donate'), ), 'InformationLabel' => array( 'ServerInfoLabel' => array('module' => 'server', 'action' => 'info'), 'ServerStatusLabel' => array('module' => 'server', 'action' => 'status'), 'WoeHoursLabel' => array('module' => 'woe'), 'CastlesLabel' => array('module' => 'castle'), 'WhosOnlineLabel' => array('module' => 'character', 'action' => 'online'), 'MapStaticsLabel'=> array('module' => 'character', 'action' => 'mapstats'), 'RankingInfoLabel' => array('module' => 'ranking', 'action' => 'character'), 'VendingInfoLabel' => array('module' => 'vending'), 'BuyingstoreInfoLabel' => array('module' => 'buyingstore'), ), 'DatabaseLabel' => array( 'ItemDatabaseLabel' => array('module' => 'item'), 'MobDatabaseLabel' => array('module' => 'monster'), ), 'SocialLabel' => array( 'JoinUsInFacebookLabel' => array('exturl' => 'https://www.facebook.com/'), 'RateUsOnRMSLabel' => array('exturl' => ''), ), 'Service Desk' => array( 'ServiceDeskLabel' => array('module' => 'servicedesk', 'action' => 'staffindex'), ), 'Misc. Stuff' => array( 'AccountLabel' => array('module' => 'account'), 'CharacterLabel' => array('module' => 'character'), 'CPLogsLabel' => array('module' => 'cplog'), 'PagesLabel' => array('module' => 'pages'), 'NewsLabel' => array('module' => 'news', 'action' => 'manage'), 'GuildsLabel' => array('module' => 'guild'), 'IPBanListLabel' => array('module' => 'ipban'), 'rALogsLabel' => array('module' => 'logdata'), 'ReInstallLabel' => array('module' => 'install', 'action' => 'reinstall'), 'SendMailLabel' => array('module' => 'mail'), 'WCTitleLabel' => array('module' => 'webcommands'), //'Auction' => array('module' => 'auction'), //'Economy' => array('module' => 'economy') ) ), // Sub-menu items that are displayed for any action belonging to a // particular module. The format it simple. 'SubMenuItems' => array( 'history' => array( 'gamelogin' => 'Game Logins', 'cplogin' => 'CP Logins', 'emailchange' => 'E-Mail Changes', 'passchange' => 'Password Changes', 'passreset' => 'Password Resets' ), 'account' => array( 'index' => 'List Accounts', 'view' => 'View Account', 'changepass' => 'Change Password', 'changemail' => 'Change E-mail', 'changesex' => 'Change Gender', 'transfer' => 'Transfer Credits', 'xferlog' => 'Credit Transfer History', 'cart' => 'Go to Shopping Cart', 'login' => 'Login', 'create' => 'Register', 'resetpass' => 'Reset Password', 'resend' => 'Resend E-mail Confirmation' ), 'guild' => array( 'index' => 'List Guilds', 'export' => 'Export Guild Emblems' ), 'server' => array( 'status' => 'View Status', 'status-xml' => 'View Status as XML' ), 'logdata' => array( 'branch' => 'Branches', 'char' => 'Characters', 'cashpoints' => 'CashPoints', 'chat' => 'Chat Messages', 'command' => 'Commands', 'feeding' => 'Feeding', 'inter' => 'Interactions', 'pick' => 'Item Picks', 'login' => 'Logins', 'mvp' => 'MVP', 'npc' => 'NPC', 'zeny' => 'Zeny' ), 'cplog' => array( 'paypal' => 'PayPal Transactions', 'create' => 'Account Registrations', 'login' => 'Logins', 'resetpass' => 'Password Resets', 'changepass' => 'Password Changes', 'changemail' => 'E-mail Changes', 'ban' => 'Account Bans', 'ipban' => 'IP Bans' ), 'purchase' => array( 'index' => 'Shop', 'cart' => 'Go to Cart', 'checkout' => 'Checkout', 'clear' => 'Empty Cart', 'pending' => 'Pending Redemption' ), 'donate' => array( 'index' => 'Make a Donation', 'history' => 'Donation History', 'trusted' => 'Trusted PayPal E-mails' ), 'ipban' => array( 'index' => 'IP Ban List', 'add' => 'Add IP Ban' ), 'ranking' => array( 'character' => 'Characters', 'death' => 'Deaths', 'alchemist' => 'Alchemists', 'blacksmith' => 'Blacksmiths', 'homunculus' => 'Homunculus', 'mvp' => 'MVPs', 'guild' => 'Guilds', 'zeny' => 'Zeny' ), 'item' => array( 'index' => 'List Items', 'iteminfo' => 'Add Item Info', ), 'pages' => array( 'index' => 'Manage Pages', 'add' => 'Add New Page', ), 'news' => array( 'index' => 'Latest News', 'manage' => 'Manage', 'add' => 'Add News', ), 'servicedesk' => array( 'staffindex' => 'View Active', 'staffviewclosed'=> 'View Closed', 'staffsettings' => 'Staff Settings', 'catcontrol' => 'Category Control', ), 'vending' => array( 'index' => 'Vendors', ), 'buyingstore' => array( 'index' => 'Buyers', ), ), 'AllowMD5PasswordSearch' => false, 'ReallyAllowMD5PasswordSearch' => false, // Are you POSITIVELY sure? // Specifies which modules and actions should be ignored by Tidy // (enabled/disabled by the OutputCleanHTML option). 'TidyIgnore' => array( array('module' => 'captcha'), array('module' => 'guild', 'action' => 'emblem') ), // Job classes, loaded from another file to avoid cluttering this one. // There isn't normally a need to modify this file, unless it's been // modified in an update. (In English: DON'T TOUCH THIS.) 'JobClasses' => include('jobs.php'), // Alchemist job classes, mostly used for alchemist rankings. // Should be left alone unless new alchemist-related job classes are introduced. 'AlchemistJobClasses' => include('jobs_alchemist.php'), // Blacksmith job classes, mostly used for blacksmith rankings. // Should be left alone unless new blacksmith-related job classes are introduced. 'BlacksmithJobClasses' => include('jobs_blacksmith.php'), // Gender-linked Job class IDs and their corresponding names. // Should be left alone unless new gender-specific job classes are introduced. 'GenderLinkedJobClasses' => include('jobs_gender_linked.php'), // Homunculus class IDs and their corresponding names. // Best not to mess with this either. 'HomunClasses' => include('homunculus.php'), // Item Types with their corresponding names. // Shouldn't touch this either. 'ItemTypes' => include('itemtypes.php'), // Item SubTypes with their corresponding names. // Shouldn't touch this either. 'ItemSubTypes' => include('itemsubtypes.php'), // Common Equip Location Combinations with their corresponding names. // Shouldn't touch this unless you've added custom combinations. 'EquipLocationCombinations' => include('equip_location_combinations.php'), // Error Code -> Error Type mapping. // Shouldn't need touching, however modifying loginerrors.php should be relatively safe. 'LoginErrors' => include('loginerrors.php'), // rA equip jobs mapping. 'EquipJobs' => include('equip_jobs.php'), // rA equip locations mapping. 'EquipLocations' => include('equip_locations.php'), // rA equip upper mapping. 'EquipUpper' => include('equip_upper.php'), // rA monster sizes mapping. 'MonsterSizes' => include('sizes.php'), // rA monster races mapping. 'MonsterRaces' => include('races.php'), // rA elements mapping. 'Elements' => include('elements.php'), // rA attributes mapping. 'Attributes' => include('attributes.php'), // rA monster modes mapping. 'MonsterModes' => include('monstermode.php'), 'MonsterAI' => include('monster_ai.php'), // Item shop categories. 'ShopCategories' => include('shopcategories.php'), // Item pick and zeny log types. 'PickTypes' => include('picktypes.php'), // Type of feeding 'FeedingTypes' => include('feedingtypes.php'), // Castle names. 'CastleNames' => include('castlenames.php'), // Trade restrictions. 'TradeRestriction' => include('trade_restrictions.php'), // Item flags. 'ItemFlags' => include('itemsflags.php'), // Item random options. 'RandomOptions' => include('item_randoptions.php'), // DON'T TOUCH. THIS IS FOR DEVELOPERS. 'FluxTables' => array( 'CreditsTable' => 'cp_credits', 'CreditTransferTable' => 'cp_xferlog', 'ItemShopTable' => 'cp_itemshop', 'TransactionTable' => 'cp_txnlog', 'RedemptionTable' => 'cp_redeemlog', 'AccountCreateTable' => 'cp_createlog', 'AccountBanTable' => 'cp_banlog', 'IpBanTable' => 'cp_ipbanlog', 'DonationTrustTable' => 'cp_trusted', 'AccountPrefsTable' => 'cp_loginprefs', 'CharacterPrefsTable' => 'cp_charprefs', 'ResetPasswordTable' => 'cp_resetpass', 'ChangeEmailTable' => 'cp_emailchange', 'LoginLogTable' => 'cp_loginlog', 'ChangePasswordTable' => 'cp_pwchange', 'OnlinePeakTable' => 'cp_onlinepeak', 'CMSNewsTable' => 'cp_cmsnews', 'CMSPagesTable' => 'cp_cmspages', 'CMSSettingsTable' => 'cp_cmssettings', 'ServiceDeskTable' => 'cp_servicedesk', 'ServiceDeskATable' => 'cp_servicedeska', 'ServiceDeskCatTable' => 'cp_servicedeskcat', 'ServiceDeskSettingsTable' => 'cp_servicedesksettings', 'WebCommandsTable' => 'cp_commands', 'ItemDescTable' => 'cp_itemdesc', ) ); ?> ================================================ FILE: config/attributes.php ================================================ 'Ice', 2 => 'Earth', 3 => 'Fire', 4 => 'Wind', ); ?> ================================================ FILE: config/cashshopcategories.php ================================================ 'New', 1 => 'Hot', 2 => 'Limited', 3 => 'Rental', 4 => 'Gear', 5 => 'Buff', 6 => 'Heal', 7 => 'Other', 8 => 'Sale' ); ?> ================================================ FILE: config/castlenames.php ================================================ 'Neuschwanstein', 1 => 'Hohenschwangau', 2 => 'Nuenberg', 3 => 'Wuerzburg', 4 => 'Rothenburg', 5 => 'Repherion', 6 => 'Eeyolbriggar', 7 => 'Yesnelph', 8 => 'Bergel', 9 => 'Mersetzdeitz', 10 => 'Bright Arbor', 11 => 'Scarlet Palace', 12 => 'Holy Shadow', 13 => 'Sacred Altar', 14 => 'Bamboo Grove Hill', 15 => 'Kriemhild', 16 => 'Swanhild', 17 => 'Fadhgridh', 18 => 'Skoegul', 19 => 'Gondul', 20 => 'Novice Aldebaran', 21 => 'Novice Geffen', 22 => 'Novice Payon', 23 => 'Novice Prontera', 24 => 'Himinn', 25 => 'Andlangr', 26 => 'Viblainn', 27 => 'Hljod', 28 => 'Skidbladnir', 29 => 'Mardol', 30 => 'Cyr', 31 => 'Horn', 32 => 'Gefn', 33 => 'Bandis', 34 => 'Leilah', 35 => 'Pavianne', 36 => 'Jasmine', 37 => 'Roxie', 38 => 'Curly Sue', 39 => 'Gaebolg', 40 => 'Richard', 41 => 'Wigner', 42 => 'Heine', 43 => 'Nerious' // kRO Names /** * 0 => 'Noisyubantian', * 1 => 'Hohensyubangawoo', * 2 => 'Nyirenverk', * 3 => 'Byirtsburi', * 4 => 'Rotenburk', * 5 => 'Reprion', * 6 => 'Yolbriger', * 7 => 'Isinlife', * 8 => 'Berigel', * 9 => 'Melsedetsu', *10 => 'Mingting', *11 => 'Tiantan', *12 => 'Fuying', *13 => 'Honglou', *14 => 'Zhulinxian', *15 => 'Creamhilt', *16 => 'Sbanhealt', *17 => 'Lazrigees', *18 => 'Squagul', *19 => 'Guindull', *20 => 'Novice Aldebaran', *21 => 'Novice Geffen', *22 => 'Novice Payon', *23 => 'Novice Prontera', *24 => 'Himinn', *25 => 'Andlangr', *26 => 'Viblainn', *27 => 'Hljod', *28 => 'Skidbladnir', *29 => 'Mardol', *30 => 'Cyr', *31 => 'Horn', *32 => 'Gefn', *33 => 'Bandis', *34 => 'Kafragarten 1', *35 => 'Kafragarten 2', *36 => 'Kafragarten 3', *37 => 'Kafragarten 4', *38 => 'Kafragarten 5', *39 => 'Gloria 1', *40 => 'Gloria 2', *41 => 'Gloria 3', *42 => 'Gloria 4', *43 => 'Gloria 5' */ ) ?> ================================================ FILE: config/elements.php ================================================ 'Neutral', 'Water' => 'Water', 'Earth' => 'Earth', 'Fire' => 'Fire', 'Wind' => 'Wind', 'Poison' => 'Poison', 'Holy' => 'Holy', 'Dark' => 'Dark', 'Ghost' => 'Ghost', 'Undead' => 'Undead' ); ?> ================================================ FILE: config/equip_jobs.php ================================================ // Default job list array( 'job_all' => 'All jobs', 'job_novice' => 'Novice', 'job_supernovice' => 'Super novice', 'job_swordman' => 'Swordman', 'job_mage' => 'Mage', 'job_archer' => 'Archer', 'job_acolyte' => 'Acolyte', 'job_merchant' => 'Merchant', 'job_thief' => 'Thief', 'job_knight' => 'Knight', 'job_priest' => 'Priest', 'job_wizard' => 'Wizard', 'job_blacksmith' => 'Blacksmith', 'job_hunter' => 'Hunter', 'job_assassin' => 'Assassin', 'job_crusader' => 'Crusader', 'job_monk' => 'Monk', 'job_sage' => 'Sage', 'job_rogue' => 'Rogue', 'job_alchemist' => 'Alchemist', 'job_barddancer' => 'Bard / Dancer', 'job_taekwon' => 'Taekwon', 'job_stargladiator' => 'Star Gladiator', 'job_soullinker' => 'Soul Linker', 'job_gunslinger' => 'Gunslinger', 'job_ninja' => 'Ninja', ), 1 => // Renewal job list array( 'job_kagerouoboro' => 'Kagerou / Oboro', 'job_rebellion' => 'Rebellion', 'job_summoner' => 'Summoner' ) ) ?> ================================================ FILE: config/equip_location_combinations.php ================================================ 'Two-Handed', 'location_head_low/location_head_mid/location_head_top' => 'Upper/Mid/Lower Headgear', 'location_head_mid/location_head_top' => 'Upper/Mid Headgear', 'location_head_top/location_head_low' => 'Upper/Lower Headgear', 'location_head_low/location_head_mid' => 'Mid/Lower Headgear', 'location_head_low/location_head_top' => 'Upper/Lower Headgear', 'location_costume_head_mid/location_costume_head_top' => 'Costume Upper/Mid Headgear', 'location_costume_head_low/location_costume_head_top' => 'Costume Upper/Lower Headgear', 'location_costume_head_low/location_costume_head_mid' => 'Costume Mid/Lower Headgear', 'location_costume_head_low/location_costume_head_mid/location_costume_head_top' => 'Costume Upper/Mid/Lower Headgear', 'location_left_accessory/location_right_accessory' => 'Accessory Left/Right', 'location_armor/location_garment/location_head_low/location_head_mid/location_head_top/location_left_accessory/location_left_hand/location_right_accessory/location_right_hand/location_shoes' => 'All equip', ) ?> ================================================ FILE: config/equip_locations.php ================================================ 'Lower Headgear', 'location_right_hand' => 'Main Hand', 'location_garment' => 'Garment', 'location_right_accessory' => 'Accessory Right', 'location_armor' => 'Armor', 'location_left_hand' => 'Off Hand', 'location_shoes' => 'Footgear', 'location_left_accessory' => 'Accessory Left', 'location_head_top' => 'Upper Headgear', 'location_head_mid' => 'Middle Headgear', 'location_costume_head_top' => 'Costume Top Headgear', 'location_costume_head_mid' => 'Costume Mid Headgear', 'location_costume_head_low' => 'Costume Low Headgear', 'location_costume_garment' => 'Costume Garment', 'location_ammo' => 'Ammo', 'location_shadow_armor' => 'Shadow Armor', 'location_shadow_weapon' => 'Shadow Weapon', 'location_shadow_shield' => 'Shadow Shield', 'location_shadow_shoes' => 'Shadow Shoes', 'location_shadow_right_accessory' => 'Shadow Accessory Right (Earring)', 'location_shadow_left_accessory' => 'Shadow Accessory Left (Pendant)', ) ?> ================================================ FILE: config/equip_upper.php ================================================ // Default class list array( 'class_all' => 'All classes', 'class_normal' => 'Normal', 'class_upper' => 'Upper', 'class_baby' => 'Baby' ), 1 => // Renewal class list array( 'class_third' => 'Third', 'class_third_upper' => 'Third Upper', 'class_third_baby' => 'Third Baby' ) ) ?> ================================================ FILE: config/error.php ================================================ ================================================ FILE: config/feedingtypes.php ================================================ 'Pet', 'H' => 'Homunculus', 'O' => 'Other', ); ================================================ FILE: config/groups.php ================================================ => array( * 'name' => "", * 'level' => "", * ), */ 0 => array( 'name' => "Player", 'level' => AccountLevel::NORMAL ), 1 => array( 'name' => "Super Player", 'level' => AccountLevel::NORMAL ), 2 => array( 'name' => "Support", 'level' => AccountLevel::LOWGM ), 3 => array( 'name' => "Script Manager", 'level' => AccountLevel::LOWGM ), 4 => array( 'name' => "Event Manager", 'level' => AccountLevel::LOWGM ), 5 => array( 'name' => "VIP", 'level' => AccountLevel::NORMAL ), 10 => array( 'name' => "Law Enforcement", 'level' => AccountLevel::HIGHGM ), 99 => array( 'name' => "Admin", 'level' => AccountLevel::ADMIN ) ); // DON'T TOUCH ANYTHING BELOW. THIS IS FOR DEVELOPERS. /** * Get array of all groups. * * @return array * @access public */ public static function getArray() { return self::$groups; } /** * Get array of group IDs that satisfy the operation * condition that compares the group level. * * @param int $compare * @param string $op * @return array * @access public */ public static function getGroupID($compare, $op) { $group_id = array(); foreach(self::$groups as $id => $group) { if( ($op == '<' && $group['level'] < $compare) || ($op == '>' && $group['level'] > $compare) || ($op == '<=' && $group['level'] <= $compare) || ($op == '>=' && $group['level'] >= $compare)) { array_push($group_id, $id); } } return $group_id; } /** * Get the level associated with the group ID. * * @param int $group_id * @return int * @access public */ public static function getGroupLevel($group_id) { if(isset(self::$groups[$group_id]['level'])) { return self::$groups[$group_id]['level']; } else { return AccountLevel::NORMAL; } } /** * Get the name associated with the group ID. * * @param int $group_id * @return string * @access public */ public static function getGroupName($group_id) { if(isset(self::$groups[$group_id]['name'])) { return self::$groups[$group_id]['name']; } else { return "N/A"; } } } ?> ================================================ FILE: config/homunculus.php ================================================ 'Lif', 6009 => 'Lif', 6005 => 'Lif', 6013 => 'Lif', // Amistr 6002 => 'Amistr', 6010 => 'Amistr', 6006 => 'Amistr', 6014 => 'Amistr', // Filir 6003 => 'Filir', 6011 => 'Filir', 6007 => 'Filir', 6015 => 'Filir', // Vanilmirth 6004 => 'Vanilmirth', 6012 => 'Vanilmirth', 6008 => 'Vanilmirth', 6016 => 'Vanilmirth', // Homunculus S 6048 => 'Eira', 6049 => 'Bayeri', 6050 => 'Sera', 6051 => 'Dieter', 6052 => 'Elanor' ); ?> ================================================ FILE: config/item_randoptions.php ================================================ 'MaxHP +%s', 2 => 'MaxSP +%s', 3 => 'STR +%s', 4 => 'AGI +%s', 5 => 'VIT +%s', 6 => 'INT +%s', 7 => 'DEX +%s', 8 => 'LUK +%s', 9 => 'MaxHP +%s%%', 10 => 'MaxSP +%s%%', 11 => 'HP regen +%s%%', 12 => 'SP regen +%s%%', 13 => 'ATK +%s%%', 14 => 'MATK +%s%%', 15 => 'ASPD +%s', 16 => 'Delay after attack -%s%%', 17 => 'ATK +%s', 18 => 'HIT +%s', 19 => 'MATK +%s', 20 => 'DEF +%s', 21 => 'MDEF +%s', 22 => 'FLEE +%s', 23 => 'Perfect dodge +%s', 24 => 'CRIT +%s', 25 => 'Neutral elemental resistance +%s%%', 26 => 'Water elemental resistance +%s%%', 27 => 'Earth elemental resistance +%s%%', 28 => 'Fire elemental resistance +%s%%', 29 => 'Wind elemental resistance +%s%%', 30 => 'Poison elemental resistance +%s%%', 31 => 'Holy elemental resistance +%s%%', 32 => 'Shadow elemental resistance +%s%%', 33 => 'Ghost elemental resistance +%s%%', 34 => 'Undead elemental resistance +%s%%', 35 => 'All elementals resistance +%s%%', 36 => 'Neutral monster resistance +%s%%', 37 => 'ATK +%s%% against Neutral monster', 38 => 'Water monster resistance +%s%%', 39 => 'ATK +%s%% against Water monster', 40 => 'Earth monster resistance +%s%%', 41 => 'ATK +%s%% against Earth monster', 42 => 'Fire monster resistance +%s%%', 43 => 'ATK +%s%% against Fire monster', 44 => 'Wind monster resistance +%s%%', 45 => 'ATK +%s%% against Wind monster', 46 => 'Poison monster resistance +%s%%', 47 => 'ATK +%s%% against Poison monster', 48 => 'Holy monster resistance +%s%%', 49 => 'ATK +%s%% against Holy monster', 50 => 'Shadow monster resistance +%s%%', 51 => 'ATK +%s%% against Shadow monster', 52 => 'Ghost monster resistance +%s%%', 53 => 'ATK +%s%% against Ghost monster', 54 => 'Undead monster resistance +%s%%', 55 => 'ATK +%s%% against Undead monster', 56 => 'Neutral monster magic resistance +%s%%', 57 => 'MATK +%s%% against Neutral monster', 58 => 'Water monster magic resistance +%s%%', 59 => 'MATK +%s%% against Water monster', 60 => 'Earth monster magic resistance +%s%%', 61 => 'MATK +%s%% against Earth monster', 62 => 'Fire monster magic resistance +%s%%', 63 => 'MATK +%s%% against Fire monster', 64 => 'Wind monster magic resistance +%s%%', 65 => 'MATK +%s%% against Wind monster', 66 => 'Poison monster magic resistance +%s%%', 67 => 'MATK +%s%% against Poison monster', 68 => 'Holy monster magic resistance +%s%%', 69 => 'MATK +%s%% against Holy monster', 70 => 'Shadow monster magic resistance +%s%%', 71 => 'MATK +%s%% against Shadow monster', 72 => 'Ghost monster magic resistance +%s%%', 73 => 'MATK +%s%% against Ghost monster', 74 => 'Undead monster magic resistance +%s%%', 75 => 'MATK +%s%% against Undead monster', 76 => 'Armor element: Neutral', 77 => 'Armor element: Water', 78 => 'Armor element: Earth', 79 => 'Armor element: Fire', 80 => 'Armor element: Wind', 81 => 'Armor element: Poison', 82 => 'Armor element: Holy', 83 => 'Armor element: Shadow', 84 => 'Armor element: Ghost', 85 => 'Armor element: Undead', //86 => '', 87 => 'Formless monster resistance +%s%%', 88 => 'Undead monster resistance +%s%%', 89 => 'Brute monster resistance +%s%%', 90 => 'Plant monster resistance +%s%%', 91 => 'Insect monster resistance +%s%%', 92 => 'Fish monster resistance +%s%%', 93 => 'Demon monster resistance +%s%%', 94 => 'Demihuman monster resistance +%s%%', 95 => 'Angel monster resistance +%s%%', 96 => 'Dragon monster resistance +%s%%', 97 => 'ATK +%s%% against Formless monster', 98 => 'ATK +%s%% against Undead monster', 99 => 'ATK +%s%% against Brute monster', 100 => 'ATK +%s%% against Plant monster', 101 => 'ATK +%s%% against Insect monster', 102 => 'ATK +%s%% against Fish monster', 103 => 'ATK +%s%% against Demon monster', 104 => 'ATK +%s%% against Demihuman monster', 105 => 'ATK +%s%% against Angel monster', 106 => 'ATK +%s%% against Dragon monster', 107 => 'MATK +%s%% against Formless monster', 108 => 'MATK +%s%% against Undead monster', 109 => 'MATK +%s%% against Brute monster', 110 => 'MATK +%s%% against Plant monster', 111 => 'MATK +%s%% against Insect monster', 112 => 'MATK +%s%% against Fish monster', 113 => 'MATK +%s%% against Devil monster', 114 => 'MATK +%s%% against Demihuman monster', 115 => 'MATK +%s%% against Angel monster', 116 => 'MATK +%s%% against Dragon monster', 117 => 'CRIT +%s against Formless monster', 118 => 'CRIT +%s against Undead monster', 119 => 'CRIT +%s against Brute monster', 120 => 'CRIT +%s against Plant monster', 121 => 'CRIT +%s against Insect monster', 122 => 'CRIT +%s against Fish monster', 123 => 'CRIT +%s against Demon monster', 124 => 'CRIT +%s against Demihuman monster', 125 => 'CRIT +%s against Angel monster', 126 => 'CRIT +%s against Dragon monster', 127 => 'Pierces %s%% DEF of Formless monster', 128 => 'Pierces %s%% DEF of Undead monster', 129 => 'Pierces %s%% DEF of Brute monster', 130 => 'Pierces %s%% DEF of Plant monster', 131 => 'Pierces %s%% DEF of Insect monster', 132 => 'Pierces %s%% DEF of Fish monster', 133 => 'Pierces %s%% DEF of Demon monster', 134 => 'Pierces %s%% DEF of Demihuman monster', 135 => 'Pierces %s%% DEF of Angel monster', 136 => 'Pierces %s%% DEF of Dragon monster', 137 => 'Pierces %s%% MDEF of Formless monster', 138 => 'Pierces %s%% MDEF of Undead monster', 139 => 'Pierces %s%% MDEF of Brute monster', 140 => 'Pierces %s%% MDEF of Plant monster', 141 => 'Pierces %s%% MDEF of Insect monster', 142 => 'Pierces %s%% MDEF of Fish monster', 143 => 'Pierces %s%% MDEF of Demon monster', 144 => 'Pierces %s%% MDEF of Demihuman monster', 145 => 'Pierces %s%% MDEF of Angel monster', 146 => 'Pierces %s%% MDEF of Dragon monster', 147 => 'ATK +%s%% against Normal monster', 148 => 'ATK +%s%% against Boss monster', 149 => 'Normal monster resistance +%s%%', 150 => 'Boss monster resistance +%s%%', 151 => 'MATK +%s%% against Normal monster', 152 => 'MATK +%s%% against Boss monster', 153 => 'Pierces %s%% DEF of Normal monster', 154 => 'Pierces %s%% DEF of Boss monster', 155 => 'Pierces %s%% MDEF of Normal monster', 156 => 'Pierces %s%% MDEF of Boss monster', 157 => 'ATK +%s%% against Small size monster', 158 => 'ATK +%s%% against Medium size monster', 159 => 'ATK +%s%% against Large size monster', 160 => 'Small monster resistance +%s%%', 161 => 'Medium monster resistance +%s%%', 162 => 'Large monster resistance +%s%%', 163 => 'Nullify weapon\'s damage size penalty', 164 => 'Critical attack +%s%%', 165 => 'Critical damage -%s%%', 166 => 'Long range physical attack +%s%%', 167 => 'Long range physical damage -%s%%', 168 => 'Healing skills +%s%%', 169 => 'Restoration gained from Healing skills +%s%%', 170 => 'Variable cast time -%s%%', 171 => 'After cast delay -%s%%', 172 => 'Reduces SP cost by %s%%', //173 => '', //174 => '', 175 => 'Weapon element: Neutral', 176 => 'Weapon element: Water', 177 => 'Weapon element: Earth', 178 => 'Weapon element: Fire', 179 => 'Weapon element: Wind', 180 => 'Weapon element: Poison', 181 => 'Weapon element: Holy', 182 => 'Weapon element: Shadow', 183 => 'Weapon element: Ghost', 184 => 'Weapon element: Undead', 185 => 'Indestructible in battle', 186 => 'Indestructible in battle', 187 => 'MATK against Small size monster +%s%%', 188 => 'MATK against Medium size monster +%s%%', 189 => 'MATK against Large size monster +%s%%', 190 => 'Small monster magic resistance +%s%%', 191 => 'Medium monster magic resistance +%s%%', 192 => 'Large monster magic resistance +%s%%', 193 => 'Elemental attacks resistance +%s%%', 194 => 'Formless monster resistance +%s%%', 195 => 'Undead monster resistance +%s%%', 196 => 'Brute monster resistance +%s%%', 197 => 'Plant monster resistance +%s%%', 198 => 'Insect monster resistance +%s%%', 199 => 'Fish monster resistance +%s%%', 200 => 'Demon monster resistance +%s%%', 201 => 'Demihuman monster resistance +%s%%', 202 => 'Angel monster resistance +%s%%', 203 => 'Dragon monster resistance +%s%%', 204 => 'Long range physical attack +%s%%', 205 => 'Long range physical damage -%s%%', 206 => 'Demi-Human players resistance + %s%%', 207 => 'Doram players resistance +%s%%', 208 => 'ATK against Demi-Human players +%s%%', 209 => 'ATK against Doram players +%s%%', 210 => 'MATK against Demi-Human players +%s%%', 211 => 'MATK against Doram players +%s%%', 212 => 'Critical +%s for Demi-Human players', 213 => 'Critical +%s for Doram players', 214 => 'Pierces %s%% DEF of Demi-Human players', 215 => 'Pierces %s%% DEF of Doram players', 216 => 'Pierces %s%% MDEF of Demi-Human players', 217 => 'Pierces %s%% MDEF of Doram players', 218 => 'Recieved reflected damage -%s%%', 219 => 'Melee physical damage +%s%%', 220 => 'Melee physical damage -%s%%', ) ?> ================================================ FILE: config/itemsflags.php ================================================ 'Item is available to Buying Stores', 'flag_deadbranch' => 'Item is a Dead Branch type', 'flag_container' => 'Item is part of a Container', 'flag_uniqueid' => 'Item is a unique stack', 'flag_bindonequip' => 'Item is bound to the character upon equipping', 'flag_dropannounce' => 'Item has a special announcement to self on drop', 'flag_noconsume' => 'Item is consumed on use', ) ?> ================================================ FILE: config/itemsubtypes.php ================================================ array( '1haxe' => 'One-Handed Axe', '1hspear' => 'One-Handed Spear', '1hsword' => 'One-Handed Sword', '2haxe' => 'Two-Handed Axe', '2hspear' => 'Two-Handed Spear', '2hstaff' => 'Two-Handed Staff', '2hsword' => 'Two-Handed Sword', 'book' => 'Book', 'bow' => 'Bow', 'dagger' => 'Dagger', 'gatling' => 'Gatling Gun', 'grenade' => 'Grenade Launcher', 'huuma' => 'Fuuma Shuriken', 'katar' => 'Katar', 'knuckle' => 'Knuckle', 'mace' => 'Mace', 'musical' => 'Musical Instrument', 'revolver' => 'Revolver', 'rifle' => 'Rifle', 'shotgun' => 'Shotgun', 'staff' => 'Staff', 'whip' => 'Whip' ), 'ammo' => array( 'arrow' => 'Arrow', 'bullet' => 'Bullet', 'dagger' => 'Throwing Dagger', 'cannonball' => 'Cannonball', 'grenade' => 'Grenade', 'kunai' => 'Kunai', 'shell' => 'Shell', 'shuriken' => 'Shuriken', 'throwweapon' => 'Throwable Item (Sling Item)' ), 'card' => array( 'normal' => 'Card', 'enchant' => 'Enchant' ) ) ?> ================================================ FILE: config/itemtypes.php ================================================ 'Ammo', 'armor' => 'Armor', 'card' => 'Card', 'cash' => 'Cash Shop Reward', 'delayconsume' => 'Delay Consume', 'etc' => 'Etc', 'healing' => 'Healing', 'petarmor' => 'Pet Armor', 'petegg' => 'Pet Egg', 'shadowgear' => 'Shadow Equipment', 'usable' => 'Usable', 'weapon' => 'Weapon' ) ?> ================================================ FILE: config/jobs.php ================================================ 'Novice', 1 => 'Swordsman', 2 => 'Mage', 3 => 'Archer', 4 => 'Acolyte', 5 => 'Merchant', 6 => 'Thief', 7 => 'Knight', 8 => 'Priest', 9 => 'Wizard', 10 => 'Blacksmith', 11 => 'Hunter', 12 => 'Assassin', //13 => 'Knight (Mounted)', 14 => 'Crusader', 15 => 'Monk', 16 => 'Sage', 17 => 'Rogue', 18 => 'Alchemist', 19 => 'Bard', 20 => 'Dancer', //21 => 'Crusader (Mounted)', 22 => 'Wedding', 23 => 'Super Novice', 24 => 'Gunslinger', 25 => 'Ninja', 26 => 'Xmas', 27 => 'Summer', 28 => 'Hanbok', 29 => 'Oktoberfest', 4001 => 'High Novice', 4002 => 'High Swordsman', 4003 => 'High Mage', 4004 => 'High Archer', 4005 => 'High Acolyte', 4006 => 'High Merchant', 4007 => 'High Thief', 4008 => 'Lord Knight', 4009 => 'High Priest', 4010 => 'High Wizard', 4011 => 'Whitesmith', 4012 => 'Sniper', 4013 => 'Assassin Cross', //4014 => 'Lord Knight (Mounted)', 4015 => 'Paladin', 4016 => 'Champion', 4017 => 'Professor', 4018 => 'Stalker', 4019 => 'Creator', 4020 => 'Clown', 4021 => 'Gypsy', //4022 => 'Paladin (Mounted)', 4023 => 'Baby', 4024 => 'Baby Swordsman', 4025 => 'Baby Mage', 4026 => 'Baby Archer', 4027 => 'Baby Acolyte', 4028 => 'Baby Merchant', 4029 => 'Baby Thief', 4030 => 'Baby Knight', 4031 => 'Baby Priest', 4032 => 'Baby Wizard', 4033 => 'Baby Blacksmith', 4034 => 'Baby Hunter', 4035 => 'Baby Assassin', //4036 => 'Baby Knight (Mounted)', 4037 => 'Baby Crusader', 4038 => 'Baby Monk', 4039 => 'Baby Sage', 4040 => 'Baby Rogue', 4041 => 'Baby Alchemist', 4042 => 'Baby Bard', 4043 => 'Baby Dancer', //4044 => 'Baby Crusader (Mounted)', 4045 => 'Super Baby', 4046 => 'Taekwon', 4047 => 'Star Gladiator', //4048 => 'Star Gladiator (Flying)', 4049 => 'Soul Linker', 4050 => 'Jiang Shi', 4051 => 'Death Knight', 4052 => 'Dark Collector', 4054 => 'Rune Knight', 4055 => 'Warlock', 4056 => 'Ranger', 4057 => 'Arch Bishop', 4058 => 'Mechanic', 4059 => 'Guillotine Cross', 4060 => 'Rune Knight+', 4061 => 'Warlock+', 4062 => 'Ranger+', 4063 => 'Arch Bishop+', 4064 => 'Mechanic+', 4065 => 'Guillotine Cross+', 4066 => 'Royal Guard', 4067 => 'Sorcerer', 4068 => 'Minstrel', 4069 => 'Wanderer', 4070 => 'Sura', 4071 => 'Genetic', 4072 => 'Shadow Chaser', 4073 => 'Royal Guard+', 4074 => 'Sorcerer+', 4075 => 'Minstrel+', 4076 => 'Wanderer+', 4077 => 'Sura+', 4078 => 'Genetic+', 4079 => 'Shadow Chaser+', //4080 => 'Rune Knight (Mounted)', //4081 => 'Rune Knight+ (Mounted)', //4082 => 'Royal Guard (Mounted)', //4083 => 'Royal Guard+ (Mounted)', //4084 => 'Ranger (Mounted)', //4085 => 'Ranger+ (Mounted)', //4086 => 'Mechanic (Magic Gear)', //4087 => 'Mechanic+ (Magic Gear)', 4096 => 'Baby Rune Knight', 4097 => 'Baby Warlock', 4098 => 'Baby Ranger', 4099 => 'Baby Arch Bishop', 4100 => 'Baby Mechanic', 4101 => 'Baby Guillotine Cross', 4102 => 'Baby Royal Guard', 4103 => 'Baby Sorcerer', 4104 => 'Baby Minstrel', 4105 => 'Baby Wanderer', 4106 => 'Baby Sura', 4107 => 'Baby Genetic', 4108 => 'Baby Shadow Chaser', //4109 => 'Baby Rune Knight (Mounted)', //4110 => 'Baby Royal Guard (Mounted)', //4111 => 'Baby Ranger (Mounted)', //4112 => 'Baby Mechanic (Magic Gear)', 4190 => 'Expanded Super Novice', 4191 => 'Expanded Super Baby', 4211 => 'Kagerou', 4212 => 'Oboro', 4215 => 'Rebellion', 4218 => 'Summoner', 4220 => 'Baby Summoner', 4222 => 'Baby Ninja', 4223 => 'Baby Kagero', 4224 => 'Baby Oboro', 4225 => 'Baby Taekwon', 4226 => 'Baby Star Gladiator', 4227 => 'Baby Soul Linker', 4228 => 'Baby Gunslinger', 4229 => 'Baby Rebellion', //4238 => 'Baby Star Gladiator (Union)', //4238 => 'Baby Star Glad (Union)', 4239 => 'Star Emperor', 4240 => 'Soul Reaper', 4241 => 'Baby Star Emperor', 4242 => 'Baby Soul Reaper', 4252 => 'Dragon Knight', 4253 => 'Meister', 4254 => 'Shadow Cross', 4255 => 'Arch Mage', 4256 => 'Cardinal', 4257 => 'WindHawk', 4258 => 'Imperial Guard', 4259 => 'Biolo', 4260 => 'Abyss Chaser', 4261 => 'Elemental Master', 4262 => 'Inquisitor', 4263 => 'Troubadour', 4264 => 'Trouvere', //4278 => 'Windhawk (Mounted)', //4279 => 'Meister (Mounted)', //4280 => 'Dragon Knight (Mounted)', //4281 => 'Imperial Guard (Mounted)', 4302 => 'Sky Emperor', 4303 => 'Soul Ascetic', 4304 => 'Shinkiro', 4305 => 'Shiranui', 4306 => 'Night Watch', 4307 => 'Hyper Novice', 4308 => 'Spirit Handler', //4316 => 'Sky Emperor (Mounted)', ) ?> ================================================ FILE: config/jobs_alchemist.php ================================================ 'Alchemist', 4019 => 'Creator', 4041 => 'Baby Alchemist', 4071 => 'Genetic', 4078 => 'Genetic+', 4107 => 'Baby Genetic', 4259 => 'Biolo' ) ?> ================================================ FILE: config/jobs_blacksmith.php ================================================ 'Blacksmith', 4011 => 'Whitesmith', 4033 => 'Baby Blacksmith', 4058 => 'Mechanic', 4064 => 'Mechanic+', 4100 => 'Baby Mechanic', 4253 => 'Meister' ) ?> ================================================ FILE: config/jobs_gender_linked.php ================================================ 'Bard', 20 => 'Dancer', 4020 => 'Clown', 4021 => 'Gypsy', 4042 => 'Baby Bard', 4043 => 'Baby Dancer', 4068 => 'Minstrel', 4069 => 'Wanderer', 4075 => 'Minstrel+', 4076 => 'Wanderer+', 4104 => 'Baby Minstrel', 4105 => 'Baby Wanderer', 4211 => 'Kagerou', 4212 => 'Oboro', 4223 => 'Baby Kagerou', 4224 => 'Baby Oboro', 4263 => 'Troubadour', 4264 => 'Trouvere' ) ?> ================================================ FILE: config/loginerrors.php ================================================ 'Unexpected Error', 1 => 'Invalid Server', 2 => 'Invalid Credentials', 3 => 'Temporarily Banned', 4 => 'Permanently Banned', 5 => 'IP Banned', 6 => 'Invalid Security Code', 7 => 'Pending Confirmation' ) ?> ================================================ FILE: config/monster_ai.php ================================================ array('mode_canattack', 'mode_canmove'), '02' => array('mode_canattack', 'mode_looter', 'mode_canmove'), '03' => array('mode_changetargetmelee', 'mode_canattack', 'mode_assist', 'mode_canmove'), '04' => array('mode_changetargetchase', 'mode_changetargetmelee', 'mode_angry', 'mode_canattack', 'mode_aggressive', 'mode_canmove'), '05' => array('mode_changetargetchase', 'mode_canattack', 'mode_aggressive', 'mode_canmove'), '06' => array(), '07' => array('mode_changetargetmelee', 'mode_canattack', 'mode_assist', 'mode_looter', 'mode_canmove'), '08' => array('mode_targetweak', 'mode_changetargetchase', 'mode_changetargetmelee', 'mode_canattack', 'mode_aggressive', 'mode_canmove'), '09' => array('mode_changetargetchase', 'mode_changetargetmelee', 'mode_canattack', 'mode_castsensoridle', 'mode_aggressive', 'mode_canmove'), '10' => array('mode_canattack', 'mode_aggressive'), '11' => array('mode_canattack', 'mode_aggressive'), '12' => array('mode_changetargetchase', 'mode_canattack', 'mode_aggressive', 'mode_canmove'), '13' => array('mode_changetargetchase', 'mode_changetargetmelee', 'mode_canattack', 'mode_assist', 'mode_aggressive', 'mode_canmove'), //14 => array(), //15 => array(), //16 => array(), '17' => array('mode_canattack', 'mode_castsensoridle', 'mode_canmove'), //18 => array(), '19' => array('mode_changetargetchase', 'mode_changetargetmelee', 'mode_canattack', 'mode_castsensoridle', 'mode_aggressive', 'mode_canmove'), '20' => array('mode_changetargetchase', 'mode_changetargetmelee', 'mode_castsensorchase', 'mode_canattack', 'mode_castsensoridle', 'mode_aggressive', 'mode_canmove'), '21' => array('mode_changetargetchase', 'mode_changetargetmelee', 'mode_changechase', 'mode_castsensorchase', 'mode_canattack', 'mode_castsensoridle', 'mode_aggressive', 'mode_canmove'), //22 => array(), //23 => array(), '24' => array('mode_canattack', 'mode_norandomwalk', 'mode_canmove'), '25' => array('mode_canmove'), '26' => array('mode_randomtarget', 'mode_changetargetchase', 'mode_changetargetmelee', 'mode_changechase', 'mode_castsensorchase', 'mode_canattack', 'mode_castsensoridle', 'mode_aggressive', 'mode_canmove'), '27' => array('mode_randomtarget', 'mode_canattack', 'mode_aggressive'), ) ?> ================================================ FILE: config/monstermode.php ================================================ 'Aggressive', 'mode_angry' => 'Angry', 'mode_assist' => 'Assist', 'mode_canattack' => 'Can Attack', 'mode_canmove' => 'Can Move', 'mode_castsensorchase' => 'Cast Sensor Chase', 'mode_castsensoridle' => 'Cast Sensor Idle', 'mode_changechase' => 'Change Chase', 'mode_changetargetchase' => 'Change Target Chase', 'mode_changetargetmelee' => 'Change Target Melee', 'mode_detector' => 'Detector', 'mode_fixeditemdrop' => 'Fixed Item Drop', 'mode_ignoremagic' => 'Ignore Magic', 'mode_ignoremelee' => 'Ignore Melee', 'mode_ignoremisc' => 'Ignore Misc', 'mode_ignoreranged' => 'Ignore Ranged', 'mode_knockbackimmune' => 'Knockback Immune', 'mode_looter' => 'Looter', 'mode_mvp' => 'MVP', 'mode_norandomwalk' => 'Plant', 'mode_randomtarget' => 'Random Target', 'mode_skillimmune' => 'Skill Immune', 'mode_statusimmune' => 'Status Immune', 'mode_targetweak' => 'Target Weak', 'mode_teleportblock' => 'Teleport Block', ) ?> ================================================ FILE: config/picktypes.php ================================================ 'Admin', 'B' => 'Buy Store', 'C' => 'Consumed', 'D' => 'Stolen/Ganked', 'E' => 'Mailed', 'F' => 'Bound Retrieval', 'G' => 'Guild Storage', //'H' => '', 'I' => 'Auctioned', //'J' => '', 'K' => 'Bank', 'L' => 'Looted', 'M' => 'Monster', 'N' => 'NPC (Script)', 'O' => 'Produced', 'P' => 'Player', 'Q' => 'Quest', 'R' => 'Storage', 'S' => 'NPC (Shop)', 'T' => 'Traded', 'U' => 'MVP', 'V' => 'Vended', //'W' => '', 'X' => 'Other', 'Y' => 'Lottery', 'Z' => 'Merged', '$' => 'Cash', ); ?> ================================================ FILE: config/races.php ================================================ 'Formless', 'Undead' => 'Undead', 'Brute' => 'Brute', 'Plant' => 'Plant', 'Insect' => 'Insect', 'Fish' => 'Fish', 'Demon' => 'Demon', 'Demihuman' => 'Demi-Human', 'Angel' => 'Angel', 'Dragon' => 'Dragon' ) ?> ================================================ FILE: config/servers.php ================================================ 'FluxRO', // Global database configuration (excludes logs database configuration). 'DbConfig' => array( //'Socket' => '/tmp/mysql.sock', //'Port' => 3306, //'Encoding' => 'utf8', // Connection encoding -- use whatever here your MySQL tables collation is. 'Convert' => 'utf8', // -- 'Convert' option only works when 'Encoding' option is specified and iconv (http://php.net/iconv) is available. // -- It specifies the encoding to convert your MySQL data to on the website (most likely needs to be utf8) 'Hostname' => '127.0.0.1', 'Username' => 'ragnarok', 'Password' => 'ragnarok', 'Database' => 'ragnarok', 'Persistent' => true, 'Timezone' => null // Example: '+0:00' is UTC. // The possible values of 'Timezone' is as documented from the MySQL website: // "The value can be given as a string indicating an offset from UTC, such as '+10:00' or '-6:00'." // "The value can be given as a named time zone, such as 'Europe/Helsinki', 'US/Eastern', or 'MET'." (see below continuation!) // **"Named time zones can be used only if the time zone information tables in the mysql database have been created and populated." ), // This is kept separate because many people choose to have their logs // database accessible under different credentials, and often on a // different server entirely to ensure the reliability of the log data. 'LogsDbConfig' => array( //'Socket' => '/tmp/mysql.sock', //'Port' => 3306, //'Encoding' => null, // Connection encoding -- use whatever here your MySQL tables collation is. 'Convert' => 'utf8', // -- 'Convert' option only works when 'Encoding' option is specified and iconv (http://php.net/iconv) is available. // -- It specifies the encoding to convert your MySQL data to on the website (most likely needs to be utf8) 'Hostname' => '127.0.0.1', 'Username' => 'ragnarok', 'Password' => 'ragnarok', 'Database' => 'ragnarok', 'Persistent' => true, 'Timezone' => null // Possible values is as described in the comment in DbConfig. ), // Web server configuration. 'WebDbConfig' => array( 'Hostname' => '127.0.0.1', 'Username' => 'ragnarok', 'Password' => 'ragnarok', 'Database' => 'ragnarok', 'Persistent' => true ), // Login server configuration. 'LoginServer' => array( 'Address' => '127.0.0.1', 'Port' => 6900, 'UseMD5' => false, 'NoCase' => true, // rA account case-sensitivity; Default: Case-INsensitive (true). 'GroupID' => 0, // Default account group ID during registration. //'Database' => 'ragnarok' ), 'CharMapServers' => array( array( 'ServerName' => 'FluxRO', 'Renewal' => true, 'MaxCharSlots' => 9, 'DateTimezone' => null, // Specifies game server's timezone for this char/map pair. (See: http://php.net/timezones) //'ResetDenyMaps' => 'sec_pri', // Defaults to 'sec_pri'. This value can be an array of map names. //'Database' => 'ragnarok', // Defaults to DbConfig.Database 'ExpRates' => array( 'Base' => 100, // Rate at which (base) exp is given 'Job' => 100, // Rate at which job exp is given 'Mvp' => 100 // MVP bonus exp rate ), 'DropRates' => array( // If drop rate was below this amount and bonus is applied to it, the bonus can't make it exceed this amount. 'DropRateCap' => 9000, // The rate the common items (in the ETC tab, besides card) are dropped 'Common' => 100, 'CommonBoss' => 100, 'CommonMVP' => 100, 'CommonMin' => 1, 'CommonMax' => 10000, // The rate healing items (that restore HP or SP) are dropped 'Heal' => 100, 'HealBoss' => 100, 'HealMVP' => 100, 'HealMin' => 1, 'HealMax' => 10000, // The rate usable items (in the item tab other then healing items) are dropped 'Useable' => 100, 'UseableBoss' => 100, 'UseableMVP' => 100, 'UseableMin' => 1, 'UseableMax' => 10000, // The rate at which equipment is dropped 'Equip' => 100, 'EquipBoss' => 100, 'EquipMVP' => 100, 'EquipMin' => 1, 'EquipMax' => 10000, // The rate at which cards are dropped 'Card' => 100, 'CardBoss' => 100, 'CardMVP' => 100, 'CardMin' => 1, 'CardMax' => 10000, // The rate adjustment for the MVP items that the MVP gets directly in their inventory 'MvpItem' => 100, 'MvpItemMin' => 1, 'MvpItemMax' => 10000, // 0 - official order (Show message "Note: Only one MVP drop will be rewarded.") , 2 - all items 'MvpItemMode' => 0, ), 'CharServer' => array( 'Address' => '127.0.0.1', 'Port' => 6121 ), 'MapServer' => array( 'Address' => '127.0.0.1', 'Port' => 5121 ), // -- WoE days and times -- // First parameter: Starding day 0=Sunday / 1=Monday / 2=Tuesday / 3=Wednesday / 4=Thursday / 5=Friday / 6=Saturday // Second parameter: Starting hour in 24-hr format. // Third paramter: Ending day (possible value is same as starting day). // Fourth (final) parameter: Ending hour in 24-hr format. // ** (Note, invalid times are ignored silently.) 'WoeDayTimes' => array( //array(0, '12:00', 0, '14:00'), // Example: Starts Sunday 12:00 PM and ends Sunday 2:00 PM //array(3, '14:00', 3, '15:00') // Example: Starts Wednesday 2:00 PM and ends Wednesday 3:00 PM ), // Modules and/or actions to disallow access to during WoE. 'WoeDisallow' => array( array('module' => 'character', 'action' => 'online'), // Disallow access to "Who's Online" page during WoE. array('module' => 'character', 'action' => 'mapstats') // Disallow access to "Map Statistics" page during WoE. ) ) ) ) ); ?> ================================================ FILE: config/shopcategories.php ================================================ 'Headgears', // Headgears category, most likely doesn't include wings. 1 => 'Wings', // Wings category, though most of the time wings are headgear, this is more dedicated. 2 => 'Armors', // Armors category, most likely doesn't include headgears. 3 => 'Weapons', // Weapons category. 4 => 'Healing Items', // Good category to place healing items under, e.g., Yggdrasil Berries and the like. 5 => 'Pets', // Some people may choose to sell pet eggs or pet-related items under here. 6 => 'Miscellaneous', // Anything you can't really categorize, you can put under this category. 7 => 'Cards' // Cards category. ); ?> ================================================ FILE: config/sizes.php ================================================ 'Small', 'Medium' => 'Medium', 'Large' => 'Large' ) ?> ================================================ FILE: config/trade_restrictions.php ================================================ 'Can\'t be dropped', 'trade_notrade' => 'Can\'t be traded with player', 'trade_tradepartner' => 'Can\'t be traded with partner', 'trade_nosell' => 'Can\'t be sold to NPC', 'trade_nocart' => 'Can\'t be put in Cart', 'trade_nostorage' => 'Can\'t be put in Storage', 'trade_noguildstorage' => 'Can\'t be put in Guild Storage', 'trade_nomail' => 'Can\'t be attached in Mail', 'trade_noauction' => 'Can\'t be auctioned' ) ?> ================================================ FILE: data/captcha/fonts/index.html ================================================ ================================================ FILE: data/captcha/index.html ================================================ ================================================ FILE: data/emblem/index.html ================================================ ================================================ FILE: data/index.html ================================================ ================================================ FILE: data/items/icons/index.html ================================================ ================================================ FILE: data/items/images/index.html ================================================ ================================================ FILE: data/items/index.html ================================================ ================================================ FILE: data/itemshop/index.html ================================================ ================================================ FILE: data/jobs/images/F/index.html ================================================ ================================================ FILE: data/jobs/images/M/index.html ================================================ ================================================ FILE: data/jobs/images/index.html ================================================ ================================================ FILE: data/jobs/index.html ================================================ ================================================ FILE: data/logs/index.html ================================================ ================================================ FILE: data/monsters/index.html ================================================ ================================================ FILE: data/npc/DonationNPC.txt ================================================ map,x,y,d script Donor Rewards Redeemer 987,{ // ----------------- NPC Settings ----------------- // --- SET THESE BEFORE LOADING THE SCRIPT! --- // Server Name set .serverName$,"FluxRO"; // NPC Name to display during chat. // Default: "[Donor Rewards Redeemer]" set .npcName$,"[Donor Rewards Redeemer]"; // DO NOT CHANGE THIS! // Default: "cp_redeemlog" set .redeemTable$,"cp_redeemlog"; // Display Credits to FluxCP Creators? // Help promote our product if its useful. // 0 = Disable. 1 = Enable. // Default: 1 set .showCredits,1; // Max number of unique items to redeem at a time. // DO NOT RAISE THIS VALUE ABOVE 128 WITHOUT // MAKING THE NECESSARY SCRIPT ENGINE MODS // FOR SCRIPT ARRAY SIZING! DANGEROUS! // Default: 128 set .numRedemptionsSimul,128; // --------------- End NPC Settings --------------- // ----------------- Begin Script ----------------- mes .npcName$; mes "Well hello there " + (Sex ? "good sir!" : "young madam!"); mes "How may I be of assistance to you on this fine day?"; next; prompt("I wish to redeem items:Who might you be?:I am merely perusing the area"); mes .npcName$; switch(@menu) { case 1: query_sql "SELECT `id`, `nameid`, `quantity` FROM `" + escape_sql(.redeemTable$) + "` WHERE `account_id` = " + getcharid(3) + " AND `redeemed` = 0 LIMIT " + .numRedemptionsSimul,.@id,.@nameid,.@quantity; if (getarraysize(.@id) > 0) { mes "Items Pending Redemption: " + getarraysize(.@id); for (set .@i,0; .@i < getarraysize(.@id); set .@i,.@i+1) if (checkweight(.@nameid[.@i],.@quantity[.@i]) == 0) { mes "I'm terribly sorry, but you are carrying too much to accept " + (.@i ? "any more of " : " ") + "your rewards at this time."; mes "Please come back with fewer items."; } else { query_sql "UPDATE `" + escape_sql(.redeemTable$) + "` SET `char_id` = " + getcharid(0) + ", `redeemed` = 1, `redemption_date` = NOW() WHERE `id` = " + .@id[.@i]; getitem .@nameid[.@i],.@quantity[.@i]; mes .@quantity[.@i] + "x " + getitemname(.@nameid[.@i]); } if (.@i == getarraysize(.@id)) { mes "Thank you for your patronage " + (Sex ? "fine sir." : "ma'am."); mes "Please enjoy your stay on " + .serverName$ + "!"; } if (.showCredits) callfunc "F_FluxCredits"; } else { mes "My records indicate that there are no rewards awaiting to be redeemed."; mes "My deepest apologies for the misunderstanding."; } break; case 2: mes "I am here to allow for the redemption of rewards for donations to " + .serverName$ + "."; mes "Donations may be made to the server via the control panel."; break; default: mes "Very well then."; mes "Good day to you."; break; } close; // ------------------ End Script ------------------ } // ------------ Credits to FluxCP Creators ------------ // - Please do not modify or delete this function or - // - its contents. To disable the credits from being - // - shown, set .showCredits to 0 in the NPC Settings - // - at the top of this file. - // ---------------------------------------------------- function script F_FluxCredits { mes "-----------------------------------"; mes "Powered by Flux Control Panel."; mes "Copyright � 2008-2012 Matthew Harris and Nikunj Mehta."; mes "http://fluxcp.googlecode.com/"; return; } ================================================ FILE: data/npc/PeakNPC.txt ================================================ - script Highest Peak -1,{ OnPCLoginEvent: // Assign current number of online players sleep 1000; .onlineusers = getusers(1); // Today's date .date$ = gettime(DT_YEAR)+"-"+gettime(DT_MONTH)+"-"+gettime(DT_DAYOFMONTH); // Query for the highest peak in the database query_sql("SELECT `users` FROM `" + .sqltable$ + "` ORDER BY `users` LIMIT 1",.@countusers); if(getarraysize(.@countusers) == 0) { // There doesn't seem to be a row in our table, so lets create one query_sql("INSERT INTO `" + .sqltable$ + "` (`users`, `date`) VALUES (" + .onlineusers + ", '" + .date$ + "')"); } else { if(.onlineusers > .@countusers[0]) { // This is where we check if we want to announce a new peak if(.displaypeakannounce == 1){ announce "We have reached a new player peak! We now have "+.onlineusers+" online!",bc_all; } // Now lets update the table with our new player peak query_sql("UPDATE `" + .sqltable$ + "` SET `users` = '" + .onlineusers + "', `date` = '" + .date$ + "'"); } } end; OnInit: // CONFIGS // We need an SQL table name first .sqltable$ = "cp_onlinepeak"; // Would you like an announcement when you reach a higher peak? // 1 = Yes // 0 = No .displaypeakannounce = 1; // END CONFIGS } ================================================ FILE: data/npc/index.html ================================================ ================================================ FILE: data/npc/support_cmd.txt ================================================ //===== rAthena Script ======================================= //= @support //===== By: ================================================== //= Akkarin //===== Current Version: ===================================== //= 1.00.01 //===== Description: ========================================= //= Script control over @support //============================================================ - script atcmd_support -1,{ OnInit: bindatcmd("support","atcmd_support::Onsupport"); end; Onsupport: query_sql "SELECT `cat_id`, `name` FROM `cp_servicedeskcat` WHERE `display` = 1 ORDER BY `name`", @cat_id, @cat_name$; mes "Please select one of the following categories"; set @j,0; for(set @i, 0; @i < getarraysize(@cat_id); set @i, @i + 1){ set @menulist$[@j],@cat_name$[@i]; set @menureference[@j],@i; set @j,@j+1; } menu @menulist$[0],-,@menulist$[1],-,@menulist$[2],-,@menulist$[3],-,@menulist$[4],-,@menulist$[5],-,@menulist$[6],-,@menulist$[7],-,@menulist$[8],-,@menulist$[9],-,@menulist$[10],-,@menulist$[11],-,@menulist$[12],-,@menulist$[13],-,@menulist$[14],-,@menulist$[15],-,@menulist$[16],-,@menulist$[17],-,@menulist$[18],-,@menulist$[19],-,@menulist$[20],-,@menulist$[21],-,@menulist$[22],-,@menulist$[23],-,@menulist$[24],-,@menulist$[25],-,@menulist$[26],-,@menulist$[27],-,@menulist$[28],-,@menulist$[29],-,@menulist$[30],-; next; mes "Next, please type in a subject line"; input @subject$; next; mes "Please tell us what the problem is. You must make sure that you keep this brief so all the text fits into the box!"; input @body$; next; mes "This is what we have so far.", "Click 'Next' to view each entry, then submit your ticket."; next; mes "^FF0000Category^000000", "You selected "+@cat_name$[@menureference[@menu-1]]; next; mes "^FF0000Subject^000000", @subject$; next; mes "^FF0000Body^000000", @body$; next; mes "If this is all correct, your ticket will be created.", "Continue?"; if(select("Yes:No")==1) { query_sql "SELECT `email`, `last_ip` FROM `login` WHERE `account_id` = '"+getcharid(3)+"'", @player_email$, @player_lastip$; query_sql("INSERT INTO `cp_servicedesk` (`account_id`, `category`, `char_id`, `timestamp`, `sslink`, `chatlink`, `videolink`, `subject`, `text`, `ip`, `curemail`) VALUES ('"+getcharid(3)+"', '"+@cat_id[@menureference[@menu-1]]+"', '"+getcharid(0)+"', NOW(), '0', '0', '0', '"+@subject$+"', '"+@body$+"', '"+@player_lastip$+"', '"+@player_email$+"')"); mes "Ticket created."; close; } else { mes "Submission terminated."; close; end; } end; } ================================================ FILE: data/npc/web_commands.txt ================================================ //===== rAthena Script ======================================= //= Web Commander //===== By: ================================================== //= Akkarin, rAthena FluxCP //===== Description: ========================================= //= Simple script to check sql table for commands to process. //= Data is input via FluxCP module and checked for unexecuted //= commands every 2 seconds. //===== Additional Comments: ================================= //= 1.0 First Version. //= 1.1 Fixed code to prevent single-run senarios. //============================================================ - script Commands -1,{ OnInit: start: initnpctimer; end; OnTimer2000: .@nb2 = query_sql("SELECT COUNT(*) FROM cp_commands WHERE done=0",.@count); if(.@count != 0) { .@nb = query_sql("SELECT command,id,account_id FROM cp_commands WHERE done=0 ORDER BY id LIMIT 1",.@command$,.@id,.@account_id); if(compare(.@command$,"@")) { attachrid(.@account_id[0]); atcommand .@command$[0]; } else charcommand .@command$[0]; query_sql("UPDATE cp_commands SET done='1' WHERE command='"+.@command$[0]+"' AND id='"+.@id[0]+"'"); .@nb = 0; .@nb2 = 0; .@count = 0; .@command$ = 0; .@id = 0; .@account_id = 0; } stopnpctimer; goto start; } ================================================ FILE: data/paypal/button.php ================================================ $session->loginAthenaGroup->serverName, 'account_id' => $session->account->account_id); $customDataEscaped = htmlspecialchars(base64_encode(serialize($customDataArray))); $businessEmail = htmlspecialchars(Flux::config('PayPalBusinessEmail')); $donationCurrency = htmlspecialchars(Flux::config('DonationCurrency')); $creditExchangeRate = Flux::config('CreditExchangeRate'); $donationCredits = floor($amount / $creditExchangeRate); $itemName = htmlspecialchars(sprintf('Donation Credits: %s CREDIT(s)', number_format($donationCredits))); ?>

================================================ FILE: data/paypal/index.html ================================================ ================================================ FILE: data/schemas/charmapdb/cp_charprefs.20080929191525.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_charprefs` ( `id` int(10) unsigned NOT NULL auto_increment, `account_id` int(11) unsigned NOT NULL, `char_id` int(11) unsigned NOT NULL, `name` varchar(80) NOT NULL, `value` varchar(255) default NULL, `create_date` datetime default NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM COMMENT='Character preferences.'; ================================================ FILE: data/schemas/charmapdb/cp_charprefs.20081109093448.sql ================================================ ALTER TABLE `cp_charprefs` ADD INDEX ( `account_id` , `char_id` ) ; ================================================ FILE: data/schemas/charmapdb/cp_charprefs.20120816150540.sql ================================================ ALTER TABLE `cp_charprefs` ADD INDEX (`char_id`); ================================================ FILE: data/schemas/charmapdb/cp_commands.20160608065501.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_commands` ( `id` int(6) NOT NULL AUTO_INCREMENT, `command` varchar(128) NOT NULL DEFAULT '0', `issuer` varchar(32) NOT NULL DEFAULT '0', `account_id` int(12) NOT NULL DEFAULT '0', `done` int(1) NOT NULL DEFAULT '0', `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ================================================ FILE: data/schemas/charmapdb/cp_itemdesc.20170210033400.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_itemdesc` ( `itemid` int(10) unsigned NOT NULL auto_increment, `itemdesc` text NOT NULL, PRIMARY KEY (`itemid`) ) ENGINE=MyISAM COMMENT='Stored item descriptions from parsed itemInfo.'; ================================================ FILE: data/schemas/charmapdb/cp_itemshop.20080928225124.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_itemshop` ( `id` int(11) unsigned NOT NULL auto_increment, `nameid` int(11) unsigned NOT NULL default '0', `quantity` int(11) unsigned NOT NULL default '0', `cost` int(11) unsigned NOT NULL, `info` text, `create_date` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM COMMENT='Item shop'; ================================================ FILE: data/schemas/charmapdb/cp_itemshop.20081109093448.sql ================================================ DROP PROCEDURE IF EXISTS cp_itemshop_20081109093448; CREATE PROCEDURE cp_itemshop_20081109093448() BEGIN DECLARE CONTINUE HANDLER FOR 1060 BEGIN END; ALTER TABLE `cp_itemshop` ADD `use_existing` TINYINT NOT NULL DEFAULT '0' AFTER `info`; END; CALL cp_itemshop_20081109093448(); DROP PROCEDURE cp_itemshop_20081109093448; ================================================ FILE: data/schemas/charmapdb/cp_itemshop.20081128093449.sql ================================================ ALTER TABLE `cp_itemshop` ADD INDEX ( `nameid` ) ; ================================================ FILE: data/schemas/charmapdb/cp_itemshop.20090104190020.sql ================================================ DROP PROCEDURE IF EXISTS cp_itemshop_20090104190020; CREATE PROCEDURE cp_itemshop_20090104190020() BEGIN DECLARE CONTINUE HANDLER FOR 1060 BEGIN END; ALTER TABLE `cp_itemshop` ADD `category` INT(11) NULL AFTER `nameid`; END; CALL cp_itemshop_20090104190020(); DROP PROCEDURE cp_itemshop_20090104190020; ================================================ FILE: data/schemas/charmapdb/cp_onlinepeak.20131120120201.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_onlinepeak` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `users` int(10) unsigned NOT NULL DEFAULT '0', `date` date NOT NULL, PRIMARY KEY (`id`) ) ENGINE = MYISAM; ================================================ FILE: data/schemas/charmapdb/cp_redeemlog.20080928225124.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_redeemlog` ( `id` int(11) unsigned NOT NULL auto_increment, `nameid` int(11) unsigned NOT NULL default '0', `quantity` int(11) unsigned NOT NULL default '0', `cost` int(11) unsigned NOT NULL, `account_id` int(11) unsigned NOT NULL, `char_id` int(11) unsigned default NULL, `redeemed` tinyint(1) unsigned NOT NULL, `redemption_date` datetime default NULL, `purchase_date` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM COMMENT='Log of redeemed donation items.'; ================================================ FILE: data/schemas/charmapdb/cp_redeemlog.20081001054354.sql ================================================ DROP PROCEDURE IF EXISTS cp_redeemlog_20081001054354; CREATE PROCEDURE cp_redeemlog_20081001054354() BEGIN DECLARE CONTINUE HANDLER FOR 1060 BEGIN END; ALTER TABLE `cp_redeemlog` ADD `credits_before` INT( 10 ) NOT NULL , ADD `credits_after` INT( 10 ) NOT NULL;END; CALL cp_redeemlog_20081001054354(); DROP PROCEDURE cp_redeemlog_20081001054354; ================================================ FILE: data/schemas/charmapdb/cp_redeemlog.20081109093448.sql ================================================ ALTER TABLE `cp_redeemlog` ADD INDEX ( `nameid` , `account_id` , `char_id` ) ; ================================================ FILE: data/schemas/charmapdb/cp_xferlog.20080928225124.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_xferlog` ( `id` int(10) unsigned NOT NULL auto_increment, `from_account_id` int(10) unsigned NOT NULL, `target_account_id` int(10) unsigned NOT NULL, `target_char_id` int(11) unsigned NOT NULL, `amount` int(10) unsigned NOT NULL, `for_free` tinyint(1) unsigned NOT NULL default '0', `transfer_date` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM COMMENT='Credit transfer log.'; ================================================ FILE: data/schemas/charmapdb/cp_xferlog.20081109093448.sql ================================================ ALTER TABLE `cp_xferlog` ADD INDEX ( `from_account_id` , `target_account_id` , `target_char_id` ) ; ================================================ FILE: data/schemas/charmapdb/index.html ================================================ ================================================ FILE: data/schemas/index.html ================================================ ================================================ FILE: data/schemas/logindb/cp_banlog.20131213174201.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_banlog` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `account_id` int(11) unsigned NOT NULL, `banned_by` int(11) unsigned DEFAULT NULL, `ban_type` tinyint(1) NOT NULL, `ban_until` datetime NOT NULL, `ban_date` datetime NOT NULL, `ban_reason` text NOT NULL, PRIMARY KEY (`id`), KEY `account_id` (`account_id`,`banned_by`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ================================================ FILE: data/schemas/logindb/cp_cmsnews.20131120145701.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_cmsnews` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(100) NOT NULL, `body` text NOT NULL, `link` varchar(100) NOT NULL, `author` varchar(100) NOT NULL, `created` datetime NOT NULL, `modified` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE = MYISAM; ================================================ FILE: data/schemas/logindb/cp_cmspages.20131120161901.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_cmspages` ( `id` int(11) NOT NULL AUTO_INCREMENT, `path` varchar(100) NOT NULL, `title` varchar(100) NOT NULL, `body` text NOT NULL, `modified` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ; INSERT INTO `cp_cmspages` (`id`, `path`, `title`, `body`, `modified`) VALUES (1, 'rules', 'Rules', 'This is a rules page.', '2013-11-20 00:00:00'), (2, 'downloads', 'Downloads', 'This is a download page.', '2017-07-20 00:00:00'); ================================================ FILE: data/schemas/logindb/cp_cmssettings.20131120145801.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_cmssettings` ( `name` varchar(128) NOT NULL, `value` varchar(128) NOT NULL, UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ================================================ FILE: data/schemas/logindb/cp_createlog.20131213174201.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_createlog` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `account_id` int(11) unsigned NOT NULL, `userid` varchar(23) NOT NULL, `user_pass` varchar(32) NOT NULL, `sex` enum('M','F','S') NOT NULL DEFAULT 'M', `email` varchar(39) NOT NULL, `reg_date` datetime NOT NULL, `reg_ip` varchar(100) NOT NULL, `delete_date` datetime DEFAULT NULL, `confirmed` tinyint(1) NOT NULL DEFAULT '1', `confirm_code` varchar(32) DEFAULT NULL, `confirm_expire` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `name` (`userid`), KEY `account_id` (`account_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ================================================ FILE: data/schemas/logindb/cp_createlog.20170720151901.sql ================================================ ALTER TABLE `cp_createlog` CHANGE `reg_date` `reg_date` DATETIME NOT NULL; ================================================ FILE: data/schemas/logindb/cp_createlog.20250614124331.sql ================================================ ALTER TABLE cp_createlog MODIFY COLUMN reg_ip VARCHAR(39) NOT NULL; ================================================ FILE: data/schemas/logindb/cp_credits.20131213174201.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_credits` ( `account_id` int(11) unsigned NOT NULL, `balance` int(11) unsigned NOT NULL DEFAULT '0', `last_donation_date` datetime DEFAULT NULL, `last_donation_amount` float unsigned DEFAULT NULL, PRIMARY KEY (`account_id`), KEY `account_id` (`account_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Donation credits balance for a given account.'; ================================================ FILE: data/schemas/logindb/cp_emailchange.20131213174201.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_emailchange` ( `id` int(11) NOT NULL AUTO_INCREMENT, `code` varchar(32) NOT NULL, `account_id` int(10) NOT NULL, `old_email` varchar(39) NOT NULL, `new_email` varchar(39) NOT NULL, `request_date` datetime NOT NULL, `request_ip` varchar(15) NOT NULL, `change_date` datetime DEFAULT NULL, `change_ip` varchar(15) DEFAULT NULL, `change_done` tinyint(4) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `account_id` (`account_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ================================================ FILE: data/schemas/logindb/cp_emailchange.20250609133400.sql ================================================ ALTER TABLE cp_emailchange MODIFY COLUMN request_ip VARCHAR(39) NOT NULL, MODIFY COLUMN change_ip VARCHAR(39) DEFAULT NULL; ================================================ FILE: data/schemas/logindb/cp_ipbanlog.20120816150540.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_ipbanlog` ( `id` int(10) unsigned NOT NULL auto_increment, `ip_address` varchar(15) NOT NULL, `banned_by` int(11) unsigned default NULL, `ban_type` tinyint(1) NOT NULL, `ban_until` datetime NOT NULL, `ban_date` datetime NOT NULL, `ban_reason` text NOT NULL, PRIMARY KEY (`id`), INDEX (`ip_address`), INDEX (`banned_by`) ) ENGINE=MyISAM ; ================================================ FILE: data/schemas/logindb/cp_ipbanlog.20250609133400.sql ================================================ ALTER TABLE cp_ipbanlog MODIFY COLUMN ip_address VARCHAR(39) NOT NULL; ================================================ FILE: data/schemas/logindb/cp_loginlog.20131213174201.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_loginlog` ( `id` int(11) NOT NULL AUTO_INCREMENT, `account_id` int(10) DEFAULT NULL, `username` varchar(23) NOT NULL, `password` varchar(32) NOT NULL, `ip` varchar(15) NOT NULL, `login_date` datetime NOT NULL, `error_code` tinyint(1) DEFAULT NULL, PRIMARY KEY (`id`), KEY `account_id` (`account_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ================================================ FILE: data/schemas/logindb/cp_loginlog.20250609133400.sql ================================================ ALTER TABLE cp_loginlog MODIFY COLUMN ip VARCHAR(39) NOT NULL; ================================================ FILE: data/schemas/logindb/cp_loginprefs.20131213174201.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_loginprefs` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `account_id` int(11) unsigned NOT NULL, `name` varchar(80) NOT NULL, `value` varchar(255) DEFAULT NULL, `create_date` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `account_id` (`account_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Account preferences' AUTO_INCREMENT=1 ; ================================================ FILE: data/schemas/logindb/cp_pwchange.20131213174201.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_pwchange` ( `id` int(11) NOT NULL AUTO_INCREMENT, `account_id` int(10) NOT NULL, `old_password` varchar(32) NOT NULL, `new_password` varchar(32) DEFAULT NULL, `change_date` datetime NOT NULL, `change_ip` varchar(15) NOT NULL, PRIMARY KEY (`id`), KEY `account_id` (`account_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ================================================ FILE: data/schemas/logindb/cp_pwchange.20250609133400.sql ================================================ ALTER TABLE cp_pwchange MODIFY COLUMN change_ip VARCHAR(39) NOT NULL; ================================================ FILE: data/schemas/logindb/cp_resetpass.20131213174201.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_resetpass` ( `id` int(11) NOT NULL AUTO_INCREMENT, `code` varchar(32) NOT NULL, `account_id` int(10) NOT NULL, `old_password` varchar(32) NOT NULL, `new_password` varchar(32) DEFAULT NULL, `request_date` datetime NOT NULL, `request_ip` varchar(15) NOT NULL, `reset_date` datetime DEFAULT NULL, `reset_ip` varchar(15) DEFAULT NULL, `reset_done` tinyint(4) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `account_id` (`account_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ================================================ FILE: data/schemas/logindb/cp_resetpass.20250609133400.sql ================================================ ALTER TABLE cp_resetpass MODIFY COLUMN request_ip VARCHAR(39) NOT NULL, MODIFY COLUMN reset_ip VARCHAR(39) DEFAULT NULL; ================================================ FILE: data/schemas/logindb/cp_servicedesk.20131122010001.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_servicedesk` ( `ticket_id` int(6) NOT NULL AUTO_INCREMENT, `account_id` int(7) NOT NULL, `category` int(6) NOT NULL, `status` varchar(12) NOT NULL DEFAULT 'Pending', `char_id` text NOT NULL, `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `sslink` text NOT NULL, `chatlink` text NOT NULL, `videolink` text NOT NULL, `subject` varchar(64) NOT NULL DEFAULT '0', `text` text NOT NULL, `ip` varchar(15) NOT NULL DEFAULT '0', `team` int(1) NOT NULL DEFAULT '1', `curemail` text NOT NULL, `lastreply` varchar(24) NOT NULL DEFAULT '0', PRIMARY KEY (`ticket_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1000 ; ================================================ FILE: data/schemas/logindb/cp_servicedesk.20250609133400.sql ================================================ ALTER TABLE cp_servicedesk MODIFY COLUMN ip VARCHAR(39) NOT NULL DEFAULT '0'; ================================================ FILE: data/schemas/logindb/cp_servicedeska.20131122010001.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_servicedeska` ( `action_id` int(6) NOT NULL AUTO_INCREMENT, `ticket_id` int(6) NOT NULL, `author` varchar(32) NOT NULL, `text` text NOT NULL, `action` text NOT NULL, `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `ip` varchar(15) NOT NULL DEFAULT '0', `isstaff` int(1) NOT NULL DEFAULT '0', PRIMARY KEY (`action_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ================================================ FILE: data/schemas/logindb/cp_servicedeska.20250609133400.sql ================================================ ALTER TABLE cp_servicedeska MODIFY COLUMN ip VARCHAR(39) NOT NULL DEFAULT '0'; ================================================ FILE: data/schemas/logindb/cp_servicedeskcat.20131122010001.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_servicedeskcat` ( `cat_id` int(3) NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `display` int(1) NOT NULL DEFAULT '1', PRIMARY KEY (`cat_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ; INSERT INTO `cp_servicedeskcat` (`cat_id`, `name`, `display`) VALUES (1, 'Technical Support', 1), (2, 'General Support', 1), (3, 'Report an Abuse', 1); ================================================ FILE: data/schemas/logindb/cp_servicedesksettings.20131122010001.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_servicedesksettings` ( `account_id` int(7) NOT NULL, `account_name` varchar(32) NOT NULL, `prefered_name` varchar(32) NOT NULL, `team` int(1) NOT NULL, `emailalerts` int(1) NOT NULL DEFAULT '0', `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`account_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; ================================================ FILE: data/schemas/logindb/cp_trusted.20131213174201.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_trusted` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `account_id` int(11) unsigned NOT NULL, `email` varchar(255) NOT NULL, `create_date` datetime NOT NULL, `delete_date` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `account_id` (`account_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; ================================================ FILE: data/schemas/logindb/cp_txnlog.20131213174201.sql ================================================ CREATE TABLE IF NOT EXISTS `cp_txnlog` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `account_id` int(11) unsigned DEFAULT '0', `server_name` varchar(255) DEFAULT NULL, `credits` int(11) DEFAULT '0', `receiver_email` varchar(60) DEFAULT NULL, `item_name` varchar(100) DEFAULT NULL, `item_number` varchar(10) DEFAULT NULL, `quantity` varchar(6) DEFAULT NULL, `payment_status` varchar(20) DEFAULT NULL, `pending_reason` varchar(20) DEFAULT NULL, `payment_date` varchar(40) DEFAULT NULL, `mc_gross` varchar(20) DEFAULT NULL, `mc_fee` varchar(20) DEFAULT NULL, `tax` varchar(20) DEFAULT NULL, `mc_currency` varchar(3) DEFAULT NULL, `parent_txn_id` varchar(20) DEFAULT NULL, `txn_id` varchar(20) DEFAULT NULL, `txn_type` varchar(20) DEFAULT NULL, `first_name` varchar(30) DEFAULT NULL, `last_name` varchar(40) DEFAULT NULL, `address_street` varchar(50) DEFAULT NULL, `address_city` varchar(30) DEFAULT NULL, `address_state` varchar(30) DEFAULT NULL, `address_zip` varchar(20) DEFAULT NULL, `address_country` varchar(30) DEFAULT NULL, `address_status` varchar(10) DEFAULT NULL, `payer_email` varchar(60) DEFAULT NULL, `payer_status` varchar(10) DEFAULT NULL, `payment_type` varchar(10) DEFAULT NULL, `notify_version` varchar(10) DEFAULT NULL, `verify_sign` varchar(255) DEFAULT NULL, `referrer_id` varchar(10) DEFAULT NULL, `process_date` datetime DEFAULT NULL, `hold_until` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `account_id` (`account_id`), KEY `parent_txn_id` (`parent_txn_id`), KEY `txn_id` (`txn_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='All PayPal transactions that go through the IPN handler.' AUTO_INCREMENT=1 ; ================================================ FILE: data/schemas/logindb/cp_txnlog.20170217073601.sql ================================================ ALTER TABLE `cp_txnlog` CHANGE `referrer_id` `referrer_id` VARCHAR(13) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL; ================================================ FILE: data/schemas/logindb/cp_txnlog.20170221184601.sql ================================================ ALTER TABLE `cp_txnlog` CHANGE `address_status` `address_status` VARCHAR(11) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL; ================================================ FILE: data/schemas/logindb/index.html ================================================ ================================================ FILE: data/templates/changemail.php ================================================ <?php echo htmlspecialchars($emailTitle) ?>

You have received this e-mail because someone has filled in the "change e-mail" form after logging into your account. If you are the one who requested this action, then please click the below link to proceed with the e-mail change.

Account:   {AccountUsername}
Old E-mail:   {OldEmail}
New E-mail:   {NewEmail}
Change E-mail:   {ChangeLink}

Note: This is an automated e-mail, please do not reply to this address.

================================================ FILE: data/templates/confirm.php ================================================ <?php echo htmlspecialchars($emailTitle) ?>

You have received this e-mail because you or someone else has created an account with using this e-mail address. Point your browser to the below link to activate the account.

All unconfirmed accounts will be deleted from our system within hour(s) of registration.

Account:   {AccountUsername}
Confirm:   {ConfirmationLink}

Note: This is an automated e-mail, please do not reply to this address.

================================================ FILE: data/templates/contactform.php ================================================ <?php echo htmlspecialchars($emailTitle) ?>

A member of our site has submitted a question/query.

AccountID:   {AccountID}
Name:   {Name}
Email:   {Email}
Subject:   {Subject}
Body:   {Body}
IP:   {IP}


Note: This is an automated e-mail, please do not reply to this address.

================================================ FILE: data/templates/index.html ================================================ ================================================ FILE: data/templates/marketing1.php ================================================ {emailtitle}

New to Server

{emailtitle}

Greetings Adventurer!

We're pleased to announce that Server is back online with brand new updates and content to ...

The FluxCP Team

Email Jargen

This email was sent by FluxCP to {username} ({email}) because you have a player account with us. We will never give your details to anyone, not even a real marketing company - so we sent this email directly to you from our website!

You can unsubscribe from receiving these emails by changing your preferences on our website.

Useful Links

Website Home || Forums || Service Desk || Wiki

================================================ FILE: data/templates/newpass.php ================================================ <?php echo htmlspecialchars($emailTitle) ?>

Here are the details outlining your new password.

Account:   {AccountUsername}
New Password:   {NewPassword}

Note: This is an automated e-mail, please do not reply to this address.

================================================ FILE: data/templates/newticket.php ================================================ <?php echo htmlspecialchars($emailTitle) ?>

You have received this e-mail because you have enabled email alerts for new tickets.

Category:   {Category}
Subject:   {Subject}
Ticket Body:   {Text}


Note: This is an automated e-mail, please do not reply to this address.

================================================ FILE: data/templates/resetpass.php ================================================ <?php echo htmlspecialchars($emailTitle) ?>

You have received this e-mail because you or someone else has filled in our "reset password" form, requesting to reset the password of your account on our server.

Account:   {AccountUsername}
Reset Link:   {ResetLink}

Note: This is an automated e-mail, please do not reply to this address.

================================================ FILE: data/templates/ticketreply.php ================================================ <?php echo htmlspecialchars($emailTitle) ?>

You have received this e-mail because a member of the support team has replied to your ticket on the Service Desk.

Ticket ID:   {TicketID}
Updated By:   {Staff}


Note: This is an automated e-mail, please do not reply to this address.

================================================ FILE: data/tmp/index.html ================================================ ================================================ FILE: data/tmp/transactions/Refunded/index.html ================================================ ================================================ FILE: data/tmp/transactions/Reversed/index.html ================================================ ================================================ FILE: data/tmp/transactions/web_accept/Completed/index.html ================================================ ================================================ FILE: data/tmp/transactions/web_accept/Denied/index.html ================================================ ================================================ FILE: data/tmp/transactions/web_accept/Pending/index.html ================================================ ================================================ FILE: doc/user_lang.md ================================================ Language Files ====== How do they work? --------- The **lang/** directory contains translations for use with FluxCP. The language used is controlled by the 'DefaultLanguage' setting in config/application.php. Simply put, `'DefaultLanguage' => 'en_us'` will load the American English language file and use the contained strings wherever `Flux::message()` is used within theme files. There are a few others within the `lang/` directory, but unfortunately they aren't maintained. How do we use them? --------- For example, in a theme file that is displaying whether a players' character is male or female, you would see `` or ``. The menus that are defined in `config/application.php` are set to automatically use the language files. For example, lets look at this specific menu: ``` 'MenuItems' => array( 'MainMenuLabel' => array( 'HomeLabel' => array('module' => 'main'), 'NewsLabel' => array('module' => 'news'), ), ), ``` When the page is rendered, you will see that these strings are replaced with their counterparts from the language file. 'MainMenuLabel' becomes 'Main Menu', 'HomeLabel' becomes 'Home', 'NewsLabel' becomes 'News'. Common Misuse --------- Many people still think that the 'Label' portion of these strings should be removed within the config file as it's outputting 'HomeLabel' to the page instead of 'Home'. **This is incorrect.** This simply means that the theme you're using was built earlier than August 2014 and you shouldn't be using it. ================================================ FILE: doc/user_theme.md ================================================ Using a Custom Theme ====== How does it work? --------- The Theme System in FluxCP is based on an "inheritance structure". In simple terms, this means you only need to add files to your new theme folder that you want to change. It all works similar to the config import system in rAthena. The default theme is read first, then if there are any files matching the required view in the custom theme, then it gets loaded instead. This means that that **you don't need to copy/paste the default theme every time you create a new custom theme**. The manifest.php file controls inheritance with `'inherit' => 'default',`. How should my theme look? --------- This is an example directory structure for a custom theme in a fresh install of FluxCP: ``` . ├── addons ├── config ├── data ├── doc ├── lang ├── lib ├── modules ├── themes | ├── bootstrap | └── cust_theme1 | └── css | ├── flux.css | └── customstyle.css | └── img | ├── bg.jpg | └── logo.png | └── js | ├── flux.unitip.js | └── ie9.js | └── main | ├── index.php | └── sidebar.php | ├── footer.php | ├── header.php | └── manifest.php | ├── default | └── installer ├── .gitignore ├── .htaccess ├── LICENSE ├── README.md ├── error.php └── index.php ``` As you can see, there are only a few files in the **cust_theme1** folder. How do I make it display on my website? --------- To enable your theme, simply add it to the theme array in /config/application.php: ```'ThemeName' => array('default', 'bootstrap', 'cust_theme1'),``` If you want your new theme to always display and remove the theme selection box in the footer, remove the other themes from this array so it looks like: ```'ThemeName' => array('cust_theme1'),``` How do I know if a theme I downloaded will work? --------- As a general rule of thumb, if your new theme has a `manifest.php` file in the theme folder, it will work with current versions of FluxCP just fine. If it doesn't have `manifest.php`, you will need to create one. This will make the new theme able to load, but you will still have problems. In the past, even after this theme system was introduced, theme designers have still opted to create themes reliant on old versions of FluxCP. They are lazy. Use at your own risk. ================================================ FILE: error.php ================================================ rA's Flux Control Panel: Critical Error

Critical Error

An error was encountered during the lifetime of the application.

This could be due to a variety of problems, such as a bug in the application.

However, normally it is caused by misconfiguration.

Exception Details

Error:

Message: getMessage())) ?>

File: getFile() ?>:getLine() ?>

getTrace())): ?> getTrace() as $trace): ?>
File Line Function/Method
()

Exception Trace As String

__construct\\((.+?)\\)/', 'PDO->__construct(*hidden*)', $e->getTraceAsString())) ?>

Error

An error occurred while trying to process your request.

Please try contacting an administrator:

================================================ FILE: index.php ================================================ $value) { if (is_string($value)) { $arr[$key] = stripslashes($value); } } } } set_include_path(FLUX_LIB_DIR.PATH_SEPARATOR.get_include_path()); // Default account group IDs. require_once FLUX_CONFIG_DIR.'/groups.php'; // Some necessary Flux core libraries. require_once 'Flux.php'; require_once 'Flux/Dispatcher.php'; require_once 'Flux/SessionData.php'; require_once 'Flux/DataObject.php'; require_once 'Flux/Authorization.php'; require_once 'Flux/Installer.php'; require_once 'Flux/PermissionError.php'; // Vendor libraries. try { // Initialize Flux. Flux::initialize(array( 'appConfigFile' => FLUX_CONFIG_DIR.'/application.php', 'serversConfigFile' => FLUX_CONFIG_DIR.'/servers.php', 'appConfigFileImport' => FLUX_CONFIG_DIR.'/import/application.php', 'serversConfigFileImport' => FLUX_CONFIG_DIR.'/import/servers.php', )); // Set time limit. set_time_limit((int)Flux::config('ScriptTimeLimit')); // Set default timezone for entire app. $timezone = Flux::config('DateDefaultTimezone'); if ($timezone && !@date_default_timezone_set($timezone)) { throw new Flux_Error("'$timezone' is not a valid timezone. Consult http://php.net/timezones for a list of valid timezones."); } // Create some basic directories. $directories = array( FLUX_DATA_DIR.'/logs/schemas', FLUX_DATA_DIR.'/logs/schemas/logindb', FLUX_DATA_DIR.'/logs/schemas/charmapdb', FLUX_DATA_DIR.'/logs/transactions', FLUX_DATA_DIR.'/logs/mail', FLUX_DATA_DIR.'/logs/mysql', FLUX_DATA_DIR.'/logs/mysql/errors', FLUX_DATA_DIR.'/logs/errors', FLUX_DATA_DIR.'/logs/errors/exceptions', FLUX_DATA_DIR.'/logs/errors/mail', ); // Schema log directories. foreach (Flux::$loginAthenaGroupRegistry as $serverName => $loginAthenaGroup) { $directories[] = FLUX_DATA_DIR."/logs/schemas/logindb/$serverName"; $directories[] = FLUX_DATA_DIR."/logs/schemas/charmapdb/$serverName"; foreach ($loginAthenaGroup->athenaServers as $athenaServer) $directories[] = FLUX_DATA_DIR."/logs/schemas/charmapdb/$serverName/{$athenaServer->serverName}"; } foreach ($directories as $directory) { if (is_writable(dirname($directory)) && !is_dir($directory)) { if (Flux::config('RequireOwnership')) mkdir($directory, 0700); else mkdir($directory, 0777); } } if (Flux::config('RequireOwnership') && function_exists('posix_getuid')) $uid = posix_getuid(); $directories = array( FLUX_DATA_DIR.'/logs' => 'log storage', FLUX_DATA_DIR.'/itemshop' => 'item shop image', FLUX_DATA_DIR.'/tmp' => 'temporary' ); foreach ($directories as $directory => $directoryFunction) { $directory = realpath($directory); if (!is_dir($directory)) mkdir($directory, 0600); if (!is_writable($directory) && is_dir($directory)) throw new Flux_PermissionError("The $directoryFunction directory '$directory' is not writable. Remedy with `chmod 0600 $directory`"); if (Flux::config('RequireOwnership') && function_exists('posix_getuid') && fileowner($directory) != $uid) throw new Flux_PermissionError("The $directoryFunction directory '$directory' is not owned by the executing user. Remedy with `chown -R ".posix_geteuid().":".posix_geteuid()." $directory`"); } if (ini_get('session.use_trans_sid')) throw new Flux_Error("The 'session.use_trans_sid' php.ini configuration must be turned off for Flux to work."); // Installer library. $installer = Flux_Installer::getInstance(); if ($hasUpdates=$installer->updateNeeded()) Flux::config('ThemeName', array('installer')); $sessionKey = Flux::config('SessionKey'); $sessionExpireDuration = Flux::config('SessionCookieExpire') * 60 * 60; $cookie_options = array( // Session timeout 'lifetime' => $sessionExpireDuration, // Flux URL 'path' => Flux::config( 'BaseURI' ), // Domain name for the cookie 'domain' => preg_replace( '/:\d+$/', '', Flux::config( 'ServerAddress' ) ), // Remove port number if present (e.g. "example.com:80") // Only transfer the cookie via HTTPS 'secure' => Flux::config( 'ForceHTTPS' ), // Only include the cookie in HTTP requests, making it inaccessible by Javascript 'httponly' => true, // Only send the cookie to the domain+path defined above 'samesite' => 'Strict' ); if( !session_set_cookie_params( $cookie_options ) ){ throw new Flux_Error( "Unable to configure the session cookie correctly" ); } ini_set('session.gc_maxlifetime', $sessionExpireDuration); ini_set('session.name', $sessionKey); @session_start(); if (empty($_SESSION[$sessionKey]) || !is_array($_SESSION[$sessionKey])) { $_SESSION[$sessionKey] = array(); } // Initialize session data. Flux::$sessionData = new Flux_SessionData($_SESSION[$sessionKey], $hasUpdates); // Initialize authorization component. $accessConfig = Flux::parseConfigFile(FLUX_CONFIG_DIR.'/access.php'); // Merge with add-on configs. foreach (Flux::$addons as $addon) { $accessConfig->merge($addon->accessConfig); } $accessConfig->set('unauthorized.index', AccountLevel::ANYONE); $authComponent = Flux_Authorization::getInstance($accessConfig, Flux::$sessionData); if (Flux::config('DebugMode')) { error_reporting(E_ALL); ini_set('display_errors', 1); } // Dispatch requests->modules->actions->views. $dispatcher = Flux_Dispatcher::getInstance(); $dispatcher->setDefaultModule(Flux::config('DefaultModule')); $dispatcher->dispatch(array( 'basePath' => Flux::config('BaseURI'), 'useCleanUrls' => Flux::config('UseCleanUrls'), 'modulePath' => FLUX_MODULE_DIR, 'themePath' => FLUX_THEME_DIR, 'themeName' => Flux::$sessionData->theme, 'missingActionModuleAction' => Flux::config('DebugMode') ? array('errors', 'missing_action') : array('main', 'page_not_found'), 'missingViewModuleAction' => Flux::config('DebugMode') ? array('errors', 'missing_view') : array('main', 'page_not_found') )); } catch (Exception $e) { $exceptionDir = FLUX_DATA_DIR.'/logs/errors/exceptions'; if (is_writable($exceptionDir)) { require_once 'Flux/LogFile.php'; $today = date('Ymd'); $eLog = new Flux_LogFile("$exceptionDir/$today.log"); // Log exception. $eLog->puts('(%s) Exception %s: %s', get_class($e), get_class($e), $e->getMessage()); foreach (explode("\n", $e->getTraceAsString()) as $traceLine) { $eLog->puts('(%s) **TRACE** %s', get_class($e), $traceLine); } } if(Flux::config('DiscordUseWebhook')) { if(Flux::config('DiscordSendOnErrorException')) { sendtodiscord(Flux::config('DiscordWebhookURL'), '```ansi ERROR Error: '. get_class($e) .' Exception: '. $e->getMessage() .' File: '. $e->getFile() .':'. $e->getLine() .'```'); } } require_once FLUX_CONFIG_DIR.'/error.php'; define('__ERROR__', 1); include $errorFile; } ?> ================================================ FILE: lang/en_us.php ================================================ 'English', 'YesLabel' => 'Yes', 'NoLabel' => 'No', 'NoteLabel' => 'Note', 'GenderTypeMale' => 'Male', 'GenderTypeFemale' => 'Female', 'GenderTypeServer' => 'Server', 'RefreshSecurityCode' => 'Refresh Security Code', 'NoneLabel' => 'None', 'NeverLabel' => 'Never', 'NotApplicableLabel' => 'Not Applicable', 'UnknownLabel' => 'Unknown', 'IsEqualToLabel' => 'is equal to', 'IsGreaterThanLabel' => 'is greater than', 'IsLessThanLabel' => 'is less than', 'AllLabel' => 'All', 'SearchLabel' => 'Search…', 'GoBackLabel' => 'Go back to previous page…', 'SearchButton' => 'Search', 'ResetButton' => 'Reset', 'FilterButton' => 'Filter', 'NotAcceptingDonations' => "We're sorry, but we are currently not accepting any donations. We apologize for the inconvenience.", //'NotAcceptingDonations' => "We're sorry, but our donation system is currently undergoing maintenance, please try again later.", 'FoundSearchResults' => 'Found a total of %d record(s) across %d page(s). Displaying result(s) %d-%d.', 'LoginToDonate' => 'Please log-in to make a donation.', 'UnknownCharacter' => 'No such character found.', 'AccountIdLabel' => 'Account ID', 'AccountGroupIDLabel' => 'Group ID', 'AccountStateLabel' => 'State', 'CreditBalanceLabel' => 'Credit Balance', 'UsernameLabel' => 'Username', 'PasswordLabel' => 'Password', 'EmailAddressLabel' => 'E-mail', 'GenderLabel' => 'Gender', 'LoginCountLabel' => 'Login Count', 'LastLoginDateLabel' => 'Last Login Date', 'LastUsedIpLabel' => 'Last Used IP', 'AccountStateNormal' => 'Normal', 'AccountStatePending' => 'Pending', 'AccountStatePermBanned' => 'Permanently Banned', 'AccountStateTempBanLbl' => 'Temporarily Banned', 'AccountStateTempBanned' => 'Temp. Banned (unban: %s)', 'OnlineLabel' => 'Online', 'OfflineLabel' => 'Offline', 'ItemIdLabel' => 'Item ID', 'ItemNameLabel' => 'Item Name', 'ItemAmountLabel' => 'Amount', 'ItemIdentifyLabel' => 'Identified', 'ItemRefineLabel' => 'Refine', 'ItemBrokenLabel' => 'Broken', 'ItemCard0Label' => 'Slot 1', 'ItemCard1Label' => 'Slot 2', 'ItemCard2Label' => 'Slot 3', 'ItemCard3Label' => 'Slot 4', 'ItemRandOptionsLabel' => 'Random options', //SIDEBAR //FluxCP Menu Items //Categories 'MainMenuLabel' => 'Main Menu', 'ForumLabel' => 'Forum', 'AccountLabel' => 'Account', 'CharacterLabel' => 'Character', 'ServiceDeskLabel' => 'Service Desk', 'CPLogsLabel' => 'CP Logs', 'FluxAdminLabel' => 'Flux Admin', 'PagesLabel' => 'Pages', 'IPBanListLabel' => 'IP Ban List', 'GuildsLabel' => 'Guilds', 'rALogsLabel' => 'rA Logs', 'SendMailLabel' => 'Send Mail', 'ReInstallLabel' => 'Re-Install', 'TaskListLabel' => 'Task List', 'DonationsLabel' => 'Donations', 'InformationLabel' => 'Information', 'DatabaseLabel' => 'Database', 'SocialLabel' => 'Social', //SubMenus 'HomeLabel' => 'Home', 'NewsLabel' => 'News', 'DownloadsLabel' => 'Downloads', 'RulesLabel' => 'Rules', 'ContactUsLabel' => 'Contact Us', 'MyAccountLabel' => 'My Account', 'HistoryLabel' => 'History', 'PurchaseLabel' => 'Purchase', 'DonateLabel' => 'Donate', 'ServerInfoLabel' => 'Server Info', 'ServerStatusLabel' => 'Server Status', 'WoeHoursLabel' => 'WOE Hours', 'CastlesLabel' => 'Castles', 'WhosOnlineLabel' => "Who's Online", 'MapStaticsLabel' => 'Map Statics', 'RankingInfoLabel' => 'Ranking Info', 'VendingInfoLabel' => 'Vending Info', 'BuyingstoreInfoLabel' => 'Buyingstore Info', 'ItemDatabaseLabel' => 'Item Database', 'MobDatabaseLabel' => 'Mob Database', 'JoinUsInFacebookLabel' => 'Join us on Facebook!', 'RateUsOnRMSLabel' => 'Rate us on RMS!', // Module: account // - account/changemail 'EmailChangeTitle' => 'Change E-mail', 'EnterEmailAddress' => 'Please enter an e-mail address.', 'EmailCannotBeSame' => 'Your new e-mail cannot be the same as your current.', 'EmailInvalid' => 'Invalid e-mail address.', 'EmailAlreadyRegistered' => "The e-mail address you've entered is already registered to another account.", 'EmailChangeSent' => 'An e-mail has been sent to your new address with a link that will confirm the change.', 'EmailAddressChanged' => 'Your e-mail address has been changed!', 'EmailChangeFailed' => 'Failed to change e-mail address. Please try again later.', 'EmailChangeHeading' => 'Change E-mail', 'EmailChangeInfo' => 'If you would like to change the e-mail address registered under your account, you can fill out the below form.', 'EmailChangeInfo2' => 'After submitting the form, you will be required to confirm your new e-mail address (an e-mail will be sent to the new address with a link).', 'EmailChangeLabel' => 'New E-mail Address', 'EmailChangeInputNote' => 'Must be a valid e-mail address!', 'EmailChangeButton' => 'Change E-mail Address', // - account/changepass 'PasswordChangeTitle' => 'Change Password', 'NeedCurrentPassword' => 'Please enter your current password.', 'NeedNewPassword' => 'Please enter your new password.', 'OldPasswordInvalid' => "The password you provided doesn't match the one we have on record.", 'ConfirmNewPassword' => 'Please confirm your new password.', 'NewPasswordHasUsername' => 'Your new password must not contain your username.', 'NewPasswordInvalid' => 'Your new password contains invalid characters.', 'NewPasswordSameAsOld' => 'New password cannot be the same as your current password.', 'NewPasswordNeedUpper' => 'Your new password must contain at least %d uppercase letter(s).', 'NewPasswordNeedLower' => 'Your new password must contain at least %d lowercase letter(s).', 'NewPasswordNeedNumber' => 'Your new password must contain at least %d number(s).', 'NewPasswordNeedSymbol' => 'Your new password must contain at least %d symbol(s).', 'PasswordHasBeenChanged' => 'Your password has been changed, please log-in again.', 'FailedToChangePassword' => 'Failed to change your password. Please contact an admin.', 'PasswordChangeHeading' => 'Change Your Password', 'PasswordChangeInfo' => 'Please enter your current password, then enter the new password you would like to use and re-enter it to confirm.', 'CurrentPasswordLabel' => 'Current Password', 'NewPasswordLabel' => 'New Password', 'NewPasswordConfirmLabel' => 'Re-enter New Password', 'PasswordChangeNote' => 'Please be sure to enter the correct information.', 'PasswordChangeNote2' => 'After changing your password, you will be logged out.', 'PasswordChangeButton' => 'Change Password', // - account/changesex 'GenderChangeTitle' => 'Change Gender', 'GenderChangeBadChars' => 'You cannot change your gender if any of your characters is a: %s', 'GenderChanged' => 'Your gender has been changed and %d credit(s) have been deducted from your account.', 'GenderChangedForFree' => 'Your gender has been changed.', 'GenderChangeHeading' => 'Change Your Gender', 'GenderChangeCost' => 'Gender changes cost %s credit(s).', 'GenderChangeBalance' => 'Your current balance is %s credit(s).', 'GenderChangeNoFunds' => 'You do not have enough credits to perform a gender change at this time.', 'GenderChangeNoCost' => 'For you, gender changes are free.', 'GenderChangeCharInfo' => 'You cannot change gender if you have the follow character jobs: %s', 'GenderChangeSubHeading' => 'Please make sure you want to really change!', 'GenderChangeFormText' => 'Would you like to change your gender to %s?', 'GenderChangeConfirm' => 'Are you absolutely sure you want to change your gender?', 'GenderChangeButton' => 'Yes, do it please.', // - account/confirm 'AccountConfirmTitle' => 'Confirm Account', 'AccountConfirmUnban' => 'Account has been confirmed and activated.', 'AccountConfirmMessage' => 'Your account has been confirmed and activated, you may now log-in.', // - account/confirmemail 'EmailConfirmTitle' => 'Confirm E-mail', 'EmailConfirmFailed' => 'There has been a technical difficulty while updating your e-mail address, please contact an admin.', 'EmailConfirmChanged' => 'Your e-mail address has been changed!', // - account/create 'AccountCreateTitle' => 'Create an Account', 'AccountConfirmBan' => 'Awaiting account activation: %s', 'AccountCreateEmailSent' => 'An e-mail has been sent containing account activation details, please check your e-mail and activate your account to log-in.', 'AccountCreateFailed' => 'Your account has been created, but unfortunately we failed to send an e-mail due to technical difficulties. Please contact a staff member and request for assistance.', 'AccountCreated' => 'Congratulations, you have been registered successfully and automatically logged in.', 'AccountCreateHeading' => 'Register', 'AccountCreateTerms' => 'Terms of Service', 'AccountCreateInfo' => 'Please read our %s (ToS) before registering for an account, to ensure that you understand the rules of holding an account with our private Ragnarok Online game server.', 'AccountCreateInfo2' => 'By clicking "Create My Account", you agree to be bound by our %s.', 'AccountCreateGenderInfo' => "The gender you choose here will affect your in-game character's gender!", 'AccountServerLabel' => 'Server', 'AccountUsernameLabel' => 'Your Username', 'AccountPasswordLabel' => 'Your Password', 'AccountPassConfirmLabel' => 'Confirm Password', 'AccountEmailLabel' => 'E-mail Address', 'AccountEmailLabel2' => 'Confirm E-mail Address', 'AccountGenderLabel' => 'Gender', 'AccountBirthdateLabel' => 'Birthdate', 'AccountSecurityLabel' => 'Security Code', 'AccountCreateButton' => 'Create My Account', 'AccountInvalidChars' => "A username can only contain these characters: '%s'", 'AccountRecaptchaKey' => 'You need Recaptcha keys, see more in config/applications.php (ReCaptchaPublicKey/ReCaptchaPrivateKey)', 'InvalidLoginServer' => 'Invalid login server selected, please try again with a valid server.', 'InvalidLoginCredentials' => 'Invalid login credentials, please verify that you typed the correct info and try again.', 'UnexpectedLoginError' => 'Unexpected error occurred, please try again or report to an admin.', 'CriticalLoginError' => 'Something bad happened. Report to an administrator ASAP.', 'UsernameAlreadyTaken' => "The username you've chosen has already been taken by another user.", 'UsernameTooShort' => sprintf('Your username should be around %d to %d characters long.', Flux::config('MinUsernameLength'), Flux::config('MaxUsernameLength')), 'UsernameTooLong' => sprintf('Your username should be around %d to %d characters long.', Flux::config('MinUsernameLength'), Flux::config('MaxUsernameLength')), 'PasswordContainsUser' => 'Your password cannot contain your username.', 'PasswordHasUsername' => 'Your password must not contain your username.', 'PasswordTooShort' => 'Your password should be around %d to %d characters long.', 'PasswordTooLong' => 'Your password should be around %d to %d characters long.', 'PasswordsDoNotMatch' => "Your passwords do not match, please make sure that you've typed them both correctly.", 'PasswordNeedUpper' => 'Your password must contain at least %d uppercase letter(s).', 'PasswordNeedLower' => 'Your password must contain at least %d lowercase letter(s).', 'PasswordNeedNumber' => 'Your password must contain at least %d number(s).', 'PasswordNeedSymbol' => 'Your password must contain at least %d symbol(s).', 'EmailAddressInUse' => "The e-mail address you've entered is already registered to another account. Please use a different e-mail address.", 'InvalidEmailAddress' => "The e-mail address you've entered is not in a valid e-mail address format.", 'InvalidEmailconf' => "E-mail addresses do not match.", 'InvalidGender' => 'Gender should be "M" or "F"', 'InvalidServer' => "The server you've selected does not exist.", 'InvalidSecurityCode' => 'Please enter the security code correctly.', 'InvalidPassword' => 'Your password contains invalid characters.', 'InvalidBirthdate' => 'Invalid birthdate input.', 'CriticalRegisterError' => 'Something bad happened. Report to an administrator ASAP.', // - account/edit 'AccountEditTitle' => 'Modify Account', 'AccountEditTitle2' => 'Modifying My Account', 'AccountEditTitle3' => 'Modifiying Account (%s)', 'CannotModifyOwnGroupID' => 'You cannot modify your own account group ID.', 'CannotModifyAnyGroupID' => 'You cannot modify account group IDs.', 'CannotModifyGroupIDHigh' => 'You cannot set an account group ID to be higher than your own.', 'InvalidGroupID' => 'Invalid group ID.', 'CannotModifyBalance' => 'You cannot modify account balances.', 'InvalidLastLoginDate' => 'Invalid last login date.', 'InvalidVIPTime' => 'Invalid VIP Time.', 'AccountModified' => 'Account has been modified.', 'AccountEditHeading' => 'Modify Account', 'AccountEditButton' => 'Modify Account', 'AccountEditNotFound' => 'No such account.', 'VIPTimeDateLabel' => 'VIP Until', // - account/index 'AccountIndexTitle' => 'List Accounts', 'AccountIndexHeading' => 'Accounts', 'LoginBetweenLabel' => 'Login Between', 'BirthdateBetweenLabel' => 'Birthdate Between', 'AccountIndexNotFound' => 'No such account.', // - account/login 'LoginTitle' => 'Log In', 'LoginHeading' => 'Log In', 'LoginButton' => 'Log In', 'LoginPageMakeAccount' => 'Don\'t have an account? Create one!', 'TemporarilyBanned' => 'Your account is temporarily banned.', 'PermanentlyBanned' => 'Your account is permanently banned.', 'IpBanned' => 'The IP address you are behind is banned.', 'PendingConfirmation' => 'Your account is pending e-mail confirmation.', // - account/logout 'LogoutTitle' => 'Logout', 'LogoutHeading' => 'Logout', 'LogoutInfo' => 'You are now logged out.', 'LogoutInfo2' => 'Please wait a moment while you are redirected…', // - account/resend 'ResendTitle' => 'Resend Confirmation E-mail', 'ResendEnterUsername' => 'Please enter your account username.', 'ResendEnterEmail' => 'Please enter your e-mail address.', 'ResendFailed' => 'Failed to resend confirmation code.', 'ResendEmailSent' => 'Your confirmation code has been resent, please check your e-mail and proceed to activate your account.', 'ResendHeading' => 'Resend Confirmation E-mail', 'ResendInfo' => 'Please enter your account name and e-mail address you used during the registration of the account to have us resend your confirmation e-mail.', 'ResendServerLabel' => 'Registered Server', 'ResendAccountLabel' => 'Account Username', 'ResendEmailLabel' => 'E-mail Address', 'ResendServerInfo' => 'This is the server the account was registered on.', 'ResendAccountInfo' => 'This is the account name you registered.', 'ResendEmailInfo' => 'This is the e-mail address you used during the registration of the above account.', 'ResendButton' => 'Resend Confirmation E-mail', // - account/resetpass 'ResetPassTitle' => 'Reset Password', 'ResetPassEnterAccount' => 'Please enter your account username.', 'ResetPassEnterEmail' => 'Please enter your e-mail address.', 'ResetPassDisallowed' => 'Password recovery cannot be used for this account.', 'ResetPassFailed' => 'Failed to send reset password e-mail.', 'ResetPassEmailSent' => 'An e-mail has been sent with details on how to reset your password.', 'ResetPassInfo' => 'If you lost your password, you can re-set it by entering the e-mail address you used to register your account.', 'ResetPassInfo2' => 'An e-mail will then be sent to the specified address with a link allowing you to reset your password, therefore a valid e-mail address is required.', 'ResetPassServerLabel' => 'Registered Server', 'ResetPassAccountLabel' => 'Account Username', 'ResetPassEmailLabel' => 'E-mail Address', 'ResetPassServerInfo' => 'This is the server the account was registered on.', 'ResetPassAccountInfo' => 'This is the account name you registered.', 'ResetPassEmailInfo' => 'This is the e-mail address you used during the registration of the above account.', 'ResetPassButton' => 'Send Reset Password E-mail', // - account/resetpw 'ResetPwTitle' => 'Reset Password', 'ResetPwFailed' => 'Failed to re-set password, please try again later.', 'ResetPwDone' => 'Your password has been reset and an e-mail containing your new password has been sent to you.', 'ResetPwDone2' => 'Your password has been reset, but we failed to deliver the e-mail containing your new password. Please reset again to resolve this issue.', // - account/transfer 'TransferTitle' => 'Transfer Donation Credits', 'TransferGreaterThanOne' => 'You can only transfer credits in amounts greater than 1.', 'TransferEnterCharName' => 'You must input the character name of who will receive the credits.', 'TransferNoCharExists' => "Character '%s' does not exist. Please make sure you typed it correctly.", 'TransferNoBalance' => 'You do not have a sufficient balance to make the transfer.', 'TransferUnexpectedError' => 'Unexpected error occurred.', 'TransferSuccessful' => 'Credits have been transferred!', 'TransferHeading' => 'Transfer Donation Credits', 'TransferSubHeading' => 'Credits will be transferred to a character on the %s server.', 'TransferInfo' => 'You currently have %s credit(s).', 'TransferInfo2' => 'Enter the amount you would like to transfer and the character name belonging to the account you would like your credits transferred to.', 'TransferAmountLabel' => 'Amount of Credits', 'TransferCharNameLabel' => 'Character Name', 'TransferAmountInfo' => 'This is the amount of credits you would like to send.', 'TransferCharNameInfo' => 'This is the character name of who will be receiving the credits.', 'TransferConfirm' => 'Are you sure you want to do this?', 'TransferButton' => 'Transfer', 'TransferNoCredits' => 'You have no credits available in your account.', // - account/view 'VIPStateLabel' => 'VIP Status', // * account/view submenus 'ModifyAccountLink' => 'Modify Account', 'AccountViewTitle' => 'View Account', 'AccountViewTitle2' => 'Viewing Account (%s)', 'AccountViewTitle3' => 'Viewing My Account', 'AccountTempBanFailed' => 'Failed to temporarily ban account.', 'AccountPermBanFailed' => 'Failed to permanently ban account.', 'AccountTempBanUnauth' => 'You are unauthorized to place temporary bans on this account.', 'AccountPermBanUnauth' => 'You are unauthorized to place permanent bans on this account.', 'AccountLiftTempBan' => 'Account has been unbanned.', 'AccountLiftPermBan' => 'Account has been unbanned.', 'AccountLiftBanUnauth' => "You are unauthorized to remove this account's ban status.", 'AccountViewHeading' => 'Viewing Account', 'AccountViewDonateLink' => '(Donate!)', 'AccountViewTempBanLabel' => 'Temporary Ban', 'AccountViewPermBanLabel' => 'Permanent Ban', 'AccountViewUnbanLabel' => 'Remove Ban', 'AccountBanReasonLabel' => 'Reason:', 'AccountBanUntilLabel' => 'Ban Until:', 'AccountTempBanButton' => 'Ban Account', 'AccountPermBanButton' => 'Permanently Ban Account', 'AccountTempUnbanButton' => 'Remove Temporary Ban', 'AccountPermUnbanButton' => 'Remove Permanent Ban', 'AccountBanConfirm' => 'Are you sure?', 'AccountBanLogSubHeading' => 'Ban Log for %s (recent to oldest)', 'BanLogBanTypeLabel' => 'Ban Type', 'BanLogBanDateLabel' => 'Ban Date', 'BanLogBanReasonLabel' => 'Ban Reason', 'BanLogBannedByLabel' => 'Banned By', 'BanLogBannedByCP' => 'Control Panel', 'BanTypeUnbanned' => 'Unbanned', 'BanTypePermBanned' => 'Permanently Banned', 'BanTypeTempBanned' => 'Temporarily Banned', 'AccountViewCharSubHead' => 'Characters on %s', 'AccountViewSlotLabel' => 'Slot', 'AccountViewCharLabel' => 'Character Name', 'AccountViewClassLabel' => 'Job Class', 'AccountViewLvlLabel' => 'Base Level', 'AccountViewJlvlLabel' => 'Job Level', 'AccountViewZenyLabel' => 'Zeny', 'AccountViewGuildLabel' => 'Guild', 'AccountViewStatusLabel' => 'Status', 'AccountViewPrefsLabel' => 'Preferences', 'CharModifyPrefsLink' => 'Modify Preferences', 'AccountViewNoChars' => 'This account has no characters on %s.', 'AccountViewStorage' => 'Storage Items of %s', 'AccountViewStorageCount' => '%s has %s storage item(s).', 'AccountViewNoStorage' => 'There are no storage items on this account.', 'AccountViewNotFound' => "Records indicate that the account you're trying to view does not exist.", // - account/xferlog 'XferLogTitle' => 'Credit Transfer History', 'XferLogHeading' => 'Credit Transfer History', 'XferLogReceivedSubHead' => 'Transfers: Received', 'XferLogSentSubHead' => 'Transfers: Sent', 'XferLogCreditsLabel' => 'Credits', 'XferLogFromLabel' => 'From E-mail', 'XferLogDateLabel' => 'Transfer Date', 'XferLogCharNameLabel' => 'To Character', 'XferLogNotReceived' => 'You have not received any credit transfers.', 'XferLogNotSent' => 'You have not sent any credit transfers.', // Module: character // - character/changeslot // - character/index // - character/mapstats // - character/online // - character/prefs // - character/resetlook 'CantResetLookWhenOnline' => 'Cannot reset look while %s is online.', 'ResetLookSuccessful' => "%s's look has been reset!", 'ResetLookFailed' => "Failed to reset %s's look.", // - character/resetpos 'CantResetPosWhenOnline' => 'Cannot reset position while %s is online.', 'CantResetFromCurrentMap' => "You cannot reset %s's position from the current map.", 'ResetPositionSuccessful' => "%s's position has been reset!", 'ResetPositionFailed' => "Failed to reset %s's position.", // - character/view // - character/divorce 'DivorceTitle' => 'Divorce', 'DivorceHeading' => 'Divorce', 'DivorceNotMarried' => '%s is not married.', 'DivorceInvalidPartner' => 'Invalid partner ID.', 'DivorceInvalidChild' => 'Invalid child ID.', 'DivorceMustBeOffline' => 'Both %s and his/her partner must be off-line.', 'DivorceMustBeOffline2' => '%s, his/her partner and their child must be off-line.', 'DivorceText1' => "Are you sure you want to divorce %s and his/her partner?", 'DivorceText2' => 'If %s has a child, the child will also be orphaned.', 'DivorceText3' => 'Wedding rings will also be deleted.', 'DivorceButton' => 'Yes, do it please.', 'DivorceSuccessful' => '%s has been divorced!', // Module: cplog // - cplog/index.php // - cplog/login.php // - cplog/paypal.php // - cplog/resetpass.php // - cplog/txnview.php // Module: donate // - donate/complete // - donate/history // - donate/index // - donate/trusted // Module: errors // - errors/missing_action 'MissingActionTitle' => 'Missing Action', 'MissingActionHeading' => 'Missing Action!', 'MissingActionModLabel' => 'Module:', 'MissingActionActLabel' => 'Action:', 'MissingActionReqLabel' => 'Request URI:', 'MissingActionLocLabel' => 'File system location:', // - errors/missing_view 'MissingViewTitle' => 'Missing View', 'MissingViewHeading' => 'Missing View!', 'MissingViewModLabel' => 'Module:', 'MissingViewActLabel' => 'Action:', 'MissingViewReqLabel' => 'Request URI:', 'MissingViewLocLabel' => 'File system location:', // Module: guild // - guild/export // - guild/index // - guild/view // Module: history // - history/cplogin 'HistoryCpLoginTitle' => 'Control Panel Logins', 'HistoryCpLoginHeading' => 'Control Panel Logins', 'HistoryLoginDateLabel' => 'Login Date/Time', 'HistoryIpAddrLabel' => 'IP Address', 'HistoryErrorCodeLabel' => 'Error Code', 'HistoryNoCpLogins' => 'No control panel login attempts found.', // -history/emailchange 'HistoryEmailTitle' => 'E-Mail Changes', 'HistoryEmailHeading' => 'E-Mail Changes', 'HistoryEmailRequestDate' => 'Request Date/Time', 'HistoryEmailRequestIp' => 'Request IP', 'HistoryEmailOldAddress' => 'Old E-Mail', 'HistoryEmailNewAddress' => 'New E-Mail', 'HistoryEmailChangeDate' => 'Change Date', 'HistoryEmailChangeIp' => 'Change IP', 'HistoryNoEmailChanges' => 'No e-mail change attempts found.', // - history/gamelogin 'HistoryGameLoginTitle' => 'Game Logins', 'HistoryGameLoginHeading' => 'Game Logins', 'HistoryRepsCodeLabel' => 'Response Code', 'HistoryLogMessageLabel' => 'Log Message', 'HistoryNoGameLogins' => 'No in-game login attempts found.', // - history/index 'HistoryIndexTitle' => 'My Account History', 'HistoryIndexHeading' => 'My Account History', 'HistoryIndexInfo' => 'Here you can view past account activity of your account.', 'HistoryIndexInfo2' => 'Please select an action from the menu.', // - history/passchange 'HistoryPassChangeTitle' => 'Password Changes', 'HistoryPassChangeHeading' => 'Password Changes', 'HistoryPassChangeChangeDate' => 'Change Date', 'HistoryPassChangeChangeIp' => 'Change IP', 'HistoryNoPassChanges' => 'No password changes found.', // -history/passreset 'HistoryPassResetTitle' => 'Password Resets', 'HistoryPassResetHeading' => 'Password Resets', 'HistoryPassResetRequestDate' => 'Request Date/Time', 'HistoryPassResetRequestIp' => 'Request IP', 'HistoryPassResetResetDate' => 'Reset Date', 'HistoryPassResetResetIp' => 'Reset IP', 'HistoryNoPassResets' => 'No password reset attempts found.', // Module: ipban // - ipban/add 'IpbanAddTitle' => 'Add IP Ban', 'IpbanEnterIpPattern' => 'Please input an IP address or pattern.', 'IpbanInvalidPattern' => 'Invalid IP address or pattern.', 'IpbanWhitelistedPattern' => 'This pattern is whitelisted and cannot be blocked.', 'IpbanEnterReason' => 'Please enter a reason for the IP ban.', 'IpbanSelectUnbanDate' => 'Unban date is required.', 'IpbanFutureDate' => 'Unban date must be specified to a future date.', 'IpbanAlreadyBanned' => 'A matching IP (%s) has already been banned.', 'IpbanPatternBanned' => "The IP address/pattern '%s' has been banned.", 'IpbanAddFailed' => 'Failed to add IP ban.', 'IpbanAddHeading' => 'Add IP Ban', 'IpbanIpAddressLabel' => 'IP Address', 'IpbanReasonLabel' => 'Ban Reason', 'IpbanUnbanDateLabel' => 'Unban Date', 'IpbanIpAddressInfo' => 'You may specify a pattern such as 218.139.*.*', 'IpbanAddButton' => 'Add IP Ban', // - ipban/edit 'IpbanEditTitle' => 'Modify IP Ban', 'IpbanEnterEditReason' => 'Please enter a reason for the IP ban modification.', 'IpbanEditFailed' => 'Failed to modify IP ban.', 'IpbanEditHeading' => 'Modify IP Ban', 'IpbanEditReasonLabel' => 'Edit Reason', 'IpbanEditButton' => 'Modify IP Ban', // - ipban/index 'IpbanListTitle' => 'IP Ban List', 'IpbanListHeading' => 'IP Ban List', 'IpbanBannedIpLabel' => 'Banned IP', 'IpbanBanDateLabel' => 'Ban Date', 'IpbanBanReasonLabel' => 'Ban Reason', 'IpbanBanExpireLabel' => 'Ban Expiration Date', 'IpbanModifyLink' => 'Modify', 'IpbanRemoveLink' => 'Remove', 'IpbanUnbanButton' => 'Unban Selected', 'IpbanListNoBans' => 'There are currently no IP bans.', // - ipban/remove 'IpbanRemoveTitle' => 'Remove IP Ban', 'IpbanEnterRemoveReason' => 'Please enter a reason for the IP ban removal.', 'IpbanNotBanned' => 'No matching IP (%s) is currently banned.', 'IpbanPatternUnbanned' => "The IP address/pattern '%s' has been unbanned.", 'IpbanRemoveFailed' => 'Failed to remove IP ban.', 'IpbanRemoveHeading' => 'Remove IP Ban', 'IpbanRemoveReasonLabel' => 'Unban Reason', 'IpbanRemoveButton' => 'Remove IP Ban', // - ipban/unban 'IpbanNothingToUnban' => 'Nothing to unban.', 'IpbanEnterUnbanReason' => 'Please enter a reason for lifting the IP ban(s).', 'IpbanUnbanned' => 'Lifted selected IP ban(s)!', 'IpbanUnbanFailed' => 'Failed to lift %d of the specified IP unban(s)!', // Module: item // - item/add // - item/copy // - item/edit // - item/index // - item/view // Module: itemshop // - itemshop/add // - itemshop/delete // - itemshop/edit // - itemshop/imagedel // Module: logdata // - logdata/chat // - logdata/cashpoints 'CashLogTitle' => 'List CashPoints Log', 'CashLogHeading' => 'CashPoint Log', 'CashLogNotFound' => 'No cash logs found.', 'CashLogDateLabel' => 'Date/Time', 'CashLogCharacterLabel' => 'Character', 'CashLogTypeLabel' => 'Type', 'CashLogCashTypeLabel' => 'Cash Type', 'CashLogAmountLabel' => 'Amount', 'CashLogMapLabel' => 'Map', // - logdata/command 'CommandLogTitle' => 'List Commands', 'CommandLogHeading' => 'Commands', 'CommandLogNotFound' => 'No commands found.', 'CommandLogDateLabel' => 'Date/Time', 'CommandLogAccountIdLabel'=> 'Account ID', 'CommandLogCharIdLabel' => 'Character ID', 'CommandLogCharNameLabel' => 'Character Name', 'CommandLogCommandLabel' => 'Command', 'CommandLogMapLabel' => 'Map', // - logdata/index // - logdata/login // - logdata/pick 'PickLogTitle' => 'List Item Picks', 'PickLogHeading' => 'Item Picks', 'PickLogNotFound' => 'No item picks found.', 'PickLogDateLabel' => 'Date/Time', 'PickLogCharacterLabel' => 'Character', 'PickLogTypeLabel' => 'Type', 'PickLogItemLabel' => 'Item Name', 'PickLogAmountLabel' => 'Amount', 'PickLogRefineLabel' => 'Refine', 'PickLogCard0Label' => 'Slot 1', 'PickLogCard1Label' => 'Slot 2', 'PickLogCard2Label' => 'Slot 3', 'PickLogCard3Label' => 'Slot 4', 'PickLogMapLabel' => 'Map', // - logdata/branch 'BranchLogTitle' => 'List Branch Log', 'BranchLogHeading' => 'Branch Log', 'BranchLogNotFound' => 'No branch logs found.', 'BranchLogIDLabel' => 'Branch Log ID', 'BranchLogDateLabel' => 'Date / Time', 'BranchLogAccountIDLabel' => 'Account ID', 'BranchLogCharIDLabel' => 'Char ID', 'BranchLogCharNameLabel' => 'Char Name', 'BranchLogMapLabel' => 'Map', // - logdata/char 'CharLogTitle' => 'List Character Log', 'CharLogHeading' => 'Character Log', 'CharLogNotFound' => 'No character logs found.', 'CharLogDateLabel' => 'Date / Time', 'CharLogMsgLabel' => 'Action', 'CharLogAccountIDLabel' => 'Account ID', 'CharLogCharNumLabel' => 'Character slot', 'CharLogCharNameLabel' => 'Character Name', // - logdata/inter 'InterLogTitle' => 'List of Interactions Log', 'InterLogHeading' => 'Interactions Log', 'InterLogNotFound' => 'No Interactions logs found.', 'InterLogDateLabel' => 'Date / Time', 'InterLogLabel' => 'Interactions Log', // - logdata/mvp 'MVPLogTitle' => 'List MVP Log', 'MVPLogHeading' => 'MVP Log', 'MVPLogNotFound' => 'No MVP logs found.', 'MVPLogIDLabel' => 'MVP Log ID', 'MVPLogDateLabel' => 'Date / Time', 'MVPLogCharacterLabel' => 'Character ID', 'MVPLogMonsterLabel' => 'MVP Monster', 'MVPLogPrizeLabel' => 'MVP Prize', 'MVPLogExpLabel' => 'MVP Experience', 'MVPLogMapLabel' => 'Map', // - logdata/npc 'NPCLogTitle' => 'List NPC Log', 'NPCLogHeading' => 'NPC Log', 'NPCLogNotFound' => 'No npc logs found.', 'NPCLogIDLabel' => 'NPC ID', 'NPCLogDateLabel' => 'Date / Time', 'NPCLogAccountIDLabel' => 'Account ID', 'NPCLogCharIDLabel' => 'Character ID', 'NPCLogCharNameLabel' => 'Character Name', 'NPCLogMapLabel' => 'Map', 'NPCLogMsgLabel' => 'Message', // - logdata/zeny 'ZenyLogTitle' => 'List Zeny Log', 'ZenyLogHeading' => 'Zeny Log', 'ZenyLogNotFound' => 'No zeny logs found.', 'ZenyLogDateLabel' => 'Date/Time', 'ZenyLogCharacterLabel' => 'Character', 'ZenyLogSourceLabel' => 'Source', 'ZenyLogTypeLabel' => 'Type', 'ZenyLogAmountLabel' => 'Amount', 'ZenyLogMapLabel' => 'Map', // - logdata/feeding 'FeedingLogTitle' => 'Feeding Log', // Module: mail // - mail/index 'MailerTitle' => 'Form Mailer', 'MailerHeading' => 'Form Mailer', 'MailerEnterToAddress' => 'Please enter a "to" address.', 'MailerEnterSubject' => 'Please enter a subject.', 'MailerEnterBodyText' => 'Please enter some body text.', 'MailerEmailHasBeenSent' => 'Your e-mail has been successfully sent.', 'MailerFailedToSend' => 'The mailer system failed to send the e-mail. This could be a misconfiguration.', 'MailerInfo' => 'You may use the below mail form to send an e-mail using the control panel.', 'MailerFromLabel' => 'From', 'MailerToLabel' => 'Where are we sending this?', 'MailerSubjectLabel' => 'Subject', 'MailerBodyLabel' => 'Body', 'MailerSelectTemplateLabel' => 'Select Template', // Module: main // - main/index 'MainPageHeading' => 'Flux Control Panel', 'MainPageInfo' => "If you are seeing this page, it's likely that you've successfully installed Flux.", 'MainPageInfo2' => "Would you like to change this page? Well, here's how you can:", 'MainPageStep1' => 'Open "%s" in your text editor.', 'MainPageStep2' => 'Edit the file from your editor and save your changes.', 'MainPageThanks' => 'Thanks for using Flux!', 'MainPageWelcome' => 'Welcome to %s!', // - main/pagenotfound 'PageNotFoundTitle' => '404 Page Not Found', 'PageNotFoundHeading' => 'Page Not Found', 'PageNotFoundInfo' => 'The page you have requested was not found on our server. Please check the address and make sure it is correct, and try again.', // - main/preprocess 'DisallowedDuringWoE' => 'The page you have requested is not accessible during WoE.', // Module: monster // - monster/index // - monster/view // Module: purchase // - purchase/add // - purchase/cart // - purchase/checkout // - purchase/clear // - purchase/index // - purchase/pending // - purchase/remove // Module: ranking // - ranking/character // - ranking/guild // - ranking/zeny // Module: server // - server/info 'ServerInfoTitle' => 'Server Information', 'ServerInfoHeading' => 'Server Information', 'ServerInfoText' => "Here you'll find various server information.", 'ServerInfoSubHeading' => 'Information for %s', 'ServerInfoSubHeading2' => 'Job Class Information for %s', 'ServerInfoAccountLabel' => 'Accounts', 'ServerInfoCharLabel' => 'Characters', 'ServerInfoGuildLabel' => 'Guilds', 'ServerInfoPartyLabel' => 'Parties', 'ServerInfoZenyLabel' => 'Zeny', // - server/status 'ServerStatusTitle' => 'Current Server Status', 'ServerStatusHeading' => 'Server Status', 'ServerStatusInfo' => "Understanding the online and offline status of each server can help you understand how an issue can relate to your problem. For example, if the login server is offline it means that you won't be able to log into the game. The character server and map servers are necessary for the actual gameplay past the point of logging in.", 'ServerStatusServerLabel' => 'Server', 'ServerStatusLoginLabel' => 'Login Server', 'ServerStatusCharLabel' => 'Character Server', 'ServerStatusMapLabel' => 'Map Server', 'ServerStatusOnlineLabel' => 'Players Online', 'ServerStatusPeakLabel' => 'Player Peak', // Module: service // - service/tos 'TermsTitle' => 'Terms of Service', 'TermsHeading' => 'Terms of Service', 'TermsInfo' => 'Please read before creating an account!', 'TermsInfo2' => "FOR CONTROL PANEL ADMINISTRATOR: You may add your server's ToS in this view file directly. The location of the view file is: %s", // Module: unauthorized // - unauthorized/index 'UnauthorizedTitle' => 'Unauthorized', 'UnauthorizedHeading' => 'Unauthorized', 'UnauthorizedInfo' => 'You are unauthorized to view this page. Redirecting…', // Module: woe // - woe/index 'WoeTitle' => 'WoE Hours', 'WoeHeading' => 'War of Emperium Hours', 'WoeInfo' => "Below are the WoE hours for %s. These hours are subject to change at anytime, but let's hope not.", 'WoeServerTimeInfo' => 'The current server time is:', 'WoeServerLabel' => 'Servers', 'WoeTimesLabel' => 'War of Emperium Times', 'WoeNotScheduledInfo' => 'There are no scheduled WoE hours.', // Module: contactform 'CFTitleSubmit' => 'Contact Us', // Module: News and Pages 'CMSNewsHeader' => 'Announcements', 'CMSPageHeader' => 'Content Management System', 'CMSPageText' => 'This module enables server admins and staff to create pages within their website with no prior flux/coding knowledge. The built-in news system can also be swapped out for an rss feed by modifying the application settings.', 'CMSNewsTitleError' => 'News title is required!', 'CMSNewsBodyError' => 'News body is required!', 'CMSPageTitleError' => 'Page Title is required!', 'CMSPageBodyError' => 'Page body is required!', 'CMSPagePathError' => 'Page path is required!', 'CMSNewsAdded' => 'News added to system', 'CMSPagesAdded' => 'Your new page has been added', 'CMSNewsUpdated' => 'News updated', 'CMSPageUpdated' => 'Your page has been updated', 'CMSNewsAddTitle' => 'Add a news item', 'CMSPageAddTitle' => 'Add a new page', 'CMSNewsEditTitle' => 'Edit news', 'CMSPageEditTitle' => 'Edit page', 'CMSNewsNotFound' => 'News not found!', 'CMSPageNotFound' => 'Page not found!', 'CMSNewsDeleted' => 'News deleted', 'CMSPageDeleted' => 'Your page has been deleted', 'CMSNewsEmpty' => 'No news articles have been found. Are you using the correct News Type? (CMSNewsType setting)', 'CMSNewsRSSNotFound' => 'RSS feed can\'t be found. Make sure the CMSNewsRSS setting is correct, or switch CMSNewsType to 1 to use built-in news system!', 'CMSPageEmpty' => 'No page added', 'CMSNewsLink' => 'read more...', 'CMSEdit' => 'Edit', 'CMSDelete' => 'Delete', 'CMSNewsTitleLabel' => 'News Title', 'CMSNewsBodyLabel' => 'News Body', 'CMSNewsLinkLabel' => 'News Link', 'CMSNewsAuthorLabel' => 'News Author', 'CMSPageTitleLabel' => 'Page Title', 'CMSPageBodyLabel' => 'Page Body', 'CMSPagePathLabel' => 'Page Path', 'CMSCreatedLabel' => 'Date Created', 'CMSModifiedLabel' => 'Date Modified', 'CMSActionLabel' => 'Action', 'CMSConfirmDeleteLabel' => 'Are you sure you want to delete?', 'CMSPageCreate' => 'Create now?', 'CMSOptionalLabel' => '(Optional)', 'CMSRequiredLabel' => '(Required)', 'CMSCreateLabel' => 'Add News', // Module: vending 'TLHeaderTasks' => 'Tasks', 'TLHeaderOwner' => 'Owner', 'TLHeaderPriority' => 'Priority', 'TLHeaderStatus' => 'Status', 'TLHeaderCreated' => 'Created', 'TLHeaderModified' => 'Modified', 'TLHeaderResources' => 'Additional Resources', 'TLHeaderBody' => 'Body', // Module: servicedesk 'SDHeader' => 'Service Desk', 'SDCreateNew' => 'Create a new ticket', 'SDWelcomeText' => 'Welcome to the Service Desk', 'SDNoTickets' => 'You have not created any tickets.', 'SDNoBlankResponse' => 'For a response to register, you must type something into the box!', 'SDNoCatsAvailable' => 'No Categories Available', 'SDNoOpenTickets' => 'There are no Open tickets in the database.', 'SDNoInactiveTickets' => 'You have no in-active tickets at the moment.', 'SDNoClosedTickets' => 'There are no Closed tickets in the database.', 'SDNoCats' => 'There are no categories within the database.', 'SDHuh' => 'You should not be here o.O', 'SDPointerChatLog' => 'We recommend pasting to pastebin.com then putting the link in here.', 'SDPointerScreenShot' => 'Provide image links as evidence', 'SDPointerVideoLink' => 'We recommend uploading to youtube then putting the link in here.', 'SDHeaderID' => 'Ticket #', 'SDHeaderSubject' => 'Subject', 'SDHeaderCategory' => 'Category', 'SDHeaderStatus' => 'Current Status', 'SDHeaderLastAuthor' => 'Last Author', 'SDHeaderTimestamp' => 'Created', 'SDHeaderAccount' => 'Account', 'SDHeaderTeam' => 'Team', 'SDH3ActiveTickets' => 'Active Tickets', 'SDH3InActiveTickets' => 'In-Active Tickets', 'SDH3ClosedTickets' => 'Closed Tickets', 'SDH3CurrentCat' => 'Current Categories', 'SDH3CreateCat' => 'Create New Category', 'SDH3StaffList' => 'Current Staff Settings', 'SDH3StaffCreate' => 'Add Staff Settings', 'SDReOpenPlayer' => 'Ticket Re-Opened by player', 'SDReOpenStaff' => '', 'SDRespTable1' => 'Respond and Return to Ticket', 'SDRespTable2' => 'Respond and Return to List', 'SDRespTable3' => 'Respond and Resolve Ticket', 'SDRespTable4' => 'Respond and Escalate', 'SDRespTable5' => 'Close Ticket', 'SDRespTable6' => 'Respond and Re-Open Ticket', 'SDRespTable7' => 'Resolve Ticket and Credit Account', 'SDGroup1' => 'Support Staff', 'SDGroup2' => 'Head of Support', 'SDGroup3' => 'Administration', 'SDLinkOpenNew' => 'Open a new ticket', // Module: webcommands 'WCTitleLabel' => 'Web Commands', ); ?> ================================================ FILE: lang/es_es.php ================================================ almacén ? No! That'd require scripts to be translated for that! // Example: ban -> expulsión -> bloqueo ? Yes! No scripts to be translated and it's widely understood! // ip ban -> IP con acceso prohibido ? return array( // Generic/Misc. 'Language' => 'Spanish', 'YesLabel' => 'Sí', 'NoLabel' => 'No', 'NoteLabel' => 'Nota', 'GenderTypeMale' => 'Hombre', 'GenderTypeFemale' => 'Mujer', 'GenderTypeServer' => 'Servidor', 'RefreshSecurityCode' => 'Actualizar Código de Seguridad', 'NoneLabel' => 'Ninguno', 'NeverLabel' => 'Nunca', 'NotApplicableLabel' => 'No Aplicable', 'UnknownLabel' => 'Desconocido', 'IsEqualToLabel' => 'es igual que', 'IsGreaterThanLabel' => 'es mayor que', 'IsLessThanLabel' => 'es menor que', 'AllLabel' => 'Todo', 'SearchLabel' => 'Buscar…', 'GoBackLabel' => 'Volver a la página anterior…', 'SearchButton' => 'Buscar', 'ResetButton' => 'Reiniciar', 'FilterButton' => 'Filtrar', 'NotAcceptingDonations' => "En estos momentos no aceptamos donacioes. Disculpa las molestias.", //'NotAcceptingDonations' => "We're sorry, but our donation system is currently undergoing maintenance, please try again later.", 'FoundSearchResults' => 'Se han encontrado un total de %d registro(s) en %d página(s). Mostrando el/los resultado(s) %d-%d.', 'LoginToDonate' => 'Por favor, inicia sesión para hacer donaciones.', 'UnknownCharacter' => 'No se ha encontrado el personaje.', 'AccountIdLabel' => 'ID de Cuenta', 'AccountGroupIDLabel' => 'ID de Grupo', 'AccountStateLabel' => 'Estado de la Cuenta', 'CreditBalanceLabel' => 'Balance de Crédito', 'UsernameLabel' => 'Nombre de Usuario', 'PasswordLabel' => 'Contraseña', 'EmailAddressLabel' => 'Correo Electrónico', 'GenderLabel' => 'Sexo', 'LoginCountLabel' => 'Número de Conexiones', 'LastLoginDateLabel' => 'Fecha de la Última Conexión', 'LastUsedIpLabel' => 'Última IP Usada', 'AccountStateNormal' => 'Normal', 'AccountStatePending' => 'Pendiente', 'AccountStatePermBanned' => 'Bloqueado Permanentemente', 'AccountStateTempBanLbl' => 'Bloqueado Temporalmente', 'AccountStateTempBanned' => 'Bloqueado Temp. (hasta: %s)', 'OnlineLabel' => 'Conectado', 'OfflineLabel' => 'Desconectado', 'ItemIdLabel' => 'ID del Objeto', 'ItemNameLabel' => 'Nombre del Objeto', 'ItemAmountLabel' => 'Cantidad', 'ItemIdentifyLabel' => 'Identificado', 'ItemRefineLabel' => 'Refinado', 'ItemBrokenLabel' => 'Roto', 'ItemCard0Label' => 'Carta 1', 'ItemCard1Label' => 'Carta 2', 'ItemCard2Label' => 'Carta 3', 'ItemCard3Label' => 'Carta 4', //SIDEBAR //FluxCP Menu Items //Categories 'MainMenuLabel' => 'Menú Principal', 'ForumLabel' => 'Forum', 'AccountLabel' => 'Cuenta', 'CharacterLabel' => 'Personaje', 'ServiceDeskLabel' => 'Service Desk', 'CPLogsLabel' => 'CP Logs', 'FluxAdminLabel' => 'Flux Admin', 'PagesLabel' => 'Pages', 'IPBanListLabel' => 'IP Ban List', 'GuildsLabel' => 'Guilds', 'rALogsLabel' => 'rA Logs', 'SendMailLabel' => 'Send Mail', 'ReInstallLabel' => 'Re-Install', 'TaskListLabel' => 'Task List', 'DonationsLabel' => 'Donaciones', 'InformationLabel' => 'Informaciones', 'DatabaseLabel' => 'Base de datos', 'SocialLabel' => 'Social', //SubMenus 'HomeLabel' => 'Inicio', 'NewsLabel' => 'Noticias', 'DownloadsLabel' => 'Descargas', 'RulesLabel' => 'Reglas', 'ContactUsLabel' => 'Contáctanos', 'MyAccountLabel' => 'Mi Cuenta', 'HistoryLabel' => 'Historial', 'ServiceDeskLabel' => 'Centro de Soporte', 'PurchaseLabel' => 'Canjear', 'DonateLabel' => 'Donar', 'ServerInfoLabel' => 'Info. del Servidor', 'ServerStatusLabel' => 'Estado del Servidor', 'WoeHoursLabel' => 'Horarios WOE', 'CastlesLabel' => 'Castillos', 'WhosOnlineLabel' => 'Jugadores Conectados', 'MapStaticsLabel' => 'Estadísticas de Mapas', 'RankingInfoLabel' => 'Ranking', 'VendingInfoLabel' => 'Vending', 'ItemDatabaseLabel' => 'Item DB', 'MobDatabaseLabel' => 'Mob DB', 'JoinUsInFacebookLabel' => '¡Encuéntranos en Facebook!', 'RateUsOnRMSLabel' => '¡Califícanos en RMS!', // Security 'SecuritySessionInvalid' => 'Lo sentimos, pero tu tiempo de sesión ha expirado. Inténtalo de nuevo.', 'SecurityNeedSession' => 'Lo sentimos, pero no se ha encontrado la sesión del formulario (¿intento de hack?)', 'SecurityNeedToken' => 'Lo sentimos, pero no se ha encontrado la identificación del formulario (¿intento de hack?)', // Module: account // - account/changemail 'EmailChangeTitle' => 'Cambiar Correo Electrónico', 'EnterEmailAddress' => 'Introduce una dirección de correo electrónico.', 'EmailCannotBeSame' => 'Tu nuevo correo electrónico no puede ser el mismo que el actual.', 'EmailInvalid' => 'Dirección de correo electrónico no válida.', 'EmailAlreadyRegistered' => "El correo electrónico especificado ya pertenece a otra cuenta.", 'EmailChangeSent' => 'Se ha enviado un correo electrónico a la nueva dirección, con un enlace para confirmar el cambio.', 'EmailAddressChanged' => '¡Se ha cambiado tu dirección de correo electrónico!', 'EmailChangeFailed' => 'No se pudo cambiar la dirección de correo electrónico. Inténtalo de nuevo más tarde.', 'EmailChangeHeading' => 'Cambiar correo electrónico', 'EmailChangeInfo' => 'Si quieres cambiar la dirección de correo electrónico registrada en tu cuenta, debes rellenar el formulario de abajo.', 'EmailChangeInfo2' => 'Tras enviar el formulario, se requerirá que confirmes tu nuevo correo electrónico (se enviará un correo electrónico a la nueva dirección con un enlace).', 'EmailChangeLabel' => 'Dirección de Correo Electrónico nueva', 'EmailChangeInputNote' => '¡Debe ser una dirección de correo electrónico correcta!!', 'EmailChangeButton' => 'Cambiar Dirección de Correo Electrónico', // - account/changepass 'PasswordChangeTitle' => 'Cambiar Contraseña', 'NeedCurrentPassword' => 'Introduce tu contraseña actual.', 'NeedNewPassword' => 'Introduce tu nueva contraseña.', 'OldPasswordInvalid' => "La contraseña introducida no coincide con la que tenemos guardada.", 'ConfirmNewPassword' => 'Confirma tu nueva contraseña.', 'NewPasswordHasUsername' => 'Tu nueva contraseña no debe contener tu nombre de usuario.', 'NewPasswordInvalid' => 'Tu nueva contraseña contiene caracteres no válidos.', 'NewPasswordSameAsOld' => 'La nueva contraseña no puede ser la misma que tu contraseña actual.', 'NewPasswordNeedUpper' => 'Tu nueva contraseña debe tener al menos %d letra(s) mayúscula(s).', 'NewPasswordNeedLower' => 'Tu nueva contraseña debe tener al menos %d letra(s) minúscula(s).', 'NewPasswordNeedNumber' => 'Tu nueva contraseña debe tener al menos %d número(s).', 'NewPasswordNeedSymbol' => 'Tu nueva contraseña debe tener al menos %d símbolo(s).', 'PasswordHasBeenChanged' => 'Se ha cambiado tu contraseña. Por favor, identifícate de nuevo.', 'FailedToChangePassword' => 'No se pudo cambiar tu contraseña. Por favor, contacta con un administrador.', 'PasswordChangeHeading' => 'Cambiar Contraseña', 'PasswordChangeInfo' => 'Por favor, introduce tu contraseña actual, después la nueva contraseña que desees usar y vuélvela a introducir para confirmarla.', 'CurrentPasswordLabel' => 'Contraseña Actual', 'NewPasswordLabel' => 'Nueva Contraseña', 'NewPasswordConfirmLabel' => 'Vuelve a introducir la Nueva Contraseña', 'PasswordChangeNote' => 'Asegúrate de introducir información correcta.', 'PasswordChangeNote2' => 'Tras cambiar tu contraseña, serás deslogueado.', 'PasswordChangeButton' => 'Cambiar Contraseña', // - account/changesex 'GenderChangeTitle' => 'Cambiar Sexo', 'GenderChangeBadChars' => 'No puedes cambiar de sexo si alguno de tus personajes es: %s', 'GenderChanged' => 'Se ha cambiado tu sexo. Además, se han descontado %d crédito(s) de tu cuenta.', 'GenderChangedForFree' => 'Se ha cambiado tu sexo.', 'GenderChangeHeading' => 'Cambiar Sexo', 'GenderChangeCost' => 'Los cambios de sexo cuestan %s crédito(s).', 'GenderChangeBalance' => 'Tu balance actual es de %s crédito(s).', 'GenderChangeNoFunds' => 'No tienes suficientes créditos para cambiar de sexo en estos momentos.', 'GenderChangeNoCost' => 'Los cambios de sexo son gratis para ti.', 'GenderChangeCharInfo' => 'No puedes cambiar de sexo si alguno de tus personajes es: %s', 'GenderChangeSubHeading' => '¡Asegúrate de que realmente quieres cambiar de sexo!', 'GenderChangeFormText' => '¿Quieres cambiar tu sexo a %s?', 'GenderChangeConfirm' => '¿Estás totalmente seguro de que quieres cambiar de sexo?', 'GenderChangeButton' => 'Sí, seguro.', // - account/confirm 'AccountConfirmTitle' => 'Confirma la Cuenta', 'AccountConfirmUnban' => 'Se ha confirmado y activado la cuenta.', 'AccountConfirmMessage' => 'Tu cuenta ha sido confirmada y activada. Ya puedes iniciar sesión.', // - account/confirmemail 'EmailConfirmTitle' => 'Confirmar Correo Electrónico', 'EmailConfirmFailed' => 'Ha habido un problema técnico al cambiar tu dirección de correo electrónico. Por favor, contacta con un administrador.', 'EmailConfirmChanged' => '¡Se ha cambiado tu dirección de correo electrónico!', // - account/create 'AccountCreateTitle' => 'Crear Cuenta', 'AccountConfirmBan' => 'Esperando activación de la cuenta: %s', 'AccountCreateEmailSent' => 'Se ha enviado un correo electrónico con detalles para la activación de tu cuenta. Por favor, comprueba tu correo electrónico y activa tu cuenta para iniciar sesión.', 'AccountCreateFailed' => 'Se ha creado tu cuenta, pero no hemos podido enviarte un correo electrónico debido a problemas técnicos. Por favor, contacta con algún miembro del equipo del servidor y pide ayuda.', 'AccountCreated' => 'Enhorabuena, te has registrado con éxito y logueado automáticamente.', 'AccountCreateHeading' => 'Registrarse', 'AccountCreateTerms' => 'Términos del Servicio', 'AccountCreateInfo' => 'Por favor, lee nuestros %s antes de registrar una cuenta para asegurarte de entender las normas respecto a tener una cuenta en nuestro servidor privado de Ragnarok Online.', 'AccountCreateInfo2' => 'Al hacer click en "Crear Cuenta", estarás de acuerdo en aceptar nuestros %s.', 'AccountCreateGenderInfo' => "¡El sexo que escojas aquí afectará al sexo de tus personajes en el juego!", 'AccountServerLabel' => 'Servidor', 'AccountUsernameLabel' => 'Tu Nombre de Usuario', 'AccountPasswordLabel' => 'Tu Contraseña', 'AccountPassConfirmLabel' => 'Confirmar Contraseña', 'AccountEmailLabel' => 'Dirección de Correo Electrónico', 'AccountEmailLabel2' => 'Confirmar dirección de E-mail', 'AccountGenderLabel' => 'Sexo', 'AccountBirthdateLabel' => 'Fecha de Cumpleaños', 'AccountSecurityLabel' => 'Código de Seguridad', 'AccountCreateButton' => 'Crear Cuenta', 'AccountInvalidChars' => "El nombre de usuario solo puede contener los siguientes caracteres: '%s'", 'AccountRecaptchaKey' => 'Necesitas claves de Recaptcha, ver más en config/applications.php (ReCaptchaPublicKey/ReCaptchaPrivateKey)', 'InvalidLoginServer' => 'Has seleccionado un login server no válido. Inténtalo de nuevo seleccionando un servidor válido.', 'InvalidLoginCredentials' => 'Las credenciales introducidas no son válidas. Asegúrate de haber escrito la información correcta e inténtalo de nuevo.', 'UnexpectedLoginError' => 'Ha ocurrido un fallo inesperado. Inténtalo de nuevo o contacta con un administrador.', 'CriticalLoginError' => 'Ha ocurrido algo malo. Contacta con un administrador cuanto antes.', 'UsernameAlreadyTaken' => "El nombre de usuario que has escogido ya ha sido tomado por otro usuario.", 'UsernameTooShort' => sprintf('Tu nombre de usuario debe tener entre %d y %d caracteres.', Flux::config('MinUsernameLength'), Flux::config('MaxUsernameLength')), 'UsernameTooLong' => sprintf('Tu nombre de usuario debe tener entre %d y %d caracteres.', Flux::config('MinUsernameLength'), Flux::config('MaxUsernameLength')), 'PasswordContainsUser' => 'Tu contraseña no puede contener tu nombre de usuario.', 'PasswordHasUsername' => 'Tu contraseña no puede contener tu nombre de usuario.', 'PasswordTooShort' => 'Tu contraseña debe tener entre %d y %d caracteres.', 'PasswordTooLong' => 'Tu contraseña debe tener entre %d y %d caracteres.', 'PasswordsDoNotMatch' => "Las contraseñas no coinciden. Asegúrate de haberlas escrito correctamente.", 'PasswordNeedUpper' => 'Tu contraseña debe contener al menos %d letra(s) mayúscula(s).', 'PasswordNeedLower' => 'Tu contraseña debe contener al menos %d letra(s) minúscula(s).', 'PasswordNeedNumber' => 'Tu contraseña debe contener al menos %d número(s).', 'PasswordNeedSymbol' => 'Tu contraseña debe contener al menos %d símbolo(s).', 'EmailAddressInUse' => "La dirección de correo electrónico que has introducido ya está registrada por otra cuenta. Utiliza otra dirección de correo electrónico.", 'InvalidEmailAddress' => "La dirección de correo electrónico que has introducido no tiene un formato válido.", 'InvalidEmailconf' => "Las direcciones de E-mail no coinciden.", 'InvalidGender' => 'El sexo de la cuenta debe ser "M" o "F"', 'InvalidServer' => "El servidor que has seleccionado no existe.", 'InvalidSecurityCode' => 'Por favor, introduce correctamente el código de seguridad.', 'InvalidPassword' => 'Tu contraseña contiene caracteres no válidos.', 'InvalidBirthdate' => 'Has introducido una fecha de cumpleaños no válida.', 'CriticalRegisterError' => 'Ha ocurrido algo malo. Contacta con un administrador cuanto antes.', // - account/edit 'AccountEditTitle' => 'Modifcar Cuenta', 'AccountEditTitle2' => 'Modificando Mi Cuenta', 'AccountEditTitle3' => 'Modificando Cuenta (%s)', 'CannotModifyOwnGroupID' => 'No puedes modificar el ID de grupo de tu cuenta.', 'CannotModifyAnyGroupID' => 'No puedes modificar ID de grupo de las cuentas.', 'CannotModifyGroupIDHigh' => 'No puedes asignar a otra cuenta una ID de grupo mayor que el que tienes.', 'InvalidGroupID' => 'ID de grupo no válido.', 'CannotModifyBalance' => 'No puedes modificar los balances de las cuentas.', 'InvalidLastLoginDate' => 'La última fecha de conexión no es válida.', 'AccountModified' => 'Se ha modificado la cuenta.', 'AccountEditHeading' => 'Modificar Cuenta', 'AccountEditButton' => 'Modificar Cuenta', 'AccountEditNotFound' => 'No se ha encontrado la cuenta.', // - account/index 'AccountIndexTitle' => 'Lista de Cuentas', 'AccountIndexHeading' => 'Cuentas', 'LoginBetweenLabel' => 'Con Actividad Entre', 'BirthdateBetweenLabel' => 'Fecha de Nacimiento Entre', 'AccountIndexNotFound' => 'No se ha encontrado la cuenta.', // - account/login 'LoginTitle' => 'Iniciar Sesión', 'LoginHeading' => 'Iniciar Sesión', 'LoginButton' => 'Acceder', 'LoginPageMakeAccount' => '¿Aún no tienes una cuenta? ¡Hazte una!', 'TemporarilyBanned' => 'Tu cuenta se encuentra bloqueada temporalmente.', 'PermanentlyBanned' => 'Tu cuenta se encuentra bloqueada permanentemente.', 'IpBanned' => 'La dirección IP desde la que te encuentras tiene el acceso prohibido.', 'PendingConfirmation' => 'Tu cuenta está aún no ha sido activada por correo electrónico.', // - account/logout 'LogoutTitle' => 'Cerrar Sesión', 'LogoutHeading' => 'Cerrar Sesión', 'LogoutInfo' => 'Has cerrado tu sesión.', 'LogoutInfo2' => 'Por favor, espera un momento mientras te redireccionamos…', // - account/resend 'ResendTitle' => 'Volver a Enviar Correo Electrónico de Confirmación', 'ResendEnterUsername' => 'Introduce el nombre de usuario de tu cuenta.', 'ResendEnterEmail' => 'Introduce tu dirección de correo electrónico.', 'ResendFailed' => 'No se pudo volver a enviar el código de confirmación.', 'ResendEmailSent' => 'Se ha vuelto a enviar tu código de confirmación. Por favor, comprueba tu correo electrónico para proceder con la activación de tu cuenta.', 'ResendHeading' => 'Volver a Enviar Correo Electrónico de Confirmación', 'ResendInfo' => 'Introduce el nombre de cuenta y la dirección de correo electrónico que has usado durante el registro para poder volver a enviar un correo electrónico de confirmación.', 'ResendServerLabel' => 'Servidor del Registro', 'ResendAccountLabel' => 'Nombre de Usuario de la Cuenta', 'ResendEmailLabel' => 'Dirección de Correo Electrónico', 'ResendServerInfo' => 'Se trata del servidor en el que has registrado la cuenta.', 'ResendAccountInfo' => 'Se trata del nombre de cuenta que has registrado.', 'ResendEmailInfo' => 'Se trata de la dirección de correo electrónico que usaste cuando registraste la cuenta del campo anterior.', 'ResendButton' => 'Volver a Enviar Correo Electrónico de Confirmación', // - account/resetpass 'ResetPassTitle' => 'Recuperar Contraseña', 'ResetPassEnterAccount' => 'Introduce el nombre de usuario de tu cuenta.', 'ResetPassEnterEmail' => 'Introduce tu dirección de correo electrónico.', 'ResetPassDisallowed' => 'No se puede hacer uso de la recuperación de contraseña para esta cuenta.', 'ResetPassFailed' => 'No se pudo enviar el correo electrónico para recuperar tu contraseña.', 'ResetPassEmailSent' => 'Se ha enviado un correo electrónico con detalles para recuperar tu contraseña.', 'ResetPassTitle' => 'Recuperar Contraseña', 'ResetPassInfo' => 'Si has perdido tu contraseña, puedes recuperarla introduciendo la dirección de correo electrónico que utilizaste para registrar tu cuenta.', 'ResetPassInfo2' => 'Entonces, se enviará un correo electrónico a la dirección especificada con un enlace que te permitirá recuperar tu contraseña, por lo que se requiere una dirección de correo electrónico válida.', 'ResetPassServerLabel' => 'Servidor del Registro', 'ResetPassAccountLabel' => 'Nombre de Usuario de la Cuenta', 'ResetPassEmailLabel' => 'Dirección de Correo Electrónico', 'ResetPassServerInfo' => 'Se trata del servidor en el que has registrado la cuenta.', 'ResetPassAccountInfo' => 'Se trata del nombre de cuenta que has registrado.', 'ResetPassEmailInfo' => 'Se trata de la dirección de correo electrónico que usaste cuando registraste la cuenta del campo anterior.', 'ResetPassButton' => 'Enviar Correo Electrónico de Recuperación de Contraseña', // - account/resetpw 'ResetPwTitle' => 'Recuperar Contraseña', 'ResetPwFailed' => 'No se pudo recuperar la contraseña. Inténtalo de nuevo más tarde.', 'ResetPwDone' => 'Se ha cambiado tu contraseña y se te ha enviado un correo electrónico con tu nueva contraseña.', 'ResetPwDone2' => 'Se ha cambiado tu contraseña, pero no hemos podido enviar el correo electrónico que contiene tu nueva contraseña. Por favor, repite el proceso de recuperar tu contraseña para resolver este problema.', // - account/transfer 'TransferTitle' => 'Transferir Créditos de Donación', 'TransferGreaterThanOne' => 'Solo puedes transferir créditos en cantidades mayores que 1.', 'TransferEnterCharName' => 'Debes introducir el nombre del personaje que recibirá los créditos.', 'TransferNoCharExists' => "El personaje '%s' no existe. Asegúrate de haberlo escrito correctamente.", 'TransferNoBalance' => 'No tienes suficiente saldo para realizar la transferencia.', 'TransferUnexpectedError' => 'Ha ocurrido un error inesperado.', 'TransferSuccessful' => '¡Se han transferido los créditos!', 'TransferHeading' => 'Transferir Créditos de Donación', 'TransferSubHeading' => 'Se transferirán los créditos a un personaje del servidor %s.', 'TransferInfo' => 'Tienes %s crédito(s) en estos instantes.', 'TransferInfo2' => 'Introduce la cantidad de créditos que te gustaría transferir y el nombre de un personaje que pertenezca a la cuenta a la que quieras transferir tus créditos.', 'TransferAmountLabel' => 'Cantidad de Créditos', 'TransferCharNameLabel' => 'Nombre de Personaje', 'TransferAmountInfo' => 'Se trata de la cantidad de créditos que deseas transferir.', 'TransferCharNameInfo' => 'Se trata del nombre del personaje que recibirá los créditos enviados.', 'TransferConfirm' => '¿Estás seguro de que quieres hacer la transferencia?', 'TransferButton' => 'Sí, transferir', 'TransferNoCredits' => 'No tienes créditos disponibles en tu cuenta.', // - account/view // * account/view submenus 'ModifyAccountLink' => 'Modificar Cuenta', 'AccountViewTitle' => 'Ver Cuenta', 'AccountViewTitle2' => 'Viendo Cuenta (%s)', 'AccountViewTitle3' => 'Viendo Mi Cuenta', 'AccountTempBanFailed' => 'No se pudo bloquear temporalmente la cuenta.', 'AccountPermBanFailed' => 'No se pudo bloquear permanentemente la cuenta.', 'AccountTempBanUnauth' => 'No estás autorizado para bloquear temporalmente a esta cuenta.', 'AccountPermBanUnauth' => 'No estás autorizado para bloquear permanentemente a esta cuenta.', 'AccountLiftTempBan' => 'Se ha desbloqueado el accedo de la cuenta.', 'AccountLiftPermBan' => 'Se ha desbloqueado el acceso de la cuenta.', 'AccountLiftBanUnauth' => "No estás autorizado para desbloquear el acceso de esta cuenta.", 'AccountViewHeading' => 'Viendo Cuenta', 'AccountViewDonateLink' => '(¡Donar!)', 'AccountViewTempBanLabel' => 'Bloquear Temporalmente', 'AccountViewPermBanLabel' => 'Bloquear Permanentemente', 'AccountViewUnbanLabel' => 'Desbloquear acceso', 'AccountBanReasonLabel' => 'Razón:', 'AccountBanUntilLabel' => 'Bloquear Hasta:', 'AccountTempBanButton' => 'Bloquear Cuenta', 'AccountPermBanButton' => 'Bloquear Cuenta Permanentemente', 'AccountTempUnbanButton' => 'Deshacer Bloqueo Temporal', 'AccountPermUnbanButton' => 'Deshacer Bloqueo Permanente', 'AccountBanConfirm' => '¿Estás seguro?', 'AccountBanLogSubHeading' => 'Registro de bloqueos de %s (más recientes primero)', 'BanLogBanTypeLabel' => 'Tipo de Bloqueo', 'BanLogBanDateLabel' => 'Fecha de Bloqueo', 'BanLogBanReasonLabel' => 'Razón del Bloqueo', 'BanLogBannedByLabel' => 'Bloqueado Por', 'BanLogBannedByCP' => 'Panel de Control', 'BanTypeUnbanned' => 'Sin Bloqueo', 'BanTypePermBanned' => 'Bloqueado Permanentemente', 'BanTypeTempBanned' => 'Bloqueado Temporalmente', 'AccountViewCharSubHead' => 'Personajes en %s', 'AccountViewSlotLabel' => 'Slot', 'AccountViewCharLabel' => 'Nombre de Personaje', 'AccountViewClassLabel' => 'Clase', 'AccountViewLvlLabel' => 'Nivel Base', 'AccountViewJlvlLabel' => 'Nivel Job', 'AccountViewZenyLabel' => 'Zeny', 'AccountViewGuildLabel' => 'Guild', 'AccountViewStatusLabel' => 'Estado', 'AccountViewPrefsLabel' => 'Preferencias', 'CharModifyPrefsLink' => 'Modificar Preferencias', 'AccountViewNoChars' => 'Esta cuenta no tiene personajes en %s.', 'AccountViewStorage' => 'Objetos en el Storage de %s', 'AccountViewStorageCount' => '%s tiene %s objeto(s) en su Storage.', 'AccountViewNoStorage' => 'No hay objetos en el Storage de esta cuenta.', 'AccountViewNotFound' => "La cuenta que estás intentando ver no existe.", // - account/xferlog 'XferLogTitle' => 'Historial de Transferencia de Crédito', 'XferLogHeading' => 'Historial de Transferencia de Crédito', 'XferLogReceivedSubHead' => 'Transferencias: Recibidas', 'XferLogSentSubHead' => 'Transferencias: Enviadas', 'XferLogCreditsLabel' => 'Créditos', 'XferLogFromLabel' => 'Correo Electrónico Remitente', 'XferLogDateLabel' => 'Fecha de Transferencia', 'XferLogCharNameLabel' => 'Para el Personaje', 'XferLogNotReceived' => 'No has recibido ninguna transferencia de crédito.', 'XferLogNotSent' => 'No has hecho ninguna transferencia de crédito.', // Module: character // - character/changeslot // - character/index // - character/mapstats // - character/online // - character/prefs // - character/resetlook 'CantResetLookWhenOnline' => 'No se puede restaurar la apariencia de %s mientras está conectado.', 'ResetLookSuccessful' => "¡Se ha restaurado la apariencia de %s!", 'ResetLookFailed' => "No se pudo restaurar la apariencia de %s.", // - character/resetpos 'CantResetPosWhenOnline' => 'No se puede restaurar la posición de %s mientras está conectado.', 'CantResetFromCurrentMap' => "No puedes restaurar la posición de %s en su mapa actual.", 'ResetPositionSuccessful' => "¡Se ha restaurado la posición de %s!", 'ResetPositionFailed' => "No se pudo restaurar la posición de %s.", // - character/view // - character/divorce 'DivorceTitle' => 'Divorciar', 'DivorceHeading' => 'Divorciar', 'DivorceNotMarried' => '%s no se encuentra casado.', 'DivorceInvalidPartner' => 'El ID del cónyuge no es válido.', 'DivorceInvalidChild' => 'El ID del hijo(a) no es válido.', 'DivorceMustBeOffline' => 'Tanto %s como el cónyuge deben estar desconectados.', 'DivorceMustBeOffline2' => '%s, su cónyuge y su hijo deben estar desconectados.', 'DivorceText1' => "¿Estás seguro de que deseas el divorcio entre %s y su cónyuge?", 'DivorceText2' => 'Si %s tiene un hijo, éste se volverá huérfano.', 'DivorceText3' => 'Además, sus Anillos de matrimonio serán eliminados.', 'DivorceButton' => 'Sí, hazlo por favor.', 'DivorceSuccessful' => '¡Se ha divorciado a %s!', // Module: cplog // - cplog/index.php // - cplog/login.php // - cplog/paypal.php // - cplog/resetpass.php // - cplog/txnview.php // Module: donate // - donate/complete // - donate/history // - donate/index // - donate/trusted // Module: errors // - errors/missing_action 'MissingActionTitle' => 'Acción Faltante', // Nociones de Programación Orientada a Objetos: Acción = "Página" 'MissingActionHeading' => 'Acción Faltante!', // Una acción es un conjunto de Vistas, cada elemento de la acción 'MissingActionModLabel' => 'Módulo:', 'MissingActionActLabel' => 'Acción:', 'MissingActionReqLabel' => 'URI de petición:', 'MissingActionLocLabel' => 'Localización en el sistema de archivos:', // - errors/missing_view 'MissingViewTitle' => 'Vista Faltante', 'MissingViewHeading' => 'Vista Faltante!', 'MissingViewModLabel' => 'Módulo:', 'MissingViewActLabel' => 'Acción:', 'MissingViewReqLabel' => 'URI de petición:', 'MissingViewLocLabel' => 'Localización en el sistema de archivos:', // Module: guild // - guild/export // - guild/index // - guild/view // Module: history // - history/cplogin 'HistoryCpLoginTitle' => 'Accesos al Panel de Control', 'HistoryCpLoginHeading' => 'Accesos al Panel de Control', 'HistoryLoginDateLabel' => 'Fecha/Hora de Acceso', 'HistoryIpAddrLabel' => 'Dirección IP', 'HistoryErrorCodeLabel' => 'Código de Error', 'HistoryNoCpLogins' => 'No se ha encontrado ningún intento de acceso al panel de control.', // -history/emailchange 'HistoryEmailTitle' => 'Cambios de Correo Electrónico', 'HistoryEmailHeading' => 'Cambios de Correo Electrónico', 'HistoryEmailRequestDate' => 'Fecha/Hora de la petición', 'HistoryEmailRequestIp' => 'IP de la petición', 'HistoryEmailOldAddress' => 'Correo Electrónico Antiguo', 'HistoryEmailNewAddress' => 'Correo Electrónico Nuevo', 'HistoryEmailChangeDate' => 'Fecha del Cambio', 'HistoryEmailChangeIp' => 'IP del Cambio', 'HistoryNoEmailChanges' => 'No se ha encontrado ningún intento de cambio de correo electrónico.', // - history/gamelogin 'HistoryGameLoginTitle' => 'Conexiones en el Juego', 'HistoryGameLoginHeading' => 'Conexiones en el Juego', 'HistoryRepsCodeLabel' => 'Código de Respuesta', 'HistoryLogMessageLabel' => 'Mensaje en el Registro', 'HistoryNoGameLogins' => 'No se ha encontrado ningún intento de conexión en el juego.', // - history/index 'HistoryIndexTitle' => 'Historial de Mi Cuenta', 'HistoryIndexHeading' => 'Historial de Mi Cuenta', 'HistoryIndexInfo' => 'Aquí puedes ver la actividad de tu cuenta en el pasado.', 'HistoryIndexInfo2' => 'Por favor, selecciona una acción en el menú.', // - history/passchange 'HistoryPassChangeTitle' => 'Cambios de Contraseña', 'HistoryPassChangeHeading' => 'Cambios de Contraseña', 'HistoryPassChangeChangeDate' => 'Fecha del Cambio', 'HistoryPassChangeChangeIp' => 'IP del Cambio', 'HistoryNoPassChanges' => 'No se ha encontrado ningún cambio de contraseña.', // -history/passreset 'HistoryPassResetTitle' => 'Recuperaciones de Contraseña', 'HistoryPassResetHeading' => 'Recuperaciones de Contraseña', 'HistoryPassResetRequestDate' => 'Fecha/Hora de la Petición', 'HistoryPassResetRequestIp' => 'IP de la Petición', 'HistoryPassResetResetDate' => 'Fecha de la Recuperación', 'HistoryPassResetResetIp' => 'IP de la Recuperación', 'HistoryNoPassResets' => 'No se ha encontrado ningún intento de recuperar la contraseña.', // Module: ipban // - ipban/add 'IpbanAddTitle' => 'Añadir Bloqueos de IP', 'IpbanEnterIpPattern' => 'Introduce una dirección o un rango de IP.', 'IpbanInvalidPattern' => 'La dirección o el rango de IP introducido no es válido/a.', 'IpbanWhitelistedPattern' => 'Este rango de IP está en la lista blanca, por lo que no puede ser bloqueado.', 'IpbanEnterReason' => 'Introduce una razón para el bloqueo.', 'IpbanSelectUnbanDate' => 'Se requiere una fecha de desbloqueo.', 'IpbanFutureDate' => 'La fecha de readmisión debe ser una fecha futura.', 'IpbanAlreadyBanned' => 'La IP (%s) ya está bloqueada.', 'IpbanPatternBanned' => "Se ha bloqueado la dirección o rango de IP '%s'.", 'IpbanAddFailed' => 'No se pudo añadir este bloqueo de IP.', 'IpbanAddHeading' => 'Añadir Bloqueos de IP', 'IpbanIpAddressLabel' => 'Dirección IP', 'IpbanReasonLabel' => 'Razón del Bloqueo', 'IpbanUnbanDateLabel' => 'Fecha de Desbloqueo', 'IpbanIpAddressInfo' => 'Puedes especificar un rango de IP, como por ejemplo 218.139.*.*', 'IpbanAddButton' => 'Añadir Bloqueos de IP', // - ipban/edit 'IpbanEditTitle' => 'Modificar Bloqueos de IP', 'IpbanEnterEditReason' => 'Introduce una razón para la modificación del bloqueo de IP.', 'IpbanEditFailed' => 'No se pudo modificar el bloqueo de IP.', 'IpbanEditHeading' => 'Modifcar Bloqueos de IP', 'IpbanEditReasonLabel' => 'Razón de la Edición', 'IpbanEditButton' => 'Modifcar Bloqueo de IP', // - ipban/index 'IpbanListTitle' => 'Lista de Bloqueos de IP', 'IpbanListHeading' => 'Lista de Bloqueos de IP', 'IpbanBannedIpLabel' => 'IP Bloqueada', 'IpbanBanDateLabel' => 'Fecha de Bloqueo', 'IpbanBanReasonLabel' => 'Razón de Bloqueo', 'IpbanBanExpireLabel' => 'Fecha de Expiración', 'IpbanModifyLink' => 'Modificar', 'IpbanRemoveLink' => 'Eliminar', 'IpbanUnbanButton' => 'Desbloquear Seleccionados', 'IpbanListNoBans' => 'En estos momentos no hay ningún bloqueo de IP.', // - ipban/remove 'IpbanRemoveTitle' => 'Deshacer Bloqueo de IP', 'IpbanEnterRemoveReason' => 'Introduce una razón para desbloquear esta IP o rango.', 'IpbanNotBanned' => 'La IP (%s) no está bloqueada.', 'IpbanPatternUnbanned' => "Se ha desbloqueado la IP o rango '%s'.", 'IpbanRemoveFailed' => 'No se pudo deshacer el bloqueo de IP.', 'IpbanRemoveHeading' => 'Deshacer Bloqueo de IP', 'IpbanRemoveReasonLabel' => 'Razón de Desbloqueo', 'IpbanRemoveButton' => 'Desbloquear IP o rango', // - ipban/unban 'IpbanNothingToUnban' => 'No hay nada que se pueda desbloquear.', 'IpbanEnterUnbanReason' => 'Introduce un motivo para desbloquear esta(s) IP.', 'IpbanUnbanned' => '¡Se ha(n) desbloqueado la(s) IP seleccionada(s)!', 'IpbanUnbanFailed' => '¡No se pudo/pudieron desbloquear %d IP especificada(s)!', // Module: item // - item/add // - item/copy // - item/edit // - item/index // - item/view // Module: itemshop // - itemshop/add // - itemshop/delete // - itemshop/edit // - itemshop/imagedel // Module: logdata // - logdata/chat // - logdata/command 'CommandLogTitle' => 'Lista de Comandos', 'CommandLogHeading' => 'Comandos Registrados', 'CommandLogNotFound' => 'No se ha registrado ningún comandos.', 'CommandLogDateLabel' => 'Fecha/Hora', 'CommandLogAccountIdLabel'=> 'ID de Cuenta', 'CommandLogCharIdLabel' => 'ID de Personaje', 'CommandLogCharNameLabel' => 'Nombre del Personaje', 'CommandLogCommandLabel' => 'Comando', 'CommandLogMapLabel' => 'Mapa', // - logdata/index // - logdata/login // - logdata/pick 'PickLogTitle' => 'Lista de Transacciones de Objetos', 'PickLogHeading' => 'Transacciones Registradas de Objetos', 'PickLogNotFound' => 'No se ha registrado ninguna transacción de objetos.', 'PickLogDateLabel' => 'Fecha/Hora', 'PickLogCharacterLabel' => 'Personaje', 'PickLogTypeLabel' => 'Tipo', 'PickLogItemLabel' => 'Nombre de Objeto', 'PickLogAmountLabel' => 'Cantidad', 'PickLogRefineLabel' => 'Refinado', 'PickLogCard0Label' => 'Carta 1', 'PickLogCard1Label' => 'Carta 2', 'PickLogCard2Label' => 'Carta 3', 'PickLogCard3Label' => 'Carta 4', 'PickLogMapLabel' => 'Mapa', // - logdata/zeny 'ZenyLogTitle' => 'Lista de Transacciones de Zeny', 'ZenyLogHeading' => 'Transacciones Registradas de Zeny', 'ZenyLogNotFound' => 'No se ha registrado ninguna transacción de zeny.', 'ZenyLogDateLabel' => 'Fecha/Hora', 'ZenyLogCharacterLabel' => 'Personaje', 'ZenyLogSourceLabel' => 'ID de Personaje', // No estoy seguro, tomado de la traducción portuguesa de JulioCF 'ZenyLogTypeLabel' => 'Tipo', 'ZenyLogAmountLabel' => 'Cantidad', 'ZenyLogMapLabel' => 'Mapa', // Module: mail // - mail/index 'MailerTitle' => 'Enviar Correo Electrónico', 'MailerHeading' => 'Enviar Correo Electrónico', 'MailerEnterToAddress' => 'Introduce el destinatario.', 'MailerEnterSubject' => 'Introduce el asunto.', 'MailerEnterBodyText' => 'Introduce el cuerpo del mensaje.', 'MailerEmailHasBeenSent' => 'Se ha enviado satisfactoriamente tu correo electrónico a %s.', 'MailerFailedToSend' => 'El sistema de envío de correo electrónico no pudo enviar este mensaje. Es posible que esto ocurra debido a un fallo en la configuración.', 'MailerInfo' => 'Utiliza el formulario de abajo para enviar un correo electrónico mediante el panel de control.', 'MailerFromLabel' => 'De', 'MailerToLabel' => 'Para', 'MailerSubjectLabel' => 'Asunto', 'MailerBodyLabel' => 'Cuerpo del mensaje', // Module: main // - main/index 'MainPageHeading' => 'Panel de Control Flux', 'MainPageInfo' => "Si puedes ver esta página, significa que has instalado Flux correctamente.", 'MainPageInfo2' => "¿Quieres cambiar esta página? Muy bien, puedes hacerlo así:", 'MainPageStep1' => 'Abre "%s" en un editor de texto.', 'MainPageStep2' => 'Edita el archivo desde el propio editor y guarda los cambios.', 'MainPageThanks' => '¡Gracias por usar Flux!', // - main/pagenotfound 'PageNotFoundTitle' => 'Error 404: Página No Encontrada.
:(', 'PageNotFoundHeading' => 'Página No Encontrada', 'PageNotFoundInfo' => 'No se ha encontrado la página que buscas en nuestro servidor. Verifica que la dirección es correcta e inténtalo de nuevo.', // - main/preprocess 'DisallowedDuringWoE' => 'No se puede acceder a la página que buscas en horario de WoE.', // Module: monster // - monster/index // - monster/view // Module: purchase // - purchase/add // - purchase/cart // - purchase/checkout // - purchase/clear // - purchase/index // - purchase/pending // - purchase/remove // Module: ranking // - ranking/character // - ranking/guild // - ranking/zeny // Module: server // - server/info 'ServerInfoTitle' => 'Información del Servidor', 'ServerInfoHeading' => 'Información del Servidor', 'ServerInfoText' => "Aquí puedes encontrar informaciones varias sobre el servidor.", 'ServerInfoSubHeading' => 'Información de %s', 'ServerInfoSubHeading2' => 'Información de Clases en %s', 'ServerInfoAccountLabel' => 'Cuentas', 'ServerInfoCharLabel' => 'Personajes', 'ServerInfoGuildLabel' => 'Guilds', 'ServerInfoPartyLabel' => 'Parties', 'ServerInfoZenyLabel' => 'Zeny', // - server/status 'ServerStatusTitle' => 'Estado Actual del Servidor', 'ServerStatusHeading' => 'Estado del Servidor', 'ServerStatusInfo' => "Entender el estado online u offline de cada servidor puede servirte de ayuda para entender cómo un fallo del servidor puede relacionarse con un problema que puedas tener. Por ejemplo, si el login server aparece offline, significa que no podrás conectarte al juego. El character server y el/los map server(s) son necesarios para el juego una vez te has conectado e identificado.", 'ServerStatusServerLabel' => 'Servidor', 'ServerStatusLoginLabel' => 'Login Server', 'ServerStatusCharLabel' => 'Character Server', 'ServerStatusMapLabel' => 'Map Server', 'ServerStatusOnlineLabel' => 'Jugadores Conectados', // Module: service // - service/tos 'TermsTitle' => 'Términos del Servicio', 'TermsHeading' => 'Términos del Servicio', 'TermsInfo' => '¡Por favor, léelos atentamente antes de crearte una cuenta!', 'TermsInfo2' => "PARA EL ADMINISTRADOR DEL PANEL DE CONTROL: Puedes añadir los Términos del Servicio de tu servidor directamente en este archivo. Su localización es: %s", // Module: unauthorized // - unauthorized/index 'UnauthorizedTitle' => 'No estás autorizado', 'UnauthorizedHeading' => 'No estás autorizado', 'UnauthorizedInfo' => 'No estás autorizado para ver esta página. Redireccionando…', // Module: woe // - woe/index 'WoeTitle' => 'Horario de WoE', 'WoeHeading' => 'Horario de War of Emperium', 'WoeInfo' => "Abajo se encuentra el horario de WoE en %s. Este horario está sujeto a cambios en cualquier momento, pero esperemos que no sea así.", 'WoeServerTimeInfo' => 'La hora actual del servidor es:', 'WoeServerLabel' => 'Servidores', 'WoeTimesLabel' => 'Horarios de War of Emperium', 'WoeNotScheduledInfo' => 'No se ha asignado ningún horario para WoE.', // Module: webcommands 'WCTitleLabel' => 'Web Commands', 'InvalidVIPTime' => 'Invalid VIP Time.', 'VIPTimeDateLabel' => 'VIP Until', 'VIPStateLabel' => 'VIP Status', 'CashLogTitle' => 'List CashPoints Log', 'CashLogHeading' => 'CashPoint Log', 'CashLogNotFound' => 'No cash logs found.', 'CashLogDateLabel' => 'Date/Time', 'CashLogCharacterLabel' => 'Character', 'CashLogTypeLabel' => 'Type', 'CashLogCashTypeLabel' => 'Cash Type', 'CashLogAmountLabel' => 'Amount', 'CashLogMapLabel' => 'Map', 'BranchLogTitle' => 'List Branch Log', 'BranchLogHeading' => 'Branch Log', 'BranchLogNotFound' => 'No branch logs found.', 'BranchLogIDLabel' => 'Branch Log ID', 'BranchLogDateLabel' => 'Date / Time', 'BranchLogAccountIDLabel' => 'Account ID', 'BranchLogCharIDLabel' => 'Char ID', 'BranchLogCharNameLabel' => 'Char Name', 'BranchLogMapLabel' => 'Map', 'CharLogTitle' => 'List Character Log', 'CharLogHeading' => 'Character Log', 'CharLogNotFound' => 'No character logs found.', 'CharLogDateLabel' => 'Date / Time', 'CharLogMsgLabel' => 'Action', 'CharLogAccountIDLabel' => 'Account ID', 'CharLogCharNumLabel' => 'Character slot', 'CharLogCharNameLabel' => 'Character Name', 'InterLogTitle' => 'List of Interactions Log', 'InterLogHeading' => 'Interactions Log', 'InterLogNotFound' => 'No Interactions logs found.', 'InterLogDateLabel' => 'Date / Time', 'InterLogLabel' => 'Interactions Log', 'MVPLogTitle' => 'List MVP Log', 'MVPLogHeading' => 'MVP Log', 'MVPLogNotFound' => 'No MVP logs found.', 'MVPLogIDLabel' => 'MVP Log ID', 'MVPLogDateLabel' => 'Date / Time', 'MVPLogCharacterLabel' => 'Character ID', 'MVPLogMonsterLabel' => 'MVP Monster', 'MVPLogPrizeLabel' => 'MVP Prize', 'MVPLogExpLabel' => 'MVP Experience', 'MVPLogMapLabel' => 'Map', 'NPCLogTitle' => 'List NPC Log', 'NPCLogHeading' => 'NPC Log', 'NPCLogNotFound' => 'No npc logs found.', 'NPCLogIDLabel' => 'NPC ID', 'NPCLogDateLabel' => 'Date / Time', 'NPCLogAccountIDLabel' => 'Account ID', 'NPCLogCharIDLabel' => 'Character ID', 'NPCLogCharNameLabel' => 'Character Name', 'NPCLogMapLabel' => 'Map', 'NPCLogMsgLabel' => 'Message', 'MailerSelectTemplateLabel' => 'Select Template', 'MainPageWelcome' => 'Welcome to %s!', 'ServerStatusPeakLabel' => 'Player Peak', 'CFTitleSubmit' => 'Contact Us', 'CMSNewsHeader' => 'Announcements', 'CMSPageHeader' => 'Content Management System', 'CMSPageText' => 'This module enables server admins and staff to create pages within their website with no prior flux/coding knowledge. The built-in news system can also be swapped out for an rss feed by modifying the application settings.', 'CMSNewsTitleError' => 'News title is required!', 'CMSNewsBodyError' => 'News body is required!', 'CMSPageTitleError' => 'Page Title is required!', 'CMSPageBodyError' => 'Page body is required!', 'CMSPagePathError' => 'Page path is required!', 'CMSNewsAdded' => 'News added to system', 'CMSPagesAdded' => 'Your new page has been added', 'CMSNewsUpdated' => 'News updated', 'CMSPageUpdated' => 'Your page has been updated', 'CMSNewsAddTitle' => 'Add a news item', 'CMSPageAddTitle' => 'Add a new page', 'CMSNewsEditTitle' => 'Edit news', 'CMSPageEditTitle' => 'Edit page', 'CMSNewsNotFound' => 'News not found!', 'CMSPageNotFound' => 'Page not found!', 'CMSNewsDeleted' => 'News deleted', 'CMSPageDeleted' => 'Your page has been deleted', 'CMSNewsEmpty' => 'No news articles have been found. Are you using the correct News Type? (CMSNewsType setting)', 'CMSNewsRSSNotFound' => "RSS feed can't be found. Make sure the CMSNewsRSS setting is correct, or switch CMSNewsType to 1 to use built-in news system!", 'CMSPageEmpty' => 'No page added', 'CMSNewsLink' => 'read more...', 'CMSEdit' => 'Edit', 'CMSDelete' => 'Delete', 'CMSNewsTitleLabel' => 'News Title', 'CMSNewsBodyLabel' => 'News Body', 'CMSNewsLinkLabel' => 'News Link', 'CMSNewsAuthorLabel' => 'News Author', 'CMSPageTitleLabel' => 'Page Title', 'CMSPageBodyLabel' => 'Page Body', 'CMSPagePathLabel' => 'Page Path', 'CMSCreatedLabel' => 'Date Created', 'CMSModifiedLabel' => 'Date Modified', 'CMSActionLabel' => 'Action', 'CMSConfirmDeleteLabel' => 'Are you sure you want to delete?', 'CMSPageCreate' => 'Create now?', 'CMSOptionalLabel' => '(Optional)', 'CMSRequiredLabel' => '(Required)', 'CMSCreateLabel' => 'Add News', 'TLHeaderTasks' => 'Tasks', 'TLHeaderOwner' => 'Owner', 'TLHeaderPriority' => 'Priority', 'TLHeaderStatus' => 'Status', 'TLHeaderCreated' => 'Created', 'TLHeaderModified' => 'Modified', 'TLHeaderResources' => 'Additional Resources', 'TLHeaderBody' => 'Body', 'SDHeader' => 'Service Desk', 'SDCreateNew' => 'Create a new ticket', 'SDWelcomeText' => 'Welcome to the Service Desk', 'SDNoTickets' => 'You have not created any tickets.', 'SDNoBlankResponse' => 'For a response to register, you must type something into the box!', 'SDNoCatsAvailable' => 'No Categories Available', 'SDNoOpenTickets' => 'There are no Open tickets in the database.', 'SDNoInactiveTickets' => 'You have no in-active tickets at the moment.', 'SDNoClosedTickets' => 'There are no Closed tickets in the database.', 'SDNoCats' => 'There are no categories within the database.', 'SDHuh' => 'You should not be here o.O', 'SDPointerChatLog' => 'We recommend pasting to pastebin.com then putting the link in here.', 'SDPointerScreenShot' => 'Provide image links as evidence', 'SDPointerVideoLink' => 'We recommend uploading to youtube then putting the link in here.', 'SDHeaderID' => 'Ticket #', 'SDHeaderSubject' => 'Subject', 'SDHeaderCategory' => 'Category', 'SDHeaderStatus' => 'Current Status', 'SDHeaderLastAuthor' => 'Last Author', 'SDHeaderTimestamp' => 'Created', 'SDHeaderAccount' => 'Account', 'SDHeaderTeam' => 'Team', 'SDH3ActiveTickets' => 'Active Tickets', 'SDH3InActiveTickets' => 'In-Active Tickets', 'SDH3ClosedTickets' => 'Closed Tickets', 'SDH3CurrentCat' => 'Current Categories', 'SDH3CreateCat' => 'Create New Category', 'SDH3StaffList' => 'Current Staff Settings', 'SDH3StaffCreate' => 'Add Staff Settings', 'SDReOpenPlayer' => 'Ticket Re-Opened by player', 'SDReOpenStaff' => '', 'SDRespTable1' => 'Respond and Return to Ticket', 'SDRespTable2' => 'Respond and Return to List', 'SDRespTable3' => 'Respond and Resolve Ticket', 'SDRespTable4' => 'Respond and Escalate', 'SDRespTable5' => 'Close Ticket', 'SDRespTable6' => 'Respond and Re-Open Ticket', 'SDRespTable7' => 'Resolve Ticket and Credit Account', 'SDGroup1' => 'Support Staff', 'SDGroup2' => 'Head of Support', 'SDGroup3' => 'Administration', 'SDLinkOpenNew' => 'Open a new ticket', ); ?> ================================================ FILE: lang/id_id.php ================================================ return array( // Generic/Misc. 'Language' => 'Indonesian', 'YesLabel' => 'Ya', 'NoLabel' => 'Tidak', 'NoteLabel' => 'Catatan', 'GenderTypeMale' => 'Pria', 'GenderTypeFemale' => 'Wanita', 'GenderTypeServer' => 'Server', 'RefreshSecurityCode' => 'Muat Ulang Kode Keamanan', 'NoneLabel' => 'Kosong', 'NeverLabel' => 'Jangan Pernah', 'NotApplicableLabel' => 'Tidak Dapat Digunakan', 'UnknownLabel' => 'Tidak Diketahui', 'IsEqualToLabel' => 'sama dengan', 'IsGreaterThanLabel' => 'lebih besar dari', 'IsLessThanLabel' => 'lebih kecil dari', 'AllLabel' => 'Semua', 'SearchLabel' => 'Cari…', 'GoBackLabel' => 'Kembali ke halaman sebelumnya…', 'SearchButton' => 'Cari', 'ResetButton' => 'Reset', 'FilterButton' => 'Penyaringan', 'NotAcceptingDonations' => "Kami mohon maaf, tapi saat ini kami sedang tidak menerima donasi. Maaf untuk ketidaknyamanannya.", //'NotAcceptingDonations' => "Kami mohon maaf, tapi sistem donasi kami saat ini sedang dalam perbaikan, mohon ulangi beberapa saat lagi.", 'FoundSearchResults' => 'Ditemukan. Total %d dari %d halaman. Menampilkan hasil %d-%d.', 'LoginToDonate' => 'Harap login untuk melakukan donasi.', 'UnknownCharacter' => 'Karakter tidak ditemukan.', 'AccountIdLabel' => 'ID Akun', 'AccountGroupIDLabel' => 'ID Grup', 'AccountStateLabel' => 'State', 'CreditBalanceLabel' => 'Saldo Kredit', 'UsernameLabel' => 'Nama Pengguna', 'PasswordLabel' => 'Sandi', 'EmailAddressLabel' => 'E-mail', 'GenderLabel' => 'Jenis Kelamin', 'LoginCountLabel' => 'Jumlah Login', //bukan "Jumlah". xD jumlah = sum(), itu count() :P 'LastLoginDateLabel' => 'Terakhir Login', 'LastUsedIpLabel' => 'IP Terakhir', 'AccountStateNormal' => 'Normal', 'AccountStatePending' => 'Pending', 'AccountStatePermBanned' => 'Ban Permanen', 'AccountStateTempBanLbl' => 'Ban Sementara', 'AccountStateTempBanned' => 'Ban Sementara (unban: %s)', 'OnlineLabel' => 'Online', 'OfflineLabel' => 'Offline', 'ItemIdLabel' => 'ID Barang', 'ItemNameLabel' => 'Nama Barang', 'ItemAmountLabel' => 'Jumlah', 'ItemIdentifyLabel' => 'Teridentifikasi', 'ItemRefineLabel' => 'Tempa', 'ItemBrokenLabel' => 'Rusak', 'ItemCard0Label' => 'Kartu 1', 'ItemCard1Label' => 'Kartu 2', 'ItemCard2Label' => 'Kartu 3', 'ItemCard3Label' => 'Kartu 4', //SIDEBAR //FluxCP Menu Items //Categories 'MainMenuLabel' => 'Menu Utama', 'ForumLabel' => 'Forum', 'AccountLabel' => 'Akun', 'CharacterLabel' => 'Character', 'ServiceDeskLabel' => 'Service Desk', 'CPLogsLabel' => 'CP Logs', 'FluxAdminLabel' => 'Flux Admin', 'PagesLabel' => 'Pages', 'IPBanListLabel' => 'IP Ban List', 'GuildsLabel' => 'Guilds', 'rALogsLabel' => 'rA Logs', 'SendMailLabel' => 'Send Mail', 'ReInstallLabel' => 'Re-Install', 'TaskListLabel' => 'Task List', 'DonationsLabel' => 'Donasi', 'InformationLabel' => 'Informasi', 'DatabaseLabel' => 'Database', 'SocialLabel' => 'Social', //SubMenus 'HomeLabel' => 'Beranda', 'NewsLabel' => 'Berita', 'DownloadsLabel' => 'Download', 'RulesLabel' => 'Peraturan', 'ContactUsLabel' => 'Hubungi Kami', 'MyAccountLabel' => 'Akun Saya', 'HistoryLabel' => 'History', 'ServiceDeskLabel' => 'Bantuan', 'PurchaseLabel' => 'Pembelian', 'DonateLabel' => 'Berikan Donasi', 'ServerInfoLabel' => 'Info Server', 'ServerStatusLabel' => 'Status Server', 'WoeHoursLabel' => 'Jadwal WOE', 'CastlesLabel' => 'Kastil', 'WhosOnlineLabel' => 'Pemain Online', 'MapStaticsLabel' => 'Informasi Map', 'RankingInfoLabel' => 'Informasi Peringkat', 'VendingInfoLabel' => 'Informasi Vending', 'ItemDatabaseLabel' => 'Database Barang', 'MobDatabaseLabel' => 'Database Monster', 'JoinUsInFacebookLabel' => 'Kunjungi kami di Facebook!', 'RateUsOnRMSLabel' => 'Kunjungi kami di RMS!', // Module: account // - account/changemail 'EmailChangeTitle' => 'Ubah E-mail', 'EnterEmailAddress' => 'Masukkan alamat e-mail.', 'EmailCannotBeSame' => 'E-mail baru Anda tidak boleh sama dengan yang ada saat ini.', 'EmailInvalid' => 'Alamat e-mail tidak diizinkan.', 'EmailAlreadyRegistered' => 'Alamat e-mail yang Anda masukkan sudah digunakan untuk akun lain', 'EmailChangeSent' => 'Sebuah e-mail telah dikirim ke alamat e-mail Anda yang baru dengan tautan yang akan mengkonfirmasi penggantian.', 'EmailAddressChanged' => 'Alamat e-mail Anda telah diubah!', 'EmailChangeFailed' => 'Gagal untuk mengubah alamat e-mail. Harap ulangi beberapa saat lagi.', 'EmailChangeHeading' => 'Ubah E-mail', 'EmailChangeInfo' => 'Jika Anda ingin mengubah alamat e-mail, Anda dapat mengisi formulir di bawah ini.', 'EmailChangeInfo2' => 'Setelah mengirim formulir, Anda akan diminta untuk mengkonfimasi alamat e-mail baru Anda (sebuah e-mail akan dikirimkan ke alamat e-mail baru berisi sebuah tautan).', 'EmailChangeLabel' => 'Alamat e-mail baru', 'EmailChangeInputNote' => 'Harus alamat e-mail yang benar!', 'EmailChangeButton' => 'Ubah alamat e-mail', // - account/changepass 'PasswordChangeTitle' => 'Ubah Sandi', 'NeedCurrentPassword' => 'Masukkan sandi yang digunakan.', 'NeedNewPassword' => 'Masukkan sandi baru.', 'OldPasswordInvalid' => 'Kata sandi yang Anda berikan tidak sesuai.', 'ConfirmNewPassword' => 'Konfirmasi kata sandi baru Anda.', 'NewPasswordHasUsername' => 'Tidak boleh ada nama pengguna di kata sandi yang baru.', 'NewPasswordInvalid' => 'Terdapat karakter yang tidak diizinkan di kata sandi yang baru.', 'NewPasswordSameAsOld' => 'Kata sandi yang baru tidak boleh sama dengan kata sandi yang ada saat ini.', 'NewPasswordNeedUpper' => 'Kata sandi yang baru harus menggunakan minimal %d huruf kapital.', 'NewPasswordNeedLower' => 'Kata sandi yang baru harus menggunakan minimal %d huruf kecil.', 'NewPasswordNeedNumber' => 'Kata sandi yang baru harus menggunakan minimal %d angka.', 'NewPasswordNeedSymbol' => 'Kata sandi yang baru harus menggunakan minimal %d simbol.', 'PasswordHasBeenChanged' => 'Kata sandi Anda telah diubah, silakan login kembali.', 'FailedToChangePassword' => 'Penggantian kata sandi tidak berhasil. Harap menghubungi admin.', 'PasswordChangeHeading' => 'Ubah Kata Sandi', 'PasswordChangeInfo' => 'Silakan masukkan kata sandi Anda, lalu masukkan kata sandi yang baru.', 'CurrentPasswordLabel' => 'Kata Sandi Saat Ini', 'NewPasswordLabel' => 'Kata Sandi Baru', 'NewPasswordConfirmLabel' => 'Konfirmasi Kata Sandi Baru', 'PasswordChangeNote' => 'Harap gunakan informasi yang benar.', 'PasswordChangeNote2' => 'Setelah mengganti kata sandi, Anda akan logout.', 'PasswordChangeButton' => 'Ganti Kata Sandi', // - account/changesex 'GenderChangeTitle' => 'Ubah Jenis Kelamin', //swt -_- 'GenderChangeBadChars' => 'Anda tidak dapat mengubah jenis kelamin jika ada karakter yang Anda miliki: %s', 'GenderChanged' => 'Jenis kelamin Anda telah diganti dan %d kredit telah dikurangi dari akun Anda.', 'GenderChangedForFree' => 'Jenis kelamin Anda telah diganti.', 'GenderChangeHeading' => 'Ubah Jenis Kelamin', 'GenderChangeCost' => 'Biaya penggantian jenis kelamin = %s kredit.', 'GenderChangeBalance' => 'Kredit yang Anda miliki = %s .', 'GenderChangeNoFunds' => 'Anda tidak memiliki kredit yang cukup untuk mengganti jenis kelamin.', 'GenderChangeNoCost' => 'Untuk Anda, gratis untuk mengganti jenis kelamin.', 'GenderChangeCharInfo' => 'Anda tidak dapat mengganti jenis kelamin jika Anda memiliki karakter dengan job: %s', 'GenderChangeSubHeading' => 'Yakinkan jika Anda ingin benar-benar mengganti!', 'GenderChangeFormText' => 'Akankah Anda mengganti jenis kelamin menjadi %s?', 'GenderChangeConfirm' => 'Apa Anda yakin untuk mengganti jenis kelamin Anda?', 'GenderChangeButton' => 'Ya.', // - account/confirm 'AccountConfirmTitle' => 'Konfirmasi akun', 'AccountConfirmUnban' => 'Akun telah dikonfirmasi dan diaktifkan.', 'AccountConfirmMessage' => 'Akun anda telah dikonfirmasi dan diaktifkan, Anda dipersilahkan untuk log-in.', // - account/confirmemail 'EmailConfirmTitle' => 'Konfirmasi E-mail', 'EmailConfirmFailed' => 'Terdapat masalah teknis ketika memperbaruhi alamat e-mail baru, harap hubungi admin.', 'EmailConfirmChanged' => 'Alamat e-mail Anda telah diganti!', // - account/create 'AccountCreateTitle' => 'Buat Akun', 'AccountConfirmBan' => 'Menunggu aktivasi akun: %s', 'AccountCreateEmailSent' => 'Sebuah e-mail telah dikirimkan dan berisi keterangan tentang detail akun Anda, harap periksa e-mail Anda untuk aktifasi.', 'AccountCreateFailed' => 'Akun Anda telah dibuat, tetapi kami gagal untuk mengirimkan e-mail kepada Anda. Harap hubungi admin untuk mendapatkan bantuan.', 'AccountCreated' => 'Selamat, Anda telah terdaftar dan login secara otomatis.', 'AccountCreateHeading' => 'Pendaftaran Akun Baru', 'AccountCreateTerms' => 'Syarat dan Ketentuan', 'AccountCreateInfo' => 'Anda diharapkan untuk membaca %s sebelum membuat akun baru, untuk memastikan bahwa Anda mengerti semua ketentuan yang berlaku di private server kami.', 'AccountCreateInfo2' => 'Dengan menekan tombol "Buat Akun Baru", Anda setuju untuk taat dan mengikuti %s kami.', 'AccountCreateGenderInfo' => "Jenis kelamin yang Anda pilih akan menentukan karakter Anda di dalam game!", 'AccountServerLabel' => 'Server', 'AccountUsernameLabel' => 'Nama Pengguna', 'AccountPasswordLabel' => 'Kata Sandi', 'AccountPassConfirmLabel' => 'Konfirmasi Kata Sandi', 'AccountEmailLabel' => 'Alamat E-mail', 'AccountEmailLabel2' => 'Konfirmasi alamat e-mail', 'AccountGenderLabel' => 'Jenis Kelamin', 'AccountBirthdateLabel' => 'Tanggal Lahir', 'AccountSecurityLabel' => 'Kode Keamanan', 'AccountCreateButton' => 'Buat Akun Baru', // "Create My Account?" bukan "new" ya? 'AccountInvalidChars' => "Nama pengguna hanya diperbolehkan menggunakan karakter: '%s'", 'InvalidLoginServer' => 'Login-server salah, ulangi lagi dengan memilih login-sevrer yang benar.', 'InvalidLoginCredentials' => 'Data login tidak sesuai, verifikasi data yang dimasukkan dan ulangi.', 'UnexpectedLoginError' => 'Terjadi kesalahan yang tidak diinginkan, ulangi beberapa saat lagi atau laporkan kepada admin.', 'CriticalLoginError' => 'Sesuatu yang buruk telah terjadi. Laporkan ke administartor SEGERA!', 'UsernameAlreadyTaken' => 'Nama pengguna yang Anda pilih sudah digunakan oleh orang lain', 'UsernameTooShort' => sprintf('Nama pengguna Anda harus %d sampai %d karakter.', Flux::config('MinUsernameLength'), Flux::config('MaxUsernameLength')), 'UsernameTooLong' => sprintf('Nama pengguna Anda harus %d sampai %d karakter.', Flux::config('MinUsernameLength'), Flux::config('MaxUsernameLength')), 'PasswordContainsUser' => 'Tidak boleh terdapat nama pengguna di kata sandi.', 'PasswordHasUsername' => 'Tidak boleh terdapat nama pengguna di kata sandi.', 'PasswordTooShort' => 'Kata sandi harus %d sampai %d karakter.', 'PasswordTooLong' => 'Kata sandi harus %d sampai %d karakter.', 'PasswordsDoNotMatch' => 'Kata sandi tidak cocok, harap masukkan kedua kata sandi dengan benar', 'PasswordNeedUpper' => 'Kata sandi harus memiliki huruf BESAR setidaknya %d huruf.', 'PasswordNeedLower' => 'Kata sandi harus memiliki huruf kecil setidaknya %d huruf.', 'PasswordNeedNumber' => 'Kata sandi harus memiliki angka setidaknya %d digit.', 'PasswordNeedSymbol' => 'Kata sandi harus memiliki simbol setidaknya %d simbol.', 'EmailAddressInUse' => 'Alamat e-mail yang Anda masukkan sudah digunakan oleh pengguna lain. Masukkan alamat e-mail yang lain', 'InvalidEmailAddress' => 'Alamat e-mail yang Anda masukkan memiliki format yang tidak diizinkan', 'InvalidEmailconf' => "Alamat e-mail Anda tidak cocok.", 'InvalidGender' => 'Jenis kelamin yang diperbolehkan adalah "M" atau "F"', 'InvalidServer' => "Server yang Anda pilih tidak tersedia.", 'InvalidSecurityCode' => 'Silakan masukkan kode keamanan dengan benar.', 'InvalidPassword' => 'Kata sandi Anda mengandung karakter yang tidak diperbolehkan.', 'InvalidBirthdate' => 'Tanggal lahir Anda tidak benar.', 'CriticalRegisterError' => 'Error. Harap hubungi admin secepatnya.', // - account/edit 'AccountEditTitle' => 'Ubah Akun', 'AccountEditTitle2' => 'Ubah Akun Saya', 'AccountEditTitle3' => 'Mengubah Akun (%s)', 'CannotModifyOwnGroupID' => 'Anda tidak bisa mengubah grup ID Anda sendiri.', 'CannotModifyAnyGroupID' => 'Anda tidak bisa mengubah grup ID.', 'CannotModifyGroupIDHigh' => 'Anda tidak bisa mengubah grup ID menjadi ID yang lebih tinggi dari akun Anda sendiri.', 'InvalidGroupID' => 'Grup ID salah.', 'CannotModifyBalance' => 'Anda tidak bisa mengubah jumlah kredit.', 'InvalidLastLoginDate' => 'Tanggal login terakhir salah.', 'InvalidVIPTime' => 'Waktu VIP salah.', 'AccountModified' => 'Akun telah berhasil diubah.', 'AccountEditHeading' => 'Ubah Akun', 'AccountEditButton' => 'Ubah Akun', 'AccountEditNotFound' => 'Akun tidak ditemukan.', 'VIPTimeDateLabel' => 'VIP Aktif Hingga', // - account/index 'AccountIndexTitle' => 'Daftar Akun', 'AccountIndexHeading' => 'Akun', 'LoginBetweenLabel' => 'Login di antara', 'BirthdateBetweenLabel' => 'Tanggal lahir di antara', 'AccountIndexNotFound' => 'Akun tidak ditemukan.', // - account/login 'LoginTitle' => 'Masuk Akun', 'LoginHeading' => 'Masuk Akun', 'LoginButton' => 'Masuk', 'LoginPageMakeAccount' => 'Belum punya akun? Daftarkan akun baru!', 'TemporarilyBanned' => 'Akun Anda telah diban untuk sementara.', 'PermanentlyBanned' => 'Akun Anda telah diban secara permanen.', 'IpBanned' => 'Alamat IP Anda telah diban.', 'PendingConfirmation' => 'Akun Anda masih menunggu aktivasi.', // - account/logout 'LogoutTitle' => 'Logout', 'LogoutHeading' => 'Logout', 'LogoutInfo' => 'Anda telah logged out.', 'LogoutInfo2' => 'Harap tunggu beberapa saat, halaman sedang dialihkan…', // - account/resend 'ResendTitle' => 'Kirim Ulang E-mail Konfirmasi', 'ResendEnterUsername' => 'Masukkan nama pengguna anda.', 'ResendEnterEmail' => 'Masukkan alamat e-mail.', 'ResendFailed' => 'Gagal mengirim ulang kode konfirmasi.', 'ResendEmailSent' => 'Kode konfirmasi anda telah dikirim ulang, silahkan cek e-mail dan ikuti langkah berikutnya untuk mengaktifkan akun.', 'ResendHeading' => 'Kirim Ulang E-mail Konfirmasi', 'ResendInfo' => 'Masukkan nama pengguna dan alamat e-mail yang digunakan ketika melakukan pendaftaran untuk pengiriman ulang e-mail konfirmasi', 'ResendServerLabel' => 'Server Terdaftar', 'ResendAccountLabel' => 'Nama Pengguna', 'ResendEmailLabel' => 'Alamat E-Mail', 'ResendServerInfo' => 'Server tempat akun didaftarkan.', 'ResendAccountInfo' => 'Nama pengguna yang didaftarkan.', 'ResendEmailInfo' => 'Alamat e-mail ini digunakan ketika Anda melakukan pendaftaran akun di atas.', 'ResendButton' => 'Kirim Ulang E-Mail Konfirmasi', // - account/resetpass 'ResetPassTitle' => 'Reset Kata Sandi', 'ResetPassEnterAccount' => 'Masukkan nama pengguna.', 'ResetPassEnterEmail' => 'Masukkan alamat e-mail.', 'ResetPassDisallowed' => 'Pemulihan kata sandi tidak dapat digunakan untuk akun ini.', 'ResetPassFailed' => 'Gagal untuk mengirim e-mail pemulihan akun.', 'ResetPassEmailSent' => 'E-mail berisi detail untuk menyetel ulang kata sandi sudah dikiriman.', 'ResetPassInfo' => 'Jika Anda lupa kata sandi, Anda dapat menyetel ulang dengan cara memasukkan alamat e-mail yang digunakan ketika mendaftarkan akun.', 'ResetPassInfo2' => 'Alamat e-mail harus benar untuk melakukan pengiriman sebuah e-mail ke alamat yang dicantumkan yang berisi tautan untuk menyetel ulang kata sandi akun Anda.', 'ResetPassServerLabel' => 'Server Terdaftar', 'ResetPassAccountLabel' => 'Nama Pengguna', 'ResetPassEmailLabel' => 'Alamat E-Mail', 'ResetPassServerInfo' => 'Server tempat akun didaftarkan.', 'ResetPassAccountInfo' => 'Nama pengguna yang didaftarkan.', 'ResetPassEmailInfo' => 'Alamat e-mail ini digunakan ketika Anda melakukan pendaftaran akun di atas.', 'ResetPassButton' => 'Kirim E-mail Penyetelan Ulang Kata Sandi', // - account/resetpw 'ResetPwTitle' => 'Reset Kata Sandi', 'ResetPwFailed' => 'Gagal untuk menyetel ulang kata sandi, ulangi beberapa saat lagi.', 'ResetPwDone' => 'Kata sandi telah disetel ulang. Sebuah e-mail berisi kata sandi baru telah dikirimkan, silahkan cek e-mail Anda.', 'ResetPwDone2' => 'Kata sandi sudah disetel ulang, tetapi e-mail yang berisi kata sandi baru gagal untuk dikirim. Silahkan ulangi menyetel ulang kata sandi.', // - account/transfer 'TransferTitle' => 'Transfer Kredit', 'TransferGreaterThanOne' => 'Anda harus mengirimkan jumlah kredit yang lebih besar dari 1.', 'TransferEnterCharName' => 'Anda harus mengisi nama karakter penerima kredit.', 'TransferNoCharExists' => "Karakter '%s' tidak ditemukan. Harap periksa kembali nama karakter tersebut.", 'TransferNoBalance' => 'Anda tidak memiliki jumlah kredit yang cukup untuk melakukan transfer.', 'TransferUnexpectedError' => 'Error! Harap hubungi admin.', 'TransferSuccessful' => 'Kredit telah dikirim!', 'TransferHeading' => 'Transfer Kredit', 'TransferSubHeading' => 'Kredit akan ditransfer kepada karakter di server %s .', 'TransferInfo' => 'Kredit sekarang %s .', 'TransferInfo2' => 'Masukkan jumlah yang ingin Anda transfer dan nama karakter yang berada di akun yang ingin Anda tuju.', 'TransferAmountLabel' => 'Jumlah Kredit', 'TransferCharNameLabel' => 'Nama Karakter', 'TransferAmountInfo' => 'Jumlah kredit yang akan Anda kirim.', 'TransferCharNameInfo' => 'Nama karakter penerima kredit.', 'TransferConfirm' => 'Apakah Anda yakin?', 'TransferButton' => 'Transfer', 'TransferNoCredits' => 'Anda tidak memiliki kredit di akun Anda.', // - account/view 'VIPStateLabel' => 'Status VIP', // * account/view submenus 'ModifyAccountLink' => 'Ubah Akun', 'AccountViewTitle' => 'Lihat Akun', 'AccountViewTitle2' => 'Sedang Melihat Akun (%s)', 'AccountViewTitle3' => 'Akun Saya', 'AccountTempBanFailed' => 'Gagal melakukan ban sementara pada akun.', 'AccountPermBanFailed' => 'Gagal melakukan ban permanen pada akun.', 'AccountTempBanUnauth' => 'Anda tidak dapat melakukan ban sementara pada akun ini.', 'AccountPermBanUnauth' => 'Anda tidak dapat melakukan ban permanen pada akun ini.', 'AccountLiftTempBan' => 'Ban sementara pada akun ini telah dibatalkan.', 'AccountLiftPermBan' => 'Ban permanen pada akun ini telah dibatalkan.', 'AccountLiftBanUnauth' => "Anda tidak dapat menghapus status ban pada akun ini.", 'AccountViewHeading' => 'Melihat Akun', 'AccountViewDonateLink' => '(Donasi!)', 'AccountViewTempBanLabel' => 'Ban Sementara', 'AccountViewPermBanLabel' => 'Ban Permanen', 'AccountViewUnbanLabel' => 'Hapus Ban', 'AccountBanReasonLabel' => 'Alasan:', 'AccountBanUntilLabel' => 'Ban Sampai:', 'AccountTempBanButton' => 'Ban Sementara', 'AccountPermBanButton' => 'Ban Permanen', 'AccountTempUnbanButton' => 'Hapus Ban Sementara', 'AccountPermUnbanButton' => 'Hapus Ban Permanen', 'AccountBanConfirm' => 'Apakah Anda yakin?', 'AccountBanLogSubHeading' => 'Catatan Ban Untuk %s (Baru ke Lama)', 'BanLogBanTypeLabel' => 'Jenis Ban', 'BanLogBanDateLabel' => 'Tanggal Ban', 'BanLogBanReasonLabel' => 'Alasan Ban', 'BanLogBannedByLabel' => 'Pemberi Ban', 'BanLogBannedByCP' => 'Control Panel', 'BanTypeUnbanned' => 'Tidak di Ban', 'BanTypePermBanned' => 'Ban Permanen', 'BanTypeTempBanned' => 'Ban Sementara', 'AccountViewCharSubHead' => 'Karakter Pada %s', 'AccountViewSlotLabel' => 'Slot', 'AccountViewCharLabel' => 'Nama Karakter', 'AccountViewClassLabel' => 'Job Class', 'AccountViewLvlLabel' => 'Base Level', 'AccountViewJlvlLabel' => 'Job Level', 'AccountViewZenyLabel' => 'Zeny', 'AccountViewGuildLabel' => 'Guild', 'AccountViewStatusLabel' => 'Status', 'AccountViewPrefsLabel' => 'Pengaturan', 'CharModifyPrefsLink' => 'Ubah Pengaturan', 'AccountViewNoChars' => 'Akun ini tidak memiliki karakter di %s.', 'AccountViewStorage' => 'Penyimpanan Barang Milik %s', 'AccountViewStorageCount' => '%s memiliki %s barang di penyimpanan.', 'AccountViewNoStorage' => 'Tidak ada apapun di dalam penyimpanan barang.', 'AccountViewNotFound' => "Akun yang Anda cari tidak ditemukan.", // - account/xferlog 'XferLogTitle' => 'Catatan Transfer Kredit', 'XferLogHeading' => 'Catatan Transfer Kredit', 'XferLogReceivedSubHead' => 'Transfer: Diterima', 'XferLogSentSubHead' => 'Transfer: Dikirim', 'XferLogCreditsLabel' => 'Kredit', 'XferLogFromLabel' => 'Dari E-mail', 'XferLogDateLabel' => 'Tanggal Transfer', 'XferLogCharNameLabel' => 'Untuk Karakter', 'XferLogNotReceived' => 'Anda tidak menerima pengiriman kredit.', 'XferLogNotSent' => 'Anda tidak mengirim pengiriman kredit.', // Module: character // - character/changeslot // - character/index // - character/mapstats // - character/online // - character/prefs // - character/resetlook 'CantResetLookWhenOnline' => 'Tidak dapat menyetel ulang penampilan %s ketika sedang online.', 'ResetLookSuccessful' => 'Penampilan %s telah disetel ulang!', 'ResetLookFailed' => 'Gagal untuk menyetel ulang penampilan %s.', // - character/resetpos 'CantResetPosWhenOnline' => 'Tidak dapat menyetel ulang posisi %s ketika sedang online.', 'CantResetFromCurrentMap' => 'Anda tidak dapat menyetel ulang posisi %s di map saat ini.', 'ResetPositionSuccessful' => 'Posisi %s telah disetel ulang!', 'ResetPositionFailed' => 'Gagal untuk menyetel ulang posisi %s.', // - character/view // - character/divorce 'DivorceTitle' => 'Bercerai', 'DivorceHeading' => 'Bercerai', 'DivorceNotMarried' => '%s belum menikah dengan siapapun.', 'DivorceInvalidPartner' => 'ID pasangan tidak ditemukan.', 'DivorceInvalidChild' => 'ID adopsi tidak ditemukan.', 'DivorceMustBeOffline' => '%s dan pasangannya harus dalam keadaan offline.', 'DivorceMustBeOffline2' => '%s, pasangan, dan anaknya harus dalam keadaan offline.', 'DivorceText1' => "Apakah Anda ingin menceraikan dengan %s dan pasangannya?", 'DivorceText2' => 'Apabila %s memiliki adopsi, status adopsi akan hilang.', 'DivorceText3' => "Item 'Wedding ring' akan dihapus.", 'DivorceButton' => 'Ya.', 'DivorceSuccessful' => '%s telah bercerai!', // Module: cplog // - cplog/index.php // - cplog/login.php // - cplog/paypal.php // - cplog/resetpass.php // - cplog/txnview.php // Module: donate // - donate/complete // - donate/history // - donate/index // - donate/trusted // Module: errors // - errors/missing_action 'MissingActionTitle' => 'Aksi Tidak Ditemukan', 'MissingActionHeading' => 'Aksi Tidak Ditemukan!', 'MissingActionModLabel' => 'Modul:', 'MissingActionActLabel' => 'Aksi:', 'MissingActionReqLabel' => 'URI Diminta:', 'MissingActionLocLabel' => 'Lokasi file:', // - errors/missing_view 'MissingViewTitle' => 'View Tidak Ditemukan', 'MissingViewHeading' => 'View Tidak Ditemukan!', 'MissingViewModLabel' => 'Modul:', 'MissingViewActLabel' => 'Aksi:', 'MissingViewReqLabel' => 'URI Diminta:', 'MissingViewLocLabel' => 'Lokasi file:', // Module: guild // - guild/export // - guild/index // - guild/view // Module: history // - history/cplogin 'HistoryCpLoginTitle' => 'Login Control Panel', 'HistoryCpLoginHeading' => 'Login Control Panel', 'HistoryLoginDateLabel' => 'Waktu/Tanggal Login', 'HistoryIpAddrLabel' => 'Alamat IP', 'HistoryErrorCodeLabel' => 'Error Code', 'HistoryNoCpLogins' => 'Tidak ada percobaan login ke Control Panel.', // -history/emailchange 'HistoryEmailTitle' => 'Perubahan E-Mail', 'HistoryEmailHeading' => 'Perubahan E-Mail', 'HistoryEmailRequestDate' => 'Waktu/Tanggal Permohonan', 'HistoryEmailRequestIp' => 'IP Pemohon', 'HistoryEmailOldAddress' => 'E-Mail Lama', 'HistoryEmailNewAddress' => 'E-Mail Baru', 'HistoryEmailChangeDate' => 'Tanggal Perubahan', 'HistoryEmailChangeIp' => 'IP Perubahan', 'HistoryNoEmailChanges' => 'Tidak ada percobaan perubahan e-mail.', // - history/gamelogin 'HistoryGameLoginTitle' => 'Masuk ke Game', 'HistoryGameLoginHeading' => 'Masuk ke Game', 'HistoryRepsCodeLabel' => 'Kode Respon', 'HistoryLogMessageLabel' => 'Catatan', 'HistoryNoGameLogins' => 'Tidak ada percobaan Masuk ke Game.', // - history/index 'HistoryIndexTitle' => 'Aktivitas Akun', 'HistoryIndexHeading' => 'Aktivitas Akun', 'HistoryIndexInfo' => 'Anda dapat melihat aktivitas yang telah lalu untuk akun Anda.', 'HistoryIndexInfo2' => 'Harap pilih aksi pada menu.', // - history/passchange 'HistoryPassChangeTitle' => 'Perubahan Kata Sandi', 'HistoryPassChangeHeading' => 'Perubahan Kata Sandi', 'HistoryPassChangeChangeDate' => 'Tanggal Perubahan', 'HistoryPassChangeChangeIp' => 'IP Perubahan', 'HistoryNoPassChanges' => 'Tidak ada perubahan kata sandi.', // -history/passreset 'HistoryPassResetTitle' => 'Penyetelan Ulang Kata Sandi', 'HistoryPassResetHeading' => 'Penyetelan Ulang Kata Sandi', 'HistoryPassResetRequestDate' => 'Tanggal Meminta', 'HistoryPassResetRequestIp' => 'IP Peminta', 'HistoryPassResetResetDate' => 'Tanggal Penyetelan', 'HistoryPassResetResetIp' => 'IP Penyetelan', 'HistoryNoPassResets' => 'Tidak ada percobaan merubah kata sandi.', // Module: ipban // - ipban/add 'IpbanAddTitle' => 'Tambah Ban IP', 'IpbanEnterIpPattern' => 'Harap masukkan alamat IP atau pola.', 'IpbanInvalidPattern' => 'Alamat IP atau pola tidak sesuai.', 'IpbanWhitelistedPattern' => 'Pola ini ada di whitelist dan tidak dapat diblokir.', 'IpbanEnterReason' => 'Harap masukkan alasan', 'IpbanSelectUnbanDate' => 'Tanggal unban dibutuhkan.', 'IpbanFutureDate' => 'Tanggal unban harus tanggal yang akan datang.', 'IpbanAlreadyBanned' => 'IP yang sesuai dengan (%s) telah diban.', 'IpbanPatternBanned' => "Pola/alamat IP '%s' telah diban.", 'IpbanAddFailed' => 'Gagal menambahkan IP yang diban.', 'IpbanAddHeading' => 'Tambahkan Ban IP', 'IpbanIpAddressLabel' => 'Alamat IP', 'IpbanReasonLabel' => 'Alasan Ban', 'IpbanUnbanDateLabel' => 'Tanggal Unban', 'IpbanIpAddressInfo' => 'Anda boleh memasukkan pola serperti 218.139.*.*', 'IpbanAddButton' => 'Tambahkan Ban IP', // - ipban/edit 'IpbanEditTitle' => 'Ubah Ban IP', 'IpbanEnterEditReason' => 'Harap masukkan alasan untuk perubahan ban IP', 'IpbanEditFailed' => 'Gagal untuk mengubah ban IP.', 'IpbanEditHeading' => 'Ubah Ban IP', 'IpbanEditReasonLabel' => 'Ubah Alasan', 'IpbanEditButton' => 'Modifikasi Ban IP', // - ipban/index 'IpbanListTitle' => 'Daftar Ban IP', 'IpbanListHeading' => 'Daftar Ban IP Ban', 'IpbanBannedIpLabel' => 'Banned IP', 'IpbanBanDateLabel' => 'Tanggal Ban', 'IpbanBanReasonLabel' => 'Alasan Ban', 'IpbanBanExpireLabel' => 'Tanggal Berakhir Ban', 'IpbanModifyLink' => 'Ubah', 'IpbanRemoveLink' => 'Hilangkan', 'IpbanUnbanButton' => 'Unban yang dipilih', 'IpbanListNoBans' => 'Tidak ada ban IP saat ini.', // - ipban/remove 'IpbanRemoveTitle' => 'Hilangkan Ban IP', 'IpbanEnterRemoveReason' => 'Harap masukkan alasan untuk penghilangan ban IP.', 'IpbanNotBanned' => 'IP (%s) tidak ditemukan.', 'IpbanPatternUnbanned' => "Pola/alamat IP '%s' telah di-unban.", 'IpbanRemoveFailed' => 'Gagal untuk menghilangkan ban IP.', 'IpbanRemoveHeading' => 'Hilangkan Ban IP', 'IpbanRemoveReasonLabel' => 'Alasan Unban', 'IpbanRemoveButton' => 'Hilangkan Ban IP', // - ipban/unban 'IpbanNothingToUnban' => 'Tidak ada yang di-unban.', 'IpbanEnterUnbanReason' => 'Harap masukkan alasan untuk pengangkatan ban IP.', 'IpbanUnbanned' => 'Ban IP telah dihilangkan!', 'IpbanUnbanFailed' => 'Gagal untuk menghilangkan %d ban IP!', // Module: item // - item/add // - item/copy // - item/edit // - item/index // - item/view // Module: itemshop // - itemshop/add // - itemshop/delete // - itemshop/edit // - itemshop/imagedel // Module: logdata // - logdata/chat // - logdata/cashpoints 'CashLogTitle' => 'Daftar Log CashPoints', 'CashLogHeading' => 'Log CashPoint', 'CashLogNotFound' => 'Tidak ada log CashPoint.', 'CashLogDateLabel' => 'Tanggal/Jam', 'CashLogCharacterLabel' => 'Karakter', 'CashLogTypeLabel' => 'Tipe', 'CashLogCashTypeLabel' => 'Tipe Cash', 'CashLogAmountLabel' => 'Jumlah', 'CashLogMapLabel' => 'Map', // - logdata/command 'CommandLogTitle' => 'Daftar Perintah', 'CommandLogHeading' => 'Perintah', 'CommandLogNotFound' => 'Perintah tidak ditemukan.', 'CommandLogDateLabel' => 'Tanggal/Jam', 'CommandLogAccountIdLabel'=> 'ID Akun', 'CommandLogCharIdLabel' => 'ID Karakter', 'CommandLogCharNameLabel' => 'Nama Karakter', 'CommandLogCommandLabel' => 'Perintah', 'CommandLogMapLabel' => 'Map', // - logdata/index // - logdata/login // - logdata/pick 'PickLogTitle' => 'Daftar Barang yang Diambil', 'PickLogHeading' => 'Barang Diambil', 'PickLogNotFound' => 'Tidak ada barang yang diambil.', 'PickLogDateLabel' => 'Tanggal/Jam', 'PickLogCharacterLabel' => 'Karakter', 'PickLogTypeLabel' => 'Tipe', 'PickLogItemLabel' => 'Nama Barang', 'PickLogAmountLabel' => 'Jumlah', 'PickLogRefineLabel' => 'Tempa', 'PickLogCard0Label' => 'Kartu 1', 'PickLogCard1Label' => 'Kartu 2', 'PickLogCard2Label' => 'Kartu 3', 'PickLogCard3Label' => 'Kartu 4', 'PickLogMapLabel' => 'Map', // - logdata/branch 'BranchLogTitle' => 'Daftar Branch', 'BranchLogHeading' => 'Branch Log', 'BranchLogNotFound' => 'Tidak ada log branch yang ditemukan.', 'BranchLogIDLabel' => 'ID Branch Log', 'BranchLogDateLabel' => 'Tanggal/Jam', 'BranchLogAccountIDLabel' => 'ID Akun', 'BranchLogCharIDLabel' => 'ID Karakter', 'BranchLogCharNameLabel' => 'Nama Karakter', 'BranchLogMapLabel' => 'Map', // - logdata/char 'CharLogTitle' => 'Dafatr Log Karakter', 'CharLogHeading' => 'Log Karakter', 'CharLogNotFound' => 'Tidak ada log karakter yang ditemukan.', 'CharLogDateLabel' => 'Tanggal/Jam', 'CharLogMsgLabel' => 'Aksi', 'CharLogAccountIDLabel' => 'ID Akun', 'CharLogCharNumLabel' => 'Slot karakter', 'CharLogCharNameLabel' => 'Nama Karakter', // - logdata/inter 'InterLogTitle' => 'Daftar Log Interaksi', 'InterLogHeading' => 'Log Interaksi', 'InterLogNotFound' => 'Tidak ada log interaksi yang diteukan.', 'InterLogDateLabel' => 'Tanggal/Jam', 'InterLogLabel' => 'Log Interaksi', // - logdata/mvp 'MVPLogTitle' => 'Daftar Log MVP', 'MVPLogHeading' => 'Log MVP', 'MVPLogNotFound' => 'Tidak ada log MVP yang ditemukan.', 'MVPLogIDLabel' => 'ID Log MVP', 'MVPLogDateLabel' => 'Tanggal/Jam', 'MVPLogCharacterLabel' => 'ID Karakter', 'MVPLogMonsterLabel' => 'Monster MVP', 'MVPLogPrizeLabel' => 'Hadiah MVP', 'MVPLogExpLabel' => 'Exp. MVP', 'MVPLogMapLabel' => 'Map', // - logdata/npc 'NPCLogTitle' => 'Daftar Log NPC', 'NPCLogHeading' => 'Log NPC', 'NPCLogNotFound' => 'Tidak ada log NPC yang ditemukan.', 'NPCLogIDLabel' => 'ID NPC', 'NPCLogDateLabel' => 'Tanggal/Jam', 'NPCLogAccountIDLabel' => 'ID Akun', 'NPCLogCharIDLabel' => 'ID Karakter', 'NPCLogCharNameLabel' => 'Nama Karakter', 'NPCLogMapLabel' => 'Map', 'NPCLogMsgLabel' => 'Pesan', // - logdata/zeny 'ZenyLogTitle' => 'Dafatr Log Zeny', 'ZenyLogHeading' => 'Log Zeny', 'ZenyLogNotFound' => 'Tidak ada log Zeny yang ditenukan.', 'ZenyLogDateLabel' => 'Tanggal/Jam', 'ZenyLogCharacterLabel' => 'Karakter', 'ZenyLogSourceLabel' => 'Sumber', 'ZenyLogTypeLabel' => 'Tipe', 'ZenyLogAmountLabel' => 'Jumlah', 'ZenyLogMapLabel' => 'Map', // Module: mail // - mail/index 'MailerTitle' => 'Formulir Pesan (Form Mailer)', 'MailerHeading' => 'Formulir Pesan', 'MailerEnterToAddress' => 'Harap masukkan alamat tujuan.', 'MailerEnterSubject' => 'Harap masukkan judul.', 'MailerEnterBodyText' => 'Harap masukkan beberapa isi pesan.', 'MailerEmailHasBeenSent' => 'E-mail anda telah sukses dikirim ke %s.', 'MailerFailedToSend' => 'Sistem pengiriman pesan gagal untuk mengirim e-mail. Mungkin terjadi karena kesalahan konfigurasi.', 'MailerInfo' => 'Anda diperbolehkan menggunakan formulir pesan di bawah ini untuk mengirimkan e-mail menggunakan control panel.', 'MailerFromLabel' => 'Dari', 'MailerToLabel' => 'Tujuan', 'MailerSubjectLabel' => 'Judul', 'MailerBodyLabel' => 'isi', 'MailerSelectTemplateLabel' => 'Pilih Template', // Module: main // - main/index 'MainPageHeading' => 'Flux Control Panel', 'MainPageInfo' => 'Jika Anda melihat halaman ini, berarti Flux telah berhasil diinstal.', 'MainPageInfo2' => 'Yakin untuk mengubah halaman ini?', 'MainPageStep1' => 'Membuka "%s" di teks editor.', 'MainPageStep2' => 'Ubah file dari editor dan simpan perubahan.', 'MainPageThanks' => 'Terima kasih telah menggunakan Flux!', 'MainPageWelcome' => 'Selamat datang di %s!', // - main/pagenotfound 'PageNotFoundTitle' => '404 Page Not Found', 'PageNotFoundHeading' => 'Halaman Tidak Ditemukan', 'PageNotFoundInfo' => 'Halaman yang diminta tidak ditemukan. Harap periksa kembali alamat yang dimasukkan.', // - main/preprocess 'DisallowedDuringWoE' => 'Halaman yang diminta tidak dapat diakses ketika WoE.', // Module: monster // - monster/index // - monster/view // Module: purchase // - purchase/add // - purchase/cart // - purchase/checkout // - purchase/clear // - purchase/index // - purchase/pending // - purchase/remove // Module: ranking // - ranking/character // - ranking/guild // - ranking/zeny // Module: server // - server/info 'ServerInfoTitle' => 'Informasi Server', 'ServerInfoHeading' => 'Informasi Server', 'ServerInfoText' => 'Di sini Anda akan menemukan berbagai informasi tentang server.', 'ServerInfoSubHeading' => 'Informasi untuk %s', 'ServerInfoSubHeading2' => 'Informasi Class untuk %s', 'ServerInfoAccountLabel' => 'Akun', 'ServerInfoCharLabel' => 'Karakter', 'ServerInfoGuildLabel' => 'Guild', 'ServerInfoPartyLabel' => 'Parties', 'ServerInfoZenyLabel' => 'Zeny', // - server/status 'ServerStatusTitle' => 'Status Server Saat Ini', 'ServerStatusHeading' => 'Status Server', 'ServerStatusInfo' => "Berikut ini adalah status dari tiap server.", 'ServerStatusServerLabel' => 'Server', 'ServerStatusLoginLabel' => 'Login Server', 'ServerStatusCharLabel' => 'Character Server', 'ServerStatusMapLabel' => 'Map Server', 'ServerStatusOnlineLabel' => 'Pemain Online', 'ServerStatusPeakLabel' => 'Pemain Terbanyak', // Module: service // - service/tos 'TermsTitle' => 'Syarat dan Ketentuan', 'TermsHeading' => 'Syarat dan Ketentuan', 'TermsInfo' => 'Harap dibaca sebelum Anda membuat akun!', 'TermsInfo2' => "FOR CONTROL PANEL ADMINISTRATOR: Anda harus menambahkan server ToS pada tampilan ini secara langsung. Lokasi dari file ini adalah: %s", // Module: unauthorized // - unauthorized/index 'UnauthorizedTitle' => 'Tidak Diperbolehkan', 'UnauthorizedHeading' => 'Tidak Diperbolehkan', 'UnauthorizedInfo' => 'Anda tidak diperbolehkan untuk melihat halaman ini. Kembali ke sebelumnya…', // Module: woe // - woe/index 'WoeTitle' => 'Jadwal WoE', 'WoeHeading' => 'Jadwal War of Emperium', 'WoeInfo' => 'Di bawah ini adalah jadwal WoE untuk %d. Jadwal berikut mungkin bisa berubah sewaktu-waktu.', 'WoeServerTimeInfo' => 'Waktu server saat ini adalah:', 'WoeServerLabel' => 'Server', 'WoeTimesLabel' => 'Jadwal War of Emperium', 'WoeNotScheduledInfo' => 'Tidak ada jadwal WoE saat ini.', // Module: contactform 'CFTitleSubmit' => 'Hubungi Kami', // Module: News and Pages 'CMSNewsHeader' => 'Pengumuman', 'CMSPageHeader' => 'Content Management System', 'CMSPageText' => 'Modul ini mengizinkan admin dan staff untuk membuat halaman pada website tanpa perlu pengetahuan tentang Flux/pemrograman. Sistem berita internal juga dapat ekspor untuk RSS Feed dengan mengubah pengaturan aplikasi.', 'CMSNewsTitleError' => 'Judul Berita harus diisi!', 'CMSNewsBodyError' => 'Isi Berita harus diisi!', 'CMSPageTitleError' => 'Judul Halaman harus diisi!', 'CMSPageBodyError' => 'Isi Halaman harus diisi!', 'CMSPagePathError' => 'Lokasi Halaman harus diisi!', 'CMSNewsAdded' => 'Berita telah ditambahkan', 'CMSPagesAdded' => 'Halaman telah ditambahkan', 'CMSNewsUpdated' => 'Berita telah diperbaruhi', 'CMSPageUpdated' => 'Halaman telah diperbaruhi', 'CMSNewsAddTitle' => 'Menambahkan isi beritaAdd a news item', 'CMSPageAddTitle' => 'Membuat halaman baru', 'CMSNewsEditTitle' => 'Mengubah berita', 'CMSPageEditTitle' => 'Mengubah halaman', 'CMSNewsNotFound' => 'Berita tidak ditemukan!', 'CMSPageNotFound' => 'Halaman tidak ditemukan!', 'CMSNewsDeleted' => 'Berita telah dihapus', 'CMSPageDeleted' => 'Halamna telah dihapus', 'CMSNewsEmpty' => 'Tidak ada bertia yang ditemukan. Cek kembali Tipe Berita di pengaturan? (pengaturan CMSNewsType)', 'CMSNewsRSSNotFound' => "RSS feed tidak dapat ditemukan. Cek kembali pengaturan CMSNewsRSS, atau ganti tipe CMSNewsType menjadi 1 untuk menggunakan sistem berita internal!", 'CMSPageEmpty' => 'Tidak ada halaman', 'CMSNewsLink' => 'baca selengkapnya...', 'CMSEdit' => 'Perbaruhi', 'CMSDelete' => 'Hapus', 'CMSNewsTitleLabel' => 'Judul Berita', 'CMSNewsBodyLabel' => 'Isi Berita', 'CMSNewsLinkLabel' => 'Tautan Berita', 'CMSNewsAuthorLabel' => 'Penulis Berita', 'CMSPageTitleLabel' => 'Judul Halaman', 'CMSPageBodyLabel' => 'Isi Halaman', 'CMSPagePathLabel' => 'Lokasi Halaman', 'CMSCreatedLabel' => 'Tanggal Pembuatan', 'CMSModifiedLabel' => 'Tanggal Diperbaruhi', 'CMSActionLabel' => 'Tindakan', 'CMSConfirmDeleteLabel' => 'Apakah yakin untuk menghapus?', 'CMSPageCreate' => 'Apakah yakin membuat halaman?', 'CMSOptionalLabel' => '(Opsional)', 'CMSRequiredLabel' => '(Harus Diisi)', 'CMSCreateLabel' => 'Buat Berita Baru', // Module: vending 'TLHeaderTasks' => 'Tugas', 'TLHeaderOwner' => 'Pemilik', 'TLHeaderPriority' => 'Prioritas', 'TLHeaderStatus' => 'Status', 'TLHeaderCreated' => 'Dibuat', 'TLHeaderModified' => 'Diubah', 'TLHeaderResources' => 'Bahan Tambahan', 'TLHeaderBody' => 'Isi', // Module: servicedesk 'SDHeader' => 'Layanan Bantuan', 'SDCreateNew' => 'Kirim Laporan', 'SDWelcomeText' => 'Selamat datang di Layanan Bantuan', 'SDNoTickets' => 'Anda tidak memiliki laporan apapun.', 'SDNoBlankResponse' => 'Anda harus mengisi data ke dalam formulir!', 'SDNoCatsAvailable' => 'Tidak ada kategori yang tersedia', 'SDNoOpenTickets' => 'Tidak ada laporan di database.', 'SDNoInactiveTickets' => "Tidak ada laporan yang 'tidak aktif' di database.", 'SDNoClosedTickets' => "Tidak ada laporan yang 'ditutup' di database.", 'SDNoCats' => 'Tidak ada kategori di database.', 'SDHuh' => 'Error', 'SDPointerChatLog' => 'Kami sarankan untuk menggunakan pastebin.com lalu kirimkan tautannya pada kami.', 'SDPointerScreenShot' => 'Kirimkan juga tautan dari gambar atau screenshot yang Anda punya', 'SDPointerVideoLink' => 'Kami sarankan untuk mengunggah video Anda ke YouTube, lalu kirimkan tautannya pada kami.', 'SDHeaderID' => 'Laporan #', 'SDHeaderSubject' => 'Subjek', 'SDHeaderCategory' => 'Kategori', 'SDHeaderStatus' => 'Status', 'SDHeaderLastAuthor' => 'Penulis Terakhir', 'SDHeaderTimestamp' => 'Dibuat', 'SDHeaderAccount' => 'Akun', 'SDHeaderTeam' => 'Tim', 'SDH3ActiveTickets' => 'Laporan Aktif', 'SDH3InActiveTickets' => 'Laporan Tidak Aktif', 'SDH3ClosedTickets' => 'Laporan Ditutup', 'SDH3CurrentCat' => 'Kategori', 'SDH3CreateCat' => 'Buat Kategori Baru', 'SDH3StaffList' => 'Pengaturan Staf', 'SDH3StaffCreate' => 'Tambah Staf', 'SDReOpenPlayer' => 'Laporan diaktifkan kembali oleh pemain', 'SDReOpenStaff' => '', 'SDRespTable1' => 'Balas dan Kembali ke Laporan', 'SDRespTable2' => 'Balas dan Kembali ke Daftar Laporan', 'SDRespTable3' => 'Balas dan Tutup Laporan', 'SDRespTable4' => 'Balas dan Tingkatkan Status', 'SDRespTable5' => 'Tutup Laporan', 'SDRespTable6' => 'Balas dan Aktifkan Laporan', 'SDRespTable7' => 'Resolve Ticket dan Credit Account', 'SDGroup1' => 'Staf Layanan Bantuan', 'SDGroup2' => 'Kepala Staf Layanan Bantuan', 'SDGroup3' => 'Administrasi', 'SDLinkOpenNew' => 'Buat laporan baru', // Module: webcommands 'WCTitleLabel' => 'Web Commands', ); ?> ================================================ FILE: lang/pt_br.php ================================================ 'Portuguese', 'YesLabel' => 'Sim', 'NoLabel' => 'Não', 'NoteLabel' => 'Nota', 'GenderTypeMale' => 'Masculino', 'GenderTypeFemale' => 'Feminino', 'GenderTypeServer' => 'Servidor', 'RefreshSecurityCode' => 'Atualizar Código de Segurança', 'NoneLabel' => 'Nada', 'NeverLabel' => 'Nunca', 'NotApplicableLabel' => 'Não Aplicável', 'UnknownLabel' => 'Desconhecido', 'IsEqualToLabel' => 'é igual a', 'IsGreaterThanLabel' => 'é maior que', 'IsLessThanLabel' => 'é menor que', 'AllLabel' => 'Tudo', 'SearchLabel' => 'Procurar…', 'GoBackLabel' => 'Voltar à página anterior…', 'SearchButton' => 'Procurar', 'ResetButton' => 'Resetar', 'FilterButton' => 'Filtrar', 'NotAcceptingDonations' => "Desculpe, mas nós não estamos aceitando doações no momento. Desculpas pela inconveniência.", //'NotAcceptingDonations' => "We're sorry, but our donation system is currently undergoing maintenance, please try again later.", 'FoundSearchResults' => 'Encontrado um total de %d registro(s) em %d páginas(s). Mostrando %d-%d.', 'LoginToDonate' => 'Por favor, faça login para poder doar.', 'UnknownCharacter' => 'Nenhum personagem encontrado.', 'AccountIdLabel' => 'ID da Conta', 'AccountGroupIDLabel' => 'Level do Grupo', 'AccountStateLabel' => 'Status da Conta', 'CreditBalanceLabel' => 'Balanço de Crédito', 'UsernameLabel' => 'Usuário', 'PasswordLabel' => 'Senha', 'EmailAddressLabel' => 'E-mail', 'GenderLabel' => 'Gênero', 'LoginCountLabel' => 'Contagem de Login', 'LastLoginDateLabel' => 'Data do último Login', 'LastUsedIpLabel' => 'Último IP registrado', 'AccountStateNormal' => 'Normal', 'AccountStatePending' => 'Pendente', 'AccountStatePermBanned' => 'Banido Permanentemente', 'AccountStateTempBanLbl' => 'Banido Temporariamente', 'AccountStateTempBanned' => 'Banido Temp. (Desbanir: %s)', 'OnlineLabel' => 'Online', 'OfflineLabel' => 'Offline', 'ItemIdLabel' => 'ID do Item', 'ItemNameLabel' => 'Nome do Item', 'ItemAmountLabel' => 'Quantidade', 'ItemIdentifyLabel' => 'Identificado', 'ItemRefineLabel' => 'Refinado', 'ItemBrokenLabel' => 'Quebrado', 'ItemCard0Label' => 'Carta 1', 'ItemCard1Label' => 'Carta 2', 'ItemCard2Label' => 'Carta 3', 'ItemCard3Label' => 'Carta 4', // Security 'SecuritySessionInvalid' => 'Desculpe, a sessão expirou, tente novamente.', 'SecurityNeedSession' => 'Desculpe, nenhuma sessão foi encontrada (tentativa de hack?)', 'SecurityNeedToken' => 'Desculpe, nenhum sinal encontrado para identificar esta forma (tentativa de hack?)', // Module: account // - account/changemail 'EmailChangeTitle' => 'Alterar E-mail', 'EnterEmailAddress' => 'Insira um E-mail.', 'EmailCannotBeSame' => 'Seu novo e-mail não pode ser igual ao atual.', 'EmailInvalid' => 'Endereço de e-mail inválido.', 'EmailAlreadyRegistered' => "Esse e-mail já está registrado para outra conta, insira outro.", 'EmailChangeSent' => 'Uma mensagem foi enviada para o seu novo email com um link para confirmar a alteração.', 'EmailAddressChanged' => 'Seu e-mail foi alterado com sucesso!', 'EmailChangeFailed' => 'Falha ao alterar e-mail. Tente novamente mais tarde.', 'EmailChangeHeading' => 'Alterar E-mail', 'EmailChangeInfo' => 'Se você quer alterar o e-mail cadastrado na sua conta, preencha o formulário abaixo.', 'EmailChangeInfo2' => 'Depois de enviar o formulário, você receberá uma mensagem no seu novo email contendo um link para você confirmar a sua alteração.', 'EmailChangeLabel' => 'Novo E-mail', 'EmailChangeInputNote' => 'Deve ser um e-mail válido!', 'EmailChangeButton' => 'Alterar E-mail', // - account/changepass 'PasswordChangeTitle' => 'Alterar Senha', 'NeedCurrentPassword' => 'Insira a sua senha atual.', 'NeedNewPassword' => 'Insira a sua nova senha.', 'OldPasswordInvalid' => "A senha que você digitou não bate com a sua senha real.", 'ConfirmNewPassword' => 'Confirme sua nova senha.', 'NewPasswordHasUsername' => 'Sua nova senha não deve conter seu nome de usuário..', 'NewPasswordInvalid' => 'Senha alterada com sucesso, favor faça login novamente.', 'NewPasswordSameAsOld' => 'Nova senha não pode ser a mesma que sua senha atual.', 'NewPasswordNeedUpper' => 'Sua nova senha deve conter pelo menos %d letra(s) maiúsculas.', 'NewPasswordNeedLower' => 'Sua nova senha deve conter pelo menos %d letra(s) minúsculas.', 'NewPasswordNeedNumber' => 'Sua nova senha deve conter pelo menos %d número(s).', 'NewPasswordNeedSymbol' => 'Sua nova senha deve conter pelo menos %d símbolo (s).', 'PasswordHasBeenChanged' => 'Sua senha foi alterada, por favor, faça log-in novamente.', 'FailedToChangePassword' => 'Falha ao alterar sua senha. Por favor, contate um administrador.', 'PasswordChangeHeading' => 'Alterar sua Senha', 'PasswordChangeInfo' => 'Por favor, digite sua senha atual e, em seguida, digite a nova senha que deseja usar e digite novamente para confirmar.', 'CurrentPasswordLabel' => 'Senha Atual', 'NewPasswordLabel' => 'Nova Senha', 'NewPasswordConfirmLabel' => 'Re-digite a nova senha', 'PasswordChangeNote' => 'Por favor, certifique-se de digitar as informações corretas.', 'PasswordChangeNote2' => 'Após alterar sua senha, você será registrado.', 'PasswordChangeButton' => 'Alterar Senha', // - account/changesex 'GenderChangeTitle' => 'Alterar Gênero', 'GenderChangeBadChars' => 'Você não pode trocar de gênero se algum dos seus personagens é um %s', 'GenderChanged' => 'Seu gênero foi alterado com sucesso e $d créditos foram debitados sua conta.', 'GenderChangedForFree' => 'Gênero alterado com sucesso.', 'GenderChangeHeading' => 'Altere Seu Gênero', 'GenderChangeCost' => 'Mudança de Gênero vai custar %s créditos para você.', 'GenderChangeBalance' => 'Você possui atualmente %s créditos.', 'GenderChangeNoFunds' => 'Você não possui créditos suficiente para completar a sua troca de gênero.', 'GenderChangeNoCost' => 'Para você, as mudanças de sexo são livres.', 'GenderChangeCharInfo' => 'Você não pode alterar seu gênero se você tiver um personagem que for um: %s', 'GenderChangeSubHeading' => 'Tenha certeza que você quer realmente alterar!', 'GenderChangeFormText' => 'Você deseja mudar seu gênero para %s?', 'GenderChangeConfirm' => 'Você tem certeza que quer alterar seu gênero?', 'GenderChangeButton' => 'Sim, por favor.', // - account/confirm 'AccountConfirmTitle' => 'Confirmar Conta', 'AccountConfirmUnban' => 'A conta foi confirmada e ativada.', 'AccountConfirmMessage' => 'Sua conta foi confirmada e ativada, agora você pode fazer login.', // - account/confirmemail 'EmailConfirmTitle' => 'Confirmar E-mail', 'EmailConfirmFailed' => 'Tivemos um problema técnico durante sua alteração de email, por favor entre em contato com algum Administrador.', 'EmailConfirmChanged' => 'Seu e-mail foi alterado com sucesso!', // - account/create 'AccountCreateTitle' => 'Criar Uma Conta', 'AccountConfirmBan' => 'Esperando ativação da conta: %s', 'AccountCreateEmailSent' => 'Um e-mail foi enviado contendo as informações de ativação da conta, por favor, cheque seu email e ative a sua conta para poder fazer login.', 'AccountCreateFailed' => 'Sua conta foi criada, mas infelizmente houve uma falha ao lhe enviar o email de confirmação devido a problemas técnicos. Por favor, procure algum GM ou Administrador para resolver o seu problema.', 'AccountCreated' => 'Parabéns! Você foi registrado com sucesso e você já está logado!', 'AccountCreateHeading' => 'Registrar', 'AccountCreateTerms' => 'Termos de Serviço', 'AccountCreateInfo' => 'Por favor, leia os nossos %s antes de criar uma conta, tenha certeza que você entendeu as regras para poder ter uma conta no nosso servidor.', 'AccountCreateInfo2' => 'Clicando em "Criar Minha Conta", você estará concordando com os nossos %s.', 'AccountCreateGenderInfo' => "O gênero que você escolheu irá afetar o gênero do seu personagem in-game!", 'AccountServerLabel' => 'Servidor', 'AccountUsernameLabel' => 'Seu Usuário', 'AccountPasswordLabel' => 'Sua Senha', 'AccountPassConfirmLabel' => 'Confirmar Senha', 'AccountEmailLabel' => 'E-mail', 'AccountGenderLabel' => 'Gênero', 'AccountBirthdateLabel' => 'Data de nascimento', 'AccountSecurityLabel' => 'Código de Segurança', 'AccountCreateButton' => 'Criar Minha Conta', 'AccountInvalidChars' => "Um nome de usuário pode conter somente estes caracteres: ' %s'", 'AccountRecaptchaKey' => 'Você precisa das chaves de Recaptcha, veja mais em config/applications.php (ReCaptchaPublicKey/ReCaptchaPrivateKey)', 'InvalidLoginServer' => 'Login inválido para servidor selecionado, por favor, tente novamente com um servidor válido.', 'InvalidLoginCredentials' => 'Login inválido credenciais, verifique se você digitou as informações corretas e tente novamente.', 'UnexpectedLoginError' => 'Ocorreu um erro inesperado, tente novamente ou reporte ao administrador.', 'CriticalLoginError' => 'Algo ruim aconteceu. Comunicar ao administrador o mais cedo possível.', 'UsernameAlreadyTaken' => "O nome de usuário que você escolheu já está em uso por outro usuário.", 'UsernameTooShort' => sprintf('Seu nome de usuário deve ser em torno de %d a %d caracteres longos.', Flux::config('MinUsernameLength'), Flux::config('MaxUsernameLength')), 'UsernameTooLong' => sprintf('Seu nome de usuário deve ser em torno de %d a %d caracteres longos.', Flux::config('MinUsernameLength'), Flux::config('MaxUsernameLength')), 'PasswordContainsUser' => 'Sua senha não pode conter seu nome de usuário.', 'PasswordHasUsername' => 'Sua senha não deve conter seu nome de usuário.', 'PasswordTooShort' => 'Sua senha deve ser em torno de %d a %d caracteres longo.', 'PasswordTooLong' => 'Sua senha deve ser em torno de %d a %d caracteres longo.', 'PasswordsDoNotMatch' => "Suas senhas não coincidem, por favor, certifique-se de que você digitou corretamente.", 'PasswordNeedUpper' => 'Sua senha deve conter pelo menos %d letra(s) maiúscula.', 'PasswordNeedLower' => 'Sua senha deve conter pelo menos %d letra(s) minúsculas.', 'PasswordNeedNumber' => 'Sua senha deve conter pelo menos %d número(s).', 'PasswordNeedSymbol' => 'Sua senha deve conter pelo menos %d símbolo(s).', 'EmailAddressInUse' => "Você digitou o endereço de e-mail já está registrado para outra conta. Por favor use um endereço de e-mail diferente.", 'InvalidEmailAddress' => "O endereço de email que você digitou não está em um formato de endereço de email válido.", 'InvalidGender' => 'Sexo deve ser "M" ou "F"', 'InvalidServer' => "O servidor que você selecionou não existe.", 'InvalidSecurityCode' => 'Por favor introduza o código de segurança corretamente.', 'InvalidPassword' => 'A senha contém caracteres inválidos.', 'InvalidBirthdate' => 'Entrada de Data de nascimento inválida.', 'CriticalRegisterError' => 'Algo ruim aconteceu. Comunicar ao administrador o mais cedo possível.', // - account/edit 'AccountEditTitle' => 'Modificar Conta', 'AccountEditTitle2' => 'Modificando Minha Conta', 'AccountEditTitle3' => 'Modificando Conta (%s)', 'CannotModifyOwnGroupID' => 'Você não pode modificar seu próprio ID do grupo da conta.', 'CannotModifyAnyGroupID' => 'Você não pode modificar IDs do grupo de contas.', 'CannotModifyGroupIDHigh' => 'Você não pode definir um ID do grupo de conta para ser maior do que o seu próprio.', 'InvalidGroupID' => 'ID do grupo inválido.', 'CannotModifyBalance' => 'Você não pode mudar o balanço da conta.', 'InvalidLastLoginDate' => 'Última data e hora de login inválidos.', 'AccountModified' => 'Conta modificada com sucesso.', 'AccountEditHeading' => 'Modificar Conta', 'AccountEditButton' => 'Modificar Conta', 'AccountEditNotFound' => 'Conta não encontrada.', // - account/index 'AccountIndexTitle' => 'Listar Contas', 'AccountIndexHeading' => 'Contas', 'LoginBetweenLabel' => 'Login Entre', 'BirthdateBetweenLabel' => 'Data de nascimento entre', 'AccountIndexNotFound' => 'Conta não encontrada.', // - account/login 'LoginTitle' => 'Login', 'LoginHeading' => 'Login', 'LoginButton' => 'Login', 'LoginPageMakeAccount' => 'Você não possui uma conta? Faça uma agora!', 'TemporarilyBanned' => 'Sua conta foi banida temporariamente.', 'PermanentlyBanned' => 'Sua conta foi banida permanentemente.', 'IpBanned' => 'O seu IP foi banido.', 'PendingConfirmation' => 'Sua conta está esperando confirmação de e-mail.', // - account/logout 'LogoutTitle' => 'Sair', 'LogoutHeading' => 'Sair', 'LogoutInfo' => 'Você saiu da sua conta.', 'LogoutInfo2' => 'Aguarde um momento enquanto você está sendo redirecionado…', // - account/resend 'ResendTitle' => 'Re-enviar E-mail de Confirmação', 'ResendEnterUsername' => 'Por favor, insira o seu Usuário.', 'ResendEnterEmail' => 'Por favor, insira o seu E-mail.', 'ResendFailed' => 'Falha ao re-enviar código de confirmação.', 'ResendEmailSent' => 'Seu código de confirmação foi enviado, olhe a sua caixa de entrada para proceder com a ativação da sua conta.', 'ResendHeading' => 'Re-enviar E-mail de Confirmação', 'ResendInfo' => 'Por favor, insira o Usuário e E-mail que você utilizou durante o registro da sua conta para podermos re-enviar o seu e-mail de confirmação.', 'ResendServerLabel' => 'Servidor Registrado', 'ResendAccountLabel' => 'Usuário', 'ResendEmailLabel' => 'E-mail', 'ResendServerInfo' => 'Este é o servidor que a conta está registrada.', 'ResendAccountInfo' => 'Este é o usuário que você registrou.', 'ResendEmailInfo' => 'Este é o e-mail que você utilizou no registro da conta acima.', 'ResendButton' => 'Re-enviar E-mail de Confirmação', // - account/resetpass 'ResetPassTitle' => 'Redefinir Senha', 'ResetPassEnterAccount' => 'Por favor, digite o seu Usuário.', 'ResetPassEnterEmail' => 'Por favor, digite o seu e-mail.', 'ResetPassDisallowed' => 'Recuperação de senha não pode ser usada para esta conta.', 'ResetPassFailed' => 'Falha ao enviar o email de redefinição de senha.', 'ResetPassEmailSent' => 'Um e-mail foi enviado para você com os detalhes de como proceder para redefinir sua senha.', 'ResetPassInfo' => 'Se você perder a sua senha, você pode redefiní-la digitando apenas o email que você cadastrou na sua conta.', 'ResetPassInfo2' => 'Uma mensagem será enviada ao email digitado contendo um link para você poder redefinir a sua senha, por isso é necessário que você possua um e-mail válido.', 'ResetPassServerLabel' => 'Servidor Registrado', 'ResetPassAccountLabel' => 'Usuário', 'ResetPassEmailLabel' => 'E-mail', 'ResetPassServerInfo' => 'Este é o servidor que a conta está registrada.', 'ResetPassAccountInfo' => 'Este é o usuário que você registrou.', 'ResetPassEmailInfo' => 'Este é o e-mail que você utilizou no registro da conta acima.', 'ResetPassButton' => 'Enviar E-mail para Redefinição de Senha', // - account/resetpw 'ResetPwTitle' => 'Redefinir Senha', 'ResetPwFailed' => 'Falha ao redefinir senha, tente novamente mais tarde.', 'ResetPwDone' => 'Sua senha foi redefinida e um e-mail contendo a sua nova senha foi enviada para você.', 'ResetPwDone2' => 'A sua senha foi redefinida, mas houve uma falha ao lhe enviar um e-mail contendo sua nova senha. Por favor, tente redefiní-la novamente para resolver esse problema.', // - account/transfer 'TransferTitle' => 'Transferir Créditos de Doação', 'TransferGreaterThanOne' => 'Você só pode transferir 1 ou mais créditos.', 'TransferEnterCharName' => 'Você deve digitar o nome do personagem que vai receber os créditos.', 'TransferNoCharExists' => "O personagem '%s' não existe. Tenha certeza que você digitou o nome correto.", 'TransferNoBalance' => 'Você não tem saldo o suficiente para fazer uma transferência.', 'TransferUnexpectedError' => 'Erro inesperado ocorreu.', 'TransferSuccessful' => 'Os créditos foram transferidos!', 'TransferHeading' => 'Transferir Créditos de Doação', 'TransferSubHeading' => 'Os créditos serão transferidos para um personagem no servidor %s.', 'TransferInfo' => 'Você possui %s crédito(s).', 'TransferInfo2' => 'Insira a quantidade que você quer transferir e o nome do personagem pertencente a conta que você quer enviar os créditos.', 'TransferAmountLabel' => 'Quantidade de Créditos', 'TransferCharNameLabel' => 'Nome do Personagem', 'TransferAmountInfo' => 'Esta é a quantidade de crédito que você deseja enviar.', 'TransferCharNameInfo' => 'Este é o nome do personagem que está recebendo os créditos.', 'TransferConfirm' => 'Tem certeza que quer transferir?', 'TransferButton' => 'Transferir', 'TransferNoCredits' => 'Você não possui créditos disponíveis na sua conta.', // - account/view // * account/view submenus 'ModifyAccountLink' => 'Modificar Conta', 'AccountViewTitle' => 'Ver Conta', 'AccountViewTitle2' => 'Vendo Conta (%s)', 'AccountViewTitle3' => 'Vendo Minha Conta', 'AccountTempBanFailed' => 'Falha ao banir temporariamente a conta.', 'AccountPermBanFailed' => 'Falha ao banir permanentemente a conta.', 'AccountTempBanUnauth' => 'Você não está autorizado a banir temporariamente essa conta.', 'AccountPermBanUnauth' => 'Você não está autorizado a banir permanentemente essa conta.', 'AccountLiftTempBan' => 'Conta foi desbanida.', 'AccountLiftPermBan' => 'Conta foi desbanida.', 'AccountLiftBanUnauth' => "Você não está autorizado a desbanir essa conta.", 'AccountViewHeading' => 'Vendo Conta', 'AccountViewDonateLink' => '(Doar!)', 'AccountViewTempBanLabel' => 'Banir Temporariamente', 'AccountViewPermBanLabel' => 'Banir Permanentemente', 'AccountViewUnbanLabel' => 'Remover Banimento', 'AccountBanReasonLabel' => 'Razão:', 'AccountBanUntilLabel' => 'Banido Até:', 'AccountTempBanButton' => 'Banir Conta', 'AccountPermBanButton' => 'Banir Conta Permanentemente', 'AccountTempUnbanButton' => 'Removeer Banimento Temporário', 'AccountPermUnbanButton' => 'Removeer Banimento Permanente', 'AccountBanConfirm' => 'Tem certeza?', 'AccountBanLogSubHeading' => 'Log de Banimento para %s (mais novo para mais antigo)', 'BanLogBanTypeLabel' => 'Tipo do Banimento', 'BanLogBanDateLabel' => 'Data do Banimento', 'BanLogBanReasonLabel' => 'Razão do Banimento', 'BanLogBannedByLabel' => 'Banido Por', 'BanLogBannedByCP' => 'Painel de Controle', 'BanTypeUnbanned' => 'Desbanido', 'BanTypePermBanned' => 'Banido Permanentemente', 'BanTypeTempBanned' => 'Banido Temporariamente', 'AccountViewCharSubHead' => 'Personagens em %s', 'AccountViewSlotLabel' => 'Slot', 'AccountViewCharLabel' => 'Nome do Personagem', 'AccountViewClassLabel' => 'Classe', 'AccountViewLvlLabel' => 'Nível de Base', 'AccountViewJlvlLabel' => 'Nível de Job', 'AccountViewZenyLabel' => 'Zeny', 'AccountViewGuildLabel' => 'Clã', 'AccountViewStatusLabel' => 'Status', 'AccountViewPrefsLabel' => 'Preferências', 'CharModifyPrefsLink' => 'Modificar Preferências', 'AccountViewNoChars' => 'Essa conta não possui personagens em %s.', 'AccountViewStorage' => 'Storage de %s', 'AccountViewStorageCount' => '%s tem %s item(s) no storage.', 'AccountViewNoStorage' => 'Não há itens no storage dessa conta.', 'AccountViewNotFound' => "Registros indicam que a conta que você está tentando ver não existe.", // - account/xferlog 'XferLogTitle' => 'Histórico de Transferência de Crédito', 'XferLogHeading' => 'Histórico de Transferência de Crédito', 'XferLogReceivedSubHead' => 'Transferências: Recebidas', 'XferLogSentSubHead' => 'Transferências: Enviadas', 'XferLogCreditsLabel' => 'Créditos', 'XferLogFromLabel' => 'Do E-mail', 'XferLogDateLabel' => 'Data da Transferência', 'XferLogCharNameLabel' => 'Para o Personagem', 'XferLogNotReceived' => 'Você não recebeu nenhuma transferência de crédito.', 'XferLogNotSent' => 'Você não fez nenhuma transferência de crédito.', // Module: character // - character/changeslot // - character/index // - character/mapstats // - character/online // - character/prefs // - character/resetlook 'CantResetLookWhenOnline' => 'Não pode redefinir aparência enquanto %s estiver online.', 'ResetLookSuccessful' => "A aparência de %s foi redefinida!", 'ResetLookFailed' => "Falha ao redefinir a aparência de %s", // - character/resetpos 'CantResetPosWhenOnline' => 'Não pode redefinir posição enquanto %s estiver online.', 'CantResetFromCurrentMap' => "Você não pode redefinir a posição de %s estando no mapa atual.", 'ResetPositionSuccessful' => "A posição de %s foi redefinida!", 'ResetPositionFailed' => "Falha ao redefinir a posição de %s.", // - character/view // - character/divorce 'DivorceTitle' => 'Divórcio', 'DivorceHeading' => 'Divórcio', 'DivorceNotMarried' => '%s não é casado.', 'DivorceInvalidPartner' => 'ID de parceiro inválido.', 'DivorceInvalidChild' => 'ID de filho inválido.', 'DivorceMustBeOffline' => 'Ambos s% e seu/sua parceiro(a) deve estar off-line.', 'DivorceMustBeOffline2' => '%s, seu/sua parceiro(a) e seu filho deve estar off-line.', 'DivorceText1' => "Você tem certeza que quer se divorciar de %s seu/sua parceiro(a)?", 'DivorceText2' => 'Se %s tem um filho, o filho também vai ser órfão.', 'DivorceText3' => 'Anéis de casamento também serão excluídos.', 'DivorceButton' => 'Sim, fazê-lo por favor.', 'DivorceSuccessful' => '%s já se divorciou!', // Module: cplog // - cplog/index.php // - cplog/login.php // - cplog/paypal.php // - cplog/resetpass.php // - cplog/txnview.php // Module: donate // - donate/complete // - donate/history // - donate/index // - donate/trusted // Module: errors // - errors/missing_action 'MissingActionTitle' => 'Ação Inexistente', 'MissingActionHeading' => 'Ação Inexistente!', 'MissingActionModLabel' => 'Módulo:', 'MissingActionActLabel' => 'Ação:', 'MissingActionReqLabel' => 'URL requerida:', 'MissingActionLocLabel' => 'Localização do arquivo de sistema:', // - errors/missing_view 'MissingViewTitle' => 'Faltando Página', // Precisa de tradução exata, original: "Missing View" 'MissingViewHeading' => 'Faltando Página!', // Precisa de tradução exata, original: "Missing View!" 'MissingViewModLabel' => 'Módulo:', 'MissingViewActLabel' => 'Ação:', 'MissingViewReqLabel' => 'URL requerida:', 'MissingViewLocLabel' => 'Localização do arquivo de sistema:', // Module: guild // - guild/export // - guild/index // - guild/view // Module: history // - history/cplogin 'HistoryCpLoginTitle' => 'Logins no Painel de Controle', 'HistoryCpLoginHeading' => 'Logins no Painel de Controle', 'HistoryLoginDateLabel' => 'Data/Hora do Login', 'HistoryIpAddrLabel' => 'Endereço de IP', 'HistoryErrorCodeLabel' => 'Código de Erro', 'HistoryNoCpLogins' => 'Não foram feitos logins no Painel de Controle ainda.', // -history/emailchange 'HistoryEmailTitle' => 'Mudanças de E-Mail', 'HistoryEmailHeading' => 'Mudanças de E-Mail', 'HistoryEmailRequestDate' => 'Data/Hora da requisição', 'HistoryEmailRequestIp' => 'IP que fez a requisição', 'HistoryEmailOldAddress' => 'E-Mail Antigo', 'HistoryEmailNewAddress' => 'E-Mail Novo', 'HistoryEmailChangeDate' => 'Data da Mudança', 'HistoryEmailChangeIp' => 'IP que fez a mudança', 'HistoryNoEmailChanges' => 'Nenhuma tentativa de mudança de email encontrada.', // - history/gamelogin 'HistoryGameLoginTitle' => 'Logins No Jogo', 'HistoryGameLoginHeading' => 'Logins No Jogo', 'HistoryRepsCodeLabel' => 'Resposta', 'HistoryLogMessageLabel' => 'Mensagem de Log', 'HistoryNoGameLogins' => 'Não foram feitos logins no jogo ainda.', // - history/index 'HistoryIndexTitle' => 'Histórico da Minha Conta', 'HistoryIndexHeading' => 'Histórico da Minha Conta', 'HistoryIndexInfo' => 'Aqui você pode ver a atividade passada da sua conta.', 'HistoryIndexInfo2' => 'Por favor, selecione a página desejada no menu.', // - history/passchange 'HistoryPassChangeTitle' => 'Alterações de senha', 'HistoryPassChangeHeading' => 'Alterações de senha', 'HistoryPassChangeChangeDate' => 'Alterar data', 'HistoryPassChangeChangeIp' => 'Mudar IP', 'HistoryNoPassChanges' => 'Nenhuma alteração de senha encontrada.', // -history/passreset 'HistoryPassResetTitle' => 'Redefinições de senha', 'HistoryPassResetHeading' => 'Redefinições de senha', 'HistoryPassResetRequestDate' => 'Solicitação de Data/Hora', 'HistoryPassResetRequestIp' => 'Solicitar IP', 'HistoryPassResetResetDate' => 'Redefinir a data', 'HistoryPassResetResetIp' => 'Redefinir o IP', 'HistoryNoPassResets' => 'Nenhuma senha Redefinida encontradas.', // Module: ipban // - ipban/add 'IpbanAddTitle' => 'Banir IP', 'IpbanEnterIpPattern' => 'Por favor, digite um IP ou um padrão de IP.', 'IpbanInvalidPattern' => 'IP ou padrão inválido.', 'IpbanWhitelistedPattern' => 'Esse padrão é lista branca e não pode ser bloqueado.', 'IpbanEnterReason' => 'Digite a razão do banimento para o IP.', 'IpbanSelectUnbanDate' => 'Data de desbanimento necessária.', 'IpbanFutureDate' => 'Data de desbanimento deve ser uma data futura.', 'IpbanAlreadyBanned' => 'O IP (%s) já consta como banido.', 'IpbanPatternBanned' => "O IP ou o padrão '%s' foi banido.", 'IpbanAddFailed' => 'Falha ao banir IP.', 'IpbanAddHeading' => 'Banir IP', 'IpbanIpAddressLabel' => 'Endereço de IP', 'IpbanReasonLabel' => 'Razão', 'IpbanUnbanDateLabel' => 'Data de desbanimento', 'IpbanIpAddressInfo' => 'Você pode especificar um padrão de IP como 218.139.*.*', 'IpbanAddButton' => 'Banir IP', // - ipban/edit 'IpbanEditTitle' => 'Modificar Banimento de IP', 'IpbanEnterEditReason' => 'Por favor, digite uma razão para a modificação de Banimento de IP .', 'IpbanEditFailed' => 'Falha ao modificar Banimento de IP.', 'IpbanEditHeading' => 'Modificar Banimento de IP', 'IpbanEditReasonLabel' => 'Editar a razão', 'IpbanEditButton' => 'Modificar Banimento de IP', // - ipban/index 'IpbanListTitle' => 'Lista de IP Banidos', 'IpbanListHeading' => 'Lista de IP Banidos', 'IpbanBannedIpLabel' => 'IP Banido', 'IpbanBanDateLabel' => 'Data do Banimento', 'IpbanBanReasonLabel' => 'Razão', 'IpbanBanExpireLabel' => 'Data de expiração do Banimento', 'IpbanModifyLink' => 'Modificar', 'IpbanRemoveLink' => 'Remover', 'IpbanUnbanButton' => 'Desbanir Selecionados', 'IpbanListNoBans' => 'Atualmente não há IPs banidos.', // - ipban/remove 'IpbanRemoveTitle' => 'Remover Banimento de IP', 'IpbanEnterRemoveReason' => 'Por favor, digite uma razão para a remoção do Banimento de IP.', 'IpbanNotBanned' => 'Nenhum IP correspondente (%s) atualmente é proibido.', 'IpbanPatternUnbanned' => "O endereço IP/padrão '%s' foi banido.", 'IpbanRemoveFailed' => 'Falha ao remover a Banimento de IP.', 'IpbanRemoveHeading' => 'Remover Banimento de IP', 'IpbanRemoveReasonLabel' => 'Razão do desbanimento', 'IpbanRemoveButton' => 'Remover Banimento de IP', // - ipban/unban 'IpbanNothingToUnban' => 'Nada para desbanir.', 'IpbanEnterUnbanReason' => 'Por favor, digite uma razão para desbanir o(s) IP(s).', 'IpbanUnbanned' => 'IP(s) selecionado(s) desbanido(s)!', 'IpbanUnbanFailed' => 'Falha ao desbanir %d IP(s) especificado(s)!', // Module: item // - item/add // - item/copy // - item/edit // - item/index // - item/view // Module: itemshop // - itemshop/add // - itemshop/delete // - itemshop/edit // - itemshop/imagedel // Module: logdata // - logdata/chat // - logdata/command 'CommandLogTitle' => 'Lista de comandos', 'CommandLogHeading' => 'Log de comandos', 'CommandLogNotFound' => 'Nenhum comando registrado', 'CommandLogDateLabel' => 'Comando Data/Hora', 'CommandLogAccountIdLabel'=> 'ID da conta', 'CommandLogCharIdLabel' => 'ID do char', 'CommandLogCharNameLabel' => 'Personagem', 'CommandLogCommandLabel' => 'Comando', 'CommandLogMapLabel' => 'Mapa', // - logdata/index // - logdata/login // - logdata/pick 'PickLogTitle' => 'Lista de log de itens', 'PickLogHeading' => 'Log de itens', 'PickLogNotFound' => 'Nenhum item registrado', 'PickLogDateLabel' => 'Data/Hora', 'PickLogCharacterLabel' => 'Personagem', 'PickLogTypeLabel' => 'Tipo', 'PickLogItemLabel' => 'Nome do item', 'PickLogAmountLabel' => 'Quantidade', 'PickLogRefineLabel' => 'Refino', 'PickLogCard0Label' => 'Carta 1', 'PickLogCard1Label' => 'Carta 2', 'PickLogCard2Label' => 'Carta 3', 'PickLogCard3Label' => 'Carta 4', 'PickLogMapLabel' => 'Mapa', // - logdata/zeny 'ZenyLogTitle' => 'Lista de log de zeny', 'ZenyLogHeading' => 'Log de zeny', 'ZenyLogNotFound' => 'Não há registro de logs de zeny', 'ZenyLogDateLabel' => 'Data/Hora', 'ZenyLogCharacterLabel' => 'Personagem', 'ZenyLogSourceLabel' => 'ID do Personagem', 'ZenyLogTypeLabel' => 'Tipo', 'ZenyLogAmountLabel' => 'Valor', 'ZenyLogMapLabel' => 'Mapa', // Module: mail // - mail/index 'MailerTitle' => 'Formulário de Email', 'MailerHeading' => 'Formulário de Email', 'MailerEnterToAddress' => 'Digite o destinatário.', 'MailerEnterSubject' => 'Digite o assunto.', 'MailerEnterBodyText' => 'Digite o corpo de texto.', 'MailerEmailHasBeenSent' => 'Seu e-mail foi enviado com sucesso para %s.', 'MailerFailedToSend' => 'O sistema de e-mail falhou ao enviar a mensagem. Isso pode ser configuração.', 'MailerInfo' => 'Você pode usar o formulário abaixo para enviar e-mails usando o Painel de Controle.', 'MailerFromLabel' => 'De', 'MailerToLabel' => 'Para', 'MailerSubjectLabel' => 'Assunto', 'MailerBodyLabel' => 'Corpo da Mensagem', // Module: main // - main/index 'MainPageHeading' => 'Flux Control Panel', 'MainPageInfo' => "Se você está vendo esta página, é porque você instalou o Flux Control Panel com sucesso!", 'MainPageInfo2' => "Você gostaria de mudar esta página? Então, aqui você pode mudar:", 'MainPageStep1' => 'Abra o arquivo "%s" no seu editor de texto.', 'MainPageStep2' => 'E edite o arquivo como você quiser!', 'MainPageThanks' => 'Obrigado por usar o Flux!', // - main/pagenotfound 'PageNotFoundTitle' => '404 Página Não Encontrada', 'PageNotFoundHeading' => 'Página Não Encontrada', 'PageNotFoundInfo' => 'A página que você solicitou não foi encontrada. Por favor, verifique se o endereço está correto e tente novamente.', // - main/preprocess 'DisallowedDuringWoE' => 'A página que você solicitou não está disponível durante a GdE.', // Module: monster // - monster/index // - monster/view // Module: purchase // - purchase/add // - purchase/cart // - purchase/checkout // - purchase/clear // - purchase/index // - purchase/pending // - purchase/remove // Module: ranking // - ranking/character // - ranking/guild // - ranking/zeny // Module: server // - server/info 'ServerInfoTitle' => 'Informação do Servidor', 'ServerInfoHeading' => 'Informação do Servidor', 'ServerInfoText' => "Aqui você encontra várias informações sobre o servidor.", 'ServerInfoSubHeading' => 'Informação para %s', 'ServerInfoSubHeading2' => 'Informação de Classe para %s', 'ServerInfoAccountLabel' => 'Contas', 'ServerInfoCharLabel' => 'Personagens', 'ServerInfoGuildLabel' => 'Clãs', 'ServerInfoPartyLabel' => 'Grupos', 'ServerInfoZenyLabel' => 'Zeny', // - server/status 'ServerStatusTitle' => 'Status do Servidor', 'ServerStatusHeading' => 'Status do Servidor', 'ServerStatusInfo' => "Entendendo o status de Online e Offline de cada servidor pode lhe ajudar a entender como relatar o seu problema. Por exemplo, se o login server estiver offline, isso quer dizer que não é possível fazer o login no jogo. O character server e o map server são necessários para você entrar na escolha de seu personagem e no mapa do jogo depois que você faz o login.", 'ServerStatusServerLabel' => 'Servidor', 'ServerStatusLoginLabel' => 'Login Server', 'ServerStatusCharLabel' => 'Character Server', 'ServerStatusMapLabel' => 'Map Server', 'ServerStatusOnlineLabel' => 'Jogadores Online', 'ServerStatusPeakLabel' => 'Pico de jogador', // Module: service // - service/tos 'TermsTitle' => 'Termos de Serviço', 'TermsHeading' => 'Termos de Serviço', 'TermsInfo' => 'Por favor, leia tudo antes de criar a sua conta!', 'TermsInfo2' => "PARA O ADMINISTRADOR DO PAINEL DE CONTROLE: Você pode adicionar os Termos de Serviço diretamente neste arquivo. A localização do arquivo é: %s", // Module: unauthorized // - unauthorized/index 'UnauthorizedTitle' => 'Não Autorizado', 'UnauthorizedHeading' => 'Não Autorizado', 'UnauthorizedInfo' => 'Você não está autrizado a ver essa página. Redirecionando…', // Module: woe // - woe/index 'WoeTitle' => 'Horários da Guerra do Emperium', 'WoeHeading' => 'Horários da Guerra do Emperium', 'WoeInfo' => "Aqui estão os horários da GdE para o %s. Esses horários estão sujeitos a alteração sem aviso prévio, portanto mantenha-se informado.", 'WoeServerTimeInfo' => 'A hora atual do servidor é:', 'WoeServerLabel' => 'Servidores', 'WoeTimesLabel' => 'Horários da Guerra do Emperium', 'WoeNotScheduledInfo' => 'Não há nenhuma Guerra do Emperium agendada.', // Module: tasks 'TaskListHeader' => 'Lista de tarefas', 'TaskListHeaderCompleted' => 'Tarefas concluídas', 'TaskListAdd' => 'Adicionar nova tarefa', 'TaskListAdded' => 'Tarefa adicionada!', 'TaskListSub' => 'Lista de tarefas dos GM\'s!', 'TLNotAssigned' => 'Não atribuído', 'TLNoTasks' => 'Não há nenhuma tarefa.!', 'TLNoMine' => 'Você não tem tarefas atribuídas a você.', 'TLNoCompleted' => 'Não há tarefas concluídas ainda.', 'TLHeaderTasks' => 'Tarefas', 'TLHeaderOwner' => 'Atribuido à', 'TLHeaderPriority' => 'Prioridade', 'TLHeaderStatus' => 'Estado', 'TLHeaderCreated' => 'Criado', 'TLHeaderModified' => 'Modificado', 'TLHeaderResources' => 'Informações', 'TLHeaderBody' => 'Caixa de Mensagem', 'TLPriority1' => 'Urgente', 'TLPriority2' => 'Alta', 'TLPriority3' => 'Baixa', 'TLStatus0' => 'Nova Tarefa', 'TLStatus1' => 'Em andamento', 'TLStatus2' => 'Aguardando Implementação', 'TLStatus5' => 'completo', 'TLHuh' => 'Você não deve ser capaz de ver isso!', // Module: contactform 'CFTitleSubmit' => 'Contate-nos', // Module: logdata/harmony 'HARTitle' => 'Harmony Logs', 'HARSearchLink' => 'Pesquisar...', 'HARDateBetween' => 'Data entre', 'HARIPAddress' => 'Endereço IP', 'HARCharacter' => 'Personagem', 'HARAccountID' => 'ID da conta', 'HARNoData' => 'Nenhum dado foi encontrado.', 'HARGoback' => 'Voltar', // Module: News and Pages 'XCMSNewsHeader' => 'Announcements', 'XCMSPageHeader' => 'Content Management System', 'XCMSPageText' => 'This FluxCP addon enables server admins and staff to create pages within their website with no prior flux/coding knowledge. The built-in news system can also be swapped out for an rss feed by modifying the addon settings.', 'XCMSNewsTitleError' => 'News title is required!', 'XCMSNewsBodyError' => 'News body is required!', 'XCMSPageTitleError' => 'Page Title is required!', 'XCMSPageBodyError' => 'Page body is required!', 'XCMSPagePathError' => 'Page path is required!', 'XCMSNewsAdded' => 'News added to system', 'XCMSPagesAdded' => 'Your new page has been added', 'XCMSNewsUpdated' => 'News updated', 'XCMSPageUpdated' => 'Your page has been updated', 'XCMSNewsAddTitle' => 'Add a news item', 'XCMSPageAddTitle' => 'Add a new page', 'XCMSNewsEditTitle' => 'Edit news', 'XCMSPageEditTitle' => 'Edit page', 'XCMSNewsNotFound' => 'News not found!', 'XCMSPageNotFound' => 'Page not found!', 'XCMSNewsDeleted' => 'News deleted', 'XCMSPageDeleted' => 'Your page has been deleted', 'XCMSNewsEmpty' => 'No news articles have been found. Are you using the correct News Type? (XCMSNewsType setting)', 'XCMSNewsRSSNotFound' => 'RSS feed can\'t be found. Make sure the XCMSNewsRSS setting is correct, or switch XCMSNewsType to 1 to use built-in news system!', 'XCMSNewsTXTNotFound' => 'File import does not work in this version. The addon.php file actually tells you this! Switch XCMSNewsType to 1 to use built-in news system, or 2 to use RSS import feature!', 'XCMSNewsFBNotFound' => 'Facebook feed not found!', 'XCMSPageEmpty' => 'No page added', 'XCMSNewsLink' => 'read more...', 'XCMSEdit' => 'Edit', 'XCMSDelete' => 'Delete', 'XCMSNewsTitleLabel' => 'News Title', 'XCMSNewsBodyLabel' => 'News Body', 'XCMSNewsLinkLabel' => 'News Link', 'XCMSNewsAuthorLabel' => 'News Author', 'XCMSPageTitleLabel' => 'Page Title', 'XCMSPageBodyLabel' => 'Page Body', 'XCMSPagePathLabel' => 'Page Path', 'XCMSCreatedLabel' => 'Date Created', 'XCMSModifiedLabel' => 'Date Modified', 'XCMSActionLabel' => 'Action', 'XCMSConfirmDelete' => 'Are you sure you want to delete?', 'XCMSPageCreate' => 'Create now?', 'XCMSOptionalLabel' => '(Optional)', 'XCMSRequiredLabel' => '(Required)', // Module: servicedesk 'SDHeader' => 'Serviço de tickets', 'SDCreateNew' => 'Criar um novo ticket', 'SDWelcomeText' => 'Bem vindo ao serviço de Ticket', 'SDNoTickets' => 'Você ainda não criou nenhum ticket.', 'SDNoBlankResponse' => 'É necessario digitar uma resposta para enviar.', 'SDNoCatsAvailable' => 'Nenhuma categoria ativa', 'SDNoOpenTickets' => 'Não existem tickets abertos.', 'SDNoInactiveTickets' => 'Não existem tickets inativos.', 'SDNoClosedTickets' => 'Não existem tickets fechados.', 'SDNoCats' => 'Não existem categorias.', 'SDHuh' => 'Você não deveria estar aqui o.O', 'SDPointerChatLog' => 'Nós recomendamos que você cole o log aqui pastebin.com e nos envie o erro.', 'SDPointerScreenShot' => 'Nos envie links de imagens para serem utilizados como provas', 'SDPointerVideoLink' => 'Recomendamos que envie para o youtube e coloque o link aqui', 'SDHeaderID' => 'Ticket #', 'SDHeaderSubject' => 'Resposta', 'SDHeaderCategory' => 'Categoria', 'SDHeaderStatus' => 'Status atual', 'SDHeaderLastAuthor' => 'Última resposta', 'SDHeaderTimestamp' => 'Criado', 'SDHeaderAccount' => 'Conta', 'SDHeaderTeam' => 'Equipe', 'SDH3ActiveTickets' => 'Tickets ativos', 'SDH3InActiveTickets' => 'Tickets inativos', 'SDH3ClosedTickets' => 'Tickets fechados', 'SDH3CurrentCat' => 'Categorias', 'SDH3CreateCat' => 'Criar nova categoria', 'SDH3StaffList' => 'Current Staff Settings', 'SDH3StaffCreate' => 'Add Staff Settings', 'SDReOpenPlayer' => 'Ticket reaberto pelo jogador', 'SDReOpenStaff' => 'Ticket reaberto pela equipe', 'SDRespTable1' => 'Responder e retornar para o Ticket', 'SDRespTable2' => 'Responder e retornar para a lista', 'SDRespTable3' => 'Responder e fechar o Ticket', 'SDRespTable4' => 'Responder e enviar para outro GM', 'SDRespTable5' => 'Fechar Ticket', 'SDRespTable6' => 'Responder e reabrir o Ticket', 'SDGroup1' => 'GM', 'SDGroup2' => 'GM Chefe', 'SDGroup3' => 'Admin', 'SDLinkOpenNew' => 'Abrir novo ticket', // Module: webcommands 'WCTitleLabel' => 'Web Commands', //Menus 'NewsLabel' => 'Novidades', 'MyAccountLabel' => 'Minha Conta', 'HistoryLabel' => 'Logs da conta', 'ServiceDeskLabel' => 'Abrir ticket', 'ServerInfoLabel' => 'Informações do servidor', 'ServerStatusLabel' => 'Status do servidor', 'WoeHoursLabel' => 'Horário da WoE', 'CastlesLabel' => 'Castelos', 'WhosOnlineLabel' => 'Quem está online', 'MapStatisticsLabel' => 'Estatisticas de mapa', 'RankingInfoLabel' => 'Informações dos Rankings', 'VendingInfoLabel' => 'Lojas abertas', 'JoinUsInFacebookLabel' => 'Pagina no facebook', 'MainMenuLabel' => 'Main Menu', 'ForumLabel' => 'Forum', 'AccountLabel' => 'Account', 'CharacterLabel' => 'Character', 'CPLogsLabel' => 'CP Logs', 'FluxAdminLabel' => 'Flux Admin', 'PagesLabel' => 'Pages', 'IPBanListLabel' => 'IP Ban List', 'GuildsLabel' => 'Guilds', 'rALogsLabel' => 'rA Logs', 'SendMailLabel' => 'Send Mail', 'ReInstallLabel' => 'Re-Install', 'TaskListLabel' => 'Task List', 'DonationsLabel' => 'Donations', 'InformationLabel' => 'Information', 'DatabaseLabel' => 'Database', 'SocialLabel' => 'Social', 'HomeLabel' => 'Home', 'DownloadsLabel' => 'Downloads', 'RulesLabel' => 'Rules', 'ContactUsLabel' => 'Contact Us', 'PurchaseLabel' => 'Purchase', 'DonateLabel' => 'Donate', 'MapStaticsLabel' => 'Map Statics', 'ItemDatabaseLabel' => 'Item Database', 'MobDatabaseLabel' => 'Mob Database', 'RateUsOnRMSLabel' => 'Rate us on RMS!', 'AccountEmailLabel2' => 'Confirm E-mail Address', 'InvalidEmailconf' => 'E-mail addresses do not match.', 'InvalidVIPTime' => 'Invalid VIP Time.', 'VIPTimeDateLabel' => 'VIP Until', 'VIPStateLabel' => 'VIP Status', 'CashLogTitle' => 'List CashPoints Log', 'CashLogHeading' => 'CashPoint Log', 'CashLogNotFound' => 'No cash logs found.', 'CashLogDateLabel' => 'Date/Time', 'CashLogCharacterLabel' => 'Character', 'CashLogTypeLabel' => 'Type', 'CashLogCashTypeLabel' => 'Cash Type', 'CashLogAmountLabel' => 'Amount', 'CashLogMapLabel' => 'Map', 'BranchLogTitle' => 'List Branch Log', 'BranchLogHeading' => 'Branch Log', 'BranchLogNotFound' => 'No branch logs found.', 'BranchLogIDLabel' => 'Branch Log ID', 'BranchLogDateLabel' => 'Date / Time', 'BranchLogAccountIDLabel' => 'Account ID', 'BranchLogCharIDLabel' => 'Char ID', 'BranchLogCharNameLabel' => 'Char Name', 'BranchLogMapLabel' => 'Map', 'CharLogTitle' => 'List Character Log', 'CharLogHeading' => 'Character Log', 'CharLogNotFound' => 'No character logs found.', 'CharLogDateLabel' => 'Date / Time', 'CharLogMsgLabel' => 'Action', 'CharLogAccountIDLabel' => 'Account ID', 'CharLogCharNumLabel' => 'Character slot', 'CharLogCharNameLabel' => 'Character Name', 'InterLogTitle' => 'List of Interactions Log', 'InterLogHeading' => 'Interactions Log', 'InterLogNotFound' => 'No Interactions logs found.', 'InterLogDateLabel' => 'Date / Time', 'InterLogLabel' => 'Interactions Log', 'MVPLogTitle' => 'List MVP Log', 'MVPLogHeading' => 'MVP Log', 'MVPLogNotFound' => 'No MVP logs found.', 'MVPLogIDLabel' => 'MVP Log ID', 'MVPLogDateLabel' => 'Date / Time', 'MVPLogCharacterLabel' => 'Character ID', 'MVPLogMonsterLabel' => 'MVP Monster', 'MVPLogPrizeLabel' => 'MVP Prize', 'MVPLogExpLabel' => 'MVP Experience', 'MVPLogMapLabel' => 'Map', 'NPCLogTitle' => 'List NPC Log', 'NPCLogHeading' => 'NPC Log', 'NPCLogNotFound' => 'No npc logs found.', 'NPCLogIDLabel' => 'NPC ID', 'NPCLogDateLabel' => 'Date / Time', 'NPCLogAccountIDLabel' => 'Account ID', 'NPCLogCharIDLabel' => 'Character ID', 'NPCLogCharNameLabel' => 'Character Name', 'NPCLogMapLabel' => 'Map', 'NPCLogMsgLabel' => 'Message', 'MailerSelectTemplateLabel' => 'Select Template', 'MainPageWelcome' => 'Welcome to %s!', 'CMSNewsHeader' => 'Announcements', 'CMSPageHeader' => 'Content Management System', 'CMSPageText' => 'This module enables server admins and staff to create pages within their website with no prior flux/coding knowledge. The built-in news system can also be swapped out for an rss feed by modifying the application settings.', 'CMSNewsTitleError' => 'News title is required!', 'CMSNewsBodyError' => 'News body is required!', 'CMSPageTitleError' => 'Page Title is required!', 'CMSPageBodyError' => 'Page body is required!', 'CMSPagePathError' => 'Page path is required!', 'CMSNewsAdded' => 'News added to system', 'CMSPagesAdded' => 'Your new page has been added', 'CMSNewsUpdated' => 'News updated', 'CMSPageUpdated' => 'Your page has been updated', 'CMSNewsAddTitle' => 'Add a news item', 'CMSPageAddTitle' => 'Add a new page', 'CMSNewsEditTitle' => 'Edit news', 'CMSPageEditTitle' => 'Edit page', 'CMSNewsNotFound' => 'News not found!', 'CMSPageNotFound' => 'Page not found!', 'CMSNewsDeleted' => 'News deleted', 'CMSPageDeleted' => 'Your page has been deleted', 'CMSNewsEmpty' => 'No news articles have been found. Are you using the correct News Type? (CMSNewsType setting)', 'CMSNewsRSSNotFound' => "RSS feed can't be found. Make sure the CMSNewsRSS setting is correct, or switch CMSNewsType to 1 to use built-in news system!", 'CMSPageEmpty' => 'No page added', 'CMSNewsLink' => 'read more...', 'CMSEdit' => 'Edit', 'CMSDelete' => 'Delete', 'CMSNewsTitleLabel' => 'News Title', 'CMSNewsBodyLabel' => 'News Body', 'CMSNewsLinkLabel' => 'News Link', 'CMSNewsAuthorLabel' => 'News Author', 'CMSPageTitleLabel' => 'Page Title', 'CMSPageBodyLabel' => 'Page Body', 'CMSPagePathLabel' => 'Page Path', 'CMSCreatedLabel' => 'Date Created', 'CMSModifiedLabel' => 'Date Modified', 'CMSActionLabel' => 'Action', 'CMSConfirmDeleteLabel' => 'Are you sure you want to delete?', 'CMSPageCreate' => 'Create now?', 'CMSOptionalLabel' => '(Optional)', 'CMSRequiredLabel' => '(Required)', 'CMSCreateLabel' => 'Add News', 'SDRespTable7' => 'Resolve Ticket and Credit Account', ); ?> ================================================ FILE: lib/Flux/Addon.php ================================================ name = $name; $this->addonDir = is_null($addonDir) ? FLUX_ADDON_DIR."/$name" : $addonDir; $this->configDir = "{$this->addonDir}/config"; $this->moduleDir = "{$this->addonDir}/modules"; $this->themeDir = "{$this->addonDir}/themes"; $files = array( 'addonConfig' => "{$this->configDir}/addon.php", 'accessConfig' => "{$this->configDir}/access.php", //'messagesConfig' => "{$this->configDir}/messages.php" // Deprecated. ); foreach ($files as $configName => $filename) { if (file_exists($filename)) { $this->{$configName} = Flux::parseConfigFile($filename); } if (!($this->{$configName} instanceOf Flux_Config)) { $tempArr = array(); $this->{$configName} = new Flux_Config($tempArr); } } // Use new language system for messages (also supports addons). $this->messagesConfig = Flux::parseLanguageConfigFile($name); } public function respondsTo($module, $action = null) { $path = is_null($action) ? "{$this->moduleDir}/$module" : "{$this->moduleDir}/$module/$action.php"; if ((is_null($action) && is_dir($path)) || file_exists($path)) { return true; } else { return false; } } public function getView(Flux_Template $template, $module, $action) { $path = "{$this->themeDir}/". $template->getName() . "/{$module}/{$action}.php"; if (file_exists($path)) { return $path; } if (!empty($template->parentTemplate)) { return $this->getView( $template->parentTemplate, $module, $action); } return false; } } ?> ================================================ FILE: lib/Flux/Athena.php ================================================ loginServer = $loginServer; $this->charServer = $charServer; $this->mapServer = $mapServer; $this->loginDatabase = $loginServer->config->getDatabase(); $this->serverName = $charMapConfig->getServerName(); $this->expRates = $charMapConfig->getExpRates()->toArray(); $this->dropRates = $charMapConfig->getDropRates()->toArray(); $this->isRenewal = (boolean)$charMapConfig->getRenewal(); $this->maxCharSlots = (int)$charMapConfig->getMaxCharSlots(); $this->dateTimezone = $charMapConfig->getDateTimezone(); $this->charMapDatabase = $charMapConfig->getDatabase(); $resetDenyMaps = $charMapConfig->getResetDenyMaps(); if (!$resetDenyMaps) { $this->resetDenyMaps = array('sec_pri'); } elseif (!is_array($resetDenyMaps)) { $this->resetDenyMaps = array($resetDenyMaps); } else { $this->resetDenyMaps = $resetDenyMaps->toArray(); } // Get WoE times specific in servers config. $woeDayTimes = $charMapConfig->getWoeDayTimes(); if ($woeDayTimes instanceOf Flux_Config) { $woeDayTimes = $woeDayTimes->toArray(); foreach ($woeDayTimes as $dayTime) { if (!is_array($dayTime) || count($dayTime) < 4) { continue; } list ($sDay, $sTime, $eDay, $eTime) = array_slice($dayTime, 0, 4); $sTime = trim($sTime); $eTime = trim($eTime); if ($sDay < 0 || $sDay > 6 || $eDay < 0 || $eDay > 6 || !preg_match('/^\d{2}:\d{2}$/', $sTime) || !preg_match('/^\d{2}:\d{2}$/', $eTime)) { continue; } $this->woeDayTimes[] = array( 'startingDay' => $sDay, 'startingTime' => $sTime, 'endingDay' => $eDay, 'endingTime' => $eTime ); } } // Config used for disallowing access to certain modules during WoE. $woeDisallow = $charMapConfig->getWoeDisallow(); $_tempArray = array(); $this->woeDisallow = new Flux_Config($_tempArray); if ($woeDisallow instanceOf Flux_Config) { $woeDisallow = $woeDisallow->toArray(); foreach ($woeDisallow as $disallow) { if (array_key_exists('module', $disallow)) { $module = $disallow['module']; if (array_key_exists('action', $disallow)) { $action = $disallow['action']; $this->woeDisallow->set("$module.$action", true); } else { $this->woeDisallow->set($module, true); } } } } } /** * Set connection object. * * @param Flux_Connection $connection * @return Flux_Connection */ public function setConnection(Flux_Connection $connection) { $this->connection = $connection; $this->logsDatabase = $connection->logsDbConfig->getDatabase(); $this->webDatabase = $connection->webDbConfig->getDatabase(); return $connection; } /** * Set cart object. * * @param Flux_ItemShop_Cart $cart * @return Flux_ItemShop_Cart */ public function setCart(Flux_ItemShop_Cart $cart) { $this->cart = $cart; return $cart; } /** * When casted to a string, the server name should be used. * * @return string * @access public */ public function __toString() { return $this->serverName; } /** * Transfer credits from one account to another. * * @param int $fromAccountID Account ID * @param string $targetCharName Character name of person receiving credits * @param int $credits Amount of credits */ public function transferCredits($fromAccountID, $targetCharName, $credits) { // // Return values: // -1 = From or to account, one or the other does not exist. (likely the latter.) // -2 = Sender has an insufficient balance. // -3 = Unknown character. // true = Successful transfer // false = Error // $sql = "SELECT account_id, char_id, name AS char_name FROM {$this->charMapDatabase}.`char` WHERE `char`.name = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); if (!$sth->execute(array($targetCharName)) || !($char=$sth->fetch())) { // Unknown character. return -3; } $targetAccountID = $char->account_id; $targetCharID = $char->char_id; $sql = "SELECT COUNT(account_id) AS accounts FROM {$this->loginDatabase}.login WHERE "; $sql .= "account_id = ? OR account_id = ? LIMIT 2"; $sth = $this->connection->getStatement($sql); if (!$sth->execute(array($fromAccountID, $targetAccountID)) || $sth->fetch()->accounts != 2) { // One or the other, from or to, are non-existent accounts. return -1; } if (!$this->loginServer->hasCreditsRecord($fromAccountID)) { // Sender has a zero balance. return -2; } $creditsTable = Flux::config('FluxTables.CreditsTable'); $xferTable = Flux::config('FluxTables.CreditTransferTable'); // Get balance of sender. $sql = "SELECT balance FROM {$this->loginDatabase}.$creditsTable WHERE account_id = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); if (!$sth->execute(array($fromAccountID))) { // Error. return false; } if ($sth->fetch()->balance < $credits) { // Insufficient balance. return -2; } // Take credits from fromAccount first. if ($this->loginServer->depositCredits($fromAccountID, -$credits)) { // Then deposit to targetAccount next. if (!$this->loginServer->depositCredits($targetAccountID, $credits)) { // Attempt to restore credits if deposit to toAccount failed. $this->loginServer->depositCredits($fromAccountID, $credits); return false; } else { $sql = "INSERT INTO {$this->charMapDatabase}.$xferTable "; $sql .= "(from_account_id, target_account_id, target_char_id, amount, transfer_date) "; $sql .= "VALUES (?, ?, ?, ?, NOW())"; $sth = $this->connection->getStatement($sql); // Log transfer. $sth->execute(array($fromAccountID, $targetAccountID, $targetCharID, $credits)); return true; } } else { return false; } } /** * Set loginAthenaGroup object. * * @param Flux_LoginAthenaGroup $loginAthenaGroup * @return Flux_LoginAthenaGroup */ public function setLoginAthenaGroup(Flux_LoginAthenaGroup $loginAthenaGroup) { $this->loginAthenaGroup = $loginAthenaGroup; return $loginAthenaGroup; } /** * Check if a character exists with a particular char ID. * * @param int $charID * @return bool True/false if char exists or doesn't. */ public function charExists($charID) { $sql = "SELECT char_id FROM {$this->charMapDatabase}.`char` WHERE "; $sql .= "`char`.char_id = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($charID)) && ($char=$sth->fetch()) && $char->char_id) { return true; } else { return false; } } /** * Check if a charID belongs to an accountID. * * @param int $charID * @param int $accountID * @return bool */ public function charBelongsToAccount($charID, $accountID) { $sql = "SELECT char_id FROM {$this->charMapDatabase}.`char` WHERE "; $sql .= "`char`.char_id = ? AND `char`.account_id = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($charID, $accountID)) && ($char=$sth->fetch()) && $char->char_id) { return true; } else { return false; } } /** * Check if char with charID is online. * * @param int $charID * @return bool */ public function charIsOnline($charID) { $sql = "SELECT char_id FROM {$this->charMapDatabase}.`char` WHERE `char`.online > 0 "; $sql .= "AND `char`.char_id = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($charID)) && ($char=$sth->fetch()) && $char->char_id) { return true; } else { return false; } } /** * Check if account has any online characters at the moment. * * @param int $accountId * @return bool */ public function accountHasOnlineChars($accountID) { $sql = "SELECT char_id FROM {$this->charMapDatabase}.`char` WHERE `char`.online > 0 "; $sql .= "AND `char`.account_id = ? ORDER BY `char`.online DESC LIMIT 1"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($accountID)) && ($char=$sth->fetch()) && $char->char_id) { return true; } else { return false; } } /** * Get character data of charID. * * @param int $charID * @return mixed Returns Flux_DataObject or false. */ public function getCharacter($charID) { $sql = "SELECT `char`.* FROM {$this->charMapDatabase}.`char` WHERE "; $sql .= "`char`.char_id = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($charID)) && ($char=$sth->fetch())) { return $char; } else { return false; } } /** * Get character prefs. * * @param int $charID Character ID * @param array $prefs Only these prefs? * @return mixed Flux_Config or false. */ public function getPrefs($charID, array $prefs = array()) { $sql = "SELECT account_id FROM {$this->charMapDatabase}.`char` WHERE char_id = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($charID)) && ($char=$sth->fetch())) { $charPrefsTable = Flux::config('FluxTables.CharacterPrefsTable'); $pref = array(); $bind = array($char->account_id, $charID); $sql = "SELECT name, value FROM {$this->charMapDatabase}.$charPrefsTable "; $sql .= "WHERE account_id = ? AND char_id = ?"; if ($prefs) { foreach ($prefs as $p) { $pref[] = "name = ?"; $bind[] = $p; } $sql .= sprintf(' AND (%s)', implode(' OR ', $pref)); } $sth = $this->connection->getStatement($sql); if ($sth->execute($bind)) { $prefsArray = array(); foreach ($sth->fetchAll() as $p) { $prefsArray[$p->name] = $p->value; } return new Flux_Config($prefsArray); } else { return false; } } else { return false; } } /** * Set character prefs. * * @param int $charID * @param array $prefsArray pref=>value pairs. * @return bool */ public function setPrefs($charID, array $prefsArray) { $sql = "SELECT account_id FROM {$this->charMapDatabase}.`char` WHERE char_id = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($charID)) && ($char=$sth->fetch())) { $charPrefsTable = Flux::config('FluxTables.CharacterPrefsTable'); $pref = array(); $bind = array($char->account_id, $charID); $sql = "SELECT id, name, value FROM {$this->charMapDatabase}.$charPrefsTable "; $sql .= "WHERE account_id = ? AND char_id = ?"; if ($prefsArray) { foreach ($prefsArray as $prefName => $prefValue) { $pref[] = "name = ?"; $bind[] = $prefName; } $sql .= sprintf(' AND (%s)', implode(' OR ', $pref)); } $sth = $this->connection->getStatement($sql); if ($sth->execute($bind)) { $prefs = $sth->fetchAll(); $update = array(); $usql = "UPDATE {$this->charMapDatabase}.$charPrefsTable "; $usql .= "SET value = ? WHERE id = ?"; $usth = $this->connection->getStatement($usql); $isql = "INSERT INTO {$this->charMapDatabase}.$charPrefsTable "; $isql .= "(account_id, char_id, name, value, create_date) "; $isql .= "VALUES (?, ?, ?, ?, NOW())"; $isth = $this->connection->getStatement($isql); foreach ($prefs as $p) { $update[$p->name] = $p->id; } foreach ($prefsArray as $pref => $value) { if (array_key_exists($pref, $update)) { $id = $update[$pref]; $usth->execute(array($value, $id)); } else { $isth->execute(array($char->account_id, $charID, $pref, $value)); } } return true; } else { return false; } } else { return false; } } /** * Get a single character pref. * * @param int $charID * @param string $pref * @return mixed string or false. */ public function getPref($charID, $pref) { $prefs = $this->getPrefs($charID, array($pref)); if ($prefs instanceOf Flux_Config) { return $prefs->get($pref); } else { return false; } } /** * Set a single character pref. * * @param int $charID * @param string $pref * @param string $value * @return bool */ public function setPref($charID, $pref, $value) { return $this->setPrefs($charID, array($pref => $value)); } /** * Re-set the appearance of a character. * * @param int $charID * @return mixed */ public function resetLook($charID) { // Return values: // -1 = Character is online, cannot reset. // -2 = Unknown character. // false = Failed to reset. // true = Successfully reset. $char = $this->getCharacter($charID); if (!$char) { return -2; } if ($char->online) { return -1; } $sql = "UPDATE {$this->charMapDatabase}.inventory SET "; $sql .= "equip = 0 WHERE char_id = ?"; $sth = $this->connection->getStatement($sql); if (!$sth->execute(array($charID))) { return false; } $sql = "UPDATE {$this->charMapDatabase}.`char` SET "; $sql .= "hair = 1, hair_color = 0, clothes_color = 0, weapon = 0, shield = 0, "; $sql .= "head_top = 0, head_mid = 0, head_bottom = 0, body = `class` "; $sql .= "WHERE char_id = ?"; $sth = $this->connection->getStatement($sql); if (!$sth->execute(array($charID))) { return false; } else { return true; } } /** * Re-set the position of a character. * * @param int $charID * @return mixed */ public function resetPosition($charID) { // Return values: // -1 = Character is online, cannot reset. // -2 = Reset cannot be done from current map. // -3 = Unknown character. // false = Failed to reset. // true = Successfully reset. $char = $this->getCharacter($charID); if (!$char) { return -3; } if ($char->online) { return -1; } $charMap = basename($char->last_map, '.gat'); foreach ($this->resetDenyMaps as $map) { $denyMap = basename($map, '.gat'); if ($charMap == $denyMap) { return -2; } } $sql = "UPDATE {$this->charMapDatabase}.`char` AS ch SET "; $sql .= "ch.last_map = ch.save_map, ch.last_x = ch.save_x, ch.last_y = ch.save_y "; $sql .= "WHERE ch.char_id = ?"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($charID))) { return true; } else { return false; } } /** * Get the current server time, based on the DateTimezone servers.php config. * * @param string $format Similar to that of PHP's date() function. * @return string */ public function getServerTime($format = 'U') { $dateTime = date_create('now'); if ($this->dateTimezone) { $dateTime->setTimeZone(new DateTimeZone($this->dateTimezone)); } return $dateTime->format($format); } /** * Check if it currently WoE according to the configured hours and timezone. * * @return bool */ public function isWoe() { $serverTime = (int)$this->getServerTime(); $dayNames = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); foreach ($this->woeDayTimes as $woeDayTime) { $sDay = $dayNames[$woeDayTime['startingDay']]; $eDay = $dayNames[$woeDayTime['endingDay']]; $start = strtotime("$sDay {$woeDayTime['startingTime']}"); $end = strtotime("$eDay {$woeDayTime['endingTime']}"); if ($serverTime > $start && $serverTime < $end) { return true; } } return false; } } ?> ================================================ FILE: lib/Flux/Authorization.php ================================================ config = $accessConfig; $this->session = $sessionData; } /** * Get authorization instance, creates one if it doesn't already exist. * * @param Flux_Config $accessConfig * @param Flux_SessionData $sessionData * @return Flux_Authorization * @access public */ public static function getInstance($accessConfig = null, $sessionData = null) { if (!self::$auth) { self::$auth = new Flux_Authorization($accessConfig, $sessionData); } return self::$auth; } /** * Checks whether or not the current user is able to perform a particular * action based on his/her group level and id. * * @param string $moduleName * @param string $actionName * @return bool * @access public */ public function actionAllowed($moduleName, $actionName = 'index') { $accessConfig = $this->config->get('modules'); $accessKeys = array("$moduleName.$actionName", "$moduleName.*"); $accountLevel = $this->session->account->group_level; $existentKeys = array(); if ($accessConfig instanceOf Flux_Config) { foreach ($accessKeys as $accessKey) { $accessLevel = $accessConfig->get($accessKey); if (!is_null($accessLevel)) { $existentKeys[] = $accessKey; if ($accessLevel == AccountLevel::ANYONE || $accessLevel == $accountLevel || ($accessLevel != AccountLevel::UNAUTH && $accessLevel <= $accountLevel)) { return true; } } } } if (empty($existentKeys)) { return -1; } else { return false; } } /** * Checks whether or not the current user is allowed to use a particular * feature based on his/her group level and id. * * @param string $featureName * @return bool * @access public */ public function featureAllowed($featureName) { $accessConfig = $this->config->get('features'); $accountLevel = $this->session->account->group_level; if (($accessConfig instanceOf Flux_Config)) { $accessLevel = $accessConfig->get($featureName); if (!is_null($accessLevel) && ($accessLevel == AccountLevel::ANYONE || $accessLevel == $accountLevel || ($accessLevel != AccountLevel::UNAUTH && $accessLevel <= $accountLevel))) { return true; } } return false; } /** * Provides convenient getters such as `allowedTo' and * `getGroupLevelTo'. * * @access public */ public function __get($prop) { if (preg_match("/^allowedTo(.+)/i", $prop, $m)) { return $this->featureAllowed($m[1]); } elseif (preg_match("/^getGroupLevelTo(.+)/i", $prop, $m)) { $accessConfig = $this->config->get('features'); if ($accessConfig instanceOf Flux_Config) { return $accessConfig->get($m[1]); } } } /** * Wrapper method for setting and getting values from the access config. * * @param string $key * @param mixed $value * @param arary $options * @access public */ public function config($key, $value = null, $options = array()) { if (!is_null($value)) { return $this->config->set($key, $value, $options); } else { return $this->config->get($key); } } } ?> ================================================ FILE: lib/Flux/BaseServer.php ================================================ config = $config; } /** * Checks whether the server is up and running (accepting connections). * Will return true/false based on the server status. * * @return bool Returns true if server is running, false if not. * @access public */ public function isUp() { $addr = $this->config->getAddress(); $port = $this->config->getPort(); $sock = @fsockopen($addr, $port, $errno, $errstr, (int)Flux::config('ServerStatusTimeout')); if (is_resource($sock)) { fclose($sock); return true; } else { return false; } } } ?> ================================================ FILE: lib/Flux/Captcha.php ================================================ options = array_merge( array( 'chars' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWWXYZ0123456789', 'length' => 5, 'background' => FLUX_DATA_DIR.'/captcha/background.png', 'fontPath' => realpath(FLUX_DATA_DIR.'/captcha/fonts'), 'fontName' => 'default.ttf', 'fontSize' => 28, 'yPosition' => 40, 'useDistort' => true, 'distortion' => 10 ), $options ); // Let GD know where our fonts are. //putenv("GDFONTPATH={$this->options['fontPath']}"); // Possibly breaks on Windows? // Generate security code. $this->generateCode(); // Generate CAPTCHA image. $this->generateImage(); } /** * Generate the security code to be used. * * @access protected */ protected function generateCode() { $code = ''; $chars = str_split($this->options['chars']); for ($i = 0; $i < $this->options['length']; ++$i) { $code .= $chars[array_rand($chars)]; } $this->code = $code; return $code; } /** * Generate the image. * * @access protected */ protected function generateImage() { $this->gd = imagecreatefrompng($this->options['background']); $yPos = $this->options['yPosition']; $font = "{$this->options['fontPath']}/{$this->options['fontName']}"; $size = $this->options['fontSize']; $shade1 = imagecolorallocate($this->gd, 240, 240, 240); $shade2 = imagecolorallocate($this->gd, 60, 60, 60); $shade3 = imagecolorallocate($this->gd, 0, 0, 0); if (function_exists('imagettftext')) { $distA = -$this->options['distortion']; $distB = +$this->options['distortion']; foreach (str_split($this->code, 1) as $i => $char) { imagettftext($this->gd, $size + 2, $this->options['useDistort'] ? rand($distA, $distB) : 0, ((28 * $i) + 10), $yPos, $shade3, $font, $char); imagettftext($this->gd, $size + 4, $this->options['useDistort'] ? rand($distA, $distB) : 0, ((28 * $i) + 10), $yPos, $shade2, $font, $char); imagettftext($this->gd, $size , $this->options['useDistort'] ? rand($distA, $distB) : 0, ((28 * $i) + 10), $yPos, $shade1, $font, $char); } } else { $text = "FreeType2 is needed\n"; $text .= "for CAPTCHA support.\n"; foreach (explode("\n", $text) as $i => $line) { imagestring($this->gd, 3, 5, (12 * ($i + 1)), $line, $shade1); } } } /** * Display image. * * @access public */ public function display() { header('Content-Type: image/png'); imagepng($this->gd); exit; } public function __destruct() { imagedestroy($this->gd); } } ?> ================================================ FILE: lib/Flux/CharServer.php ================================================ ================================================ FILE: lib/Flux/Config.php ================================================ true, 'force' => true); /** * This is here for any developer's convenience, just in case he/she would * like to re-use this library without having to depend on the Flux_Error * class to do so. This will cause Flux_Config to raise the exception class * of your choice. * * It's preferable that the developer change the value directly from the * class, instead of finding ways to do it from code. * * @access private * @var string */ private $exceptionClass = 'Flux_Error'; /** * The list of configuration keys that are cleared if found in the import config. * These are used for "normal" arrays, not associative arrays. This way is faster than * checking if each array in the config is associative or not. * @access private * @var array */ private $clearKeysOnImport = array( 'ThemeName', 'PayPalReceiverEmails', 'PayPalAllowedHosts', 'BanPaymentStatuses', 'ShopImageExtensions', ); /** * Construct a Flux_Config instance which acts as a more convenient * accessor to the specified configuration array. * * @param array $configArray Configuration array. * @access public */ public function __construct(array &$configArr) { $this->configArr = &$configArr; } /** * This is here... for no real GOOD reason, but should the need arise, at * least you aren't deprived of access to it. * * @return array Configuration array. * @access public */ public function &toArray() { return $this->configArr; } /** * Goes through each child in the array which is also an array, and returns * them collectively as an array of Flux_Config instances. * * @return array Array of Flux_Config instances of all children arrays. * @access public */ public function &getChildrenConfigs() { $children = array(); foreach ($this->configArr as $key => &$child) { if (is_array($child)) { $children[$key] = new Flux_Config($child); } } return $children; } /** * Get the value held by the specified key. If the value is an array it * will be returned as an instance of Flux_Config by default, unless * $configObjectIfArray is set to false. * * Keys are specified in an object-like format, such as: 'Foo.Bar.Baz' * where each dot would denote the difference in depth from key-to-key. * * @param string $key Key sequence. * @param bool $configObjectIfArray True/false whether or not to return Flux_Config instances for values that are an array. * @access public */ public function get($key, $configObjectIfArray = true) { if (!is_string($key) || empty($key)) { return null; } $keys = explode('.', $key); $base = &$this->configArr; $size = count($keys) - 1; for ($i = 0; $i < $size; ++$i) { $currentKey = $keys[$i]; if (is_array($base) && array_key_exists($currentKey, $base)) { $base = &$base[$currentKey]; } else { // Short-circuit and return null. return null; } } $currentKey = $keys[$size]; if (array_key_exists($currentKey, $base)) { $value = &$base[$currentKey]; if (is_array($value) && $configObjectIfArray) { $configClassName = get_class($this); return new $configClassName($value); } elseif ($value instanceOf Flux_Config && !$configObjectIfArray) { return $value->toArray(); } else { return $value; } } else { // We want to avoid a traditional PHP error when referencing // non-existent keys, so we'll silently return null as an // alternative ;) return null; } } /** * Set a key to hold the specified value. The format for specifying a key * is 100% identical to Flux_Config::get(). * * Options outline: * overwrite - true/false to overwrite existing keys. * force - true/false to force the creation of the key hierarchy. * * @param string $key Key sequence. * @param mixed $value Value to set in the key. * @param array $options Array of options. * @access public */ public function set($key, $value, $options = array()) { $opts = array_merge($this->defaultSetOptions, $options); $keys = explode('.', $key); $base = &$this->configArr; $size = count($keys) - 1; for ($i = 0; $i < $size; ++$i) { $currentKey = $keys[$i]; if (is_array($base) && array_key_exists($currentKey, $base)) { $base = &$base[$currentKey]; } elseif ($opts['force']) { $base[$currentKey] = array(); $base = &$base[$currentKey]; } else { // Short-circuit and return false. return false; } } $currentKey = $keys[$size]; if (array_key_exists($currentKey, $base) && !$opts['overwrite']) { return false; } $base[$currentKey] = $value; return $value; } /** * Convenience method for raising an internal exception. * * @param string $message Error message. * @access public */ public function raise($message) { $exceptionClass = $this->exceptionClass; throw new $exceptionClass($message); } /** * Adds the ability to call set() as native methods. * * @param string $method * @param array $args * @access public */ public function __call($method, $args = array()) { if (preg_match('/^get(\S+)$/', $method, $m)) { return $this->get($m[1]); } elseif (preg_match('/^set(\S+)$/', $method, $m)) { $options = array(); $argc = count($args); if ($argc > 1) { $options = $args[1]; } elseif ($argc < 1) { $class = get_class($this); $this->raise("Missing value argument in $class::$method()"); } return $this->set($m[1], $args[0], $options); } } /** * */ public function merge(Flux_Config $config, $recursive = true, $distinct = false) { if (!$recursive && $distinct) { $this->raise('Cannot merge non-recursively and distinctively at the same time.'); } if ($distinct) { $this->configArr = $this->array_merge_recursive_distinct($this->configArr, $config->toArray()); } else if ($recursive) { $this->configArr = array_merge_recursive($this->configArr, $config->toArray()); } else { $this->configArr = array_merge($this->configArr, $config->toArray()); } } /** * array_merge_recursive does indeed merge arrays, but it converts values with duplicate * keys to arrays rather than overwriting the value in the first array with the duplicate * value in the second array, as array_merge does. I.e., with array_merge_recursive, * this happens (documented behavior): * * array_merge_recursive(array('key' => 'org value'), array('key' => 'new value')); * => array('key' => array('org value', 'new value')); * * array_merge_recursive_distinct does not change the datatypes of the values in the arrays. * Matching keys' values in the second array overwrite those in the first array, as is the * case with array_merge, i.e.: * * array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value')); * => array('key' => array('new value')); * * Because arrays are appended, not overwritten, we check each key against $clearKeysOnImport, * and if it matches, we clear the array before importing the new values. * * @param array $array1 * @param array $array2 * @return array * @author Daniel * @author Gabriel Sobrinho */ public function array_merge_recursive_distinct(array $base, array $import) { $merged = $base; foreach ($import as $key => &$value) { if (in_array($key, $this->clearKeysOnImport)) { $merged[$key] = array(); } if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) { $merged[$key] = $this->array_merge_recursive_distinct($merged[$key], $value); } else { $merged[$key] = $value; } } return $merged; } } ?> ================================================ FILE: lib/Flux/Connection/Statement.php ================================================ stmt = $stmt; if (!self::$errorLog) { self::$errorLog = new Flux_LogFile(FLUX_DATA_DIR.'/logs/mysql/errors/'.date('Ymd').'.log', 'a'); } } private function getParamType($param) { switch (true) { case is_bool($param): return PDO::PARAM_BOOL; case is_int($param): return PDO::PARAM_INT; case is_null($param): return PDO::PARAM_NULL; } return PDO::PARAM_STR; } public function execute(array $inputParameters = array(), $bind_param = false) { if ($bind_param) { foreach ($inputParameters as $key => &$param) { if (is_string($key) && $key[0] == ":") { if (is_array($param)) { // $params = [ :param => [ val, PDO::PARAM_ ], ... ]; $this->stmt->bindParam($key, $param[0], $param[1]); } else { // $params = [ :param => val, ... ]; $this->stmt->bindParam($key, $param, $this->getParamType($param)); } } else { // $params = [ val, ... ]; $this->stmt->bindParam($key+1, $param, $this->getParamType($param)); } } $res = $this->stmt->execute(); } else { $res = $this->stmt->execute(empty($inputParameters) ? null : $inputParameters); } Flux::$numberOfQueries++; if ((int)$this->stmt->errorCode()) { $info = $this->stmt->errorInfo(); self::$errorLog->puts('[SQLSTATE=%s] Err %s: %s', $info[0], $info[1], $info[2]); if (Flux::config('DebugMode')) { $message = sprintf('MySQL error (SQLSTATE: %s, ERROR: %s): %s', $info[0], $info[1], $info[2]); throw new Flux_Error($message); } } return $res; } public function __call($method, $args) { return call_user_func_array(array($this->stmt, $method), $args); } } ================================================ FILE: lib/Flux/Connection/index.html ================================================ ================================================ FILE: lib/Flux/Connection.php ================================================ dbConfig = $dbConfig; $this->logsDbConfig = $logsDbConfig; $this->webDbConfig = $webDbConfig; } /** * Establish connection to server based on config. * * @param Flux_Config $dbConfig * @return PDO * @access private */ private function connect(Flux_Config $dbConfig) { $dsn = 'mysql:'; // Differentiate between a socket-type connection or an ip:port // connection. if ($sock=$dbConfig->getSocket()) { $dsn .= "unix_socket=$sock"; } else { $dsn .= 'host='.$dbConfig->getHostname(); if ($port=$dbConfig->getPort()) { $dsn .= ";port=$port"; } } // May or may not have a database name specified. if ($dbName=$dbConfig->getDatabase()) { $dsn .= ";dbname=$dbName"; } $persistent = array(PDO::ATTR_PERSISTENT => (bool)$dbConfig->getPersistent()); return new PDO($dsn, $dbConfig->getUsername(), $dbConfig->getPassword(), $persistent); } /** * Get the PDO instance for the main database server connection. * * @return PDO * @access private */ private function getConnection() { if (!$this->pdoMain) { // Establish connection for main databases. $pdoMain = $this->connect($this->dbConfig); $this->pdoMain = $pdoMain; if ($encoding=$this->dbConfig->getEncoding()) { $sth = $this->getStatement("SET NAMES ?"); $sth->execute(array($encoding)); } if ($timezone=$this->dbConfig->getTimezone()) { $sth = $this->getStatement("SET time_zone = ?"); $sth->execute(array($timezone)); } } return $this->pdoMain; } /** * Get the PDO instance for the logs database server connection. * * @return PDO * @access private */ private function getLogsConnection() { if (!$this->pdoLogs) { // Establish separate connection just for the log database. $pdoLogs = $this->connect($this->logsDbConfig); $this->pdoLogs = $pdoLogs; if ($encoding=$this->logsDbConfig->getEncoding()) { $sth = $this->getStatementForLogs("SET NAMES ?"); $sth->execute(array($encoding)); } if ($timezone=$this->logsDbConfig->getTimezone()) { $sth = $this->getStatementForLogs("SET time_zone = ?"); $sth->execute(array($timezone)); } } return $this->pdoLogs; } /** * Get the PDO instance for the web server database server connection. * * @return PDO * @access private */ private function getWebConnection() { if (!$this->pdoWeb) { // Establish separate connection just for the web server database. $pdoWeb = $this->connect($this->webDbConfig); $this->pdoWeb = $pdoWeb; if ($encoding=$this->webDbConfig->getEncoding()) { $sth = $this->getStatementForWeb("SET NAMES ?"); $sth->execute(array($encoding)); } if ($timezone=$this->webDbConfig->getTimezone()) { $sth = $this->getStatementForWeb("SET time_zone = ?"); $sth->execute(array($timezone)); } } return $this->pdoWeb; } /** * Select database to use. * * @param string $dbName * @return mixed * @access public */ public function useDatabase($dbName) { if ($this->pdoMain) { return $this->getStatement("USE $dbName")->execute(); } else { return false; } } /** * Instanciate a PDOStatement without obtaining a PDO handler before-hand. * * @return PDOStatement * @access public */ public function getStatement($statement, $options = array()) { $dbh = $this->getConnection(); $sth = $dbh->prepare($statement, $options); @$sth->setFetchMode(PDO::FETCH_CLASS, 'Flux_DataObject', array(null, array('dbconfig' => $this->dbConfig))); if ($sth) { return new Flux_Connection_Statement($sth); } else { return false; } } /** * Instanciate a PDOStatement without obtaining a PDO handler before-hand. * * @return PDOStatement * @access public */ public function getStatementForLogs($statement, $options = array()) { $dbh = $this->getLogsConnection(); $sth = $dbh->prepare($statement, $options); @$sth->setFetchMode(PDO::FETCH_CLASS, 'Flux_DataObject', array(null, array('dbconfig' => $this->logsDbConfig))); if ($sth) { return new Flux_Connection_Statement($sth); } else { return false; } } /** * Instanciate a PDOStatement without obtaining a PDO handler before-hand. * * @return PDOStatement * @access public */ public function getStatementForWeb($statement, $options = array()) { $dbh = $this->getWebConnection(); $sth = $dbh->prepare($statement, $options); @$sth->setFetchMode(PDO::FETCH_CLASS, 'Flux_DataObject', array(null, array('dbconfig' => $this->webDbConfig))); if ($sth) { return new Flux_Connection_Statement($sth); } else { return false; } } /** * */ public function reconnectAs($username, $password) { if ($this->pdoMain) { $this->pdoMain = null; } $this->dbConfig->setPersistent(false); $this->dbConfig->setUsername($username); $this->dbConfig->setPassword($password); return true; } /** * */ public function isCaseSensitive($database, $table, $column, $useLogsConnection = false) { $stm = $useLogsConnection ? 'getStatementForLogs' : 'getStatement'; $sql = 'SELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_NAME = ?'; $sth = $this->$stm($sql); $sth->execute(array($database, $table, $column)); $row = $sth->fetch(); if (preg_match('/_ci$/', $row->COLLATION_NAME)) { return false; } else { return true; } } } ?> ================================================ FILE: lib/Flux/DataObject.php ================================================ _dbConfig = $defaults['dbconfig']; unset($defaults['dbconfig']); } else { $tmpArr = array(); $this->_dbConfig = new Flux_Config($tmpArr); } $this->_encFrom = $this->_dbConfig->getEncoding(); $this->_encTo = $this->_encFrom ? $this->_dbConfig->get('Convert') : false; if (!is_null($data)) { $this->_data = $data; } foreach ($defaults as $prop => $value) { if (!isset($this->_data[$prop])) { $this->_data[$prop] = $value; } } if ($this->_encTo) { foreach ($this->_data as $prop => $value) { $this->_data[$prop] = iconv($this->_encFrom, $this->_encTo, $value); } } } public function __set($prop, $value) { $this->_data[$prop] = $value; return $value; } public function __get($prop) { if (isset($this->_data[$prop])) { return $this->_data[$prop]; } else { return null; } } } ?> ================================================ FILE: lib/Flux/Dispatcher.php ================================================ get('basePath'); $paramsArr = $config->get('params'); $modulePath = $config->get('modulePath'); $themePath = $config->get('themePath'); $defaultModule = $config->get('defaultModule'); $themeName = $config->get('themeName'); $defaultAction = $config->get('defaultAction'); $missingActionModuleAction = $config->get('missingActionModuleAction'); $missingViewModuleAction = $config->get('missingViewModuleAction'); $useCleanUrls = $config->get('useCleanUrls'); if (!$defaultModule && $this->defaultModule) { $defaultModule = $this->defaultModule; } if (!$defaultAction && $this->defaultAction) { $defaultAction = $this->defaultAction; } if (!$defaultModule) { throw new Flux_Error('Please set the default module with $dispatcher->setDefaultModule()'); } elseif (!$defaultAction) { throw new Flux_Error('Please set the default action with $dispatcher->setDefaultAction()'); } if (!$paramsArr) { $paramsArr = &$_REQUEST; } // Provide easier access to parameters. $params = new Flux_Config($paramsArr); $baseURI = Flux::config('BaseURI'); if ($params->get('module')) { $safetyArr = array('..', '/', '\\'); $moduleName = str_replace($safetyArr, '', $params->get('module')); if ($params->get('action')) { $actionName = str_replace($safetyArr, '', $params->get('action')); } else { $actionName = $defaultAction; } } elseif (Flux::config('UseCleanUrls')) { $baseURI = preg_replace('&/+&', '/', rtrim($baseURI, '/')).'/'; $requestURI = preg_replace('&/+&', '/', rtrim($_SERVER['REQUEST_URI'], '/')).'/'; $requestURI = preg_replace('&\?.*?$&', '', $requestURI); $components = explode('/', trim((string)substr($requestURI, strlen($baseURI)), '/')); $moduleName = empty($components[0]) ? $defaultModule : $components[0]; $actionName = empty($components[1]) ? $defaultAction : $components[1]; } elseif (!$params->get('module') && !$params->get('action')) { $moduleName = $defaultModule; $actionName = $defaultAction; } // Authorization handling. $auth = Flux_Authorization::getInstance(); if ($auth->actionAllowed($moduleName, $actionName) === false) { if (!Flux::$sessionData->isLoggedIn()) { Flux::$sessionData->setMessageData('Please log-in to continue.'); $this->loginRequired($baseURI); } else { $moduleName = 'unauthorized'; $actionName = $this->defaultAction; } } $params->set('module', $moduleName); $params->set('action', $actionName); $templateArray = array( 'params' => $params, 'basePath' => $basePath, 'modulePath' => $modulePath, 'moduleName' => $moduleName, 'themePath' => $themePath, 'themeName' => $themeName, 'actionName' => $actionName, 'viewName' => $actionName, 'headerName' => 'header', 'footerName' => 'footer', 'missingActionModuleAction' => $missingActionModuleAction, 'missingViewModuleAction' => $missingViewModuleAction, 'useCleanUrls' => $useCleanUrls ); $templateConfig = new Flux_Config($templateArray); $template = new Flux_Template($templateConfig); // Default data available to all actions and views. $data = array( 'auth' => Flux_Authorization::getInstance(), 'session' => Flux::$sessionData, 'params' => $params ); $template->setDefaultData($data); // Render template! :D $template->render(); } /** * This usually needs to be called after instanciating the dispatcher, as * it's very necessary to the dispatcher's failsafe functionality. * * @param string $module Module name * @return string * @access public */ public function setDefaultModule($module) { $this->defaultModule = $module; return $module; } /** * (DEPRECATED) By default, 'index' is the default action for any module, but you may * override that by using this method. * * @param string $action Action name * @return string * @access public */ public function setDefaultAction($action) { $this->defaultAction = $action; return $action; } /** * Redirect to login page if the user is not currently logged in. * * @param string $baseURI * @param string $loginModule * @param string $loginAction * @access private */ public function loginRequired($baseURI, $message = null, $loginModule = 'account', $loginAction = 'login') { $session = Flux::$sessionData; if (!$message) { $message = 'Please login to continue.'; } if (!$session->isLoggedIn()) { if (Flux::config('UseCleanUrls')) { $loginURL = sprintf('%s/%s/%s/?return_url=%s', $baseURI, $loginModule, $loginAction, rawurlencode($_SERVER['REQUEST_URI'])); } else { $loginURL = sprintf('%s/?module=%s&action=%s&return_url=%s', $baseURI, rawurlencode($loginModule), rawurlencode($loginAction), rawurlencode($_SERVER['REQUEST_URI'])); } $session->setMessageData($message); header('Location: '.preg_replace('&/{2,}&', '/', $loginURL)); exit; } } } ?> ================================================ FILE: lib/Flux/EmblemExporter.php ================================================ loginAthenaGroup = $loginAthenaGroup; } /** * */ public function addAthenaServer(Flux_Athena $athenaServer) { if (!in_array($athenaServer, $this->loginAthenaGroup->athenaServers, true)) { throw new Flux_Error( "{$athenaServer->serverName} is not a valid char/map server defined in the {$this->loginAthenaGroup->serverName} group."); } $this->athenaServers[$athenaServer->serverName] = $athenaServer; } /** * */ public function exportArchive() { $topDir = $this->sanitizePathName($this->loginAthenaGroup->serverName); $tmpDir = FLUX_DATA_DIR.'/tmp'; $tmpFile = tempnam($tmpDir, 'zip'); // Create zip archive. $zip = new ZipArchive(); $zip->open($tmpFile, ZIPARCHIVE::OVERWRITE); $zip->addEmptyDir($topDir); foreach ($this->athenaServers as $athenaServer) { $athenaDir = $this->sanitizePathName($athenaServer->serverName); $zip->addEmptyDir("$topDir/$athenaDir"); $sql = "SELECT name, emblem_data FROM {$athenaServer->charMapDatabase}.guild WHERE emblem_len > 0 ORDER BY name ASC"; $sth = $athenaServer->connection->getStatement($sql); $sth->execute(); $guilds = $sth->fetchAll(); if ($guilds) { foreach ($guilds as $guild) { $emblemData = @gzuncompress(pack('H*', $guild->emblem_data)); $emblemImage = imagecreatefrombmpstring($emblemData); ob_start(); imagepng($emblemImage); $data = ob_get_clean(); $emblemName = sprintf('%s.png', $this->sanitizePathName($guild->name)); $zip->addFromString("$topDir/$athenaDir/$emblemName", $data); } } } // Close archive. $zip->close(); // Send out appropriate HTTP headers. $filename = urlencode(sprintf('%s-%s-emblems.zip', strtolower($topDir), date('Ymd'))); header('Content-Type: application/zip'); header('Content-Length: '.filesize($tmpFile)); header("Content-Disposition: attachment; filename=$filename"); // Read contents of the file. readfile($tmpFile); // Remove temporary file. unlink($tmpFile); exit; } /** * */ private function sanitizePathName($pathName) { return preg_replace('/[^\w\d ]+/', '', $pathName); } } ?> ================================================ FILE: lib/Flux/Error.php ================================================ ================================================ FILE: lib/Flux/FileLoad.php ================================================ 'The uploaded file exceeds the upload_max_filesize directive in php.ini', 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', 3 => 'The uploaded file was only partially uploaded', 4 => 'No file was uploaded', 6 => 'Missing a temporary folder', 7 => 'Failed to write file to disk', 8 => 'A PHP extension stopped the file upload' ); public function load($file, $path){ $this->path = $path; if($file->get('error')){ return $this->errorCodeMessages[$file->get('error')]; } if(is_uploaded_file($file->get('tmp_name'))) { if(move_uploaded_file($file->get('tmp_name'), $path)) { return true; } } return 'During the boot file error occurred'; } public function delete(){ unlink($this->path); } } ================================================ FILE: lib/Flux/Installer/CharMapServer.php ================================================ mainServer = $mainServer; $this->athena = $athena; $this->schemas = Flux_Installer_Schema::getSchemas($mainServer, $this); } } ?> ================================================ FILE: lib/Flux/Installer/MainServer.php ================================================ loginAthenaGroup = $loginAthenaGroup; $this->schemas = Flux_Installer_Schema::getSchemas($this); if (array_key_exists($loginAthenaGroup->serverName, Flux::$athenaServerRegistry)) { foreach (Flux::$athenaServerRegistry[$loginAthenaGroup->serverName] as $athena) { $this->charMapServers[$athena->serverName] = new Flux_Installer_CharMapServer($this, $athena); } } } /** * */ public function updateAll() { foreach ($this->schemas as $schema) { if (!$schema->isLatest()) { $schema->update(); } } foreach ($this->charMapServers as $charMapServer) { foreach ($charMapServer->schemas as $schema) { if (!$schema->isLatest()) { $schema->update(); } } } } } ?> ================================================ FILE: lib/Flux/Installer/Schema.php ================================================ mainServerName = $dataArray['mainServerName']; $this->charMapServerName = $dataArray['charMapServerName']; $this->databaseName = $dataArray['databaseName']; $this->connection = $dataArray['connection']; $this->availableSchemaDir = $dataArray['availableSchemaDir']; $this->installedSchemaDir = $dataArray['installedSchemaDir']; $this->schemaInfo = $dataArray['schemaInfo']; ksort($this->schemaInfo['versions']); $this->determineInstalledVersions(); } /** * */ protected function determineInstalledVersions() { foreach ($this->schemaInfo['versions'] as $version => $installed) { if ($installed) { $this->versionInstalled = $version; } $this->latestVersion = $version; $this->latestVersionInstalled = $installed; } } /** * */ public function install($version) { if (!array_key_exists($version, $this->schemaInfo['versions']) || !$this->schemaInfo['versions'][$version]) { // Switch database. $this->connection->useDatabase($this->databaseName); // Get schema content. $sql = file_get_contents($this->schemaInfo['files'][$version]); $sth = $this->connection->getStatement($sql); // Execute. $sth->execute(); if ($sth->errorCode()) { $errorInfo = $sth->errorInfo(); if (count($errorInfo) > 1) { list ($sqlstate, $errnum, $errmsg) = $errorInfo; } else { $errmsg = implode(', ', $errorInfo); } if (!empty($errnum) && $errnum == 1045) { throw new Flux_Error("Critical MySQL error in Installer/Updater: $errnum: $errmsg"); } elseif (!empty($errnum) && $errnum == 1142) { // Bail-out. $message = "MySQL error: $errmsg\n\n"; throw new Flux_Installer_SchemaPermissionError( $message, $this->schemaInfo['files'][$version], $this->databaseName, $this->mainServerName, $this->charMapServerName, $sql ); } elseif (!empty($errmsg) && strcmp($errmsg,'00000') != 0) { // Only quit with an error if there is actually an error. throw new Flux_Error("Critical MySQL error in Installer/Updater: $errmsg"); } } $this->schemaInfo['versions'][$version] = true; $this->determineInstalledVersions(); // Create file indicating schema is installed. $file = "{$this->schemaInfo['name']}.$version.txt"; fclose(fopen("{$this->installedSchemaDir}/{$file}", 'w')); } else { return false; } } /** * */ public function update() { if (!$this->isLatest()) { foreach ($this->schemaInfo['versions'] as $version => $installed) { if (!$installed) { $this->install($version); } } return true; } else { return false; } } /** * */ public function versionInstalled($version) { $installed = array_key_exists($version, $this->schemaInfo['versions']) && $this->schemaInfo['versions'][$version]; return $installed; } /** * */ public function isLatest() { return $this->latestVersionInstalled; } /** * */ public static function getSchemas(Flux_Installer_MainServer $mainServer, Flux_Installer_CharMapServer $charMapServer = null) { $mainServerName = $mainServer->loginAthenaGroup->serverName; if (is_null($charMapServer)) { $charMapServerName = null; $databaseName = $mainServer->loginAthenaGroup->loginDatabase; $connection = $mainServer->loginAthenaGroup->connection; $availableSchemaDir = array(FLUX_DATA_DIR."/schemas/logindb"); $installedSchemaDir = FLUX_DATA_DIR."/logs/schemas/logindb/$mainServerName"; foreach (Flux::$addons as $addon) { $_schemaDir = "{$addon->addonDir}/schemas/logindb"; if (file_exists($_schemaDir) && is_dir($_schemaDir)) { $availableSchemaDir[] = $_schemaDir; } } } else { $charMapServerName = $charMapServer->athena->serverName; $databaseName = $charMapServer->athena->charMapDatabase; $connection = $charMapServer->athena->connection; $availableSchemaDir = array(FLUX_DATA_DIR."/schemas/charmapdb"); $installedSchemaDir = FLUX_DATA_DIR."/logs/schemas/charmapdb/$mainServerName/{$charMapServer->athena->serverName}"; foreach (Flux::$addons as $addon) { $_schemaDir = "{$addon->addonDir}/schemas/charmapdb"; if (file_exists($_schemaDir) && is_dir($_schemaDir)) { $availableSchemaDir[] = $_schemaDir; } } } $dataArray = array( 'mainServerName' => $mainServerName, 'charMapServerName' => $charMapServerName, 'databaseName' => $databaseName, 'connection' => $connection, //'availableSchemaDir' => $availableSchemaDir, 'installedSchemaDir' => $installedSchemaDir, ); $availableSchemas = array(); $installedSchemas = array(); $directories = array(); foreach ($availableSchemaDir as $dir) { $directories[] = array($dir, 'availableSchemas', 'sql'); } $directories[] = array($installedSchemaDir, 'installedSchemas', 'txt'); foreach ($directories as $directory) { list ($schemaDir, $schemaArray, $fileExt) = $directory; $schemas = &$$schemaArray; $sFiles = glob("$schemaDir/*.$fileExt"); if (!$sFiles) { $sFiles = array(); } foreach ($sFiles as $schemaFilePath) { $schemaName = basename($schemaFilePath, ".$fileExt"); if (preg_match('/^(\w+)\.(\d+)$/', $schemaName, $m)) { $schemaName = $m[1]; $schemaVersion = $m[2]; // Dynamically set schema directory. $dataArray['availableSchemaDir'] = $directory; if (!array_key_exists($schemaName, $schemas)) { $schemas[$schemaName] = array( 'name' => $schemaName, 'versions' => array(), ); } $schemas[$schemaName]['versions'][$schemaFilePath] = $schemaVersion; } } } $objects = array(); foreach ($availableSchemas as $schemaName => $schema) { $schemaInfo = array( 'name' => $schemaName, 'versions' => array_flip($schema['versions']), 'files' => array_flip($schema['versions']) ); foreach ($schemaInfo['versions'] as $key => $value) { $schemaInfo['versions'][$key] = false; } if (array_key_exists($schemaName, $installedSchemas)) { foreach ($installedSchemas[$schemaName]['versions'] as $key => $value) { $schemaInfo['versions'][$value] = true; } } $dataArray['schemaInfo'] = $schemaInfo; $objects[] = new Flux_Installer_Schema($dataArray); } return $objects; } } ?> ================================================ FILE: lib/Flux/Installer/SchemaPermissionError.php ================================================ schemaFile = $schemaFile; $this->databaseName = $databaseName; $this->mainServerName = $mainServerName; $this->charMapServerName = $charMapServerName; $this->query = $query; } public function isLoginDbSchema() { return $this->mainServerName && !$this->charMapServerName; } public function isCharMapDbSchema() { return $this->mainServerName && $this->charMapServerName; } } ?> ================================================ FILE: lib/Flux/Installer/index.html ================================================ ================================================ FILE: lib/Flux/Installer.php ================================================ $loginAthenaGroup) { $this->servers[$serverName] = new Flux_Installer_MainServer($loginAthenaGroup); } } /** * */ public static function getInstance() { if (!self::$installer) { self::$installer = new Flux_Installer(); } return self::$installer; } /** * */ public function updateNeeded() { foreach ($this->servers as $mainServer) { foreach ($mainServer->schemas as $schema) { if (!$schema->isLatest()) { return true; } } foreach ($mainServer->charMapServers as $charMapServer) { foreach ($charMapServer->schemas as $schema) { if (!$schema->isLatest()) { return true; } } } } return false; } /** * */ public function updateAll() { foreach ($this->servers as $mainServer) { foreach ($mainServer->schemas as $schema) { if (!$schema->isLatest()) { $schema->update(); } } foreach ($mainServer->charMapServers as $charMapServer) { foreach ($charMapServer->schemas as $schema) { if (!$schema->isLatest()) { $schema->update(); } } } } } } ?> ================================================ FILE: lib/Flux/ItemExistsError.php ================================================ ================================================ FILE: lib/Flux/ItemShop/Cart.php ================================================ account = $account; return $account; } public function requiresAccount() { if (!$this->account) { throw new Flux_Error('Account is required to use the shopping cart.'); } } public function add(Flux_DataObject $item) { $this->cart[] = $item; return $item; } public function delete(Flux_DataObject $item, $deleteAll = false) { $deleted = array(); foreach ($this->cart as $cartItem) { if ($cartItem == $item) { if ($deleteAll) { $deleted[] = $cartItem; } else { return $cartItem; } } } if ($deleted) { return $deleted; } else { return false; } } public function deleteAll(Flux_DataObject $item) { return $this->delete($item, true); } public function clear() { $itemCount = count($this->cart); $this->cart = array(); return $itemCount; } public function buy(Flux_ItemShop $fromShop) { if (!$this->hasFunds()) { return false; } $successful = array(); foreach ($this->cart as $cartItem) { $successful[] = array( 'item' => $cartItem, 'name' => $cartItem->shop_item_name, 'cost' => $cartItem->shop_item_cost, 'quantity' => $cartItem->shop_item_qty, 'success' => $fromShop->buy($cartItem->shop_item_id) ); } $this->clear(); return $successful; } public function getCartItems() { return $this->cart; } public function getCartItemNames() { $names = array(); foreach ($this->cart as $cartItem) { $names[] = $cartItem->shop_item_name; } return $names; } public function getTotal() { $total = 0; foreach ($this->cart as $cartItem) { $total += $cartItem->shop_item_cost; } return $total; } public function hasFunds() { $this->requiresAccount(); $creditsAvailable = $this->account->balance; $creditsNeeded = $this->getTotal(); if ($creditsAvailable < $creditsNeeded) { return false; } else { return true; } } /** * Check if the cart is empty. */ public function isEmpty() { $empty = !count($this->cart); return $empty; } public function deleteByItemNum($num) { if (!is_array($num)) { $num = array((int)$num); } else { $num = array_map('intval', $num); } $nDeleted = 0; foreach ($num as $n) { if (array_key_exists($n, $this->cart)) { unset($this->cart[$n]); $nDeleted += 1; } } return $nDeleted; } } ?> ================================================ FILE: lib/Flux/ItemShop/index.html ================================================ ================================================ FILE: lib/Flux/ItemShop.php ================================================ server = $server; } /** * Add an item to the shop. */ public function add($itemID, $categoryID, $cost, $quantity, $info, $useExisting = 0) { $db = $this->server->charMapDatabase; $table = Flux::config('FluxTables.ItemShopTable'); $sql = "INSERT INTO $db.$table (nameid, category, quantity, cost, info, use_existing, create_date) VALUES (?, ?, ?, ?, ?, ?, NOW())"; $sth = $this->server->connection->getStatement($sql); $res = $sth->execute(array($itemID, $categoryID, $quantity, $cost, $info, $useExisting)); $sth2 = $this->server->connection->getStatement('SELECT LAST_INSERT_ID() AS insID'); $res2 = $sth2->execute(); if ($res && $res2 && ($insertID=$sth2->fetch()->insID)) { return $insertID; } else { return false; } } /** * Modify item info in the shop. */ public function edit($shopItemID, $categoryID = null, $cost = null, $quantity = null, $info = null, $useExisting = null) { $catQ = ''; $crdQ = ''; $qtyQ = ''; $infQ = ''; $imgQ = ''; $bind = array(); if (!is_null($categoryID)) { $catQ = "category = ? "; $bind[] = (int)$categoryID; } if (!is_null($cost)) { if ($catQ) { $crdQ = ", cost = ? "; } else { $crdQ = "cost = ? "; } $bind[] = (int)$cost; } if (!is_null($quantity)) { if ($crdQ) { $qtyQ = ', quantity = ? '; } else { $qtyQ = "quantity = ? "; } $bind[] = (int)$quantity; } if (!is_null($info)) { if ($qtyQ) { $infQ = ', info = ? '; } else { $infQ = "info = ? "; } $bind[] = trim($info); } if (!is_null($useExisting)) { if ($infQ) { $imgQ = ', use_existing = ? '; } else { $imgQ = "use_existing = ? "; } $bind[] = (int)$useExisting; } if (empty($bind)) { return false; } $db = $this->server->charMapDatabase; $table = Flux::config('FluxTables.ItemShopTable'); $sql = "UPDATE $db.$table SET $catQ $crdQ $qtyQ $infQ $imgQ WHERE id = ?"; $sth = $this->server->connection->getStatement($sql); $bind[] = $shopItemID; return $sth->execute($bind); } /** * */ public function delete($shopItemID) { $db = $this->server->charMapDatabase; $table = Flux::config('FluxTables.ItemShopTable'); $sql = "DELETE FROM $db.$table WHERE id = ?"; $sth = $this->server->connection->getStatement($sql); return $sth->execute(array($shopItemID)); } /** * */ public function buy(Flux_DataObject $account, $shopItemID) { } /** * */ public function getItem($shopItemID) { $db = $this->server->charMapDatabase; if($this->server->isRenewal) { $fromTables = array("$db.item_db_re", "$db.item_db2_re"); } else { $fromTables = array("$db.item_db", "$db.item_db2"); } $temp = new Flux_TemporaryTable($this->server->connection, "$db.items", $fromTables); $shop = Flux::config('FluxTables.ItemShopTable'); $col = "$shop.id AS shop_item_id, $shop.category AS shop_item_category, $shop.cost AS shop_item_cost, $shop.quantity AS shop_item_qty, $shop.use_existing AS shop_item_use_existing, "; $col .= "$shop.nameid AS shop_item_nameid, $shop.info AS shop_item_info, items.name_english AS shop_item_name"; $sql = "SELECT $col FROM $db.$shop LEFT OUTER JOIN $db.items ON items.id = $shop.nameid WHERE $shop.id = ?"; $sth = $this->server->connection->getStatement($sql); if ($sth->execute(array($shopItemID))) { return $sth->fetch(); } else { return false; } } /** * */ public function getItems($paginator, $categoryID = null) { $sqlpartial = ""; $bind = array(); $db = $this->server->charMapDatabase; if($this->server->isRenewal) { $fromTables = array("$db.item_db_re", "$db.item_db2_re"); } else { $fromTables = array("$db.item_db", "$db.item_db2"); } $temp = new Flux_TemporaryTable($this->server->connection, "$db.items", $fromTables); $shop = Flux::config('FluxTables.ItemShopTable'); $col = "$shop.id AS shop_item_id, $shop.cost AS shop_item_cost, $shop.quantity AS shop_item_qty, $shop.use_existing AS shop_item_use_existing, "; $col .= "$shop.nameid AS shop_item_nameid, $shop.info AS shop_item_info, items.name_english AS shop_item_name"; if (!is_null($categoryID)) { $sqlpartial = " WHERE $shop.category = ?"; $bind[] = $categoryID; } $sql = $paginator->getSQL("SELECT $col FROM $db.$shop LEFT OUTER JOIN $db.items ON items.id = $shop.nameid $sqlpartial"); $sth = $this->server->connection->getStatement($sql); if ($sth->execute($bind)) { return $sth->fetchAll(); } else { return false; } } /** * */ public function deleteShopItemImage($shopItemID) { $serverName = $this->server->loginAthenaGroup->serverName; $athenaServerName = $this->server->serverName; $dir = FLUX_DATA_DIR."/itemshop/$serverName/$athenaServerName"; $files = glob("$dir/$shopItemID.*"); foreach ($files as $file) { unlink($file); } return true; } /** * */ public function uploadShopItemImage($shopItemID, Flux_Config $file) { if ($file->get('error')) { return false; } $validexts = array_map('strtolower', Flux::config('ShopImageExtensions')->toArray()); $extension = strtolower(pathinfo($file->get('name'), PATHINFO_EXTENSION)); if (!in_array($extension, $validexts)) { return false; } $serverName = $this->server->loginAthenaGroup->serverName; $athenaServerName = $this->server->serverName; $dir = FLUX_DATA_DIR."/itemshop/$serverName/$athenaServerName"; if (!is_dir(FLUX_DATA_DIR."/itemshop/$serverName")) { mkdir(FLUX_DATA_DIR."/itemshop/$serverName"); } if (!is_dir($dir)) { mkdir($dir); } $this->deleteShopItemImage($shopItemID); if (move_uploaded_file($file->get('tmp_name'), "$dir/$shopItemID.$extension")) { return true; } else { return false; } } } ?> ================================================ FILE: lib/Flux/LogFile.php ================================================ filename = "$filename.php"; $isNewFile = !file_exists($this->filename); if ($isNewFile) { touch($this->filename); chmod($this->filename, 0600); } $this->fp = fopen($this->filename, $mode); if ($isNewFile) { fputs($this->fp, "\n"); } } /** * Close file handle. */ public function __destruct() { if ($this->fp) { fclose($this->fp); } } /** * Write a line to the log file. * * @param string $format * @param string $var, ... * @access public */ public function puts() { $args = func_get_args(); if (count($args) > 0) { $args[0] = sprintf("%s%s\n", date($this->dateFormat), $args[0]); $arguments = array_merge(array($this->fp), $args); return call_user_func_array('fprintf', $arguments); } else { return false; } } } ?> ================================================ FILE: lib/Flux/LoginAthenaGroup.php ================================================ serverName = $serverName; $this->connection = $connection; $this->loginServer = $loginServer; $this->loginDatabase = $loginServer->config->getDatabase(); $this->logsDatabase = $connection->logsDbConfig->getDatabase(); $this->webDatabase = $connection->webDbConfig->getDatabase(); // Assign connection to LoginServer, used mainly to enable // authentication feature. $this->loginServer->setConnection($connection); foreach ($athenaServers as $athenaServer) { $this->addAthenaServer($athenaServer); } } /** * Add an Athena instance to the current collection. * * @return mixed Returns false if login servers aren't identical. * @access public */ public function addAthenaServer(Flux_Athena $athenaServer) { if ($athenaServer->loginServer === $this->loginServer) { $athenaServer->setLoginAthenaGroup($this); $athenaServer->setConnection($this->connection); $this->athenaServers[] = $athenaServer; return $this->athenaServers; } else { return false; } } /** * See Flux_LoginServer->isAuth(). * * @param string $username * @param string $password * @return bool * @access public */ public function isAuth($username, $password) { return $this->loginServer->isAuth($username, $password); } } ?> ================================================ FILE: lib/Flux/LoginError.php ================================================ ================================================ FILE: lib/Flux/LoginServer.php ================================================ loginDatabase = $config->getDatabase(); } /** * Set the connection object to be used for this LoginServer instance. * * @param Flux_Connection $connection * @return Flux_Connection * @access public */ public function setConnection(Flux_Connection $connection) { $this->connection = $connection; $this->logsDatabase = $connection->logsDbConfig->getDatabase(); $this->webDatabase = $connection->webDbConfig->getDatabase(); return $connection; } /** * Validate credentials against the login server's database information. * * @param string $username Ragnarok account username. * @param string $password Ragnarok account password. * @return bool True/false if valid or invalid. * @access public */ public function isAuth($username, $password) { if (trim($username) == '' || trim($password) == '') { return false; } if ($this->config->get('UseMD5')) { $password = Flux::hashPassword($password); } $sql = "SELECT userid FROM {$this->loginDatabase}.login WHERE sex != 'S' AND group_id >= 0 "; if ($this->config->getNoCase()) { $sql .= 'AND LOWER(userid) = LOWER(?) '; } else { $sql .= 'AND CAST(userid AS BINARY) = ? '; } $sql .= "AND user_pass = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); $sth->execute(array($username, $password)); $res = $sth->fetch(); if ($res) { return true; } else { return false; } } /** * */ public function register($username, $password, $confirmPassword, $email,$email2, $gender, $birthdate, $securityCode) { if (preg_match('/[^' . Flux::config('UsernameAllowedChars') . ']/', $username)) { throw new Flux_RegisterError('Invalid character(s) used in username', Flux_RegisterError::INVALID_USERNAME); } elseif (strlen($username) < Flux::config('MinUsernameLength')) { throw new Flux_RegisterError('Username is too short', Flux_RegisterError::USERNAME_TOO_SHORT); } elseif (strlen($username) > Flux::config('MaxUsernameLength')) { throw new Flux_RegisterError('Username is too long', Flux_RegisterError::USERNAME_TOO_LONG); } elseif (!Flux::config('AllowUserInPassword') && stripos($password, $username) !== false) { throw new Flux_RegisterError('Password contains username', Flux_RegisterError::PASSWORD_HAS_USERNAME); } elseif (!ctype_graph($password)) { throw new Flux_RegisterError('Invalid character(s) used in password', Flux_RegisterError::INVALID_PASSWORD); } elseif (strlen($password) < Flux::config('MinPasswordLength')) { throw new Flux_RegisterError('Password is too short', Flux_RegisterError::PASSWORD_TOO_SHORT); } elseif (strlen($password) > Flux::config('MaxPasswordLength')) { throw new Flux_RegisterError('Password is too long', Flux_RegisterError::PASSWORD_TOO_LONG); } elseif ($password !== $confirmPassword) { throw new Flux_RegisterError('Passwords do not match', Flux_RegisterError::PASSWORD_MISMATCH); } elseif (Flux::config('PasswordMinUpper') > 0 && preg_match_all('/[A-Z]/', $password, $matches) < Flux::config('PasswordMinUpper')) { throw new Flux_RegisterError('Passwords must contain at least ' . intval(Flux::config('PasswordMinUpper')) . ' uppercase letter(s)', Flux_RegisterError::PASSWORD_NEED_UPPER); } elseif (Flux::config('PasswordMinLower') > 0 && preg_match_all('/[a-z]/', $password, $matches) < Flux::config('PasswordMinLower')) { throw new Flux_RegisterError('Passwords must contain at least ' . intval(Flux::config('PasswordMinLower')) . ' lowercase letter(s)', Flux_RegisterError::PASSWORD_NEED_LOWER); } elseif (Flux::config('PasswordMinNumber') > 0 && preg_match_all('/[0-9]/', $password, $matches) < Flux::config('PasswordMinNumber')) { throw new Flux_RegisterError('Passwords must contain at least ' . intval(Flux::config('PasswordMinNumber')) . ' number(s)', Flux_RegisterError::PASSWORD_NEED_NUMBER); } elseif (Flux::config('PasswordMinSymbol') > 0 && preg_match_all('/[^A-Za-z0-9]/', $password, $matches) < Flux::config('PasswordMinSymbol')) { throw new Flux_RegisterError('Passwords must contain at least ' . intval(Flux::config('PasswordMinSymbol')) . ' symbol(s)', Flux_RegisterError::PASSWORD_NEED_SYMBOL); } elseif (!preg_match('/^(.+?)@(.+?)$/', $email)) { throw new Flux_RegisterError('Invalid e-mail address', Flux_RegisterError::INVALID_EMAIL_ADDRESS); } elseif ($email!==$email2) { throw new Flux_RegisterError('Email do not match', Flux_RegisterError::INVALID_EMAIL_CONF); } elseif (!in_array(strtoupper($gender), array('M', 'F'))) { throw new Flux_RegisterError('Invalid gender', Flux_RegisterError::INVALID_GENDER); } elseif (($birthdatestamp = strtotime($birthdate)) === false || date('Y-m-d', $birthdatestamp) != $birthdate) { throw new Flux_RegisterError('Invalid birthdate', Flux_RegisterError::INVALID_BIRTHDATE); } elseif (Flux::config('UseCaptcha')) { if (Flux::config('EnableReCaptcha')) { if(isset($_POST['g-recaptcha-response']) && $_POST['g-recaptcha-response'] != ""){ $response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".Flux::config('ReCaptchaPrivateKey')."&response=".$_POST['g-recaptcha-response']."&remoteip=".$_SERVER['REMOTE_ADDR']); } $responseKeys = json_decode($response,true); if(intval($responseKeys["success"]) !== 1) { throw new Flux_RegisterError('Invalid security code', Flux_RegisterError::INVALID_SECURITY_CODE); } } elseif (strtolower($securityCode) !== strtolower(Flux::$sessionData->securityCode)) { throw new Flux_RegisterError('Invalid security code', Flux_RegisterError::INVALID_SECURITY_CODE); } } $sql = "SELECT userid FROM {$this->loginDatabase}.login WHERE "; if ($this->config->getNoCase()) { $sql .= 'LOWER(userid) = LOWER(?) '; } else { $sql .= 'BINARY userid = ? '; } $sql .= 'LIMIT 1'; $sth = $this->connection->getStatement($sql); $sth->execute(array($username)); $res = $sth->fetch(); if ($res) { throw new Flux_RegisterError('Username is already taken', Flux_RegisterError::USERNAME_ALREADY_TAKEN); } if (!Flux::config('AllowDuplicateEmails')) { $sql = "SELECT email FROM {$this->loginDatabase}.login WHERE email = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); $sth->execute(array($email)); $res = $sth->fetch(); if ($res) { throw new Flux_RegisterError('E-mail address is already in use', Flux_RegisterError::EMAIL_ADDRESS_IN_USE); } } if ($this->config->getUseMD5()) { $password = Flux::hashPassword($password); } $sql = "INSERT INTO {$this->loginDatabase}.login (userid, user_pass, email, sex, group_id, birthdate) VALUES (?, ?, ?, ?, ?, ?)"; $sth = $this->connection->getStatement($sql); $res = $sth->execute(array($username, $password, $email, $gender, (int)$this->config->getGroupID(), date('Y-m-d', $birthdatestamp))); if ($res) { $idsth = $this->connection->getStatement("SELECT LAST_INSERT_ID() AS account_id"); $idsth->execute(); $idres = $idsth->fetch(); $createTable = Flux::config('FluxTables.AccountCreateTable'); $sql = "INSERT INTO {$this->loginDatabase}.{$createTable} (account_id, userid, user_pass, sex, email, reg_date, reg_ip, confirmed) "; $sql .= "VALUES (?, ?, ?, ?, ?, NOW(), ?, 1)"; $sth = $this->connection->getStatement($sql); $sth->execute(array($idres->account_id, $username, $password, $gender, $email, $_SERVER['REMOTE_ADDR'])); return $idres->account_id; } else { return false; } } /** * */ public function temporarilyBan($bannedBy, $banReason, $accountID, $until) { $table = Flux::config('FluxTables.AccountBanTable'); $sql = "INSERT INTO {$this->loginDatabase}.$table (account_id, banned_by, ban_type, ban_until, ban_date, ban_reason) "; $sql .= "VALUES (?, ?, 1, ?, NOW(), ?)"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($accountID, $bannedBy, $until, $banReason))) { $ts = strtotime($until); $sql = "UPDATE {$this->loginDatabase}.login SET state = 0, unban_time = '$ts' WHERE account_id = ?"; $sth = $this->connection->getStatement($sql); return $sth->execute(array($accountID)); } else { return false; } } /** * */ public function permanentlyBan($bannedBy, $banReason, $accountID) { $table = Flux::config('FluxTables.AccountBanTable'); $sql = "INSERT INTO {$this->loginDatabase}.$table (account_id, banned_by, ban_type, ban_until, ban_date, ban_reason) "; $sql .= "VALUES (?, ?, 2, '9999-12-31 23:59:59', NOW(), ?)"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($accountID, $bannedBy, $banReason))) { $sql = "UPDATE {$this->loginDatabase}.login SET state = 5, unban_time = 0 WHERE account_id = ?"; $sth = $this->connection->getStatement($sql); return $sth->execute(array($accountID)); } else { return false; } } /** * */ public function unban($unbannedBy, $unbanReason, $accountID) { $table = Flux::config('FluxTables.AccountBanTable'); $createTable = Flux::config('FluxTables.AccountCreateTable'); $sql = "INSERT INTO {$this->loginDatabase}.$table (account_id, banned_by, ban_type, ban_until, ban_date, ban_reason) "; $sql .= "VALUES (?, ?, 0, '1000-01-01 00:00:00', NOW(), ?)"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($accountID, $unbannedBy, $unbanReason))) { $sql = "UPDATE {$this->loginDatabase}.$createTable SET confirmed = 1, confirm_expire = NULL WHERE account_id = ?"; $sth = $this->connection->getStatement($sql); $sth->execute(array($accountID)); $sql = "UPDATE {$this->loginDatabase}.login SET state = 0, unban_time = 0 WHERE account_id = ?"; $sth = $this->connection->getStatement($sql); return $sth->execute(array($accountID)); } else { return false; } } /** * */ public function getBanInfo($accountID) { $table = Flux::config('FluxTables.AccountBanTable'); $col = "$table.id, $table.account_id, $table.banned_by, $table.ban_type, "; $col .= "$table.ban_until, $table.ban_date, $table.ban_reason, login.userid"; $sql = "SELECT $col FROM {$this->loginDatabase}.$table "; $sql .= "LEFT OUTER JOIN {$this->loginDatabase}.login ON login.account_id = $table.banned_by "; $sql .= "WHERE $table.account_id = ? ORDER BY $table.ban_date DESC "; $sth = $this->connection->getStatement($sql); $res = $sth->execute(array($accountID)); if ($res) { $ban = $sth->fetchAll(); return $ban; } else { return false; } } /** * */ public function addIpBan($bannedBy, $banReason, $unbanTime, $ipAddress) { $table = Flux::config('FluxTables.IpBanTable'); $sql = "INSERT INTO {$this->loginDatabase}.$table (ip_address, banned_by, ban_type, ban_until, ban_date, ban_reason) "; $sql .= "VALUES (?, ?, 1, ?, NOW(), ?)"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($ipAddress, $bannedBy, $unbanTime, $banReason))) { $sql = "INSERT INTO {$this->loginDatabase}.ipbanlist (list, reason, rtime, btime) "; $sql .= "VALUES (?, ?, ?, NOW())"; $sth = $this->connection->getStatement($sql); return $sth->execute(array($ipAddress, $banReason, $unbanTime)); } else { return false; } } /** * */ public function removeIpBan($unbannedBy, $unbanReason, $ipAddress) { $table = Flux::config('FluxTables.IpBanTable'); $sql = "INSERT INTO {$this->loginDatabase}.$table (ip_address, banned_by, ban_type, ban_until, ban_date, ban_reason) "; $sql .= "VALUES (?, ?, 0, '1000-01-01 00:00:00', NOW(), ?)"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($ipAddress, $unbannedBy, $unbanReason))) { $sql = "DELETE FROM {$this->loginDatabase}.ipbanlist WHERE list = ?"; $sth = $this->connection->getStatement($sql); return $sth->execute(array($ipAddress)); } else { return false; } } /** * */ public function hasCreditsRecord($accountID) { $creditsTable = Flux::config('FluxTables.CreditsTable'); $sql = "SELECT COUNT(account_id) AS hasRecord FROM {$this->loginDatabase}.$creditsTable WHERE account_id = ?"; $sth = $this->connection->getStatement($sql); $sth->execute(array($accountID)); if ($sth->fetch()->hasRecord) { return true; } else { return false; } } /** * */ public function depositCredits($targetAccountID, $credits, $donationAmount = null) { $sql = "SELECT COUNT(account_id) AS accountExists FROM {$this->loginDatabase}.login WHERE account_id = ?"; $sth = $this->connection->getStatement($sql); if (!$sth->execute(array($targetAccountID)) || !$sth->fetch()->accountExists) { return false; // Account doesn't exist. } $creditsTable = Flux::config('FluxTables.CreditsTable'); if (!$this->hasCreditsRecord($targetAccountID)) { $fields = 'account_id, balance'; $values = '?, ?'; if (!is_null($donationAmount)) { $fields .= ', last_donation_date, last_donation_amount'; $values .= ', NOW(), ?'; } $sql = "INSERT INTO {$this->loginDatabase}.$creditsTable ($fields) VALUES ($values)"; $sth = $this->connection->getStatement($sql); $vals = array($targetAccountID, $credits); if (!is_null($donationAmount)) { $vals[] = $donationAmount; } return $sth->execute($vals); } else { $vals = array(); $sql = "UPDATE {$this->loginDatabase}.$creditsTable SET balance = balance + ? "; if (!is_null($donationAmount)) { $sql .= ", last_donation_date = NOW(), last_donation_amount = ? "; } $vals[] = $credits; if (!is_null($donationAmount)) { $vals[] = $donationAmount; } $vals[] = $targetAccountID; $sql .= "WHERE account_id = ?"; $sth = $this->connection->getStatement($sql); return $sth->execute($vals); } } /** * */ public function getPrefs($accountID, array $prefs = array()) { $sql = "SELECT account_id FROM {$this->loginDatabase}.`login` WHERE account_id = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($accountID)) && ($char=$sth->fetch())) { $accountPrefsTable = Flux::config('FluxTables.AccountPrefsTable'); $pref = array(); $bind = array($accountID); $sql = "SELECT name, value FROM {$this->loginDatabase}.$accountPrefsTable "; $sql .= "WHERE account_id = ?"; if ($prefs) { foreach ($prefs as $p) { $pref[] = "name = ?"; $bind[] = $p; } $sql .= sprintf(' AND (%s)', implode(' OR ', $pref)); } $sth = $this->connection->getStatement($sql); if ($sth->execute($bind)) { $prefsArray = array(); foreach ($sth->fetchAll() as $p) { $prefsArray[$p->name] = $p->value; } return new Flux_Config($prefsArray); } else { return false; } } else { return false; } } /** * */ public function setPrefs($accountID, array $prefsArray) { $sql = "SELECT account_id FROM {$this->loginDatabase}.`login` WHERE account_id = ? LIMIT 1"; $sth = $this->connection->getStatement($sql); if ($sth->execute(array($accountID)) && ($char=$sth->fetch())) { $accountPrefsTable = Flux::config('FluxTables.AccountPrefsTable'); $pref = array(); $bind = array($accountID); $sql = "SELECT id, name, value FROM {$this->loginDatabase}.$accountPrefsTable "; $sql .= "WHERE account_id = ?"; if ($prefsArray) { foreach ($prefsArray as $prefName => $prefValue) { $pref[] = "name = ?"; $bind[] = $prefName; } $sql .= sprintf(' AND (%s)', implode(' OR ', $pref)); } $sth = $this->connection->getStatement($sql); if ($sth->execute($bind)) { $prefs = $sth->fetchAll(); $update = array(); $usql = "UPDATE {$this->loginDatabase}.$accountPrefsTable "; $usql .= "SET value = ? WHERE id = ?"; $usth = $this->connection->getStatement($usql); $isql = "INSERT INTO {$this->loginDatabase}.$accountPrefsTable "; $isql .= "(account_id, name, value, create_date) "; $isql .= "VALUES (?, ?, ?, NOW())"; $isth = $this->connection->getStatement($isql); foreach ($prefs as $p) { $update[$p->name] = $p->id; } foreach ($prefsArray as $pref => $value) { if (array_key_exists($pref, $update)) { $id = $update[$pref]; $usth->execute(array($value, $id)); } else { $isth->execute(array($accountID, $pref, $value)); } } return true; } else { return false; } } else { return false; } } /** * */ public function getPref($accountID, $pref) { $prefs = $this->getPrefs($accountID, array($pref)); if ($prefs instanceOf Flux_Config) { return $prefs->get($pref); } else { return false; } } /** * */ public function setPref($accountID, $pref, $value) { return $this->setPrefs($accountID, array($pref => $value)); } /** * */ public function isIpBanned($ip = null) { if (is_null($ip)) { $ip = $_SERVER['REMOTE_ADDR']; } $ip = trim($ip); if (!preg_match('/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $ip, $m)) { // Invalid IP. return false; } $sql = "SELECT list FROM {$this->loginDatabase}.ipbanlist WHERE "; $sql .= "rtime > NOW() AND (list = ? OR list = ? OR list = ? OR list = ?) LIMIT 1"; $sth = $this->connection->getStatement($sql); $list = array( sprintf('%u.*.*.*', $m[1]), sprintf('%u.%u.*.*', $m[1], $m[2]), sprintf('%u.%u.%u.*', $m[1], $m[2], $m[3]), sprintf('%u.%u.%u.%u', $m[1], $m[2], $m[3], $m[4]) ); $sth->execute($list); $ipban = $sth->fetch(); if ($ipban) { return true; } else { return false; } } } ?> ================================================ FILE: lib/Flux/Mailer.php ================================================ pm = $pm = new PHPMailer(); $this->errLog = self::$errLog; $this->log = self::$log; if (Flux::config('MailerUseSMTP')) { $pm->IsSMTP(); if (is_array($hosts=Flux::config('MailerSMTPHosts'))) { $hosts = implode(';', $hosts); } $pm->Host = $hosts; if ($user=Flux::config('MailerSMTPUsername')) { $pm->SMTPAuth = true; if (Flux::config('MailerSMTPUseTLS')) { $pm->SMTPSecure = 'tls'; } if (Flux::config('MailerSMTPUseSSL')) { $pm->SMTPSecure = 'ssl'; } if ($port=Flux::config('MailerSMTPPort')) { $pm->Port = (int)$port; } $pm->Username = $user; if ($pass=Flux::config('MailerSMTPPassword')) { $pm->Password = $pass; } } } // From address. $pm->setFrom(Flux::config('MailerFromAddress'), Flux::config('MailerFromName')); } public function send($recipient, $subject, $template, array $templateVars = array()) { if (array_key_exists('_ignoreTemplate', $templateVars) && $templateVars['_ignoreTemplate']) { $content = $template; } else { $templatePath = FLUX_DATA_DIR."/templates/$template.php"; if (!file_exists($templatePath)) { return false; } $find = array(); $repl = array(); foreach ($templateVars as $key => $value) { $find[] = '{'.$key.'}'; $repl[] = $value; } ob_start(); include $templatePath; $content = ob_get_clean(); if (!empty($find) && !empty($repl)) { $content = str_replace($find, $repl, $content); } } $this->pm->isHTML(true); $this->pm->CharSet = 'UTF-8'; $this->pm->AddAddress($recipient); $this->pm->Subject = $subject; $this->pm->msgHTML($content); if ($sent=$this->pm->Send()) { self::$log->puts("sent e-mail -- Recipient: $recipient, Subject: $subject"); } else { self::$errLog->puts("{$this->pm->ErrorInfo} (while attempting -- Recipient: $recipient, Subject: $subject)"); } return $sent; } } ?> ================================================ FILE: lib/Flux/MapServer.php ================================================ ================================================ FILE: lib/Flux/Paginator.php ================================================ requestURI = $requestURI; $perPage = Flux::config('ResultsPerPage'); if (!$perPage) { $perPage = 20; } $pagesToShow = Flux::config('PagesToShow'); if (!$pagesToShow) { $pagesToShow = 10; } $showSinglePage = (bool)Flux::config('ShowSinglePage'); $options = array_merge( array( 'showSinglePage' => $showSinglePage, 'perPage' => $perPage, 'pagesToShow' => $pagesToShow, 'pageVariable' => 'p', 'pageSeparator' => '|'), $options ); $this->total = (int)$total; $this->showSinglePage = $options['showSinglePage']; $this->perPage = $options['perPage']; $this->pagesToShow = $options['pagesToShow']; $this->pageVariable = $options['pageVariable']; $this->pageSeparator = $options['pageSeparator']; $this->currentPage = isset($_GET[$this->pageVariable]) && $_GET[$this->pageVariable] > 0 ? $_GET[$this->pageVariable] : 1; $this->calculatePages(); } /** * Calculate the number of pages. * * @access private */ private function calculatePages() { $this->numberOfPages = (int)ceil($this->total / $this->perPage); } /** * Get an SQL query with the "LIMIT offset,num" and appropriate "ORDER BY" * strings appended to the end. * * @param string $sql * @return string * @access public */ public function getSQL($sql) { $orderBy = false; foreach ($this->sortableColumns as $column => $value) { if (strpos($column, '.') !== false) { list ($table, $column) = explode('.', $column, 2); $param = "{$table}_{$column}_order"; $columnName = "`{$table}`.`{$column}`"; } else { $table = false; $param = "{$column}_order"; $columnName = "`$column`"; } $sortValues = array('ASC', 'DESC', 'NONE'); // First, check if a GET parameter was passed for this column. if (isset($_GET[$param]) && in_array(strtoupper($_GET[$param]), $sortValues)) { $value = $_GET[$param]; } // Check again just in case we're working with the default here. if (!is_null($value) && in_array( ($value=strtoupper($value)), $sortValues ) && $value != 'NONE') { $this->currentSortOrder[str_replace("`", "", $columnName)] = $value; if (!$orderBy) { $sql .= ' ORDER BY'; $orderBy = true; } if ($value == 'ASC') { $sql .= " (CASE WHEN $columnName IS NULL THEN 1 ELSE 0 END) ASC, $columnName ASC,"; } else { $sql .= " $columnName $value,"; } } } if ($orderBy) { $sql = rtrim($sql, ','); } $offset = ($this->perPage * $this->currentPage) - $this->perPage; return "$sql LIMIT $offset,{$this->perPage}"; } /** * Generate some basic HTML which creates a list of page numbers. Will * return an empty string if DisplaySinglePages config is set to false. * * @return string * @access public */ public function getHTML() { if (!Flux::config('DisplaySinglePages') && $this->numberOfPages === 1) { return ''; } $pages = array(); $start = (floor(($this->currentPage - 1) / $this->pagesToShow) * $this->pagesToShow) + 1; $end = $start + $this->pagesToShow + 1; if ($end > $this->numberOfPages) { $end = $this->numberOfPages + 1; } else { $end = $end - 1; } $hasPrev = $start > 1; $hasNext = $end < $this->numberOfPages; for ($i = $start; $i < $end; ++$i) { $request = $this->getPageURI($i); if ($i == $this->currentPage) { $pages[] = sprintf( '%d', $i, $i ); } else { $pages[] = sprintf( '%d', $request, $i, $i ); } } if ($hasPrev) { array_unshift($pages, sprintf('Prev. ', $this->getPageURI($start - 1), $start - 1)); } if ($hasNext) { array_push($pages, sprintf(' Next', $this->getPageURI($end), $end)); } $links = sprintf('
%s
', implode(" {$this->pageSeparator} ", $pages))."\n"; if (Flux::config('ShowPageJump') && $this->numberOfPages > Flux::config('PageJumpMinimumPages')) { // This is some tricky shit. Don't even attempt to understand it =( // Page jumping is entirely JavaScript dependent. $pageVar = preg_quote($this->pageVariable); $event = "location.href='".$this->getPageURI(0)."'"; $event = preg_replace("/$pageVar=0/", "{$this->pageVariable}='+this.value+'", $event); $jump = ''; $jump = sprintf($jump, $event); $links .= sprintf('
%s
', $jump); } if (!$this->showSinglePage && $this->numberOfPages === 1) { return null; } else { return $links; } } /** * Create a link to the current request with a different page number. * * @param int $pageNumber * @return string * @access protected */ protected function getPageURI($pageNumber) { $request = preg_replace('/(\?.*)$/', '', $this->requestURI); $qString = $_SERVER['QUERY_STRING']; $pageVar = preg_quote($this->pageVariable); $pageNum = (int)$pageNumber; $qStringVars = array(); $qStringLines = preg_split('/&/', $qString, -1, PREG_SPLIT_NO_EMPTY); foreach ($qStringLines as $qStringVar) { if (strpos($qStringVar, '=') !== false) { list($qStringKey, $qStringVal) = explode('=', $qStringVar, 2); $qStringVars[$qStringKey] = $qStringVal; } } $qStringVars[$pageVar] = $pageNum; $qStringLines = array(); foreach ($qStringVars as $qStringKey => $qStringVal) { $qStringLines[] = sprintf('%s=%s', $qStringKey, $qStringVal); } return sprintf('%s?%s', $request, implode('&', $qStringLines)); } /** * Specify an array (or a string single column name) of columns that are * sortable by the paginator's features. * * @param array $columns * @return array * @access public */ public function setSortableColumns($columns) { if (!is_array($columns)) { $columns = array($columns); } foreach ($columns as $key => $column) { if (!is_numeric($key)) { $value = $column; $column = $key; } else { $value = null; } $this->sortableColumns[$column] = $value; } return $this->sortableColumns; } /** * Get an HTML anchor which automatically links to the current request * based on current sorting conditions and sets ascending/descending * sorting parameters accordingly. * * @param string $column * @param string $name * @return string * @access public */ public function sortableColumn($column, $name = null) { if (!$name) { $name = $column; } if (!array_key_exists($column, $this->sortableColumns)) { return htmlspecialchars($name); } else { if (strpos($column, '.') !== false) { list ($_table, $_column) = explode('.', $column, 2); $param = "{$_table}_{$_column}_order"; } else { $param = "{$column}_order"; } $order = 'asc'; $format = '%s'; $name = htmlspecialchars($name); $request = $_SERVER['REQUEST_URI']; if (isset($this->currentSortOrder[$column])) { switch (strtolower($this->currentSortOrder[$column])) { case 'asc': $order = 'desc'; $name .= Flux::config('ColumnSortAscending'); break; case 'desc': $order = is_null($this->sortableColumns[$column]) ? false : 'none'; $name .= Flux::config('ColumnSortDescending'); break; default: $order = 'asc'; break; } } if ($order) { $value = "$param=$order"; if (preg_match("/$param=(\w*)/", $request)) { $request = preg_replace("/$param=(\w*)/", $value, $request); } elseif (empty($_SERVER['QUERY_STRING'])) { $request = "$request?$value"; } else { $request = "$request&$value"; } return sprintf($format, $request, $name); } else { $request = rtrim(preg_replace("%(?:(\?)$param=(?:\w*)&?|&?$param=(?:\w*))%", '$1', $request), '?'); return sprintf($format, $request, $name); } } } /** * */ public function infoText() { $currPage = $this->currentPage; $results = $this->perPage; $infoText = sprintf( Flux::message('FoundSearchResults'), $this->total, $this->numberOfPages, ($currPage*$results-($results - 1)), $currPage * $results < $this->total ? ($currPage*$results) : ($this->total) ); return sprintf('

%s

', $infoText); } } ?> ================================================ FILE: lib/Flux/PaymentNotifyRequest.php ================================================ ppLogFile = new Flux_LogFile(FLUX_DATA_DIR.'/logs/paypal.log'); $this->ppServer = Flux::config('PayPalIpnUrl'); $this->myBusinessEmail = Flux::config('PayPalBusinessEmail'); $this->myCurrencyCode = strtoupper(Flux::config('DonationCurrency')); $this->ipnVariables = new Flux_Config($ipnPostVars); $this->txnLogTable = Flux::config('FluxTables.TransactionTable'); $this->creditsTable = Flux::config('FluxTables.CreditsTable'); } /** * Log to PayPal log file. Works like printf(). * * @param string $format * @param mixed ... * @return string * @access protected */ protected function logPayPal() { $args = func_get_args(); $func = array($this->ppLogFile, 'puts'); return call_user_func_array($func, $args); } /** * Get user IP. * Checks if CloudFlare used to get real IP. * * @access public */ protected function fetchIP() { $alt_ip = $_SERVER['REMOTE_ADDR']; if (isset($_SERVER['HTTP_X_REAL_IP'])) { $alt_ip = $_SERVER['HTTP_X_REAL_IP']; } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $alt_ip = $_SERVER['HTTP_X_FORWARDED_FOR']; } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) { $alt_ip = $_SERVER['HTTP_CLIENT_IP']; } elseif (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) { $alt_ip = $_SERVER['HTTP_CF_CONNECTING_IP']; } return $alt_ip; } /** * Process transaction. * * @access public */ public function process() { $allowed_hosts = Flux::config('PayPalAllowedHosts')->toArray(); $received_from = gethostbyaddr($this->fetchIP()); $this->logPayPal('Received notification from %s (%s)', $this->fetchIP(), $received_from); if ((in_array($received_from, $allowed_hosts) && $this->verify()) || $this->verifyiprange($received_from)) { $this->logPayPal('Proceeding to validate the authenticity of the transaction...'); $accountEmails = Flux::config('PayPalReceiverEmails'); $accountEmails = array_merge(array($this->myBusinessEmail), $accountEmails->toArray()); $receiverEmail = $this->ipnVariables->get('receiver_email'); $transactionID = $this->ipnVariables->get('txn_id'); $paymentStatus = $this->ipnVariables->get('payment_status'); $payerEmail = $this->ipnVariables->get('payer_email'); $currencyCode = strtoupper(substr($this->ipnVariables->get('mc_currency'), 0, 3)); $trusted = true; // Identify transaction number. $this->logPayPal('Transaction identified as %s.', $transactionID); if (!in_array($receiverEmail, $accountEmails)) { $this->logPayPal('Receiver e-mail (%s) is not recognized, unauthorized to continue.', $receiverEmail); } else { $customArray = @unserialize(base64_decode((string)$this->ipnVariables->get('custom'))); $customArray = $customArray && is_array($customArray) ? $customArray : array(); $customData = new Flux_Config($customArray); $accountID = $customData->get('account_id'); $serverName = $customData->get('server_name'); if ($currencyCode != $this->myCurrencyCode) { $this->logPayPal('Transaction currency not exchangeable, accepting anyways. (recv: %s, expected: %s)', $currencyCode, $this->myCurrencyCode); $exchangeableCurrency = false; } else { $exchangeableCurrency = true; } // How much was received? (and in what currency?) $this->logPayPal('Received %s (%s).', $this->ipnVariables->get('mc_gross'), $currencyCode); // How much will be deposited? $settleAmount = $this->ipnVariables->get('settle_amount'); $settleCurrency = $this->ipnVariables->get('settle_currency'); if ($settleAmount && $settleCurrency) { $this->logPayPal('Deposited into PayPal account: %s %s.', $settleAmount, $settleCurrency); } // Let's see where the donation credits should go to. $this->logPayPal('Game server name: %s, account ID: %s', ($serverName ? $serverName : '(absent)'), ($accountID ? $accountID : '(absent)')); if (!$accountID || !$serverName) { $this->logPayPal('Account ID and/or game server name absent, cannot exchange for credits.'); } elseif ($this->ipnVariables->get('txn_type') != 'web_accept') { $this->logPayPal('Transaction type is not web_accept, amount will not be exchanged for credits.'); } elseif (!($servGroup = Flux::getServerGroupByName($serverName))) { $this->logPayPal('Unknown game server "%s", cannot process donation for credits.', $serverName); } if ($paymentStatus == 'Completed') { $this->logPayPal('Payment for txn_id#%s has been completed.', $transactionID); if ($servGroup && $exchangeableCurrency) { $sql = "SELECT COUNT(account_id) AS acc_id_count FROM {$servGroup->loginDatabase}.login WHERE sex != 'S' AND group_id >= 0 AND account_id = ?"; $sth = $servGroup->connection->getStatement($sql); $sth->execute(array($accountID)); $res = $sth->fetch(); if (!$res) { $this->logPayPal('Unknown account #%s on server %s, cannot exchange for credits.', $accountID, $serverName); } else { if (!$servGroup->loginServer->hasCreditsRecord($accountID)) { $this->logPayPal('Identified as first-time donation to the server from this account.'); } $amount = (float)$this->ipnVariables->get('mc_gross'); $minimum = (float)Flux::config('MinDonationAmount'); if ($amount >= $minimum) { $trustTable = Flux::config('FluxTables.DonationTrustTable'); $holdHours = +(int)Flux::config('HoldUntrustedAccount'); if ($holdHours) { $sql = "SELECT account_id, email FROM {$servGroup->loginDatabase}.$trustTable WHERE account_id = ? AND email = ? LIMIT 1"; $sth = $servGroup->connection->getStatement($sql); $sth->execute(array($accountID, $payerEmail)); $res = $sth->fetch(); if ($res && $res->account_id) { $this->logPayPal('Account ID and e-mail are trusted.'); $trusted = true; } else { $trusted = false; } } $rate = Flux::config('CreditExchangeRate'); $credits = floor($amount / $rate); if ($trusted) { $sql = "SELECT * FROM {$servGroup->loginDatabase}.{$this->creditsTable} WHERE account_id = ?"; $sth = $servGroup->connection->getStatement($sql); $sth->execute(array($accountID)); $acc = $sth->fetch(); $this->logPayPal('Updating account credit balance from %s to %s', (int)$acc->balance, $acc->balance + $credits); $res = $servGroup->loginServer->depositCredits($accountID, $credits, $amount); if ($res) { $this->logPayPal('Deposited credits.'); } else { $this->logPayPal('Failed to deposit credits.'); } } else { $this->logPayPal('Account/e-mail is not trusted, holding donation credits for %d hours.', $holdHours); } } else { $this->logPayPal('User has donated less than the configured minimum, not exchanging credits.'); } } } } else { $this->logPayPal('Incomplete payment status: %s (exchanging for credits will not take place)', $paymentStatus); $banStatuses = Flux::config('BanPaymentStatuses'); if ($banStatuses instanceOf Flux_Config) { $banStatuses = $banStatuses->toArray(); } else { $banStatuses = array(); } $pymntStatus = strtolower($paymentStatus); $banStatuses = array_map('strtolower', $banStatuses); if (in_array($pymntStatus, $banStatuses)) { $this->logPayPal('Auto-ban payment status detected: %s', $paymentStatus); if ($servGroup && $serverName && $accountID) { $this->logPayPal('Banning account! (serv: %s, account_id: %s)', $serverName, $accountID); $servGroup->loginServer->permanentlyBan( null, "Banned for invalid payment status: $paymentStatus", $accountID ); } else { $this->logPayPal("Couldn't ban account, it's unknown."); } } } if (!$servGroup) { foreach (Flux::$loginAthenaGroupRegistry as $servGroup) { $this->logToPayPalTable($servGroup, $accountID, $serverName, $trusted); } } else { if (empty($credits)) { $credits = 0; } $this->logToPayPalTable($servGroup, $accountID, $serverName, $trusted, $credits); } $this->logPayPal('Saving transaction details for %s...', $transactionID); if ($logFile=$this->saveDetailsToFile()) { $this->logPayPal('Saved transaction details for %s to: %s', $transactionID, $logFile); } else { $this->logPayPal('Failed to save transaction details for %s to file.', $transactionID); } $this->logPayPal('Done processing %s.', $transactionID); } } else { $this->logPayPal('Transaction invalid, aborting.'); if(!in_array($received_from, $allowed_hosts) && Flux::config('PaypalHackNotify')){ require_once 'Flux/Mailer.php'; $customArray = @unserialize(base64_decode((string)$this->ipnVariables->get('custom'))); $customArray = $customArray && is_array($customArray) ? $customArray : array(); $customData = new Flux_Config($customArray); $accountID = $customData->get('account_id'); $serverName = $customData->get('server_name'); $mail = new Flux_Mailer(); $tmpl = "

Paypal hack detected!

"; $tmpl .= "

Account: ".$accountID."

"; $tmpl .= "

serverName: ".$serverName."

"; $tmpl .= "


"; $tmpl .= "

======= IP Info ========

"; $tmpl .= nl2br(var_export(['ip' => $this->fetchIP(), 'host' => $received_from], true)); $tmpl .= "

======= End IP Info ========

"; $tmpl .= "


"; $tmpl .= "

======= Account Info ========

"; $tmpl .= nl2br(var_export($customData, true)); $tmpl .= "

======= End Account Info ========

"; $tmpl .= "


"; $tmpl .= "

======= Transaction Info ========

"; $tmpl .= nl2br(var_export($this->ipnVariables->toArray(), true)); $tmpl .= "

======= End Transaction Info ========

"; $accountEmails = Flux::config('PayPalReceiverEmails'); $accountEmails = array_merge(array($this->myBusinessEmail), $accountEmails->toArray()); foreach($accountEmails as $email) { $sent = $mail->send($email, '['.Flux::config('SiteTitle').'] Paypal hack', $tmpl, array('_ignoreTemplate' => true)); } $this->logPayPal('Hack detected!'); } } return false; } /** * Translate the IPN variables into a query string for use in a POST * request. * * @return string * @access private */ private function ipnVarsToQueryString() { $ipnVars = $this->ipnVariables->toArray(); $qString = ''; foreach ($ipnVars as $key => $value) { $qString .= sprintf('&%s=%s', $key, urlencode($value)); } $qString = ltrim($qString, '&'); return $qString; } /** * Verify IPN variables against PayPal server. * * Updated to comply with changes being implemented Feb 1, 2013 * https://www.x.com/node/320404 * * @return bool True if verified, false if not. * @access private */ private function verify() { $qString = 'cmd=_notify-validate&'.$this->ipnVarsToQueryString(); $request = "POST /cgi-bin/webscr HTTP/1.1\r\n"; $request .= "Content-Type: application/x-www-form-urlencoded\r\n"; $request .= 'Content-Length: '.strlen($qString)."\r\n"; $request .= 'Host: '.$this->ppServer."\r\n"; $request .= "Connection: close\r\n\r\n"; $request .= $qString; $this->logPayPal('Query string: %s', $qString); $this->logPayPal('Establishing connection to PayPal server at %s:443...', $this->ppServer); $fp = @fsockopen('ssl://'.$this->ppServer, 443, $errno, $errstr, 20); if (!$fp) { $this->logPayPal("Failed to connect to PayPal server: [%d] %s", $errno, $errstr); return false; } else { $this->logPayPal('Connected. Sending request back to PayPal...'); // Send POST request just as PayPal sent it. $this->logPayPal('Sent %d bytes of transaction data. Request size: %d bytes.', strlen($qString), fputs($fp, $request)); $this->logPayPal('Reading back response from PayPal...'); // Read until body starts while (!feof($fp) && ($line = trim(fgets($fp))) != ''); $line = ''; // Read until EOF, contains VERIFIED or INVALID. while (!feof($fp)) { $line .= strtoupper(trim(fgets($fp))); } // Close connection. fclose($fp); // Check verification status of the notify request. if (strpos($line, 'VERIFIED') !== false) { $this->logPayPal('Notification verified. (recv: %s)', $line); $this->txnIsValid = true; return true; } else { $this->logPayPal('Notification failed to verify. (recv: %s)', $line); return false; } } } /* */ private function verifyiprange($received_from) { $allowed_hosts = Flux::config('PayPalAllowedHosts')->toArray(); $ip_long = ip2long ( $received_from ); for ($i = 0; $i < 72; $i++) { if(strpos($allowed_hosts[$i], '/') !== false) { $ip_arr = explode ( '/' , $allowed_hosts[$i] ); $network_long = ip2long ( $ip_arr[0] ); $x = ip2long ( $ip_arr [1]); $mask = long2ip ( $x ) == $ip_arr [ 1 ] ? $x : 0xffffffff << ( 32 - $ip_arr [ 1 ]); if(( $ip_long & $mask ) == ( $network_long & $mask )) return true; } else { if($allowed_hosts[$i] == $received_from) return true; } } return false; } /** * Save the transaction details to disk in the file name format of: * data/logs/transactions/TXN_TYPE/PAYMENT_STATUS.log * * @return string File name * @access private */ private function saveDetailsToFile() { if ($this->txnIsValid) { $logDir1 = realpath(FLUX_DATA_DIR.'/logs/transactions'); $logDir2 = $logDir1.'/'.$this->ipnVariables->get('txn_type'); $logDir3 = $logDir2.'/'.$this->ipnVariables->get('payment_status'); $logFile = $logDir3.'/'.$this->ipnVariables->get('txn_id').'.log.php'; if (!is_dir($logDir2)) { mkdir($logDir2, 0600); } if (!is_dir($logDir3)) { mkdir($logDir3, 0600); } $fp = fopen($logFile, 'w'); if ($fp) { fwrite($fp, "\n"); foreach ($this->ipnVariables->toArray() as $key => $value) { fwrite($fp, "$key: $value\n"); } fclose($fp); return $logFile; } } return false; } /** * Log the transaction details into the flux_paypal_transactions table. * * @param Flux_LoginAthenaGroup $servGroup * @param string $accountID * @param string $serverName * @access private */ private function logToPayPalTable(Flux_LoginAthenaGroup $servGroup, $accountID, $serverName, $trusted, $credits = 0) { if ($this->txnIsValid) { $holdUntil = null; if (!$trusted) { $email = $this->ipnVariables->get('payer_email'); $sql = "SELECT hold_until FROM {$servGroup->loginDatabase}.{$this->txnLogTable} "; $sql .= "WHERE account_id = ? AND payer_email = ? AND hold_until > NOW() AND payment_status = 'Completed' LIMIT 1"; $sth = $sth = $servGroup->connection->getStatement($sql); $sth->execute(array($accountID, $email)); $row = $sth->fetch(); if ($row && $row->hold_until) { $holdUntil = $row->hold_until; } else { $hours = +(int)Flux::config('HoldUntrustedAccount'); $holdUntil = date('Y-m-d H:i:s', time()+($hours*60*60)); } } $this->logPayPal('Saving transaction details to PayPal transactions table...'); $sql = " INSERT INTO {$servGroup->loginDatabase}.{$this->txnLogTable} ( account_id, server_name, credits, receiver_email, item_name, item_number, quantity, payment_status, pending_reason, payment_date, mc_gross, mc_fee, tax, mc_currency, parent_txn_id, txn_id, txn_type, first_name, last_name, address_street, address_city, address_state, address_zip, address_country, address_status, payer_email, payer_status, payment_type, notify_version, verify_sign, referrer_id, process_date, hold_until ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), ? ) "; $var = $this->ipnVariables; $sth = $servGroup->connection->getStatement($sql); $ret = $sth->execute(array( $accountID, $serverName, $credits, $var->get('receiver_email'), $var->get('item_name'), $var->get('item_number'), $var->get('quantity'), $var->get('payment_status'), $var->get('pending_reason'), $var->get('payment_date'), $var->get('mc_gross'), $var->get('mc_fee'), $var->get('tax'), $var->get('mc_currency'), $var->get('parent_txn_id'), $var->get('txn_id'), $var->get('txn_type'), $var->get('first_name'), $var->get('last_name'), $var->get('address_street'), $var->get('address_city'), $var->get('address_state'), $var->get('address_zip'), $var->get('address_country'), $var->get('address_status'), $var->get('payer_email'), $var->get('payer_status'), $var->get('payment_type'), $var->get('notify_version'), $var->get('verify_sign'), $var->get('receiver_id'), $holdUntil )); if ($ret) { if (!trim($serverName)) { $serverName = '(unknown)'; } $this->logPayPal('Stored information in PayPal transactions table for server %s.', $serverName); } else { $errorInfo = implode('/', $sth->errorInfo()); $this->logPayPal('Failed to save information in PayPal transactions table. (%s)', $errorInfo); } } } } ?> ================================================ FILE: lib/Flux/PermissionError.php ================================================ ================================================ FILE: lib/Flux/RegisterError.php ================================================ ================================================ FILE: lib/Flux/SessionData.php ================================================ sessionData = &$sessionData; if ($logout) { $this->logout(); } else { $this->initialize(); } } /** * Initialize session data. * * @param bool $force * @return bool * @access private */ private function initialize($force = false) { $keysToInit = array('username', 'serverName', 'athenaServerName', 'securityCode', 'theme'); foreach ($keysToInit as $key) { if ($force || !$this->{$key}) { $method = ucfirst($key); $method = "set{$method}Data"; $this->$method(null); } } $loggedIn = true; if (!$this->username) { $loggedIn = false; $cfgAthenaServerName = Flux::config('DefaultCharMapServer'); $cfgLoginAthenaGroup = Flux::config('DefaultLoginGroup'); if (Flux::getServerGroupByName($cfgLoginAthenaGroup)){ $this->setServerNameData($cfgLoginAthenaGroup); } else { $defaultServerName = current(array_keys(Flux::$loginAthenaGroupRegistry)); $this->setServerNameData($defaultServerName); } } if ($this->serverName && ($this->loginAthenaGroup = Flux::getServerGroupByName($this->serverName))) { $this->loginServer = $this->loginAthenaGroup->loginServer; if (!$loggedIn && $cfgAthenaServerName && $this->getAthenaServer($cfgAthenaServerName)) { $this->setAthenaServerNameData($cfgAthenaServerName); } if (!$this->athenaServerName || ((!$loggedIn && !$this->getAthenaServer($cfgAthenaServerName)) || !$this->getAthenaServer($this->athenaServerName))) { $this->setAthenaServerNameData(current($this->getAthenaServerNames())); } } // Get new account data every request. if ($this->loginAthenaGroup && $this->username && ($account = $this->getAccount($this->loginAthenaGroup, $this->username))) { $this->account = $account; $this->account->group_level = AccountLevel::getGroupLevel($account->group_id); // Automatically log out of account when detected as banned. $permBan = ($account->state == 5 && !Flux::config('AllowPermBanLogin')); $tempBan = (($account->unban_time > 0 && $account->unban_time < time()) && !Flux::config('AllowTempBanLogin')); if ($permBan || $tempBan) { $this->logout(); } } else { $this->account = new Flux_DataObject(null, array('group_level' => AccountLevel::UNAUTH)); } if (!is_array($this->cart)) { $this->setCartData(array()); } if ($this->account->account_id && $this->loginAthenaGroup) { if (!array_key_exists($this->loginAthenaGroup->serverName, $this->cart)) { $this->cart[$this->loginAthenaGroup->serverName] = array(); } foreach ($this->getAthenaServerNames() as $athenaServerName) { $athenaServer = $this->getAthenaServer($athenaServerName); $cartArray = &$this->cart[$this->loginAthenaGroup->serverName]; $accountID = $this->account->account_id; if (!array_key_exists($accountID, $cartArray)) { $cartArray[$accountID] = array(); } if (!array_key_exists($athenaServerName, $cartArray[$accountID])) { $cartArray[$accountID][$athenaServerName] = new Flux_ItemShop_Cart(); } $cartArray[$accountID][$athenaServerName]->setAccount($this->account); $athenaServer->setCart($cartArray[$accountID][$athenaServerName]); } } if (!$this->theme || $this->theme === 'installer') { // always update if coming from installer $this->setThemeData(Flux::config('ThemeName.0')); } return true; } /** * Log current user out. * * @return bool * @access public */ public function logout() { $this->loginAthenaGroup = null; $this->loginServer = null; return $this->initialize(true); } public function __call($method, $args) { if (count($args) && preg_match('/set(.+?)Data/', $method, $m)) { $arg = current($args); $meth = $m[1]; $meth[0] = strtolower($meth[0]); if (array_key_exists($meth, $this->dataFilters)) { foreach ($this->dataFilters[$meth] as $callback) { $arg = call_user_func($callback, $arg); } } $this->sessionData[$meth] = $arg; } } public function &__get($prop) { $value = null; if (array_key_exists($prop, $this->sessionData)) { $value = &$this->sessionData[$prop]; } return $value; } /** * Set session data. * * @param array $keys Session keys to be affected. * @param mixed $value Value to be assigned to all specified keys. * @return mixed whatever was set * @access public */ public function setData(array $keys, $value) { foreach ($keys as $key) { $key = ucfirst($key); $this->{"set{$key}Data"}($value); } return $value; } /** * Add a session data setter filter. * * @param string $key Which session key * @param string $callback Function callback. * @return string Callback * @access public */ public function addDataFilter($key, $callback) { if (!array_key_exists($key, $this->dataFilters)) { $this->dataFilters[$key] = array(); } $this->dataFilters[$key][] = $callback; return $callback; } /** * Checks whether the current user is logged in. */ public function isLoggedIn() { return $this->account->group_level >= AccountLevel::NORMAL; } /** * Check securityCode from user with $this->securityCode or reCaptcha * @param $securityCode Code from user * @param $recaptcha True if check using recaptcha * @return true on success and false on failure */ public function checkSecurityCode($securityCode, $recaptcha = false) { if ($recaptcha) { if (Flux::config('ReCaptchaPrivateKey') && Flux::config('ReCaptchaPublicKey')) { $responseKeys = array(); if (isset($_POST['g-recaptcha-response']) && $_POST['g-recaptcha-response'] != "") { $response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".Flux::config('ReCaptchaPrivateKey')."&response=".$_POST['g-recaptcha-response']."&remoteip=".$_SERVER['REMOTE_ADDR']); $responseKeys = json_decode($response,true); } if (count($responseKeys) && intval($responseKeys["success"]) == 1) { return true; } } } else if ($securityCode && !empty($securityCode) && strtolower($securityCode) == strtolower($this->securityCode)) { return true; } return false; } /** * User login. * * @param string $server Server name * @param string $username * @param string $password * @throws Flux_LoginError * @access public */ public function login($server, $username, $password, $securityCode = null) { $loginAthenaGroup = Flux::getServerGroupByName($server); if (!$loginAthenaGroup) { throw new Flux_LoginError('Invalid server.', Flux_LoginError::INVALID_SERVER); } if ($loginAthenaGroup->loginServer->isIpBanned() && !Flux::config('AllowIpBanLogin')) { throw new Flux_LoginError('IP address is banned', Flux_LoginError::IPBANNED); } if (Flux::config('UseLoginCaptcha') && !self::checkSecurityCode($securityCode, Flux::config('EnableReCaptcha'))) { throw new Flux_LoginError('Invalid security code', Flux_LoginError::INVALID_SECURITY_CODE); } if (!$loginAthenaGroup->isAuth($username, $password)) { throw new Flux_LoginError('Invalid login', Flux_LoginError::INVALID_LOGIN); } $creditsTable = Flux::config('FluxTables.CreditsTable'); $creditColumns = 'credits.balance, credits.last_donation_date, credits.last_donation_amount'; $sql = "SELECT login.*, {$creditColumns} FROM {$loginAthenaGroup->loginDatabase}.login "; $sql .= "LEFT OUTER JOIN {$loginAthenaGroup->loginDatabase}.{$creditsTable} AS credits ON login.account_id = credits.account_id "; $sql .= "WHERE login.sex != 'S' AND login.group_id >= 0 AND login.userid = ? LIMIT 1"; $smt = $loginAthenaGroup->connection->getStatement($sql); $res = $smt->execute(array($username)); if ($res && ($row = $smt->fetch())) { if ($row->unban_time > 0) { if (time() >= $row->unban_time) { $row->unban_time = 0; $sql = "UPDATE {$loginAthenaGroup->loginDatabase}.login SET unban_time = 0 WHERE account_id = ?"; $sth = $loginAthenaGroup->connection->getStatement($sql); $sth->execute(array($row->account_id)); } elseif (!Flux::config('AllowTempBanLogin')) { throw new Flux_LoginError('Temporarily banned', Flux_LoginError::BANNED); } } if ($row->state == 5) { $createTable = Flux::config('FluxTables.AccountCreateTable'); $sql = "SELECT id FROM {$loginAthenaGroup->loginDatabase}.$createTable "; $sql .= "WHERE account_id = ? AND confirmed = 0"; $sth = $loginAthenaGroup->connection->getStatement($sql); $sth->execute(array($row->account_id)); $row2 = $sth->fetch(); if ($row2 && $row2->id) { throw new Flux_LoginError('Pending confirmation', Flux_LoginError::PENDING_CONFIRMATION); } } if (!Flux::config('AllowPermBanLogin') && $row->state == 5) { throw new Flux_LoginError('Permanently banned', Flux_LoginError::PERMABANNED); } $this->setServerNameData($server); $this->setUsernameData($username); $this->initialize(false); } else { $message = "Unexpected error during login.\n"; $message .= 'PDO error info, if any: '.print_r($smt->errorInfo(), true); throw new Flux_LoginError($message, Flux_LoginError::UNEXPECTED); } return true; } /** * Get account object for a particular user name. * * @param Flux_LoginAthenaGroup $loginAthenaGroup * @param string $username * @return mixed * @access private */ private function getAccount(Flux_LoginAthenaGroup $loginAthenaGroup, $username) { $creditsTable = Flux::config('FluxTables.CreditsTable'); $creditColumns = 'credits.balance, credits.last_donation_date, credits.last_donation_amount'; $sql = "SELECT login.*, {$creditColumns} FROM {$loginAthenaGroup->loginDatabase}.login "; $sql .= "LEFT OUTER JOIN {$loginAthenaGroup->loginDatabase}.{$creditsTable} AS credits ON login.account_id = credits.account_id "; $sql .= "WHERE login.sex != 'S' AND login.group_id >= 0 AND login.userid = ? LIMIT 1"; $smt = $loginAthenaGroup->connection->getStatement($sql); $res = $smt->execute(array($username)); if ($res && ($row = $smt->fetch())) { return $row; } else { return false; } } /** * Get available server names. * * @access public */ public function getAthenaServerNames() { if ($this->loginAthenaGroup) { $names = array(); foreach ($this->loginAthenaGroup->athenaServers as $server) { $names[] = $server->serverName; } return $names; } else { return array(); } } /** * Get a Flux_Athena instance by its name based on current server settings. * * @param string $name * @access public */ public function getAthenaServer($name = null) { if (is_null($name) && $this->athenaServerName) { return $this->getAthenaServer($this->athenaServerName); } if ($this->loginAthenaGroup && ($server = Flux::getAthenaServerByName($this->serverName, $name))) { return $server; } else { return false; } } /** * Get flash message. * * @return string * @access public */ public function getMessage() { $message = $this->message; $this->setMessageData(null); return $message; } } ?> ================================================ FILE: lib/Flux/Template.php ================================================ params = $config->get('params'); $this->basePath = $config->get('basePath'); $this->modulePath = $config->get('modulePath'); $this->moduleName = $config->get('moduleName'); $this->themePath = $config->get('themePath'); $this->themeName = $config->get('themeName'); $this->actionName = $config->get('actionName'); $this->viewName = $config->get('viewName'); $this->headerName = $config->get('headerName'); $this->footerName = $config->get('footerName'); $this->useCleanUrls = $config->get('useCleanUrls'); $this->missingActionModuleAction = $config->get('missingActionModuleAction', false); $this->missingViewModuleAction = $config->get('missingViewModuleAction', false); $this->referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''; // Read manifest file if exists if (file_exists($this->themePath.'/'.$this->themeName.'/manifest.php')) { $manifest = include($this->themePath.'/'.$this->themeName.'/manifest.php'); // Inherit views and controllers from another template if (!empty($manifest['inherit'])) { if (in_array($manifest['inherit'], self::$themeLoaded)) { throw new Flux_Error('Circular dependencies in themes : ' . implode(' -> ', self::$themeLoaded) . ' -> ' . $manifest['inherit']); } $config->set('themeName', $manifest['inherit']); self::$themeLoaded[] = $manifest['inherit']; $this->parentTemplate = new Flux_Template($config); } } } /** * Any data that gets set here will be available to all templates as global * variables unless they are overridden by variables of the same name set * in the render() method. * * @return array * @access public */ public function setDefaultData(array &$data) { $this->defaultData = $data; return $data; } /** * Render a template, but before doing so, call the action file and render * the header->view->footer in that order. * * @param array $dataArr Key=>value pairs of variables to be exposed to the template as globals. * @access public */ public function render(array $dataArr = array()) { // GZip compression. if (Flux::config('GzipCompressOutput')) { header('Accept-Encoding: gzip'); ini_set('zlib.output_handler', ''); ini_set('zlib.output_compression', 'On'); ini_set('zlib.output_compression_level', (int)Flux::config('GzipCompressionLevel')); } $addon = false; $this->actionPath = sprintf('%s/%s/%s.php', $this->modulePath, $this->moduleName, $this->actionName); if (!file_exists($this->actionPath)) { foreach (Flux::$addons as $_tmpAddon) { if ($_tmpAddon->respondsTo($this->moduleName, $this->actionName)) { $addon = $_tmpAddon; $this->actionPath = sprintf('%s/%s/%s.php', $addon->moduleDir, $this->moduleName, $this->actionName); } } if (!$addon) { $this->moduleName = $this->missingActionModuleAction[0]; $this->actionName = $this->missingActionModuleAction[1]; $this->viewName = $this->missingActionModuleAction[1]; $this->actionPath = sprintf('%s/%s/%s.php', $this->modulePath, $this->moduleName, $this->actionName); } } $this->viewPath = $this->themePath(sprintf('%s/%s.php', $this->moduleName, $this->actionName), true); if (!file_exists($this->viewPath) && $addon) { $this->viewPath = $addon->getView( $this, $this->moduleName, $this->actionName); if ( $this->viewPath === false ) { $this->moduleName = $this->missingViewModuleAction[0]; $this->actionName = $this->missingViewModuleAction[1]; $this->viewName = $this->missingViewModuleAction[1]; $this->actionPath = sprintf('%s/%s/%s.php', $this->modulePath, $this->moduleName, $this->actionName); $this->viewPath = $this->themePath(sprintf('%s/%s.php', $this->moduleName, $this->viewName), true); } } $this->headerPath = $this->themePath($this->headerName.'.php', true); $this->footerPath = $this->themePath($this->footerName.'.php', true); $this->url = $this->url($this->moduleName, $this->actionName); $this->urlWithQS = $this->url; if (!empty($_SERVER['QUERY_STRING'])) { if ($this->useCleanUrls) { $this->urlWithQS .= "?{$_SERVER['QUERY_STRING']}"; } else { foreach (explode('&', trim($_SERVER['QUERY_STRING'], '&')) as $line) { list ($key,$val) = explode('=', $line, 2); $key = urldecode($key); $val = urldecode($val); if ($key != 'module' && $key != 'action') { $this->urlWithQS .= sprintf('&%s=%s', urlencode($key), urlencode($val)); } } } } // Compatibility. $this->urlWithQs = $this->urlWithQS; // Tidy up! if (Flux::config('OutputCleanHTML')) { $dispatcher = Flux_Dispatcher::getInstance(); $tidyIgnore = false; if (($tidyIgnores = Flux::config('TidyIgnore')) instanceOf Flux_Config) { foreach ($tidyIgnores->getChildrenConfigs() as $ignore) { $ignore = $ignore->toArray(); if (is_array($ignore) && array_key_exists('module', $ignore)) { $module = $ignore['module']; $action = array_key_exists('action', $ignore) ? $ignore['action'] : $dispatcher->defaultAction; if ($this->moduleName == $module && $this->actionName == $action) { $tidyIgnore = true; } } } } if (!$tidyIgnore) { ob_start(); } } // Merge with default data. $data = array_merge($this->defaultData, $dataArr); // Extract data array and make them appear as though they were global // variables from the template. extract($data, EXTR_REFS); // Files object. $files = new Flux_Config($_FILES); $preprocessorPath = sprintf('%s/main/preprocess.php', $this->modulePath); if (file_exists($preprocessorPath)) { include $preprocessorPath; } include $this->actionPath; $pageMenuFile = FLUX_ROOT."/modules/{$this->moduleName}/pagemenu/{$this->actionName}.php"; $pageMenuItems = array(); // Get the main menu file first (located in the actual module). if (file_exists($pageMenuFile)) { ob_start(); $pageMenuItems = include $pageMenuFile; ob_end_clean(); } $addonPageMenuFiles = glob(FLUX_ADDON_DIR."/*/modules/{$this->moduleName}/pagemenu/{$this->actionName}.php"); if ($addonPageMenuFiles) { foreach ($addonPageMenuFiles as $addonPageMenuFile) { ob_start(); $pageMenuItems = array_merge($pageMenuItems, include $addonPageMenuFile); ob_end_clean(); } } if (file_exists($this->headerPath)) { include $this->headerPath; } include $this->viewPath; if (file_exists($this->footerPath)) { include $this->footerPath; } // Really, tidy up! if (Flux::config('OutputCleanHTML') && !$tidyIgnore && function_exists('tidy_repair_string')) { $content = ob_get_clean(); $content = tidy_repair_string($content, array('indent' => true, 'wrap' => false, 'output-xhtml' => true), 'utf8'); echo $content; } } /** * Returns an array of menu items that should be diplayed from the theme. * Only menu items the current user (and their group level) have access to * will be returned as part of the array; * * @return array */ public function getMenuItems($adminMenus = false) { $auth = Flux_Authorization::getInstance(); $adminMenuLevel = Flux::config('AdminMenuGroupLevel'); $defaultAction = Flux_Dispatcher::getInstance()->defaultAction; $menuItems = Flux::config('MenuItems'); $allowedItems = array(); if (!($menuItems instanceOf Flux_Config)) { return array(); } foreach ($menuItems->toArray() as $categoryName => $menu) { foreach ($menu as $menuName => $menuItem) { $module = array_key_exists('module', $menuItem) ? $menuItem['module'] : false; $action = array_key_exists('action', $menuItem) ? $menuItem['action'] : $defaultAction; $param = array_key_exists('param', $menuItem) ? $menuItem['param'] : array(); $exturl = array_key_exists('exturl', $menuItem) ? $menuItem['exturl'] : null; if ($adminMenus) { if ($auth->actionAllowed($module, $action) && $auth->config("modules.$module.$action") >= $adminMenuLevel) { $allowedItems[] = array( 'name' => $menuName, 'exturl' => null, 'module' => $module, 'action' => $action, 'url' => $this->url($module, $action, $param) ); } } else { if (empty($allowedItems[$categoryName])) { $allowedItems[$categoryName] = array(); } if ($exturl) { $allowedItems[$categoryName][] = array( 'name' => $menuName, 'exturl' => $exturl, 'module' => null, 'action' => null, 'url' => $exturl ); } elseif ($auth->actionAllowed($module, $action) && $auth->config("modules.$module.$action") < $adminMenuLevel) { $allowedItems[$categoryName][] = array( 'name' => $menuName, 'exturl' => null, 'module' => $module, 'action' => $action, 'url' => $this->url($module, $action, $param) ); } } } } return $allowedItems; } /** * @see Flux_Template::getMenuItems() */ public function getAdminMenuItems() { return $this->getMenuItems(true); } /** * Get sub-menu items for a particular module. * * @param string $moduleName * @return array */ public function getSubMenuItems($moduleName = null) { $auth = Flux_Authorization::getInstance(); $moduleName = $moduleName ? $moduleName : $this->moduleName; $subMenuItems = Flux::config('SubMenuItems'); $allowedItems = array(); if (!($subMenuItems instanceOf Flux_Config) || !( ($menus = $subMenuItems->get($moduleName)) instanceOf Flux_Config )) { return array(); } foreach ($menus->toArray() as $actionName => $menuName) { if ($auth->actionAllowed($moduleName, $actionName)) { $allowedItems[] = array('name' => $menuName, 'module' => $moduleName, 'action' => $actionName); } } return $allowedItems; } /** * Get an array of login server names. * * @return array */ public function getServerNames() { return array_keys(Flux::$loginAthenaGroupRegistry); } /** * Determine if more than 1 server exists. * * @return bool */ public function hasManyServers() { return count(Flux::$loginAthenaGroupRegistry) > 1; } /** * Obtain the absolute web path of the specified user path. Specify the * path as a relative path. * * @param string $path Relative path from basePath. * @param boolean $included * @access public */ public function path($path, $included = false) { if (is_array($path)) { $path = implode('/', $path); } if ($included === false) { $path = "{$this->basePath}/$path"; } return preg_replace('&/{2,}&', '/', $path); } /** * Similar to the path() method, but uses the $themePath as the path from * which the user-specified path is relative. * * @param string $path Relative path from themePath. * @access public */ public function themePath($path, $included = false) { if (is_array($path)) { $path = implode('/', $path); } // Remove frag for file checking. $frag = ""; preg_match("/(\?|\#).*/", $path, $matches); if (count($matches)) { $frag = $matches[0]; $path = substr($path, 0, -strlen($frag)); } $uri = $this->path("{$this->themePath}/{$this->themeName}/{$path}", $included); // normalized basePath. $base = preg_replace('/(\/+)$/', '', $this->basePath ) . '/'; $base = preg_quote( $base, '/' ); $chk = FLUX_ROOT .'/'. preg_replace('/^('.$base.')/', '', $uri ); // If file not found, search in parent's template. if (!file_exists($chk) && !empty($this->parentTemplate)) { $path = $this->parentTemplate->themePath($path, $included); $chk = FLUX_ROOT .'/'. preg_replace('/^('.$base.')/', '', $path ); if (file_exists($chk)) { $uri = $path; } } elseif (!file_exists($chk)) { foreach (Flux::$addons as $_tmpAddon_key => $_tmpAddon) { $chk = FLUX_ROOT .'/'. FLUX_ADDON_DIR .'/'. $_tmpAddon_key .'/'. preg_replace('/^('.$base.')/', '', $uri ); if (file_exists($chk)) { $path = sprintf('%s/%s/%s', FLUX_ADDON_DIR, $_tmpAddon_key, preg_replace('/^('.$base.')/', '', $uri )); $uri = $path; break; } } } return $uri . $frag; } /** * Create a URI based on the setting of $useCleanUrls. This will determine * whether or not we will create a mod_rewrite-based clean URL or just a * regular query string based one. * * @param string $moduleName * @param string $actionName * @access public */ public function url($moduleName, $actionName = null, $params = array()) { $defaultAction = Flux_Dispatcher::getInstance()->defaultAction; $serverProtocol = ''; $serverAddress = ''; if ($params instanceOf Flux_Config) { $params = $params->toArray(); } if (array_key_exists('_host', $params)) { $_host = $params['_host']; $_https = false; if ($_host && ($addr=Flux::config('ServerAddress'))) { if (array_key_exists('_https', $params)) { $_https = $params['_https']; } elseif (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== "off") { $_https = true; } else { $_https = false; } $serverProtocol = $_https ? 'https://' : 'http://'; $serverAddress = $addr; } unset($params['_host']); if (array_key_exists('_https', $params)) { unset($params['_https']); } } $queryString = ''; if (count($params)) { $queryString .= Flux::config('UseCleanUrls') ? '?' : '&'; foreach ($params as $param => $value) { $queryString .= sprintf('%s=%s&', $param, urlencode($value ?: '')); } $queryString = rtrim($queryString, '&'); } if ($this->useCleanUrls) { if ($actionName && $actionName != $defaultAction) { $url = sprintf('%s/%s/%s/%s', $this->basePath, $moduleName, $actionName, $queryString); } else { $url = sprintf('%s/%s/%s', $this->basePath, $moduleName, $queryString); } } else { if ($actionName && $actionName != $defaultAction) { $url = sprintf('%s/?module=%s&action=%s%s', $this->basePath, $moduleName, $actionName, $queryString); } else { $url = sprintf('%s/?module=%s%s', $this->basePath, $moduleName, $queryString); } } return $serverProtocol.preg_replace('&/{2,}&', '/', "$serverAddress/$url"); } /** * Format currency strings. * * @param float $number Amount * @return string Formatted amount */ public function formatCurrency($number) { $number = (float)$number; $amount = number_format( $number, Flux::config('MoneyDecimalPlaces'), Flux::config('MoneyDecimalSymbol'), Flux::config('MoneyThousandsSymbol') ); return $amount; } /** * Format a MySQL DATE column according to the DateFormat config. * * @param string $data * @return string * @access public */ public function formatDate($date = null) { $ts = $date ? strtotime($date) : time(); return date(Flux::config('DateFormat'), $ts); } /** * Format a MySQL DATETIME column according to the DateTimeFormat config. * * @param string $dataTime * @return string * @access public */ public function formatDateTime($dateTime = null) { $ts = $dateTime ? strtotime($dateTime) : time(); return date(Flux::config('DateTimeFormat'), $ts); } /** * Create a series of select fields matching a MySQL DATE format. * * @param string $name * @param string $value DATE formatted string. * @param int $fowardYears * @param int $backwardYears * @return string */ public function dateField($name, $value = null, $fowardYears = null, $backwardYears = null) { if(!isset($fowardYears)) { $fowardYears = (int)Flux::config('ForwardYears'); } if(!isset($backwardYears)) { $backwardYears = (int)Flux::config('BackwardYears'); } $ts = $value && !preg_match('/^0000-00-00(?: 00:00:00)?$/', $value) ? strtotime($value) : time(); $year = ($year =$this->params->get("{$name}_year")) ? $year : date('Y', $ts); $month = ($month=$this->params->get("{$name}_month")) ? $month : date('m', $ts); $day = ($day =$this->params->get("{$name}_day")) ? $day : date('d', $ts); $fw = $year + $fowardYears; $bw = $year - $backwardYears; // Get years. $years = sprintf(''; // Get months. $months = sprintf(''; // Get days. $days = sprintf(''; return sprintf('%s-%s-%s', $years, $months, $days); } /** * Create a series of select fields matching a MySQL DATETIME format. * * @param string $name * @param string $value DATETIME formatted string. * @return string */ public function dateTimeField($name, $value = null) { $dateField = $this->dateField($name, $value); $ts = $value ? strtotime($value) : strtotime('00:00:00'); $hour = date('H', $ts); $minute = date('i', $ts); $second = date('s', $ts); // Get hours. $hours = sprintf(''; // Get minutes. $minutes = sprintf(''; // Get seconds. $seconds = sprintf(''; return sprintf('%s @ %s:%s:%s', $dateField, $hours, $minutes, $seconds); } /** * Returns "up" or "down" in a span HTML element with either the class * .up or .down, based on the value of $bool. True returns up, false * returns down. * * @param bool $bool True/false value * @return string Up/down */ public function serverUpDown($bool) { $class = $bool ? 'up' : 'down'; return sprintf('%s', $class, $bool ? 'Online' : 'Offline'); } /** * Redirect client to another location. Script execution is terminated * after instructing the client to redirect. * * @param string $location */ public function redirect($location = null) { if (is_null($location)) { $location = $this->basePath; } header("Location: $location"); exit; } /** * Guess the HTTP server's current full URL. * * @param bool $withRequest True to include REQUEST_URI, false if not. * @return string URL */ public function entireUrl($withRequest = true) { $proto = empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === "off" ? 'http://' : 'https://'; $hostname = empty($_SERVER['HTTP_HOST']) ? $_SERVER['SERVER_NAME'] : $_SERVER['HTTP_HOST']; $request = $_SERVER['REQUEST_URI']; if ($withRequest) { $url = $proto.$hostname.$request; } else { $url = $proto.$hostname.'/'.$this->basePath; } $url = rtrim(preg_replace('&/{2,}&', '/', $url), '/'); return $url; } /** * Convenience method for retrieving a paginator instance. * * @param int $total Total number of records. * @param array $options Paginator options. * @return Flux_Paginator * @access public */ public function getPaginator($total, array $options = array()) { $paginator = new Flux_Paginator($total, $this->url($this->moduleName, $this->actionName, array('_host' => false)), $options); return $paginator; } /** * Link to an account view page. * * @param int $accountID * @param string $text * @return mixed * @access public */ public function linkToAccount($accountID, $text) { if ($accountID) { $url = $this->url('account', 'view', array('id' => $accountID)); return sprintf('', $url, htmlspecialchars($text)); } else { return false; } } /** * Link to an account search. * * @param array $params * @param string $text * @return mixed * @access public */ public function linkToAccountSearch($params, $text) { if (is_array($params) && count($params)) { $url = $this->url('account', 'index', $params); return sprintf('', $url, htmlspecialchars($text)); } else { return false; } } /** * Link to a character view page. * * @param int $charID * @param string $text * @return mixed * @access public */ public function linkToCharacter($charID, $text, $server = null) { if ($charID) { $params = array('id' => $charID); if ($server) { $params['preferred_server'] = $server; } $url = $this->url('character', 'view', $params); return sprintf('%s', $url, htmlspecialchars($text)); } else { return false; } } /** * Deny entry to a page if called. This method should be used from a module * script, and no where else. */ public function deny() { $location = $this->url('unauthorized'); $this->redirect($location); } /** * Get the full gender string from a gender letter (e.g. M for Male). * * @param string $gender * @return string * @access public */ public function genderText($gender) { switch (strtoupper($gender)) { case 'M': return Flux::message('GenderTypeMale'); break; case 'F': return Flux::message('GenderTypeFemale'); break; case 'S': return Flux::message('GenderTypeServer'); break; default: return false; break; } } /** * Get the account state name corresponding to the state number. * * @param int $state * @return mixed State name or false. * @access public */ public function accountStateText($state) { $text = false; $state = (int)$state; switch ($state) { case 0: $text = Flux::message('AccountStateNormal'); $class = 'state-normal'; break; case 5: $text = Flux::message('AccountStatePermBanned'); $class = 'state-permanently-banned'; break; } if ($text) { $text = htmlspecialchars($text); return sprintf('