Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatt <matt@59fd770c-687e-43c8-a1e3-f5a4ff64c105>2010-06-23 07:45:36 +0400
committermatt <matt@59fd770c-687e-43c8-a1e3-f5a4ff64c105>2010-06-23 07:45:36 +0400
commit7e1b5d6b762340cbff1bb928d15815980c7649a7 (patch)
treee07da179b9e1372866d2349777bd1cc6b4c9e8cf
parent999f46479294713104c962bfe7469e9b6e7a4bbf (diff)
parentc98ea06f2cccec81c6ccce49162a583494e44d91 (diff)
-rw-r--r--README11
-rw-r--r--config/.htaccess2
-rw-r--r--config/config.ini.sample.php1
-rw-r--r--config/global.ini.php107
-rw-r--r--core/API/DataTableGenericFilter.php23
-rw-r--r--core/API/DocumentationGenerator.php2
-rw-r--r--core/API/Proxy.php11
-rw-r--r--core/API/Request.php29
-rw-r--r--core/API/ResponseBuilder.php83
-rw-r--r--core/Access.php50
-rw-r--r--core/Archive.php2
-rw-r--r--core/Archive/Array/IndexedByDate.php16
-rw-r--r--core/Archive/Array/IndexedBySite.php2
-rw-r--r--core/Archive/Single.php24
-rw-r--r--core/ArchiveProcessing.php256
-rw-r--r--core/ArchiveProcessing/Day.php44
-rw-r--r--core/ArchiveProcessing/Period.php80
-rw-r--r--core/CacheFile.php9
-rw-r--r--core/Common.php229
-rw-r--r--core/Config.php90
-rw-r--r--core/Controller.php280
-rw-r--r--core/Cookie.php22
-rw-r--r--core/DataFiles/SearchEngines.php276
-rw-r--r--core/DataTable.php17
-rw-r--r--core/DataTable/Filter/AddColumnsWhenShowAllColumns.php8
-rw-r--r--core/DataTable/Filter/ColumnCallbackAddColumnPercentage.php53
-rw-r--r--core/DataTable/Filter/ColumnCallbackAddColumnQuotient.php80
-rw-r--r--core/DataTable/Filter/ColumnCallbackAddMetadata.php11
-rw-r--r--core/DataTable/Filter/ColumnCallbackDeleteRow.php3
-rw-r--r--core/DataTable/Filter/ColumnCallbackReplace.php8
-rw-r--r--core/DataTable/Filter/ColumnDelete.php36
-rw-r--r--core/DataTable/Filter/ReplaceColumnNames.php5
-rw-r--r--core/DataTable/Filter/Sort.php4
-rw-r--r--core/DataTable/Filter/UpdateColumnsWhenShowAllGoals.php48
-rw-r--r--core/DataTable/Manager.php12
-rw-r--r--core/DataTable/Renderer.php54
-rw-r--r--core/DataTable/Renderer/Console.php26
-rw-r--r--core/DataTable/Renderer/Csv.php24
-rw-r--r--core/DataTable/Renderer/Html.php8
-rw-r--r--core/DataTable/Renderer/Json.php23
-rw-r--r--core/DataTable/Renderer/Php.php14
-rw-r--r--core/DataTable/Renderer/Rss.php13
-rw-r--r--core/DataTable/Renderer/Tsv.php34
-rw-r--r--core/DataTable/Renderer/Xml.php14
-rw-r--r--core/DataTable/Row.php2
-rw-r--r--core/Date.php425
-rw-r--r--core/Db/Adapter.php (renamed from core/Db.php)87
-rw-r--r--core/Db/Adapter/Mysqli.php (renamed from core/Db/Mysqli.php)49
-rw-r--r--core/Db/Adapter/Pdo/Mssql.php253
-rw-r--r--core/Db/Adapter/Pdo/Mysql.php (renamed from core/Db/Pdo/Mysql.php)47
-rw-r--r--core/Db/Adapter/Pdo/Pgsql.php (renamed from core/Db/Pdo/Pgsql.php)84
-rw-r--r--core/Db/Schema.php282
-rw-r--r--core/Db/Schema/Myisam.php484
-rw-r--r--core/ExceptionHandler.php2
-rw-r--r--core/Form.php14
-rw-r--r--core/FrontController.php35
-rw-r--r--core/Http.php385
-rw-r--r--core/Log.php25
-rw-r--r--core/Log/APICall.php10
-rw-r--r--core/Log/Error.php10
-rw-r--r--core/Log/Exception.php4
-rw-r--r--core/Log/Message.php2
-rw-r--r--core/Nonce.php81
-rw-r--r--core/Option.php17
-rw-r--r--core/Period.php32
-rw-r--r--core/Period/Day.php9
-rw-r--r--core/Period/Month.php14
-rw-r--r--core/Period/Range.php11
-rw-r--r--core/Period/Year.php2
-rw-r--r--core/Piwik.php2018
-rw-r--r--core/Plugin.php32
-rw-r--r--core/PluginsFunctions/AdminMenu.php50
-rw-r--r--core/PluginsFunctions/Menu.php20
-rw-r--r--core/PluginsFunctions/Sql.php85
-rw-r--r--core/PluginsFunctions/WidgetsList.php33
-rw-r--r--core/PluginsManager.php81
-rw-r--r--core/Session.php72
-rw-r--r--core/Site.php35
-rw-r--r--core/Smarty.php3
-rw-r--r--core/SmartyPlugins/function.ajaxErrorDiv.php30
-rw-r--r--core/SmartyPlugins/function.ajaxLoadingDiv.php35
-rw-r--r--core/SmartyPlugins/function.ajaxRequestErrorDiv.php22
-rw-r--r--core/SmartyPlugins/function.assignTopBar.php5
-rw-r--r--core/SmartyPlugins/modifier.inlineHelp.php26
-rw-r--r--core/SmartyPlugins/modifier.money.php27
-rw-r--r--core/SmartyPlugins/modifier.stripeol.php32
-rw-r--r--core/SmartyPlugins/modifier.translate.php14
-rw-r--r--core/SmartyPlugins/modifier.urlRewriteWithParameters.php1
-rw-r--r--core/SmartyPlugins/outputfilter.ajaxcdn.php4
-rw-r--r--core/TablePartitioning.php12
-rw-r--r--core/Tracker.php52
-rw-r--r--core/Tracker/Action.php51
-rw-r--r--core/Tracker/Config.php41
-rw-r--r--core/Tracker/Db.php19
-rw-r--r--core/Tracker/GoalManager.php33
-rw-r--r--core/Tracker/Visit.php245
-rw-r--r--core/Tracker/javascriptTag.tpl2
-rw-r--r--core/Translate.php26
-rw-r--r--core/UpdateCheck.php15
-rw-r--r--core/Updater.php99
-rw-r--r--core/Updates.php (renamed from core/iUpdate.php)17
-rw-r--r--core/Updates/0.2.10.php40
-rw-r--r--core/Updates/0.2.12.php21
-rw-r--r--core/Updates/0.2.13.php16
-rw-r--r--core/Updates/0.2.24.php21
-rw-r--r--core/Updates/0.2.27.php20
-rw-r--r--core/Updates/0.2.32.php37
-rw-r--r--core/Updates/0.2.33.php19
-rw-r--r--core/Updates/0.2.34.php4
-rw-r--r--core/Updates/0.2.35.php15
-rw-r--r--core/Updates/0.2.37.php15
-rw-r--r--core/Updates/0.4.1.php19
-rw-r--r--core/Updates/0.4.2.php21
-rw-r--r--core/Updates/0.4.3.php65
-rw-r--r--core/Updates/0.4.4.php12
-rw-r--r--core/Updates/0.4.php22
-rw-r--r--core/Updates/0.5.4.php75
-rw-r--r--core/Updates/0.5.5.php46
-rw-r--r--core/Updates/0.5.php31
-rw-r--r--core/Updates/0.6-rc1.php68
-rw-r--r--core/Updates/0.6.2.php47
-rw-r--r--core/Updates/0.6.3.php54
-rw-r--r--core/Url.php131
-rw-r--r--core/Version.php2
-rw-r--r--core/View.php93
-rw-r--r--core/ViewDataTable.php103
-rw-r--r--core/ViewDataTable/Cloud.php6
-rw-r--r--core/ViewDataTable/GenerateGraphData.php8
-rw-r--r--core/ViewDataTable/GenerateGraphData/ChartEvolution.php54
-rw-r--r--core/ViewDataTable/GenerateGraphHTML.php26
-rw-r--r--core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php21
-rw-r--r--core/ViewDataTable/HtmlTable.php14
-rw-r--r--core/ViewDataTable/HtmlTable/Goals.php122
-rw-r--r--core/Visualization/Chart.php11
-rw-r--r--core/Visualization/Sparkline.php25
-rw-r--r--core/testMinimumPhpVersion.php6
-rw-r--r--index.php36
-rw-r--r--js/README33
-rw-r--r--js/index.php66
-rw-r--r--js/piwik.js48
-rw-r--r--lang/am.php736
-rw-r--r--lang/be.php868
-rw-r--r--lang/bg.php935
-rw-r--r--lang/ca.php100
-rw-r--r--lang/cs.php69
-rw-r--r--lang/da.php1052
-rw-r--r--lang/de.php2008
-rw-r--r--lang/el.php1307
-rw-r--r--lang/en.php845
-rw-r--r--lang/es.php321
-rw-r--r--lang/et.php43
-rw-r--r--lang/eu.php836
-rw-r--r--lang/fi.php1505
-rw-r--r--lang/fr.php882
-rw-r--r--lang/gl.php3
-rw-r--r--lang/hu.php31
-rw-r--r--lang/it.php683
-rw-r--r--lang/ja.php29
-rw-r--r--lang/ko.php31
-rw-r--r--lang/lt.php502
-rw-r--r--lang/nb.php360
-rw-r--r--lang/nl.php758
-rw-r--r--lang/pl.php919
-rw-r--r--lang/pt-br.php1096
-rw-r--r--lang/pt.php31
-rw-r--r--lang/ro.php49
-rw-r--r--lang/ru.php114
-rw-r--r--lang/sk.php4
-rw-r--r--lang/sq.php795
-rw-r--r--lang/sr.php30
-rw-r--r--lang/sv.php45
-rw-r--r--lang/th.php6
-rw-r--r--lang/uk.php4
-rw-r--r--lang/zh-cn.php29
-rw-r--r--lang/zh-tw.php31
-rw-r--r--libs/HTML/QuickForm.php18
-rw-r--r--libs/HTML/QuickForm/Renderer/Array.php4
-rw-r--r--libs/HTML/QuickForm/Renderer/ArraySmarty.php4
-rw-r--r--libs/HTML/QuickForm/Renderer/Default.php2
-rw-r--r--libs/HTML/QuickForm/Renderer/ITDynamic.php2
-rw-r--r--libs/HTML/QuickForm/Renderer/ITStatic.php4
-rw-r--r--libs/HTML/QuickForm/Renderer/Object.php26
-rw-r--r--libs/HTML/QuickForm/Renderer/ObjectFlexy.php7
-rw-r--r--libs/HTML/QuickForm/Renderer/QuickHtml.php2
-rw-r--r--libs/HTML/QuickForm/Rule/Callback.php4
-rw-r--r--libs/HTML/QuickForm/Rule/Compare.php2
-rw-r--r--libs/HTML/QuickForm/Rule/Email.php4
-rw-r--r--libs/HTML/QuickForm/Rule/Range.php4
-rw-r--r--libs/HTML/QuickForm/Rule/Regex.php4
-rw-r--r--libs/HTML/QuickForm/Rule/Required.php2
-rw-r--r--libs/HTML/QuickForm/RuleRegistry.php2
-rw-r--r--libs/HTML/QuickForm/advcheckbox.php2
-rw-r--r--libs/HTML/QuickForm/autocomplete.php2
-rw-r--r--libs/HTML/QuickForm/button.php2
-rw-r--r--libs/HTML/QuickForm/checkbox.php2
-rw-r--r--libs/HTML/QuickForm/date.php6
-rw-r--r--libs/HTML/QuickForm/element.php4
-rw-r--r--libs/HTML/QuickForm/file.php2
-rw-r--r--libs/HTML/QuickForm/group.php4
-rw-r--r--libs/HTML/QuickForm/header.php2
-rw-r--r--libs/HTML/QuickForm/hidden.php2
-rw-r--r--libs/HTML/QuickForm/hiddenselect.php2
-rw-r--r--libs/HTML/QuickForm/hierselect.php6
-rw-r--r--libs/HTML/QuickForm/html.php2
-rw-r--r--libs/HTML/QuickForm/image.php2
-rw-r--r--libs/HTML/QuickForm/input.php2
-rw-r--r--libs/HTML/QuickForm/link.php2
-rw-r--r--libs/HTML/QuickForm/password.php2
-rw-r--r--libs/HTML/QuickForm/radio.php2
-rw-r--r--libs/HTML/QuickForm/reset.php2
-rw-r--r--libs/HTML/QuickForm/select.php131
-rw-r--r--libs/HTML/QuickForm/static.php2
-rw-r--r--libs/HTML/QuickForm/submit.php2
-rw-r--r--libs/HTML/QuickForm/text.php2
-rw-r--r--libs/HTML/QuickForm/textarea.php2
-rw-r--r--libs/HTML/QuickForm/xbutton.php2
-rw-r--r--libs/PclZip/pclzip.lib.php1090
-rw-r--r--libs/Smarty/Config_File.class.php2
-rw-r--r--libs/Smarty/Smarty.class.php24
-rw-r--r--libs/Smarty/Smarty_Compiler.class.php51
-rw-r--r--libs/Smarty/plugins/function.cycle.php6
-rw-r--r--libs/Smarty/plugins/function.math.php4
-rw-r--r--libs/Smarty/plugins/outputfilter.trimwhitespace.php11
-rw-r--r--libs/UserAgentParser/README11
-rw-r--r--libs/UserAgentParser/UserAgentParser.php452
-rw-r--r--libs/Zend/Auth.php12
-rw-r--r--libs/Zend/Auth/Adapter/DbTable.php57
-rw-r--r--libs/Zend/Auth/Adapter/Digest.php16
-rw-r--r--libs/Zend/Auth/Adapter/Exception.php12
-rw-r--r--libs/Zend/Auth/Adapter/Http.php38
-rw-r--r--libs/Zend/Auth/Adapter/Http/Resolver/Exception.php8
-rw-r--r--libs/Zend/Auth/Adapter/Http/Resolver/File.php20
-rw-r--r--libs/Zend/Auth/Adapter/Http/Resolver/Interface.php6
-rw-r--r--libs/Zend/Auth/Adapter/InfoCard.php12
-rw-r--r--libs/Zend/Auth/Adapter/Interface.php8
-rw-r--r--libs/Zend/Auth/Adapter/Ldap.php56
-rw-r--r--libs/Zend/Auth/Adapter/OpenId.php10
-rw-r--r--libs/Zend/Auth/Exception.php8
-rw-r--r--libs/Zend/Auth/Result.php6
-rw-r--r--libs/Zend/Auth/Storage/Exception.php12
-rw-r--r--libs/Zend/Auth/Storage/Interface.php11
-rw-r--r--libs/Zend/Auth/Storage/NonPersistent.php13
-rw-r--r--libs/Zend/Auth/Storage/Session.php14
-rw-r--r--libs/Zend/Cache.php39
-rw-r--r--libs/Zend/Cache/Backend.php82
-rw-r--r--libs/Zend/Cache/Backend/Apc.php60
-rw-r--r--libs/Zend/Cache/Backend/BlackHole.php250
-rw-r--r--libs/Zend/Cache/Backend/ExtendedInterface.php36
-rw-r--r--libs/Zend/Cache/Backend/File.php25
-rw-r--r--libs/Zend/Cache/Backend/Interface.php6
-rw-r--r--libs/Zend/Cache/Backend/Memcached.php74
-rw-r--r--libs/Zend/Cache/Backend/Sqlite.php10
-rw-r--r--libs/Zend/Cache/Backend/Static.php558
-rw-r--r--libs/Zend/Cache/Backend/Test.php162
-rw-r--r--libs/Zend/Cache/Backend/TwoLevels.php59
-rw-r--r--libs/Zend/Cache/Backend/Xcache.php12
-rw-r--r--libs/Zend/Cache/Backend/ZendPlatform.php10
-rw-r--r--libs/Zend/Cache/Backend/ZendServer.php10
-rw-r--r--libs/Zend/Cache/Backend/ZendServer/Disk.php28
-rw-r--r--libs/Zend/Cache/Backend/ZendServer/ShMem.php10
-rw-r--r--libs/Zend/Cache/Core.php139
-rw-r--r--libs/Zend/Cache/Exception.php8
-rw-r--r--libs/Zend/Cache/Frontend/Capture.php87
-rw-r--r--libs/Zend/Cache/Frontend/Class.php19
-rw-r--r--libs/Zend/Cache/Frontend/File.php110
-rw-r--r--libs/Zend/Cache/Frontend/Function.php21
-rw-r--r--libs/Zend/Cache/Frontend/Output.php8
-rw-r--r--libs/Zend/Cache/Frontend/Page.php16
-rw-r--r--libs/Zend/Cache/Manager.php286
-rw-r--r--libs/Zend/Config.php58
-rw-r--r--libs/Zend/Config/Exception.php8
-rw-r--r--libs/Zend/Config/Ini.php71
-rw-r--r--libs/Zend/Config/Writer.php24
-rw-r--r--libs/Zend/Config/Writer/Array.php103
-rw-r--r--libs/Zend/Config/Writer/FileAbstract.php134
-rw-r--r--libs/Zend/Config/Writer/Ini.php137
-rw-r--r--libs/Zend/Config/Writer/Xml.php131
-rw-r--r--libs/Zend/Config/Xml.php59
-rw-r--r--libs/Zend/Db.php20
-rw-r--r--libs/Zend/Db/Adapter/Abstract.php38
-rw-r--r--libs/Zend/Db/Adapter/Db2.php46
-rw-r--r--libs/Zend/Db/Adapter/Db2/Exception.php14
-rw-r--r--libs/Zend/Db/Adapter/Exception.php21
-rw-r--r--libs/Zend/Db/Adapter/Mysqli.php38
-rw-r--r--libs/Zend/Db/Adapter/Mysqli/Exception.php8
-rw-r--r--libs/Zend/Db/Adapter/Oracle.php40
-rw-r--r--libs/Zend/Db/Adapter/Oracle/Exception.php8
-rw-r--r--libs/Zend/Db/Adapter/Pdo/Abstract.php46
-rw-r--r--libs/Zend/Db/Adapter/Pdo/Ibm.php22
-rw-r--r--libs/Zend/Db/Adapter/Pdo/Ibm/Db2.php14
-rw-r--r--libs/Zend/Db/Adapter/Pdo/Ibm/Ids.php14
-rw-r--r--libs/Zend/Db/Adapter/Pdo/Mssql.php90
-rw-r--r--libs/Zend/Db/Adapter/Pdo/Mysql.php12
-rw-r--r--libs/Zend/Db/Adapter/Pdo/Oci.php14
-rw-r--r--libs/Zend/Db/Adapter/Pdo/Pgsql.php18
-rw-r--r--libs/Zend/Db/Adapter/Pdo/Sqlite.php22
-rw-r--r--libs/Zend/Db/Adapter/Sqlsrv.php93
-rw-r--r--libs/Zend/Db/Adapter/Sqlsrv/Exception.php10
-rw-r--r--libs/Zend/Db/Exception.php8
-rw-r--r--libs/Zend/Db/Expr.php6
-rw-r--r--libs/Zend/Db/Profiler.php31
-rw-r--r--libs/Zend/Db/Profiler/Exception.php8
-rw-r--r--libs/Zend/Db/Profiler/Firebug.php42
-rw-r--r--libs/Zend/Db/Profiler/Query.php6
-rw-r--r--libs/Zend/Db/Select.php85
-rw-r--r--libs/Zend/Db/Select/Exception.php8
-rw-r--r--libs/Zend/Db/Statement.php30
-rw-r--r--libs/Zend/Db/Statement/Db2.php28
-rw-r--r--libs/Zend/Db/Statement/Db2/Exception.php8
-rw-r--r--libs/Zend/Db/Statement/Exception.php31
-rw-r--r--libs/Zend/Db/Statement/Interface.php6
-rw-r--r--libs/Zend/Db/Statement/Mysqli.php32
-rw-r--r--libs/Zend/Db/Statement/Mysqli/Exception.php8
-rw-r--r--libs/Zend/Db/Statement/Oracle.php38
-rw-r--r--libs/Zend/Db/Statement/Oracle/Exception.php8
-rw-r--r--libs/Zend/Db/Statement/Pdo.php52
-rw-r--r--libs/Zend/Db/Statement/Pdo/Ibm.php10
-rw-r--r--libs/Zend/Db/Statement/Pdo/Oci.php30
-rw-r--r--libs/Zend/Db/Statement/Sqlsrv.php25
-rw-r--r--libs/Zend/Db/Statement/Sqlsrv/Exception.php8
-rw-r--r--libs/Zend/Db/Table.php27
-rw-r--r--libs/Zend/Db/Table/Abstract.php100
-rw-r--r--libs/Zend/Db/Table/Definition.php26
-rw-r--r--libs/Zend/Db/Table/Exception.php8
-rw-r--r--libs/Zend/Db/Table/Row.php8
-rw-r--r--libs/Zend/Db/Table/Row/Abstract.php130
-rw-r--r--libs/Zend/Db/Table/Row/Exception.php8
-rw-r--r--libs/Zend/Db/Table/Rowset.php8
-rw-r--r--libs/Zend/Db/Table/Rowset/Abstract.php20
-rw-r--r--libs/Zend/Db/Table/Rowset/Exception.php8
-rw-r--r--libs/Zend/Db/Table/Select.php14
-rw-r--r--libs/Zend/Db/Table/Select/Exception.php8
-rw-r--r--libs/Zend/Exception.php82
-rw-r--r--libs/Zend/Feed.php44
-rw-r--r--libs/Zend/Feed/Abstract.php18
-rw-r--r--libs/Zend/Feed/Atom.php18
-rw-r--r--libs/Zend/Feed/Builder.php28
-rw-r--r--libs/Zend/Feed/Builder/Entry.php10
-rw-r--r--libs/Zend/Feed/Builder/Exception.php8
-rw-r--r--libs/Zend/Feed/Builder/Header.php32
-rw-r--r--libs/Zend/Feed/Builder/Header/Itunes.php26
-rw-r--r--libs/Zend/Feed/Builder/Interface.php6
-rw-r--r--libs/Zend/Feed/Element.php40
-rw-r--r--libs/Zend/Feed/Entry/Abstract.php18
-rw-r--r--libs/Zend/Feed/Entry/Atom.php32
-rw-r--r--libs/Zend/Feed/Entry/Rss.php10
-rw-r--r--libs/Zend/Feed/Exception.php8
-rw-r--r--libs/Zend/Feed/Pubsubhubbub.php152
-rw-r--r--libs/Zend/Feed/Pubsubhubbub/CallbackAbstract.php307
-rw-r--r--libs/Zend/Feed/Pubsubhubbub/CallbackInterface.php68
-rw-r--r--libs/Zend/Feed/Pubsubhubbub/Exception.php33
-rw-r--r--libs/Zend/Feed/Pubsubhubbub/HttpResponse.php233
-rw-r--r--libs/Zend/Feed/Pubsubhubbub/Model/ModelAbstract.php64
-rw-r--r--libs/Zend/Feed/Pubsubhubbub/Model/Subscription.php131
-rw-r--r--libs/Zend/Feed/Pubsubhubbub/Model/SubscriptionInterface.php64
-rw-r--r--libs/Zend/Feed/Pubsubhubbub/Publisher.php417
-rw-r--r--libs/Zend/Feed/Pubsubhubbub/Subscriber.php856
-rw-r--r--libs/Zend/Feed/Pubsubhubbub/Subscriber/Callback.php328
-rw-r--r--libs/Zend/Feed/Reader.php173
-rw-r--r--libs/Zend/Feed/Reader/Collection.php33
-rw-r--r--libs/Zend/Feed/Reader/Collection/Author.php51
-rw-r--r--libs/Zend/Feed/Reader/Collection/Category.php57
-rw-r--r--libs/Zend/Feed/Reader/Collection/CollectionAbstract.php41
-rw-r--r--libs/Zend/Feed/Reader/Entry/Atom.php61
-rw-r--r--libs/Zend/Feed/Reader/Entry/Rss.php172
-rw-r--r--libs/Zend/Feed/Reader/EntryAbstract.php28
-rw-r--r--libs/Zend/Feed/Reader/EntryInterface.php13
-rw-r--r--libs/Zend/Feed/Reader/Extension/Atom/Entry.php291
-rw-r--r--libs/Zend/Feed/Reader/Extension/Atom/Feed.php210
-rw-r--r--libs/Zend/Feed/Reader/Extension/Content/Entry.php17
-rw-r--r--libs/Zend/Feed/Reader/Extension/CreativeCommons/Entry.php10
-rw-r--r--libs/Zend/Feed/Reader/Extension/CreativeCommons/Feed.php10
-rw-r--r--libs/Zend/Feed/Reader/Extension/DublinCore/Entry.php66
-rw-r--r--libs/Zend/Feed/Reader/Extension/DublinCore/Feed.php72
-rw-r--r--libs/Zend/Feed/Reader/Extension/EntryAbstract.php23
-rw-r--r--libs/Zend/Feed/Reader/Extension/FeedAbstract.php43
-rw-r--r--libs/Zend/Feed/Reader/Extension/Podcast/Entry.php10
-rw-r--r--libs/Zend/Feed/Reader/Extension/Podcast/Feed.php8
-rw-r--r--libs/Zend/Feed/Reader/Extension/Slash/Entry.php12
-rw-r--r--libs/Zend/Feed/Reader/Extension/Syndication/Feed.php22
-rw-r--r--libs/Zend/Feed/Reader/Extension/Thread/Entry.php12
-rw-r--r--libs/Zend/Feed/Reader/Extension/WellFormedWeb/Entry.php12
-rw-r--r--libs/Zend/Feed/Reader/Feed/Atom.php100
-rw-r--r--libs/Zend/Feed/Reader/Feed/Atom/Source.php102
-rw-r--r--libs/Zend/Feed/Reader/Feed/Rss.php298
-rw-r--r--libs/Zend/Feed/Reader/FeedAbstract.php83
-rw-r--r--libs/Zend/Feed/Reader/FeedInterface.php13
-rw-r--r--libs/Zend/Feed/Reader/FeedSet.php148
-rw-r--r--libs/Zend/Feed/Rss.php28
-rw-r--r--libs/Zend/Feed/Writer.php267
-rw-r--r--libs/Zend/Feed/Writer/Deleted.php202
-rw-r--r--libs/Zend/Feed/Writer/Entry.php761
-rw-r--r--libs/Zend/Feed/Writer/Exception/InvalidMethodException.php41
-rw-r--r--libs/Zend/Feed/Writer/Extension/Atom/Renderer/Feed.php123
-rw-r--r--libs/Zend/Feed/Writer/Extension/Content/Renderer/Entry.php92
-rw-r--r--libs/Zend/Feed/Writer/Extension/DublinCore/Renderer/Entry.php96
-rw-r--r--libs/Zend/Feed/Writer/Extension/DublinCore/Renderer/Feed.php96
-rw-r--r--libs/Zend/Feed/Writer/Extension/ITunes/Entry.php242
-rw-r--r--libs/Zend/Feed/Writer/Extension/ITunes/Feed.php361
-rw-r--r--libs/Zend/Feed/Writer/Extension/ITunes/Renderer/Entry.php216
-rw-r--r--libs/Zend/Feed/Writer/Extension/ITunes/Renderer/Feed.php320
-rw-r--r--libs/Zend/Feed/Writer/Extension/RendererAbstract.php179
-rw-r--r--libs/Zend/Feed/Writer/Extension/RendererInterface.php59
-rw-r--r--libs/Zend/Feed/Writer/Extension/Slash/Renderer/Entry.php91
-rw-r--r--libs/Zend/Feed/Writer/Extension/Threading/Renderer/Entry.php145
-rw-r--r--libs/Zend/Feed/Writer/Extension/WellFormedWeb/Renderer/Entry.php96
-rw-r--r--libs/Zend/Feed/Writer/Feed.php281
-rw-r--r--libs/Zend/Feed/Writer/Feed/FeedAbstract.php805
-rw-r--r--libs/Zend/Feed/Writer/Renderer/Entry/Atom.php410
-rw-r--r--libs/Zend/Feed/Writer/Renderer/Entry/Atom/Deleted.php121
-rw-r--r--libs/Zend/Feed/Writer/Renderer/Entry/Rss.php346
-rw-r--r--libs/Zend/Feed/Writer/Renderer/Feed/Atom.php130
-rw-r--r--libs/Zend/Feed/Writer/Renderer/Feed/Atom/AtomAbstract.php427
-rw-r--r--libs/Zend/Feed/Writer/Renderer/Feed/Atom/Source.php110
-rw-r--r--libs/Zend/Feed/Writer/Renderer/Feed/Rss.php505
-rw-r--r--libs/Zend/Feed/Writer/Renderer/RendererAbstract.php250
-rw-r--r--libs/Zend/Feed/Writer/Renderer/RendererInterface.php111
-rw-r--r--libs/Zend/Feed/Writer/Source.php33
-rw-r--r--libs/Zend/Http/Client.php208
-rw-r--r--libs/Zend/Http/Client/Adapter/Curl.php180
-rw-r--r--libs/Zend/Http/Client/Adapter/Exception.php8
-rw-r--r--libs/Zend/Http/Client/Adapter/Interface.php6
-rw-r--r--libs/Zend/Http/Client/Adapter/Proxy.php29
-rw-r--r--libs/Zend/Http/Client/Adapter/Socket.php175
-rw-r--r--libs/Zend/Http/Client/Adapter/Stream.php46
-rw-r--r--libs/Zend/Http/Client/Adapter/Test.php45
-rw-r--r--libs/Zend/Http/Client/Exception.php8
-rw-r--r--libs/Zend/Http/Cookie.php62
-rw-r--r--libs/Zend/Http/CookieJar.php22
-rw-r--r--libs/Zend/Http/Exception.php8
-rw-r--r--libs/Zend/Http/Response.php18
-rw-r--r--libs/Zend/Http/Response/Stream.php235
-rw-r--r--libs/Zend/Loader.php89
-rw-r--r--libs/Zend/Loader/Autoloader.php88
-rw-r--r--libs/Zend/Loader/Autoloader/Interface.php8
-rw-r--r--libs/Zend/Loader/Autoloader/Resource.php141
-rw-r--r--libs/Zend/Loader/Exception.php12
-rw-r--r--libs/Zend/Loader/PluginLoader.php62
-rw-r--r--libs/Zend/Loader/PluginLoader/Exception.php8
-rw-r--r--libs/Zend/Loader/PluginLoader/Interface.php12
-rw-r--r--libs/Zend/Log.php237
-rw-r--r--libs/Zend/Log/Exception.php10
-rw-r--r--libs/Zend/Log/FactoryInterface.php38
-rw-r--r--libs/Zend/Log/Filter/Abstract.php60
-rw-r--r--libs/Zend/Log/Filter/Interface.php9
-rw-r--r--libs/Zend/Log/Filter/Message.php36
-rw-r--r--libs/Zend/Log/Filter/Priority.php47
-rw-r--r--libs/Zend/Log/Filter/Suppress.php23
-rw-r--r--libs/Zend/Log/Formatter/Firebug.php12
-rw-r--r--libs/Zend/Log/Formatter/Interface.php8
-rw-r--r--libs/Zend/Log/Formatter/Simple.php12
-rw-r--r--libs/Zend/Log/Formatter/Xml.php47
-rw-r--r--libs/Zend/Log/Writer/Abstract.php36
-rw-r--r--libs/Zend/Log/Writer/Db.php42
-rw-r--r--libs/Zend/Log/Writer/Firebug.php74
-rw-r--r--libs/Zend/Log/Writer/Mail.php26
-rw-r--r--libs/Zend/Log/Writer/Mock.php24
-rw-r--r--libs/Zend/Log/Writer/Null.php25
-rw-r--r--libs/Zend/Log/Writer/Stream.php55
-rw-r--r--libs/Zend/Log/Writer/Syslog.php20
-rw-r--r--libs/Zend/Log/Writer/ZendMonitor.php111
-rw-r--r--libs/Zend/Mail.php356
-rw-r--r--libs/Zend/Mail/Exception.php8
-rw-r--r--libs/Zend/Mail/Message.php12
-rw-r--r--libs/Zend/Mail/Message/File.php12
-rw-r--r--libs/Zend/Mail/Message/Interface.php8
-rw-r--r--libs/Zend/Mail/Part.php26
-rw-r--r--libs/Zend/Mail/Part/File.php34
-rw-r--r--libs/Zend/Mail/Part/Interface.php10
-rw-r--r--libs/Zend/Mail/Protocol/Abstract.php94
-rw-r--r--libs/Zend/Mail/Protocol/Exception.php10
-rw-r--r--libs/Zend/Mail/Protocol/Imap.php33
-rw-r--r--libs/Zend/Mail/Protocol/Pop3.php29
-rw-r--r--libs/Zend/Mail/Protocol/Smtp.php30
-rw-r--r--libs/Zend/Mail/Protocol/Smtp/Auth/Crammd5.php10
-rw-r--r--libs/Zend/Mail/Protocol/Smtp/Auth/Login.php10
-rw-r--r--libs/Zend/Mail/Protocol/Smtp/Auth/Plain.php10
-rw-r--r--libs/Zend/Mail/Storage.php6
-rw-r--r--libs/Zend/Mail/Storage/Abstract.php14
-rw-r--r--libs/Zend/Mail/Storage/Exception.php10
-rw-r--r--libs/Zend/Mail/Storage/Folder.php10
-rw-r--r--libs/Zend/Mail/Storage/Folder/Interface.php8
-rw-r--r--libs/Zend/Mail/Storage/Folder/Maildir.php32
-rw-r--r--libs/Zend/Mail/Storage/Folder/Mbox.php30
-rw-r--r--libs/Zend/Mail/Storage/Imap.php64
-rw-r--r--libs/Zend/Mail/Storage/Maildir.php42
-rw-r--r--libs/Zend/Mail/Storage/Mbox.php32
-rw-r--r--libs/Zend/Mail/Storage/Pop3.php24
-rw-r--r--libs/Zend/Mail/Storage/Writable/Interface.php8
-rw-r--r--libs/Zend/Mail/Storage/Writable/Maildir.php148
-rw-r--r--libs/Zend/Mail/Transport/Abstract.php18
-rw-r--r--libs/Zend/Mail/Transport/Exception.php10
-rw-r--r--libs/Zend/Mail/Transport/Sendmail.php75
-rw-r--r--libs/Zend/Mail/Transport/Smtp.php32
-rw-r--r--libs/Zend/Mime.php6
-rw-r--r--libs/Zend/Mime/Decode.php8
-rw-r--r--libs/Zend/Mime/Exception.php8
-rw-r--r--libs/Zend/Mime/Message.php12
-rw-r--r--libs/Zend/Mime/Part.php14
-rw-r--r--libs/Zend/Registry.php22
-rw-r--r--libs/Zend/Session.php76
-rw-r--r--libs/Zend/Session/Abstract.php12
-rw-r--r--libs/Zend/Session/Exception.php8
-rw-r--r--libs/Zend/Session/Namespace.php60
-rw-r--r--libs/Zend/Session/SaveHandler/DbTable.php36
-rw-r--r--libs/Zend/Session/SaveHandler/Exception.php8
-rw-r--r--libs/Zend/Session/SaveHandler/Interface.php6
-rw-r--r--libs/Zend/Session/Validator/Abstract.php8
-rw-r--r--libs/Zend/Session/Validator/HttpUserAgent.php8
-rw-r--r--libs/Zend/Session/Validator/Interface.php6
-rw-r--r--libs/Zend/Uri.php85
-rw-r--r--libs/Zend/Uri/Exception.php8
-rw-r--r--libs/Zend/Uri/Http.php89
-rw-r--r--libs/Zend/Validate.php90
-rw-r--r--libs/Zend/Validate/Abstract.php42
-rw-r--r--libs/Zend/Validate/Alnum.php32
-rw-r--r--libs/Zend/Validate/Alpha.php30
-rw-r--r--libs/Zend/Validate/Barcode.php182
-rw-r--r--libs/Zend/Validate/Barcode/AdapterAbstract.php315
-rw-r--r--libs/Zend/Validate/Barcode/AdapterInterface.php68
-rw-r--r--libs/Zend/Validate/Barcode/Code25.php64
-rw-r--r--libs/Zend/Validate/Barcode/Code25interleaved.php64
-rw-r--r--libs/Zend/Validate/Barcode/Code39.php100
-rw-r--r--libs/Zend/Validate/Barcode/Code39ext.php58
-rw-r--r--libs/Zend/Validate/Barcode/Code93.php120
-rw-r--r--libs/Zend/Validate/Barcode/Code93ext.php58
-rw-r--r--libs/Zend/Validate/Barcode/Ean12.php52
-rw-r--r--libs/Zend/Validate/Barcode/Ean13.php88
-rw-r--r--libs/Zend/Validate/Barcode/Ean14.php52
-rw-r--r--libs/Zend/Validate/Barcode/Ean18.php52
-rw-r--r--libs/Zend/Validate/Barcode/Ean2.php58
-rw-r--r--libs/Zend/Validate/Barcode/Ean5.php58
-rw-r--r--libs/Zend/Validate/Barcode/Ean8.php69
-rw-r--r--libs/Zend/Validate/Barcode/Gtin12.php52
-rw-r--r--libs/Zend/Validate/Barcode/Gtin13.php52
-rw-r--r--libs/Zend/Validate/Barcode/Gtin14.php52
-rw-r--r--libs/Zend/Validate/Barcode/Identcode.php52
-rw-r--r--libs/Zend/Validate/Barcode/Intelligentmail.php58
-rw-r--r--libs/Zend/Validate/Barcode/Issn.php119
-rw-r--r--libs/Zend/Validate/Barcode/Itf14.php52
-rw-r--r--libs/Zend/Validate/Barcode/Leitcode.php52
-rw-r--r--libs/Zend/Validate/Barcode/Planet.php52
-rw-r--r--libs/Zend/Validate/Barcode/Postnet.php52
-rw-r--r--libs/Zend/Validate/Barcode/Royalmail.php121
-rw-r--r--libs/Zend/Validate/Barcode/Sscc.php52
-rw-r--r--libs/Zend/Validate/Barcode/UpcA.php103
-rw-r--r--libs/Zend/Validate/Barcode/Upca.php52
-rw-r--r--libs/Zend/Validate/Barcode/Upce.php69
-rw-r--r--libs/Zend/Validate/Between.php52
-rw-r--r--libs/Zend/Validate/Callback.php174
-rw-r--r--libs/Zend/Validate/Ccnum.php19
-rw-r--r--libs/Zend/Validate/CreditCard.php317
-rw-r--r--libs/Zend/Validate/Date.php63
-rw-r--r--libs/Zend/Validate/Db/Abstract.php310
-rw-r--r--libs/Zend/Validate/Db/NoRecordExists.php9
-rw-r--r--libs/Zend/Validate/Db/RecordExists.php52
-rw-r--r--libs/Zend/Validate/Digits.php18
-rw-r--r--libs/Zend/Validate/EmailAddress.php502
-rw-r--r--libs/Zend/Validate/Exception.php11
-rw-r--r--libs/Zend/Validate/File/Count.php45
-rw-r--r--libs/Zend/Validate/File/Crc32.php18
-rw-r--r--libs/Zend/Validate/File/ExcludeExtension.php14
-rw-r--r--libs/Zend/Validate/File/ExcludeMimeType.php12
-rw-r--r--libs/Zend/Validate/File/Exists.php14
-rw-r--r--libs/Zend/Validate/File/Extension.php16
-rw-r--r--libs/Zend/Validate/File/FilesSize.php31
-rw-r--r--libs/Zend/Validate/File/Hash.php24
-rw-r--r--libs/Zend/Validate/File/ImageSize.php24
-rw-r--r--libs/Zend/Validate/File/IsCompressed.php117
-rw-r--r--libs/Zend/Validate/File/IsImage.php145
-rw-r--r--libs/Zend/Validate/File/Md5.php20
-rw-r--r--libs/Zend/Validate/File/MimeType.php102
-rw-r--r--libs/Zend/Validate/File/NotExists.php10
-rw-r--r--libs/Zend/Validate/File/Sha1.php18
-rw-r--r--libs/Zend/Validate/File/Size.php27
-rw-r--r--libs/Zend/Validate/File/Upload.php30
-rw-r--r--libs/Zend/Validate/File/WordCount.php12
-rw-r--r--libs/Zend/Validate/Float.php64
-rw-r--r--libs/Zend/Validate/GreaterThan.php28
-rw-r--r--libs/Zend/Validate/Hex.php13
-rw-r--r--libs/Zend/Validate/Hostname.php208
-rw-r--r--libs/Zend/Validate/Hostname/Biz.php6
-rw-r--r--libs/Zend/Validate/Hostname/Cn.php6
-rw-r--r--libs/Zend/Validate/Hostname/Com.php6
-rw-r--r--libs/Zend/Validate/Hostname/Jp.php6
-rw-r--r--libs/Zend/Validate/Iban.php49
-rw-r--r--libs/Zend/Validate/Identical.php65
-rw-r--r--libs/Zend/Validate/InArray.php108
-rw-r--r--libs/Zend/Validate/Int.php44
-rw-r--r--libs/Zend/Validate/Interface.php23
-rw-r--r--libs/Zend/Validate/Ip.php141
-rw-r--r--libs/Zend/Validate/Isbn.php279
-rw-r--r--libs/Zend/Validate/LessThan.php27
-rw-r--r--libs/Zend/Validate/NotEmpty.php190
-rw-r--r--libs/Zend/Validate/PostCode.php210
-rw-r--r--libs/Zend/Validate/Regex.php47
-rw-r--r--libs/Zend/Validate/Sitemap/Changefreq.php20
-rw-r--r--libs/Zend/Validate/Sitemap/Lastmod.php29
-rw-r--r--libs/Zend/Validate/Sitemap/Loc.php28
-rw-r--r--libs/Zend/Validate/Sitemap/Priority.php27
-rw-r--r--libs/Zend/Validate/StringLength.php52
-rw-r--r--libs/Zend/Version.php8
-rw-r--r--libs/javascript/json2.js30
-rw-r--r--libs/jquery/fdd2div-modified.js6
-rw-r--r--libs/jquery/jquery-calendar.css190
-rw-r--r--libs/jquery/jquery-calendar.js72
-rw-r--r--libs/jquery/jquery-ui.js391
-rw-r--r--libs/jquery/jquery.bgiframe.js10
-rw-r--r--libs/jquery/jquery.blockUI.js15
-rw-r--r--libs/jquery/jquery.js165
-rw-r--r--libs/jquery/jquery.scrollTo-min.js11
-rw-r--r--libs/jquery/macFFBgHack.pngbin207 -> 0 bytes
-rw-r--r--libs/jquery/original lib/jquery-calendar.js814
-rw-r--r--libs/jquery/original lib/jquery-ui.js5586
-rw-r--r--libs/jquery/original lib/jquery.blockUI.js638
-rw-r--r--libs/jquery/original lib/jquery.js6289
-rw-r--r--libs/jquery/stop.pngbin288 -> 0 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-anim_basic_16x16.gifbin0 -> 1553 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.pngbin0 -> 180 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-bg_flat_75_ffffff_40x100.pngbin0 -> 178 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.pngbin0 -> 120 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-bg_glass_65_ffffff_1x400.pngbin0 -> 105 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-bg_glass_75_dadada_1x400.pngbin0 -> 111 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.pngbin0 -> 110 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-bg_glass_95_fef1ec_1x400.pngbin0 -> 119 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.pngbin0 -> 101 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-icons_222222_256x240.pngbin0 -> 4369 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-icons_2e83ff_256x240.pngbin0 -> 4369 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-icons_454545_256x240.pngbin0 -> 4369 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-icons_888888_256x240.pngbin0 -> 4369 bytes
-rw-r--r--libs/jquery/themes/base/images/ui-icons_cd0a0a_256x240.pngbin0 -> 4369 bytes
-rw-r--r--libs/jquery/themes/base/jquery-ui.css487
-rw-r--r--libs/jquery/thickbox-loading.gifbin5886 -> 0 bytes
-rw-r--r--libs/jquery/thickbox.css194
-rw-r--r--libs/jquery/thickbox.js319
-rw-r--r--libs/json/json.js317
-rw-r--r--libs/open-flash-chart/php-ofc-library/ofc_bar.php2
-rw-r--r--libs/open-flash-chart/php-ofc-library/ofc_bar_3d.php2
-rw-r--r--libs/open-flash-chart/php-ofc-library/ofc_bar_filled.php2
-rw-r--r--libs/open-flash-chart/php-ofc-library/ofc_bar_glass.php4
-rw-r--r--libs/open-flash-chart/php-ofc-library/ofc_bar_sketch.php2
-rw-r--r--libs/open-flash-chart/php-ofc-library/ofc_bar_stack.php4
-rw-r--r--libs/open-flash-chart/php-ofc-library/ofc_candle.php2
-rw-r--r--libs/open-flash-chart/php-ofc-library/ofc_tooltip.php2
-rw-r--r--libs/open-flash-chart/php-ofc-library/ofc_y_axis_label.php74
-rw-r--r--libs/open-flash-chart/php-ofc-library/ofc_y_axis_labels.php112
-rw-r--r--libs/open-flash-chart/php-ofc-library/open-flash-chart.php84
-rw-r--r--libs/sparkline/LICENSE-BSD.txt (renamed from libs/sparkline/LICENSE)2
-rw-r--r--libs/sparkline/LICENSE-GPL.txt278
-rw-r--r--libs/sparkline/lib/Sparkline.php11
-rw-r--r--libs/sparkline/lib/Sparkline_Bar.php8
-rw-r--r--libs/sparkline/lib/Sparkline_Line.php24
-rw-r--r--libs/upgradephp/common.php137
-rw-r--r--misc/TODO7
-rw-r--r--misc/WebAppGallery/Manifest.xml10
-rw-r--r--misc/WebAppGallery/parameters.xml24
-rw-r--r--misc/cron/archive.sh65
-rw-r--r--misc/cron/archive.windows.ps188
-rw-r--r--misc/generateVisits.php118
-rw-r--r--misc/redirectToUrl.php5
-rw-r--r--piwik.js16
-rw-r--r--piwik.php18
-rw-r--r--plugins/API/API.php8
-rw-r--r--plugins/API/templates/listAllAPI.tpl21
-rw-r--r--plugins/Actions/API.php13
-rw-r--r--plugins/Actions/Actions.php86
-rw-r--r--plugins/Actions/Controller.php168
-rw-r--r--plugins/Actions/tests/Actions.test.php6
-rw-r--r--plugins/AnonymizeIP/AnonymizeIP.php79
-rw-r--r--plugins/AnonymizeIP/tests/AnonymizeIP.test.php46
-rw-r--r--plugins/CoreAdminHome/Controller.php49
-rw-r--r--plugins/CoreAdminHome/CoreAdminHome.php16
-rw-r--r--plugins/CoreAdminHome/templates/footer.tpl2
-rw-r--r--plugins/CoreAdminHome/templates/generalSettings.js30
-rw-r--r--plugins/CoreAdminHome/templates/generalSettings.tpl53
-rw-r--r--plugins/CoreAdminHome/templates/header.tpl30
-rw-r--r--plugins/CoreAdminHome/templates/index.tpl17
-rw-r--r--plugins/CoreAdminHome/templates/menu.css7
-rw-r--r--plugins/CoreAdminHome/templates/menu.tpl16
-rw-r--r--plugins/CoreAdminHome/templates/styles.css53
-rw-r--r--plugins/CoreHome/Controller.php45
-rw-r--r--plugins/CoreHome/CoreHome.php7
-rw-r--r--plugins/CoreHome/templates/broadcast.js58
-rw-r--r--plugins/CoreHome/templates/calendar.js153
-rw-r--r--plugins/CoreHome/templates/cloud.tpl4
-rw-r--r--plugins/CoreHome/templates/datatable.css62
-rw-r--r--plugins/CoreHome/templates/datatable.js163
-rw-r--r--plugins/CoreHome/templates/datatable.tpl8
-rw-r--r--plugins/CoreHome/templates/datatable_actions.tpl7
-rw-r--r--plugins/CoreHome/templates/datatable_actions_recursive.tpl2
-rw-r--r--plugins/CoreHome/templates/datatable_actions_subdatable.tpl1
-rw-r--r--plugins/CoreHome/templates/datatable_footer.tpl38
-rw-r--r--plugins/CoreHome/templates/date.js10
-rw-r--r--plugins/CoreHome/templates/graph.tpl8
-rw-r--r--plugins/CoreHome/templates/header.tpl22
-rw-r--r--plugins/CoreHome/templates/header_message.tpl12
-rw-r--r--plugins/CoreHome/templates/index.tpl25
-rw-r--r--plugins/CoreHome/templates/js_css_includes.tpl8
-rw-r--r--plugins/CoreHome/templates/loading.tpl4
-rw-r--r--plugins/CoreHome/templates/menu.css11
-rw-r--r--plugins/CoreHome/templates/menu.js14
-rw-r--r--plugins/CoreHome/templates/period_select.tpl10
-rw-r--r--plugins/CoreHome/templates/piwik_tag.tpl4
-rw-r--r--plugins/CoreHome/templates/sites_selection.tpl4
-rw-r--r--plugins/CoreHome/templates/styles.css28
-rw-r--r--plugins/CoreHome/templates/top_bar.tpl4
-rw-r--r--plugins/CoreHome/templates/top_screen.tpl7
-rw-r--r--plugins/CorePluginsAdmin/Controller.php34
-rw-r--r--plugins/CorePluginsAdmin/CorePluginsAdmin.php12
-rw-r--r--plugins/CorePluginsAdmin/templates/manage.tpl9
-rw-r--r--plugins/CoreUpdater/Controller.php58
-rw-r--r--plugins/CoreUpdater/CoreUpdater.php43
-rw-r--r--plugins/CoreUpdater/templates/cli_update_database_done.tpl4
-rw-r--r--plugins/CoreUpdater/templates/cli_update_welcome.tpl22
-rw-r--r--plugins/CoreUpdater/templates/header.tpl14
-rw-r--r--plugins/CoreUpdater/templates/update_database_done.tpl26
-rw-r--r--plugins/CoreUpdater/templates/update_new_version_available.tpl10
-rw-r--r--plugins/CoreUpdater/templates/update_one_click_done.tpl12
-rw-r--r--plugins/CoreUpdater/templates/update_welcome.tpl93
-rw-r--r--plugins/DBStats/API.php13
-rw-r--r--plugins/DBStats/Controller.php3
-rw-r--r--plugins/DBStats/DBStats.php12
-rw-r--r--plugins/DBStats/templates/DBStats.tpl7
-rw-r--r--plugins/Dashboard/Controller.php96
-rw-r--r--plugins/Dashboard/Dashboard.php23
-rw-r--r--plugins/Dashboard/templates/Dashboard.js42
-rw-r--r--plugins/Dashboard/templates/dashboard.css7
-rw-r--r--plugins/Dashboard/templates/index.tpl42
-rw-r--r--plugins/Dashboard/templates/widgetMenu.js12
-rw-r--r--plugins/ExampleAPI/ExampleAPI.php9
-rw-r--r--plugins/ExampleFeedburner/ExampleFeedburner.php76
-rw-r--r--plugins/ExampleFeedburner/templates/feedburner.tpl60
-rw-r--r--plugins/ExamplePlugin/ExamplePlugin.php90
-rw-r--r--plugins/ExamplePlugin/lang/en.php1
-rw-r--r--plugins/ExampleRssWidget/ExampleRssWidget.php12
-rw-r--r--plugins/ExampleUI/API.php12
-rw-r--r--plugins/ExampleUI/Controller.php4
-rw-r--r--plugins/ExampleUI/ExampleUI.php12
-rw-r--r--plugins/ExampleUI/images/icons-planet/LICENSE4
-rw-r--r--plugins/Feedback/Controller.php38
-rw-r--r--plugins/Feedback/Feedback.php29
-rw-r--r--plugins/Feedback/images/go-previous.pngbin0 -> 1200 bytes
-rw-r--r--plugins/Feedback/templates/feedback.js28
-rw-r--r--plugins/Feedback/templates/index.tpl79
-rw-r--r--plugins/Feedback/templates/sent.tpl41
-rw-r--r--plugins/Feedback/templates/styles.css28
-rw-r--r--plugins/Goals/API.php37
-rw-r--r--plugins/Goals/Controller.php218
-rw-r--r--plugins/Goals/Goals.php30
-rw-r--r--plugins/Goals/templates/GoalForm.js111
-rw-r--r--plugins/Goals/templates/add_edit_goal.tpl68
-rw-r--r--plugins/Goals/templates/add_new_goal.tpl4
-rw-r--r--plugins/Goals/templates/form_add_goal.tpl149
-rw-r--r--plugins/Goals/templates/goals.css40
-rw-r--r--plugins/Goals/templates/list_goal_edit.tpl39
-rw-r--r--plugins/Goals/templates/list_top_segment.tpl11
-rw-r--r--plugins/Goals/templates/overview.tpl41
-rw-r--r--plugins/Goals/templates/release_notes.tpl36
-rw-r--r--plugins/Goals/templates/single_goal.tpl46
-rw-r--r--plugins/Goals/templates/table_by_segment.tpl72
-rw-r--r--plugins/Goals/templates/title_and_evolution_graph.tpl12
-rw-r--r--plugins/Installation/Controller.php417
-rw-r--r--plugins/Installation/FormDatabaseSetup.php20
-rw-r--r--plugins/Installation/FormFirstWebsiteSetup.php30
-rw-r--r--plugins/Installation/FormGeneralSetup.php19
-rw-r--r--plugins/Installation/Installation.php22
-rw-r--r--plugins/Installation/View.php5
-rw-r--r--plugins/Installation/templates/databaseCheck.tpl34
-rw-r--r--plugins/Installation/templates/databaseSetup.tpl2
-rw-r--r--plugins/Installation/templates/displayJavascriptCode.tpl11
-rw-r--r--plugins/Installation/templates/firstWebsiteSetup.tpl4
-rw-r--r--plugins/Installation/templates/integrityDetails.tpl43
-rw-r--r--plugins/Installation/templates/structure.tpl71
-rw-r--r--plugins/Installation/templates/systemCheck.tpl75
-rw-r--r--plugins/Installation/templates/tablesCreation.tpl21
-rw-r--r--plugins/Installation/templates/welcome.tpl25
-rw-r--r--plugins/LanguagesManager/API.php49
-rw-r--r--plugins/LanguagesManager/Controller.php4
-rw-r--r--plugins/LanguagesManager/LanguagesManager.php48
-rw-r--r--plugins/LanguagesManager/templates/languages.tpl5
-rw-r--r--plugins/LanguagesManager/tests/LanguagesManager.test.php45
-rw-r--r--plugins/Live/API.php254
-rw-r--r--plugins/Live/Controller.php181
-rw-r--r--plugins/Live/Live.php51
-rw-r--r--plugins/Live/Visitor.php126
-rw-r--r--plugins/Live/templates/images/download.pngbin0 -> 734 bytes
-rw-r--r--plugins/Live/templates/images/file0.pngbin0 -> 535 bytes
-rw-r--r--plugins/Live/templates/images/file1.pngbin0 -> 683 bytes
-rw-r--r--plugins/Live/templates/images/file2.pngbin0 -> 632 bytes
-rw-r--r--plugins/Live/templates/images/file3.pngbin0 -> 661 bytes
-rw-r--r--plugins/Live/templates/images/file4.pngbin0 -> 596 bytes
-rw-r--r--plugins/Live/templates/images/file5.pngbin0 -> 653 bytes
-rw-r--r--plugins/Live/templates/images/file6.pngbin0 -> 654 bytes
-rw-r--r--plugins/Live/templates/images/file7.pngbin0 -> 637 bytes
-rw-r--r--plugins/Live/templates/images/file8.pngbin0 -> 574 bytes
-rw-r--r--plugins/Live/templates/images/file9.pngbin0 -> 566 bytes
-rw-r--r--plugins/Live/templates/images/goal.pngbin0 -> 672 bytes
-rw-r--r--plugins/Live/templates/images/outboundlink.pngbin0 -> 799 bytes
-rw-r--r--plugins/Live/templates/index.tpl180
-rw-r--r--plugins/Live/templates/lastVisits.tpl40
-rw-r--r--plugins/Live/templates/scripts/spy.js39
-rw-r--r--plugins/Live/templates/structure.tpl5
-rw-r--r--plugins/Live/templates/totalVisits.tpl26
-rw-r--r--plugins/Login/Auth.php4
-rw-r--r--plugins/Login/Controller.php174
-rw-r--r--plugins/Login/Form.php9
-rw-r--r--plugins/Login/Login.php43
-rw-r--r--plugins/Login/PasswordForm.php4
-rw-r--r--plugins/Login/ResetPasswordForm.php6
-rw-r--r--plugins/Login/templates/header.tpl7
-rw-r--r--plugins/Login/templates/login.css2
-rw-r--r--plugins/Login/templates/login.tpl8
-rw-r--r--plugins/Login/templates/lostPassword.tpl3
-rw-r--r--plugins/Login/templates/passwordchanged.tpl2
-rw-r--r--plugins/Login/templates/passwordsent.tpl2
-rw-r--r--plugins/Login/templates/resetPassword.tpl3
-rw-r--r--plugins/MultiSites/Controller.php195
-rw-r--r--plugins/MultiSites/MultiSites.php46
-rw-r--r--plugins/MultiSites/images/arrow_asc.gifbin0 -> 120 bytes
-rw-r--r--plugins/MultiSites/images/arrow_desc.gifbin0 -> 122 bytes
-rw-r--r--plugins/MultiSites/images/arrow_down.pngbin0 -> 685 bytes
-rw-r--r--plugins/MultiSites/images/arrow_up.pngbin0 -> 707 bytes
-rw-r--r--plugins/MultiSites/images/door_in.pngbin0 -> 693 bytes
-rw-r--r--plugins/MultiSites/images/link.gifbin0 -> 75 bytes
-rw-r--r--plugins/MultiSites/images/loading-blue.gifbin0 -> 1849 bytes
-rw-r--r--plugins/MultiSites/images/stop.pngbin0 -> 577 bytes
-rw-r--r--plugins/MultiSites/templates/common.js245
-rw-r--r--plugins/MultiSites/templates/index.tpl99
-rw-r--r--plugins/MultiSites/templates/row.tpl26
-rw-r--r--plugins/MultiSites/templates/styles.css46
-rw-r--r--plugins/Provider/API.php4
-rw-r--r--plugins/Provider/Provider.php37
-rw-r--r--plugins/Provider/functions.php6
-rw-r--r--plugins/Referers/API.php31
-rw-r--r--plugins/Referers/Controller.php4
-rw-r--r--plugins/Referers/Referers.php54
-rw-r--r--plugins/Referers/images/searchEngines/1.cz.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/acont.de.pngbin488 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/all.by.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/apollo.lv.pngbin0 -> 578 bytes
-rw-r--r--plugins/Referers/images/searchEngines/bg.setooz.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/blogs.gigablast.com.pngbin0 -> 752 bytes
-rw-r--r--plugins/Referers/images/searchEngines/blogs.seekport.de.pngbin475 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/blogsearch.google.com.pngbin838 -> 1207 bytes
-rw-r--r--plugins/Referers/images/searchEngines/cf.dir.yahoo.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/class.hit-parade.com.pngbin1214 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/clusty.com.pngbin0 -> 802 bytes
-rw-r--r--plugins/Referers/images/searchEngines/data.quicksearches.net.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/de.forestle.org.pngbin0 -> 694 bytes
-rw-r--r--plugins/Referers/images/searchEngines/digg.com.pngbin0 -> 377 bytes
-rw-r--r--plugins/Referers/images/searchEngines/directory.google.com.pngbin1127 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/duckduckgo.com.pngbin0 -> 892 bytes
-rw-r--r--plugins/Referers/images/searchEngines/ecosia.org.pngbin0 -> 1031 bytes
-rw-r--r--plugins/Referers/images/searchEngines/find.copernic.com.pngbin28708 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/friendfeed.com.pngbin0 -> 421 bytes
-rw-r--r--plugins/Referers/images/searchEngines/froogle.google.com.pngbin838 -> 1207 bytes
-rw-r--r--plugins/Referers/images/searchEngines/fulltext.centrum.cz.pngbin507 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/g.msn.com.pngbin1102 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/gais.cs.ccu.edu.tw.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/google.canoe.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/googlesyndicatedsearch.com.pngbin0 -> 854 bytes
-rw-r--r--plugins/Referers/images/searchEngines/guide.opendns.com.pngbin478 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/hledani.tiscali.cz.pngbin284 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/hotbot.lycos.com.pngbin0 -> 798 bytes
-rw-r--r--plugins/Referers/images/searchEngines/hotbox.pngbin1130 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/ie4.nomade.fr.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/images.google.com.pngbin1127 -> 1207 bytes
-rw-r--r--plugins/Referers/images/searchEngines/images.search.yahoo.com.pngbin0 -> 454 bytes
-rw-r--r--plugins/Referers/images/searchEngines/ko.search.need2find.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/lo.st.pngbin0 -> 819 bytes
-rw-r--r--plugins/Referers/images/searchEngines/meta.rrzn.uni-hannover.de.pngbin0 -> 160 bytes
-rw-r--r--plugins/Referers/images/searchEngines/metaresults.copernic.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/morfeo.centrum.cz.pngbin507 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/mserv.rrzn.uni-hannover.de.pngbin170 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/msxml.excite.com.pngbin1008 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/news.google.com.pngbin1127 -> 1207 bytes
-rw-r--r--plugins/Referers/images/searchEngines/news.openfind.com.tw.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/news.seekport.de.pngbin475 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/nmsearch.3721.com.pngbin446 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/otsing.delfi.ee.pngbin0 -> 445 bytes
-rw-r--r--plugins/Referers/images/searchEngines/p.zhongsou.com.pngbin0 -> 822 bytes
-rw-r--r--plugins/Referers/images/searchEngines/pesquisa.sapo.pt.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/recherche.hit-parade.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/rechercher.nomade.tiscali.fr.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search-dyn.tiscali.it.pngbin1055 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.babylon.com.pngbin0 -> 1008 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.conduit.com.pngbin0 -> 388 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.dogpile.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.freecause.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.iwon.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.msn.com.pngbin1055 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.naver.com.pngbin0 -> 133 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.netscape.com.pngbin1132 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.nifty.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.opera.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.rambler.ru.pngbin228 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.supereva.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.www.ee.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search.yaca.yandex.ru.pngbin341 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/search1.seznam.cz.pngbin1149 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/searchservice.myspace.com.pngbin0 -> 463 bytes
-rw-r--r--plugins/Referers/images/searchEngines/servizi.mediaset.it.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/smart.delfi.lv.pngbin0 -> 445 bytes
-rw-r--r--plugins/Referers/images/searchEngines/suche.defind.de.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/translate.google.com.pngbin1127 -> 1207 bytes
-rw-r--r--plugins/Referers/images/searchEngines/travel.gigablast.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/vivisimo.com.pngbin0 -> 458 bytes
-rw-r--r--plugins/Referers/images/searchEngines/web.toile.com.pngbin1115 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/wps.openfind.com.tw.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.123people.com.pngbin0 -> 559 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.4call.dastelefonbuch.de.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.acoon.de.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.caloweb.de.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.crossbot.de.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.cuil.com.pngbin0 -> 644 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.dasoertliche.de.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.deskfeeds.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.dino-online.de.pngbin0 -> 653 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.eniro.se.pngbin0 -> 697 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.enrio.se.pngbin505 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.eo.st.pngbin598 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.eu.ixquick.com.pngbin489 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.eudip.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.eurip.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.everyclick.com.pngbin0 -> 798 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.facebook.com.pngbin0 -> 246 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.feedminer.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.feedster.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.firstsfind.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.fixsuche.de.pngbin0 -> 947 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.gnadenmeer.de.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.google.com.pngbin1127 -> 1207 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.google.interia.pl.pngbin382 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.hooseek.com.pngbin0 -> 536 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.hotbot.com.pngbin237 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.ilse.nl.pngbin0 -> 856 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.jungle-spider.de.pngbin0 -> 870 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.kostenlos.de.pngbin0 -> 707 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.latne.lv.pngbin0 -> 704 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.maailm.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.meceoo.fr.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.meinestadt.de.pngbin671 -> 232 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.mister-wong.com.pngbin0 -> 977 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.monstercrawler.com.pngbin0 -> 992 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.mozbot.com.pngbin1041 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.multimania.lycos.fr.pngbin1214 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.mysearch.com.png (renamed from plugins/Referers/images/searchEngines/www.mywebsearch.com.png)bin1092 -> 1092 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.neti.ee.pngbin0 -> 822 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.netster.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.overture.com.pngbin0 -> 454 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.qualigo.at.pngbin0 -> 556 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.qualigo.de.pngbin576 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.rpmfind.net.pngbin0 -> 829 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.searchscout.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.seekport.de.pngbin475 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.sogou.com.pngbin0 -> 560 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.soso.com.pngbin0 -> 771 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.start.no.pngbin440 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.tixuma.de.pngbin0 -> 896 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.trusted--search.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.vindex.nl.pngbin0 -> 687 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.web.nl.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.webalta.ru.pngbin389 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.x-recherche.com.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.ya.ru.pngbin341 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/www.yandex.ru.pngbin341 -> 0 bytes
-rw-r--r--plugins/Referers/images/searchEngines/wxsl.nl.pngbin0 -> 726 bytes
-rw-r--r--plugins/Referers/images/searchEngines/ya.ru.pngbin341 -> 0 bytes
-rw-r--r--plugins/Referers/templates/index.tpl4
-rw-r--r--plugins/SecurityInfo/Controller.php44
-rw-r--r--plugins/SecurityInfo/LICENSE10
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/PhpSecInfo.php591
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Application/php.php66
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Application/piwik.php58
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/CGI/force_redirect.php71
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/allow_url_fopen.php79
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/allow_url_include.php82
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/display_errors.php62
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/expose_php.php64
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/file_uploads.php63
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/gid.php93
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/magic_quotes_gpc.php80
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/memory_limit.php88
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/open_basedir.php69
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/post_max_size.php71
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/register_globals.php77
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/uid.php93
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/upload_max_filesize.php70
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Core/upload_tmp_dir.php99
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Curl/file_support.php75
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Session/save_path.php99
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Session/use_trans_sid.php66
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Suhosin/extension.php46
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Suhosin/patch.php55
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Test.php571
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Test_Application.php54
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Test_Cgi.php61
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Test_Core.php44
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Test_Curl.php62
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Test_Session.php46
-rw-r--r--plugins/SecurityInfo/PhpSecInfo/Test/Test_Suhosin.php50
-rw-r--r--plugins/SecurityInfo/README89
-rw-r--r--plugins/SecurityInfo/SecurityInfo.php44
-rw-r--r--plugins/SecurityInfo/templates/index.tpl31
-rw-r--r--plugins/SitesManager/API.php567
-rw-r--r--plugins/SitesManager/Controller.php45
-rw-r--r--plugins/SitesManager/SitesManager.php106
-rw-r--r--plugins/SitesManager/templates/DisplayJavascriptCode.tpl5
-rw-r--r--plugins/SitesManager/templates/SitesManager.js168
-rw-r--r--plugins/SitesManager/templates/SitesManager.tpl132
-rw-r--r--plugins/SitesManager/tests/SitesManager.test.php369
-rw-r--r--plugins/UserCountry/API.php3
-rw-r--r--plugins/UserCountry/UserCountry.php29
-rw-r--r--plugins/UserSettings/API.php5
-rw-r--r--plugins/UserSettings/Controller.php2
-rw-r--r--plugins/UserSettings/UserSettings.php39
-rw-r--r--plugins/UserSettings/functions.php35
-rw-r--r--plugins/UserSettings/images/browsers/AB.gifbin0 -> 1065 bytes
-rw-r--r--plugins/UserSettings/images/browsers/AN.gifbin0 -> 568 bytes
-rw-r--r--plugins/UserSettings/images/browsers/BE.gifbin0 -> 1074 bytes
-rw-r--r--plugins/UserSettings/images/browsers/BX.gifbin55 -> 522 bytes
-rw-r--r--plugins/UserSettings/images/browsers/CO.gifbin0 -> 1043 bytes
-rw-r--r--plugins/UserSettings/images/browsers/CS.gifbin0 -> 549 bytes
-rw-r--r--plugins/UserSettings/images/browsers/DI.gifbin55 -> 1092 bytes
-rw-r--r--plugins/UserSettings/images/browsers/EL.gifbin0 -> 90 bytes
-rw-r--r--plugins/UserSettings/images/browsers/EP.gifbin0 -> 317 bytes
-rw-r--r--plugins/UserSettings/images/browsers/FD.gifbin0 -> 1051 bytes
-rw-r--r--plugins/UserSettings/images/browsers/FE.gifbin0 -> 550 bytes
-rw-r--r--plugins/UserSettings/images/browsers/FL.gifbin0 -> 1039 bytes
-rw-r--r--plugins/UserSettings/images/browsers/GE.gifbin0 -> 999 bytes
-rw-r--r--plugins/UserSettings/images/browsers/HA.gifbin0 -> 1009 bytes
-rw-r--r--plugins/UserSettings/images/browsers/KP.gifbin0 -> 1040 bytes
-rw-r--r--plugins/UserSettings/images/browsers/KZ.gifbin0 -> 1063 bytes
-rw-r--r--plugins/UserSettings/images/browsers/MI.gifbin0 -> 1028 bytes
-rw-r--r--plugins/UserSettings/images/browsers/WO.gifbin0 -> 1065 bytes
-rw-r--r--plugins/UserSettings/images/browsers/WP.gifbin0 -> 983 bytes
-rw-r--r--plugins/UserSettings/images/os/AIX.gifbin330 -> 925 bytes
-rw-r--r--plugins/UserSettings/images/os/AMI.gifbin0 -> 1060 bytes
-rw-r--r--plugins/UserSettings/images/os/BEO.gifbin0 -> 1030 bytes
-rw-r--r--plugins/UserSettings/images/os/BSD.gifbin1084 -> 1016 bytes
-rw-r--r--plugins/UserSettings/images/os/DFB.gifbin0 -> 338 bytes
-rw-r--r--plugins/UserSettings/images/os/DSI.gifbin0 -> 1090 bytes
-rw-r--r--plugins/UserSettings/images/os/HPX.gifbin1115 -> 245 bytes
-rw-r--r--plugins/UserSettings/images/os/IPA.gifbin0 -> 582 bytes
-rw-r--r--plugins/UserSettings/images/os/IPH.gifbin569 -> 582 bytes
-rw-r--r--plugins/UserSettings/images/os/IRI.gifbin1113 -> 179 bytes
-rw-r--r--plugins/UserSettings/images/os/LIN.gifbin1084 -> 170 bytes
-rw-r--r--plugins/UserSettings/images/os/MAC.gifbin1083 -> 171 bytes
-rw-r--r--plugins/UserSettings/images/os/NBS.gifbin1084 -> 168 bytes
-rw-r--r--plugins/UserSettings/images/os/NDS.gifbin0 -> 1091 bytes
-rw-r--r--plugins/UserSettings/images/os/OBS.gifbin0 -> 572 bytes
-rw-r--r--plugins/UserSettings/images/os/OS2.gifbin1068 -> 214 bytes
-rw-r--r--plugins/UserSettings/images/os/POS.gifbin0 -> 1067 bytes
-rw-r--r--plugins/UserSettings/images/os/SOS.gifbin1026 -> 1077 bytes
-rw-r--r--plugins/UserSettings/images/os/SYL.gifbin0 -> 1019 bytes
-rw-r--r--plugins/UserSettings/images/os/T64.gifbin0 -> 235 bytes
-rw-r--r--plugins/UserSettings/images/os/UNK.gifbin975 -> 61 bytes
-rw-r--r--plugins/UserSettings/images/os/W2K.gifbin1100 -> 239 bytes
-rw-r--r--plugins/UserSettings/images/os/W95.gifbin1100 -> 239 bytes
-rw-r--r--plugins/UserSettings/images/os/W98.gifbin1100 -> 239 bytes
-rw-r--r--plugins/UserSettings/images/os/WI7.gifbin1118 -> 245 bytes
-rw-r--r--plugins/UserSettings/images/os/WME.gifbin1100 -> 239 bytes
-rw-r--r--plugins/UserSettings/images/os/WNT.gifbin1100 -> 239 bytes
-rw-r--r--plugins/UserSettings/images/os/WOS.gifbin0 -> 70 bytes
-rw-r--r--plugins/UserSettings/images/os/WS3.gifbin1118 -> 245 bytes
-rw-r--r--plugins/UserSettings/images/os/WVI.gifbin1118 -> 245 bytes
-rw-r--r--plugins/UserSettings/images/os/WXP.gifbin1118 -> 245 bytes
-rw-r--r--plugins/UserSettings/images/plugins/cookie.gifbin351 -> 211 bytes
-rw-r--r--plugins/UserSettings/images/plugins/director.gifbin887 -> 887 bytes
-rw-r--r--plugins/UserSettings/images/plugins/flash.gifbin957 -> 1018 bytes
-rw-r--r--plugins/UserSettings/images/plugins/gears.gifbin550 -> 950 bytes
-rw-r--r--plugins/UserSettings/images/plugins/java.gifbin706 -> 961 bytes
-rw-r--r--plugins/UserSettings/images/plugins/pdf.gifbin951 -> 1018 bytes
-rw-r--r--plugins/UserSettings/images/plugins/quicktime.gifbin846 -> 999 bytes
-rw-r--r--plugins/UserSettings/images/plugins/realplayer.gifbin661 -> 1026 bytes
-rw-r--r--plugins/UserSettings/images/plugins/silverlight.gifbin1007 -> 1007 bytes
-rw-r--r--plugins/UserSettings/images/plugins/windowsmedia.gifbin703 -> 1026 bytes
-rw-r--r--plugins/UserSettings/images/screens/dual.gifbin1089 -> 1081 bytes
-rw-r--r--plugins/UserSettings/images/screens/normal.gifbin1096 -> 1088 bytes
-rw-r--r--plugins/UserSettings/images/screens/wide.gifbin1028 -> 1020 bytes
-rw-r--r--plugins/UserSettings/templates/index.tpl2
-rw-r--r--plugins/UserSettings/tests/UserSettings.test.php800
-rw-r--r--plugins/UsersManager/API.php217
-rw-r--r--plugins/UsersManager/Controller.php253
-rw-r--r--plugins/UsersManager/UsersManager.php16
-rw-r--r--plugins/UsersManager/templates/UsersManager.js50
-rw-r--r--plugins/UsersManager/templates/UsersManager.tpl44
-rw-r--r--plugins/UsersManager/templates/userSettings.js60
-rw-r--r--plugins/UsersManager/templates/userSettings.tpl130
-rw-r--r--plugins/UsersManager/tests/UsersManager.test.php261
-rw-r--r--plugins/VisitFrequency/API.php2
-rw-r--r--plugins/VisitFrequency/VisitFrequency.php18
-rw-r--r--plugins/VisitFrequency/templates/index.tpl2
-rw-r--r--plugins/VisitTime/Controller.php6
-rw-r--r--plugins/VisitTime/VisitTime.php46
-rw-r--r--plugins/VisitorGenerator/Controller.php118
-rw-r--r--plugins/VisitorGenerator/Generator.php (renamed from core/Tracker/Generator.php)34
-rw-r--r--plugins/VisitorGenerator/Tracker.php (renamed from core/Tracker/Generator/Tracker.php)16
-rw-r--r--plugins/VisitorGenerator/Visit.php (renamed from core/Tracker/Generator/Visit.php)17
-rw-r--r--plugins/VisitorGenerator/VisitorGenerator.php44
-rw-r--r--plugins/VisitorGenerator/data/AcceptLanguage.php (renamed from misc/generateVisitsData/AcceptLanguage.php)16
-rw-r--r--plugins/VisitorGenerator/data/Referers.php (renamed from misc/generateVisitsData/Referers.php)16
-rw-r--r--plugins/VisitorGenerator/data/UserAgent.php (renamed from misc/generateVisitsData/UserAgent.php)16
-rw-r--r--plugins/VisitorGenerator/templates/generate.tpl30
-rw-r--r--plugins/VisitorGenerator/templates/index.tpl45
-rw-r--r--plugins/VisitorInterest/VisitorInterest.php13
-rw-r--r--plugins/VisitsSummary/API.php20
-rw-r--r--plugins/VisitsSummary/VisitsSummary.php9
-rw-r--r--plugins/VisitsSummary/templates/sparklines.tpl4
-rw-r--r--plugins/Widgetize/Controller.php11
-rw-r--r--plugins/Widgetize/Widgetize.php7
-rw-r--r--plugins/Widgetize/templates/index.tpl25
-rw-r--r--plugins/Widgetize/templates/js.tpl26
-rw-r--r--plugins/Widgetize/templates/widgetize.js29
-rw-r--r--tests/all_tests.php1
-rw-r--r--tests/build.xml82
-rw-r--r--tests/config/mysqli.template.php30
-rw-r--r--tests/config/pdo_mysql.template.php (renamed from tests/config.ini.template.php)2
-rw-r--r--tests/config_test.php13
-rw-r--r--tests/core/API/DocumentationGenerator.test.php3
-rw-r--r--tests/core/ArchiveProcessing.test.php121
-rw-r--r--tests/core/Common.test.php119
-rw-r--r--tests/core/DataTable.test.php4
-rw-r--r--tests/core/DataTable/Renderer.test.php13
-rw-r--r--tests/core/Database.test.php46
-rw-r--r--tests/core/Date.test.php105
-rw-r--r--tests/core/Http.test.php52
-rw-r--r--tests/core/Period.test.php52
-rw-r--r--tests/core/Piwik.test.php1
-rw-r--r--tests/core/ReleaseCheckList.test.php25
-rw-r--r--tests/core/TablePartitioning.test.php6
-rw-r--r--tests/core/Tracker/Action.test.php131
-rw-r--r--tests/core/Tracker/Visit.test.php108
-rw-r--r--tests/core/Url.test.php2
-rw-r--r--tests/javascript/assets/qunit.css130
-rw-r--r--tests/javascript/assets/qunit.js390
-rw-r--r--tests/javascript/index.php10
-rw-r--r--tests/simpletest/expectation.php3
-rw-r--r--tests/simpletest/simpletest.php6
-rw-r--r--tests/webtest/testcases/level0/test.piwik.index.xml31
-rw-r--r--themes/default/common.css44
-rw-r--r--themes/default/common.js93
-rw-r--r--themes/default/genericForm.tpl2
-rw-r--r--themes/default/simple_structure.css8
-rw-r--r--web.config20
1145 files changed, 65316 insertions, 22266 deletions
diff --git a/README b/README
index 1456071b5c..91fadb07ae 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
- Piwik - piwik.org
+ Piwik - piwik.org
Description
===========
@@ -20,10 +20,10 @@ Piwik is released under the GPL v3 license, see misc/license.txt
Requirements
============
-- php 5.1.3 minimum
-- mysql 4.1
-- php PDO module enabled
+- php 5.1.3 or greater
+- mysql 4.1 or greater, mysqli or PDO library must be enabled
- OS / server independant
+See http://piwik.org/docs/requirements/
Install
=======
@@ -31,10 +31,11 @@ Install
- Point your browser to the directory
- Follow the steps
- Add the given javascript code to your pages
+See http://piwik.org/docs/installation/
Changelog
=========
-see http://piwik.org/changelog/
+See http://piwik.org/changelog/
API
===
diff --git a/config/.htaccess b/config/.htaccess
deleted file mode 100644
index f1f7d1cfff..0000000000
--- a/config/.htaccess
+++ /dev/null
@@ -1,2 +0,0 @@
-# Deny all users web access to this directory
-Deny from all \ No newline at end of file
diff --git a/config/config.ini.sample.php b/config/config.ini.sample.php
index 1195f55753..f2604435ce 100644
--- a/config/config.ini.sample.php
+++ b/config/config.ini.sample.php
@@ -17,3 +17,4 @@ password = datatabasePassword
dbname = databaseName
adapter = PDO_MYSQL ; PDO_MYSQL, MYSQLI, or PDO_PGSQL
tables_prefix = piwik_
+;charset = utf8
diff --git a/config/global.ini.php b/config/global.ini.php
index f60a813a3e..12a2dff802 100644
--- a/config/global.ini.php
+++ b/config/global.ini.php
@@ -2,10 +2,10 @@
; If you want to change some of these default values, the best practise is to override
; them in your configuration file in config/config.ini.php. If you directly edit this file,
; you risk losing your changes when you upgrade Piwik.
-; For example if you want to override enable_browser_archiving_triggering,
+; For example if you want to override action_title_category_delimiter,
; edit config/config.ini.php and add the following:
; [General]
-; enable_browser_archiving_triggering = 0
+; action_title_category_delimiter = "-"
[superuser]
login = root
@@ -19,6 +19,10 @@ dbname =
tables_prefix =
port = 3306
adapter = PDO_MYSQL
+; if charset is set to utf8, Piwik will ensure that it is storing its data using UTF8 charset.
+; it will add a sql query SET at each page view.
+; Piwik should work correctly without this setting.
+;charset = utf8
[database_tests]
host = localhost
@@ -44,46 +48,22 @@ enable_sql_profiler = 0
track_visits_inside_piwik_ui = 0
[General]
-; Time in seconds after which an archive will be computed again.
-; This setting is used only for today's statistics.
-; Defaults to 10 seconds so that by default, Piwik provides real time reporting.
-time_before_today_archive_considered_outdated = 10
-
-; When loading piwik interface, we redirect the user to 'yesterday' statistics by default
-; Possible values: yesterday, today, or any YYYY-MM-DD
-default_day = yesterday
-; Possible values: day, week, month, year
-default_period = day
-
-; When loading piwik interface, Piwik will load by default the CoreHome module
-; You can override the setting to force the user to login.
-; This is useful when you have some websites view "anonymous" access but you want to
-; force users to login instead of viewing the first anonymous website available
-default_module_login = 0
-
-; When loading the piwik interface in the browser (as opposed to from the PHP-CLI client)
-; should we launch the archiving process if the archives have not yet been processed?
-; You want to set it to 0 when triggering the archiving is done through a crontab,
-; so that your users do not trigger archiving in their browser when this is not expected
-enable_browser_archiving_triggering = 1
-
-; character used to automatically create categories in the "Action" "Downloads" reports
+; character used to automatically create categories in the Actions > Pages, Outlinks and Downloads reports
; for example a URL like "example.com/blog/development/first-post" will create
; the page first-post in the subcategory development which belongs to the blog category
-action_category_delimiter = /
+action_url_category_delimiter = /
+
+; similar to above, but this delimiter is only used for page titles in the Actions > Page titles report
+action_title_category_delimiter = /
; this action name is used when the URL ends with a slash /
; it is useful to have an actual string to write in the UI
-action_default_name = index
+action_default_name = index
; this action name is used when the URL has no page title or page URL defined
action_default_name_when_not_defined = "page title not defined"
action_default_url_when_not_defined = "page url not defined"
-; currency used by default when reporting money in Piwik
-; the trailing space is required for php 5.2.x vs 5.3 compatibility
-default_currency = "$ "
-
; if you want all your users to use Piwik in only one language, disable the LanguagesManager
; plugin, and set this default_language (users won't see the language drop down)
default_language = en
@@ -99,10 +79,26 @@ API_datatable_default_limit = 50
; as it slows down the loading of the Piwik UI by setting this value to 0
show_website_selector_in_user_interface = 1
+; This setting is overriden in the UI, under "User Settings".
+; The date and period loaded by Piwik uses the defaults below. Possible values: yesterday, today.
+default_day = yesterday
+; Possible values: day, week, month, year.
+default_period = day
+
+; This setting is overriden in the UI, under "General Settings". This is the default value used if the setting hasn't been overriden via the UI.
+; Time in seconds after which an archive will be computed again. This setting is used only for today's statistics.
+; Defaults to 10 seconds so that by default, Piwik provides real time reporting.
+time_before_today_archive_considered_outdated = 10
+
+; This setting is overriden in the UI, under "General Settings". The default value is to allow browsers
+; to trigger the Piwik archiving process.
+enable_browser_archiving_triggering = 1
+
; PHP minimum required version (minimum requirement known to date = ->newInstanceArgs)
minimum_php_version = 5.1.3
; MySQL minimum required version
+; note: timezone support added in 4.1.3
minimum_mysql_version = 4.1
; PostgreSQL minimum required version
@@ -117,6 +113,10 @@ login_cookie_name = piwik_auth
; login cookie expiration (30 days)
login_cookie_expire = 2592000
+; The path on the server in which the cookie will be available on.
+; Defaults to empty. See spec in http://curl.haxx.se/rfc/cookie_spec.html
+login_cookie_path =
+
; email address that appears as a Sender in the password recovery email
; if specified, {DOMAIN} will be replaced by the current Piwik domain
login_password_recovery_email_address = "password-recovery@{DOMAIN}"
@@ -126,22 +126,27 @@ login_password_recovery_email_name = Piwik
; during archiving, Piwik will limit the number of results recorded, for performance reasons
; maximum number of rows for any of the Referers tables (keywords, search engines, campaigns, etc.)
-datatable_archiving_maximum_rows_referers = 500
+datatable_archiving_maximum_rows_referers = 1000
; maximum number of rows for any of the Referers subtable (search engines by keyword, keyword by campaign, etc.)
datatable_archiving_maximum_rows_subtable_referers = 50
; maximum number of rows for any of the Actions tables (pages, downloads, outlinks)
datatable_archiving_maximum_rows_actions = 500
; maximum number of rows for pages in categories (sub pages, when clicking on the + for a page category)
+; note: should not exceed the display limit in Piwik_Actions_Controller::ACTIONS_REPORT_ROWS_DISPLAY
+; because each subdirectory doesn't have paging at the bottom, so all data should be displayed if possible.
datatable_archiving_maximum_rows_subtable_actions = 100
+; maximum number of rows for other tables (Providers, User settings configurations)
+datatable_archiving_maximum_rows_standard = 500
+
; by default, Piwik uses self-hosted AJAX libraries.
; If set to 1, Piwik uses a Content Distribution Network
use_ajax_cdn = 0
; required AJAX library versions
-jquery_version = 1.3.2
-jqueryui_version = 1.7.2
+jquery_version = 1.4.2
+jqueryui_version = 1.8.2
swfobject_version = 2.2
; If set to 0, Flash widgets require separate HTTP requests
@@ -149,6 +154,9 @@ swfobject_version = 2.2
; If set to 1, Piwik uses a single HTTP request per Flash widget to serve both the widget and data
serve_widget_and_data = 1
+; If set to 1, Piwik adds a response header to workaround the IE+Flash+HTTPS bug.
+reverse_proxy = 0
+
[Tracker]
; set to 0 if you want to stop tracking the visitors. Useful if you need to stop all the connections on the DB.
record_statistics = 1
@@ -156,8 +164,8 @@ record_statistics = 1
; length of a visit in seconds. If a visitor comes back on the website visit_standard_length seconds after his last page view, it will be recorded as a new visit
visit_standard_length = 1800
-; visitors that stay on the website and view only one page will be considered staying 10 seconds
-default_time_one_page_visit = 10
+; visitors that stay on the website and view only one page will be considered staying 0 second
+default_time_one_page_visit = 0
; if set to 0, any goal conversion will be credited to the last more recent non empty referer.
; when set to 1, the first ever referer used to reach the website will be used
@@ -180,6 +188,13 @@ cookie_name = piwik_visitor
; by default, the Piwik tracking cookie expires in 2 years
cookie_expire = 63072000
+; The path on the server in which the cookie will be available on.
+; Defaults to empty. See spec in http://curl.haxx.se/rfc/cookie_spec.html
+cookie_path =
+
+; name of the cookie to ignore visits
+ignore_visits_cookie_name = piwik_ignore
+
; variable name to track any campaign, for example CPC campaign
; Example: If a visitor first visits 'index.php?piwik_campaign=Adwords-CPC' then it will be counted as a campaign referer named 'Adwords-CPC'
campaign_var_name = piwik_campaign
@@ -188,10 +203,19 @@ campaign_var_name = piwik_campaign
; Example: If a visitor first visits 'index.php?piwik_campaign=Adwords-CPC&piwik_kwd=My killer keyword' then it will be counted as a campaign referer named 'Adwords-CPC' with the keyword 'My killer keyword'
campaign_keyword_var_name = piwik_kwd
+; maximum length of a Page Title or a Page URL recorded in the log_action.name table
+page_maximum_length = 1024;
+
+; number of octets in IP address to mask, in order to anonymize a visitor's IP address
+; if the AnonymizeIP plugin is deactivated, this value is ignored
+; for IPv4 addresses, valid values are 0..4
+ip_address_mask_length = 1
+
+
[log]
;possible values for log: screen, database, file
-; normal messages
-logger_message[] = screen
+; by default, standard logging/debug messages are hidden from screen
+;logger_message[] = screen
logger_error[] = screen
logger_exception[] = screen
@@ -218,9 +242,6 @@ cache_dir = tmp/cache
; error reporting inside Smarty
error_reporting = E_ALL|E_NOTICE
-; allow smarty debugging using {debug}
-debugging = 1
-
[Plugins]
Plugins[] = CorePluginsAdmin
Plugins[] = CoreAdminHome
@@ -230,8 +251,10 @@ Plugins[] = Widgetize
Plugins[] = LanguagesManager
Plugins[] = Actions
Plugins[] = Dashboard
+Plugins[] = MultiSites
Plugins[] = Referers
Plugins[] = UserSettings
+Plugins[] = Goals
Plugins[] = UserCountry
Plugins[] = VisitsSummary
diff --git a/core/API/DataTableGenericFilter.php b/core/API/DataTableGenericFilter.php
index d339a080e7..c8843059c6 100644
--- a/core/API/DataTableGenericFilter.php
+++ b/core/API/DataTableGenericFilter.php
@@ -58,7 +58,8 @@ class Piwik_API_DataTableGenericFilter
'filter_add_columns_when_show_all_columns' => array('integer')
),
'UpdateColumnsWhenShowAllGoals' => array(
- 'filter_update_columns_when_show_all_goals' => array('integer')
+ 'filter_update_columns_when_show_all_goals' => array('integer'),
+ 'filter_only_display_idgoal' => array('integer', Piwik_DataTable_Filter_UpdateColumnsWhenShowAllGoals::GOALS_OVERVIEW),
),
'Sort' => array(
'filter_sort_column' => array('string'),
@@ -84,15 +85,23 @@ class Piwik_API_DataTableGenericFilter
if($datatable instanceof Piwik_DataTable_Array )
{
$tables = $datatable->getArray();
+ $filterWasApplied = false;
foreach($tables as $table)
{
- $this->applyGenericFilters($table);
+ $filterWasApplied = $this->applyGenericFilters($table);
+ // if no generic filter was applied to the first table, we can return
+ // as no filter would be applied to any other dataTable
+ if(!$filterWasApplied)
+ {
+ return;
+ }
}
return;
}
$genericFilters = self::getGenericFiltersInformation();
+ $filterApplied = false;
foreach($genericFilters as $filterName => $parameters)
{
$filterParameters = array();
@@ -123,18 +132,14 @@ class Piwik_API_DataTableGenericFilter
if(!$exceptionRaised)
{
- // a generic filter class name must follow this pattern
- $class = "Piwik_DataTable_Filter_".$filterName;
if($filterName == 'Limit')
{
$datatable->setRowsCountBeforeLimitFilter();
}
- // build the set of parameters for the filter
- $filterParameters = array_merge(array($datatable), $filterParameters);
- // use Reflection to create a new instance of the filter, given parameters $filterParameters
- $reflectionObj = new ReflectionClass($class);
- $filter = $reflectionObj->newInstanceArgs($filterParameters);
+ $datatable->filter($filterName, $filterParameters);
+ $filterApplied = true;
}
}
+ return $filterApplied;
}
}
diff --git a/core/API/DocumentationGenerator.php b/core/API/DocumentationGenerator.php
index 8a1d71de9f..0d959171fb 100644
--- a/core/API/DocumentationGenerator.php
+++ b/core/API/DocumentationGenerator.php
@@ -96,7 +96,7 @@ class Piwik_API_DocumentationGenerator
$str .= "</span>";
}
$str .= '</small>';
- $str .= "\n<br>";
+ $str .= "\n<br />";
}
}
return $str;
diff --git a/core/API/Proxy.php b/core/API/Proxy.php
index 26c11288c9..9bd12e25b4 100644
--- a/core/API/Proxy.php
+++ b/core/API/Proxy.php
@@ -12,6 +12,9 @@
/**
* To differentiate between "no value" and default value of null
+ *
+ * @package Piwik
+ * @subpackage Piwik_API
*/
class Piwik_API_Proxy_NoDefaultValue {}
@@ -215,8 +218,8 @@ class Piwik_API_Proxy
}
}
} catch(Exception $e) {
- throw new Exception("The required variable '$name' is not correct or has not been found in the API Request. Add the parameter '&$name=' (with a value) in the URL.");
- }
+ throw new Exception(Piwik_TranslateException('General_ExceptionVariableNotFound', array($name)));
+ }
$finalParameters[] = $requestValue;
}
return $finalParameters;
@@ -232,7 +235,7 @@ class Piwik_API_Proxy
$module = self::getModuleNameFromClassName($fileName);
$path = PIWIK_INCLUDE_PATH . '/plugins/' . $module . '/API.php';
- if(Zend_Loader::isReadable($path))
+ if(is_readable($path))
{
require_once $path; // prefixed by PIWIK_INCLUDE_PATH
}
@@ -282,7 +285,7 @@ class Piwik_API_Proxy
{
if(!$this->isMethodAvailable($className, $methodName))
{
- throw new Exception("The method '$methodName' does not exist or is not available in the module '".$className."'.");
+ throw new Exception(Piwik_TranslateException('General_ExceptionMethodNotFound', array($methodName,$className)));
}
}
diff --git a/core/API/Request.php b/core/API/Request.php
index b6d5f09f2a..c0ad14d5fc 100644
--- a/core/API/Request.php
+++ b/core/API/Request.php
@@ -87,7 +87,7 @@ class Piwik_API_Request
$outputFormat = strtolower(Piwik_Common::getRequestVar('format', 'xml', 'string', $this->request));
// create the response
- $response = new Piwik_API_ResponseBuilder($this->request, $outputFormat);
+ $response = new Piwik_API_ResponseBuilder($outputFormat, $this->request);
try {
// read parameters
@@ -101,13 +101,7 @@ class Piwik_API_Request
}
$module = "Piwik_" . $module . "_API";
- // if a token_auth is specified in the API request, we load the right permissions
- $token_auth = Piwik_Common::getRequestVar('token_auth', '', 'string', $this->request);
- if($token_auth)
- {
- Piwik_PostEvent('API.Request.authenticate', $token_auth);
- Zend_Registry::get('access')->reloadAccess();
- }
+ self::reloadAuthUsingTokenAuth($this->request);
// call the method
$returnedValue = Piwik_API_Proxy::getInstance()->call($module, $method, $this->request);
@@ -120,6 +114,25 @@ class Piwik_API_Request
}
/**
+ * If the token_auth is found in the $request parameter,
+ * the current session will be authenticated using this token_auth.
+ * It will overwrite the previous Auth object.
+ *
+ * @param $request If null, uses the default request ($_GET)
+ * @return void
+ */
+ static public function reloadAuthUsingTokenAuth($request = null)
+ {
+ // if a token_auth is specified in the API request, we load the right permissions
+ $token_auth = Piwik_Common::getRequestVar('token_auth', '', 'string', $request);
+ if($token_auth)
+ {
+ Piwik_PostEvent('API.Request.authenticate', $token_auth);
+ Zend_Registry::get('access')->reloadAccess();
+ }
+ }
+
+ /**
* Returns array( $class, $method) from the given string $class.$method
*
* @return array
diff --git a/core/API/ResponseBuilder.php b/core/API/ResponseBuilder.php
index a632163108..1d94dc9888 100644
--- a/core/API/ResponseBuilder.php
+++ b/core/API/ResponseBuilder.php
@@ -19,7 +19,7 @@ class Piwik_API_ResponseBuilder
private $request = null;
private $outputFormat = null;
- public function __construct($request, $outputFormat)
+ public function __construct($outputFormat, $request = array())
{
$this->request = $request;
$this->outputFormat = $outputFormat;
@@ -49,11 +49,17 @@ class Piwik_API_ResponseBuilder
*
* @throws Exception If an object/resource is returned, if any of conversion fails, etc.
*
- * @param mixed The initial returned value, before post process
+ * @param mixed The initial returned value, before post process. If set to null, success response is returned.
* @return mixed Usually a string, but can still be a PHP data structure if the format requested is 'original'
*/
- public function getResponse($value)
+ public function getResponse($value = null)
{
+ // when null or void is returned from the api call, we handle it as a successful operation
+ if(!isset($value))
+ {
+ return $this->handleSuccess();
+ }
+
// If the returned value is an object DataTable we
// apply the set of generic filters if asked in the URL
// and we render the DataTable according to the format specified in the URL
@@ -73,12 +79,6 @@ class Piwik_API_ResponseBuilder
return $this->handleArray($value);
}
- // when null or void is returned from the api call, we handle it as a successful operation
- if(!isset($value))
- {
- return $this->handleSuccess();
- }
-
// original data structure requested, we return without process
if( $this->outputFormat == 'original' )
{
@@ -104,41 +104,30 @@ class Piwik_API_ResponseBuilder
*/
public function getResponseException(Exception $e)
{
- $message = htmlentities($e->getMessage(), ENT_COMPAT, "UTF-8");
- switch($this->outputFormat)
+ $format = strtolower($this->outputFormat);
+
+ if( $format == 'original' )
{
- case 'original':
- throw $e;
- break;
- case 'xml':
- @header("Content-Type: text/xml;charset=utf-8");
- $return =
- "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" .
- "<result>\n".
- "\t<error message=\"".$message."\" />\n".
- "</result>";
- break;
- case 'json':
- @header( "Content-type: application/json" );
- // we remove the \n from the resulting string as this is not allowed in json
- $message = str_replace("\n","",$message);
- $return = '{"result":"error", "message":"'.$message.'"}';
- break;
- case 'php':
- $return = array('result' => 'error', 'message' => $message);
- if($this->caseRendererPHPSerialize())
- {
- $return = serialize($return);
- }
- break;
- case 'html':
- $return = nl2br($message);
- break;
- default:
- $return = 'Error: '.$message;
- break;
+ throw $e;
}
- return $return;
+
+ try
+ {
+ $renderer = Piwik_DataTable_Renderer::factory($format);
+
+ } catch (Exception $e) {
+
+ return "Error: " . $e->getMessage();
+ }
+
+ $renderer->setException($e);
+
+ if($format == 'php')
+ {
+ $renderer->setSerialize($this->caseRendererPHPSerialize());
+ }
+
+ return $renderer->renderException();
}
/**
@@ -202,6 +191,10 @@ class Piwik_API_ResponseBuilder
{
$renderer->setTableId($this->request['method']);
}
+ else if($format == 'csv')
+ {
+ $renderer->setConvertToUnicode( Piwik_Common::getRequestVar('convertToUnicode', true, 'int') );
+ }
return $renderer->render();
}
@@ -226,7 +219,7 @@ class Piwik_API_ResponseBuilder
"</result>";
break;
case 'json':
- @header( "Content-type: application/json" );
+ @header( "Content-Type: application/json" );
$return = '{"result":"success", "message":"'.$message.'"}';
break;
case 'php':
@@ -238,7 +231,7 @@ class Piwik_API_ResponseBuilder
break;
case 'csv':
- header("Content-type: application/vnd.ms-excel");
+ header("Content-Type: application/vnd.ms-excel");
header("Content-Disposition: attachment; filename=piwik-report-export.csv");
$return = "message\n".$message;
break;
@@ -296,5 +289,5 @@ class Piwik_API_ResponseBuilder
$dataTable->addRowsFromSimpleArray($array);
return $this->getRenderedDataTable($dataTable);
}
- }
+ }
}
diff --git a/core/Access.php b/core/Access.php
index 2485a7658b..4d08347b44 100644
--- a/core/Access.php
+++ b/core/Access.php
@@ -146,10 +146,7 @@ class Piwik_Access
// we join with site in case there are rows in access for an idsite that doesn't exist anymore
// (backward compatibility ; before we deleted the site without deleting rows in _access table)
- $accessRaw = Piwik_FetchAll("SELECT access, t2.idsite
- FROM ".Piwik::prefixTable('access'). " as t1
- JOIN ".Piwik::prefixTable('site')." as t2 USING (idsite) ".
- " WHERE login = ?", $this->login);
+ $accessRaw = Piwik_FetchAll(self::getSqlAccessSite("access, t2.idsite"), $this->login);
foreach($accessRaw as $access)
{
$this->idsitesByAccess[$access['access']][] = $access['idsite'];
@@ -158,6 +155,20 @@ class Piwik_Access
}
/**
+ * Returns the SQL query joining sites and access table for a given login
+ *
+ * @param $select eg. "MIN(ts_created)"
+ * @return string SQL query
+ */
+ static public function getSqlAccessSite($select)
+ {
+ return "SELECT ". $select ."
+ FROM ".Piwik_Common::prefixTable('access'). " as t1
+ JOIN ".Piwik_Common::prefixTable('site')." as t2 USING (idsite) ".
+ " WHERE login = ?";
+ }
+
+ /**
* Reload super user access
*
* @return bool
@@ -165,7 +176,7 @@ class Piwik_Access
protected function reloadAccessSuperUser()
{
$this->isSuperUser = true;
- $this->idsitesByAccess['superuser'] = Piwik_SitesManager_API::getAllSitesId();
+ $this->idsitesByAccess['superuser'] = Piwik_SitesManager_API::getInstance()->getAllSitesId();
return true;
}
@@ -173,9 +184,17 @@ class Piwik_Access
* We bypass the normal auth method and give the current user Super User rights.
* This should be very carefully used.
*/
- public function setSuperUser()
+ public function setSuperUser($bool = true)
{
- $this->reloadAccessSuperUser();
+ if($bool)
+ {
+ $this->reloadAccessSuperUser();
+ }
+ else
+ {
+ $this->isSuperUser = false;
+ $this->idsitesByAccess['superuser'] = array();
+ }
}
/**
@@ -223,8 +242,7 @@ class Piwik_Access
$this->idsitesByAccess['superuser'])
);
}
-
-
+
/**
* Returns an array of ID sites for which the user has an ADMIN access.
*
@@ -261,7 +279,7 @@ class Piwik_Access
{
if($this->isSuperUser === false)
{
- throw new Piwik_Access_NoAccessException("You can't access this resource as it requires a 'superuser' access.");
+ throw new Piwik_Access_NoAccessException(Piwik_TranslateException('General_ExceptionPrivilege', array("'superuser'")));
}
}
@@ -272,10 +290,14 @@ class Piwik_Access
*/
public function checkUserHasSomeAdminAccess()
{
+ if($this->isSuperUser())
+ {
+ return;
+ }
$idSitesAccessible = $this->getSitesIdWithAdminAccess();
if(count($idSitesAccessible) == 0)
{
- throw new Piwik_Access_NoAccessException("You can't access this resource as it requires an 'admin' access for at least one website.");
+ throw new Piwik_Access_NoAccessException(Piwik_TranslateException('General_ExceptionPrivilegeAtLeastOneWebsite', array('admin')));
}
}
@@ -289,7 +311,7 @@ class Piwik_Access
$idSitesAccessible = $this->getSitesIdWithAtLeastViewAccess();
if(count($idSitesAccessible) == 0)
{
- throw new Piwik_Access_NoAccessException("You can't access this resource as it requires a 'view' access for at least one website.");
+ throw new Piwik_Access_NoAccessException(Piwik_TranslateException('General_ExceptionPrivilegeAtLeastOneWebsite', array('view')));
}
}
@@ -315,7 +337,7 @@ class Piwik_Access
{
if(!in_array($idsite, $idSitesAccessible))
{
- throw new Piwik_Access_NoAccessException("You can't access this resource as it requires an 'admin' access for the website id = $idsite.");
+ throw new Piwik_Access_NoAccessException(Piwik_TranslateException('General_ExceptionPrivilegeAccessWebsite', array("'admin'", $idsite)));
}
}
}
@@ -344,7 +366,7 @@ class Piwik_Access
{
if(!in_array($idsite, $idSitesAccessible))
{
- throw new Piwik_Access_NoAccessException("You can't access this resource as it requires a 'view' access for the website id = $idsite.");
+ throw new Piwik_Access_NoAccessException(Piwik_TranslateException('General_ExceptionPrivilegeAccessWebsite', array("'view'", $idsite)));
}
}
}
diff --git a/core/Archive.php b/core/Archive.php
index bcc86237a3..17900f51a5 100644
--- a/core/Archive.php
+++ b/core/Archive.php
@@ -120,7 +120,7 @@ abstract class Piwik_Archive
{
if($idSite === 'all')
{
- $sites = Piwik_SitesManager_API::getSitesIdWithAtLeastViewAccess();
+ $sites = Piwik_SitesManager_API::getInstance()->getSitesIdWithAtLeastViewAccess();
}
else
{
diff --git a/core/Archive/Array/IndexedByDate.php b/core/Archive/Array/IndexedByDate.php
index 53a0369153..8629ef9672 100644
--- a/core/Archive/Array/IndexedByDate.php
+++ b/core/Archive/Array/IndexedByDate.php
@@ -25,7 +25,7 @@ class Piwik_Archive_Array_IndexedByDate extends Piwik_Archive_Array
*/
function __construct(Piwik_Site $oSite, $strPeriod, $strDate)
{
- $rangePeriod = new Piwik_Period_Range($strPeriod, $strDate);
+ $rangePeriod = new Piwik_Period_Range($strPeriod, $strDate, $oSite->getTimezone());
foreach($rangePeriod->getSubperiods() as $subPeriod)
{
$startDate = $subPeriod->getDateStart();
@@ -42,6 +42,13 @@ class Piwik_Archive_Array_IndexedByDate extends Piwik_Archive_Array
return 'date';
}
+ /**
+ * Adds metadata information to the Piwik_DataTable_Array
+ * using the information given by the Archive
+ *
+ * @param Piwik_DataTable_Array $table
+ * @param Piwik_Archive $archive
+ */
protected function loadMetadata(Piwik_DataTable_Array $table, $archive)
{
$table->metadata[$archive->getPrettyDate()] = array(
@@ -91,21 +98,22 @@ class Piwik_Archive_Array_IndexedByDate extends Piwik_Archive_Array
$arrayValues = array();
foreach($queries as $table => $aIds)
{
- $inIds = implode(', ', $aIds);
+ $inIds = implode(', ', array_filter($aIds));
if(empty($inIds))
{
// Probable timezone configuration error, i.e., mismatch between PHP and MySQL server.
continue;
}
- $sql = "SELECT value, name, UNIX_TIMESTAMP(date1) as timestamp
+ $sql = "SELECT value, name, date1 as startDate
FROM $table
WHERE idarchive IN ( $inIds )
AND name IN ( $inNames )";
$values = $db->fetchAll($sql);
foreach($values as $value)
{
- $arrayValues[$value['timestamp']][$value['name']] = (float)$value['value'];
+ $timestamp = Piwik_Date::factory($value['startDate'])->getTimestamp();
+ $arrayValues[$timestamp][$value['name']] = (float)$value['value'];
}
}
diff --git a/core/Archive/Array/IndexedBySite.php b/core/Archive/Array/IndexedBySite.php
index 22cbd88dbd..a5d4cf6163 100644
--- a/core/Archive/Array/IndexedBySite.php
+++ b/core/Archive/Array/IndexedBySite.php
@@ -112,7 +112,7 @@ class Piwik_Archive_Array_IndexedBySite extends Piwik_Archive_Array
}
$archiveIds[] = $archive->getIdArchive();
}
- return implode(', ', $archiveIds);
+ return implode(', ', array_filter($archiveIds));
}
private function getNumericTableName()
diff --git a/core/Archive/Single.php b/core/Archive/Single.php
index 464ecf7f31..991ecd7a67 100644
--- a/core/Archive/Single.php
+++ b/core/Archive/Single.php
@@ -134,9 +134,12 @@ class Piwik_Archive_Single extends Piwik_Archive
{
if(!is_null($this->archiveProcessing))
{
- return $this->archiveProcessing->getTimestampStartDate();
+ $timestamp = $this->archiveProcessing->getTimestampStartDate();
+ if(!empty($timestamp))
+ {
+ return $timestamp;
+ }
}
-
return $this->period->getDateStart()->getTimestamp();
}
@@ -152,18 +155,20 @@ class Piwik_Archive_Single extends Piwik_Archive
{
$this->isThereSomeVisits = false;
$this->alreadyChecked = true;
-
+ $logMessage = "Preparing archive: ";
// if the END of the period is BEFORE the website creation date
// we already know there are no stats for this period
// we add one day to make sure we don't miss the day of the website creation
if( $this->period->getDateEnd()->addDay(2)->isEarlier( $this->site->getCreationDate() ) )
{
- return;
+ Piwik::log("$logMessage skipped, archive is before the website was created.");
+ return;
}
// if the starting date is in the future we know there is no visit
- if( $this->period->getDateStart()->subDay(1)->isLater( Piwik_Date::today() ) )
+ if( $this->period->getDateStart()->subDay(2)->isLater( Piwik_Date::today() ) )
{
+ Piwik::log("$logMessage skipped, archive is after today.");
return;
}
@@ -173,12 +178,17 @@ class Piwik_Archive_Single extends Piwik_Archive
$archiveProcessing->setSite($this->site);
$archiveProcessing->setPeriod($this->period);
$idArchive = $archiveProcessing->loadArchive();
- if($idArchive === null)
+ if(empty($idArchive))
{
+ Piwik::log("$logMessage not archived yet, starting processing...");
$archiveJustProcessed = true;
$archiveProcessing->launchArchiving();
$idArchive = $archiveProcessing->getIdArchive();
}
+ else
+ {
+ Piwik::log("$logMessage archive already processed [id = $idArchive]...");
+ }
$this->isThereSomeVisits = $archiveProcessing->isThereSomeVisits;
$this->idArchive = $idArchive;
$this->archiveProcessing = $archiveProcessing;
@@ -442,7 +452,7 @@ class Piwik_Archive_Single extends Piwik_Archive
if($data === false
&& $idSubTable !== null)
{
- throw new Exception("You are requesting a precise subTable but there is not such data in the Archive.");
+ throw new Exception(Piwik_TranslateException('General_ExceptionSubtableNotFoundInArchive'));
}
return $table;
diff --git a/core/ArchiveProcessing.php b/core/ArchiveProcessing.php
index 91eed568a4..23dca365cf 100644
--- a/core/ArchiveProcessing.php
+++ b/core/ArchiveProcessing.php
@@ -45,6 +45,14 @@ abstract class Piwik_ArchiveProcessing
* @var int
*/
const DONE_ERROR = 2;
+
+ /**
+ * Flag indicates the archive is over a period that is not finished, eg. the current day, current week, etc.
+ * Archives flagged will be regularly purged from the DB.
+ *
+ * @var int
+ */
+ const DONE_OK_TEMPORARY = 3;
/**
* Idarchive in the DB for the requested archive
@@ -96,11 +104,11 @@ abstract class Piwik_ArchiveProcessing
protected $tableArchiveBlob;
/**
- * Maximum timestamp above which a given archive is considered out of date
+ * Minimum timestamp looked at for processed archives
*
* @var int
*/
- protected $maxTimestampArchive;
+ protected $minDatetimeArchiveProcessedUTC = false;
/**
* Compress blobs
@@ -110,6 +118,13 @@ abstract class Piwik_ArchiveProcessing
protected $compressBlob;
/**
+ * Is the current archive temporary. ie.
+ * - today
+ * - current week / month / year
+ */
+ protected $temporaryArchive;
+
+ /**
* Id of the current site
* Can be accessed by plugins (that is why it's public)
*
@@ -121,7 +136,7 @@ abstract class Piwik_ArchiveProcessing
* Period of the current archive
* Can be accessed by plugins (that is why it's public)
*
- * @var Piwik_Period
+ * @var $period Piwik_Period
*/
public $period = null;
@@ -134,14 +149,14 @@ abstract class Piwik_ArchiveProcessing
public $site = null;
/**
- * Starting date @see Piwik_Date::toString()
+ * Starting datetime in UTC
*
* @var string
*/
- public $strDateStart;
+ public $startDatetimeUTC;
/**
- * Ending date @see Piwik_Date::toString()
+ * Ending date in UTC
*
* @var string
*/
@@ -183,6 +198,9 @@ abstract class Piwik_ArchiveProcessing
*/
public $isThereSomeVisits = false;
+ protected $startTimestampUTC;
+ protected $endTimestampUTC;
+
/**
* Constructor
*/
@@ -218,61 +236,142 @@ abstract class Piwik_ArchiveProcessing
return $process;
}
+ const OPTION_TODAY_ARCHIVE_TTL = 'todayArchiveTimeToLive';
+ const OPTION_BROWSER_TRIGGER_ARCHIVING = 'enableBrowserTriggerArchiving';
+
+ static public function setTodayArchiveTimeToLive($timeToLiveSeconds)
+ {
+ $timeToLiveSeconds = (int)$timeToLiveSeconds;
+ if($timeToLiveSeconds <= 0)
+ {
+ throw new Exception(Piwik_TranslateException('General_ExceptionInvalidArchiveTimeToLive'));
+ }
+ Piwik_SetOption(self::OPTION_TODAY_ARCHIVE_TTL, $timeToLiveSeconds, $autoload = true);
+ }
+
+ static public function getTodayArchiveTimeToLive()
+ {
+ $timeToLive = Piwik_GetOption(self::OPTION_TODAY_ARCHIVE_TTL);
+ if($timeToLive !== false)
+ {
+ return $timeToLive;
+ }
+ return Zend_Registry::get('config')->General->time_before_today_archive_considered_outdated;
+ }
+
+ static public function setBrowserTriggerArchiving($enabled)
+ {
+ if(!is_bool($enabled))
+ {
+ throw new Exception('Browser trigger archiving must be set to true or false.');
+ }
+ Piwik_SetOption(self::OPTION_BROWSER_TRIGGER_ARCHIVING, (int)$enabled, $autoload = true);
+
+ }
+ static public function isBrowserTriggerArchivingEnabled()
+ {
+ $browserArchivingEnabled = Piwik_GetOption(self::OPTION_BROWSER_TRIGGER_ARCHIVING);
+ if($browserArchivingEnabled !== false)
+ {
+ return (bool)$browserArchivingEnabled;
+ }
+ return (bool)Zend_Registry::get('config')->General->enable_browser_archiving_triggering;
+ }
+
public function getIdArchive()
{
return $this->idArchive;
}
/**
- * Inits the object
+ * Sets object attributes that will be used throughout the process
*/
- protected function loadArchiveProperties()
- {
+ public function init()
+ {
$this->idsite = $this->site->getId();
-
$this->periodId = $this->period->getId();
-
- $this->dateStart = $this->period->getDateStart();
- $this->dateEnd = $this->period->getDateEnd();
+
+ $dateStartLocalTimezone = $this->period->getDateStart();
+ $dateEndLocalTimezone = $this->period->getDateEnd();
$this->tableArchiveNumeric = new Piwik_TablePartitioning_Monthly('archive_numeric');
$this->tableArchiveNumeric->setIdSite($this->idsite);
- $this->tableArchiveNumeric->setTimestamp($this->dateStart->get());
+ $this->tableArchiveNumeric->setTimestamp($dateStartLocalTimezone->getTimestamp());
$this->tableArchiveBlob = new Piwik_TablePartitioning_Monthly('archive_blob');
$this->tableArchiveBlob->setIdSite($this->idsite);
- $this->tableArchiveBlob->setTimestamp($this->dateStart->get());
+ $this->tableArchiveBlob->setTimestamp($dateStartLocalTimezone->getTimestamp());
+
+ $dateStartUTC = $dateStartLocalTimezone->setTimezone($this->site->getTimezone());
+ $dateEndUTC = $dateEndLocalTimezone->setTimezone($this->site->getTimezone());
+ $this->startDatetimeUTC = $dateStartUTC->getDateStartUTC();
+ $this->endDatetimeUTC = $dateEndUTC->getDateEndUTC();
- $this->strDateStart = $this->dateStart->toString();
- $this->strDateEnd = $this->dateEnd->toString();
+ $this->startTimestampUTC = $dateStartUTC->getTimestamp();
+ $this->endTimestampUTC = strtotime($this->endDatetimeUTC);
+ $this->minDatetimeArchiveProcessedUTC = $this->getMinTimeArchivedProcessed();
+ $db = Zend_Registry::get('db');
+ $this->compressBlob = $db->hasBlobDataType();
+ }
+
+ public function getStartDatetimeUTC()
+ {
+ return $this->startDatetimeUTC;
+ }
+
+ public function getEndDatetimeUTC()
+ {
+ return $this->endDatetimeUTC;
+ }
+
+ public function isArchiveTemporary()
+ {
+ return $this->temporaryArchive;
+ }
+
+ /**
+ * Returns the minimum archive processed datetime to look at
+ *
+ * @return string Datetime string, or false if must look at any archive available
+ */
+ public function getMinTimeArchivedProcessed()
+ {
+ $this->temporaryArchive = false;
// if the current archive is a DAY and if it's today,
- // we set this maxTimestampArchive that defines the lifetime value of today's archive
- $this->maxTimestampArchive = 0;
+ // we set this minDatetimeArchiveProcessedUTC that defines the lifetime value of today's archive
if( $this->period->getNumberOfSubperiods() == 0
- && $this->period->toString() == date("Y-m-d")
+ && $this->startTimestampUTC <= time() && $this->endTimestampUTC > time()
)
{
- $this->maxTimestampArchive = time() - Zend_Registry::get('config')->General->time_before_today_archive_considered_outdated;
+ $this->temporaryArchive = true;
+ $minDatetimeArchiveProcessedUTC = time() - self::getTodayArchiveTimeToLive();
+ // see #1150; if new archives are not triggered from the browser,
+ // we still want to try and return the latest archive available for today (rather than return nothing)
+ if($this->isArchivingDisabled())
+ {
+ return false;
+ }
}
// either
// - if the period we're looking for is finished, we look for a ts_archived that
// is greater than the last day of the archive
// - if the period we're looking for is not finished, we look for a recent enough archive
- // recent enough means maxTimestampArchive = 00:00:01 this morning
+ // recent enough means minDatetimeArchiveProcessedUTC = 00:00:01 this morning
else
{
- if($this->period->isFinished())
+ if($this->endTimestampUTC <= time())
{
- $this->maxTimestampArchive = $this->period->getDateEnd()->setTime('00:00:00')->addDay(1)->getTimestamp();
+ $minDatetimeArchiveProcessedUTC = $this->endTimestampUTC+1;
}
else
{
- $this->maxTimestampArchive = Piwik_Date::today()->getTimestamp();
+ $this->temporaryArchive = true;
+ $minDatetimeArchiveProcessedUTC = Piwik_Date::today()
+ ->setTimezone($this->site->getTimezone())
+ ->getTimestamp();
}
}
-
- $db = Zend_Registry::get('db');
- $this->compressBlob = $db->hasBlobDataType();
+ return $minDatetimeArchiveProcessedUTC;
}
/**
@@ -286,7 +385,7 @@ abstract class Piwik_ArchiveProcessing
*/
public function loadArchive()
{
- $this->loadArchiveProperties();
+ $this->init();
$this->idArchive = $this->isArchived();
if($this->idArchive === false
@@ -327,10 +426,19 @@ abstract class Piwik_ArchiveProcessing
{
$this->loadNextIdarchive();
$this->insertNumericRecord('done', Piwik_ArchiveProcessing::DONE_ERROR);
- $this->logTable = Piwik::prefixTable('log_visit');
- $this->logVisitActionTable = Piwik::prefixTable('log_link_visit_action');
- $this->logActionTable = Piwik::prefixTable('log_action');
- $this->logConversionTable = Piwik::prefixTable('log_conversion');
+ $this->logTable = Piwik_Common::prefixTable('log_visit');
+ $this->logVisitActionTable = Piwik_Common::prefixTable('log_link_visit_action');
+ $this->logActionTable = Piwik_Common::prefixTable('log_action');
+ $this->logConversionTable = Piwik_Common::prefixTable('log_conversion');
+
+ $temporary = 'definitive archive';
+ if($this->isArchiveTemporary())
+ {
+ $temporary = 'temporary archive';
+ }
+ Piwik::log("Processing archive '" . $this->period->getLabel() . "',
+ idsite = ". $this->idsite." ($temporary) -
+ UTC datetime [".$this->startDatetimeUTC." -> ".$this->endDatetimeUTC." ]...");
}
/**
@@ -343,12 +451,17 @@ abstract class Piwik_ArchiveProcessing
{
// delete the first done = ERROR
Piwik_Query("/* SHARDING_ID_SITE = ".$this->idsite." */
- DELETE FROM ".$this->tableArchiveNumeric->getTableName()."
- WHERE idarchive = ? AND name = 'done'",
+ DELETE FROM ".$this->tableArchiveNumeric->getTableName()."
+ WHERE idarchive = ? AND name = 'done'",
array($this->idArchive)
- );
+ );
- $this->insertNumericRecord('done', Piwik_ArchiveProcessing::DONE_OK);
+ $flag = Piwik_ArchiveProcessing::DONE_OK;
+ if($this->isArchiveTemporary())
+ {
+ $flag = Piwik_ArchiveProcessing::DONE_OK_TEMPORARY;
+ }
+ $this->insertNumericRecord('done', $flag);
Piwik_DataTable_Manager::getInstance()->deleteAll();
}
@@ -400,14 +513,8 @@ abstract class Piwik_ArchiveProcessing
*/
public function getTimestampStartDate()
{
- // case when archive processing is in the past or the future, the starting date has not been set or processed yet
- if(is_null($this->timestampDateStart))
- {
- return Piwik_Date::factory($this->strDateStart)->getTimestamp();
- }
return $this->timestampDateStart;
}
-
// exposing the number of visits publicly (number used to compute conversions rates)
protected $nb_visits = null;
@@ -438,7 +545,9 @@ abstract class Piwik_ArchiveProcessing
protected function loadNextIdarchive()
{
$db = Zend_Registry::get('db');
- $id = $db->fetchOne("/* SHARDING_ID_SITE = ".$this->idsite." */ SELECT max(idarchive) FROM ".$this->tableArchiveNumeric->getTableName());
+ $id = $db->fetchOne("/* SHARDING_ID_SITE = ".$this->idsite." */
+ SELECT max(idarchive)
+ FROM ".$this->tableArchiveNumeric->getTableName());
if(empty($id))
{
$id = 0;
@@ -498,23 +607,31 @@ abstract class Piwik_ArchiveProcessing
*/
protected function insertRecord($record)
{
+
// table to use to save the data
if(is_numeric($record->value))
{
+ // We choose not to record records with a value of 0
+ if($record->value == 0)
+ {
+ return;
+ }
$table = $this->tableArchiveNumeric;
}
else
{
$table = $this->tableArchiveBlob;
}
-
- $query = "INSERT INTO ".$table->getTableName()." (idarchive, idsite, date1, date2, period, ts_archived, name, value)
+
+ // ignore duplicate idarchive
+ // @see http://dev.piwik.org/trac/ticket/987
+ $query = "INSERT IGNORE INTO ".$table->getTableName()." (idarchive, idsite, date1, date2, period, ts_archived, name, value)
VALUES (?,?,?,?,?,?,?,?)";
Piwik_Query($query,
array( $this->idArchive,
$this->idsite,
- $this->strDateStart,
- $this->strDateEnd,
+ $this->period->getDateStart()->toString('Y-m-d'),
+ $this->period->getDateEnd()->toString('Y-m-d'),
$this->periodId,
date("Y-m-d H:i:s"),
$record->name,
@@ -528,7 +645,7 @@ abstract class Piwik_ArchiveProcessing
* Returns false if the archive needs to be computed.
*
* An archive is available if
- * - for today, the archive was computed less than maxTimestampArchive seconds ago
+ * - for today, the archive was computed less than minDatetimeArchiveProcessedUTC seconds ago
* - for any other day, if the archive was computed once this day was finished
* - for other periods, if the archive was computed once the period was finished
*
@@ -537,20 +654,27 @@ abstract class Piwik_ArchiveProcessing
protected function isArchived()
{
$bindSQL = array( $this->idsite,
- $this->strDateStart,
- $this->strDateEnd,
- $this->periodId,
- );
- $timeStampWhere = " AND UNIX_TIMESTAMP(ts_archived) >= ? ";
- $bindSQL[] = $this->maxTimestampArchive;
+ $this->period->getDateStart()->toString('Y-m-d'),
+ $this->period->getDateEnd()->toString('Y-m-d'),
+ $this->periodId,
+ );
+
+ $timeStampWhere = '';
- $sqlQuery = " SELECT idarchive, value, name, UNIX_TIMESTAMP(date1) as timestamp
+ if($this->minDatetimeArchiveProcessedUTC)
+ {
+ $timeStampWhere = " AND ts_archived >= ? ";
+ $bindSQL[] = Piwik_Date::factory($this->minDatetimeArchiveProcessedUTC)->getDatetime();
+ }
+
+ $sqlQuery = " SELECT idarchive, value, name, date1 as startDate
FROM ".$this->tableArchiveNumeric->getTableName()."
WHERE idsite = ?
AND date1 = ?
AND date2 = ?
AND period = ?
AND ( (name = 'done' AND value = ".Piwik_ArchiveProcessing::DONE_OK.")
+ OR (name = 'done' AND value = ".Piwik_ArchiveProcessing::DONE_OK_TEMPORARY.")
OR name = 'nb_visits')
$timeStampWhere
ORDER BY ts_archived DESC";
@@ -567,7 +691,7 @@ abstract class Piwik_ArchiveProcessing
if($result['name'] == 'done')
{
$idarchive = $result['idarchive'];
- $this->timestampDateStart = $result['timestamp'];
+ $this->timestampDateStart = Piwik_Date::factory($result['startDate'])->getTimestamp();
break;
}
}
@@ -579,7 +703,7 @@ abstract class Piwik_ArchiveProcessing
return false;
}
- // we look for the nb_visits result for this more recent archive
+ // we look for the nb_visits result for this most recent archive
foreach($results as $result)
{
if($result['name'] == 'nb_visits'
@@ -599,19 +723,11 @@ abstract class Piwik_ArchiveProcessing
*/
protected function isArchivingDisabled()
{
- static $archivingIsDisabled = null;
- if(is_null($archivingIsDisabled))
+ if(!self::isBrowserTriggerArchivingEnabled()
+ && !Piwik_Common::isPhpCliMode())
{
- $archivingIsDisabled = false;
- $enableBrowserArchivingTriggering = (bool)Zend_Registry::get('config')->General->enable_browser_archiving_triggering;
- if($enableBrowserArchivingTriggering == false)
- {
- if( !Piwik_Common::isPhpCliMode())
- {
- $archivingIsDisabled = true;
- }
- }
+ return true;
}
- return $archivingIsDisabled;
+ return false;
}
}
diff --git a/core/ArchiveProcessing/Day.php b/core/ArchiveProcessing/Day.php
index df823b978b..5193a39562 100644
--- a/core/ArchiveProcessing/Day.php
+++ b/core/ArchiveProcessing/Day.php
@@ -44,12 +44,12 @@ class Piwik_ArchiveProcessing_Day extends Piwik_ArchiveProcessing
sum(case visit_total_actions when 1 then 1 else 0 end) as bounce_count,
sum(case visit_goal_converted when 1 then 1 else 0 end) as nb_visits_converted
FROM ".$this->logTable."
- WHERE visit_server_date = ?
+ WHERE visit_last_action_time >= ?
+ AND visit_last_action_time <= ?
AND idsite = ?
- GROUP BY visit_server_date
ORDER BY NULL";
- $row = $this->db->fetchRow($query, array($this->strDateStart,$this->idsite ) );
- if($row === false || $row === null)
+ $row = $this->db->fetchRow($query, array($this->getStartDatetimeUTC(), $this->getEndDatetimeUTC(), $this->idsite ) );
+ if($row === false || $row === null || $row['nb_visits'] == 0)
{
return;
}
@@ -87,9 +87,10 @@ class Piwik_ArchiveProcessing_Day extends Piwik_ArchiveProcessing
{
$query = "SELECT $select
FROM ".$this->logTable."
- WHERE visit_server_date = ?
- AND idsite = ?";
- $data = $this->db->fetchRow($query, array( $this->strDateStart, $this->idsite ));
+ WHERE visit_last_action_time >= ?
+ AND visit_last_action_time <= ?
+ AND idsite = ?";
+ $data = $this->db->fetchRow($query, array( $this->getStartDatetimeUTC(), $this->getEndDatetimeUTC(), $this->idsite ));
foreach($data as $label => &$count)
{
@@ -152,11 +153,12 @@ class Piwik_ArchiveProcessing_Day extends Piwik_ArchiveProcessing
sum(case visit_total_actions when 1 then 1 else 0 end) as bounce_count,
sum(case visit_goal_converted when 1 then 1 else 0 end) as nb_visits_converted
FROM ".$this->logTable."
- WHERE visit_server_date = ?
- AND idsite = ?
+ WHERE visit_last_action_time >= ?
+ AND visit_last_action_time <= ?
+ AND idsite = ?
GROUP BY label
ORDER BY NULL";
- $query = $this->db->query($query, array( $this->strDateStart, $this->idsite ) );
+ $query = $this->db->query($query, array( $this->getStartDatetimeUTC(), $this->getEndDatetimeUTC(), $this->idsite ) );
$interest = array();
while($row = $query->fetch())
@@ -327,11 +329,12 @@ class Piwik_ArchiveProcessing_Day extends Piwik_ArchiveProcessing
sum(revenue) as revenue
$segments
FROM ".$this->logConversionTable."
- WHERE visit_server_date = ?
- AND idsite = ?
+ WHERE server_time >= ?
+ AND server_time <= ?
+ AND idsite = ?
GROUP BY idgoal $segments
ORDER BY NULL";
- $query = $this->db->query($query, array( $this->strDateStart, $this->idsite ));
+ $query = $this->db->query($query, array( $this->getStartDatetimeUTC(), $this->getEndDatetimeUTC(), $this->idsite ));
return $query;
}
@@ -342,15 +345,20 @@ class Piwik_ArchiveProcessing_Day extends Piwik_ArchiveProcessing
sum(revenue) as revenue,
$segment as label
FROM ".$this->logConversionTable."
- WHERE visit_server_date = ?
- AND idsite = ?
+ WHERE server_time >= ?
+ AND server_time <= ?
+ AND idsite = ?
GROUP BY idgoal, label
ORDER BY NULL";
- $query = $this->db->query($query, array( $this->strDateStart, $this->idsite ));
+ $query = $this->db->query($query, array( $this->getStartDatetimeUTC(), $this->getEndDatetimeUTC(), $this->idsite ));
return $query;
}
/**
+ * Given an array of stats, it will process the sum of goal conversions
+ * and sum of revenue and add it in the stats array in two new fields.
+ *
+ * @param $interestByLabel Passed by reference, it will be modified as follows:
* Input:
* array(
* LABEL => array( Piwik_Archive::INDEX_NB_VISITS => X,
@@ -362,10 +370,12 @@ class Piwik_ArchiveProcessing_Day extends Piwik_ArchiveProcessing
* LABEL2 => array( Piwik_Archive::INDEX_NB_VISITS => Y, [...] )
* );
*
+ *
* Output:
* array(
* LABEL => array( Piwik_Archive::INDEX_NB_VISITS => X,
- *
+ * Piwik_Archive::INDEX_NB_CONVERSIONS => Y, // sum of all conversions
+ * Piwik_Archive::INDEX_REVENUE => Z, // sum of all revenue
* Piwik_Archive::INDEX_GOALS => array(
* idgoal1 => array( [...] ),
* idgoal2 => array( [...] ),
diff --git a/core/ArchiveProcessing/Period.php b/core/ArchiveProcessing/Period.php
index 7f40c744e7..37b65cba70 100644
--- a/core/ArchiveProcessing/Period.php
+++ b/core/ArchiveProcessing/Period.php
@@ -156,6 +156,11 @@ class Piwik_ArchiveProcessing_Period extends Piwik_ArchiveProcessing
* final DataTable (ie. the number of distinct LABEL over the period) (eg. the number of distinct keywords over the last month)
*
* @param string|array Field name(s) of DataTable to select so we can get the sum
+ * @param array (current_column_name => new_column_name) for columns that must change names when summed (eg. unique visitors go from nb_uniq_visitors to sum_daily_nb_uniq_visitors)
+ * @param int Max row count of parent datatable to archive
+ * @param int Max row count of children datatable(s) to archive
+ * @param string Column name to sort by, before truncating rows (ie. if there are more rows than the specified max row count)
+ *
* @return array array (
* nameTable1 => number of rows,
* nameTable2 => number of rows,
@@ -283,10 +288,14 @@ class Piwik_ArchiveProcessing_Period extends Piwik_ArchiveProcessing
protected function computeNbUniqVisitors()
{
- $query = "SELECT count(distinct visitor_idcookie) as nb_uniq_visitors FROM ".$this->logTable."
- WHERE visit_server_date >= ? AND visit_server_date <= ? AND idsite = ?";
+ $query = "
+ SELECT count(distinct visitor_idcookie) as nb_uniq_visitors
+ FROM ".$this->logTable."
+ WHERE visit_last_action_time >= ?
+ AND visit_last_action_time <= ?
+ AND idsite = ?";
- return Zend_Registry::get('db')->fetchOne($query, array( $this->strDateStart, $this->strDateEnd, $this->idsite ));
+ return Zend_Registry::get('db')->fetchOne($query, array( $this->getStartDatetimeUTC(), $this->getEndDatetimeUTC(), $this->idsite ));
}
/**
@@ -297,46 +306,53 @@ class Piwik_ArchiveProcessing_Period extends Piwik_ArchiveProcessing
{
parent::postCompute();
+ foreach($this->archives as $archive)
+ {
+ destroy($archive);
+ }
+ $this->archives = array();
+
$blobTable = $this->tableArchiveBlob->getTableName();
$numericTable = $this->tableArchiveNumeric->getTableName();
- // delete out of date records maximum once per day (DELETE request is costly)
$key = 'lastPurge_' . $blobTable;
$timestamp = Piwik_GetOption($key);
if(!$timestamp
- || $timestamp < time() - 86400 )
+ || $timestamp < time() - 86400)
{
- // we delete out of date daily archives from table, maximum once per day
- // those for day N that were processed on day N (means the archives are only partial as the day wasn't finished)
- $query = "/* SHARDING_ID_SITE = ".$this->idsite." */ DELETE
- FROM %s
- WHERE period = ?
- AND date1 = DATE(ts_archived)
- AND DATE(ts_archived) <> CURRENT_DATE()
- ";
- Piwik_Query(sprintf($query, $blobTable), Piwik::$idPeriods['day']);
- Piwik_Query(sprintf($query, $numericTable), Piwik::$idPeriods['day']);
-
- // we delete out of date Period records (week/month/etc)
- // we delete archives that were archived before the end of the period
- // and only if they are at least 1 day old (so we don't delete archives computed today that may be stil valid)
- $query = " DELETE
- FROM %s
- WHERE period > ?
- AND DATE(ts_archived) <= date2
- AND date(ts_archived) < date_sub(CURRENT_DATE(), INTERVAL 1 DAY)
- ";
+ Piwik_SetOption($key, time());
- Piwik_Query(sprintf($query, $blobTable), Piwik::$idPeriods['day']);
- Piwik_Query(sprintf($query, $numericTable), Piwik::$idPeriods['day']);
+ // we delete out of date daily archives from table, maximum once per day
+ // we only delete archives processed that are older than 1 day, to not delete archives we just processed
+ $yesterday = Piwik_Date::factory('yesterday')->getDateTime();
+ $result = Piwik_FetchAll("
+ SELECT idarchive
+ FROM $numericTable
+ WHERE name='done'
+ AND value = ". Piwik_ArchiveProcessing::DONE_OK_TEMPORARY ."
+ AND ts_archived < ?", array($yesterday));
- Piwik_SetOption($key, time());
+ $idArchivesToDelete = array();
+ if(!empty($result))
+ {
+ foreach($result as $row) {
+ $idArchivesToDelete[] = $row['idarchive'];
+ }
+ $query = "/* SHARDING_ID_SITE = ".$this->idsite." */
+ DELETE
+ FROM %s
+ WHERE idarchive IN (".implode(',',$idArchivesToDelete).")
+ ";
+
+ Piwik_Query(sprintf($query, $blobTable));
+ Piwik_Query(sprintf($query, $numericTable));
+ }
+ Piwik::log("Purging temporary archives: done [ purged archives older than $yesterday from $blobTable and $numericTable ] [Deleted IDs: ". implode(',',$idArchivesToDelete)."]");
}
-
- foreach($this->archives as $archive)
+ else
{
- destroy($archive);
+ Piwik::log("Purging temporary archives: skipped.");
}
- $this->archives = array();
+
}
}
diff --git a/core/CacheFile.php b/core/CacheFile.php
index 8d877abddc..6a3f95cf9e 100644
--- a/core/CacheFile.php
+++ b/core/CacheFile.php
@@ -28,7 +28,6 @@ class Piwik_CacheFile
function __construct($directory)
{
$this->cachePath = PIWIK_USER_PATH . '/tmp/cache/' . $directory . '/';
-// echo $this->cachePath;exit;
}
/**
@@ -112,4 +111,12 @@ class Piwik_CacheFile
}
return false;
}
+
+ /**
+ * A function to delete all cache entries in the directory
+ */
+ function deleteAll()
+ {
+ Piwik::unlinkRecursive($this->cachePath, $deleteRootToo = false);
+ }
}
diff --git a/core/Common.php b/core/Common.php
index b1f152b95c..e972cc3a70 100644
--- a/core/Common.php
+++ b/core/Common.php
@@ -47,7 +47,7 @@ class Piwik_Common
static $prefixTable = null;
if(is_null($prefixTable))
{
- if(defined('PIWIK_TRACKER_MODE') && PIWIK_TRACKER_MODE)
+ if(!empty($GLOBALS['PIWIK_TRACKER_MODE']))
{
$prefixTable = Piwik_Tracker_Config::getInstance()->database['tables_prefix'];
}
@@ -84,23 +84,40 @@ class Piwik_Common
{
return $cacheContent;
}
- if(defined('PIWIK_TRACKER_MODE')
- && PIWIK_TRACKER_MODE)
+ if(!empty($GLOBALS['PIWIK_TRACKER_MODE']))
{
require_once PIWIK_INCLUDE_PATH . '/core/PluginsManager.php';
require_once PIWIK_INCLUDE_PATH . '/core/Translate.php';
require_once PIWIK_INCLUDE_PATH . '/core/Option.php';
- Zend_Registry::set('db', Piwik_Tracker::getDatabase());
- Piwik::createAccessObject();
- Piwik::createConfigObject();
- Piwik::setUserIsSuperUser();
+ try {
+ $access = Zend_Registry::get('access');
+ } catch (Exception $e) {
+ Piwik::createAccessObject();
+ }
+ try {
+ $config = Zend_Registry::get('config');
+ } catch (Exception $e) {
+ Piwik::createConfigObject();
+ }
+ try {
+ $db = Zend_Registry::get('db');
+ } catch (Exception $e) {
+ Piwik::createDatabaseObject();
+ }
+
$pluginsManager = Piwik_PluginsManager::getInstance();
- $pluginsManager->setPluginsToLoad( Zend_Registry::get('config')->Plugins->Plugins->toArray() );
+ $pluginsManager->loadPlugins( Zend_Registry::get('config')->Plugins->Plugins->toArray() );
}
+ $isSuperUser = Piwik::isUserIsSuperUser();
+ Piwik::setUserIsSuperUser();
$content = array();
Piwik_PostEvent('Common.fetchWebsiteAttributes', $content, $idSite);
+
+ // we remove the temporary Super user privilege
+ Piwik::setUserIsSuperUser($isSuperUser);
+
// if nothing is returned from the plugins, we don't save the content
// this is not expected: all websites are expected to have at least one URL
if(!empty($content))
@@ -140,6 +157,16 @@ class Piwik_Common
}
/**
+ * Deletes all Tracker cache files
+ */
+ static public function deleteAllCache()
+ {
+ $cache = new Piwik_CacheFile('tracker');
+ $cache->deleteAll();
+ }
+
+
+ /**
* Returns the path and query part from a URL.
* Eg. http://piwik.org/test/index.php?module=CoreHome will return /test/index.php?module=CoreHome
*
@@ -190,7 +217,6 @@ class Piwik_Common
/**
* Returns an URL query string in an array format
- * The input query string should be htmlspecialchar'ed
*
* @param string urlQuery
* @return array array( param1=> value1, param2=>value2)
@@ -243,6 +269,35 @@ class Piwik_Common
}
/**
+ * Builds a URL from the result of parse_url function
+ * Copied from the PHP comments at http://php.net/parse_url
+ * @param array
+ */
+ static public function getParseUrlReverse($parsed)
+ {
+ if (!is_array($parsed))
+ {
+ return false;
+ }
+
+ $uri = !empty($parsed['scheme']) ? $parsed['scheme'].':'.((strtolower($parsed['scheme']) == 'mailto') ? '' : '//') : '';
+ $uri .= !empty($parsed['user']) ? $parsed['user'].(!empty($parsed['pass']) ? ':'.$parsed['pass'] : '').'@' : '';
+ $uri .= !empty($parsed['host']) ? $parsed['host'] : '';
+ $uri .= !empty($parsed['port']) ? ':'.$parsed['port'] : '';
+
+ if (!empty($parsed['path']))
+ {
+ $uri .= (substr($parsed['path'], 0, 1) == '/')
+ ? $parsed['path']
+ : ((!empty($uri) ? '/' : '' ) . $parsed['path']);
+ }
+
+ $uri .= !empty($parsed['query']) ? '?'.$parsed['query'] : '';
+ $uri .= !empty($parsed['fragment']) ? '#'.$parsed['fragment'] : '';
+ return $uri;
+ }
+
+ /**
* Create directory if permitted
*
* @param string $path
@@ -272,10 +327,11 @@ class Piwik_Common
* Apache-specific; for IIS @see web.config
*
* @param string $path without trailing slash
+ * @param string $content
*/
- static public function createHtAccess( $path )
+ static public function createHtAccess( $path, $content = "<Files \"*\">\nDeny from all\n</Files>\n" )
{
- @file_put_contents($path . '/.htaccess', 'Deny from all');
+ @file_put_contents($path . '/.htaccess', $content);
}
/**
@@ -355,8 +411,8 @@ class Piwik_Common
{
$value = self::sanitizeInputValue($value);
- // Undo the damage caused by magic_quotes -- only before php 5.3 as it is now deprecated
- if ( version_compare(phpversion(), '5.3') === -1
+ // Undo the damage caused by magic_quotes; deprecated in php 5.3 but not removed until php 6
+ if ( version_compare(phpversion(), '6') === -1
&& get_magic_quotes_gpc())
{
$value = stripslashes($value);
@@ -508,6 +564,30 @@ class Piwik_Common
}
/**
+ * Unserialize (serialized) array
+ *
+ * @param string
+ * @return array or original string if not unserializable
+ */
+ public static function unserialize_array( $str )
+ {
+ // we set the unserialized version only for arrays as you can have set a serialized string on purpose
+ if (preg_match('/^a:[0-9]+:{/', $str)
+ && !preg_match('/(^|;|{|})O:[0-9]+:"/', $str)
+ && strpos($str, "\0") === false)
+ {
+ if( ($arrayValue = @unserialize($str)) !== false
+ && is_array($arrayValue) )
+ {
+ return $arrayValue;
+ }
+ }
+
+ // return original string
+ return $str;
+ }
+
+ /**
* Returns a 32 characters long uniq ID
*
* @return string 32 chars
@@ -518,13 +598,47 @@ class Piwik_Common
}
/**
+ * Get salt from [superuser] section
+ *
+ * @return string
+ */
+ static public function getSalt()
+ {
+ static $salt = null;
+ if(is_null($salt))
+ {
+ if(!empty($GLOBALS['PIWIK_TRACKER_MODE']))
+ {
+ $salt = Piwik_Tracker_Config::getInstance()->superuser['salt'];
+ }
+ else
+ {
+ $config = Zend_Registry::get('config');
+ if($config !== false)
+ {
+ $salt = $config->superuser->salt;
+ }
+ }
+ }
+ return $salt;
+ }
+
+ /**
* Convert dotted IP to a stringified integer representation
*
* @return string ip
*/
static public function getIp()
{
- return sprintf("%u", ip2long(self::getIpString()));
+ $ip = self::getIpString();
+
+ // accept ipv4-mapped addresses
+ if(strpos($ip, '::ffff:') === 0)
+ {
+ $ip = substr($ip, 7);
+ }
+
+ return sprintf("%u", ip2long($ip));
}
/**
@@ -534,38 +648,34 @@ class Piwik_Common
*/
static public function getIpString()
{
- if(isset($_SERVER['HTTP_CLIENT_IP'])
- && ($ip = self::getFirstIpFromList($_SERVER['HTTP_CLIENT_IP']))
- && strpos($ip, "unknown") === false)
- {
- return $ip;
- }
- elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR'])
- && $ip = self::getFirstIpFromList($_SERVER['HTTP_X_FORWARDED_FOR'])
- && isset($ip)
- && !empty($ip)
- && strpos($ip, "unknown")===false )
- {
- return $ip;
- }
- elseif( isset($_SERVER['HTTP_CLIENT_IP'])
- && strlen( self::getFirstIpFromList($_SERVER['HTTP_CLIENT_IP']) ) != 0 )
- {
- return self::getFirstIpFromList($_SERVER['HTTP_CLIENT_IP']);
- }
- else if( isset($_SERVER['HTTP_X_FORWARDED_FOR'])
- && strlen ($ip = self::getFirstIpFromList($_SERVER['HTTP_X_FORWARDED_FOR'])) != 0)
+ // note: these may be spoofed
+ static $clientHeaders = array(
+ // ISP proxy
+ 'HTTP_CLIENT_IP',
+
+ // de facto standard
+ 'HTTP_X_FORWARDED_FOR',
+ );
+
+ foreach($clientHeaders as $clientHeader)
{
- return $ip;
+ if(!empty($_SERVER[$clientHeader]))
+ {
+ $ip = self::getFirstIpFromList($_SERVER[$clientHeader]);
+ if(!empty($ip) && stripos($ip, 'unknown') === false)
+ {
+ return $ip;
+ }
+ }
}
- elseif(isset($_SERVER['REMOTE_ADDR']))
+
+ // default
+ if(isset($_SERVER['REMOTE_ADDR']))
{
return self::getFirstIpFromList($_SERVER['REMOTE_ADDR']);
}
- else
- {
- return '0.0.0.0';
- }
+
+ return '0.0.0.0';
}
/**
@@ -575,7 +685,7 @@ class Piwik_Common
*
* @return string first element before ','
*/
- static private function getFirstIpFromList($ip)
+ static public function getFirstIpFromList($ip)
{
$p = strpos($ip, ',');
if($p!==false)
@@ -657,14 +767,23 @@ class Piwik_Common
}
/**
- * Returns the visitor country based only on the Browser 'accepted language' information
+ * Returns the visitor country based on the Browser 'accepted language'
+ * information, but provides a hook for geolocation via IP address.
*
* @param string $lang browser lang
* @param bool If set to true, some assumption will be made and detection guessed more often, but accuracy could be affected
+ * @param string $ip
* @return string 2 letter ISO code
*/
- static public function getCountry( $lang, $enableLanguageToCountryGuess )
+ static public function getCountry( $lang, $enableLanguageToCountryGuess, $ip )
{
+ $country = null;
+ Piwik_PostEvent('Common.getCountry', $country, $ip);
+ if($country)
+ {
+ return $country;
+ }
+
if(empty($lang) || strlen($lang) < 2)
{
return 'xx';
@@ -797,13 +916,26 @@ class Piwik_Common
{
return false;
}
+ // some search engines (eg. Bing Images) use the same domain
+ // as an existing search engine (eg. Bing), we must also use the url path
+ $refererPath = '';
+ if(isset($refererParsed['path']))
+ {
+ $refererPath = $refererParsed['path'];
+ }
+ // no search query
if(!isset($refererParsed['query']))
{
return false;
}
require_once PIWIK_INCLUDE_PATH . '/core/DataFiles/SearchEngines.php';
- if(!array_key_exists($refererHost, $GLOBALS['Piwik_SearchEngines']))
+ $refererHostPath = $refererHost . $refererPath;
+ if(array_key_exists($refererHostPath, $GLOBALS['Piwik_SearchEngines']))
+ {
+ $refererHost = $refererHostPath;
+ }
+ elseif(!array_key_exists($refererHost, $GLOBALS['Piwik_SearchEngines']))
{
return false;
}
@@ -824,10 +956,12 @@ class Piwik_Common
}
$query = $refererParsed['query'];
- if($searchEngineName == 'Google Images')
+ if($searchEngineName == 'Google Images'
+ || ($searchEngineName == 'Google' && strpos($refererUrl, '/imgres') !== false) )
{
$query = urldecode(trim(strtolower(self::getParameterFromQueryString($query, 'prev'))));
$query = str_replace('&', '&amp;', strstr($query, '?'));
+ $searchEngineName = 'Google Images';
}
foreach($variableNames as $variableName)
@@ -892,7 +1026,8 @@ class Piwik_Common
*/
static public function isPhpCliMode()
{
+ $remoteAddr = @$_SERVER['REMOTE_ADDR'];
return PHP_SAPI == 'cli' ||
- (substr(PHP_SAPI, 0, 3) == 'cgi' && @$_SERVER['REMOTE_ADDR'] == '');
+ (substr(PHP_SAPI, 0, 3) == 'cgi' && empty($remoteAddr));
}
}
diff --git a/core/Config.php b/core/Config.php
index 84851053ea..4801875131 100644
--- a/core/Config.php
+++ b/core/Config.php
@@ -20,6 +20,7 @@
* will read the value minimumMemoryLimit under the [General] section of the config file
*
* @package Piwik
+ * @subpackage Piwik_Config
*/
class Piwik_Config
{
@@ -37,7 +38,8 @@ class Piwik_Config
protected $pathIniFileDefaultConfig = null;
protected $configFileUpdated = false;
protected $doWriteFileWhenUpdated = true;
- protected $cachedConfigArray = array();
+ protected $cachedConfigArray = array();
+ protected $isTestEnvironment = false;
/**
* Storing the correct cwd() because the value is not correct in the destructor
@@ -104,12 +106,25 @@ class Piwik_Config
public function init()
{
- $this->defaultConfig = new Zend_Config_Ini($this->pathIniFileDefaultConfig, null, true);
- if(!Zend_Loader::isReadable($this->pathIniFileUserConfig))
+ if(!is_readable($this->pathIniFileDefaultConfig))
{
- throw new Exception("The configuration file {$this->pathIniFileUserConfig} has not been found.");
+ Piwik_ExitWithMessage(Piwik_TranslateException('General_ExceptionConfigurationFileNotFound', array($this->pathIniFileDefaultConfig)));
+ }
+ $this->defaultConfig = new Piwik_Config_Ini($this->pathIniFileDefaultConfig, null, true);
+ if(is_null($this->defaultConfig) || count($this->defaultConfig->toArray()) == 0)
+ {
+ Piwik_ExitWithMessage(Piwik_TranslateException('General_ExceptionUnreadableFileDisabledMethod', array($this->pathIniFileDefaultConfig, "parse_ini_file()")));
+ }
+
+ if(!is_readable($this->pathIniFileUserConfig))
+ {
+ throw new Exception(Piwik_TranslateException('General_ExceptionConfigurationFileNotFound', array($this->pathIniFileUserConfig)));
+ }
+ $this->userConfig = new Piwik_Config_Ini($this->pathIniFileUserConfig, null, true);
+ if(is_null($this->userConfig) || count($this->userConfig->toArray()) == 0)
+ {
+ Piwik_ExitWithMessage(Piwik_TranslateException('General_ExceptionUnreadableFileDisabledMethod', array($this->pathIniFileUserConfig, "parse_ini_file()")));
}
- $this->userConfig = new Zend_Config_Ini($this->pathIniFileUserConfig, null, true);
}
/**
@@ -154,16 +169,35 @@ class Piwik_Config
$configFile .= "\n";
}
chdir($this->correctCwd);
- file_put_contents($this->pathIniFileUserConfig, $configFile );
+ @file_put_contents($this->pathIniFileUserConfig, $configFile );
}
}
+ public function isFileWritable()
+ {
+ return is_writable($this->pathIniFileUserConfig);
+ }
+
/**
* If called, we use the database_tests credentials
*/
public function setTestEnvironment()
{
+ $this->isTestEnvironment = true;
$this->database = $this->database_tests->toArray();
+ // for unit tests, we set that no plugin is installed. This will force
+ // the test initialization to create the plugins tables, execute ALTER queries, etc.
+ $this->PluginsInstalled = array();
+ $this->disableSavingConfigurationFileUpdates();
+ }
+
+ /**
+ * Is the config file set to use the test values?
+ * @return bool
+ */
+ public function isTestEnvironment()
+ {
+ return $this->isTestEnvironment;
}
/**
@@ -294,3 +328,47 @@ class Piwik_Config
return $this->cachedConfigArray[$name];
}
}
+
+/**
+ * Subclasses Zend_Config_Ini so we can use our own parse_ini_file() wrapper.
+ *
+ * @package Piwik
+ * @subpackage Piwik_Config
+ */
+class Piwik_Config_Ini extends Zend_Config_Ini
+{
+ /**
+ * Handle any errors from parse_ini_file
+ *
+ * @param integer $errno
+ * @param string $errstr
+ * @param string $errfile
+ * @param integer $errline
+ */
+ public function _parseFileErrorHandler($errno, $errstr, $errfile, $errline)
+ {
+ $this->_loadFileErrorHandler($errno, $errstr, $errfile, $errline);
+ }
+
+ /**
+ * Load ini file configuration
+ *
+ * Derived from Zend_Config_Ini->_loadIniFile() and Zend_Config_Ini->_parseIniFile()
+ * @license New BSD License
+ *
+ * @param string $filename
+ * @return array
+ */
+ protected function _loadIniFile($filename)
+ {
+ set_error_handler(array($this, '_parseFileErrorHandler'));
+ $iniArray = _parse_ini_file($filename, true);
+ restore_error_handler();
+ // Check if there was an error while loading the file
+ if ($this->_loadFileErrorStr !== null) {
+ throw new Zend_Config_Exception($this->_loadFileErrorStr);
+ }
+
+ return $iniArray;
+ }
+}
diff --git a/core/Controller.php b/core/Controller.php
index 04d950fa80..f3c9fce465 100644
--- a/core/Controller.php
+++ b/core/Controller.php
@@ -37,6 +37,8 @@ abstract class Piwik_Controller
* @var Piwik_Date|null
*/
protected $date;
+ protected $idSite;
+ protected $site = null;
/**
* Builds the controller object, reads the date from the request, extracts plugin name from
@@ -45,11 +47,12 @@ abstract class Piwik_Controller
{
$aPluginName = explode('_', get_class($this));
$this->pluginName = $aPluginName[1];
- $this->strDate = Piwik_Common::getRequestVar('date', 'yesterday', 'string');
- try{
- // the date looks like YYYY-MM-DD we can build it
- $this->date = Piwik_Date::factory($this->strDate);
- $this->strDate = $this->date->toString();
+ $date = Piwik_Common::getRequestVar('date', 'yesterday', 'string');
+ try {
+ $this->idSite = Piwik_Common::getRequestVar('idSite', false, 'int');
+ $this->site = new Piwik_Site($this->idSite);
+ $date = $this->getDateParameterInTimezone($date, $this->site->getTimezone());
+ $this->setDate($date);
} catch(Exception $e){
// the date looks like YYYY-MM-DD,YYYY-MM-DD or other format
$this->date = null;
@@ -57,6 +60,48 @@ abstract class Piwik_Controller
}
/**
+ * Helper method to convert "today" or "yesterday" to the default timezone specified.
+ * If the date is absolute, ie. YYYY-MM-DD, it will not be converted to the timezone
+ * @param $date today, yesterday, YYYY-MM-DD
+ * @param $defaultTimezone
+ * @return Piwik_Date
+ */
+ protected function getDateParameterInTimezone($date, $defaultTimezone )
+ {
+ $timezone = null;
+ // if the requested date is not YYYY-MM-DD, we need to ensure
+ // it is relative to the website's timezone
+ if(in_array($date, array('today', 'yesterday')))
+ {
+ // today is at midnight; we really want to get the time now, so that
+ // * if the website is UTC+12 and it is 5PM now in UTC, the calendar will allow to select the UTC "tomorrow"
+ // * if the website is UTC-12 and it is 5AM now in UTC, the calendar will allow to select the UTC "yesterday"
+ if($date == 'today')
+ {
+ $date = 'now';
+ }
+ elseif($date == 'yesterday')
+ {
+ $date = 'yesterdaySameTime';
+ }
+ $timezone = $defaultTimezone;
+ }
+ return Piwik_Date::factory($date, $timezone);
+ }
+
+ /**
+ * Sets the date to be used by all other methods in the controller.
+ * If the date has to be modified, it should be called just after the controller construct
+ * @param $date
+ * @return void
+ */
+ protected function setDate(Piwik_Date $date)
+ {
+ $this->date = $date;
+ $this->strDate = $this->date->toString();
+ }
+
+ /**
* Returns the name of the default method that will be called
* when visiting: index.php?module=PluginName without the action parameter
*
@@ -181,14 +226,13 @@ abstract class Piwik_Controller
{
$period = $paramsToSet['period'];
}
- $last30Relative = new Piwik_Period_Range($period, $range );
+ $last30Relative = new Piwik_Period_Range($period, $range, $this->site->getTimezone() );
$last30Relative->setDefaultEndDate(Piwik_Date::factory($endDate));
$paramDate = $last30Relative->getDateStart()->toString() . "," . $last30Relative->getDateEnd()->toString();
$params = array_merge($paramsToSet , array( 'date' => $paramDate ) );
-
return $params;
}
@@ -228,6 +272,37 @@ abstract class Piwik_Controller
return $url;
}
+ /**
+ * Sets the first date available in the calendar
+ * @param $minDate
+ * @param $view
+ * @return void
+ */
+ protected function setMinDateView(Piwik_Date $minDate, $view)
+ {
+ $view->minDateYear = $minDate->toString('Y');
+ $view->minDateMonth = $minDate->toString('m');
+ $view->minDateDay = $minDate->toString('d');
+ }
+
+ /**
+ * Sets "today" in the calendar. Today does not always mean "UTC" today, eg. for websites in UTC+12.
+ * @param $maxDate
+ * @param $view
+ * @return void
+ */
+ protected function setMaxDateView(Piwik_Date $maxDate, $view)
+ {
+ $view->maxDateYear = $maxDate->toString('Y');
+ $view->maxDateMonth = $maxDate->toString('m');
+ $view->maxDateDay = $maxDate->toString('d');
+ }
+
+ /**
+ * Sets general variables to the view that are used by various templates and Javascript
+ * @param $view
+ * @return void
+ */
protected function setGeneralVariablesView($view)
{
$view->date = $this->strDate;
@@ -236,29 +311,35 @@ abstract class Piwik_Controller
$this->setPeriodVariablesView($view);
$period = Piwik_Period::factory(Piwik_Common::getRequestVar('period'), Piwik_Date::factory($this->strDate));
$view->prettyDate = $period->getLocalizedLongString();
- $idSite = Piwik_Common::getRequestVar('idSite');
- $view->idSite = $idSite;
- $site = new Piwik_Site($idSite);
- $view->siteName = $site->getName();
- $view->siteMainUrl = $site->getMainUrl();
+ $view->idSite = $this->idSite;
+ if(is_null($this->site))
+ {
+ throw new Exception("invalid website");
+ }
+ $view->siteName = $this->site->getName();
+ $view->siteMainUrl = $this->site->getMainUrl();
- $minDate = $site->getCreationDate();
- $view->minDateYear = $minDate->toString('Y');
- $view->minDateMonth = $minDate->toString('m');
- $view->minDateDay = $minDate->toString('d');
+ $datetimeMinDate = $this->site->getCreationDate()->getDatetime();
+ $minDate = Piwik_Date::factory($datetimeMinDate, $this->site->getTimezone());
+ $this->setMinDateView($minDate, $view);
- $maxDate = Piwik_Date::factory('today');
- $view->maxDateYear = $maxDate->toString('Y');
- $view->maxDateMonth = $maxDate->toString('m');
- $view->maxDateDay = $maxDate->toString('d');
+ $maxDate = Piwik_Date::factory('now', $this->site->getTimezone());
+ $this->setMaxDateView($maxDate, $view);
+ $view->currentAdminMenuName = Piwik_GetCurrentAdminMenuName();
$view->debugTrackVisitsInsidePiwikUI = Zend_Registry::get('config')->Debug->track_visits_inside_piwik_ui;
+ $view->isSuperUser = Zend_Registry::get('access')->isSuperUser();
} catch(Exception $e) {
self::redirectToIndex(Piwik::getModule(), Piwik::getAction());
}
}
+ /**
+ * Sets general period variables (available periods, current period, period labels) used by templates
+ * @param $view
+ * @return void
+ */
public static function setPeriodVariablesView($view)
{
if(isset($view->period))
@@ -288,44 +369,137 @@ abstract class Piwik_Controller
$view->periodsNames = $periodNames;
}
- function redirectToIndex($moduleToRedirect, $actionToRedirect)
+ /**
+ * Helper method used to redirect the current http request to another module/action
+ * If specified, will also redirect to a given website, period and /or date
+ *
+ * @param $moduleToRedirect eg. "MultiSites"
+ * @param $actionToRedirect eg. "index"
+ * @param $websiteId eg. 1
+ * @param $defaultPeriod eg. "day"
+ * @param $defaultDate eg. "today"
+ * @return issues a http header redirect and exits
+ */
+ function redirectToIndex($moduleToRedirect, $actionToRedirect, $websiteId = null, $defaultPeriod = null, $defaultDate = null)
{
- $sitesId = Piwik_SitesManager_API::getSitesIdWithAtLeastViewAccess();
- if(!empty($sitesId))
+ if(is_null($websiteId))
{
- $firstSiteId = $sitesId[0];
- $firstSite = new Piwik_Site($firstSiteId);
- if ($firstSite->getCreationDate()->isToday())
- {
- $defaultDate = 'today';
- }
- else
- {
- $defaultDate = Zend_Registry::get('config')->General->default_day;
- }
- $defaultPeriod = Zend_Registry::get('config')->General->default_period;
- header("Location:index.php?module=".$moduleToRedirect."&action=".$actionToRedirect."&idSite=$firstSiteId&period=$defaultPeriod&date=$defaultDate");
+ $websiteId = $this->getDefaultWebsiteId();
}
- else
+ if(is_null($defaultDate))
{
- if(Piwik::isUserIsSuperUser())
- {
- Piwik_ExitWithMessage("Error: no website were found in this Piwik installation.
- <br>Check the table '". Piwik::prefixTable('site') ."' that should contain your Piwik websites.", false, true);
- }
- $currentLogin = Piwik::getCurrentUserLogin();
- if(!empty($currentLogin)
- && $currentLogin != 'anonymous')
- {
- $errorMessage = sprintf(Piwik_Translate('CoreHome_NoPrivileges'),$currentLogin);
- $errorMessage .= "<br /><br />&nbsp;&nbsp;&nbsp;<b><a href='index.php?module=". Zend_Registry::get('auth')->getName() ."&amp;action=logout'>&rsaquo; ". Piwik_Translate('General_Logout'). "</a></b><br />";
- Piwik_ExitWithMessage($errorMessage, false, true);
- }
- else
- {
- Piwik_FrontController::dispatch('Login', false);
- }
+ $defaultDate = $this->getDefaultDate();
+ }
+ if(is_null($defaultPeriod))
+ {
+ $defaultPeriod = $this->getDefaultPeriod();
}
+
+ if($websiteId) {
+ header("Location:index.php?module=".$moduleToRedirect
+ ."&action=".$actionToRedirect
+ ."&idSite=".$websiteId
+ ."&period=".$defaultPeriod
+ ."&date=".$defaultDate);
+ exit;
+ }
+
+ if(Piwik::isUserIsSuperUser())
+ {
+ Piwik_ExitWithMessage("Error: no website were found in this Piwik installation.
+ <br />Check the table '". Piwik_Common::prefixTable('site') ."' that should contain your Piwik websites.", false, true);
+ }
+
+ $currentLogin = Piwik::getCurrentUserLogin();
+ if(!empty($currentLogin)
+ && $currentLogin != 'anonymous')
+ {
+ $errorMessage = sprintf(Piwik_Translate('CoreHome_NoPrivileges'),$currentLogin);
+ $errorMessage .= "<br /><br />&nbsp;&nbsp;&nbsp;<b><a href='index.php?module=". Zend_Registry::get('auth')->getName() ."&amp;action=logout'>&rsaquo; ". Piwik_Translate('General_Logout'). "</a></b><br />";
+ Piwik_ExitWithMessage($errorMessage, false, true);
+ }
+
+ Piwik_FrontController::dispatch(Piwik::getLoginPluginName(), false);
exit;
}
+
+
+ /**
+ * Returns default website that Piwik should load
+ * @return Piwik_Site
+ */
+ protected function getDefaultWebsiteId()
+ {
+ $defaultWebsiteId = false;
+
+ // User preference: default website ID to load
+ $defaultReport = Piwik_UsersManager_API::getInstance()->getUserPreference(Piwik::getCurrentUserLogin(), Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT);
+ if(is_numeric($defaultReport))
+ {
+ $defaultWebsiteId = $defaultReport;
+ }
+
+ Piwik_PostEvent( 'Controller.getDefaultWebsiteId', $defaultWebsiteId );
+
+ if($defaultWebsiteId)
+ {
+ return $defaultWebsiteId;
+ }
+
+ $sitesId = Piwik_SitesManager_API::getInstance()->getSitesIdWithAtLeastViewAccess();
+ if(!empty($sitesId))
+ {
+ return $sitesId[0];
+ }
+ return false;
+ }
+
+ /**
+ * Returns default date for Piwik reports
+ * @return string today, 2010-01-01, etc.
+ */
+ protected function getDefaultDate()
+ {
+ $userSettingsDate = Piwik_UsersManager_API::getInstance()->getUserPreference(Piwik::getCurrentUserLogin(), Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT_DATE);
+ if($userSettingsDate === false)
+ {
+ return Zend_Registry::get('config')->General->default_day;
+ }
+ if($userSettingsDate == 'yesterday')
+ {
+ return $userSettingsDate;
+ }
+ return 'today';
+ }
+
+ /**
+ * Returns default date for Piwik reports
+ * @return string today, 2010-01-01, etc.
+ */
+ protected function getDefaultPeriod()
+ {
+ $userSettingsDate = Piwik_UsersManager_API::getInstance()->getUserPreference(Piwik::getCurrentUserLogin(), Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT_DATE);
+ if($userSettingsDate === false)
+ {
+ return Zend_Registry::get('config')->General->default_period;
+ }
+ if(in_array($userSettingsDate, array('today','yesterday')))
+ {
+ return 'day';
+ }
+ return $userSettingsDate;
+ }
+
+ /**
+ * Checks that the specified token matches the current logged in user token
+ * Protection against CSRF
+ *
+ * @return throws exception if token doesn't match
+ */
+ protected function checkTokenInUrl()
+ {
+ if(Piwik_Common::getRequestVar('token_auth', false) != Piwik::getCurrentUserTokenAuth()) {
+ throw new Piwik_Access_NoAccessException(Piwik_TranslateException('General_ExceptionInvalidToken'));
+ }
+ }
}
diff --git a/core/Cookie.php b/core/Cookie.php
index 3da0fe5cd4..215f985450 100644
--- a/core/Cookie.php
+++ b/core/Cookie.php
@@ -46,11 +46,12 @@ class Piwik_Cookie
*
* @param string cookie Name
* @param int The timestamp after which the cookie will expire, eg time() + 86400
+ * @param string The path on the server in which the cookie will be available on.
*/
- public function __construct( $cookieName, $expire = null)
+ public function __construct( $cookieName, $expire = null, $path = null)
{
$this->name = $cookieName;
-
+ $this->path = $path;
$this->expire = $expire;
if(is_null($expire)
|| !is_numeric($expire)
@@ -59,6 +60,7 @@ class Piwik_Cookie
$this->expire = $this->getDefaultExpire();
}
+
if($this->isCookieFound())
{
$this->loadContentFromCookie();
@@ -139,7 +141,7 @@ class Piwik_Cookie
public function save()
{
$this->setP3PHeader();
- $this->setCookie( $this->name, $this->generateContentString(), $this->expire);
+ $this->setCookie( $this->name, $this->generateContentString(), $this->expire, $this->path);
}
/**
@@ -164,13 +166,7 @@ class Piwik_Cookie
$varValue = base64_decode($varValue);
// some of the values may be serialized array so we try to unserialize it
- if( ($arrayValue = @unserialize($varValue)) !== false
- // we set the unserialized version only for arrays as you can have set a serialized string on purpose
- && is_array($arrayValue)
- )
- {
- $varValue = $arrayValue;
- }
+ $varValue = Piwik_Common::unserialize_array($varValue);
}
$this->set($varName, $varValue);
@@ -245,12 +241,12 @@ class Piwik_Cookie
*/
public function __toString()
{
- $str = "<-- Content of the cookie '{$this->name}' <br>\n";
+ $str = "&lt;-- Content of the cookie '{$this->name}' <br />\n";
foreach($this->value as $name => $value )
{
- $str .= $name . " = " . var_export($this->get($name), true) . "<br>\n";
+ $str .= $name . " = " . var_export($this->get($name), true) . "<br />\n";
}
- $str .= "--> <br>\n";
+ $str .= "--&gt; <br />\n";
return $str;
}
diff --git a/core/DataFiles/SearchEngines.php b/core/DataFiles/SearchEngines.php
index 7239247aea..6d467076df 100644
--- a/core/DataFiles/SearchEngines.php
+++ b/core/DataFiles/SearchEngines.php
@@ -1,37 +1,37 @@
<?php
/**
* Piwik - Open source web analytics
- *
+ *
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
- *
+ *
* @category Piwik
* @package DataFiles
*/
/**
* Search Engine database
- *
+ *
* ======================================
* HOW TO ADD A SEARCH ENGINE TO THE LIST
* ======================================
* If you want to add a new entry, please email us the information + icon at hello at piwik.org
*
* See also: http://piwik.org/faq/general/#faq_39
- *
+ *
* Detail of a line:
* Url => array( SearchEngineName, KeywordParameter, [path containing the keyword], [charset used by the search engine])
- *
+ *
* The main search engine URL has to be at the top of the list for the given search Engine.
- * You can add new search engines icons by adding the icon in the plugins/Referers/images/SearchEngines directory
+ * You can add new search engines icons by adding the icon in the plugins/Referers/images/SearchEngines directory
* using the format 'mainSearchEngineUrl.png'. Example: www.google.com.png
- * To help Piwik link directly the search engine result page for the keyword, specify the third entry in the array
+ * To help Piwik link directly the search engine result page for the keyword, specify the third entry in the array
* using the macro {k} that will automatically be replaced by the keyword.
- *
+ *
* A simple example is:
* 'www.google.com' => array('Google', 'q', 'search?q={k}'),
- *
+ *
* A more complicated example, with an array of possible variable names, and a custom charset:
* 'www.baidu.com' => array('Baidu', array('wd', 'word', 'kw'), 's?wd={k}', 'gb2312'),
*/
@@ -50,10 +50,7 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// 1und1
'portal.1und1.de' => array('1und1', 'search'),
-
- // 3271
- 'nmsearch.3721.com' => array('3271', 'p'),
- 'seek.3721.com' => array('3271', 'p'),
+ 'search.1und1.de' => array('1und1', 'su', 'search/web/?mc=suche%40web%40home.suche%40web&allparams=&smode=&su={k}&search=Suche&webRb='),
// A9
'www.a9.com' => array('A9', ''),
@@ -72,9 +69,6 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Acoon
'www.acoon.de' => array('Acoon', 'begriff'),
- // Acont
- 'acont.de' => array('Acont', 'query'),
-
// Alexa
'www.alexa.com' => array('Alexa', 'q', 'search?q={k}'),
'alexa.com' => array('Alexa', 'q'),
@@ -126,7 +120,6 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'www.aolrecherches.aol.fr' => array('AOL', array('query', 'q')),
'www.aolimages.aol.fr' => array('AOL', array('query', 'q')),
'www.recherche.aol.fr' => array('AOL', array('query', 'q')),
- 'aolsearcht.aol.com' => array('AOL', array('query', 'q')),
'find.web.aol.com' => array('AOL', array('query', 'q')),
'recherche.aol.ca' => array('AOL', array('query', 'q')),
'aolsearch.aol.co.uk' => array('AOL', array('query', 'q')),
@@ -156,6 +149,7 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Ask
'www.ask.com' => array('Ask', array('ask', 'q'), 'web?q={k}'),
'web.ask.com' => array('Ask', array('ask', 'q')),
+ 'images.ask.com' => array('Ask', 'q'),
'ask.reference.com' => array('Ask', 'q'),
'www.ask.co.uk' => array('Ask', 'q'),
'uk.ask.com' => array('Ask', 'q'),
@@ -198,6 +192,9 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Bing
'www.bing.com' => array('Bing', 'q', 'search?q={k}'),
+ // Bing Images
+ 'www.bing.com/images/search'=> array('Bing Images', 'q', 'search?q={k}'),
+
// Blogdigger
'www.blogdigger.com' => array('Blogdigger', 'q'),
@@ -236,9 +233,7 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Comcast
'www.comcast.net' => array('Comcast', 'query'),
'search.comcast.net' => array('Comcast', 'q'),
-
- // Comet systems
- 'search.cometsystems.com' => array('CometSystems', 'q'),
+ 'search3.comcast.com' => array('Comcast', 'url'),
// Compuserve
'suche.compuserve.de' => array('Compuserve.de (Powered by Google)', 'q'),
@@ -274,6 +269,9 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Deskfeeds
'www.deskfeeds.com' => array('Deskfeeds', 'sx'),
+ // Digg
+ 'digg.com' => array('Digg', 's', 'search?s={k}'),
+
// Dino
'www.dino-online.de' => array('Dino', 'query'),
@@ -290,9 +288,16 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'search.dogpile.com' => array('Dogpile', 'q'),
'nbci.dogpile.com' => array('Dogpile', 'q'),
+ // DuckDuckGo
+ 'duckduckgo.com' => array('DuckDuckGo', 'q', '?q={k}'),
+
// earthlink
'search.earthlink.net' => array('Earthlink', 'q'),
+ // Ecosia (powered by Bing)
+ 'ecosia.org' => array('Ecosia', 'q', 'search.php?q={k}'),
+ 'www.ecosia.org' => array('Ecosia', 'q'),
+
// Eniro
'www.eniro.se' => array('Eniro', 'q'),
@@ -323,6 +328,9 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// eo
'eo.st' => array('eo', 'q'),
+ // Facebook
+ 'www.facebook.com' => array('Facebook', 'q', 'search/?q={k}'),
+
// Feedminer
'www.feedminer.com' => array('Feedminer', 'q'),
@@ -335,6 +343,7 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Fireball
'suche.fireball.de' => array('Fireball', 'query'),
+ 'www.fireball.de' => array('Fireball', 'q'),
// Firstfind
'www.firstsfind.com' => array('Firstsfind', 'qry'),
@@ -345,6 +354,13 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Flix
'www.flix.de' => array('Flix.de', 'keyword'),
+ // Forestle
+ 'de.forestle.org' => array('Forestle', 'q', 'search.php?q={k}'),
+ 'at.forestle.org' => array('Forestle', 'q', 'search.php?q={k}'),
+ 'ch.forestle.org' => array('Forestle', 'q', 'search.php?q={k}'),
+ 'us.forestle.org' => array('Forestle', 'q', 'search.php?q={k}'),
+ 'fr.forestle.org' => array('Forestle', 'q', 'search.php?q={k}'),
+
// Free
'search.free.fr' => array('Free', 'q'),
'search1-2.free.fr' => array('Free', 'q'),
@@ -365,14 +381,13 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'froogle.google.co.uk' => array('Google (Froogle)', 'q'),
// GAIS
- 'gais.cs.ccu.edu.tw' => array('GAIS)', 'query'),
+ 'gais.cs.ccu.edu.tw' => array('GAIS', 'query'),
// Gigablast
'www.gigablast.com' => array('Gigablast', 'q'),
'blogs.gigablast.com' => array('Gigablast (Blogs)', 'q'),
'travel.gigablast.com' => array('Gigablast (Travel)', 'q'),
'dir.gigablast.com' => array('Gigablast (Directory)', 'q'),
- 'gov.gigablast.com' => array('Gigablast (Gov)', 'q'),
// GMX
'suche.gmx.net' => array('GMX', 'su'),
@@ -396,7 +411,10 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'www.gogole.com' => array('Google', 'q'),
'www.gppgle.com' => array('Google', 'q'),
'go.google.com' => array('Google', 'q'),
+ 'www.google.ad' => array('Google', 'q'),
'www.google.ae' => array('Google', 'q'),
+ 'www.google.am' => array('Google', 'q'),
+ 'www.google.it.ao' => array('Google', 'q'),
'www.google.as' => array('Google', 'q'),
'www.google.at' => array('Google', 'q'),
'wwwgoogle.at' => array('Google', 'q'),
@@ -405,21 +423,28 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'www.google.az' => array('Google', 'q'),
'www.google.ba' => array('Google', 'q'),
'www.google.be' => array('Google', 'q'),
+ 'www.google.bf' => array('Google', 'q'),
'www.google.bg' => array('Google', 'q'),
'google.bg' => array('Google', 'q'),
'www.google.bi' => array('Google', 'q'),
+ 'www.google.bj' => array('Google', 'q'),
+ 'www.google.bs' => array('Google', 'q'),
'www.google.ca' => array('Google', 'q'),
'ww.google.ca' => array('Google', 'q'),
'w.google.ca' => array('Google', 'q'),
+ 'www.google.cat' => array('Google', 'q'),
'www.google.cc' => array('Google', 'q'),
'www.google.cd' => array('Google', 'q'),
+ 'google.cf' => array('Google', 'q'),
'www.google.cg' => array('Google', 'q'),
'www.google.ch' => array('Google', 'q'),
'ww.google.ch' => array('Google', 'q'),
'w.google.ch' => array('Google', 'q'),
'www.google.ci' => array('Google', 'q'),
+ 'google.co.ck' => array('Google', 'q'),
'www.google.cl' => array('Google', 'q'),
'www.google.cn' => array('Google', 'q'),
+ 'google.cm' => array('Google', 'q'),
'www.google.co' => array('Google', 'q'),
'www.google.cz' => array('Google', 'q'),
'wwwgoogle.cz' => array('Google', 'q'),
@@ -427,11 +452,14 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'ww.google.de' => array('Google', 'q'),
'w.google.de' => array('Google', 'q'),
'wwwgoogle.de' => array('Google', 'q'),
+ 'google.dm' => array('Google', 'q'),
+ 'google.dz' => array('Google', 'q'),
'www.google.ee' => array('Google', 'q'),
'www.google.dj' => array('Google', 'q'),
'www.google.dk' => array('Google', 'q'),
'www.google.es' => array('Google', 'q'),
'www.google.fi' => array('Google', 'q'),
+ 'www.googel.fi' => array('Google', 'q'),
'www.google.fm' => array('Google', 'q'),
'gogole.fr' => array('Google', 'q'),
'www.gogole.fr' => array('Google', 'q'),
@@ -441,35 +469,53 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'www.google.fr' => array('Google', 'q'),
'www.google.fr.' => array('Google', 'q'),
'google.fr' => array('Google', 'q'),
- 'www.google.gg' => array('Google', 'q'),
+ 'www.google.ga' => array('Google', 'q'),
'google.ge' => array('Google', 'q'),
'w.google.ge' => array('Google', 'q'),
'ww.google.ge' => array('Google', 'q'),
'www.google.ge' => array('Google', 'q'),
+ 'www.google.gg' => array('Google', 'q'),
'google.gr' => array('Google', 'q'),
- 'www.googel.fi' => array('Google', 'q'),
'www.google.gl' => array('Google', 'q'),
'www.google.gm' => array('Google', 'q'),
+ 'www.google.gp' => array('Google', 'q'),
'www.google.gr' => array('Google', 'q'),
+ 'www.google.gy' => array('Google', 'q'),
'www.google.hn' => array('Google', 'q'),
'www.google.hr' => array('Google', 'q'),
+ 'www.google.ht' => array('Google', 'q'),
'www.google.hu' => array('Google', 'q'),
'www.google.ie' => array('Google', 'q'),
+ 'www.google.im' => array('Google', 'q'),
'www.google.is' => array('Google', 'q'),
'www.google.it' => array('Google', 'q'),
+ 'www.google.je' => array('Google', 'q'),
'www.google.jo' => array('Google', 'q'),
+ 'www.google.ki' => array('Google', 'q'),
+ 'www.google.kg' => array('Google', 'q'),
'www.google.kz' => array('Google', 'q'),
+ 'www.google.la' => array('Google', 'q'),
'www.google.li' => array('Google', 'q'),
'www.google.lk' => array('Google', 'q'),
'www.google.lt' => array('Google', 'q'),
'www.google.lu' => array('Google', 'q'),
'www.google.lv' => array('Google', 'q'),
'www.google.md' => array('Google', 'q'),
+ 'www.google.me' => array('Google', 'q'),
+ 'www.google.mg' => array('Google', 'q'),
+ 'www.google.mk' => array('Google', 'q'),
+ 'www.google.ml' => array('Google', 'q'),
+ 'www.google.mn' => array('Google', 'q'),
'www.google.ms' => array('Google', 'q'),
'www.google.mu' => array('Google', 'q'),
+ 'www.google.mv' => array('Google', 'q'),
'www.google.mw' => array('Google', 'q'),
+ 'www.google.ne' => array('Google', 'q'),
'www.google.nl' => array('Google', 'q'),
'www.google.no' => array('Google', 'q'),
+ 'www.google.nr' => array('Google', 'q'),
+ 'www.google.nu' => array('Google', 'q'),
+ 'www.google.ps' => array('Google', 'q'),
'www.google.pl' => array('Google', 'q'),
'www.google.pn' => array('Google', 'q'),
'www.google.pt' => array('Google', 'q'),
@@ -477,16 +523,26 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'www.google.rs' => array('Google', 'q'),
'www.google.ru' => array('Google', 'q'),
'www.google.rw' => array('Google', 'q'),
+ 'www.google.sc' => array('Google', 'q'),
'www.google.se' => array('Google', 'q'),
'www.google.sh' => array('Google', 'q'),
'www.google.si' => array('Google', 'q'),
'www.google.sk' => array('Google', 'q'),
'www.google.sm' => array('Google', 'q'),
'www.google.sn' => array('Google', 'q'),
+ 'www.google.st' => array('Google', 'q'),
'www.google.td' => array('Google', 'q'),
+ 'www.google.tg' => array('Google', 'q'),
+ 'www.google.tk' => array('Google', 'q'),
+ 'www.google.tl' => array('Google', 'q'),
+ 'www.google.tm' => array('Google', 'q'),
+ 'www.google.to' => array('Google', 'q'),
'www.google.tt' => array('Google', 'q'),
'www.google.uz' => array('Google', 'q'),
+ 'www.google.vu' => array('Google', 'q'),
'www.google.vg' => array('Google', 'q'),
+ 'www.google.ws' => array('Google', 'q'),
+ 'www.google.co.bw' => array('Google', 'q'),
'www.google.co.cr' => array('Google', 'q'),
'www.google.co.gg' => array('Google', 'q'),
'www.google.co.hu' => array('Google', 'q'),
@@ -499,23 +555,36 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'www.google.co.ke' => array('Google', 'q'),
'www.google.co.kr' => array('Google', 'q'),
'www.google.co.ma' => array('Google', 'q'),
+ 'www.google.co.mz' => array('Google', 'q'),
'www.google.co.nz' => array('Google', 'q'),
'www.google.co.th' => array('Google', 'q'),
+ 'www.google.co.tz' => array('Google', 'q'),
+ 'www.google.co.ug' => array('Google', 'q'),
'www.google.co.uk' => array('Google', 'q'),
+ 'www.google.co.uz' => array('Google', 'q'),
+ 'www.google.co.vi' => array('Google', 'q'),
'www.google.co.ve' => array('Google', 'q'),
'www.google.co.za' => array('Google', 'q'),
+ 'www.google.co.zm' => array('Google', 'q'),
'www.google.co.zw' => array('Google', 'q'),
+ 'www.google.com.af' => array('Google', 'q'),
+ 'www.google.com.ag' => array('Google', 'q'),
+ 'www.google.com.ai' => array('Google', 'q'),
'www.google.com.ar' => array('Google', 'q'),
'www.google.com.au' => array('Google', 'q'),
+ 'www.google.com.bd' => array('Google', 'q'),
'www.google.com.bh' => array('Google', 'q'),
+ 'www.google.com.bn' => array('Google', 'q'),
'www.google.com.bo' => array('Google', 'q'),
'www.google.com.br' => array('Google', 'q'),
'www.google.com.by' => array('Google', 'q'),
+ 'www.google.com.bz' => array('Google', 'q'),
'www.google.com.co' => array('Google', 'q'),
'www.google.com.cu' => array('Google', 'q'),
'www.google.com.do' => array('Google', 'q'),
'www.google.com.ec' => array('Google', 'q'),
'www.google.com.eg' => array('Google', 'q'),
+ 'www.google.com.et' => array('Google', 'q'),
'www.google.com.fj' => array('Google', 'q'),
'www.google.com.gh' => array('Google', 'q'),
'www.google.com.gi' => array('Google', 'q'),
@@ -523,7 +592,9 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'www.google.com.gt' => array('Google', 'q'),
'www.google.com.hk' => array('Google', 'q'),
'www.google.com.jm' => array('Google', 'q'),
+ 'www.google.com.kh' => array('Google', 'q'),
'www.google.com.kw' => array('Google', 'q'),
+ 'www.google.com.lb' => array('Google', 'q'),
'www.google.com.ly' => array('Google', 'q'),
'www.google.com.mt' => array('Google', 'q'),
'www.google.com.mx' => array('Google', 'q'),
@@ -544,8 +615,11 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'www.google.com.qa' => array('Google', 'q'),
'www.google.com.ru' => array('Google', 'q'),
'www.google.com.sa' => array('Google', 'q'),
+ 'www.google.com.sb' => array('Google', 'q'),
'www.google.com.sg' => array('Google', 'q'),
+ 'www.google.com.sl' => array('Google', 'q'),
'www.google.com.sv' => array('Google', 'q'),
+ 'www.google.com.tj' => array('Google', 'q'),
'www.google.com.tr' => array('Google', 'q'),
'www.google.com.tw' => array('Google', 'q'),
'www.google.com.ua' => array('Google', 'q'),
@@ -594,6 +668,9 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'blogsearch.google.co.in' => array('Google Blogsearch', 'q'),
'blogsearch.google.co.uk' => array('Google Blogsearch', 'q'),
+ // Google Custom Search
+ 'www.google.com/cse' => array('Google Custom Search', 'q'),
+
// Google translation
'translate.google.com' => array('Google Translations', 'q'),
@@ -690,7 +767,7 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Goyellow.de
'www.goyellow.de' => array('GoYellow.de', 'MDN'),
- // Gule Sider:
+ // Gule Sider
'www.gulesider.no' => array('Gule Sider', 'q'),
// HighBeam
@@ -726,9 +803,7 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'search.icq.com' => array('ICQ', 'q'),
// Ilse
- 'spsearch.ilse.nl' => array('Startpagina', 'search_for'),
- 'be.ilse.nl' => array('Ilse BE', 'query'),
- 'search.ilse.nl' => array('Ilse NL', 'search_for'),
+ 'www.ilse.nl' => array('Ilse NL', 'search_for', '?search_for={k}'),
// Iwon
'search.iwon.com' => array('Iwon', 'searchfor'),
@@ -885,23 +960,23 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'ariadna.elmundo.es' => array('El Mundo', 'q'),
// MySpace
- 'searchservice.myspace.com' => array('MySpace', 'qry'),
+ 'searchservice.myspace.com' => array('MySpace', 'qry', 'index.cfm?fuseaction=sitesearch.results&type=Web&qry={k}'),
- // MyWebSearch
- 'kf.mysearch.myway.com' => array('MyWebSearch', 'searchfor'),
+ // MySearch / MyWay / MyWebSearch (default: powered by Ask.com)
+ 'www.mysearch.com' => array('MyWebSearch', 'searchfor', 'search/Ajmain.jhtml?searchfor={k}'),
'ms114.mysearch.com' => array('MyWebSearch', 'searchfor'),
'ms146.mysearch.com' => array('MyWebSearch', 'searchfor'),
- 'mysearch.myway.com' => array('MyWebSearch', 'searchfor'),
- 'searchfr.myway.com' => array('MyWebSearch', 'searchfor'),
+ 'kf.mysearch.myway.com' => array('MyWebSearch', 'searchfor'),
'ki.mysearch.myway.com' => array('MyWebSearch', 'searchfor'),
- 'search.mywebsearch.com' => array('MyWebSearch', 'searchfor'),
- 'www.mywebsearch.com' => array('MyWebSearch', 'searchfor'),
+ 'search.myway.com' => array('MyWebSearch', 'searchfor'),
+ 'search.mywebsearch.com' => array('MyWebSearch', 'searchfor', 'mywebsearch/Ajmain.jhtml?searchfor={k}'),
+
// Najdi
'www.najdi.si' => array('Najdi.si', 'q'),
// Naver
- 'search.naver.com' => array('Naver', 'query'),
+ 'search.naver.com' => array('Naver', 'query', 'search.naver?query={k}', 'x-windows-949'),
// Needtofind
'ko.search.need2find.com' => array('Needtofind', 'searchfor'),
@@ -939,7 +1014,7 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Onet
'szukaj.onet.pl' => array('Onet.pl', 'qt'),
- // Online.no:
+ // Online.no
'www.online.no' => array('Online.no', 'q'),
'online.no' => array('Online.no', 'q'),
@@ -951,7 +1026,7 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'bbs2.openfind.com.tw' => array('Openfind (BBS)', 'query'),
'news.openfind.com.tw' => array('Openfind (News)', 'query'),
- // Opplysningen 1881:
+ // Opplysningen 1881
'www.1881.no' => array('Opplysningen 1881', 'Query'),
// Overture
@@ -981,9 +1056,9 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'data.quicksearches.net' => array('QuickSearches', 'q'),
// Qualigo
- 'www.qualigo.de' => array('Qualigo', 'q'),
- 'www.qualigo.ch' => array('Qualigo', 'q'),
'www.qualigo.at' => array('Qualigo', 'q'),
+ 'www.qualigo.ch' => array('Qualigo', 'q'),
+ 'www.qualigo.de' => array('Qualigo', 'q'),
'www.qualigo.nl' => array('Qualigo', 'q'),
// Rambler
@@ -994,6 +1069,11 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Reacteur.com
'www.reacteur.com' => array('Reacteur', 'kw'),
+ // RPMFind
+ 'www.rpmfind.net' => array('rpmfind', 'query', 'linux/rpm2html/search.php?query={k}'),
+ 'rpmfind.net' => array('rpmfind', 'query'),
+ 'fr2.rpmfind.net' => array('rpmfind', 'query'),
+
// Sapo
'pesquisa.sapo.pt' => array('Sapo', 'q'),
@@ -1003,36 +1083,13 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Search.ch
'www.search.ch' => array('Search.ch', 'q'),
- // Search a lot
- 'www.searchalot.com' => array('Searchalot', 'query'),
+ // Searchalot
+ 'www.searchalot.com' => array('Searchalot', 'q', '?q={k}'),
+ 'searchalot.com' => array('Searchalot', 'q'),
// Seek
'www.seek.fr' => array('Searchalot', 'qry_str'),
- // Seekport
- 'www.seekport.de' => array('Seekport', 'query'),
- 'www.seekport.co.uk' => array('Seekport', 'query'),
- 'www.seekport.fr' => array('Seekport', 'query'),
- 'www.seekport.at' => array('Seekport', 'query'),
- 'www.seekport.es' => array('Seekport', 'query'),
- 'www.seekport.it' => array('Seekport', 'query'),
-
- // Seekport (blogs)
- 'blogs.seekport.de' => array('Seekport (Blogs)', 'query'),
- 'blogs.seekport.co.uk' => array('Seekport (Blogs)', 'query'),
- 'blogs.seekport.fr' => array('Seekport (Blogs)', 'query'),
- 'blogs.seekport.at' => array('Seekport (Blogs)', 'query'),
- 'blogs.seekport.es' => array('Seekport (Blogs)', 'query'),
- 'blogs.seekport.it' => array('Seekport (Blogs)', 'query'),
-
- // Seekport (news)
- 'news.seekport.de' => array('Seekport (News)', 'query'),
- 'news.seekport.co.uk' => array('Seekport (News)', 'query'),
- 'news.seekport.fr' => array('Seekport (News)', 'query'),
- 'news.seekport.at' => array('Seekport (News)', 'query'),
- 'news.seekport.es' => array('Seekport (News)', 'query'),
- 'news.seekport.it' => array('Seekport (News)', 'query'),
-
// Searchscout
'www.searchscout.com' => array('Search Scout', 'gt_keywords'),
@@ -1046,13 +1103,13 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'bg.setooz.com' => array('Setooz', 'query'),
'el.setooz.com' => array('Setooz', 'query'),
'et.setooz.com' => array('Setooz', 'query'),
- 'lv.setooz.com' => array('Setooz', 'query'),
- 'lt.setooz.com' => array('Setooz', 'query'),
+ 'fi.setooz.com' => array('Setooz', 'query'),
'hu.setooz.com' => array('Setooz', 'query'),
+ 'lt.setooz.com' => array('Setooz', 'query'),
+ 'lv.setooz.com' => array('Setooz', 'query'),
'no.setooz.com' => array('Setooz', 'query'),
'pl.setooz.com' => array('Setooz', 'query'),
'sk.setooz.com' => array('Setooz', 'query'),
- 'fi.setooz.com' => array('Setooz', 'query'),
'sv.setooz.com' => array('Setooz', 'query'),
'tr.setooz.com' => array('Setooz', 'query'),
'uk.setooz.com' => array('Setooz', 'query'),
@@ -1069,8 +1126,11 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Skynet
'search.skynet.be' => array('Skynet', 'keywords'),
+ // Sogou
+ 'www.sogou.com' => array('Sogou', 'query', 'web?query={k}'),
+
// soso.com
- 'www.soso.com' => array('Soso', 'w'),
+ 'www.soso.com' => array('Soso', 'w', 'q?w={k}', 'gb2312'),
// Sphere
'www.sphere.com' => array('Sphere', 'q'),
@@ -1109,8 +1169,12 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'search-dyn.tiscali.de' => array('Tiscali', 'key'),
'hledani.tiscali.cz' => array('Tiscali', 'query', false, 'windows-1250'),
+ // Tixuma
+ 'www.tixuma.de' => array('Tixuma', 'sc', 'index.php?mp=search&stp=&sc={k}&tg=0'),
+
// T-Online
'suche.t-online.de' => array('T-Online', 'q'),
+ 'navigationshilfe.t-online.de'=> array('T-Online', 'q', 'dtag/dns/results?mode=search_top&q={k}'),
// Trouvez.com
'www.trouvez.com' => array('Trouvez.com', 'query'),
@@ -1156,9 +1220,31 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'suche.web.de' => array('Web.de (Websuche)', 'su'),
'dir.web.de' => array('Web.de (Directory)', 'su'),
+ // Web.nl
+ 'www.web.nl' => array('Web.nl', 'query'),
+
+ // Weborama
+ 'www.weborama.fr' => array('weborama', 'query'),
+
+ // WebSearch
+ 'is1.websearch.com' => array('WebSearch', 'qkw'),
+ 'www.websearch.com' => array('WebSearch', 'qkw'),
+
// Webtip
'www.webtip.de' => array('Webtip', 'keyword'),
+ // Wedoo
+ 'fr.wedoo.com' => array('Wedoo', 'keyword'),
+
+ // Witch
+ 'www.witch.de' => array('Witch', 'search'),
+
+ // WXS
+ 'wxsl.nl' => array('Planet Internet', 'q'),
+
+ // WWW
+ 'search.www.ee' => array('www värav', 'query'),
+
// X-recherche
'www.x-recherche.com' => array('X-Recherche', 'mots'),
@@ -1174,28 +1260,32 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'au.search.yahoo.com' => array('Yahoo!', 'p'),
'br.search.yahoo.com' => array('Yahoo!', 'p'),
'ch.search.yahoo.com' => array('Yahoo!', 'p'),
- 'de.search.yahoo.com' => array('Yahoo!', 'p'),
'ca.search.yahoo.com' => array('Yahoo!', 'p'),
+ 'cade.search.yahoo.com' => array('Yahoo!', 'p'),
'cf.search.yahoo.com' => array('Yahoo!', 'p'),
- 'fr.search.yahoo.com' => array('Yahoo!', 'p'),
- 'espanol.search.yahoo.com' => array('Yahoo!', 'p'),
+ 'de.search.yahoo.com' => array('Yahoo!', 'p'),
'es.search.yahoo.com' => array('Yahoo!', 'p'),
+ 'espanol.search.yahoo.com' => array('Yahoo!', 'p'),
+ 'fr.search.yahoo.com' => array('Yahoo!', 'p'),
+ 'hk.search.yahoo.com' => array('Yahoo!', 'p'),
'id.search.yahoo.com' => array('Yahoo!', 'p'),
'it.search.yahoo.com' => array('Yahoo!', 'p'),
'kr.search.yahoo.com' => array('Yahoo!', 'p'),
'mx.search.yahoo.com' => array('Yahoo!', 'p'),
'nl.search.yahoo.com' => array('Yahoo!', 'p'),
'qc.search.yahoo.com' => array('Yahoo!', 'p'),
- 'uk.search.yahoo.com' => array('Yahoo!', 'p'),
- 'cade.search.yahoo.com' => array('Yahoo!', 'p'),
- 'tw.search.yahoo.com' => array('Yahoo!', 'p'),
+ 'ru.search.yahoo.com' => array('Yahoo!', 'p'),
'se.search.yahoo.com' => array('Yahoo!', 'p'),
+ 'tw.search.yahoo.com' => array('Yahoo!', 'p'),
+ 'uk.search.yahoo.com' => array('Yahoo!', 'p'),
'us.search.yahoo.com' => array('Yahoo!', 'p'),
- 'ru.search.yahoo.com' => array('Yahoo!', 'p'),
- 'www.yahoo.com.cn' => array('Yahoo!', 'p'),
+ 'search.cn.yahoo.com' => array('Yahoo!', 'p'),
+ 'one.cn.yahoo.com' => array('Yahoo!', 'p'),
+ 'cns.3721.com' => array('Yahoo!', 'p'), // acquired by Yahoo!
'au.yhs.search.yahoo.com' => array('Yahoo!', 'p', 'avg/search?p={k}'),
-
+ 'de.yhs.search.yahoo.com' => array('Yahoo!', 'p', 'avg/search?p={k}'),
+ 'us.yhs.search.yahoo.com' => array('Yahoo!', 'p', 'avg/search?p={k}'),
'de.dir.yahoo.com' => array('Yahoo! Webverzeichnis', ''),
'cf.dir.yahoo.com' => array('Yahoo! Directory', ''),
'fr.dir.yahoo.com' => array('Yahoo! Directory', ''),
@@ -1205,6 +1295,7 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
// Yandex
'yandex.ru' => array('Yandex', 'text', 'yandsearch?text={k}'),
+ 'yandex.ua' => array('Yandex', 'text'),
'www.yandex.ru' => array('Yandex', 'text'),
'search.yaca.yandex.ru' => array('Yandex', 'text'),
'ya.ru' => array('Yandex', 'text'),
@@ -1224,33 +1315,6 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
'www.yellowmap.de' => array('Yellowmap', ' '),
'yellowmap.de' => array('Yellowmap', ' '),
- // Wanadoo
- 'search.ke.wanadoo.fr' => array('Wanadoo', 'kw'),
- 'busca.wanadoo.es' => array('Wanadoo', 'buscar'),
-
- // Wedoo
- 'fr.wedoo.com' => array('Wedoo', 'keyword'),
-
- // Web.nl
- 'www.web.nl' => array('Web.nl', 'query'),
-
- // Weborama
- 'www.weborama.fr' => array('weborama', 'query'),
-
- // WebSearch
- 'is1.websearch.com' => array('WebSearch', 'qkw'),
- 'www.websearch.com' => array('WebSearch', 'qkw'),
- 'websearch.cs.com' => array('WebSearch', 'query'),
-
- // Witch
- 'www.witch.de' => array('Witch', 'search'),
-
- // WWW
- 'search.www.ee' => array('www värav', 'query'),
-
- // WXS
- 'wxsl.nl' => array('Planet Internet', 'q'),
-
// Zoek
'www3.zoek.nl' => array('Zoek', 'q'),
diff --git a/core/DataTable.php b/core/DataTable.php
index a5590e1cbb..13f7f1e3ff 100644
--- a/core/DataTable.php
+++ b/core/DataTable.php
@@ -588,14 +588,13 @@ class Piwik_DataTable
*/
public function getRowsCount()
{
- $count = count($this->rows);
if(is_null($this->summaryRow))
{
- return $count;
+ return count($this->rows);
}
else
{
- return $count + 1;
+ return count($this->rows) + 1;
}
}
@@ -820,10 +819,7 @@ class Piwik_DataTable
$table1->rebuildIndex();
$table2->rebuildIndex();
- $countrows1 = $table1->getRowsCount();
- $countrows2 = $table2->getRowsCount();
-
- if($countrows1 != $countrows2)
+ if($table1->getRowsCount() != $table2->getRowsCount())
{
return false;
}
@@ -831,11 +827,8 @@ class Piwik_DataTable
foreach($rows1 as $row1)
{
$row2 = $table2->getRowFromLabel($row1->getColumn('label'));
- if($row2 === false)
- {
- return false;
- }
- if( !Piwik_DataTable_Row::isEqual($row1,$row2) )
+ if($row2 === false
+ || !Piwik_DataTable_Row::isEqual($row1,$row2))
{
return false;
}
diff --git a/core/DataTable/Filter/AddColumnsWhenShowAllColumns.php b/core/DataTable/Filter/AddColumnsWhenShowAllColumns.php
index 1e1e703b66..1b126e42a5 100644
--- a/core/DataTable/Filter/AddColumnsWhenShowAllColumns.php
+++ b/core/DataTable/Filter/AddColumnsWhenShowAllColumns.php
@@ -17,7 +17,13 @@
class Piwik_DataTable_Filter_AddColumnsWhenShowAllColumns extends Piwik_DataTable_Filter
{
protected $roundPrecision = 1;
- public function __construct( $table )
+
+ /**
+ * @param $table
+ * @param $enable Automatically set to true when filter_add_columns_when_show_all_columns is found in the API request
+ * @return void
+ */
+ public function __construct( $table, $enable = true )
{
parent::__construct($table);
$this->filter();
diff --git a/core/DataTable/Filter/ColumnCallbackAddColumnPercentage.php b/core/DataTable/Filter/ColumnCallbackAddColumnPercentage.php
index 90ea6b9ee5..d63d8298e3 100644
--- a/core/DataTable/Filter/ColumnCallbackAddColumnPercentage.php
+++ b/core/DataTable/Filter/ColumnCallbackAddColumnPercentage.php
@@ -19,61 +19,16 @@
* You can also specify the precision of the percentage value to be displayed (defaults to 0, eg "11%")
*
* Usage:
- * $nbVisits = Piwik_VisitsSummary_API::getVisits($idSite, $period, $date);
+ * $nbVisits = Piwik_VisitsSummary_API::getInstance()->getVisits($idSite, $period, $date);
* $dataTable->queueFilter('ColumnCallbackAddColumnPercentage', array('nb_visits', 'nb_visits_percentage', $nbVisits, 1));
*
* @package Piwik
* @subpackage Piwik_DataTable
*/
-class Piwik_DataTable_Filter_ColumnCallbackAddColumnPercentage extends Piwik_DataTable_Filter
+class Piwik_DataTable_Filter_ColumnCallbackAddColumnPercentage extends Piwik_DataTable_Filter_ColumnCallbackAddColumnQuotient
{
- private $columnValueToRead;
- private $columnNamePercentageToAdd;
- private $columnNameUsedAsDivisor;
- private $totalValueUsedAsDivisor;
- private $percentagePrecision;
-
- /**
- * @param Piwik_DataTable $table
- * @param string $columnValueToRead
- * @param string $columnNamePercentageToAdd
- * @param numeric|string $totalValueUsedToComputePercentageOrColumnName
- * if a numeric value is given, we use this value as the divisor to process the percentage.
- * if a string is given, this string is the column name's value used as the divisor.
- * @param int $percentagePrecision precision 0 means "11", 1 means "11.2"
- */
- public function __construct( $table, $columnValueToRead, $columnNamePercentageToAdd, $totalValueUsedToComputePercentageOrColumnName, $percentagePrecision = 0 )
+ protected function formatValue($value, $divisor)
{
- parent::__construct($table);
- $this->columnValueToRead = $columnValueToRead;
- $this->columnNamePercentageToAdd = $columnNamePercentageToAdd;
- if(is_numeric($totalValueUsedToComputePercentageOrColumnName))
- {
- $this->totalValueUsedAsDivisor = $totalValueUsedToComputePercentageOrColumnName;
- }
- else
- {
- $this->columnNameUsedAsDivisor = $totalValueUsedToComputePercentageOrColumnName;
- }
- $this->percentagePrecision = $percentagePrecision;
- $this->filter();
- }
-
- protected function filter()
- {
- foreach($this->table->getRows() as $key => $row)
- {
- $value = $row->getColumn($this->columnValueToRead);
- if(!is_null($this->totalValueUsedAsDivisor))
- {
- $divisor = $this->totalValueUsedAsDivisor;
- }
- else
- {
- $divisor = $row->getColumn($this->columnNameUsedAsDivisor);
- }
- $percentage = Piwik::getPercentageSafe($value, $divisor, $this->percentagePrecision);
- $row->addColumn($this->columnNamePercentageToAdd, $percentage);
- }
+ return Piwik::getPercentageSafe($value, $divisor, $this->quotientPrecision) . '%';
}
}
diff --git a/core/DataTable/Filter/ColumnCallbackAddColumnQuotient.php b/core/DataTable/Filter/ColumnCallbackAddColumnQuotient.php
new file mode 100644
index 0000000000..1e389360dc
--- /dev/null
+++ b/core/DataTable/Filter/ColumnCallbackAddColumnQuotient.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Adds a new column that is a division of two columns of the current row.
+ * Useful to process bounce rates, exit rates, average time on page, etc.
+ *
+ * @package Piwik
+ * @subpackage Piwik_DataTable
+ */
+class Piwik_DataTable_Filter_ColumnCallbackAddColumnQuotient extends Piwik_DataTable_Filter
+{
+ protected $columnValueToRead;
+ protected $columnNameToAdd;
+ protected $columnNameUsedAsDivisor;
+ protected $totalValueUsedAsDivisor;
+ protected $quotientPrecision;
+
+ /**
+ * @param Piwik_DataTable $table
+ * @param string $columnValueToRead
+ * @param string $columnNameToAdd
+ * @param numeric|string $divisorValueOrDivisorColumnName
+ * if a numeric value is given, we use this value as the divisor to process the percentage.
+ * if a string is given, this string is the column name's value used as the divisor.
+ * @param numeric $quotientPrecision Division precision
+ */
+ public function __construct( $table, $columnNameToAdd, $columnValueToRead, $divisorValueOrDivisorColumnName, $quotientPrecision = 0)
+ {
+ parent::__construct($table);
+ $this->columnValueToRead = $columnValueToRead;
+ $this->columnNameToAdd = $columnNameToAdd;
+ if(is_numeric($divisorValueOrDivisorColumnName))
+ {
+ $this->totalValueUsedAsDivisor = $divisorValueOrDivisorColumnName;
+ }
+ else
+ {
+ $this->columnNameUsedAsDivisor = $divisorValueOrDivisorColumnName;
+ }
+ $this->filter();
+ }
+
+ protected function filter()
+ {
+ foreach($this->table->getRows() as $key => $row)
+ {
+ $value = $row->getColumn($this->columnValueToRead);
+ if(!is_null($this->totalValueUsedAsDivisor))
+ {
+ $divisor = $this->totalValueUsedAsDivisor;
+ }
+ else
+ {
+ $divisor = $row->getColumn($this->columnNameUsedAsDivisor);
+ }
+ $formattedValue = $this->formatValue($value, $divisor);
+ $row->addColumn($this->columnNameToAdd, $formattedValue);
+ }
+ }
+
+ protected function formatValue($value, $divisor)
+ {
+ $quotient = 0;
+ if($divisor > 0 && $value > 0)
+ {
+ $quotient = round($value / $divisor, $this->quotientPrecision);
+ }
+ return $quotient;
+ }
+}
diff --git a/core/DataTable/Filter/ColumnCallbackAddMetadata.php b/core/DataTable/Filter/ColumnCallbackAddMetadata.php
index bef01a9945..d90079e3f1 100644
--- a/core/DataTable/Filter/ColumnCallbackAddMetadata.php
+++ b/core/DataTable/Filter/ColumnCallbackAddMetadata.php
@@ -27,7 +27,7 @@ class Piwik_DataTable_Filter_ColumnCallbackAddMetadata extends Piwik_DataTable_F
private $functionParameters;
private $metadataToAdd;
- public function __construct( $table, $columnToRead, $metadataToAdd, $functionToApply, $functionParameters = null )
+ public function __construct( $table, $columnToRead, $metadataToAdd, $functionToApply = null, $functionParameters = null )
{
parent::__construct($table);
$this->functionToApply = $functionToApply;
@@ -47,7 +47,14 @@ class Piwik_DataTable_Filter_ColumnCallbackAddMetadata extends Piwik_DataTable_F
{
$parameters = array_merge($parameters, $this->functionParameters);
}
- $newValue = call_user_func_array( $this->functionToApply, $parameters);
+ if(!is_null($this->functionToApply))
+ {
+ $newValue = call_user_func_array( $this->functionToApply, $parameters);
+ }
+ else
+ {
+ $newValue = $oldValue;
+ }
$row->addMetadata($this->metadataToAdd, $newValue);
}
}
diff --git a/core/DataTable/Filter/ColumnCallbackDeleteRow.php b/core/DataTable/Filter/ColumnCallbackDeleteRow.php
index c9ed614bb0..14468b14ef 100644
--- a/core/DataTable/Filter/ColumnCallbackDeleteRow.php
+++ b/core/DataTable/Filter/ColumnCallbackDeleteRow.php
@@ -34,8 +34,7 @@ class Piwik_DataTable_Filter_ColumnCallbackDeleteRow extends Piwik_DataTable_Fil
foreach($this->table->getRows() as $key => $row)
{
$columnValue = $row->getColumn($this->columnToFilter);
- if( $columnValue !== false
- && !call_user_func( $this->function, $columnValue))
+ if( !call_user_func( $this->function, $columnValue))
{
$this->table->deleteRow($key);
}
diff --git a/core/DataTable/Filter/ColumnCallbackReplace.php b/core/DataTable/Filter/ColumnCallbackReplace.php
index 6b286f228c..0c0e05b67e 100644
--- a/core/DataTable/Filter/ColumnCallbackReplace.php
+++ b/core/DataTable/Filter/ColumnCallbackReplace.php
@@ -35,7 +35,13 @@ class Piwik_DataTable_Filter_ColumnCallbackReplace extends Piwik_DataTable_Filte
{
foreach($this->table->getRows() as $key => $row)
{
- $parameters = array($this->getElementToReplace($row, $this->columnToFilter));
+ // when a value is not defined, we set it to zero by default (rather than displaying '-')
+ $value = $this->getElementToReplace($row, $this->columnToFilter);
+ if($value === false)
+ {
+ $value = 0;
+ }
+ $parameters = array($value);
if(!is_null($this->functionParameters))
{
$parameters = array_merge($parameters, $this->functionParameters);
diff --git a/core/DataTable/Filter/ColumnDelete.php b/core/DataTable/Filter/ColumnDelete.php
new file mode 100644
index 0000000000..c300f11d6d
--- /dev/null
+++ b/core/DataTable/Filter/ColumnDelete.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Deletes a column from a datatable
+ *
+ * @package Piwik
+ * @subpackage Piwik_DataTable
+ */
+class Piwik_DataTable_Filter_ColumnDelete extends Piwik_DataTable_Filter
+{
+ private $columnToFilter;
+ private $functionToApply;
+
+ public function __construct( $table, $columnToDelete )
+ {
+ parent::__construct($table);
+ $this->columnToDelete = $columnToDelete;
+ $this->filter();
+ }
+
+ protected function filter()
+ {
+ $this->table->deleteColumn($this->columnToDelete);
+ }
+
+}
diff --git a/core/DataTable/Filter/ReplaceColumnNames.php b/core/DataTable/Filter/ReplaceColumnNames.php
index 8671f2f81a..3865cace7c 100644
--- a/core/DataTable/Filter/ReplaceColumnNames.php
+++ b/core/DataTable/Filter/ReplaceColumnNames.php
@@ -77,9 +77,10 @@ class Piwik_DataTable_Filter_ReplaceColumnNames extends Piwik_DataTable_Filter
$newColumns = array();
foreach($columns as $columnName => $columnValue)
{
- if(isset(Piwik_Archive::$mappingFromIdToName[$columnName]))
+ if(isset($this->mappingToApply[$columnName]))
{
- $columnName = Piwik_Archive::$mappingFromIdToName[$columnName];
+ $columnName = $this->mappingToApply[$columnName];
+
if($columnName == 'goals')
{
$newSubColumns = array();
diff --git a/core/DataTable/Filter/Sort.php b/core/DataTable/Filter/Sort.php
index eabf22415d..2b5dbff5ea 100644
--- a/core/DataTable/Filter/Sort.php
+++ b/core/DataTable/Filter/Sort.php
@@ -161,6 +161,10 @@ class Piwik_DataTable_Filter_Sort extends Piwik_DataTable_Filter
return;
}
$row = current($rows);
+ if($row === false)
+ {
+ return;
+ }
$this->columnToSort = $this->selectColumnToSort($row);
$value = $row->getColumn($this->columnToSort);
diff --git a/core/DataTable/Filter/UpdateColumnsWhenShowAllGoals.php b/core/DataTable/Filter/UpdateColumnsWhenShowAllGoals.php
index 47caecf80d..26e296e2e2 100644
--- a/core/DataTable/Filter/UpdateColumnsWhenShowAllGoals.php
+++ b/core/DataTable/Filter/UpdateColumnsWhenShowAllGoals.php
@@ -16,12 +16,22 @@
*/
class Piwik_DataTable_Filter_UpdateColumnsWhenShowAllGoals extends Piwik_DataTable_Filter
{
+ const GOALS_OVERVIEW = -1;
+ const GOALS_FULL_TABLE = 0;
+
protected $mappingIdToNameGoal;
- public function __construct( $table, $mappingToApply = null )
+ /**
+ * @param $table
+ * @param $enable Automatically set to true when filter_update_columns_when_show_all_goals is found in the API request
+ * @param $processOnlyIdGoal
+ * @return unknown_type
+ */
+ public function __construct( $table, $enable = true, $processOnlyIdGoal )
{
parent::__construct($table);
$this->mappingIdToNameGoal = Piwik_Archive::$mappingFromIdToNameGoal;
+ $this->processOnlyIdGoal = $processOnlyIdGoal;
$this->filter();
}
@@ -36,14 +46,13 @@ class Piwik_DataTable_Filter_UpdateColumnsWhenShowAllGoals extends Piwik_DataTab
$newColumns = array();
$nbVisits = 0;
- // visits could be undefined when there is a convertion but no visit
+ // visits could be undefined when there is a conversion but no visit
if(isset($currentColumns[Piwik_Archive::INDEX_NB_VISITS]))
{
$nbVisits = $currentColumns[Piwik_Archive::INDEX_NB_VISITS];
}
$newColumns['nb_visits'] = $nbVisits;
$newColumns['label'] = $currentColumns['label'];
-
if(isset($currentColumns[Piwik_Archive::INDEX_GOALS]))
{
$nbVisitsConverted = $revenue = 0;
@@ -61,6 +70,7 @@ class Piwik_DataTable_Filter_UpdateColumnsWhenShowAllGoals extends Piwik_DataTab
{
$conversionRate = round(100 * $nbVisitsConverted / $nbVisits, $roundingPrecision);
}
+ $newColumns['goals_conversion_rate'] = $conversionRate;
if($nbVisits == 0)
{
@@ -70,8 +80,16 @@ class Piwik_DataTable_Filter_UpdateColumnsWhenShowAllGoals extends Piwik_DataTab
{
$revenuePerVisit = round( $revenue / $nbVisits, $roundingPrecision );
}
+ $newColumns['revenue_per_visit'] = $revenuePerVisit;
foreach($currentColumns[Piwik_Archive::INDEX_GOALS] as $goalId => $columnValue)
{
+ if($this->processOnlyIdGoal > self::GOALS_FULL_TABLE
+ && $this->processOnlyIdGoal != $goalId)
+ {
+ continue;
+ }
+
+ // Goal Conversion rate
$name = 'goal_' . $goalId . '_conversion_rate';
if($nbVisits == 0)
{
@@ -84,12 +102,32 @@ class Piwik_DataTable_Filter_UpdateColumnsWhenShowAllGoals extends Piwik_DataTab
$newColumns[$name] = $value;
$expectedColumns[$name] = true;
+ // When the table is displayed by clicking on the flag icon, we only display the columns
+ // Visits, Conversions, Per goal conversion rate, Revenue
+ if($this->processOnlyIdGoal == self::GOALS_OVERVIEW)
+ {
+ continue;
+ }
+
+ // Goal Conversions
$name = 'goal_' . $goalId . '_nb_conversions';
$newColumns[$name] = $columnValue[Piwik_Archive::INDEX_GOAL_NB_CONVERSIONS];
$expectedColumns[$name] = true;
+
+ // Goal Revenue per visit
+ $name = 'goal_' . $goalId . '_revenue_per_visit';
+ if($nbVisits == 0)
+ {
+ $value = $invalidDivision;
+ }
+ else
+ {
+ $revenuePerVisit = round( $columnValue[Piwik_Archive::INDEX_GOAL_REVENUE] / $nbVisits, $roundingPrecision );
+ }
+ $newColumns[$name] = $revenuePerVisit;
+ $expectedColumns[$name] = true;
+
}
- $newColumns['revenue_per_visit'] = $revenuePerVisit;
- $newColumns['goals_conversion_rate'] = $conversionRate;
}
$row->setColumns($newColumns);
diff --git a/core/DataTable/Manager.php b/core/DataTable/Manager.php
index 8e3506187e..54976f014c 100644
--- a/core/DataTable/Manager.php
+++ b/core/DataTable/Manager.php
@@ -122,22 +122,22 @@ class Piwik_DataTable_Manager
*/
public function dumpAllTables()
{
- echo "<hr>Piwik_DataTable_Manager->dumpAllTables()<br>";
+ echo "<hr />Piwik_DataTable_Manager->dumpAllTables()<br />";
foreach($this->tables as $id => $table)
{
if(!($table instanceof Piwik_DataTable ))
{
- echo "Error table $id is not instance of datatable<br>";
+ echo "Error table $id is not instance of datatable<br />";
var_dump($table);
}
else
{
- echo "<hr>";
- echo "Table (index=$id) TableId = ". $table->getId() . "<br>";
+ echo "<hr />";
+ echo "Table (index=$id) TableId = ". $table->getId() . "<br />";
echo $table;
- echo "<br>";
+ echo "<br />";
}
}
- echo "<br>-- End Piwik_DataTable_Manager->dumpAllTables()<hr>";
+ echo "<br />-- End Piwik_DataTable_Manager->dumpAllTables()<hr />";
}
}
diff --git a/core/DataTable/Renderer.php b/core/DataTable/Renderer.php
index c9458f16a3..5f1a42671f 100644
--- a/core/DataTable/Renderer.php
+++ b/core/DataTable/Renderer.php
@@ -24,8 +24,13 @@
abstract class Piwik_DataTable_Renderer
{
protected $table;
+ protected $exception;
protected $renderSubTables = false;
+ public function __construct()
+ {
+ }
+
public function setRenderSubTables($enableRenderSubTable)
{
$this->renderSubTables = (bool)$enableRenderSubTable;
@@ -44,6 +49,13 @@ abstract class Piwik_DataTable_Renderer
abstract public function render();
/**
+ * Computes the exception output and returns the string/binary
+ *
+ * @return string
+ */
+ abstract public function renderException();
+
+ /**
* @see render()
* @return string
*/
@@ -67,6 +79,19 @@ abstract class Piwik_DataTable_Renderer
}
/**
+ * Set the Exception to be rendered
+ * @param Exception $exception to be rendered
+ */
+ public function setException($exception)
+ {
+ if(!($exception instanceof Exception))
+ {
+ throw new Exception("The exception renderer accepts only an Exception object.");
+ }
+ $this->exception = $exception;
+ }
+
+ /**
* Returns the DataTable associated to the output format $name
*
* @throws exception If the renderer is unknown
@@ -75,18 +100,25 @@ abstract class Piwik_DataTable_Renderer
static public function factory( $name )
{
$name = ucfirst(strtolower($name));
- $path = PIWIK_INCLUDE_PATH .'/core/DataTable/Renderer/'.$name.'.php';
$className = 'Piwik_DataTable_Renderer_' . $name;
- if( Piwik_Common::isValidFilename($name)
- && Zend_Loader::isReadable($path) )
- {
- require_once $path; // prefixed by PIWIK_INCLUDE_PATH
+ try {
+ Piwik_Loader::autoload($className);
return new $className;
- }
- else
- {
- throw new Exception("Renderer format '$name' not valid. Try 'xml' or 'json' or 'csv' or 'html' or 'php' or 'original' instead.");
+ } catch(Exception $e) {
+ $availableRenderers = 'xml, json, csv, tsv, html, php, original';
+ throw new Exception(Piwik_TranslateException('General_ExceptionInvalidRendererFormat', array($name, $availableRenderers)));
}
- }
-}
+ }
+
+ /**
+ * Returns $rawData after all applicable characters have been converted to HTML entities.
+ *
+ * @param String $rawData to be converted
+ * @return String
+ */
+ static protected function renderHtmlEntities( $rawData )
+ {
+ return htmlentities($rawData, ENT_COMPAT, "UTF-8");
+ }
+} \ No newline at end of file
diff --git a/core/DataTable/Renderer/Console.php b/core/DataTable/Renderer/Console.php
index 0929de6744..7d0fb5f001 100644
--- a/core/DataTable/Renderer/Console.php
+++ b/core/DataTable/Renderer/Console.php
@@ -25,6 +25,12 @@ class Piwik_DataTable_Renderer_Console extends Piwik_DataTable_Renderer
return $this->renderTable($this->table);
}
+ function renderException()
+ {
+ $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage());
+ return 'Error: '.$exceptionMessage;
+ }
+
function setPrefixRow($str)
{
$this->prefixRows = $str;
@@ -32,25 +38,25 @@ class Piwik_DataTable_Renderer_Console extends Piwik_DataTable_Renderer
protected function renderDataTableArray(Piwik_DataTable_Array $tableArray, $prefix )
{
- $output = "Piwik_DataTable_Array<hr>";
+ $output = "Piwik_DataTable_Array<hr />";
$prefix = $prefix . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
foreach($tableArray->getArray() as $descTable => $table)
{
- $output .= $prefix . "<b>". $descTable. "</b><br>";
+ $output .= $prefix . "<b>". $descTable. "</b><br />";
$output .= $prefix . $this->renderTable($table, $prefix . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
- $output .= "<hr>";
+ $output .= "<hr />";
}
- $output .= "Metadata<br>";
+ $output .= "Metadata<br />";
foreach($tableArray->metadata as $id => $metadata)
{
- $output .= "<br>";
- $output .= $prefix . " <b>$id</b> <br>";
+ $output .= "<br />";
+ $output .= $prefix . " <b>$id</b><br />";
foreach($metadata as $name => $value)
{
$output .= $prefix . $prefix . "$name => $value";
}
}
- $output .= "<hr>";
+ $output .= "<hr />";
return $output;
}
@@ -63,7 +69,7 @@ class Piwik_DataTable_Renderer_Console extends Piwik_DataTable_Renderer
if($table->getRowsCount() == 0)
{
- return "Empty table <br>\n";
+ return "Empty table<br />\n";
}
static $depth=0;
@@ -103,7 +109,7 @@ class Piwik_DataTable_Renderer_Console extends Piwik_DataTable_Renderer
$output.= str_repeat($this->prefixRows, $depth)
. "- $i [".$columns."] [".$metadata."] [idsubtable = "
- . $row->getIdSubDataTable()."]<br>\n";
+ . $row->getIdSubDataTable()."]<br />\n";
if($row->getIdSubDataTable() !== null)
{
@@ -116,7 +122,7 @@ class Piwik_DataTable_Renderer_Console extends Piwik_DataTable_Renderer
$prefix . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'
);
} catch(Exception $e) {
- $output.= "-- Sub DataTable not loaded<br>\n";
+ $output.= "-- Sub DataTable not loaded<br />\n";
}
$depth--;
}
diff --git a/core/DataTable/Renderer/Csv.php b/core/DataTable/Renderer/Csv.php
index e756b518e6..3ff46a3dd4 100644
--- a/core/DataTable/Renderer/Csv.php
+++ b/core/DataTable/Renderer/Csv.php
@@ -31,7 +31,7 @@ class Piwik_DataTable_Renderer_Csv extends Piwik_DataTable_Renderer
*
* @var string
*/
- public $separator = ',';
+ public $separator = ",";
/**
* Line end
@@ -61,11 +61,27 @@ class Piwik_DataTable_Renderer_Csv extends Piwik_DataTable_Renderer
*/
public $exportIdSubtable = true;
- function render()
+ public function render()
{
return $this->output($this->renderTable($this->table));
}
+ function renderException()
+ {
+ $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage());
+ return 'Error: '.$exceptionMessage;
+ }
+
+ public function setConvertToUnicode($bool)
+ {
+ $this->convertToUnicode = $bool;
+ }
+
+ public function setSeparator($separator)
+ {
+ $this->separator = $separator;
+ }
+
protected function renderTable($table)
{
if($table instanceof Piwik_DataTable_Array)
@@ -234,7 +250,7 @@ class Piwik_DataTable_Renderer_Csv extends Piwik_DataTable_Renderer
$value = 0;
}
if(strpos($value, '"') !== false
- || strpos($value, ',') !== false )
+ || strpos($value, $this->separator) !== false )
{
$value = '"'. str_replace('"', '""', $value). '"';
}
@@ -248,7 +264,7 @@ class Piwik_DataTable_Renderer_Csv extends Piwik_DataTable_Renderer
return 'No data available';
}
// silent fail otherwise unit tests fail
- @header("Content-type: application/vnd.ms-excel");
+ @header("Content-Type: application/vnd.ms-excel");
@header("Content-Disposition: attachment; filename=piwik-report-export.csv");
if($this->convertToUnicode
&& function_exists('mb_convert_encoding'))
diff --git a/core/DataTable/Renderer/Html.php b/core/DataTable/Renderer/Html.php
index 62739fd035..2ebc36c0ce 100644
--- a/core/DataTable/Renderer/Html.php
+++ b/core/DataTable/Renderer/Html.php
@@ -38,6 +38,12 @@ class Piwik_DataTable_Renderer_Html extends Piwik_DataTable_Renderer
return $this->renderTable($this->table);
}
+ function renderException()
+ {
+ $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage());
+ return nl2br($exceptionMessage);
+ }
+
protected function renderTable($table)
{
if($table instanceof Piwik_DataTable_Array)
@@ -96,7 +102,7 @@ class Piwik_DataTable_Renderer_Html extends Piwik_DataTable_Renderer
if(count($metadata) != 0)
{
$someMetadata = true;
- $metadata = implode("<br>", $metadata);
+ $metadata = implode("<br />", $metadata);
$this->tableStructure[$i]['_metadata'] = $metadata;
}
diff --git a/core/DataTable/Renderer/Json.php b/core/DataTable/Renderer/Json.php
index 5febed6a88..0ce45db6ba 100644
--- a/core/DataTable/Renderer/Json.php
+++ b/core/DataTable/Renderer/Json.php
@@ -21,9 +21,21 @@ class Piwik_DataTable_Renderer_Json extends Piwik_DataTable_Renderer
{
public function render()
{
+ Piwik_DataTable_Renderer_Json::renderHeader();
return $this->renderTable($this->table);
}
+ function renderException()
+ {
+ Piwik_DataTable_Renderer_Json::renderHeader();
+
+ $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage());
+ $exceptionMessage = str_replace("\n", "", $exceptionMessage);
+ $exceptionMessage = '{"result":"error", "message":"'.$exceptionMessage.'"}';
+
+ return $this->jsonpWrap($exceptionMessage);
+ }
+
protected function renderTable($table)
{
$renderer = new Piwik_DataTable_Renderer_Php();
@@ -38,6 +50,11 @@ class Piwik_DataTable_Renderer_Json extends Piwik_DataTable_Renderer
}
$str = json_encode($array);
+ return $this->jsonpWrap($str);
+ }
+
+ protected function jsonpWrap($str)
+ {
if(($jsonCallback = Piwik_Common::getRequestVar('jsoncallback', false)) !== false)
{
if(preg_match('/^[0-9a-zA-Z]*$/', $jsonCallback) > 0)
@@ -45,6 +62,12 @@ class Piwik_DataTable_Renderer_Json extends Piwik_DataTable_Renderer
$str = $jsonCallback . "(" . $str . ")";
}
}
+
return $str;
}
+
+ static private function renderHeader ()
+ {
+ @header( "Content-Type: application/json" );
+ }
}
diff --git a/core/DataTable/Renderer/Php.php b/core/DataTable/Renderer/Php.php
index b7d5f216da..18f24452e0 100644
--- a/core/DataTable/Renderer/Php.php
+++ b/core/DataTable/Renderer/Php.php
@@ -64,6 +64,20 @@ class Piwik_DataTable_Renderer_Php extends Piwik_DataTable_Renderer
return $toReturn;
}
+ function renderException()
+ {
+ $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage());
+
+ $return = array('result' => 'error', 'message' => $exceptionMessage);
+
+ if($this->serialize)
+ {
+ $return = serialize($return);
+ }
+
+ return $return;
+ }
+
/**
* Produces a flat php array from the DataTable, putting "columns" and "metadata" on the same level.
*
diff --git a/core/DataTable/Renderer/Rss.php b/core/DataTable/Renderer/Rss.php
index 4dbfa58b7c..9c07515678 100644
--- a/core/DataTable/Renderer/Rss.php
+++ b/core/DataTable/Renderer/Rss.php
@@ -25,6 +25,12 @@ class Piwik_DataTable_Renderer_Rss extends Piwik_DataTable_Renderer
return $this->renderTable($this->table);
}
+ function renderException()
+ {
+ $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage());
+ return 'Error: '.$exceptionMessage;
+ }
+
protected function renderTable($table)
{
if(!($table instanceof Piwik_DataTable_Array)
@@ -47,8 +53,9 @@ class Piwik_DataTable_Renderer_Rss extends Piwik_DataTable_Renderer
$site = $table->metadata[$date]['site'];
$pudDate = date('r', $timestamp);
- $dateUrl = date('Y-m-d', $timestamp);
- $thisPiwikUrl = htmlentities($piwikUrl . "&date=$dateUrl");
+
+ $dateInSiteTimezone = Piwik_Date::factory($timestamp)->setTimezone($site->getTimezone())->toString('Y-m-d');
+ $thisPiwikUrl = htmlentities($piwikUrl . "&date=$dateInSiteTimezone");
$siteName = $site->getName();
$title = $siteName . " on ". $date;
@@ -98,7 +105,7 @@ class Piwik_DataTable_Renderer_Rss extends Piwik_DataTable_Renderer
{
if($table->getRowsCount() == 0)
{
- return "<b><i>Empty table</i></b> <br>\n";
+ return "<b><i>Empty table</i></b><br />\n";
}
$i = 1;
diff --git a/core/DataTable/Renderer/Tsv.php b/core/DataTable/Renderer/Tsv.php
new file mode 100644
index 0000000000..1af22ca122
--- /dev/null
+++ b/core/DataTable/Renderer/Tsv.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * TSV export
+ *
+ * Excel doesn't import CSV properly, it expects TAB separated values by default.
+ * TSV is therefore the 'CSV' that is Excel compatible
+ *
+ * @package Piwik
+ * @subpackage Piwik_DataTable
+ */
+class Piwik_DataTable_Renderer_Tsv extends Piwik_DataTable_Renderer_Csv
+{
+ function __construct()
+ {
+ parent::__construct();
+ $this->setSeparator("\t");
+ }
+
+ function render()
+ {
+ return parent::render();
+ }
+}
diff --git a/core/DataTable/Renderer/Xml.php b/core/DataTable/Renderer/Xml.php
index 9eb2c30bbf..828b890ab7 100644
--- a/core/DataTable/Renderer/Xml.php
+++ b/core/DataTable/Renderer/Xml.php
@@ -27,6 +27,20 @@ class Piwik_DataTable_Renderer_Xml extends Piwik_DataTable_Renderer
return $this->renderTable($this->table);
}
+ function renderException()
+ {
+ $exceptionMessage = self::renderHtmlEntities($this->exception->getMessage());
+
+ @header("Content-Type: text/xml;charset=utf-8");
+ $return =
+ "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" .
+ "<result>\n".
+ "\t<error message=\"".$exceptionMessage."\" />\n".
+ "</result>";
+
+ return $return;
+ }
+
protected function getArrayFromDataTable($table)
{
$renderer = new Piwik_DataTable_Renderer_Php();
diff --git a/core/DataTable/Row.php b/core/DataTable/Row.php
index cb8a20959b..1a07bd80a4 100644
--- a/core/DataTable/Row.php
+++ b/core/DataTable/Row.php
@@ -122,7 +122,7 @@ class Piwik_DataTable_Row
$metadata[] = "'$name' => $value";
}
$metadata = implode(", ", $metadata);
- $output = "# [".$columns."] [".$metadata."] [idsubtable = " . $this->getIdSubDataTable()."]<br>\n";
+ $output = "# [".$columns."] [".$metadata."] [idsubtable = " . $this->getIdSubDataTable()."]<br />\n";
return $output;
}
diff --git a/core/Date.php b/core/Date.php
index f6aefce606..87fd5d55a0 100644
--- a/core/Date.php
+++ b/core/Date.php
@@ -18,66 +18,192 @@
class Piwik_Date
{
/**
+ * Builds a Piwik_Date object
+ *
+ * @param int timestamp
+ */
+ protected function __construct( $timestamp, $timezone = 'UTC')
+ {
+ if(!is_int( $timestamp ))
+ {
+ throw new Exception("Piwik_Date is expecting a unix timestamp");
+ }
+ $this->timezone = $timezone;
+ $this->timestamp = $timestamp ;
+ }
+
+
+ /**
* Returns a Piwik_Date objects.
- * Accepts strings 'today' 'yesterday' or any YYYY-MM-DD or timestamp
*
- * @param string $strDate
- * @return Piwik_Date
+ * @param string $strDate 'today' 'yesterday' or any YYYY-MM-DD or timestamp
+ * @param string $timezone if specified, the dateString will be relative to this $timezone.
+ * For example, today in UTC+12 will be a timestamp in the future for UTC.
+ * This is different from using ->setTimezone()
+ * @return Piwik_Date
*/
- static public function factory($dateString)
+ static public function factory($dateString, $timezone = null)
{
- if($dateString == 'today')
+ if($dateString == 'now')
+ {
+ $date = self::now();
+ }
+ elseif($dateString == 'today')
{
- return self::today();
+ $date = self::today();
}
- if($dateString == 'yesterday')
+ elseif($dateString == 'yesterday')
{
- return self::yesterday();
+ $date = self::yesterday();
}
- if (!is_int($dateString)
+ elseif($dateString == 'yesterdaySameTime')
+ {
+ $date = self::yesterdaySameTime();
+ }
+ elseif (!is_int($dateString)
&& ($dateString = strtotime($dateString)) === false)
{
- throw new Exception("Date format must be: YYYY-MM-DD, or 'today' or 'yesterday' or any keyword supported by the strtotime function (see http://php.net/strtotime for more information)");
+ throw new Exception(Piwik_TranslateException('General_ExceptionInvalidDateFormat', array("YYYY-MM-DD, or 'today' or 'yesterday'", "strtotime", "http://php.net/strtotime")));
+ }
+ else
+ {
+ $date = new Piwik_Date($dateString);
+ }
+ if(is_null($timezone))
+ {
+ return $date;
+ }
+
+ // manually adjust for UTC timezones
+ $utcOffset = self::extractUtcOffset($timezone);
+ if($utcOffset !== false)
+ {
+ return $date->addHour($utcOffset);
}
- return new Piwik_Date($dateString);
+
+ date_default_timezone_set($timezone);
+ $datetime = $date->getDatetime();
+ date_default_timezone_set('UTC');
+
+ $date = Piwik_Date::factory(strtotime($datetime));
+
+ return $date;
}
+ /*
+ * The stored timestamp is always UTC based.
+ * The returned timestamp via getTimestamp() will have the conversion applied
+ */
protected $timestamp = null;
+
+ /*
+ * Timezone the current date object is set to.
+ * Timezone will only affect the returned timestamp via getTimestamp()
+ */
+ protected $timezone = 'UTC';
+
+ const DATE_TIME_FORMAT = 'Y-m-d H:i:s';
+
+ /**
+ * Returns the datetime start in UTC
+ *
+ * @return string
+ */
+ function getDateStartUTC()
+ {
+ $dateStartUTC = date('Y-m-d', $this->timestamp);
+ $date = Piwik_Date::factory($dateStartUTC)->setTimezone($this->timezone);
+ return $date->toString(self::DATE_TIME_FORMAT);
+ }
+ /**
+ * Returns the datetime of the current timestamp
+ *
+ * @return string
+ */
+ function getDatetime()
+ {
+ return $this->toString(self::DATE_TIME_FORMAT);
+ }
+
+ /**
+ * Returns the datetime end in UTC
+ *
+ * @return string
+ */
+ function getDateEndUTC()
+ {
+ $dateEndUTC = date('Y-m-d 23:59:59', $this->timestamp);
+ $date = Piwik_Date::factory($dateEndUTC)->setTimezone($this->timezone);
+ return $date->toString(self::DATE_TIME_FORMAT);
+ }
+
/**
- * Returns the unix timestamp of the date
- *
- * @return int
+ * Returns a new date object, copy of $this, with the timezone set
+ * This timezone is used to offset the UTC timestamp returned by @see getTimestamp()
+ * Doesn't modify $this
+ *
+ * @param string $timezone 'UTC', 'Europe/London', ...
*/
- public function getTimestamp()
+ public function setTimezone($timezone)
{
- return $this->timestamp;
+ return new Piwik_Date($this->timestamp, $timezone);
}
/**
- * Builds a Piwik_Date object
+ * Helper function that returns the offset in the timezone string 'UTC+14'
+ * Returns false if the timezone is not UTC+X or UTC-X
*
- * @param int timestamp
+ * @param $timezone
+ * @return int or false
*/
- protected function __construct( $date )
+ static protected function extractUtcOffset($timezone)
{
- if(!is_int( $date ))
+ if($timezone == 'UTC')
{
- throw new Exception("Piwik_Date is expecting a unix timestamp");
+ return 0;
+ }
+ $start = substr($timezone, 0, 4);
+ if($start != 'UTC-'
+ && $start != 'UTC+')
+ {
+ return false;
}
- $this->timestamp = $date ;
+ $offset = (float)substr($timezone, 4);
+ if($start == 'UTC-') {
+ $offset = -$offset;
+ }
+ return $offset;
}
/**
- * Sets the time part of the date
- * Doesn't modify $this
- *
- * @param string $time HH:MM:SS
- * @return Piwik_Date The new date with the time part set
+ * Returns the unix timestamp of the date in UTC,
+ * converted from the date timezone
+ *
+ * @return int
*/
- public function setTime($time)
+ public function getTimestamp()
{
- return new Piwik_Date( strtotime( $this->get("j F Y") . " $time"));
+ $utcOffset = self::extractUtcOffset($this->timezone);
+ if($utcOffset !== false) {
+ return (int)($this->timestamp - $utcOffset * 3600);
+ }
+ // @fixme
+ // The following code seems clunky - I thought the DateTime php class would allow to return timestamps
+ // after applying the timezone offset. Instead, the underlying timestamp is not changed.
+ // I decided to get the date without the timezone information, and create the timestamp from the truncated string.
+ // Unit tests pass (@see Date.test.php) but I'm pretty sure this is not the right way to do it
+ date_default_timezone_set($this->timezone);
+ $dtzone = timezone_open('UTC');
+ $time = date('r', $this->timestamp);
+ $dtime = date_create($time);
+ date_timezone_set($dtime, $dtzone);
+ $dateWithTimezone = date_format($dtime, 'r');
+ $dateWithoutTimezone = substr($dateWithTimezone, 0, -6);
+ $timestamp = strtotime($dateWithoutTimezone);
+ date_default_timezone_set('UTC');
+
+ return (int)$timestamp;
}
/**
@@ -113,7 +239,7 @@ class Piwik_Date
{
return date($part, $this->getTimestamp());
}
-
+
/**
* @see toString()
*
@@ -125,6 +251,114 @@ class Piwik_Date
}
/**
+ * Compares the week of the current date against the given $date
+ * Returns 0 if equal, -1 if current week is earlier or 1 if current week is later
+ * Example: 09.Jan.2007 13:07:25 -> compareWeek(2); -> 0
+ *
+ * @param Piwik_Date $date
+ * @return integer 0 = equal, 1 = later, -1 = earlier
+ */
+ public function compareWeek(Piwik_Date $date)
+ {
+ $currentWeek = date('W', $this->getTimestamp());
+ $toCompareWeek = date('W', $date->getTimestamp());
+ if( $currentWeek == $toCompareWeek)
+ {
+ return 0;
+ }
+ if( $currentWeek < $toCompareWeek)
+ {
+ return -1;
+ }
+ return 1;
+ }
+
+ /**
+ * Compares the month of the current date against the given $date month
+ * Returns 0 if equal, -1 if current month is earlier or 1 if current month is later
+ * For example: 10.03.2000 -> 15.03.1950 -> 0
+ *
+ * @param Piwik_Date $month Month to compare
+ * @return integer 0 = equal, 1 = later, -1 = earlier
+ */
+ function compareMonth( Piwik_Date $date )
+ {
+ $currentMonth = date('n', $this->getTimestamp());
+ $toCompareMonth = date('n', $date->getTimestamp());
+ if( $currentMonth == $toCompareMonth)
+ {
+ return 0;
+ }
+ if( $currentMonth < $toCompareMonth)
+ {
+ return -1;
+ }
+ return 1;
+ }
+
+ /**
+ * Returns true if current date is today
+ *
+ * @return bool
+ */
+ public function isToday()
+ {
+ return $this->toString('Y-m-d') === Piwik_Date::factory('today', $this->timezone)->toString('Y-m-d');
+ }
+
+ /**
+ * Returns a date object set to now (same as today, except that the time is also set)
+ *
+ * @return Piwik_Date
+ */
+ static public function now()
+ {
+ return new Piwik_date(time());
+ }
+
+ /**
+ * Returns a date object set to today midnight
+ *
+ * @return Piwik_Date
+ */
+ static public function today()
+ {
+ return new Piwik_Date(strtotime(date("Y-m-d 00:00:00")));
+ }
+
+ /**
+ * Returns a date object set to yesterday midnight
+ *
+ * @return Piwik_Date
+ */
+ static public function yesterday()
+ {
+ return new Piwik_Date(strtotime("yesterday"));
+ }
+
+ /**
+ * Returns a date object set to yesterday same time of day
+ *
+ * @return Piwik_Date
+ */
+ static public function yesterdaySameTime()
+ {
+ return new Piwik_Date(strtotime("yesterday ".date('H:i:s')));
+ }
+
+ /**
+ * Sets the time part of the date
+ * Doesn't modify $this
+ *
+ * @param string $time HH:MM:SS
+ * @return Piwik_Date The new date with the time part set
+ */
+ public function setTime($time)
+ {
+ return new Piwik_Date( strtotime( date("Y-m-d", $this->timestamp) . " $time"), $this->timezone);
+ }
+
+ /**
* Sets a new day
* Returned is the new date object
* Doesn't modify $this
@@ -134,7 +368,7 @@ class Piwik_Date
*/
public function setDay( $day )
{
- $ts = $this->getTimestamp();
+ $ts = $this->timestamp;
$result = mktime(
date('H', $ts),
date('i', $ts),
@@ -143,7 +377,7 @@ class Piwik_Date
1,
date('Y', $ts)
);
- return new Piwik_Date( $result );
+ return new Piwik_Date( $result, $this->timezone );
}
/**
@@ -156,7 +390,7 @@ class Piwik_Date
*/
public function setYear( $year )
{
- $ts = $this->getTimestamp();
+ $ts = $this->timestamp;
$result = mktime(
date('H', $ts),
date('i', $ts),
@@ -165,11 +399,9 @@ class Piwik_Date
date('j', $ts),
$year
);
- return new Piwik_Date( $result );
+ return new Piwik_Date( $result, $this->timezone );
}
-
-
/**
* Subtracts days from the existing date object and returns a new Piwik_Date object
* Returned is the new date object
@@ -183,8 +415,8 @@ class Piwik_Date
{
return clone $this;
}
- $ts = strtotime("-$n day", $this->getTimestamp());
- return new Piwik_Date( $ts );
+ $ts = strtotime("-$n day", $this->timestamp);
+ return new Piwik_Date( $ts, $this->timezone );
}
/**
@@ -200,7 +432,7 @@ class Piwik_Date
{
return clone $this;
}
- $ts = $this->getTimestamp();
+ $ts = $this->timestamp;
$result = mktime(
date('H', $ts),
date('i', $ts),
@@ -209,23 +441,8 @@ class Piwik_Date
1, // we set the day to 1
date('Y', $ts)
);
- return new Piwik_Date( $result );
+ return new Piwik_Date( $result, $this->timezone );
}
-
- /**
- * Returns a representation of a date or datepart
- *
- * @param string OPTIONAL Part of the date to return, if null the timestamp is returned
- * @return integer|string date or datepart
- */
- public function get($part = null)
- {
- if(is_null($part))
- {
- return $this->getTimestamp();
- }
- return date($part, $this->getTimestamp());
- }
/**
* Returns a localized date string, given a template.
@@ -247,12 +464,12 @@ class Piwik_Date
"%longDay%" => Piwik_Translate('General_LongDay_'.$dayOfWeek),
"%longYear%" => $this->toString('Y'),
"%shortYear%" => $this->toString('y'),
- "%time%" => $this->toString('H:i:s T')
+ "%time%" => $this->toString('H:i:s')
);
$out = str_replace(array_keys($patternToValue), array_values($patternToValue), $template);
return $out;
}
-
+
/**
* Adds days to the existing date object.
* Returned is the new date object
@@ -263,82 +480,44 @@ class Piwik_Date
*/
public function addDay( $n )
{
- $ts = strtotime("+$n day", $this->getTimestamp());
- return new Piwik_Date( $ts );
+ $ts = strtotime("+$n day", $this->timestamp);
+ return new Piwik_Date( $ts, $this->timezone );
}
-
- /**
- * Compares the week of the current date against the given $date
- * Returns 0 if equal, -1 if current week is earlier or 1 if current week is later
- * Example: 09.Jan.2007 13:07:25 -> compareWeek(2); -> 0
- *
- * @param Piwik_Date $date
- * @return integer 0 = equal, 1 = later, -1 = earlier
- */
- public function compareWeek(Piwik_Date $date)
- {
- $currentWeek = date('W', $this->getTimestamp());
- $toCompareWeek = date('W', $date->getTimestamp());
- if( $currentWeek == $toCompareWeek)
- {
- return 0;
- }
- if( $currentWeek < $toCompareWeek)
- {
- return -1;
- }
- return 1;
- }
+
/**
- * Compares the month of the current date against the given $date month
- * Returns 0 if equal, -1 if current month is earlier or 1 if current month is later
- * For example: 10.03.2000 -> 15.03.1950 -> 0
- *
- * @param Piwik_Date $month Month to compare
- * @return integer 0 = equal, 1 = later, -1 = earlier
+ * Adds hours to the existing date object.
+ * Returned is the new date object
+ * Doesn't modify $this
+ *
+ * @param int Number of hours to add
+ * @return Piwik_Date new date
*/
- function compareMonth( Piwik_Date $date )
+ public function addHour( $n )
{
- $currentMonth = date('n', $this->getTimestamp());
- $toCompareMonth = date('n', $date->getTimestamp());
- if( $currentMonth == $toCompareMonth)
+ $minutes = 0;
+ if($n != round($n))
{
- return 0;
+ $minutes = abs($n - floor($n)) * 60;
+ $n = floor($n);
}
- if( $currentMonth < $toCompareMonth)
+ if($n > 0 )
{
- return -1;
+ $n = '+'.$n;
}
- return 1;
+ $ts = strtotime("$n hour $minutes minutes", $this->timestamp);
+ return new Piwik_Date( $ts, $this->timezone );
}
-
- /**
- * Returns true if current date is today
- *
- * @return bool
- */
- public function isToday()
- {
- return $this->get('Y-m-d') === date('Y-m-d', time());
- }
-
- /**
- * Returns a date object set to today midnight
- *
- * @return Piwik_Date
- */
- static public function today()
- {
- return new Piwik_Date(strtotime(date("Y-m-d 00:00:00")));
- }
-
+
/**
- * Returns a date object set to yesterday midnight
- *
- * @return Piwik_Date
- */
- static public function yesterday()
+ * Substract hour to the existing date object.
+ * Returned is the new date object
+ * Doesn't modify $this
+ *
+ * @param int Number of hours to substract
+ * @return Piwik_Date new date
+ */
+ public function subHour( $n )
{
- return new Piwik_Date(strtotime("yesterday"));
+ return $this->addHour(-$n);
}
}
diff --git a/core/Db.php b/core/Db/Adapter.php
index a8efb337a8..7a3b4fccf6 100644
--- a/core/Db.php
+++ b/core/Db/Adapter.php
@@ -1,43 +1,63 @@
<?php
/**
* Piwik - Open source web analytics
- *
+ *
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
- *
+ *
* @category Piwik
* @package Piwik
*/
/**
* @package Piwik
+ * @subpackage Piwik_Db
*/
-class Piwik_Db
+class Piwik_Db_Adapter
{
/**
- * Get adapter class name
+ * Create adapter
*
- * @param string $adapterName
- * @return string
+ * @param string $adapterName database adapter name
+ * @param array $dbInfos database connection info
+ * @return mixed (Piwik_Db_Adapter_Mysqli, Piwik_Db_Adapter_Pdo_Mysql, etc)
*/
- private static function getAdapterClassName($adapterName)
+ public static function factory($adapterName, & $dbInfos)
{
- return 'Piwik_Db_' . str_replace(' ', '_', ucwords(str_replace('_', ' ', strtolower($adapterName))));
+ if($dbInfos['port'][0] == '/')
+ {
+ $dbInfos['unix_socket'] = $dbInfos['port'];
+ unset($dbInfos['host']);
+ unset($dbInfos['port']);
+ }
+
+ // not used by Zend Framework
+ unset($dbInfos['tables_prefix']);
+ unset($dbInfos['adapter']);
+ unset($dbInfos['schema']);
+
+ $className = self::getAdapterClassName($adapterName);
+ $adapter = new $className($dbInfos);
+ $adapter->getConnection();
+
+ Zend_Db_Table::setDefaultAdapter($adapter);
+
+ // we don't want the connection information to appear in the logs
+ $adapter->resetConfig();
+
+ return $adapter;
}
/**
- * Create adapter
+ * Get adapter class name
*
* @param string $adapterName
- * @oaran array $config
- * @return mixed (Piwik_Db_Mysqli, Piwik_Db_Pdo_Mysql, etc)
+ * @return string
*/
- public static function factory($adapterName, $config)
+ private static function getAdapterClassName($adapterName)
{
- $className = self::getAdapterClassName($adapterName);
- $adapter = new $className($config);
- return $adapter;
+ return 'Piwik_Db_Adapter_' . str_replace(' ', '_', ucwords(str_replace('_', ' ', strtolower($adapterName))));
}
/**
@@ -59,24 +79,41 @@ class Piwik_Db
*/
public static function getAdapters()
{
- $path = PIWIK_INCLUDE_PATH . '/core/Db';
- $pathLength = strlen($path) + 1;
- $adapters = Piwik::globr($path, '*.php');
- $adapterNames = array();
- foreach($adapters as $adapter)
+ static $adapterNames = array(
+ // currently supported by Piwik
+ 'Pdo_Mysql',
+ 'Mysqli',
+
+ // other adapters supported by Zend_Db
+// 'Pdo_Pgsql',
+// 'Pdo_Mssql',
+// 'Sqlsrv',
+// 'Pdo_Ibm',
+// 'Db2',
+// 'Pdo_Oci',
+// 'Oracle',
+ );
+
+ $adapters = array();
+
+ foreach($adapterNames as $adapterName)
{
- $adapterName = str_replace('/', '_', substr($adapter, $pathLength, -strlen('.php')));
- $className = 'Piwik_Db_'.$adapterName;
+ $className = 'Piwik_Db_Adapter_'.$adapterName;
if(call_user_func(array($className, 'isEnabled')))
{
- $adapterNames[strtoupper($adapterName)] = call_user_func(array($className, 'getDefaultPort'));
+ $adapters[strtoupper($adapterName)] = call_user_func(array($className, 'getDefaultPort'));
}
}
- return $adapterNames;
+
+ return $adapters;
}
}
-interface Piwik_Db_iAdapter
+/**
+ * @package Piwik
+ * @subpackage Piwik_Db
+ */
+interface Piwik_Db_Adapter_Interface
{
/**
* Reset the configuration variables in this adapter.
diff --git a/core/Db/Mysqli.php b/core/Db/Adapter/Mysqli.php
index 6f62f9f546..37bb46540f 100644
--- a/core/Db/Mysqli.php
+++ b/core/Db/Adapter/Mysqli.php
@@ -12,8 +12,9 @@
/**
* @package Piwik
+ * @subpackage Piwik_Db
*/
-class Piwik_Db_Mysqli extends Zend_Db_Adapter_Mysqli implements Piwik_Db_iAdapter
+class Piwik_Db_Adapter_Mysqli extends Zend_Db_Adapter_Mysqli implements Piwik_Db_Adapter_Interface
{
public function __construct($config)
{
@@ -43,15 +44,29 @@ class Piwik_Db_Mysqli extends Zend_Db_Adapter_Mysqli implements Piwik_Db_iAdapte
*/
public function checkServerVersion()
{
- $databaseVersion = $this->getServerVersion();
+ $serverVersion = $this->getServerVersion();
$requiredVersion = Zend_Registry::get('config')->General->minimum_mysql_version;
- if(version_compare($databaseVersion, $requiredVersion) === -1)
+ if(version_compare($serverVersion, $requiredVersion) === -1)
{
- throw new Exception(Piwik_TranslateException('General_ExceptionDatabaseVersion', array('MySQL', $databaseVersion, $requiredVersion)));
+ throw new Exception(Piwik_TranslateException('General_ExceptionDatabaseVersion', array('MySQL', $serverVersion, $requiredVersion)));
}
}
/**
+ * Check client version compatibility against database server
+ */
+ public function checkClientVersion()
+ {
+ $serverVersion = $this->getServerVersion();
+ $clientVersion = $this->getClientVersion();
+ if(version_compare($serverVersion, '5') >= 0
+ && version_compare($clientVersion, '5') < 0)
+ {
+ throw new Exception(Piwik_TranslateException('General_ExceptionIncompatibleClientServerVersions', array('MySQL', $clientVersion, $serverVersion)));
+ }
+ }
+
+ /**
* Returns true if this adapter's required extensions are enabled
*
* @return bool
@@ -59,7 +74,7 @@ class Piwik_Db_Mysqli extends Zend_Db_Adapter_Mysqli implements Piwik_Db_iAdapte
public static function isEnabled()
{
$extensions = @get_loaded_extensions();
- return in_array('mysqli', $extensions) && function_exists('mysqli_set_charset');
+ return in_array('mysqli', $extensions);
}
/**
@@ -81,6 +96,15 @@ class Piwik_Db_Mysqli extends Zend_Db_Adapter_Mysqli implements Piwik_Db_iAdapte
*/
public function isErrNo($e, $errno)
{
+ if(is_null($this->_connection))
+ {
+ if(preg_match('/(?:\[|\s)([0-9]{4})(?:\]|\s)/', $e->getMessage(), $match))
+ {
+ return $match[1] == $errno;
+ }
+ return mysqli_connect_errno() == $errno;
+ }
+
return mysqli_errno($this->_connection) == $errno;
}
@@ -114,4 +138,19 @@ class Piwik_Db_Mysqli extends Zend_Db_Adapter_Mysqli implements Piwik_Db_iAdapte
$charset = mysqli_character_set_name($this->_connection);
return $charset === 'utf8';
}
+
+ /**
+ * Get client version
+ *
+ * @return string
+ */
+ public function getClientVersion()
+ {
+ $this->_connect();
+ $version = $this->_connection->server_version;
+ $major = (int) ($version / 10000);
+ $minor = (int) ($version % 10000 / 100);
+ $revision = (int) ($version % 100);
+ return $major . '.' . $minor . '.' . $revision;
+ }
}
diff --git a/core/Db/Adapter/Pdo/Mssql.php b/core/Db/Adapter/Pdo/Mssql.php
new file mode 100644
index 0000000000..7246c3838e
--- /dev/null
+++ b/core/Db/Adapter/Pdo/Mssql.php
@@ -0,0 +1,253 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * @package Piwik
+ * @subpackage Piwik_Db
+ */
+class Piwik_Db_Pdo_Mssql extends Zend_Db_Adapter_Pdo_Mssql implements Piwik_Db_Adapter_Interface
+{
+ /**
+ * Returns connection handle
+ *
+ * @return resource
+ */
+ public function getConnection()
+ {
+ // if we already have a PDO object, no need to re-connect.
+ if ($this->_connection)
+ {
+ return $this->_connection;
+ }
+
+ $this->_pdoType = "sqlsrv";
+ // get the dsn first, because some adapters alter the $_pdoType
+ //$dsn = $this->_dsn();
+
+ // check for PDO extension
+ if (!extension_loaded('pdo'))
+ {
+ /**
+ * @see Zend_Db_Adapter_Exception
+ */
+ throw new Zend_Db_Adapter_Exception('The PDO extension is required for this adapter but the extension is not loaded');
+ }
+
+ // check the PDO driver is available
+ if (!in_array($this->_pdoType, PDO::getAvailableDrivers()))
+ {
+ /**
+ * @see Zend_Db_Adapter_Exception
+ */
+ throw new Zend_Db_Adapter_Exception('The ' . $this->_pdoType . ' driver is not currently installed');
+ }
+
+ // create PDO connection
+ $q = $this->_profiler->queryStart('connect', Zend_Db_Profiler::CONNECT);
+
+ // add the persistence flag if we find it in our config array
+ if (isset($this->_config['persistent']) && ($this->_config['persistent'] == true))
+ {
+ $this->_config['driver_options'][PDO::ATTR_PERSISTENT] = true;
+ }
+
+ try {
+ $serverName = $this->_config["host"];
+ $database = $this->_config["dbname"];
+ if(is_null($database))
+ {
+ $database = 'master';
+ }
+ $uid = $this->_config['username'];
+ $pwd = $this->_config['password'];
+ if($this->_config["port"] != "")
+ {
+ $serverName = $serverName.",".$this->_config["port"];
+ }
+
+ $this->_connection = new PDO( "sqlsrv:$serverName", $uid, $pwd, array( 'Database' => $database ));
+
+
+ if( $this->_connection === false )
+ {
+ die( self::FormatErrors( sqlsrv_errors() ) );
+ }
+
+ /*
+ $this->_connection = new PDO(
+ $dsn,
+ $this->_config['username'],
+ $this->_config['password'],
+ $this->_config['driver_options']
+ );
+ */
+
+ $this->_profiler->queryEnd($q);
+
+ // set the PDO connection to perform case-folding on array keys, or not
+ $this->_connection->setAttribute(PDO::ATTR_CASE, $this->_caseFolding);
+ $this->_connection->setAttribute(PDO::SQLSRV_ENCODING_UTF8, true);
+
+
+ // always use exceptions.
+ $this->_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+ return $this->_connection;
+ } catch (PDOException $e) {
+ /**
+ * @see Zend_Db_Adapter_Exception
+ */
+ throw new Zend_Db_Adapter_Exception($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+
+ /**
+ * Reset the configuration variables in this adapter.
+ */
+ public function resetConfig()
+ {
+ $this->_config = array();
+ }
+
+ /**
+ * Return default port.
+ *
+ * @return int
+ */
+ public static function getDefaultPort()
+ {
+ return 1433;
+ }
+
+ /**
+ * Check MSSQL version
+ */
+ public function checkServerVersion()
+ {
+ $serverVersion = $this->getServerVersion();
+ $requiredVersion = Zend_Registry::get('config')->General->minimum_mssql_version;
+ if(version_compare($serverVersion, $requiredVersion) === -1)
+ {
+ throw new Exception(Piwik_TranslateException('General_ExceptionDatabaseVersion', array('MSSQL', $serverVersion, $requiredVersion)));
+ }
+
+ }
+
+ public function getServerVersion()
+ {
+ try
+ {
+ $stmt = $this->query("SELECT CAST(SERVERPROPERTY('productversion') as VARCHAR) as productversion");
+ $result = $stmt->fetchAll(Zend_Db::FETCH_NUM);
+ if (count($result))
+ {
+ return $result[0][0];
+ }
+ }
+ catch (PDOException $e)
+ {
+ }
+
+ return null;
+ }
+
+ /**
+ * Check client version compatibility against database server
+ */
+ public function checkClientVersion()
+ {
+ $serverVersion = $this->getServerVersion();
+ $clientVersion = $this->getClientVersion();
+ if(version_compare($serverVersion, '10') >= 0
+ && version_compare($clientVersion, '10') < 0)
+ {
+ throw new Exception(Piwik_TranslateException('General_ExceptionIncompatibleClientServerVersions', array('MSSQL', $clientVersion, $serverVersion)));
+ }
+ }
+
+ /**
+ * Returns true if this adapter's required extensions are enabled
+ *
+ * @return bool
+ */
+ public static function isEnabled()
+ {
+ $extensions = @get_loaded_extensions();
+ return in_array('PDO', $extensions) && in_array('pdo_sqlsrv', $extensions);
+ }
+
+ /**
+ * Returns true if this adapter supports blobs as fields
+ *
+ * @return bool
+ */
+ public function hasBlobDataType()
+ {
+ return true;
+ }
+
+ /**
+ * Test error number
+ *
+ * @param Exception $e
+ * @param string $errno
+ * @return bool
+ */
+ public function isErrNo($e, $errno)
+ {
+ if(preg_match('/(?:\[|\s)([0-9]{4})(?:\]|\s)/', $e->getMessage(), $match))
+ {
+ return $match[1] == $errno;
+ }
+ return false;
+ }
+
+ /**
+ * Is the connection character set equal to utf8?
+ *
+ * @return bool
+ */
+ public function isConnectionUTF8()
+ {
+ //check the getconnection, it's specified on the connection string.
+ return true;
+ }
+
+ /**
+ * Retrieve client version in PHP style
+ *
+ * @return string
+ */
+ public function getClientVersion()
+ {
+ $this->_connect();
+ try
+ {
+ $version = $this->_connection->getAttribute(PDO::ATTR_CLIENT_VERSION);
+ $requiredVersion = Zend_Registry::get('config')->General->minimum_mssql_client_version;
+ if(version_compare($version['DriverVer'], $requiredVersion) === -1)
+ {
+ throw new Exception(Piwik_TranslateException('General_ExceptionDatabaseVersion', array('MSSQL', $serverVersion, $requiredVersion)));
+ }
+ else
+ {
+ return $version['DriverVer'];
+ }
+ }
+ catch (PDOException $e)
+ {
+ // In case of the driver doesn't support getting attributes
+ }
+
+ return null;
+ }
+}
diff --git a/core/Db/Pdo/Mysql.php b/core/Db/Adapter/Pdo/Mysql.php
index 86f804e76b..4e8f8793a1 100644
--- a/core/Db/Pdo/Mysql.php
+++ b/core/Db/Adapter/Pdo/Mysql.php
@@ -12,8 +12,9 @@
/**
* @package Piwik
+ * @subpackage Piwik_Db
*/
-class Piwik_Db_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Mysql implements Piwik_Db_iAdapter
+class Piwik_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Mysql implements Piwik_Db_Adapter_Interface
{
/**
* Returns connection handle
@@ -67,15 +68,29 @@ class Piwik_Db_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Mysql implements Piwik_Db_i
*/
public function checkServerVersion()
{
- $databaseVersion = $this->getServerVersion();
+ $serverVersion = $this->getServerVersion();
$requiredVersion = Zend_Registry::get('config')->General->minimum_mysql_version;
- if(version_compare($databaseVersion, $requiredVersion) === -1)
+ if(version_compare($serverVersion, $requiredVersion) === -1)
{
- throw new Exception(Piwik_TranslateException('General_ExceptionDatabaseVersion', array('MySQL', $databaseVersion, $requiredVersion)));
+ throw new Exception(Piwik_TranslateException('General_ExceptionDatabaseVersion', array('MySQL', $serverVersion, $requiredVersion)));
}
}
/**
+ * Check client version compatibility against database server
+ */
+ public function checkClientVersion()
+ {
+ $serverVersion = $this->getServerVersion();
+ $clientVersion = $this->getClientVersion();
+ if(version_compare($serverVersion, '5') >= 0
+ && version_compare($clientVersion, '5') < 0)
+ {
+ throw new Exception(Piwik_TranslateException('General_ExceptionIncompatibleClientServerVersions', array('MySQL', $clientVersion, $serverVersion)));
+ }
+ }
+
+ /**
* Returns true if this adapter's required extensions are enabled
*
* @return bool
@@ -83,7 +98,7 @@ class Piwik_Db_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Mysql implements Piwik_Db_i
public static function isEnabled()
{
$extensions = @get_loaded_extensions();
- return in_array('PDO', $extensions) && in_array('pdo_mysql', $extensions);
+ return in_array('PDO', $extensions) && in_array('pdo_mysql', $extensions) && in_array('mysql', PDO::getAvailableDrivers());
}
/**
@@ -105,7 +120,7 @@ class Piwik_Db_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Mysql implements Piwik_Db_i
*/
public function isErrNo($e, $errno)
{
- if(preg_match('/ ([0-9]{4}) /', $e->getMessage(), $match))
+ if(preg_match('/(?:\[|\s)([0-9]{4})(?:\]|\s)/', $e->getMessage(), $match))
{
return $match[1] == $errno;
}
@@ -123,4 +138,24 @@ class Piwik_Db_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Mysql implements Piwik_Db_i
$charset = $charsetInfo[0]['Value'];
return $charset === 'utf8';
}
+
+ /**
+ * Retrieve client version in PHP style
+ *
+ * @return string
+ */
+ public function getClientVersion()
+ {
+ $this->_connect();
+ try {
+ $version = $this->_connection->getAttribute(PDO::ATTR_CLIENT_VERSION);
+ $matches = null;
+ if (preg_match('/((?:[0-9]{1,2}\.){1,3}[0-9]{1,2})/', $version, $matches)) {
+ return $matches[1];
+ }
+ } catch (PDOException $e) {
+ // In case of the driver doesn't support getting attributes
+ }
+ return null;
+ }
}
diff --git a/core/Db/Pdo/Pgsql.php b/core/Db/Adapter/Pdo/Pgsql.php
index 8c3cf0a6c5..f83a023b01 100644
--- a/core/Db/Pdo/Pgsql.php
+++ b/core/Db/Adapter/Pdo/Pgsql.php
@@ -12,8 +12,9 @@
/**
* @package Piwik
+ * @subpackage Piwik_Db
*/
-class Piwik_Db_Pdo_Pgsql extends Zend_Db_Adapter_Pdo_Pgsql implements Piwik_Db_iAdapter
+class Piwik_Db_Adapter_Pdo_Pgsql extends Zend_Db_Adapter_Pdo_Pgsql implements Piwik_Db_Adapter_Interface
{
/**
* Reset the configuration variables in this adapter.
@@ -39,11 +40,18 @@ class Piwik_Db_Pdo_Pgsql extends Zend_Db_Adapter_Pdo_Pgsql implements Piwik_Db_i
public function checkServerVersion()
{
$databaseVersion = $this->getServerVersion();
- $requiredVersion = Zend_Registry::get('config')->General->minimum_pgsql_version;
- if(version_compare($databaseVersion, $requiredVersion) === -1)
- {
- throw new Exception(Piwik_TranslateException('General_ExceptionDatabaseVersion', array('PostgreSQL', $databaseVersion, $requiredVersion)));
- }
+ $requiredVersion = Zend_Registry::get('config')->General->minimum_pgsql_version;
+ if(version_compare($databaseVersion, $requiredVersion) === -1)
+ {
+ throw new Exception(Piwik_TranslateException('General_ExceptionDatabaseVersion', array('PostgreSQL', $databaseVersion, $requiredVersion)));
+ }
+ }
+
+ /**
+ * Check client version compatibility against database server
+ */
+ public function checkClientVersion()
+ {
}
/**
@@ -53,10 +61,6 @@ class Piwik_Db_Pdo_Pgsql extends Zend_Db_Adapter_Pdo_Pgsql implements Piwik_Db_i
*/
public static function isEnabled()
{
- /**
- * @todo This adapter is incomplete.
- */
- return false;
$extensions = @get_loaded_extensions();
return in_array('PDO', $extensions) && in_array('pdo_pgsql', $extensions);
}
@@ -76,32 +80,6 @@ class Piwik_Db_Pdo_Pgsql extends Zend_Db_Adapter_Pdo_Pgsql implements Piwik_Db_i
}
/**
- * Pre-process SQL to handle MySQL-isms
- *
- * @return string
- */
- public function preprocessSql($query)
- {
- $search = array(
- // In MySQL, OPTION is still a reserved keyword; Piwik uses
- // backticking in case table_prefix is empty.
- '`',
-
- // MySQL implicitly does 'ORDER BY column' when there's a
- // 'GROUP BY column'; Piwik uses 'ORDER BY NULL' when order
- // doesn't matter, for better performance.
- 'ORDER BY NULL',
- );
-
- $replace = array(
- '',
- '',
- );
-
- $query = str_replace($search, $replace, $query);
- }
-
- /**
* Test error number
*
* @param Exception $e
@@ -128,6 +106,10 @@ class Piwik_Db_Pdo_Pgsql extends Zend_Db_Adapter_Pdo_Pgsql implements Piwik_Db_i
// PostgreSQL: column "%s" of relation "%s" already exists
'1060' => '42701',
+ // MySQL: Duplicate key name '%s'
+ // PostgreSQL: relation "%s" already exists
+ '1061' => '42P07',
+
// MySQL: Duplicate entry '%s' for key '%s'
// PostgreSQL: duplicate key violates unique constraint
'1062' => '23505',
@@ -160,24 +142,22 @@ class Piwik_Db_Pdo_Pgsql extends Zend_Db_Adapter_Pdo_Pgsql implements Piwik_Db_i
}
/**
- * Returns a list of the tables in the database.
+ * Retrieve client version in PHP style
*
- * Replaces parent::listTables() which uses subqueries.
- * @see ZF-8046
- *
- * @return array
+ * @return string
*/
- public function listTables()
+ public function getClientVersion()
{
- $sql = "SELECT c.relname AS table_name "
- . "FROM pg_catalog.pg_class c "
- . "JOIN pg_catalog.pg_roles r ON r.oid = c.relowner "
- . "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace "
- . "WHERE n.nspname <> 'pg_catalog' "
- . "AND n.nspname !~ '^pg_toast' "
- . "AND pg_catalog.pg_table_is_visible(c.oid) "
- . "AND c.relkind = 'r' ";
-
- return $this->fetchCol($sql);
+ $this->_connect();
+ try {
+ $version = $this->_connection->getAttribute(PDO::ATTR_CLIENT_VERSION);
+ $matches = null;
+ if (preg_match('/((?:[0-9]{1,2}\.){1,3}[0-9]{1,2})/', $version, $matches)) {
+ return $matches[1];
+ }
+ } catch (PDOException $e) {
+ // In case of the driver doesn't support getting attributes
+ }
+ return null;
}
}
diff --git a/core/Db/Schema.php b/core/Db/Schema.php
new file mode 100644
index 0000000000..7afe91d0e8
--- /dev/null
+++ b/core/Db/Schema.php
@@ -0,0 +1,282 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Schema abstraction
+ *
+ * Note: no relation to the ZF proposals for Zend_Db_Schema_Manager
+ *
+ * @package Piwik
+ * @subpackage Piwik_Db
+ */
+class Piwik_Db_Schema
+{
+ static private $instance = null;
+
+ private $schema = null;
+
+ /**
+ * Returns the singleton Piwik_Db_Schema
+ *
+ * @return Piwik_Db_Schema
+ */
+ static public function getInstance()
+ {
+ if (self::$instance === null)
+ {
+ $c = __CLASS__;
+ self::$instance = new $c();
+ }
+ return self::$instance;
+ }
+
+ /**
+ * Get schema class name
+ *
+ * @param string $schemaName
+ * @return string
+ */
+ private static function getSchemaClassName($schemaName)
+ {
+ return 'Piwik_Db_Schema_' . str_replace(' ', '_', ucwords(str_replace('_', ' ', strtolower($schemaName))));
+ }
+
+ /**
+ * Get list of schemas
+ *
+ * @return array
+ */
+ public static function getSchemas($adapterName)
+ {
+ static $allSchemaNames = array(
+ // MySQL storage engines
+ 'MYSQL' => array(
+ 'Myisam',
+// 'Innodb',
+// 'Infinidb',
+ ),
+
+ // Microsoft SQL Server
+// 'MSSQL' => array( 'Mssql' ),
+
+ // PostgreSQL
+// 'PDO_PGSQL' => array( 'Pgsql' ),
+
+ // IBM DB2
+// 'IBM' => array( 'Ibm' ),
+
+ // Oracle
+// 'OCI' => array( 'Oci' ),
+ );
+
+ $adapterName = strtoupper($adapterName);
+ switch($adapterName)
+ {
+ case 'PDO_MYSQL':
+ case 'MYSQLI':
+ $adapterName = 'MYSQL';
+ break;
+
+ case 'PDO_MSSQL':
+ case 'SQLSRV':
+ $adapterName = 'MSSQL';
+ break;
+
+ case 'PDO_IBM':
+ case 'DB2':
+ $adapterName = 'IBM';
+ break;
+
+ case 'PDO_OCI':
+ case 'ORACLE':
+ $adapterName = 'OCI';
+ break;
+ }
+ $schemaNames = $allSchemaNames[$adapterName];
+
+ $schemas = array();
+
+ foreach($schemaNamess as $schemaName)
+ {
+ $className = 'Piwik_Db_Schema_'.$schemaName;
+ if(call_user_func(array($className, 'isAvailable')))
+ {
+ $schemas[] = $schemaName;
+ }
+ }
+
+ return $schemas;
+ }
+
+ /**
+ * Load schema
+ */
+ private function loadSchema()
+ {
+ $schema = null;
+ Piwik_PostEvent('Schema.loadSchema', $schema);
+ if($schema === null)
+ {
+ $config = Zend_Registry::get('config');
+ $dbInfos = $config->database->toArray();
+ if(isset($dbInfos['schema']))
+ {
+ $schemaName = $dbInfos['schema'];
+ }
+ else
+ {
+ $schemaName = 'Myisam';
+ }
+ $className = self::getSchemaClassName($schemaName);
+ $schema = new $className();
+ }
+ $this->schema = $schema;
+ }
+
+ /**
+ * Returns an instance that subclasses Piwik_Db_Schema
+ *
+ * @return Piwik_Db_Schema_Interface
+ */
+ private function getSchema()
+ {
+ if ($this->schema === null)
+ {
+ $this->loadSchema();
+ }
+ return $this->schema;
+ }
+
+ /**
+ * Get the SQL to create a specific Piwik table
+ *
+ * @return string SQL
+ */
+ public function getTableCreateSql( $tableName )
+ {
+ return $this->getSchema()->getTableCreateSql($tableName);
+ }
+
+ /**
+ * Get the SQL to create Piwik tables
+ *
+ * @return array of strings containing SQL
+ */
+ public function getTablesCreateSql()
+ {
+ return $this->getSchema()->getTablesCreateSql();
+ }
+
+ /**
+ * Create database
+ */
+ public function createDatabase( $dbName = null )
+ {
+ $this->getSchema()->createDatabase($dbName);
+ }
+
+ /**
+ * Drop database
+ */
+ public function dropDatabase()
+ {
+ $this->getSchema()->dropDatabase();
+ }
+
+ /**
+ * Create all tables
+ */
+ public function createTables()
+ {
+ $this->getSchema()->createTables();
+ }
+
+ /**
+ * Creates an entry in the User table for the "anonymous" user.
+ */
+ public function createAnonymousUser()
+ {
+ $this->getSchema()->createAnonymousUser();
+ }
+
+ /**
+ * Truncate all tables
+ */
+ public function truncateAllTables()
+ {
+ $this->getSchema()->truncateAllTables();
+ }
+
+ /**
+ * Drop specific tables
+ */
+ public function dropTables( $doNotDelete = array() )
+ {
+ $this->getSchema()->dropTables($doNotDelete);
+ }
+
+ /**
+ * Names of all the prefixed tables in piwik
+ * Doesn't use the DB
+ *
+ * @return array Table names
+ */
+ public function getTablesNames()
+ {
+ return $this->getSchema()->getTablesNames();
+ }
+
+ /**
+ * Get list of tables installed
+ *
+ * @param bool $forceReload Invalidate cache
+ * @param string $idSite
+ * @return array Tables installed
+ */
+ public function getTablesInstalled($forceReload = true, $idSite = null)
+ {
+ return $this->getSchema()->getTablesInstalled($forceReload, $idSite);
+ }
+
+ /**
+ * Returns true if Piwik tables exist
+ *
+ * @return bool True if tables exist; false otherwise
+ */
+ public function hasTables()
+ {
+ return $this->getSchema()->hasTables();
+ }
+}
+
+/**
+ * @package Piwik
+ */
+interface Piwik_Db_Schema_Interface
+{
+ static public function isAvailable();
+
+ public function getTableCreateSql($tableName);
+ public function getTablesCreateSql();
+
+ public function createDatabase( $dbName = null );
+ public function dropDatabase();
+
+ public function createTables();
+ public function createAnonymousUser();
+ public function truncateAllTables();
+ public function dropTables( $doNotDelete = array() );
+
+ public function getTablesNames();
+ public function getTablesInstalled($forceReload = true, $idSite = null);
+ public function hasTables();
+}
diff --git a/core/Db/Schema/Myisam.php b/core/Db/Schema/Myisam.php
new file mode 100644
index 0000000000..790e07db38
--- /dev/null
+++ b/core/Db/Schema/Myisam.php
@@ -0,0 +1,484 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * MySQL schema
+ *
+ * @package Piwik
+ * @subpackage Piwik_Db
+ */
+class Piwik_Db_Schema_Myisam implements Piwik_Db_Schema_Interface
+{
+ /**
+ * Is this MySQL storage engine available?
+ *
+ * @param string $engineName
+ * @return bool True if available and enabled; false otherwise
+ */
+ static private function hasStorageEngine($engineName)
+ {
+ $db = Zend_Registry::get('db');
+ $allEngines = $db->fetchAssoc('SHOW ENGINES');
+ if(key_exists($engineName, $allEngines))
+ {
+ $support = $allEngines[$engineName]['Support'];
+ return $support == 'DEFAULT' || $support == 'YES';
+ }
+ return false;
+ }
+
+ /**
+ * Is this schema available?
+ *
+ * @return bool True if schema is available; false otherwise
+ */
+ static public function isAvailable()
+ {
+ return self::hasStorageEngine('MyISAM');
+ }
+
+ /**
+ * Get the SQL to create Piwik tables
+ *
+ * @return array of strings containing SQL
+ */
+ public function getTablesCreateSql()
+ {
+ $config = Zend_Registry::get('config');
+ $prefixTables = $config->database->tables_prefix;
+ $tables = array(
+ 'user' => "CREATE TABLE {$prefixTables}user (
+ login VARCHAR(100) NOT NULL,
+ password CHAR(32) NOT NULL,
+ alias VARCHAR(45) NOT NULL,
+ email VARCHAR(100) NOT NULL,
+ token_auth CHAR(32) NOT NULL,
+ date_registered TIMESTAMP NULL,
+ PRIMARY KEY(login),
+ UNIQUE KEY uniq_keytoken(token_auth)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'access' => "CREATE TABLE {$prefixTables}access (
+ login VARCHAR(100) NOT NULL,
+ idsite INTEGER UNSIGNED NOT NULL,
+ access VARCHAR(10) NULL,
+ PRIMARY KEY(login, idsite)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'site' => "CREATE TABLE {$prefixTables}site (
+ idsite INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ name VARCHAR(90) NOT NULL,
+ main_url VARCHAR(255) NOT NULL,
+ ts_created TIMESTAMP NULL,
+ timezone VARCHAR( 50 ) NOT NULL,
+ currency CHAR( 3 ) NOT NULL,
+ excluded_ips TEXT NOT NULL,
+ excluded_parameters VARCHAR ( 255 ) NOT NULL,
+ PRIMARY KEY(idsite)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'site_url' => "CREATE TABLE {$prefixTables}site_url (
+ idsite INTEGER(10) UNSIGNED NOT NULL,
+ url VARCHAR(255) NOT NULL,
+ PRIMARY KEY(idsite, url)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'goal' => " CREATE TABLE `{$prefixTables}goal` (
+ `idsite` int(11) NOT NULL,
+ `idgoal` int(11) NOT NULL,
+ `name` varchar(50) NOT NULL,
+ `match_attribute` varchar(20) NOT NULL,
+ `pattern` varchar(255) NOT NULL,
+ `pattern_type` varchar(10) NOT NULL,
+ `case_sensitive` tinyint(4) NOT NULL,
+ `revenue` float NOT NULL,
+ `deleted` tinyint(4) NOT NULL default '0',
+ PRIMARY KEY (`idsite`,`idgoal`)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'logger_message' => "CREATE TABLE {$prefixTables}logger_message (
+ idlogger_message INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ timestamp TIMESTAMP NULL,
+ message TEXT NULL,
+ PRIMARY KEY(idlogger_message)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'logger_api_call' => "CREATE TABLE {$prefixTables}logger_api_call (
+ idlogger_api_call INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ class_name VARCHAR(255) NULL,
+ method_name VARCHAR(255) NULL,
+ parameter_names_default_values TEXT NULL,
+ parameter_values TEXT NULL,
+ execution_time FLOAT NULL,
+ caller_ip INT UNSIGNED NULL,
+ timestamp TIMESTAMP NULL,
+ returned_value TEXT NULL,
+ PRIMARY KEY(idlogger_api_call)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'logger_error' => "CREATE TABLE {$prefixTables}logger_error (
+ idlogger_error INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ timestamp TIMESTAMP NULL,
+ message TEXT NULL,
+ errno INTEGER UNSIGNED NULL,
+ errline INTEGER UNSIGNED NULL,
+ errfile VARCHAR(255) NULL,
+ backtrace TEXT NULL,
+ PRIMARY KEY(idlogger_error)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'logger_exception' => "CREATE TABLE {$prefixTables}logger_exception (
+ idlogger_exception INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ timestamp TIMESTAMP NULL,
+ message TEXT NULL,
+ errno INTEGER UNSIGNED NULL,
+ errline INTEGER UNSIGNED NULL,
+ errfile VARCHAR(255) NULL,
+ backtrace TEXT NULL,
+ PRIMARY KEY(idlogger_exception)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'log_action' => "CREATE TABLE {$prefixTables}log_action (
+ idaction INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ name TEXT,
+ hash INTEGER(10) UNSIGNED NOT NULL,
+ type TINYINT UNSIGNED NULL,
+ PRIMARY KEY(idaction),
+ INDEX index_type_hash (type, hash)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'log_visit' => "CREATE TABLE {$prefixTables}log_visit (
+ idvisit INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+ idsite INTEGER(10) UNSIGNED NOT NULL,
+ visitor_localtime TIME NOT NULL,
+ visitor_idcookie CHAR(32) NOT NULL,
+ visitor_returning TINYINT(1) NOT NULL,
+ visit_first_action_time DATETIME NOT NULL,
+ visit_last_action_time DATETIME NOT NULL,
+ visit_server_date DATE NOT NULL,
+ visit_exit_idaction_url INTEGER(11) NOT NULL,
+ visit_entry_idaction_url INTEGER(11) NOT NULL,
+ visit_total_actions SMALLINT(5) UNSIGNED NOT NULL,
+ visit_total_time SMALLINT(5) UNSIGNED NOT NULL,
+ visit_goal_converted TINYINT(1) NOT NULL,
+ referer_type INTEGER UNSIGNED NULL,
+ referer_name VARCHAR(70) NULL,
+ referer_url TEXT NOT NULL,
+ referer_keyword VARCHAR(255) NULL,
+ config_md5config CHAR(32) NOT NULL,
+ config_os CHAR(3) NOT NULL,
+ config_browser_name VARCHAR(10) NOT NULL,
+ config_browser_version VARCHAR(20) NOT NULL,
+ config_resolution VARCHAR(9) NOT NULL,
+ config_pdf TINYINT(1) NOT NULL,
+ config_flash TINYINT(1) NOT NULL,
+ config_java TINYINT(1) NOT NULL,
+ config_director TINYINT(1) NOT NULL,
+ config_quicktime TINYINT(1) NOT NULL,
+ config_realplayer TINYINT(1) NOT NULL,
+ config_windowsmedia TINYINT(1) NOT NULL,
+ config_gears TINYINT(1) NOT NULL,
+ config_silverlight TINYINT(1) NOT NULL,
+ config_cookie TINYINT(1) NOT NULL,
+ location_ip INT UNSIGNED NOT NULL,
+ location_browser_lang VARCHAR(20) NOT NULL,
+ location_country CHAR(3) NOT NULL,
+ location_continent CHAR(3) NOT NULL,
+ PRIMARY KEY(idvisit),
+ INDEX index_idsite_idvisit (idsite, idvisit),
+ INDEX index_idsite_date_config (idsite, visit_server_date, config_md5config(8)),
+ INDEX index_idsite_datetime_config (idsite, visit_last_action_time, config_md5config(8))
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'log_conversion' => "CREATE TABLE `{$prefixTables}log_conversion` (
+ idvisit int(10) unsigned NOT NULL,
+ idsite int(10) unsigned NOT NULL,
+ visitor_idcookie char(32) NOT NULL,
+ server_time datetime NOT NULL,
+ idaction_url int(11) default NULL,
+ idlink_va int(11) default NULL,
+ referer_idvisit int(10) unsigned default NULL,
+ referer_visit_server_date date default NULL,
+ referer_type int(10) unsigned default NULL,
+ referer_name varchar(70) default NULL,
+ referer_keyword varchar(255) default NULL,
+ visitor_returning tinyint(1) NOT NULL,
+ location_country char(3) NOT NULL,
+ location_continent char(3) NOT NULL,
+ url text NOT NULL,
+ idgoal int(10) unsigned NOT NULL,
+ revenue float default NULL,
+ PRIMARY KEY (idvisit, idgoal),
+ INDEX index_idsite_datetime ( idsite, server_time )
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'log_link_visit_action' => "CREATE TABLE {$prefixTables}log_link_visit_action (
+ idlink_va INTEGER(11) NOT NULL AUTO_INCREMENT,
+ idvisit INTEGER(10) UNSIGNED NOT NULL,
+ idaction_url INTEGER(10) UNSIGNED NOT NULL,
+ idaction_url_ref INTEGER(10) UNSIGNED NOT NULL,
+ idaction_name INTEGER(10) UNSIGNED,
+ time_spent_ref_action INTEGER(10) UNSIGNED NOT NULL,
+ PRIMARY KEY(idlink_va),
+ INDEX index_idvisit(idvisit)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'log_profiling' => "CREATE TABLE {$prefixTables}log_profiling (
+ query TEXT NOT NULL,
+ count INTEGER UNSIGNED NULL,
+ sum_time_ms FLOAT NULL,
+ UNIQUE KEY query(query(100))
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'option' => "CREATE TABLE `{$prefixTables}option` (
+ option_name VARCHAR( 64 ) NOT NULL,
+ option_value LONGTEXT NOT NULL,
+ autoload TINYINT NOT NULL DEFAULT '1',
+ PRIMARY KEY ( option_name )
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'archive_numeric' => "CREATE TABLE {$prefixTables}archive_numeric (
+ idarchive INTEGER UNSIGNED NOT NULL,
+ name VARCHAR(255) NOT NULL,
+ idsite INTEGER UNSIGNED NULL,
+ date1 DATE NULL,
+ date2 DATE NULL,
+ period TINYINT UNSIGNED NULL,
+ ts_archived DATETIME NULL,
+ value FLOAT NULL,
+ PRIMARY KEY(idarchive, name),
+ INDEX index_idsite_dates_period(idsite, date1, date2, period, ts_archived),
+ INDEX index_period_archived(period, ts_archived)
+ ) DEFAULT CHARSET=utf8
+ ",
+
+ 'archive_blob' => "CREATE TABLE {$prefixTables}archive_blob (
+ idarchive INTEGER UNSIGNED NOT NULL,
+ name VARCHAR(255) NOT NULL,
+ idsite INTEGER UNSIGNED NULL,
+ date1 DATE NULL,
+ date2 DATE NULL,
+ period TINYINT UNSIGNED NULL,
+ ts_archived DATETIME NULL,
+ value MEDIUMBLOB NULL,
+ PRIMARY KEY(idarchive, name),
+ INDEX index_period_archived(period, ts_archived)
+ ) DEFAULT CHARSET=utf8
+ ",
+ );
+ return $tables;
+ }
+
+ /**
+ * Get the SQL to create a specific Piwik table
+ *
+ * @param string $tableName
+ * @return string SQL
+ */
+ public function getTableCreateSql( $tableName )
+ {
+ $tables = Piwik::getTablesCreateSql();
+
+ if(!isset($tables[$tableName]))
+ {
+ throw new Exception("The table '$tableName' SQL creation code couldn't be found.");
+ }
+
+ return $tables[$tableName];
+ }
+
+ /**
+ * Names of all the prefixed tables in piwik
+ * Doesn't use the DB
+ *
+ * @return array Table names
+ */
+ public function getTablesNames()
+ {
+ $aTables = array_keys($this->getTablesCreateSql());
+ $config = Zend_Registry::get('config');
+ $prefixTables = $config->database->tables_prefix;
+ $return = array();
+ foreach($aTables as $table)
+ {
+ $return[] = $prefixTables.$table;
+ }
+ return $return;
+ }
+
+ private $tablesInstalled = null;
+
+ /**
+ * Get list of tables installed
+ *
+ * @param bool $forceReload Invalidate cache
+ * @param string $idSite
+ * @return array Tables installed
+ */
+ public function getTablesInstalled($forceReload = true, $idSite = null)
+ {
+ if(is_null($this->tablesInstalled)
+ || $forceReload === true)
+ {
+ $db = Zend_Registry::get('db');
+ $config = Zend_Registry::get('config');
+ $prefixTables = $config->database->tables_prefix;
+
+ $allTables = $db->fetchCol("SHOW TABLES");
+
+ // all the tables to be installed
+ $allMyTables = $this->getTablesNames();
+
+ // we get the intersection between all the tables in the DB and the tables to be installed
+ $tablesInstalled = array_intersect($allMyTables, $allTables);
+
+ // at this point we have only the piwik tables which is good
+ // but we still miss the piwik generated tables (using the class Piwik_TablePartitioning)
+ $idSiteInSql = "no";
+ if(!is_null($idSite))
+ {
+ $idSiteInSql = $idSite;
+ }
+ $allArchiveNumeric = $db->fetchCol("/* SHARDING_ID_SITE = ".$idSiteInSql." */
+ SHOW TABLES LIKE '".$prefixTables."archive_numeric%'");
+ $allArchiveBlob = $db->fetchCol("/* SHARDING_ID_SITE = ".$idSiteInSql." */
+ SHOW TABLES LIKE '".$prefixTables."archive_blob%'");
+
+ $allTablesReallyInstalled = array_merge($tablesInstalled, $allArchiveNumeric, $allArchiveBlob);
+
+ $this->tablesInstalled = $allTablesReallyInstalled;
+ }
+ return $this->tablesInstalled;
+ }
+
+ /**
+ * Do tables exist?
+ *
+ * @return bool True if tables exist; false otherwise
+ */
+ public function hasTables()
+ {
+ return count($this->getTablesInstalled()) != 0;
+ }
+
+ /**
+ * Create database
+ *
+ * @param string $dbName
+ */
+ public function createDatabase( $dbName = null )
+ {
+ if(is_null($dbName))
+ {
+ $dbName = Zend_Registry::get('config')->database->dbname;
+ }
+ Piwik_Exec("CREATE DATABASE IF NOT EXISTS ".$dbName);
+ }
+
+ /**
+ * Drop database
+ */
+ public function dropDatabase()
+ {
+ $dbName = Zend_Registry::get('config')->database->dbname;
+ Piwik_Exec("DROP DATABASE IF EXISTS " . $dbName);
+
+ }
+
+ /**
+ * Create all tables
+ */
+ public function createTables()
+ {
+ $db = Zend_Registry::get('db');
+ $config = Zend_Registry::get('config');
+ $prefixTables = $config->database->tables_prefix;
+
+ $tablesAlreadyInstalled = $this->getTablesInstalled();
+ $tablesToCreate = $this->getTablesCreateSql();
+ unset($tablesToCreate['archive_blob']);
+ unset($tablesToCreate['archive_numeric']);
+
+ foreach($tablesToCreate as $tableName => $tableSql)
+ {
+ $tableName = $prefixTables . $tableName;
+ if(!in_array($tableName, $tablesAlreadyInstalled))
+ {
+ $db->query( $tableSql );
+ }
+ }
+ }
+
+ /**
+ * Creates an entry in the User table for the "anonymous" user.
+ */
+ public function createAnonymousUser()
+ {
+ // The anonymous user is the user that is assigned by default
+ // note that the token_auth value is anonymous, which is assigned by default as well in the Login plugin
+ $db = Zend_Registry::get('db');
+ $db->query("INSERT INTO ". Piwik_Common::prefixTable("user") . "
+ VALUES ( 'anonymous', '', 'anonymous', 'anonymous@example.org', 'anonymous', '".Piwik_Date::factory('now')->getDatetime()."' );" );
+ }
+
+ /**
+ * Truncate all tables
+ */
+ public function truncateAllTables()
+ {
+ $tablesAlreadyInstalled = $this->getTablesInstalled($forceReload = true);
+ foreach($tablesAlreadyInstalled as $table)
+ {
+ Piwik_Query("TRUNCATE `$table`");
+ }
+ }
+
+ /**
+ * Drop specific tables
+ *
+ * @param array $doNotDelete Names of tables to not delete
+ */
+ public function dropTables( $doNotDelete = array() )
+ {
+ $tablesAlreadyInstalled = $this->getTablesInstalled();
+ $db = Zend_Registry::get('db');
+
+ $doNotDeletePattern = '/('.implode('|',$doNotDelete).')/';
+
+ foreach($tablesAlreadyInstalled as $tableName)
+ {
+ if( count($doNotDelete) == 0
+ || (!in_array($tableName,$doNotDelete)
+ && !preg_match($doNotDeletePattern,$tableName)
+ )
+ )
+ {
+ $db->query("DROP TABLE `$tableName`");
+ }
+ }
+ }
+}
diff --git a/core/ExceptionHandler.php b/core/ExceptionHandler.php
index f5554ad89c..7c8d070ec0 100644
--- a/core/ExceptionHandler.php
+++ b/core/ExceptionHandler.php
@@ -32,7 +32,7 @@ function Piwik_ExceptionHandler(Exception $exception)
$formatter = new Piwik_Log_Exception_Formatter_ScreenFormatter();
$message = $formatter->format($event);
- $message .= "<br><br>And this exception raised another exception \"". $e->getMessage()."\"";
+ $message .= "<br /><br />And this exception raised another exception \"". $e->getMessage()."\"";
Piwik::exitWithErrorMessage( $message );
}
diff --git a/core/Form.php b/core/Form.php
index 6c00803938..4dfbdc087e 100644
--- a/core/Form.php
+++ b/core/Form.php
@@ -23,13 +23,13 @@ abstract class Piwik_Form extends HTML_QuickForm
{
protected $a_formElements = array();
- function __construct( $action = '' )
+ function __construct( $action = '', $attributes = '' )
{
if(empty($action))
{
$action = Piwik_Url::getCurrentQueryString();
}
- parent::HTML_QuickForm('form', 'POST', $action);
+ parent::HTML_QuickForm('form', 'POST', $action, $target='', $attributes);
$this->registerRule( 'checkEmail', 'function', 'Piwik_Form_isValidEmailString');
$this->registerRule( 'fieldHaveSameValue', 'function', 'Piwik_Form_fieldHaveSameValue');
@@ -96,6 +96,16 @@ abstract class Piwik_Form extends HTML_QuickForm
}
}
}
+ function setSelected( $nameElement, $value )
+ {
+ foreach( $this->_elements as $key => $value)
+ {
+ if($value->_attributes['name'] == $nameElement)
+ {
+ $this->_elements[$key]->_attributes['selected'] = 'selected';
+ }
+ }
+ }
}
function Piwik_Form_fieldHaveSameValue($element, $value, $arg)
diff --git a/core/FrontController.php b/core/FrontController.php
index 9d691d4421..22c99c84b2 100644
--- a/core/FrontController.php
+++ b/core/FrontController.php
@@ -10,9 +10,6 @@
* @package Piwik
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see core/PluginsManager.php
* @see core/Translate.php
@@ -108,7 +105,7 @@ class Piwik_FrontController
if(!class_exists($controllerClassName, false))
{
$moduleController = PIWIK_INCLUDE_PATH . '/plugins/' . $module . '/Controller.php';
- if( !Zend_Loader::isReadable($moduleController))
+ if(!is_readable($moduleController))
{
throw new Exception("Module controller $moduleController not found!");
}
@@ -163,13 +160,14 @@ class Piwik_FrontController
try {
Piwik::printSqlProfilingReportZend();
Piwik::printQueryCount();
+/*
+ if(Piwik::getModule() !== 'API')
+ {
+ Piwik::printMemoryUsage();
+ Piwik::printTimer();
+ }
+ */
} catch(Exception $e) {}
-
- if(Piwik::getModule() !== 'API')
- {
-// Piwik::printMemoryUsage();
-// Piwik::printTimer();
- }
}
/**
@@ -206,16 +204,21 @@ class Piwik_FrontController
}
$pluginsManager = Piwik_PluginsManager::getInstance();
- $pluginsManager->setPluginsToLoad( Zend_Registry::get('config')->Plugins->Plugins->toArray() );
+ $pluginsManager->loadPlugins( Zend_Registry::get('config')->Plugins->Plugins->toArray() );
if($exceptionToThrow)
{
throw $exceptionToThrow;
}
- Piwik_Translate::getInstance()->loadUserTranslation();
- Piwik::createDatabaseObject();
+ try {
+ Piwik::createDatabaseObject();
+ } catch(Exception $e) {
+ Piwik_PostEvent('FrontController.badConfigurationFile', $e);
+ throw $e;
+ }
+
Piwik::createLogObject();
// creating the access object, so that core/Updates/* can enforce Super User and use some APIs
@@ -230,16 +233,18 @@ class Piwik_FrontController
$authAdapter = Zend_Registry::get('auth');
} catch(Exception $e){
throw new Exception("Authentication object cannot be found in the Registry. Maybe the Login plugin is not activated?
- <br>You can activate the plugin by adding:<br>
- <code>Plugins[] = Login</code><br>
+ <br />You can activate the plugin by adding:<br />
+ <code>Plugins[] = Login</code><br />
under the <code>[Plugins]</code> section in your config/config.inc.php");
}
Zend_Registry::get('access')->reloadAccess($authAdapter);
+ Piwik_Translate::getInstance()->loadUserTranslation();
Piwik::raiseMemoryLimitIfNecessary();
$pluginsManager->setLanguageToLoad( Piwik_Translate::getInstance()->getLanguageToLoad() );
+ $pluginsManager->loadTranslations();
$pluginsManager->postLoadPlugins();
Piwik_PostEvent('FrontController.checkForUpdates');
diff --git a/core/Http.php b/core/Http.php
new file mode 100644
index 0000000000..9ca4d229e4
--- /dev/null
+++ b/core/Http.php
@@ -0,0 +1,385 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Server-side http client to retrieve content from remote servers, and optionally save to a local file.
+ * Used to check for the latest Piwik version and download updates.
+ *
+ * @package Piwik
+ */
+class Piwik_Http
+{
+ /**
+ * Get "best" available transport method for sendHttpRequest() calls.
+ *
+ * @return string
+ */
+ static public function getTransportMethod()
+ {
+ $method = 'curl';
+ if(!extension_loaded('curl'))
+ {
+ $method = 'stream';
+ if(@ini_get('allow_url_fopen') != '1')
+ {
+ $method = 'socket';
+ if(!function_exists('fsockopen'))
+ {
+ return null;
+ }
+ }
+ }
+ return $method;
+ }
+
+ /**
+ * Sends http request ensuring the request will fail before $timeout seconds
+ *
+ * If no $destinationPath is specified, the trimmed response (without header) is returned as a string.
+ * If a $destinationPath is specified, the response (without header) is saved to a file.
+ *
+ * @param string $aUrl
+ * @param int $timeout
+ * @param string $userAgent
+ * @param string $destinationPath
+ * @param int $followDepth
+ * @return bool true (or string) on success; false on HTTP response error code (1xx or 4xx)
+ * @throws Exception for all other errors
+ */
+ static public function sendHttpRequest($aUrl, $timeout, $userAgent = null, $destinationPath = null, $followDepth = 0)
+ {
+ // create output file
+ $file = null;
+ if($destinationPath)
+ {
+ if (($file = @fopen($destinationPath, 'wb')) === false || !is_resource($file))
+ {
+ throw new Exception('Error while creating the file: ' . $destinationPath);
+ }
+ }
+
+ return self::sendHttpRequestBy(self::getTransportMethod(), $aUrl, $timeout, $userAgent, $destinationPath, $file, $followDepth);
+ }
+
+ /**
+ * Sends http request using the specified transport method
+ *
+ * @param string $method
+ * @param string $aUrl
+ * @param int $timeout
+ * @param string $userAgent
+ * @param string $destinationPath
+ * @param resource $file
+ * @param int $followDepth
+ * @return bool true (or string) on success; false on HTTP response error code (1xx or 4xx)
+ * @throws Exception for all other errors
+ */
+ static public function sendHttpRequestBy($method = 'socket', $aUrl, $timeout, $userAgent = null, $destinationPath = null, $file = null, $followDepth = 0)
+ {
+ if ($followDepth > 5)
+ {
+ throw new Exception('Too many redirects ('.$followDepth.')');
+ }
+
+ $contentLength = 0;
+ $fileLength = 0;
+
+ if($method == 'socket')
+ {
+ // initialization
+ $url = @parse_url($aUrl);
+ if($url === false || !isset($url['scheme']))
+ {
+ throw new Exception('Malformed URL: '.$aUrl);
+ }
+
+ if($url['scheme'] != 'http')
+ {
+ throw new Exception('Invalid protocol/scheme: '.$url['scheme']);
+ }
+ $host = $url['host'];
+ $port = isset($url['port)']) ? $url['port'] : 80;
+ $path = isset($url['path']) ? $url['path'] : '/';
+ if(isset($url['query']))
+ {
+ $path .= '?'.$url['query'];
+ }
+ $errno = null;
+ $errstr = null;
+
+ // connection attempt
+ if (($fsock = @fsockopen($host, $port, $errno, $errstr, $timeout)) === false || !is_resource($fsock))
+ {
+ if(is_resource($file)) { @fclose($file); }
+ throw new Exception("Error while connecting to: $host. Please try again later. $errstr");
+ }
+
+ // send HTTP request header
+ fwrite($fsock,
+ "GET $path HTTP/1.0\r\n"
+ ."Host: $host".($port != 80 ? ':'.$port : '')."\r\n"
+ ."User-Agent: Piwik/".Piwik_Version::VERSION.($userAgent ? " $userAgent" : '')."\r\n"
+ .'Referer: http://'.Piwik_Common::getIpString()."/\r\n"
+ ."Connection: close\r\n"
+ ."\r\n"
+ );
+
+ $streamMetaData = array('timed_out' => false);
+ @stream_set_blocking($fsock, true);
+ @stream_set_timeout($fsock, $timeout);
+
+ // process header
+ $status = null;
+ $expectRedirect = false;
+
+ while(!feof($fsock))
+ {
+ $line = fgets($fsock, 4096);
+
+ $streamMetaData = @stream_get_meta_data($fsock);
+ if($streamMetaData['timed_out'])
+ {
+ if(is_resource($file)) { @fclose($file); }
+ @fclose($fsock);
+ throw new Exception('Timed out waiting for server response');
+ }
+
+ // a blank line marks the end of the server response header
+ if(rtrim($line, "\r\n") == '')
+ {
+ break;
+ }
+
+ // parse first line of server response header
+ if(!$status)
+ {
+ // expect first line to be HTTP response status line, e.g., HTTP/1.1 200 OK
+ if(!preg_match('~^HTTP/(\d\.\d)\s+(\d+)(\s*.*)?~', $line, $m))
+ {
+ if(is_resource($file)) { @fclose($file); }
+ @fclose($fsock);
+ throw new Exception('Expected server response code. Got '.rtrim($line, "\r\n"));
+ }
+
+ $status = (integer) $m[2];
+
+ // Informational 1xx or Client Error 4xx
+ if ($status < 200 || $status >= 400)
+ {
+ if(is_resource($file)) { @fclose($file); }
+ @fclose($fsock);
+ return false;
+ }
+
+ continue;
+ }
+
+ // handle redirect
+ if(preg_match('/^Location:\s*(.+)/', rtrim($line, "\r\n"), $m))
+ {
+ if(is_resource($file)) { @fclose($file); }
+ @fclose($fsock);
+ // Successful 2xx vs Redirect 3xx
+ if($status < 300)
+ {
+ throw new Exception('Unexpected redirect to Location: '.rtrim($line).' for status code '.$status);
+ }
+ return self::sendHttpRequestBy($method, trim($m[1]), $timeout, $userAgent, $pathDestination, $file, $followDepth+1);
+ }
+
+ // save expected content length for later verification
+ if(preg_match('/^Content-Length:\s*(\d+)/', $line, $m))
+ {
+ $contentLength = (integer) $m[1];
+ }
+ }
+
+ if(feof($fsock))
+ {
+ throw new Exception('Unexpected end of transmission');
+ }
+
+ // process content/body
+ $response = '';
+
+ while(!feof($fsock))
+ {
+ $line = fread($fsock, 8192);
+
+ $streamMetaData = @stream_get_meta_data($fsock);
+ if($streamMetaData['timed_out'])
+ {
+ if(is_resource($file)) { @fclose($file); }
+ @fclose($fsock);
+ throw new Exception('Timed out waiting for server response');
+ }
+
+ $fileLength += strlen($line);
+
+ if(is_resource($file))
+ {
+ // save to file
+ fwrite($file, $line);
+ }
+ else
+ {
+ // concatenate to response string
+ $response .= $line;
+ }
+ }
+
+ // determine success or failure
+ @fclose(@$fsock);
+ }
+ else if($method == 'stream')
+ {
+ $response = false;
+
+ // we make sure the request takes less than a few seconds to fail
+ // we create a stream_context (works in php >= 5.2.1)
+ // we also set the socket_timeout (for php < 5.2.1)
+ $default_socket_timeout = @ini_get('default_socket_timeout');
+ @ini_set('default_socket_timeout', $timeout);
+
+ $ctx = null;
+ if(function_exists('stream_context_create')) {
+ $stream_options = array(
+ 'http' => array(
+ 'header' => 'User-Agent: Piwik/'.Piwik_Version::VERSION.($userAgent ? " $userAgent" : '')."\r\n"
+ .'Referer: http://'.Piwik_Common::getIpString()."/\r\n",
+ 'max_redirects' => 5, // PHP 5.1.0
+ 'timeout' => $timeout, // PHP 5.2.1
+ )
+ );
+ $ctx = stream_context_create($stream_options);
+ }
+
+ $response = @file_get_contents($aUrl, 0, $ctx);
+ $fileLength = strlen($response);
+
+ if(is_resource($file))
+ {
+ // save to file
+ fwrite($file, $response);
+ }
+
+ // restore the socket_timeout value
+ if(!empty($default_socket_timeout))
+ {
+ @ini_set('default_socket_timeout', $default_socket_timeout);
+ }
+ }
+ else if($method == 'curl')
+ {
+ $ch = @curl_init();
+
+ $curl_options = array(
+ // internal to ext/curl
+ CURLOPT_BINARYTRANSFER => is_resource($file),
+
+ // curl options (sorted oldest to newest)
+ CURLOPT_URL => $aUrl,
+ CURLOPT_REFERER => 'http://'.Piwik_Common::getIpString(),
+ CURLOPT_USERAGENT => 'Piwik/'.Piwik_Version::VERSION.($userAgent ? " $userAgent" : ''),
+ CURLOPT_HEADER => false,
+ CURLOPT_CONNECTTIMEOUT => $timeout,
+ );
+ @curl_setopt_array($ch, $curl_options);
+
+ /*
+ * as of php 5.2.0, CURLOPT_FOLLOWLOCATION can't be set if
+ * in safe_mode or open_basedir is set
+ */
+ if((string)ini_get('safe_mode') == '' && ini_get('open_basedir') == '')
+ {
+ $curl_options = array(
+ // curl options (sorted oldest to newest)
+ CURLOPT_FOLLOWLOCATION => true,
+ CURLOPT_MAXREDIRS => 5,
+ );
+ @curl_setopt_array($ch, $curl_options);
+ }
+
+ if(is_resource($file))
+ {
+ // write output directly to file
+ @curl_setopt($ch, CURLOPT_FILE, $file);
+ }
+ else
+ {
+ // internal to ext/curl
+ @curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ }
+
+ ob_start();
+ $response = @curl_exec($ch);
+ ob_end_clean();
+
+ if($response === true)
+ {
+ $response = '';
+ }
+ else if($response === false)
+ {
+ $errstr = curl_error($ch);
+ if($errstr != '')
+ {
+ throw new Exception('curl_exec: '.$errstr);
+ }
+ $response = '';
+ }
+
+ $contentLength = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
+ $fileLength = is_resource($file) ? curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD) : strlen($response);
+
+ @curl_close($ch);
+ unset($ch);
+ }
+ else
+ {
+ throw new Exception('Invalid request method: '.$method);
+ }
+
+ if(is_resource($file))
+ {
+ fflush($file);
+ @fclose($file);
+
+ $fileSize = filesize($destinationPath);
+ if((($contentLength > 0) && ($fileLength != $contentLength)) || ($fileSize != $fileLength))
+ {
+ throw new Exception('File size error: '.$destinationPath.'; expected '.$contentLength.' bytes; received '.$fileLength.' bytes; saved '.$fileSize.' bytes to file');
+ }
+ return true;
+ }
+
+ if(($contentLength > 0) && ($fileLength != $contentLength))
+ {
+ throw new Exception('Content length error: expected '.$contentLength.' bytes; received '.$fileLength.' bytes');
+ }
+ return trim($response);
+ }
+
+ /**
+ * Fetch the file at $url in the destination $pathDestination
+ * @param string $url
+ * @param string $pathDestination
+ * @param int $tries
+ * @return true on success, throws Exception on failure
+ */
+ static public function fetchRemoteFile($url, $pathDestination, $tries = 0)
+ {
+ @ignore_user_abort(true);
+ Piwik::setMaxExecutionTime(0);
+ return self::sendHttpRequest($url, 10, 'Update', $pathDestination, $tries);
+ }
+}
diff --git a/core/Log.php b/core/Log.php
index 0be03c98d0..15481b315d 100644
--- a/core/Log.php
+++ b/core/Log.php
@@ -42,7 +42,7 @@ abstract class Piwik_Log extends Zend_Log
$this->fileFormatter = $fileFormatter;
$this->screenFormatter = $screenFormatter;
- $this->logToDatabaseTableName = Piwik::prefixTable($logToDatabaseTableName);
+ $this->logToDatabaseTableName = Piwik_Common::prefixTable($logToDatabaseTableName);
$this->logToDatabaseColumnMapping = $logToDatabaseColumnMapping;
}
@@ -61,7 +61,6 @@ abstract class Piwik_Log extends Zend_Log
function addWriteToNull()
{
- Zend_Loader::loadClass('Zend_Log_Writer_Null');
$this->addWriter( new Zend_Log_Writer_Null );
}
@@ -90,7 +89,7 @@ abstract class Piwik_Log extends Zend_Log
/**
* Log an event
*/
- public function log($event, $priority)
+ public function log($event, $priority, $extras = null)
{
// sanity checks
if (empty($this->_writers)) {
@@ -139,8 +138,7 @@ class Piwik_Log_Formatter_FileFormatter implements Zend_Log_Formatter_Interface
}
$ts = $event['timestamp'];
unset($event['timestamp']);
- $str = $ts . ' ' . implode(" ", $event) . "\n";
- return $str;
+ return $ts . ' ' . implode(" ", $event) . "\n";
}
}
@@ -156,11 +154,10 @@ class Piwik_Log_Formatter_ScreenFormatter implements Zend_Log_Formatter_Interfac
// no injection in error messages, backtrace when displayed on screen
return array_map('htmlspecialchars', $event);
}
-
+
function format($string)
{
- $string = self::getFormattedString($string);
- return $string;
+ return self::getFormattedString($string);
}
static public function getFormattedString($string)
@@ -168,7 +165,17 @@ class Piwik_Log_Formatter_ScreenFormatter implements Zend_Log_Formatter_Interfac
if(Piwik_Common::isPhpCliMode())
{
$string = str_replace(array('<br>','<br />','<br/>'), "\n", $string);
- $string = strip_tags($string);
+ if(is_array($string))
+ {
+ for($i=0; $i< count($string); $i++)
+ {
+ $string[$i] = strip_tags($string[$i]);
+ }
+ }
+ else
+ {
+ $string = strip_tags($string);
+ }
}
return $string;
}
diff --git a/core/Log/APICall.php b/core/Log/APICall.php
index ae390798b4..8148c77014 100644
--- a/core/Log/APICall.php
+++ b/core/Log/APICall.php
@@ -47,7 +47,7 @@ class Piwik_Log_APICall extends Piwik_Log
$event['execution_time'] = $executionTime;
$event['returned_value'] = is_array($returnedValue) ? serialize($returnedValue) : $returnedValue;
- parent::log($event, Piwik_Log::INFO);
+ parent::log($event, Piwik_Log::INFO, null);
}
}
@@ -67,8 +67,8 @@ class Piwik_Log_APICall_Formatter_ScreenFormatter extends Piwik_Log_Formatter_Sc
*/
public function format($event)
{
- $str = "\n<br> ";
- $str .= "Called: {$event['class_name']}.{$event['method_name']} (took {$event['execution_time']}ms) \n<br>";
+ $str = "\n<br /> ";
+ $str .= "Called: {$event['class_name']}.{$event['method_name']} (took {$event['execution_time']}ms)\n<br /> ";
$str .= "Parameters: ";
$parameterNamesAndDefault = unserialize($event['parameter_names_default_values']);
$parameterValues = unserialize($event['parameter_values']);
@@ -90,10 +90,10 @@ class Piwik_Log_APICall_Formatter_ScreenFormatter extends Piwik_Log_Formatter_Sc
$i++;
}
- $str .= "\n<br> ";
+ $str .= "\n<br /> ";
// $str .= "Returned: ".$this->formatValue($event['returned_value']);
- $str .= "\n<br> ";
+ $str .= "\n<br /> ";
return parent::format($str);
}
diff --git a/core/Log/Error.php b/core/Log/Error.php
index 7c41fa91e6..a6f71ac718 100644
--- a/core/Log/Error.php
+++ b/core/Log/Error.php
@@ -51,7 +51,7 @@ class Piwik_Log_Error extends Piwik_Log
$event['errline'] = $errline;
$event['backtrace'] = $backtrace;
- parent::log($event, Piwik_Log::ERR);
+ parent::log($event, Piwik_Log::ERR, null);
}
}
@@ -106,10 +106,10 @@ class Piwik_Log_Error_Formatter_ScreenFormatter extends Piwik_Log_Formatter_Scre
default: $strReturned .= "Unknown error ($errno)"; break;
}
$strReturned .= ":</b> <i>$errstr</i> in <b>$errfile</b> on line <b>$errline</b>\n";
- $strReturned .= "<br><br>Backtrace --><DIV style='font-family:Courier;font-size:10pt'>";
- $strReturned .= str_replace("\n", "<br>\n", $backtrace);
- $strReturned .= "</div><br><br>";
- $strReturned .= "\n</pre></div><br>";
+ $strReturned .= "<br /><br />Backtrace --&gt;<div style=\"font-family:Courier;font-size:10pt\">";
+ $strReturned .= str_replace("\n", "<br />\n", $backtrace);
+ $strReturned .= "</div><br /><br />";
+ $strReturned .= "\n</pre></div><br />";
return parent::format($strReturned);
}
diff --git a/core/Log/Exception.php b/core/Log/Exception.php
index 6ae10b64cd..fe3e6ef98e 100644
--- a/core/Log/Exception.php
+++ b/core/Log/Exception.php
@@ -52,7 +52,7 @@ class Piwik_Log_Exception extends Piwik_Log
$event['errline'] = $exception->getLine();
$event['backtrace'] = $exception->getTraceAsString();
- parent::log($event, Piwik_Log::CRIT);
+ parent::log($event, Piwik_Log::CRIT, null);
}
}
@@ -80,7 +80,7 @@ class Piwik_Log_Exception_Formatter_ScreenFormatter extends Piwik_Log_Formatter_
$backtrace = $event['backtrace'] ;
$outputFormat = strtolower(Piwik_Common::getRequestVar('format', 'html', 'string'));
- $response = new Piwik_API_ResponseBuilder(null, $outputFormat);
+ $response = new Piwik_API_ResponseBuilder($outputFormat);
$message = $response->getResponseException(new Exception($errstr));
return parent::format($message);
}
diff --git a/core/Log/Message.php b/core/Log/Message.php
index 239fd1bc53..f5b1120a2e 100644
--- a/core/Log/Message.php
+++ b/core/Log/Message.php
@@ -38,7 +38,7 @@ class Piwik_Log_Message extends Piwik_Log
{
$event = array();
$event['message'] = $message;
- parent::log($event, Piwik_Log::INFO);
+ parent::log($event, Piwik_Log::INFO, null);
}
}
diff --git a/core/Nonce.php b/core/Nonce.php
new file mode 100644
index 0000000000..632ed55b07
--- /dev/null
+++ b/core/Nonce.php
@@ -0,0 +1,81 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Nonce class.
+ *
+ * A cryptographic nonce -- "number used only once" -- is often recommended as part of a robust defense against cross-site request forgery (CSRF/XSRF).
+ * Desrable characteristics: limited lifetime, uniqueness, unpredictability (pseudo-randomness).
+ *
+ * We use a session-dependent nonce with a configurable expiration that combines and hashes:
+ * - a private salt because it's non-public
+ * - time() because it's unique
+ * - a mix of PRNGs (pseudo-random number generators) to increase entropy and make it less predictable
+ *
+ * @package Piwik
+ */
+class Piwik_Nonce
+{
+ /**
+ * Generate nonce
+ *
+ * @param string $id Unique id to avoid namespace conflicts, e.g., ModuleName.ActionName
+ * @param int $ttl Optional time-to-live in seconds; default is 5 minutes
+ * @return string Nonce
+ */
+ static public function getNonce($id, $ttl = 300)
+ {
+ // save session-dependent nonce
+ $ns = new Zend_Session_Namespace($id);
+ $nonce = $ns->nonce;
+
+ // re-use an unexpired nonce (a small deviation from the "used only once" principle, so long as we do not reset the expiration)
+ // to handle browser pre-fetch or double fetch caused by some browser add-ons/extensions
+ if(empty($nonce))
+ {
+ // generate a new nonce
+ $nonce = md5(Piwik_Common::getSalt() . time() . Piwik_Common::generateUniqId());
+ $ns->nonce = $nonce;
+ $ns->setExpirationSeconds($ttl, 'nonce');
+ }
+
+ return $nonce;
+ }
+
+ /**
+ * Verify nonce and check referrer (if present, i.e., it may be suppressed by the browser or a proxy/network).
+ *
+ * @param string $id Unique id
+ * @param string $cnonce Nonce sent to client
+ * @return bool true if valid; false otherwise
+ */
+ static public function verifyNonce($id, $cnonce)
+ {
+ $ns = new Zend_Session_Namespace($id);
+ $nonce = $ns->nonce;
+
+ // validate token
+ if(empty($cnonce) || $cnonce !== $nonce)
+ {
+ return false;
+ }
+
+ // validate referer
+ $referer = Piwik_Url::getReferer();
+ if(!empty($referer) && (Piwik_Url::getLocalReferer() === false))
+ {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/core/Option.php b/core/Option.php
index da1905dc82..75244c7f3a 100644
--- a/core/Option.php
+++ b/core/Option.php
@@ -54,7 +54,7 @@ class Piwik_Option
return $this->all[$name];
}
$value = Piwik_FetchOne( 'SELECT option_value
- FROM `' . Piwik::prefixTable('option') . '`
+ FROM `' . Piwik_Common::prefixTable('option') . '`
WHERE option_name = ?', $name);
if($value === false)
{
@@ -74,7 +74,7 @@ class Piwik_Option
public function set($name, $value, $autoload = 0)
{
$autoload = (int)$autoload;
- Piwik_Query('INSERT INTO `'. Piwik::prefixTable('option') . '` (option_name, option_value, autoload) '.
+ Piwik_Query('INSERT INTO `'. Piwik_Common::prefixTable('option') . '` (option_name, option_value, autoload) '.
' VALUES (?, ?, ?) '.
' ON DUPLICATE KEY UPDATE option_value = ?',
array($name, $value, $autoload, $value));
@@ -89,7 +89,7 @@ class Piwik_Option
return;
}
$all = Piwik_FetchAll('SELECT option_value, option_name
- FROM `'. Piwik::prefixTable('option') . '`
+ FROM `'. Piwik_Common::prefixTable('option') . '`
WHERE autoload = 1');
foreach($all as $option)
{
@@ -97,6 +97,17 @@ class Piwik_Option
}
$loaded = true;
}
+
+ /**
+ * Clears the cache
+ * Used in unit tests to reset the state of the object between tests
+ *
+ * @return void
+ */
+ public function clearCache()
+ {
+ $this->all = array();
+ }
}
function Piwik_GetOption($name)
diff --git a/core/Period.php b/core/Period.php
index 7fd59b84e8..4e5e6e37bb 100644
--- a/core/Period.php
+++ b/core/Period.php
@@ -30,8 +30,7 @@ abstract class Piwik_Period
protected $subperiodsProcessed = false;
protected $label = null;
protected $date = null;
-
- protected static $unknowPeriodException = "The period '%s' is not supported. Try 'day' or 'week' or 'month' or 'year'";
+ static protected $errorAvailablePeriods = 'day, week, month, year';
public function __construct( $date )
{
@@ -44,7 +43,7 @@ abstract class Piwik_Period
* @param $date Piwik_Date object
* @return Piwik_Period
*/
- static public function factory($strPeriod, $date)
+ static public function factory($strPeriod, Piwik_Date $date)
{
switch ($strPeriod) {
case 'day':
@@ -64,11 +63,12 @@ abstract class Piwik_Period
break;
default:
- throw new Exception(sprintf(self::$unknowPeriodException, $strPeriod));
+ throw new Exception(Piwik_TranslateException('General_ExceptionInvalidPeriod', array($strPeriod, self::$errorAvailablePeriods)));
break;
}
}
+
/**
* Returns the first day of the period
*
@@ -186,25 +186,6 @@ abstract class Piwik_Period
$this->subperiods[] = $date;
}
- /**
- * A period is finished if all the subperiods are finished
- */
- public function isFinished()
- {
- if(!$this->subperiodsProcessed)
- {
- $this->generate();
- }
- foreach($this->subperiods as $period)
- {
- if(!$period->isFinished())
- {
- return false;
- }
- }
- return true;
- }
-
public function toString()
{
if(!$this->subperiodsProcessed)
@@ -221,8 +202,7 @@ abstract class Piwik_Period
public function __toString()
{
- $elements = $this->toString();
- return implode(",", $elements);
+ return implode(",", $this->toString());
}
public function get( $part= null )
@@ -231,7 +211,7 @@ abstract class Piwik_Period
{
$this->generate();
}
- return $this->date->get($part);
+ return $this->date->toString($part);
}
abstract public function getPrettyString();
diff --git a/core/Period/Day.php b/core/Period/Day.php
index 32686a0f51..a5eda257ed 100644
--- a/core/Period/Day.php
+++ b/core/Period/Day.php
@@ -41,15 +41,6 @@ class Piwik_Period_Day extends Piwik_Period
return $out;
}
- public function isFinished()
- {
- $todayMidnight = Piwik_Date::today();
- if($this->date->isEarlier($todayMidnight))
- {
- return true;
- }
- }
-
public function getNumberOfSubperiods()
{
return 0;
diff --git a/core/Period/Month.php b/core/Period/Month.php
index 40fda847ca..1918ec3650 100644
--- a/core/Period/Month.php
+++ b/core/Period/Month.php
@@ -55,18 +55,4 @@ class Piwik_Period_Month extends Piwik_Period
$currentDay = $currentDay->addDay(1);
}
}
-
- public function isFinished()
- {
- if(!$this->subperiodsProcessed)
- {
- $this->generate();
- }
- // a month is finished
- // if current month > month AND current year == year
- // OR if current year > year
- $year = $this->date->get("Y");
- return ( date("m") > $this->date->get("m") && date("Y") == $year)
- || date("Y") > $year;
- }
}
diff --git a/core/Period/Range.php b/core/Period/Range.php
index ba30cb9f36..2f1b33bdad 100644
--- a/core/Period/Range.php
+++ b/core/Period/Range.php
@@ -18,11 +18,12 @@
*/
class Piwik_Period_Range extends Piwik_Period
{
- public function __construct( $strPeriod, $strDate )
+ public function __construct( $strPeriod, $strDate, $timezone = 'UTC' )
{
$this->strPeriod = $strPeriod;
$this->strDate = $strDate;
$this->defaultEndDate = null;
+ $this->timezone = $timezone;
}
public function getLocalizedShortString()
{
@@ -71,10 +72,6 @@ class Piwik_Period_Range extends Piwik_Period
case 'year':
$startDate = $date->subMonth( 12 * $n );
break;
-
- default:
- throw new Exception(sprintf(self::$unknowPeriodException, $this->strPeriod));
- break;
}
return $startDate;
}
@@ -125,7 +122,7 @@ class Piwik_Period_Range extends Piwik_Period
}
else
{
- $defaultEndDate = Piwik_Date::today();
+ $defaultEndDate = Piwik_Date::factory('now', $this->timezone);
}
if($lastOrPrevious == 'last')
{
@@ -154,7 +151,7 @@ class Piwik_Period_Range extends Piwik_Period
}
else
{
- throw new Exception("The date '$this->strDate' is not a date range. Should have the following format: 'lastN' or 'previousN' or 'YYYY-MM-DD,YYYY-MM-DD'.");
+ throw new Exception(Piwik_TranslateException('General_ExceptionInvalidDateRange', array($this->strDate, ' \'lastN\', \'previousN\', \'YYYY-MM-DD,YYYY-MM-DD\'')));
}
$endSubperiod = Piwik_Period::factory($this->strPeriod, $endDate);
diff --git a/core/Period/Year.php b/core/Period/Year.php
index 7e04b8c898..19500be9ed 100644
--- a/core/Period/Year.php
+++ b/core/Period/Year.php
@@ -43,7 +43,7 @@ class Piwik_Period_Year extends Piwik_Period
}
parent::generate();
- $year = $this->date->get("Y");
+ $year = $this->date->toString("Y");
for($i=1; $i<=12; $i++)
{
$this->addSubperiod( new Piwik_Period_Month(
diff --git a/core/Piwik.php b/core/Piwik.php
index af7c5f083c..67fd9a24c4 100644
--- a/core/Piwik.php
+++ b/core/Piwik.php
@@ -10,69 +10,279 @@
* @package Piwik
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see core/Translate.php
*/
require_once PIWIK_INCLUDE_PATH . '/core/Translate.php';
/**
+ * @see mysqli_set_charset
+ * @see parse_ini_file
+ */
+require_once PIWIK_INCLUDE_PATH . '/libs/upgradephp/common.php';
+
+/**
* Main piwik helper class.
* Contains static functions you can call from the plugins.
- *
+ *
* @package Piwik
*/
class Piwik
{
const CLASSES_PREFIX = "Piwik_";
-
+
public static $idPeriods = array(
'day' => 1,
'week' => 2,
'month' => 3,
'year' => 4,
);
-
+
+/*
+ * Prefix/unprefix class name
+ */
+
+ /**
+ * Prefix class name (if needed)
+ *
+ * @param string $class
+ * @return string
+ */
+ static public function prefixClass( $class )
+ {
+ if(substr_count($class, Piwik::CLASSES_PREFIX) > 0)
+ {
+ return $class;
+ }
+ return Piwik::CLASSES_PREFIX.$class;
+ }
+
+ /**
+ * Unprefix class name (if needed)
+ *
+ * @param string $class
+ * @return string
+ */
+ static public function unprefixClass( $class )
+ {
+ $lenPrefix = strlen(Piwik::CLASSES_PREFIX);
+ if(substr($class, 0, $lenPrefix) == Piwik::CLASSES_PREFIX)
+ {
+ return substr($class, $lenPrefix);
+ }
+ return $class;
+ }
+
+/*
+ * Installation / Uninstallation
+ */
+
+ /**
+ * Installation helper
+ */
+ static public function install()
+ {
+ Piwik_Common::mkdir(Zend_Registry::get('config')->smarty->compile_dir);
+ }
+
+ /**
+ * Uninstallation helper
+ */
+ static public function uninstall()
+ {
+ Piwik_Db_Schema::getInstance()->dropTables();
+ }
+
+ /**
+ * Returns true if Piwik is installed
+ *
+ * @since 0.6.3
+ *
+ * @return bool True if installed; false otherwise
+ */
+ static public function isInstalled()
+ {
+ return Piwik_Db_Schema::getInstance()->hasTables();
+ }
+
+/*
+ * File and directory operations
+ */
+
+ /**
+ * Copy recursively from $source to $target.
+ *
+ * @param string $source eg. './tmp/latest'
+ * @param string $target eg. '.'
+ * @param bool $excludePhp
+ */
+ static public function copyRecursive($source, $target, $excludePhp=false )
+ {
+ if ( is_dir( $source ) )
+ {
+ @mkdir( $target );
+ $d = dir( $source );
+ while ( false !== ( $entry = $d->read() ) )
+ {
+ if ( $entry == '.' || $entry == '..' )
+ {
+ continue;
+ }
+
+ $sourcePath = $source . '/' . $entry;
+ if ( is_dir( $sourcePath ) )
+ {
+ self::copyRecursive( $sourcePath, $target . '/' . $entry, $excludePhp );
+ continue;
+ }
+ $destPath = $target . '/' . $entry;
+ self::copy($sourcePath, $destPath, $excludePhp);
+ }
+ $d->close();
+ }
+ else
+ {
+ self::copy($source, $target, $excludePhp);
+ }
+ }
+
+ /**
+ * Copy individual file from $source to $target.
+ *
+ * @param string $source eg. './tmp/latest/index.php'
+ * @param string $target eg. './index.php'
+ * @param bool $excludePhp
+ * @return bool
+ */
+ static public function copy($source, $dest, $excludePhp=false)
+ {
+ static $phpExtensions = array('php', 'tpl');
+
+ if($excludePhp)
+ {
+ $path_parts = pathinfo($source);
+ if(in_array($path_parts['extension'], $phpExtensions))
+ {
+ return true;
+ }
+ }
+
+ if(!@copy( $source, $dest ))
+ {
+ @chmod($dest, 0755);
+ if(!@copy( $source, $dest ))
+ {
+ throw new Exception("
+ Error while copying file to <code>$dest</code>. <br />
+ Please check that the web server has enough permission to overwrite this file. <br />
+ For example, on a linux server, if your apache user is www-data you can try to execute:<br />
+ <code>chown -R www-data:www-data ".Piwik_Common::getPathToPiwikRoot()."</code><br />
+ <code>chmod -R 0755 ".Piwik_Common::getPathToPiwikRoot()."</code><br />
+ ");
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Recursively delete a directory
+ *
+ * @param string $dir Directory name
+ * @param boolean $deleteRootToo Delete specified top-level directory as well
+ */
+ static public function unlinkRecursive($dir, $deleteRootToo)
+ {
+ if(!$dh = @opendir($dir))
+ {
+ return;
+ }
+ while (false !== ($obj = readdir($dh)))
+ {
+ if($obj == '.' || $obj == '..')
+ {
+ continue;
+ }
+
+ if (!@unlink($dir . '/' . $obj))
+ {
+ self::unlinkRecursive($dir.'/'.$obj, true);
+ }
+ }
+ closedir($dh);
+ if ($deleteRootToo)
+ {
+ @rmdir($dir);
+ }
+ return;
+ }
+
+ /**
+ * Recursively find pathnames that match a pattern
+ * @see glob()
+ *
+ * @param string $sDir directory
+ * @param string $sPattern pattern
+ * @param int $nFlags glob() flags
+ * @return array
+ */
+ public static function globr($sDir, $sPattern, $nFlags = NULL)
+ {
+ if(($aFiles = glob("$sDir/$sPattern", $nFlags)) == false)
+ {
+ $aFiles = array();
+ }
+ if(($aDirs = glob("$sDir/*", GLOB_ONLYDIR)) != false)
+ {
+ foreach ($aDirs as $sSubDir)
+ {
+ $aSubFiles = self::globr($sSubDir, $sPattern, $nFlags);
+ $aFiles = array_merge($aFiles, $aSubFiles);
+ }
+ }
+ return $aFiles;
+ }
+
/**
* Checks that the directories Piwik needs write access are actually writable
* Displays a nice error page if permissions are missing on some directories
+ *
+ * @param array $directoriesToCheck Array of directory names to check
*/
static public function checkDirectoriesWritableOrDie( $directoriesToCheck = null )
{
$resultCheck = Piwik::checkDirectoriesWritable( $directoriesToCheck );
- if( array_search(false, $resultCheck) !== false )
- {
- $directoryList = '';
- foreach($resultCheck as $dir => $bool)
+ if( array_search(false, $resultCheck) === false )
+ {
+ return;
+ }
+ $directoryList = '';
+ foreach($resultCheck as $dir => $bool)
+ {
+ $realpath = Piwik_Common::realpath($dir);
+ if(!empty($realpath) && $bool === false)
{
- $realpath = Piwik_Common::realpath($dir);
- if(!empty($realpath) && $bool === false)
- {
- $directoryList .= "<code>chmod 777 $realpath</code><br>";
- }
+ $directoryList .= "<code>chmod 777 $realpath</code><br />";
}
- $directoryList .= '';
- $directoryMessage = "<p><b>Piwik couldn't write to some directories</b>.</p> <p>Try to Execute the following commands on your Linux server:</P>";
- $directoryMessage .= $directoryList;
- $directoryMessage .= "<p>If this doesn't work, you can try to create the directories with your FTP software, and set the CHMOD to 777 (with your FTP software, right click on the directories, permissions).";
- $directoryMessage .= "<p>After applying the modifications, you can <a href='index.php'>refresh the page</a>.";
- $directoryMessage .= "<p>If you need more help, try <a href='misc/redirectToUrl.php?url=http://piwik.org'>Piwik.org</a>.";
-
- Piwik_ExitWithMessage($directoryMessage, false, true);
}
+ $directoryList .= '';
+ $directoryMessage = "<p><b>Piwik couldn't write to some directories</b>.</p> <p>Try to Execute the following commands on your Linux server:</P>";
+ $directoryMessage .= $directoryList;
+ $directoryMessage .= "<p>If this doesn't work, you can try to create the directories with your FTP software, and set the CHMOD to 777 (with your FTP software, right click on the directories, permissions).";
+ $directoryMessage .= "<p>After applying the modifications, you can <a href='index.php'>refresh the page</a>.";
+ $directoryMessage .= "<p>If you need more help, try <a href='misc/redirectToUrl.php?url=http://piwik.org'>Piwik.org</a>.";
+
+ Piwik_ExitWithMessage($directoryMessage, false, true);
}
-
+
/**
* Checks if directories are writable and create them if they do not exist.
- *
+ *
* @param array $directoriesToCheck array of directories to check - if not given default Piwik directories that needs write permission are checked
* @return array direcory name => true|false (is writable)
*/
static public function checkDirectoriesWritable($directoriesToCheck = null)
{
- if( $directoriesToCheck == null )
+ if( $directoriesToCheck == null )
{
$directoriesToCheck = array(
'/config',
@@ -80,9 +290,9 @@ class Piwik
'/tmp/templates_c',
'/tmp/cache',
'/tmp/latest',
- );
+ );
}
-
+
$resultCheck = array();
foreach($directoriesToCheck as $directoryToCheck)
{
@@ -90,12 +300,12 @@ class Piwik
{
$directoryToCheck = PIWIK_USER_PATH . $directoryToCheck;
}
-
+
if(!file_exists($directoryToCheck))
{
Piwik_Common::mkdir($directoryToCheck, 0755, false);
}
-
+
$directory = Piwik_Common::realpath($directoryToCheck);
$resultCheck[$directory] = false;
if($directory !== false // realpath() returns FALSE on failure
@@ -106,29 +316,168 @@ class Piwik
}
return $resultCheck;
}
-
+
/**
- * Returns the Javascript code to be inserted on every page to track
+ * Generate .htaccess files at runtime to avoid permission problems.
+ */
+ static public function createHtAccessFiles()
+ {
+ // deny access to these folders
+ $directoriesToProtect = array(
+ '/config',
+ '/core',
+ '/lang',
+ );
+ foreach($directoriesToProtect as $directoryToProtect)
+ {
+ Piwik_Common::createHtAccess(PIWIK_INCLUDE_PATH . $directoryToProtect);
+ }
+
+ // more selective allow/deny filters
+ $allowAny = "<Files \"*\">\nAllow from all\nSatisfy any\n</Files>\n";
+ $allowStaticAssets = "<Files ~ \"\\.(test\.php|gif|ico|jpg|png|js|css|swf)$\">\nSatisfy any\nAllow from all\n</Files>\n";
+ $denyDirectPhp = "<Files ~ \"\\.(php|php4|php5|inc|tpl)$\">\nDeny from all\n</Files>\n";
+ $directoriesToProtect = array(
+ '/js' => $allowAny,
+ '/libs' => $denyDirectPhp . $allowStaticAssets,
+ '/plugins' => $denyDirectPhp . $allowStaticAssets,
+ '/themes' => $denyDirectPhp . $allowStaticAssets,
+ );
+ foreach($directoriesToProtect as $directoryToProtect => $content)
+ {
+ Piwik_Common::createHtAccess(PIWIK_INCLUDE_PATH . $directoryToProtect, $content);
+ }
+ }
+
+ /**
+ * Generate web.config files at runtime
*
- * @param int $idSite
- * @param string $piwikUrl http://path/to/piwik/directory/
- * @param string $actionName
- * @return string
+ * Note: for IIS 7 and above
*/
- static public function getJavascriptCode($idSite, $piwikUrl, $actionName = "''")
- {
- $jsTag = file_get_contents( PIWIK_INCLUDE_PATH . "/core/Tracker/javascriptTag.tpl");
- $jsTag = nl2br(htmlentities($jsTag));
- $piwikUrl = preg_match('~^(http|https)://(.*)$~', $piwikUrl, $matches);
- $piwikUrl = $matches[2];
- $jsTag = str_replace('{$actionName}', $actionName, $jsTag);
- $jsTag = str_replace('{$idSite}', $idSite, $jsTag);
- $jsTag = str_replace('{$piwikUrl}', $piwikUrl, $jsTag);
- $jsTag = str_replace('{$hrefTitle}', Piwik::getRandomTitle(), $jsTag);
- return $jsTag;
+ static public function createWebConfigFiles()
+ {
+ @file_put_contents(PIWIK_INCLUDE_PATH . '/web.config',
+'<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <system.webServer>
+ <security>
+ <requestFiltering>
+ <hiddenSegments>
+ <add segment="config" />
+ <add segment="core" />
+ <add segment="lang" />
+ </hiddenSegments>
+ <fileExtensions>
+ <add fileExtension=".tpl" allowed="false" />
+ </fileExtensions>
+ </requestFiltering>
+ </security>
+ <directoryBrowse enabled="false" />
+ <defaultDocument>
+ <files>
+ <remove value="index.php" />
+ <add value="index.php" />
+ </files>
+ </defaultDocument>
+ </system.webServer>
+</configuration>');
+
+ // deny direct access to .php files
+ $directoriesToProtect = array(
+ '/libs',
+ '/plugins',
+ );
+ foreach($directoriesToProtect as $directoryToProtect)
+ {
+ @file_put_contents(PIWIK_INCLUDE_PATH . $directoryToProtect . '/web.config',
+'<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <system.webServer>
+ <security>
+ <requestFiltering>
+ <denyUrlSequences>
+ <add sequence=".php" />
+ </denyUrlSequences>
+ </requestFiltering>
+ </security>
+ </system.webServer>
+</configuration>');
+ }
}
/**
+ * Get file integrity information (in PIWIK_INCLUDE_PATH).
+ *
+ * @return array(bool, string, ...) Return code (true/false), followed by zero or more error messages
+ */
+ static public function getFileIntegrityInformation()
+ {
+ $exclude = array(
+ 'robots.txt',
+ );
+ $messages = array();
+ $messages[] = true;
+
+ // ignore dev environments
+ if(file_exists(PIWIK_INCLUDE_PATH . '/.svn'))
+ {
+ $messages[] = Piwik_Translate('General_WarningFileIntegritySkipped');
+ return $messages;
+ }
+
+ $manifest = PIWIK_INCLUDE_PATH . '/config/manifest.inc.php';
+ if(!file_exists($manifest))
+ {
+ $messages[] = Piwik_Translate('General_WarningFileIntegrityNoManifest');
+ return $messages;
+ }
+
+ require_once $manifest;
+
+ $files = Manifest::$files;
+
+ $hasMd5file = function_exists('md5_file');
+ foreach($files as $path => $props)
+ {
+ if(in_array($path, $exclude))
+ {
+ continue;
+ }
+
+ $file = PIWIK_INCLUDE_PATH . '/' . $path;
+
+ if(!file_exists($file))
+ {
+ $messages[] = Piwik_Translate('General_ExceptionMissingFile', $file);
+ }
+ else if(filesize($file) != $props[0])
+ {
+ $messages[] = Piwik_Translate('General_ExceptionFilesizeMismatch', array($file, $props[0], filesize($file)));
+ }
+ else if($hasMd5file && (@md5_file($file) !== $props[1]))
+ {
+ $messages[] = Piwik_Translate('General_ExceptionFileIntegrity', $file);
+ }
+ }
+
+ if(count($messages) > 1)
+ {
+ $messages[0] = false;
+ }
+
+ if(!$hasMd5file)
+ {
+ $messages[] = Piwik_Translate('General_WarningFileIntegrityNoMd5file');
+ }
+
+ return $messages;
+ }
+
+/*
+ * PHP environment settings
+ */
+
+ /**
* Set maximum script execution time.
*
* @param int max execution time in seconds (0 = no limit)
@@ -140,15 +489,46 @@ class Piwik
@set_time_limit($executionTime);
}
+ /**
+ * Get php memory_limit
+ *
+ * Prior to PHP 5.2.1, or on Windows, --enable-memory-limit is not a
+ * compile-time default, so ini_get('memory_limit') may return false.
+ *
+ * @see http://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
+ * @return int memory limit in megabytes
+ */
static public function getMemoryLimitValue()
{
if($memory = ini_get('memory_limit'))
{
- return substr($memory, 0, strlen($memory) - 1);
+ // handle shorthand byte options (case-insensitive)
+ $shorthandByteOption = substr($memory, -1);
+ switch($shorthandByteOption)
+ {
+ case 'G':
+ case 'g':
+ return substr($memory, 0, -1) * 1024;
+ case 'M':
+ case 'm':
+ return substr($memory, 0, -1);
+ case 'K':
+ case 'k':
+ return substr($memory, 0, -1) / 1024;
+ }
+ return $memory / 1048576;
}
return false;
}
-
+
+ /**
+ * Set PHP memory limit
+ *
+ * Note: system settings may prevent scripts from overriding the master value
+ *
+ * @param int $minimumMemoryLimit
+ * @return bool true if set; false otherwise
+ */
static public function setMemoryLimit($minimumMemoryLimit)
{
$currentValue = self::getMemoryLimitValue();
@@ -160,7 +540,12 @@ class Piwik
}
return false;
}
-
+
+ /**
+ * Raise PHP memory limit if below the minimum required
+ *
+ * @return bool true if set; false otherwise
+ */
static public function raiseMemoryLimitIfNecessary()
{
$minimumMemoryLimit = Zend_Registry::get('config')->General->minimum_memory_limit;
@@ -170,22 +555,25 @@ class Piwik
{
return self::setMemoryLimit($minimumMemoryLimit);
}
-
+
return false;
}
-
+
+/*
+ * Logging and error handling
+ */
+
static public function log($message = '')
{
Zend_Registry::get('logger_message')->logEvent($message);
- Zend_Registry::get('logger_message')->logEvent( "<br>" . PHP_EOL);
+ Zend_Registry::get('logger_message')->logEvent( "<br />" . PHP_EOL);
}
-
-
+
static public function error($message = '')
{
trigger_error($message, E_USER_ERROR);
}
-
+
/**
* Display the message in a nice red font with a nice icon
* ... and dies
@@ -194,46 +582,54 @@ class Piwik
{
$output = "<style>a{color:red;}</style>\n".
"<div style='color:red;font-family:Georgia;font-size:120%'>".
- "<p><img src='themes/default/images/error_medium.png' style='vertical-align:middle; float:left;padding:20 20 20 20'>".
+ "<p><img src='themes/default/images/error_medium.png' style='vertical-align:middle; float:left;padding:20 20 20 20' />".
$message.
"</p></div>";
print(Piwik_Log_Formatter_ScreenFormatter::getFormattedString($output));
exit;
}
-
+
+/*
+ * Profiling
+ */
+
/**
- * Computes the division of i1 by i2. If either i1 or i2 are not number, or if i2 has a value of zero
- * we return 0 to avoid the division by zero.
+ * Get total number of queries
*
- * @param numeric $i1
- * @param numeric $i2
- * @return numeric The result of the division or zero
+ * @return int number of queries
*/
- static public function secureDiv( $i1, $i2 )
- {
- if ( is_numeric($i1) && is_numeric($i2) && floatval($i2) != 0)
- {
- return $i1 / $i2;
- }
- return 0;
- }
static public function getQueryCount()
{
$profiler = Zend_Registry::get('db')->getProfiler();
return $profiler->getTotalNumQueries();
}
+
+ /**
+ * Get total elapsed time (in seconds)
+ *
+ * @return int elapsed time
+ */
static public function getDbElapsedSecs()
{
$profiler = Zend_Registry::get('db')->getProfiler();
return $profiler->getTotalElapsedSecs();
}
+
+ /**
+ * Print number of queries and elapsed time
+ */
static public function printQueryCount()
{
$totalTime = self::getDbElapsedSecs();
$queryCount = self::getQueryCount();
Piwik::log("Total queries = $queryCount (total sql time = ".round($totalTime,2)."s)");
}
-
+
+ /**
+ * Print profiling report for the tracker
+ *
+ * @param Piwik_Tracker_Db $db Tracker database object (or null)
+ */
static public function printSqlProfilingReportTracker( $db = null )
{
if(!function_exists('maxSumMsFirst'))
@@ -243,20 +639,20 @@ class Piwik
return $a['sum_time_ms'] < $b['sum_time_ms'];
}
}
-
+
if(is_null($db))
{
$db = Piwik_Tracker::getDatabase();
}
$tableName = Piwik_Common::prefixTable('log_profiling');
-
+
$all = $db->fetchAll('SELECT * FROM '.$tableName );
- if($all === false)
+ if($all === false)
{
return;
}
uasort($all, 'maxSumMsFirst');
-
+
$infoIndexedByQuery = array();
foreach($all as $infoQuery)
{
@@ -264,24 +660,23 @@ class Piwik
$count = $infoQuery['count'];
$sum_time_ms = $infoQuery['sum_time_ms'];
$infoIndexedByQuery[$query] = array('count' => $count, 'sumTimeMs' => $sum_time_ms);
- }
+ }
Piwik::getSqlProfilingQueryBreakdownOutput($infoIndexedByQuery);
}
/**
- * Outputs SQL Profiling reports
+ * Outputs SQL Profiling reports
* It is automatically called when enabling the SQL profiling in the config file enable_sql_profiler
- *
*/
static function printSqlProfilingReportZend()
{
$profiler = Zend_Registry::get('db')->getProfiler();
-
+
if(!$profiler->getEnabled())
{
throw new Exception("To display the profiler you should enable enable_sql_profiler on your config/config.ini.php file");
}
-
+
$infoIndexedByQuery = array();
foreach($profiler->getQueryProfiles() as $query)
{
@@ -306,9 +701,9 @@ class Piwik
}
}
uasort( $infoIndexedByQuery, 'sortTimeDesc');
-
- Piwik::log('<hr><b>SQL Profiler</b>');
- Piwik::log('<hr><b>Summary</b>');
+
+ Piwik::log('<hr /><b>SQL Profiler</b>');
+ Piwik::log('<hr /><b>Summary</b>');
$totalTime = $profiler->getTotalElapsedSecs();
$queryCount = $profiler->getTotalNumQueries();
$longestTime = 0;
@@ -321,44 +716,63 @@ class Piwik
}
$str = 'Executed ' . $queryCount . ' queries in ' . round($totalTime,3) . ' seconds' . "\n";
$str .= '(Average query length: ' . round($totalTime / $queryCount,3) . ' seconds)' . "\n";
- $str .= '<br>Queries per second: ' . round($queryCount / $totalTime,1) . "\n";
- $str .= '<br>Longest query length: ' . round($longestTime,3) . " seconds (<code>$longestQuery</code>) \n";
+ $str .= '<br />Queries per second: ' . round($queryCount / $totalTime,1) . "\n";
+ $str .= '<br />Longest query length: ' . round($longestTime,3) . " seconds (<code>$longestQuery</code>) \n";
Piwik::log($str);
Piwik::getSqlProfilingQueryBreakdownOutput($infoIndexedByQuery);
}
-
+
+ /**
+ * Log a breakdown by query
+ *
+ * @param array $infoIndexedByQuery
+ */
static private function getSqlProfilingQueryBreakdownOutput( $infoIndexedByQuery )
{
- Piwik::log('<hr><b>Breakdown by query</b>');
+ Piwik::log('<hr /><b>Breakdown by query</b>');
$output = '';
- foreach($infoIndexedByQuery as $query => $queryInfo)
+ foreach($infoIndexedByQuery as $query => $queryInfo)
{
$timeMs = round($queryInfo['sumTimeMs'],1);
$count = $queryInfo['count'];
$avgTimeString = '';
- if($count > 1)
+ if($count > 1)
{
$avgTimeMs = $timeMs / $count;
- $avgTimeString = " (average = <b>". round($avgTimeMs,1) . "ms</b>)";
+ $avgTimeString = " (average = <b>". round($avgTimeMs,1) . "ms</b>)";
}
$query = preg_replace('/([\t\n\r ]+)/', ' ', $query);
$output .= "Executed <b>$count</b> time". ($count==1?'':'s') ." in <b>".$timeMs."ms</b> $avgTimeString <pre>\t$query</pre>";
}
Piwik::log($output);
}
-
+
+ /**
+ * Print timer
+ */
static public function printTimer()
{
echo Zend_Registry::get('timer');
}
- static public function printMemoryLeak($prefix = '', $suffix = '<br>')
+ /**
+ * Print memory leak
+ *
+ * @param string $prefix
+ * @param string $suffix
+ */
+ static public function printMemoryLeak($prefix = '', $suffix = '<br />')
{
echo $prefix;
echo Zend_Registry::get('timer')->getMemoryLeak();
echo $suffix;
}
-
+
+ /**
+ * Print memory usage
+ *
+ * @param string $prefixString
+ */
static public function printMemoryUsage( $prefixString = null )
{
$memory = false;
@@ -370,7 +784,7 @@ class Piwik
{
$memory = memory_get_usage();
}
-
+
if($memory !== false)
{
$usage = round( $memory / 1024 / 1024, 2);
@@ -385,385 +799,220 @@ class Piwik
Piwik::log("Memory usage function not found.");
}
}
-
- static public function getPrettySizeFromBytes($size)
+
+/*
+ * Amounts, Percentages, Currency, Time, Math Operations, and Pretty Printing
+ */
+
+ /**
+ * Computes the division of i1 by i2. If either i1 or i2 are not number, or if i2 has a value of zero
+ * we return 0 to avoid the division by zero.
+ *
+ * @param numeric $i1
+ * @param numeric $i2
+ * @return numeric The result of the division or zero
+ */
+ static public function secureDiv( $i1, $i2 )
{
- $bytes = array('','K','M','G','T');
- foreach($bytes as $val)
+ if ( is_numeric($i1) && is_numeric($i2) && floatval($i2) != 0)
{
- if($size > 1024)
- {
- $size = $size / 1024;
- }
- else
- {
- break;
- }
+ return $i1 / $i2;
}
- return round($size, 1)." ".$val;
+ return 0;
}
/**
- * Returns true if PHP was invoked as CGI or command-line interface (shell)
+ * Safely compute a percentage. Return 0 to avoid division by zero.
*
- * @deprecated deprecated in 0.4.4
- * @see Piwik_Common::isPhpCliMode()
- * @return bool true if PHP invoked as a CGI or from CLI
+ * @param numeric $dividend
+ * @param numeric $divisor
+ * @param int $precision
+ * @return numeric
*/
- static public function isPhpCliMode()
+ static public function getPercentageSafe($dividend, $divisor, $precision = 0)
{
- return Piwik_Common::isPhpCliMode();
+ if($divisor == 0)
+ {
+ return 0;
+ }
+ return round(100 * $dividend / $divisor, $precision);
}
-
- static public function getCurrency()
+
+ /**
+ * Get currency symbol for a site
+ *
+ * @param int $idSite
+ * @return string
+ */
+ static public function getCurrency($idSite)
{
- static $symbol = null;
- if(is_null($symbol))
+ static $symbols = null;
+ if(is_null($symbols))
{
- $symbol = trim(Zend_Registry::get('config')->General->default_currency);
+ $symbols = Piwik_SitesManager_API::getInstance()->getCurrencySymbols();
}
- return $symbol;
+ $site = new Piwik_Site($idSite);
+ return $symbols[$site->getCurrency()];
}
- static public function getPrettyMoney($value)
+ /**
+ * Pretty format monetary value for a site
+ *
+ * @param numeric $value
+ * @param int $idSite
+ * @return string
+ */
+ static public function getPrettyMoney($value, $idSite)
{
- $symbol = self::getCurrency();
- return sprintf("$symbol%.2f", $value);
+ $currencyBefore = self::getCurrency($idSite);
+ $currencyAfter = '';
+
+ // manually put the currency symbol after the amount for euro
+ // (maybe more currencies prefer this notation?)
+ if(in_array($currencyBefore,array('€')))
+ {
+ $currencyAfter = '&nbsp;'.$currencyBefore;
+ $currencyBefore = '';
+ }
+ return sprintf("$currencyBefore&nbsp;%s$currencyAfter", $value);
}
-
- static public function getPercentageSafe($dividend, $divisor, $precision = 0)
+
+ /**
+ * Pretty format a memory size value
+ *
+ * @param numeric $size in bytes
+ * @return string
+ */
+ static public function getPrettySizeFromBytes($size)
{
- if($divisor == 0)
+ $bytes = array('','K','M','G','T');
+ foreach($bytes as $val)
{
- return 0;
+ if($size > 1024)
+ {
+ $size = $size / 1024;
+ }
+ else
+ {
+ break;
+ }
}
- return round(100 * $dividend / $divisor, $precision);
+ return round($size, 1)." ".$val;
}
-
+
+ /**
+ * Pretty format a time
+ *
+ * @param numeric $numberOfSeconds
+ * @return string
+ */
static public function getPrettyTimeFromSeconds($numberOfSeconds)
{
$numberOfSeconds = (double)$numberOfSeconds;
$days = floor($numberOfSeconds / 86400);
-
+
$minusDays = $numberOfSeconds - $days * 86400;
$hours = floor($minusDays / 3600);
-
+
$minusDaysAndHours = $minusDays - $hours * 3600;
$minutes = floor($minusDaysAndHours / 60 );
-
+
$seconds = $minusDaysAndHours - $minutes * 60;
-
+
if($days > 0)
{
- return sprintf("%d days %d hours", $days, $hours);
+ $return = sprintf(Piwik_Translate('General_DaysHours'), $days, $hours);
}
elseif($hours > 0)
{
- return sprintf("%d hours %d min", $hours, $minutes);
+ $return = sprintf(Piwik_Translate('General_HoursMinutes'), $hours, $minutes);
}
elseif($minutes > 0)
{
- return sprintf("%d&nbsp;min&nbsp;%ds", $minutes, $seconds);
+ $return = sprintf(Piwik_Translate('General_MinutesSeconds'), $minutes, $seconds);
}
else
{
- return sprintf("%ds", $seconds);
+ $return = sprintf(Piwik_Translate('General_Seconds'), $seconds);
}
+ return str_replace(' ', '&nbsp;', $return);
}
-
- static public function getRandomTitle()
- {
- $titles = array( 'Web analytics',
- 'Analytics',
- 'Web analytics api',
- 'Open source analytics',
- 'Open source web analytics',
- 'Google Analytics alternative',
- 'open source Google Analytics',
- 'Free analytics',
- 'Analytics software',
- 'Free web analytics',
- 'Free web statistics',
- 'Web 2.0 analytics',
- 'Statistics web 2.0',
- );
- $id = abs(intval(md5(substr(Piwik_Url::getCurrentHost(),7))));
- $title = $titles[ $id % count($titles)];
- return $title;
- }
-
- static public function getTableCreateSql( $tableName )
+
+ /**
+ * Returns the Javascript code to be inserted on every page to track
+ *
+ * @param int $idSite
+ * @param string $piwikUrl http://path/to/piwik/directory/
+ * @param string $actionName
+ * @return string
+ */
+ static public function getJavascriptCode($idSite, $piwikUrl, $actionName = "''")
{
- $tables = Piwik::getTablesCreateSql();
-
- if(!isset($tables[$tableName]))
- {
- throw new Exception("The table '$tableName' SQL creation code couldn't be found.");
- }
-
- return $tables[$tableName];
+ $jsTag = file_get_contents( PIWIK_INCLUDE_PATH . "/core/Tracker/javascriptTag.tpl");
+ $jsTag = nl2br(htmlentities($jsTag));
+ $piwikUrl = preg_match('~^(http|https)://(.*)$~', $piwikUrl, $matches);
+ $piwikUrl = $matches[2];
+ $jsTag = str_replace('{$actionName}', $actionName, $jsTag);
+ $jsTag = str_replace('{$idSite}', $idSite, $jsTag);
+ $jsTag = str_replace('{$piwikUrl}', $piwikUrl, $jsTag);
+ $jsTag = str_replace('{$hrefTitle}', Piwik::getRandomTitle(), $jsTag);
+ return $jsTag;
}
-
- static public function getTablesCreateSql()
+
+ /**
+ * Generate a title for image tags
+ *
+ * @return string
+ */
+ static public function getRandomTitle()
{
- $config = Zend_Registry::get('config');
- $prefixTables = $config->database->tables_prefix;
- $tables = array(
- 'user' => "CREATE TABLE {$prefixTables}user (
- login VARCHAR(100) NOT NULL,
- password CHAR(32) NOT NULL,
- alias VARCHAR(45) NOT NULL,
- email VARCHAR(100) NOT NULL,
- token_auth CHAR(32) NOT NULL,
- date_registered TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
- PRIMARY KEY(login),
- UNIQUE INDEX uniq_keytoken(token_auth)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'access' => "CREATE TABLE {$prefixTables}access (
- login VARCHAR(100) NOT NULL,
- idsite INTEGER UNSIGNED NOT NULL,
- access VARCHAR(10) NULL,
- PRIMARY KEY(login, idsite)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'site' => "CREATE TABLE {$prefixTables}site (
- idsite INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
- name VARCHAR(90) NOT NULL,
- main_url VARCHAR(255) NOT NULL,
- ts_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
- PRIMARY KEY(idsite)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'site_url' => "CREATE TABLE {$prefixTables}site_url (
- idsite INTEGER(10) UNSIGNED NOT NULL,
- url VARCHAR(255) NOT NULL,
- PRIMARY KEY(idsite, url)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'goal' => " CREATE TABLE `{$prefixTables}goal` (
- `idsite` int(11) NOT NULL,
- `idgoal` int(11) NOT NULL,
- `name` varchar(50) NOT NULL,
- `match_attribute` varchar(20) NOT NULL,
- `pattern` varchar(255) NOT NULL,
- `pattern_type` varchar(10) NOT NULL,
- `case_sensitive` tinyint(4) NOT NULL,
- `revenue` float NOT NULL,
- `deleted` tinyint(4) NOT NULL default '0',
- PRIMARY KEY (`idsite`,`idgoal`)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'logger_message' => "CREATE TABLE {$prefixTables}logger_message (
- idlogger_message INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- timestamp TIMESTAMP NULL,
- message TEXT NULL,
- PRIMARY KEY(idlogger_message)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'logger_api_call' => "CREATE TABLE {$prefixTables}logger_api_call (
- idlogger_api_call INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- class_name VARCHAR(255) NULL,
- method_name VARCHAR(255) NULL,
- parameter_names_default_values TEXT NULL,
- parameter_values TEXT NULL,
- execution_time FLOAT NULL,
- caller_ip BIGINT UNSIGNED NULL,
- timestamp TIMESTAMP NULL,
- returned_value TEXT NULL,
- PRIMARY KEY(idlogger_api_call)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'logger_error' => "CREATE TABLE {$prefixTables}logger_error (
- idlogger_error INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- timestamp TIMESTAMP NULL,
- message TEXT NULL,
- errno INTEGER UNSIGNED NULL,
- errline INTEGER UNSIGNED NULL,
- errfile VARCHAR(255) NULL,
- backtrace TEXT NULL,
- PRIMARY KEY(idlogger_error)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'logger_exception' => "CREATE TABLE {$prefixTables}logger_exception (
- idlogger_exception INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
- timestamp TIMESTAMP NULL,
- message TEXT NULL,
- errno INTEGER UNSIGNED NULL,
- errline INTEGER UNSIGNED NULL,
- errfile VARCHAR(255) NULL,
- backtrace TEXT NULL,
- PRIMARY KEY(idlogger_exception)
- ) DEFAULT CHARSET=utf8
- ",
-
-
- 'log_action' => "CREATE TABLE {$prefixTables}log_action (
- idaction INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
- name VARCHAR(255) NOT NULL,
- hash INTEGER(10) UNSIGNED NOT NULL,
- type TINYINT UNSIGNED NULL,
- PRIMARY KEY(idaction),
- INDEX index_type_hash (type, hash)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'log_visit' => "CREATE TABLE {$prefixTables}log_visit (
- idvisit INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
- idsite INTEGER(10) UNSIGNED NOT NULL,
- visitor_localtime TIME NOT NULL,
- visitor_idcookie CHAR(32) NOT NULL,
- visitor_returning TINYINT(1) NOT NULL,
- visit_first_action_time DATETIME NOT NULL,
- visit_last_action_time DATETIME NOT NULL,
- visit_server_date DATE NOT NULL,
- visit_exit_idaction_url INTEGER(11) NOT NULL,
- visit_entry_idaction_url INTEGER(11) NOT NULL,
- visit_total_actions SMALLINT(5) UNSIGNED NOT NULL,
- visit_total_time SMALLINT(5) UNSIGNED NOT NULL,
- visit_goal_converted TINYINT(1) NOT NULL,
- referer_type INTEGER UNSIGNED NULL,
- referer_name VARCHAR(70) NULL,
- referer_url TEXT NOT NULL,
- referer_keyword VARCHAR(255) NULL,
- config_md5config CHAR(32) NOT NULL,
- config_os CHAR(3) NOT NULL,
- config_browser_name VARCHAR(10) NOT NULL,
- config_browser_version VARCHAR(20) NOT NULL,
- config_resolution VARCHAR(9) NOT NULL,
- config_pdf TINYINT(1) NOT NULL,
- config_flash TINYINT(1) NOT NULL,
- config_java TINYINT(1) NOT NULL,
- config_director TINYINT(1) NOT NULL,
- config_quicktime TINYINT(1) NOT NULL,
- config_realplayer TINYINT(1) NOT NULL,
- config_windowsmedia TINYINT(1) NOT NULL,
- config_gears TINYINT(1) NOT NULL,
- config_silverlight TINYINT(1) NOT NULL,
- config_cookie TINYINT(1) NOT NULL,
- location_ip BIGINT UNSIGNED NOT NULL,
- location_browser_lang VARCHAR(20) NOT NULL,
- location_country CHAR(3) NOT NULL,
- location_continent CHAR(3) NOT NULL,
- PRIMARY KEY(idvisit),
- INDEX index_idsite_date (idsite, visit_server_date)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'log_conversion' => "CREATE TABLE `{$prefixTables}log_conversion` (
- `idvisit` int(10) unsigned NOT NULL,
- `idsite` int(10) unsigned NOT NULL,
- `visitor_idcookie` char(32) NOT NULL,
- `server_time` datetime NOT NULL,
- `visit_server_date` date NOT NULL,
- `idaction_url` int(11) default NULL,
- `idlink_va` int(11) default NULL,
- `referer_idvisit` int(10) unsigned default NULL,
- `referer_visit_server_date` date default NULL,
- `referer_type` int(10) unsigned default NULL,
- `referer_name` varchar(70) default NULL,
- `referer_keyword` varchar(255) default NULL,
- `visitor_returning` tinyint(1) NOT NULL,
- `location_country` char(3) NOT NULL,
- `location_continent` char(3) NOT NULL,
- `url` text NOT NULL,
- `idgoal` int(10) unsigned NOT NULL,
- `revenue` float default NULL,
- PRIMARY KEY (`idvisit`,`idgoal`),
- KEY `index_idsite_date` (`idsite`,`visit_server_date`)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'log_link_visit_action' => "CREATE TABLE {$prefixTables}log_link_visit_action (
- idlink_va INTEGER(11) NOT NULL AUTO_INCREMENT,
- idvisit INTEGER(10) UNSIGNED NOT NULL,
- idaction_url INTEGER(10) UNSIGNED NOT NULL,
- idaction_url_ref INTEGER(10) UNSIGNED NOT NULL,
- idaction_name INTEGER(10) UNSIGNED,
- time_spent_ref_action INTEGER(10) UNSIGNED NOT NULL,
- PRIMARY KEY(idlink_va),
- INDEX index_idvisit(idvisit)
- ) DEFAULT CHARSET=utf8
- ",
-
- 'log_profiling' => "CREATE TABLE {$prefixTables}log_profiling (
- query TEXT NOT NULL,
- count INTEGER UNSIGNED NULL,
- sum_time_ms FLOAT NULL,
- UNIQUE INDEX query(query(100))
- ) DEFAULT CHARSET=utf8
- ",
-
- 'option' => "CREATE TABLE `{$prefixTables}option` (
- option_name VARCHAR( 64 ) NOT NULL ,
- option_value LONGTEXT NOT NULL ,
- autoload TINYINT NOT NULL DEFAULT '1',
- PRIMARY KEY ( option_name )
- ) DEFAULT CHARSET=utf8
- ",
-
- 'archive_numeric' => "CREATE TABLE {$prefixTables}archive_numeric (
- idarchive INTEGER UNSIGNED NOT NULL,
- name VARCHAR(255) NOT NULL,
- idsite INTEGER UNSIGNED NULL,
- date1 DATE NULL,
- date2 DATE NULL,
- period TINYINT UNSIGNED NULL,
- ts_archived DATETIME NULL,
- value FLOAT NULL,
- PRIMARY KEY(idarchive, name),
- KEY `index_all` (`idsite`,`date1`,`date2`,`name`,`ts_archived`)
- ) DEFAULT CHARSET=utf8
- ",
- 'archive_blob' => "CREATE TABLE {$prefixTables}archive_blob (
- idarchive INTEGER UNSIGNED NOT NULL,
- name VARCHAR(255) NOT NULL,
- idsite INTEGER UNSIGNED NULL,
- date1 DATE NULL,
- date2 DATE NULL,
- period TINYINT UNSIGNED NULL,
- ts_archived DATETIME NULL,
- value MEDIUMBLOB NULL,
- PRIMARY KEY(idarchive, name),
- KEY `index_all` (`idsite`,`date1`,`date2`,`name`,`ts_archived`)
- ) DEFAULT CHARSET=utf8
- ",
+ static $titles = array(
+ 'Web analytics',
+ 'Analytics',
+ 'Real time web analytics',
+ 'Real time analytics',
+ 'Open source analytics',
+ 'Open source web analytics',
+ 'Google Analytics alternative',
+ 'Open source Google Analytics',
+ 'Free analytics',
+ 'Analytics software',
+ 'Free web analytics',
+ 'Free web statistics',
);
- return $tables;
+ $id = abs(intval(md5(Piwik_Url::getCurrentHost())));
+ $title = $titles[ $id % count($titles)];
+ return $title;
}
-
+
+/*
+ * Access
+ */
+
+ /**
+ * Get current user login
+ *
+ * @return string
+ */
static public function getCurrentUserLogin()
{
return Zend_Registry::get('access')->getLogin();
}
-
- static public function getCurrentUserTokenAuth()
- {
- return Zend_Registry::get('access')->getTokenAuth();
- }
-
+
/**
- * Returns the plugin currently being used to display the page
+ * Get current user's token auth
*
- * @return Piwik_Plugin
+ * @return string
*/
- static public function getCurrentPlugin()
+ static public function getCurrentUserTokenAuth()
{
- return Piwik_PluginsManager::getInstance()->getLoadedPlugin(Piwik::getModule());
+ return Zend_Registry::get('access')->getTokenAuth();
}
-
+
/**
* Returns true if the current user is either the super user, or the user $theUser
* Used when modifying user preference: this usually requires super user or being the user itself.
- *
+ *
* @param string $theUser
* @return bool
*/
@@ -776,8 +1025,10 @@ class Piwik
return false;
}
}
-
+
/**
+ * Check that current user is either the specified user or the superuser
+ *
* @param string $theUser
* @throws exception if the user is neither the super user nor the user $theUser
*/
@@ -793,9 +1044,10 @@ class Piwik
throw new Piwik_Access_NoAccessException("The user has to be either the Super User or the user '$theUser' itself.");
}
}
-
+
/**
* Returns true if the current user is the Super User
+ *
* @return bool
*/
static public function isUserIsSuperUser()
@@ -807,21 +1059,32 @@ class Piwik
return false;
}
}
-
+
/**
* Helper method user to set the current as Super User.
* This should be used with great care as this gives the user all permissions.
*/
- static public function setUserIsSuperUser()
+ static public function setUserIsSuperUser( $bool = true )
{
- Zend_Registry::get('access')->setSuperUser();
+ Zend_Registry::get('access')->setSuperUser($bool);
}
-
+
+ /**
+ * Check that user is the superuser
+ *
+ * @throws Exception if not the superuser
+ */
static public function checkUserIsSuperUser()
{
Zend_Registry::get('access')->checkUserIsSuperUser();
}
-
+
+ /**
+ * Returns true if the user has admin access to the sites
+ *
+ * @param mixed $idSites
+ * @return bool
+ */
static public function isUserHasAdminAccess( $idSites )
{
try{
@@ -831,12 +1094,23 @@ class Piwik
return false;
}
}
-
+
+ /**
+ * Check user has admin access to the sites
+ *
+ * @param mixed $idSites
+ * @throws Exception if user doesn't have admin access to the sites
+ */
static public function checkUserHasAdminAccess( $idSites )
{
Zend_Registry::get('access')->checkUserHasAdminAccess( $idSites );
}
-
+
+ /**
+ * Returns true if the user has admin access to any sites
+ *
+ * @return bool
+ */
static public function isUserHasSomeAdminAccess()
{
try{
@@ -846,17 +1120,23 @@ class Piwik
return false;
}
}
-
+
+ /**
+ * Check user has admin access to any sites
+ *
+ * @throws Exception if user doesn't have admin access to any sites
+ */
static public function checkUserHasSomeAdminAccess()
{
Zend_Registry::get('access')->checkUserHasSomeAdminAccess();
}
-
- static public function checkUserHasSomeViewAccess()
- {
- Zend_Registry::get('access')->checkUserHasSomeViewAccess();
- }
-
+
+ /**
+ * Returns true if the user has view access to the sites
+ *
+ * @param mixed $idSites
+ * @return bool
+ */
static public function isUserHasViewAccess( $idSites )
{
try{
@@ -866,635 +1146,139 @@ class Piwik
return false;
}
}
-
- static public function checkUserHasViewAccess( $idSites )
- {
- Zend_Registry::get('access')->checkUserHasViewAccess( $idSites );
- }
-
- static public function prefixClass( $class )
- {
- if(substr_count($class, Piwik::CLASSES_PREFIX) > 0)
- {
- return $class;
- }
- return Piwik::CLASSES_PREFIX.$class;
- }
- static public function unprefixClass( $class )
- {
- $lenPrefix = strlen(Piwik::CLASSES_PREFIX);
- if(substr($class, 0, $lenPrefix) == Piwik::CLASSES_PREFIX)
- {
- return substr($class, $lenPrefix);
- }
- return $class;
- }
/**
- * Returns the current module read from the URL (eg. 'API', 'UserSettings', etc.)
- *
- * @return string
- */
- static public function getModule()
- {
- return Piwik_Common::getRequestVar('module', '', 'string');
- }
-
- /**
- * Returns the current action read from the URL
+ * Check user has view access to the sites
*
- * @return string
+ * @param mixed $idSites
+ * @throws Exception if user doesn't have view access to sites
*/
- static public function getAction()
- {
- return Piwik_Common::getRequestVar('action', '', 'string');
- }
-
- /**
- * returns false if the URL to redirect to is already this URL
- */
- static public function redirectToModule( $newModule, $newAction = '' )
+ static public function checkUserHasViewAccess( $idSites )
{
- $currentModule = self::getModule();
- $currentAction = self::getAction();
-
- if($currentModule != $newModule
- || $currentAction != $newAction )
- {
-
- $newUrl = 'index.php' . Piwik_Url::getCurrentQueryStringWithParametersModified(
- array('module' => $newModule, 'action' => $newAction)
- );
-
- Piwik_Url::redirectToUrl($newUrl);
- }
- return false;
+ Zend_Registry::get('access')->checkUserHasViewAccess( $idSites );
}
/**
- * Get "best" available transport method for sendHttpRequest() calls.
+ * Returns true if the user has view access to any sites
+ *
+ * @return bool
*/
- static public function getTransportMethod()
+ static public function isUserHasSomeViewAccess()
{
- $method = 'curl';
- if(!extension_loaded('curl'))
- {
- $method = 'stream';
- if(@ini_get('allow_url_fopen') != '1')
- {
- $method = 'socket';
- if(preg_match('/(^|,|\s)fsockopen($|,|\s)/', @ini_get('disable_functions')))
- {
- return null;
- }
- }
+ try{
+ self::checkUserHasSomeViewAccess();
+ return true;
+ } catch( Exception $e){
+ return false;
}
- return $method;
}
/**
- * Sends http request ensuring the request will fail before $timeout seconds
+ * Check user has view access to any sites
*
- * If no $destinationPath is specified, the trimmed response (without header) is returned as a string.
- * If a $destinationPath is specified, the response (without header) is saved to a file.
- *
- * @param string $aUrl
- * @param int $timeout
- * @param string $userAgent
- * @param string $destinationPath
- * @param int $followDepth
- * @return true (or string) on success; false on HTTP response error code (1xx or 4xx); throws exception on all other errors
+ * @throws Exception if user doesn't have view access to any sites
*/
- static public function sendHttpRequest($aUrl, $timeout, $userAgent = null, $destinationPath = null, $followDepth = 0)
+ static public function checkUserHasSomeViewAccess()
{
- // create output file
- $file = null;
- if($destinationPath)
- {
- if (($file = @fopen($destinationPath, 'wb')) === false || !is_resource($file))
- {
- throw new Exception('Error while creating the file: ' . $destinationPath);
- }
- }
-
- return self::sendHttpRequestBy(self::getTransportMethod(), $aUrl, $timeout, $userAgent, $destinationPath, $file, $followDepth);
+ Zend_Registry::get('access')->checkUserHasSomeViewAccess();
}
- static public function sendHttpRequestBy($method = 'socket', $aUrl, $timeout, $userAgent = null, $destinationPath = null, $file = null, $followDepth = 0)
- {
- if ($followDepth > 3)
- {
- throw new Exception('Too many redirects ('.$followDepth.')');
- }
-
- $contentLength = 0;
-
- if($method == 'socket')
- {
- // initialization
- $url = @parse_url($aUrl);
- if($url === false || !isset($url['scheme']))
- {
- throw new Exception('Malformed URL: '.$aUrl);
- }
-
- if($url['scheme'] != 'http')
- {
- throw new Exception('Invalid protocol/scheme: '.$url['scheme']);
- }
- $host = $url['host'];
- $port = isset($url['port)']) ? $url['port'] : 80;
- $path = isset($url['path']) ? $url['path'] : '/';
- if(isset($url['query']))
- {
- $path .= '?'.$url['query'];
- }
- $errno = null;
- $errstr = null;
-
- // connection attempt
- if (($fsock = @fsockopen($host, $port, $errno, $errstr, $timeout)) === false || !is_resource($fsock))
- {
- if(is_resource($file)) { @fclose($file); }
- throw new Exception("Error while connecting to: $host. Please try again later. $errstr");
- }
-
- // send HTTP request header
- fwrite($fsock,
- "GET $path HTTP/1.0\r\n"
- ."Host: $host".($port != 80 ? ':'.$port : '')."\r\n"
- ."User-Agent: Piwik/".Piwik_Version::VERSION.($userAgent ? " $userAgent" : '')."\r\n"
- .'Referer: http://'.Piwik_Common::getIpString()."/\r\n"
- ."Connection: close\r\n"
- ."\r\n"
- );
-
- $streamMetaData = array('timed_out' => false);
- @stream_set_blocking($fsock, true);
- @stream_set_timeout($fsock, $timeout);
-
- // process header
- $status = null;
- $expectRedirect = false;
- $fileLength = 0;
-
- while (!feof($fsock))
- {
- $line = fgets($fsock, 4096);
-
- $streamMetaData = @stream_get_meta_data($fsock);
- if($streamMetaData['timed_out'])
- {
- if(is_resource($file)) { @fclose($file); }
- @fclose($fsock);
- throw new Exception('Timed out waiting for server response');
- }
-
- // a blank line marks the end of the server response header
- if(rtrim($line, "\r\n") == '')
- {
- break;
- }
-
- // parse first line of server response header
- if(!$status)
- {
- // expect first line to be HTTP response status line, e.g., HTTP/1.1 200 OK
- if(!preg_match('~^HTTP/(\d\.\d)\s+(\d+)(\s*.*)?~', $line, $m))
- {
- if(is_resource($file)) { @fclose($file); }
- @fclose($fsock);
- throw new Exception('Expected server response code. Got '.rtrim($line, "\r\n"));
- }
-
- $status = (integer) $m[2];
-
- // Informational 1xx or Client Error 4xx
- if ($status < 200 || $status >= 400)
- {
- if(is_resource($file)) { @fclose($file); }
- @fclose($s);
- return false;
- }
-
- continue;
- }
-
- // handle redirect
- if(preg_match('/^Location:\s*(.+)/', rtrim($line, "\r\n"), $m))
- {
- if(is_resource($file)) { @fclose($file); }
- @fclose($s);
- // Successful 2xx vs Redirect 3xx
- if($status < 300)
- {
- throw new Exception('Unexpected redirect to Location: '.rtrim($line).' for status code '.$status);
- }
- return self::sendHttpRequest(trim($m[1]), $pathDestination, $tries+1);
- }
-
- // save expected content length for later verification
- if(preg_match('/^Content-Length:\s*(\d+)/', $line, $m))
- {
- $contentLength = (integer) $m[1];
- }
- }
-
- if(feof($fsock))
- {
- throw new Exception('Unexpected end of transmission');
- }
-
- // process content/body
- $response = '';
-
- while (!feof($fsock))
- {
- $line = fread($fsock, 8192);
-
- $streamMetaData = @stream_get_meta_data($fsock);
- if($streamMetaData['timed_out'])
- {
- if(is_resource($file)) { @fclose($file); }
- @fclose($fsock);
- throw new Exception('Timed out waiting for server response');
- }
-
- if(is_resource($file))
- {
- // save to file
- $fileLength += fwrite($file, $line);
- }
- else
- {
- // concatenate to response string
- $response .= $line;
- }
- }
-
- // determine success or failure
- @fclose(@$fsock);
- }
- else if($method == 'stream')
- {
- $response = false;
-
- // we make sure the request takes less than a few seconds to fail
- // we create a stream_context (works in php >= 5.2.1)
- // we also set the socket_timeout (for php < 5.2.1)
- $default_socket_timeout = @ini_get('default_socket_timeout');
- @ini_set('default_socket_timeout', $timeout);
-
- $ctx = null;
- if(function_exists('stream_context_create')) {
- $stream_options = array(
- 'http' => array(
- 'header' => 'User-Agent: Piwik/'.Piwik_Version::VERSION.($userAgent ? " $userAgent" : '')."\r\n"
- .'Referer: http://'.Piwik_Common::getIpString()."/\r\n",
- 'max_redirects' => 3, // PHP 5.1.0
- 'timeout' => $timeout, // PHP 5.2.1
- )
- );
- $ctx = stream_context_create($stream_options);
- }
-
- $response = @file_get_contents($aUrl, 0, $ctx);
- if(is_resource($file))
- {
- // save to file
- fwrite($file, $response);
- }
-
- // restore the socket_timeout value
- if(!empty($default_socket_timeout))
- {
- @ini_set('default_socket_timeout', $default_socket_timeout);
- }
- }
- else if($method == 'curl')
- {
- $ch = @curl_init();
-
- $curl_options = array(
- CURLOPT_URL => $aUrl,
- CURLOPT_HEADER => false,
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_TIMEOUT => $timeout,
- CURLOPT_BINARYTRANSFER => is_resource($file),
- CURLOPT_FOLLOWLOCATION => true,
- CURLOPT_MAXREDIRS => 3,
- CURLOPT_USERAGENT => 'Piwik/'.Piwik_Version::VERSION.($userAgent ? " $userAgent" : ''),
- CURLOPT_REFERER => 'http://'.Piwik_Common::getIpString(),
- );
- @curl_setopt_array($ch, $curl_options);
-
- $response = @curl_exec($ch);
- if(is_resource($file))
- {
- // save to file
- fwrite($file, $response);
- }
-
- @curl_close($ch);
- unset($ch);
- }
- else
- {
- throw new Exception('Invalid request method: '.$method);
- }
-
- if(is_resource($file))
- {
- fflush($file);
- @fclose($file);
- if($contentLength && (($fileLength != $contentLength) || (filesize($destinationPath) != $contentLength)))
- {
- throw new Exception('File size error: '.$destinationPath.'; expected '.$contentLength.' bytes; received '.$fileLength.' bytes');
- }
- return true;
- }
-
- if($contentLength && strlen($response) != $contentLength)
- {
- throw new Exception('Content length error: expected '.$contentLength.' bytes; received '.$fileLength.' bytes');
- }
- return trim($response);
- }
+/*
+ * Current module, action, plugin
+ */
/**
- * Fetch the file at $url in the destination $pathDestination
- * @param string $url
- * @param string $pathDestination
- * @param int $tries
- * @return true on success, throws Exception on failure
+ * Returns the name of the Login plugin currently being used.
+ * Must be used since it is not allowed to hardcode 'Login' in URLs
+ * in case another Login plugin is being used.
+ *
+ * @return string
*/
- static public function fetchRemoteFile($url, $pathDestination, $tries = 0)
+ static public function getLoginPluginName()
{
- return self::sendHttpRequest($url, 10, 'Update', $pathDestination, $tries);
+ return Zend_Registry::get('auth')->getName();
}
/**
- * Recursively delete a directory
+ * Returns the plugin currently being used to display the page
*
- * @param string $dir Directory name
- * @param boolean $deleteRootToo Delete specified top-level directory as well
- */
- static public function unlinkRecursive($dir, $deleteRootToo)
- {
- if(!$dh = @opendir($dir))
- {
- return;
- }
- while (false !== ($obj = readdir($dh)))
- {
- if($obj == '.' || $obj == '..')
- {
- continue;
- }
-
- if (!@unlink($dir . '/' . $obj))
- {
- self::unlinkRecursive($dir.'/'.$obj, true);
- }
- }
- closedir($dh);
- if ($deleteRootToo)
- {
- @rmdir($dir);
- }
- return;
- }
-
- /**
- * Copy recursively from $source to $target.
- *
- * @param string $source eg. './tmp/latest'
- * @param string $target eg. '.'
- * @param bool $excludePhp
+ * @return Piwik_Plugin
*/
- static public function copyRecursive($source, $target, $excludePhp=false )
+ static public function getCurrentPlugin()
{
- if ( is_dir( $source ) )
- {
- @mkdir( $target );
- $d = dir( $source );
- while ( false !== ( $entry = $d->read() ) )
- {
- if ( $entry == '.' || $entry == '..' )
- {
- continue;
- }
-
- $sourcePath = $source . '/' . $entry;
- if ( is_dir( $sourcePath ) )
- {
- self::copyRecursive( $sourcePath, $target . '/' . $entry, $excludePhp );
- continue;
- }
- $destPath = $target . '/' . $entry;
- self::copy($sourcePath, $destPath, $excludePhp);
- }
- $d->close();
- }
- else
- {
- self::copy($source, $target, $excludePhp);
- }
+ return Piwik_PluginsManager::getInstance()->getLoadedPlugin(Piwik::getModule());
}
-
+
/**
- * Copy individual file from $source to $target.
- *
- * @param string $source eg. './tmp/latest/index.php'
- * @param string $target eg. './index.php'
- * @param bool $excludePhp
- * @return bool
+ * Returns the current module read from the URL (eg. 'API', 'UserSettings', etc.)
+ *
+ * @return string
*/
- static public function copy($source, $dest, $excludePhp=false)
+ static public function getModule()
{
- static $phpExtensions = array('php', 'tpl');
-
- if($excludePhp)
- {
- $path_parts = pathinfo($source);
- if(in_array($path_parts['extension'], $phpExtensions))
- {
- return true;
- }
- }
-
- if(!@copy( $source, $dest ))
- {
- @chmod($dest, 0755);
- if(!@copy( $source, $dest ))
- {
- throw new Exception("
- Error while copying file to <code>$dest</code>. <br />
- Please check that the web server has enough permission to overwrite this file. <br/>
- For example, on a linux server, if your apache user is www-data you can try to execute:<br>
- <code>chown -R www-data:www-data ".Piwik_Common::getPathToPiwikRoot()."</code><br>
- <code>chmod -R 0755 ".Piwik_Common::getPathToPiwikRoot()."</code><br>
- ");
- }
- }
- return true;
+ return Piwik_Common::getRequestVar('module', '', 'string');
}
/**
- * Recursively find pathnames that match a pattern
- * @see glob()
+ * Returns the current action read from the URL
*
- * @param string $sDir directory
- * @param string $sPattern pattern
- * @param int $nFlags glob() flags
- * @return array
+ * @return string
*/
- public static function globr($sDir, $sPattern, $nFlags = NULL)
+ static public function getAction()
{
- if(($aFiles = glob("$sDir/$sPattern", $nFlags)) == false)
- {
- $aFiles = array();
- }
- if(($aDirs = glob("$sDir/*", GLOB_ONLYDIR)) != false)
- {
- foreach ($aDirs as $sSubDir)
- {
- $aSubFiles = self::globr($sSubDir, $sPattern, $nFlags);
- $aFiles = array_merge($aFiles, $aSubFiles);
- }
- }
- return $aFiles;
+ return Piwik_Common::getRequestVar('action', '', 'string');
}
/**
- * API was simplified in 0.2.27, but we maintain backward compatibility
- * when calling Piwik::prefixTable
+ * Redirect to module (and action)
*
- * @deprecated as of 0.2.27
+ * @param string $newModule
+ * @param string $newAction
+ * @return bool false if the URL to redirect to is already this URL
*/
- static public function prefixTable( $table )
+ static public function redirectToModule( $newModule, $newAction = '', $parameters = array() )
{
- return Piwik_Common::prefixTable($table);
+ $newUrl = 'index.php' . Piwik_Url::getCurrentQueryStringWithParametersModified(
+ array('module' => $newModule, 'action' => $newAction)
+ + $parameters
+ );
+ Piwik_Url::redirectToUrl($newUrl);
}
-
+
+/*
+ * Global database object
+ */
+
/**
- * Names of all the prefixed tables in piwik
- * Doesn't use the DB
+ * Create database object and connect to database
*/
- static public function getTablesNames()
- {
- $aTables = array_keys(self::getTablesCreateSql());
- $config = Zend_Registry::get('config');
- $prefixTables = $config->database->tables_prefix;
- $return = array();
- foreach($aTables as $table)
- {
- $return[] = $prefixTables.$table;
- }
- return $return;
- }
-
- static $tablesInstalled = null;
-
- static public function getTablesInstalled($forceReload = true, $idSite = null)
- {
- if(is_null(self::$tablesInstalled)
- || $forceReload === true)
- {
- $db = Zend_Registry::get('db');
- $config = Zend_Registry::get('config');
- $prefixTables = $config->database->tables_prefix;
-
- $allTables = $db->fetchCol("SHOW TABLES");
-
- // all the tables to be installed
- $allMyTables = self::getTablesNames();
-
- // we get the intersection between all the tables in the DB and the tables to be installed
- $tablesInstalled = array_intersect($allMyTables, $allTables);
-
- // at this point we have only the piwik tables which is good
- // but we still miss the piwik generated tables (using the class Piwik_TablePartitioning)
- $idSiteInSql = "no";
- if(!is_null($idSite))
- {
- $idSiteInSql = $idSite;
- }
- $allArchiveNumeric = $db->fetchCol("/* SHARDING_ID_SITE = ".$idSiteInSql." */
- SHOW TABLES LIKE '".$prefixTables."archive_numeric%'");
- $allArchiveBlob = $db->fetchCol("/* SHARDING_ID_SITE = ".$idSiteInSql." */
- SHOW TABLES LIKE '".$prefixTables."archive_blob%'");
-
- $allTablesReallyInstalled = array_merge($tablesInstalled, $allArchiveNumeric, $allArchiveBlob);
-
- self::$tablesInstalled = $allTablesReallyInstalled;
- }
- return self::$tablesInstalled;
- }
-
- static public function createDatabase( $dbName = null )
- {
- if(is_null($dbName))
- {
- $dbName = Zend_Registry::get('config')->database->dbname;
- }
- Piwik_Exec("CREATE DATABASE IF NOT EXISTS ".$dbName);
- }
-
- static public function dropDatabase()
- {
- $dbName = Zend_Registry::get('config')->database->dbname;
- Piwik_Exec("DROP DATABASE IF EXISTS " . $dbName);
- }
-
static public function createDatabaseObject( $dbInfos = null )
{
$config = Zend_Registry::get('config');
-
+
if(is_null($dbInfos))
{
$dbInfos = $config->database->toArray();
}
-
+
$dbInfos['profiler'] = $config->Debug->enable_sql_profiler;
-
+
$db = null;
Piwik_PostEvent('Reporting.createDatabase', $db);
if(is_null($db))
{
- if($dbInfos['port'][0] == '/')
- {
- $dbInfos['unix_socket'] = $dbInfos['port'];
- unset($dbInfos['host']);
- unset($dbInfos['port']);
- }
-
- // not used by Zend Framework
- unset($dbInfos['tables_prefix']);
- unset($dbInfos['adapter']);
-
- $db = Piwik_Db::factory($config->database->adapter, $dbInfos);
- $db->getConnection();
-
- Zend_Db_Table::setDefaultAdapter($db);
- $db->resetConfig(); // we don't want this information to appear in the logs
+ $adapter = $dbInfos['adapter'];
+ $db = Piwik_Db_Adapter::factory($adapter, $dbInfos);
}
Zend_Registry::set('db', $db);
}
-
- static public function disconnectDatabase()
- {
- Zend_Registry::get('db')->closeConnection();
- }
-
+
/**
- * Returns the MySQL database server version
- *
- * @deprecated 0.4.4
+ * Disconnect from database
*/
- static public function getMysqlVersion()
+ static public function disconnectDatabase()
{
- return Piwik_FetchOne("SELECT VERSION()");
+ Zend_Registry::get('db')->closeConnection();
}
/**
@@ -1520,23 +1304,30 @@ class Piwik
return Zend_Registry::get('db')->isConnectionUTF8();
}
+/*
+ * Global log object
+ */
+
+ /**
+ * Create log object
+ */
static public function createLogObject()
{
$configAPI = Zend_Registry::get('config')->log;
-
+
$aLoggers = array(
'logger_api_call' => new Piwik_Log_APICall,
'logger_exception' => new Piwik_Log_Exception,
'logger_error' => new Piwik_Log_Error,
'logger_message' => new Piwik_Log_Message,
- );
-
+ );
+
foreach($configAPI as $loggerType => $aRecordTo)
{
if(isset($aLoggers[$loggerType]))
{
$logger = $aLoggers[$loggerType];
-
+
foreach($aRecordTo as $recordTo)
{
switch($recordTo)
@@ -1544,15 +1335,15 @@ class Piwik
case 'screen':
$logger->addWriteToScreen();
break;
-
+
case 'database':
$logger->addWriteToDatabase();
break;
-
+
case 'file':
- $logger->addWriteToFile();
+ $logger->addWriteToFile();
break;
-
+
default:
throw new Exception("'$recordTo' is not a valid Log type. Valid logger types are: screen, database, file.");
break;
@@ -1560,7 +1351,7 @@ class Piwik
}
}
}
-
+
foreach($aLoggers as $loggerType =>$logger)
{
if($logger->getWritersCount() == 0)
@@ -1570,7 +1361,16 @@ class Piwik
Zend_Registry::set($loggerType, $logger);
}
}
-
+
+/*
+ * Global config object
+ */
+
+ /**
+ * Create configuration object
+ *
+ * @param string $pathConfigFile
+ */
static public function createConfigObject( $pathConfigFile = null )
{
$config = new Piwik_Config($pathConfigFile);
@@ -1578,93 +1378,181 @@ class Piwik
$config->init();
}
+/*
+ * Global access object
+ */
+
+ /**
+ * Create access object
+ */
static public function createAccessObject()
{
Zend_Registry::set('access', new Piwik_Access());
}
-
- static public function dropTables( $doNotDelete = array() )
- {
- $tablesAlreadyInstalled = self::getTablesInstalled();
- $db = Zend_Registry::get('db');
-
- $doNotDeletePattern = '/('.implode('|',$doNotDelete).')/';
-
- foreach($tablesAlreadyInstalled as $tableName)
- {
-
- if( count($doNotDelete) == 0
- || (!in_array($tableName,$doNotDelete)
- && !preg_match($doNotDeletePattern,$tableName)
- )
- )
- {
- $db->query("DROP TABLE `$tableName`");
- }
- }
- }
-
+
+/*
+ * User input validation
+ */
+
/**
* Returns true if the email is a valid email
- *
+ *
* @param string email
* @return bool
*/
- static public function isValidEmailString( $email )
+ static public function isValidEmailString( $email )
{
return (preg_match('/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z]{2,4}$/', $email) > 0);
}
-
+
/**
- * Creates an entry in the User table for the "anonymous" user.
+ * Returns true if the login is valid.
+ * Warning: does not check if the login already exists! You must use UsersManager_API->userExists as well.
+ *
+ * @param string $login
+ * @return bool or throws exception
*/
- static public function createAnonymousUser()
+ static public function checkValidLoginString( $userLogin )
+ {
+ $loginMinimumLength = 3;
+ $loginMaximumLength = 100;
+ $l = strlen($userLogin);
+ if(!($l >= $loginMinimumLength
+ && $l <= $loginMaximumLength
+ && (preg_match('/^[A-Za-z0-9_.-]*$/', $userLogin) > 0))
+ )
+ {
+ throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidLoginFormat', array($loginMinimumLength, $loginMaximumLength)));
+ }
+ }
+
+/*
+ * Date / Timezone
+ */
+
+ /**
+ * Returns true if the current php version supports timezone manipulation
+ * (most likely if php >= 5.2)
+ *
+ * @return bool
+ */
+ static public function isTimezoneSupportEnabled()
{
- // The anonymous user is the user that is assigned by default
- // note that the token_auth value is anonymous, which is assigned by default as well in the Login plugin
- $db = Zend_Registry::get('db');
- $db->query("INSERT INTO ". Piwik::prefixTable("user") . "
- VALUES ( 'anonymous', '', 'anonymous', 'anonymous@example.org', 'anonymous', CURRENT_TIMESTAMP );" );
+ return
+ function_exists( 'date_create' ) &&
+ function_exists( 'date_default_timezone_set' ) &&
+ function_exists( 'timezone_identifiers_list' ) &&
+ function_exists( 'timezone_open' ) &&
+ function_exists( 'timezone_offset_get' );
}
-
- static public function createTables()
+
+/*
+ * Database and table definition methods
+ */
+
+ /**
+ * Is the schema available?
+ *
+ * @return bool True if schema is available; false otherwise
+ */
+ static public function isAvailable()
{
- $db = Zend_Registry::get('db');
- $config = Zend_Registry::get('config');
- $prefixTables = $config->database->tables_prefix;
+ return Piwik_Db_Schema::getInstance()->isAvailable();
+ }
- $tablesAlreadyInstalled = self::getTablesInstalled();
- $tablesToCreate = self::getTablesCreateSql();
- unset($tablesToCreate['archive_blob']);
- unset($tablesToCreate['archive_numeric']);
+ /**
+ * Get the SQL to create a specific Piwik table
+ *
+ * @param string $tableName
+ * @return string SQL
+ */
+ static public function getTableCreateSql( $tableName )
+ {
+ return Piwik_Db_Schema::getInstance()->getTableCreateSql($tableName);
+ }
- foreach($tablesToCreate as $tableName => $tableSql)
- {
- $tableName = $prefixTables . $tableName;
- if(!in_array($tableName, $tablesAlreadyInstalled))
- {
- $db->query( $tableSql );
- }
- }
+ /**
+ * Get the SQL to create Piwik tables
+ *
+ * @return array of strings containing SQL
+ */
+ static public function getTablesCreateSql()
+ {
+ return Piwik_Db_Schema::getInstance()->getTablesCreateSql();
+ }
+
+ /**
+ * Create database
+ *
+ * @param string $dbName
+ */
+ static public function createDatabase( $dbName = null )
+ {
+ Piwik_Db_Schema::getInstance()->createDatabase($dbName);
}
-
+
+ /**
+ * Drop database
+ */
+ static public function dropDatabase()
+ {
+ Piwik_Db_Schema::getInstance()->dropDatabase();
+ }
+
+ /**
+ * Create all tables
+ */
+ static public function createTables()
+ {
+ Piwik_Db_Schema::getInstance()->createTables();
+ }
+
+ /**
+ * Creates an entry in the User table for the "anonymous" user.
+ */
+ static public function createAnonymousUser()
+ {
+ Piwik_Db_Schema::getInstance()->createAnonymousUser();
+ }
+
+ /**
+ * Truncate all tables
+ */
static public function truncateAllTables()
{
- $tablesAlreadyInstalled = self::getTablesInstalled($forceReload = true);
- foreach($tablesAlreadyInstalled as $table)
- {
- Piwik_Query("TRUNCATE `$table`");
- }
+ Piwik_Db_Schema::getInstance()->truncateAllTables();
}
-
- static public function install()
+
+ /**
+ * Drop specific tables
+ *
+ * @param array $doNotDelete Names of tables to not delete
+ */
+ static public function dropTables( $doNotDelete = array() )
{
- Piwik_Common::mkdir(Zend_Registry::get('config')->smarty->compile_dir);
+ Piwik_Db_Schema::getInstance()->dropTables($doNotDelete);
}
-
- static public function uninstall()
+
+ /**
+ * Names of all the prefixed tables in piwik
+ * Doesn't use the DB
+ *
+ * @return array Table names
+ */
+ static public function getTablesNames()
+ {
+ return Piwik_Db_Schema::getInstance()->getTablesNames();
+ }
+
+ /**
+ * Get list of tables installed
+ *
+ * @param bool $forceReload Invalidate cache
+ * @param string $idSite
+ * @return array Tables installed
+ */
+ static public function getTablesInstalled($forceReload = true, $idSite = null)
{
- $db = Zend_Registry::get('db');
- $db->query( "DROP TABLE IF EXISTS ". implode(", ", self::getTablesNames()) );
+ return Piwik_Db_Schema::getInstance()->getTablesInstalled($forceReload, $idSite);
}
}
diff --git a/core/Plugin.php b/core/Plugin.php
index d0d118180a..82ac6c523f 100644
--- a/core/Plugin.php
+++ b/core/Plugin.php
@@ -20,14 +20,14 @@ abstract class Piwik_Plugin
{
/**
* Returns the plugin details
- * 'name' => string // plugin name
- * 'description' => string // 1/2 sentences description of the plugin
- * 'author' => string // plugin author
- * 'author_homepage' => string // author homepage (or email "mailto:youremail@example.org")
- * 'homepage' => string // plugin homepage
- * 'version' => string // plugin version number
+ * 'description' => string // 1-2 sentence description of the plugin
+ * 'author' => string // plugin author
+ * 'author_homepage' => string // author homepage URL (or email "mailto:youremail@example.org")
+ * 'homepage' => string // plugin homepage URL
+ * 'version' => string // plugin version number; examples and 3rd party plugins must not use Piwik_Version::VERSION;
+ * // 3rd party plugins must increment the version number with each plugin release
* 'translationAvailable' => bool // is there a translation file in plugins/your-plugin/lang/* ?
- * 'TrackerPlugin' => bool // should we load this plugin during the stats logging process?
+ * 'TrackerPlugin' => bool // should we load this plugin during the stats logging process?
*/
abstract function getInformation();
@@ -69,17 +69,6 @@ abstract class Piwik_Plugin
}
/**
- * Returns the plugin name
- *
- * @return string
- */
- public function getName()
- {
- $info = $this->getInformation();
- return $info['name'];
- }
-
- /**
* Returns the plugin version number
*
* @return string
@@ -91,12 +80,13 @@ abstract class Piwik_Plugin
}
/**
- * Returns the UserCountry part when the plugin class is Piwik_UserCountry
+ * Returns the plugin's base name without the "Piwik_" prefix,
+ * e.g., "UserCountry" when the plugin class is "Piwik_UserCountry"
*
* @return string
*/
- public function getClassName()
+ final public function getClassName()
{
- return substr(get_class($this), strlen("Piwik_"));
+ return Piwik::unprefixClass(get_class($this));
}
}
diff --git a/core/PluginsFunctions/AdminMenu.php b/core/PluginsFunctions/AdminMenu.php
index e926c77d7f..44142e9841 100644
--- a/core/PluginsFunctions/AdminMenu.php
+++ b/core/PluginsFunctions/AdminMenu.php
@@ -16,6 +16,7 @@
class Piwik_AdminMenu
{
private $adminMenu = null;
+ private $adminMenuOrdered = null;
static private $instance = null;
/**
@@ -36,31 +37,37 @@ class Piwik_AdminMenu
*/
public function get()
{
- if(!is_null($this->adminMenu))
+ if(!is_null($this->adminMenuOrdered))
{
- return;
+ return $this->adminMenuOrdered;
}
Piwik_PostEvent('AdminMenu.add');
-
- foreach($this->adminMenu as $key => &$element)
+
+ $this->adminMenuOrdered = array();
+ ksort($this->adminMenu);
+ foreach($this->adminMenu as $order => $menu)
{
- if(is_null($element))
- {
- unset($this->adminMenu[$key]);
- }
+ foreach($menu as $key => &$element)
+ {
+ if(!is_null($element))
+ {
+ $this->adminMenuOrdered[$key] = $element;
+ }
+ }
}
- return $this->adminMenu;
+ return $this->adminMenuOrdered;
}
/*
*
*/
- public function add($adminMenuName, $url)
+ public function add($adminMenuName, $url, $displayedForCurrentUser, $order)
{
- if(!isset($this->adminMenu[$adminMenuName]))
+ if($displayedForCurrentUser
+ && !isset($this->adminMenu[$adminMenuName]))
{
- $this->adminMenu[$adminMenuName] = $url;
+ $this->adminMenu[$order][$adminMenuName] = $url;
}
}
@@ -74,15 +81,30 @@ class Piwik_AdminMenu
$this->adminMenu[$adminMenuRenamed] = $save;
}
}
+function Piwik_GetCurrentAdminMenuName()
+{
+ $menu = Piwik_GetAdminMenu();
+ $currentModule = Piwik::getModule();
+ $currentAction = Piwik::getAction();
+ foreach($menu as $name => $parameters)
+ {
+ if($parameters['module'] == $currentModule
+ && $parameters['action'] == $currentAction)
+ {
+ return $name;
+ }
+ }
+ return false;
+}
function Piwik_GetAdminMenu()
{
return Piwik_AdminMenu::getInstance()->get();
}
-function Piwik_AddAdminMenu( $adminMenuName, $url )
+function Piwik_AddAdminMenu( $adminMenuName, $url, $displayedForCurrentUser = true, $order = 10 )
{
- return Piwik_AdminMenu::getInstance()->add($adminMenuName, $url);
+ return Piwik_AdminMenu::getInstance()->add($adminMenuName, $url, $displayedForCurrentUser, $order);
}
function Piwik_RenameAdminMenuEntry($adminMenuOriginal, $adminMenuRenamed)
diff --git a/core/PluginsFunctions/Menu.php b/core/PluginsFunctions/Menu.php
index d2b33675c6..73041c1d6d 100644
--- a/core/PluginsFunctions/Menu.php
+++ b/core/PluginsFunctions/Menu.php
@@ -60,6 +60,21 @@ class Piwik_Menu
}
}
+ function isUrlFound($url)
+ {
+ $menu = Piwik_Menu::getInstance()->get();
+ foreach($menu as $mainMenuName => $subMenus)
+ {
+ foreach($subMenus as $subMenuName => $menuUrl)
+ {
+ if($menuUrl == $url)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
/*
*
*/
@@ -163,6 +178,11 @@ class Piwik_Menu
}
}
+function Piwik_IsMenuUrlFound($url)
+{
+ return Piwik_Menu::getInstance()->isUrlFound($url);
+}
+
function Piwik_GetMenu()
{
return Piwik_Menu::getInstance()->get();
diff --git a/core/PluginsFunctions/Sql.php b/core/PluginsFunctions/Sql.php
index 5cd5ff6784..aa219d619b 100644
--- a/core/PluginsFunctions/Sql.php
+++ b/core/PluginsFunctions/Sql.php
@@ -11,15 +11,64 @@
*/
/**
+ * SQL wrapper
+ *
* @package PluginsFunctions
*/
class Piwik_Sql
{
+ static private function getDb()
+ {
+ $db = null;
+ if(!empty($GLOBALS['PIWIK_TRACKER_MODE']))
+ {
+ $db = Piwik_Tracker::getDatabase();
+ }
+ if($db === null)
+ {
+ $db = Zend_Registry::get('db');
+ }
+ return $db;
+ }
+
+ static public function exec($sql)
+ {
+ return self::getDb()->exec($sql);
+ }
+
+ static public function query($sql, $parameters = array())
+ {
+ return self::getDb()->query($sql, $parameters);
+ }
+
+ static public function fetchAll($sql, $parameters = array())
+ {
+ return self::getDb()->fetchAll($sql, $parameters);
+ }
+
+ static public function fetchRow($sql, $parameters = array())
+ {
+ return self::getDb()->fetchRow($sql, $parameters);
+ }
+
+ static public function fetchOne($sql, $parameters = array())
+ {
+ return self::getDb()->fetchOne($sql, $parameters);
+ }
}
-function Piwik_Exec( $sqlQuery )
+/**
+ * Executes an unprepared SQL query on the DB. Recommended for DDL statements, e.g., CREATE/DROP/ALTER.
+ * The return result is DBMS-specific. For MySQLI, it returns the number of rows affected. For PDO, it returns the Zend_Db_Statement object
+ * If you want to fetch data from the DB you should use the function Piwik_FetchAll()
+ *
+ * @param string $sqlQuery
+ * @param array Parameters to bind in the query, array( param1 => value1, param2 => value2)
+ * @return integer|Zend_Db_Statement
+ */
+function Piwik_Exec($sqlQuery)
{
- return Zend_Registry::get('db')->exec( $sqlQuery );
+ return Piwik_Sql::exec($sqlQuery);
}
/**
@@ -32,25 +81,43 @@ function Piwik_Exec( $sqlQuery )
* @param array Parameters to bind in the query, array( param1 => value1, param2 => value2)
* @return Zend_Db_Statement
*/
-function Piwik_Query( $sqlQuery, $parameters = array())
+function Piwik_Query($sqlQuery, $parameters = array())
{
- return Zend_Registry::get('db')->query( $sqlQuery, $parameters);
+ return Piwik_Sql::query($sqlQuery, $parameters);
}
/**
- * Executes the SQL Query and fetches all the rows from the database
+ * Executes the SQL Query and fetches all the rows from the database query
*
* @param string $sqlQuery
- * @param array Parameters to bind in the query, array( param1 => value1, param2 => value2)
+ * @param array $parameters Parameters to bind in the query, array( param1 => value1, param2 => value2)
* @return array (one row in the array per row fetched in the DB)
*/
function Piwik_FetchAll( $sqlQuery, $parameters = array())
{
- return Zend_Registry::get('db')->fetchAll( $sqlQuery, $parameters );
+ return Piwik_Sql::fetchAll($sqlQuery, $parameters);
}
-function Piwik_FetchOne( $sqlQuery, $parameters = array())
+/**
+ * Fetches first row of result from the database query
+ *
+ * @param string $sqlQuery
+ * @param array $parameters Parameters to bind in the query, array( param1 => value1, param2 => value2)
+ * @return array
+ */
+function Piwik_FetchRow($sqlQuery, $parameters = array())
{
- return Zend_Registry::get('db')->fetchOne( $sqlQuery, $parameters );
+ return Piwik_Sql::fetchRow($sqlQuery, $parameters);
}
+/**
+ * Fetches first column of first row of result from the database query
+ *
+ * @param string $sqlQuery
+ * @param array $parameters Parameters to bind in the query, array( param1 => value1, param2 => value2)
+ * @return string
+ */
+function Piwik_FetchOne( $sqlQuery, $parameters = array())
+{
+ return Piwik_Sql::fetchOne($sqlQuery, $parameters);
+}
diff --git a/core/PluginsFunctions/WidgetsList.php b/core/PluginsFunctions/WidgetsList.php
index ce1b7a417f..1ab172a645 100644
--- a/core/PluginsFunctions/WidgetsList.php
+++ b/core/PluginsFunctions/WidgetsList.php
@@ -16,10 +16,15 @@
class Piwik_WidgetsList
{
static protected $widgets = null;
+ static protected $hookCalled = false;
static function get()
{
- Piwik_PostEvent('WidgetsList.add');
+ if(!self::$hookCalled)
+ {
+ self::$hookCalled = true;
+ Piwik_PostEvent('WidgetsList.add');
+ }
return self::$widgets;
}
@@ -28,6 +33,10 @@ class Piwik_WidgetsList
$widgetCategory = Piwik_Translate($widgetCategory);
$widgetName = Piwik_Translate($widgetName);
$widgetUniqueId = 'widget' . $controllerName . $controllerAction;
+ foreach($customParameters as $name => $value)
+ {
+ $widgetUniqueId .= $name . $value;
+ }
self::$widgets[$widgetCategory][] = array(
'name' => $widgetName,
'uniqueId' => $widgetUniqueId,
@@ -36,6 +45,23 @@ class Piwik_WidgetsList
) + $customParameters
);
}
+
+ static function isDefined($controllerName, $controllerAction)
+ {
+ $widgetsList = self::get();
+ foreach($widgetsList as $widgetCategory => $widgets)
+ {
+ foreach($widgets as $widget)
+ {
+ if($widget['parameters']['module'] == $controllerName
+ && $widget['parameters']['action'] == $controllerAction)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
function Piwik_GetWidgetsList()
@@ -47,3 +73,8 @@ function Piwik_AddWidget( $widgetCategory, $widgetName, $controllerName, $contro
{
Piwik_WidgetsList::add($widgetCategory, $widgetName, $controllerName, $controllerAction, $customParameters);
}
+
+function Piwik_IsWidgetDefined($controllerName, $controllerAction)
+{
+ return Piwik_WidgetsList::isDefined($controllerName, $controllerAction);
+}
diff --git a/core/PluginsManager.php b/core/PluginsManager.php
index 5e2c3e20d7..d31289ac23 100644
--- a/core/PluginsManager.php
+++ b/core/PluginsManager.php
@@ -10,9 +10,6 @@
* @package Piwik
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see core/PluginsFunctions/Menu.php
* @see core/PluginsFunctions/AdminMenu.php
@@ -42,7 +39,13 @@ class Piwik_PluginsManager
protected $loadedPlugins = array();
protected $doLoadAlwaysActivatedPlugins = true;
- protected $pluginToAlwaysActivate = array( 'CoreHome', 'CoreUpdater', 'CoreAdminHome', 'CorePluginsAdmin' );
+ protected $pluginToAlwaysActivate = array( 'CoreHome',
+ 'CoreUpdater',
+ 'CoreAdminHome',
+ 'CorePluginsAdmin',
+ 'Installation',
+ 'SitesManager',
+ 'UsersManager' );
static private $instance = null;
@@ -112,7 +115,7 @@ class Piwik_PluginsManager
if($key !== false)
{
unset($pluginsTracker[$key]);
- Zend_Registry::get('config')->Plugins_Tracker = $pluginsTracker;
+ Zend_Registry::get('config')->Plugins_Tracker = array('Plugins_Tracker' => $pluginsTracker);
}
}
}
@@ -154,7 +157,7 @@ class Piwik_PluginsManager
Zend_Registry::get('config')->Plugins = $plugins;
}
- public function setPluginsToLoad( array $pluginsToLoad )
+ public function loadPlugins( array $pluginsToLoad )
{
// case no plugins to load
if(is_null($pluginsToLoad))
@@ -162,7 +165,7 @@ class Piwik_PluginsManager
$pluginsToLoad = array();
}
$this->pluginsToLoad = $pluginsToLoad;
- $this->loadPlugins();
+ $this->reloadPlugins();
}
public function doNotLoadPlugins()
@@ -174,13 +177,22 @@ class Piwik_PluginsManager
{
$this->doLoadAlwaysActivatedPlugins = false;
}
-
- public function postLoadPlugins()
+
+ public function loadTranslations()
{
$plugins = $this->getLoadedPlugins();
+
foreach($plugins as $plugin)
{
$this->loadTranslation( $plugin, $this->languageToLoad );
+ }
+ }
+
+ public function postLoadPlugins()
+ {
+ $plugins = $this->getLoadedPlugins();
+ foreach($plugins as $plugin)
+ {
$plugin->postLoad();
}
}
@@ -192,9 +204,7 @@ class Piwik_PluginsManager
*/
public function getLoadedPluginsName()
{
- $oPlugins = $this->getLoadedPlugins();
- $pluginNames = array_map('get_class',$oPlugins);
- return $pluginNames;
+ return array_map('get_class', $this->getLoadedPlugins());
}
/**
@@ -230,7 +240,7 @@ class Piwik_PluginsManager
* Register the observers for every plugin.
*
*/
- public function loadPlugins()
+ private function reloadPlugins()
{
$this->pluginsToLoad = array_unique($this->pluginsToLoad);
@@ -248,17 +258,17 @@ class Piwik_PluginsManager
&& $this->isPluginActivated($pluginName))
{
$this->addPluginObservers( $newPlugin );
- $this->addLoadedPlugin( $pluginName, $newPlugin);
}
}
}
}
/**
- * Loads the plugin filename and instanciates the plugin with the given name, eg. UserCountry
+ * Loads the plugin filename and instantiates the plugin with the given name, eg. UserCountry
* Do NOT give the class name ie. Piwik_UserCountry, but give the plugin name ie. UserCountry
*
- * @param Piwik_Plugin $pluginName
+ * @param string $pluginName
+ * @return Piwik_Plugin
*/
public function loadPlugin( $pluginName )
{
@@ -278,7 +288,8 @@ class Piwik_PluginsManager
if(!file_exists($path))
{
- throw new Exception("Unable to load plugin '$pluginName' because '$path' couldn't be found.");
+ throw new Exception("Unable to load plugin '$pluginName' because '$path' couldn't be found.
+ You can manually uninstall the plugin by removing the line <code>Plugins[] = $pluginName</code> from the Piwik config file.");
}
// Don't remove this.
@@ -295,6 +306,9 @@ class Piwik_PluginsManager
{
throw new Exception("The plugin $pluginClassName in the file $path must inherit from Piwik_Plugin.");
}
+
+ $this->addLoadedPlugin( $pluginName, $newPlugin);
+
return $newPlugin;
}
@@ -347,7 +361,7 @@ class Piwik_PluginsManager
try{
$plugin->install();
} catch(Exception $e) {
- throw new Piwik_PluginsManager_PluginException($plugin->getName(), $plugin->getClassName(), $e->getMessage()); }
+ throw new Piwik_PluginsManager_PluginException($plugin->getClassName(), $e->getMessage()); }
}
@@ -381,12 +395,12 @@ class Piwik_PluginsManager
*/
private function loadTranslation( $plugin, $langCode )
{
- // we are certainly in Tracker mode, Zend is not loaded
- if(!class_exists('Zend_Loader', false))
+ // we are in Tracker mode if Piwik_Loader is not (yet) loaded
+ if(!class_exists('Piwik_Loader', false))
{
return ;
}
-
+
$infos = $plugin->getInformation();
if(!isset($infos['translationAvailable']))
{
@@ -398,7 +412,7 @@ class Piwik_PluginsManager
{
return;
}
-
+
$pluginName = $plugin->getClassName();
$path = PIWIK_INCLUDE_PATH . '/plugins/' . $pluginName .'/lang/%s.php';
@@ -436,13 +450,6 @@ class Piwik_PluginsManager
return $pluginNames;
}
- public function getInstalledPlugins()
- {
- $plugins = $this->getLoadedPlugins();
- $installed = $this->getInstalledPluginsName();
- return array_intersect_key($plugins, array_combine($installed, array_fill(0, count($installed), 1)));
- }
-
private function installPluginIfNecessary( Piwik_Plugin $plugin )
{
$pluginName = $plugin->getClassName();
@@ -486,18 +493,24 @@ class Piwik_PluginsManager
*/
class Piwik_PluginsManager_PluginException extends Exception
{
- function __construct($pluginName, $className, $message)
+ function __construct($pluginName, $message)
{
parent::__construct("There was a problem installing the plugin ". $pluginName . ": " . $message. "
If this plugin has already been installed, and if you want to hide this message</b>, you must add the following line under the
[PluginsInstalled]
entry in your config/config.ini.php file:
- PluginsInstalled[] = $className" );
+ PluginsInstalled[] = $pluginName" );
}
}
/**
* Post an event to the dispatcher which will notice the observers
+ *
+ * @param $eventName The event name
+ * @param $object Object, array or string that the listeners can read and/or modify.
+ * Listeners can call $object =& $notification->getNotificationObject(); to fetch and then modify this variable.
+ * @param $info Additional array of data that can be used by the listeners, but not edited
+ * @return void
*/
function Piwik_PostEvent( $eventName, &$object = null, $info = array() )
{
@@ -530,11 +543,11 @@ class Piwik_Event_Notification extends Event_Notification
$className = is_object($callback[0]) ? get_class($callback[0]) : $callback[0];
$method = $callback[1];
- echo "after $className -> $method <br>";
+ echo "after $className -> $method <br />";
echo "-"; Piwik::printTimer();
- echo "<br>";
+ echo "<br />";
echo "-"; Piwik::printMemoryLeak();
- echo "<br>";
+ echo "<br />";
}
}
}
diff --git a/core/Session.php b/core/Session.php
new file mode 100644
index 0000000000..49969f2066
--- /dev/null
+++ b/core/Session.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Piwik
+ */
+
+/**
+ * Session initialization.
+ *
+ * @package Piwik
+ */
+class Piwik_Session extends Zend_Session
+{
+ public static function start($options = false)
+ {
+ // don't use the default: PHPSESSID
+ $sessionName = defined('PIWIK_SESSION_NAME') ? PIWIK_SESSION_NAME : 'PIWIK_SESSID';
+ @ini_set('session.name', $sessionName);
+
+ // we consider this a misconfiguration (i.e., Piwik doesn't implement user-defined session handler functions)
+ if(ini_get('session.save_handler') == 'user')
+ {
+ @ini_set('session.save_handler', 'files');
+ @ini_set('session.save_path', '');
+ }
+
+ // for "files", we want a writeable folder;
+ // for shared hosting, we assume the web server has been securely configured to prevent local session file hijacking
+ if(ini_get('session.save_handler') == 'files')
+ {
+ $sessionPath = ini_get('session.save_path');
+ if(preg_match('/^[0-9]+;(.*)/', $sessionPath, $matches))
+ {
+ $sessionPath = $matches[1];
+ }
+ if(ini_get('safe_mode') || ini_get('open_basedir') || empty($sessionPath) || !@is_readable($sessionPath) || !@is_writable($sessionPath))
+ {
+ $sessionPath = PIWIK_USER_PATH . '/tmp/sessions';
+ $ok = true;
+
+ if(!is_dir($sessionPath))
+ {
+ @mkdir($sessionPath, 0755, true);
+ if(!is_dir($sessionPath))
+ {
+ // Unable to mkdir $sessionPath
+ $ok = false;
+ }
+ }
+ else if(!@is_writable($sessionPath))
+ {
+ // $sessionPath is not writable
+ $ok = false;
+ }
+
+ if($ok)
+ {
+ @ini_set('session.save_path', $sessionPath);
+ }
+ // else rely on default setting (assuming it is configured to a writeable folder)
+ }
+ }
+
+ Zend_Session::start();
+ }
+}
diff --git a/core/Site.php b/core/Site.php
index d692c470ae..d5915e30b3 100644
--- a/core/Site.php
+++ b/core/Site.php
@@ -25,13 +25,19 @@ class Piwik_Site
$this->id = $idsite;
if(!isset(self::$infoSites[$this->id]))
{
- self::$infoSites[$this->id] = Piwik_SitesManager_API::getSiteFromId($idsite);
+ self::$infoSites[$this->id] = Piwik_SitesManager_API::getInstance()->getSiteFromId($idsite);
}
}
function __toString()
{
- return "site id=".$this->getId().", name=".$this->getName();
+ return "site id=".$this->getId().",
+ name=".$this->getName() .",
+ url = ". $this->getMainUrl() .",
+ IPs excluded = ".$this->getExcludedIps().",
+ timezone = ".$this->getTimezone().",
+ currency = ".$this->getCurrency().",
+ creation date = ".$this->getCreationDate();
}
function getName()
@@ -54,6 +60,26 @@ class Piwik_Site
$date = self::$infoSites[$this->id]['ts_created'];
return Piwik_Date::factory($date);
}
+
+ function getTimezone()
+ {
+ return self::$infoSites[$this->id]['timezone'];
+ }
+
+ function getCurrency()
+ {
+ return self::$infoSites[$this->id]['currency'];
+ }
+
+ function getExcludedIps()
+ {
+ return self::$infoSites[$this->id]['excluded_ips'];
+ }
+
+ function getExcludedQueryParameters()
+ {
+ return self::$infoSites[$this->id]['excluded_parameters'];
+ }
/**
* @param string comma separated idSite list
@@ -70,4 +96,9 @@ class Piwik_Site
}
return $validIds;
}
+
+ static public function clearCache()
+ {
+ self::$infoSites = array();
+ }
}
diff --git a/core/Smarty.php b/core/Smarty.php
index a5b8165583..cc5c000bbf 100644
--- a/core/Smarty.php
+++ b/core/Smarty.php
@@ -10,9 +10,6 @@
* @package Piwik
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see libs/Smarty/Smarty.class.php
* @link http://smarty.net
diff --git a/core/SmartyPlugins/function.ajaxErrorDiv.php b/core/SmartyPlugins/function.ajaxErrorDiv.php
new file mode 100644
index 0000000000..b143fae09e
--- /dev/null
+++ b/core/SmartyPlugins/function.ajaxErrorDiv.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package SmartyPlugins
+ */
+
+/**
+ * Outputs the generic Ajax error div (displayed when ajax requests are throwing exceptions and returning error messages)
+ *
+ * @param id=$ID_NAME ID of the HTML div, defaults to ajaxError
+ * @return string Html of the error message div, hidden by defayult
+ */
+function smarty_function_ajaxErrorDiv($params, &$smarty)
+{
+ if(empty($params['id']))
+ {
+ $id = 'ajaxError';
+ }
+ else
+ {
+ $id = $params['id'];
+ }
+ return '<div class="ajaxError" id="'.$id.'" style="display:none"></div>';
+}
diff --git a/core/SmartyPlugins/function.ajaxLoadingDiv.php b/core/SmartyPlugins/function.ajaxLoadingDiv.php
new file mode 100644
index 0000000000..86b624f7f6
--- /dev/null
+++ b/core/SmartyPlugins/function.ajaxLoadingDiv.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package SmartyPlugins
+ */
+
+/**
+ * Outputs the generic Ajax Loading div (displayed when ajax requests are triggered)
+ *
+ * @param id=$ID_NAME ID of the HTML div, defaults to ajaxLoading
+ * @return string Html of the Loading... div
+ */
+function smarty_function_ajaxLoadingDiv($params, &$smarty)
+{
+ if(empty($params['id']))
+ {
+ $id = 'ajaxLoading';
+ }
+ else
+ {
+ $id = $params['id'];
+ }
+ return '<div id="'.$id.'" style="display:none">'.
+ '<div id="loadingPiwik"><img src="themes/default/images/loading-blue.gif" alt="" /> '.
+ Piwik_Translate('General_LoadingData') .
+ ' </div>'.
+ '</div>';
+ ;
+}
diff --git a/core/SmartyPlugins/function.ajaxRequestErrorDiv.php b/core/SmartyPlugins/function.ajaxRequestErrorDiv.php
new file mode 100644
index 0000000000..d0878ae00c
--- /dev/null
+++ b/core/SmartyPlugins/function.ajaxRequestErrorDiv.php
@@ -0,0 +1,22 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package SmartyPlugins
+ */
+
+/**
+ * Outputs the generic Ajax request error div
+ * will be displayed when the ajax request fails (connectivity, server error, etc)
+ *
+ * @return string Html of the div
+ */
+function smarty_function_ajaxRequestErrorDiv()
+{
+ return '<div id="loadingError">'.Piwik_Translate('General_ErrorRequest').'</div>';
+}
diff --git a/core/SmartyPlugins/function.assignTopBar.php b/core/SmartyPlugins/function.assignTopBar.php
index 4d5beb44fc..e5313fa179 100644
--- a/core/SmartyPlugins/function.assignTopBar.php
+++ b/core/SmartyPlugins/function.assignTopBar.php
@@ -21,10 +21,11 @@ function smarty_function_assignTopBar($params, &$smarty)
{
$topBarElements = array();
$elements = array(
- array('CoreHome', Piwik_Translate('General_YourDashboard'), array('module' => 'CoreHome', 'action' => 'index')),
+ array('CoreHome', Piwik_Translate('General_Dashboard'), array('module' => 'CoreHome', 'action' => 'index')),
+ array('MultiSites', Piwik_Translate('General_MultiSitesSummary'), array('module' => 'MultiSites', 'action' => 'index')),
array('Widgetize', Piwik_Translate('General_Widgets'), array('module' => 'Widgetize', 'action' => 'index')),
array('API', Piwik_Translate('General_API'), array('module' => 'API', 'action' => 'listAllAPI')),
- array('Feedback', Piwik_Translate('General_GiveUsYourFeedback'), array('module' => 'Feedback', 'action' => 'index', 'keepThis' => 'true', 'TB_iframe' => 'true', 'height' => '400', 'width' => '350'), 'title="'.Piwik_Translate('General_GiveUsYourFeedback').'" class="thickbox"'),
+ array('Feedback', Piwik_Translate('General_GiveUsYourFeedback'), array('module' => 'Feedback', 'action' => 'index'), 'id="topbar-feedback"'),
);
foreach($elements as $element)
diff --git a/core/SmartyPlugins/modifier.inlineHelp.php b/core/SmartyPlugins/modifier.inlineHelp.php
new file mode 100644
index 0000000000..bbd9892e61
--- /dev/null
+++ b/core/SmartyPlugins/modifier.inlineHelp.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package SmartyPlugins
+ */
+
+/**
+ * Displays inline help using the jquery UI CSS
+ */
+function smarty_modifier_inlineHelp($text)
+{
+ return
+ '<div class="ui-widget">'.
+ '<div class="ui-inline-help ui-state-highlight ui-corner-all">'.
+ '<p style="font-size:8pt;"><span class="ui-icon ui-icon-info" style="float:left;margin-right:.3em;"></span>'.
+ $text.
+ '</p>'.
+ '</div>'.
+ '</div>';
+}
diff --git a/core/SmartyPlugins/modifier.money.php b/core/SmartyPlugins/modifier.money.php
new file mode 100644
index 0000000000..52acffd4fd
--- /dev/null
+++ b/core/SmartyPlugins/modifier.money.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package SmartyPlugins
+ */
+
+/**
+ * Prints money, given the currency symbol.
+ *
+ * @return string The amount with the currency symbol
+ */
+function smarty_modifier_money($amount)
+{
+ if(func_num_args() != 2)
+ {
+ throw new Exception('the smarty modifier money expects one parameter: the idSite.');
+ }
+ $idSite = func_get_args();
+ $idSite = $idSite[1];
+ return Piwik::getPrettyMoney($amount, $idSite);
+}
diff --git a/core/SmartyPlugins/modifier.stripeol.php b/core/SmartyPlugins/modifier.stripeol.php
new file mode 100644
index 0000000000..d9e70f810d
--- /dev/null
+++ b/core/SmartyPlugins/modifier.stripeol.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package SmartyPlugins
+ */
+
+/**
+ * Smarty stripeol modifier plugin
+ *
+ * Type: modifier<br>
+ * Name: stripeol<br>
+ * Purpose: Replace all end-of-line characters with platform specific string.<br>
+ * Example: {$var|stripeol}
+ * Date: March 10th, 2010
+ * @author anthon (at) piwik.org
+ * @version 1.0
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_stripeol($text)
+{
+ return preg_replace('!(\r\n|\r|\n)!', PHP_EOL, $text);
+}
+
+/* vim: set expandtab: */
diff --git a/core/SmartyPlugins/modifier.translate.php b/core/SmartyPlugins/modifier.translate.php
index 3c3a7346cc..09a2ecdf89 100644
--- a/core/SmartyPlugins/modifier.translate.php
+++ b/core/SmartyPlugins/modifier.translate.php
@@ -11,13 +11,19 @@
*/
/**
- * Read the translation string from the given index (read form the selected language in Piwik).
- * The translations strings are located either in /lang/xx.php or within the plugin lang directory.
+ * Translates in the currently selected language the specified translation $stringToken
+ * Translations strings are located either in /lang/xx.php or within the plugin lang directory.
*
- * Example:
+ * Usage:
* {'General_Unknown'|translate} will be translated as 'Unknown' (see the entry in /lang/en.php)
*
- * @return string The translated string
+ * Usage with multiple substrings to be replaced in the translation string:
+ * - in lang/en.php you would find:
+ * 'VisitorInterest_BetweenXYMinutes' => '%1s-%2s min',
+ * - in the smarty template you would then translate the string, passing the two parameters:
+ * {'VisitorInterest_BetweenXYMinutes'|translate:$min:$max}
+ *
+ * @return string The translated string, with optional substrings parameters replaced
*/
function smarty_modifier_translate($stringToken)
{
diff --git a/core/SmartyPlugins/modifier.urlRewriteWithParameters.php b/core/SmartyPlugins/modifier.urlRewriteWithParameters.php
index e2077b493c..7f42333820 100644
--- a/core/SmartyPlugins/modifier.urlRewriteWithParameters.php
+++ b/core/SmartyPlugins/modifier.urlRewriteWithParameters.php
@@ -18,6 +18,7 @@
*/
function smarty_modifier_urlRewriteWithParameters($parameters)
{
+ $parameters['updated'] = null;
$url = Piwik_Url::getCurrentQueryStringWithParametersModified($parameters);
return htmlspecialchars($url);
}
diff --git a/core/SmartyPlugins/outputfilter.ajaxcdn.php b/core/SmartyPlugins/outputfilter.ajaxcdn.php
index 7c2de1e65e..9d010f7475 100644
--- a/core/SmartyPlugins/outputfilter.ajaxcdn.php
+++ b/core/SmartyPlugins/outputfilter.ajaxcdn.php
@@ -39,14 +39,18 @@ function smarty_outputfilter_ajaxcdn($source, &$smarty)
$swfobject_version = Zend_Registry::get('config')->General->swfobject_version;
$pattern = array(
+ '~<link rel="stylesheet" type="text/css" href="libs/jquery/themes/([^"]*)" class="ui-theme" />~',
'~<script type="text/javascript" src="libs/jquery/jquery\.js([^"]*)">~',
'~<script type="text/javascript" src="libs/jquery/jquery-ui\.js([^"]*)">~',
+ '~<script type="text/javascript" src="libs/jquery/jquery-ui-18n\.js([^"]*)">~',
'~<script type="text/javascript" src="libs/swfobject/swfobject\.js([^"]*)">~',
);
$replace = array(
+ '<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/'.$jqueryui_version.'/themes/\\1" class="ui-theme" />',
'<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/'.$jquery_version.'/jquery.min.js">',
'<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/'.$jqueryui_version.'/jquery-ui.min.js">',
+ '<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/'.$jqueryui_version.'/i18n/jquery-ui-18n.min.js">',
'<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/swfobject/'.$swfobject_version.'/swfobject.js">',
);
diff --git a/core/TablePartitioning.php b/core/TablePartitioning.php
index 1edcbb4ef4..d74eefff3b 100644
--- a/core/TablePartitioning.php
+++ b/core/TablePartitioning.php
@@ -108,11 +108,7 @@ class Piwik_TablePartitioning_Monthly extends Piwik_TablePartitioning
protected function generateTableName()
{
$config = Zend_Registry::get('config');
- $prefixTables = $config->database->tables_prefix;
-
- $date = date("Y_m", $this->timestamp);
-
- return $prefixTables . $this->tableName . "_" . $date;
+ return $config->database->tables_prefix . $this->tableName . "_" . date("Y_m", $this->timestamp);
}
}
@@ -131,10 +127,6 @@ class Piwik_TablePartitioning_Daily extends Piwik_TablePartitioning
protected function generateTableName()
{
$config = Zend_Registry::get('config');
- $prefixTables = $config->database->tables_prefix;
-
- $date = date("Y_m_d", $this->timestamp);
-
- return $prefixTables . $this->tableName . "_" . $date;
+ return $config->database->tables_prefix . $this->tableName . "_" . date("Y_m_d", $this->timestamp);
}
}
diff --git a/core/Tracker.php b/core/Tracker.php
index e49ecc06c2..d2284c4528 100644
--- a/core/Tracker.php
+++ b/core/Tracker.php
@@ -35,6 +35,7 @@ class Piwik_Tracker
const STATE_LOGGING_DISABLE = 10;
const STATE_EMPTY_REQUEST = 11;
const STATE_TRACK_ONLY = 12;
+ const STATE_NOSCRIPT_REQUEST = 13;
const COOKIE_INDEX_IDVISITOR = 1;
const COOKIE_INDEX_TIMESTAMP_LAST_ACTION = 2;
@@ -110,7 +111,7 @@ class Piwik_Tracker
case self::STATE_EMPTY_REQUEST:
printDebug("Empty request => Piwik page");
- echo "<a href='index.php'>Piwik</a> is a free open source <a href='http://piwik.org'>web analytics</a> alternative to Google analytics.";
+ echo "<a href='/'>Piwik</a> is a free open source <a href='http://piwik.org'>web analytics</a> alternative to Google analytics.";
break;
case self::STATE_TO_REDIRECT_URL:
@@ -121,6 +122,7 @@ class Piwik_Tracker
printDebug("Data push, tracking only");
break;
+ case self::STATE_NOSCRIPT_REQUEST:
case self::STATE_NOTHING_TO_NOTICE:
default:
printDebug("Nothing to notice => default behaviour");
@@ -131,8 +133,10 @@ class Piwik_Tracker
if($GLOBALS['PIWIK_TRACKER_DEBUG'] === true)
{
- self::$db->recordProfiling();
- Piwik::printSqlProfilingReportTracker(self::$db);
+ if(isset(self::$db)) {
+ self::$db->recordProfiling();
+ Piwik::printSqlProfilingReportTracker(self::$db);
+ }
}
self::disconnectDatabase();
@@ -237,7 +241,7 @@ class Piwik_Tracker
if( !isset($GLOBALS['PIWIK_TRACKER_DEBUG']) || !$GLOBALS['PIWIK_TRACKER_DEBUG'] )
{
$trans_gif_64 = "R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
- header("Content-type: image/gif");
+ header("Content-Type: image/gif");
print(base64_decode($trans_gif_64));
}
}
@@ -281,7 +285,7 @@ class Piwik_Tracker
&& count($pluginsTracker) != 0)
{
Piwik_PluginsManager::getInstance()->doNotLoadAlwaysActivatedPlugins();
- Piwik_PluginsManager::getInstance()->setPluginsToLoad( $pluginsTracker['Plugins_Tracker'] );
+ Piwik_PluginsManager::getInstance()->loadPlugins( $pluginsTracker['Plugins_Tracker'] );
printDebug("Loading plugins: { ". implode(",", $pluginsTracker['Plugins_Tracker']) . "}");
}
@@ -328,10 +332,15 @@ class Piwik_Tracker
protected function handleEmptyRequest()
{
- if( count($this->request) == 0)
+ $countParameters = count($this->request);
+ if($countParameters == 0)
{
$this->setState(self::STATE_EMPTY_REQUEST);
}
+ if($countParameters == 1 )
+ {
+ $this->setState(self::STATE_NOSCRIPT_REQUEST);
+ }
}
protected function handleDisabledTracker()
@@ -344,19 +353,22 @@ class Piwik_Tracker
}
}
-function printDebug( $info = '' )
+if(!function_exists('printDebug'))
{
- if(isset($GLOBALS['PIWIK_TRACKER_DEBUG']) && $GLOBALS['PIWIK_TRACKER_DEBUG'])
- {
- if(is_array($info))
- {
- print("<pre>");
- print(var_export($info,true));
- print("</pre>");
- }
- else
- {
- print($info . "<br>\n");
- }
- }
+ function printDebug( $info = '' )
+ {
+ if(isset($GLOBALS['PIWIK_TRACKER_DEBUG']) && $GLOBALS['PIWIK_TRACKER_DEBUG'])
+ {
+ if(is_array($info))
+ {
+ print("<pre>");
+ print(var_export($info,true));
+ print("</pre>");
+ }
+ else
+ {
+ print($info . "<br />\n");
+ }
+ }
+ }
}
diff --git a/core/Tracker/Action.php b/core/Tracker/Action.php
index f7a9445058..e2641f35f1 100644
--- a/core/Tracker/Action.php
+++ b/core/Tracker/Action.php
@@ -65,6 +65,8 @@ class Piwik_Tracker_Action implements Piwik_Tracker_Action_Interface
private $actionType;
private $actionUrl;
+ static private $queryParametersToExclude = array('phpsessid', 'jsessionid', 'sessionid', 'aspsessionid');
+
public function setRequest($requestArray)
{
$this->request = $requestArray;
@@ -117,17 +119,54 @@ class Piwik_Tracker_Action implements Piwik_Tracker_Action_Interface
protected function setActionName($name)
{
+ $name = $this->truncate($name);
$this->actionName = $name;
}
+
protected function setActionType($type)
{
$this->actionType = $type;
}
+
protected function setActionUrl($url)
{
+ $url = self::excludeQueryParametersFromUrl($url, $this->idSite);
+ $url = $this->truncate($url);
$this->actionUrl = $url;
}
+ static public function excludeQueryParametersFromUrl($originalUrl, $idSite)
+ {
+ $website = Piwik_Common::getCacheWebsiteAttributes( $idSite );
+ $originalUrl = Piwik_Common::unsanitizeInputValue($originalUrl);
+ $parsedUrl = @parse_url($originalUrl);
+ if(empty($parsedUrl['query']))
+ {
+ return $originalUrl;
+ }
+ $excludedParameters = isset($website['excluded_parameters']) ? $website['excluded_parameters'] : array();
+ $parametersToExclude = array_merge($excludedParameters, self::$queryParametersToExclude);
+
+ $parametersToExclude = array_map('strtolower', $parametersToExclude);
+ $queryParameters = Piwik_Common::getArrayFromQueryString($parsedUrl['query']);
+
+ $validQuery = '';
+ $separator = '&';
+ foreach($queryParameters as $name => $value)
+ {
+ if(!in_array(strtolower($name), $parametersToExclude))
+ {
+ $validQuery .= $name.'='.$value.$separator;
+ }
+ }
+ $parsedUrl['query'] = substr($validQuery,0,-strlen($separator));
+ $url = Piwik_Common::getParseUrlReverse($parsedUrl);
+ printDebug('Excluded parameters "'.implode(',',$excludedParameters).'" from URL.
+ Before was <br/><code>"'.$originalUrl.'"</code>, <br/>
+ After is <br/><code>"'.$url.'"</code>');
+ return $url;
+ }
+
public function init()
{
$info = $this->extractUrlAndActionNameFromRequest();
@@ -136,6 +175,12 @@ class Piwik_Tracker_Action implements Piwik_Tracker_Action_Interface
$this->setActionUrl($info['url']);
}
+ protected function truncate( $label )
+ {
+ $limit = Piwik_Tracker_Config::getInstance()->Tracker['page_maximum_length'];
+ return substr($label, 0, $limit);
+ }
+
/**
* Loads the idaction of the current action name and the current action url.
* These idactions are used in the visitor logging table to link the visit information
@@ -288,8 +333,10 @@ class Piwik_Tracker_Action implements Piwik_Tracker_Action_Interface
$actionType = self::TYPE_ACTION_URL;
$url = Piwik_Common::getRequestVar( 'url', '', 'string', $this->request);
- // get the delimiter, by default '/'
- $actionCategoryDelimiter = Piwik_Tracker_Config::getInstance()->General['action_category_delimiter'];
+ // get the delimiter, by default '/'; BC, we read the old action_category_delimiter first (see #1067)
+ $actionCategoryDelimiter = isset(Piwik_Tracker_Config::getInstance()->General['action_category_delimiter'])
+ ? Piwik_Tracker_Config::getInstance()->General['action_category_delimiter']
+ : Piwik_Tracker_Config::getInstance()->General['action_url_category_delimiter'];
// create an array of the categories delimited by the delimiter
$split = explode($actionCategoryDelimiter, $actionName);
diff --git a/core/Tracker/Config.php b/core/Tracker/Config.php
index 1fd8a74a19..8d9e6f7499 100644
--- a/core/Tracker/Config.php
+++ b/core/Tracker/Config.php
@@ -48,36 +48,39 @@ class Piwik_Tracker_Config
* @var array
*/
public $config = array();
- protected $init = false;
+ protected $initialized = false;
public function init($pathIniFileUser = null, $pathIniFileGlobal = null)
{
+ if(is_null($pathIniFileGlobal))
+ {
+ $pathIniFileGlobal = PIWIK_USER_PATH . '/config/global.ini.php';
+ }
+ $this->configGlobal = _parse_ini_file($pathIniFileGlobal, true);
+
if(is_null($pathIniFileUser))
{
$pathIniFileUser = PIWIK_USER_PATH . '/config/config.ini.php';
}
- if(is_null($pathIniFileGlobal))
+ $this->configUser = _parse_ini_file($pathIniFileUser, true);
+ if($this->configUser)
{
- $pathIniFileGlobal = PIWIK_USER_PATH . '/config/global.ini.php';
- }
- $this->configUser = parse_ini_file($pathIniFileUser, true);
- $this->configGlobal = parse_ini_file($pathIniFileGlobal, true);
-
- foreach($this->configUser as $section => &$sectionValues)
- {
- foreach($sectionValues as $name => &$value)
- {
- if(is_array($value))
- {
- $value = array_map("html_entity_decode", $value);
- }
- else
+ foreach($this->configUser as $section => &$sectionValues)
+ {
+ foreach($sectionValues as $name => &$value)
{
- $value = html_entity_decode($value);
+ if(is_array($value))
+ {
+ $value = array_map("html_entity_decode", $value);
+ }
+ else
+ {
+ $value = html_entity_decode($value);
+ }
}
}
}
- $this->init = true;
+ $this->initialized = true;
}
/**
@@ -90,7 +93,7 @@ class Piwik_Tracker_Config
*/
public function __get( $name )
{
- if(!$this->init)
+ if(!$this->initialized)
{
$this->init();
}
diff --git a/core/Tracker/Db.php b/core/Tracker/Db.php
index 01291712d1..331fb3593a 100644
--- a/core/Tracker/Db.php
+++ b/core/Tracker/Db.php
@@ -155,6 +155,25 @@ abstract class Piwik_Tracker_Db
}
/**
+ * This function is a proxy to fetch(), used to maintain compatibility with Zend_Db interface
+ * @see fetch()
+ */
+ public function fetchOne( $query, $parameters = array() )
+ {
+ $result = $this->fetch($query, $parameters);
+ return is_array($result) && !empty($result) ? reset($result) : false;
+ }
+
+ /**
+ * This function is a proxy to fetch(), used to maintain compatibility with Zend_Db + PDO interface
+ * @see fetch()
+ */
+ public function exec( $query, $parameters = array() )
+ {
+ return $this->fetch($query, $parameters);
+ }
+
+ /**
* Return number of affected rows in last query
*
* @param mixed $queryResult Result from query()
diff --git a/core/Tracker/GoalManager.php b/core/Tracker/GoalManager.php
index f1ff810891..29e6d508db 100644
--- a/core/Tracker/GoalManager.php
+++ b/core/Tracker/GoalManager.php
@@ -52,7 +52,7 @@ class Piwik_Tracker_GoalManager
return $goal;
}
}
- throw new Exception("The goal id = $idGoal couldn't be found.");
+ throw new Exception(Piwik_TranslateException('General_ExceptionGoalNotFound', array($idGoal)));
}
static public function getGoalIds( $idSite )
@@ -71,14 +71,14 @@ class Piwik_Tracker_GoalManager
return Piwik_PluginsManager::getInstance()->isPluginActivated('Goals');
}
- //TODO does this code work for manually triggered goals, with custom revenue?
function detectGoalsMatchingUrl($idSite, $action)
{
if(!$this->isGoalPluginEnabled())
{
return false;
}
- $url = $action->getActionUrl();
+ $sanitizedUrl = $action->getActionUrl();
+ $url = htmlspecialchars_decode($sanitizedUrl);
$actionType = $action->getActionType();
$goals = $this->getGoalDefinitions($idSite);
foreach($goals as $goal)
@@ -129,12 +129,12 @@ class Piwik_Tracker_GoalManager
$match = ($matched == 0);
break;
default:
- throw new Exception("Pattern type $pattern_type not valid.");
+ throw new Exception(Piwik_TranslateException('General_ExceptionInvalidGoalPattern', array($pattern_type)));
break;
}
if($match)
{
- $goal['url'] = $url;
+ $goal['url'] = $sanitizedUrl;
$this->convertedGoals[] = $goal;
}
}
@@ -154,7 +154,9 @@ class Piwik_Tracker_GoalManager
return false;
}
$goal = $goals[$idGoal];
- $goal['url'] = Piwik_Common::getRequestVar( 'url', '', 'string', $request);
+
+ $url = Piwik_Common::getRequestVar( 'url', '', 'string', $request);
+ $goal['url'] = Piwik_Tracker_Action::excludeQueryParametersFromUrl($url, $idSite);
$goal['revenue'] = Piwik_Common::getRequestVar('revenue', $goal['revenue'], 'float', $request);
$this->convertedGoals[] = $goal;
return true;
@@ -162,15 +164,22 @@ class Piwik_Tracker_GoalManager
function recordGoals($visitorInformation, $action)
{
- $location_country = isset($visitorInformation['location_country']) ? $visitorInformation['location_country'] : Piwik_Common::getCountry(Piwik_Common::getBrowserLanguage(), $enableLanguageToCountryGuess = Piwik_Tracker_Config::getInstance()->Tracker['enable_language_to_country_guess']);
- $location_continent = isset($visitorInformation['location_continent']) ? $visitorInformation['location_continent'] : Piwik_Common::getContinent($location_country);
+ $location_country = isset($visitorInformation['location_country'])
+ ? $visitorInformation['location_country']
+ : Piwik_Common::getCountry(
+ Piwik_Common::getBrowserLanguage(),
+ $enableLanguageToCountryGuess = Piwik_Tracker_Config::getInstance()->Tracker['enable_language_to_country_guess'], $visitorInformation['location_ip']
+ );
+
+ $location_continent = isset($visitorInformation['location_continent'])
+ ? $visitorInformation['location_continent']
+ : Piwik_Common::getContinent($location_country);
$goal = array(
'idvisit' => $visitorInformation['idvisit'],
'idsite' => $visitorInformation['idsite'],
'visitor_idcookie' => $visitorInformation['visitor_idcookie'],
'server_time' => Piwik_Tracker::getDatetimeFromTimestamp($visitorInformation['visit_last_action_time']),
- 'visit_server_date' => $visitorInformation['visit_server_date'],
'location_country' => $location_country,
'location_continent'=> $location_continent,
'visitor_returning' => $this->cookie->get( Piwik_Tracker::COOKIE_INDEX_VISITOR_RETURNING ),
@@ -207,14 +216,14 @@ class Piwik_Tracker_GoalManager
try {
Piwik_Tracker::getDatabase()->query(
- "INSERT INTO " . Piwik_Common::prefixTable('log_conversion') . " ($fields)
+ "INSERT IGNORE INTO " . Piwik_Common::prefixTable('log_conversion') . " ($fields)
VALUES ($bindFields) ", array_values($newGoal)
);
} catch( Exception $e) {
- if(Piwik_Tracker::isErrNo($e, '1062'))
+ if(Piwik_Tracker::getDatabase()->isErrNo($e, '1062'))
{
// integrity violation when same visit converts to the same goal twice
- printDebug("--> Goal already recorded for this (idvisit, idgoal)");
+ printDebug("--&gt; Goal already recorded for this (idvisit, idgoal)");
}
else
{
diff --git a/core/Tracker/Visit.php b/core/Tracker/Visit.php
index 18c636f483..b216f742e7 100644
--- a/core/Tracker/Visit.php
+++ b/core/Tracker/Visit.php
@@ -59,9 +59,10 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$this->request = $requestArray;
$idsite = Piwik_Common::getRequestVar('idsite', 0, 'int', $this->request);
+ Piwik_PostEvent('Tracker.setRequest.idSite', $idsite);
if($idsite <= 0)
{
- throw new Exception("The 'idsite' in the request is invalid.");
+ throw new Exception(Piwik_TranslateException('General_ExceptionInvalidIdsite'));
}
$this->idsite = $idsite;
}
@@ -88,6 +89,9 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
*/
public function handle()
{
+ // the IP is needed by isExcluded() and GoalManager->recordGoals()
+ $this->visitorInfo['location_ip'] = Piwik_Common::getIp();
+
if($this->isExcluded())
{
return;
@@ -106,6 +110,7 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
// if we find a idgoal in the URL, but then the goal is not valid, this is most likely a fake request
if(!$someGoalsConverted)
{
+ printDebug('Invalid goal tracking request for goal id = '.$idGoal);
unset($goalManager);
return;
}
@@ -127,9 +132,10 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$isLastActionInTheSameVisit = $this->isLastActionInTheSameVisit();
// Known visit when:
- // - the visitor has the Piwik cookie with the idcookie ID used by Piwik to match the visitor
- // OR
- // - the visitor doesn't have the Piwik cookie but could be match using heuristics @see recognizeTheVisitor()
+ // ( - the visitor has the Piwik cookie with the idcookie ID used by Piwik to match the visitor
+ // OR
+ // - the visitor doesn't have the Piwik cookie but could be match using heuristics @see recognizeTheVisitor()
+ // )
// AND
// - the last page view for this visitor was less than 30 minutes ago @see isLastActionInTheSameVisit()
if( $this->isVisitorKnown()
@@ -232,26 +238,31 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
visit_total_actions = visit_total_actions + 1, ";
$this->visitorInfo['visit_exit_idaction_url'] = $actionUrlId;
}
- $result = Piwik_Tracker::getDatabase()->query("/* SHARDING_ID_SITE = ". $this->idsite ." */
+ $sqlQuery = "/* SHARDING_ID_SITE = ". $this->idsite ." */
UPDATE ". Piwik_Common::prefixTable('log_visit')."
SET $sqlActionIdUpdate
$sqlUpdateGoalConverted
visit_last_action_time = ?,
- visit_total_time = UNIX_TIMESTAMP(visit_last_action_time) - UNIX_TIMESTAMP(visit_first_action_time)
- WHERE idvisit = ?
+ visit_total_time = ?
+ WHERE idsite = ?
+ AND idvisit = ?
AND visitor_idcookie = ?
- LIMIT 1",
- array( $datetimeServer,
- $this->visitorInfo['idvisit'],
- $this->visitorInfo['visitor_idcookie'] )
- );
+ LIMIT 1";
+ $sqlBind = array( $datetimeServer,
+ $visitTotalTime = $this->getCurrentTimestamp() - $this->visitorInfo['visit_first_action_time'],
+ $this->idsite,
+ $this->visitorInfo['idvisit'],
+ $this->visitorInfo['visitor_idcookie'] );
+
+ $result = Piwik_Tracker::getDatabase()->query($sqlQuery, $sqlBind);
+
+ printDebug('Updating visitor with idvisit='.$this->visitorInfo['idvisit'].', setting visit_last_action_time='.$datetimeServer.' and visit_total_time='.$visitTotalTime);
if(Piwik_Tracker::getDatabase()->rowCount($result) == 0)
{
throw new Piwik_Tracker_Visit_VisitorNotFoundInDatabase("The visitor with visitor_idcookie=".$this->visitorInfo['visitor_idcookie']." and idvisit=".$this->visitorInfo['idvisit']." wasn't found in the DB, we fallback to a new visitor");
}
$this->visitorInfo['idsite'] = $this->idsite;
- $this->visitorInfo['visit_server_date'] = $this->getCurrentDate();
// will be updated in cookie
$this->visitorInfo['time_spent_ref_action'] = $serverTime - $this->visitorInfo['visit_last_action_time'];
@@ -275,7 +286,6 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
.':'. Piwik_Common::getRequestVar( 'm', $this->getCurrentDate("i"), 'int', $this->request)
.':'. Piwik_Common::getRequestVar( 's', $this->getCurrentDate("s"), 'int', $this->request);
$serverTime = $this->getCurrentTimestamp();
- $serverDate = $this->getCurrentDate();
$idcookie = $this->getVisitorIdcookie();
$returningVisitor = $this->isVisitorKnown() ? 1 : 0;
@@ -283,47 +293,49 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$defaultTimeOnePageVisit = Piwik_Tracker_Config::getInstance()->Tracker['default_time_one_page_visit'];
$userInfo = $this->getUserSettingsInformation();
- $country = Piwik_Common::getCountry($userInfo['location_browser_lang'], $enableLanguageToCountryGuess = Piwik_Tracker_Config::getInstance()->Tracker['enable_language_to_country_guess']);
+ $country = Piwik_Common::getCountry($userInfo['location_browser_lang'],
+ $enableLanguageToCountryGuess = Piwik_Tracker_Config::getInstance()->Tracker['enable_language_to_country_guess'],
+ $this->getVisitorIp());
$refererInfo = $this->getRefererInformation();
/**
* Save the visitor
*/
$this->visitorInfo = array(
- 'idsite' => $this->idsite,
- 'visitor_localtime' => $localTime,
- 'visitor_idcookie' => $idcookie,
- 'visitor_returning' => $returningVisitor,
- 'visit_first_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($serverTime),
- 'visit_last_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($serverTime),
- 'visit_server_date' => $serverDate,
- 'visit_entry_idaction_url' => $actionUrlId,
- 'visit_exit_idaction_url' => $actionUrlId,
- 'visit_total_actions' => 1,
- 'visit_total_time' => $defaultTimeOnePageVisit,
- 'visit_goal_converted' => $someGoalsConverted ? 1: 0,
- 'referer_type' => $refererInfo['referer_type'],
- 'referer_name' => $refererInfo['referer_name'],
- 'referer_url' => $refererInfo['referer_url'],
- 'referer_keyword' => $refererInfo['referer_keyword'],
- 'config_md5config' => $userInfo['config_md5config'],
- 'config_os' => $userInfo['config_os'],
- 'config_browser_name' => $userInfo['config_browser_name'],
- 'config_browser_version' => $userInfo['config_browser_version'],
- 'config_resolution' => $userInfo['config_resolution'],
- 'config_pdf' => $userInfo['config_pdf'],
- 'config_flash' => $userInfo['config_flash'],
- 'config_java' => $userInfo['config_java'],
- 'config_director' => $userInfo['config_director'],
- 'config_quicktime' => $userInfo['config_quicktime'],
- 'config_realplayer' => $userInfo['config_realplayer'],
- 'config_windowsmedia' => $userInfo['config_windowsmedia'],
- 'config_gears' => $userInfo['config_gears'],
- 'config_silverlight' => $userInfo['config_silverlight'],
- 'config_cookie' => $userInfo['config_cookie'],
- 'location_ip' => $userInfo['location_ip'],
- 'location_browser_lang' => $userInfo['location_browser_lang'],
- 'location_country' => $country,
+ 'idsite' => $this->idsite,
+ 'visitor_localtime' => $localTime,
+ 'visitor_idcookie' => $idcookie,
+ 'visitor_returning' => $returningVisitor,
+ 'visit_server_date' => $this->getCurrentDate(),
+ 'visit_first_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($serverTime),
+ 'visit_last_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($serverTime),
+ 'visit_entry_idaction_url' => $actionUrlId,
+ 'visit_exit_idaction_url' => $actionUrlId,
+ 'visit_total_actions' => 1,
+ 'visit_total_time' => $defaultTimeOnePageVisit,
+ 'visit_goal_converted' => $someGoalsConverted ? 1: 0,
+ 'referer_type' => $refererInfo['referer_type'],
+ 'referer_name' => $refererInfo['referer_name'],
+ 'referer_url' => $refererInfo['referer_url'],
+ 'referer_keyword' => $refererInfo['referer_keyword'],
+ 'config_md5config' => $userInfo['config_md5config'],
+ 'config_os' => $userInfo['config_os'],
+ 'config_browser_name' => $userInfo['config_browser_name'],
+ 'config_browser_version' => $userInfo['config_browser_version'],
+ 'config_resolution' => $userInfo['config_resolution'],
+ 'config_pdf' => $userInfo['config_pdf'],
+ 'config_flash' => $userInfo['config_flash'],
+ 'config_java' => $userInfo['config_java'],
+ 'config_director' => $userInfo['config_director'],
+ 'config_quicktime' => $userInfo['config_quicktime'],
+ 'config_realplayer' => $userInfo['config_realplayer'],
+ 'config_windowsmedia' => $userInfo['config_windowsmedia'],
+ 'config_gears' => $userInfo['config_gears'],
+ 'config_silverlight' => $userInfo['config_silverlight'],
+ 'config_cookie' => $userInfo['config_cookie'],
+ 'location_ip' => $this->getVisitorIp(),
+ 'location_browser_lang' => $userInfo['location_browser_lang'],
+ 'location_country' => $country,
);
Piwik_PostEvent('Tracker.newVisitorInformation', $this->visitorInfo);
@@ -389,8 +401,9 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
*/
protected function getVisitorIp()
{
- return Piwik_Common::getIp();
+ return $this->visitorInfo['location_ip'];
}
+
/**
* Returns the visitor's browser (user agent)
@@ -433,20 +446,62 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
*/
protected function isExcluded()
{
+ $excluded = false;
+
$ip = $this->getVisitorIp();
$ua = $this->getUserAgent();
/*
- * Live/Bing bot and Googlebot are evolving to detect cloaked websites.
+ * Live/Bing/MSN bot and Googlebot are evolving to detect cloaked websites.
* As a result, these sophisticated bots exhibit characteristics of
* browsers (cookies enabled, executing JavaScript, etc).
*/
- $excluded = preg_match('/65\.55/', long2ip($ip)) // Live/Bing
- || preg_match('/Googlebot/', $ua); // Googlebot
-
- /* custom filters can override the built-in filter above */
+ $dotIp = long2ip($ip);
+ if (strpos($dotIp, '65.55') === 0 // Live/Bing
+ || strpos($dotIp, '207.46') === 0 // MSN
+ || strpos($ua, 'Googlebot') !== false) // Googlebot
+ {
+ printDebug('Search bot detected, visit excluded');
+ $excluded = true;
+ }
+
+
+ /*
+ * Requests built with piwik.js will contain a rec=1 parameter. This is used as
+ * an indication that the request is made by a JS enabled device. By default, Piwik
+ * doesn't track non-JS visitors.
+ */
+ if(!$excluded)
+ {
+ $parameterForceRecord = 'rec';
+ $toRecord = Piwik_Common::getRequestVar($parameterForceRecord, false, 'int');
+ if(!$toRecord)
+ {
+ printDebug('GET parameter '.$parameterForceRecord.' not found in URL, request excluded');
+ $excluded = true;
+ }
+ }
+
+ /* custom filters can override the built-in filters above */
Piwik_PostEvent('Tracker.Visit.isExcluded', $excluded);
-
+
+ /*
+ * Following exclude operations happen after the hook.
+ * These are of higher priority and should not be overwritten by plugins.
+ */
+
+ // Checking if the Piwik ignore cookie is set
+ if(!$excluded)
+ {
+ $excluded = $this->isIgnoreCookieFound();
+ }
+
+ // Checking for excluded IPs
+ if(!$excluded)
+ {
+ $excluded = $this->isVisitorIpExcluded($ip);
+ }
+
if($excluded)
{
printDebug("Visitor excluded.");
@@ -455,8 +510,47 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
return false;
}
+
+ /**
+ * Looks for the ignore cookie that users can set in the Piwik admin screen.
+ * @return bool
+ */
+ protected function isIgnoreCookieFound()
+ {
+ $cookie = new Piwik_Cookie($this->getIgnoreVisitsCookieName());
+ if($cookie->isCookieFound())
+ {
+ printDebug('Piwik ignore cookie was found, visit not tracked.');
+ return true;
+ }
+ return false;
+ }
/**
+ * Checks if the visitor ip is in the excluded list
+ *
+ * @param $ip Long IP
+ * @return bool
+ */
+ protected function isVisitorIpExcluded($ip)
+ {
+ $websiteAttributes = Piwik_Common::getCacheWebsiteAttributes( $this->idsite );
+ if(!empty($websiteAttributes['excluded_ips']))
+ {
+ foreach($websiteAttributes['excluded_ips'] as $ipRange)
+ {
+ if($ip >= $ipRange[0]
+ && $ip <= $ipRange[1])
+ {
+ printDebug('Visitor IP '.long2ip($ip).' is excluded from being tracked');
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
* Returns the cookie name used for the Piwik Tracker cookie
*
* @return string
@@ -467,13 +561,33 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
}
/**
+ * Returns the cookie name used to ignore/exclude webmaster visits
+ *
+ * @return string
+ */
+ protected function getIgnoreVisitsCookieName()
+ {
+ return Piwik_Tracker_Config::getInstance()->Tracker['ignore_visits_cookie_name'];
+ }
+
+ /**
* Returns the cookie expiration date.
*
* @return int
*/
protected function getCookieExpire()
{
- return time() + Piwik_Tracker_Config::getInstance()->Tracker['cookie_expire'];
+ return $this->getCurrentTimestamp() + Piwik_Tracker_Config::getInstance()->Tracker['cookie_expire'];
+ }
+
+ /**
+ * Returns cookie path
+ *
+ * @return string
+ */
+ protected function getCookiePath()
+ {
+ return Piwik_Tracker_Config::getInstance()->Tracker['cookie_path'];
}
/**
@@ -508,7 +622,7 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
protected function recognizeTheVisitor()
{
$this->visitorKnown = false;
- $this->setCookie( new Piwik_Cookie( $this->getCookieName(), $this->getCookieExpire() ) );
+ $this->setCookie( new Piwik_Cookie( $this->getCookieName(), $this->getCookieExpire(), $this->getCookiePath() ) );
/*
* Case the visitor has the piwik cookie.
@@ -551,8 +665,8 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$visitRow = Piwik_Tracker::getDatabase()->fetch(
" SELECT visitor_idcookie,
- UNIX_TIMESTAMP(visit_last_action_time) as visit_last_action_time,
- UNIX_TIMESTAMP(visit_first_action_time) as visit_first_action_time,
+ visit_last_action_time,
+ visit_first_action_time,
idvisit,
visit_exit_idaction_url
FROM ".Piwik_Common::prefixTable('log_visit').
@@ -566,14 +680,14 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
&& count($visitRow) > 0)
{
$this->visitorInfo['visitor_idcookie'] = $visitRow['visitor_idcookie'];
- $this->visitorInfo['visit_last_action_time'] = $visitRow['visit_last_action_time'];
- $this->visitorInfo['visit_first_action_time'] = $visitRow['visit_first_action_time'];
+ $this->visitorInfo['visit_last_action_time'] = strtotime($visitRow['visit_last_action_time']);
+ $this->visitorInfo['visit_first_action_time'] = strtotime($visitRow['visit_first_action_time']);
$this->visitorInfo['idvisit'] = $visitRow['idvisit'];
$this->visitorInfo['visit_exit_idaction_url'] = $visitRow['visit_exit_idaction_url'];
$this->visitorKnown = true;
- printDebug("The visitor is known because of his userSettings+IP (idcookie = {$visitRow['visitor_idcookie']}, idvisit = {$this->visitorInfo['idvisit']}, last action = ".date("r", $this->visitorInfo['visit_last_action_time']).") ");
+ printDebug("The visitor is known because of his userSettings+IP (idcookie = {$visitRow['visitor_idcookie']}, idvisit = {$this->visitorInfo['idvisit']}, last action = ".date("r", $this->visitorInfo['visit_last_action_time']).", first action = ".date("r", $this->visitorInfo['visit_first_action_time']) .")");
}
}
}
@@ -614,8 +728,6 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$resolution = Piwik_Common::getRequestVar('res', 'unknown', 'string', $this->request);
- $ip = $this->getVisitorIp();
-
$browserLang = Piwik_Common::getBrowserLanguage();
$configurationHash = $this->getConfigHash(
@@ -633,7 +745,7 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$plugin_Gears,
$plugin_Silverlight,
$plugin_Cookie,
- $ip,
+ $this->getVisitorIp(),
$browserLang);
$this->userSettingsInformation = array(
@@ -652,7 +764,6 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
'config_gears' => $plugin_Gears,
'config_silverlight' => $plugin_Silverlight,
'config_cookie' => $plugin_Cookie,
- 'location_ip' => $ip,
'location_browser_lang' => $browserLang,
);
diff --git a/core/Tracker/javascriptTag.tpl b/core/Tracker/javascriptTag.tpl
index 6730f1b1b7..f0370aca3d 100644
--- a/core/Tracker/javascriptTag.tpl
+++ b/core/Tracker/javascriptTag.tpl
@@ -8,5 +8,5 @@ try {
piwikTracker.trackPageView();
piwikTracker.enableLinkTracking();
} catch( err ) {}
-</script><noscript><p><img src="http://{$piwikUrl}piwik.php?idsite={$idSite}" style="border:0" alt=""/></p></noscript>
+</script><noscript><p><img src="http://{$piwikUrl}piwik.php?idsite={$idSite}" style="border:0" alt="" /></p></noscript>
<!-- End Piwik Tag -->
diff --git a/core/Translate.php b/core/Translate.php
index 9d4b3a3efb..adc3379cf4 100644
--- a/core/Translate.php
+++ b/core/Translate.php
@@ -47,8 +47,12 @@ class Piwik_Translate
{
return;
}
-
- require PIWIK_INCLUDE_PATH . '/lang/' . $language . '.php';
+ $path = PIWIK_INCLUDE_PATH . '/lang/' . $language . '.php';
+ if(!is_readable($path))
+ {
+ throw new Exception(Piwik_TranslateException('General_ExceptionLanguageFileNotFound', array($language)));
+ }
+ require $path;
$this->mergeTranslationArray($translations);
$this->setLocale();
}
@@ -74,9 +78,11 @@ class Piwik_Translate
{
return $language;
}
+
Piwik_PostEvent('Translate.getLanguageToLoad', $language);
- if(is_null($language) || empty($language))
+ $language = Piwik_Common::getRequestVar('language', is_null($language) ? '' : $language, 'string');
+ if(empty($language))
{
$language = Zend_Registry::get('config')->General->default_language;
}
@@ -110,7 +116,7 @@ class Piwik_Translate
$moduleRegex .= $module.'|';
}
$moduleRegex = substr($moduleRegex, 0, -1);
- $moduleRegex .= ')_([^_]+)_js$#i';
+ $moduleRegex .= ')_.*_js$#i';
foreach($GLOBALS['Piwik_translations'] as $key => $value)
{
@@ -124,14 +130,22 @@ class Piwik_Translate
'for(var i in translations) { piwik_translations[i] = translations[i];} ';
$js .= 'function _pk_translate(translationStringId) { '.
'if( typeof(piwik_translations[translationStringId]) != \'undefined\' ){ return piwik_translations[translationStringId]; }'.
- 'return "The string "+translationStringId+" was not loaded in javascript. Make sure it is prefixed with _js";}';
+ 'return "The string "+translationStringId+" was not loaded in javascript. Make sure it is suffixed with _js and that you called {loadJavascriptTranslations plugins=\'\$YOUR_PLUGIN_NAME\'} before your javascript code.";}';
return $js;
}
+ /**
+ * Set locale
+ *
+ * @see http://php.net/setlocale
+ */
private function setLocale()
{
- setlocale(LC_ALL, $GLOBALS['Piwik_translations']['General_Locale']);
+ $locale = $GLOBALS['Piwik_translations']['General_Locale'];
+ $locale_variant = str_replace('UTF-8', 'UTF8', $locale);
+ setlocale(LC_ALL, $locale, $locale_variant);
+ setlocale(LC_CTYPE, '');
}
}
diff --git a/core/UpdateCheck.php b/core/UpdateCheck.php
index c5ebe07874..8e7b09b581 100644
--- a/core/UpdateCheck.php
+++ b/core/UpdateCheck.php
@@ -17,7 +17,7 @@
*/
class Piwik_UpdateCheck
{
- const CHECK_INTERVAL = 86400;
+ const CHECK_INTERVAL = 28800; // every 8 hours
const LAST_TIME_CHECKED = 'UpdateCheck_LastTimeChecked';
const LATEST_VERSION = 'UpdateCheck_LatestVersion';
const PIWIK_HOST = 'http://api.piwik.org/1.0/getLatestVersion/';
@@ -25,29 +25,34 @@ class Piwik_UpdateCheck
/**
* Check for a newer version
+ *
+ * @param bool $force Force check
*/
- public static function check()
+ public static function check($force = false)
{
$lastTimeChecked = Piwik_GetOption(self::LAST_TIME_CHECKED);
- if($lastTimeChecked === false
+ if($force || $lastTimeChecked === false
|| time() - self::CHECK_INTERVAL > $lastTimeChecked )
{
+ // set the time checked first, so that parallel Piwik requests don't all trigger the http requests
+ Piwik_SetOption(self::LAST_TIME_CHECKED, time(), $autoload = 1);
$parameters = array(
'piwik_version' => Piwik_Version::VERSION,
'php_version' => phpversion(),
'url' => Piwik_Url::getCurrentUrlWithoutQueryString(),
'trigger' => Piwik_Common::getRequestVar('module','','string'),
+ 'timezone' => Piwik_SitesManager_API::getInstance()->getDefaultTimezone(),
);
$url = self::PIWIK_HOST . "?" . http_build_query($parameters, '', '&');
$timeout = self::SOCKET_TIMEOUT;
try {
- $latestVersion = Piwik::sendHttpRequest($url, $timeout);
+ $latestVersion = Piwik_Http::sendHttpRequest($url, $timeout);
Piwik_SetOption(self::LATEST_VERSION, $latestVersion);
} catch(Exception $e) {
// e.g., disable_functions = fsockopen; allow_url_open = Off
+ Piwik_SetOption(self::LATEST_VERSION, '');
}
- Piwik_SetOption(self::LAST_TIME_CHECKED, time(), $autoload = 1);
}
}
diff --git a/core/Updater.php b/core/Updater.php
index 695826daa5..b45a16436f 100644
--- a/core/Updater.php
+++ b/core/Updater.php
@@ -10,9 +10,6 @@
* @package Piwik
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see core/Option.php
*/
@@ -61,13 +58,23 @@ class Piwik_Updater
public function recordComponentSuccessfullyUpdated($name, $version)
{
try {
- Piwik_SetOption('version_'.$name, $version, $autoload = 1);
+ Piwik_SetOption($this->getNameInOptionTable($name), $version, $autoload = 1);
} catch(Exception $e) {
// case when the option table is not yet created (before 0.2.10)
}
}
/**
+ * Returns the flag name to use in the option table to record current schema version
+ * @param string $name
+ * @return string
+ */
+ private function getNameInOptionTable($name)
+ {
+ return 'version_'.$name;
+ }
+
+ /**
* Returns a list of components (core | plugin) that need to run through the upgrade process.
*
* @return array( componentName => array( file1 => version1, [...]), [...])
@@ -80,34 +87,79 @@ class Piwik_Updater
}
/**
+ * Component has a new version?
+ *
+ * @param string $componentName
+ * @return bool TRUE if compoment is to be updated; FALSE if not
+ */
+ public function hasNewVersion($componentName)
+ {
+ return isset($this->componentsWithNewVersion) &&
+ isset($this->componentsWithNewVersion[$componentName]);
+ }
+
+ /**
+ * Returns the list of SQL queries that would be executed during the update
+ *
+ * @return array of SQL queries
+ */
+ public function getSqlQueriesToExecute()
+ {
+ $queries = array();
+ foreach($this->componentsWithUpdateFile as $componentName => $componentUpdateInfo)
+ {
+ foreach($componentUpdateInfo as $file => $fileVersion)
+ {
+ require_once $file; // prefixed by PIWIK_INCLUDE_PATH
+
+ $className = $this->getUpdateClassName($componentName, $fileVersion);
+ if(class_exists($className, false))
+ {
+ $queriesForComponent = call_user_func( array($className, 'getSql'));
+ foreach($queriesForComponent as $query => $error) {
+ $queries[] = $query.';';
+ }
+ }
+ }
+ // unfortunately had to extract this query from the Piwik_Option class
+ $queries[] = 'UPDATE '.Piwik_Common::prefixTable('option').'
+ SET option_value = "' .$fileVersion.'"
+ WHERE option_name = "'. $this->getNameInOptionTable($componentName).'";';
+ }
+ return $queries;
+ }
+
+ private function getUpdateClassName($componentName, $fileVersion)
+ {
+ $suffix = strtolower(str_replace(array('-','.'), '_', $fileVersion));
+ if($componentName == 'core')
+ {
+ return 'Piwik_Updates_' . $suffix;
+ }
+ return 'Piwik_'. $componentName .'_Updates_' . $suffix;
+ }
+
+ /**
* Update the named component
*
- * @param string $name
+ * @param string $componentName 'core', or plugin name
* @return array of warning strings if applicable
*/
- public function update($name)
+ public function update($componentName)
{
$warningMessages = array();
- foreach($this->componentsWithUpdateFile[$name] as $file => $fileVersion)
+ foreach($this->componentsWithUpdateFile[$componentName] as $file => $fileVersion)
{
try {
require_once $file; // prefixed by PIWIK_INCLUDE_PATH
- if($name == 'core')
- {
- $className = 'Piwik_Updates_' . str_replace('.', '_', $fileVersion);
- }
- else
- {
- $className = 'Piwik_'. $name .'_Updates_' . str_replace('.', '_', $fileVersion);
- }
-
+ $className = $this->getUpdateClassName($componentName, $fileVersion);
if(class_exists($className, false))
{
call_user_func( array($className, 'update') );
}
- $this->recordComponentSuccessfullyUpdated($name, $fileVersion);
+ $this->recordComponentSuccessfullyUpdated($componentName, $fileVersion);
} catch( Piwik_Updater_UpdateErrorException $e) {
throw $e;
} catch( Exception $e) {
@@ -116,7 +168,7 @@ class Piwik_Updater
}
// to debug, create core/Updates/X.php, update the core/Version.php, throw an Exception in the try, and comment the following line
- $this->recordComponentSuccessfullyUpdated($name, $this->componentsWithNewVersion[$name][self::INDEX_NEW_VERSION]);
+ $this->recordComponentSuccessfullyUpdated($componentName, $this->componentsWithNewVersion[$componentName][self::INDEX_NEW_VERSION]);
return $warningMessages;
}
@@ -145,12 +197,16 @@ class Piwik_Updater
$files = glob( $pathToUpdates );
if($files === false)
{
- continue;
+ $files = array();
}
+
foreach( $files as $file)
{
$fileVersion = basename($file, '.php');
- if(version_compare($currentVersion, $fileVersion) == -1)
+ if( // if the update is from a newer version
+ version_compare($currentVersion, $fileVersion) == -1
+ // but we don't execute updates from non existing future releases
+ && version_compare($fileVersion, $newVersion) <= 0)
{
$componentsWithUpdateFile[$name][$file] = $fileVersion;
}
@@ -246,7 +302,8 @@ class Piwik_Updater
try {
Piwik_Exec( $update );
} catch(Exception $e) {
- if(($ignoreError === false) || !Zend_Registry::get('db')->isErrNo($e, $ignoreError))
+ if(($ignoreError === false)
+ || !Zend_Registry::get('db')->isErrNo($e, $ignoreError))
{
$message = $file .":\nError trying to execute the query '". $update ."'.\nThe error was: ". $e->getMessage();
throw new Piwik_Updater_UpdateErrorException($message);
diff --git a/core/iUpdate.php b/core/Updates.php
index 5b9888558c..3d5e4df537 100644
--- a/core/iUpdate.php
+++ b/core/Updates.php
@@ -11,15 +11,26 @@
*/
/**
- * Interface to be implemented by update scripts
+ * Abstract class for update scripts
*
* @example core/Updates/0.4.2.php
* @package Piwik
*/
-interface Piwik_iUpdate
+abstract class Piwik_Updates
{
/**
+ * Return SQL to be executed in this update
+ *
+ * @param string Adapter name
+ * @return array
+ */
+ static function getSql($adapter = 'PDO_MYSQL')
+ {
+ return array();
+ }
+
+ /**
* Incremental version update
*/
- static function update();
+ abstract static function update();
}
diff --git a/core/Updates/0.2.10.php b/core/Updates/0.2.10.php
index ef64070237..6caf21ae46 100644
--- a/core/Updates/0.2.10.php
+++ b/core/Updates/0.2.10.php
@@ -13,14 +13,46 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_2_10 implements Piwik_iUpdate
+class Piwik_Updates_0_2_10 extends Piwik_Updates
{
- static function update()
+ static function getSql($adapter = 'PDO_MYSQL')
{
$tables = Piwik::getTablesCreateSql();
- Piwik_Updater::updateDatabase(__FILE__, array(
+
+ return array(
$tables['option'] => false,
- ));
+
+ // 0.1.7 [463]
+ 'ALTER IGNORE TABLE `'. Piwik_Common::prefixTable('log_visit') .'`
+ CHANGE `location_provider` `location_provider` VARCHAR( 100 ) DEFAULT NULL' => '1054',
+
+ // 0.1.7 [470]
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('logger_api_call') .'`
+ CHANGE `parameter_names_default_values` `parameter_names_default_values` TEXT,
+ CHANGE `parameter_values` `parameter_values` TEXT,
+ CHANGE `returned_value` `returned_value` TEXT' => false,
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('logger_error') .'`
+ CHANGE `message` `message` TEXT' => false,
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('logger_exception') .'`
+ CHANGE `message` `message` TEXT' => false,
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('logger_message') .'`
+ CHANGE `message` `message` TEXT' => false,
+
+ // 0.2.2 [489]
+ 'ALTER IGNORE TABLE `'. Piwik_Common::prefixTable('site') .'`
+ CHANGE `feedburnerName` `feedburnerName` VARCHAR( 100 ) DEFAULT NULL' => '1054',
+ );
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
+
+ $obsoleteFile = '/plugins/ExamplePlugin/API.php';
+ if(file_exists(PIWIK_INCLUDE_PATH . $obsoleteFile))
+ {
+ @unlink(PIWIK_INCLUDE_PATH . $obsoleteFile);
+ }
$obsoleteDirectories = array(
'/plugins/AdminHome',
diff --git a/core/Updates/0.2.12.php b/core/Updates/0.2.12.php
index 5227f68586..3a4b33ac8d 100644
--- a/core/Updates/0.2.12.php
+++ b/core/Updates/0.2.12.php
@@ -13,15 +13,24 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_2_12 implements Piwik_iUpdate
+class Piwik_Updates_0_2_12 extends Piwik_Updates
{
- static function update()
+ static function getSql($adapter = 'PDO_MYSQL')
{
- Piwik_Updater::updateDatabase(__FILE__, array(
- 'ALTER TABLE `'. Piwik::prefixTable('site') .'`
+ return array(
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('site') .'`
CHANGE `ts_created` `ts_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL' => false,
- 'ALTER TABLE `'. Piwik::prefixTable('log_visit') .'`
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('log_visit') .'`
DROP `config_color_depth`' => false,
- ));
+
+ // 0.2.12 [673]
+ // Note: requires INDEX privilege
+ 'DROP INDEX index_idaction ON `'. Piwik_Common::prefixTable('log_action') .'`' => '1091',
+ );
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
}
}
diff --git a/core/Updates/0.2.13.php b/core/Updates/0.2.13.php
index fb8a875f54..11f49ff709 100644
--- a/core/Updates/0.2.13.php
+++ b/core/Updates/0.2.13.php
@@ -13,14 +13,20 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_2_13 implements Piwik_iUpdate
+class Piwik_Updates_0_2_13 extends Piwik_Updates
{
- static function update()
+ static function getSql($adapter = 'PDO_MYSQL')
{
$tables = Piwik::getTablesCreateSql();
- Piwik_Updater::updateDatabase(__FILE__, array(
- 'DROP TABLE IF EXISTS `'. Piwik::prefixTable('option') .'`' => false,
+
+ return array(
+ 'DROP TABLE IF EXISTS `'. Piwik_Common::prefixTable('option') .'`' => false,
$tables['option'] => false,
- ));
+ );
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
}
}
diff --git a/core/Updates/0.2.24.php b/core/Updates/0.2.24.php
index a5a19837e6..81a0e4df22 100644
--- a/core/Updates/0.2.24.php
+++ b/core/Updates/0.2.24.php
@@ -13,17 +13,22 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_2_24 implements Piwik_iUpdate
+class Piwik_Updates_0_2_24 extends Piwik_Updates
{
- static function update()
+ static function getSql($adapter = 'PDO_MYSQL')
{
- Piwik_Updater::updateDatabase(__FILE__, array(
+ return array(
'CREATE INDEX index_type_name
- ON '. Piwik::prefixTable('log_action') .' (type, name(15))' => false,
+ ON '. Piwik_Common::prefixTable('log_action') .' (type, name(15))' => false,
'CREATE INDEX index_idsite_date
- ON '. Piwik::prefixTable('log_visit') .' (idsite, visit_server_date)' => false,
- 'DROP INDEX index_idsite ON '. Piwik::prefixTable('log_visit') => false,
- 'DROP INDEX index_visit_server_date ON '. Piwik::prefixTable('log_visit') => false,
- ));
+ ON '. Piwik_Common::prefixTable('log_visit') .' (idsite, visit_server_date)' => false,
+ 'DROP INDEX index_idsite ON '. Piwik_Common::prefixTable('log_visit') => false,
+ 'DROP INDEX index_visit_server_date ON '. Piwik_Common::prefixTable('log_visit') => false,
+ );
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
}
}
diff --git a/core/Updates/0.2.27.php b/core/Updates/0.2.27.php
index 3424216245..57cf3465d6 100644
--- a/core/Updates/0.2.27.php
+++ b/core/Updates/0.2.27.php
@@ -13,12 +13,17 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_2_27 implements Piwik_iUpdate
+class Piwik_Updates_0_2_27 extends Piwik_Updates
{
- static function update()
+ static function getSql($adapter = 'PDO_MYSQL')
{
- $sqlarray[ 'ALTER TABLE `'. Piwik::prefixTable('log_visit') .'`
- ADD `visit_goal_converted` VARCHAR( 1 ) NOT NULL AFTER `visit_total_time`' ] = false;
+ $sqlarray = array(
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('log_visit') .'`
+ ADD `visit_goal_converted` VARCHAR( 1 ) NOT NULL AFTER `visit_total_time`' => false,
+ // 0.2.27 [826]
+ 'ALTER IGNORE TABLE `'. Piwik_Common::prefixTable('log_visit') .'`
+ CHANGE `visit_goal_converted` `visit_goal_converted` TINYINT(1) NOT NULL' => false,
+ );
$tables = Piwik::getTablesCreateSql();
$sqlarray[ $tables['log_conversion'] ] = false;
@@ -33,6 +38,11 @@ class Piwik_Updates_0_2_27 implements Piwik_iUpdate
}
}
- Piwik_Updater::updateDatabase(__FILE__, $sqlarray);
+ return $sqlarray;
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
}
}
diff --git a/core/Updates/0.2.32.php b/core/Updates/0.2.32.php
new file mode 100644
index 0000000000..5594b6f521
--- /dev/null
+++ b/core/Updates/0.2.32.php
@@ -0,0 +1,37 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Updates
+ */
+
+/**
+ * @package Updates
+ */
+class Piwik_Updates_0_2_32 extends Piwik_Updates
+{
+ static function getSql($adapter = 'PDO_MYSQL')
+ {
+ return array(
+ // 0.2.32 [941]
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('access') .'`
+ CHANGE `login` `login` VARCHAR( 100 ) NOT NULL' => false,
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('user') .'`
+ CHANGE `login` `login` VARCHAR( 100 ) NOT NULL' => false,
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('user_dashboard') .'`
+ CHANGE `login` `login` VARCHAR( 100 ) NOT NULL' => '1146',
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('user_language') .'`
+ CHANGE `login` `login` VARCHAR( 100 ) NOT NULL' => '1146',
+ );
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
+ }
+}
diff --git a/core/Updates/0.2.33.php b/core/Updates/0.2.33.php
index ce936f5731..ed94e78fb8 100644
--- a/core/Updates/0.2.33.php
+++ b/core/Updates/0.2.33.php
@@ -13,10 +13,18 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_2_33 implements Piwik_iUpdate
+class Piwik_Updates_0_2_33 extends Piwik_Updates
{
- static function update()
+ static function getSql($adapter = 'PDO_MYSQL')
{
+ $sqlarray = array(
+ // 0.2.33 [1020]
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('user_dashboard') .'`
+ CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci ' => '1146',
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('user_language') .'`
+ CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci ' => '1146',
+ );
+
// alter table to set the utf8 collation
$tablesToAlter = Piwik::getTablesInstalled(true);
foreach($tablesToAlter as $table) {
@@ -24,6 +32,11 @@ class Piwik_Updates_0_2_33 implements Piwik_iUpdate
CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci ' ] = false;
}
- Piwik_Updater::updateDatabase(__FILE__, $sqlarray);
+ return $sqlarray;
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
}
}
diff --git a/core/Updates/0.2.34.php b/core/Updates/0.2.34.php
index a36b284589..ca7ae16211 100644
--- a/core/Updates/0.2.34.php
+++ b/core/Updates/0.2.34.php
@@ -13,13 +13,13 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_2_34 implements Piwik_iUpdate
+class Piwik_Updates_0_2_34 extends Piwik_Updates
{
static function update()
{
// force regeneration of cache files following #648
Piwik::setUserIsSuperUser();
- $allSiteIds = Piwik_SitesManager_API::getAllSitesId();
+ $allSiteIds = Piwik_SitesManager_API::getInstance()->getAllSitesId();
Piwik_Common::regenerateCacheWebsiteAttributes($allSiteIds);
}
}
diff --git a/core/Updates/0.2.35.php b/core/Updates/0.2.35.php
index 3fbeb4ab87..4ceadcf30d 100644
--- a/core/Updates/0.2.35.php
+++ b/core/Updates/0.2.35.php
@@ -13,13 +13,18 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_2_35 implements Piwik_iUpdate
+class Piwik_Updates_0_2_35 extends Piwik_Updates
{
- static function update()
+ static function getSql($adapter = 'PDO_MYSQL')
{
- Piwik_Updater::updateDatabase(__FILE__, array(
- 'ALTER TABLE `'. Piwik::prefixTable('user_dashboard') .'`
+ return array(
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('user_dashboard') .'`
CHANGE `layout` `layout` TEXT NOT NULL' => false,
- ));
+ );
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
}
}
diff --git a/core/Updates/0.2.37.php b/core/Updates/0.2.37.php
index ed1a36160d..51d77a6c32 100644
--- a/core/Updates/0.2.37.php
+++ b/core/Updates/0.2.37.php
@@ -13,14 +13,19 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_2_37 implements Piwik_iUpdate
+class Piwik_Updates_0_2_37 extends Piwik_Updates
{
- static function update()
+ static function getSql($adapter = 'PDO_MYSQL')
{
- Piwik_Updater::updateDatabase(__FILE__, array(
- 'DELETE FROM `'. Piwik::prefixTable('user_dashboard') ."`
+ return array(
+ 'DELETE FROM `'. Piwik_Common::prefixTable('user_dashboard') ."`
WHERE layout LIKE '%.getLastVisitsGraph%'
OR layout LIKE '%.getLastVisitsReturningGraph%'" => false,
- ));
+ );
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
}
}
diff --git a/core/Updates/0.4.1.php b/core/Updates/0.4.1.php
index 93fe25064c..ec1995e399 100644
--- a/core/Updates/0.4.1.php
+++ b/core/Updates/0.4.1.php
@@ -13,15 +13,20 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_4_1 implements Piwik_iUpdate
+class Piwik_Updates_0_4_1 extends Piwik_Updates
{
- static function update()
+ static function getSql($adapter = 'PDO_MYSQL')
{
- Piwik_Updater::updateDatabase(__FILE__, array(
- 'ALTER TABLE `'. Piwik::prefixTable('log_conversion') .'`
+ return array(
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('log_conversion') .'`
CHANGE `idlink_va` `idlink_va` INT(11) DEFAULT NULL' => false,
- 'ALTER TABLE `'. Piwik::prefixTable('log_conversion') .'`
- CHANGE `idaction` `idaction` INT(11) DEFAULT NULL' => false,
- ));
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('log_conversion') .'`
+ CHANGE `idaction` `idaction` INT(11) DEFAULT NULL' => '1054',
+ );
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
}
}
diff --git a/core/Updates/0.4.2.php b/core/Updates/0.4.2.php
index ef91786033..9be470e46a 100644
--- a/core/Updates/0.4.2.php
+++ b/core/Updates/0.4.2.php
@@ -13,19 +13,24 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_4_2 implements Piwik_iUpdate
+class Piwik_Updates_0_4_2 extends Piwik_Updates
{
- // when restoring (possibly) previousy dropped columns, ignore mysql code error 1060: duplicate column
- static function update()
+ static function getSql($adapter = 'PDO_MYSQL')
{
- Piwik_Updater::updateDatabase(__FILE__, array(
- 'ALTER TABLE `'. Piwik::prefixTable('log_visit') .'`
+ return array(
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('log_visit') .'`
ADD `config_java` TINYINT(1) NOT NULL AFTER `config_flash`' => '1060',
- 'ALTER TABLE `'. Piwik::prefixTable('log_visit') .'`
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('log_visit') .'`
ADD `config_quicktime` TINYINT(1) NOT NULL AFTER `config_director`' => '1060',
- 'ALTER TABLE `'. Piwik::prefixTable('log_visit') .'`
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('log_visit') .'`
ADD `config_gears` TINYINT(1) NOT NULL AFTER `config_windowsmedia`,
ADD `config_silverlight` TINYINT(1) NOT NULL AFTER `config_gears`' => false,
- ));
+ );
+ }
+
+ // when restoring (possibly) previousy dropped columns, ignore mysql code error 1060: duplicate column
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
}
}
diff --git a/core/Updates/0.4.3.php b/core/Updates/0.4.3.php
deleted file mode 100644
index b4524186a1..0000000000
--- a/core/Updates/0.4.3.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-/**
- * Piwik - Open source web analytics
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
- * @version $Id$
- *
- * @category Piwik
- * @package Updates
- */
-
-/**
- * @package Updates
- */
-class Piwik_Updates_0_4_3 implements Piwik_iUpdate
-{
- static function update()
- {
- Piwik_Updater::updateDatabase(__FILE__, array(
- // 0.1.7 [463]
- 'ALTER IGNORE TABLE `'. Piwik::prefixTable('log_visit') .'`
- CHANGE `location_provider` `location_provider` VARCHAR( 100 ) DEFAULT NULL' => '1054',
- // 0.1.7 [470]
- 'ALTER TABLE `'. Piwik::prefixTable('logger_api_call') .'`
- CHANGE `parameter_names_default_values` `parameter_names_default_values` TEXT,
- CHANGE `parameter_values` `parameter_values` TEXT,
- CHANGE `returned_value` `returned_value` TEXT' => false,
- 'ALTER TABLE `'. Piwik::prefixTable('logger_error') .'`
- CHANGE `message` `message` TEXT' => false,
- 'ALTER TABLE `'. Piwik::prefixTable('logger_exception') .'`
- CHANGE `message` `message` TEXT' => false,
- 'ALTER TABLE `'. Piwik::prefixTable('logger_message') .'`
- CHANGE `message` `message` TEXT' => false,
- // 0.2.2 [489]
- 'ALTER IGNORE TABLE `'. Piwik::prefixTable('site') .'`
- CHANGE `feedburnerName` `feedburnerName` VARCHAR( 100 ) DEFAULT NULL' => '1054',
- // 0.2.12 [673]
- // Note: requires INDEX privilege
- 'DROP INDEX index_idaction ON `'. Piwik::prefixTable('log_action') .'`' => '1091',
- // 0.2.27 [826]
- 'ALTER IGNORE TABLE `'. Piwik::prefixTable('log_visit') .'`
- CHANGE `visit_goal_converted` `visit_goal_converted` TINYINT(1) NOT NULL' => false,
- // 0.2.32 [941]
- 'ALTER TABLE `'. Piwik::prefixTable('access') .'`
- CHANGE `login` `login` VARCHAR( 100 ) NOT NULL' => false,
- 'ALTER TABLE `'. Piwik::prefixTable('user') .'`
- CHANGE `login` `login` VARCHAR( 100 ) NOT NULL' => false,
- 'ALTER TABLE `'. Piwik::prefixTable('user_dashboard') .'`
- CHANGE `login` `login` VARCHAR( 100 ) NOT NULL' => '1146',
- 'ALTER TABLE `'. Piwik::prefixTable('user_language') .'`
- CHANGE `login` `login` VARCHAR( 100 ) NOT NULL' => '1146',
- // 0.2.33 [1020]
- 'ALTER TABLE `'. Piwik::prefixTable('user_dashboard') .'`
- CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci ' => '1146',
- 'ALTER TABLE `'. Piwik::prefixTable('user_language') .'`
- CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci ' => '1146',
- // 0.4 [1140]
- 'ALTER TABLE `'. Piwik::prefixTable('log_visit') .'`
- CHANGE `location_ip` `location_ip` BIGINT UNSIGNED NOT NULL' => false,
- 'ALTER TABLE `'. Piwik::prefixTable('logger_api_call') .'`
- CHANGE `caller_ip` `caller_ip` BIGINT UNSIGNED' => false,
- ));
- }
-}
diff --git a/core/Updates/0.4.4.php b/core/Updates/0.4.4.php
index e6c986a0b4..e29c07eed8 100644
--- a/core/Updates/0.4.4.php
+++ b/core/Updates/0.4.4.php
@@ -13,14 +13,18 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_4_4 implements Piwik_iUpdate
+class Piwik_Updates_0_4_4 extends Piwik_Updates
{
static function update()
{
- $obsoleteFile = '/libs/open-flash-chart/php-ofc-library/ofc_upload_image.php';
- if(file_exists(PIWIK_DOCUMENT_ROOT . $obsoleteFile))
+ $obsoleteFile = PIWIK_DOCUMENT_ROOT . '/libs/open-flash-chart/php-ofc-library/ofc_upload_image.php';
+ if(file_exists($obsoleteFile))
{
- @unlink(PIWIK_DOCUMENT_ROOT . $obsoleteFile);
+ $rc = @unlink($obsoleteFile);
+ if(!$rc)
+ {
+ throw new Exception(Piwik_TranslateException('General_ExceptionUndeletableFile', array($obsoleteFile)));
+ }
}
}
}
diff --git a/core/Updates/0.4.php b/core/Updates/0.4.php
index a0ac958c11..cdd9911bdd 100644
--- a/core/Updates/0.4.php
+++ b/core/Updates/0.4.php
@@ -13,19 +13,25 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_4 implements Piwik_iUpdate
+class Piwik_Updates_0_4 extends Piwik_Updates
{
- static function update()
+ static function getSql($adapter = 'PDO_MYSQL')
{
- Piwik_Updater::updateDatabase(__FILE__, array(
- 'UPDATE `'. Piwik::prefixTable('log_visit') .'`
+ return array(
+ // 0.4 [1140]
+ 'UPDATE `'. Piwik_Common::prefixTable('log_visit') .'`
SET location_ip=location_ip+CAST(POW(2,32) AS UNSIGNED) WHERE location_ip < 0' => false,
- 'ALTER TABLE `'. Piwik::prefixTable('log_visit') .'`
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('log_visit') .'`
CHANGE `location_ip` `location_ip` BIGINT UNSIGNED NOT NULL' => false,
- 'UPDATE `'. Piwik::prefixTable('logger_api_call') .'`
+ 'UPDATE `'. Piwik_Common::prefixTable('logger_api_call') .'`
SET caller_ip=caller_ip+CAST(POW(2,32) AS UNSIGNED) WHERE caller_ip < 0' => false,
- 'ALTER TABLE `'. Piwik::prefixTable('logger_api_call') .'`
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('logger_api_call') .'`
CHANGE `caller_ip` `caller_ip` BIGINT UNSIGNED' => false,
- ));
+ );
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
}
}
diff --git a/core/Updates/0.5.4.php b/core/Updates/0.5.4.php
new file mode 100644
index 0000000000..859301e3ff
--- /dev/null
+++ b/core/Updates/0.5.4.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Updates
+ */
+
+/**
+ * @package Updates
+ */
+class Piwik_Updates_0_5_4 extends Piwik_Updates
+{
+ static function getSql($adapter = 'PDO_MYSQL')
+ {
+ return array(
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('log_action') .'`
+ CHANGE `name` `name` TEXT' => false,
+ );
+ }
+
+ static function update()
+ {
+ $config = Zend_Registry::get('config');
+ $salt = Piwik_Common::generateUniqId();
+ if(!isset($config->superuser->salt))
+ {
+ try {
+ if(is_writable( Piwik_Config::getDefaultUserConfigPath() ))
+ {
+ $superuser_info = $config->superuser->toArray();
+ $superuser_info['salt'] = $salt;
+ $config->superuser = $superuser_info;
+
+ $config->__destruct();
+ Piwik::createConfigObject();
+ }
+ else
+ {
+ throw new Exception('mandatory update failed');
+ }
+ } catch(Exception $e) {
+ throw new Piwik_Updater_UpdateErrorException("Please edit your config/config.ini.php file and add below <code>[superuser]</code> the following line: <br /><code>salt = $salt</code>");
+ }
+ }
+
+ $config = Zend_Registry::get('config');
+ $plugins = $config->Plugins->toArray();
+ if(!in_array('MultiSites', $plugins))
+ {
+ try {
+ if(is_writable( Piwik_Config::getDefaultUserConfigPath() ))
+ {
+ $plugins[] = 'MultiSites';
+ $config->Plugins = $plugins;
+
+ $config->__destruct();
+ Piwik::createConfigObject();
+ }
+ else
+ {
+ throw new Exception('optional update failed');
+ }
+ } catch(Exception $e) {
+ throw new Exception("You can now enable the new MultiSites plugin in the Plugins screen in the Piwik admin!");
+ }
+ }
+
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
+ }
+}
diff --git a/core/Updates/0.5.5.php b/core/Updates/0.5.5.php
new file mode 100644
index 0000000000..a82cf44cd7
--- /dev/null
+++ b/core/Updates/0.5.5.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Updates
+ */
+
+/**
+ * @package Updates
+ */
+class Piwik_Updates_0_5_5 extends Piwik_Updates
+{
+ static function getSql($adapter = 'PDO_MYSQL')
+ {
+ $sqlarray = array(
+ 'DROP INDEX index_idsite_date ON ' . Piwik_Common::prefixTable('log_visit') => '1091',
+ 'CREATE INDEX index_idsite_date_config ON ' . Piwik_Common::prefixTable('log_visit') . ' (idsite, visit_server_date, config_md5config(8))' => '1061',
+ );
+
+ $tables = Piwik::getTablesInstalled();
+ foreach($tables as $tableName)
+ {
+ if(preg_match('/archive_/', $tableName) == 1)
+ {
+ $sqlarray[ 'DROP INDEX index_all ON '. $tableName ] = '1091';
+ }
+ if(preg_match('/archive_numeric_/', $tableName) == 1)
+ {
+ $sqlarray[ 'CREATE INDEX index_idsite_dates_period ON '. $tableName .' (idsite, date1, date2, period)' ] = '1061';
+ }
+ }
+
+ return $sqlarray;
+ }
+
+ static function update()
+ {
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
+
+ }
+}
diff --git a/core/Updates/0.5.php b/core/Updates/0.5.php
index 108e651617..5d23f8a811 100644
--- a/core/Updates/0.5.php
+++ b/core/Updates/0.5.php
@@ -13,21 +13,26 @@
/**
* @package Updates
*/
-class Piwik_Updates_0_5 implements Piwik_iUpdate
+class Piwik_Updates_0_5 extends Piwik_Updates
{
+ static function getSql($adapter = 'PDO_MYSQL')
+ {
+ return array(
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_action') . ' ADD COLUMN `hash` INTEGER(10) UNSIGNED NOT NULL AFTER `name`;' => '1060',
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_visit') . ' CHANGE visit_exit_idaction visit_exit_idaction_url INTEGER(11) NOT NULL;' => '1054',
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_visit') . ' CHANGE visit_entry_idaction visit_entry_idaction_url INTEGER(11) NOT NULL;' => '1054',
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_link_visit_action') . ' CHANGE `idaction_ref` `idaction_url_ref` INTEGER(10) UNSIGNED NOT NULL;' => '1054',
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_link_visit_action') . ' CHANGE `idaction` `idaction_url` INTEGER(10) UNSIGNED NOT NULL;' => '1054',
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_link_visit_action') . ' ADD COLUMN `idaction_name` INTEGER(10) UNSIGNED AFTER `idaction_url_ref`;' => '1060',
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_conversion') . ' CHANGE `idaction` `idaction_url` INTEGER(11) UNSIGNED NOT NULL;' => '1054',
+ 'UPDATE ' . Piwik_Common::prefixTable('log_action') . ' SET `hash` = CRC32(name);' => false,
+ 'CREATE INDEX index_type_hash ON ' . Piwik_Common::prefixTable('log_action') . ' (type, hash);' => '1061',
+ 'DROP INDEX index_type_name ON ' . Piwik_Common::prefixTable('log_action') . ';' => '1091',
+ );
+ }
+
static function update()
{
- Piwik_Updater::updateDatabase(__FILE__, array(
- 'ALTER TABLE ' . Piwik::prefixTable('log_action'). ' ADD COLUMN `hash` INTEGER(10) UNSIGNED NOT NULL AFTER `name`;' => false,
- 'UPDATE '. Piwik::prefixTable('log_action'). ' SET `hash` = CRC32(name);' => false,
- 'CREATE INDEX index_type_hash ON '. Piwik::prefixTable('log_action') .' (type, hash);' => false,
- 'DROP INDEX index_type_name ON '. Piwik::prefixTable('log_action') .';' => false,
- 'ALTER TABLE '. Piwik::prefixTable('log_visit') .' CHANGE visit_exit_idaction visit_exit_idaction_url INTEGER(11) NOT NULL;' => false,
- 'ALTER TABLE '. Piwik::prefixTable('log_visit') .' CHANGE visit_entry_idaction visit_entry_idaction_url INTEGER(11) NOT NULL;' => false,
- 'ALTER TABLE ' . Piwik::prefixTable('log_link_visit_action'). ' CHANGE `idaction_ref` `idaction_url_ref` INTEGER(10) UNSIGNED NOT NULL;' => false,
- 'ALTER TABLE ' . Piwik::prefixTable('log_link_visit_action'). ' CHANGE `idaction` `idaction_url` INTEGER(10) UNSIGNED NOT NULL;' => false,
- 'ALTER TABLE ' . Piwik::prefixTable('log_link_visit_action'). ' ADD COLUMN `idaction_name` INTEGER(10) UNSIGNED AFTER `idaction_url_ref`;' => false,
- 'ALTER TABLE ' . Piwik::prefixTable('log_conversion'). ' CHANGE `idaction` `idaction_url` INTEGER(11) UNSIGNED NOT NULL;' => false,
- ));
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
}
}
diff --git a/core/Updates/0.6-rc1.php b/core/Updates/0.6-rc1.php
new file mode 100644
index 0000000000..14929092ee
--- /dev/null
+++ b/core/Updates/0.6-rc1.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Updates
+ */
+
+/**
+ * @package Updates
+ */
+class Piwik_Updates_0_6_rc1 extends Piwik_Updates
+{
+ static function getSql($adapter = 'PDO_MYSQL')
+ {
+ $defaultTimezone = 'UTC';
+ $defaultCurrency = 'USD';
+ return array(
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('user') . ' CHANGE date_registered date_registered TIMESTAMP NULL' => false,
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('site') . ' CHANGE ts_created ts_created TIMESTAMP NULL' => false,
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('site') . ' ADD `timezone` VARCHAR( 50 ) NOT NULL AFTER `ts_created` ;' => false,
+ 'UPDATE ' . Piwik_Common::prefixTable('site') . ' SET `timezone` = "'.$defaultTimezone.'";' => false,
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('site') . ' ADD currency CHAR( 3 ) NOT NULL AFTER `timezone` ;' => false,
+ 'UPDATE ' . Piwik_Common::prefixTable('site') . ' SET `currency` = "'.$defaultCurrency.'";' => false,
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('site') . ' ADD `excluded_ips` TEXT NOT NULL AFTER `currency` ;' => false,
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('site') . ' ADD excluded_parameters VARCHAR( 255 ) NOT NULL AFTER `excluded_ips` ;' => false,
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_visit') . ' ADD INDEX `index_idsite_datetime_config` ( `idsite` , `visit_last_action_time` , `config_md5config` ( 8 ) ) ;' => false,
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_visit') . ' ADD INDEX index_idsite_idvisit (idsite, idvisit) ;' => false,
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_conversion') . ' DROP INDEX index_idsite_date' => false,
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_conversion') . ' DROP visit_server_date;' => false,
+ 'ALTER TABLE ' . Piwik_Common::prefixTable('log_conversion') . ' ADD INDEX index_idsite_datetime ( `idsite` , `server_time` )' => false,
+ );
+ }
+
+ static function update()
+ {
+ // first we disable the plugins and keep an array of warnings messages
+ $pluginsToDisableMessage = array(
+ 'SearchEnginePosition' => "SearchEnginePosition plugin was disabled, because it is not compatible with the new Piwik 0.6. \n You can download the latest version of the plugin, compatible with Piwik 0.6.\n<a target='_blank' href='misc/redirectToUrl.php?url=http://dev.piwik.org/trac/ticket/502'>Click here.</a>",
+ 'GeoIP' => "GeoIP plugin was disabled, because it is not compatible with the new Piwik 0.6. \nYou can download the latest version of the plugin, compatible with Piwik 0.6.\n<a target='_blank' href='misc/redirectToUrl.php?url=http://dev.piwik.org/trac/ticket/45'>Click here.</a>"
+ );
+ $disabledPlugins = array();
+ foreach($pluginsToDisableMessage as $pluginToDisable => $warningMessage)
+ {
+ if(Piwik_PluginsManager::getInstance()->isPluginActivated($pluginToDisable))
+ {
+ Piwik_PluginsManager::getInstance()->deactivatePlugin($pluginToDisable);
+ $disabledPlugins[] = $warningMessage;
+ }
+ }
+
+ // Run the SQL
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
+
+ // Outputs warning message, pointing users to the plugin download page
+ if(!empty($disabledPlugins))
+ {
+ throw new Exception("The following plugins were disabled during the upgrade:"
+ ."<ul><li>" .
+ implode('</li><li>', $disabledPlugins) .
+ "</li></ul>");
+ }
+ }
+}
diff --git a/core/Updates/0.6.2.php b/core/Updates/0.6.2.php
new file mode 100644
index 0000000000..5c564df099
--- /dev/null
+++ b/core/Updates/0.6.2.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Updates
+ */
+
+/**
+ * @package Updates
+ */
+class Piwik_Updates_0_6_2 extends Piwik_Updates
+{
+ static function update()
+ {
+ $obsoleteFiles = array(
+ PIWIK_INCLUDE_PATH . '/core/Db/Mysqli.php',
+ );
+ foreach($obsoleteFiles as $obsoleteFile)
+ {
+ if(file_exists($obsoleteFile))
+ {
+ @unlink($obsoleteFile);
+ }
+ }
+
+ $obsoleteDirectories = array(
+ PIWIK_INCLUDE_PATH . '/core/Db/Pdo',
+ );
+ foreach($obsoleteDirectories as $dir)
+ {
+ if(file_exists($dir))
+ {
+ Piwik::unlinkRecursive($dir, true);
+ }
+ }
+
+ // force regeneration of cache files
+ Piwik::setUserIsSuperUser();
+ $allSiteIds = Piwik_SitesManager_API::getInstance()->getAllSitesId();
+ Piwik_Common::regenerateCacheWebsiteAttributes($allSiteIds);
+ }
+}
diff --git a/core/Updates/0.6.3.php b/core/Updates/0.6.3.php
new file mode 100644
index 0000000000..d4e5a8b38a
--- /dev/null
+++ b/core/Updates/0.6.3.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik
+ * @package Updates
+ */
+
+/**
+ * @package Updates
+ */
+class Piwik_Updates_0_6_3 extends Piwik_Updates
+{
+ static function getSql($adapter = 'PDO_MYSQL')
+ {
+ return array(
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('log_visit') .'`
+ CHANGE `location_ip` `location_ip` INT UNSIGNED NOT NULL' => false,
+ 'ALTER TABLE `'. Piwik_Common::prefixTable('logger_api_call') .'`
+ CHANGE `caller_ip` `caller_ip` INT UNSIGNED' => false,
+ );
+ }
+
+ static function update()
+ {
+ $config = Zend_Registry::get('config');
+ $dbInfos = $config->database->toArray();
+ if(!isset($dbInfos['schema']))
+ {
+ try {
+ if(is_writable( Piwik_Config::getDefaultUserConfigPath() ))
+ {
+ $dbInfos['schema'] = 'Myisam';
+ $config->database = $dbInfos;
+
+ $config->__destruct();
+ Piwik::createConfigObject();
+ }
+ else
+ {
+ throw new Exception('mandatory update failed');
+ }
+ } catch(Exception $e) {
+ throw new Piwik_Updater_UpdateErrorException("Please edit your config/config.ini.php file and add below <code>[database]</code> the following line: <br /><code>schema = Myisam</code>");
+ }
+ }
+
+ Piwik_Updater::updateDatabase(__FILE__, self::getSql());
+ }
+}
diff --git a/core/Url.php b/core/Url.php
index 7ba48bbc99..cc6164ac26 100644
--- a/core/Url.php
+++ b/core/Url.php
@@ -1,11 +1,11 @@
<?php
/**
* Piwik - Open source web analytics
- *
+ *
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
- *
+ *
* @category Piwik
* @package Piwik
*/
@@ -26,11 +26,12 @@ class Piwik_Url
*/
static public function getCurrentUrl()
{
- return self::getCurrentHost()
- . self::getCurrentScriptName()
- . self::getCurrentQueryString();
+ return self::getCurrentScheme() . '://'
+ . self::getCurrentHost()
+ . self::getCurrentScriptName()
+ . self::getCurrentQueryString();
}
-
+
/**
* If current URL is "http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
* will return "http://example.org/dir1/dir2/index.php"
@@ -39,10 +40,11 @@ class Piwik_Url
*/
static public function getCurrentUrlWithoutQueryString()
{
- return self::getCurrentHost()
- . self::getCurrentScriptName() ;
+ return self::getCurrentScheme() . '://'
+ . self::getCurrentHost()
+ . self::getCurrentScriptName();
}
-
+
/**
* If current URL is "http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
* will return "http://example.org/dir1/dir2/"
@@ -51,9 +53,9 @@ class Piwik_Url
*/
static public function getCurrentUrlWithoutFileName()
{
- $host = self::getCurrentHost();
- $urlDir = self::getCurrentScriptPath();
- return $host.$urlDir;
+ return self::getCurrentScheme() . '://'
+ . self::getCurrentHost()
+ . self::getCurrentScriptPath();
}
/**
@@ -76,7 +78,7 @@ class Piwik_Url
}
return $urlDir;
}
-
+
/**
* If current URL is "http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
* will return "/dir1/dir2/index.php"
@@ -106,41 +108,56 @@ class Piwik_Url
{
$url = $_SERVER['SCRIPT_NAME'];
}
+
+ if($url[0] !== '/')
+ {
+ $url = '/' . $url;
+ }
return $url;
}
/**
- * If current URL is "http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
- * will return "http://example.org"
+ * If the current URL is 'http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
+ * will return 'http'
*
- * @return string
+ * @return string 'https' or 'http'
*/
- static public function getCurrentHost()
+ static public function getCurrentScheme()
{
if(isset($_SERVER['HTTPS'])
- && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] === true)
+ && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] === true)
)
{
- $url = 'https';
+ $scheme = 'https';
}
- else
+ else
{
- $url = 'http';
+ $scheme = 'http';
}
-
- $url .= '://';
-
- if(isset($_SERVER['HTTP_HOST']))
+ return $scheme;
+ }
+
+ /**
+ * If current URL is "http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
+ * will return "http://example.org"
+ *
+ * @return string
+ */
+ static public function getCurrentHost()
+ {
+ if (!empty($_SERVER['HTTP_X_FORWARDED_HOST']))
{
- $url .= $_SERVER['HTTP_HOST'];
+ return Piwik_Common::getFirstIpFromList($_SERVER['HTTP_X_FORWARDED_HOST']);
}
- else
+
+ if(isset($_SERVER['HTTP_HOST']))
{
- $url .= 'unknown';
+ return $_SERVER['HTTP_HOST'];
}
- return $url;
+
+ return 'unknown';
}
-
+
/**
* If current URL is "http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
* will return "?param1=value1&param2=value2"
@@ -157,7 +174,7 @@ class Piwik_Url
}
return $url;
}
-
+
/**
* If current URL is "http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
* will return
@@ -173,7 +190,7 @@ class Piwik_Url
$urlValues = Piwik_Common::getArrayFromQueryString($queryString);
return $urlValues;
}
-
+
/**
* Given an array of name-values, it will return the current query string
* with the new requested parameter key-values;
@@ -196,7 +213,7 @@ class Piwik_Url
}
return '';
}
-
+
/**
* Given an array of parameters name->value, returns the query string.
* Also works with array values using the php array syntax for GET parameters.
@@ -228,7 +245,7 @@ class Piwik_Url
$query = substr($query, 0, -1);
return $query;
}
-
+
/**
* Redirects the user to the Referer if found.
* If the user doesn't have a referer set, it redirects to the current URL without query string.
@@ -242,7 +259,7 @@ class Piwik_Url
}
self::redirectToUrl(self::getCurrentUrlWithoutQueryString());
}
-
+
/**
* Redirects the user to the specified URL
*
@@ -253,7 +270,7 @@ class Piwik_Url
header("Location: $url");
exit;
}
-
+
/**
* Returns the HTTP_REFERER header, false if not found.
*
@@ -267,4 +284,46 @@ class Piwik_Url
}
return false;
}
+
+ /**
+ * Is the URL on the same host and in the same script path?
+ *
+ * @param string $url
+ * @return bool True if local; false otherwise.
+ */
+ static public function isLocalUrl($url)
+ {
+ // handle case-sensitivity differences
+ $pathContains = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' ? 'stripos' : 'strpos';
+
+ // test the scheme/protocol portion of the reconstructed "current" URL
+ if(stripos($url, 'http://') === 0 || stripos($url, 'https://') === 0)
+ {
+ // determine the offset to begin the comparison
+ $offset = strpos($url, '://');
+ $current = strstr(self::getCurrentUrlWithoutFileName(), '://');
+ if($pathContains($url, $current, $offset) === $offset)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get local referer, i.e., on the same host and in the same script path.
+ *
+ * @return string|false
+ */
+ static public function getLocalReferer()
+ {
+ // verify that the referer contains the current URL (minus the filename & query parameters), http://example.org/dir1/dir2/
+ $referer = self::getReferer();
+ if($referer !== false && self::isLocalUrl($referer)) {
+ return $referer;
+ }
+
+ return false;
+ }
}
diff --git a/core/Version.php b/core/Version.php
index 26e24c4dfc..a6031b12a7 100644
--- a/core/Version.php
+++ b/core/Version.php
@@ -17,5 +17,5 @@
*/
final class Piwik_Version
{
- const VERSION = '0.5';
+ const VERSION = '0.6.3';
}
diff --git a/core/View.php b/core/View.php
index 24b7339738..6757a101dd 100644
--- a/core/View.php
+++ b/core/View.php
@@ -9,7 +9,6 @@
* @category Piwik
* @package Piwik
*/
-
/*
* Transition for pre-Piwik 0.4.4
* @todo Remove this post-1.0
@@ -34,7 +33,8 @@ class Piwik_View implements Piwik_iView
private $template = '';
private $smarty = false;
private $variables = array();
-
+ private $contentType = 'text/html; charset=utf-8';
+
public function __construct( $templateFile, $smConf = array(), $filter = true )
{
$this->template = $templateFile;
@@ -50,7 +50,7 @@ class Piwik_View implements Piwik_iView
}
$this->smarty->template_dir = $smConf->template_dir->toArray();
- array_walk($this->smarty->template_dir, array("Piwik_View","addPiwikPath"), PIWIK_USER_PATH);
+ array_walk($this->smarty->template_dir, array("Piwik_View","addPiwikPath"), PIWIK_INCLUDE_PATH);
$this->smarty->plugins_dir = $smConf->plugins_dir->toArray();
array_walk($this->smarty->plugins_dir, array("Piwik_View","addPiwikPath"), PIWIK_INCLUDE_PATH);
@@ -61,8 +61,12 @@ class Piwik_View implements Piwik_iView
$this->smarty->cache_dir = $smConf->cache_dir;
Piwik_View::addPiwikPath($this->smarty->cache_dir, null, PIWIK_USER_PATH);
- $this->smarty->error_reporting = $smConf->debugging;
- $this->smarty->error_reporting = $smConf->error_reporting;
+ $error_reporting = $smConf->error_reporting;
+ if($error_reporting != (string)(int)$error_reporting)
+ {
+ $error_reporting = self::bitwise_eval($error_reporting);
+ }
+ $this->smarty->error_reporting = $error_reporting;
$this->smarty->assign('tag', 'piwik=' . Piwik_Version::VERSION);
if($filter)
@@ -100,17 +104,20 @@ class Piwik_View implements Piwik_iView
return $this->smarty->get_template_vars($key);
}
+ /**
+ * Render view
+ */
public function render()
{
try {
$this->currentModule = Piwik::getModule();
- $this->currentPluginName = Piwik::getCurrentPlugin()->getName();
+ $this->currentPluginName = Piwik::getCurrentPlugin()->getClassName();
$this->userLogin = Piwik::getCurrentUserLogin();
$showWebsiteSelectorInUserInterface = Zend_Registry::get('config')->General->show_website_selector_in_user_interface;
if($showWebsiteSelectorInUserInterface)
{
- $sites = Piwik_SitesManager_API::getSitesWithAtLeastViewAccess();
+ $sites = Piwik_SitesManager_API::getInstance()->getSitesWithAtLeastViewAccess();
usort($sites, create_function('$site1, $site2', 'return strcasecmp($site1["name"], $site2["name"]);'));
$this->sites = $sites;
}
@@ -122,7 +129,7 @@ class Piwik_View implements Piwik_iView
$this->piwik_version = Piwik_Version::VERSION;
$this->latest_version_available = Piwik_UpdateCheck::isNewestVersionAvailable();
- $this->loginModule = Zend_Registry::get('auth')->getName();
+ $this->loginModule = Piwik::getLoginPluginName();
} catch(Exception $e) {
// can fail, for example at installation (no plugin loaded yet)
}
@@ -135,13 +142,28 @@ class Piwik_View implements Piwik_iView
$this->totalNumberOfQueries = 0;
}
- @header('Content-Type: text/html; charset=utf-8');
+ @header('Content-Type: '.$this->contentType);
@header("Pragma: ");
@header("Cache-Control: no-store, must-revalidate");
return $this->smarty->fetch($this->template);
}
-
+
+ /**
+ * Set Content-Type field in HTTP response
+ *
+ * @param string $contentType
+ */
+ public function setContentType( $contentType )
+ {
+ $this->contentType = $contentType;
+ }
+
+ /**
+ * Add form to view
+ *
+ * @param Piwik_Form $form
+ */
public function addForm( $form )
{
// Create the renderer object
@@ -154,7 +176,13 @@ class Piwik_View implements Piwik_iView
$this->smarty->assign('form_data', $renderer->toArray());
$this->smarty->assign('element_list', $form->getElementList());
}
-
+
+ /**
+ * Assign value to a variable for use in Smarty template
+ *
+ * @param string|array $var
+ * @param mixed $value
+ */
public function assign($var, $value=null)
{
if (is_string($var))
@@ -170,6 +198,9 @@ class Piwik_View implements Piwik_iView
}
}
+ /**
+ * Clear compiled Smarty templates
+ */
public function clearCompiledTemplates()
{
$this->smarty->clear_compiled_tpl();
@@ -192,6 +223,13 @@ class Piwik_View implements Piwik_iView
}
*/
+ /**
+ * Prepend relative paths with absolute Piwik path
+ *
+ * @param string $value relative path (pass by reference)
+ * @param int $key (don't care)
+ * @param string $path Piwik root
+ */
static public function addPiwikPath(&$value, $key, $path)
{
if($value[0] != '/' && $value[0] != DIRECTORY_SEPARATOR)
@@ -201,6 +239,33 @@ class Piwik_View implements Piwik_iView
}
/**
+ * Evaluate expression containing only bitwise operators.
+ * Replaces defined constants with corresponding values.
+ * Does not use eval() or create_function().
+ *
+ * @param string $expression Expression.
+ * @return string
+ */
+ static public function bitwise_eval($expression)
+ {
+ // replace defined constants
+ $buf = get_defined_constants(true);
+
+ // use only the 'Core' PHP constants, e.g., E_ALL, E_STRICT, ...
+ $consts = isset($buf['Core']) ? $buf['Core'] : (isset($buf['mhash']) ? $buf['mhash'] : $buf['internal']);
+ $expression = str_replace(' ', '', strtr($expression, $consts));
+
+ // bitwise operators in order of precedence (highest to lowest)
+ // @todo: boolean ! (NOT) and parentheses aren't handled
+ $expression = preg_replace_callback('/~(-?[0-9]+)/', create_function('$matches', 'return (string)((~(int)$matches[1]));'), $expression);
+ $expression = preg_replace_callback('/(-?[0-9]+)&(-?[0-9]+)/', create_function('$matches', 'return (string)((int)$matches[1]&(int)$matches[2]);'), $expression);
+ $expression = preg_replace_callback('/(-?[0-9]+)\^(-?[0-9]+)/', create_function('$matches', 'return (string)((int)$matches[1]^(int)$matches[2]);'), $expression);
+ $expression = preg_replace_callback('/(-?[0-9]+)\|(-?[0-9]+)/', create_function('$matches', 'return (string)((int)$matches[1]|(int)$matches[2]);'), $expression);
+
+ return (string)((int)$expression & PHP_INT_MAX);
+ }
+
+ /**
* View factory method
*
* @param $templateName Template name (e.g., 'index')
@@ -211,10 +276,10 @@ class Piwik_View implements Piwik_iView
Piwik_PostEvent('View.getViewType', $viewType);
// get caller
- $bt = debug_backtrace();
- if(!isset($bt[0]))
+ $bt = @debug_backtrace();
+ if($bt === null || !isset($bt[0]))
{
- throw new Exception("View factory cannot be invoked directly");
+ throw new Exception("View factory cannot be invoked");
}
$path = dirname($bt[0]['file']);
diff --git a/core/ViewDataTable.php b/core/ViewDataTable.php
index 5608dd152f..703044d78b 100644
--- a/core/ViewDataTable.php
+++ b/core/ViewDataTable.php
@@ -82,6 +82,14 @@ abstract class Piwik_ViewDataTable
*/
protected $dataTable = null;
+
+ /**
+ * List of filters to apply after the data has been loaded from the API
+ *
+ * @var array
+ */
+ protected $queuedFilters = array();
+
/**
* @see init()
* @var string
@@ -121,8 +129,19 @@ abstract class Piwik_ViewDataTable
*/
protected $columnsTranslations = array();
-
+ /**
+ * Array of columns set to display
+ *
+ * @var array
+ */
protected $columnsToDisplay = array();
+
+ /**
+ * Variable that is used as the DIV ID in the rendered HTML
+ *
+ * @var string
+ */
+ protected $uniqIdTable = null;
/**
* Method to be implemented by the ViewDataTable_*.
@@ -251,7 +270,7 @@ abstract class Piwik_ViewDataTable
$this->viewProperties['show_all_views_icons'] = Piwik_Common::getRequestVar('show_all_views_icons', true);
$this->viewProperties['show_export_as_image_icon'] = Piwik_Common::getRequestVar('show_export_as_image_icon', false);
$this->viewProperties['show_exclude_low_population'] = Piwik_Common::getRequestVar('show_exclude_low_population', true);
- $this->viewProperties['show_offset_information'] = Piwik_Common::getRequestVar('show_offset_information', true);;
+ $this->viewProperties['show_offset_information'] = Piwik_Common::getRequestVar('show_offset_information', true);
$this->viewProperties['show_footer'] = Piwik_Common::getRequestVar('show_footer', true);
$this->viewProperties['show_footer_icons'] = ($this->idSubtable == false);
$this->viewProperties['apiMethodToRequestDataTable'] = $this->apiMethodToRequestDataTable;
@@ -344,6 +363,21 @@ abstract class Piwik_ViewDataTable
}
/**
+ * Hook called after the dataTable has been loaded from the API
+ * Can be used to add, delete or modify the data freshly loaded
+ */
+ protected function postDataTableLoadedFromAPI()
+ {
+ // Apply datatable filters that were queued by the controllers
+ foreach($this->queuedFilters as $filter)
+ {
+ $filterName = $filter[0];
+ $filterParameters = $filter[1];
+ $this->dataTable->filter($filterName, $filterParameters);
+ }
+ }
+
+ /**
* @return string URL to call the API, eg. "method=Referers.getKeywords&period=day&date=yesterday"...
*/
protected function getRequestString()
@@ -415,7 +449,7 @@ abstract class Piwik_ViewDataTable
* @see datatable.js
* @return string
*/
- protected function getUniqueIdViewDataTable()
+ protected function loadUniqueIdViewDataTable()
{
// if we request a subDataTable the $this->currentControllerAction DIV ID is already there in the page
// we make the DIV ID really unique by appending the ID of the subtable requested
@@ -434,6 +468,27 @@ abstract class Piwik_ViewDataTable
}
return $uniqIdTable;
}
+
+ /**
+ * Sets the $uniqIdTable variable that is used as the DIV ID in the rendered HTML
+ */
+ public function setUniqueIdViewDataTable($uniqIdTable)
+ {
+ $this->viewProperties['uniqueId'] = $uniqIdTable;
+ $this->uniqIdTable = $uniqIdTable;
+ }
+
+ /**
+ * Returns current value of $uniqIdTable variable that is used as the DIV ID in the rendered HTML
+ */
+ public function getUniqueIdViewDataTable()
+ {
+ if( $this->uniqIdTable == null )
+ {
+ $this->uniqIdTable = $this->loadUniqueIdViewDataTable();
+ }
+ return $this->uniqIdTable;
+ }
/**
* Returns array of properties, eg. "show_footer", "show_search", etc.
@@ -721,7 +776,7 @@ abstract class Piwik_ViewDataTable
*/
public function setLimit( $limit )
{
- if($limit != 0)
+ if($limit !== 0)
{
$this->variablesDefault['filter_limit'] = $limit;
}
@@ -739,6 +794,15 @@ abstract class Piwik_ViewDataTable
$this->variablesDefault['filter_sort_order'] = $order;
}
+ /**
+ * Returns the column name on which the table will be sorted
+ *
+ * @return string
+ */
+ public function getSortedColumn()
+ {
+ return $this->variablesDefault['filter_sort_column'];
+ }
/**
* Sets translation string for given column
@@ -746,9 +810,10 @@ abstract class Piwik_ViewDataTable
* @param string $columnName column name
* @param string $columnTranslation column name translation
*/
- public function setColumnTranslation( $columnName, $columnTranslation )
+ public function setColumnTranslation( $columnName, $columnTranslation, $columnDescription = false )
{
$this->columnsTranslations[$columnName] = $columnTranslation;
+ $this->columnsDescriptions[$columnName] = $columnDescription;
}
/**
@@ -762,10 +827,20 @@ abstract class Piwik_ViewDataTable
{
return html_entity_decode($this->columnsTranslations[$columnName], ENT_COMPAT, 'UTF-8');
}
- else
+ return $columnName;
+ }
+
+ /**
+ * Returns column description, or false
+ * @param string $columnName column name
+ */
+ public function getColumnDescription( $columnName )
+ {
+ if( !empty($this->columnsDescriptions[$columnName]) )
{
- return $columnName;
+ return html_entity_decode($this->columnsDescriptions[$columnName], ENT_COMPAT, 'UTF-8');
}
+ return false;
}
/**
@@ -830,4 +905,18 @@ abstract class Piwik_ViewDataTable
}
$this->variablesDefault[$parameter] = $value;
}
+
+ /**
+ * Queues a Datatable filter, that will be applied once the datatable is loaded from the API.
+ * Useful when the controller needs to add columns, or decorate existing columns, when these filters don't
+ * necessarily make sense directly in the API.
+ *
+ * @param $filterName
+ * @param $parameters
+ * @return void
+ */
+ public function queueFilter($filterName, $parameters)
+ {
+ $this->queuedFilters[] = array($filterName, $parameters);
+ }
}
diff --git a/core/ViewDataTable/Cloud.php b/core/ViewDataTable/Cloud.php
index f819ef6c3c..c7d68be64a 100644
--- a/core/ViewDataTable/Cloud.php
+++ b/core/ViewDataTable/Cloud.php
@@ -36,11 +36,13 @@ class Piwik_ViewDataTable_Cloud extends Piwik_ViewDataTable
*/
function init($currentControllerName,
$currentControllerAction,
- $apiMethodToRequestDataTable )
+ $apiMethodToRequestDataTable,
+ $controllerActionCalledWhenRequestSubTable = null)
{
parent::init($currentControllerName,
$currentControllerAction,
- $apiMethodToRequestDataTable );
+ $apiMethodToRequestDataTable,
+ $controllerActionCalledWhenRequestSubTable);
$this->dataTableTemplate = 'CoreHome/templates/cloud.tpl';
$this->disableOffsetInformation();
$this->disableExcludeLowPopulation();
diff --git a/core/ViewDataTable/GenerateGraphData.php b/core/ViewDataTable/GenerateGraphData.php
index d3b1251f73..4a2fcce75e 100644
--- a/core/ViewDataTable/GenerateGraphData.php
+++ b/core/ViewDataTable/GenerateGraphData.php
@@ -87,8 +87,14 @@ abstract class Piwik_ViewDataTable_GenerateGraphData extends Piwik_ViewDataTable
}
$this->mainAlreadyExecuted = true;
- @header( "Content-type: application/json" );
+ if (!Zend_Registry::get('config')->General->serve_widget_and_data)
+ {
+ @header( "Content-Type: application/json" );
+ }
+ // Graphs require the full dataset, setting limit to null (same as 'no limit')
+ $this->setLimit(null);
+
// the queued filters will be manually applied later. This is to ensure that filtering using search
// will be done on the table before the labels are enhanced (see ReplaceColumnNames)
$this->disableQueuedFilters();
diff --git a/core/ViewDataTable/GenerateGraphData/ChartEvolution.php b/core/ViewDataTable/GenerateGraphData/ChartEvolution.php
index 5ed804c3ad..8c8d961ade 100644
--- a/core/ViewDataTable/GenerateGraphData/ChartEvolution.php
+++ b/core/ViewDataTable/GenerateGraphData/ChartEvolution.php
@@ -28,11 +28,11 @@ class Piwik_ViewDataTable_GenerateGraphData_ChartEvolution extends Piwik_ViewDat
$this->view = new Piwik_Visualization_Chart_Evolution();
}
- protected function guessUnitFromRequestedColumnNames($requestedColumnNames)
+ protected function guessUnitFromRequestedColumnNames($requestedColumnNames, $idSite)
{
$nameToUnit = array(
'_rate' => '%',
- '_revenue' => Piwik::getCurrency(),
+ '_revenue' => Piwik::getCurrency($idSite),
);
foreach($requestedColumnNames as $columnName)
{
@@ -119,11 +119,12 @@ class Piwik_ViewDataTable_GenerateGraphData_ChartEvolution extends Piwik_ViewDat
$yAxisLabelToValueCleaned[$yAxisLabel][] = $columnValue;
}
}
+ $idSite = Piwik_Common::getRequestVar('idSite');
$unit = $this->yAxisUnit;
if(empty($unit))
{
- $unit = $this->guessUnitFromRequestedColumnNames($requestedColumnNames);
+ $unit = $this->guessUnitFromRequestedColumnNames($requestedColumnNames, $idSite);
}
$this->view->setAxisXLabels($xLabels);
@@ -145,24 +146,63 @@ class Piwik_ViewDataTable_GenerateGraphData_ChartEvolution extends Piwik_ViewDat
if($this->isLinkEnabled())
{
$axisXOnClick = array();
+ $queryStringAsHash = $this->getQueryStringAsHash();
foreach($this->dataTable->metadata as $idDataTable => $metadataDataTable)
{
$period = $metadataDataTable['period'];
$dateInUrl = $period->getDateStart();
+ $parameters = array(
+ 'idSite' => $idSite,
+ 'period' => $period->getLabel(),
+ 'date' => $dateInUrl->toString()
+ );
+ $hash = '';
+ if(!empty($queryStringAsHash))
+ {
+ $hash = '#' . Piwik_Url::getQueryStringFromParameters( $queryStringAsHash + $parameters);
+ }
$link = Piwik_Url::getCurrentUrlWithoutQueryString() .
'?' .
Piwik_Url::getQueryStringFromParameters( array(
'module' => 'CoreHome',
'action' => 'index',
- 'idSite' => Piwik_Common::getRequestVar('idSite'),
- 'period' => $period->getLabel(),
- 'date' => $dateInUrl,
- ));
+ ) + $parameters)
+ . $hash;
$axisXOnClick[] = $link;
}
$this->view->setAxisXOnClick($axisXOnClick);
}
}
+
+ /**
+ * We link the graph dots to the same report as currently being displayed (only the date would change).
+ *
+ * In some cases the widget is loaded within a report that doesn't exist as such.
+ * For example, the dashboards loads the 'Last visits graph' widget which can't be directly linked to.
+ * Instead, the graph must link back to the dashboard.
+ *
+ * In other cases, like Visitors>Overview or the Goals graphs, we can link the graph clicks to the same report.
+ *
+ * To detect whether or not we can link to a report, we simply check if the current URL from which it was loaded
+ * belongs to the menu or not. If it doesn't belong to the menu, we do not append the hash to the URL,
+ * which results in loading the dashboard.
+ *
+ * @return array Query string array to append to the URL hash or false if the dashboard should be displayed
+ */
+ private function getQueryStringAsHash()
+ {
+ $queryString = Piwik_Url::getArrayFromCurrentQueryString();
+ $piwikParameters = array('idSite', 'date', 'period', 'XDEBUG_SESSION_START', 'KEY');
+ foreach($piwikParameters as $parameter)
+ {
+ unset($queryString[$parameter]);
+ }
+ if(Piwik_IsMenuUrlFound($queryString))
+ {
+ return $queryString;
+ }
+ return false;
+ }
private function isLinkEnabled()
{
diff --git a/core/ViewDataTable/GenerateGraphHTML.php b/core/ViewDataTable/GenerateGraphHTML.php
index 1c3bad57f3..be7e774a0a 100644
--- a/core/ViewDataTable/GenerateGraphHTML.php
+++ b/core/ViewDataTable/GenerateGraphHTML.php
@@ -28,12 +28,13 @@ abstract class Piwik_ViewDataTable_GenerateGraphHTML extends Piwik_ViewDataTable
*/
function init($currentControllerName,
$currentControllerAction,
- $apiMethodToRequestDataTable )
+ $apiMethodToRequestDataTable,
+ $controllerActionCalledWhenRequestSubTable = null)
{
parent::init($currentControllerName,
$currentControllerAction,
- $apiMethodToRequestDataTable );
-
+ $apiMethodToRequestDataTable,
+ $controllerActionCalledWhenRequestSubTable);
$this->dataTableTemplate = 'CoreHome/templates/graph.tpl';
$this->disableOffsetInformation();
@@ -67,7 +68,8 @@ abstract class Piwik_ViewDataTable_GenerateGraphHTML extends Piwik_ViewDataTable
/**
* We persist the parametersToModify values in the javascript footer.
- * This is used by the "export links" that use the "date" attribute from the json properties array in the datatable footer.
+ * This is used by the "export links" that use the "date" attribute
+ * from the json properties array in the datatable footer.
*/
protected function getJavascriptVariablesToSet()
{
@@ -125,9 +127,19 @@ abstract class Piwik_ViewDataTable_GenerateGraphHTML extends Piwik_ViewDataTable
foreach($this->parametersToModify as $key => $val)
{
- if (is_array($val)) {
+ // We do not forward filter data to the graph controller.
+ // This would cause the graph to have filter_limit=5 set by default,
+ // which would break them (graphs need the full dataset to build the "Others" aggregate value)
+ if(strpos($key, 'filter_') !== false)
+ {
+ continue;
+ }
+ if (is_array($val))
+ {
$_GET[$key] = unserialize(serialize($val));
- } else {
+ }
+ else
+ {
$_GET[$key] = $val;
}
}
@@ -135,7 +147,7 @@ abstract class Piwik_ViewDataTable_GenerateGraphHTML extends Piwik_ViewDataTable
$_GET = $saveGet;
- return str_replace(array("\r", "\n", "'"), array('', '', "\\'"), $content);
+ return str_replace(array("\r", "\n", "'", '\"'), array('', '', "\\'", '\\\"'), $content);
}
protected function getFlashParameters()
diff --git a/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php b/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php
index fae0235bfb..78b990e62b 100644
--- a/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php
+++ b/core/ViewDataTable/GenerateGraphHTML/ChartEvolution.php
@@ -38,17 +38,34 @@ class Piwik_ViewDataTable_GenerateGraphHTML_ChartEvolution extends Piwik_ViewDat
function init($currentControllerName,
$currentControllerAction,
- $apiMethodToRequestDataTable )
+ $apiMethodToRequestDataTable,
+ $controllerActionCalledWhenRequestSubTable = null)
{
parent::init($currentControllerName,
$currentControllerAction,
- $apiMethodToRequestDataTable );
+ $apiMethodToRequestDataTable,
+ $controllerActionCalledWhenRequestSubTable);
$this->setParametersToModify(array('date' => Piwik_Common::getRequestVar('date', 'last30', 'string')));
$this->disableShowAllViewsIcons();
$this->disableShowTable();
}
+
+ /**
+ * We ensure that the graph for a given Goal has a different ID than the 'Goals Overview' graph
+ * so that both can display on the dashboard at the same time
+ */
+ public function getUniqueIdViewDataTable()
+ {
+ $id = parent::getUniqueIdViewDataTable();
+ if(isset($this->parametersToModify['idGoal']))
+ {
+ $id .= $this->parametersToModify['idGoal'];
+ }
+ return $id;
+ }
+
/**
* Sets the columns that will be displayed on output evolution chart
* By default all columns are displayed ($columnsNames = array() will display all columns)
diff --git a/core/ViewDataTable/HtmlTable.php b/core/ViewDataTable/HtmlTable.php
index d40ed84696..cac953024c 100644
--- a/core/ViewDataTable/HtmlTable.php
+++ b/core/ViewDataTable/HtmlTable.php
@@ -41,7 +41,7 @@ class Piwik_ViewDataTable_HtmlTable extends Piwik_ViewDataTable
function init($currentControllerName,
$currentControllerAction,
$apiMethodToRequestDataTable,
- $controllerActionCalledWhenRequestSubTable = null )
+ $controllerActionCalledWhenRequestSubTable = null)
{
parent::init($currentControllerName,
$currentControllerAction,
@@ -82,14 +82,6 @@ class Piwik_ViewDataTable_HtmlTable extends Piwik_ViewDataTable
}
/**
- * Hook called after the dataTable has been loaded from the API
- * Can be used to add, delete or modify the data freshly loaded
- */
- protected function postDataTableLoadedFromAPI()
- {
- }
-
- /**
* @return Piwik_View with all data set
*/
protected function buildView()
@@ -103,10 +95,11 @@ class Piwik_ViewDataTable_HtmlTable extends Piwik_ViewDataTable
else
{
$columns = $this->getColumnsToDisplay();
- $columnTranslations = array();
+ $columnTranslations = $columnDescriptions = array();
foreach($columns as $columnName)
{
$columnTranslations[$columnName] = $this->getColumnTranslation($columnName);
+ $columnDescriptions[$columnName] = $this->getColumnDescription($columnName);
}
$nbColumns = count($columns);
// case no data in the array we use the number of columns set to be displayed
@@ -118,6 +111,7 @@ class Piwik_ViewDataTable_HtmlTable extends Piwik_ViewDataTable
$view->arrayDataTable = $this->getPHPArrayFromDataTable();
$view->dataTableColumns = $columns;
$view->columnTranslations = $columnTranslations;
+ $view->columnDescriptions = $columnDescriptions;
$view->nbColumns = $nbColumns;
$view->defaultWhenColumnValueNotDefined = '-';
}
diff --git a/core/ViewDataTable/HtmlTable/Goals.php b/core/ViewDataTable/HtmlTable/Goals.php
index a4627e0cd5..8bac47b4b1 100644
--- a/core/ViewDataTable/HtmlTable/Goals.php
+++ b/core/ViewDataTable/HtmlTable/Goals.php
@@ -23,14 +23,35 @@ class Piwik_ViewDataTable_HtmlTable_Goals extends Piwik_ViewDataTable_HtmlTable
public function main()
{
+ $this->idSite = Piwik_Common::getRequestVar('idSite', null, 'int');
+ $this->processOnlyIdGoal = Piwik_Common::getRequestVar('filter_only_display_idgoal', 0, 'int');
$this->viewProperties['show_exclude_low_population'] = true;
$this->viewProperties['show_goals'] = true;
- $this->setColumnsToDisplay( array( 'label',
- 'nb_visits',
- 'goals_conversion_rate',
- 'goal_%s_conversion_rate',
- 'revenue_per_visit',
- ));
+
+ $this->setColumnsTranslations( array(
+ 'goal_%s_conversion_rate' => '%s conversion rate',
+ 'goal_%s_nb_conversions' => '%s conversions',
+ 'goal_%s_revenue_per_visit' => '%s revenue per visit',
+ ));
+
+ $this->setColumnsToDisplay( array(
+ 'label',
+ 'nb_visits',
+ 'goal_%s_nb_conversions',
+ 'goal_%s_conversion_rate',
+ 'goal_%s_revenue_per_visit',
+ 'goals_conversion_rate',
+ 'revenue_per_visit',
+ ));
+
+ // We ensure that the 'Sort by' column is actually displayed in the table
+ // eg. most daily reports sort by nb_uniq_visitors but this column is not displayed in the Goals table
+ $columnsToDisplay = $this->getColumnsToDisplay();
+ $columnToSortBy = $this->getSortedColumn();
+ if(!in_array($columnToSortBy, $columnsToDisplay))
+ {
+ $this->setSortedColumn('nb_visits', 'desc');
+ }
parent::main();
}
@@ -39,35 +60,49 @@ class Piwik_ViewDataTable_HtmlTable_Goals extends Piwik_ViewDataTable_HtmlTable
$this->controllerActionCalledWhenRequestSubTable = null;
}
- protected function getRequestString()
- {
- $requestString = parent::getRequestString();
- return $requestString . '&filter_update_columns_when_show_all_goals=1';
- }
-
- protected $columnsToPercentageFilter = array();
-
- private function getIdSite()
- {
- return Piwik_Common::getRequestVar('idSite', null, 'int');
- }
-
public function setColumnsToDisplay($columnsNames)
{
$newColumnsNames = array();
+ $goals = array();
+ $idSite = $this->getIdSite();
+ if($idSite)
+ {
+ $goals = Piwik_Goals_API::getInstance()->getGoals( $idSite );
+ }
foreach($columnsNames as $columnName)
{
- if($columnName == 'goal_%s_conversion_rate')
+ if(in_array($columnName, array('goal_%s_conversion_rate', 'goal_%s_nb_conversions', 'goal_%s_revenue_per_visit')))
{
- $goals = Piwik_Goals_API::getGoals( $this->getIdSite() );
foreach($goals as $goal)
{
$idgoal = $goal['idgoal'];
- $name = $goal['name'];
- $columnName = 'goal_'.$idgoal.'_conversion_rate';
- $newColumnsNames[] = $columnName;
- $this->setColumnTranslation($columnName, $name);
- $this->columnsToPercentageFilter[] = $columnName;
+ if($this->processOnlyIdGoal > Piwik_DataTable_Filter_UpdateColumnsWhenShowAllGoals::GOALS_FULL_TABLE
+ && $this->processOnlyIdGoal != $idgoal)
+ {
+ continue;
+ }
+ $name = Piwik_Translate($this->getColumnTranslation($columnName), $goal['name']);
+ $columnNameGoal = str_replace('%s', $idgoal, $columnName);
+ $this->setColumnTranslation($columnNameGoal, $name);
+ if(strstr($columnNameGoal, '_rate') !== false)
+ {
+ $this->columnsToPercentageFilter[] = $columnNameGoal;
+ }
+ // For the goal table (when the flag icon is clicked), we only display the per Goal Conversion rate
+ elseif($this->processOnlyIdGoal == Piwik_DataTable_Filter_UpdateColumnsWhenShowAllGoals::GOALS_OVERVIEW)
+ {
+ continue;
+ }
+
+ if(strstr($columnNameGoal, '_revenue') !== false)
+ {
+ $this->columnsToRevenueFilter[] = $columnNameGoal;
+ }
+ else
+ {
+ $this->columnsToConversionFilter[] = $columnNameGoal;
+ }
+ $newColumnsNames[] = $columnNameGoal;
}
}
else
@@ -78,14 +113,45 @@ class Piwik_ViewDataTable_HtmlTable_Goals extends Piwik_ViewDataTable_HtmlTable
parent::setColumnsToDisplay($newColumnsNames);
}
+ protected function getRequestString()
+ {
+ $requestString = parent::getRequestString();
+ if($this->processOnlyIdGoal > Piwik_DataTable_Filter_UpdateColumnsWhenShowAllGoals::GOALS_FULL_TABLE)
+ {
+ $requestString .= "&filter_only_display_idgoal=".$this->processOnlyIdGoal;
+ }
+ return $requestString . '&filter_update_columns_when_show_all_goals=1';
+ }
+
+ protected $columnsToPercentageFilter = array();
+ protected $columnsToRevenueFilter = array();
+ protected $columnsToConversionFilter = array();
+ protected $idSite = false;
+
+ private function getIdSite()
+ {
+ return $this->idSite;
+ }
+
protected function postDataTableLoadedFromAPI()
{
parent::postDataTableLoadedFromAPI();
$this->columnsToPercentageFilter[] = 'goals_conversion_rate';
foreach($this->columnsToPercentageFilter as $columnName)
{
- $this->dataTable->filter('ColumnCallbackReplace', array($columnName, create_function('$rate', 'return $rate."%";')));
+ $this->dataTable->filter('ColumnCallbackReplace', array($columnName, create_function('$rate', 'return sprintf("%.1f",$rate)."%";')));
+ }
+ $this->columnsToRevenueFilter[] = 'revenue_per_visit';
+ foreach($this->columnsToRevenueFilter as $columnName)
+ {
+ $this->dataTable->filter('ColumnCallbackReplace', array($columnName, create_function('$value', 'return sprintf("%.1f",$value);')));
+ $this->dataTable->filter('ColumnCallbackReplace', array($columnName, array("Piwik", "getPrettyMoney"), array($this->getIdSite())));
+ }
+
+ foreach($this->columnsToConversionFilter as $columnName)
+ {
+ // this ensures that the value is set to zero for all rows where the value was not set (no conversion)
+ $this->dataTable->filter('ColumnCallbackReplace', array($columnName, create_function('$value', 'return $value;')));
}
- $this->dataTable->filter('ColumnCallbackReplace', array('revenue_per_visit', array("Piwik", "getPrettyMoney")));
}
}
diff --git a/core/Visualization/Chart.php b/core/Visualization/Chart.php
index 9efd164aa9..c795522d8d 100644
--- a/core/Visualization/Chart.php
+++ b/core/Visualization/Chart.php
@@ -10,9 +10,6 @@
* @package Piwik
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see libs/open-flash-chart/php-ofc-library/open-flash-chart.php
* @link http://teethgrinder.co.uk/open-flash-chart-2/
@@ -128,8 +125,12 @@ abstract class Piwik_Visualization_Chart implements Piwik_iView
public function render()
{
- @header("Pragma: ");
- @header("Cache-Control: no-store, must-revalidate");
+ if(Piwik_Url::getCurrentScheme() == 'https' ||
+ Zend_Registry::get('config')->General->reverse_proxy)
+ {
+ @header("Pragma: ");
+ @header("Cache-Control: must-revalidate");
+ }
return $this->chart->toPrettyString();
}
diff --git a/core/Visualization/Sparkline.php b/core/Visualization/Sparkline.php
index 53110906f4..3b17e8fceb 100644
--- a/core/Visualization/Sparkline.php
+++ b/core/Visualization/Sparkline.php
@@ -10,9 +10,6 @@
* @package Piwik
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see libs/sparkline/lib/Sparkline_Line.php
* @link http://sparkline.org
@@ -52,18 +49,22 @@ class Piwik_Visualization_Sparkline implements Piwik_iView
$width = self::getWidth();
$height = self::getHeight();
- $data = $this->values;
$sparkline = new Sparkline_Line();
$sparkline->SetColor('lineColor', 22, 44, 74); // dark blue
$sparkline->SetColorHtml('red', '#FF7F7F');
$sparkline->SetColorHtml('blue', '#55AAFF');
$sparkline->SetColorHtml('green', '#75BF7C');
- $data = array_reverse($data);
$min = $max = $last = null;
$i = 0;
foreach($this->values as $value)
{
+ // 50% should be plotted as 50
+ $toRemove = '%';
+ if(strpos($value, $toRemove) !== false)
+ {
+ $value = str_replace($toRemove, '', $value);
+ }
$sparkline->SetData($i, $value);
if( null == $min || $value <= $min[1])
{
@@ -77,14 +78,12 @@ class Piwik_Visualization_Sparkline implements Piwik_iView
$i++;
}
$sparkline->SetYMin(0);
- $sparkline->setYMax($max[1] + 0.5); // the +0.5 seems to be mandatory to not lose some pixels when value = max
- $sparkline->SetPadding( 3, 0, 2, 0);
- $font = FONT_2;
- // the -0.5 is a hack as the sparkline samping rendering is obviously slightly bugged
- // (see also fix marked as //FIX FROM PIWIK in libs/sparkline/lib/Sparkline.php)
- $sparkline->SetFeaturePoint($min[0] -1, $min[1], 'red', 5);
- $sparkline->SetFeaturePoint($max[0] -1, $max[1], 'green', 5);
- $sparkline->SetFeaturePoint($last[0] -1, $last[1], 'blue', 5);
+ $sparkline->SetYMax($max[1]);
+ $sparkline->SetPadding( 3, 0, 2, 0 ); // top, right, bottom, left
+// $font = FONT_2;
+ $sparkline->SetFeaturePoint($min[0], $min[1], 'red', 5);
+ $sparkline->SetFeaturePoint($max[0], $max[1], 'green', 5);
+ $sparkline->SetFeaturePoint($last[0], $last[1], 'blue', 5);
$sparkline->SetLineSize(3); // for renderresampled, linesize is on virtual image
$ratio = 1;
// var_dump($min);var_dump($max);var_dump($lasts);exit;
diff --git a/core/testMinimumPhpVersion.php b/core/testMinimumPhpVersion.php
index 36a6ac1f1f..bd28c3fe72 100644
--- a/core/testMinimumPhpVersion.php
+++ b/core/testMinimumPhpVersion.php
@@ -10,9 +10,6 @@
* @package Piwik
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* This file is executed before anything else.
* It checks the minimum PHP version required to run Piwik.
@@ -48,7 +45,7 @@ function Piwik_ExitWithMessage($message, $optionalTrace = false, $optionalLinks
{
if($optionalTrace)
{
- $optionalTrace = '<font color="#888888">Backtrace:<br/><pre>'.$optionalTrace.'</pre></font>';
+ $optionalTrace = '<font color="#888888">Backtrace:<br /><pre>'.$optionalTrace.'</pre></font>';
}
if($optionalLinks)
{
@@ -69,6 +66,7 @@ function Piwik_ExitWithMessage($message, $optionalTrace = false, $optionalLinks
exit;
}
+// added in PHP 4.3.0
if (!function_exists('file_get_contents'))
{
function file_get_contents($filename)
diff --git a/index.php b/index.php
index 3d14f533a5..07c2ebc0de 100644
--- a/index.php
+++ b/index.php
@@ -31,49 +31,17 @@ if(!defined('PIWIK_INCLUDE_PATH'))
define('PIWIK_INCLUDE_PATH', PIWIK_DOCUMENT_ROOT);
}
-if(!defined('PIWIK_INCLUDE_SEARCH_PATH'))
-{
- define('PIWIK_INCLUDE_SEARCH_PATH', PIWIK_INCLUDE_PATH . '/core'
- . PATH_SEPARATOR . PIWIK_INCLUDE_PATH . '/libs'
- . PATH_SEPARATOR . PIWIK_INCLUDE_PATH . '/plugins');
- @ini_set('include_path', PIWIK_INCLUDE_SEARCH_PATH);
- @set_include_path(PIWIK_INCLUDE_SEARCH_PATH);
-}
-
-if(!defined('PIWIK_SESSION_NAME'))
-{
- define('PIWIK_SESSION_NAME', 'PIWIK_SESSID');
-}
-@ini_set('session.name', PIWIK_SESSION_NAME);
-if(ini_get('session.save_handler') == 'user')
-{
- @ini_set('session.save_handler', 'files');
- @ini_set('session.save_path', '');
-}
-if(ini_get('session.save_handler') == 'files')
-{
- if(ini_get('safe_mode') || ini_get('open_basedir') || !@is_writable(ini_get('session.save_path')))
- {
- $sessionPath = PIWIK_USER_PATH . '/tmp/sessions';
- @ini_set('session.save_path', $sessionPath);
- if(!is_dir($sessionPath))
- {
- @mkdir($sessionPath, 0755, true);
- }
- }
-}
-
require_once PIWIK_INCLUDE_PATH . '/core/testMinimumPhpVersion.php';
// NOTE: the code above this comment must be PHP4 compatible
session_cache_limiter('nocache');
-@date_default_timezone_set(date_default_timezone_get());
+@date_default_timezone_set('UTC');
require_once PIWIK_INCLUDE_PATH .'/core/Loader.php';
if(!defined('PIWIK_ENABLE_SESSION_START') || PIWIK_ENABLE_SESSION_START)
{
- Zend_Session::start();
+ Piwik_Session::start();
}
if(!defined('PIWIK_ENABLE_ERROR_HANDLER') || PIWIK_ENABLE_ERROR_HANDLER)
diff --git a/js/README b/js/README
index 39939896c4..b07a766228 100644
--- a/js/README
+++ b/js/README
@@ -1,3 +1,27 @@
+Introduction
+
+* The js/ folder contains:
+
+ - index.php - a servlet described below
+ - piwik.js - the uncompressed piwik.js source for you to study or reference
+ - README - this documentation file
+
+Why Use "js/index.php"?
+
+* js/index.php (or implicitly as "js/") can be used to serve up the minified
+ piwik.js
+
+ - it supports conditional-GET and Last-Modified, so piwik.js can be cached
+ by the browser
+ - it supports deflate/gzip compression if your web server (e.g., Apache
+ without mod_deflate or mod_gzip), shrinking the data transfer to 3.5K
+
+* js/index.php (or implicitly as "js/") can also act as a proxy to piwik.php
+
+* If you are concerned about the impact of browser-based privacy filters which
+ attempt to block tracking, you can change your tracking code to use "js/"
+ instead of "piwik.js" and "piwik.php", respectively.
+
Deployment
* piwik.js is minified using YUICompressor 2.4.2.
@@ -12,13 +36,8 @@ Deployment
$ cd /path/to/piwik/js/
$ sed 's/eval/replacedEvilString/' <piwik.js | java -jar yuicompressor-2.4.2/build/yuicompressor-2.4.2.jar --type js --line-break 1000 | sed 's/replacedEvilString/eval/' > piwik-min.js && cp piwik-min.js ../piwik.js
- This will generate the minify /path/to/piwik/js/piwik-min.js and copy it to /path/to/piwik/piwik.js
-
-* The uncompressed piwik.js resides in the js/ folder. If you omit the filename,
- js/index.php will serve the minified version. A side effect of this feature
- is that it is not currently blockable by various AdBlock filters.
-
- <script src="http"//yoursite/js/" type="text/javascript">
+ This will generate the minify /path/to/piwik/js/piwik-min.js and copy it to
+ /path/to/piwik/piwik.js
* In a production environment, the tests/javascript folder is not used and can
be removed (if present).
diff --git a/js/index.php b/js/index.php
index 60786f2849..afba718085 100644
--- a/js/index.php
+++ b/js/index.php
@@ -7,18 +7,64 @@
* @version $Id$
*/
-$file = "../piwik.js";
+if(!empty($_SERVER['QUERY_STRING'])) {
+ include '../piwik.php';
+ exit;
+}
-/*
- * Conditional GET
- */
-if (file_exists($file)) {
+$file = '../piwik.js';
+
+if (file_exists($file) && function_exists('readfile')) {
+ // conditional GET
$modifiedSince = '';
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
$modifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
}
$lastModified = gmdate('D, d M Y H:i:s', filemtime($file)) . ' GMT';
+ // optional compression
+ $compressed = false;
+ $encoding = '';
+ if (isset($_SERVER['HTTP_ACCEPT_ENCODING'])) {
+ $acceptEncoding = $_SERVER['HTTP_ACCEPT_ENCODING'];
+ if (extension_loaded('zlib') && function_exists('file_get_contents') && function_exists('file_put_contents')) {
+ if (preg_match('/(?:^|, ?)(deflate)(?:,|$)/', $acceptEncoding, $matches)) {
+ $encoding = 'deflate';
+ $filegz = '../piwik.js.deflate';
+ } else if (preg_match('/(?:^|, ?)((x-)?gzip)(?:,|$)/', $acceptEncoding, $matches)) {
+ $encoding = $matches[1];
+ $filegz = '../piwik.js.gz';
+ }
+
+ if (!empty($encoding)) {
+ // compress-on-demand and use cache
+ if(!file_exists($filegz) || (filemtime($file) > filemtime($filegz))) {
+ $data = file_get_contents($file);
+
+ if ($encoding == 'deflate') {
+ $data = gzcompress($data, 9);
+ } else if ($encoding == 'gzip' || $encoding == 'x-gzip') {
+ $data = gzencode($data, 9);
+ }
+
+ file_put_contents($filegz, $data);
+ $file = $filegz;
+ }
+
+ $compressed = true;
+ $file = $filegz;
+ }
+ } else {
+ // manually compressed
+ $filegz = '../piwik.js.gz';
+ if (preg_match('/(?:^|, ?)((x-)?gzip)(?:,|$)/', $acceptEncoding, $matches) && file_exists($filegz) && (filemtime($file) < filemtime($filegz))) {
+ $encoding = $matches[1];
+ $compressed = true;
+ $file = $filegz;
+ }
+ }
+ }
+
// strip any trailing data appended to header
if (false !== ($semicolon = strpos($modifiedSince, ';'))) {
$modifiedSince = substr($modifiedSince, 0, $semicolon);
@@ -29,13 +75,17 @@ if (file_exists($file)) {
} else {
header('Last-Modified: ' . $lastModified);
header('Content-Length: ' . filesize($file));
- header('Content-Type: application/x-javascript');
+ header('Content-Type: application/javascript; charset=UTF-8');
+
+ if ($compressed) {
+ header('Content-Encoding: ' . $encoding);
+ }
if (!readfile($file)) {
- header ("HTTP/1.0 505 Internal server error");
+ header ('HTTP/1.0 505 Internal server error');
}
}
} else {
- header ("HTTP/1.0 404 Not Found");
+ header ('HTTP/1.0 404 Not Found');
}
exit;
diff --git a/js/piwik.js b/js/piwik.js
index e14b91c8cd..8c4527be4e 100644
--- a/js/piwik.js
+++ b/js/piwik.js
@@ -6,7 +6,7 @@
* @version $Id$
*/
-/*jslint browser:true, forin:true, plusplus:false, onevar:false, eqeqeq:false; strict:false */
+/*jslint browser:true, forin:true, plusplus:false, onevar:false, eqeqeq:false, strict:false */
/*global window escape unescape ActiveXObject */
// Note: YUICompressor 2.4.2 won't compress piwik_log() because of the the "evil" eval().
@@ -18,6 +18,8 @@
*
* This version of piwik.js is known to not work with:
* - IE4 (and below) - try..catch and for..in not introduced until IE5
+ *
+ * @todo Move to minimum EMCAScript v3 (IE5.5).
*/
// Guard against loading the script twice
@@ -93,11 +95,11 @@ if (!this.Piwik) {
* Delay/pause (blocks UI)
*/
if (isDefined(expireDateTime)) {
- var now = new Date();
+ var now;
- while (now.getTime() < expireDateTime) {
+ do {
now = new Date();
- }
+ } while (now.getTime() < expireDateTime);
}
executePluginMethod('unload');
@@ -122,19 +124,24 @@ if (!this.Piwik) {
*/
function addReadyListener() {
if (documentAlias.addEventListener) {
+// addEventListener(documentAlias, "DOMContentLoaded", function ready() { // named functions added in IE 5.5
addEventListener(documentAlias, "DOMContentLoaded", function () {
+// documentAlias.removeEventListener("DOMContentLoaded", ready, false);
documentAlias.removeEventListener("DOMContentLoaded", arguments.callee, false);
loadHandler();
});
} else if (documentAlias.attachEvent) {
- documentAlias.attachEvent("onreadystatechange", function () {
+// documentAlias.attachEvent("onreadystatechange", function ready() {
+ documentAlias.attachEvent("onreadystatechange", function () { // named functions added in IE 5.5
if (documentAlias.readyState === "complete") {
+// documentAlias.detachEvent("onreadystatechange", ready);
documentAlias.detachEvent("onreadystatechange", arguments.callee);
loadHandler();
}
});
if (documentAlias.documentElement.doScroll && windowAlias == windowAlias.top) {
+// (function ready() { // named functions added in IE 5.5
(function () {
if (hasLoaded) {
return;
@@ -142,6 +149,7 @@ if (!this.Piwik) {
try {
documentAlias.documentElement.doScroll("left");
} catch (error) {
+// setTimeout(ready, 0);
setTimeout(arguments.callee, 0);
return;
}
@@ -172,13 +180,13 @@ if (!this.Piwik) {
configTrackerSiteId = siteId || '',
// Document URL
- configUrl = documentAlias.location.href,
+ configCustomUrl,
// Document title
configTitle = documentAlias.title,
// Extensions to be treated as download links
- configDownloadExtensions = '7z|aac|arc|arj|asf|asx|avi|bin|csv|doc|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt|qtm?|ra(m|r)?|sea|sit|tar|t?bz2?|tgz|torrent|txt|wav|wma|wmv|wpd||xls|xml|z|zip',
+ configDownloadExtensions = '7z|aac|arc|arj|asf|asx|avi|bin|csv|deb|dmg|doc|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt|qtm?|ra(m|r)?|rpm|sea|sit|tar|t?bz2?|tgz|torrent|txt|wav|wma|wmv|wpd||xls|xml|z|zip',
// Hosts or alias(es) to not treat as outlinks
configHostsAlias = [hostnameAlias],
@@ -296,7 +304,7 @@ if (!this.Piwik) {
// the remote chance that this gets fixed someday.
return String(value);
- case 'object':
+ case 'object':
// Make an array to hold the partial results of stringifying this object value.
partial = [];
@@ -478,7 +486,8 @@ if (!this.Piwik) {
var i, now, request;
now = new Date();
request = 'idsite=' + configTrackerSiteId +
- '&url=' + escapeWrapper(configUrl) +
+ '&rec=1' +
+ '&url=' + escapeWrapper(isDefined(configCustomUrl) ? configCustomUrl : documentAlias.location.href) +
'&res=' + screenAlias.width + 'x' + screenAlias.height +
'&h=' + now.getHours() + '&m=' + now.getMinutes() + '&s=' + now.getSeconds() +
'&cookie=' + browserHasCookies +
@@ -496,9 +505,9 @@ if (!this.Piwik) {
/*
* Log the page view / visit
*/
- function logPageView() {
+ function logPageView(customTitle) {
var request = getRequest();
- request += '&action_name=' + escapeWrapper(configTitle); // refs #530;
+ request += '&action_name=' + escapeWrapper(isDefined(customTitle) ? customTitle : configTitle); // refs #530;
// encode custom data
if (isDefined(configCustomData)) {
@@ -534,11 +543,12 @@ if (!this.Piwik) {
}
/*
- * Log the click with the server
+ * Log the link or click with the server
*/
- function logClick(url, linkType, customData) {
+ function logLink(url, linkType, customData) {
var request;
request = 'idsite=' + configTrackerSiteId +
+ '&rec=1' +
'&' + linkType + '=' + escapeWrapper(url) +
'&rand=' + Math.random() +
'&redirect=0';
@@ -589,7 +599,7 @@ if (!this.Piwik) {
* Construct regular expression of classes
*/
function getClassesRegExp(configClasses, defaultClass) {
- var i, classesRegExp = '(^| )(piwik_' + defaultClass;
+ var i, classesRegExp = '(^| )(piwik[_-]' + defaultClass;
if (isDefined(configClasses)) {
for (i = 0; i < configClasses.length; i++) {
@@ -676,7 +686,7 @@ if (!this.Piwik) {
// track outlinks and all downloads
linkType = getLinkType(sourceElement.className, sourceHref, isSiteHostName(sourceHostName));
if (linkType) {
- logClick(sourceHref, linkType);
+ logLink(sourceHref, linkType);
}
}
}
@@ -844,7 +854,7 @@ if (!this.Piwik) {
*/
setCustomUrl: function (url) {
if (isDefined(url)) {
- configUrl = url;
+ configCustomUrl = url;
}
},
@@ -935,14 +945,14 @@ if (!this.Piwik) {
* Manually log a click from your own code
*/
trackLink: function (sourceUrl, linkType, customData) {
- logClick(sourceUrl, linkType, customData);
+ logLink(sourceUrl, linkType, customData);
},
/*
* Log visit to this page
*/
- trackPageView: function () {
- logPageView();
+ trackPageView: function (customTitle) {
+ logPageView(customTitle);
}
};
}
diff --git a/lang/am.php b/lang/am.php
new file mode 100644
index 0000000000..d94b92031d
--- /dev/null
+++ b/lang/am.php
@@ -0,0 +1,736 @@
+<?php
+$translations = array(
+ 'General_Locale' => 'am_ET.UTF-8',
+ 'General_TranslatorName' => 'Alazar Tekle, <a href="http://www.ethiopia-map.com/">Bandira AddisMap Ent PLC</a>',
+ 'General_TranslatorEmail' => 'info@addismap.com',
+ 'General_EnglishLanguageName' => 'Amharic',
+ 'General_OriginalLanguageName' => 'አማርኛ',
+ 'General_HelloUser' => 'ሃሎ, %s!',
+ 'General_OpenSourceWebAnalytics' => 'ክፍት የሆነ የድር ጣቢያ ማመዛዘኛ',
+ 'General_YourDashboard' => 'ዳሽቦርድዎ',
+ 'General_API' => 'ኤፒአይI',
+ 'General_Widgets' => 'Widgets',
+ 'General_Settings' => 'ቅንብሮች',
+ 'General_GiveUsYourFeedback' => 'እባክዎ መልሰህ መግብ ስጡን!',
+ 'General_Unknown' => 'ያልታወቀ',
+ 'General_Required' => '%s አስፈላጊ',
+ 'General_Error' => 'ስህተት',
+ 'General_Warning' => 'ማስጠንቀቂያ',
+ 'General_BackToHomepage' => 'ወደ ፒዊክ መነሻ ገፅ ተመለስ',
+ 'General_Yes' => 'አዎን',
+ 'General_No' => 'የለም',
+ 'General_Delete' => 'ሰርዝ',
+ 'General_Edit' => 'አርትእ',
+ 'General_Ok' => 'ይሁን',
+ 'General_Close' => 'ዝጋ',
+ 'General_Logout' => 'ውጣ',
+ 'General_Done' => 'አልቋል',
+ 'General_LoadingData' => 'ውሂብ በማስገባት ላይ...',
+ 'General_Loading' => 'በማስገባት ላይ...',
+ 'General_ErrorRequest' => 'Oops&hellip; problem during the request, please try again.',
+ 'General_Next' => 'ቀጥል',
+ 'General_Previous' => 'ቀደም ያለ',
+ 'General_Search' => 'ፈልግ',
+ 'General_Others' => 'ለሎች',
+ 'General_Table' => 'ሰንጠረዥ',
+ 'General_Piechart' => 'አምባሻ ገበታ',
+ 'General_TagCloud' => 'መለያ Cloud',
+ 'General_VBarGraph' => 'አቀባዊ አሞሌ ግራፍ',
+ 'General_Export' => 'ላክ',
+ 'General_ExportAsImage' => 'እንደምስል ላክ',
+ 'General_SaveImageOnYourComputer' => 'ምስሉን በኮምፒውተር ላይ ለማስቀመጥ ቀኙን ጠቅ አድርግን ተጠቅመህ "ምስሉን እንደ --- አስቀምጥ" የሚለውን ምረጥ',
+ 'General_Refresh' => 'ገፁን አድስ',
+ 'General_Visitors' => 'ጎብኝዎች',
+ 'General_ColumnNbUniqVisitors' => 'ብቸኛ ጎብኚዎች',
+ 'General_ColumnNbVisits' => 'ጉብኝቶች',
+ 'General_ColumnNbActions' => 'ርምጃዎች',
+ 'General_ColumnMaxActions' => 'በአንድ ጉብኝት የተወሰዱ ከፍተኛ ርምጃዎች',
+ 'General_ColumnSumVisitLength' => 'በጎብኚዎች የተፈጀ ከፍተኛ ሰዓት (በሰከንዶች)',
+ 'General_ColumnLabel' => 'መሰየሚያ',
+ 'General_ColumnActionsPerVisit' => 'ርምጃ ከጉብኝት',
+ 'General_ColumnAvgTimeOnSite' => 'በየድር ጣቢያ የተፈጀ አማካይ ሰዓት',
+ 'General_ColumnBounceRate' => 'ተመላሽ',
+ 'General_ColumnPageviews' => 'ገፅ ትይታዎች',
+ 'General_ColumnUniquePageviews' => 'ብቸኛ ገፅ ትይታዎች',
+ 'General_ColumnValuePerVisit' => 'እሴት በጉብኝት',
+ 'General_ColumnVisitsWithConversions' => 'ጉብኝት ከልወጣዎች ጋር',
+ 'General_Save' => 'አስቀምጥ',
+ 'General_Website' => 'ድር ጣቢያ',
+ 'General_NoDataForGraph' => 'ለዚህ ግራፍ ምንም ውሂብ የለም',
+ 'General_NoDataForTagCloud' => 'ለዚህ መለያ ክላውድ ምንም ውሂብ የለም.',
+ 'General_DisplayNormalTable' => 'የተለመደ ሰንጠረዥ አሳይ',
+ 'General_DisplayMoreData' => 'ተጨማሪ ውሂብ አሳይ',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s ፒዊክ %s በትብብር የተዘረጋ ፕሮጀክት ነው። %s ፒዊክ ከተስማማችሁ ድጋፍ መሰጠት ትችላላችሁ! ለፒዊክ ፕሮጀክት %s እንዴት አስተዋፃኦ ማድረግ እንደሚችሉ ይመልከቱ?%s ',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'አሁን እየተመለከቱ ያሉት የሙከራ ፕሮግራሙን ነው%s; ሙሉ ፕሮግራሙን %sያውርዱ%s ይጎብኙት %s',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'ፒዊክን %s ማግኘት ይቻላል። %s እባክዎን ያልቁት!%s (ለውጦቹን%s ይመልከቱ%s).',
+ 'General_BackToPiwik' => 'ወደፒዊክ ተመለስ',
+ 'General_ShortMonth_1' => 'ጥር',
+ 'General_ShortMonth_2' => 'የካ ',
+ 'General_ShortMonth_3' => 'መጋ',
+ 'General_ShortMonth_4' => 'ሚያ',
+ 'General_ShortMonth_5' => 'ግን',
+ 'General_ShortMonth_6' => 'ሰኔ',
+ 'General_ShortMonth_7' => 'ሐም',
+ 'General_ShortMonth_8' => 'ነሐሴ',
+ 'General_ShortMonth_9' => 'መስከ',
+ 'General_ShortMonth_10' => 'ጥቅ',
+ 'General_ShortMonth_11' => 'ሀዳ',
+ 'General_ShortMonth_12' => 'ታህ',
+ 'General_LongMonth_1' => 'ጥር',
+ 'General_LongMonth_2' => 'የካቲት',
+ 'General_LongMonth_3' => 'መጋቢት',
+ 'General_LongMonth_4' => 'ሚያዝያ',
+ 'General_LongMonth_5' => 'ግንቦት',
+ 'General_LongMonth_6' => 'ሰኔ',
+ 'General_LongMonth_7' => 'ሐምሌ',
+ 'General_LongMonth_8' => 'ነሐሴ',
+ 'General_LongMonth_9' => 'መስከረም',
+ 'General_LongMonth_10' => 'ጥቅምት',
+ 'General_LongMonth_11' => 'ሀዳር',
+ 'General_LongMonth_12' => 'ታህሳስ',
+ 'General_ShortDay_1' => 'ሰኞ',
+ 'General_ShortDay_2' => 'ማክ',
+ 'General_ShortDay_3' => 'ረቡ',
+ 'General_ShortDay_4' => 'ሐሙ',
+ 'General_ShortDay_5' => 'አር',
+ 'General_ShortDay_6' => 'ቅዳ',
+ 'General_ShortDay_7' => 'እሁ',
+ 'General_LongDay_1' => 'ሰኞ',
+ 'General_LongDay_2' => 'ማክሰኞ',
+ 'General_LongDay_3' => 'ረቡዕ ',
+ 'General_LongDay_4' => 'ሐሙስ',
+ 'General_LongDay_5' => 'አርብ',
+ 'General_LongDay_6' => 'ቅዳሜ',
+ 'General_LongDay_7' => 'እሁድ',
+ 'CorePluginsAdmin_Plugins' => 'ተሰኪዎች',
+ 'CorePluginsAdmin_PluginsManagement' => 'ተሰኪዎች መመነጅ',
+ 'CorePluginsAdmin_MainDescription' => 'ተሰኪዎች የፒዊክን አገልግሎት ያራዝማሉ ያሰፋሉ። ተሰኪዎች አንዴ ከተጫኑ እዚሁ ጋር መገበርም ማቦዘንም ይቻላል።',
+ 'CorePluginsAdmin_Plugin' => 'ተሰኪ',
+ 'CorePluginsAdmin_Version' => 'ስሪት',
+ 'CorePluginsAdmin_Description' => 'ገለጣ',
+ 'CorePluginsAdmin_Status' => 'ሁኔታ',
+ 'CorePluginsAdmin_Action' => 'ርምጃ',
+ 'CorePluginsAdmin_PluginHomepage' => 'የተሰኪ መነሻ ገፅ',
+ 'CorePluginsAdmin_Activated' => 'የተገበረ',
+ 'CorePluginsAdmin_Active' => 'ገባሪ',
+ 'CorePluginsAdmin_Inactive' => 'ያልተመረጠ',
+ 'CorePluginsAdmin_ActivatedHelp' => 'ይህ ተሰኪ ሊቦዝን አይችልም',
+ 'CorePluginsAdmin_Deactivate' => 'አቦዝን',
+ 'CorePluginsAdmin_Activate' => 'አግብር',
+ 'CorePluginsAdmin_MenuPlugins' => 'ተሰኪዎች',
+ 'API_QuickDocumentation' => '<h2>የኤፒአይ ፈጣን ስነዳ</h2><p>ለዛሬ ውሂብ ከሌለዎት በመጀመሪያ <a href=\'misc/generateVisits.php\' target=_blank>ወሂብ ለማመንጨት</a> ጉብኝት አመንጪ ስክሪፕቱን መጠቀም ይችላሉ።</p><p>የተለያዩ ቅርፀቶችን ለተቀሩት ሜተዶች መጠቀም ይቻላል። ከፒዊክ ላይ የሚፈለገውን ውሂብ ብቻ ለይቶ ማውጣት ይቻላል!</p><p><b>ለተጨማሪ መረጃ የሚከተለውን መመልከት ይችላሉ<a href=\'http://dev.piwik.org/trac/wiki/API\'>የኤፒአይ ይፋ ስነዳ</a> or the <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>የኤፒአይ ማጣቀሻ</a>.</b></P><h2>የተጠቃሚ ማረጋገጫ</h2><p>በግል ስክሪፕትዎ ላይ <b>የተመለከተውን ውሂብ በክሮንታብ ወዘተ ማግኘት ከፈለጉ. </b> የሚከተለውን ግቤት<code><u>&token_auth=%s</u></code> ማረጋገጫ ወደ ሚፈልገው የኤፒአይ የመጥሪያ ዩአርኤል መጨመር ይጠበቅብዎታል።
+</p><p>ይህ token_auth እንደመግቢያ እና የይለፍ ቃል በምስጢር መያዝ ይኖርበታል <b>ከማንም ጋር አይጋሩት!</p>',
+ 'API_LoadedAPIs' => 'ማስጋባት ተሳክቷል %s ኤፒአይዎች',
+ 'CoreHome_NoPrivileges' => 'እንደ \'%s\' ገብተዋል ነገር ግን ፒዊክ ውስጥ ምንም ዓይነት ፈቃድ አልተቀመጠልዎትም።<br />የፒዊክ መናጅዎትን የድር ገበታ ትይታ ፈቃድ እንዲሰጥዎ ይጠይቁ።.',
+ 'CoreHome_JavascriptDisabled' => 'የፒዊክን መደበኛ ትይታ ለመጠቀም ከፈለጉ ጃቫ ስክሪፕትን ማንቃት አለብዎ።<br />ነገር ግን ጃቫ ስክሪፕት አንድ ቦዝኗል ወይም በማሰሺያዎ ድጋፍ አላገኘም።<br />መደበኛ ትይታን ለመጠቀም የማሰሺያዎን አማራጭ በመለወጥ ጃቫ ስክሪፕትዎን ማንቃት አለብዎ በመቀጠልም%1ኛ ይሞክሩ%2s.<br />',
+ 'CoreHome_TableNoData' => 'ለዚህ ሰንጠረዥ ምንም ውሂብ የለም',
+ 'CoreHome_CategoryNoData' => 'በዚህ ፈርጅ ምንም ውሂብ የለም. "ሁሉንም ምድብ" ለማጠቃለል ይሞክሩ።',
+ 'CoreHome_ShowJSCode' => 'ለማስገባት የጃቫ ስክሪፕትን ኮድ አሳይ',
+ 'CoreHome_IncludeAllPopulation_js' => 'ሁሉንም ምድብ ያጠቃሉ',
+ 'CoreHome_ExcludeLowPopulation_js' => 'አነስተኛ ምድቦችን ይቀንሱ',
+ 'CoreHome_PageOf_js' => '%s የ %s',
+ 'CoreHome_Loading_js' => 'ባማስገባት ላይ...',
+ 'CoreHome_DayFormat' => '%ረዥም ቀን% %ቀን% %lረዥም ወር% %ረዥም ዓመት%',
+ 'CoreHome_PeriodDay' => 'ቀን',
+ 'CoreHome_PeriodWeek' => 'ሳምንት',
+ 'CoreHome_PeriodMonth' => 'ወር',
+ 'CoreHome_PeriodYear' => 'ዓመት',
+ 'CoreHome_PeriodDays' => 'ቀናት',
+ 'CoreHome_PeriodWeeks' => 'ሳምንታት',
+ 'CoreHome_PeriodMonths' => 'ወራት',
+ 'CoreHome_PeriodYears' => 'ዓመታት',
+ 'CoreHome_DaySu_js' => 'እሁ',
+ 'CoreHome_DayMo_js' => 'ሰኞ',
+ 'CoreHome_DayTu_js' => 'ማክ',
+ 'CoreHome_DayWe_js' => 'ረቡ',
+ 'CoreHome_DayTh_js' => 'ሐሙ,',
+ 'CoreHome_DayFr_js' => 'አርብ',
+ 'CoreHome_DaySa_js' => 'ቅዳ',
+ 'CoreHome_MonthJanuary_js' => 'ጥር',
+ 'CoreHome_MonthFebruary_js' => 'የካቲት',
+ 'CoreHome_MonthMarch_js' => 'መጋቢት',
+ 'CoreHome_MonthApril_js' => 'ሚያዚያ',
+ 'CoreHome_MonthMay_js' => 'ግንቦት',
+ 'CoreHome_MonthJune_js' => 'ሰኔ',
+ 'CoreHome_MonthJuly_js' => 'ሐምሌ',
+ 'CoreHome_MonthAugust_js' => 'ነሐሴ',
+ 'CoreHome_MonthSeptember_js' => 'መስከረም',
+ 'CoreHome_MonthOctober_js' => 'ጥቅምት',
+ 'CoreHome_MonthNovember_js' => 'ህዳር',
+ 'CoreHome_MonthDecember_js' => 'ታህሳስ',
+ 'CoreUpdater_UpdateTitle' => 'ፒዊክ &rsaquo; አልቅ',
+ 'CoreUpdater_DatabaseUpgradeRequired' => 'የውሂብ ጎታ ማላቅ ያስፈልጋል',
+ 'CoreUpdater_YourDatabaseIsOutOfDate' => 'የፒዊክ የውሂብ ጎታዎ ቀኑ ሰላለፈበት ከመቀጠልዎ በፊት ማላቅ ያስፈልገዋል',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'የፒዊክ የውሂብ ጎታዎ ከ %sስሪት ወደ %sስሪት ይልቃል.',
+ 'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'የሚከተሉት ተሰኪዎችም ይልቃሉ: %s.',
+ 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'የውሂብ ጎታ ማላቅ ሂደቱ ጥቂት ጊዜ ስለሚወስድ እባክዎ በትዕግስት ይጠብቁ',
+ 'CoreUpdater_UpgradePiwik' => 'ፒዊክን አልቅ',
+ 'CoreUpdater_HelpMessageContent' => 'የ %s ፒዊክን ኤፍ ኤ ኪው %s ይመልከቱ ምከነያቱም ባማላቀ ወቅት በጣም ተደጋጋሚ ለሆኑ ስህተቶች መልስ የሰጣልና %s የስርዓት አስተዳዳሪዎን ይጠይቁ - ከአገልጋይ ወይም ማይ ኤስ ኪው ኤል መዋቅር ጋር ተዛማጅነት ላላቸው ስህተቶች ርዳታ ሊያገኙ ይችላሉ',
+ 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'በማላቅ ሂደት ላይ ያጋጠመ ከባድ እንከን:',
+ 'CoreUpdater_HelpMessageIntroductionWhenError' => 'ከላይ ያለው የስህተት ኮር መልእክት ነው። ምክንያቱን ለማስረዳት አጋዥ ሊሆን ይችላል ነገር ግን ተጨማሪ ርዳታ ከፈለጉ እባክዎ:',
+ 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'ማላቁ በሚጋባ ተጠናቅቋል ቢሆንም በሂደቱ ላይ ችግሮች ነበሩ። ዝርዝር ከፈለጉ ከላይ የተቀመጡትን መግለጫዎች ያንቡ። ለተጨማሪ ርዳታ፡',
+ 'CoreUpdater_UpgradeComplete' => 'ማላቅ ተጠናቋል!',
+ 'CoreUpdater_WarningMessages' => 'የማስጠንቀቂያ መልዕክቶች:',
+ 'CoreUpdater_ErrorDuringPluginsUpdates' => 'ተሰኪዎችን በማላቅ ሂደት ያጋጠሙ ስህተቶች:',
+ 'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'የሚከተሉትን ተሰኪዎች በራስሰር አቦዝነናል: %s',
+ 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'ፒዊክን ማላቅ በተሳካ ሁኔታ ተጠናቋል!',
+ 'CoreUpdater_ContinueToPiwik' => 'ወደ ፒዊክ ቀጥል',
+ 'CoreUpdater_UpdateAutomatically' => 'ራስሰር አልቅ',
+ 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'ለማላቅ ዝግጁ የሆነ የፒዊክ ሰሪት አለ',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'ወደ ስሪት %s ራስሰር ማላቅ ወይም አካታቾቹን አውርዶ በጅ መጫን ይቻላል ይቻላል:',
+ 'CoreUpdater_DownloadX' => 'አውርድ %s',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'ፒዊክ አንድ ጠቅ አርግ ማላቅ ተሰርዟል። ከላይ ያለውን የስህተት መልዕክት መጠገን ካልቻልክ ፒዊክን በእጅ እንድታልቅትመከራለህ። %s ለመጀመር የ %sማላቂያ ስነዳ %sተመልከት!',
+ 'CoreUpdate_DownloadingUpdateFromX' => 'ማላቂያ ከ %sበማውረድ ላይ',
+ 'CoreUpdate_UnpackingTheUpdate' => 'አልቁን በመበተን ላይ',
+ 'CoreUpdater_VerifyingUnpackedFiles' => 'የተበተኑትን ፋይሎች በመበተን ላይ',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'የውቅረት ፋይሉን መጠባበቂያ በመፍጠር ላይ %s',
+ 'CoreUpdater_InstallingTheLatestVersion' => 'አዲሱን ስሪት በመጫን ላይ',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'የፒዊክ ማላቅ ተሳክቷል!',
+ 'Actions_Actions' => 'ርምጃዎች',
+ 'Actions_SubmenuPages' => 'ገፆች',
+ 'Actions_SubmenuOutlinks' => 'ወጪአገናኞች',
+ 'Actions_SubmenuDownloads' => 'የወረዱ',
+ 'Actions_ColumnClicks' => 'ጠቃድርጎች',
+ 'Actions_ColumnUniqueClicks' => 'ብቸኛ ጠቅአድርጎች',
+ 'Actions_ColumnDownloads' => 'የወረዱ',
+ 'Actions_ColumnUniqueDownloads' => 'ብቸኛ የወረዱ',
+ 'Actions_ColumnPageName' => 'የገፅ ስም',
+ 'Actions_ColumnClickedURL' => 'ጠቅ አድርግ ዩ አር ኤል ',
+ 'Actions_ColumnDownloadURL' => 'የማውረጃ ዩ አር ኤል',
+ 'Dashboard_Dashboard' => 'ዳሽቦርድ',
+ 'Dashboard_AddWidget' => 'widget ጨምር...',
+ 'Dashboard_DeleteWidgetConfirm' => 'እርግጠኛ ነህ ይህ widget ከዳሽቦርድ ይሰረዝ?',
+ 'Dashboard_SelectWidget' => 'ወደ ዳሽቦርድ የሚጨመረውን widget ምረጥ',
+ 'Dashboard_AddPreviewedWidget_js' => 'ቅድመ እይታ የተሰጠውን widget ወደ ዳሽቦርዱ ጨምር',
+ 'Dashboard_WidgetPreview_js' => 'የWidget ቅድመእይታ',
+ 'Dashboard_Close_js' => 'ዝጋ',
+ 'Dashboard_TitleWidgetInDashboard_js' => 'Widget ወደዳሽቦርዱ አስቀድሞ ገብቷል ',
+ 'Dashboard_TitleClickToAdd_js' => 'ወደ ዳሽቦርዱ ለመጨመር ጠቅ አድርግ',
+ 'Dashboard_LoadingWidget_js' => 'widget በመጫን ላይ, እባክዎ ይጠበቁ...',
+ 'Dashboard_WidgetNotFound_js' => 'Widget አልተገኘም',
+ 'Referers_Referers' => 'አመላካቾች',
+ 'Referers_SearchEngines' => 'የመፈለጊያ ሞተሮች',
+ 'Referers_Keywords' => 'ቁልፍ ቃላት',
+ 'Referers_DirectEntry' => 'ቀጥተኛ ምዝግብ',
+ 'Referers_Websites' => 'ድር ጣቢያዎች',
+ 'Referers_Campaigns' => 'Campaigns',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%1s (ከ %2s)',
+ 'Referers_Evolution' => 'Evolution በክፍለ ጊዜው',
+ 'Referers_Type' => 'የምልከታ ዓይነት',
+ 'Referers_ColumnRefererType' => 'የአመላካች ዓይነት',
+ 'Referers_ColumnSearchEngine' => 'የመፈለጊያ ሞተሮች',
+ 'Referers_ColumnWebsite' => 'ድር ጣቢያዎች',
+ 'Referers_ColumnWebsitePage' => 'የድር ጣቢያዎች ገፅ',
+ 'Referers_ColumnKeyword' => 'ቁልፍ ቃላት',
+ 'Referers_ColumnCampaign' => 'Campaign',
+ 'Referers_DetailsByRefererType' => 'ዝርዝር በአመላካች ዓይነት ',
+ 'Referers_TypeDirectEntries' => '%s ቀጥተኛ ምዝግቦች',
+ 'Referers_TypeSearchEngines' => '%s ከመፈለጊያ ሞተሮች',
+ 'Referers_TypeWebsites' => '%s ከድር ጣቢያዎች',
+ 'Referers_TypeCampaigns' => '%s ከ campaigns',
+ 'Referers_Distinct' => 'የተለዩ ምልከታዎች በአመላካች ዓይነት',
+ 'Referers_DistinctSearchEngines' => 'የተለዩ የመፈለጊያ ሞተሮች',
+ 'Referers_DistinctKeywords' => 'የተለዩ ቁልፍ ቃላት',
+ 'Referers_DistinctCampaigns' => 'የተለዩ campaigns',
+ 'Referers_DistinctWebsites' => 'የተለዩ ድር ጣቢያዎች',
+ 'Referers_UsingNDistinctUrls' => ' (using የተለዩ ዩ አር ኤሎችን %2s በመጠቀም ላይ)',
+ 'Referers_SubmenuEvolution' => 'Evolution',
+ 'Referers_SubmenuSearchEngines' => 'የመፈለጊያ ሞተሮች እና ቁልፍ ቃላት',
+ 'Referers_SubmenuWebsites' => 'ድር ጣቢያዎች',
+ 'Referers_SubmenuCampaigns' => 'Campaigns',
+ 'Referers_WidgetKeywords' => 'የቁልፍ ቃላት ዝርዝር',
+ 'Referers_WidgetCampaigns' => 'የCampaigns ዝርዝር',
+ 'Referers_WidgetExternalWebsites' => 'የውጫዊ ድር ጣቢያዎች ዝርዝር',
+ 'Referers_WidgetSearchEngines' => 'ምርጥ የመፈለጊያ ሞተር',
+ 'Referers_WidgetOverview' => 'አጠቃላይ እይታ',
+ 'UserSettings_VisitorSettings' => 'የጎበኚዎች ቅንብሮች',
+ 'UserSettings_BrowserFamilies' => 'የማሰሺያ ቤተሰቦች',
+ 'UserSettings_Browsers' => 'ማሰሻዎች',
+ 'UserSettings_Plugins' => 'ተሰኪዎች',
+ 'UserSettings_Configurations' => 'ውቅረቶች',
+ 'UserSettings_OperatinsSystems' => 'ስርዓተ ክወናዎች',
+ 'UserSettings_Resolutions' => 'ጥራቶች',
+ 'UserSettings_WideScreen' => 'ሰፊ ማያ',
+ 'UserSettings_ColumnBrowserFamily' => 'የማሰሻ ቤተሰብ',
+ 'UserSettings_ColumnBrowser' => 'ማሰሺያ',
+ 'UserSettings_ColumnPlugin' => 'ተሰኪ',
+ 'UserSettings_ColumnConfiguration' => 'ውቅረት',
+ 'UserSettings_ColumnOperatinsSystem' => 'ስርዓተ ክወና',
+ 'UserSettings_ColumnResolution' => 'ጥራት',
+ 'UserSettings_ColumnTypeOfScreen' => 'የማያ ዓይነት',
+ 'UserSettings_WidgetResolutions' => 'የማያ ጥራቶች',
+ 'UserSettings_WidgetBrowsers' => 'የጎብኚ ማሰሻዎች',
+ 'UserSettings_WidgetPlugins' => 'የተሰኪዎች ዝርዝር',
+ 'UserSettings_WidgetWidescreen' => 'የተለመደ / ሰፊ ማያ',
+ 'UserSettings_WidgetBrowserFamilies' => 'ማሰሺያ በቤተሰብ',
+ 'UserSettings_WidgetOperatingSystems' => 'ስርዓተ ክወናዎች',
+ 'UserSettings_WidgetGlobalVisitors' => 'የሁሉም ጎብኚዎች ውቅረት',
+ 'UserSettings_SubmenuSettings' => 'ቅንብሮች',
+ 'UserCountry_Country' => 'ሀገር',
+ 'UserCountry_Continent' => 'አህጉር',
+ 'UserCountry_DistinctCountries' => '%s የተለዩ ሀገራት',
+ 'UserCountry_SubmenuLocations' => 'አቀማመጦች',
+ 'UserCountry_WidgetContinents' => 'የጎብኚዎች አህጉራት',
+ 'UserCountry_WidgetCountries' => 'የጎብኚዎች ሀገራት',
+ 'UserCountry_country_ac' => 'Ascension Islands',
+ 'UserCountry_country_ad' => 'Andorra',
+ 'UserCountry_country_ae' => 'United Arab Emirates',
+ 'UserCountry_country_af' => 'Afghanistan',
+ 'UserCountry_country_ag' => 'Antigua and Barbuda',
+ 'UserCountry_country_ai' => 'Anguilla',
+ 'UserCountry_country_al' => 'Albania',
+ 'UserCountry_country_am' => 'Armenia',
+ 'UserCountry_country_an' => 'Netherlands Antilles',
+ 'UserCountry_country_ao' => 'Angola',
+ 'UserCountry_country_aq' => 'Antarctica',
+ 'UserCountry_country_ar' => 'Argentina',
+ 'UserCountry_country_as' => 'American Samoa',
+ 'UserCountry_country_at' => 'Austria',
+ 'UserCountry_country_au' => 'Australia',
+ 'UserCountry_country_aw' => 'Aruba',
+ 'UserCountry_country_ax' => 'Aland Islands',
+ 'UserCountry_country_az' => 'Azerbaijan',
+ 'UserCountry_country_ba' => 'Bosnia and Herzegovina',
+ 'UserCountry_country_bb' => 'Barbados',
+ 'UserCountry_country_bd' => 'Bangladesh',
+ 'UserCountry_country_be' => 'Belgium',
+ 'UserCountry_country_bf' => 'Burkina Faso',
+ 'UserCountry_country_bg' => 'Bulgaria',
+ 'UserCountry_country_bh' => 'Bahrain',
+ 'UserCountry_country_bi' => 'Burundi',
+ 'UserCountry_country_bj' => 'Benin',
+ 'UserCountry_country_bl' => 'Saint Barthelemy',
+ 'UserCountry_country_bm' => 'Bermuda',
+ 'UserCountry_country_bn' => 'Bruneo',
+ 'UserCountry_country_bo' => 'Bolivia',
+ 'UserCountry_country_br' => 'Brazil',
+ 'UserCountry_country_bs' => 'Bahamas',
+ 'UserCountry_country_bt' => 'Bhutan',
+ 'UserCountry_country_bu' => 'Burma',
+ 'UserCountry_country_bv' => 'Bouvet Island',
+ 'UserCountry_country_bw' => 'Botswana',
+ 'UserCountry_country_by' => 'Belarus',
+ 'UserCountry_country_bz' => 'Belize',
+ 'UserCountry_country_ca' => 'Canada',
+ 'UserCountry_country_cc' => 'Cocos (Keeling) Islands',
+ 'UserCountry_country_cd' => 'Congo, The Democratic Republic of the',
+ 'UserCountry_country_cf' => 'Central African Republic',
+ 'UserCountry_country_cg' => 'Congo',
+ 'UserCountry_country_ch' => 'Switzerland',
+ 'UserCountry_country_ci' => 'Cote D\'Ivoire',
+ 'UserCountry_country_ck' => 'Cook Islands',
+ 'UserCountry_country_cl' => 'Chile',
+ 'UserCountry_country_cm' => 'Cameroon',
+ 'UserCountry_country_cn' => 'China',
+ 'UserCountry_country_co' => 'Colombia',
+ 'UserCountry_country_cp' => 'Clipperton Island',
+ 'UserCountry_country_cr' => 'Costa Rica',
+ 'UserCountry_country_cs' => 'Serbia Montenegro',
+ 'UserCountry_country_cu' => 'Cuba',
+ 'UserCountry_country_cv' => 'Cape Verde',
+ 'UserCountry_country_cx' => 'Christmas Island',
+ 'UserCountry_country_cy' => 'Cyprus',
+ 'UserCountry_country_cz' => 'Czech Republic',
+ 'UserCountry_country_de' => 'Germany',
+ 'UserCountry_country_dg' => 'Diego Garcia',
+ 'UserCountry_country_dj' => 'Djibouti',
+ 'UserCountry_country_dk' => 'Denmark',
+ 'UserCountry_country_dm' => 'Dominica',
+ 'UserCountry_country_do' => 'Dominican Republic',
+ 'UserCountry_country_dz' => 'Algeria',
+ 'UserCountry_country_ea' => 'Ceuta, Melilla',
+ 'UserCountry_country_ec' => 'Ecuador',
+ 'UserCountry_country_ee' => 'Estonia',
+ 'UserCountry_country_eg' => 'Egypt',
+ 'UserCountry_country_eh' => 'Western Sahara',
+ 'UserCountry_country_er' => 'Eritrea',
+ 'UserCountry_country_es' => 'Spain',
+ 'UserCountry_country_et' => 'Ethiopia',
+ 'UserCountry_country_eu' => 'European Union',
+ 'UserCountry_country_fi' => 'Finland',
+ 'UserCountry_country_fj' => 'Fiji',
+ 'UserCountry_country_fk' => 'Falkland Islands (Malvinas)',
+ 'UserCountry_country_fm' => 'Micronesia, Federated States of',
+ 'UserCountry_country_fo' => 'Faroe Islands',
+ 'UserCountry_country_fr' => 'France',
+ 'UserCountry_country_fx' => 'France, Metropolitan',
+ 'UserCountry_country_ga' => 'Gabon',
+ 'UserCountry_country_gb' => 'Great Britain',
+ 'UserCountry_country_gd' => 'Grenada',
+ 'UserCountry_country_ge' => 'Georgia',
+ 'UserCountry_country_gf' => 'French Guyana',
+ 'UserCountry_country_gg' => 'Guernsey',
+ 'UserCountry_country_gh' => 'Ghana',
+ 'UserCountry_country_gi' => 'Gibraltar',
+ 'UserCountry_country_gl' => 'Greenland',
+ 'UserCountry_country_gm' => 'Gambia',
+ 'UserCountry_country_gn' => 'Guinea',
+ 'UserCountry_country_gp' => 'Guadeloupe',
+ 'UserCountry_country_gq' => 'Equatorial Guinea',
+ 'UserCountry_country_gr' => 'Greece',
+ 'UserCountry_country_gs' => 'South Georgia and the South Sandwich Islands',
+ 'UserCountry_country_gt' => 'Guatemala',
+ 'UserCountry_country_gu' => 'Guam',
+ 'UserCountry_country_gw' => 'Guinea-Bissau',
+ 'UserCountry_country_gy' => 'Guyana',
+ 'UserCountry_country_hk' => 'Hong Kong',
+ 'UserCountry_country_hm' => 'Heard Island and McDonald Islands',
+ 'UserCountry_country_hn' => 'Honduras',
+ 'UserCountry_country_hr' => 'Croatia',
+ 'UserCountry_country_ht' => 'Haiti',
+ 'UserCountry_country_hu' => 'Hungary',
+ 'UserCountry_country_ic' => 'Canary Islands',
+ 'UserCountry_country_id' => 'Indonesia',
+ 'UserCountry_country_ie' => 'Ireland',
+ 'UserCountry_country_il' => 'Israel',
+ 'UserCountry_country_im' => 'Man Island',
+ 'UserCountry_country_in' => 'India',
+ 'UserCountry_country_io' => 'British Indian Ocean Territory',
+ 'UserCountry_country_iq' => 'Iraq',
+ 'UserCountry_country_ir' => 'Iran, Islamic Republic of',
+ 'UserCountry_country_is' => 'Iceland',
+ 'UserCountry_country_it' => 'Italy',
+ 'UserCountry_country_je' => 'Jersey',
+ 'UserCountry_country_jm' => 'Jamaica',
+ 'UserCountry_country_jo' => 'Jordan',
+ 'UserCountry_country_jp' => 'Japan',
+ 'UserCountry_country_ke' => 'Kenya',
+ 'UserCountry_country_kg' => 'Kyrgyzstan',
+ 'UserCountry_country_kh' => 'Cambodia',
+ 'UserCountry_country_ki' => 'Kiribati',
+ 'UserCountry_country_km' => 'Comoros',
+ 'UserCountry_country_kn' => 'Saint Kitts and Nevis',
+ 'UserCountry_country_kp' => 'Korea, Democratic People\'s Republic of',
+ 'UserCountry_country_kr' => 'Korea, Republic of',
+ 'UserCountry_country_kw' => 'Kuwait',
+ 'UserCountry_country_ky' => 'Cayman Islands',
+ 'UserCountry_country_kz' => 'Kazakhstan',
+ 'UserCountry_country_la' => 'Laos',
+ 'UserCountry_country_lb' => 'Lebanon',
+ 'UserCountry_country_lc' => 'Saint Lucia',
+ 'UserCountry_country_li' => 'Liechtenstein',
+ 'UserCountry_country_lk' => 'Sri Lanka',
+ 'UserCountry_country_lr' => 'Liberia',
+ 'UserCountry_country_ls' => 'Lesotho',
+ 'UserCountry_country_lt' => 'Lithuania',
+ 'UserCountry_country_lu' => 'Luxembourg',
+ 'UserCountry_country_lv' => 'Latvia',
+ 'UserCountry_country_ly' => 'Libya',
+ 'UserCountry_country_ma' => 'Morocco',
+ 'UserCountry_country_mc' => 'Monaco',
+ 'UserCountry_country_md' => 'Moldova, Republic of',
+ 'UserCountry_country_me' => 'Montenegro',
+ 'UserCountry_country_mf' => 'Saint Martin',
+ 'UserCountry_country_mg' => 'Madagascar',
+ 'UserCountry_country_mh' => 'Marshall Islands',
+ 'UserCountry_country_mk' => 'Macedonia',
+ 'UserCountry_country_ml' => 'Mali',
+ 'UserCountry_country_mm' => 'Myanmar',
+ 'UserCountry_country_mn' => 'Mongolia',
+ 'UserCountry_country_mo' => 'Macau',
+ 'UserCountry_country_mp' => 'Northern Mariana Islands',
+ 'UserCountry_country_mq' => 'Martinique',
+ 'UserCountry_country_mr' => 'Mauritania',
+ 'UserCountry_country_ms' => 'Montserrat',
+ 'UserCountry_country_mt' => 'Malta',
+ 'UserCountry_country_mu' => 'Mauritius',
+ 'UserCountry_country_mv' => 'Maldives',
+ 'UserCountry_country_mw' => 'Malawi',
+ 'UserCountry_country_mx' => 'Mexico',
+ 'UserCountry_country_my' => 'Malaysia',
+ 'UserCountry_country_mz' => 'Mozambique',
+ 'UserCountry_country_na' => 'Namibia',
+ 'UserCountry_country_nc' => 'New Caledonia',
+ 'UserCountry_country_ne' => 'Niger',
+ 'UserCountry_country_nf' => 'Norfolk Island',
+ 'UserCountry_country_ng' => 'Nigeria',
+ 'UserCountry_country_ni' => 'Nicaragua',
+ 'UserCountry_country_nl' => 'Netherlands',
+ 'UserCountry_country_no' => 'Norway',
+ 'UserCountry_country_np' => 'Nepal',
+ 'UserCountry_country_nr' => 'Nauru',
+ 'UserCountry_country_nt' => 'Neutral Zone',
+ 'UserCountry_country_nu' => 'Niue',
+ 'UserCountry_country_nz' => 'New Zealand',
+ 'UserCountry_country_om' => 'Oman',
+ 'UserCountry_country_pa' => 'Panama',
+ 'UserCountry_country_pe' => 'Peru',
+ 'UserCountry_country_pf' => 'French Polynesia',
+ 'UserCountry_country_pg' => 'Papua New Guinea',
+ 'UserCountry_country_ph' => 'Philippines',
+ 'UserCountry_country_pk' => 'Pakistan',
+ 'UserCountry_country_pl' => 'Poland',
+ 'UserCountry_country_pm' => 'Saint Pierre and Miquelon',
+ 'UserCountry_country_pn' => 'Pitcairn',
+ 'UserCountry_country_pr' => 'Puerto Rico',
+ 'UserCountry_country_ps' => 'Palestinian Territory',
+ 'UserCountry_country_pt' => 'Portugal',
+ 'UserCountry_country_pw' => 'Palau',
+ 'UserCountry_country_py' => 'Paraguay',
+ 'UserCountry_country_qa' => 'Qatar',
+ 'UserCountry_country_re' => 'Reunion Island',
+ 'UserCountry_country_ro' => 'Romania',
+ 'UserCountry_country_ru' => 'Russia',
+ 'UserCountry_country_rs' => 'Serbia',
+ 'UserCountry_country_rw' => 'Rwanda',
+ 'UserCountry_country_sa' => 'Saudi Arabia',
+ 'UserCountry_country_sb' => 'Solomon Islands',
+ 'UserCountry_country_sc' => 'Seychelles',
+ 'UserCountry_country_sd' => 'Sudan',
+ 'UserCountry_country_se' => 'Sweden',
+ 'UserCountry_country_sf' => 'Finland',
+ 'UserCountry_country_sg' => 'Singapore',
+ 'UserCountry_country_sh' => 'Saint Helena',
+ 'UserCountry_country_si' => 'Slovenia',
+ 'UserCountry_country_sj' => 'Svalbard',
+ 'UserCountry_country_sk' => 'Slovakia',
+ 'UserCountry_country_sl' => 'Sierra Leone',
+ 'UserCountry_country_sm' => 'San Marino',
+ 'UserCountry_country_sn' => 'Senegal',
+ 'UserCountry_country_so' => 'Somalia',
+ 'UserCountry_country_sr' => 'Suriname',
+ 'UserCountry_country_st' => 'Sao Tome and Principe',
+ 'UserCountry_country_su' => 'Old U.S.S.R',
+ 'UserCountry_country_sv' => 'El Salvador',
+ 'UserCountry_country_sy' => 'Syrian Arab Republic',
+ 'UserCountry_country_sz' => 'Swaziland',
+ 'UserCountry_country_ta' => 'Tristan da Cunha',
+ 'UserCountry_country_tc' => 'Turks and Caicos Islands',
+ 'UserCountry_country_td' => 'Chad',
+ 'UserCountry_country_tf' => 'French Southern Territories',
+ 'UserCountry_country_tg' => 'Togo',
+ 'UserCountry_country_th' => 'Thailand',
+ 'UserCountry_country_tj' => 'Tajikistan',
+ 'UserCountry_country_tk' => 'Tokelau',
+ 'UserCountry_country_tl' => 'East Timor',
+ 'UserCountry_country_tm' => 'Turkmenistan',
+ 'UserCountry_country_tn' => 'Tunisia',
+ 'UserCountry_country_to' => 'Tonga',
+ 'UserCountry_country_tp' => 'East Timor',
+ 'UserCountry_country_tr' => 'Turkey',
+ 'UserCountry_country_tt' => 'Trinidad and Tobago',
+ 'UserCountry_country_tv' => 'Tuvalu',
+ 'UserCountry_country_tw' => 'Taiwan',
+ 'UserCountry_country_tz' => 'Tanzania, United Republic of',
+ 'UserCountry_country_ua' => 'Ukraine',
+ 'UserCountry_country_ug' => 'Uganda',
+ 'UserCountry_country_uk' => 'United Kingdom',
+ 'UserCountry_country_um' => 'United States Minor Outlying Islands',
+ 'UserCountry_country_us' => 'United States',
+ 'UserCountry_country_uy' => 'Uruguay',
+ 'UserCountry_country_uz' => 'Uzbekistan',
+ 'UserCountry_country_va' => 'Vatican City',
+ 'UserCountry_country_vc' => 'Saint Vincent and the Grenadines',
+ 'UserCountry_country_ve' => 'Venezuela',
+ 'UserCountry_country_vg' => 'Virgin Islands, British',
+ 'UserCountry_country_vi' => 'Virgin Islands, U.S.',
+ 'UserCountry_country_vn' => 'Vietnam',
+ 'UserCountry_country_vu' => 'Vanuatu',
+ 'UserCountry_country_wf' => 'Wallis and Futuna',
+ 'UserCountry_country_ws' => 'Samoa',
+ 'UserCountry_country_ye' => 'Yemen',
+ 'UserCountry_country_yt' => 'Mayotte',
+ 'UserCountry_country_yu' => 'Yugoslavia',
+ 'UserCountry_country_za' => 'South Africa',
+ 'UserCountry_country_zm' => 'Zambia',
+ 'UserCountry_country_zr' => 'Zaire',
+ 'UserCountry_country_zw' => 'Zimbabwe',
+ 'UserCountry_continent_eur' => 'Europe',
+ 'UserCountry_continent_afr' => 'Africa',
+ 'UserCountry_continent_asi' => 'Asia',
+ 'UserCountry_continent_ams' => 'South and Central America',
+ 'UserCountry_continent_amn' => 'North America',
+ 'UserCountry_continent_oce' => 'Oceania',
+ 'VisitsSummary_NbVisits' => '%s ጉበኝቶች',
+ 'VisitsSummary_NbUniqueVisitors' => '%s የተለዩ ጎብኚዎች',
+ 'VisitsSummary_NbActions' => '%s ርምጃዎች (የገፅ ትይታዎች)',
+ 'VisitsSummary_TotalTime' => '%s በጎብኚዎች የተፈጀ አጠቃላይ ሰዓት',
+ 'VisitsSummary_MaxNbActions' => '%s በአንድ ጉብኝት የተወሰዱ ከፍተኛ ርምጃዎች',
+ 'VisitsSummary_NbVisitsBounced' => '%s የተመለሱ ጉብኝቶች (ከአንድ ገፅ በኋላ ገፁን የተዉ)',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Evolution በመጨረሻው ላይ %s',
+ 'VisitsSummary_Report' => 'ሪፖርት',
+ 'VisitsSummary_GenerateTime' => '%s ሰከንዶች ገፁን ለማመንጨት',
+ 'VisitsSummary_GenerateQueries' => '%s ጥያቄዎች ተሰርተዋል',
+ 'VisitsSummary_WidgetLastVisits' => 'የመጨረሻው ጉብኝቶች ግራፍ',
+ 'VisitsSummary_WidgetVisits' => 'የጉብኝቶች አጠቃላይ እይታ',
+ 'VisitsSummary_WidgetLastVisitors' => 'የመጨረሻው የተለዩ ጎብኚዎች ግራፍ',
+ 'VisitsSummary_WidgetOverviewGraph' => 'አጠቃላይ እይታ ከግራፍ ጋር',
+ 'VisitsSummary_SubmenuOverview' => 'አጠቃላይ እይታ ከግራፍ ጋር',
+ 'VisitFrequency_Evolution' => 'Evolution በፔሬዱ ላይ',
+ 'VisitFrequency_ColumnReturningVisits' => 'መልስ ጉበኝቶች',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'በመልስ ጉብኝቶች የተወሰዱ ርምጃዎች',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'በመልስ ጉብኝቶች የተወሰዱ ከፍተኛ ርምጃዎች',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'በመልስ ጉብኝቶች የተፈጁ ከፍተኛ ሰዓታት (በሰከንዶች)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'የመልስ ጉብኝቶች ተመላሽ ፍጥነት',
+ 'VisitFrequency_ReturnVisits' => '%s መልስ ጉብኝቶች',
+ 'VisitFrequency_ReturnActions' => '%s በመልስ ጉብኝቶች የተወሰዱ ርምጃዎች',
+ 'VisitFrequency_ReturnMaxActions' => '%s በመልስ ጉብኝቶች የተወሰዱ ከፍተኛ ርምጃዎች',
+ 'VisitFrequency_ReturnTotalTime' => '%s በመልስ ጉብኝቶች የተፈጁ ከፍተኛ ሰዓታት',
+ 'VisitFrequency_ReturnBounceRate' => '%s መልስ ጉብኝቶች ተመላሽ ሆነዋል (ከአንድ ድር ጣቢያ በኋላ ገፁን ትተዋል)',
+ 'VisitFrequency_WidgetOverview' => 'የድግግሞሽ አጠቃላይ እይታ',
+ 'VisitFrequency_WidgetGraphReturning' => 'የመልስ ጉብኝቶች ግራፍ',
+ 'VisitFrequency_SubmenuFrequency' => 'ድግግሞሽ',
+ 'VisitTime_LocalTime' => 'ጉብኝቶች ከአካባቢያዊ ሰዓት',
+ 'VisitTime_ServerTime' => 'ጉብኝቶች ከአገልጋይ ሰዓት',
+ 'VisitTime_ColumnServerTime' => 'የአገልጋይ ሰዓት',
+ 'VisitTime_ColumnLocalTime' => 'አካባቢያዊ ሰዓት',
+ 'VisitTime_WidgetLocalTime' => 'ጉብኝቶች በአካባቢያዊ ሰዓት',
+ 'VisitTime_WidgetServerTime' => 'ጉብኝቶች በአገልጋይ ሰዓት',
+ 'VisitTime_SubmenuTimes' => 'ሰዓታት',
+ 'VisitTime_NHour' => '%sh',
+ 'VisitorInterest_VisitsPerDuration' => 'ጉብኝት ከጉብኝት ቆይታ ጋር',
+ 'VisitorInterest_VisitsPerNbOfPages' => 'ጉብኝት ከገፅ ቁጥር ጋር',
+ 'VisitorInterest_ColumnVisitDuration' => 'የጉብኝት ቆይታዎች',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'ጉብኝት ከገፆች ጋር',
+ 'VisitorInterest_WidgetLengths' => 'የጉብኝት ርዝመት',
+ 'VisitorInterest_WidgetPages' => 'ጉብኝት ከገፆች ጋር',
+ 'VisitorInterest_SubmenuFrequencyLoyalty' => 'ድግግሞሽ እና ታማኝነት',
+ 'VisitorInterest_PlusXMin' => '%s ደቂቃ',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%2s ደቂቃ',
+ 'VisitorInterest_OnePage' => '1 ገፅ',
+ 'VisitorInterest_NPages' => '%s ገፆች',
+ 'VisitorInterest_BetweenXYSeconds' => '%1s-%2sሰከንዶች',
+ 'Login_LoginPasswordNotCorrect' => 'የተጠቃሚ ስም እና የይለፍ ቃል ትክክል አይደለም',
+ 'Login_Login' => 'የተጠቃሚ ስም',
+ 'Login_Password' => 'የይለፍ ቃል',
+ 'Login_LoginOrEmail' => 'ግባ ወይም ኢ-ሜይል',
+ 'Login_LogIn' => 'ግባ',
+ 'Login_Logout' => 'ውጣ',
+ 'Login_LostYourPassword' => 'የይለፍ ቃል ጠፋብህ?',
+ 'Login_RemindPassword' => 'የይለፍ ቃል አስታውስ',
+ 'Login_PasswordReminder' => 'እባክህ የተጠቃሚ ስም ወይም የኢ-ሜይል አድራሻ አስገባ. አዲስ የይለፍ ቃል በኢ-ሜይል ይላካል።',
+ 'Login_InvalidUsernameEmail' => 'የተሳሳት የተጠቃሚ ስም እና/ወይም ኢ-ሜይል አድራሻ',
+ 'Login_MailTopicPasswordRecovery' => 'የይለፍ ቃል ማግኛ',
+ 'Login_MailPasswordRecoveryBody' => 'ሃይ %1s, \n\n አዲሱ የይለፍ ቃልዎ: %2s \n\n አሁን በዚህ ለመግባት ይችላሉ: %3s',
+ 'Login_PasswordSent' => 'የይለፍ ቃል አሁን ተልኳል። ኢ-ሜይልዎን አሁን ይመልከቱ',
+ 'Login_ContactAdmin' => 'ተገቢው ምክንያት: አስተናጋጅዎ የ ሜይል() ተግባርን አቦዝኖት ሊሆን ይችላል። <br />እባክዎ የፒዊክ መናጅዎን ያነጋግሩ',
+ 'UsersManager_UsersManagement' => 'የተጠቃሚዎች ምነጃ',
+ 'UsersManager_UsersManagementMainDescription' => 'አዳዲስ ተጤቃሚዎችን ይፍጠሩ ወይም ያሉትን ያልቁ።ፈቃዳቸውን ከላይ ማዘጋጀት ይቻላል.',
+ 'UsersManager_ManageAccess' => 'መድረሻ መንጅ',
+ 'UsersManager_MainDescription' => 'የትኞቹ ተጠቃሚዎች የትኛው በድር ጣቢያህ ላይ የፒዊክ መድረሻ እንዳላቸው ወስን። በሁሉም ድር ጣቢያዎች ላይ ፈቃዳቸውን በአንድ ጊዜ ማዘጋጀት ይቻላል።',
+ 'UsersManager_Sites' => 'ድር ጣቢያዎች',
+ 'UsersManager_AllWebsites' => 'ሁሉንም ድር ጣቢያዎች',
+ 'UsersManager_ApplyToAllWebsites' => 'በሁሉም ድር ጣቢያዎች ላይ ተግብር',
+ 'UsersManager_User' => 'ተጠቃሚ',
+ 'UsersManager_PrivNone' => 'መድረሻ የለም',
+ 'UsersManager_PrivView' => 'ትእይታ',
+ 'UsersManager_PrivAdmin' => 'አስተዳዳሪ',
+ 'UsersManager_ChangeAllConfirm' => 'እርግጠኛ ነህ \'%s\' የሁሉንም ድር ጣቢያዎች ፈቃድ መቀየር ትፈልጋለህ?',
+ 'UsersManager_Login' => 'ግባ',
+ 'UsersManager_Password' => 'የይለፍ ቃል',
+ 'UsersManager_Email' => 'ኢ-ሜይል',
+ 'UsersManager_Alias' => 'ተለዋጭ ስም',
+ 'UsersManager_Edit' => 'አርትእ',
+ 'UsersManager_AddUser' => 'አዲስ ተጤቃሚ ጨምር',
+ 'UsersManager_MenuUsers' => 'ተጠቃሚዎች',
+ 'UsersManager_DeleteConfirm_js' => 'እርግጠኛ ነህ ተጠቃሚዎቹን መሰረዝ ትፈልጋለህ %s?',
+ 'UsersManager_ExceptionLoginExists' => 'ግባ \'%s\' አስቀድሞ ማለት.',
+ 'UsersManager_ExceptionEmailExists' => 'በዚህ ኢ-ሜይል ተጠቃሚ \'%s\'አለ.',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'ገባ በ %s እና %s በ ቁምፊ መካከል መሆን አለበት እንዲሁም ፊደላት፣ቁጥሮች ወይም ቁምፊ ብቻ መያዝ አለበት \'_\' ወይም \'-\' ወይም \'.\'',
+ 'UsersManager_ExceptionInvalidPassword' => 'የይለፍ ቃሉ ርዝመት በ6 እና በ26 ቁምፊ መካከል መሆን አለበት.',
+ 'UsersManager_ExceptionInvalidEmail' => 'ኢ-ሜይሉ ትክክለኛ ቅርፀት የለውም',
+ 'UsersManager_ExceptionDeleteDoesNotExist' => 'ተጠቃሚው \'%s\' የለም ስለዚህ ሊሰረዝ አይችልም',
+ 'UsersManager_ExceptionAdminAnonymous' => 'የአስተዳዳሪን ፈቃድ ላልታወቀ ሰው መስጠት አይቻልም',
+ 'UsersManager_ExceptionEditAnonymous' => 'ያልታወቀው ተጠቃሚን መሰረዝ ወይም አርትእ አይቻልም። በፒዊክ ያልገባን ተጤቃሚ ለመግለፅ ይጠቅማል። ለምሳሌ የርስዎን ስታቲስቲክ \'የትይታ\' ፈቃድ \'ላልታወቀ\' ተጠቃሚ በመስጠት ግልፅ ማድረግ ትችላለህ።',
+ 'UsersManager_ExceptionSuperUser' => 'የተጠየቀው ተጠቃሚ ሊቀ ተጠቃሚ ስለሆነ በኤፒአይ ሊጠየቅ፣ አርትእ ወይም ሊሰረዝ አይችልም። ሊቀ ተጠቃሚውን ዝርዝር በፒዊክ ውቅረት ፋይል በእጅ አርትእ ይቻላል።',
+ 'UsersManager_ExceptionUserDoesNotExist' => 'ተጠቃሚው የለም',
+ 'UsersManager_ExceptionAccessValues' => 'የግቤት መድረሻ ከሚከተሉት አንዱ እሴት ሊኖረው ይገባል: [ %s ]',
+ 'SitesManager_Sites' => 'ድር ጣቢያ',
+ 'SitesManager_WebsitesManagement' => 'የድር ጣቢያ ምነጃ',
+ 'SitesManager_MainDescription' => 'የድር ማመዛዘኛ ሪፖርት ድር ጣቢያ ያስፈልጋቸዋል! ጨምር፣ አልቅ፣ ድር ጣቢያ ሰርዝ እና በገፅህ ላይ ለማስገባት የፈለግከውን የጃቫ ስክሪፕት አሳይ',
+ 'SitesManager_JsTrackingTag' => 'የጃቫ ስክሪፕት ዱካ መከተያ መለያ',
+ 'SitesManager_JsTrackingTagHelp' => 'በሁሉም ገፆች ለማካተት እንዲያስችልህ የጃቫ ስክሪፕት ዱካ መከተያ መለያ እዚህ አለ',
+ 'SitesManager_ShowTrackingTag' => 'የዱካ መከተያ መለያ አሳይ',
+ 'SitesManager_NoWebsites' => 'ለታስተዳድረው የምትችለው ምንም አይነት ድር ጣቢያ የለም',
+ 'SitesManager_AddSite' => 'አዲስ ድር ጣቢያ ጨምር',
+ 'SitesManager_Id' => 'መታወቂያ',
+ 'SitesManager_Name' => 'ስም',
+ 'SitesManager_Urls' => 'ዩ አር ኤሎች',
+ 'SitesManager_MenuSites' => 'ድር ጣቢያዎች',
+ 'SitesManager_DeleteConfirm_js' => 'እርግጠኛ ነህ ድር ጣቢያውን ለመሰረዝ %s?',
+ 'SitesManager_ExceptionDeleteSite' => 'የተመዘገበ ብቸኛው ድር ጣቢያ ስለሆነ ለመዘረዝ አይቻልም። በመጀመሪያ አዲስ ድር ጣቢያ ጨምርና ቀጠሎ ይህንን ሰርዝ።',
+ 'SitesManager_ExceptionNoUrl' => 'ለዚህ ድር ጣቢያ ቢያንስ አንድ ዩ አር ኤል ማምር አለብህ።',
+ 'SitesManager_ExceptionEmptyName' => 'የድር ጣቢያው ስም ባዶ መሆን አይችልም።',
+ 'SitesManager_ExceptionInvalidUrl' => 'ዩ አር ኤሉ ትክክለኛ ዩ አር ኤል አይደለም።',
+ 'Installation_Installation' => 'መጫኛ',
+ 'Installation_InstallationStatus' => 'የመጫኛ ሁኔታ',
+ 'Installation_PercentDone' => '%s %% አልቋል',
+'Installation_NoConfigFound' => 'የፒዊክ ውቅረት ፋይል ሊገኝ አልቻለም እና እርስዎ የፒዊክ ገፅ ለመድረስ እየሞከሩ ነው። <br /><b>&nbsp;&nbsp;&raquo; እርስዎ <a href=\'index.php\'>ፒዊክን አሁን መጫን ይችላሉ</a></b><br /><small>ፒዊክን ከዚህ ቀደም ጭነው ከነበረ እና በዲቢዎ ላይ የተወሰኑ ሰንጠረዦች ካለዎ የነበሩትን ሰንጠረዦች ደግመው መጠቀምና የነበረዎትን ውሂብ ማስቀመጥ ይችላሉ!</small>',
+ 'Installation_MysqlSetup' => 'ማይ ኤስ ኪው ኤል የውሂብ ጎታ መዋቅር',
+ 'Installation_MysqlErrorConnect' => 'ከማይ ኤስ ኪው ኤል የውሂብ ጎታ ጋር በመገናኘት ጊዜ የተፈጠረ ስህተት',
+ 'Installation_JsTag' => 'የጃቫ ስክሪፕት መለያ',
+ 'Installation_JsTagHelp' => '<p>ሁሉንም ጎብኚዎች ለመቁጠር የጃቫ ስክሪፕቱን ኮድ በሁሉም ገፆች ላይ ማስገባት አለብዎ።</p><p>ገፆችዎ የግድ በፒ ኤች ፒ መሰራት የለባቸውም ፒዊክ በሁሉም ገፆች ላይ ይሰራል (ኤች ቲ ኤም ኤል ፣ ኤ ኤስ ፒ፣ ፐርል ወይም ማንኛውም ቋንቋ ቢሆን)</p><p>በሁሉም ገፆችዎ ማስገባት ያለብዎ ኮድ የሚከተለው ነው: (በሁሉም ገፆች ላይ ኮፒ አድርገው ይለጥፉ) </p>',
+ 'Installation_Congratulations' => 'እንኳን ደስያለዎ',
+ 'Installation_CongratulationsHelp' => '<p>እንኳን ደስያለዎ! የፒዊክ መጫንዎ ተሳክቷል።</p><p>የጃቫ ስክሪፕትዎ ቾድ በሁሉ ገፆች ላይ መግባቱን ያረጋግጡና የመጀመሪያ ጎበኚዎችዎን ይጠብቁ!</p>',
+ 'Installation_ContinueToPiwik' => 'ወደ ፒዊክ ይቀጥሉ',
+ 'Installation_SetupWebsite' => 'ድር ጣቢያ ጫን',
+ 'Installation_SetupWebsiteError' => 'ድር ጣቢያውን በመጫን ጊዜ ስህተት አጋጥሟል',
+ 'Installation_GeneralSetup' => 'አጠቃላይ መዋቅር',
+ 'Installation_GeneralSetupSuccess' => 'አጠቃላይ መዋቅር በተሳካ ሁኔታ ተዋቅሯል',
+ 'Installation_SuperUserLogin' => 'ሊቀ ተገልጋይ ግባ',
+ 'Installation_Password' => 'የይለፍ ቃል',
+ 'Installation_PasswordRepeat' => 'የይለፍ ቃል (ድገም)',
+ 'Installation_Email' => 'ኢ-ሜይል',
+ 'Installation_SecurityNewsletter' => 'ከዋነኛ የፒዊክ ማላቂያዎች እና የጥበቃ ማስጠንቀቂያዎች ጋር ኢ-ሜይል አድርግልኝ',
+ 'Installation_CommunityNewsletter' => 'ከማህበረሰብ አልቅ ጋር ኢ-ሜይል አድርግልኝ(አዲስ ተሰኪዎች, አዲስ ባህርይዎች, ወዘተ.)',
+ 'Installation_PasswordDoNotMatch' => 'የይለፍ ቃሉ አቻ አይደለም %s',
+ 'Installation_SubmitGo' => 'ሂድ!',
+ 'Installation_SystemCheck' => 'ስርዓት አረጋግጥ',
+ 'Installation_SystemCheckPhp' => 'የፒ ኤች ፒ ስሪት',
+ 'Installation_SystemCheckPdo' => 'የፒ ዲ ኦ ቅጥያ',
+ 'Installation_SystemCheckPdoMysql' => 'ፒ ዲ ኦ_ማይ ኤስ ኪው ኤል ቅጥያ',
+ 'Installation_SystemCheckPdoError' => 'ፒ ዲ ኦ እና ፒ ዲ ኦ_ማይ ኤስ ኪው ኤል ቅጥያን በ php.ini ፋይል ውስጥ ማንቃት ያስፈልጋል።',
+ 'Installation_SystemCheckPdoHelp' => 'በዊንዶውስ አገልጋይ ላይ በ php.ini ፋይልዎ ውስጥ የሚከተሉትን መስመሮች ማካተት ይችላሉ %s <br /><br />በሊኑክስ አገልጋይ ላይ ፒ ኤች ፒን በሚከተለው ምርጫ ላይ የራስዎን ማቀናበር ይችላሉ %s በ php.ini ላይ የሚከተሉትን መስመሮች ይጨምሩ%s<br /><br />ተጨማሪ መረጃ<a style="color:red" href="http://php.net/pdo">ፒ ኤች ፒ ድር ጣቢያ </a>ላይ ያገኛሉ።',
+ 'Installation_SystemCheckWriteDirs' => 'ማውጫ ከፃፍ መድረሻ ጋር',
+ 'Installation_SystemCheckWriteDirsHelp' => 'ይህንን ስህተት በሊኑክስ ስርዓት ላይ ለማስተካከል የሚከተሉትን ትእዛዝ(ዞች) ይተይቡ',
+ 'Installation_SystemCheckMemoryLimit' => 'የማህደረ ትውስታ ገደብ',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'ከፍተኛ የጎብኚ መጨናነቅ ባለባችው ድር ጣቢያዎች ላይ የምዝገባ ሂድት በወቅቱ ከተፈቀደው ብላይ ብዙ ማህደረ ትውስታ ሊያስፈልገው ይችላል።<br />የማህደረ ትውስታውን ገደብ መመሪያ በ php.ini ፋይል ውስጥ አስፈላጊ ከሆነ መመልከት ትችላለህ።',
+ 'Installation_SystemCheckGD' => 'ጂዲ &gt; 2.x (ንድፋንድፍ)',
+ 'Installation_SystemCheckGDHelp' => 'የብልጭታ መስመሮቹ (ትናንሽ ግራፎች)አይሰሩም',
+ 'Installation_SystemCheckTimeLimit' => 'set_time_limit() ይቻላል',
+ 'Installation_SystemCheckTimeLimitHelp' => 'ከፍተኛ የትራፊክ መጨናነቅ ያለባቸው የድር ጣቢያዎች ላይ የምዝገባ ሂደቱን ማስፈፀም ከተፈቀደው ሰዓት በላይ ሊፈልግ ይችላል።<br />ከፍተኛ_የማስፈፀሚያ_ጊዜ መመሪያውን በ php.ini ፋይል ውስጥ አስፈላጊ ከሆነ መመልከት ትችላለህ።',
+ 'Installation_SystemCheckMail' => 'mail() ይቻላል',
+ 'Installation_SystemCheckError' => 'ስህተት ተከስቷል - ከመቀጠልዎ በፊት መጠገን አለበት',
+ 'Installation_SystemCheckWarning' => 'ፒዊክ በመደበኛነት ሊሰራ ይችላል ነገርግን አንዳንድ ባህርይዎች ጠፍተው ሊሆን ይችላል',
+ 'Installation_Tables' => 'ሠንጠረዦቹን በመፍጠር ላይ',
+ 'Installation_TablesWithSameNamesFound' => 'አንዳንድ %s በውሂብ ጎታ ውስጥ ያሉ ሰንጠረዦች%s ፒዊክ ለመፍጠር እየሞከረ ካሉት ሰንጠረዦች ጋር ተመሳሳይ ስም አላቸው',
+ 'Installation_TablesFound' => 'የሚከተሉት ሰንጠረዦች በውሂብ ጎታዎች ውስጥ ተገኝተዋል',
+ 'Installation_TablesWarningHelp' => 'ቀደም ሲል የነበሩትን የውሂብ ጎታዎች ስንጠረዥመልሰህ ለመጠቀም ምረጥ ወይም በውሂብ ጎታዎቹ ውስጥ ያሉትን ውሂቦች ለማጥፋት ንፁህ ጫን ምረጥ',
+ 'Installation_TablesReuse' => 'ቀደም ሲል የነበሩትን ሰንጠረዦች መልሰህ ተጠቀም',
+ 'Installation_TablesDelete' => 'የተገኙትን ሰንጠረዦች ሰርዝ',
+ 'Installation_TablesDeletedSuccess' => 'ቀደም ሲል የነበሩት የፒዊክ ሰንጠረዦች በሚገባ ተሰርዘዋል',
+ 'Installation_TablesCreatedSuccess' => 'ሰንጠረዦች በሚገባ ተፈጥረዋል!',
+ 'Installation_DatabaseCreatedSuccess' => 'የውሂብ ጎታ %s በሚገባ ተፈጥሯል!',
+ 'Installation_GoBackAndDefinePrefix' => 'ወደኋላ ተመለስና ለፒዊክ ሰንጠረዦቹ ቅድም ቅጥያውን በይን',
+ 'Installation_ConfirmDeleteExistingTables' => 'እርግጠኛ ነህ ይህንን ሰንጠረዥ ከውሂብ ጎታህ ውስጥ : %s መሰረዝ ትፈልጋለህ? ማስጠንቀቂያ: ከዚህ ሰንጠረዥ ውስጥ የጠፉ ውሂቦች ተመልሰው ሊገኙ አይችሉም!',
+ 'Installation_Welcome' => 'እንኳን ደህና መጡ!',
+ 'Installation_WelcomeHelp' => '<p>ፒዊክ ክፍት የሆነ የድር ማመዛዘኛ ሶፍትዌር ሲሆን ከጎብኚዎችዎ የሚፈልጉትን መረጃ ለማግኘት ቀላል ያደርገዋል።</p><p>ይህ ሂደት ወደ ቀላል ደረጃዎች %s የተከፋፈለ ሲሆን ወደ 5 ደቂቃ አካባቢ ይፈጃል።</p>',
+ 'Installation_ErrorInvalidState' => 'ስህተት: የመጫኑን ሂደት የዘለልክ ይመስላል ወይም ኩኪዎቹ ቦዝነዋል ውይም የፒዊክ ውቅረት ፋይል አስቀድሞ ተፈጥሯል። %sኩኪዎቹ መንቃታቸውን አረጋግጥ%s እና ተመልሰህ %s ወደ መጫኛው የመጀመሪያ ገፅ ሂድ። %s.',
+ 'Provider_WidgetProviders' => 'አቅራቢዎች',
+ 'Provider_ColumnProvider' => 'አቅራቢ',
+ 'Provider_SubmenuLocationsProvider' => 'መገኛ እና አቅራቢ',
+ 'Goals_ColumnConversions' => 'ልወጣዎች',
+ 'Goals_ColumnConversionRate' => 'የልወጣ ፍጥነት',
+ 'Goals_ColumnRevenue' => 'ገቢ',
+ 'DBStats_DatabaseUsage' => 'የውሂብ ጎታ አጠቃቀም',
+ 'DBStats_MainDescription' => 'ፒዊክ የድር ምዘናዎቹን ውሂብ በመይ ኤስ ኪው ኤል ይውሂብ ጎታ ውስጥ በማከማቸት ላይ ነው። በአሁን ወቅት የፒዊክ ሰንጠረዦች እየተጠቀሙ ያሉት %s።',
+ 'DBStats_Table' => 'ሰንጠረዥ',
+ 'DBStats_RowNumber' => 'የረድፍ ቁጥር',
+ 'DBStats_DataSize' => 'የውሂብ መጠን',
+ 'DBStats_IndexSize' => 'የመረጃ ጠቋሚ መጠን',
+ 'DBStats_TotalSize' => 'አጠቃላይ መጠን',
+ 'TranslationsAdmin_MenuTranslations' => 'ትርጉሞች',
+ 'TranslationsAdmin_MenuLanguages' => 'ቋንቋዎች',
+ 'TranslationsAdmin_Plugin' => 'ተሰኪ',
+ 'TranslationsAdmin_Definition' => 'ብየና',
+ 'TranslationsAdmin_DefaultString' => 'ነባሪ መዋቅር (እንግሊዘኛ)',
+ 'TranslationsAdmin_TranslationString' => 'የትርጉም መዋቅር (የአሁኑ ቋንቋ: %s)',
+ 'TranslationsAdmin_Translations' => 'ትርጉሞች',
+ 'TranslationsAdmin_FixPermissions' => 'እባክህ የሥርዓተ ፋይል ፈቃዶቹን ጠግን',
+ 'TranslationsAdmin_AvailableLanguages' => 'ያሉ ቋንቋዎች',
+ 'TranslationsAdmin_AddLanguage' => 'ቋንቋ ጨምር',
+ 'TranslationsAdmin_LanguageCode' => 'የቋንቋ ኮድ',
+ 'TranslationsAdmin_Export' => 'ቋንቋ ላክ',
+ 'TranslationsAdmin_Import' => 'ቋንቋ አስመጣ',
+);
+
diff --git a/lang/be.php b/lang/be.php
index a9efcc0c28..76815b32de 100644
--- a/lang/be.php
+++ b/lang/be.php
@@ -1,10 +1,17 @@
<?php
$translations = array(
- 'General_Locale' => 'be_BY.UTF-8',
- 'General_TranslatorName' => 'Fat Cow',
- 'General_TranslatorEmail' => 'zhr@tut.by',
- 'General_EnglishLanguageName' => 'Belarusian',
+ 'General_Locale' => 'ru_RU.UTF-8',
+ 'General_TranslatorName' => 'Fat Cow, <a href="http://www.fatcow.com">www.fatcow.com</a>',
+ 'General_TranslatorEmail' => 'by.marcis@gmail.com',
+ 'General_EnglishLanguageName' => 'Belarussian',
'General_OriginalLanguageName' => 'Беларуская',
+ 'General_HelloUser' => 'Прывітанне, %s!',
+ 'General_OpenSourceWebAnalytics' => 'Open Source Web Analytics',
+ 'General_YourDashboard' => 'Інфармацыйная панэль',
+ 'General_API' => 'API функцыі',
+ 'General_Widgets' => 'Віджеты',
+ 'General_Settings' => 'Налады',
+ 'General_GiveUsYourFeedback' => 'Зваротная сувязь',
'General_Unknown' => 'Невядома',
'General_Required' => '%s неабходна',
'General_Error' => 'Памылка',
@@ -17,8 +24,9 @@ $translations = array(
'General_Ok' => 'ОК',
'General_Close' => 'Зачыніць',
'General_Logout' => 'Выйсці',
- 'General_Done' => 'Завершанае',
+ 'General_Done' => 'Завершана',
'General_LoadingData' => 'Загрузка дадзеных...',
+ 'General_Loading' => 'Загрузка...',
'General_ErrorRequest' => 'Oops&hellip; праблема выканання запыту, калі ласка, паспрабуйце зноў.',
'General_Next' => 'Далей',
'General_Previous' => 'Папярэдняе',
@@ -28,41 +36,141 @@ $translations = array(
'General_Piechart' => 'Кругавая дыяграма',
'General_TagCloud' => 'Тэгі',
'General_VBarGraph' => 'Столбчатая дыяграма',
+ 'General_Export' => 'Экспарт',
+ 'General_ExportAsImage' => 'Экспартаваць як малюнак',
+ 'General_SaveImageOnYourComputer' => 'Каб захаваць малюнак на кампутары, націсніце правай кнопкай на ім і абярыце "Захаваць малюнак як..."',
'General_Refresh' => 'Абнавіць старонку',
+ 'General_Visitors' => 'Наведвальнікі',
'General_ColumnNbUniqVisitors' => 'Унікальных наведвальнікаў',
'General_ColumnNbVisits' => 'Наведванняў',
+ 'General_ColumnNbActions' => 'Дзеянняў',
+ 'General_ColumnMaxActions' => 'Макс. дзеянняў за адно наведванне',
+ 'General_ColumnSumVisitLength' => 'Агульны час наведвальнікаў на сайце (секунд)',
'General_ColumnLabel' => 'Пазначэнне',
+ 'General_ColumnActionsPerVisit' => 'Дзеянняў за наведванне',
+ 'General_ColumnAvgTimeOnSite' => 'Средн. час на сайце',
+ 'General_ColumnBounceRate' => 'Дзель карыстачоў, якія пайшлі пасля прагляду адной старонкі',
+ 'General_ColumnPageviews' => 'Прагляды старонак',
+ 'General_ColumnUniquePageviews' => 'Унікальныя прагляды старонак',
+ 'General_ColumnValuePerVisit' => 'Кошт візіту',
+ 'General_ColumnVisitsWithConversions' => 'Паўторныя візіты',
'General_Save' => 'Захаваць',
- 'General_NoDataForGraph' => 'Няма дадзеных для гэтага графіка',
- 'CorePluginsAdmin_Plugins' => 'Модулі',
+ 'General_Website' => 'Сайт',
+ 'General_NoDataForGraph' => 'Няма дадзеных для пабудовы графіка',
+ 'General_NoDataForTagCloud' => 'Няма дадзеных па гэтых тэгах',
+ 'General_DisplayNormalTable' => 'Паказаць звычайную табліцу',
+ 'General_DisplayMoreData' => 'Паказаць больш дадзеных',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s - гэта калектыўны праект. %s Калі Вам падабаецца Piwik, Вы можаце дапамагчы! Праверце, калі ласка %s як Вы можаце гэта зрабіць?%s ',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Цяпер Вы выкарыстоўваеце дэмаверсію скрыпту %s; %s запампуйце%s поўную версію! Гледзіце %s',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s даступны для спампоўкі. %s Калі ласка, абновіцеся!%s (гл. %s змены%s).',
+ 'General_BackToPiwik' => 'Вярнуцца да Piwik',
+ 'General_ShortMonth_1' => 'Янв',
+ 'General_ShortMonth_2' => 'Фев',
+ 'General_ShortMonth_3' => 'Мар',
+ 'General_ShortMonth_4' => 'Апр',
+ 'General_ShortMonth_5' => 'Травень',
+ 'General_ShortMonth_6' => 'іюн',
+ 'General_ShortMonth_7' => 'іюл',
+ 'General_ShortMonth_8' => 'Авг',
+ 'General_ShortMonth_9' => 'Сен',
+ 'General_ShortMonth_10' => 'Окт',
+ 'General_ShortMonth_11' => 'Ноя',
+ 'General_ShortMonth_12' => 'Дэк',
+ 'General_LongMonth_1' => 'Студзень',
+ 'General_LongMonth_2' => 'Люты',
+ 'General_LongMonth_3' => 'Сакавік',
+ 'General_LongMonth_4' => 'Красавік',
+ 'General_LongMonth_5' => 'Травень',
+ 'General_LongMonth_6' => 'Чэрвень',
+ 'General_LongMonth_7' => 'Ліпень',
+ 'General_LongMonth_8' => 'Аўгуст',
+ 'General_LongMonth_9' => 'Верасень',
+ 'General_LongMonth_10' => 'Октыбрь',
+ 'General_LongMonth_11' => 'Лістапад',
+ 'General_LongMonth_12' => 'Снежань',
+ 'General_ShortDay_1' => 'Пн',
+ 'General_ShortDay_2' => 'Вт',
+ 'General_ShortDay_3' => 'Ср',
+ 'General_ShortDay_4' => 'Чт',
+ 'General_ShortDay_5' => 'Пт',
+ 'General_ShortDay_6' => 'Сб',
+ 'General_ShortDay_7' => 'Вс',
+ 'General_LongDay_1' => 'Панядзелак',
+ 'General_LongDay_2' => 'Аўторак',
+ 'General_LongDay_3' => 'Асяроддзе',
+ 'General_LongDay_4' => 'Чацвер',
+ 'General_LongDay_5' => 'Пятніца',
+ 'General_LongDay_6' => 'Субота',
+ 'General_LongDay_7' => 'Нядзеля',
+ 'CorePluginsAdmin_Plugins' => 'Убудовы',
+ 'CorePluginsAdmin_PluginsManagement' => 'Кіраванне ўбудовамі',
+ 'CorePluginsAdmin_MainDescription' => 'Убудовы пашыраюць функцыянальнасць Piwik. Пасля ўсталёўкі ўбудовы Вы можаце актываваць ці дэактываваць яго тут.',
+ 'CorePluginsAdmin_Plugin' => 'Убудова',
+ 'CorePluginsAdmin_Version' => 'Версія',
+ 'CorePluginsAdmin_Description' => 'Апісанне',
+ 'CorePluginsAdmin_Status' => 'Статут',
+ 'CorePluginsAdmin_Action' => 'Дзеянне',
+ 'CorePluginsAdmin_PluginHomepage' => 'Хата. старонка ўбудовы',
'CorePluginsAdmin_Activated' => 'Актывавана',
- 'CorePluginsAdmin_ActivatedHelp' => 'Гэтая ўбудова не можа быць дэактываваны',
+ 'CorePluginsAdmin_Active' => 'Актыўныя',
+ 'CorePluginsAdmin_Inactive' => 'Неактыўныя',
+ 'CorePluginsAdmin_ActivatedHelp' => 'Гэта ўбудова не можа быць дэактываваны',
'CorePluginsAdmin_Deactivate' => 'Дэактываваць',
'CorePluginsAdmin_Activate' => 'Актываваць',
- 'CorePluginsAdmin_MenuPlugins' => 'Модулі',
- 'API_QuickDocumentation' => '<h2>Кароткая API дакументацыя</h2><p>Калі вы не маеце дадзеных на сёння, вы можаце спачатку <a href=\'misc/generateVisits.php\' target=_blank>згенераваць некаторыя дадзеныя</a>, выкарыстаючы скрыпт генеравання наведванняў.</p><p>Вы можаце выкарыстаць розныя фарматы для кожнага метаду. Выцягнуць неабходную інфармацыю з Piwik вельмі лёгка!</p><p><b>Для далейшай інфармацыі чытайце <a href=\'http://dev.piwik.org/trac/wiki/API\'>афіцыйную API Дакументацыю</a>, або <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API Reference</a>.</b></P><h2>Аўтэнтыфікацыя карыстачоў</h2><p>Калі вам неабходна <b>запытваць дадзеныя ў вашых скрыптах, cron-задачах і т.д.</b>, то вам неабходна дадаць параметр <code><u>&token_auth=%s</u></code> да URL API-выкліку, які патрабуе аўтэнтыфікацыю. </p><p>Гэты параметр token_auth такі жа сакрэтны, як і ваш пароль, <b>НЕ ПАВЕДАМЛЯЙЦЕ ЯГО!</p>',
+ 'CorePluginsAdmin_MenuPlugins' => 'Убудовы',
+ 'API_QuickDocumentation' => '<h2>Кароткая API дакументацыя</h2><p>Калі вы не маеце дадзеных на сёння, вы можаце спачатку <a href=\'misc/generateVisits.php\' target=_blank>згенераваць некаторыя дадзеныя</a>, выкарыстоўваючы скрыпт генерацыі наведванняў.</p><p>Вы можаце выкарыстоўваць розныя фарматы для кожнага метаду. Выключыць неабходную інфармацыю з Piwik вельмі лёгка!</p><p><b>Для далейшай інфармацыі чытайце <a href=\'http://dev.piwik.org/trac/wiki/API\'>афіцыйную API Дакументацыю</a>, ці <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API Reference</a>.</b></P><h2>Аўтэнтыфікацыя карыстачоў</h2><p>Калі вам неабходна <b>запытваць дадзеныя ў вашых скрыптах, cron-задачах і г.д.</b>, то вам неабходна дадаць параметр <code><u>&token_auth=%s</u></code> да URL API-выкліку, які патрабуе аўтэнтыфікацыю. </p><p>Гэты параметр token_auth такі ж сакрэтны, як і ваш пароль, <b>НЕ ПАВЕДАМЛЯЙЦЕ ЯГО НІКОМУ!</p>',
'API_LoadedAPIs' => '%s API паспяхова загружана',
- 'CoreHome_NoPrivileges' => 'Вы зашлі як \'%s\', але, падобна, Вы не маеце дазволаў праглядаць статыстыку Piwik.<br />Паведаміце адміністратару аб падаванні Вам доступу на выкарыстанне сістэмы.',
- 'CoreHome_JavascriptDisabled' => 'JavaScript павінен быць дазволены для карэктнага стандартнага адлюстравання Piwik.<br />Калі Вы чытаеце гэтае паведамленне, значыць JavaScript забаронены, альбо не падтрымліваецца Вашым браўзэрам.<br />Для выкарыстання стандартнага выгляду, дазволіце JavaScript у наладах Вашага браўзэра, потым %1sпопробуйте абнавіць старонку%2s.<br />',
+ 'CoreHome_NoPrivileges' => 'Вы зайшлі як \'%s\', але, падобна, Вы не маеце дазволаў праглядаць статыстыку Piwik.<br />Паведаміце адміністратару пра падаванне Вам доступу на выкарыстанне сістэмы.',
+ 'CoreHome_JavascriptDisabled' => 'JavaScript павінен быць дазволены для карэктнага стандартнага адлюстравання Piwik.<br />Калі Вы чытаеце гэта паведамленне, значыць JavaScript забаронены, або не падтрымліваецца Вашым браўзарам.<br />Для выкарыстання стандартнага выгляду, дазволіце JavaScript у наладах Вашага браўзара, потым %1sпопробуйте абнавіць старонку%2s.<br />',
'CoreHome_TableNoData' => 'Няма таблічных дадзеных.',
- 'CoreHome_CategoryNoData' => 'Няма дадзеных у гэтай катэгорыі. Паспрабуйце "Уключыць усе паказчыкі".',
+ 'CoreHome_CategoryNoData' => 'Няма дадзеных у гэтай катэгорыі. Паспрабуйце "Ўключыць усе паказчыкі".',
'CoreHome_ShowJSCode' => 'Паказаць Java-код для ўстаўкі',
'CoreHome_IncludeAllPopulation_js' => 'Уключыць усе паказчыкі...',
'CoreHome_ExcludeLowPopulation_js' => 'Выключыць нізкія паказчыкі...',
'CoreHome_PageOf_js' => '%s з %s',
'CoreHome_Loading_js' => 'Загрузка...',
- 'CoreHome_LocalizedDateFormat' => '%A %d %B %Y',
+ 'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
'CoreHome_PeriodDay' => 'Дзень',
'CoreHome_PeriodWeek' => 'Тыдзень',
'CoreHome_PeriodMonth' => 'Месяц',
'CoreHome_PeriodYear' => 'Год',
- 'CoreHome_DaySu_js' => 'Нядзеля',
- 'CoreHome_DayMo_js' => 'Панядзелак',
- 'CoreHome_DayTu_js' => 'Аўторак',
- 'CoreHome_DayWe_js' => 'Серада',
- 'CoreHome_DayTh_js' => 'Чацвер',
- 'CoreHome_DayFr_js' => 'Пятніца',
- 'CoreHome_DaySa_js' => 'Субота',
+ 'CoreHome_PeriodDays' => 'дзён',
+ 'CoreHome_PeriodWeeks' => 'тыдняў',
+ 'CoreHome_PeriodMonths' => 'месяцаў',
+ 'CoreHome_PeriodYears' => 'гадоў',
+ 'CoreHome_DaySu_js' => 'Вс',
+ 'CoreHome_DayMo_js' => 'Пн',
+ 'CoreHome_DayTu_js' => 'Вт',
+ 'CoreHome_DayWe_js' => 'Ср',
+ 'CoreHome_DayTh_js' => 'Чт',
+ 'CoreHome_DayFr_js' => 'Пт',
+ 'CoreHome_DaySa_js' => 'Сб',
+ 'CoreHome_ShortDay_1_js' => 'вск',
+ 'CoreHome_ShortDay_2_js' => 'пнд',
+ 'CoreHome_ShortDay_3_js' => 'втр',
+ 'CoreHome_ShortDay_4_js' => 'срд',
+ 'CoreHome_ShortDay_5_js' => 'чтв',
+ 'CoreHome_ShortDay_6_js' => 'птн',
+ 'CoreHome_ShortDay_7_js' => 'сбт',
+ 'CoreHome_LongDay_1_js' => 'нядзеля',
+ 'CoreHome_LongDay_2_js' => 'панядзелак',
+ 'CoreHome_LongDay_3_js' => 'аўторак',
+ 'CoreHome_LongDay_4_js' => 'асяроддзе',
+ 'CoreHome_LongDay_5_js' => 'чацвер',
+ 'CoreHome_LongDay_6_js' => 'пятніца',
+ 'CoreHome_LongDay_7_js' => 'субота',
+ 'CoreHome_ShortMonth_1_js' => 'Янв',
+ 'CoreHome_ShortMonth_2_js' => 'Фев',
+ 'CoreHome_ShortMonth_3_js' => 'Мар',
+ 'CoreHome_ShortMonth_4_js' => 'Апр',
+ 'CoreHome_ShortMonth_5_js' => 'Травень',
+ 'CoreHome_ShortMonth_6_js' => 'іюн',
+ 'CoreHome_ShortMonth_7_js' => 'іюл',
+ 'CoreHome_ShortMonth_8_js' => 'Авг',
+ 'CoreHome_ShortMonth_9_js' => 'Сен',
+ 'CoreHome_ShortMonth_10_js' => 'Окт',
+ 'CoreHome_ShortMonth_11_js' => 'Ноя',
+ 'CoreHome_ShortMonth_12_js' => 'Дэк',
'CoreHome_MonthJanuary_js' => 'Студзень',
'CoreHome_MonthFebruary_js' => 'Люты',
'CoreHome_MonthMarch_js' => 'Сакавік',
@@ -70,64 +178,117 @@ $translations = array(
'CoreHome_MonthMay_js' => 'Травень',
'CoreHome_MonthJune_js' => 'Чэрвень',
'CoreHome_MonthJuly_js' => 'Ліпень',
- 'CoreHome_MonthAugust_js' => 'Жнівень',
+ 'CoreHome_MonthAugust_js' => 'Аўгуст',
'CoreHome_MonthSeptember_js' => 'Верасень',
'CoreHome_MonthOctober_js' => 'Кастрычнік',
'CoreHome_MonthNovember_js' => 'Лістапад',
'CoreHome_MonthDecember_js' => 'Снежань',
+ 'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; - абнаўленне',
+ 'CoreUpdater_DatabaseUpgradeRequired' => 'Патрабуецца абнаўленне базы дадзеных',
+ 'CoreUpdater_YourDatabaseIsOutOfDate' => 'Тэрмін дзеяння Вашай Piwik базы мінуў, Вам трэба яе абнавіць для працягу. ',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik база будзе абноўлена з версіі %s да версіі %s.',
+ 'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Наступныя ўбудовы будуць абноўлены: %s.',
+ 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Абнаўленне базы дадзеных можа заняць некаторы час, таму пачакайце трохі.',
+ 'CoreUpdater_UpgradePiwik' => 'Абнавіць Piwik',
+ 'CoreUpdater_HelpMessageContent' => 'Праверце %s Piwik FAQ %s, у якім тлумачыцца большасць вядомых памылак, якія могуць здарыцца падчас абнаўлення. %s Звернецеся да сістэмнага адміністратара - ён можа дапамагчы Вам з рашэннем праблемы на серверы ці з наладамі MySQL.',
+ 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Крытычная памылка падчас абнаўлення:',
+ 'CoreUpdater_HelpMessageIntroductionWhenError' => 'Вышэй падаецца код памылкі ядра сістэмы. Ён дапаможа Вам растлумачыць чыннік памылкі, але калі ж Вам неабходна дадатковая дапамога, калі ласка:',
+ 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Абнаўленне завершана паспяхова, аднак падчас паўстала некалькі папярэджанняў. Калі ласка, прачытайце нататкі ніжэй. Для дадатковай дапамогі:',
+ 'CoreUpdater_UpgradeComplete' => 'Абнаўленне завершана!',
+ 'CoreUpdater_WarningMessages' => 'Папярэджанні:',
+ 'CoreUpdater_ErrorDuringPluginsUpdates' => 'Памылка падчас абнаўлення ўбудовы:',
+ 'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Наступныя ўбудовы аўтаматычна дэактываваны: %s',
+ 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik паспяхова абноўлены!',
+ 'CoreUpdater_ContinueToPiwik' => 'Перайсці да Piwik',
+ 'CoreUpdater_UpdateAutomatically' => 'Абнавіць аўтаматычна',
+ 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Даступная новая версія Piwik',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Вы можаце абнавіцца да версіі %s аўтаматычна ці запампаваць усталявальны пакет і ўручную ўсталяваць яго:',
+ 'CoreUpdater_DownloadX' => 'Запампаваць %s',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Piwik One Click Update адменены. Калі Вы не можаце выправіць вышэйапісаныя памылкі, рэкамендуецца абнавіць Piwik уручную. %s Калі ласка, праверце %sдокументацію абнаўленні%s для тона, каб пачаць!',
+ 'CoreUpdate_DownloadingUpdateFromX' => 'Спампоўваю абнаўленне з %s',
+ 'CoreUpdate_UnpackingTheUpdate' => 'Распакоўваю абнаўленне',
+ 'CoreUpdater_VerifyingUnpackedFiles' => 'Правяраю распакаваныя файлы',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Содаю рэзервовую копію файла канфігурацыі ў %s',
+ 'CoreUpdater_InstallingTheLatestVersion' => 'Усталёўка апошняй версіі',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik абноўлены паспяхова!',
+ 'CoreUpdater_EmptyDatabaseError' => 'База дадзеных %s пустая. Вам неабходна кіраваць уручную ці выдаліць файл канфігурацыі Piwik.',
+ 'Actions_Actions' => 'Дзеянні',
'Actions_SubmenuPages' => 'Старонкі',
- 'Actions_SubmenuOutlinks' => 'Внешн.спасылкі',
+ 'Actions_SubmenuOutlinks' => 'Внешн. спасылкі',
'Actions_SubmenuDownloads' => 'Загрузкі',
- 'Dashboard_AddWidget' => 'Дадаць інформер...',
- 'Dashboard_DeleteWidgetConfirm' => 'Вы ўпэўненыя, што жадаеце выдаліць інформер з панэлі прыбораў?',
- 'Dashboard_SelectWidget' => 'Вылучыце інформер для дадання на информпанель',
- 'Dashboard_AddPreviewedWidget' => 'Дадаць предпросмотренный інформер на информпанель',
- 'Dashboard_WidgetPreview' => 'Прадпрагляд інформера',
- 'Dashboard_TitleWidgetInDashboard_js' => 'Інформер ужо існуе на информпанели',
- 'Dashboard_TitleClickToAdd_js' => 'Клікніце для дадання на информпанель',
- 'Dashboard_LoadingPreview_js' => 'Загрузка предспросмотра, калі ласка пачакайце...',
- 'Dashboard_LoadingWidget_js' => 'Загрузка інформера, калі ласка пачакайце...',
- 'Dashboard_WidgetNotFound_js' => 'Інформер не знойдзены',
+ 'Actions_ColumnClicks' => 'Зграі',
+ 'Actions_ColumnUniqueClicks' => 'Унікальныя зграі',
+ 'Actions_ColumnDownloads' => 'Загрузкі',
+ 'Actions_ColumnUniqueDownloads' => 'Унікальныя загрузкі',
+ 'Actions_ColumnPageName' => 'Назва старонкі',
+ 'Actions_ColumnClickedURL' => 'URL клікаў',
+ 'Actions_ColumnDownloadURL' => 'URL загрузак',
+ 'Dashboard_Dashboard' => 'Інфармацыйная панэль',
+ 'Dashboard_AddWidget' => 'Дадаць віджет...',
+ 'Dashboard_DeleteWidgetConfirm' => 'Вы ўпэўнены, што жадаеце выдаліць гэты віджет з інфармацыйнай панэлі?',
+ 'Dashboard_SelectWidget' => 'Абярыце віджет для дадання на інформпанель',
+ 'Dashboard_AddPreviewedWidget_js' => 'Дадаць предпросмотренный віджет на інформпанель',
+ 'Dashboard_WidgetPreview_js' => 'Прадпрагляд віджета',
+ 'Dashboard_Close_js' => 'Зачыніць',
+ 'Dashboard_TitleWidgetInDashboard_js' => 'Віджет ужо існуе на інформпанелі',
+ 'Dashboard_TitleClickToAdd_js' => 'Клікніце для дадання на інформпанель',
+ 'Dashboard_LoadingWidget_js' => 'Загрузка віджета, калі ласка пачакайце...',
+ 'Dashboard_WidgetNotFound_js' => 'Віджет не знойдзены',
+ 'Referers_Referers' => 'Рэфералы',
'Referers_SearchEngines' => 'Пошукавыя рухавічкі',
'Referers_Keywords' => 'Ключавыя словы',
'Referers_DirectEntry' => 'Прамы ўваход',
'Referers_Websites' => 'Вэбсайты',
- 'Referers_Newsletters' => 'Навінавыя стужкі',
- 'Referers_Campaigns' => 'Кампанія',
+ 'Referers_Campaigns' => 'Кампаніі',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%1s (з %2s)',
'Referers_Evolution' => 'Эвалюцыя па перыядзе',
- 'Referers_Type' => 'Тып рефера',
+ 'Referers_Type' => 'Тып рэферала',
+ 'Referers_ColumnRefererType' => 'Тып рэферала',
+ 'Referers_ColumnSearchEngine' => 'Пошукавы рухавічок',
+ 'Referers_ColumnWebsite' => 'Вэбсайт',
+ 'Referers_ColumnWebsitePage' => 'Старонка вэбсайта',
+ 'Referers_ColumnKeyword' => 'Ключавое слова',
+ 'Referers_ColumnCampaign' => 'Кампанія',
+ 'Referers_DetailsByRefererType' => 'Дэталі па тыпе рэферала',
'Referers_TypeDirectEntries' => '%s прамых уваходаў',
'Referers_TypeSearchEngines' => '%s уваходаў з пошукавых рухавічкоў',
'Referers_TypeWebsites' => '%s уваходаў з вэбсайтаў',
- 'Referers_TypeNewsletters' => '%s уваходаў з навінавых стужак',
'Referers_TypeCampaigns' => '%s уваходаў з кампаній',
- 'Referers_Other' => 'Іншыя',
- 'Referers_OtherDistinctSearchEngines' => '%s унікальных пошукавых рухавічкоў',
- 'Referers_OtherDistinctKeywords' => '%s унікальных ключавых слоў',
- 'Referers_OtherDistinctWebsites' => '%1s унікальных вэбсайтаў (выкарыстаючы %2s унікальных URL)',
- 'Referers_OtherDistinctCampaigns' => '%s унікальных кампаній',
- 'Referers_TagCloud' => 'Воблака тэгаў',
+ 'Referers_Distinct' => 'Розныя рэфералы па тыпе',
+ 'Referers_DistinctSearchEngines' => 'Розныя пошукавыя рухавічкі',
+ 'Referers_DistinctKeywords' => 'Розныя ключавыя словы',
+ 'Referers_DistinctCampaigns' => 'Розныя кампаніі',
+ 'Referers_DistinctWebsites' => 'Розныя вэбсайты',
+ 'Referers_UsingNDistinctUrls' => ' (выкарыстоўваючы %2s розных url)',
'Referers_SubmenuEvolution' => 'Эвалюцыя',
'Referers_SubmenuSearchEngines' => 'Пошукавыя рухавічкі і ключ. словы',
'Referers_SubmenuWebsites' => 'Вэбсайты',
'Referers_SubmenuCampaigns' => 'Кампаніі',
'Referers_WidgetKeywords' => 'Спіс ключавых слоў',
'Referers_WidgetCampaigns' => 'Спіс кампаній',
- 'Referers_WidgetExternalWebsites' => 'Спіс знешніх вэбсайтаў',
+ 'Referers_WidgetExternalWebsites' => 'Спіс вонкавых вэбсайтаў',
'Referers_WidgetSearchEngines' => 'Лепшыя пошукавыя рухавічкі',
'Referers_WidgetOverview' => 'Агляд',
- 'UserSettings_BrowserFamilies' => 'Па сямействе браўзэраў',
- 'UserSettings_Browsers' => 'Па браўзэрах',
- 'UserSettings_Plugins' => 'Падлучальныя модулі',
+ 'UserSettings_VisitorSettings' => 'Налады карыстача',
+ 'UserSettings_BrowserFamilies' => 'Па сямействе браўзараў',
+ 'UserSettings_Browsers' => 'Па браўзарах',
+ 'UserSettings_Plugins' => 'Убудовы',
'UserSettings_Configurations' => 'Па канфігурацыі',
- 'UserSettings_OperatinsSystems' => 'Па аперацыйных сістэмах',
+ 'UserSettings_OperatingSystems' => 'Па аперацыйных сістэмах',
'UserSettings_Resolutions' => 'Па дазволе манітораў',
'UserSettings_WideScreen' => 'Па шырыні экрана',
+ 'UserSettings_ColumnBrowserFamily' => 'Сямейства браўзараў',
+ 'UserSettings_ColumnBrowser' => 'Браўзар',
+ 'UserSettings_ColumnPlugin' => 'Убудова',
+ 'UserSettings_ColumnConfiguration' => 'Канфігурацыя',
+ 'UserSettings_ColumnOperatingSystem' => 'Аперацыйная сістэма',
+ 'UserSettings_ColumnResolution' => 'Дазвол',
+ 'UserSettings_ColumnTypeOfScreen' => 'Тып экрана',
'UserSettings_WidgetResolutions' => 'Па дазволе манітораў',
- 'UserSettings_WidgetBrowsers' => 'Браўзэры карыстачоў',
- 'UserSettings_WidgetPlugins' => 'Спіс падлучальных модуляў',
- 'UserSettings_WidgetWidescreen' => 'Нармалёвы / Шырокаэкранны',
- 'UserSettings_WidgetBrowserFamilies' => 'Браўзэры па сямействе',
+ 'UserSettings_WidgetBrowsers' => 'Браўзары карыстачоў',
+ 'UserSettings_WidgetPlugins' => 'Спіс убудоў',
+ 'UserSettings_WidgetWidescreen' => 'Звычайны / Шырокаэкранны',
+ 'UserSettings_WidgetBrowserFamilies' => 'Браўзары па сямействе',
'UserSettings_WidgetOperatingSystems' => 'Аперацыйныя сістэмы',
'UserSettings_WidgetGlobalVisitors' => 'Глабальная канфігурацыя',
'UserSettings_SubmenuSettings' => 'Налады карыстачоў',
@@ -139,13 +300,13 @@ $translations = array(
'UserCountry_WidgetCountries' => 'Краіны наведвальнікаў',
'UserCountry_country_ac' => 'Выспы Ўшэсці',
'UserCountry_country_ad' => 'Андора',
- 'UserCountry_country_ae' => 'Абяднаныя Арабскія Эміраты',
+
'UserCountry_country_af' => 'Афганістан',
'UserCountry_country_ag' => 'Антыгуа і Барбуда',
- 'UserCountry_country_ai' => 'Ангвила',
+ 'UserCountry_country_ai' => 'Ангвіла',
'UserCountry_country_al' => 'Албанія',
'UserCountry_country_am' => 'Арменія',
- 'UserCountry_country_an' => 'Антильские выспы',
+ 'UserCountry_country_an' => 'Антыльскія выспы',
'UserCountry_country_ao' => 'Ангола',
'UserCountry_country_aq' => 'Антарктыка',
'UserCountry_country_ar' => 'Аргентына',
@@ -153,29 +314,32 @@ $translations = array(
'UserCountry_country_at' => 'Аўстрыя',
'UserCountry_country_au' => 'Аўстралія',
'UserCountry_country_aw' => 'Аруба',
+ 'UserCountry_country_ax' => 'Аландскіе выспы',
'UserCountry_country_az' => 'Азербайджан',
'UserCountry_country_ba' => 'Боснія і Герцагавіна',
'UserCountry_country_bb' => 'Барбадос',
'UserCountry_country_bd' => 'Бангладэш',
'UserCountry_country_be' => 'Бельгія',
- 'UserCountry_country_bf' => 'Буркина-Фасо',
+ 'UserCountry_country_bf' => 'Буркіна-Фаса',
'UserCountry_country_bg' => 'Балгарыя',
'UserCountry_country_bh' => 'Бахрэйн',
'UserCountry_country_bi' => 'Бурундзі',
'UserCountry_country_bj' => 'Бенін',
+ 'UserCountry_country_bl' => 'Сен-Бартельмі',
'UserCountry_country_bm' => 'Бярмудскія выспы',
'UserCountry_country_bn' => 'Бруней',
'UserCountry_country_bo' => 'Балівія',
'UserCountry_country_br' => 'Бразілія',
'UserCountry_country_bs' => 'Багамскія выспы',
'UserCountry_country_bt' => 'Бутан',
+ 'UserCountry_country_bu' => 'Бірма',
'UserCountry_country_bv' => 'Выспа Буве',
- 'UserCountry_country_bw' => 'Ботсвана',
+ 'UserCountry_country_bw' => 'Батсвана',
'UserCountry_country_by' => 'Беларусь',
'UserCountry_country_bz' => 'Беліз',
'UserCountry_country_ca' => 'Канада',
'UserCountry_country_cc' => 'Какосавыя выспы',
- 'UserCountry_country_cd' => 'Конга, дэмакратычная рэспубалік',
+ 'UserCountry_country_cd' => 'Конга, дэмакратычная рэспубліка',
'UserCountry_country_cf' => 'Цэнтральнаафрыканская Рэспубліка',
'UserCountry_country_cg' => 'Конга',
'UserCountry_country_ch' => 'Швейцарыя',
@@ -185,19 +349,22 @@ $translations = array(
'UserCountry_country_cm' => 'Камерун',
'UserCountry_country_cn' => 'Кітай',
'UserCountry_country_co' => 'Калумбія',
- 'UserCountry_country_cr' => 'Коста-Рика',
+ 'UserCountry_country_cp' => 'Кліппертонскіе выспы',
+ 'UserCountry_country_cr' => 'Коста-Ріка',
'UserCountry_country_cs' => 'Сербія і Чарнагорыя',
'UserCountry_country_cu' => 'Куба',
- 'UserCountry_country_cv' => 'Кабо-Верде',
+ 'UserCountry_country_cv' => 'Кабо Верде',
'UserCountry_country_cx' => 'Выспа Каляд',
'UserCountry_country_cy' => 'Кіпр',
'UserCountry_country_cz' => 'Чэшская Рэспубліка',
'UserCountry_country_de' => 'Нямеччына',
- 'UserCountry_country_dj' => 'Джибути',
+ 'UserCountry_country_dg' => 'Діего-Гарсія',
+ 'UserCountry_country_dj' => 'Джібуті',
'UserCountry_country_dk' => 'Данія',
'UserCountry_country_dm' => 'Дамініка',
'UserCountry_country_do' => 'Дамініканская Рэспубліка',
'UserCountry_country_dz' => 'Алжыр',
+ 'UserCountry_country_ea' => 'Сеута і Мелілья',
'UserCountry_country_ec' => 'Эквадор',
'UserCountry_country_ee' => 'Эстонія',
'UserCountry_country_eg' => 'Егіпет',
@@ -205,17 +372,20 @@ $translations = array(
'UserCountry_country_er' => 'Эрытрэя',
'UserCountry_country_es' => 'Іспанія',
'UserCountry_country_et' => 'Эфіёпія',
+ 'UserCountry_country_eu' => 'Еўрапейскі Звяз',
'UserCountry_country_fi' => 'Фінляндыя',
'UserCountry_country_fj' => 'Фіджы',
- 'UserCountry_country_fk' => 'Фолклендские выспы (Мальвинские)',
- 'UserCountry_country_fm' => 'Мікранэзія',
+ 'UserCountry_country_fk' => 'Фалклэндскія выспы (Мальвінскіе)',
+ 'UserCountry_country_fm' => 'Федэратыўныя Штаты Мікранэзіі',
'UserCountry_country_fo' => 'Фарэрскія выспы',
'UserCountry_country_fr' => 'Францыя',
+ 'UserCountry_country_fx' => 'Метраполія Францыі',
'UserCountry_country_ga' => 'Габон',
+ 'UserCountry_country_gb' => 'Вялікабрытанія',
'UserCountry_country_gd' => 'Грэнада',
'UserCountry_country_ge' => 'Грузія',
'UserCountry_country_gf' => 'Фр. Гаяна',
- 'UserCountry_country_gg' => 'Гернси',
+ 'UserCountry_country_gg' => 'Гернсі',
'UserCountry_country_gh' => 'Гана',
'UserCountry_country_gi' => 'Гібралтар',
'UserCountry_country_gl' => 'Грэнландыя',
@@ -224,7 +394,7 @@ $translations = array(
'UserCountry_country_gp' => 'Гвадэлупа',
'UserCountry_country_gq' => 'Экватарыяльная Гвінея',
'UserCountry_country_gr' => 'Грэцыя',
- 'UserCountry_country_gs' => 'Паўднёвая Джорджыя і Паўднёвыя Сандвичевы выспы',
+ 'UserCountry_country_gs' => 'Паўднёвая Джорджыя і Паўднёвыя Сандвічевы выспы',
'UserCountry_country_gt' => 'Гватэмала',
'UserCountry_country_gu' => 'Гуам',
'UserCountry_country_gw' => 'Гвінея-Бісаў',
@@ -235,6 +405,7 @@ $translations = array(
'UserCountry_country_hr' => 'Харватыя',
'UserCountry_country_ht' => 'Гаіці',
'UserCountry_country_hu' => 'Вугоршчына',
+ 'UserCountry_country_ic' => 'Канарскія выспы',
'UserCountry_country_id' => 'Інданэзія',
'UserCountry_country_ie' => 'Ірландыя',
'UserCountry_country_il' => 'Ізраіль',
@@ -250,11 +421,11 @@ $translations = array(
'UserCountry_country_jo' => 'Іярданія',
'UserCountry_country_jp' => 'Японія',
'UserCountry_country_ke' => 'Кенія',
- 'UserCountry_country_kg' => 'Киргизстан',
+ 'UserCountry_country_kg' => 'Кіргізстан',
'UserCountry_country_kh' => 'Камбоджа',
'UserCountry_country_ki' => 'Кірыбаты',
'UserCountry_country_km' => 'Каморскія выспы',
- 'UserCountry_country_kn' => 'Сэнт-Китс і Невис',
+ 'UserCountry_country_kn' => 'Сэнт-Кітс і Невіс',
'UserCountry_country_kp' => 'КНДР',
'UserCountry_country_kr' => 'Карэя',
'UserCountry_country_kw' => 'Кувейт',
@@ -263,8 +434,8 @@ $translations = array(
'UserCountry_country_la' => 'Лаос',
'UserCountry_country_lb' => 'Ліван',
'UserCountry_country_lc' => 'Сэнт-Люсія',
- 'UserCountry_country_li' => 'Ліхтэнштайн',
- 'UserCountry_country_lk' => 'Шри-Ланка',
+ 'UserCountry_country_li' => 'Ліхтэнштэйн',
+ 'UserCountry_country_lk' => 'Шрі-Ланка',
'UserCountry_country_lr' => 'Ліберыя',
'UserCountry_country_ls' => 'Лесота',
'UserCountry_country_lt' => 'Літва',
@@ -274,20 +445,21 @@ $translations = array(
'UserCountry_country_ma' => 'Марока',
'UserCountry_country_mc' => 'Манака',
'UserCountry_country_md' => 'Малдова',
+ 'UserCountry_country_me' => 'Чарнагорыя',
+ 'UserCountry_country_mf' => 'Выспа Святога Марціна',
'UserCountry_country_mg' => 'Мадагаскар',
'UserCountry_country_mh' => 'Маршалавы выспы',
'UserCountry_country_mk' => 'Македонія',
'UserCountry_country_ml' => 'Малі',
- 'UserCountry_country_mm' => 'Мянма',
'UserCountry_country_mn' => 'Манголія',
'UserCountry_country_mo' => 'Макау',
- 'UserCountry_country_mp' => 'Паўночныя Марианские выспы',
+ 'UserCountry_country_mp' => 'Паўночныя Маріанскіе выспы',
'UserCountry_country_mq' => 'Мартыніка',
'UserCountry_country_mr' => 'Маўрытанія',
'UserCountry_country_ms' => 'Монсеррат',
'UserCountry_country_mt' => 'Мальта',
'UserCountry_country_mu' => 'Маўрыкій',
- 'UserCountry_country_mv' => 'Мальдивские выспы',
+ 'UserCountry_country_mv' => 'Мальдыўскія выспы',
'UserCountry_country_mw' => 'Малаві',
'UserCountry_country_mx' => 'Мексіка',
'UserCountry_country_my' => 'Малайзія',
@@ -295,25 +467,26 @@ $translations = array(
'UserCountry_country_na' => 'Намібія',
'UserCountry_country_nc' => 'Новая Калядонія',
'UserCountry_country_ne' => 'Нігер',
- 'UserCountry_country_nf' => 'Норфолкские выспы',
+ 'UserCountry_country_nf' => 'Норфолкскіе выспы',
'UserCountry_country_ng' => 'Нігерыя',
'UserCountry_country_ni' => 'Нікарагуа',
'UserCountry_country_nl' => 'Нідэрланды',
'UserCountry_country_no' => 'Нарвегія',
'UserCountry_country_np' => 'Непал',
'UserCountry_country_nr' => 'Наўру',
- 'UserCountry_country_nu' => 'Ние',
+ 'UserCountry_country_nt' => 'Нейтральныя тэрыторыі',
+ 'UserCountry_country_nu' => 'Ніе',
'UserCountry_country_nz' => 'Новая Зеландыя',
'UserCountry_country_om' => 'Аман',
'UserCountry_country_pa' => 'Панама',
- 'UserCountry_country_pe' => 'Пяру',
- 'UserCountry_country_pf' => 'Фр. Палінэзія',
+ 'UserCountry_country_pe' => 'Перу',
+ 'UserCountry_country_pf' => 'Фр. Палінезія',
'UserCountry_country_pg' => 'Папуа - Новая Гвінея',
'UserCountry_country_ph' => 'Філіпіны',
'UserCountry_country_pk' => 'Пакістан',
'UserCountry_country_pl' => 'Польшча',
- 'UserCountry_country_pm' => 'Сен-Пер і Микелон',
- 'UserCountry_country_pn' => 'Питкэрн',
+
+ 'UserCountry_country_pn' => 'Піткэрн',
'UserCountry_country_pr' => 'Пуэрта-Рыко',
'UserCountry_country_ps' => 'Палестынская тэрыторыя',
'UserCountry_country_pt' => 'Партугалія',
@@ -322,34 +495,39 @@ $translations = array(
'UserCountry_country_qa' => 'Катар',
'UserCountry_country_re' => 'Выспа Реюньон',
'UserCountry_country_ro' => 'Румынія',
+ 'UserCountry_country_ru' => 'Расія',
+ 'UserCountry_country_rs' => 'Сербія',
'UserCountry_country_rw' => 'Руанда',
- 'UserCountry_country_sa' => 'Саўдаўская Аравія',
+ 'UserCountry_country_sa' => 'Саудаўская Аравія',
'UserCountry_country_sb' => 'Саламонавы выспы',
'UserCountry_country_sc' => 'Сейшэльскія выспы',
'UserCountry_country_sd' => 'Судан',
'UserCountry_country_se' => 'Швецыя',
+ 'UserCountry_country_sf' => 'Фінляндыя',
'UserCountry_country_sg' => 'Сінгапур',
'UserCountry_country_sh' => 'Выспа Святой Алены',
'UserCountry_country_si' => 'Славенія',
'UserCountry_country_sj' => 'Свольбар',
'UserCountry_country_sk' => 'Славакія',
- 'UserCountry_country_sl' => 'Сьера-Лявоне',
+ 'UserCountry_country_sl' => 'Сьера-Леонэ',
'UserCountry_country_sm' => 'Сан-Марына',
'UserCountry_country_sn' => 'Сенегал',
'UserCountry_country_so' => 'Самалі',
'UserCountry_country_sr' => 'Сурынам',
- 'UserCountry_country_st' => 'Сан-Томе і Принсипи',
+ 'UserCountry_country_st' => 'Сан-Томе і Прінсіпі',
'UserCountry_country_su' => 'СССР (былы)',
'UserCountry_country_sv' => 'Сальвадор',
'UserCountry_country_sy' => 'Сірыйская Арабская Рэспубліка',
'UserCountry_country_sz' => 'Свазіленд',
- 'UserCountry_country_tc' => 'Выспы Турцыі і Каикоса',
- 'UserCountry_country_td' => 'Чад',
+ 'UserCountry_country_ta' => 'Трістан-так-Кунья',
+ 'UserCountry_country_tc' => 'Выспы Турцыі і Каікоса',
+ 'UserCountry_country_td' => 'Дзяцей',
'UserCountry_country_tf' => 'Паўднёвыя тэрыторыі Францыі',
'UserCountry_country_tg' => 'Таго',
'UserCountry_country_th' => 'Тайланд',
'UserCountry_country_tj' => 'Таджыкістан',
'UserCountry_country_tk' => 'Токело',
+ 'UserCountry_country_tl' => 'Усходні Тымор',
'UserCountry_country_tm' => 'Туркменістан',
'UserCountry_country_tn' => 'Туніс',
'UserCountry_country_to' => 'Тонга',
@@ -362,26 +540,24 @@ $translations = array(
'UserCountry_country_ua' => 'Украіна',
'UserCountry_country_ug' => 'Уганда',
'UserCountry_country_uk' => 'Злучанае Каралеўства',
- 'UserCountry_country_gb' => 'Вялікабрытанія',
- 'UserCountry_country_um' => 'Выспы ЗША',
+ 'UserCountry_country_um' => 'Вонкавыя малыя выспы ЗША',
'UserCountry_country_us' => 'ЗША',
'UserCountry_country_uy' => 'Уругвай',
'UserCountry_country_uz' => 'Узбекістан',
'UserCountry_country_va' => 'Ватыкан',
- 'UserCountry_country_vc' => 'Сэнт-Вінцэнт і Гренадины',
+ 'UserCountry_country_vc' => 'Сэнт-Вінцэнт і Гренадіны',
'UserCountry_country_ve' => 'Венесуэла',
'UserCountry_country_vg' => 'Віргінскія выспы Брытаніі',
'UserCountry_country_vi' => 'Віргінскія выспы ЗША',
- 'UserCountry_country_vn' => 'Ветнам',
'UserCountry_country_vu' => 'Вануату',
- 'UserCountry_country_wf' => 'Уоллис і Футуна',
+ 'UserCountry_country_wf' => 'Уолліс і Футуна',
'UserCountry_country_ws' => 'Самоа',
'UserCountry_country_ye' => 'Емен',
'UserCountry_country_yt' => 'Майотта',
'UserCountry_country_yu' => 'Югаславія',
'UserCountry_country_za' => 'Паўднёва-Афрыканская Рэспубліка',
'UserCountry_country_zm' => 'Замбія',
- 'UserCountry_country_zr' => 'Заир',
+ 'UserCountry_country_zr' => 'Заір',
'UserCountry_country_zw' => 'Зімбабвэ',
'UserCountry_continent_eur' => 'Еўропа',
'UserCountry_continent_afr' => 'Афрыка',
@@ -394,10 +570,10 @@ $translations = array(
'VisitsSummary_NbActions' => '%s дзеянняў (праглядаў старонак)',
'VisitsSummary_TotalTime' => '%s агульны час наведванняў',
'VisitsSummary_MaxNbActions' => '%s макс. дзеянняў за адно наведванне',
- 'VisitsSummary_NbBounced' => '%s наведвальнікаў сыйшло пасля наведвання адной старонкі',
- 'VisitsSummary_Evolution' => 'Эвалюцыя за 30 апошніх дзён',
+ 'VisitsSummary_NbVisitsBounced' => '%s наведвальнікаў сышло пасля наведвання адной старонкі',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Эвалюцыя за 30 апошніх дзён',
'VisitsSummary_Report' => 'Справаздача',
- 'VisitsSummary_GenerateTime' => 'Старонка згенераваная за %s секунд',
+ 'VisitsSummary_GenerateTime' => 'Старонка згенеравана за %s секунд',
'VisitsSummary_GenerateQueries' => '%s запытаў выканана',
'VisitsSummary_WidgetLastVisits' => 'Графік апошніх наведванняў',
'VisitsSummary_WidgetVisits' => 'Агляд наведванняў',
@@ -405,48 +581,56 @@ $translations = array(
'VisitsSummary_WidgetOverviewGraph' => 'Агляд па ўсіх графіках',
'VisitsSummary_SubmenuOverview' => 'Агляд',
'VisitFrequency_Evolution' => 'Эвалюцыя за перыяд',
+ 'VisitFrequency_ColumnReturningVisits' => 'Паўторныя наведванні',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Дзеянняў за паўторнае наведванне',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Макс. дзеянняў за паўторнае наведванне',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Агульны час карыстачоў, паўторна наведалых сайт (секунд)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Паўторных наведванняў на адну старонку',
'VisitFrequency_ReturnVisits' => '%s паўторных наведванняў',
- 'VisitFrequency_ReturnActions' => '%s дзеянняў у паўторныя наведванні',
+ 'VisitFrequency_ReturnActions' => '%s дзеянняў за паўторныя наведванні',
'VisitFrequency_ReturnMaxActions' => '%s максімальных дзеянняў на паўторнае наведванне',
'VisitFrequency_ReturnTotalTime' => '%s агульнага часу на паўторных наведваннях',
- 'VisitFrequency_ReturnBounces' => '%s раз карыстачы вышлі пасля прагляду адной старонкі',
- 'VisitFrequency_WidgetOverview' => 'Агляд частаты наведванняў',
+ 'VisitFrequency_ReturnBounceRate' => '%s раз карыстачы выйшлі пасля прагляду адной старонкі',
+ 'VisitFrequency_WidgetOverview' => 'Агляд чашчыні наведванняў',
'VisitFrequency_WidgetGraphReturning' => 'Графік паўторных наведванняў',
- 'VisitFrequency_SubmenuFrequency' => 'Частата',
+ 'VisitFrequency_SubmenuFrequency' => 'Чашчыня',
'VisitTime_LocalTime' => 'Наведванняў па мясцовым часе',
'VisitTime_ServerTime' => 'Наведванняў па серверным часе',
+ 'VisitTime_ColumnServerTime' => 'Серверны час',
+ 'VisitTime_ColumnLocalTime' => 'Мясцовы час',
'VisitTime_WidgetLocalTime' => 'Наведванняў па мясцовым часе',
'VisitTime_WidgetServerTime' => 'Наведванняў па серверным часе',
'VisitTime_SubmenuTimes' => 'Па часе',
'VisitTime_NHour' => '%s ч.',
'VisitorInterest_VisitsPerDuration' => 'Наведванняў па даўжыні візіту',
'VisitorInterest_VisitsPerNbOfPages' => 'Наведванняў па колькасці старонак',
+ 'VisitorInterest_ColumnVisitDuration' => 'Даўжыня наведванняў',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Старонак за наведванне',
'VisitorInterest_WidgetLengths' => 'Даўжыня наведванняў',
- 'VisitorInterest_WidgetPages' => 'Старниц за наведванне',
- 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Частата наведванняў',
+ 'VisitorInterest_WidgetPages' => 'Старніц за наведванне',
+ 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Чашчыня наведванняў',
'VisitorInterest_PlusXMin' => '%s мін.',
- 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s мін.',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%2s мін.',
'VisitorInterest_OnePage' => '1 старонка',
'VisitorInterest_NPages' => '%s старонак',
'VisitorInterest_BetweenXYSeconds' => '%1s-%2s сек.',
- 'Provider_WidgetProviders' => 'Правайдэры',
- 'Provider_SubmenuLocationsProvider' => 'Лакацыі і правайдэры',
- 'Login_PluginDescription' => 'Экран уваходу карыстачоў у сістэму.',
- 'Login_LoginPasswordNotCorrect' => 'Лагін або пароль няслушныя',
+ 'Login_LoginPasswordNotCorrect' => 'Лагін ці пароль няслушныя',
'Login_Login' => 'Лагін',
'Login_Password' => 'Пароль',
- 'Login_LoginOrEmail' => 'Лагін або E-mail',
+ 'Login_LoginOrEmail' => 'Лагін ці E-mail',
'Login_LogIn' => 'Увайсці',
'Login_Logout' => 'Выйсці',
'Login_LostYourPassword' => 'Страцілі пароль?',
'Login_RemindPassword' => 'Успомніць пароль',
- 'Login_PasswordReminder' => 'Калі ласка, увядзіце свой лагін або e-mail. Новы пароль прийдет вам па e-mail.',
- 'Login_InvalidUsernameEmail' => 'Няслушнае імя карыстача і/або e-mail',
+ 'Login_PasswordReminder' => 'Калі ласка, увядзіце свой лагін ці e-mail. Новы пароль прійдет вам па e-mail.',
+ 'Login_InvalidUsernameEmail' => 'Няслушнае імя карыстача і/ці e-mail',
'Login_MailTopicPasswordRecovery' => 'Аднаўленне пароля',
- 'Login_MailPasswordRecoveryBody' => 'Дабрыдзень, %1s, \n\n Ваш новы пароль: %2s \n\n Зараз вы можаце ўвайсці: %3s',
'Login_PasswordSent' => 'Пароль ужо высланы, праверце сваю пошту.',
- 'Login_ContactAdmin' => 'Магчымы чыннік: функцыя mail() адключаная. <br />Калі ласка, звяжыцеся з адміністратарам.',
+ 'Login_ContactAdmin' => 'Магчымы чыннік: функцыя mail() адключана. <br />Калі ласка, звяжыцеся з адміністратарам.',
+ 'UsersManager_UsersManagement' => 'Кіраванне карыстачамі',
+ 'UsersManager_UsersManagementMainDescription' => 'Стварэнне новых карыстачоў ці рэдагаванне існых. Таксама Вы можаце задаць правы доступу для карыстача.',
'UsersManager_ManageAccess' => 'Кіраванне правамі доступу',
+ 'UsersManager_MainDescription' => 'Пакажыце, якія карыстачы маюць доступ да Piwik на Вашым сайце. Таксама Вы можаце задаць правы доступу на ўсе сайты.',
'UsersManager_Sites' => 'Сайты',
'UsersManager_AllWebsites' => 'Усе сайты',
'UsersManager_ApplyToAllWebsites' => 'Ужыць да ўсіх сайтаў',
@@ -458,82 +642,110 @@ $translations = array(
'UsersManager_Login' => 'Лагін',
'UsersManager_Password' => 'Пароль',
'UsersManager_Email' => 'Email',
- 'UsersManager_Alias' => 'Алиас',
- 'UsersManager_Token' => 'token_auth-ключ',
+ 'UsersManager_Alias' => 'Аліас',
'UsersManager_Edit' => 'Рэдагаваць',
'UsersManager_AddUser' => 'Дадаць новага карыстача',
'UsersManager_MenuUsers' => 'Карыстачы',
'UsersManager_DeleteConfirm_js' => 'Вы сапраўды жадаеце выдаліць карыстача %s?',
'UsersManager_ExceptionLoginExists' => 'Лагін \'%s\' ужо існуе.',
'UsersManager_ExceptionEmailExists' => 'Карыстач з Email \'%s\' ужо існуе.',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'Лагін павінен быць даўжынёй ад %s да %s знакаў, а таксама ўтрымоўваць толькі літары, лічбы ці знакі \'_\', \'-\', \'.\'',
'UsersManager_ExceptionInvalidPassword' => 'Даўжыня пароля павінна быць ад 6 да 26 знакаў.',
'UsersManager_ExceptionInvalidEmail' => 'Email няправільнага фармату',
'UsersManager_ExceptionDeleteDoesNotExist' => 'Карыстача \'%s\' не існуе, таму ён не можа быць выдалены.',
'UsersManager_ExceptionAdminAnonymous' => 'Вы не можаце даваць правы \'Адмін\' ананімнаму карыстачу.',
- 'UsersManager_ExceptionEditAnonymous' => 'Ананімны карыстач не можа быць выдалены. Ён неабходны Piwik для ідэнтыфікацыі карыстачоў, якія не ўвайшлі ў сістэму. Дапушчальны, вы можаце зрабіць статыстыку публічнай, падаючы права \'Прагляд\' ананімнаму карыстачу.',
+ 'UsersManager_ExceptionEditAnonymous' => 'Ананімны карыстач не можа быць выдалены. Ён неабходзен Piwik для ідэнтыфікацыі карыстачоў, якія не ўвайшлі ў сістэму. Дапушчальны, вы можаце зрабіць статыстыку публічнай, падаючы права \'Прагляд\' ананімнаму карыстачу.',
'UsersManager_ExceptionUserDoesNotExist' => 'Карыстач \'%s\' не існуе.',
'UsersManager_ExceptionAccessValues' => 'Параметр доступу можа мець толькі адно з наступных значэнняў: [ %s ]',
'SitesManager_Sites' => 'Сайты',
- 'SitesManager_JsCode' => 'Код JavaScript',
- 'SitesManager_JsCodeHelp' => 'Код JavaScript, які неабходна ўставіць ва ўсе вашы старонкі',
- 'SitesManager_ShowJsCode' => 'Паказаць код',
- 'SitesManager_NoWebsites' => 'Вы не маеце ні аднаго сайта на ўліку.',
+ 'SitesManager_WebsitesManagement' => 'Кіраванне сайтамі',
+ 'SitesManager_MainDescription' => 'Для вядзення статыстыкі патрабуецца дадаць сайты! Дадавайце, абнаўляйце, выдаляйце інфармацыю пра сайты, а таксама прагледзіце Java-код для ўстаўкі на Вашы старонкі.',
+ 'SitesManager_JsTrackingTag' => 'Код JavaScript',
+ 'SitesManager_JsTrackingTagHelp' => 'Гэта код JavaScript, які неабходна ўставіць ва ўсе вашы старонкі',
+ 'SitesManager_ShowTrackingTag' => 'Паказаць код',
+ 'SitesManager_NoWebsites' => 'Вы не маеце ніводнага сайта на ўліку.',
'SitesManager_AddSite' => 'Дадаць новы сайт',
'SitesManager_Id' => 'ID',
- 'SitesManager_Name' => 'Найменне',
+ 'SitesManager_Name' => 'Назва',
'SitesManager_Urls' => 'URL-ы',
'SitesManager_MenuSites' => 'Сайты',
'SitesManager_DeleteConfirm_js' => 'Вы сапраўды жадаеце выдаліць гэты сайт %s?',
'SitesManager_ExceptionDeleteSite' => 'Немагчыма выдаліць, бо гэта адзіны сайт у вашым спісе. Дадайце яшчэ які-небудзь сайт для выдалення дадзенага.',
'SitesManager_ExceptionNoUrl' => 'Вы павінны паказаць хоць бы адзін URL для гэтага сайта.',
- 'SitesManager_ExceptionEmptyName' => 'Назоў сайта не можа быць пустое.',
+ 'SitesManager_ExceptionEmptyName' => 'Назва сайта не можа быць пустое.',
'SitesManager_ExceptionInvalidUrl' => 'URL \'%s\' не дакладны.',
'Installation_Installation' => 'Усталёўка',
'Installation_InstallationStatus' => 'Статут усталёўкі',
- 'Installation_PercentDone' => '%s %% Завершанае',
- 'Installation_NoConfigFound' => 'Канфігурацыйны файл Piwik не можа быць знойдзены, аднак вы спрабуеце зайсці ў сістэму.<br /><b>&nbsp;&nbsp;&raquo; Вы можаце <a href=\'index.php\'>усталяваць Piwik зараз</a></b><br /><small>. Калі Piwik ужо быў усталяваны і вы маеце дадзеныя ў БД, вы ўсё яшчэ можаце выкарыстаць іх.</small>',
+ 'Installation_PercentDone' => '%s %% Завершана',
+ 'Installation_NoConfigFound' => 'Канфігурацыйны файл Piwik не можа быць знойдзены, аднак вы спрабуеце зайсці ў сістэму.<br /><b>&nbsp;&nbsp;&raquo; Вы можаце <a href=\'index.php\'>усталяваць Piwik цяпер</a></b><br /><small>. Калі Piwik ужо быў усталяваны і вы маеце дадзеныя ў БД, вы можаце выкарыстоўваць іх.</small>',
'Installation_MysqlSetup' => 'Налады БД Mysql',
- 'Installation_MysqlErrorConnect' => 'Памылка злучэння з базай дадзеных.',
+ 'Installation_MysqlErrorConnect' => 'Памылка злучэння з базай дадзеных MySQL.',
'Installation_JsTag' => 'JavaScript тэг',
- 'Installation_JsTagHelp' => '<p>Для падліку наведвальнікаў вы павінны ўставіць дадзены JavaScript-код на ўсе старонкі сайта.</p><p>Код не павінен размяшчацца ў PHP, Piwik будзе толькі працаваць на ўсіх тыпах старонак (уключаючы HTML, ASP, Perl або любая іншая мова).</p><p>Вось сам код, які неабходна ўставіць(скапіюйце і ўстаўце на ўсе свае старонкі):</p>',
+ 'Installation_JsTagHelp' => '<p>Для падліку наведвальнікаў вы павінны ўставіць дадзены JavaScript-код на ўсе старонкі сайта.</p><p>Код не павінен месцавацца ў PHP, Piwik будзе працаваць на ўсіх тыпах старонак (уключаючы HTML, ASP, Perl ці любая іншая мова).</p><p>Вось сам код, які неабходна ўставіць(скапіюйце і ўстаўце на ўсе свае старонкі):</p>',
'Installation_Congratulations' => 'Віншуем',
- 'Installation_CongratulationsHelp' => '<p>Віншуем! Усталёўка Piwik скончаная.</p><p>Упэўніцеся, што JavaScript-код размешчаны на ўсіх старонках, і, чакайце першых наведвальнікаў!',
- 'Installation_GoToPiwik' => 'Перайсці да Piwik',
+ 'Installation_CongratulationsHelp' => '<p>Віншуем! Усталёўка Piwik скончана.</p><p>Пераканаецеся, што JavaScript-код змесцаваны на ўсіх старонках, і, чакайце першых наведвальнікаў!',
+ 'Installation_ContinueToPiwik' => 'Перайсці да Piwik',
'Installation_SetupWebsite' => 'Дадаць сайт',
'Installation_SetupWebsiteError' => 'Паўстала памылка пры даданні сайта',
'Installation_GeneralSetup' => 'Агульныя налады',
- 'Installation_GeneralSetupSuccess' => 'Агульнае канфігураванне паспяхова завершанае',
+ 'Installation_GeneralSetupSuccess' => 'Агульнае канфігураванне паспяхова завершана',
+ 'Installation_SuperUserLogin' => 'лагін суперпользователя',
+ 'Installation_Password' => 'пароль',
+ 'Installation_PasswordRepeat' => 'пароль (яшчэ раз)',
+ 'Installation_Email' => 'email',
+ 'Installation_SecurityNewsletter' => 'паведамляць мне пра значныя абнаўленні Piwik і памылках бяспекі па email',
+ 'Installation_CommunityNewsletter' => 'паведамляць мне пра абнаўленні супольнасці (новыя ўбудовы, новыя функцыі і г.д.) па email',
+ 'Installation_PasswordDoNotMatch' => 'пароль не супадае',
+ 'Installation_SubmitGo' => 'Далей',
+ 'Installation_Requirements' => 'Патрабаванні Piwik',
+ 'Installation_Optional' => 'Апцыянальна',
+ 'Installation_Legend' => 'Легенда',
'Installation_SystemCheck' => 'Праверка сістэмы',
- 'Installation_SystemCheckPhp' => 'PHP версія',
- 'Installation_SystemCheckPdo' => 'Модуль Pdo',
- 'Installation_SystemCheckPdoMysql' => 'Модуль Pdo_Mysql',
- 'Installation_SystemCheckPdoError' => 'Вам неабходна актывізаваць модулі PDO і PDO_MYSQL у наладах php.ini.',
- 'Installation_SystemCheckPdoHelp' => 'На Windows-серверы вам неабходна дадаць наступныя лініі ў php.ini %s <br /><br />на Linux-серверы вы павінны адкампіляваць PHP са наступнымі значэннямі %s У php.ini дадайце наступнае %s<br /><br />Больш інфармацыі вы знойдзеце на <a style="color:red" href="http://php.net/pdo">рэсурсе PHP.net</a>.',
+ 'Installation_SystemCheckPhp' => 'Версія PHP',
+ 'Installation_SystemCheckExtensions' => 'Неабходныя модулі',
+ 'Installation_SystemCheckPdoHelp' => 'Вам неабходна актываваць модуль PDO у файле php.ini.',
+ 'Installation_SystemCheckPdoMysqlHelp' => 'Вам неабходна актываваць модуль PDO_MYSQL у файле php.ini.',
+ 'Installation_SystemCheckSplHelp' => 'Вам неабходна сканфігураваць ііл перасабраць PHP з уключанай стандартнай бібліятэкай (значэнне па змаўчанні).',
+ 'Installation_SystemCheckZlibHelp' => 'Вам неабходна сканфігураваць PHP на падтрымку zlib, ці перакампіляваць з параметрам --with-zlib.',
'Installation_SystemCheckWriteDirs' => 'Тэчкі з правамі запісу',
- 'Installation_SystemCheckWriteDirsHelp' => 'Для выпраўлення гэтай памылкі ў АС Linux, паспрабуйце ўвесці следущие каманды',
+ 'Installation_SystemCheckWriteDirsHelp' => 'Для выпраўлення гэтай памылкі ў АС Linux, паспрабуйце ўвесці следущіе каманды',
'Installation_SystemCheckMemoryLimit' => 'Абмежаванне памяці',
- 'Installation_SystemCheckMemoryLimitHelp' => 'На сайце з вялікім абёмам трафіку, працэс архівавання можа заняць больш памяці, чым дазволена.<br />Праверце опцыю memory_limit у вашым php.ini, калі неабходна.',
'Installation_SystemCheckGD' => 'GD &gt; 2.x (графіка)',
- 'Installation_SystemCheckGDHelp' => 'Адлюстраванне тонкага графіка не будзе працаваць.',
- 'Installation_SystemCheckTimeLimit' => 'set_time_limit() дазволены',
- 'Installation_SystemCheckTimeLimitHelp' => 'На сайце з вялікім абёмам трафіку, працэс выканання архівавання можа заняць больш часу, чым дазволена.<br />Праверце опцыю max_execution_time у вашым php.ini, калі неабходна.',
- 'Installation_SystemCheckMail' => 'mail() дазволена',
- 'Installation_SystemCheckError' => 'Паўстала памылка - павінна быць выпраўленая перад працягам',
- 'Installation_SystemCheckWarning' => 'Piwik будзе працаваць нармалёва, але некаторыя функцыі не будуць даступныя',
+ 'Installation_SystemCheckGDHelp' => 'Адлюстраванне тонкіх (маленькіх) графікаў не будзе працаваць.',
+ 'Installation_SystemCheckFunctions' => 'Патрабаваныя функцыі',
+ 'Installation_SystemCheckMailHelp' => 'Функцыі водгукаў о Piwik і аднаўленне пароляў не будуць працаваць без mail().',
+ 'Installation_SystemCheckError' => 'Паўстала памылка - павінна быць выпраўлена перад працягам',
+ 'Installation_SystemCheckWarning' => 'Piwik будзе працаваць звычайна, але некаторыя функцыі не будуць даступныя',
'Installation_Tables' => 'Стварэнне табліц',
- 'Installation_TablesWarning' => 'Некаторыя <span id="linkToggle">табліцы</span> ужо ўсталяваныя ў БД',
- 'Installation_TablesFound' => 'Наступныя табліцы знойдзеныя ў БД',
- 'Installation_TablesWarningHelp' => 'Вылучыце адно з двух: выкарыстаць наяўных табліц БД, або чыстую ўсталёўку, якая выдаліць усе наяўныя дадзеныя ў базе дадзеных.',
- 'Installation_TablesReuse' => 'Выкарыстаць наяўныя табліцы',
+ 'Installation_TablesWithSameNamesFound' => 'Некаторыя %s табліцы ў Вашай базе дадзеных %s маюць супадальныя назвы з табліцамі, якія Piwik спрабуе стварыць.',
+ 'Installation_TablesFound' => 'Наступныя табліцы знойдзены ў БД',
+ 'Installation_TablesWarningHelp' => 'Абярыце адно з дзвюх: выкарыстоўваць існых табліц БД, ці чыстую ўсталёўку, якая выдаліць усе існыя дадзеныя ў базе дадзеных.',
+ 'Installation_TablesReuse' => 'Выкарыстоўваць існыя табліцы',
'Installation_TablesDelete' => 'Выдаліць знойдзеныя табліцы',
- 'Installation_TablesDeletedSuccess' => 'Наяўныя табліцы Piwik паспяхова выдаленыя',
- 'Installation_TablesCreatedSuccess' => 'Табліцы паспяхова створаныя!',
- 'Installation_TablesDeleteConfirm' => 'Вы сапраўды жадаеце выдаліць табліцы Piwik з БД?',
+ 'Installation_TablesDeletedSuccess' => 'Існыя табліцы Piwik паспяхова выдалены',
+ 'Installation_TablesCreatedSuccess' => 'Табліцы паспяхова створаны!',
+ 'Installation_DatabaseCreatedSuccess' => 'База дадзеных %s створана паспяхова!',
+ 'Installation_GoBackAndDefinePrefix' => 'Вярніцеся назад і ўвядзіце прэфікс для табліц Piwik',
+ 'Installation_ConfirmDeleteExistingTables' => 'Вы сапраўды жадаеце выдаліць табліцы: %s з базы дадзеных? УВАГА: ВЫДАЛЕНЫЯ ДАДЗЕНЫЯ НЕМАГЧЫМА АДНАВІЦЬ!',
'Installation_Welcome' => 'Сардэчна запрашаем!',
- 'Installation_WelcomeHelp' => '<p>Piwik - гэтае адчыненае праграмнае забеспячэнне, якое дазваляе вам весткі статыстычны ўлік наведванняў вашага сайта і праводзіць аналітычныя разлікі для атрымання інфармацыі неабходнай вам інфармацыі аб наведвальніках. Гэты працэс складаецца з 8 крокаў і займае каля 5 хвілін часу.</p>',
+ 'Installation_WelcomeHelp' => '<p>Piwik - гэта адкрытае праграмнае забеспячэнне, якое дазваляе вам весткі статыстычны ўлік наведванняў вашага сайта і праводзіць аналітычныя разлікі для атрымання інфармацыі неабходным вам інфармацыі пра наведвальнікаў. Гэты працэс складаецца з %s простых крокаў і займае каля 5 мінуць чакай.</p>',
+ 'Installation_ErrorInvalidState' => 'Памылка: Падобна, Вы спрабуеце прапусціць крок усталявальнай праграмы, ці cookie забаронены ў брауезере, ці файл канфігурацыі Piwik ужо існуе. %sУбедітесь, што cookies дазволены%s і вярніцеся назад %s да першага кроку ўсталёўкі %s.',
+ 'Provider_WidgetProviders' => 'Правайдары',
+ 'Provider_ColumnProvider' => 'Правайдар',
+ 'Provider_SubmenuLocationsProvider' => 'Лакацыі і правайдары',
+ 'Goals_ColumnConversions' => 'Наведванні невядомых ці новых карыстачоў',
+ 'Goals_ColumnConversionRate' => 'Дзель новых карыстачоў',
+ 'Goals_ColumnRevenue' => 'Прыбытак',
+ 'DBStats_DatabaseUsage' => 'Выкарыстанне БД',
+ 'DBStats_MainDescription' => 'Piwik захоўвае ўсю Вашу web статыстыку ў базе MySQL. Выкарыстанне Piwik табліц на дадзены момант %s.',
+ 'DBStats_Table' => 'Табліца',
+ 'DBStats_RowNumber' => 'Колькасць запісаў',
+ 'DBStats_DataSize' => 'Памер дадзеных',
+ 'DBStats_IndexSize' => 'Памер індэксу',
+ 'DBStats_TotalSize' => 'Агульны памер',
'TranslationsAdmin_MenuTranslations' => 'Пераклады',
'TranslationsAdmin_MenuLanguages' => 'Мовы',
- 'TranslationsAdmin_Plugin' => 'Падлучальны модуль',
+ 'TranslationsAdmin_Plugin' => 'Убудова',
'TranslationsAdmin_Definition' => 'Апісанне',
'TranslationsAdmin_DefaultString' => 'Радок па змаўчанні (ангельскі)',
'TranslationsAdmin_TranslationString' => 'Перакладзены радок (бягучая мова: %s )',
@@ -544,368 +756,4 @@ $translations = array(
'TranslationsAdmin_LanguageCode' => 'Код мовы',
'TranslationsAdmin_Export' => 'Экспарт моўнага файла',
'TranslationsAdmin_Import' => 'Імпарт моўнага файла',
- 'General_HelloUser' => 'Прывітанне, %s!',
- 'General_OpenSourceWebAnalytics' => '',
- 'General_YourDashboard' => 'Інфармацыйная панэль',
- 'General_API' => 'API функцыі',
- 'General_Widgets' => 'Інформеры',
- 'General_Settings' => 'Налады',
- 'General_GiveUsYourFeedback' => 'Зваротная сувязь',
- 'General_Export' => 'Экспарт',
- 'General_Visitors' => 'Наведвальнікі',
- 'General_ColumnActionsPerVisit' => 'Дзеянняў у візіт',
- 'General_ColumnAvgTimeOnSite' => 'Ср. час на сайце',
- 'General_ColumnBounceRate' => '',
- 'General_ColumnPageviews' => 'Прагляды старонак',
- 'General_ColumnUniquePageviews' => 'Унікальныя прагляды старонак',
- 'General_Website' => 'Сайт',
- 'General_NoDataForTagCloud' => 'Няма дадзеных па гэтых тэгах',
- 'General_DisplayNormalTable' => 'Паказаць нармалёвую табліцу',
- 'General_DisplayMoreData' => 'Паказаць больш дадзеных',
- 'General_PiwikIsACollaborativeProject' => '%s Piwik %s - калектыўны праект і знаходзіцца ў стадыі Бэта тэставання. Калі Вы жадаеце дапамагчы праекту, калі ласка, %s напішыце нам! %s',
- 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Зараз Вы выкарыстаеце Demo версію прадукта %s; %sскачайте%s поўную версію!%s',
- 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s даступны для запампоўкі. %s Калі ласка, абновіцеся!%s (гл. %sизменения%s).',
- 'General_BackToPiwik' => 'Вярнуцца да Piwik',
- 'Actions_Actions' => 'Дзеянні',
- 'CorePluginsAdmin_PluginsManagement' => 'Кіраванне модулямі',
- 'CorePluginsAdmin_MainDescription' => 'Модулі пашыраюць функцыянальнасць Piwik. Пасля ўсталёўкі модуля Вы можаце актываваць або дэактываваць яго.',
- 'CorePluginsAdmin_Plugin' => 'Модуль',
- 'CorePluginsAdmin_Version' => 'Версія',
- 'CorePluginsAdmin_Description' => 'Нататка',
- 'CorePluginsAdmin_Status' => 'Статут',
- 'CorePluginsAdmin_Action' => 'Дзеянне',
- 'CorePluginsAdmin_PluginHomepage' => 'Хата. старонка модуля',
- 'CorePluginsAdmin_Active' => 'Актыўна',
- 'CorePluginsAdmin_Inactive' => 'Неактыўна',
- 'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; - абнаўленне',
- 'CoreUpdater_DatabaseUpgradeRequired' => 'Патрабуецца абнаўленне базы дадзеных',
- 'CoreUpdater_YourDatabaseIsOutOfDate' => 'Тэрмін дзеяння Вашай Piwik базы мінуў, Вам трэба яе абнавіць для працягу. ',
- 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik база будзе абноўленая з версіі %s да версіі %s.',
- 'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Наступныя модулі будуць абноўленыя: %s.',
- 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Абнаўленне базы дадзеных можа заняць некаторы час, таму будзьце цярплівыя.',
- 'CoreUpdater_UpgradePiwik' => 'Абнавіць Piwik',
- 'CoreUpdater_HelpMessageContent' => 'Праверце %s Piwik FAQ %s, у якім абмяркоўваецца большасць вядомых памылак падчас абнаўлення. %s Звернецеся да сістэмнага адміністратара - ён можа дапамагчы Вам з рашэннем праблемы на серверы або з наладамі MySQL.',
- 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Крытычная памылка падчас абнаўлення:',
- 'CoreUpdater_HelpMessageIntroductionWhenError' => '',
- 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Абнаўленне завершанае паспяхова, аднак у працэсе паўстала некалькі папярэджанняў. Калі ласка, прачытайце нататкі ніжэй. Для далейшай дапамогі:',
- 'CoreUpdater_UpgradeComplete' => 'Абнаўленне завершанае!',
- 'CoreUpdater_WarningMessages' => 'Папярэджанні:',
- 'CoreUpdater_ErrorDuringPluginsUpdates' => 'Памылка падчас абнаўлення модуля:',
- 'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Наступныя модулі аўтаматычна дэактываваныя: %s',
- 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik паспяхова абноўлены!',
- 'CoreUpdater_ContinueToPiwik' => 'Працягнуць да Piwik',
- 'CoreUpdater_UpdateAutomatically' => 'Абнавіць аўтаматычна',
- 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Даступная новая версія Piwik',
- 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Вы можаце абнавіцца да версіі %s аўтаматычна або запампаваць усталявальны пакет і ўручную ўсталяваць яго:',
- 'CoreUpdater_DownloadX' => 'Запампаваць %s',
- 'CoreUpdater_UpdateHasBeenCancelled' => 'Абнаўленне скасавана.',
- 'CoreUpdater_VerifyingUnpackedFiles' => 'Праверка неархивированных файлаў',
- 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Стварэнне копіі канфігурацыйнага файла ў %s',
- 'CoreUpdater_InstallingTheLatestVersion' => 'Усталёўка апошняй версіі',
- 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik абноўлены паспяхова!',
- 'DBStats_DatabaseUsage' => 'Выкарыстанне БД',
- 'DBStats_MainDescription' => 'Piwik захоўвае ўсю Вашу web статыстыку ў базе MySQL. Выкарыстанне Piwik табліц на дадзены момант %s.',
- 'DBStats_Table' => 'Табліца',
- 'DBStats_RowNumber' => 'колькасць запісаў',
- 'DBStats_DataSize' => 'Памер дадзеных',
- 'DBStats_IndexSize' => 'Памер індэксу',
- 'DBStats_TotalSize' => 'Агульны памер',
- 'Dashboard_Dashboard' => 'Информпанель',
- 'GeoIP_Country' => 'Краіна',
- 'GeoIP_Continent' => 'Кантынент',
- 'GeoIP_DistinctCountries' => '',
- 'GeoIP_SubmenuLocations' => 'Лакацыі',
- 'GeoIP_WidgetContinents' => 'Континеты наведвальнікаў',
- 'GeoIP_WidgetCountries' => 'Краіны наведвальнікаў',
- 'GeoIP_country_' => 'Дадзеныя недаступныя',
- 'GeoIP_country_ac' => '',
- 'GeoIP_country_ad' => '',
- 'GeoIP_country_ae' => '',
- 'GeoIP_country_af' => '',
- 'GeoIP_country_ag' => '',
- 'GeoIP_country_ai' => '',
- 'GeoIP_country_al' => '',
- 'GeoIP_country_am' => '',
- 'GeoIP_country_an' => '',
- 'GeoIP_country_ao' => '',
- 'GeoIP_country_aq' => '',
- 'GeoIP_country_ar' => '',
- 'GeoIP_country_as' => '',
- 'GeoIP_country_at' => '',
- 'GeoIP_country_au' => '',
- 'GeoIP_country_aw' => '',
- 'GeoIP_country_az' => '',
- 'GeoIP_country_ba' => '',
- 'GeoIP_country_bb' => '',
- 'GeoIP_country_bd' => '',
- 'GeoIP_country_be' => '',
- 'GeoIP_country_bf' => '',
- 'GeoIP_country_bg' => '',
- 'GeoIP_country_bh' => '',
- 'GeoIP_country_bi' => '',
- 'GeoIP_country_bj' => '',
- 'GeoIP_country_bm' => '',
- 'GeoIP_country_bn' => '',
- 'GeoIP_country_bo' => '',
- 'GeoIP_country_br' => '',
- 'GeoIP_country_bs' => '',
- 'GeoIP_country_bt' => '',
- 'GeoIP_country_bv' => '',
- 'GeoIP_country_bw' => '',
- 'GeoIP_country_by' => '',
- 'GeoIP_country_bz' => '',
- 'GeoIP_country_ca' => '',
- 'GeoIP_country_cc' => '',
- 'GeoIP_country_cd' => '',
- 'GeoIP_country_cf' => '',
- 'GeoIP_country_cg' => '',
- 'GeoIP_country_ch' => '',
- 'GeoIP_country_ci' => '',
- 'GeoIP_country_ck' => '',
- 'GeoIP_country_cl' => '',
- 'GeoIP_country_cm' => '',
- 'GeoIP_country_cn' => '',
- 'GeoIP_country_co' => '',
- 'GeoIP_country_cr' => '',
- 'GeoIP_country_cs' => '',
- 'GeoIP_country_cu' => '',
- 'GeoIP_country_cv' => '',
- 'GeoIP_country_cx' => '',
- 'GeoIP_country_cy' => '',
- 'GeoIP_country_cz' => '',
- 'GeoIP_country_de' => '',
- 'GeoIP_country_dj' => '',
- 'GeoIP_country_dk' => '',
- 'GeoIP_country_dm' => '',
- 'GeoIP_country_do' => '',
- 'GeoIP_country_dz' => '',
- 'GeoIP_country_ec' => '',
- 'GeoIP_country_ee' => '',
- 'GeoIP_country_eg' => '',
- 'GeoIP_country_eh' => '',
- 'GeoIP_country_er' => '',
- 'GeoIP_country_es' => '',
- 'GeoIP_country_et' => '',
- 'GeoIP_country_eu' => '',
- 'GeoIP_country_fi' => '',
- 'GeoIP_country_fj' => '',
- 'GeoIP_country_fk' => '',
- 'GeoIP_country_fm' => '',
- 'GeoIP_country_fo' => '',
- 'GeoIP_country_fr' => '',
- 'GeoIP_country_ga' => '',
- 'GeoIP_country_gd' => '',
- 'GeoIP_country_ge' => '',
- 'GeoIP_country_gf' => '',
- 'GeoIP_country_gg' => '',
- 'GeoIP_country_gh' => '',
- 'GeoIP_country_gi' => '',
- 'GeoIP_country_gl' => '',
- 'GeoIP_country_gm' => '',
- 'GeoIP_country_gn' => '',
- 'GeoIP_country_gp' => '',
- 'GeoIP_country_gq' => '',
- 'GeoIP_country_gr' => '',
- 'GeoIP_country_gs' => '',
- 'GeoIP_country_gt' => '',
- 'GeoIP_country_gu' => '',
- 'GeoIP_country_gw' => '',
- 'GeoIP_country_gy' => '',
- 'GeoIP_country_hk' => '',
- 'GeoIP_country_hm' => '',
- 'GeoIP_country_hn' => '',
- 'GeoIP_country_hr' => '',
- 'GeoIP_country_ht' => '',
- 'GeoIP_country_hu' => '',
- 'GeoIP_country_id' => '',
- 'GeoIP_country_ie' => '',
- 'GeoIP_country_il' => '',
- 'GeoIP_country_im' => '',
- 'GeoIP_country_in' => '',
- 'GeoIP_country_io' => '',
- 'GeoIP_country_iq' => '',
- 'GeoIP_country_ir' => '',
- 'GeoIP_country_is' => '',
- 'GeoIP_country_it' => '',
- 'GeoIP_country_je' => '',
- 'GeoIP_country_jm' => '',
- 'GeoIP_country_jo' => '',
- 'GeoIP_country_jp' => '',
- 'GeoIP_country_ke' => '',
- 'GeoIP_country_kg' => '',
- 'GeoIP_country_kh' => '',
- 'GeoIP_country_ki' => '',
- 'GeoIP_country_km' => '',
- 'GeoIP_country_kn' => '',
- 'GeoIP_country_kp' => '',
- 'GeoIP_country_kr' => '',
- 'GeoIP_country_kw' => '',
- 'GeoIP_country_ky' => '',
- 'GeoIP_country_kz' => '',
- 'GeoIP_country_la' => '',
- 'GeoIP_country_lb' => '',
- 'GeoIP_country_lc' => '',
- 'GeoIP_country_li' => '',
- 'GeoIP_country_lk' => '',
- 'GeoIP_country_lr' => '',
- 'GeoIP_country_ls' => '',
- 'GeoIP_country_lt' => '',
- 'GeoIP_country_lu' => '',
- 'GeoIP_country_lv' => '',
- 'GeoIP_country_ly' => '',
- 'GeoIP_country_ma' => '',
- 'GeoIP_country_mc' => '',
- 'GeoIP_country_md' => '',
- 'GeoIP_country_mg' => '',
- 'GeoIP_country_mh' => '',
- 'GeoIP_country_mk' => '',
- 'GeoIP_country_ml' => '',
- 'GeoIP_country_mm' => '',
- 'GeoIP_country_mn' => '',
- 'GeoIP_country_mo' => '',
- 'GeoIP_country_mp' => '',
- 'GeoIP_country_mq' => '',
- 'GeoIP_country_mr' => '',
- 'GeoIP_country_ms' => '',
- 'GeoIP_country_mt' => '',
- 'GeoIP_country_mu' => '',
- 'GeoIP_country_mv' => '',
- 'GeoIP_country_mw' => '',
- 'GeoIP_country_mx' => '',
- 'GeoIP_country_my' => '',
- 'GeoIP_country_mz' => '',
- 'GeoIP_country_na' => '',
- 'GeoIP_country_nc' => '',
- 'GeoIP_country_ne' => '',
- 'GeoIP_country_nf' => '',
- 'GeoIP_country_ng' => '',
- 'GeoIP_country_ni' => '',
- 'GeoIP_country_nl' => '',
- 'GeoIP_country_no' => '',
- 'GeoIP_country_np' => '',
- 'GeoIP_country_nr' => '',
- 'GeoIP_country_nu' => '',
- 'GeoIP_country_nz' => '',
- 'GeoIP_country_om' => '',
- 'GeoIP_country_pa' => '',
- 'GeoIP_country_pe' => '',
- 'GeoIP_country_pf' => '',
- 'GeoIP_country_pg' => '',
- 'GeoIP_country_ph' => '',
- 'GeoIP_country_pk' => '',
- 'GeoIP_country_pl' => '',
- 'GeoIP_country_pm' => '',
- 'GeoIP_country_pn' => '',
- 'GeoIP_country_pr' => '',
- 'GeoIP_country_ps' => '',
- 'GeoIP_country_pt' => '',
- 'GeoIP_country_pw' => '',
- 'GeoIP_country_py' => '',
- 'GeoIP_country_qa' => '',
- 'GeoIP_country_re' => '',
- 'GeoIP_country_ro' => '',
- 'GeoIP_country_ru' => '',
- 'GeoIP_country_rs' => '',
- 'GeoIP_country_rw' => '',
- 'GeoIP_country_sa' => '',
- 'GeoIP_country_sb' => '',
- 'GeoIP_country_sc' => '',
- 'GeoIP_country_sd' => '',
- 'GeoIP_country_se' => '',
- 'GeoIP_country_sg' => '',
- 'GeoIP_country_sh' => '',
- 'GeoIP_country_si' => '',
- 'GeoIP_country_sj' => '',
- 'GeoIP_country_sk' => '',
- 'GeoIP_country_sl' => '',
- 'GeoIP_country_sm' => '',
- 'GeoIP_country_sn' => '',
- 'GeoIP_country_so' => '',
- 'GeoIP_country_sr' => '',
- 'GeoIP_country_st' => '',
- 'GeoIP_country_su' => '',
- 'GeoIP_country_sv' => '',
- 'GeoIP_country_sy' => '',
- 'GeoIP_country_sz' => '',
- 'GeoIP_country_tc' => '',
- 'GeoIP_country_td' => '',
- 'GeoIP_country_tf' => '',
- 'GeoIP_country_tg' => '',
- 'GeoIP_country_th' => '',
- 'GeoIP_country_tj' => '',
- 'GeoIP_country_tk' => '',
- 'GeoIP_country_tm' => '',
- 'GeoIP_country_tn' => '',
- 'GeoIP_country_to' => '',
- 'GeoIP_country_tp' => '',
- 'GeoIP_country_tr' => '',
- 'GeoIP_country_tt' => '',
- 'GeoIP_country_tv' => '',
- 'GeoIP_country_tw' => '',
- 'GeoIP_country_tz' => '',
- 'GeoIP_country_ua' => '',
- 'GeoIP_country_ug' => '',
- 'GeoIP_country_uk' => '',
- 'GeoIP_country_gb' => '',
- 'GeoIP_country_um' => '',
- 'GeoIP_country_us' => '',
- 'GeoIP_country_uy' => '',
- 'GeoIP_country_uz' => '',
- 'GeoIP_country_va' => '',
- 'GeoIP_country_vc' => '',
- 'GeoIP_country_ve' => '',
- 'GeoIP_country_vg' => '',
- 'GeoIP_country_vi' => '',
- 'GeoIP_country_vn' => '',
- 'GeoIP_country_vu' => '',
- 'GeoIP_country_wf' => '',
- 'GeoIP_country_ws' => '',
- 'GeoIP_country_ye' => '',
- 'GeoIP_country_yt' => '',
- 'GeoIP_country_yu' => '',
- 'GeoIP_country_za' => '',
- 'GeoIP_country_zm' => '',
- 'GeoIP_country_zr' => '',
- 'GeoIP_country_zw' => '',
- 'GeoIP_continent_' => 'Дадзеныя недаступныя',
- 'GeoIP_continent_eur' => 'Еўропа',
- 'GeoIP_continent_afr' => 'Афрыка',
- 'GeoIP_continent_asi' => 'Азія',
- 'GeoIP_continent_ams' => 'Паўднёвая і Цэнтральная Амерыка',
- 'GeoIP_continent_amn' => 'Паўночная Амерыка',
- 'GeoIP_continent_oce' => 'Акіянія',
- 'Installation_ContinueToPiwik' => 'Працягнуць да Piwik',
- 'Installation_SuperUserLogin' => 'суперюзер',
- 'Installation_Password' => 'пароль',
- 'Installation_PasswordRepeat' => 'пароль (паўтор)',
- 'Installation_Email' => 'е-маил',
- 'Installation_SecurityNewsletter' => '',
- 'Installation_CommunityNewsletter' => '',
- 'Installation_PasswordDoNotMatch' => 'паролі не аднолькавыя',
- 'Installation_SubmitGo' => 'Наперад!',
- 'Installation_DatabaseCreatedSuccess' => 'База %s створаная паспяхова!',
- 'Referers_Referers' => 'Рэфералы',
- 'SitesManager_WebsitesManagement' => 'Кіраванне сайтамі',
- 'SitesManager_MainDescription' => 'Для вядзення статыстыкі патрабуецца дадаць сайты! Дадавайце, абнаўляйце, выдаляйце інфармацыю аб сайтах, а таксама праглядзіце Java-код для ўстаўкі на Вашы старонкі.',
- 'UserCountry_country_ax' => 'Выспы Аланд',
- 'UserCountry_country_bl' => '',
- 'UserCountry_country_bu' => 'Бірма',
- 'UserCountry_country_cp' => 'Выспа Клиппертон',
- 'UserCountry_country_dg' => '',
- 'UserCountry_country_ea' => '',
- 'UserCountry_country_eu' => 'Еўрасаюз',
- 'UserCountry_country_fx' => 'Францыя, Метрапалітэн',
- 'UserCountry_country_ic' => 'Канарскія выспы',
- 'UserCountry_country_me' => 'Монтенегро',
- 'UserCountry_country_mf' => 'Сан-Марцін',
- 'UserCountry_country_nt' => 'Нейтральная зона',
- 'UserCountry_country_ru' => 'Расія',
- 'UserCountry_country_rs' => 'Сербія',
- 'UserCountry_country_sf' => 'Фінляндыя',
- 'UserCountry_country_ta' => '',
- 'UserCountry_country_tl' => '',
- 'UsersManager_UsersManagement' => 'Кіраванне карыстачамі',
- 'UsersManager_UsersManagementMainDescription' => 'Стварэнне новых карыстачоў або рэдагаванне наяўных. Таксама Вы можаце задаць правы доступу для карыстача.',
- 'UsersManager_MainDescription' => 'Пакажыце, якія карыстачы маюць доступ да Piwik на Вашым сайце. Таксама Вы можаце задаць правы доступу на ўсе сайты.',
- 'UsersManager_ExceptionInvalidLoginFormat' => 'Лагін павінен быць даўжынёй ад %s да %s знакаў, а таксама ўтрымоўваць толькі літары, лічбы або знакі \'_\', \'-\', \'.\'',
);
diff --git a/lang/bg.php b/lang/bg.php
new file mode 100644
index 0000000000..d429f1b082
--- /dev/null
+++ b/lang/bg.php
@@ -0,0 +1,935 @@
+<?php
+
+setlocale(LC_TIME, 'bg_BG.UTF-8');
+
+$translations = array(
+ 'General_Locale' => 'bg_BG.UTF-8',
+ 'General_TranslatorName' => 'Kristalin Chavdarov
+
+Andon Ivanov',
+ 'General_TranslatorEmail' => 'kristalin@kividesign.com, www.kristalinchavdarov.net
+
+Virosss@abv.bg, www.coffebreak.info',
+ 'General_EnglishLanguageName' => 'Bulgarian',
+ 'General_OriginalLanguageName' => 'Български',
+ 'General_HelloUser' => 'Здравей, %s!',
+ 'General_OpenSourceWebAnalytics' => 'Уеб Брояч с Отворен Код',
+ 'General_YourDashboard' => 'Вашето табло',
+ 'General_API' => 'API',
+ 'General_Widgets' => 'Джаджи',
+ 'General_Settings' => 'Настройки',
+ 'General_GiveUsYourFeedback' => 'Обратна връзка',
+ 'General_Unknown' => 'Неизвестен',
+ 'General_Required' => '%s са необходими',
+ 'General_Error' => 'Грешка',
+ 'General_Warning' => 'Предупреждение',
+ 'General_BackToHomepage' => 'Върни се обратно',
+ 'General_Yes' => 'Да',
+ 'General_No' => 'Не',
+ 'General_Delete' => 'Изтрий',
+ 'General_Edit' => 'Редактирай',
+ 'General_Ok' => 'Ок',
+ 'General_Close' => 'Затвори',
+ 'General_Logout' => 'Излез',
+ 'General_Done' => 'Готово',
+ 'General_LoadingData' => 'Зарежда данни...',
+ 'General_Loading' => 'Зарежда...',
+ 'General_ErrorRequest' => 'Ооопс&hellip; възникна грешка! Опитайте отново.',
+ 'General_Next' => 'Напред',
+ 'General_Previous' => 'Назад',
+ 'General_Search' => 'Търсене',
+ 'General_Others' => 'Други',
+ 'General_Table' => 'Таблица',
+ 'General_Piechart' => 'Диаграма',
+ 'General_TagCloud' => 'Тагове',
+ 'General_VBarGraph' => 'Графика',
+ 'General_Export' => 'Експорт',
+ 'General_ExportAsImage' => 'Експортирай изображение',
+ 'General_SaveImageOnYourComputer' => 'За да запазите изображението на вашия компютър, натиснете десен бутон върху него и изберете "Запиши изображението като..."',
+ 'General_Refresh' => 'Обнови страницата',
+ 'General_Visitors' => 'Посетители',
+ 'General_ColumnNbUniqVisitors' => 'Уникални посетители',
+ 'General_ColumnNbVisits' => 'Посещения',
+ 'General_ColumnNbActions' => 'Действия',
+ 'General_ColumnMaxActions' => 'Максимум действия при едно посещение',
+ 'General_ColumnSumVisitLength' => 'Цялото време прекарано от потребителите (в секунди)',
+ 'General_ColumnLabel' => 'Етикет',
+ 'General_ColumnActionsPerVisit' => 'Десйтвия при посещение',
+ 'General_ColumnAvgTimeOnSite' => 'Средно време прекарано в сайта',
+ 'General_ColumnBounceRate' => 'Bounce Rate',
+ 'General_ColumnPageviews' => 'Посещения',
+ 'General_ColumnUniquePageviews' => 'Уникални посещения',
+ 'General_ColumnValuePerVisit' => 'Стойност на посещението',
+ 'General_ColumnVisitsWithConversions' => 'Посещения с Конверсия',
+ 'General_Save' => 'Запиши',
+ 'General_Website' => 'Сайт',
+ 'General_NoDataForGraph' => 'Няма данни за графиката',
+ 'General_NoDataForTagCloud' => 'Няма данни за този таг облак.',
+ 'General_DisplayNormalTable' => 'Нормална таблица',
+ 'General_DisplayMoreData' => 'Покажи повече данни',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s е отворен проект. %s Ако Piwik, ви допада можете да ни помогнете! Научете %s как можете да ни помогнете?%s ',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Това е демо версия, можете да %s; %sизтеглите%s пълната версия! Вижте %s',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s е наличен. %s Обновете сега. %s (вижте %s промените%s).',
+ 'General_BackToPiwik' => 'Върни се в Piwik',
+ 'General_ShortMonth_1' => 'Яну',
+ 'General_ShortMonth_2' => 'Фев',
+ 'General_ShortMonth_3' => 'Мар',
+ 'General_ShortMonth_4' => 'Апр',
+ 'General_ShortMonth_5' => 'Май',
+ 'General_ShortMonth_6' => 'Юни',
+ 'General_ShortMonth_7' => 'Юли',
+ 'General_ShortMonth_8' => 'Авг',
+ 'General_ShortMonth_9' => 'Сеп',
+ 'General_ShortMonth_10' => 'Окт',
+ 'General_ShortMonth_11' => 'Ное',
+ 'General_ShortMonth_12' => 'Дек',
+ 'General_LongMonth_1' => 'Януари',
+ 'General_LongMonth_2' => 'Февруари',
+ 'General_LongMonth_3' => 'Март',
+ 'General_LongMonth_4' => 'Април',
+ 'General_LongMonth_5' => 'Май',
+ 'General_LongMonth_6' => 'Юни',
+ 'General_LongMonth_7' => 'Юли',
+ 'General_LongMonth_8' => 'Август',
+ 'General_LongMonth_9' => 'Септември',
+ 'General_LongMonth_10' => 'Октомври',
+ 'General_LongMonth_11' => 'Ноември',
+ 'General_LongMonth_12' => 'Декември',
+ 'General_ShortDay_1' => 'Пон',
+ 'General_ShortDay_2' => 'Вто',
+ 'General_ShortDay_3' => 'Сря',
+ 'General_ShortDay_4' => 'Чет',
+ 'General_ShortDay_5' => 'Пет',
+ 'General_ShortDay_6' => 'Съб',
+ 'General_ShortDay_7' => 'Нед',
+ 'General_LongDay_1' => 'Понеделник',
+ 'General_LongDay_2' => 'Вторник',
+ 'General_LongDay_3' => 'Сряда',
+ 'General_LongDay_4' => 'Четвъртък',
+ 'General_LongDay_5' => 'Петък',
+ 'General_LongDay_6' => 'Събота',
+ 'General_LongDay_7' => 'Неделя',
+ 'Core_ExceptionDatabaseVersion' => 'Вие използвате %s версия %s , но Piwik изисква да използвате последната версия%s.',
+ 'CorePluginsAdmin_Plugins' => 'Плъгини',
+ 'CorePluginsAdmin_PluginsManagement' => 'Управление на плъгините',
+ 'CorePluginsAdmin_MainDescription' => 'Плъгините спомагат за по-обширното функциониране на Piwik. Веднъж инсталиран плъгин би могъл да бъде активиран (пускан) или деактивиран (спиран).',
+ 'CorePluginsAdmin_Plugin' => 'Плъгин',
+ 'CorePluginsAdmin_Version' => 'Версия',
+ 'CorePluginsAdmin_Description' => 'Описание',
+ 'CorePluginsAdmin_Status' => 'Състояние',
+ 'CorePluginsAdmin_Action' => 'Действие',
+ 'CorePluginsAdmin_PluginHomepage' => 'Сайт на плъгина',
+ 'CorePluginsAdmin_Activated' => 'Активиран',
+ 'CorePluginsAdmin_Active' => 'Активен',
+ 'CorePluginsAdmin_Inactive' => 'Неактивен',
+ 'CorePluginsAdmin_ActivatedHelp' => 'Този плъгин не може да бъде деактивиран',
+ 'CorePluginsAdmin_Deactivate' => 'Деактивирай',
+ 'CorePluginsAdmin_Activate' => 'Активирай',
+ 'CorePluginsAdmin_MenuPlugins' => 'Плъгини',
+ 'API_QuickDocumentation' => '<h2>API документация</h2><p>Ако все още нямате данни <a href=\'misc/generateVisits.php\' target=_blank>можете да генерирате</a> използвайки скрипта за Генериране на Посещения.</p><p>Можете да използвате различни формати за различните методи. Извличането на информация от Piwik е много лесно!</p><p><b>За повече информация вижте: <a href=\'http://dev.piwik.org/trac/wiki/API\'>официалната API документация</a> или <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API ръководство</a>.</b></P><h2>Идентифициране на потребител</h2><p>Ако искате да <b>извлечете данни </b> трябва да добавите <code><u>&token_auth=%s</u></code> параметъра в кода.</p><p>Този token_auth е шифър (вашето потребителско име и парола), <b>запазете го само за вас!</p>',
+ 'API_LoadedAPIs' => 'Успещно заредени %s API-та',
+ 'CoreHome_NoPrivileges' => 'Вие сте влезли, като \'%s\' , но нямате достъп до тази услуга в Piwik.<br />Моля, поискайте от Piwik администратора права за да извършите това действие.',
+ 'CoreHome_JavascriptDisabled' => 'JavaScript трябва да бъед разрешен за да използвате Piwik в стандартен изглед.<br />Същото е ако JavaScript не е разрешен или браузера не го поддържа.<br />За да използвате стандартен изглед разрешете JavaScript от настройките на вашия браузер и %sопитайте отново%s.<br />',
+ 'CoreHome_TableNoData' => 'Няма данни',
+ 'CoreHome_CategoryNoData' => 'Няма данни в тази категория. Опитайте "Включи всички данни".',
+ 'CoreHome_ShowJSCode' => 'Покажи JavaScript кода за вмъкване в сайта',
+ 'CoreHome_IncludeAllPopulation_js' => 'Включи всички данни',
+ 'CoreHome_ExcludeLowPopulation_js' => 'Изключи данните с ниско равнище',
+ 'CoreHome_PageOf_js' => '%s от %s',
+ 'CoreHome_Loading_js' => 'Зарежда...',
+ 'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
+ 'CoreHome_PeriodDay' => 'Ден',
+ 'CoreHome_PeriodWeek' => 'Седмица',
+ 'CoreHome_PeriodMonth' => 'Месец',
+ 'CoreHome_PeriodYear' => 'Година',
+ 'CoreHome_PeriodDays' => 'дни',
+ 'CoreHome_PeriodWeeks' => 'седмици',
+ 'CoreHome_PeriodMonths' => 'месеци',
+ 'CoreHome_PeriodYears' => 'години',
+ 'CoreHome_DaySu_js' => 'Нд',
+ 'CoreHome_DayMo_js' => 'По',
+ 'CoreHome_DayTu_js' => 'Вт',
+ 'CoreHome_DayWe_js' => 'Ср',
+ 'CoreHome_DayTh_js' => 'Чт',
+ 'CoreHome_DayFr_js' => 'Пт',
+ 'CoreHome_DaySa_js' => 'Съ',
+ 'CoreHome_MonthJanuary_js' => 'Януари',
+ 'CoreHome_MonthFebruary_js' => 'Февруари',
+ 'CoreHome_MonthMarch_js' => 'Март',
+ 'CoreHome_MonthApril_js' => 'Април',
+ 'CoreHome_MonthMay_js' => 'Май',
+ 'CoreHome_MonthJune_js' => 'Юни',
+ 'CoreHome_MonthJuly_js' => 'Юли',
+ 'CoreHome_MonthAugust_js' => 'Август',
+ 'CoreHome_MonthSeptember_js' => 'Септември',
+ 'CoreHome_MonthOctober_js' => 'Октомври',
+ 'CoreHome_MonthNovember_js' => 'Ноевмри',
+ 'CoreHome_MonthDecember_js' => 'Декември',
+ 'CoreUpdater_UpdateTitle' => 'Обновления',
+ 'CoreUpdater_DatabaseUpgradeRequired' => 'Необходимо е да се обнови базата от данни (БД)',
+ 'CoreUpdater_YourDatabaseIsOutOfDate' => 'Базата от данни (БД) на Piwik е остаряла. Трябва да обновите преди да продължите нататък.',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik базата от данни (БД) ще бъде обновена от %s версия към %s.',
+ 'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Следните плъгини ще бъдеат обновени: %s.',
+ 'CoreUpdater_TheUpgradeProcessMayFail' => 'Ако е голяма Piwik базата от данни (БД), обновяването може да отнеме по-дълго време от стандартното. Ако желаете обновяването да е по-бързо можете да обновите, чрез командния ред така (само за напреднали): <code>$ php път/до/piwik/index.php</code>',
+ 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Обновяването на базата от данни (БД) отнема известно време! Бъдете търпеливи...',
+ 'CoreUpdater_UpgradePiwik' => 'Обновете Piwik',
+ 'CoreUpdater_ErrorDIYHelp' => 'Ако сте напреднал потребител и попаднете на грешка при обновяване на базата от данни (БД):',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'открийте и редактирайте в конфигурационния файл (напр., memory_limit or max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'изпълни останалите заявки за обновяване от това поле',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'опцията `ръчно обновяване` на таблиците в Piwik базата от данни (БД), setting the value of version_core to the version of the failed update',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'повторно стартирайте обновлението (чрез браузера или от командния ред) за да продължите с останалите обновления',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'изпратете този проблем и/или решение на Piwik екипа - възможно е това да е важно!',
+ 'CoreUpdater_HelpMessageContent' => 'Проверете %s Често Задавани Въпроси (ЧЗВ) %s , където са обяснени възможните грешки по време на обновяването. %s Посъветвайте се с вашия системен администратор - те са в състояние да ви помогнат с грешка, която най-вероятно е свързана със сървъра или MySQL настройка.',
+ 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Открита е КРИТИЧНА грешка по време на обновяването:',
+ 'CoreUpdater_HelpMessageIntroductionWhenError' => 'Открита е грешка в ядрото на Piwik. Ако имате нужда от допълнителна помощ моля обърнете се към нашия форум и/или прочетете документацията:',
+ 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Актуализацията приключи успешно, но бяха открити грешки по време на процеса. Моля, прочетете документацията за допълнителна информация:',
+ 'CoreUpdater_UpgradeComplete' => 'Обновяването приключи!',
+ 'CoreUpdater_WarningMessages' => 'Предупредителни съобщения:',
+ 'CoreUpdater_ErrorDuringPluginsUpdates' => 'Открита е грешка при обновяването на плъгините:',
+ 'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Автоматично са деактивирани следните плъгини: %s',
+ 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik успешно е обновен!',
+ 'CoreUpdater_ContinueToPiwik' => 'Продължете към Piwik',
+ 'CoreUpdater_UpdateAutomatically' => 'Обновете автоматично',
+ 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Открита е нова версия на Piwik, можете да обновите!',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Можете да обновите автоматично към версия %s или да изтеглите обновлението и инсталирате ръчно:',
+ 'CoreUpdater_DownloadX' => 'Изтегляне %s',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Автоматичното обновяване на Piwik е отказано. Опитайте отново! Ако не успеете автоматично да обновите Piwik, опитайте ръчно. %s Моля прочетете %s документацията %s и продължете!',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Изтегляне на обновлението от %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Разархивиране на обновлението',
+ 'CoreUpdater_VerifyingUnpackedFiles' => ' разархивираните файлове',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Създаден е бекъп на конфигурационния файл в %s',
+ 'CoreUpdater_InstallingTheLatestVersion' => 'Инсталиране на последната версия',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Обновлението на Piwik завърши успешно!',
+ 'CoreUpdater_EmptyDatabaseError' => 'Базата от данни (БД) %s е празна. Трябва да редактирате или изтриете конфигурационният файл на Piwik.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Тази версия %s на Piwik е актуална.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Несъвместим архив: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Празен архив.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Несъвместим архив: някои файлове липсват (напр. %s).',
+ 'Actions_Actions' => 'Действия',
+ 'Actions_SubmenuPages' => 'Страници',
+ 'Actions_SubmenuOutlinks' => 'Изходящи',
+ 'Actions_SubmenuDownloads' => 'Изтегляния',
+ 'Actions_ColumnClicks' => 'Кликове',
+ 'Actions_ColumnUniqueClicks' => 'Уникални клика',
+ 'Actions_ColumnDownloads' => 'Сваляния',
+ 'Actions_ColumnUniqueDownloads' => 'Уникални сваляния',
+ 'Actions_ColumnPageName' => 'Име на страницата',
+ 'Actions_ColumnClickedURL' => 'Щракнат URL',
+ 'Actions_ColumnDownloadURL' => 'Свален URL',
+ 'Dashboard_Dashboard' => 'Табло',
+ 'Dashboard_AddWidget' => 'Добави джаджа...',
+ 'Dashboard_DeleteWidgetConfirm' => 'Наистина ли искате да изтриете тази джаджа от таблото?',
+ 'Dashboard_SelectWidget' => 'Изберете джаджа, която да добавите на таблото',
+ 'Dashboard_AddPreviewedWidget_js' => 'Добави джаджата на таблото',
+ 'Dashboard_WidgetPreview_js' => 'Преглед на джаджата',
+ 'Dashboard_Close_js' => 'Затвори',
+ 'Dashboard_TitleWidgetInDashboard_js' => 'Джаджата в момента е на таблото',
+ 'Dashboard_TitleClickToAdd_js' => 'Щракнете за да добавите на таблото',
+ 'Dashboard_LoadingWidget_js' => 'Зарежда джаджата, почакайте...',
+ 'Dashboard_WidgetNotFound_js' => 'Несъществуваща джаджа',
+ 'Referers_Referers' => 'Референции',
+ 'Referers_SearchEngines' => 'Търсачки',
+ 'Referers_Keywords' => 'Ключови думи',
+ 'Referers_DirectEntry' => 'Директни посещения',
+ 'Referers_Websites' => 'Сайтове',
+ 'Referers_Campaigns' => 'Кампании',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%s (от %s)',
+ 'Referers_Evolution' => 'Развитие за периода',
+ 'Referers_Type' => 'Тип на референцията',
+ 'Referers_ColumnRefererType' => 'Тип на референцията',
+ 'Referers_ColumnSearchEngine' => 'Търсещи машини',
+ 'Referers_ColumnWebsite' => 'Сайт',
+ 'Referers_ColumnWebsitePage' => 'Интернет страница',
+ 'Referers_ColumnKeyword' => 'Ключови думи',
+ 'Referers_ColumnCampaign' => 'Кампании',
+ 'Referers_DetailsByRefererType' => 'Детайли за типовете референции',
+ 'Referers_TypeDirectEntries' => '%s директни посещения',
+ 'Referers_TypeSearchEngines' => '%s от търсещите машини',
+ 'Referers_TypeWebsites' => '%s от сайтове',
+ 'Referers_TypeCampaigns' => '%s от кампании',
+ 'Referers_Distinct' => 'Отделни референции от Тип на референциите',
+ 'Referers_DistinctSearchEngines' => 'отделни тъсещи машини',
+ 'Referers_DistinctKeywords' => 'отделни ключови думи',
+ 'Referers_DistinctCampaigns' => 'отделни кампании',
+ 'Referers_DistinctWebsites' => 'отделни сайтове',
+ 'Referers_UsingNDistinctUrls' => ' (използват %2s отделни адреси (url) )',
+ 'Referers_SubmenuEvolution' => 'Развитие',
+ 'Referers_SubmenuSearchEngines' => 'Търсачки & Ключови думи',
+ 'Referers_SubmenuWebsites' => 'Сайтове',
+ 'Referers_SubmenuCampaigns' => 'Кампании',
+ 'Referers_WidgetKeywords' => 'Популярни ключови думи',
+ 'Referers_WidgetCampaigns' => 'Популярни кампании',
+ 'Referers_WidgetExternalWebsites' => 'Външни сайтове',
+ 'Referers_WidgetSearchEngines' => 'Популярни търсещи машини',
+ 'Referers_WidgetOverview' => 'Резюме',
+ 'UserSettings_VisitorSettings' => 'Настройки на посетителя',
+ 'UserSettings_BrowserFamilies' => 'Фамилия браузери',
+ 'UserSettings_Browsers' => 'Браузери',
+ 'UserSettings_Plugins' => 'Плъгини',
+ 'UserSettings_Configurations' => 'Конфигурации',
+ 'UserSettings_OperatingSystems' => 'Операционни системи',
+ 'UserSettings_Resolutions' => 'Разделителна способност',
+ 'UserSettings_WideScreen' => 'Екран',
+ 'UserSettings_ColumnBrowserFamily' => 'Фамилия браузери',
+ 'UserSettings_ColumnBrowser' => 'Браузер и версия',
+ 'UserSettings_ColumnPlugin' => 'Плъгин',
+ 'UserSettings_ColumnConfiguration' => 'Обобщена конфигурация',
+ 'UserSettings_ColumnOperatingSystem' => 'Операционна система и версия',
+ 'UserSettings_ColumnResolution' => 'Разделителна способност на екрана',
+ 'UserSettings_ColumnTypeOfScreen' => 'Тип на екрана',
+ 'UserSettings_WidgetResolutions' => 'Разделителна способност',
+ 'UserSettings_WidgetBrowsers' => 'Браузери на посетителите',
+ 'UserSettings_WidgetPlugins' => 'Плъгини',
+ 'UserSettings_WidgetWidescreen' => 'Нормален / Широкоекранен',
+ 'UserSettings_WidgetBrowserFamilies' => 'Браузери',
+ 'UserSettings_WidgetOperatingSystems' => 'Операционни системи',
+ 'UserSettings_WidgetGlobalVisitors' => 'Конфигурация на глобалните посетители',
+ 'UserSettings_SubmenuSettings' => 'Настройки',
+ 'UserCountry_Country' => 'Държава',
+ 'UserCountry_Continent' => 'Континент',
+ 'UserCountry_DistinctCountries' => '%s отделни държави',
+ 'UserCountry_SubmenuLocations' => 'Местонахождение',
+ 'UserCountry_WidgetContinents' => 'Контитент на посетителя',
+ 'UserCountry_WidgetCountries' => 'Държава на посетителя',
+ 'UserCountry_country_ac' => 'Възнесение',
+ 'UserCountry_country_ad' => 'Андора',
+ 'UserCountry_country_ae' => 'ОАЕ',
+ 'UserCountry_country_af' => 'Афганистан',
+ 'UserCountry_country_ag' => 'Антигуа и Барбуда',
+ 'UserCountry_country_ai' => 'Ангуила',
+ 'UserCountry_country_al' => 'Албания',
+ 'UserCountry_country_am' => 'Армения',
+ 'UserCountry_country_an' => 'Холандски Антили',
+ 'UserCountry_country_ao' => 'Ангола',
+ 'UserCountry_country_aq' => 'Антрактида',
+ 'UserCountry_country_ar' => 'Аржентина',
+ 'UserCountry_country_as' => 'Американска Самоа',
+ 'UserCountry_country_at' => 'Австрия',
+ 'UserCountry_country_au' => 'Австралия',
+ 'UserCountry_country_aw' => 'Аруба',
+ 'UserCountry_country_az' => 'Азербайджан',
+ 'UserCountry_country_ba' => 'Босна и Херцеговина',
+ 'UserCountry_country_bb' => 'Барбадос',
+ 'UserCountry_country_bd' => 'Бангладеш',
+ 'UserCountry_country_be' => 'Белгия',
+ 'UserCountry_country_bf' => 'Буркина Фасо',
+ 'UserCountry_country_bg' => 'България',
+ 'UserCountry_country_bh' => 'Бахрейн',
+ 'UserCountry_country_bi' => 'Бурунди',
+ 'UserCountry_country_bj' => 'Бенин',
+ 'UserCountry_country_bm' => 'Бермуди',
+ 'UserCountry_country_bn' => 'Бруней',
+ 'UserCountry_country_bo' => 'Боливия',
+ 'UserCountry_country_br' => 'Бразилия',
+ 'UserCountry_country_bs' => 'Бахамите',
+ 'UserCountry_country_bt' => 'Бутан',
+ 'UserCountry_country_bv' => 'Буве',
+ 'UserCountry_country_bw' => 'Боцвана',
+ 'UserCountry_country_by' => 'Беларус',
+ 'UserCountry_country_bz' => 'Белиз',
+ 'UserCountry_country_ca' => 'Канада',
+ 'UserCountry_country_cc' => 'Кокосови острови',
+ 'UserCountry_country_cd' => 'Демократична република Конго',
+ 'UserCountry_country_cf' => 'Централноафриканска република',
+ 'UserCountry_country_cg' => 'Конго',
+ 'UserCountry_country_ch' => 'Швейцария',
+ 'UserCountry_country_ci' => 'Кот д\'Ивоар',
+ 'UserCountry_country_ck' => 'Кук (острови)',
+ 'UserCountry_country_cl' => 'Чили',
+ 'UserCountry_country_cm' => 'Камерун',
+ 'UserCountry_country_cn' => 'Китай',
+ 'UserCountry_country_co' => 'Колумбия',
+ 'UserCountry_country_cr' => 'Коста Рика',
+ 'UserCountry_country_cs' => 'Сърбия и Черна гора',
+ 'UserCountry_country_cu' => 'Куба',
+ 'UserCountry_country_cv' => 'Кабо Верде',
+ 'UserCountry_country_cx' => 'Рождество (остров)',
+ 'UserCountry_country_cy' => 'Кипър',
+ 'UserCountry_country_cz' => 'Чехия',
+ 'UserCountry_country_de' => 'Германия',
+ 'UserCountry_country_dj' => 'Джибути',
+ 'UserCountry_country_dk' => 'Дания',
+ 'UserCountry_country_dm' => 'Доминика',
+ 'UserCountry_country_do' => 'Доминиканска република',
+ 'UserCountry_country_dz' => 'Алжир',
+ 'UserCountry_country_ec' => 'Еквадор',
+ 'UserCountry_country_ee' => 'Естония',
+ 'UserCountry_country_eg' => 'Египет',
+ 'UserCountry_country_eh' => 'Западна Сахара',
+ 'UserCountry_country_er' => 'Еритрея',
+ 'UserCountry_country_es' => 'Испания',
+ 'UserCountry_country_et' => 'Етиопия',
+ 'UserCountry_country_fi' => 'Финландия',
+ 'UserCountry_country_fj' => 'Фиджи',
+ 'UserCountry_country_fk' => 'Фолкландски острови',
+ 'UserCountry_country_fm' => 'Микронезия',
+ 'UserCountry_country_fo' => 'Фарьорски острови',
+ 'UserCountry_country_fr' => 'Франция',
+ 'UserCountry_country_ga' => 'Габон',
+ 'UserCountry_country_gd' => 'Гренада',
+ 'UserCountry_country_ge' => 'Грузия',
+ 'UserCountry_country_gf' => 'Френска Гвиана',
+ 'UserCountry_country_gg' => 'Гърнси',
+ 'UserCountry_country_gh' => 'Гана',
+ 'UserCountry_country_gi' => 'Гибралтар',
+ 'UserCountry_country_gl' => 'Гренландия',
+ 'UserCountry_country_gm' => 'Гамбия',
+ 'UserCountry_country_gn' => 'Гвинея',
+ 'UserCountry_country_gp' => 'Гваделупа',
+ 'UserCountry_country_gq' => 'Екваториална Гвинея',
+ 'UserCountry_country_gr' => 'Гърция',
+ 'UserCountry_country_gs' => 'Южна Джорджия и Южни Сандвичеви острови',
+ 'UserCountry_country_gt' => 'Гватемала',
+ 'UserCountry_country_gu' => 'Гуам',
+ 'UserCountry_country_gw' => 'Гвинея-Бисау',
+ 'UserCountry_country_gy' => 'Гвиана',
+ 'UserCountry_country_hk' => 'Хон Конг',
+ 'UserCountry_country_hm' => 'Хърд и Макдоналд',
+ 'UserCountry_country_hn' => 'Хондурас',
+ 'UserCountry_country_hr' => 'Хърватска',
+ 'UserCountry_country_ht' => 'Хаити',
+ 'UserCountry_country_hu' => 'Унгария',
+ 'UserCountry_country_id' => 'Индонезия',
+ 'UserCountry_country_ie' => 'Ирландия',
+ 'UserCountry_country_il' => 'Израел',
+ 'UserCountry_country_im' => 'Man Island',
+ 'UserCountry_country_in' => 'Индия',
+ 'UserCountry_country_io' => 'Британска индоокеанска територия',
+ 'UserCountry_country_iq' => 'Ирак',
+ 'UserCountry_country_ir' => 'ИРА',
+ 'UserCountry_country_is' => 'Исландия',
+ 'UserCountry_country_it' => 'Италия',
+ 'UserCountry_country_je' => 'Джърси',
+ 'UserCountry_country_jm' => 'Ямайка',
+ 'UserCountry_country_jo' => 'Йордания',
+ 'UserCountry_country_jp' => 'Япония',
+ 'UserCountry_country_ke' => 'Кения',
+ 'UserCountry_country_kg' => 'Киргистан',
+ 'UserCountry_country_kh' => 'Камбоджа',
+ 'UserCountry_country_ki' => 'Кирибати',
+ 'UserCountry_country_km' => 'Коморски острови',
+ 'UserCountry_country_kn' => 'Сейнт Китс и Невис',
+ 'UserCountry_country_kp' => 'Корейска народнодемократична република',
+ 'UserCountry_country_kr' => 'Южна Корея',
+ 'UserCountry_country_kw' => 'Кувейт',
+ 'UserCountry_country_ky' => 'Кайманови острови',
+ 'UserCountry_country_kz' => 'Казахстан',
+ 'UserCountry_country_la' => 'Лаос',
+ 'UserCountry_country_lb' => 'Ливан',
+ 'UserCountry_country_lc' => 'Сейнт Лусия',
+ 'UserCountry_country_li' => 'Лихтенщайн',
+ 'UserCountry_country_lk' => 'Шри Ланка',
+ 'UserCountry_country_lr' => 'Либерия',
+ 'UserCountry_country_ls' => 'Лесото',
+ 'UserCountry_country_lt' => 'Литва',
+ 'UserCountry_country_lu' => 'Люксембург',
+ 'UserCountry_country_lv' => 'Латвия',
+ 'UserCountry_country_ly' => 'Либия',
+ 'UserCountry_country_ma' => 'Мароко',
+ 'UserCountry_country_mc' => 'Монако',
+ 'UserCountry_country_md' => 'Молдова',
+ 'UserCountry_country_mg' => 'Мадагаскар',
+ 'UserCountry_country_mh' => 'Маршалови острови',
+ 'UserCountry_country_mk' => 'Македония',
+ 'UserCountry_country_ml' => 'Мали',
+ 'UserCountry_country_mm' => 'Мианмар',
+ 'UserCountry_country_mn' => 'Монголия',
+ 'UserCountry_country_mo' => 'Макао',
+ 'UserCountry_country_mp' => 'Северни Мариански острови',
+ 'UserCountry_country_mq' => 'Мартиника',
+ 'UserCountry_country_mr' => 'Мавритания',
+ 'UserCountry_country_ms' => 'Монсерат',
+ 'UserCountry_country_mt' => 'Малта',
+ 'UserCountry_country_mu' => 'Мавриций',
+ 'UserCountry_country_mv' => 'Малдивите',
+ 'UserCountry_country_mw' => 'Малави',
+ 'UserCountry_country_mx' => 'Мексико',
+ 'UserCountry_country_my' => 'Малайзия',
+ 'UserCountry_country_mz' => 'Мозамбик',
+ 'UserCountry_country_na' => 'Намибия',
+ 'UserCountry_country_nc' => 'Нова Каледония',
+ 'UserCountry_country_ne' => 'Нигер',
+ 'UserCountry_country_nf' => 'Норфолк',
+ 'UserCountry_country_ng' => 'Нигерия',
+ 'UserCountry_country_ni' => 'Никарагуа',
+ 'UserCountry_country_nl' => 'Нидерландия',
+ 'UserCountry_country_no' => 'Норвегия',
+ 'UserCountry_country_np' => 'Непал',
+ 'UserCountry_country_nr' => 'Науру',
+ 'UserCountry_country_nu' => 'Ниуе',
+ 'UserCountry_country_nz' => 'Нова Зеландия',
+ 'UserCountry_country_om' => 'Оман',
+ 'UserCountry_country_pa' => 'Панама',
+ 'UserCountry_country_pe' => 'Перу',
+ 'UserCountry_country_pf' => 'Френска Полинезия',
+ 'UserCountry_country_pg' => 'Папуа - Нова Гвинея',
+ 'UserCountry_country_ph' => 'Филипините',
+ 'UserCountry_country_pk' => 'Пакистан',
+ 'UserCountry_country_pl' => 'Полша',
+ 'UserCountry_country_pm' => 'Сен Пиер и Микелон',
+ 'UserCountry_country_pn' => 'Питкерн',
+ 'UserCountry_country_pr' => 'Пуерто Рико',
+ 'UserCountry_country_ps' => 'Палестина',
+ 'UserCountry_country_pt' => 'Португалия',
+ 'UserCountry_country_pw' => 'Палау',
+ 'UserCountry_country_py' => 'Парагвай',
+ 'UserCountry_country_qa' => 'Катар',
+ 'UserCountry_country_re' => 'Реюнион',
+ 'UserCountry_country_ro' => 'Румъния',
+ 'UserCountry_country_ru' => 'Русия',
+ 'UserCountry_country_rs' => 'Сърбия',
+ 'UserCountry_country_rw' => 'Руанда',
+ 'UserCountry_country_sa' => 'Саудитска Арабия',
+ 'UserCountry_country_sb' => 'Соломоновите острови',
+ 'UserCountry_country_sc' => 'Сейшелските острови',
+ 'UserCountry_country_sd' => 'Судан',
+ 'UserCountry_country_se' => 'Швеция',
+ 'UserCountry_country_sg' => 'Сингапур',
+ 'UserCountry_country_sh' => 'Света Хелена',
+ 'UserCountry_country_si' => 'Словения',
+ 'UserCountry_country_sj' => 'Свалбард',
+ 'UserCountry_country_sk' => 'Словакия',
+ 'UserCountry_country_sl' => 'Сиера Леоне',
+ 'UserCountry_country_sm' => 'Сан МАрино',
+ 'UserCountry_country_sn' => 'Сенегал',
+ 'UserCountry_country_so' => 'Сомалия',
+ 'UserCountry_country_sr' => 'Суринам',
+ 'UserCountry_country_st' => 'Сао Томе и Принсипи',
+ 'UserCountry_country_su' => 'СССР',
+ 'UserCountry_country_sv' => 'Ел Салвадор',
+ 'UserCountry_country_sy' => 'Сирия',
+ 'UserCountry_country_sz' => 'Швейцария',
+ 'UserCountry_country_tc' => 'Търкс и Кайкос',
+ 'UserCountry_country_td' => 'Чад',
+ 'UserCountry_country_tf' => 'Френски южни и антарктически територии',
+ 'UserCountry_country_tg' => 'Того',
+ 'UserCountry_country_th' => 'Тайланд',
+ 'UserCountry_country_tj' => 'Таджикистан',
+ 'UserCountry_country_tk' => 'Токелау',
+ 'UserCountry_country_tm' => 'Туркменистан',
+ 'UserCountry_country_tn' => 'Тунис',
+ 'UserCountry_country_to' => 'Тонга',
+ 'UserCountry_country_tp' => 'Източен Тимор',
+ 'UserCountry_country_tr' => 'Турция',
+ 'UserCountry_country_tt' => 'Тринидад и Тубаго',
+ 'UserCountry_country_tv' => 'Тувалу',
+ 'UserCountry_country_tw' => 'Тайван',
+ 'UserCountry_country_tz' => 'Танзания',
+ 'UserCountry_country_ua' => 'Украйна',
+ 'UserCountry_country_ug' => 'Уганда',
+ 'UserCountry_country_uk' => 'Обединено Кралство',
+ 'UserCountry_country_gb' => 'Великобритания',
+ 'UserCountry_country_um' => 'Малки далечни острови на САЩ',
+ 'UserCountry_country_us' => 'САЩ',
+ 'UserCountry_country_uy' => 'Уругвай',
+ 'UserCountry_country_uz' => 'Узбекистан',
+ 'UserCountry_country_va' => 'Ватикана',
+ 'UserCountry_country_vc' => 'Сейнт Винсент и Гренадини',
+ 'UserCountry_country_ve' => 'Венецуела',
+ 'UserCountry_country_vg' => 'Британски Вирджински острови',
+ 'UserCountry_country_vi' => 'Американски Вирджински острови',
+ 'UserCountry_country_vn' => 'Виетнам',
+ 'UserCountry_country_vu' => 'Вануату',
+ 'UserCountry_country_wf' => 'Уолис и Футуна',
+ 'UserCountry_country_ws' => 'Самоа',
+ 'UserCountry_country_ye' => 'Йемен',
+ 'UserCountry_country_yt' => 'Майот',
+ 'UserCountry_country_yu' => 'Югославия',
+ 'UserCountry_country_za' => 'ЮАР',
+ 'UserCountry_country_zm' => 'Замбия',
+ 'UserCountry_country_zr' => 'Зайре',
+ 'UserCountry_country_zw' => 'Зимбабве',
+ 'UserCountry_continent_eur' => 'Европа',
+ 'UserCountry_continent_afr' => 'Африка',
+ 'UserCountry_continent_asi' => 'Азия',
+ 'UserCountry_continent_ams' => 'Южна и Централна Америка',
+ 'UserCountry_continent_amn' => 'Северна Америка',
+ 'UserCountry_continent_oce' => 'Океания',
+ 'VisitsSummary_VisitsSummary' => 'Резюме на посещенията',
+ 'VisitsSummary_NbVisits' => '%s посещения',
+ 'VisitsSummary_NbUniqueVisitors' => '%s уникални посетителя',
+ 'VisitsSummary_NbActions' => '%s дейстивя (разглеждания на страници)',
+ 'VisitsSummary_TotalTime' => '%s тотално време прекарано от посетителите',
+ 'VisitsSummary_MaxNbActions' => '%s макс. действия при едно посещение',
+ 'VisitsSummary_NbVisitsBounced' => '%s посещения са отскочили (напуснали още след първата разгледана страница)',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Развитие за последните %s',
+ 'VisitsSummary_Report' => 'Справка',
+ 'VisitsSummary_GenerateTime' => '%s секунди за генериране на страницата',
+ 'VisitsSummary_GenerateQueries' => '%s заявки са изпълнени',
+ 'VisitsSummary_WidgetLastVisits' => 'Последни посетители',
+ 'VisitsSummary_WidgetVisits' => 'Резюме на посещенията',
+ 'VisitsSummary_WidgetLastVisitors' => 'Последни уникални посетители',
+ 'VisitsSummary_WidgetOverviewGraph' => 'Резюме с графика',
+ 'VisitsSummary_SubmenuOverview' => 'Резюме',
+ 'VisitFrequency_Evolution' => 'Развитие за периода',
+ 'VisitFrequency_ColumnReturningVisits' => 'Върнали се посетители',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Действия от Върнали се посетители',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Макс. действия от върнали се посетители',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Прекарано време от Върнали се посетители (в секунди)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Bounce rate за върнали се посетители',
+ 'VisitFrequency_ReturnVisits' => '%s върнали се посетители',
+ 'VisitFrequency_ReturnActions' => '%s действия от върнали се посетители',
+ 'VisitFrequency_ReturnMaxActions' => '%s макс. действие от върнали се посетители',
+ 'VisitFrequency_ReturnTotalTime' => '%s тотално време прекарано от върнали се посетители',
+ 'VisitFrequency_ReturnBounceRate' => '%s върнали се потребители, които са отскочили (напуснали са сайта още след първата страница)',
+ 'VisitFrequency_WidgetOverview' => 'Резюме на честотата',
+ 'VisitFrequency_WidgetGraphReturning' => 'Графика на върналити се посещения',
+ 'VisitFrequency_SubmenuFrequency' => 'Честота',
+ 'VisitTime_LocalTime' => 'Посещения по локално време',
+ 'VisitTime_ServerTime' => 'Посещения по сървърно време',
+ 'VisitTime_ColumnServerTime' => 'Сървърно време (на сървъра)',
+ 'VisitTime_ColumnLocalTime' => 'Локално време (на посетителя)',
+ 'VisitTime_WidgetLocalTime' => 'Посещения по локално време',
+ 'VisitTime_WidgetServerTime' => 'Посещения по сървърно време',
+ 'VisitTime_SubmenuTimes' => 'Време',
+ 'VisitTime_NHour' => '%sч',
+ 'VisitorInterest_VisitsPerDuration' => 'Посещения по продължителност',
+ 'VisitorInterest_VisitsPerNbOfPages' => 'Посещения по прегледани страници',
+ 'VisitorInterest_ColumnVisitDuration' => 'Продължителност на посещение',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Импресии / Посещения',
+ 'VisitorInterest_WidgetLengths' => 'Продължителност на посещенията',
+ 'VisitorInterest_WidgetPages' => 'Импресии / Посещения',
+ 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Честота & Лоялност',
+ 'VisitorInterest_PlusXMin' => '%s мин',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s мин',
+ 'VisitorInterest_OnePage' => '1 страница',
+ 'VisitorInterest_NPages' => '%s страници',
+ 'VisitorInterest_BetweenXYSeconds' => '%1s-%2sс',
+ 'Login_LoginPasswordNotCorrect' => 'Потребителското име & Паролата не са верни',
+ 'Login_Login' => 'Потребителско име',
+ 'Login_Password' => 'Парола',
+ 'Login_PasswordRepeat' => 'Парола (повторно)',
+ 'Login_ChangePassword' => 'Смяна на парола',
+ 'Login_LoginOrEmail' => 'потребителско име или имейл',
+ 'Login_LogIn' => 'Вход',
+ 'Login_Logout' => 'Изход',
+ 'Login_LostYourPassword' => 'Забравена парола?',
+ 'Login_RemindPassword' => 'Изпрати',
+ 'Login_PasswordResetToken' => 'Паролата възстанови token',
+ 'Login_PasswordReminder' => 'Въведете вашето потребителско име или имейл. Ние ще изпратим информация как да смените паролата си.',
+ 'Login_PasswordsDoNotMatch' => 'Паролите не съвпадат.',
+ 'Login_PasswordSuccessfullyChanged' => 'Паролата успешно е сменена!',
+ 'Login_InvalidUsernameEmail' => 'Грешно потребителско име и/или имейл адрес',
+ 'Login_InvalidOrExpiredToken' => 'Token е грешен или изтекъл',
+ 'Login_MailTopicPasswordRecovery' => 'Възстановяване на парола',
+ 'Login_MailPasswordRecoveryBody' => 'Здравей %s,
+
+Искането за възстановяване на парола генерира формуляр, който трябва да попълните %s.
+
+За да възстановите паролата си:
+
+1) Отидете на Възстановяване на парола от тук:
+ %s
+
+2) Въведете следния token:
+ %s
+
+3) Попълнете формуляра (въведете паролата си) и изпратете.
+
+Забележка: този token ще изтече след 24 часа.
+',
+ 'Login_PasswordSent' => 'Информацията относно възтановяването на парлата в изпратена. Проверете електронната си поща.',
+ 'Login_ContactAdmin' => 'Възможни причини: функцията mail() е липсваща или забранена на сървъра. <br />Свържете се с вашия Piwik администратор.',
+ 'UsersManager_UsersManagement' => 'Управление на потребители',
+ 'UsersManager_UsersManagementMainDescription' => 'Създайте нови потребители или управлявайте вече съществуващи. Също така и можете да задавате правата за достъп.',
+ 'UsersManager_ManageAccess' => 'Управление на правата',
+ 'UsersManager_MainDescription' => 'Можете да управлявате правата на потребителите в Piwik, които да имат достъп до статистиките на вашия сайт. Също така можете да зададете права над всички сайтове.',
+ 'UsersManager_Sites' => 'Сайтове',
+ 'UsersManager_AllWebsites' => 'Всички сайтове',
+ 'UsersManager_ApplyToAllWebsites' => 'Запомни за всички сайтове',
+ 'UsersManager_User' => 'Потребител',
+ 'UsersManager_PrivNone' => 'Без права',
+ 'UsersManager_PrivView' => 'Гледане',
+ 'UsersManager_PrivAdmin' => 'Админ',
+ 'UsersManager_ChangeAllConfirm' => 'Сигрен ли сте, че искате да промените на \'%s\' правата за всички сайтове?',
+ 'UsersManager_Login' => 'Име',
+ 'UsersManager_Password' => 'Парола',
+ 'UsersManager_Email' => 'Имейл',
+ 'UsersManager_Alias' => 'Псевдоним',
+ 'UsersManager_Edit' => 'Редактирай',
+ 'UsersManager_AddUser' => 'Добави нов потребител',
+ 'UsersManager_MenuUsers' => 'Потребители',
+ 'UsersManager_DeleteConfirm_js' => 'Наистина ли искате да изтриете потребителя %s?',
+ 'UsersManager_ExceptionLoginExists' => 'Потребител с име \'%s\' вече съществува.',
+ 'UsersManager_ExceptionEmailExists' => 'Потребител с имейл \'%s\' вече съществува.',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'Потребителското име трябва да бъде между %s и %s символа дълго и може да съдържа само букви, цифри и/или символите \'_\' и/или \'-\' и/или \'.\'',
+ 'UsersManager_ExceptionInvalidPassword' => 'Дължината на паролата трябва да бъде между 6 и 26 символа.',
+ 'UsersManager_ExceptionInvalidEmail' => 'Имейла, който сте въвели не е валиден.',
+ 'UsersManager_ExceptionDeleteDoesNotExist' => 'Потребителя \'%s\' несъществува, по тази причина не може да бъде изтрит.',
+ 'UsersManager_ExceptionAdminAnonymous' => 'Не може да зададете \'админ\' права на \'анонимен\' потребител.',
+ 'UsersManager_ExceptionEditAnonymous' => 'Анонимният потебител не може да бъде редактиран или изтрит. Piwik по този начин дефинира в система потребители, които не са логнати. Например можете да направите данните на брояча ви публични, като зададете \'view\' права на \'анонимния\' потребител.',
+ 'UsersManager_ExceptionSuperUser' => 'Този потребител е СУПЕР ПОТРЕБИТЕЛ - не може да бъде редактиран и изтрит през API. Можете ръчно да редактирате СУПЕР ПОТРЕБИТЕЛ от конфигурационния файл на Piwik.',
+ 'UsersManager_ExceptionUserDoesNotExist' => 'Потребителя \'%s\' не съществува.',
+ 'UsersManager_ExceptionAccessValues' => 'Този параметър може да има само един от следните параметри : [ %s ]',
+ 'SitesManager_Sites' => 'Сайтове',
+ 'SitesManager_WebsitesManagement' => 'Управление на сайтове',
+ 'SitesManager_MainDescription' => 'За да работи брояча е необходимо да добавите САЙТОВЕ! Добавете, редактирайте, изтрийте Сайт и вземете кода за вмъкване.',
+ 'SitesManager_JsTrackingTag' => 'JavaScript код',
+ 'SitesManager_JsTrackingTagHelp' => 'JavaScript кода, който трябва да вмъкнете във всички страници',
+ 'SitesManager_ShowTrackingTag' => 'покажи кода за вмъкване',
+ 'SitesManager_NoWebsites' => 'Вие нямате сайт, който да администрирате.',
+ 'SitesManager_AddSite' => 'Добави нов сайт',
+ 'SitesManager_Id' => 'Ид',
+ 'SitesManager_Name' => 'Име',
+ 'SitesManager_Urls' => 'Адреси',
+ 'SitesManager_MenuSites' => 'Сайтове',
+ 'SitesManager_DeleteConfirm_js' => 'Наистина ли искате да изтриете този сайт %s?',
+ 'SitesManager_ExceptionDeleteSite' => 'Не е възможно да изтриете този сайт, защото той е единствения регистриран в системата. Преди да изтриете този сайт е нужно да добавите нов сайт.',
+ 'SitesManager_ExceptionNoUrl' => 'Необхогимо е да въведете поне един адрес (URL) за сайта.',
+ 'SitesManager_ExceptionEmptyName' => 'Полето за име на сайт не може да бъде празно.',
+ 'SitesManager_ExceptionInvalidUrl' => 'Адреса \'%s\' не е валиден.',
+ 'Installation_Installation' => 'Инсталация',
+ 'Installation_InstallationStatus' => 'Състояние на инсталацията',
+ 'Installation_PercentDone' => '%s %% развитие',
+ 'Installation_NoConfigFound' => 'Piwik конфигурационният файл не е открит.<br /><b>&nbsp;&nbsp;&raquo; Можете да <a href=\'index.php\'>инсталирате Piwik сега</a></b><br /><small>Ако преди това сте инсталирали Piwik и имате в базата от данни (БД) таблици - можете да запазите вашите данни!</small>',
+ 'Installation_DatabaseSetup' => 'Настройки на базата от данни (БД)',
+ 'Installation_DatabaseErrorConnect' => 'ГРЕШКА! Няма връзка с БД сървъра ',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'Връзката към базата от данни (БД) не е UTF8',
+ 'Installation_JsTag' => 'JavaScript код',
+ 'Installation_JsTagHelp' => '<p>За да се отчитат всички посетители, трябва JavaScript кода да е добавен във всички страници на вашия сайт.</p><p>Вашият сайт не е необходимо да е разработен на PHP, Piwik работи на всички платформи и езици (независимо какво използвате: HTML, ASP, Perl или някой друг език и/или технология).</p><p>Това е кода, който трябва да добавите: (копирайте и го поставете във всички страници на сайта) </p>',
+ 'Installation_JsTagQuicHelpk' => 'Бърза помощ',
+ 'Installation_JsTagArchivingHelp' => 'За средно и силно натоварените сайтове, вижте: <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">Какви настройки да използваме за архивиране на данните</a> за да заема по-малко ресурси Piwik и работи по-бързо!',
+ 'Installation_Congratulations' => 'Поздравления',
+ 'Installation_CongratulationsHelp' => '<p>Поздравления! Инсталацията на вашия Piwik завърши.</p><p>Убедете се, че сте добавили вашия JavaScript код в сайта!</p>',
+ 'Installation_ContinueToPiwik' => 'Продължете към Piwik',
+ 'Installation_SetupWebsite' => 'Настройки на сайт',
+ 'Installation_SetupWebsiteError' => 'Възникнала е грешка при добавянето на сайт',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Сайта %s е добавен успешно!',
+ 'Installation_GeneralSetup' => 'Основни настройки',
+ 'Installation_GeneralSetupSuccess' => 'Основните настройки са създадени успешно',
+ 'Installation_SuperUserLogin' => 'СУПЕР ПОТРЕБИТЕЛСКИ вход',
+ 'Installation_Password' => 'парола',
+ 'Installation_PasswordRepeat' => 'парола (повторно)',
+ 'Installation_Email' => 'имейл',
+ 'Installation_SecurityNewsletter' => 'изпращай на имейл информация за обновленията и сигнали относно сигурността',
+ 'Installation_CommunityNewsletter' => 'изпращай на имейл информация за нови плъгини, функции и др.',
+ 'Installation_PasswordDoNotMatch' => 'паролата не съвпада',
+ 'Installation_SubmitGo' => 'Инсталирай!',
+ 'Installation_Requirements' => 'Piwik Изисквания',
+ 'Installation_Optional' => 'По избор',
+ 'Installation_Legend' => 'Легенда',
+ 'Installation_Extension' => 'разширения',
+ 'Installation_SystemCheck' => 'Проверка на системата',
+ 'Installation_SystemCheckPhp' => 'PHP версия',
+ 'Installation_SystemCheckExtensions' => 'Други необходими разширения',
+ 'Installation_SystemCheckDatabaseHelp' => 'Необходимо е за да инстаалирате Piwik базата от данни(БД) да поддържа mysqli или PDO и pdo_mysql разширенията.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'За Linux сървър компилирайте php със следните опции: %s
+In въ вашия php.ini, добавете следните редове: %s',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Повече информация: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> и <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'За Windows сървър добавете следните редове в php.ini: %s',
+ 'Installation_SystemCheckSplHelp' => 'Трябва да конфигурирате PHP - Standard PHP Library (SPL) да се поддържа (по подразбиране).',
+ 'Installation_SystemCheckZlibHelp' => 'Трябва да конфигурирате PHP "zlib" да се поддържа, --със-zlib.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'Трябва да конфигурирате PHP да поддържа или "json" или "xml" разширенията.',
+ 'Installation_SystemCheckJsonSite' => 'Повече информация: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Някои плъгини, услуги и библиотеки изискват "xml".',
+ 'Installation_SystemCheckXmlSite' => 'Повече информация в: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckWriteDirs' => 'Директории с права за писане',
+ 'Installation_SystemCheckWriteDirsHelp' => 'За да поправите тази грешка (на Linux сървър), опитайте със следните команди',
+ 'Installation_SystemCheckMemoryLimit' => 'Лимит на паметта',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'За силно натоварените сайтове, времето за архивиране на данните отнема повече ресурси. Ако е необходимо моля редактирайте memory_limit директивата в php.ini.',
+ 'Installation_SystemCheckOpenURL' => 'Отворен адрес(URL)',
+ 'Installation_SystemCheckOpenURLHelp' => 'Новините, съобщенията за обновления и автоматичното обновяване за да функционират е необходимо сървъра да поддържа "curl" разширение, allow_url_fopen=On, или fsockopen() да бъдат поддържани.',
+ 'Installation_SystemCheckGD' => 'GD &gt; 2.x (graphics)',
+ 'Installation_SystemCheckGDHelp' => 'Sparklines (малки графики) няма да работят.',
+ 'Installation_SystemCheckFunctions' => 'Необходими функции',
+ 'Installation_SystemCheckTimeLimitHelp' => 'За силно натоварените сайтове, времето за архивиране на данните отнема повече време. Ако е необходимо моля редактирайте max_execution_time директивата в php.ini файла.',
+ 'Installation_SystemCheckMailHelp' => 'Модулите Обратна връзка и Забравена парола не биха работили без mail() функцията на PHP.',
+ 'Installation_SystemCheckError' => 'Открита е грешка - трябва да бъде поправена преди да преминете нататък',
+ 'Installation_SystemCheckWarning' => 'Piwik ще работи нормално, но някои услуги ще липсват',
+ 'Installation_Tables' => 'Създаване на таблици',
+ 'Installation_TablesWithSameNamesFound' => 'Някои %s таблици в базата от данни (БД) %s имат същите имена, както тези, които Piwik се опитва да създаде',
+ 'Installation_TablesFound' => 'Следните таблици бяха открити в базата от данни (БД)',
+ 'Installation_TablesWarningHelp' => 'Изберете дали да обновите данните в съществуващите таблици или да инсталирате Piwik на чисто.',
+ 'Installation_TablesReuse' => 'Използвай съществуващите таблици',
+ 'Installation_TablesDelete' => 'Изтрий съществуващите таблици',
+ 'Installation_TablesDeletedSuccess' => 'Съществуващите Piwik таблици бяха изтрити усшешно',
+ 'Installation_TablesCreatedSuccess' => 'Таблиците са създадени успешно!',
+ 'Installation_DatabaseCreatedSuccess' => 'Базата от данни (БД) %s е създадена успешно!',
+ 'Installation_GoBackAndDefinePrefix' => 'Върнете се за да зададете Prefix за Piwik таблиците в базата от данни (БД)',
+ 'Installation_ConfirmDeleteExistingTables' => 'Наистина ли искате да изтриете следните таблици: %s от базата от данни (БД)? ПРЕДУПРЕЖДЕНИЕ: ДАННИТЕ ОТ ТАЗИ ТАБЛИЦА НЕ МОГАТ ДА БЪДАТ ВЪЗСТАНОВЕНИ!!!',
+ 'Installation_Welcome' => 'Добре дошли!',
+ 'Installation_WelcomeHelp' => '<p>Piwik е анализатор (уеб брояч) с отворен код, който гъвкаво и лесно предоставя информация за посетителите на сайта ви.</p><p>Този процес е съкратен в %s лесни стъпки и не отнема повече от 5 минути.</p>',
+ 'Installation_ErrorInvalidState' => 'Грешка: възможно е да сте опитали да прескочите стъпка от инсталацията или е забранена поддръжката на бисквитките (cookies) или конфигурационният файл на Piwik вече съществува. %sПроверете дали са разрешени бисквитките (cookies)%s и се върнете %s на първата страница на инсталацията%s.',
+ 'Provider_WidgetProviders' => 'Провайдъри',
+ 'Provider_ColumnProvider' => 'И-нет доставчик',
+ 'Provider_SubmenuLocationsProvider' => 'Локация & провайдър',
+ 'Goals_ColumnConversions' => 'Конверсия',
+ 'Goals_ColumnConversionRate' => 'Стойност на Конверсия',
+ 'Goals_ColumnRevenue' => 'Приход',
+ 'DBStats_DatabaseUsage' => 'Натоварване на БД',
+ 'DBStats_MainDescription' => 'Piwik съхранява цялата информация в MySQL база от данни (БД). В момента Piwik таблиците използват %s.',
+ 'DBStats_Table' => 'Таблици',
+ 'DBStats_RowNumber' => 'Брой клетки',
+ 'DBStats_DataSize' => 'Данни (размер)',
+ 'DBStats_IndexSize' => 'Индекс (размер)',
+ 'DBStats_TotalSize' => 'Общ размер',
+ 'TranslationsAdmin_MenuTranslations' => 'Преводи',
+ 'TranslationsAdmin_MenuLanguages' => 'Езици',
+ 'TranslationsAdmin_Plugin' => 'Плъгин',
+ 'TranslationsAdmin_Definition' => 'Дефиниция',
+ 'TranslationsAdmin_DefaultString' => 'По подразбиране (Английски)',
+ 'TranslationsAdmin_TranslationString' => 'Превод (текущ език: %s)',
+ 'TranslationsAdmin_Translations' => 'Преводи',
+ 'TranslationsAdmin_FixPermissions' => 'Моля поправете правата над файловата система',
+ 'TranslationsAdmin_AvailableLanguages' => 'Налични езици',
+ 'TranslationsAdmin_AddLanguage' => 'Добави език',
+ 'TranslationsAdmin_LanguageCode' => 'Код на езика',
+ 'TranslationsAdmin_Export' => 'Експортирай език',
+ 'TranslationsAdmin_Import' => 'Импортирай език',
+ 'General_Dashboard' => 'Табло',
+ 'General_DashboardForASpecificWebsite' => 'Табло за определен сайт',
+ 'General_MultiSitesSummary' => 'Всички сайтове',
+ 'General_AllWebsitesDashboard' => 'Табло за всички сайтове',
+ 'General_NotValid' => '%s не е валиден',
+ 'General_Username' => 'Потребител',
+ 'General_Details' => 'Детайли',
+ 'General_Default' => 'По подразбиране',
+ 'General_GoTo' => 'Към %s',
+ 'General_YourChangesHaveBeenSaved' => 'Промените бяха запазени.',
+ 'General_ExportAsImage_js' => 'Експортиране като изображение',
+ 'General_SaveImageOnYourComputer_js' => 'За да запазите изображението на вашият компютър, натиснете с десен бутон на изображението и изберете "Save Image As..."',
+ 'General_Today' => 'Днес',
+ 'General_Yesterday' => 'Вчера',
+ 'General_CurrentWeek' => 'Тази Седмица',
+ 'General_CurrentMonth' => 'Този Месец',
+ 'General_CurrentYear' => 'Тази Година',
+ 'General_PageBounceRateDefinition' => 'Процента посетители посетили тази страница и напуснали веднага след това.',
+ 'General_ColumnExitRate' => '',
+ 'General_PageExitRateDefinition' => '',
+ 'General_ColumnBounces' => '',
+ 'General_BouncesDefinition' => 'Броят посещения на тази страница и излезли веднага след това.',
+ 'General_ColumnEntrances' => '',
+ 'General_EntrancesDefinition' => '',
+ 'General_ColumnExits' => '',
+ 'General_ExitsDefinition' => '',
+ 'General_ColumnAverageTimeOnPage' => '',
+ 'General_AverageTimeOnPageDefinition' => 'Средният период прекарано време в сайта от посетителите',
+ 'General_DaysHours' => '%1$s дни %2$s часа',
+ 'General_HoursMinutes' => '%1$s часа %2$s мин.',
+ 'General_MinutesSeconds' => '%1$s мин. %2$sс',
+ 'General_Seconds' => '%sс',
+ 'General_ForExampleShort' => '',
+ 'General_GeneralSettings' => 'Основни Настройки',
+ 'General_AllowPiwikArchivingToTriggerBrowser' => 'Разреши Piwik архивиране, веднага след като докладите бъдат гледани от Броузер',
+ 'General_ArchivingInlineHelp' => 'За сайтовете с среден или висок трафик, препоръчваме да изключите Piwik архивиране след гледане от броузер. Съветваме ви в този случай да използвате cron job за вашите доклади на всеки час.',
+ 'General_ArchivingTriggerDescription' => 'За по-големи Piwik инсталации, се препоръчва %scron job%s за автоматични доклади.',
+ 'General_SeeTheOfficialDocumentationForMoreInformation' => 'Прегледайте %sofficial documentation%s за повече информация',
+ 'General_ReportsForTodayWillBeProcessedAtMostEvery' => '',
+ 'General_NSeconds' => '%s секунди',
+ 'General_SmallTrafficYouCanLeaveDefault' => 'За сайтове с малък трафик, може да оставите по подразбиране %s секунди, както и достъп до всички доклади в реално време.',
+ 'General_MediumToHighTrafficItIsRecommendedTo' => '',
+ 'General_RequiresFlash' => 'За да виждате графиките в Piwik се нуждаете от Flash',
+ 'General_GraphHelp' => 'Повече информация за показаните графики в Piwik.',
+ 'General_DisplayGoals' => 'Покажи Целите',
+ 'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin' => '%s е на разположение. Моля уведомете администратора на сайта.',
+ 'General_ConfigFileIsNotWritable' => 'Конфигурационният файл %s на Piwik не е достъпен и вашите настройки няма да бъдат запазени. %s Моля променете правата на файла, така, че да може да се пише в него.',
+ 'General_ExceptionDatabaseVersion' => '',
+ 'General_ExceptionIncompatibleClientServerVersions' => '',
+ 'General_ExceptionMissingFile' => 'Липсващ файл: %s',
+ 'General_ExceptionFilesizeMismatch' => '',
+ 'General_ExceptionFileIntegrity' => '',
+ 'General_ExceptionNonceMismatch' => '',
+ 'General_WarningFileIntegritySkipped' => '',
+ 'General_WarningFileIntegrityNoManifest' => '',
+ 'General_WarningFileIntegrityNoMd5file' => '',
+ 'General_FileIntegrityWarningExplanation' => '',
+ 'ExampleFeedburner_PluginDescription' => 'Примерен Plugin: Как да се показват вашите Feedburner абонати в джаджа на Таблото?',
+ 'Dashboard_PluginDescription' => 'Табло на вашият Уеб Анализатор. Можете да персонализирате вашето Табло: да добавяте нови джаджи, да променяте подредбата им. Всеки потребител има достъп до своето собствено Табло.',
+ 'CoreUpdater_PluginDescription' => 'Механизъм за актуализиране на Piwik',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Важна бележка за големи Piwik инсталации',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'Ако имате голяма Piwik база данни, актуализирането и може да отнеме прекалено много време, ако я стартирате през вашият броузер. В този случай, можете да извършите актуализацията чрез команден ред: %s',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => '',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => '',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => '',
+ 'CoreUpdater_ReadyToGo' => 'Готови ли сте?',
+ 'Provider_PluginDescription' => 'Доклад за Провайдърите на посетителите.',
+ 'UsersManager_PluginDescription' => '',
+ 'UsersManager_TheSuperUserAliasCannotBeChanged' => 'Псевдонимът не може да бъде променян.',
+ 'UsersManager_ReportToLoadByDefault' => '',
+ 'UsersManager_ReportDateToLoadByDefault' => '',
+ 'UsersManager_ForAnonymousUsersReportDateToLoadByDefault' => '',
+ 'UsersManager_ExcludeVisitsViaCookie' => 'Изключете вашите посещения с помощта на бисквитка',
+ 'UsersManager_YourVisitsAreIgnoredOnDomain' => '',
+ 'UsersManager_YourVisitsAreNotIgnored' => '%sВашите посещения не се игнорират от Piwik%s(Бисквитката за игнориране на вашите посещения, не е открита в вашият броузер).',
+ 'UsersManager_ClickHereToDeleteTheCookie' => 'Натиснете тук за да изтриете бисквитката и Piwik да отчита вашите посещения',
+ 'UsersManager_ClickHereToSetTheCookieOnDomain' => 'Натиснете тук за да запазите бисквитка, което ви гарантира, че вашите посещения ще се отчитат от Piwik в %s',
+ 'UsersManager_MenuUserSettings' => 'Потребителски настройки',
+ 'UsersManager_MenuAnonymousUserSettings' => '',
+ 'UsersManager_NoteNoAnonymousUserAccessSettingsWontBeUsed' => '',
+ 'UsersManager_WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess' => '',
+ 'UsersManager_ChangePassword' => 'Нова парола',
+ 'UsersManager_IfYouWouldLikeToChangeThePasswordTypeANewOne' => 'Ако желаете да промените паролата си, въведете нова. В противен случай оставете полето празно.',
+ 'UsersManager_TypeYourPasswordAgain' => 'Вашата нова парола отново.',
+ 'UsersManager_TheLoginScreen' => '',
+ 'UsersManager_YourUsernameCannotBeChanged' => 'Потребителското име не може да се променя.',
+ 'Feedback_PluginDescription' => 'Изпратете обратна връзка към Piwik Team. Споделете вашите идеи и предложения с нас!',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Желаете да докладвате за грешка или имате предложение?',
+ 'Feedback_ViewAnswersToFAQ' => 'Вижте някой от отговорите в %sЧесто Задавани Въпроси%s',
+ 'Feedback_WhyAreMyVisitsNoTracked' => 'Защо посещенията в сайта ми не се отчитат?',
+ 'Feedback_HowToExclude' => 'Как мога да изключа моите посещения от доклада?',
+ 'Feedback_WhyWrongCountry' => 'Защо Piwik не отчита правилно държавата от която съм?',
+ 'Feedback_HowToAnonymizeIP' => 'Как да маскирам IP адресите в моята база данни?',
+ 'Feedback_VisitTheForums' => 'Посетете нашият %sФорум%s',
+ 'Feedback_LearnWaysToParticipate' => 'Научете повече за начините, как бихте могли да %sучаствате%s',
+ 'Feedback_SpecialRequest' => 'Имате ли специална молба към Piwik Team?',
+ 'Feedback_ContactThePiwikTeam' => 'Свържете се с Piwik Team!',
+ 'Feedback_IWantTo' => 'Желая да:',
+ 'Feedback_CategoryShareStory' => 'Споделете вашата успешна Piwik история',
+ 'Feedback_CategorySponsor' => 'Piwik Спонсор',
+ 'Feedback_CategoryHire' => 'Наемане на Piwik консултант',
+ 'Feedback_CategorySecurity' => 'Докладвай проблем в сигурността',
+ 'Feedback_MyEmailAddress' => 'Моят email адрес:',
+ 'Feedback_MyMessage' => 'Моето съобщение:',
+ 'Feedback_DetailsPlease' => '(моля приложете детайли)',
+ 'Feedback_SendFeedback' => 'Изпрати съобщението',
+ 'Feedback_ManuallySendEmailTo' => 'Моля изпратете ръчно вашето съобщение до',
+ 'Feedback_MessageSent' => 'Вашето съобщение е изпратено до Piwik Team.',
+ 'Feedback_ThankYou' => 'Благодаря, че помогнахте да направим Piwik по-добър!',
+ 'Feedback_ThePiwikTeam' => 'Piwik Team',
+ 'Feedback_ExceptionBodyLength' => 'Съобщението трябва да бъде дълго поне %s символа.',
+ 'Feedback_ExceptionNoUrls' => 'За да се избегнат спам съобщения, не може да добавяте URL адрес в вашето съобщение.',
+ 'Actions_PluginDescription' => 'Доклади за посещения, изходящи връзки и сваляния. Изходящите връзки и Свалянията се отчитат автоматично!',
+ 'Actions_SubmenuPagesEntry' => '',
+ 'Actions_SubmenuPagesExit' => '',
+ 'Actions_SubmenuPageTitles' => '',
+ 'Actions_ColumnPageURL' => 'Страница URL',
+ 'API_PluginDescription' => 'Цялата информация от Piwik е достъпна чрез просто API. Тази добавка ви дава възможност да получите данни от вашият Уеб Анализатор под формата на xml,json,php,cvs и др.',
+ 'ExampleAPI_PluginDescription' => 'Примерен Плугин: Как да създадете API за вашият плугин, за да извличате данни под всякакъв формат, без да е нужно специално кодиране?',
+ 'Live_PluginDescription' => 'Следете вашите посетители, на живо, в реално време!',
+ 'Live_VisitorLog' => '',
+ 'Live_Date' => 'Дата',
+ 'Live_Time' => 'Време',
+ 'Live_Referrer_URL' => 'URL Реферации',
+ 'Live_Last30Minutes' => 'Последни 30 минути',
+ 'ExamplePlugin_PluginDescription' => 'Примерен Плугин: Как да създадете прост плугин, който да изнесе две джаджи на вашето Табло.',
+ 'ExamplePlugin_exampleWidgets' => 'Примерни Джаджи',
+ 'ExamplePlugin_exampleWidget' => 'Примерна джаджа',
+ 'ExamplePlugin_blogPiwikRss' => 'RSS от блога на Piwik',
+ 'ExamplePlugin_photostreamMatt' => 'Снимките на Мат',
+ 'UserCountry_PluginDescription' => 'Доклад за Държавите на вашите посетители.',
+ 'UserCountry_country_ax' => 'Аландските острови',
+ 'UserCountry_country_bl' => 'Сен Бартелеми',
+ 'UserCountry_country_bu' => 'Бирма',
+ 'UserCountry_country_cp' => 'Остров Клипертон',
+ 'UserCountry_country_dg' => 'Диего Гарсия',
+ 'UserCountry_country_ea' => 'Сеута, Мелила',
+ 'UserCountry_country_eu' => 'Европейски съюз',
+ 'UserCountry_country_fx' => 'Франция, Метрополитен',
+ 'UserCountry_country_ic' => 'Канарски острови',
+ 'UserCountry_country_me' => 'Монтенегро',
+ 'UserCountry_country_mf' => 'Сейнт Мартин',
+ 'UserCountry_country_nt' => 'Неутрална зона',
+ 'UserCountry_country_sf' => 'Финландия',
+ 'UserCountry_country_ta' => 'Тристан да Куня',
+ 'UserCountry_country_tl' => 'Източен Тимор',
+ 'VisitTime_PluginDescription' => 'Доклад за сървърно и местно време. Сървърното време, може да бъде полезно при предвиждане на спиране за поддръжка на сайта.',
+ 'VisitorInterest_PluginDescription' => 'Статистики за посетителите: разгледани страници, прекарано време в сайта.',
+ 'VisitorInterest_Engagement' => 'Ангажимент',
+ 'VisitFrequency_PluginDescription' => 'Статистики на Завърналите се посетители срещу уникалните посетители.',
+ 'TranslationsAdmin_PluginDescription' => 'Помощ за Piwik превода на вашият език.',
+ 'CoreAdminHome_PluginDescription' => 'Администраторски панел на Piwik',
+ 'CoreAdminHome_MenuGeneralSettings' => 'Основни настройки',
+ 'CoreAdminHome_Administration' => 'Администрация',
+); \ No newline at end of file
diff --git a/lang/ca.php b/lang/ca.php
index 012661f54c..64f8575e32 100644
--- a/lang/ca.php
+++ b/lang/ca.php
@@ -20,7 +20,7 @@ $translations = array(
'General_Done' => 'Fet',
'General_LoadingData' => 'Les dades s\'estan carregant&hellip;',
'General_ErrorRequest' => 'Ups! Hi ha hagut un problema amb la sol&middot;licitud, torneu-ho a intentar.',
- 'General_Next' => 'Seg&uuml;ent',
+ 'General_Next' => 'Següent',
'General_Previous' => 'Anterior',
'General_Search' => 'Cerca',
'General_Others' => 'Altres',
@@ -139,7 +139,7 @@ $translations = array(
'CoreHome_DaySa_js' => 'ds',
'CoreHome_MonthJanuary_js' => 'Gener',
'CoreHome_MonthFebruary_js' => 'Febrer',
- 'CoreHome_MonthMarch_js' => 'Mar&ccedil;',
+ 'CoreHome_MonthMarch_js' => 'Març',
'CoreHome_MonthApril_js' => 'Abril',
'CoreHome_MonthMay_js' => 'Maig',
'CoreHome_MonthJune_js' => 'Juny',
@@ -199,6 +199,21 @@ $translations = array(
'CoreUpdater_InstallingTheLatestVersion' => 'S\'està instal·lant la darrera versió',
'CoreUpdater_PiwikUpdatedSuccessfully' => 'El Piwik s\'ha actualitzat correctament!',
'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'L\'actualització en un clic del Piwik ha estat cancel·lada. Si no podeu arreglar l\'error de més amunt, us recomanem que actualitzeu el Piwik manualment. %s Si us plau, mireu-vos la %sDocumentació d\'actualització (en anglès)%s per a començar!',
+ 'CoreUpdater_TheUpgradeProcessMayFail' => 'Si teniu una base de dades molt gran, les actualitzacions poden trigar massa temps en acabar a través del navegador. En aquesta situació podeu executar les actualitzacions des del terminal:
+<code>$ php path/to/piwik/index.php</code>',
+ 'CoreUpdater_ErrorDIYHelp' => 'Si sou un usuari avançat i trobeu un error en l\'actualització de la base de dades:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'identifiqueu i corregiu l\'origen de l\'error (per exemple: memory_limit o max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'executeu les consultes restants de l\'actualització que han fallat',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'actualitzeu la taula `option` de la base de dades del Piwik, introduint la versió que ha fallat a l\'hora d\'actualitzar a version_core',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'torneu a engegar l\'actualització (a través del navegador o la línia de comandes) per a continuar amb les actualitzacions restants.',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'informeu sobre el problema (i la solució) per tal que puguem millorar el Piwik',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'S\'està descarregant l\'actualització de %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'S\'està desempacant l\'actualització',
+ 'CoreUpdater_EmptyDatabaseError' => 'La base de dades %s està buida. Heu d\'editar o esborrar el fitxer de configuració del Piwik.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'El Piwik està actualitzat a la versió %s.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Arxiu incompatible: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Arxiu buit',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'L\'arxiu és incomplet: manquen alguns fitxers (per exemple, %s).',
'Dashboard_AddWidget' => 'Afegeix un giny&hellip;',
'Dashboard_DeleteWidgetConfirm' => 'Realment voleu esborrar aquest giny?',
'Dashboard_SelectWidget' => 'Escolliu el giny que voleu afegir a la consola',
@@ -223,10 +238,10 @@ $translations = array(
'Goals_ColumnConversions' => 'Conversions',
'Goals_ColumnConversionRate' => 'Raó de conversions',
'Goals_ColumnRevenue' => 'Ingressos',
- 'Installation_Installation' => 'Instal&middot;lació',
- 'Installation_InstallationStatus' => 'Estat de la instal&middot;lació',
+ 'Installation_Installation' => 'Instal·lació',
+ 'Installation_InstallationStatus' => 'Estat de la instal·lació',
'Installation_PercentDone' => '%s%% fet',
- 'Installation_NoConfigFound' => 'No s\'ha trobat el fitxer de configuració del Piwik i esteu intentant accedir una pàgina del Piwik.<br /><strong>&nbsp;&nbsp;&raquo;Podeu <a href=\'index.php\'>instal&middot;lar el Piwik ara</a></strong>.<br /><small>Si heu instal·lat el Piwik abans i teniu algunes taules a la vostra base de dades, no us preocupeu; podeu continuar fent servir les mateixes taules i les dades existents es conservaran!</small>',
+ 'Installation_NoConfigFound' => 'No s\'ha trobat el fitxer de configuració del Piwik i esteu intentant accedir una pàgina del Piwik.<br /><strong>&nbsp;&nbsp;&raquo;Podeu <a href=\'index.php\'>instal&middot;lar el Piwik ara</a></strong>.<br /><small>Si heu instal·lat el Piwik abans i teniu algunes taules a la vostra base de dades, no us amoïneu; podeu continuar fent servir les mateixes taules i les dades existents es conservaran!</small>',
'Installation_MysqlSetup' => 'Configuració de la base de dades MySQL',
'Installation_MysqlErrorConnect' => 'Hi ha hagut un error en l\'intent de connexió amb la base de dades.',
'Installation_JsTag' => 'Etiqueta JavaScript',
@@ -270,17 +285,44 @@ $translations = array(
'Installation_DatabaseCreatedSuccess' => 'La base de dades %s s\'ha creat correctament!',
'Installation_ContinueToPiwik' => 'Vés cap al Piwik',
'Installation_SuperUserLogin' => 'Usuari administrador principal',
- 'Installation_Password' => 'Contrassenya',
- 'Installation_PasswordRepeat' => 'Torneu a escriure la contrassenya',
+ 'Installation_Password' => 'Contrasenya',
+ 'Installation_PasswordRepeat' => 'Torneu a escriure la contrasenya',
'Installation_Email' => 'Correu-e',
'Installation_SecurityNewsletter' => 'Envieu-me correus-e sobre les actualitzacions grans del Piwik i les alertes de seguretat',
'Installation_CommunityNewsletter' => 'Envieu-me correus-e amb les actualitzacions de la comunitat (nous connectors, funcionalitats, etc.)',
- 'Installation_PasswordDoNotMatch' => 'Les contrassenyes no coincideixen',
+ 'Installation_PasswordDoNotMatch' => 'Les contrasenyes no coincideixen',
'Installation_SubmitGo' => 'Vés-hi!',
'Installation_TablesWithSameNamesFound' => 'Algunes %s taules de la base de dades %s tenen el mateix nom que les taules que el Piwik intenta crear',
'Installation_GoBackAndDefinePrefix' => 'Torna enrere i defineix un prefix per a les taules',
'Installation_ConfirmDeleteExistingTables' => 'Realment voleu esborrar les taules %s de la base de dades? AVÍS: NO ES PODRAN RECUPERAR LES DADES!',
'Installation_ErrorInvalidState' => 'Hi ha hagut un error: sembla que esteu intentant saltar-vos un pas de la instal·lació, o teniu les galetes desactivades o el fitxer de configuració del Piwik ja existeix. %sAssegureu-vos que teniu les galetes activades%s i torneu enrera %s al primer pas de la instal·lació %s.',
+ 'Installation_DatabaseSetup' => 'Configuració de la base de dades',
+ 'Installation_DatabaseErrorConnect' => 'Hi ha hagut un error amb la connexió al servidor de bases de dades.',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'La connexió del client al servidor de bases de dades no és UTF8 (unicode)',
+ 'Installation_JsTagQuicHelpk' => 'Ajuda ràpida',
+ 'Installation_JsTagArchivingHelp' => 'Per a llocs amb un tràfic mitjà o alt, visiteu <a target="" href="http://piwik.org/docs/setup-auto-archiving/">Com configurar una pàgina d\'autoarxivació (en anglès)</a> per tal que el Piwik vagi realment ràpid!',
+ 'Installation_SetupWebsiteSetupSuccess' => 'El lloc %s s\'ha creat amb èxit!',
+ 'Installation_Requirements' => 'Requeriments del Piwik',
+ 'Installation_Optional' => 'Opcional',
+ 'Installation_Legend' => 'Llegenda',
+ 'Installation_Extension' => 'extensió',
+ 'Installation_SystemCheckExtensions' => 'Altres extensions necessàries',
+ 'Installation_SystemCheckDatabaseHelp' => 'El Piwik necessita l\'extensió mysqli o ambdues extensións PDO i pdo_mysql.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'En un servidor Linux podeu compilar el php amb les següents opcions: %s Al fitxer php.ini, afegiu les línies: %s',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Trobareu més informació a <a style="color:red" href="http://php.net/pdo">PHP PDO</a> i <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'En un servidor Windows podeu afegir les línies següents al fitxer php.ini: %s',
+ 'Installation_SystemCheckSplHelp' => 'Heu de configurar i recompilar el PHP amb la biblioteca Standard PHP Library (SPL) activada (per defecte).',
+ 'Installation_SystemCheckZlibHelp' => 'Heu de configurar i recompilar el PHP amb el suport per a "zlib" habilitat, --with-zlib.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'Heu de configurar i recompilar el PHP amb les extensions "json" o "xml" activades.',
+ 'Installation_SystemCheckJsonSite' => 'Podeu trobar meś informació a <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Alguns connectors de tercers i biblioteques de desenvolupament poden necessitar l\'extensió "xml".',
+ 'Installation_SystemCheckXmlSite' => 'Podeu trobar meś informació a <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckOpenURL' => 'Obre l\'adreça',
+ 'Installation_SystemCheckOpenURLHelp' => 'Les subscripcions a les llistes de correu, notificacions d\'actualització i actualitzacions en un clic necessiten l\'extensió "curl", allow_url_fopen=On, o fsockopen() actiu.',
+ 'Installation_SystemCheckFunctions' => 'Funcions necessàries',
+ 'Installation_SystemCheckMailHelp' => 'Les opinions i els missatges de pèrdua de la contrassenya no s\'enviaran sense la funció mail().',
'Login_PluginDescription' => 'Pàgina d\'inici de sessió, dóna les credencials als usuaris',
'Login_LoginPasswordNotCorrect' => 'L\'usuari o la contrasenya no són correctes',
'Login_Login' => 'Nom d\'usuari',
@@ -293,10 +335,15 @@ $translations = array(
'Login_PasswordReminder' => 'Si us plau, inseriu el vostre nom d\'usuari o el vostre correu-e. Rebreu una contrasenya nova al vostre correu-e.',
'Login_InvalidUsernameEmail' => 'Aquest usuari i/o direcció de correu-e és invàlid.',
'Login_MailTopicPasswordRecovery' => 'Recuperació de la contrasenya',
- 'Login_MailBodyPasswordRecovery' => 'Hola %1s! La vostra nova contrasenya és %2s<br />Ara ja podeu iniciar la sessió a %3s',
- 'Login_PasswordSent' => 'La contrasenya s\'acaba d\'enviar. Reviseu el vostre correu-e',
+ 'Login_PasswordSent' => 'La informació per a canviar la contrasenya s\'ha enviat. Reviseu el vostre correu-e',
'Login_ContactAdmin' => 'Possiblement sigui perquè el vostre proveïdor d\'allotjament ha desactivat la funció mail().<br />Contacteu amb l\'administrador del lloc.',
- 'Login_MailPasswordRecoveryBody' => 'Hola %1s, \n\n La nova contrasenya que teniu és: %2s \n\n Ja podeu iniciar la vostra sessió a %3s',
+ 'Login_MailPasswordRecoveryBody' => 'Hola %s, una petició de reinicialització de la contrasenya ha estat rebuda de %s. Per a reiniciar-la: 1)Aneu al formulari de reinicialització de contrasenyes a %s 2)Introduïu el següent codi: %s 3)Ompliu el formulari (introduint la nova contrasenya dos cops) i envieu-lo. Nota: el codi caduca en 24 hores.',
+ 'Login_PasswordRepeat' => 'Contrasenya (torneu-la a escriure)',
+ 'Login_ChangePassword' => 'Canvia la contrasenya',
+ 'Login_PasswordResetToken' => 'Codi de reinicialització de la contrasenya.',
+ 'Login_PasswordsDoNotMatch' => 'Les contrasenyes no coincideixen',
+ 'Login_PasswordSuccessfullyChanged' => 'La contrasenya ha estat canviada amb èxit!',
+ 'Login_InvalidOrExpiredToken' => 'El codi és invàlid o ha caducat',
'Provider_WidgetProviders' => 'Proveïdors',
'Provider_SubmenuLocationsProvider' => 'Localitzacions i proveïdors',
'Provider_ColumnProvider' => 'Proveïdor',
@@ -351,15 +398,15 @@ $translations = array(
'SitesManager_AddSite' => 'Afegeix un lloc nou',
'SitesManager_Id' => 'ID',
'SitesManager_Name' => 'Nom',
- 'SitesManager_Urls' => 'URLs',
+ 'SitesManager_Urls' => 'Adreces',
'SitesManager_MenuSites' => 'Llocs',
'SitesManager_DeleteConfirm_js' => 'Realment voleu esborrar el lloc \'%s\'?',
'SitesManager_ExceptionDeleteSite' => 'No és possible eliminar aquest lloc ja que és l\'únic configurat. Afegiu un altre lloc primer i, llavors, ja esborrareu aquest.',
'SitesManager_ExceptionNoUrl' => 'Heu d\'especificar una URL com a mínim.',
'SitesManager_ExceptionEmptyName' => 'El nom del lloc no pot estar buit.',
- 'SitesManager_ExceptionInvalidUrl' => 'La URL \'%s\' no és vàlida.',
+ 'SitesManager_ExceptionInvalidUrl' => 'L\'adreça \'%s\' no és vàlida.',
'SitesManager_WebsitesManagement' => 'Gestiona els llocs',
- 'SitesManager_MainDescription' => 'Els informes d\'anàlisi web necessiten llocs web! Afegiu, actualitzeu i esborreu-ne. Veieu també el codi JavaScript que heu d\'inserir a les pàgines',
+ 'SitesManager_MainDescription' => 'Els informes d\'anàlisi web necessiten llocs web! Afegiu, actualitzeu i esborreu-ne. Veieu també el codi JavaScript que heu d\'inserir a les pàgines.',
'SitesManager_JsTrackingTag' => 'Etiqueta de seguiment JavaScript',
'SitesManager_JsTrackingTagHelp' => 'Aquí teniu l\'etiqueta de seguiment JavaScript per tal d\'incloure-la a totes les pàgines',
'SitesManager_ShowTrackingTag' => 'mostra l\'etiqueta de seguiment',
@@ -522,11 +569,11 @@ $translations = array(
'UserCountry_country_mg' => 'Madagascar',
'UserCountry_country_mh' => 'Illes Marshall',
'UserCountry_country_mk' => 'Macedònia',
- 'UserCountry_country_ml' => 'Mañi',
+ 'UserCountry_country_ml' => 'Mali',
'UserCountry_country_mm' => 'Myanmar',
'UserCountry_country_mn' => 'Mongòlia',
'UserCountry_country_mo' => 'Macau',
- 'UserCountry_country_mp' => 'Illes Mariannes Septentrionals',
+ 'UserCountry_country_mp' => 'Illes Marianes Septentrionals',
'UserCountry_country_mq' => 'Martinica',
'UserCountry_country_mr' => 'Mauritània',
'UserCountry_country_ms' => 'Montserrat',
@@ -543,7 +590,7 @@ $translations = array(
'UserCountry_country_nf' => 'Illa Norfolk',
'UserCountry_country_ng' => 'Nigèria',
'UserCountry_country_ni' => 'Nicaragua',
- 'UserCountry_country_nl' => 'Pa&iuml;sos Baixos',
+ 'UserCountry_country_nl' => 'Països Baixos',
'UserCountry_country_no' => 'Noruega',
'UserCountry_country_np' => 'Nepal',
'UserCountry_country_nr' => 'Nauru',
@@ -655,7 +702,7 @@ $translations = array(
'UserSettings_Browsers' => 'Navegadors',
'UserSettings_Plugins' => 'Connectors',
'UserSettings_Configurations' => 'Configuracions',
- 'UserSettings_OperatinsSystems' => 'Sistemes operatius',
+ 'UserSettings_OperatingSystems' => 'Sistemes operatius',
'UserSettings_Resolutions' => 'Resolucions',
'UserSettings_WideScreen' => 'Pantalla panoràmica',
'UserSettings_WidgetResolutions' => 'Resoulucions',
@@ -671,7 +718,7 @@ $translations = array(
'UserSettings_ColumnBrowser' => 'Navegador',
'UserSettings_ColumnPlugin' => 'Connector',
'UserSettings_ColumnConfiguration' => 'Configuració',
- 'UserSettings_ColumnOperatinsSystem' => 'Sistema operatiu',
+ 'UserSettings_ColumnOperatingSystem' => 'Sistema operatiu',
'UserSettings_ColumnResolution' => 'Resolució',
'UserSettings_ColumnTypeOfScreen' => 'Tipus de pantalla',
'UsersManager_ManageAccess' => 'Gestiona els permisos',
@@ -708,14 +755,14 @@ Podeu configurar els seus permisos a dalt.',
'UsersManager_ExceptionInvalidLoginFormat' => 'El nom d\'usuari ha de tenir una longitud d\'entre %s i %s caràcters i estar format únicament per lletres, xifres o els caràcters \'_\', \'-\' o \'.\'',
'UsersManager_ExceptionSuperUser' => 'Aquest és el superusuari i no es pot consultar, editar o esborrar mitjançant l\'API. Podeu editar-lo manualment en el fitxer de configuració del Piwik.',
'VisitFrequency_Evolution' => 'Evolució del període',
- 'VisitFrequency_ReturnVisits' => 'Han tornat %s visites',
- 'VisitFrequency_ReturnActions' => 'Les visites que han tornat han fet %s accions',
- 'VisitFrequency_ReturnMaxActions' => 'Una visita que ha tornat ha fet un màxim de %s accions',
- 'VisitFrequency_ReturnTotalTime' => '%s de temps que han fet servir les visites que han tornat',
+ 'VisitFrequency_ReturnVisits' => 'Han tornat %s visitants',
+ 'VisitFrequency_ReturnActions' => 'Els visitants que han tornat han fet %s accions',
+ 'VisitFrequency_ReturnMaxActions' => 'Un visitant que ha tornat ha fet un màxim de %s accions',
+ 'VisitFrequency_ReturnTotalTime' => 'Els visitants que han tornat han estat %s',
'VisitFrequency_ReturnBounces' => 'Una visita que ha tornat ha rebotat %s cops (ha abandonat el lloc després de veure només una pàgina)',
- 'VisitFrequency_WidgetOverview' => 'Resum de la freq&uuml;ència',
+ 'VisitFrequency_WidgetOverview' => 'Resum de la freqüència',
'VisitFrequency_WidgetGraphReturning' => 'Gràfic de les visites que han tornat',
- 'VisitFrequency_SubmenuFrequency' => 'Freq&uuml;ència',
+ 'VisitFrequency_SubmenuFrequency' => 'Freqüència',
'VisitFrequency_ColumnReturningVisits' => 'Visitants que retornen (antics)',
'VisitFrequency_ColumnActionsByReturningVisits' => 'Accions dels visitants antics',
'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Quantitat màxima d\'accions fetes per un visitant antic',
@@ -733,7 +780,7 @@ Podeu configurar els seus permisos a dalt.',
'VisitorInterest_NPages' => '%s pàgines',
'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
'VisitorInterest_ColumnVisitDuration' => 'Durada de la visita',
- 'VisitorInterest_ColumnPagesPerVisit' => 'P+a',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Pàgines per visita',
'VisitsSummary_NbVisits' => '%s visites',
'VisitsSummary_NbUniqueVisitors' => '%s visitants únics',
'VisitsSummary_NbActions' => '%s accions (pàgines vistes)',
@@ -751,6 +798,7 @@ Podeu configurar els seus permisos a dalt.',
'VisitsSummary_SubmenuOverview' => 'Resum',
'VisitsSummary_NbVisitsBounced' => '%s visites han rebotat (abandonat el lloc després de veure una pàgina)',
'VisitsSummary_EvolutionOverLastPeriods' => 'Evolució dels darrers %s',
+ 'VisitsSummary_VisitsSummary' => 'Resum de les visites',
'VisitTime_LocalTime' => 'Visites segons l\'hora local',
'VisitTime_ServerTime' => 'Visites segons l\'hora del servidor',
'VisitTime_WidgetLocalTime' => 'Visites segons l\'hora local',
diff --git a/lang/cs.php b/lang/cs.php
index 50b7d1948f..bcf2768929 100644
--- a/lang/cs.php
+++ b/lang/cs.php
@@ -138,25 +138,51 @@ $translations = array(
'CoreHome_PeriodWeeks' => 'týdnů',
'CoreHome_PeriodMonths' => 'měsíců',
'CoreHome_PeriodYears' => 'let',
- 'CoreHome_DaySu_js' => 'Ne',
- 'CoreHome_DayMo_js' => 'Po',
- 'CoreHome_DayTu_js' => 'Út',
- 'CoreHome_DayWe_js' => 'St',
- 'CoreHome_DayTh_js' => 'Čt',
- 'CoreHome_DayFr_js' => 'Pá',
- 'CoreHome_DaySa_js' => 'So',
- 'CoreHome_MonthJanuary_js' => 'Leden',
- 'CoreHome_MonthFebruary_js' => 'Únor',
- 'CoreHome_MonthMarch_js' => 'Březen',
- 'CoreHome_MonthApril_js' => 'Duben',
- 'CoreHome_MonthMay_js' => 'Květen',
- 'CoreHome_MonthJune_js' => 'Červen',
- 'CoreHome_MonthJuly_js' => 'Červenec',
- 'CoreHome_MonthAugust_js' => 'Srpen',
- 'CoreHome_MonthSeptember_js' => 'Záři',
- 'CoreHome_MonthOctober_js' => 'Říjen',
- 'CoreHome_MonthNovember_js' => 'Listopad',
- 'CoreHome_MonthDecember_js' => 'Prosinec',
+ 'CoreHome_DaySu_js' => 'ne',
+ 'CoreHome_DayMo_js' => 'po',
+ 'CoreHome_DayTu_js' => 'út',
+ 'CoreHome_DayWe_js' => 'st',
+ 'CoreHome_DayTh_js' => 'čt',
+ 'CoreHome_DayFr_js' => 'pá',
+ 'CoreHome_DaySa_js' => 'so',
+ 'CoreHome_ShortDay_1_js' => 'ne',
+ 'CoreHome_ShortDay_2_js' => 'po',
+ 'CoreHome_ShortDay_3_js' => 'út',
+ 'CoreHome_ShortDay_4_js' => 'st',
+ 'CoreHome_ShortDay_5_js' => 'čt',
+ 'CoreHome_ShortDay_6_js' => 'pá',
+ 'CoreHome_ShortDay_7_js' => 'so',
+ 'CoreHome_LongDay_1_js' => 'neděle',
+ 'CoreHome_LongDay_2_js' => 'pondělí',
+ 'CoreHome_LongDay_3_js' => 'úterý',
+ 'CoreHome_LongDay_4_js' => 'středa',
+ 'CoreHome_LongDay_5_js' => 'čtvrtek',
+ 'CoreHome_LongDay_6_js' => 'pátek',
+ 'CoreHome_LongDay_7_js' => 'sobota',
+ 'CoreHome_ShortMonth_1_js' => 'led',
+ 'CoreHome_ShortMonth_2_js' => 'úno',
+ 'CoreHome_ShortMonth_3_js' => 'bře',
+ 'CoreHome_ShortMonth_4_js' => 'dub',
+ 'CoreHome_ShortMonth_5_js' => 'kvě',
+ 'CoreHome_ShortMonth_6_js' => 'čer',
+ 'CoreHome_ShortMonth_7_js' => 'čvc',
+ 'CoreHome_ShortMonth_8_js' => 'srp',
+ 'CoreHome_ShortMonth_9_js' => 'zář',
+ 'CoreHome_ShortMonth_10_js' => 'říj',
+ 'CoreHome_ShortMonth_11_js' => 'lis',
+ 'CoreHome_ShortMonth_12_js' => 'pro',
+ 'CoreHome_MonthJanuary_js' => 'leden',
+ 'CoreHome_MonthFebruary_js' => 'únor',
+ 'CoreHome_MonthMarch_js' => 'březen',
+ 'CoreHome_MonthApril_js' => 'duben',
+ 'CoreHome_MonthMay_js' => 'květen',
+ 'CoreHome_MonthJune_js' => 'červen',
+ 'CoreHome_MonthJuly_js' => 'červenec',
+ 'CoreHome_MonthAugust_js' => 'srpen',
+ 'CoreHome_MonthSeptember_js' => 'září',
+ 'CoreHome_MonthOctober_js' => 'říjen',
+ 'CoreHome_MonthNovember_js' => 'listopad',
+ 'CoreHome_MonthDecember_js' => 'prosinec',
'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; Update',
'CoreUpdater_DatabaseUpgradeRequired' => 'Vyžadováno povýšení databáze',
'CoreUpdater_YourDatabaseIsOutOfDate' => 'Vaše databáze Piwiku jw zastaralá a musí být aktualizována než budete pokračovat.',
@@ -247,14 +273,14 @@ $translations = array(
'UserSettings_Browsers' => 'WWW prohlížeče',
'UserSettings_Plugins' => 'Pluginy',
'UserSettings_Configurations' => 'Nastavení',
- 'UserSettings_OperatinsSystems' => 'Operační systémy',
+ 'UserSettings_OperatingSystems' => 'Operační systémy',
'UserSettings_Resolutions' => 'Rozlišení',
'UserSettings_WideScreen' => 'Širokoúhlá obrazovka',
'UserSettings_ColumnBrowserFamily' => 'Rodina WWW prohlížeče',
'UserSettings_ColumnBrowser' => 'WWW prohlížeč',
'UserSettings_ColumnPlugin' => 'Plugin',
'UserSettings_ColumnConfiguration' => 'Konfigurace',
- 'UserSettings_ColumnOperatinsSystem' => 'Operační systém',
+ 'UserSettings_ColumnOperatingSystem' => 'Operační systém',
'UserSettings_ColumnResolution' => 'Rozlišení',
'UserSettings_ColumnTypeOfScreen' => 'Typ obrazovky',
'UserSettings_WidgetResolutions' => 'Rozlišení obrazovky',
@@ -600,7 +626,6 @@ $translations = array(
'Login_PasswordReminder' => 'Prosím zadejte vase uživatelské jméno, nebo e-mailovou adresu. Nové heslo dostanete e-mailem.',
'Login_InvalidUsernameEmail' => 'Neplatné uživatelské jméno a/nebo e-mailová adresa',
'Login_MailTopicPasswordRecovery' => 'Záchrana hesla',
- 'Login_MailPasswordRecoveryBody' => 'Ahoj %1s, \n\n Vaše nové heslo je: %2s \n\n Můžete se přihlásit na: %3s',
'Login_PasswordSent' => 'Heslo bylo právě odesláno. Zkontrolujte si váš e-mail.',
'Login_ContactAdmin' => 'Možná příčina: Váš hosting zakázal funkci mail().. <br />Prosím kontaktujte vašeho administrátora Piwiku.',
'UsersManager_UsersManagement' => 'Správa uživatelů',
diff --git a/lang/da.php b/lang/da.php
index 7c389ab43d..ee5a9662e8 100644
--- a/lang/da.php
+++ b/lang/da.php
@@ -1,33 +1,41 @@
-<?php
+<?php
$translations = array(
'General_Locale' => 'da_DK.UTF-8',
'General_TranslatorName' => 'JSM',
'General_TranslatorEmail' => 'jsm@janz.dk',
'General_EnglishLanguageName' => 'Danish',
'General_OriginalLanguageName' => 'Dansk',
-'General_HelloUser' => 'Hej, %s!',
-'General_OpenSourceWebAnalytics' => 'Open source webstatistik',
-'General_YourDashboard' => 'Kontrolpanel',
+'General_HelloUser' => 'Hej %s!',
+'General_OpenSourceWebAnalytics' => 'Open Source webstatistik',
+'General_Dashboard' => 'Kontrolpanel',
+'General_DashboardForASpecificWebsite' => 'Kontrolpanel for en specifik hjemmeside',
+'General_MultiSitesSummary' => 'Alle hjemmesider',
+'General_AllWebsitesDashboard' => 'Kontrolpanel for alle hjemmesider',
'General_API' => 'API',
-'General_Widgets' => 'Widgets',
+'General_Widgets' => 'Kontroller',
'General_Settings' => 'Indstillinger',
'General_GiveUsYourFeedback' => 'Tilbagemelding!',
'General_Unknown' => 'Ukendt',
'General_Required' => '%s påkrævet',
+'General_NotValid' => '%s er ikke gyldig',
'General_Error' => 'Fejl',
'General_Warning' => 'Advarsel',
'General_BackToHomepage' => 'Tilbage til Piwik startside',
'General_Yes' => 'Ja',
'General_No' => 'Nej',
'General_Delete' => 'Slet',
-'General_Edit' => 'Ændre',
+'General_Edit' => 'Rediger',
'General_Ok' => 'OK',
'General_Close' => 'Luk',
'General_Logout' => 'Log af',
+'General_Username' => 'Brugernavn',
'General_Done' => 'Færdig',
+'General_Details' => 'Detaljer',
+'General_Default' => 'Standard',
'General_LoadingData' => 'Indlæser data...',
'General_Loading' => 'Indlæser...',
-'General_ErrorRequest' => 'Oops&hellip; problemer, prøv igen.',
+'General_YourChangesHaveBeenSaved' => 'Ændringer er gemt.',
+'General_ErrorRequest' => 'Ups... problemer, prøv igen.',
'General_Next' => 'Næste',
'General_Previous' => 'Forrige',
'General_Search' => 'Søg',
@@ -36,98 +44,129 @@ $translations = array(
'General_Piechart' => 'Cirkeldiagram',
'General_TagCloud' => 'Emne sky',
'General_VBarGraph' => 'Søjlediagram',
-'General_Export' => 'Eksporter',
-'General_ExportAsImage' => 'Eksporter som billede',
-'General_SaveImageOnYourComputer' => 'Gem billede på computer, højreklik på billede og vælg "Gem billede som…"',
+'General_Export' => 'Eksport',
+'General_ExportAsImage_js' => 'Eksporter som billede',
+'General_SaveImageOnYourComputer_js' => 'Gem billedet på computer, højreklik på billede og vælg "Gem billede som…"',
'General_Refresh' => 'Opdater siden',
+'General_Today' => 'I dag',
+'General_Yesterday' => 'I går',
+'General_CurrentWeek' => 'Nuværende uge',
+'General_CurrentMonth' => 'Denne måned',
+'General_CurrentYear' => 'Dette år',
'General_Visitors' => 'Besøgende',
'General_ColumnNbUniqVisitors' => 'Unikke besøgende',
'General_ColumnNbVisits' => 'Besøg',
'General_ColumnNbActions' => 'Handlinger',
-'General_ColumnMaxActions' => 'Max handlinger i et besøg',
-'General_ColumnSumVisitLength' => 'Total tid brugt af besøgende visitors (i sekunder)',
+'General_ColumnMaxActions' => 'Max handlinger i et enkelt besøg',
+'General_ColumnSumVisitLength' => 'Samlet tid brugt af besøgende (i sekunder)',
'General_ColumnLabel' => 'Etiket',
'General_ColumnActionsPerVisit' => 'Handlinger pr. besøg',
-'General_ColumnAvgTimeOnSite' => 'Gennemsnitstid på netsted',
+'General_ColumnAvgTimeOnSite' => 'Gennemsnitstid på hjemmeside',
'General_ColumnBounceRate' => 'Afvisningsfrekvens',
'General_ColumnPageviews' => 'Sidevisninger',
'General_ColumnUniquePageviews' => 'Unikke sidevisninger',
'General_ColumnValuePerVisit' => 'Værdi pr. besøg',
'General_ColumnVisitsWithConversions' => 'Besøg med konverteringer',
'General_Save' => 'Gem',
-'General_Website' => 'Side',
-'General_NoDataForGraph' => 'Ingen data endnu',
+'General_ForExampleShort' => 'fx.',
+'General_Website' => 'Hjemmeside',
+'General_GeneralSettings' => 'Generelle indstillinger',
+'General_AllowPiwikArchivingToTriggerBrowser' => 'Tillad at udføre Piwik-arkivering når rapporter vises i browseren',
+'General_ArchivingInlineHelp' => 'For hjemmesider med medium til høj trafik anbefales det at deaktivere Piwik-arkivering udløst fra browseren. I stedet anbefales det at køre et cron job hver time til at behandle Piwik rapporter.',
+'General_ArchivingTriggerDescription' => 'Til større Piwik installationer anbefales det, at %soprette et cron job%s til at behandle rapporterne automatisk.',
+'General_SeeTheOfficialDocumentationForMoreInformation' => 'Se den %sofficielle dokumentation%s for mere information.',
+'General_ReportsForTodayWillBeProcessedAtMostEvery' => 'Rapporter for i dag vil blive udført mindst hver',
+'General_NSeconds' => '%s sekunder',
+'General_SmallTrafficYouCanLeaveDefault' => 'For hjemmesider med lidt trafik brug standard % s sekunder og få adgang til alle rapporter i realtid.',
+'General_MediumToHighTrafficItIsRecommendedTo' => 'For hjemmesider med medium til høj trafik anbefales det kun at behandle rapporter for i dag højst hver halve time (%s sekunder) eller hver time (%s sekunder).',
+'General_RequiresFlash' => 'Visning af grafer i Piwik kræver Flash',
+'General_GraphHelp' => 'Flere oplysninger om visning af grafer i Piwik.',
+'General_NoDataForGraph' => 'Ingen data for graf',
'General_NoDataForTagCloud' => 'Ingen data for emnesky.',
'General_DisplayNormalTable' => 'Vis normal tabel',
'General_DisplayMoreData' => 'Vis flere data',
-'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s er et åbent kodeprojekt (OS). %s Hvis du vil hjælpe, så se: %s Hvordan kan man bidrage til Piwik?%s.',
-'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Du bruger en demo af %s; %shent%s fuld version! Se %s',
-'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s er udkommet. %s Opdater nu!%s (se %s ændringer%s).',
+'General_PiwikIsACollaborativeProjectYouCanContribute' => '%1$s Piwik %2$s er et samarbejdsprojekt. %3$s Hvis du vil hjælpe, så se: %4$s Hvordan bidrager man til Piwik? %5$s.',
+'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Du bruger en demo af %1$s; %2$shent%3$s fuld version! Se %4$s',
+'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %1$s er tilgængelig. %2$s Opdater nu!%3$s (se %4$s ændringer%5$s).',
+'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin' => '%s er tilgængelig. Underet administratoren.',
'General_BackToPiwik' => 'Tilbage til Piwik',
-'General_ShortMonth_1' => 'Jan',
-'General_ShortMonth_2' => 'Feb',
-'General_ShortMonth_3' => 'Mar',
-'General_ShortMonth_4' => 'Apr',
-'General_ShortMonth_5' => 'Maj',
-'General_ShortMonth_6' => 'Jun',
-'General_ShortMonth_7' => 'Jul',
-'General_ShortMonth_8' => 'Aug',
-'General_ShortMonth_9' => 'Sep',
-'General_ShortMonth_10' => 'Okt',
-'General_ShortMonth_11' => 'Nov',
-'General_ShortMonth_12' => 'Dec',
-'General_LongMonth_1' => 'Januar',
-'General_LongMonth_2' => 'Februar',
-'General_LongMonth_3' => 'Marts',
-'General_LongMonth_4' => 'April',
-'General_LongMonth_5' => 'Maj',
-'General_LongMonth_6' => 'Juni',
-'General_LongMonth_7' => 'Juli',
-'General_LongMonth_8' => 'August',
-'General_LongMonth_9' => 'September',
-'General_LongMonth_10' => 'Oktober',
-'General_LongMonth_11' => 'November',
-'General_LongMonth_12' => 'December',
-'General_ShortDay_1' => 'Man',
-'General_ShortDay_2' => 'Tir',
-'General_ShortDay_3' => 'Ons',
-'General_ShortDay_4' => 'Tor',
-'General_ShortDay_5' => 'Fre',
-'General_ShortDay_6' => 'Lør',
-'General_ShortDay_7' => 'Søn',
-'General_LongDay_1' => 'Mandag',
-'General_LongDay_2' => 'Tirsdag',
-'General_LongDay_3' => 'Onsdag',
-'General_LongDay_4' => 'Torsdag',
-'General_LongDay_5' => 'Fredag',
-'General_LongDay_6' => 'Lørdag',
-'General_LongDay_7' => 'Søndag',
-'CorePluginsAdmin_Plugins' => 'Plugins',
-'CorePluginsAdmin_PluginsManagement' => 'Plugin administration',
-'CorePluginsAdmin_MainDescription' => 'Plugins kan udvide eller begrænse funktionaliteten i Piwik. Når et plugin er installeret, kan det aktiveres eller deaktiveres her.',
-'CorePluginsAdmin_Plugin' => 'Plugin',
-'CorePluginsAdmin_Version' => 'Version',
-'CorePluginsAdmin_Description' => 'Beskrivelse',
-'CorePluginsAdmin_Status' => 'Status',
-'CorePluginsAdmin_Action' => 'Handling',
-'CorePluginsAdmin_PluginHomepage' => 'Plugin hjemmeside',
-'CorePluginsAdmin_Activated' => 'Aktiveret',
-'CorePluginsAdmin_Active' => 'Aktiv',
-'CorePluginsAdmin_Inactive' => 'Inaktiv',
-'CorePluginsAdmin_ActivatedHelp' => 'Plugin kan ikke deaktiveres',
-'CorePluginsAdmin_Deactivate' => 'Deaktiver',
-'CorePluginsAdmin_Activate' => 'Aktiver',
-'CorePluginsAdmin_MenuPlugins' => 'Plugins',
+'General_ShortMonth_1' => 'jan.',
+'General_ShortMonth_2' => 'feb.',
+'General_ShortMonth_3' => 'mar.',
+'General_ShortMonth_4' => 'apr.',
+'General_ShortMonth_5' => 'maj.',
+'General_ShortMonth_6' => 'jun.',
+'General_ShortMonth_7' => 'jul.',
+'General_ShortMonth_8' => 'aug.',
+'General_ShortMonth_9' => 'sep.',
+'General_ShortMonth_10' => 'okt.',
+'General_ShortMonth_11' => 'nov.',
+'General_ShortMonth_12' => 'dec.',
+'General_LongMonth_1' => 'januar',
+'General_LongMonth_2' => 'februar',
+'General_LongMonth_3' => 'marts',
+'General_LongMonth_4' => 'april',
+'General_LongMonth_5' => 'maj',
+'General_LongMonth_6' => 'juni',
+'General_LongMonth_7' => 'juli',
+'General_LongMonth_8' => 'august',
+'General_LongMonth_9' => 'september',
+'General_LongMonth_10' => 'oktober',
+'General_LongMonth_11' => 'november',
+'General_LongMonth_12' => 'december',
+'General_ShortDay_1' => 'man',
+'General_ShortDay_2' => 'tir',
+'General_ShortDay_3' => 'ons',
+'General_ShortDay_4' => 'tor',
+'General_ShortDay_5' => 'fre',
+'General_ShortDay_6' => 'lør',
+'General_ShortDay_7' => 'søn',
+'General_LongDay_1' => 'mandag',
+'General_LongDay_2' => 'tirsdag',
+'General_LongDay_3' => 'onsdag',
+'General_LongDay_4' => 'torsdag',
+'General_LongDay_5' => 'fredag',
+'General_LongDay_6' => 'lørdag',
+'General_LongDay_7' => 'søndag',
+'General_ExceptionDatabaseVersion' => 'Din %1$s version er %2$s, men Piwik behøver mindst version %3$s.',
+'General_ExceptionIncompatibleClientServerVersions' => ' %1$s klient version er %2$s, som er uforenelig med server version %3$s.',
+'General_ExceptionMissingFile' => 'Mangler fil: %s',
+'General_ExceptionFilesizeMismatch' => 'Fil størrelse passer ikke: %1s (forventet længde: %2s, fundet: %3s)',
+'General_ExceptionFileIntegrity' => 'Integritet check mislykkedes: %s',
+'General_ExceptionNonceMismatch' => 'Kan ikke kontrollere sikkerheden på formularen.',
+'General_WarningFileIntegritySkipped' => 'Udvikling miljø opdaget. Fil integritet check springes over.',
+'General_WarningFileIntegrityNoManifest' => 'Fil integritet kontrol kunne ikke udføres på grund af manglende manifest.inc.php.',
+'General_WarningFileIntegrityNoMd5file' => 'Fil integritet kontrol kunne ikke gennemføres pga. manglende md5_file () funktion.',
+'General_FileIntegrityWarningExplanation' => 'Fil integritet check mislykkedes og rapporterede nogle fejl. Det skyldes mest sandsynligt en delvis eller mislykket overførelse af nogle Piwik filer. Du bør overføre alle Piwik filer igen og opdatere denne side, indtil den ingen fejl viser.',
+'Actions_PluginDescription' => 'Rapporter om sidevisninger, udgående links og filhentninger. Udgående links og filhentnnger spores automatisk!',
+'Actions_Actions' => 'Handlinger',
+'Actions_SubmenuPages' => 'Sider',
+'Actions_SubmenuPageTitles' => 'Sidetitler',
+'Actions_SubmenuOutlinks' => 'Udgående links',
+'Actions_SubmenuDownloads' => 'Filhentninger',
+'Actions_ColumnClicks' => 'Klik',
+'Actions_ColumnUniqueClicks' => 'Unikke klik',
+'Actions_ColumnDownloads' => 'Filhentninger',
+'Actions_ColumnUniqueDownloads' => 'Unikke filhentninger',
+'Actions_ColumnPageName' => 'Sidenavn',
+'Actions_ColumnPageURL' => 'Webadresse',
+'Actions_ColumnClickedURL' => 'Klikkede webadresser',
+'Actions_ColumnDownloadURL' => 'Download webadresser',
+'AnonymizeIP_PluginDescription' => 'Anonymiser besøgendes IP-adresser for at efterkomme den lokale lovgivning om privatlivets fred/retningslinjer.',
+'API_PluginDescription' => 'Alle data i Piwik er tilgængelig via enkle API\'er. Programudvidelsen er webservice indgangen, som kan kaldes for at få Web analyse-data i xml, json, php, csv, osv.',
'API_QuickDocumentation' => '<h2>API - hurtig i gang dokumentation</h2><p>Hvis du ikke har data før i \'dag\' kan du <a href=\'misc/generateVisits.php\' target=_blank>genere data</a> med besøgsgeneratoren.</p><p>Du kan prøve de forskellige formater der findes for de forskellige metoder. Det er meget let at udtrække data som ønsket fra Piwik!</p><p><b>Mere information findes på den <a href=\'http://dev.piwik.org/trac/wiki/API\'>officiellle API dokumentation </a>side eller her <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API reference</a>.</b></P><h2>Bruger authentication</h2><p>Hvis du ønsker at <b>hente data i scripts, i crontab, m.m. </b> skal du tilføje parameteren <code><u>&token_auth=%s</u></code> til API kaldets webadresse som kræver authentication.</p><p>token_auth er ligeså hemmeligt som brugernavn og adgangskode, <b>del det ikke ud!</p>',
'API_LoadedAPIs' => '%s APIs indlæst',
+'CoreAdminHome_PluginDescription' => 'Piwik  administration.',
+'CoreAdminHome_MenuGeneralSettings' => 'Generelle indstillinger',
+'CoreHome_PluginDescription' => 'Struktur for webanalyserapporter.',
'CoreHome_NoPrivileges' => 'Du er logget på som \'%s\' men det ser ikke ud som du har adgang til Piwik.<br />Spørg Piwik administrator om læseadgang.',
-'CoreHome_JavascriptDisabled' => 'JavaSript skal være aktiveret for at Piwik kan bruges i standardvisning. JavaScript er enten deaktiver eller ikke understøttet i netlæseren.<br />For at bruge standardvisning, aktiver JavaScript i indstillingerne for netlæseren, og %1s prøv igen %2s.<br />',
+'CoreHome_JavascriptDisabled' => 'JavaSript skal være aktiveret for at Piwik kan bruges i standardvisning. JavaScript er enten deaktiver eller ikke understøttet i netlæseren.<br />For at bruge standardvisning, aktiver JavaScript i indstillingerne for netlæseren, og %1$s prøv igen %2$s.<br />',
'CoreHome_TableNoData' => 'Ingen data endnu.',
'CoreHome_CategoryNoData' => 'Ingen data i kategorien. Prøv at \'Inkluder hele populationen\'.',
-'CoreHome_ShowJSCode' => 'Vis JavaScript-koden til at indsætte på websiden.',
+'CoreHome_ShowJSCode' => 'Vis JavaScript-koden til at indsætte.',
'CoreHome_IncludeAllPopulation_js' => 'Medtag alle data',
-'CoreHome_ExcludeLowPopulation_js' => 'Skjul mindste data',
-'CoreHome_PageOf_js' => '%s af %s',
+'CoreHome_ExcludeLowPopulation_js' => 'Udeluk data',
+'CoreHome_PageOf_js' => '%1$s af %2$s',
'CoreHome_Loading_js' => 'Indlæser...',
'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
'CoreHome_PeriodDay' => 'Dag',
@@ -138,133 +177,436 @@ $translations = array(
'CoreHome_PeriodWeeks' => 'uger',
'CoreHome_PeriodMonths' => 'måneder',
'CoreHome_PeriodYears' => 'år',
-'CoreHome_DaySu_js' => 'Søn',
-'CoreHome_DayMo_js' => 'Man',
-'CoreHome_DayTu_js' => 'Tir',
-'CoreHome_DayWe_js' => 'Ons',
-'CoreHome_DayTh_js' => 'Tor',
-'CoreHome_DayFr_js' => 'Fre',
-'CoreHome_DaySa_js' => 'Lør',
-'CoreHome_MonthJanuary_js' => 'Januar',
-'CoreHome_MonthFebruary_js' => 'Februar',
-'CoreHome_MonthMarch_js' => 'Marts',
-'CoreHome_MonthApril_js' => 'April',
-'CoreHome_MonthMay_js' => 'Maj',
-'CoreHome_MonthJune_js' => 'Juni',
-'CoreHome_MonthJuly_js' => 'Juli',
-'CoreHome_MonthAugust_js' => 'August',
-'CoreHome_MonthSeptember_js' => 'September',
-'CoreHome_MonthOctober_js' => 'Oktober',
-'CoreHome_MonthNovember_js' => 'November',
-'CoreHome_MonthDecember_js' => 'December',
-'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; opdatering',
+'CoreHome_DaySu_js' => 'S',
+'CoreHome_DayMo_js' => 'M',
+'CoreHome_DayTu_js' => 'T',
+'CoreHome_DayWe_js' => 'O',
+'CoreHome_DayTh_js' => 'T',
+'CoreHome_DayFr_js' => 'F',
+'CoreHome_DaySa_js' => 'L',
+'CoreHome_ShortDay_1_js' => 'søn',
+'CoreHome_ShortDay_2_js' => 'man',
+'CoreHome_ShortDay_3_js' => 'tir',
+'CoreHome_ShortDay_4_js' => 'ons',
+'CoreHome_ShortDay_5_js' => 'tor',
+'CoreHome_ShortDay_6_js' => 'fre',
+'CoreHome_ShortDay_7_js' => 'lør',
+'CoreHome_LongDay_1_js' => 'søndag',
+'CoreHome_LongDay_2_js' => 'mandag',
+'CoreHome_LongDay_3_js' => 'tirsdag',
+'CoreHome_LongDay_4_js' => 'onsdag',
+'CoreHome_LongDay_5_js' => 'torsdag',
+'CoreHome_LongDay_6_js' => 'Fredag',
+'CoreHome_LongDay_7_js' => 'lørdag',
+'CoreHome_ShortMonth_1_js' => 'jan',
+'CoreHome_ShortMonth_2_js' => 'feb',
+'CoreHome_ShortMonth_3_js' => 'mar',
+'CoreHome_ShortMonth_4_js' => 'apr',
+'CoreHome_ShortMonth_5_js' => 'maj',
+'CoreHome_ShortMonth_6_js' => 'jun',
+'CoreHome_ShortMonth_7_js' => 'jul',
+'CoreHome_ShortMonth_8_js' => 'aug',
+'CoreHome_ShortMonth_9_js' => 'sep',
+'CoreHome_ShortMonth_10_js' => 'okt',
+'CoreHome_ShortMonth_11_js' => 'nov',
+'CoreHome_ShortMonth_12_js' => 'dec',
+'CoreHome_MonthJanuary_js' => 'januar',
+'CoreHome_MonthFebruary_js' => 'februar',
+'CoreHome_MonthMarch_js' => 'marts',
+'CoreHome_MonthApril_js' => 'april',
+'CoreHome_MonthMay_js' => 'maj',
+'CoreHome_MonthJune_js' => 'juni',
+'CoreHome_MonthJuly_js' => 'juli',
+'CoreHome_MonthAugust_js' => 'august',
+'CoreHome_MonthSeptember_js' => 'september',
+'CoreHome_MonthOctober_js' => 'oktober',
+'CoreHome_MonthNovember_js' => 'november',
+'CoreHome_MonthDecember_js' => 'december',
+'CorePluginsAdmin_PluginDescription' => 'Programudvidelses administration.',
+'CorePluginsAdmin_Plugins' => 'Udvidelsesmoduler',
+'CorePluginsAdmin_PluginsManagement' => 'Udvidelsesmodul administration',
+'CorePluginsAdmin_MainDescription' => 'Udvidelsesmoduler udvider funktionaliteten i Piwik. Når et udvidelsesmodul er installeret, kan det aktiveres eller deaktiveres her.',
+'CorePluginsAdmin_Plugin' => 'Udvidelsesmodul',
+'CorePluginsAdmin_Version' => 'Version',
+'CorePluginsAdmin_Description' => 'Beskrivelse',
+'CorePluginsAdmin_Status' => 'Status',
+'CorePluginsAdmin_Action' => 'Handling',
+'CorePluginsAdmin_PluginHomepage' => 'Udvidelsesmodul hjemmeside',
+'CorePluginsAdmin_Activated' => 'Aktiveret',
+'CorePluginsAdmin_Active' => 'Aktiv',
+'CorePluginsAdmin_Inactive' => 'Inaktiv',
+'CorePluginsAdmin_ActivatedHelp' => 'Udvidelsesmodulet kan ikke deaktiveres',
+'CorePluginsAdmin_Deactivate' => 'Deaktiver',
+'CorePluginsAdmin_Activate' => 'Aktiver',
+'CorePluginsAdmin_MenuPlugins' => 'Udvidelsesmoduler',
+'CoreUpdater_PluginDescription' => ' Piwik ajourføringsmekanisme',
+'CoreUpdater_UpdateTitle' => 'Opdatering',
'CoreUpdater_DatabaseUpgradeRequired' => 'Database opdatering er nødvendig',
'CoreUpdater_YourDatabaseIsOutOfDate' => 'Piwik databasen er ikke opdateret, og skal opgraderes før du kan fortsættes.',
-'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik vil blive opgraderet fra version %s til version den nye %s.',
-'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Følgende plugins vil blive opgraderet: %s.',
-'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Opgraderingen kan tage lidt tid, vær tålmodig.',
+'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik vil blive opgraderet fra version %1$s til den nye version %2$s.',
+'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Følgende udvidelsesmoduler vil blive opgraderet: %s.',
+'CoreUpdater_NoteForLargePiwikInstances' => 'Vigtig bemærkning til store Piwik installationer',
+'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'Hvis du har en stor Piwik database, kan opdateringer tage for lang tid at køre i browseren. I denne situation, kan du udføre opdateringen fra kommandolinjen: %s',
+'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => 'Hvis du ikke er i stand til at bruge kommandolinjen opdateringsprogrammet og hvis Piwik opgradering fejler (på grund af en timeout i databasen, en browser timeout, eller andet), kan du manuelt udføre SQL-forespørgsler til at opdatere Piwik.',
+'CoreUpdater_ClickHereToViewSqlQueries' => 'Klik her for at se og kopiere listen over SQL-forespørgsler, der vil blive udført',
+'CoreUpdater_NoteItIsExpectedThatQueriesFail' => 'Bemærk: Hvis du manuelt udfører disse forespørgelser, forventes det, at nogle af dem mislykkes. I så fald ignoreres fejlene blot, og køre den næste forespørgsel på listen.',
+'CoreUpdater_ReadyToGo' => 'Klar, parat, start?',
+'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Database opgraderingen kan tage lidt tid, vær tålmodig.',
'CoreUpdater_UpgradePiwik' => 'Opgrader Piwik',
-'CoreUpdater_HelpMessageContent' => 'se %s Piwik FAQ %s som forklarer de mest almindelige fejl om opdateringer. %s Spørg systemadministratoren - vedkommende kan måske hjælpe med fejlen som sikkert har at skyldes server eller MySQL-installation/opsætning.',
-'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Kritisk fejl med opdateringen:',
-'CoreUpdater_HelpMessageIntroductionWhenError' => 'ovenfor vises fejlmeldingen. Den bør hjælpe med at forklare årsagen, men hvis der behøves mere hjælp:',
-'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Opdateringen er fuldført, men det var nogle småproblemer under processen. Læs detaljerne ovenfor. For videre hjælp:',
+'CoreUpdater_ErrorDIYHelp' => 'Hvis du er en erfaren bruger og støder på en fejl i database opgraderingen:',
+'CoreUpdater_ErrorDIYHelp_1' => 'identificere og ret kilden til problemet (f. eks. memory_limit eller max_execution_time) ',
+'CoreUpdater_ErrorDIYHelp_2' => 'udfør de resterende forespørgelser i opdateringen, som mislykkedes',
+'CoreUpdater_ErrorDIYHelp_3' => 'opdater manuelt "option" tabellen i Piwik databasen, skift værdien af "version_core" til versionen på den mislykkede opdatering',
+'CoreUpdater_ErrorDIYHelp_4' => 'kør opdateringsprogrammet igen (via browseren eller kommando-linje) for at fortsætte med de resterende opdateringer',
+'CoreUpdater_ErrorDIYHelp_5' => 'indberet problemet (og løsning), så Piwik kan forbedres',
+'CoreUpdater_HelpMessageContent' => 'se %1$s Piwik FAQ %2$s som forklarer de mest almindelige fejl om opdateringer. %3$s Spørg systemadministratoren - vedkommende kan måske hjælpe med fejlen som sandsynligvis skyldes server eller MySQL-opsætning.',
+'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Kritisk fejl under opdateringen:',
+'CoreUpdater_HelpMessageIntroductionWhenError' => 'Ovenstående vises fejlmeddelelsen . Den bør hjælpe med at forklare årsagen, men hvis der behøves mere hjælp:',
+'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Opdateringen er fuldført, men det var nogle småproblemer under processen. Læs detaljerne ovenfor. For yderligere hjælp:',
'CoreUpdater_UpgradeComplete' => 'Opgradering fuldført!',
'CoreUpdater_WarningMessages' => 'Advarsler:',
-'CoreUpdater_ErrorDuringPluginsUpdates' => 'Fejl under plugin opdatering:',
-'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Vil automatisk deaktivere følgende plugins: %s',
+'CoreUpdater_ErrorDuringPluginsUpdates' => 'Fejl under udvidelsesmodul opdatering:',
+'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Vil automatisk deaktivere følgende udvidelsesmoduler: %s',
'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik blev opdateret!',
'CoreUpdater_ContinueToPiwik' => 'Fortsæt til Piwik',
'CoreUpdater_UpdateAutomatically' => 'Opdater automatisk',
'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Ny version af Piwik tilgængelig for opdatering',
'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Opdater til version %s automatisk eller hent programpakken og installer manuelt:',
'CoreUpdater_DownloadX' => 'Hent %s',
-'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Piwik ét klik-opdatering er blevet annulleret. Kan ovenstående fejlmeddelelse ike løses, anbefales det at opdatere Piwik manuelt. %s Læs %sOpdaterings dokumentationen%s for at komme i gang!',
-'CoreUpdate_DownloadingUpdateFromX' => 'Henter opdatering fra %s',
-'CoreUpdate_UnpackingTheUpdate' => 'Opdatering pakkes ud',
+'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Piwik ét klik-opdatering er blevet annulleret. Kan ovenstående fejlmeddelelse ikke løses, anbefales det at opdatere Piwik manuelt. %1$s Læs %2$sOpdaterings dokumentationen%3$s for at komme i gang!',
+'CoreUpdater_DownloadingUpdateFromX' => 'Henter opdatering fra %s',
+'CoreUpdater_UnpackingTheUpdate' => 'Opdatering pakkes ud',
'CoreUpdater_VerifyingUnpackedFiles' => 'Kontrollerer filer',
-'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Backup af konfigurationfiler i %s',
-'CoreUpdater_InstallingTheLatestVersion' => 'Installerer den nyeste version',
+'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Opretter sikkerhedskopi af konfigurationfiler i %s',
+'CoreUpdater_InstallingTheLatestVersion' => 'Installerer den seneste version',
'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik er opdateret!',
-'Actions_Actions' => 'Handlinger',
-'Actions_SubmenuPages' => 'Sider',
-'Actions_SubmenuOutlinks' => 'Udgående links',
-'Actions_SubmenuDownloads' => 'Filhentninger',
-'Actions_ColumnClicks' => 'Klik',
-'Actions_ColumnUniqueClicks' => 'Unikke klik',
-'Actions_ColumnDownloads' => 'Filhentninger',
-'Actions_ColumnUniqueDownloads' => 'Unikke filhentninger',
-'Actions_ColumnPageName' => 'Sidenavn',
-'Actions_ColumnClickedURL' => 'Klikkede på webadresser',
-'Actions_ColumnDownloadURL' => 'Download webadresser',
+'CoreUpdater_EmptyDatabaseError' => 'Databasen %s er tom. Redigere eller fjern Piwiks konfigurationsfil.',
+'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Piwik version %s er fuld opdateret.',
+'CoreUpdater_ExceptionArchiveIncompatible' => 'Inkompatibel arkiv: %s',
+'CoreUpdater_ExceptionArchiveEmpty' => 'Tomt arkiv.',
+'CoreUpdater_ExceptionArchiveIncomplete' => 'Arkiv er ikke komplet: nogle filer mangler (fx. %s).',
+'Dashboard_PluginDescription' => ' Kontrolpanelet kan tilpasses: tilføj nye kontroller, ændre rækkefølgen af dem. Hver bruger kan få adgang til sit eget brugerdefinerede kontrolpanel.',
'Dashboard_Dashboard' => 'Kontrolpanel',
-'Dashboard_AddWidget' => 'Tilføj en widget...',
-'Dashboard_DeleteWidgetConfirm' => 'Bekræft fjernelse af widget fra kontrolpanelet?',
-'Dashboard_SelectWidget' => 'Vælg hvilken widget som skal tilføjes kontrolpanelet.',
-'Dashboard_AddPreviewedWidget_js' => 'Tilføj forhåndsvist widget til kontrolpanelet.',
-'Dashboard_WidgetPreview_js' => 'Forhåndsvisning af widget',
+'Dashboard_AddWidget' => 'Tilføj en kontrol...',
+'Dashboard_DeleteWidgetConfirm' => 'Bekræft fjernelse af kontrol fra kontrolpanelet?',
+'Dashboard_SelectWidget' => 'Vælg kontrol som skal tilføjes kontrolpanelet.',
+'Dashboard_AddPreviewedWidget_js' => 'Tilføj forhåndsvist kontrol til kontrolpanelet.',
+'Dashboard_WidgetPreview_js' => 'Forhåndsvisning af kontrol',
'Dashboard_Close_js' => 'Luk',
-'Dashboard_TitleWidgetInDashboard_js' => 'Widget er allerede i kontrolpanelet',
+'Dashboard_TitleWidgetInDashboard_js' => 'Kontrol er allerede i kontrolpanelet',
'Dashboard_TitleClickToAdd_js' => 'Klik for at tilføje til kontrolpanelet',
-'Dashboard_LoadingWidget_js' => 'Indlæser Widget, vent...',
-'Dashboard_WidgetNotFound_js' => 'Fandt ikke widget',
+'Dashboard_LoadingWidget_js' => 'Indlæser kontrol, vent...',
+'Dashboard_WidgetNotFound_js' => 'Fandt ikke kontrol',
+'DBStats_PluginDescription' => 'Programudvidelsen viser MySQL-database brugen af Piwik tabeller.',
+'DBStats_DatabaseUsage' => 'Database brug',
+'DBStats_MainDescription' => 'Piwik gemmer al statistik i MySQL-databasen. Lige nu bruger Piwik-tabellerne %s.',
+'DBStats_LearnMore' => 'Hvis du vil vide mere om, hvordan Piwik behandler data, og hvordan man kan få Piwik til arbejde godt på mellem til stærkt trafikerede hjemmesider, se dokumentationen på % s.',
+'DBStats_Table' => 'Tabel',
+'DBStats_RowCount' => 'Række antal',
+'DBStats_DataSize' => 'Data',
+'DBStats_IndexSize' => 'Index',
+'DBStats_TotalSize' => 'Samlet størrelse',
+'ExampleAPI_PluginDescription' => 'Programudvidelse eksempel: Hvordan oprettes et API til at eksportere data i flere formater, uden nogen særlig programkodning?',
+'ExampleFeedburner_PluginDescription' => 'Programudvidelse eksempel: Hvordan vises et FeedBurner abonnent i en kontrol på kontrolpanelet?',
+'ExampleRssWidget_PluginDescription' => 'Programudvidelse eksempel: Hvordan oprettes en ny kontrol, der læser et RSS-feed?',
+'ExampleUI_PluginDescription' => 'Programudvidelse eksempel: programudvidelsen viser, hvordan man arbejder med Piwik UI: opretter tabeller, grafer osv.',
+'Feedback_PluginDescription' => 'Send tilbagemelding til Piwik Team med et enkelt klik. Del dine ideer og forslag med os!',
+'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Har du en fejlrapport eller en anmodning om en funktion?',
+'Feedback_ViewAnswersToFAQ' => 'Se svarene på %s Ofte stillede spørgsmål%s',
+'Feedback_WhyAreMyVisitsNoTracked' => 'Hvorfor spores besøg på hjemmesiden ikke?',
+'Feedback_HowToExclude' => 'Hvordan kan jeg udelade sporing af mine egne besøg?',
+'Feedback_WhyWrongCountry' => 'Hvorfor viser Piwik mit besøg fra et forkert land?',
+'Feedback_HowToAnonymizeIP' => 'Hvordan besøgendes IP-adresser maskeres i databasen?',
+'Feedback_VisitTheForums' => 'Besøg %s Forum%s',
+'Feedback_LearnWaysToParticipate' => 'Lær om alle de måder, du kan %s bidrage%s',
+'Feedback_SpecialRequest' => 'Har du en speciel anmodning til Piwik holdet?',
+'Feedback_ContactThePiwikTeam' => 'Kontakt Piwik holdet',
+'Feedback_IWantTo' => 'Jeg ønsker at:',
+'Feedback_CategoryShareStory' => 'Dele en Piwik succeshistorie',
+'Feedback_CategorySponsor' => 'Sponsere Piwik',
+'Feedback_CategoryHire' => 'Ansætte en Piwik konsulent',
+'Feedback_CategorySecurity' => 'Rapporter et sikkerhedsproblem',
+'Feedback_MyEmailAddress' => 'Min e-mailaddresse:',
+'Feedback_MyMessage' => 'Min besked:',
+'Feedback_DetailsPlease' => '(vedlæg detaljer)',
+'Feedback_SendFeedback' => 'Send tilbagemelding',
+'Feedback_ManuallySendEmailTo' => 'Send din besked manuelt til',
+'Feedback_MessageSent' => 'Din besked blev sendt til Piwik holdet.',
+'Feedback_ThankYou' => 'Tak, fordi du hjælper med at gøre Piwik bedre!',
+'Feedback_ThePiwikTeam' => 'Piwik holdet',
+'Feedback_ExceptionBodyLength' => 'Meddelelse skal være på mindst %s tegn.',
+'Feedback_ExceptionNoUrls' => 'For at undgå spam, kan meddelelsen ikke indeholde en webadresse.',
+'Goals_PluginDescription' => ' Opret mål og se rapporter om målkonverteringer: udvikling over tid, indtjening pr besøg, konverteringer pr referer, for hvert enkelt søgeord osv.',
+'Goals_ColumnConversions' => 'Omregninger',
+'Goals_ColumnConversionRate' => 'Omregningsfrekvens',
+'Goals_ColumnRevenue' => 'Indtægter',
+'Goals_OverallRevenue' => '%s samlede indtægter',
+'Goals_OverallConversionRate' => '%s samlet konverteringsrate (besøg med et færdigt mål)',
+'Goals_Conversions' => '%s konverteringer',
+'Goals_ConversionRate' => '%s konverteringsrate',
+'Goals_NoGoalsNeedAccess' => 'Kun en administrator eller superbruger kan tilføje mål for en given hjemmeside. Bed din Piwik administrator om at oprette et mål for din hjemmeside. <br> Sporingsmål er en fantastisk måde til at forstå og optimere din hjemmesides ydelse!',
+'Goals_AddNewGoal' => 'Tilføj et nyt mål',
+'Goals_AddNewGoalOrEditExistingGoal' => '%sTilføj et nyt mål%s eller %srediger%s eksisterende mål',
+'Goals_AddGoal_js' => 'Tilføj mål',
+'Goals_UpdateGoal_js' => 'Opdater mål',
+'Goals_DeleteGoalConfirm_js' => 'Bekræft sletning af mål %s?',
+'Goals_GoalName' => 'Navn',
+'Goals_GoalIsTriggered' => 'Målet er opfyldt',
+'Goals_GoalIsTriggeredWhen' => 'Målet er opfyldt, når',
+'Goals_WhenVisitors' => 'når de besøgende',
+'Goals_Manually' => 'manuelt',
+'Goals_ManuallyTriggeredUsingJavascriptFunction' => 'Målet udløses manuelt ved hjælp af JavaScript API trackGoal ()',
+'Goals_VisitUrl' => 'Besøg en bestemt hjemmeside (side eller en gruppe af sider)',
+'Goals_Download' => 'Henter en fil',
+'Goals_ClickOutlink' => 'Klik på et link til en ekstern hjemmeside',
+'Goals_Optional' => '(valgfri)',
+'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => 'hvor den besøgte side indeholder et kald til JavaScriptet piwikTracker.trackGoal () metode (%s lær mere%s)',
+'Goals_DefaultRevenue' => 'Målets standard indtægter er ',
+'Goals_DefaultRevenueHelp' => 'F. eks. en kontaktformular sendt af en besøgende kan være 10 kr. værd i gennemsnit. Piwik vil hjælpe dig med at forstå, hvor godt dine besøgendes segmenter klarer sig.',
+'Goals_ConversionsOverview' => 'Konverteringsoversigt',
+'Goals_BestCountries' => 'De bedste konverteringslande er: ',
+'Goals_BestKeywords' => 'Top konverteringssøgeord er: ',
+'Goals_BestReferers' => 'Bedste konverteringshjemmeside henvisning er:',
+'Goals_ReturningVisitorsConversionRateIs' => 'Tilbagevendende besøgendes konverteringsrate er %s',
+'Goals_NewVisitorsConversionRateIs' => 'Nye besøgendes konverteringsrate er %s',
+'Goals_Contains' => 'indeholder %s',
+'Goals_IsExactly' => 'er nøjagtig %s',
+'Goals_MatchesExpression' => 'matcher udtrykket %s',
+'Goals_CaseSensitive' => 'Forskel på små og store bogstaver',
+'Goals_Pattern' => 'Mønster',
+'Installation_PluginDescription' => 'Installation af Piwik. Installationen sker som regel kun én gang. Hvis konfigurationsfilen config/config.inc.php slettes starter installationen igen.',
+'Installation_Installation' => 'Installation',
+'Installation_InstallationStatus' => 'Installationstatus',
+'Installation_PercentDone' => '%s %% udført',
+'Installation_NoConfigFound' => 'Piwik-konfigurationsfil blev ikke fundet og du prøver at få adgang til Piwik. <ul><li>Du kan <a href=\'index.php\'>installere Piwik nu</a></b><small> Hvis du har installeret Piwik tidligere og har nogle tabeller i databasen, kan du genbruge tabellerne og holde dine eksisterende data!</small>',
+'Installation_DatabaseSetup' => 'Database oprettelse',
+'Installation_DatabaseSetupServer' => 'Databaseserver',
+'Installation_DatabaseSetupLogin' => 'Brugernavn',
+'Installation_DatabaseSetupPassword' => 'Adgangskode',
+'Installation_DatabaseSetupDatabaseName' => 'Databasenavn',
+'Installation_DatabaseSetupTablePrefix' => 'Tabel præfix',
+'Installation_DatabaseSetupAdapter' => 'Adapter',
+'Installation_DatabaseErrorConnect' => 'Fejl ved tilkobling til databaseserveren',
+'Installation_DatabaseCheck' => 'Database check',
+'Installation_DatabaseServerVersion' => 'Databaseserver version',
+'Installation_DatabaseClientVersion' => 'Database klient version',
+'Installation_DatabaseCreation' => 'Database oprettet',
+'Installation_PleaseFixTheFollowingErrors' => 'Ret følgende fejl',
+'Installation_JsTag' => 'JavaScript kode',
+'Installation_JsTagHelp' => '<p>For at tælle alle besøgende, indsættes JavaScript-koden på alle sider.</p><p>Siderne behøver ikke være lavet med PHP, Piwik vil virke på alle typer sider (uanset om det er HTML, ASP, Perl eller et andet sprog).</p><p>Her er koden der skal indsættes: (kopier og indsæt på alle sider)</p>',
+'Installation_JsTagHelpTitle' => ' Hvordan indsættes koden på hjemmesider?',
+'Installation_LargePiwikInstances' => 'Hjælp til store Piwik installationer',
+'Installation_JsTagArchivingHelp' => 'Hjemmesider med medium og høj trafik se: <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">How to setup auto archiving page</a> og få Piwik til at køre rigtig hurtigt!',
+'Installation_Congratulations' => 'Tillykke',
+'Installation_CongratulationsHelp' => '<p>Tillykke! Piwik installationen er færdig.</p><p>Sørg for at JavaScript-koden er tilføjet på dine sider, og vent på de første besøgende!</p>',
+'Installation_ContinueToPiwik' => 'Fortsæt til Piwik',
+'Installation_SetupWebsite' => 'Tilføj en hjemmeside',
+'Installation_SetupWebSiteName' => 'hjemmeside navn',
+'Installation_SetupWebSiteURL' => 'hjemmeside URL',
+'Installation_Timezone' => 'hjemmeside tidszone',
+'Installation_SetupWebsiteError' => 'Fejl ved tilføjelse af hjemmeside',
+'Installation_SetupWebsiteSetupSuccess' => 'Hjemmeside %s oprettet!',
+'Installation_GeneralSetup' => 'Generel opsætning',
+'Installation_GeneralSetupSuccess' => 'Generel opsætning gemt',
+'Installation_SuperUserLogin' => 'Superbruger navn',
+'Installation_Password' => 'Adgangskode',
+'Installation_PasswordRepeat' => 'Gentag adgangskode',
+'Installation_Email' => 'E-mail',
+'Installation_SecurityNewsletter' => 'send e-mail med vigtige Piwik opgraderinger og sikkerheds advarsler',
+'Installation_CommunityNewsletter' => 'send e-mail med opdateringer (nye udvidelsesmoduler, nye muligheder m.m.)',
+'Installation_PasswordDoNotMatch' => 'adgangskoder stemmer ikke overens',
+'Installation_SubmitGo' => 'Start!',
+'Installation_Requirements' => 'Piwik krav',
+'Installation_Optional' => 'Valgfri',
+'Installation_Legend' => 'Beskrivelse',
+'Installation_Extension' => 'udvidelse',
+'Installation_SystemCheck' => 'Systemcheck',
+'Installation_SystemCheckPhp' => 'PHP version',
+'Installation_SystemCheckExtensions' => 'Andre nødvendige udvidelser',
+'Installation_SystemCheckDatabaseHelp' => 'Piwik behøver enten mysqli udvidelsen eller både PDO og pdo_mysql udvidelserne.',
+'Installation_SystemCheckPdoAndMysqliHelp' => 'På en linux-server kan php kompileres med følgende valg: %1\$s\n i php.ini, tilføj følgende linjer: %2\$s',
+'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Mere information på: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> og <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+'Installation_SystemCheckWinPdoAndMysqliHelp' => 'På en Windows-server tilføj følgende linjer til php-ini: %s ',
+'Installation_SystemCheckSplHelp' => 'Konfigurer og genstart PHP med standard PHP Biblioteket (SPL) aktiveret (som standard).',
+'Installation_SystemCheckZlibHelp' => 'Konfigurer og genstart PHP med zlib support aktiveret, --with-zlib.',
+'Installation_SystemCheckIconvHelp' => 'PHP skal konfigureres og genstartes med "iconv" støtte aktiveret, --with-iconv.',
+'Installation_SystemCheckDomHelp' => 'DOM er en del af PHP kernen. DOM modulet skal sandsynligvis installeres, f.eks. php-5-dom.',
+'Installation_SystemCheckJson' => 'JSON',
+'Installation_SystemCheckJsonHelp' => 'Konfigurer og genstart PHP med enten "json" eller "xml" udvidelserne aktiveret.',
+'Installation_SystemCheckJsonSite' => 'Mere information på: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+'Installation_SystemCheckXml' => 'XML',
+'Installation_SystemCheckXmlHelp' => 'Nogle tredjeparts udvidelsesmoduler og udvikler biblioteker kan kræve "xml" udvidelsen.',
+'Installation_SystemCheckXmlSite' => 'Mere information på: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+'Installation_SystemCheckWriteDirs' => 'Mapper med skriveadgang',
+'Installation_SystemCheckWriteDirsHelp' => 'Prøv at skrive følgende kommandoer for at rette fejlen på et linux-system',
+'Installation_SystemCheckMemoryLimit' => 'Hukommelses grænse',
+'Installation_SystemCheckMemoryLimitHelp' => 'På et stærkt trafikeret hjemmesider, kan arkiveringsprocessen kræve mere hukommelse end der er tilladt.<br />Se på memory_limit i php.ini filen hvis nødvendig.',
+'Installation_SystemCheckOpenURL' => 'Åbn URL',
+'Installation_SystemCheckOpenURLHelp' => 'Nyhedsbrev tilmelding, opdateringsbeskeder og et-klik opdatering kræver "curl" udvidelsen, allow_url_fopen=On, eller fsockopen() aktiveret.',
+'Installation_SystemCheckGD' => 'GD > 2.x (grafik)',
+'Installation_SystemCheckGDHelp' => 'Mindre grafiske elementer vil ikke fungere som ønsket.',
+'Installation_SystemCheckFunctions' => 'Nødvendige funktioner',
+'Installation_SystemCheckTimeLimitHelp' => 'På en stærkt trafikeret hjemmeside, kan arkiveringsprocessen kræve mere tid end der tilladt.<br />Se på max_execution_time i php.ini filen hvis nødvendig.',
+'Installation_SystemCheckMailHelp' => 'Tilbagemelding og Glemt adgangskode vil ikke blive sendt uden mail() funktion',
+'Installation_SystemCheckParseIniFileHelp' => 'Den indbyggede funktion er blevet deaktiveret hos udbyderen. Piwik vil forsøge at efterligne funktionen, men kan støde på yderligere sikkerhed restriktioner. Sporingsydelsen vil også blive påvirket.',
+'Installation_SystemCheckDebugBacktraceHelp' => 'View:: factory kan ikke oprette visninger for det modul.',
+'Installation_SystemCheckCreateFunctionHelp' => 'Piwik bruger anonyme funktioner til tilbagekald.',
+'Installation_SystemCheckMbstring' => 'mbstring',
+'Installation_SystemCheckMbstringHelp' => 'Manglende mb_substr_replace () funktion. Angiv mbstring.func_overload til "0".',
+'Installation_SystemCheckFileIntegrity' => 'Fil integritet',
+'Installation_SystemCheckError' => 'En fejl opstod - skal rettes før der fortsættes',
+'Installation_SystemCheckWarning' => 'Piwik vil virke normalt, men nogle funktioner vil måske mangle',
+'Installation_SystemCheckProtocol' => 'Protokol',
+'Installation_SystemCheckProtocolHelp' => 'Hvis du er bag en reverse proxy tilføj disse linjer til config/config.ini.php under [General] afsnittet:',
+'Installation_SystemCheckIpv4' => 'IPv4',
+'Installation_SystemCheckIpv4Help' => ' »IPv6 bør deaktivere på webserveren.',
+'Installation_Tables' => 'Opretter tabeller',
+'Installation_TablesWithSameNamesFound' => 'Nogle %1$s tabeller i databasen %2$s har samme navn, som dem Piwik prøver at oprette',
+'Installation_TablesFound' => 'Følgende tabeller blev fundet i databasen',
+'Installation_TablesWarningHelp' => 'Vælg enten at genbruge de eksisterende tabeller eller vælg en ren installation for at slette alle eksisterende data.',
+'Installation_TablesReuse' => 'Genbrug de eksisterende tabeller',
+'Installation_TablesDelete' => 'Slet detekterede tabeller',
+'Installation_TablesDeletedSuccess' => 'Eksisterende Piwik-tabeller blev slettet',
+'Installation_TablesCreatedSuccess' => 'Tabellerne blev oprettet!',
+'Installation_DatabaseCreatedSuccess' => 'Databasen %s blev oprettet!',
+'Installation_GoBackAndDefinePrefix' => 'Gå tilbage og opret præfix for Piwik Tabeller',
+'Installation_ConfirmDeleteExistingTables' => 'Bekræft sletning af tabellerne: %s fra databasen? ADVARSEL: DATA FRA DISSE TABELLER KAN IKKE GENSKABES!',
+'Installation_Welcome' => 'Velkommen!',
+'Installation_WelcomeHelp' => '<p>Piwik er et Open Source statistik-program som gør det nemt at finde information om besøgende.</p><p> Processen er delt op i %s lette trin og vil tage ca. 5 minutter.</p>',
+'Installation_ConfigurationHelp' => 'Piwik konfigurationsfil synes at være konfigureret forkert. Fjern enten config/config.ini.php og genoptage installation eller ret database forbindelsesindstillinger.',
+'Installation_ErrorInvalidState' => 'Fejl: Det lader til at du forsøger at springe et skridt af installationen over, eller cookies er slået fra, eller Piwik opsætningsfil allerede er oprettet. %1$sSørg for, at cookies er aktiveret%2$s og gå tilbage %3$s til den første side i installationen %4$s.',
+'LanguagesManager_PluginDescription' => ' Programudvidelsen viser en liste over de tilgængelige sprog for Piwik brugerflade. Det valgte sprog vil blive gemt i præferencer for hver bruger.',
+'LanguagesManager_AboutPiwikTranslations' => 'Om Piwik oversættelser',
+'Live_PluginDescription' => 'Besøgende her og nu!',
+'Live_VisitorLog' => 'Besøgslog',
+'Live_Date' => 'Dato',
+'Live_Time' => 'Tid',
+'Live_Referrer_URL' => 'Henvisning URL',
+'Login_PluginDescription' => ' Log ind godkendelse modul læser legitimationsoplysninger fra config/config.inc.php fil for superbrugeren og fra databasen for andre brugere. Kan let udskiftes for at indføre en ny godkendelses metode (OpenID, htaccess, brugerdefineret godkendelse, osv.).',
+'Login_LoginPasswordNotCorrect' => 'Brugernavn og adgangskode er ikke korrekt',
+'Login_Password' => 'Adgangskode',
+'Login_PasswordRepeat' => 'Adgangskode (gentag)',
+'Login_ChangePassword' => 'Skift adgangskode',
+'Login_LoginOrEmail' => 'Brugernavn eller e-mailadresse',
+'Login_LogIn' => 'Log på',
+'Login_Logout' => 'Log af',
+'Login_LostYourPassword' => 'Glemt adgangskoden?',
+'Login_RemindPassword' => 'Send adgangskode nulstilling',
+'Login_PasswordResetToken' => 'Token til nulstilling af adgangskode',
+'Login_PasswordReminder' => 'Indtaste brugernavn eller e-mail-adresse. Du vil modtage en e-mail med oplysninger til at nulstille adgangskoden.',
+'Login_PasswordsDoNotMatch' => 'Adgangskoder er ikke ens.',
+'Login_PasswordSuccessfullyChanged' => 'Adgangskode er ændret!',
+'Login_InvalidUsernameEmail' => 'Fejl i brugernavn og/eller e-mailadresse.',
+'Login_InvalidNonceOrReferer' => 'Formular sikkerhedsnøglen er invalid eller er udløbet. Genindlæs formularen og kontrollerer, at cookies er aktiveret.',
+'Login_InvalidOrExpiredToken' => 'Nøglen er forkert eller udløbet',
+'Login_MailTopicPasswordRecovery' => 'Genopret adgangskode',
+'Login_MailPasswordRecoveryBody' => 'Hej %1$s, \n\n Anmodning om nulstilling af adgangskode er modtaget fra %2$s.\n\nFor at nulstille adgangskode:\n\n1) Gå til nulstil adgangskode formularen:\n\t%3$s\n\n2) Indtast følgende nøgle:\n\t%4$s\n\n3) Udfyld formularen (indtast ny adgangskode 2 gange) og send.\n\nObs: nøglen udløber efter 24 timer.\n',
+'Login_PasswordSent' => 'Oplysninger til at nulstille din adgangskode er blevet sendt. Tjek din e-mail.',
+'Login_ContactAdmin' => 'Mulig årsag: udbyderen har måske deaktiveret mail()-funktionen. <br />Kontakt Piwik administrator.',
+'MultiSites_PluginDescription' => ' Viser multi-site resumé/statistik. Vedligeholdes som et kerne Piwik programudvidelse.',
+'Provider_PluginDescription' => 'Rapporter de besøgendes udbyder.',
+'Provider_WidgetProviders' => 'Udbydere',
+'Provider_ColumnProvider' => 'Udbyder',
+'Provider_SubmenuLocationsProvider' => 'Sted og udbyder',
+'Referers_PluginDescription' => 'Rapporterer henvisningsdata: Søgemaskiner, nøgleord, hjemmesider, kampagnesporing, direkte træf.',
'Referers_Referers' => 'Henvisninger',
'Referers_SearchEngines' => 'Søgemaskine',
-'Referers_Keywords' => ' Top søgeord',
+'Referers_Keywords' => 'Søgeord',
'Referers_DirectEntry' => 'Direkte træf',
-'Referers_Websites' => 'Websider',
+'Referers_Websites' => 'Hjemmesider',
'Referers_Campaigns' => 'Kampagner',
-'Referers_MetricsFromRefererTypeGraphLegend' => '%1s (fra %2s)',
-'Referers_Evolution' => 'Udvikling over perioden',
-'Referers_Type' => 'Kilde type',
+'Referers_MetricsFromRefererTypeGraphLegend' => '%1$s (fra %2$s)',
+'Referers_Evolution' => 'Udvikling i perioden',
+'Referers_Type' => 'Henvisningstype',
'Referers_ColumnRefererType' => 'Henvisningstype',
'Referers_ColumnSearchEngine' => 'Søgemaskine',
-'Referers_ColumnWebsite' => 'Websted',
-'Referers_ColumnWebsitePage' => 'Websider',
+'Referers_ColumnWebsite' => 'Hjemmesider',
+'Referers_ColumnWebsitePage' => 'Hjemmeside',
'Referers_ColumnKeyword' => 'Søgeord',
-'Referers_ColumnCampaign' => 'Kampagner',
+'Referers_ColumnCampaign' => 'Kampagne',
'Referers_DetailsByRefererType' => 'Detaljer efter kildetype',
'Referers_TypeDirectEntries' => '%s direkte træf',
'Referers_TypeSearchEngines' => '%s fra søgemaskine',
-'Referers_TypeWebsites' => '%s fra websider',
+'Referers_TypeWebsites' => '%s fra hjemmesider',
'Referers_TypeCampaigns' => '%s fra kampagner',
'Referers_Distinct' => 'Distinkte kilder efter kildetype',
'Referers_DistinctSearchEngines' => '%s distinkte søgemaskine',
'Referers_DistinctKeywords' => '%s distinkte søgeord',
'Referers_DistinctCampaigns' => 'distinkte kampagner',
-'Referers_DistinctWebsites' => 'Distinkte websider ',
-'Referers_UsingNDistinctUrls' => ' (bruger %2s distinkte webadresser)',
+'Referers_DistinctWebsites' => 'distinkte hjemmesider',
+'Referers_UsingNDistinctUrls' => ' (bruger %1s distinkte webadresser)',
'Referers_SubmenuEvolution' => 'Udvikling',
'Referers_SubmenuSearchEngines' => 'Søgemaskine og søgeord',
-'Referers_SubmenuWebsites' => 'Websider',
+'Referers_SubmenuWebsites' => 'Hjemmesider',
'Referers_SubmenuCampaigns' => 'Kampagner',
'Referers_WidgetKeywords' => 'Søgeord',
'Referers_WidgetCampaigns' => 'Kampagner',
-'Referers_WidgetExternalWebsites' => 'Eksterne henvisninger',
+'Referers_WidgetExternalWebsites' => 'Eksterne hjemmesider',
'Referers_WidgetSearchEngines' => 'Top søgemaskine',
'Referers_WidgetOverview' => 'Oversigt',
-'UserSettings_VisitorSettings' => 'Besøgendes indstillinger',
-'UserSettings_BrowserFamilies' => 'Netlæsertyper',
-'UserSettings_Browsers' => 'Netlæsere',
-'UserSettings_Plugins' => 'Plugins',
-'UserSettings_Configurations' => 'Indstillinger',
-'UserSettings_OperatinsSystems' => 'Styresystemer',
-'UserSettings_Resolutions' => 'Opløsninger',
-'UserSettings_WideScreen' => 'Widescreen',
-'UserSettings_ColumnBrowserFamily' => 'Netlæsertype',
-'UserSettings_ColumnBrowser' => 'Netlæser',
-'UserSettings_ColumnPlugin' => 'Plugin',
-'UserSettings_ColumnConfiguration' => 'Konfiguration',
-'UserSettings_ColumnOperatinsSystem' => 'Styresystem',
-'UserSettings_ColumnResolution' => 'Opløsning',
-'UserSettings_ColumnTypeOfScreen' => 'Skærmtype',
-'UserSettings_WidgetResolutions' => 'Skærmopløsninger',
-'UserSettings_WidgetBrowsers' => 'Netlæsere',
-'UserSettings_WidgetPlugins' => 'Plugins',
-'UserSettings_WidgetWidescreen' => 'Normal/Widescreen',
-'UserSettings_WidgetBrowserFamilies' => 'Netlæsere efter type',
-'UserSettings_WidgetOperatingSystems' => 'Styresystemer',
-'UserSettings_WidgetGlobalVisitors' => 'Besøgendes konfiguration',
-'UserSettings_SubmenuSettings' => 'Indstillinger',
+'SecurityInfo_PluginDescription' => ' Baseret på PhpSecInfo fra PHP Security Consortium, giver udvidelsesmodulet sikkerhedsoplysninger om PHP-miljøet, og giver forslag til forbedringer. Det er et værktøj i en flersidig sikkerhedstilgang. Det erstatter ikke sikker udviklingspraksis eller revision af kode/program.',
+'SecurityInfo_Security' => 'Sikkerhed',
+'SecurityInfo_SecurityInformation' => 'PHP sikkerhedsinformation',
+'SecurityInfo_Test' => 'Test',
+'SecurityInfo_Result' => 'Resultat',
+'SitesManager_PluginDescription' => 'Hjemmeside styring i Piwik: Tilføj en ny hjemmeside, rediger en eksisterende, vis JavaScript-koden til at inkludere på siderne. Alle handlinger er også tilgængelige via API.',
+'SitesManager_Sites' => 'Hjemmesider',
+'SitesManager_WebsitesManagement' => 'Administration af hjemmesider',
+'SitesManager_MainDescription' => 'Web statistik behøver hjemmesider! Tilføj, opdater, slet hjemmesider og vis JavaScriptkoden, som skal tilføjes hjemmesiderne.',
+'SitesManager_JsTrackingTag' => 'JavaScript sporingskode',
+'SitesManager_JsTrackingTagHelp' => 'JavaScript-sporingskoden som skal tilføjes til alle sider',
+'SitesManager_ShowTrackingTag' => 'vis sporingskode',
+'SitesManager_NoWebsites' => 'Der er ingen hjemmeside at administrere',
+'SitesManager_AddSite' => 'Tilføj en ny hjemmeside',
+'SitesManager_AliasUrlHelp' => 'Det anbefales, men er ikke nødvendigt at angive de forskellige webadresser, en på hver linje, som dine besøgende kan komme ind på denne hjemmeside. Alias webadresser for et websted, vises ikke i Henvisning> Websider rapport. Bemærk, at det ikke er nødvendigt at specificere webadresser med og uden \'www\' da piwik automatisk finder begge.',
+'SitesManager_Id' => 'ID',
+'SitesManager_Name' => 'Navn',
+'SitesManager_Urls' => 'Webadresser',
+'SitesManager_MenuSites' => 'Hjemmesider',
+'SitesManager_DeleteConfirm_js' => 'Bekræft sletning af følgende hjemmeside? %s',
+'SitesManager_ExceptionDeleteSite' => 'Det er ikke muligt at slette hjemmeside, da det er det eneste oprettede. Tilføj en ny hjemmeside, og slet så dette .',
+'SitesManager_ExceptionNoUrl' => 'Angiv mindst én webadresse til hjemmesiden.',
+'SitesManager_ExceptionEmptyName' => 'Hjemmesidens navn kan ikke være tomt.',
+'SitesManager_ExceptionInvalidUrl' => 'Webadressen \'%s\' er ikke gyldig.',
+'SitesManager_SuperUserCan' => 'Superbrugeren kan også %s angive globale indstillinger%s for nye hjemmesider.',
+'SitesManager_ExcludedIps' => 'Udeluk IP-adresser',
+'SitesManager_GlobalListExcludedIps' => 'Liste over udelukkede IP-adresser',
+'SitesManager_ListOfIpsToBeExcludedOnAllWebsites' => 'Indtast IP-adresser, som skal udelukkes fra at blive sporet på alle hjemmesider.',
+'SitesManager_ExcludedParameters' => 'Udeluk parametre',
+'SitesManager_GlobalListExcludedQueryParameters' => ' Global liste over udelukkede søgeparametre på hjemmesideadresser',
+'SitesManager_ListOfQueryParametersToBeExcludedOnAllWebsites' => 'Hjemmesideadresse søgeparameterne nedenfor vil blive udelukket fra hjemmesideadresser på alle hjemmesider.',
+'SitesManager_ListOfQueryParametersToExclude' => 'Indtast en liste over søgeparametre for hjemmesideadresser, én pr linje, der skal udelukkes fra hjemmesideadresse rapporter.',
+'SitesManager_PiwikWillAutomaticallyExcludeCommonSessionParameters' => ' Piwik vil automatisk udelukke den fælles session parametre (%s).',
+'SitesManager_HelpExcludedIps' => 'Indtast IP-adresserne, en pr. linje, som du ønsker at udelukke fra sporing. Du kan bruge jokertegn, f.eks. %1s eller %2s',
+'SitesManager_YourCurrentIpAddressIs' => 'Din aktuelle IP-adresse er %s',
+'SitesManager_SelectACity' => 'Vælg en by',
+'SitesManager_ChooseCityInSameTimezoneAsYou' => ' Vælg en by i samme tidszone som dig.',
+'SitesManager_ChangingYourTimezoneWillOnlyAffectDataForward' => ' Ændring af tidszonen kun påvirke fremtidige data og vil ikke blive anvendt med tilbagevirkende kraft.',
+'SitesManager_AdvancedTimezoneSupportNotFound' => 'PHP understøtter ikke avancerede tidszoner (understøttes i PHP> = 5.2). Du kan stadig vælge en manuel UTC offset.',
+'SitesManager_UTCTimeIs' => 'UTC tid er %s.',
+'SitesManager_Timezone' => 'Tidszone',
+'SitesManager_GlobalWebsitesSettings' => 'Globale hjemmeside indstillinger',
+'SitesManager_DefaultTimezone' => 'Standard tidszone',
+'SitesManager_SelectDefaultTimezone' => ' Vælg standard tidszone for nye hjemmesider.',
+'SitesManager_Currency' => 'Valuta',
+'SitesManager_CurrencySymbolWillBeUsedForGoals' => 'Valuta symbol vises ved siden af mål indtægter.',
+'SitesManager_DefaultCurrency' => 'Standard valuta',
+'SitesManager_SelectDefaultCurrency' => 'Vælg standard valuta for nye hjemmesider.',
+'TranslationsAdmin_PluginDescription' => ' Hjælpe med at oversætte Piwik.',
+'TranslationsAdmin_MenuTranslations' => 'Oversættelser',
+'TranslationsAdmin_MenuLanguages' => 'Sprog',
+'TranslationsAdmin_Plugin' => 'Udvidelsesmodul',
+'TranslationsAdmin_Definition' => 'Definition',
+'TranslationsAdmin_DefaultString' => 'Standard (English)',
+'TranslationsAdmin_TranslationString' => 'Oversættelse (nuværende sprog: %s)',
+'TranslationsAdmin_Translations' => 'Oversættelser',
+'TranslationsAdmin_FixPermissions' => 'Ret filsystem-rettighederne',
+'TranslationsAdmin_AvailableLanguages' => 'Tilgængelige sprog',
+'TranslationsAdmin_AddLanguage' => 'Tilføj sprog',
+'TranslationsAdmin_LanguageCode' => 'Sprogkode',
+'TranslationsAdmin_Export' => 'Eksporter sprog',
+'TranslationsAdmin_Import' => 'Importer sprog',
+'UserCountry_PluginDescription' => 'Rapporter besøgendes land.',
'UserCountry_Country' => 'Land',
'UserCountry_Continent' => 'Kontinent',
'UserCountry_DistinctCountries' => '%s distinkte lande',
@@ -287,7 +629,7 @@ $translations = array(
'UserCountry_country_at' => 'Østrig',
'UserCountry_country_au' => 'Australien',
'UserCountry_country_aw' => 'Aruba',
-'UserCountry_country_ax' => 'Aland Islands',
+'UserCountry_country_ax' => 'Åland',
'UserCountry_country_az' => 'Aserbajdsjan',
'UserCountry_country_ba' => 'Bosnien-Hercegovina',
'UserCountry_country_bb' => 'Barbados',
@@ -298,7 +640,7 @@ $translations = array(
'UserCountry_country_bh' => 'Bahrain',
'UserCountry_country_bi' => 'Burundi',
'UserCountry_country_bj' => 'Benin',
-'UserCountry_country_bl' => 'Saint Barthelemy',
+'UserCountry_country_bl' => 'Saint Barthélemy',
'UserCountry_country_bm' => 'Bermuda',
'UserCountry_country_bn' => 'Brunei Darussalam',
'UserCountry_country_bo' => 'Bolivia',
@@ -306,17 +648,17 @@ $translations = array(
'UserCountry_country_bs' => 'Bahamas',
'UserCountry_country_bt' => 'Bhutan',
'UserCountry_country_bu' => 'Burma',
-'UserCountry_country_bv' => 'Bouvet-øen',
+'UserCountry_country_bv' => 'Bouvetø',
'UserCountry_country_bw' => 'Botswana',
-'UserCountry_country_by' => 'Belarus',
+'UserCountry_country_by' => 'Hviderusland',
'UserCountry_country_bz' => 'Belize',
'UserCountry_country_ca' => 'Canada',
-'UserCountry_country_cc' => 'Kokos-øerne (Keeling-øerne)',
-'UserCountry_country_cd' => 'Den Demokratiske Republik Congo',
+'UserCountry_country_cc' => 'Cocosøerne)',
+'UserCountry_country_cd' => 'Congo-Kinshasa',
'UserCountry_country_cf' => 'Centralafrikanske Republik',
'UserCountry_country_cg' => 'Congo',
'UserCountry_country_ch' => 'Schweiz',
-'UserCountry_country_ci' => 'Côte d\'Ivoire (Elfenbenskysten)',
+'UserCountry_country_ci' => 'Elfenbenskysten',
'UserCountry_country_ck' => 'Cook-øerne',
'UserCountry_country_cl' => 'Chile',
'UserCountry_country_cm' => 'Cameroun',
@@ -324,7 +666,7 @@ $translations = array(
'UserCountry_country_co' => 'Colombia',
'UserCountry_country_cp' => 'Clipperton Island',
'UserCountry_country_cr' => 'Costa Rica',
-'UserCountry_country_cs' => 'Serbien-Montenegro',
+'UserCountry_country_cs' => 'Serbien og Montenegro',
'UserCountry_country_cu' => 'Cuba',
'UserCountry_country_cv' => 'Kap Verde',
'UserCountry_country_cx' => 'Juleøen',
@@ -335,39 +677,39 @@ $translations = array(
'UserCountry_country_dj' => 'Djibouti',
'UserCountry_country_dk' => 'Danmark',
'UserCountry_country_dm' => 'Dominica',
-'UserCountry_country_do' => 'Dominikanske Republik',
+'UserCountry_country_do' => 'Den Dominikanske Republik',
'UserCountry_country_dz' => 'Algier',
'UserCountry_country_ea' => 'Ceuta, Melilla',
'UserCountry_country_ec' => 'Ecuador',
'UserCountry_country_ee' => 'Estland',
'UserCountry_country_eg' => 'Egypten',
-'UserCountry_country_eh' => 'Vest-Sahara',
+'UserCountry_country_eh' => 'Vestsahara',
'UserCountry_country_er' => 'Eritrea',
'UserCountry_country_es' => 'Spanien',
'UserCountry_country_et' => 'Etiopien',
'UserCountry_country_eu' => 'Europæiske Union',
'UserCountry_country_fi' => 'Finland',
-'UserCountry_country_fj' => 'Fiji',
-'UserCountry_country_fk' => 'Falklandsøerne (Malvinerne)',
-'UserCountry_country_fm' => 'Mikronesien',
+'UserCountry_country_fj' => 'Fiji-øerne',
+'UserCountry_country_fk' => 'Falklandsøerne',
+'UserCountry_country_fm' => 'Mikronesiens Forenede Stater',
'UserCountry_country_fo' => 'Færøerne',
'UserCountry_country_fr' => 'Frankrig',
'UserCountry_country_fx' => 'Fransk Metropolitan',
'UserCountry_country_ga' => 'Gabon',
'UserCountry_country_gb' => 'Storbritannien',
'UserCountry_country_gd' => 'Grenada',
-'UserCountry_country_ge' => 'Grenada',
-'UserCountry_country_gf' => 'Georgien',
-'UserCountry_country_gg' => 'Fransk Guyana',
+'UserCountry_country_ge' => 'Georgien',
+'UserCountry_country_gf' => 'Fransk Guyana',
+'UserCountry_country_gg' => 'Guernsey',
'UserCountry_country_gh' => 'Ghana',
'UserCountry_country_gi' => 'Gibraltar',
'UserCountry_country_gl' => 'Grønland',
'UserCountry_country_gm' => 'Gambia',
'UserCountry_country_gn' => 'Guinea',
'UserCountry_country_gp' => 'Guadeloupe',
-'UserCountry_country_gq' => 'Ækvatorial Guinea',
+'UserCountry_country_gq' => 'Ækvatorialguinea',
'UserCountry_country_gr' => 'Grækenland',
-'UserCountry_country_gs' => 'Syd-Georgien og Sydlige Sandwich-øer',
+'UserCountry_country_gs' => 'Syd Georgien og Sydlige Sandwichøer',
'UserCountry_country_gt' => 'Guatemala',
'UserCountry_country_gu' => 'Guam',
'UserCountry_country_gw' => 'Guinea-Bissau',
@@ -384,7 +726,7 @@ $translations = array(
'UserCountry_country_il' => 'Israel',
'UserCountry_country_im' => 'Man Island',
'UserCountry_country_in' => 'Indien',
-'UserCountry_country_io' => 'British Indian Ocean Territory',
+'UserCountry_country_io' => 'Det Britiske Territorium i Det Indiske Ocean',
'UserCountry_country_iq' => 'Irak',
'UserCountry_country_ir' => 'Iran',
'UserCountry_country_is' => 'Island',
@@ -395,19 +737,19 @@ $translations = array(
'UserCountry_country_jp' => 'Japan',
'UserCountry_country_ke' => 'Kenya',
'UserCountry_country_kg' => 'Kirgisistan',
-'UserCountry_country_kh' => 'Cambodia',
+'UserCountry_country_kh' => 'Cambodja',
'UserCountry_country_ki' => 'Kiribati',
'UserCountry_country_km' => 'Comorerne',
'UserCountry_country_kn' => 'Sankt Kitts og Nevis',
'UserCountry_country_kp' => 'Nordkorea',
'UserCountry_country_kr' => 'Sydkorea',
'UserCountry_country_kw' => 'Kuwait',
-'UserCountry_country_ky' => 'Cayman-øerne',
+'UserCountry_country_ky' => 'Caymanøerne',
'UserCountry_country_kz' => 'Kasakhstan',
'UserCountry_country_la' => 'Laos',
'UserCountry_country_lb' => 'Libanon',
'UserCountry_country_lc' => 'Sankt Lucia',
-'UserCountry_country_li' => 'Lichtenstein',
+'UserCountry_country_li' => 'Liechtenstein',
'UserCountry_country_lk' => 'Sri Lanka',
'UserCountry_country_lr' => 'Liberia',
'UserCountry_country_ls' => 'Lesotho',
@@ -417,17 +759,17 @@ $translations = array(
'UserCountry_country_ly' => 'Libyen',
'UserCountry_country_ma' => 'Marokko',
'UserCountry_country_mc' => 'Monaco',
-'UserCountry_country_md' => 'Moldova',
+'UserCountry_country_md' => 'Republikken Moldova',
'UserCountry_country_me' => 'Montenegro',
'UserCountry_country_mf' => 'Saint Martin',
'UserCountry_country_mg' => 'Madagaskar',
-'UserCountry_country_mh' => 'Marshall-øerne',
-'UserCountry_country_mk' => 'Makedonien',
+'UserCountry_country_mh' => 'Marshalløerne',
+'UserCountry_country_mk' => 'Republikken Makedonien',
'UserCountry_country_ml' => 'Mali',
'UserCountry_country_mm' => 'Myanmar',
'UserCountry_country_mn' => 'Mongoliet',
-'UserCountry_country_mo' => 'Macau',
-'UserCountry_country_mp' => 'Nordlige Marianere',
+'UserCountry_country_mo' => 'Macao',
+'UserCountry_country_mp' => 'Nordmarianerne',
'UserCountry_country_mq' => 'Martinique',
'UserCountry_country_mr' => 'Mauretanien',
'UserCountry_country_ms' => 'Montserrat',
@@ -439,7 +781,7 @@ $translations = array(
'UserCountry_country_my' => 'Malaysia',
'UserCountry_country_mz' => 'Mozambique',
'UserCountry_country_na' => 'Namibia',
-'UserCountry_country_nc' => 'New Caledonia',
+'UserCountry_country_nc' => 'Ny Caledonien',
'UserCountry_country_ne' => 'Niger',
'UserCountry_country_nf' => 'Norfolk-øen',
'UserCountry_country_ng' => 'Nigeria',
@@ -455,8 +797,8 @@ $translations = array(
'UserCountry_country_pa' => 'Panama',
'UserCountry_country_pe' => 'Peru',
'UserCountry_country_pf' => 'Fransk Polynesien',
-'UserCountry_country_pg' => 'Papua New Guinea',
-'UserCountry_country_ph' => 'Philippinerne',
+'UserCountry_country_pg' => 'Papua Ny Guinea',
+'UserCountry_country_ph' => 'Filippinerne',
'UserCountry_country_pk' => 'Pakistan',
'UserCountry_country_pl' => 'Polen',
'UserCountry_country_pm' => 'Sankt Pierre og Miquelon',
@@ -464,22 +806,22 @@ $translations = array(
'UserCountry_country_pr' => 'Puerto Rico',
'UserCountry_country_ps' => 'Palæstina',
'UserCountry_country_pt' => 'Portugal',
-'UserCountry_country_pw' => 'Palau-øerne',
+'UserCountry_country_pw' => 'Palau',
'UserCountry_country_py' => 'Paraguay',
'UserCountry_country_qa' => 'Qatar',
-'UserCountry_country_re' => 'Réunion',
+'UserCountry_country_re' => 'Reunion',
'UserCountry_country_ro' => 'Rumænien',
-'UserCountry_country_ru' => 'Russiske Føderation',
+'UserCountry_country_ru' => 'Rusland',
'UserCountry_country_rs' => 'Serbien',
'UserCountry_country_rw' => 'Rwanda',
'UserCountry_country_sa' => 'Saudi-Arabien',
-'UserCountry_country_sb' => 'Salomon-øerne',
+'UserCountry_country_sb' => 'Salomonøerne',
'UserCountry_country_sc' => 'Seychellerne',
'UserCountry_country_sd' => 'Sudan',
'UserCountry_country_se' => 'Sverige',
'UserCountry_country_sf' => 'Finland',
'UserCountry_country_sg' => 'Singapore',
-'UserCountry_country_sh' => 'Sankt Helena',
+'UserCountry_country_sh' => 'St. Helena',
'UserCountry_country_si' => 'Slovenien',
'UserCountry_country_sj' => 'Svalbard og Jan Mayen',
'UserCountry_country_sk' => 'Slovakiet',
@@ -487,16 +829,16 @@ $translations = array(
'UserCountry_country_sm' => 'San Marino',
'UserCountry_country_sn' => 'Senegal',
'UserCountry_country_so' => 'Somalia',
-'UserCountry_country_sr' => 'Suriname',
-'UserCountry_country_st' => 'São Tomé og Príncipe',
-'UserCountry_country_su' => '[Russiske Føderation]',
+'UserCountry_country_sr' => 'Surinam',
+'UserCountry_country_st' => 'Sao Tome og Príncipe',
+'UserCountry_country_su' => 'Russiske Føderation',
'UserCountry_country_sv' => 'El Salvador',
'UserCountry_country_sy' => 'Syrien',
'UserCountry_country_sz' => 'Swaziland',
'UserCountry_country_ta' => 'Tristan da Cunha',
-'UserCountry_country_tc' => 'Turks- og Caicos-øerne',
-'UserCountry_country_td' => 'Chad',
-'UserCountry_country_tf' => 'Franske Sydlige Territorier',
+'UserCountry_country_tc' => 'Turks- og Caicosøerne',
+'UserCountry_country_td' => 'Tchad',
+'UserCountry_country_tf' => 'Franske besiddelser i det sydlige indiske ocean',
'UserCountry_country_tg' => 'Togo',
'UserCountry_country_th' => 'Thailand',
'UserCountry_country_tj' => 'Tadsjikistan',
@@ -513,26 +855,26 @@ $translations = array(
'UserCountry_country_tz' => 'Tanzania',
'UserCountry_country_ua' => 'Ukraine',
'UserCountry_country_ug' => 'Uganda',
-'UserCountry_country_uk' => 'England',
-'UserCountry_country_um' => 'Forenede Staters Mindre Perifere',
-'UserCountry_country_us' => 'Amerikas Forenede Stater (USA)',
+'UserCountry_country_uk' => 'Storbritannien',
+'UserCountry_country_um' => 'De Mindre Amerikanske Oversøiske Øer',
+'UserCountry_country_us' => 'USA',
'UserCountry_country_uy' => 'Uruguay',
'UserCountry_country_uz' => 'Usbekistan',
'UserCountry_country_va' => 'Vatikanstaten',
'UserCountry_country_vc' => 'Sankt Vincent og Grenadinerne',
'UserCountry_country_ve' => 'Venezuela',
-'UserCountry_country_vg' => 'Jomfruøerne, Engelsk',
-'UserCountry_country_vi' => 'Jomfruøerne, USA',
-'UserCountry_country_vn' => 'Viet Nam',
+'UserCountry_country_vg' => 'De Britiske Jomfruøer',
+'UserCountry_country_vi' => 'De amerikanske Jomfruøer',
+'UserCountry_country_vn' => 'Vietnam',
'UserCountry_country_vu' => 'Vanuatu',
-'UserCountry_country_wf' => 'Wallis- og Futuna-øerne',
+'UserCountry_country_wf' => 'Wallis- og Futunaøerne',
'UserCountry_country_ws' => 'Samoa',
'UserCountry_country_ye' => 'Yemen',
'UserCountry_country_yt' => 'Mayotte',
-'UserCountry_country_yu' => 'Jugoslavien (Serbien og Montenegro)',
-'UserCountry_country_za' => 'Sydafrikanske Republik',
+'UserCountry_country_yu' => 'Jugoslavien',
+'UserCountry_country_za' => 'Sydafrika',
'UserCountry_country_zm' => 'Zambia',
-'UserCountry_country_zr' => 'Zaire [Den Demokratiske Republik',
+'UserCountry_country_zr' => 'Zaire',
'UserCountry_country_zw' => 'Zimbabwe',
'UserCountry_continent_eur' => 'Europa',
'UserCountry_continent_afr' => 'Afrika',
@@ -540,195 +882,127 @@ $translations = array(
'UserCountry_continent_ams' => 'Syd- og Centralamerika',
'UserCountry_continent_amn' => 'Nordamerika',
'UserCountry_continent_oce' => 'Oceanien',
-'VisitsSummary_NbVisits' => '%s besøg',
-'VisitsSummary_NbUniqueVisitors' => '%s unikke besøgende',
-'VisitsSummary_NbActions' => '%s handlinger (sidevisninger)',
-'VisitsSummary_TotalTime' => '%s samlet tid brugt af besøgende',
-'VisitsSummary_MaxNbActions' => '%s maks. handlinger i ét besøg',
-'VisitsSummary_NbVisitsBounced' => '%s har forladt websted efter én sidevisning',
-'VisitsSummary_EvolutionOverLastPeriods' => 'Udvikling de sidste %s',
-'VisitsSummary_Report' => 'Rapport',
-'VisitsSummary_GenerateTime' => 'Siden generedes på %s sek.',
-'VisitsSummary_GenerateQueries' => '%s forespørgelser kørt',
-'VisitsSummary_WidgetLastVisits' => 'Seneste besøg',
-'VisitsSummary_WidgetVisits' => 'Besøgsoversigt',
-'VisitsSummary_WidgetLastVisitors' => 'Seneste unikke besøgende',
-'VisitsSummary_WidgetOverviewGraph' => 'Oversigt med grafik',
-'VisitsSummary_SubmenuOverview' => 'Oversigt',
-'VisitFrequency_Evolution' => 'Udvikling i perioden',
-'VisitFrequency_ColumnReturningVisits' => 'Tilbagevendende besøg',
-'VisitFrequency_ColumnActionsByReturningVisits' => 'Handlinger af tilbagevendene besøg',
-'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Max antal handlinger af tilbagevendene besøg',
-'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Samlet tid brugt af tilbagevendene besøg (i sekunder)',
-'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Afvisningsfrekvens for tilbagevendene besøg',
-'VisitFrequency_ReturnVisits' => '%s tilbagevendende besøg',
-'VisitFrequency_ReturnActions' => '%s handlinger af de tilbagevendende besøg',
-'VisitFrequency_ReturnMaxActions' => '%s maks. handlinger af de tilbagevendende besøg',
-'VisitFrequency_ReturnTotalTime' => '%s total tid brugt af de tilbagevendende besøg',
-'VisitFrequency_ReturnBounceRate' => '%s tilbagevendende besøg har forladt siden efter en sidevisning.',
-'VisitFrequency_WidgetOverview' => 'Hyppighedsoversigt',
-'VisitFrequency_WidgetGraphReturning' => 'Tilbagevendende besøg',
-'VisitFrequency_SubmenuFrequency' => 'Hyppighed',
-'VisitTime_LocalTime' => 'Besøg pr. lokaltid',
-'VisitTime_ServerTime' => 'Besøg pr. servertid',
-'VisitTime_ColumnServerTime' => 'Servertid',
-'VisitTime_ColumnLocalTime' => 'Lokaltid',
-'VisitTime_WidgetLocalTime' => 'Besøg (lokaltid)',
-'VisitTime_WidgetServerTime' => 'Besøg (servertid)',
-'VisitTime_SubmenuTimes' => 'Tider',
-'VisitTime_NHour' => '%s',
-'VisitorInterest_VisitsPerDuration' => 'Tid pr. besøg',
-'VisitorInterest_VisitsPerNbOfPages' => 'Besøg pr. antal sider',
-'VisitorInterest_ColumnVisitDuration' => 'Besøgslængde',
-'VisitorInterest_ColumnPagesPerVisit' => 'Sider pr. besøg',
-'VisitorInterest_WidgetLengths' => 'Besøgslængde',
-'VisitorInterest_WidgetPages' => 'Sidevisninger pr. besøg',
-'VisitorInterest_SubmenuFrequencyLoyalty' => 'Hyppighed og loyalitet',
-'VisitorInterest_PlusXMin' => '%s min.',
-'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min.',
-'VisitorInterest_OnePage' => '1 side',
-'VisitorInterest_NPages' => '%s sider',
-'VisitorInterest_BetweenXYSeconds' => '%1s-%2 sek.',
-'Login_LoginPasswordNotCorrect' => 'Brugernavn og adgangskode er ikke korrekt',
-'Login_Login' => 'Brugernavn',
-'Login_Password' => 'Adgangskode',
-'Login_LoginOrEmail' => 'Brugernavn eller e-mailadresse',
-'Login_LogIn' => 'Log på',
-'Login_Logout' => 'Log af',
-'Login_LostYourPassword' => 'Glemt adgangskode?',
-'Login_RemindPassword' => 'Husk adgangskode',
-'Login_PasswordReminder' => 'Skriv dit brugernavn eller e-mailadresse. Du vil modtage en ny adgangskode med e-mail.',
-'Login_InvalidUsernameEmail' => 'Fejl i brugernavn og/eller e-mailadresse.',
-'Login_MailTopicPasswordRecovery' => 'Genopret adgangskode',
-'Login_MailPasswordRecoveryBody' => 'Hej %1s, \n\m Ny adgangskode er: %2s \n\n Du kan logge på her: %3s',
-'Login_PasswordSent' => 'Adgangskoden er sendt. Tjek din e-mail.',
-'Login_ContactAdmin' => 'Mulig grund: udbyderen har måske deaktiveret mail()-funktionen. <br />Kontakt Piwik administrator.',
+'UserSettings_PluginDescription' => 'Rapporter bruger-indstillinger: netlæser, netlæser gruppe, operativsystem, plugins, opløsning , globale indstillinger.',
+'UserSettings_VisitorSettings' => 'Besøgendes indstillinger',
+'UserSettings_BrowserFamilies' => 'Netlæsertyper',
+'UserSettings_Browsers' => 'Netlæsere',
+'UserSettings_Plugins' => 'Udvidelsesmoduler',
+'UserSettings_Configurations' => 'Indstillinger',
+'UserSettings_OperatingSystems' => 'Styresystemer',
+'UserSettings_Resolutions' => 'Opløsninger',
+'UserSettings_WideScreen' => 'Bredformat',
+'UserSettings_ColumnBrowserFamily' => 'Netlæsertype',
+'UserSettings_ColumnBrowser' => 'Netlæser',
+'UserSettings_ColumnPlugin' => 'Udvidelsesmodul',
+'UserSettings_ColumnConfiguration' => 'Konfiguration',
+'UserSettings_ColumnOperatingSystem' => 'Styresystem',
+'UserSettings_ColumnResolution' => 'Opløsning',
+'UserSettings_ColumnTypeOfScreen' => 'Skærmtype',
+'UserSettings_WidgetResolutions' => 'Skærmopløsninger',
+'UserSettings_WidgetBrowsers' => 'Netlæsere',
+'UserSettings_WidgetPlugins' => 'Udvidelsesmoduler',
+'UserSettings_WidgetWidescreen' => 'Normal / bredformat',
+'UserSettings_WidgetBrowserFamilies' => 'Netlæsere efter type',
+'UserSettings_WidgetOperatingSystems' => 'Styresystemer',
+'UserSettings_WidgetGlobalVisitors' => 'Besøgendes konfiguration',
+'UserSettings_SubmenuSettings' => 'Indstillinger',
+'UsersManager_PluginDescription' => 'Brugere styring i Piwik: tilføje en ny bruger, redigere en eksisterende, opdatere tilladelserne. Alle handlinger er også tilgængelige via API.',
'UsersManager_UsersManagement' => 'Bruger administration',
'UsersManager_UsersManagementMainDescription' => 'Opret nye brugere eller opdater eksisterende. Efterfølgende kan tilladelser ændres.',
'UsersManager_ManageAccess' => 'Administrer adgang',
-'UsersManager_MainDescription' => 'Bestem hvilken bruger der har adgang til Piwik på websiderne. Adgang kan også sættes på alle websider på en gang.',
-'UsersManager_Sites' => 'Websteder',
-'UsersManager_AllWebsites' => 'Alle websteder',
-'UsersManager_ApplyToAllWebsites' => 'Tilføj til alle websteder',
+'UsersManager_MainDescription' => 'Bestem hvilke brugere der har hvilken Piwik adgang til hjemmesiderne. Adgang kan også sættes på alle hjemmesider på en gang.',
+'UsersManager_Sites' => 'Hjemmesider',
+'UsersManager_AllWebsites' => 'Alle hjemmesider',
+'UsersManager_ApplyToAllWebsites' => 'Tilføj til alle hjemmesider',
'UsersManager_User' => 'Bruger',
'UsersManager_PrivNone' => 'Ingen adgang',
'UsersManager_PrivView' => 'Vis',
'UsersManager_PrivAdmin' => 'Admin',
-'UsersManager_ChangeAllConfirm' => 'Bekræft ændring \'%s\' adgang på alle websiderne?',
-'UsersManager_Login' => 'Log på',
+'UsersManager_ChangeAllConfirm' => 'Bekræft ændring af \'%s\' tilladelse på alle hjemmesiderne?',
'UsersManager_Password' => 'Adgangskode',
'UsersManager_Email' => 'E-mail',
'UsersManager_Alias' => 'Alias',
-'UsersManager_Edit' => 'Ændre',
+'UsersManager_TheSuperUserAliasCannotBeChanged' => 'Superbruger alias kan ikke ændres.',
+'UsersManager_ReportToLoadByDefault' => 'Standard rapport',
+'UsersManager_ReportDateToLoadByDefault' => 'Standard rapport dato',
+'UsersManager_ForAnonymousUsersReportDateToLoadByDefault' => 'Standard rapport dato for anonyme brugere',
+'UsersManager_Edit' => 'Rediger',
'UsersManager_AddUser' => 'Opret ny bruger',
'UsersManager_MenuUsers' => 'Brugere',
+'UsersManager_MenuUserSettings' => 'Bruger indstillinger',
+'UsersManager_MenuAnonymousUserSettings' => 'Anonym bruger indstilling',
+'UsersManager_NoteNoAnonymousUserAccessSettingsWontBeUsed' => ' Bemærk: den anonyme bruger ikke adgang til nogen hjemmeside, følgende indstillinger anvendes ikke.',
+'UsersManager_WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess' => 'Når ingen brugere er logget ind på Piwik bør de tilgå',
+'UsersManager_ChangePassword' => 'Skift adgangskode',
+'UsersManager_IfYouWouldLikeToChangeThePasswordTypeANewOne' => ' Hvis du ønsker at ændre adgangskode skriv en ny. Ellers lad være blank.',
+'UsersManager_TypeYourPasswordAgain' => 'Gentag den nye adgangskode.',
+'UsersManager_TheLoginScreen' => 'Log på skærmbillede',
'UsersManager_DeleteConfirm_js' => 'Bekræft sletning af bruger %s?',
+'UsersManager_YourUsernameCannotBeChanged' => 'Brugernavnet kan ikke ændres.',
'UsersManager_ExceptionLoginExists' => 'Brugernavn \'%s\' eksisterer allerede.',
-'UsersManager_ExceptionEmailExists' => 'Bruger med e-mail \'%s\' eksisterer allerede.',
-'UsersManager_ExceptionInvalidLoginFormat' => 'Brugernavn kan kun indeholde bogstaver, tal og tegnene \'_\' eller \'-\' eller \'.\'',
+'UsersManager_ExceptionEmailExists' => 'Bruger med e-mail \'%s\' findes allerede.',
+'UsersManager_ExceptionInvalidLoginFormat' => 'Brugernavn skal være mellem %1$s og %2$s tegn og kan kun indeholde bogstaver, tal og tegnene \'_\' eller \'-\' eller \'.\'',
'UsersManager_ExceptionInvalidPassword' => 'Længden på adgangskoden skal være mellem 6 og 26 tegn.',
-'UsersManager_ExceptionInvalidEmail' => 'E-mailadressen er ikke i gyldig format.',
+'UsersManager_ExceptionInvalidEmail' => 'E-mailadressen er ikke i gyldigt format.',
'UsersManager_ExceptionDeleteDoesNotExist' => 'Bruger \'%s\' eksisterer ikke, og kan derfor ikke slettes.',
'UsersManager_ExceptionAdminAnonymous' => 'Administrator-adgang kan ikke gives til \'anonyme\'-bruger.',
-'UsersManager_ExceptionEditAnonymous' => 'Anonyme brugere kan ikke redigeres eller slettet. Anvendes af Piwik til at definere en bruger, som ikke er blevet logget på endnu. For eksempel kan du gøre din statistik offentlig ved at give \'se\' adgang til \'anonym\' bruger',
-'UsersManager_ExceptionSuperUser' => 'Anmodede bruger er Superbrugeren og kan ikke forespørges, rettes eller slettes gennem API. Kan rettes manuelt under Superbruger detaljer i Piwik konfigurationsfilen.',
+'UsersManager_ExceptionEditAnonymous' => 'Anonyme brugere kan ikke redigeres eller slettet. Anvendes af Piwik til at definere en bruger, som ikke er blevet logget på endnu. For eksempel kan du gøre din statistik offentlig ved at give \'se\' adgang til \'anonym\' bruger',
+'UsersManager_ExceptionSuperUser' => 'Anmodet bruger er Superbrugeren og kan ikke forespørges, rettes eller slettes gennem API. Kan rettes manuelt under Superbruger detaljerne i Piwik konfigurationsfilen.',
'UsersManager_ExceptionUserDoesNotExist' => 'Bruger \'%s\' findes ikke.',
'UsersManager_ExceptionAccessValues' => 'Parameteren skal have en af de følgende værdier: [ %s ]',
-'SitesManager_Sites' => 'Websteder',
-'SitesManager_WebsitesManagement' => 'Administration af websteder',
-'SitesManager_MainDescription' => 'Analyser behøver websteder! Tilføj, opdater, slet websteder, og vis JavaScriptkoden som skal tilføjes webstederne.',
-'SitesManager_JsTrackingTag' => 'JavaScript sporingskode',
-'SitesManager_JsTrackingTagHelp' => 'JavaScript-sporingskoden som skal tilføjes til alle sider',
-'SitesManager_ShowTrackingTag' => 'vis sporingskode',
-'SitesManager_NoWebsites' => 'Der er ingen websteder at administrere',
-'SitesManager_AddSite' => 'Tilføj et nyt websted',
-'SitesManager_Id' => 'ID',
-'SitesManager_Name' => 'Navn',
-'SitesManager_Urls' => 'Webadresser',
-'SitesManager_MenuSites' => 'Websteder',
-'SitesManager_DeleteConfirm_js' => 'Bekræft sletning af følgende websted? %s',
-'SitesManager_ExceptionDeleteSite' => 'Det er ikke muligt at slette webstedet, da det er det eneste oprettede websted. Tilføj et nyt websted, og slet så dette .',
-'SitesManager_ExceptionNoUrl' => 'Angiv mindst én webadresse til webstedet.',
-'SitesManager_ExceptionEmptyName' => 'Webstedets navn kan ikke være tomt.',
-'SitesManager_ExceptionInvalidUrl' => 'Webadressen \'%s\' er ikke gyldig.',
-'Installation_Installation' => 'Installation',
-'Installation_InstallationStatus' => 'Installationstatus',
-'Installation_PercentDone' => '%s %% udført',
-'Installation_NoConfigFound' => 'Piwik-konfigurationsfil blev ikke fundet og du prøver at få adgang til Piwik. <br /><b>&nbsp;&nbsp;&raquo;Du kan <a href=\'index.php\'>installere Piwik nu</a></b><br /><small> Hvis du har installeret Piwik tidliger og har nogle tabeller i databasen, kan du genbruge tabellerne og holde dine eksisterende data!</small>',
-'Installation_MysqlSetup' => 'MySQL database oprettet',
-'Installation_MysqlErrorConnect' => 'Fejl ved tilkobling til databasen',
-'Installation_JsTag' => 'JavaScript kode',
-'Installation_JsTagHelp' => '<p>For at tælle alle besøgende, indsættes JavaScript-koden på alle sider.</p><p>Siderne behøver ikke være lavet med PHP, Piwik vil virke på alle typer sider (uanset om det er HTML, ASP, Perl eller et andet sprog).</p><p>Her er koden der skal indsættes: (kopier og indsæt på alle sider)</p>',
-'Installation_Congratulations' => 'Tillykke',
-'Installation_CongratulationsHelp' => '<p>Tillykke! Piwik installationen er færdig.</p><p>Sørg for at JavaScript-koden er tilføjet på dine sider, og vent på de første besøgende!</p>',
-'Installation_ContinueToPiwik' => 'Fortsæt til Piwik',
-'Installation_SetupWebsite' => 'Tilføj et websted',
-'Installation_SetupWebsiteError' => 'Fejl ved tilføjelse af websted',
-'Installation_GeneralSetup' => 'Generel opsætning',
-'Installation_GeneralSetupSuccess' => 'Generel opsætning gemt',
-'Installation_SuperUserLogin' => 'superbruger log på',
-'Installation_Password' => 'adgangskode',
-'Installation_PasswordRepeat' => 'gentag adgangskode',
-'Installation_Email' => 'e-mail',
-'Installation_SecurityNewsletter' => 'Send e-mail med vigtige Piwik opgraderinger og sikkerheds advarsler',
-'Installation_CommunityNewsletter' => 'Send e-mail med opdateringer (nye plugins, nye muligheder m.m.)',
-'Installation_PasswordDoNotMatch' => 'adgangskoder stemmer ikke overens',
-'Installation_SubmitGo' => 'Kør!',
-'Installation_SystemCheck' => 'Systemcheck',
-'Installation_SystemCheckPhp' => 'PHP version',
-'Installation_SystemCheckPdo' => 'Pdo udvidelse',
-'Installation_SystemCheckPdoMysql' => 'Pdo_MySql udvidelse',
-'Installation_SystemCheckPdoError' => 'Aktivere PDO og PDO_MYSQL i php.ini filen.',
-'Installation_SystemCheckPdoHelp' => 'På en Windows-server tilføj følgende linjer til php-ini %s <br /><br />På en linux-server kompilere php med følgende valg %s I php.ini, tilføj følgende linjer %s<br /><br />Mere information findes på <a style=\'color:red\' href=\'http://php.net/pdo\'>PHP.net</a>.',
-'Installation_SystemCheckWriteDirs' => 'Mapper med skriveadgang',
-'Installation_SystemCheckWriteDirsHelp' => 'Prøv at skrive følgende kommandoer for at rette fejlen på et linux-system',
-'Installation_SystemCheckMemoryLimit' => 'Hukommelses grænse',
-'Installation_SystemCheckMemoryLimitHelp' => 'På et stærkt trafikeret websted, kan arkiveringsprocessen kræve mere hukommelse end der er tilladt.<br />Se på memory_limit i php.ini filen hvis nødvendig.',
-'Installation_SystemCheckGD' => 'GD &gt; 2.x (grafik)',
-'Installation_SystemCheckGDHelp' => 'Mindre grafiske elementer vil ikke fungere som ønsket.',
-'Installation_SystemCheckTimeLimit' => 'set_time_limit() tilladt',
-'Installation_SystemCheckTimeLimitHelp' => 'På et stærkt trafikeret websted, kan arkiveringsprocessen kræve mere tid end der tilladt.<br />Se på max_execution_time i php.ini filen hvis nødvendig.',
-'Installation_SystemCheckMail' => 'mail() tilgængelig',
-'Installation_SystemCheckError' => 'En fejl opstod - skal rettes før der kan fortsættes',
-'Installation_SystemCheckWarning' => 'Piwik vil virke normalt, men nogle funktioner vil måske mangle',
-'Installation_Tables' => 'Opretter tabeller',
-'Installation_TablesWithSameNamesFound' => 'Nogle %s tabeller i databasen %s har samme navn, som dem Piwik prøver at oprette',
-'Installation_TablesFound' => 'Følgende tabeller blev fundet i databasen',
-'Installation_TablesWarningHelp' => 'Vælg enten at genbruge de eksisterende tabeller eller vælg en ren installation for at slette alle eksisterende data.',
-'Installation_TablesReuse' => 'Genbrug de eksisterende tabeller',
-'Installation_TablesDelete' => 'Slet detekterede tabeller',
-'Installation_TablesDeletedSuccess' => 'Eksisterende Piwik-tabeller blev slettet',
-'Installation_TablesCreatedSuccess' => 'Tabellerne blev oprettet!',
-'Installation_DatabaseCreatedSuccess' => 'Databasen %s blev oprettet!',
-'Installation_GoBackAndDefinePrefix' => 'Gå tilbage og opret prefix for Piwik Tabeller',
-'Installation_ConfirmDeleteExistingTables' => 'Bekræft sletning af tabellerne: %s fra databasen? ADVARSEL: DATA FRA DISSE TABELLER KAN IKKE GENSKABES!',
-'Installation_Welcome' => 'Velkommen!',
-'Installation_WelcomeHelp' => '<p>Piwik er et Open Source statistik-program som gør det enkelt at finde information om besøgende.</p><p> Processen er delt op i %s lette trin og vil tage ca. 5 minutter.</p>',
-'Installation_ErrorInvalidState' => 'Fejl: Det lader til at du forsøger at springe et skridt af installationen over, eller cookies er slået fra, eller Piwik opsætningsfil allerede er oprettet. %sSørg for, at cookies er aktiveret%s og gå tilbage%s til den første side i installationen%s. ',
-'Provider_WidgetProviders' => 'Udbydere',
-'Provider_ColumnProvider' => 'Udbyder',
-'Provider_SubmenuLocationsProvider' => 'Sted og udbyder',
-'Goals_ColumnConversions' => 'Omregninger',
-'Goals_ColumnConversionRate' => 'Omregnings frekvens',
-'Goals_ColumnRevenue' => 'Indtægter',
-'DBStats_DatabaseUsage' => 'Databasebrug',
-'DBStats_MainDescription' => 'Piwik gemmer al statistik i MySQL-databasen. Lige nu bruger Piwik-tabellen %s.',
-'DBStats_Table' => 'Tabel',
-'DBStats_RowNumber' => 'Antal rækker',
-'DBStats_DataSize' => 'Data',
-'DBStats_IndexSize' => 'Index',
-'DBStats_TotalSize' => 'Samlet størrelse',
-'TranslationsAdmin_MenuTranslations' => 'Oversættelser',
-'TranslationsAdmin_MenuLanguages' => 'Sprog',
-'TranslationsAdmin_Plugin' => 'Plugin',
-'TranslationsAdmin_Definition' => 'Definition',
-'TranslationsAdmin_DefaultString' => 'Standard (English)',
-'TranslationsAdmin_TranslationString' => 'Oversættelse (gældende sprog: %s)',
-'TranslationsAdmin_Translations' => 'Oversættelser',
-'TranslationsAdmin_FixPermissions' => 'Ret filsystem-rettighederne',
-'TranslationsAdmin_AvailableLanguages' => 'Tilgængelige sprog',
-'TranslationsAdmin_AddLanguage' => 'Tilføj sprog',
-'TranslationsAdmin_LanguageCode' => 'Sprogkode',
-'TranslationsAdmin_Export' => 'Eksporter sprog',
-'TranslationsAdmin_Import' => 'Importer sprog',
-);
+'VisitFrequency_PluginDescription' => 'Rapporter forskellige statistikker om tilbagevendende besøgende kontra førstegangs besøgende..',
+'VisitFrequency_Evolution' => 'Udvikling i perioden',
+'VisitFrequency_ColumnReturningVisits' => 'Tilbagevendende besøg',
+'VisitFrequency_ColumnActionsByReturningVisits' => 'Handlinger af tilbagevendende besøg',
+'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Max antal handlinger af tilbagevendende besøg',
+'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Samlet tid brugt af tilbagevendende besøg (i sekunder)',
+'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Afvisningsfrekvens for tilbagevendende besøg',
+'VisitFrequency_ReturnVisits' => '%s tilbagevendende besøg',
+'VisitFrequency_ReturnActions' => '%s handlinger af tilbagevendende besøg',
+'VisitFrequency_ReturnMaxActions' => '%s maks. handlinger af tilbagevendende besøg',
+'VisitFrequency_ReturnTotalTime' => '%s samlet tid brugt af tilbagevendende besøg',
+'VisitFrequency_ReturnBounceRate' => '%s tilbagevendende besøg er blevet afvist (har forladt hjemmesiden efter en sidevisning)',
+'VisitFrequency_WidgetOverview' => 'Hyppighedsoversigt',
+'VisitFrequency_WidgetGraphReturning' => 'Tilbagevendende besøg',
+'VisitFrequency_SubmenuFrequency' => 'Hyppighed',
+'VisitorInterest_PluginDescription' => 'Rapporter om den besøgendes Interesser: antal viste sider, tidsforbrug på hjemmeside.',
+'VisitorInterest_VisitsPerDuration' => 'Besøgsvarighed pr. besøg',
+'VisitorInterest_VisitsPerNbOfPages' => 'Besøg pr. antal sider',
+'VisitorInterest_ColumnVisitDuration' => 'Besøgslængde',
+'VisitorInterest_ColumnPagesPerVisit' => 'Sider pr. besøg',
+'VisitorInterest_WidgetLengths' => 'Besøgslængde',
+'VisitorInterest_WidgetPages' => 'Sidevisninger pr. besøg',
+'VisitorInterest_SubmenuFrequencyLoyalty' => 'Hyppighed og loyalitet',
+'VisitorInterest_PlusXMin' => '%s min.',
+'VisitorInterest_BetweenXYMinutes' => '%1s-%2s min.',
+'VisitorInterest_OnePage' => '1 side',
+'VisitorInterest_NPages' => '%s sider',
+'VisitorInterest_BetweenXYSeconds' => '%1s-%2 sek.',
+'VisitsSummary_PluginDescription' => 'Rapporterer generelle analyse-sammendrag:: besøg, unikke besøgende, antal handlinger, afvisningsprocent osv..',
+'VisitsSummary_VisitsSummary' => 'Besøg resumé',
+'VisitsSummary_NbVisits' => '%s besøg',
+'VisitsSummary_NbUniqueVisitors' => '%s unikke besøgende',
+'VisitsSummary_NbActionsDescription' => '%s handlinger (sidevisninger, filhentninger og udgående links)',
+'VisitsSummary_TotalTime' => '%s samlet tid brugt af besøgende',
+'VisitsSummary_MaxNbActions' => '%s maks. handlinger i ét enkelt besøg',
+'VisitsSummary_NbVisitsBounced' => '%s har forladt hjemmesiden efter én sidevisning',
+'VisitsSummary_EvolutionOverLastPeriods' => 'Udvikling de seneste %s',
+'VisitsSummary_Report' => 'Rapport',
+'VisitsSummary_GenerateTime' => 'Siden generedes på %s sek.',
+'VisitsSummary_GenerateQueries' => '%s forespørgelser kørt',
+'VisitsSummary_WidgetLastVisits' => 'Seneste besøg',
+'VisitsSummary_WidgetVisits' => 'Besøgsoversigt',
+'VisitsSummary_WidgetLastVisitors' => 'Seneste unikke besøgende',
+'VisitsSummary_WidgetOverviewGraph' => 'Oversigt med grafik',
+'VisitsSummary_SubmenuOverview' => 'Oversigt',
+'VisitTime_PluginDescription' => 'Rapporter lokal- og servertid. Servertiden kan være nyttigt ved planlægning af vedligeholdelse på hjemmesiden.',
+'VisitTime_LocalTime' => 'Besøg pr. lokaltid',
+'VisitTime_ServerTime' => 'Besøg pr. servertid',
+'VisitTime_ColumnServerTime' => 'Servertid',
+'VisitTime_ColumnLocalTime' => 'Lokaltid',
+'VisitTime_WidgetLocalTime' => 'Besøg (lokaltid)',
+'VisitTime_WidgetServerTime' => 'Besøg (servertid)',
+'VisitTime_SubmenuTimes' => 'Tider',
+'VisitTime_NHour' => '%s',
+'Widgetize_PluginDescription' => 'Programudvidelsen gør det nemt at eksportere Piwik kontroller til blogs, hjemmeside eller på iGoogle og Netvibes!',
+); \ No newline at end of file
diff --git a/lang/de.php b/lang/de.php
index 97a9cc21aa..bf1b0ae0de 100644
--- a/lang/de.php
+++ b/lang/de.php
@@ -1,735 +1,1277 @@
<?php
+
+setlocale(LC_TIME, 'de_DE.UTF-8');
+
$translations = array(
-'General_Locale'=>'de_DE.UTF-8',
-'General_TranslatorName'=>'Frank Bueltge, Thorsten Taube, Arthur W. Borens, Marco Ziesing',
-'General_TranslatorEmail'=>'frank@bueltge.de, piwik@thorstentaube.de, arthur.borens@gmx.de, mail@marco-ziesing.de',
-'General_EnglishLanguageName'=>'German',
-'General_OriginalLanguageName'=>'Deutsch',
-'General_HelloUser'=>'Hallo, %s!',
-'General_OpenSourceWebAnalytics'=>'Quelloffene Webanalytik',
-'General_YourDashboard'=>'Ihr Dashboard',
-'General_API'=>'API',
-'General_Widgets'=>'Widgets',
-'General_Settings'=>'Einstellungen',
-'General_GiveUsYourFeedback'=>'Feedback geben!',
-'General_Unknown'=>'unbekannt',
-'General_Required'=>'%s benötigt',
-'General_Error'=>'Fehler',
-'General_Warning'=>'Warnung',
-'General_BackToHomepage'=>'Zurück zur Piwik Homepage',
-'General_Yes'=>'Ja',
-'General_No'=>'Nein',
-'General_Delete'=>'Löschen',
-'General_Edit'=>'Ändern',
-'General_Ok'=>'OK',
-'General_Close'=>'Schließen',
-'General_Logout'=>'Abmelden',
-'General_Done'=>'Erledigt',
-'General_LoadingData'=>'Lade Daten...',
-'General_Loading'=>'Laden...',
-'General_ErrorRequest'=>'Oops&hellip; es ist ein Problem während der Anfrage aufgetreten, bitte noch einmal versuchen.',
-'General_Next'=>'nächste',
-'General_Previous'=>'vorherige',
-'General_Search'=>'Suchen',
-'General_Others'=>'Andere',
-'General_Table'=>'Tabelle',
-'General_Piechart'=>'Kreisdiagramm',
-'General_TagCloud'=>'Schlagwortwolke',
-'General_VBarGraph'=>'Säulendiagramm',
-'General_Export'=>'Export',
-'General_ExportAsImage'=>'Als Bild exportieren',
-'General_SaveImageOnYourComputer'=>'Um das Bild auf dem Computer zu speichern, einen Rechtsklick auf das Bild machen und „Bild speichern unter..." auswählen.',
-'General_Refresh'=>'Aktualisiere die Seite',
-'General_Visitors'=>'Besucher',
-'General_ColumnNbUniqVisitors'=>'Eindeutige Besucher',
-'General_ColumnNbVisits'=>'Besucher',
-'General_ColumnNbActions'=>'Aktionen',
-'General_ColumnMaxActions'=>'Maximale Aktionen bei einem Besuch',
-'General_ColumnSumVisitLength'=>'Von Besuchern verbrachte Gesamtzeit (in Sekunden)',
-'General_ColumnLabel'=>'Label',
-'General_ColumnActionsPerVisit'=>'Aktionen pro Besuch',
-'General_ColumnAvgTimeOnSite'=>'Durchschnittszeit auf der Seite',
-'General_ColumnBounceRate'=>'Absprungsrate',
-'General_ColumnPageviews'=>'Seitenansichten',
-'General_ColumnUniquePageviews'=>'Einmalige Seitenansichten',
-'General_ColumnValuePerVisit'=>'Wert pro Besuch',
-'General_ColumnVisitsWithConversions'=>'Besuche mit Konversionen',
-'General_Save'=>'Speichern',
-'General_Website'=>'Webseite',
-'General_NoDataForGraph'=>'Keine Daten für dieses Diagramm',
-'General_NoDataForTagCloud'=>'Keine Daten für diese Schlagwortwolke.',
-'General_DisplayNormalTable'=>'Normale Tabelle anzeigen',
-'General_DisplayMoreData'=>'Mehr Daten anzeigen',
-'General_PiwikIsACollaborativeProjectYouCanContribute'=>'%s Piwik %s ist ein gemeinschaftliches Projekt. %s Wenn Ihnen Piwik gefällt, können Sie helfen! Möchten Sie herausfinden %s wie Sie zu Piwik beitragen können?%s ',
-'General_YouAreCurrentlyViewingDemoOfPiwik'=>'Zur Zeit betrachten Sie die Demo von%s; %sLaden Sie%s die Vollversion herunter! Besuchen Sie %s',
-'General_PiwikXIsAvailablePleaseUpdateNow'=>'Piwik %s ist verfügbar. %s Bitte jetzt ein Update machen!%s (siehe %s Änderungen%s).',
-'General_BackToPiwik'=>'Zurück zu Piwik',
-'General_ShortMonth_1'=>'Jan',
-'General_ShortMonth_2'=>'Feb',
-'General_ShortMonth_3'=>'Mar',
-'General_ShortMonth_4'=>'Apr',
-'General_ShortMonth_5'=>'Mai',
-'General_ShortMonth_6'=>'Jun',
-'General_ShortMonth_7'=>'Jul',
-'General_ShortMonth_8'=>'Aug',
-'General_ShortMonth_9'=>'Sep',
-'General_ShortMonth_10'=>'Okt',
-'General_ShortMonth_11'=>'Nov',
-'General_ShortMonth_12'=>'Dez',
-'General_LongMonth_1'=>'Januar',
-'General_LongMonth_2'=>'Februar',
-'General_LongMonth_3'=>'März',
-'General_LongMonth_4'=>'April',
-'General_LongMonth_5'=>'Mai',
-'General_LongMonth_6'=>'Juni',
-'General_LongMonth_7'=>'Juli',
-'General_LongMonth_8'=>'August',
-'General_LongMonth_9'=>'September',
-'General_LongMonth_10'=>'Oktober',
-'General_LongMonth_11'=>'November',
-'General_LongMonth_12'=>'Dezember',
-'General_ShortDay_1'=>'Mon',
-'General_ShortDay_2'=>'Die',
-'General_ShortDay_3'=>'Mit',
-'General_ShortDay_4'=>'Don',
-'General_ShortDay_5'=>'Fre',
-'General_ShortDay_6'=>'Sam',
-'General_ShortDay_7'=>'Son',
-'General_LongDay_1'=>'Montag',
-'General_LongDay_2'=>'Dienstag',
-'General_LongDay_3'=>'Mittwoch',
-'General_LongDay_4'=>'Donnerstag',
-'General_LongDay_5'=>'Freitag',
-'General_LongDay_6'=>'Samstag',
-'General_LongDay_7'=>'Sonntag',
-'CorePluginsAdmin_Plugins'=>'Plugins',
-'CorePluginsAdmin_PluginsManagement'=>'Pluginverwaltung',
-'CorePluginsAdmin_MainDescription'=>'Plugins erweitern die Funktionalität von Piwik. Installierte Plugins können hier aktiviert oder deaktiviert werden.',
-'CorePluginsAdmin_Plugin'=>'Plugin',
-'CorePluginsAdmin_Version'=>'Version',
-'CorePluginsAdmin_Description'=>'Beschreibung',
-'CorePluginsAdmin_Status'=>'Status',
-'CorePluginsAdmin_Action'=>'Aktion',
-'CorePluginsAdmin_PluginHomepage'=>'Plugin Webseite',
-'CorePluginsAdmin_Activated'=>'Aktiviert',
-'CorePluginsAdmin_Active'=>'Aktiv',
-'CorePluginsAdmin_Inactive'=>'Inaktiv',
-'CorePluginsAdmin_ActivatedHelp'=>'Dieses Plugin kann nicht deaktiviert werden.',
-'CorePluginsAdmin_Deactivate'=>'Deaktivieren',
-'CorePluginsAdmin_Activate'=>'Aktivieren',
-'CorePluginsAdmin_MenuPlugins'=>'Plugins',
-'API_QuickDocumentation'=>'<h2>API Schnelle Dokumentatoin</h2><p>Wenn Sie f&uuml;r heute keine Daten haben, k&ouml;nnen Sie sich mit diesem Besucher-Generator-Script welche <a href=\'misc/generateVisits.php\' target=_blank>generieren</a>.</p><p>Sie k&ouml;nnen f&uuml;r jede Methode die verschiedenen Formate ausprobieren. Es ist sehr einfach, alle Daten die Sie von piwik haben wollen zu extrahieren!</p><p><b>F&uuml;r mehr Informationen lohnt sich ein Blick auf die <a href=\'http://dev.piwik.org/trac/wiki/API\'>offizielle API Dokumentation</a> oder die <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API Referenz</a>.</b></P><h2>Benutzer-Authentifizierung</h2><p>Wenn Sie die Daten in <b>einem Script, einem crontab, etc</b> anfordern wollen, m&uuml;ssen Sie den Parameter <code><u>&token_auth=%s</u></code> zu der API hinzuf&uuml;gen welche URLs aufruft die Authentifizierung ben&ouml;tigen.</p><p>Dieser Paramter (token) ist so geheim wie Ihr Benutzername und Passwort, <b>ver&ouml;ffentlichen Sie es nicht!</p>',
-'API_LoadedAPIs'=>'%s APIs erfolgreich geladen',
-'CoreHome_NoPrivileges'=>'Sie sind angemeldet als \'%s\', allerdings fehlen Ihnen Berechtigungen für Piwik.<br/>Kontaktieren Sie Ihren Administrator um \'view\'-Rechte zu erhalten.',
-'CoreHome_JavascriptDisabled'=>'JavaScript muss aktiviert sein, damit Piwik im Standard-Modus verwendet werden kann.<br/>Um fortzufahren bitte JavaScript in den Eigenschaften Ihres Browsers aktivieren und die Seite anschließend neu laden.',
-'CoreHome_TableNoData'=>'Keine Daten',
-'CoreHome_CategoryNoData'=>'Keine Daten in dieser Kategorie. Probieren Sie "Gesamte Population einbeziehen"',
-'CoreHome_ShowJSCode'=>'Einzupflegendes JavaScript darstellen.',
-'CoreHome_IncludeAllPopulation_js'=>'Gesamte Population einbeziehen.',
-'CoreHome_ExcludeLowPopulation_js'=>'Geringe Population ausschließen.',
-'CoreHome_PageOf_js'=>'%s von %s',
-'CoreHome_Loading_js'=>'Laden...',
-'CoreHome_DayFormat'=>'%longDay% %day% %longMonth% %longYear%',
-'CoreHome_PeriodDay'=>'Tag',
-'CoreHome_PeriodWeek'=>'Woche',
-'CoreHome_PeriodMonth'=>'Monat',
-'CoreHome_PeriodYear'=>'Jahr',
-'CoreHome_PeriodDays'=>'Tage',
-'CoreHome_PeriodWeeks'=>'Wochen',
-'CoreHome_PeriodMonths'=>'Monate',
-'CoreHome_PeriodYears'=>'Jahre',
-'CoreHome_DaySu_js'=>'So',
-'CoreHome_DayMo_js'=>'Mo',
-'CoreHome_DayTu_js'=>'Di',
-'CoreHome_DayWe_js'=>'Mi',
-'CoreHome_DayTh_js'=>'Do',
-'CoreHome_DayFr_js'=>'Fr',
-'CoreHome_DaySa_js'=>'Sa',
-'CoreHome_MonthJanuary_js'=>'Januar',
-'CoreHome_MonthFebruary_js'=>'Februar',
-'CoreHome_MonthMarch_js'=>'März',
-'CoreHome_MonthApril_js'=>'April',
-'CoreHome_MonthMay_js'=>'Mai',
-'CoreHome_MonthJune_js'=>'Juni',
-'CoreHome_MonthJuly_js'=>'Juli',
-'CoreHome_MonthAugust_js'=>'August',
-'CoreHome_MonthSeptember_js'=>'September',
-'CoreHome_MonthOctober_js'=>'Oktober',
-'CoreHome_MonthNovember_js'=>'November',
-'CoreHome_MonthDecember_js'=>'Dezember',
-'CoreUpdater_UpdateTitle'=>'Piwik-Aktualisierung',
-'CoreUpdater_DatabaseUpgradeRequired'=>'Datenbank-Upgrade benötigt',
-'CoreUpdater_YourDatabaseIsOutOfDate'=>'Ihre Piwik-Datenbank ist nicht mehr aktuell und muss aktualisiert werden, bevor Sie weiter damit arbeiten können.',
-'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY'=>'Mit der Piwik-Datenbank wird ein Upgrade von Version %s auf die neue Version %s durchgeführt.',
-'CoreUpdater_TheFollowingPluginsWillBeUpgradedX'=>'Die folgenden Plugins werden aktualisiert: %s',
-'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient'=>'Der Upgrade-Prozess kann eine Weile dauern. Bitte haben Sie etwas Geduld.',
-'CoreUpdater_UpgradePiwik'=>'Upgrade Piwik',
-'CoreUpdater_HelpMessageContent'=>'Schauen Sie sich die %s Piwik FAQ %s an welche versucht, die &uuml;blichsten Fehler bei einem Upgrade zu erkl&auml;ren. Fragen Sie Ihre Systemadministratoren - diese k&ouml;nnten in der Lage sein Ihnen bei den Fehleren zu helfen welche h&ouml;chstwahrscheinlich mit Ihrem Server oder der MySQL-Installation zusammenh&auml;ngen.',
-'CoreUpdater_CriticalErrorDuringTheUpgradeProcess'=>'Kritischer Fehler w&auml;hrend dem Upgrade-Prozess:',
-'CoreUpdater_HelpMessageIntroductionWhenError'=>'Das dar&uuml;ber ist die Kernfehlermeldung. Sie sollte die Ursache erkl&auml;ren, aber wenn Sie mehr erfahren wollen, helfen Sie bitte:',
-'CoreUpdater_HelpMessageIntroductionWhenWarning'=>'Das Upgrade verlief reibungslos, dennoch gab es Meldungen w&auml;hrend des Prozesses. Bitte die Beschreibung lesen, um mehr Details zu erfahren. F&uuml;r weitere Hilfe:',
-'CoreUpdater_UpgradeComplete'=>'Upgrade abgeschlossen!',
-'CoreUpdater_WarningMessages'=>'Warnhinweis:',
-'CoreUpdater_ErrorDuringPluginsUpdates'=>'Fehler w&auml;hrend Plugin-Aktualisierungen:',
-'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins'=>'Wir deaktivierten automatisch folgende Plugins: %s',
-'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded'=>'Piwik wurde erfolgreich aktualisiert!',
-'CoreUpdater_ContinueToPiwik'=>'Weiter zu Piwik',
-'CoreUpdater_UpdateAutomatically'=>'Automatisch Update durchführen',
-'CoreUpdater_ThereIsNewVersionAvailableForUpdate'=>'Eine neue Version von Piwik ist als Update verfügbar',
-'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage'=>'Ein Update auf Version %s kann durchgeführt oder das Paket kann heruntergeladen und manuell installiert werden:',
-'CoreUpdater_DownloadX'=>'%s herunterladen',
-'CoreUpdater_UpdateHasBeenCancelledExplanation'=>'Das Piwik Ein-Klick-Update wurde abgebrochen. Wenn die oben stehende Fehlermeldung nicht\ behoben werden kann, empfehlen wir Ihnen, ein manuelles Update von Piwik durchzuführen. %s Bitte die %sUpdate-Dokumentatierung%s ansehen, um loszulegen!',
-'CoreUpdate_DownloadingUpdateFromX'=>'Update wird von %s heruntergeladen',
-'CoreUpdate_UnpackingTheUpdate'=>'Update wird entpackt',
-'CoreUpdater_VerifyingUnpackedFiles'=>'Die entpackten Dateien werden überprüft',
-'CoreUpdater_CreatingBackupOfConfigurationFile'=>'Ein Backup der Konfigurationsdatei wird in %s erstellt',
-'CoreUpdater_InstallingTheLatestVersion'=>'Die neueste Version wird installiert',
-'CoreUpdater_PiwikUpdatedSuccessfully'=>'Es wurde erfolgreich ein Update von Piwik durchgeführt!',
-'Actions_Actions'=>'Aktionen',
-'Actions_SubmenuPages'=>'Seiten',
-'Actions_SubmenuOutlinks'=>'Ausgehende Verweise',
-'Actions_SubmenuDownloads'=>'Downloads',
-'Actions_ColumnClicks'=>'Klicks',
-'Actions_ColumnUniqueClicks'=>'Einmalige Klicks',
-'Actions_ColumnDownloads'=>'Downloads',
-'Actions_ColumnUniqueDownloads'=>'Einmalige Downloads',
-'Actions_ColumnPageName'=>'Seitenname',
-'Actions_ColumnClickedURL'=>'Angeklickte URL',
-'Actions_ColumnDownloadURL'=>'Download-URL',
-'Dashboard_Dashboard'=>'Übersicht',
-'Dashboard_AddWidget'=>'Widget hinzufügen...',
-'Dashboard_DeleteWidgetConfirm'=>'Sicher, dass dieses Widget vom Dashboard entfernt werden soll?',
-'Dashboard_SelectWidget'=>'Das hinzuzufügende Widget auswählen',
-'Dashboard_AddPreviewedWidget_js'=>'Vorheriges Widget zum Dashboard hinzufügen',
-'Dashboard_WidgetPreview_js'=>'Widget-Vorschau',
-'Dashboard_Close_js'=>'Schließen',
-'Dashboard_TitleWidgetInDashboard_js'=>'Widget befindet sich bereits im Dashboard',
-'Dashboard_TitleClickToAdd_js'=>'Klicken, um zum Dashboard hinzuzufügen',
-'Dashboard_LoadingWidget_js'=>'Lade Widget, bitte warten...',
-'Dashboard_WidgetNotFound_js'=>'Widget nicht gefunden',
-'Referers_Referers'=>'Verweise',
-'Referers_SearchEngines'=>'Suchmaschinen',
-'Referers_Keywords'=>'Suchbegriffe',
-'Referers_DirectEntry'=>'Direkte Zugriffe',
-'Referers_Websites'=>'Webseiten',
-'Referers_Campaigns'=>'Kampagnen',
-'Referers_MetricsFromRefererTypeGraphLegend'=>'%1s (von %2s)',
-'Referers_Evolution'=>'Entwicklung über den Zeitraum',
-'Referers_Type'=>'Verweisart',
-'Referers_ColumnRefererType'=>'Referer Type',
-'Referers_ColumnSearchEngine'=>'Suchmaschine',
-'Referers_ColumnWebsite'=>'Website',
-'Referers_ColumnWebsitePage'=>'Webseiten-Seite',
-'Referers_ColumnKeyword'=>'Stichwort',
-'Referers_ColumnCampaign'=>'Kampagne',
-'Referers_DetailsByRefererType'=>'Details nach Verweisart',
-'Referers_TypeDirectEntries'=>'%s direkte Zugriffe',
-'Referers_TypeSearchEngines'=>'%s von Suchmaschinen',
-'Referers_TypeWebsites'=>'%s von Webseiten',
-'Referers_TypeCampaigns'=>'%s von Kampagnen',
-'Referers_Distinct'=>'Vermittler nach Verweisart unterscheiden',
-'Referers_DistinctSearchEngines'=>'Suchmaschinen unterscheiden',
-'Referers_DistinctKeywords'=>'Stichwörter unterscheiden',
-'Referers_DistinctCampaigns'=>'Kampagnen unterscheiden',
-'Referers_DistinctWebsites'=>'Webseiten unterscheiden',
-'Referers_UsingNDistinctUrls'=>' (%2s zum URL unterscheiden werden verwendet)',
-'Referers_SubmenuEvolution'=>'Entwicklung',
-'Referers_SubmenuSearchEngines'=>'Suchmaschinen und Suchbegriffe',
-'Referers_SubmenuWebsites'=>'Webseiten',
-'Referers_SubmenuCampaigns'=>'Kampagnen',
-'Referers_WidgetKeywords'=>'Liste der Suchbegriffe',
-'Referers_WidgetCampaigns'=>'Liste der Kampagnen',
-'Referers_WidgetExternalWebsites'=>'Liste externer Webseiten',
-'Referers_WidgetSearchEngines'=>'Beste Suchmaschinen',
-'Referers_WidgetOverview'=>'Übersicht',
-'UserSettings_VisitorSettings'=>'Besuchereinstellungen',
-'UserSettings_BrowserFamilies'=>'Browserfamilien',
-'UserSettings_Browsers'=>'Browser',
-'UserSettings_Plugins'=>'Plugins',
-'UserSettings_Configurations'=>'Konfigurationen',
-'UserSettings_OperatinsSystems'=>'Betriebssysteme',
-'UserSettings_Resolutions'=>'Auflösungen',
-'UserSettings_WideScreen'=>'Breitbild',
-'UserSettings_ColumnBrowserFamily'=>'Browserfamilie',
-'UserSettings_ColumnBrowser'=>'Browser',
-'UserSettings_ColumnPlugin'=>'Plugin',
-'UserSettings_ColumnConfiguration'=>'Konfiguration',
-'UserSettings_ColumnOperatinsSystem'=>'Betriebssystem',
-'UserSettings_ColumnResolution'=>'Auflösung',
-'UserSettings_ColumnTypeOfScreen'=>'Bildschirmtyp',
-'UserSettings_WidgetResolutions'=>'Bildschirmauflösungen',
-'UserSettings_WidgetBrowsers'=>'Besucher Browser',
-'UserSettings_WidgetPlugins'=>'Liste der Plugins',
-'UserSettings_WidgetWidescreen'=>'Normal / Breitbild',
-'UserSettings_WidgetBrowserFamilies'=>'Browser nach Familie',
-'UserSettings_WidgetOperatingSystems'=>'Betriebssysteme',
-'UserSettings_WidgetGlobalVisitors'=>'Globale Besucherkonfiguration',
-'UserSettings_SubmenuSettings'=>'Einstellungen',
-'UserCountry_Country'=>'Land',
-'UserCountry_Continent'=>'Kontinent',
-'UserCountry_DistinctCountries'=>'%s unterschiedliche Länder',
-'UserCountry_SubmenuLocations'=>'Ort',
-'UserCountry_WidgetContinents'=>'Besucherkontinente',
-'UserCountry_WidgetCountries'=>'Besucherländer',
-'UserCountry_country_ac'=>'Ascension',
-'UserCountry_country_ad'=>'Andorra',
-'UserCountry_country_ae'=>'Vereinigte Arabische Emirate',
-'UserCountry_country_af'=>'Afghanistan',
-'UserCountry_country_ag'=>'Antigua und Barbuda',
-'UserCountry_country_ai'=>'Anguilla',
-'UserCountry_country_al'=>'Albanien',
-'UserCountry_country_am'=>'Armenien',
-'UserCountry_country_an'=>'Niederländische Antillen',
-'UserCountry_country_ao'=>'Angola',
-'UserCountry_country_aq'=>'Antarktis',
-'UserCountry_country_ar'=>'Argentinien',
-'UserCountry_country_as'=>'Amerikanisch Samoa',
-'UserCountry_country_at'=>'Österreich',
-'UserCountry_country_au'=>'Australien',
-'UserCountry_country_aw'=>'Aruba',
-'UserCountry_country_ax'=>'Aland-Inseln',
-'UserCountry_country_az'=>'Aserbajdschan',
-'UserCountry_country_ba'=>'Bosnien und Herzegovina',
-'UserCountry_country_bb'=>'Barbados',
-'UserCountry_country_bd'=>'Bangladesch',
-'UserCountry_country_be'=>'Belgien',
-'UserCountry_country_bf'=>'Burkina Faso',
-'UserCountry_country_bg'=>'Bulgarien',
-'UserCountry_country_bh'=>'Bahrain',
-'UserCountry_country_bi'=>'Burundi',
-'UserCountry_country_bj'=>'Benin',
-'UserCountry_country_bl'=>'Sankt Bartholomäus',
-'UserCountry_country_bm'=>'Bermuda',
-'UserCountry_country_bn'=>'Bruneo',
-'UserCountry_country_bo'=>'Bolivien',
-'UserCountry_country_br'=>'Brasilien',
-'UserCountry_country_bs'=>'Bahamas',
-'UserCountry_country_bt'=>'Bhutan',
-'UserCountry_country_bu'=>'Birma',
-'UserCountry_country_bv'=>'Bouvetinsel',
-'UserCountry_country_bw'=>'Botsuana',
-'UserCountry_country_by'=>'Weissrussland',
-'UserCountry_country_bz'=>'Belize',
-'UserCountry_country_ca'=>'Kanada',
-'UserCountry_country_cc'=>'Cocos Islands',
-'UserCountry_country_cd'=>'Demokratische Republik Kongo',
-'UserCountry_country_cf'=>'Zentralafrikanische Republik ',
-'UserCountry_country_cg'=>'Kongo',
-'UserCountry_country_ch'=>'Schweiz',
-'UserCountry_country_ci'=>'Elfenbeinküste',
-'UserCountry_country_ck'=>'Cook-Inseln',
-'UserCountry_country_cl'=>'Chile',
-'UserCountry_country_cm'=>'Kamerun',
-'UserCountry_country_cn'=>'China',
-'UserCountry_country_co'=>'Kolumbien',
-'UserCountry_country_cp'=>'Clipperton-Insel',
-'UserCountry_country_cr'=>'Costa Rica',
-'UserCountry_country_cs'=>'Serbien Montenegro',
-'UserCountry_country_cu'=>'Cuba',
-'UserCountry_country_cv'=>'Kap Verde',
-'UserCountry_country_cx'=>'Weihnachtsinsel',
-'UserCountry_country_cy'=>'Zypern',
-'UserCountry_country_cz'=>'Tschechische Republik',
-'UserCountry_country_de'=>'Deutschland',
-'UserCountry_country_dg'=>'Diego Garcia',
-'UserCountry_country_dj'=>'Djibuti',
-'UserCountry_country_dk'=>'Dänemark',
-'UserCountry_country_dm'=>'Dominica',
-'UserCountry_country_do'=>'Dominikanische Republik',
-'UserCountry_country_dz'=>'Algerien',
-'UserCountry_country_ea'=>'Ceuta, Melilla',
-'UserCountry_country_ec'=>'Equador',
-'UserCountry_country_ee'=>'Estland',
-'UserCountry_country_eg'=>'Ägypten',
-'UserCountry_country_eh'=>'Westsahara',
-'UserCountry_country_er'=>'Eritrea',
-'UserCountry_country_es'=>'Spanien',
-'UserCountry_country_et'=>'Äthiopien',
-'UserCountry_country_eu'=>'Europäische Union',
-'UserCountry_country_fi'=>'Finnland',
-'UserCountry_country_fj'=>'Fiji Inseln',
-'UserCountry_country_fk'=>'Falklandinseln',
-'UserCountry_country_fm'=>'Mikronesien',
-'UserCountry_country_fo'=>'Färöer',
-'UserCountry_country_fr'=>'Frankreich',
-'UserCountry_country_fx'=>'Frankreich, Metropolitanisch',
-'UserCountry_country_ga'=>'Gabun',
-'UserCountry_country_gb'=>'Grossbritannien',
-'UserCountry_country_gd'=>'Grenada',
-'UserCountry_country_ge'=>'Georgien',
-'UserCountry_country_gf'=>'Französisch-Guayana',
-'UserCountry_country_gg'=>'Kanalinseln (Guernsey)',
-'UserCountry_country_gh'=>'Ghana',
-'UserCountry_country_gi'=>'Gibraltar',
-'UserCountry_country_gl'=>'Grönland',
-'UserCountry_country_gm'=>'Gambia',
-'UserCountry_country_gn'=>'Guinea',
-'UserCountry_country_gp'=>'Guadeloupe',
-'UserCountry_country_gq'=>'Äquatorialguinea',
-'UserCountry_country_gr'=>'Griechenland',
-'UserCountry_country_gs'=>'Südgeorgien/Süd-Sandwich-Inseln',
-'UserCountry_country_gt'=>'Guatemala',
-'UserCountry_country_gu'=>'Guam',
-'UserCountry_country_gw'=>'Guinea-Bissau',
-'UserCountry_country_gy'=>'Guyana',
-'UserCountry_country_hk'=>'Hong Kong',
-'UserCountry_country_hm'=>'Heard und McDonaldinseln',
-'UserCountry_country_hn'=>'Honduras',
-'UserCountry_country_hr'=>'Kroatien',
-'UserCountry_country_ht'=>'Haiti',
-'UserCountry_country_hu'=>'Ungarn',
-'UserCountry_country_ic'=>'Kanarische Inseln',
-'UserCountry_country_id'=>'Indonesien',
-'UserCountry_country_ie'=>'Irland',
-'UserCountry_country_il'=>'Israel',
-'UserCountry_country_im'=>'Insel Man',
-'UserCountry_country_in'=>'Indien',
-'UserCountry_country_io'=>'Chagos-Archipel',
-'UserCountry_country_iq'=>'Irak',
-'UserCountry_country_ir'=>'Iran',
-'UserCountry_country_is'=>'Island',
-'UserCountry_country_it'=>'Italien',
-'UserCountry_country_je'=>'Kanalinseln (Jersey)',
-'UserCountry_country_jm'=>'Jamaika',
-'UserCountry_country_jo'=>'Jordanien',
-'UserCountry_country_jp'=>'Japan',
-'UserCountry_country_ke'=>'Kenia',
-'UserCountry_country_kg'=>'Kirgistan',
-'UserCountry_country_kh'=>'Kambodscha',
-'UserCountry_country_ki'=>'Kiribati',
-'UserCountry_country_km'=>'Komoren',
-'UserCountry_country_kn'=>'St. Kitts and Nevis',
-'UserCountry_country_kp'=>'Korea (Nord)',
-'UserCountry_country_kr'=>'Korea (Süd)',
-'UserCountry_country_kw'=>'Kuwait',
-'UserCountry_country_ky'=>'Kaimaninseln',
-'UserCountry_country_kz'=>'Kasachstan',
-'UserCountry_country_la'=>'Laos',
-'UserCountry_country_lb'=>'Libanon',
-'UserCountry_country_lc'=>'St. Lucia',
-'UserCountry_country_li'=>'Liechtenstein',
-'UserCountry_country_lk'=>'Sri Lanka',
-'UserCountry_country_lr'=>'Liberia',
-'UserCountry_country_ls'=>'Lesotho',
-'UserCountry_country_lt'=>'Litauen',
-'UserCountry_country_lu'=>'Luxemburg',
-'UserCountry_country_lv'=>'Lettland',
-'UserCountry_country_ly'=>'Libysch-Arabische Dschamahirija',
-'UserCountry_country_ma'=>'Marokko',
-'UserCountry_country_mc'=>'Monaco',
-'UserCountry_country_md'=>'Montenegro',
-'UserCountry_country_me'=>'Republik Moldau',
-'UserCountry_country_mf'=>'Sankt Martin',
-'UserCountry_country_mg'=>'Madagaskar',
-'UserCountry_country_mh'=>'Marshallinseln',
-'UserCountry_country_mk'=>'Mazedonien',
-'UserCountry_country_ml'=>'Mali',
-'UserCountry_country_mm'=>'Myanmar',
-'UserCountry_country_mn'=>'Mongolei',
-'UserCountry_country_mo'=>'Macao',
-'UserCountry_country_mp'=>'Nördliche Marianen',
-'UserCountry_country_mq'=>'Martinique',
-'UserCountry_country_mr'=>'Mauretanien',
-'UserCountry_country_ms'=>'Montserrat',
-'UserCountry_country_mt'=>'Malta',
-'UserCountry_country_mu'=>'Mauritius',
-'UserCountry_country_mv'=>'Malediven',
-'UserCountry_country_mw'=>'Malawi',
-'UserCountry_country_mx'=>'Mexiko',
-'UserCountry_country_my'=>'Malaysia',
-'UserCountry_country_mz'=>'Mosambik',
-'UserCountry_country_na'=>'Namibia',
-'UserCountry_country_nc'=>'Neukaledonien',
-'UserCountry_country_ne'=>'Niger',
-'UserCountry_country_nf'=>'Norfolkinsel',
-'UserCountry_country_ng'=>'Nigeria',
-'UserCountry_country_ni'=>'Nicaragua',
-'UserCountry_country_nl'=>'Niederlande',
-'UserCountry_country_no'=>'Norwegen',
-'UserCountry_country_np'=>'Nepal',
-'UserCountry_country_nr'=>'Nauru',
-'UserCountry_country_nt'=>'Neutrale Zone',
-'UserCountry_country_nu'=>'Niue',
-'UserCountry_country_nz'=>'Neuseeland',
-'UserCountry_country_om'=>'Oman',
-'UserCountry_country_pa'=>'Panama',
-'UserCountry_country_pe'=>'Peru',
-'UserCountry_country_pf'=>'Französisch-Polynesien',
-'UserCountry_country_pg'=>'Papua-Neuguinea',
-'UserCountry_country_ph'=>'Philippinen',
-'UserCountry_country_pk'=>'Pakistan',
-'UserCountry_country_pl'=>'Polen',
-'UserCountry_country_pm'=>'Saint-Pierre-et-Miquelon',
-'UserCountry_country_pn'=>'Pitcairn',
-'UserCountry_country_pr'=>'Puerto Rico',
-'UserCountry_country_ps'=>'Palästinensische Gebiete',
-'UserCountry_country_pt'=>'Portugal',
-'UserCountry_country_pw'=>'Palau',
-'UserCountry_country_py'=>'Paraguay',
-'UserCountry_country_qa'=>'Katar',
-'UserCountry_country_re'=>'Reunion',
-'UserCountry_country_ro'=>'Rumänien',
-'UserCountry_country_ru'=>'Russische Förderation',
-'UserCountry_country_rs'=>'Serbien',
-'UserCountry_country_rw'=>'Ruanda',
-'UserCountry_country_sa'=>'Saudi Arabien',
-'UserCountry_country_sb'=>'Salomonen',
-'UserCountry_country_sc'=>'Seychellen',
-'UserCountry_country_sd'=>'Sudan',
-'UserCountry_country_se'=>'Schweden',
-'UserCountry_country_sf'=>'Finnland',
-'UserCountry_country_sg'=>'Singapur',
-'UserCountry_country_sh'=>'St. Helena',
-'UserCountry_country_si'=>'Slowenien',
-'UserCountry_country_sj'=>'Svalbard',
-'UserCountry_country_sk'=>'Slowakei',
-'UserCountry_country_sl'=>'Sierra Leone',
-'UserCountry_country_sm'=>'San Marino',
-'UserCountry_country_sn'=>'Senegal',
-'UserCountry_country_so'=>'Somalia',
-'UserCountry_country_sr'=>'Suriname',
-'UserCountry_country_st'=>'São Tomé und Príncipe',
-'UserCountry_country_su'=>'Sowjetunion',
-'UserCountry_country_sv'=>'El Salvador',
-'UserCountry_country_sy'=>'Syrien',
-'UserCountry_country_sz'=>'Swaziland',
-'UserCountry_country_ta'=>'Tristan da Cunha',
-'UserCountry_country_tc'=>'Turks- und Caicosinseln',
-'UserCountry_country_td'=>'Tschad',
-'UserCountry_country_tf'=>'Französischen Süd- und Antarktisgebiete',
-'UserCountry_country_tg'=>'Togo',
-'UserCountry_country_th'=>'Thailand',
-'UserCountry_country_tj'=>'Tadschikistan',
-'UserCountry_country_tk'=>'Tokelau',
-'UserCountry_country_tl'=>'Osttimor',
-'UserCountry_country_tm'=>'Turkmenistan',
-'UserCountry_country_tn'=>'Tunesien',
-'UserCountry_country_to'=>'Tonga',
-'UserCountry_country_tp'=>'Osttimor',
-'UserCountry_country_tr'=>'Türkei',
-'UserCountry_country_tt'=>'Trinidad und Tobago',
-'UserCountry_country_tv'=>'Tuvalu',
-'UserCountry_country_tw'=>'Taiwan',
-'UserCountry_country_tz'=>'Tansania',
-'UserCountry_country_ua'=>'Ukraine',
-'UserCountry_country_ug'=>'Uganda',
-'UserCountry_country_uk'=>'Vereinigtes Königreich',
-'UserCountry_country_um'=>'Kleinere Inselbesitzungen der Vereinigten Staaten',
-'UserCountry_country_us'=>'USA',
-'UserCountry_country_uy'=>'Uruguay',
-'UserCountry_country_uz'=>'Usbekistan',
-'UserCountry_country_va'=>'Vatikan',
-'UserCountry_country_vc'=>'St. Vincent und die Grenadinen',
-'UserCountry_country_ve'=>'Venezuela',
-'UserCountry_country_vg'=>'Britische Jungferninseln',
-'UserCountry_country_vi'=>'Amerikanische Jungferninseln',
-'UserCountry_country_vn'=>'Vietnam',
-'UserCountry_country_vu'=>'Vanuatu',
-'UserCountry_country_wf'=>'Wallis und Futuna',
-'UserCountry_country_ws'=>'Samoa',
-'UserCountry_country_ye'=>'Jemen',
-'UserCountry_country_yt'=>'Mayotte',
-'UserCountry_country_yu'=>'Jugoslawien',
-'UserCountry_country_za'=>'Südafrika',
-'UserCountry_country_zm'=>'Sambia',
-'UserCountry_country_zr'=>'Demokratische Republik Kongo (ehem. Zaire)',
-'UserCountry_country_zw'=>'Simbabwe',
-'UserCountry_continent_eur'=>'Europa',
-'UserCountry_continent_afr'=>'Afrika',
-'UserCountry_continent_asi'=>'Asien',
-'UserCountry_continent_ams'=>'Südamerika',
-'UserCountry_continent_amn'=>'Nordamerika',
-'UserCountry_continent_oce'=>'Ozeanien',
-'VisitsSummary_NbVisits'=>'%s Besuche',
-'VisitsSummary_NbUniqueVisitors'=>'%s eindeutige Besucher',
-'VisitsSummary_NbActions'=>'%s Aktionen (Seitenbesuche)',
-'VisitsSummary_TotalTime'=>'%s Zeit aller Besucher',
-'VisitsSummary_MaxNbActions'=>'%s max. Aktionen pro Besuch',
-'VisitsSummary_NbVisitsBounced'=>'%s Besucher sind abgesprungen (haben die Seite nach einer Seite verlassen)',
-'VisitsSummary_EvolutionOverLastPeriods'=>'Entwicklung über die letzten %s',
-'VisitsSummary_Report'=>'Report',
-'VisitsSummary_GenerateTime'=>'%s Sekunden um die Seite zu generieren',
-'VisitsSummary_GenerateQueries'=>'%s Abfragen durchgeführt',
-'VisitsSummary_WidgetLastVisits'=>'Grafik der letzten Besucher',
-'VisitsSummary_WidgetVisits'=>'Besucherübersicht',
-'VisitsSummary_WidgetLastVisitors'=>'Grafik der eindeutigen Besucher',
-'VisitsSummary_WidgetOverviewGraph'=>'Übersicht mit Grafik',
-'VisitsSummary_SubmenuOverview'=>'Übersicht',
-'VisitFrequency_Evolution'=>'Entwicklung über die Zeit',
-'VisitFrequency_ColumnReturningVisits'=>'Wiederkehrende Besuche',
-'VisitFrequency_ColumnActionsByReturningVisits'=>'Aktionen von wiederkehrenden Besuchen',
-'VisitFrequency_ColumnMaximumActionsByAReturningVisit'=>'Maximale Aktionen von einem wiederkehrenden Besuch',
-'VisitFrequency_ColumnTotalTimeSpentByReturningVisits'=>'Von wiederkehrenden Besuchen verbrachte Gesamtzeit (in Sekunden)',
-'VisitFrequency_ColumnBounceRateForReturningVisits'=>'Absprungsrate für wiederkehrende Besuche',
-'VisitFrequency_ReturnVisits'=>'%s wiederkehrende Besucher',
-'VisitFrequency_ReturnActions'=>'%s Aktionen von wiederkehrenden Besuchern',
-'VisitFrequency_ReturnMaxActions'=>'%s max. Aktionen von wiederkehrenden Besuchern',
-'VisitFrequency_ReturnTotalTime'=>'%s verbrauchte Zeit aller wiederkehrenden Besucher',
-'VisitFrequency_ReturnBounceRate'=>'%s wiederkehrende Besuche sind abgesprungen (haben die Seite nach einer Seite verlassen)',
-'VisitFrequency_WidgetOverview'=>'Frequenzübersicht',
-'VisitFrequency_WidgetGraphReturning'=>'Grafik der wiederkehrenden Besucher',
-'VisitFrequency_SubmenuFrequency'=>'Frequenz',
-'VisitTime_LocalTime'=>'Besuche nach lokaler Zeit des Users',
-'VisitTime_ServerTime'=>'Besuche nach lokaler Zeit des Servers',
-'VisitTime_ColumnServerTime'=>'Server-Zeit',
-'VisitTime_ColumnLocalTime'=>'Ortszeit',
-'VisitTime_WidgetLocalTime'=>'Besuche nach lokaler Zeit des Users',
-'VisitTime_WidgetServerTime'=>'Besuche nach lokaler Zeit des Servers',
-'VisitTime_SubmenuTimes'=>'Zeiten',
-'VisitTime_NHour'=>'%sh',
-'VisitorInterest_VisitsPerDuration'=>'Besuche pro Besuchsdauer',
-'VisitorInterest_VisitsPerNbOfPages'=>'Besuche pro Seitenanzahl',
-'VisitorInterest_ColumnVisitDuration'=>'Besuchsdauer',
-'VisitorInterest_ColumnPagesPerVisit'=>'Seiten pro Besuch',
-'VisitorInterest_WidgetLengths'=>'Besuchslänge',
-'VisitorInterest_WidgetPages'=>'Seiten pro Besuch',
-'VisitorInterest_SubmenuFrequencyLoyalty'=>'Häufigkeit und Loyalität',
-'VisitorInterest_PlusXMin'=>'%s min',
-'VisitorInterest_BetweenXYMinutes'=>'%1s-%1s min',
-'VisitorInterest_OnePage'=>'1 Seite',
-'VisitorInterest_NPages'=>'%s Seiten',
-'VisitorInterest_BetweenXYSeconds'=>'%1s-%2ss',
-'Login_LoginPasswordNotCorrect'=>'Benutzername und Passwort sind nicht korrekt',
-'Login_Login'=>'Benutzername',
-'Login_Password'=>'Passwort',
-'Login_LoginOrEmail'=>'Login oder E-Mail',
-'Login_LogIn'=>'Anmelden',
-'Login_Logout'=>'Abmelden',
-'Login_LostYourPassword'=>'Passwort verloren?',
-'Login_RemindPassword'=>'An das Passwort erinnern?',
-'Login_PasswordReminder'=>'Benutzername oder E-Mail-Adresse eingeben um ein neues Passwort per E-Mail zu erhalten.',
-'Login_InvalidUsernameEmail'=>'Ungültiger Bernutzername und/oder E-Mail-Adresse',
-'Login_MailTopicPasswordRecovery'=>'Passwort wiederherstellen',
-'Login_MailPasswordRecoveryBody'=>'Hallo %1s, \n\n Ihr neues Passwort lautet: %2s\n\n Damit können Sie sich unter %3s anmelden.',
-'Login_PasswordSent'=>'Das Passwort wurde gesendet. Bitte Postfach auf neue E-Mails überprüfen.',
-'Login_ContactAdmin'=>'Möglicher Grund: Der Server könnte die mail()-Funktion abgeschaltet haben.<br/>Bitte sprechen Sie mit Ihrem Piwik-Administrator.',
-'UsersManager_UsersManagement'=>'Benutzerverwaltung',
-'UsersManager_UsersManagementMainDescription'=>'Benutzer erstellen oder bearbeiten, Rechte können dann oben gesetzt werden.',
-'UsersManager_ManageAccess'=>'Zugriffsverwaltung',
-'UsersManager_MainDescription'=>'Hier kann Zugriff auf bestimmte Webseiten innerhalb von Piwik erteilt werden. Es ist auch möglich Zugriff für alle Webseiten auf einmal zu setzen.',
-'UsersManager_Sites'=>'Seiten',
-'UsersManager_AllWebsites'=>'Alle Webseiten',
-'UsersManager_ApplyToAllWebsites'=>'Für alle Webseiten anwenden',
-'UsersManager_User'=>'Benutzer',
-'UsersManager_PrivNone'=>'Kein Zugriff',
-'UsersManager_PrivView'=>'Ansicht',
-'UsersManager_PrivAdmin'=>'Administrator',
-'UsersManager_ChangeAllConfirm'=>'Sollen \'%s\' die Berechtigungen für alle Webseiten wirklich geändert werden?',
-'UsersManager_Login'=>'Anmelden',
-'UsersManager_Password'=>'Passwort',
-'UsersManager_Email'=>'E-Mail',
-'UsersManager_Alias'=>'Alias',
-'UsersManager_Token'=>'Authentifizierungs-Token',
-'UsersManager_Edit'=>'Bearbeiten',
-'UsersManager_AddUser'=>'Neuer Benutzer',
-'UsersManager_MenuUsers'=>'Benutzer',
-'UsersManager_DeleteConfirm_js'=>'Soll der Benutzer %s wirklich gelöscht werden?',
-'UsersManager_ExceptionLoginExists'=>'Benutzername \'%s\' existiert bereits.',
-'UsersManager_ExceptionEmailExists'=>'Ein Benutzer mit der E-Mail-Adresse \'%s\' existiert bereits.',
-'UsersManager_ExceptionInvalidLoginFormat'=>'Das Login muss zwischen %s und %s Zeichen lang sein und darf nur Buchstaben, Zahlen oder die Zeichen \'_\' oder \'-\' oder \'.\' enthalten.',
-'UsersManager_ExceptionInvalidPassword'=>'Das Passwort muss zwischen 6 und 26 Zeichen lang sein.',
-'UsersManager_ExceptionInvalidEmail'=>'Die E-Mail-Adresse scheint nicht gültig zu sein.',
-'UsersManager_ExceptionDeleteDoesNotExist'=>'Benutzer \'%s\' existiert nicht und kann daher nicht gelöscht werden.',
-'UsersManager_ExceptionAdminAnonymous'=>'Das \'admin\'-Recht kann nicht dem Benutzer \'anonymous\' vergeben werden.',
-'UsersManager_ExceptionEditAnonymous'=>'Der anonyme Benutzer kann nicht bearbeitet oder gelöscht werden. Er wird von Piwik benutzt um einen Benutzer zu simulieren, der sich noch nicht angemeldet hat. Zum Beispiel könnte das Statistik-Plugin öffentlich gemacht werden, indem dem Benutzer \'anonymous\' das Recht \'view\' dafür vergeben würde.',
-'UsersManager_ExceptionSuperUser'=>'Der angeforderte Benutzer ist der Super-Benutzer und kann über das API nicht angefragt, editiert oder gelöscht werden. Die Angaben zum Super-Benutzer können in der Piwik-Konfigurationsdatei manuell editiert werden.',
-'UsersManager_ExceptionUserDoesNotExist'=>'Der Benutzer \'%s\' existiert nicht.',
-'UsersManager_ExceptionAccessValues'=>'Der Parameter access muss einen der folgenden Werte enthalten: [ %s ]',
-'SitesManager_Sites'=>'Seiten',
-'SitesManager_WebsitesManagement'=>'Webseitenverwaltung',
-'SitesManager_MainDescription'=>'Die Web-Analyse benötigt Webseiten! Webseiten können hinzugefügt, aktualisiert und gelöscht werden. Hier wird auch der JavaScript-Code gezeigt, der einer Webseite hinzugefügt werden muss.',
-'SitesManager_JsCode'=>'JavaScript-Code',
-'SitesManager_JsCodeHelp'=>'Dies ist der JavaScript-Code, der in alle Seiten eingepflegt werden muss.',
-'SitesManager_ShowJsCode'=>'Code darstellen',
-'SitesManager_NoWebsites'=>'Keine Webseite zum Administrieren vorhanden.',
-'SitesManager_AddSite'=>'Neue Webseite hinzufügen',
-'SitesManager_Id'=>'Id',
-'SitesManager_Name'=>'Name',
-'SitesManager_Urls'=>'URLs',
-'SitesManager_MenuSites'=>'Webseiten',
-'SitesManager_DeleteConfirm_js'=>'Soll die Webseite %s wirklich gelöscht werden?',
-'SitesManager_ExceptionDeleteSite'=>'Diese Webseite kann nicht gelöscht werden, da sie die einzige registrierte Webseite ist. Bitte zunächst eine weitere Webseite hinzufügen, dann kann die erste gelöscht werden.',
-'SitesManager_ExceptionNoUrl'=>'Es muss mindestens eine URL für diese Webseite angegeben werden.',
-'SitesManager_ExceptionEmptyName'=>'Der Webseitenname kann nicht leer sein.',
-'SitesManager_ExceptionInvalidUrl'=>'Die Adresse \'%s\' ist kein gültiger URL.',
-'Installation_Installation'=>'Installation',
-'Installation_InstallationStatus'=>'Installationstatus',
-'Installation_PercentDone'=>'%s %% Fertig',
-'Installation_NoConfigFound'=>'Die Piwik-Konfigurationsdatei konnte nicht gefunden werden und es wird versucht, eine Piwik-Seite aufzurufen.<br /><b>&nbsp;&nbsp;&raquo; Sie können <a href=\'index.php\'>Piwik jetzt installieren</a></b><br /><small>Wenn Sie Piwik zuvor schon installiert haben und noch Tabellen in der Datenbank vorhanden sind: Keine Angst, Sie können diese Tabellen und die enthaltenen Daten weiterhin verwenden!</small>',
-'Installation_MysqlSetup'=>'MySQL Datenbanksetup',
-'Installation_MysqlErrorConnect'=>'Fehler beim Verbindungsaufbau zum Datenbankserver',
-'Installation_JsTag'=>'JavaScript tag',
-'Installation_JsTagHelp'=>'<p>Um alle Besucher zählen zu können, muss der Javascript-Code auf jeder Seite eingebaut werden.</p><p>Es muss sich nicht um eine PHP-Seite handeln, da Piwik auch mit HTML, ASP, Perl, etc. funktioniert.</p><p>Hier ist der Code, welcher eingefügt werden muss (Copy & Paste): </p>',
-'Installation_Congratulations'=>'Glückwunsch',
-'Installation_CongratulationsHelp'=>'<p>Glückwunsch! Piwik ist nun installiert.</p><p>Stellen Sie sicher, dass der Javascript-Code auf Ihrer Website eingefügt wurde und warten Sie auf die ersten Besucher.</p>',
-'Installation_ContinueToPiwik'=>'Weiter zu Piwik',
-'Installation_SetupWebsite'=>'Webseite hinzufügen',
-'Installation_SetupWebsiteError'=>'Fehler beim Hinzufügen der Webseite',
-'Installation_GeneralSetup'=>'Grundeinstellungen',
-'Installation_GeneralSetupSuccess'=>'Grundeinstellungen wurden erfolgreich durchgeführt!',
-'Installation_SuperUserLogin'=>'Super-Benutzer Login',
-'Installation_Password'=>'Passwort',
-'Installation_PasswordRepeat'=>'Passwort (wiederholen)',
-'Installation_Email'=>'E-Mail',
-'Installation_SecurityNewsletter'=>'Senden Sie mir wichtige Updates von Piwik und Sicherheitswarnungen per E-Mail',
-'Installation_CommunityNewsletter'=>'Senden Sie mir Community-Updates (neue Plugins, neue Funktionen usw.) per E-Mail',
-'Installation_PasswordDoNotMatch'=>'Passwörter stimmen nicht überein',
-'Installation_SubmitGo'=>'Los!',
-'Installation_SystemCheck'=>'Systemprüfung',
-'Installation_SystemCheckPhp'=>'PHP-Version',
-'Installation_SystemCheckPdo'=>'PDO Erweiterung',
-'Installation_SystemCheckPdoMysql'=>'PDO_Mysql Erweiterung',
-'Installation_SystemCheckPdoError'=>'Sie müssen die PDO- und PDO_MySQL - Erweiterungen in der php.ini aktivieren.',
-'Installation_SystemCheckPdoHelp'=>'On a windows server you can add the following lines in your php.ini %s <br /><br />On a Linux server you can compile php with the following option %s In your php.ini, add the following lines %s<br /><br />More information on the <a style="color:red" href="http://php.net/pdo">PHP website</a>.',
-'Installation_SystemCheckWriteDirs'=>'Verzeichnisse mit Schreibzugriff',
-'Installation_SystemCheckWriteDirsHelp'=>'Um diesen Fehler im Linux-System zu beheben, versuchen Sie den/die folgenden Befehl(e) einzugeben',
-'Installation_SystemCheckMemoryLimit'=>'Speicherlimit',
-'Installation_SystemCheckMemoryLimitHelp'=>'On a high traffic website, the archiving process may require more memory than currently allowed.<br />See the directive memory_limit in your php.ini file if necessary.',
-'Installation_SystemCheckGD'=>'GD &gt; 2.x (graphics)',
-'Installation_SystemCheckGDHelp'=>'The sparklines (small graphs) will not work.',
-'Installation_SystemCheckTimeLimit'=>'set_time_limit() erlaubt',
-'Installation_SystemCheckTimeLimitHelp'=>'On a high traffic website, executing the archiving process may require more time than currently allowed.<br />See the directive max_execution_time in your php.ini file if necessary',
-'Installation_SystemCheckMail'=>'mail() erlaubt',
-'Installation_SystemCheckError'=>'An error occured - must be fixed before you proceed',
-'Installation_SystemCheckWarning'=>'Piwik will work normally but some features may be missing',
-'Installation_Tables'=>'Erstelle die Tabellen',
-'Installation_TablesWithSameNamesFound'=>'Einige %s Tabellen in Ihrer %s Datenbank haben dieselben Namen wie die Tabellen, die Piwik versucht zu erstellen',
-'Installation_TablesFound'=>'Die folgenden Tabellen wurden in der Datenbank gefunden',
-'Installation_TablesWarningHelp'=>'Either choose to reuse the existing database tables or select a clean install to erase all existing data in the database.',
-'Installation_TablesReuse'=>'Benutze die vorhandenen Tabellen',
-'Installation_TablesDelete'=>'Entferne die erkannten Tabellen',
-'Installation_TablesDeletedSuccess'=>'Vorhandene Piwiktabellen wurden entfernt',
-'Installation_TablesCreatedSuccess'=>'Die Tabellen wurden erfolgreich erzeugt!',
-'Installation_DatabaseCreatedSuccess'=>'Datenbank %s erfolgreich erstellt!',
-'Installation_GoBackAndDefinePrefix'=>'Zurückgehen und einen Präfix für die Piwik-Tabellen definieren',
-'Installation_ConfirmDeleteExistingTables'=>'Sicher, dass die Tabellen: %s aus der Datenbank gelöscht werden sollen? WARNUNG: DATEN AUS DIESEN TABELLEN KÖNNEN NICHT WIEDERHERGESTELLT WERDEN!',
-'Installation_Welcome'=>'Willkommen!',
-'Installation_WelcomeHelp'=>'<p>Piwik is an open source web analytics software that makes it easy to get the information you want from your visitors.</p><p>This process is split up into %s easy steps and will take around 5 minutes.</p>',
-'Installation_ErrorInvalidState'=>'Fehler: Sie scheinen zu versuchen, einen Schritt des Installationsvorgangs zu überspringen oder Ihre Cookies sind deaktiviert, oder die Piwik-Konfigurationsdatei wurde bereits erstellt. %sStellen Sie sicher, dass Ihre Cookies aktiviert%s sind und gehen Sie zurück %s zur ersten Seite der Installation. %s',
-'Provider_WidgetProviders'=>'Provider',
-'Provider_ColumnProvider'=>'Anbieter',
-'Provider_SubmenuLocationsProvider'=>'Standorte und Provider',
-'Goals_ColumnConversions'=>'Konversionen',
-'Goals_ColumnConversionRate'=>'Konversionsquote',
-'Goals_ColumnRevenue'=>'Einnahmen',
-'DBStats_DatabaseUsage'=>'Datenbanknutzung',
-'DBStats_MainDescription'=>'Piwik speichert die Analyse-Daten in einer MySQL-Datenbank. Aktuell belegter Speicherplatz %s.',
-'DBStats_Table'=>'Tabelle',
-'DBStats_RowNumber'=>'Zeilenanzahl',
-'DBStats_DataSize'=>'Datenmenge',
-'DBStats_IndexSize'=>'Indexgrösse',
-'DBStats_TotalSize'=>'Gesamtgröße',
-'TranslationsAdmin_MenuTranslations'=>'Übersetzungen',
-'TranslationsAdmin_MenuLanguages'=>'Sprachen',
-'TranslationsAdmin_Plugin'=>'Plugin',
-'TranslationsAdmin_Definition'=>'Definition',
-'TranslationsAdmin_DefaultString'=>'Vorgabetext (Englisch)',
-'TranslationsAdmin_TranslationString'=>'Übersetzter Text (aktuelle Sprache: %s)',
-'TranslationsAdmin_Translations'=>'Übersetzungen',
-'TranslationsAdmin_FixPermissions'=>'Bitte folgende Dateiberechtigungen korrigieren',
-'TranslationsAdmin_AvailableLanguages'=>'Verfügbare Sprachen',
-'TranslationsAdmin_AddLanguage'=>'Sprache hinzufügen',
-'TranslationsAdmin_LanguageCode'=>'Sprach-Code',
-'TranslationsAdmin_Export'=>'Sprache exportieren',
-'TranslationsAdmin_Import'=>'Sprache importieren',
-);
+ 'General_Locale' => 'de_DE.UTF-8',
+ 'General_TranslatorName' => 'Frank Bueltge, Thorsten Taube, Arthur W. Borens, Marco Ziesing, Andreas Just, Fabian Becker, Henry Müller, Pascal Herbert,Christian W. Schneider',
+ 'General_TranslatorEmail' => 'frank@bueltge.de, piwik@thorstentaube.de, arthur.borens@gmx.de, mail@marco-ziesing.de, andreas.just@cmsmadesimple.de, halfdan@xnorfz.de,ich@pascal90.de, christian@conlabz.de',
+ 'General_EnglishLanguageName' => 'German',
+ 'General_OriginalLanguageName' => 'Deutsch',
+ 'General_HelloUser' => 'Hallo, %s!',
+ 'General_OpenSourceWebAnalytics' => 'Quelloffene Webanalytik',
+ 'General_YourDashboard' => 'Ihr Dashboard',
+ 'General_API' => 'API',
+ 'General_Widgets' => 'Widgets',
+ 'General_Settings' => 'Einstellungen',
+ 'General_GiveUsYourFeedback' => 'Feedback geben!',
+ 'General_Unknown' => 'unbekannt',
+ 'General_Required' => '%s benötigt',
+ 'General_Error' => 'Fehler',
+ 'General_Warning' => 'Warnung',
+ 'General_BackToHomepage' => 'Zurück zur Piwik Homepage',
+ 'General_Yes' => 'Ja',
+ 'General_No' => 'Nein',
+ 'General_Delete' => 'Löschen',
+ 'General_Edit' => 'Ändern',
+ 'General_Ok' => 'OK',
+ 'General_Close' => 'Schließen',
+ 'General_Logout' => 'Abmelden',
+ 'General_Done' => 'Erledigt',
+ 'General_LoadingData' => 'Lade Daten...',
+ 'General_Loading' => 'Laden...',
+ 'General_ErrorRequest' => 'Einen Moment bitte. Wir laden die erforderlichen Daten. Bitte neu laden, falls längere Zeit keine Aktion ausgeführt wird.',
+ 'General_Next' => 'nächste',
+ 'General_Previous' => 'vorherige',
+ 'General_Search' => 'Suchen',
+ 'General_Others' => 'Andere',
+ 'General_Table' => 'Tabelle',
+ 'General_Piechart' => 'Kreisdiagramm',
+ 'General_TagCloud' => 'Schlagwortwolke',
+ 'General_VBarGraph' => 'Säulendiagramm',
+ 'General_Export' => 'Export',
+ 'General_ExportAsImage' => 'Als Bild exportieren',
+ 'General_SaveImageOnYourComputer' => 'Um das Bild auf dem Computer zu speichern, einen Rechtsklick auf das Bild machen und „Bild speichern unter..." auswählen.',
+ 'General_Refresh' => 'Aktualisiere die Seite',
+ 'General_Visitors' => 'Besucher',
+ 'General_ColumnNbUniqVisitors' => 'Eindeutige Besucher',
+ 'General_ColumnNbVisits' => 'Besucher',
+ 'General_ColumnNbActions' => 'Aktionen',
+ 'General_ColumnMaxActions' => 'Maximale Aktionen bei einem Besuch',
+ 'General_ColumnSumVisitLength' => 'Von Besuchern verbrachte Gesamtzeit (in Sekunden)',
+ 'General_ColumnLabel' => 'Label',
+ 'General_ColumnActionsPerVisit' => 'Aktionen pro Besuch',
+ 'General_ColumnAvgTimeOnSite' => 'Durchschnittszeit auf der Seite',
+ 'General_ColumnBounceRate' => 'Absprungsrate',
+ 'General_ColumnPageviews' => 'Seitenansichten',
+ 'General_ColumnUniquePageviews' => 'Einmalige Seitenansichten',
+ 'General_ColumnValuePerVisit' => 'Wert pro Besuch',
+ 'General_ColumnVisitsWithConversions' => 'Besuche mit Konversionen',
+ 'General_Save' => 'Speichern',
+ 'General_Website' => 'Webseite',
+ 'General_NoDataForGraph' => 'Keine Daten für dieses Diagramm',
+ 'General_NoDataForTagCloud' => 'Keine Daten für diese Schlagwortwolke.',
+ 'General_DisplayNormalTable' => 'Normale Tabelle anzeigen',
+ 'General_DisplayMoreData' => 'Mehr Daten anzeigen',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s ist ein gemeinschaftliches Projekt. %s Wenn Ihnen Piwik gefällt, können Sie helfen! Möchten Sie herausfinden %s wie Sie zu Piwik beitragen können?%s ',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Zur Zeit betrachten Sie die Demo von%s; %sLaden Sie%s die Vollversion herunter! Besuchen Sie %s',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s ist verfügbar. %s Bitte jetzt ein Update machen!%s (siehe %s Änderungen%s).',
+ 'General_BackToPiwik' => 'Zurück zu Piwik',
+ 'General_ShortMonth_1' => 'Jan',
+ 'General_ShortMonth_2' => 'Feb',
+ 'General_ShortMonth_3' => 'Mar',
+ 'General_ShortMonth_4' => 'Apr',
+ 'General_ShortMonth_5' => 'Mai',
+ 'General_ShortMonth_6' => 'Jun',
+ 'General_ShortMonth_7' => 'Jul',
+ 'General_ShortMonth_8' => 'Aug',
+ 'General_ShortMonth_9' => 'Sep',
+ 'General_ShortMonth_10' => 'Okt',
+ 'General_ShortMonth_11' => 'Nov',
+ 'General_ShortMonth_12' => 'Dez',
+ 'General_LongMonth_1' => 'Januar',
+ 'General_LongMonth_2' => 'Februar',
+ 'General_LongMonth_3' => 'März',
+ 'General_LongMonth_4' => 'April',
+ 'General_LongMonth_5' => 'Mai',
+ 'General_LongMonth_6' => 'Juni',
+ 'General_LongMonth_7' => 'Juli',
+ 'General_LongMonth_8' => 'August',
+ 'General_LongMonth_9' => 'September',
+ 'General_LongMonth_10' => 'Oktober',
+ 'General_LongMonth_11' => 'November',
+ 'General_LongMonth_12' => 'Dezember',
+ 'General_ShortDay_1' => 'Mon',
+ 'General_ShortDay_2' => 'Die',
+ 'General_ShortDay_3' => 'Mit',
+ 'General_ShortDay_4' => 'Don',
+ 'General_ShortDay_5' => 'Fre',
+ 'General_ShortDay_6' => 'Sam',
+ 'General_ShortDay_7' => 'Son',
+ 'General_LongDay_1' => 'Montag',
+ 'General_LongDay_2' => 'Dienstag',
+ 'General_LongDay_3' => 'Mittwoch',
+ 'General_LongDay_4' => 'Donnerstag',
+ 'General_LongDay_5' => 'Freitag',
+ 'General_LongDay_6' => 'Samstag',
+ 'General_LongDay_7' => 'Sonntag',
+ 'General_Dashboard' => 'Dashboard',
+ 'General_MultiSitesSummary' => 'Alle Webseiten',
+ 'General_Details' => 'Details',
+ 'General_ExportAsImage_js' => 'Als Bild exportieren',
+ 'General_SaveImageOnYourComputer_js' => 'Um das Bild auf ihre Festplatte zu speichern, klicken Sie mit der rechten Maustaste auf das Bild und wählen "Bild speichern unter..."',
+ 'General_ForExampleShort' => 'z.B.',
+ 'General_RequiresFlash' => 'Die Darstellung von Graphiken in Piwik erfordert Flash.',
+ 'General_GraphHelp' => 'Mehr Informationen über die Darstellung von Graphiken in Piwik.',
+ 'General_ExceptionDatabaseVersion' => 'Die %1$ Version ist %2$, allerdings erfordert Piwik mindestens die Version %3$.',
+ 'General_ExceptionIncompatibleClientServerVersions' => 'Die %1$ Clientversion ist %2$s welche nicht kompatible mit der Serverversion %3$ ist.',
+ 'General_ExceptionMissingFile' => 'Fehlende Datei: %s',
+ 'General_ExceptionFilesizeMismatch' => 'Falsche Dateigröße: %1$ (erwartete Länge: %2$, aktuell: %3$)',
+ 'General_ExceptionFileIntegrity' => 'Integritätscheck fehlgeschlagen: %s',
+ 'General_ExceptionNonceMismatch' => 'Der Sicherheitstoken kann in dieser Form nicht verifiziert werden.',
+ 'General_WarningFileIntegritySkipped' => 'Es wurde Entwicklungsumgebung ermittelt, daher wurde der Integritätscheck übersprungen.',
+ 'General_WarningFileIntegrityNoManifest' => 'Durch die fehlende Datei: manifest.inc.php konnte der Integritätscheck nicht durchgeführt werden.',
+ 'General_WarningFileIntegrityNoMd5file' => 'Durch die Fehlende md5_file() Funktion konnte der Integritätscheck nicht durchgeführt werden.',
+ 'General_FileIntegrityWarningExplanation' => 'Der Integritätscheck ist fehlgeschlagen und hat Fehler ausgegeben. Oftmals geschieht dies durch einen partiellen oder fehlgeschlagenen Upload einiger Piwik Dateien. Laden Sie die Piwik Dateien erneut hoch und aktualisieren Sie diese Seite bis keine Fehler mehr vorhanden sind.',
+ 'Actions_Actions' => 'Aktionen',
+ 'Actions_SubmenuPages' => 'Seiten',
+ 'Actions_SubmenuOutlinks' => 'Ausgehende Verweise',
+ 'Actions_SubmenuDownloads' => 'Downloads',
+ 'Actions_ColumnClicks' => 'Klicks',
+ 'Actions_ColumnUniqueClicks' => 'Einmalige Klicks',
+ 'Actions_ColumnDownloads' => 'Downloads',
+ 'Actions_ColumnUniqueDownloads' => 'Einmalige Downloads',
+ 'Actions_ColumnPageName' => 'Seitenname',
+ 'Actions_ColumnClickedURL' => 'Angeklickte URL',
+ 'Actions_ColumnDownloadURL' => 'Download-URL',
+ 'Actions_PluginDescription' => 'Zusammenfassung über die Anzahl der betrachteten Seiten, ausgehenden Verweise und Downloads. Ausgehende Verweise und Downloads werden automatisch getrackt.',
+ 'Actions_SubmenuPageTitles' => 'Seitentitel',
+ 'Actions_ColumnPageURL' => 'Seiten-URL',
+ 'AnonymizeIP_PluginDescription' => 'Auf Grund lokaler Datenschutzbedingungen können Sie mit diesem Plugin die IP-Adresse des Besuchers anonymisieren.',
+ 'API_QuickDocumentation' => '<h2>API Schnelle Dokumentation</h2><p>Wenn Sie f&uuml;r heute keine Daten haben, k&ouml;nnen Sie sich mit diesem Besucher-Generator-Script welche <a href=\'misc/generateVisits.php\' target=_blank>generieren</a>.</p><p>Sie k&ouml;nnen f&uuml;r jede Methode die verschiedenen Formate ausprobieren. Es ist sehr einfach, alle Daten die Sie von piwik haben wollen zu extrahieren!</p><p><b>F&uuml;r mehr Informationen lohnt sich ein Blick auf die <a href=\'http://dev.piwik.org/trac/wiki/API\'>offizielle API Dokumentation</a> oder die <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API Referenz</a>.</b></P><h2>Benutzer-Authentifizierung</h2><p>Wenn Sie die Daten in <b>einem Script, einem crontab, etc</b> anfordern wollen, m&uuml;ssen Sie den Parameter <code><u>&token_auth=%s</u></code> zu der API hinzuf&uuml;gen welche URLs aufruft die Authentifizierung ben&ouml;tigen.</p><p>Dieser Paramter (token) ist so geheim wie Ihr Benutzername und Passwort, <b>ver&ouml;ffentlichen Sie es nicht!</p>',
+ 'API_LoadedAPIs' => '%s APIs erfolgreich geladen',
+ 'API_PluginDescription' => 'Alle Daten sind über eine einfache API verfügbar. Diese Plugin ist der Webservice um Daten in XML, JSON, PHP, CSV, etc. zu exportieren.',
+ 'ExampleAPI_PluginDescription' => 'Beispiel-Plugin: Wir erzeugt man eine API für ein Plugin, das Daten in verschiedene Formate ohne zusätzliche Programmierung exportier.',
+ 'CoreAdminHome_PluginDescription' => 'Piwik Einstellungen',
+ 'CoreHome_NoPrivileges' => 'Sie sind angemeldet als \'%s\', allerdings fehlen Ihnen Berechtigungen.<br/>Kontaktieren Sie Ihren Administrator um \'view\'-Rechte zu erhalten.',
+ 'CoreHome_JavascriptDisabled' => 'JavaScript muss aktiviert sein, damit Piwik im Standard-Modus verwendet werden kann.<br/>Um fortzufahren bitte JavaScript in den Eigenschaften Ihres Browsers aktivieren und die Seite anschließend neu laden.',
+ 'CoreHome_TableNoData' => 'Keine Daten',
+ 'CoreHome_CategoryNoData' => 'Keine Daten in dieser Kategorie. Probieren Sie "Gesamte Population einbeziehen"',
+ 'CoreHome_ShowJSCode' => 'Einzupflegendes JavaScript darstellen.',
+ 'CoreHome_IncludeAllPopulation_js' => 'Gesamte Population einbeziehen.',
+ 'CoreHome_ExcludeLowPopulation_js' => 'Geringe Population ausschließen.',
+ 'CoreHome_PageOf_js' => '%s von %s',
+ 'CoreHome_Loading_js' => 'Laden...',
+ 'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
+ 'CoreHome_PeriodDay' => 'Tag',
+ 'CoreHome_PeriodWeek' => 'Woche',
+ 'CoreHome_PeriodMonth' => 'Monat',
+ 'CoreHome_PeriodYear' => 'Jahr',
+ 'CoreHome_PeriodDays' => 'Tage',
+ 'CoreHome_PeriodWeeks' => 'Wochen',
+ 'CoreHome_PeriodMonths' => 'Monate',
+ 'CoreHome_PeriodYears' => 'Jahre',
+ 'CoreHome_DaySu_js' => 'So',
+ 'CoreHome_DayMo_js' => 'Mo',
+ 'CoreHome_DayTu_js' => 'Di',
+ 'CoreHome_DayWe_js' => 'Mi',
+ 'CoreHome_DayTh_js' => 'Do',
+ 'CoreHome_DayFr_js' => 'Fr',
+ 'CoreHome_DaySa_js' => 'Sa',
+ 'CoreHome_ShortDay_1_js' => 'So',
+ 'CoreHome_ShortDay_2_js' => 'Mo',
+ 'CoreHome_ShortDay_3_js' => 'Di',
+ 'CoreHome_ShortDay_4_js' => 'Mi',
+ 'CoreHome_ShortDay_5_js' => 'Do',
+ 'CoreHome_ShortDay_6_js' => 'Fr',
+ 'CoreHome_ShortDay_7_js' => 'Sa',
+ 'CoreHome_LongDay_1_js' => 'Sonntag',
+ 'CoreHome_LongDay_2_js' => 'Montag',
+ 'CoreHome_LongDay_3_js' => 'Dienstag',
+ 'CoreHome_LongDay_4_js' => 'Mittwoch',
+ 'CoreHome_LongDay_5_js' => 'Donnerstag',
+ 'CoreHome_LongDay_6_js' => 'Freitag',
+ 'CoreHome_LongDay_7_js' => 'Samstag',
+ 'CoreHome_ShortMonth_1_js' => 'Jan',
+ 'CoreHome_ShortMonth_2_js' => 'Feb',
+ 'CoreHome_ShortMonth_3_js' => 'Mär',
+ 'CoreHome_ShortMonth_4_js' => 'Apr',
+ 'CoreHome_ShortMonth_5_js' => 'Mai',
+ 'CoreHome_ShortMonth_6_js' => 'Jun',
+ 'CoreHome_ShortMonth_7_js' => 'Jul',
+ 'CoreHome_ShortMonth_8_js' => 'Aug',
+ 'CoreHome_ShortMonth_9_js' => 'Sep',
+ 'CoreHome_ShortMonth_10_js' => 'Okt',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dez',
+ 'CoreHome_MonthJanuary_js' => 'Januar',
+ 'CoreHome_MonthFebruary_js' => 'Februar',
+ 'CoreHome_MonthMarch_js' => 'März',
+ 'CoreHome_MonthApril_js' => 'April',
+ 'CoreHome_MonthMay_js' => 'Mai',
+ 'CoreHome_MonthJune_js' => 'Juni',
+ 'CoreHome_MonthJuly_js' => 'Juli',
+ 'CoreHome_MonthAugust_js' => 'August',
+ 'CoreHome_MonthSeptember_js' => 'September',
+ 'CoreHome_MonthOctober_js' => 'Oktober',
+ 'CoreHome_MonthNovember_js' => 'November',
+ 'CoreHome_MonthDecember_js' => 'Dezember',
+ 'CoreHome_PluginDescription' => 'Struktur der Webanalyse',
+ 'CorePluginsAdmin_Plugins' => 'Plugins',
+ 'CorePluginsAdmin_PluginsManagement' => 'Pluginverwaltung',
+ 'CorePluginsAdmin_MainDescription' => 'Plugins erweitern die Funktionalität von Piwik. Installierte Plugins können hier aktiviert oder deaktiviert werden.',
+ 'CorePluginsAdmin_Plugin' => 'Plugin',
+ 'CorePluginsAdmin_Version' => 'Version',
+ 'CorePluginsAdmin_Description' => 'Beschreibung',
+ 'CorePluginsAdmin_Status' => 'Status',
+ 'CorePluginsAdmin_Action' => 'Aktion',
+ 'CorePluginsAdmin_PluginHomepage' => 'Plugin Webseite',
+ 'CorePluginsAdmin_Activated' => 'Aktiviert',
+ 'CorePluginsAdmin_Active' => 'Aktiv',
+ 'CorePluginsAdmin_Inactive' => 'Inaktiv',
+ 'CorePluginsAdmin_ActivatedHelp' => 'Dieses Plugin kann nicht deaktiviert werden.',
+ 'CorePluginsAdmin_Deactivate' => 'Deaktivieren',
+ 'CorePluginsAdmin_Activate' => 'Aktivieren',
+ 'CorePluginsAdmin_MenuPlugins' => 'Plugins',
+ 'CorePluginsAdmin_PluginDescription' => 'Oberfläche zur Plugin Verwaltung',
+ 'CoreUpdater_UpdateTitle' => 'Aktualisierung',
+ 'CoreUpdater_DatabaseUpgradeRequired' => 'Datenbank-Upgrade benötigt',
+ 'CoreUpdater_YourDatabaseIsOutOfDate' => 'Ihre Piwik-Datenbank ist nicht mehr aktuell und muss aktualisiert werden, bevor Sie weiter damit arbeiten können.',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Mit der Piwik-Datenbank wird ein Upgrade von Version %s auf die neue Version %s durchgeführt.',
+ 'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Die folgenden Plugins werden aktualisiert: %s',
+ 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Der Upgrade-Prozess kann eine Weile dauern. Bitte haben Sie etwas Geduld.',
+ 'CoreUpdater_UpgradePiwik' => 'Piwik aktualisieren',
+ 'CoreUpdater_HelpMessageContent' => 'Schauen Sie sich die %s Piwik FAQ %s an welche versucht, die &uuml;blichsten Fehler bei einem Upgrade zu erkl&auml;ren. Fragen Sie Ihre Systemadministratoren - diese k&ouml;nnten in der Lage sein Ihnen bei den Fehleren zu helfen welche h&ouml;chstwahrscheinlich mit Ihrem Server oder der MySQL-Installation zusammenh&auml;ngen.',
+ 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Kritischer Fehler w&auml;hrend dem Upgrade-Prozess:',
+ 'CoreUpdater_HelpMessageIntroductionWhenError' => 'Das dar&uuml;ber ist die Kernfehlermeldung. Sie sollte die Ursache erkl&auml;ren, aber wenn Sie mehr erfahren wollen, helfen Sie bitte:',
+ 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Das Upgrade verlief reibungslos, dennoch gab es Meldungen w&auml;hrend des Prozesses. Bitte die Beschreibung lesen, um mehr Details zu erfahren. F&uuml;r weitere Hilfe:',
+ 'CoreUpdater_UpgradeComplete' => 'Upgrade abgeschlossen!',
+ 'CoreUpdater_WarningMessages' => 'Warnhinweis:',
+ 'CoreUpdater_ErrorDuringPluginsUpdates' => 'Fehler w&auml;hrend Plugin-Aktualisierungen:',
+ 'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Wir deaktivierten automatisch folgende Plugins: %s',
+ 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik wurde erfolgreich aktualisiert!',
+ 'CoreUpdater_ContinueToPiwik' => 'Weiter zu Piwik',
+ 'CoreUpdater_UpdateAutomatically' => 'Automatisch Update durchführen',
+ 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Eine neue Version von Piwik ist als Update verfügbar',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Ein Update auf Version %s kann durchgeführt oder das Paket kann heruntergeladen und manuell installiert werden:',
+ 'CoreUpdater_DownloadX' => '%s herunterladen',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Das Piwik Ein-Klick-Update wurde abgebrochen. Wenn die oben stehende Fehlermeldung nicht\ behoben werden kann, empfehlen wir Ihnen, ein manuelles Update von Piwik durchzuführen. %s Bitte die %sUpdate-Dokumentatierung%s ansehen, um loszulegen!',
+ 'CoreUpdater_VerifyingUnpackedFiles' => 'Die entpackten Dateien werden überprüft',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Ein Backup der Konfigurationsdatei wird in %s erstellt',
+ 'CoreUpdater_InstallingTheLatestVersion' => 'Die neueste Version wird installiert',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Es wurde erfolgreich ein Update von Piwik durchgeführt!',
+ 'CoreUpdater_PluginDescription' => 'Piwik Update',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Wichtiger Hinweis für große Piwik Installationen',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'Wenn Sie eine große Piwik Datenbank haben, können Updates zu lange dauern um erfolgreich im Browser durchgeführt zu werden. In solch einem Fall können Sie das Update von der Kommandozeile aus starten: %s',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => 'Wenn Sie nicht das Update von der Kommandozeile aus ausführen können und Piwik den Update nicht durchführen kann (wegen Zeitüberschreitungen der Datenbank, des Browser oder sonstigen Fällen), können Sie die SQL-Kommandos manuell ausführen.',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => 'Klicken Sie hier um die Liste der auszuführenden SQL Kommandos zu sehen.',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => 'Hinweis: Wenn Sie die Kommandos manuell ausführen, könnte es passieren, dass einige fehlschlagen. Führen Sie in solch einem Fall einfach das nächsten Kommando in der Liste aus.',
+ 'CoreUpdater_ReadyToGo' => 'Fertig?',
+ 'CoreUpdater_ErrorDIYHelp' => 'Wenn Sie ein professioneller Benutzer sind und einen unerwarteten Fehler in der Aktualisierung der Datenbank entdecken:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'identifizieren und korrigieren Sie die Quelle des Problem (z.B. memory_limit oder max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'führen Sie die fehlgeschlagenen Kommandos nochmal aus',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'aktualisieren Sie die Tabelle `option` in der Datenbank und setzen dabei den Wert version_core auf die aktuelle Version, deren Update fehlgeschlagen ist',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'starten Sie die Aktualisierung erneut (im Browser oder auf der Kommandozeile) um das Update zu wiederholen',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'berichten Sie den Fehler (und die Lösung) um Piwik zu verbessern',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Update wird von %s runtergeladen',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Update wird entpackt',
+ 'CoreUpdater_EmptyDatabaseError' => 'Datenbank %s ist leer. Sie müssen die Konfigurationsdatei anpassen oder entfernen.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Ihr Version %s ist aktuell.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Archiv inkompatibel: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Leeres Archiv.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Archiv ist nicht komplett. Einige Dateien fehlen (z.B. %s).',
+ 'Dashboard_Dashboard' => 'Übersicht',
+ 'Dashboard_AddWidget' => 'Widget hinzufügen...',
+ 'Dashboard_DeleteWidgetConfirm' => 'Sicher, dass dieses Widget vom Dashboard entfernt werden soll?',
+ 'Dashboard_SelectWidget' => 'Das hinzuzufügende Widget auswählen',
+ 'Dashboard_AddPreviewedWidget_js' => 'Vorheriges Widget zum Dashboard hinzufügen',
+ 'Dashboard_WidgetPreview_js' => 'Widget-Vorschau',
+ 'Dashboard_Close_js' => 'Schließen',
+ 'Dashboard_TitleWidgetInDashboard_js' => 'Widget befindet sich bereits im Dashboard',
+ 'Dashboard_TitleClickToAdd_js' => 'Klicken, um zum Dashboard hinzuzufügen',
+ 'Dashboard_LoadingWidget_js' => 'Lade Widget, bitte warten...',
+ 'Dashboard_WidgetNotFound_js' => 'Widget nicht gefunden',
+ 'Dashboard_PluginDescription' => 'Ihr Dashboard. Sie können es sich individuell anpassen: neue Widgets hinzufügen oder die Reihenfolge ändern. Jeder Benutzer hat ein eigenes Dashboard.',
+ 'DBStats_DatabaseUsage' => 'Datenbanknutzung',
+ 'DBStats_MainDescription' => 'Ihre Analyse-Daten werden in einer MySQL-Datenbank gespeichert. Aktuell belegter Speicherplatz %s.',
+ 'DBStats_Table' => 'Tabelle',
+ 'DBStats_RowNumber' => 'Zeilenanzahl',
+ 'DBStats_DataSize' => 'Datenmenge',
+ 'DBStats_IndexSize' => 'Indexgrösse',
+ 'DBStats_TotalSize' => 'Gesamtgröße',
+ 'DBStats_PluginDescription' => 'Dieses Plugin berichtet über die Nutzung und Auslastung der Piwik Tabellen.',
+ 'DBStats_LearnMore' => 'Um mehr darüber zu erfahren wie Piwik Daten verarbeitet und wie sie dies auf stark besuchten Webseiten handhaben können, schauen Sie in die Dokumentation unter: %s.',
+ 'DBStats_RowCount' => 'Zeilenanzahl',
+ 'EntryPage_Bounces' => 'Absprünge',
+ 'EntryPage_Referrers' => 'Verweis',
+ 'ExampleFeedburner_PluginDescription' => 'Beispiel Plugin: Wie können Feedburner Informationen auf dem Dashboard in einem Widget dargestellt werden?',
+ 'ExamplePlugin_PluginDescription' => 'Beispiel Plugin: Dieses Plugin zeigt, wie Sie ein einfaches Plugin erstellen welches zwei Widgets im Dashboard erzeugt.',
+ 'ExamplePlugin_exampleWidgets' => 'Beispielwidgets',
+ 'ExamplePlugin_exampleWidget' => 'Beispielwidget',
+ 'ExamplePlugin_blogPiwikRss' => 'Piwik Blog RSS',
+ 'ExamplePlugin_photostreamMatt' => 'Matt\'s Fotos',
+ 'ExampleRssWidget_PluginDescription' => 'Beispielplugin: Wie erzeugt man ein neues Widget das RSS Feeds lesen und darstellen kann?',
+ 'ExampleUI_PluginDescription' => 'Beispielplugin: Dieses Plugin zeigt wie man mit der Oberfläche arbeitet: Tabellen, Graphiken, etc. erzeugen kann.',
+ 'Feedback_PluginDescription' => 'Senden Sie Ihr Feedback an das Piwik Team. Teilen Sie Ihre Ideen, Anforderungen und Wünsche mit uns!',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Wollen Sie einen Fehler berichten oder haben Sie einen speziellen Wunsch?',
+ 'Feedback_ViewAnswersToFAQ' => 'Achten Sie auf auf %s häufig gestellte Fragen%s',
+ 'Feedback_WhyAreMyVisitsNoTracked' => 'Warum werden Zugriffe auf meine Webseiten nicht registriert?',
+ 'Feedback_HowToExclude' => 'Wie verhindere ich dass meine Zugriff mit gerechnet werden?',
+ 'Feedback_WhyWrongCountry' => 'Warum zeichnet Piwik meine Zugriff aus einem fremden Land auf?',
+ 'Feedback_HowToAnonymizeIP' => 'Wie verschleiere ich die IP Adressen meiner Besucher in der Datenbank?',
+ 'Feedback_VisitTheForums' => 'Besuchen Sie die %s Foren%s',
+ 'Feedback_LearnWaysToParticipate' => 'Sehen Sie alle Möglichkeiten die Sie %s unterstützen können%s',
+ 'Feedback_SpecialRequest' => 'Haven Sie eine spezielle Anfrage an das Team?',
+ 'Feedback_ContactThePiwikTeam' => 'Kontaktieren Sie das Piwik Team!',
+ 'Feedback_IWantTo' => 'Ich möchte:',
+ 'Feedback_CategoryShareStory' => 'Teilen Sie uns eine Erfolgsgeschichte mit',
+ 'Feedback_CategorySponsor' => 'Fördern Sie Piwik',
+ 'Feedback_CategoryHire' => 'Fragen Sie einen Piwik Berater an',
+ 'Feedback_CategorySecurity' => 'Berichten Sie über eine Sicherheitslücke',
+ 'Feedback_MyEmailAddress' => 'E-Mail - Adresse:',
+ 'Feedback_MyMessage' => 'Nachricht:',
+ 'Feedback_DetailsPlease' => '(bitte so viel Details wie möglich)',
+ 'Feedback_SendFeedback' => 'Feedback absenden',
+ 'Feedback_ManuallySendEmailTo' => 'Senden Sie ihre Nachricht an',
+ 'Feedback_MessageSent' => 'Ihre Nachricht wurde an das Piwik Team übermittelt.',
+ 'Feedback_ThankYou' => 'Danke für Ihre Unterstützung um Piwik zu verbessern!',
+ 'Feedback_ThePiwikTeam' => 'Das Piwik Team',
+ 'Feedback_ExceptionBodyLength' => 'Nachricht muss mindestens %s Zeichen lang sein.',
+ 'Feedback_ExceptionNoUrls' => 'Um Spam zu vermeiden kann die Nachricht keine URL enthalten.',
+ 'Forecast_Widget' => 'Vorhersage f&uuml;r Heute',
+ 'Forecast_Column' => 'Erwartung',
+ 'Forecast_Actions' => 'Seitenbesuche',
+ 'Forecast_Visitors' => 'Besucher',
+ 'Forecast_Bounce' => 'abgesprungene Besucher',
+ 'Forecast_ReturnVisits' => 'wiederkehrende Besucher',
+ 'GeoIP_Country' => 'Land',
+ 'GeoIP_Continent' => 'Kontinent',
+ 'GeoIP_DistinctCountries' => '%s verschiedene Länder',
+ 'GeoIP_SubmenuLocations' => 'Standorte',
+ 'GeoIP_WidgetContinents' => 'Besucherkontinente',
+ 'GeoIP_WidgetCountries' => 'Besucherländer',
+ 'GeoIP_ColumnCity' => 'Stadt',
+ 'Goals_ColumnConversions' => 'Konversionen',
+ 'Goals_ColumnConversionRate' => 'Konversionsquote',
+ 'Goals_ColumnRevenue' => 'Einnahmen',
+ 'Goals_PluginDescription' => 'Erzeugen Sie Zielen und berichten über die erzielten Umsätze: Verhalten über die Zeit, Einkommen pro Besuch, Konversion je Zugriff, je Suchbegriff, etc.',
+ 'Goals_OverallRevenue' => '%s Gesamteinnahmen',
+ 'Goals_OverallConversionRate' => '%s Gesamtumsatz (Besuch mit einem abgeschlossenen Ziel)',
+ 'Goals_Conversions' => '%s Umsätze',
+ 'Goals_ConversionRate' => 'Konversionsrate',
+ 'Goals_NoGoalsNeedAccess' => 'Nur ein Administrator kann eine Ziel zu einer Webseite hinzufügen. Bitte fragen Sie Ihren Administrator um ein Ziel für die Webseite zu definieren. <br />Ziele zu erstellen unterstützt Sie beim der Verbesserung Ihrer Webseite',
+ 'Goals_AddNewGoal' => 'Ein neues Ziel definieren.',
+ 'Goals_AddNewGoalOrEditExistingGoal' => '%s Eine neues Ziel definieren%s oder ein existierendes Ziel %sbearbeiten%s',
+ 'Goals_AddGoal_js' => 'Ziel definieren',
+ 'Goals_UpdateGoal_js' => 'Ziel aktualisieren',
+ 'Goals_DeleteGoalConfirm_js' => 'Wollen Sie dieses Ziel wirklich löschen?',
+ 'Goals_GoalName' => 'Name',
+ 'Goals_GoalIsTriggered' => 'Ziel wurde betrachtet',
+ 'Goals_GoalIsTriggeredWhen' => 'Ziel wurde betrachtet als',
+ 'Goals_WhenVisitors' => 'der Besucher',
+ 'Goals_Manually' => 'manuell',
+ 'Goals_ManuallyTriggeredUsingJavascriptFunction' => 'Ziel wurde manuell über die Javascript API trackGoal() angestoßen',
+ 'Goals_VisitUrl' => 'Betrachten Sie ein angegebene URL (Seite oder Gruppe von Seiten)',
+ 'Goals_Download' => 'Datei herunterladen',
+ 'Goals_ClickOutlink' => 'Klicken Sie auf einen Link zur externen Webseite',
+ 'Goals_Optional' => '(optional)',
+ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => 'wo die besuchte Seiten einen Aufruf der Javascript piwikTracker.trackGoal() - Methode enthält ($sweitere Informationen%s)',
+ 'Goals_DefaultRevenue' => 'Standardeinkommen des Ziel ist',
+ 'Goals_DefaultRevenueHelp' => 'Z.B. das Absenden eine Kontaktformulars durch einen Besucher dann durchschnittlich 10 € wert sein.',
+ 'Goals_ConversionsOverview' => 'Umsatzüberblick',
+ 'Goals_BestCountries' => 'Beste Umsätze nach Länder:',
+ 'Goals_BestKeywords' => 'Beste Umsätze nach Suchbegriffen:',
+ 'Goals_BestReferers' => 'Beste Umsätze nach verweisenden Webseiten:',
+ 'Goals_ReturningVisitorsConversionRateIs' => 'Umsätze pro wiederkehrenden Besuchern: %s',
+ 'Goals_NewVisitorsConversionRateIs' => 'Umsätze pro neuem Besucher: %s',
+ 'Goals_Contains' => 'beinhaltet %s',
+ 'Goals_IsExactly' => 'ist genau %s',
+ 'Goals_MatchesExpression' => 'entspricht dem Ausdruck %s',
+ 'Goals_CaseSensitive' => 'Genauer Vergleich',
+ 'Goals_Pattern' => 'Muster',
+ 'Installation_Installation' => 'Installation',
+ 'Installation_InstallationStatus' => 'Installationstatus',
+ 'Installation_PercentDone' => '%s %% Fertig',
+ 'Installation_NoConfigFound' => 'Die Piwik-Konfigurationsdatei konnte nicht gefunden werden und es wird versucht, eine Piwik-Seite aufzurufen.<br /><b>&nbsp;&nbsp;&raquo; Sie können <a href=\'index.php\'>Piwik jetzt installieren</a></b><br /><small>Wenn Sie Piwik zuvor schon installiert haben und noch Tabellen in der Datenbank vorhanden sind: Keine Angst, Sie können diese Tabellen und die enthaltenen Daten weiterhin verwenden!</small>',
+ 'Installation_MysqlSetup' => 'MySQL Datenbanksetup',
+ 'Installation_MysqlErrorConnect' => 'Fehler beim Verbindungsaufbau zum Datenbankserver',
+ 'Installation_JsTag' => 'Javascript tag',
+ 'Installation_JsTagHelp' => '<p>Um alle Besucher zählen zu können, muss der Javascript-Code auf jeder Seite eingebaut werden.</p><p>Es muss sich nicht um eine PHP-Seite handeln, da Piwik auch mit HTML, ASP, Perl, etc. funktioniert.</p><p>Hier ist der Code, welcher eingefügt werden muss (Copy & Paste): </p>',
+ 'Installation_Congratulations' => 'Glückwunsch',
+ 'Installation_CongratulationsHelp' => '<p>Glückwunsch! Piwik ist nun installiert.</p><p>Stellen Sie sicher, dass der Javascript-Code auf Ihrer Website eingefügt wurde und warten Sie auf die ersten Besucher.</p>',
+ 'Installation_ContinueToPiwik' => 'Weiter zu Piwik',
+ 'Installation_SetupWebsite' => 'Webseite hinzufügen',
+ 'Installation_SetupWebsiteError' => 'Fehler beim Hinzufügen der Webseite',
+ 'Installation_GeneralSetup' => 'Grundeinstellungen',
+ 'Installation_GeneralSetupSuccess' => 'Grundeinstellungen wurden erfolgreich durchgeführt!',
+ 'Installation_SuperUserLogin' => 'Super-Benutzer Login',
+ 'Installation_Password' => 'Passwort',
+ 'Installation_PasswordRepeat' => 'Passwort (wiederholen)',
+ 'Installation_Email' => 'E-Mail',
+ 'Installation_SecurityNewsletter' => 'Senden Sie mir wichtige Updates von Piwik und Sicherheitswarnungen per E-Mail',
+ 'Installation_CommunityNewsletter' => 'Senden Sie mir Community-Updates (neue Plugins, neue Funktionen usw.) per E-Mail',
+ 'Installation_PasswordDoNotMatch' => 'Passwörter stimmen nicht überein',
+ 'Installation_SubmitGo' => 'Los!',
+ 'Installation_SystemCheck' => 'Systemprüfung',
+ 'Installation_SystemCheckPhp' => 'PHP-Version',
+ 'Installation_SystemCheckPdo' => 'PDO Erweiterung',
+ 'Installation_SystemCheckPdoMysql' => 'PDO_Mysql Erweiterung',
+ 'Installation_SystemCheckPdoError' => 'Sie müssen die PDO- und PDO_MySQL - Erweiterungen in der php.ini aktivieren.',
+ 'Installation_SystemCheckPdoHelp' => 'On a windows server you can add the following lines in your php.ini %s <br /><br />On a Linux server you can compile php with the following option %s In your php.ini, add the following lines %s<br /><br />More information on the <a style="color:red" href="http://php.net/pdo">PHP website</a>.',
+ 'Installation_SystemCheckWriteDirs' => 'Verzeichnisse mit Schreibzugriff',
+ 'Installation_SystemCheckWriteDirsHelp' => 'Um diesen Fehler im Linux-System zu beheben, versuchen Sie den/die folgenden Befehl(e) einzugeben',
+ 'Installation_SystemCheckMemoryLimit' => 'Speicherlimit',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'Auf einer stark frequentierten Webseite könnte es passieren, dass die Archivierung mehr Speicher erfordert als erlaubt. Wenn erforderlich, ändern Sie den memory_limit Wert in ihrer php.ini Datei.',
+ 'Installation_SystemCheckGD' => 'GD &gt; 2.x (graphics)',
+ 'Installation_SystemCheckGDHelp' => 'Die Textgraphiken (kleine Graphiken) werden nicht funktionieren.',
+ 'Installation_SystemCheckTimeLimit' => 'set_time_limit() erlaubt',
+ 'Installation_SystemCheckTimeLimitHelp' => 'Auf einer stark frequentierten Webseite könnte es passieren, dass die Archivierung mehr Zeit erfordert als erlaubt. Falls erforderlich ändern Sie den max_execution_time Wert in ihrer php.ini Datei.',
+ 'Installation_SystemCheckMail' => 'mail() erlaubt',
+ 'Installation_SystemCheckError' => 'Ein Fehler ist aufgetreten - dieser sollte behoben werden bevor Sie weiter machen können.',
+ 'Installation_SystemCheckWarning' => 'Piwik wird funktionieren aber einige Funktionen werden fehlen',
+ 'Installation_Tables' => 'Erstelle die Tabellen',
+ 'Installation_TablesWithSameNamesFound' => 'Einige %s Tabellen in Ihrer %s Datenbank haben dieselben Namen wie die Tabellen, die Piwik versucht zu erstellen',
+ 'Installation_TablesFound' => 'Die folgenden Tabellen wurden in der Datenbank gefunden',
+ 'Installation_TablesWarningHelp' => 'Entweder wählen Sie der Verwendung der existierenden Datenbanktabellen oder wählen Sie eine leere Installation um die existierenden Daten zu löschen.',
+ 'Installation_TablesReuse' => 'Benutze die vorhandenen Tabellen',
+ 'Installation_TablesDelete' => 'Entferne die erkannten Tabellen',
+ 'Installation_TablesDeletedSuccess' => 'Vorhandene Piwiktabellen wurden entfernt',
+ 'Installation_TablesCreatedSuccess' => 'Die Tabellen wurden erfolgreich erzeugt!',
+ 'Installation_DatabaseCreatedSuccess' => 'Datenbank %s erfolgreich erstellt!',
+ 'Installation_GoBackAndDefinePrefix' => 'Zurückgehen und einen Präfix für die Piwik-Tabellen definieren',
+ 'Installation_ConfirmDeleteExistingTables' => 'Sicher, dass die Tabellen: %s aus der Datenbank gelöscht werden sollen? WARNUNG: DATEN AUS DIESEN TABELLEN KÖNNEN NICHT WIEDERHERGESTELLT WERDEN!',
+ 'Installation_Welcome' => 'Willkommen!',
+ 'Installation_WelcomeHelp' => '<p>Piwik ist eine freiverfügbare Analyse-Software um einfach Informationen über die Besucher Ihrer Webseite zu erhalten.</p><p>Der Prozess teilt sich in %s einfache Schritte und wird rund 5 Minuten dauern.</p>',
+ 'Installation_ErrorInvalidState' => 'Fehler: Sie scheinen zu versuchen, einen Schritt des Installationsvorgangs zu überspringen oder Ihre Cookies sind deaktiviert, oder die Piwik-Konfigurationsdatei wurde bereits erstellt. %sStellen Sie sicher, dass Ihre Cookies aktiviert%s sind und gehen Sie zurück %s zur ersten Seite der Installation. %s',
+ 'Installation_PluginDescription' => 'Installationsprozess. Die Installation wird einmalig durchgeführt. Wenn die Konfigurationsdaten (config/config.php) gelöscht wird, dann startet die Installation erneut.',
+ 'Installation_DatabaseSetup' => 'Datenbank einrichten',
+ 'Installation_DatabaseSetupServer' => 'Datenbankserver',
+ 'Installation_DatabaseSetupLogin' => 'Benutzer',
+ 'Installation_DatabaseSetupPassword' => 'Passwort',
+ 'Installation_DatabaseSetupDatabaseName' => 'Datenbankname',
+ 'Installation_DatabaseSetupTablePrefix' => 'Tabellenprefix',
+ 'Installation_DatabaseSetupAdapter' => 'Adapter',
+ 'Installation_DatabaseErrorConnect' => 'Fehler beim Verbindungsaufbau zur Datenbank',
+ 'Installation_DatabaseCheck' => 'Datenbankkontrolle',
+ 'Installation_DatabaseServerVersion' => 'Version des Datenbankserver',
+ 'Installation_DatabaseClientVersion' => 'Version der Datenbank',
+ 'Installation_DatabaseCreation' => 'Erzeuge Datenbank',
+ 'Installation_DatabaseClientCharset' => 'Zeichensatz der Datenbank ',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'Die Verbindung wird standardmäßig nicht auf UTF8 gesetzt. Die ist nicht tragisch: <b>Piwik sollte ordnungsgemäß arbeiten</b>. Trotzdem sollten Sie die folgenden Dinge tun: <ul style="list-style: disc;margin-left:10px"><li>fügen Sie die Zeile <code>charset = utf8</code> im Abschnitt [database] in Konfigurationsdatei <code>config/config.ini.php</code>ein</li><li>übersetzen Sie libmysql mit dem Parameter --with-charset=utf8</li></ul>',
+ 'Installation_DatabaseTimezone' => 'Zeitzone der Datenbank',
+ 'Installation_TimezoneMismatch' => 'PHP date.timezone ist nicht identisch mit der Datenbank. Dadurch könnte es passieren, dass die Auswertungen der Stunden eines Tages nicht passen. Weitere Informationen unter %s',
+ 'Installation_JsTagHelpTitle' => 'Wie wird der Tag in die Webseite eingefügt?',
+ 'Installation_LargePiwikInstances' => 'Hilfe für große Installationen',
+ 'Installation_JsTagArchivingHelp' => 'Für mittelgroße und große Webseite, beachten Sie die Hinweise unter: <a target="_blank" href="http://de.piwik.org/dokumentation/wie-wird-die-nachtliche-auto-archivierung-der-berichte-konfiguriert/">Wie wird die nächtliche Auto-Archivierung der Berichte konfiguriert?</a> um Piwik schnell zu machen!',
+ 'Installation_SetupWebSiteName' => 'Name der Webseite',
+ 'Installation_SetupWebSiteURL' => 'URL der Webseite',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Webseite %s erfolgreich angelegt!',
+ 'Installation_Requirements' => 'Anforderungen',
+ 'Installation_Optional' => 'Optional',
+ 'Installation_Legend' => 'Legende',
+ 'Installation_Extension' => 'Erweiterung',
+ 'Installation_SystemCheckExtensions' => 'Weitere erforderliche Anforderungen',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik erfordert entweder die mysqli Erweiterung oder die PDO und pdo_mysql Erweiterung.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'Auf einem Linux Server können Sie PHP mit den folgenden Optionen übersetzen: %1$s Fügen Sie in Ihrer php.ini die Zeile: %2$a ein',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Weitere Informationen unter: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> und <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'Auf einem Windows-Server können Sie die folgenden Zeile in Ihre php.ini einfügen: %s',
+ 'Installation_SystemCheckSplHelp' => 'Sie müssen PHP konfigurieren und neu übersetzen mit der Standard PHP Bibliothek (SPL) aktiviert (standardmäßig).',
+ 'Installation_SystemCheckZlibHelp' => 'Sie müssen PHP mit "zlib" Unterstützung konfigurieren und neu übersetzen, --with-zlib.',
+ 'Installation_SystemCheckIconvHelp' => 'Sie müssen PHP mit "iconv" Unterstützung konfigurieren und neu übersetzen, --with-iconv.',
+ 'Installation_SystemCheckDomHelp' => 'DOM ist Teil von PHP. Sie müssen evtl. das DOM Modul, z.B. php-5-dom installieren.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'Sie müssen PHP entweder mit "json" oder "xml" Erweiterung konfigurieren und neu übersetzen.',
+ 'Installation_SystemCheckJsonSite' => 'Weitere Informationen unter: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Einige externe Plugins und Entwicklerversionen erfordern eventuell die "xml" Erweiterung.',
+ 'Installation_SystemCheckXmlSite' => 'Weitere Informationen unter: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckOpenURL' => 'URL',
+ 'Installation_SystemCheckOpenURLHelp' => 'Eintragen in den Newsletter, Aktualisierungshinweise, und Ein-Klick-Aktualisierungen erfordern die "curl" Erweiterung, allow_url_fopen=On und fsockopen() aktiviert.',
+ 'Installation_SystemCheckFunctions' => 'Erforderliche Funktionen',
+ 'Installation_SystemCheckMailHelp' => 'Feedback und Passwort verloren Nachrichten können nicht ohne mail() versendet werden.',
+ 'Installation_SystemCheckParseIniFileHelp' => 'Diese Funktion wird von Ihrem System nicht unterstützt. Piwik wird versuchen diese Funktion nach zu ahmen, aber es könnte sein, dass daduruch Sicherheitseinstellungen gelockert werden müssen. Die Geschwindigkeit des Tracker könnte auch beeinflußt werden.',
+ 'Installation_SystemCheckDebugBacktraceHelp' => 'View::factory wird nicht in der Lage sein die Module für die Anzeige zu laden.',
+ 'Installation_SystemCheckCreateFunctionHelp' => 'Piwik verwendet anonyme Funktionen für Rückfragen.',
+ 'Installation_SystemCheckMbstring' => 'mbstring',
+ 'Installation_SystemCheckMbstringHelp' => 'Sie sollten mbstring.func_overload auf "0" setzen.',
+ 'Installation_SystemCheckFileIntegrity' => 'Dateiintegrität',
+ 'Installation_SystemCheckProtocol' => 'Protokoll',
+ 'Installation_SystemCheckProtocolHelp' => 'Wenn Sie hinter einen Reverse Proxy sind, fügen Sie die folgenden Zeilen in ihre config/config.ini.php Datei in den [General] Abschnitt:',
+ 'Installation_SystemCheckIpv4' => 'IPv4',
+ 'Installation_SystemCheckIpv4Help' => 'Sie sollten IPv6 in Ihrer Webserverkonfiguration deaktivieren',
+ 'Installation_ConfigurationHelp' => 'Ihre Konfigurationsdatei enthält Fehler. Sie können entweder die config/config.php löschen und neu installieren, oder korrigieren die Einstellung zur Datenbankverbindung.',
+ 'LanguagesManager_PluginDescription' => 'Dieses Plugin zeigt eine Liste aller verfügbaren Sprachen für die Oberfläche. Die ausgewählte Sprache wird in den Benutzereinstellungen gespeichert.',
+ 'Live_PluginDescription' => 'Spion auf Ihrer Webseite, live und in Echtzeit können Sie die Besucher auf Ihrer Webseite beobachten ',
+ 'Live_VisitorLog' => 'Besucher',
+ 'Live_Date' => 'Datum',
+ 'Live_Time' => 'Zeit',
+ 'Live_Referrer_URL' => 'Herkunftsseite',
+ 'Login_LoginPasswordNotCorrect' => 'Benutzername und Passwort sind nicht korrekt',
+ 'Login_Login' => 'Benutzername',
+ 'Login_Password' => 'Passwort',
+ 'Login_LoginOrEmail' => 'Login oder E-Mail',
+ 'Login_LogIn' => 'Anmelden',
+ 'Login_Logout' => 'Abmelden',
+ 'Login_LostYourPassword' => 'Passwort verloren?',
+ 'Login_RemindPassword' => 'An das Passwort erinnern?',
+ 'Login_PasswordReminder' => 'Benutzername oder E-Mail-Adresse eingeben um ein neues Passwort per E-Mail zu erhalten.',
+ 'Login_InvalidUsernameEmail' => 'Ungültiger Bernutzername und/oder E-Mail-Adresse',
+ 'Login_MailTopicPasswordRecovery' => 'Passwort wiederherstellen',
+ 'Login_PasswordSent' => 'Das Passwort wurde gesendet. Bitte Postfach auf neue E-Mails überprüfen.',
+ 'Login_ContactAdmin' => 'Möglicher Grund: Der Server könnte die mail()-Funktion abgeschaltet haben.<br/>Bitte sprechen Sie mit Ihrem Piwik-Administrator.',
+ 'Login_PluginDescription' => 'Plugin für die Anmeldung. Die Daten werden dabei aus der Konfigurationsdatei für den Administrator und für die anderen Benutzer aus der Datenbank ausgelesen. ',
+ 'Login_PasswordRepeat' => 'Passwortwiederholung',
+ 'Login_ChangePassword' => 'Passwort ändern',
+ 'Login_PasswordResetToken' => 'Token um das Passwort zu ändern.',
+ 'Login_PasswordsDoNotMatch' => 'Passwörter stimmen nicht überein.',
+ 'Login_PasswordSuccessfullyChanged' => 'Passwort erfolgreich geändert.',
+ 'Login_InvalidOrExpiredToken' => 'Token ist nicht mehr gültig.',
+ 'Login_MailPasswordRecoveryBody' => 'Hi %1$s, eine Anfrage für ein Passwort wurde von %2$s gestellt. <br/>Um das Passwort zu ändern: <br/>1) Gehen Sie zum Formular um das Passwort neuzusetzen: %3$s <br/>2) Geben Sie den folgenden Token ein: %4$s <br/>3)Füllen Sie das Formular aus (das neue Passwort muss zweimal eingegeben werden) und speichern es ab. <br/><br/>Hinweis: Der Token wird in den nächsten 24 Stunden ungültig.',
+ 'MultiSites_PluginDescription' => 'Zeigt kurze Informationen über alle Webseiten/Statistiken.',
+ 'Provider_WidgetProviders' => 'Provider',
+ 'Provider_ColumnProvider' => 'Anbieter',
+ 'Provider_SubmenuLocationsProvider' => 'Standorte und Provider',
+ 'Provider_PluginDescription' => 'Stellt Informationen über den Provider des Besuchers dar.',
+ 'Referers_Referers' => 'Verweise',
+ 'Referers_SearchEngines' => 'Suchmaschinen',
+ 'Referers_Keywords' => 'Suchbegriffe',
+ 'Referers_DirectEntry' => 'Direkte Zugriffe',
+ 'Referers_Websites' => 'Webseiten',
+ 'Referers_Campaigns' => 'Kampagnen',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%1s (von %2s)',
+ 'Referers_Evolution' => 'Entwicklung über den Zeitraum',
+ 'Referers_Type' => 'Verweisart',
+ 'Referers_ColumnRefererType' => 'Referer Type',
+ 'Referers_ColumnSearchEngine' => 'Suchmaschine',
+ 'Referers_ColumnWebsite' => 'Website',
+ 'Referers_ColumnWebsitePage' => 'Webseiten-Seite',
+ 'Referers_ColumnKeyword' => 'Stichwort',
+ 'Referers_ColumnCampaign' => 'Kampagne',
+ 'Referers_DetailsByRefererType' => 'Details nach Verweisart',
+ 'Referers_TypeDirectEntries' => '%s direkte Zugriffe',
+ 'Referers_TypeSearchEngines' => '%s von Suchmaschinen',
+ 'Referers_TypeWebsites' => '%s von Webseiten',
+ 'Referers_TypeCampaigns' => '%s von Kampagnen',
+ 'Referers_Distinct' => 'Vermittler nach Verweisart unterscheiden',
+ 'Referers_DistinctSearchEngines' => 'Suchmaschinen unterscheiden',
+ 'Referers_DistinctKeywords' => 'Stichwörter unterscheiden',
+ 'Referers_DistinctCampaigns' => 'Kampagnen unterscheiden',
+ 'Referers_DistinctWebsites' => 'Webseiten unterscheiden',
+ 'Referers_UsingNDistinctUrls' => '(%s zum URL unterscheiden werden verwendet)',
+ 'Referers_SubmenuEvolution' => 'Entwicklung',
+ 'Referers_SubmenuSearchEngines' => 'Suchmaschinen und Suchbegriffe',
+ 'Referers_SubmenuWebsites' => 'Webseiten',
+ 'Referers_SubmenuCampaigns' => 'Kampagnen',
+ 'Referers_WidgetKeywords' => 'Liste der Suchbegriffe',
+ 'Referers_WidgetCampaigns' => 'Liste der Kampagnen',
+ 'Referers_WidgetExternalWebsites' => 'Liste externer Webseiten',
+ 'Referers_WidgetSearchEngines' => 'Beste Suchmaschinen',
+ 'Referers_WidgetOverview' => 'Übersicht',
+ 'Referers_PluginDescription' => 'Zeigt Informationen über die Herkunft: Suchmaschinen, Suchbegriffe, Webseiten, Kampagnen, direkte Seitenaufrufe.',
+ 'SecurityInfo_PluginDescription' => 'Basierend auf PhpSecInfo vom PHP Sicherheitskonsortium, dieses Plugin zeigt Sicherheitsinformationen über die PHP Umgebung an und bietet Vorschläge zur Verbesserung. ',
+ 'SecurityInfo_Security' => 'Sicherheit',
+ 'SecurityInfo_SecurityInformation' => 'PHP Sicherheitsinformationen',
+ 'SecurityInfo_Test' => 'Test',
+ 'SecurityInfo_Result' => 'Ergebnis',
+ 'SitesManager_Sites' => 'Seiten',
+ 'SitesManager_WebsitesManagement' => 'Webseitenverwaltung',
+ 'SitesManager_MainDescription' => 'Die Web-Analyse benötigt Webseiten! Webseiten können hinzugefügt, aktualisiert und gelöscht werden. Hier wird auch der JavaScript-Code gezeigt, der einer Webseite hinzugefügt werden muss.',
+ 'SitesManager_JsCode' => 'JavaScript-Code',
+ 'SitesManager_JsCodeHelp' => 'Dies ist der JavaScript-Code, der in alle Seiten eingepflegt werden muss.',
+ 'SitesManager_ShowJsCode' => 'Code darstellen',
+ 'SitesManager_NoWebsites' => 'Keine Webseite zum Administrieren vorhanden.',
+ 'SitesManager_AddSite' => 'Neue Webseite hinzufügen',
+ 'SitesManager_Id' => 'Id',
+ 'SitesManager_Name' => 'Name',
+ 'SitesManager_Urls' => 'URLs',
+ 'SitesManager_MenuSites' => 'Webseiten',
+ 'SitesManager_DeleteConfirm_js' => 'Soll die Webseite %s wirklich gelöscht werden?',
+ 'SitesManager_ExceptionDeleteSite' => 'Diese Webseite kann nicht gelöscht werden, da sie die einzige registrierte Webseite ist. Bitte zunächst eine weitere Webseite hinzufügen, dann kann die erste gelöscht werden.',
+ 'SitesManager_ExceptionNoUrl' => 'Es muss mindestens eine URL für diese Webseite angegeben werden.',
+ 'SitesManager_ExceptionEmptyName' => 'Der Webseitenname kann nicht leer sein.',
+ 'SitesManager_ExceptionInvalidUrl' => 'Die Adresse \'%s\' ist kein gültiger URL.',
+ 'SitesManager_PluginDescription' => 'Webseitenverwaltung: Webseite hinzufügen, Webseite editieren, JavaScript Code anzeigen. Alle Aktionen sind auch über die API steuerbar.',
+ 'SitesManager_JsTrackingTag' => 'JavaScript Tracking Code',
+ 'SitesManager_JsTrackingTagHelp' => 'Hier ist der JavaScript Code zum Tracken. Bitte fügen Sie diesen in all ihre Seiten ein.',
+ 'SitesManager_ShowTrackingTag' => 'Tracking Code anzeigen',
+ 'SitesManager_AliasUrlHelp' => 'Wir empfehlen, dass sie alle URLs ihrer Webseite über die Besucher kommen können, hier angeben. Alias URLs werden dann nicht in als Weiterleitungen aufgeführt. Beachten Sie bitte, dass es nicht erforderlich ist, URL mit und ohne "www" anzugeben, da dies automatisch beachtet wird.',
+ 'TranslationsAdmin_MenuTranslations' => 'Übersetzungen',
+ 'TranslationsAdmin_MenuLanguages' => 'Sprachen',
+ 'TranslationsAdmin_Plugin' => 'Plugin',
+ 'TranslationsAdmin_Definition' => 'Definition',
+ 'TranslationsAdmin_DefaultString' => 'Vorgabetext (Englisch)',
+ 'TranslationsAdmin_TranslationString' => 'Übersetzter Text (aktuelle Sprache: %s)',
+ 'TranslationsAdmin_Translations' => 'Übersetzungen',
+ 'TranslationsAdmin_FixPermissions' => 'Bitte folgende Dateiberechtigungen korrigieren',
+ 'TranslationsAdmin_AvailableLanguages' => 'Verfügbare Sprachen',
+ 'TranslationsAdmin_AddLanguage' => 'Sprache hinzufügen',
+ 'TranslationsAdmin_LanguageCode' => 'Sprach-Code',
+ 'TranslationsAdmin_Export' => 'Sprache exportieren',
+ 'TranslationsAdmin_Import' => 'Sprache importieren',
+ 'TranslationsAdmin_PluginDescription' => 'Plugin um Piwik in Ihrer Sprache zu übersetzen.',
+ 'UserCountry_Country' => 'Land',
+ 'UserCountry_Continent' => 'Kontinent',
+ 'UserCountry_DistinctCountries' => '%s unterschiedliche Länder',
+ 'UserCountry_SubmenuLocations' => 'Ort',
+ 'UserCountry_WidgetContinents' => 'Besucherkontinente',
+ 'UserCountry_WidgetCountries' => 'Besucherländer',
+ 'UserCountry_country_ac' => 'Ascension',
+ 'UserCountry_country_ad' => 'Andorra',
+ 'UserCountry_country_ae' => 'Vereinigte Arabische Emirate',
+ 'UserCountry_country_af' => 'Afghanistan',
+ 'UserCountry_country_ag' => 'Antigua und Barbuda',
+ 'UserCountry_country_ai' => 'Anguilla',
+ 'UserCountry_country_al' => 'Albanien',
+ 'UserCountry_country_am' => 'Armenien',
+ 'UserCountry_country_an' => 'Niederländische Antillen',
+ 'UserCountry_country_ao' => 'Angola',
+ 'UserCountry_country_aq' => 'Antarktis',
+ 'UserCountry_country_ar' => 'Argentinien',
+ 'UserCountry_country_as' => 'Amerikanisch Samoa',
+ 'UserCountry_country_at' => 'Österreich',
+ 'UserCountry_country_au' => 'Australien',
+ 'UserCountry_country_aw' => 'Aruba',
+ 'UserCountry_country_ax' => 'Aland-Inseln',
+ 'UserCountry_country_az' => 'Aserbajdschan',
+ 'UserCountry_country_ba' => 'Bosnien und Herzegovina',
+ 'UserCountry_country_bb' => 'Barbados',
+ 'UserCountry_country_bd' => 'Bangladesch',
+ 'UserCountry_country_be' => 'Belgien',
+ 'UserCountry_country_bf' => 'Burkina Faso',
+ 'UserCountry_country_bg' => 'Bulgarien',
+ 'UserCountry_country_bh' => 'Bahrain',
+ 'UserCountry_country_bi' => 'Burundi',
+ 'UserCountry_country_bj' => 'Benin',
+ 'UserCountry_country_bl' => 'Sankt Bartholomäus',
+ 'UserCountry_country_bm' => 'Bermuda',
+ 'UserCountry_country_bn' => 'Bruneo',
+ 'UserCountry_country_bo' => 'Bolivien',
+ 'UserCountry_country_br' => 'Brasilien',
+ 'UserCountry_country_bs' => 'Bahamas',
+ 'UserCountry_country_bt' => 'Bhutan',
+ 'UserCountry_country_bu' => 'Birma',
+ 'UserCountry_country_bv' => 'Bouvetinsel',
+ 'UserCountry_country_bw' => 'Botsuana',
+ 'UserCountry_country_by' => 'Weissrussland',
+ 'UserCountry_country_bz' => 'Belize',
+ 'UserCountry_country_ca' => 'Kanada',
+ 'UserCountry_country_cc' => 'Cocos Islands',
+ 'UserCountry_country_cd' => 'Demokratische Republik Kongo',
+ 'UserCountry_country_cf' => 'Zentralafrikanische Republik ',
+ 'UserCountry_country_cg' => 'Kongo',
+ 'UserCountry_country_ch' => 'Schweiz',
+ 'UserCountry_country_ci' => 'Elfenbeinküste',
+ 'UserCountry_country_ck' => 'Cook-Inseln',
+ 'UserCountry_country_cl' => 'Chile',
+ 'UserCountry_country_cm' => 'Kamerun',
+ 'UserCountry_country_cn' => 'China',
+ 'UserCountry_country_co' => 'Kolumbien',
+ 'UserCountry_country_cp' => 'Clipperton-Insel',
+ 'UserCountry_country_cr' => 'Costa Rica',
+ 'UserCountry_country_cs' => 'Serbien Montenegro',
+ 'UserCountry_country_cu' => 'Cuba',
+ 'UserCountry_country_cv' => 'Kap Verde',
+ 'UserCountry_country_cx' => 'Weihnachtsinsel',
+ 'UserCountry_country_cy' => 'Zypern',
+ 'UserCountry_country_cz' => 'Tschechische Republik',
+ 'UserCountry_country_de' => 'Deutschland',
+ 'UserCountry_country_dg' => 'Diego Garcia',
+ 'UserCountry_country_dj' => 'Djibuti',
+ 'UserCountry_country_dk' => 'Dänemark',
+ 'UserCountry_country_dm' => 'Dominica',
+ 'UserCountry_country_do' => 'Dominikanische Republik',
+ 'UserCountry_country_dz' => 'Algerien',
+ 'UserCountry_country_ea' => 'Ceuta, Melilla',
+ 'UserCountry_country_ec' => 'Equador',
+ 'UserCountry_country_ee' => 'Estland',
+ 'UserCountry_country_eg' => 'Ägypten',
+ 'UserCountry_country_eh' => 'Westsahara',
+ 'UserCountry_country_er' => 'Eritrea',
+ 'UserCountry_country_es' => 'Spanien',
+ 'UserCountry_country_et' => 'Äthiopien',
+ 'UserCountry_country_eu' => 'Europäische Union',
+ 'UserCountry_country_fi' => 'Finnland',
+ 'UserCountry_country_fj' => 'Fiji Inseln',
+ 'UserCountry_country_fk' => 'Falklandinseln',
+ 'UserCountry_country_fm' => 'Mikronesien',
+ 'UserCountry_country_fo' => 'Färöer',
+ 'UserCountry_country_fr' => 'Frankreich',
+ 'UserCountry_country_fx' => 'Frankreich, Metropolitanisch',
+ 'UserCountry_country_ga' => 'Gabun',
+ 'UserCountry_country_gb' => 'Grossbritannien',
+ 'UserCountry_country_gd' => 'Grenada',
+ 'UserCountry_country_ge' => 'Georgien',
+ 'UserCountry_country_gf' => 'Französisch-Guayana',
+ 'UserCountry_country_gg' => 'Kanalinseln (Guernsey)',
+ 'UserCountry_country_gh' => 'Ghana',
+ 'UserCountry_country_gi' => 'Gibraltar',
+ 'UserCountry_country_gl' => 'Grönland',
+ 'UserCountry_country_gm' => 'Gambia',
+ 'UserCountry_country_gn' => 'Guinea',
+ 'UserCountry_country_gp' => 'Guadeloupe',
+ 'UserCountry_country_gq' => 'Äquatorialguinea',
+ 'UserCountry_country_gr' => 'Griechenland',
+ 'UserCountry_country_gs' => 'Südgeorgien/Süd-Sandwich-Inseln',
+ 'UserCountry_country_gt' => 'Guatemala',
+ 'UserCountry_country_gu' => 'Guam',
+ 'UserCountry_country_gw' => 'Guinea-Bissau',
+ 'UserCountry_country_gy' => 'Guyana',
+ 'UserCountry_country_hk' => 'Hong Kong',
+ 'UserCountry_country_hm' => 'Heard und McDonaldinseln',
+ 'UserCountry_country_hn' => 'Honduras',
+ 'UserCountry_country_hr' => 'Kroatien',
+ 'UserCountry_country_ht' => 'Haiti',
+ 'UserCountry_country_hu' => 'Ungarn',
+ 'UserCountry_country_ic' => 'Kanarische Inseln',
+ 'UserCountry_country_id' => 'Indonesien',
+ 'UserCountry_country_ie' => 'Irland',
+ 'UserCountry_country_il' => 'Israel',
+ 'UserCountry_country_im' => 'Insel Man',
+ 'UserCountry_country_in' => 'Indien',
+ 'UserCountry_country_io' => 'Chagos-Archipel',
+ 'UserCountry_country_iq' => 'Irak',
+ 'UserCountry_country_ir' => 'Iran',
+ 'UserCountry_country_is' => 'Island',
+ 'UserCountry_country_it' => 'Italien',
+ 'UserCountry_country_je' => 'Kanalinseln (Jersey)',
+ 'UserCountry_country_jm' => 'Jamaika',
+ 'UserCountry_country_jo' => 'Jordanien',
+ 'UserCountry_country_jp' => 'Japan',
+ 'UserCountry_country_ke' => 'Kenia',
+ 'UserCountry_country_kg' => 'Kirgistan',
+ 'UserCountry_country_kh' => 'Kambodscha',
+ 'UserCountry_country_ki' => 'Kiribati',
+ 'UserCountry_country_km' => 'Komoren',
+ 'UserCountry_country_kn' => 'St. Kitts and Nevis',
+ 'UserCountry_country_kp' => 'Korea (Nord)',
+ 'UserCountry_country_kr' => 'Korea (Süd)',
+ 'UserCountry_country_kw' => 'Kuwait',
+ 'UserCountry_country_ky' => 'Kaimaninseln',
+ 'UserCountry_country_kz' => 'Kasachstan',
+ 'UserCountry_country_la' => 'Laos',
+ 'UserCountry_country_lb' => 'Libanon',
+ 'UserCountry_country_lc' => 'St. Lucia',
+ 'UserCountry_country_li' => 'Liechtenstein',
+ 'UserCountry_country_lk' => 'Sri Lanka',
+ 'UserCountry_country_lr' => 'Liberia',
+ 'UserCountry_country_ls' => 'Lesotho',
+ 'UserCountry_country_lt' => 'Litauen',
+ 'UserCountry_country_lu' => 'Luxemburg',
+ 'UserCountry_country_lv' => 'Lettland',
+ 'UserCountry_country_ly' => 'Libysch-Arabische Dschamahirija',
+ 'UserCountry_country_ma' => 'Marokko',
+ 'UserCountry_country_mc' => 'Monaco',
+ 'UserCountry_country_md' => 'Montenegro',
+ 'UserCountry_country_me' => 'Republik Moldau',
+ 'UserCountry_country_mf' => 'Sankt Martin',
+ 'UserCountry_country_mg' => 'Madagaskar',
+ 'UserCountry_country_mh' => 'Marshallinseln',
+ 'UserCountry_country_mk' => 'Mazedonien',
+ 'UserCountry_country_ml' => 'Mali',
+ 'UserCountry_country_mm' => 'Myanmar',
+ 'UserCountry_country_mn' => 'Mongolei',
+ 'UserCountry_country_mo' => 'Macao',
+ 'UserCountry_country_mp' => 'Nördliche Marianen',
+ 'UserCountry_country_mq' => 'Martinique',
+ 'UserCountry_country_mr' => 'Mauretanien',
+ 'UserCountry_country_ms' => 'Montserrat',
+ 'UserCountry_country_mt' => 'Malta',
+ 'UserCountry_country_mu' => 'Mauritius',
+ 'UserCountry_country_mv' => 'Malediven',
+ 'UserCountry_country_mw' => 'Malawi',
+ 'UserCountry_country_mx' => 'Mexiko',
+ 'UserCountry_country_my' => 'Malaysia',
+ 'UserCountry_country_mz' => 'Mosambik',
+ 'UserCountry_country_na' => 'Namibia',
+ 'UserCountry_country_nc' => 'Neukaledonien',
+ 'UserCountry_country_ne' => 'Niger',
+ 'UserCountry_country_nf' => 'Norfolkinsel',
+ 'UserCountry_country_ng' => 'Nigeria',
+ 'UserCountry_country_ni' => 'Nicaragua',
+ 'UserCountry_country_nl' => 'Niederlande',
+ 'UserCountry_country_no' => 'Norwegen',
+ 'UserCountry_country_np' => 'Nepal',
+ 'UserCountry_country_nr' => 'Nauru',
+ 'UserCountry_country_nt' => 'Neutrale Zone',
+ 'UserCountry_country_nu' => 'Niue',
+ 'UserCountry_country_nz' => 'Neuseeland',
+ 'UserCountry_country_om' => 'Oman',
+ 'UserCountry_country_pa' => 'Panama',
+ 'UserCountry_country_pe' => 'Peru',
+ 'UserCountry_country_pf' => 'Französisch-Polynesien',
+ 'UserCountry_country_pg' => 'Papua-Neuguinea',
+ 'UserCountry_country_ph' => 'Philippinen',
+ 'UserCountry_country_pk' => 'Pakistan',
+ 'UserCountry_country_pl' => 'Polen',
+ 'UserCountry_country_pm' => 'Saint-Pierre-et-Miquelon',
+ 'UserCountry_country_pn' => 'Pitcairn',
+ 'UserCountry_country_pr' => 'Puerto Rico',
+ 'UserCountry_country_ps' => 'Palästinensische Gebiete',
+ 'UserCountry_country_pt' => 'Portugal',
+ 'UserCountry_country_pw' => 'Palau',
+ 'UserCountry_country_py' => 'Paraguay',
+ 'UserCountry_country_qa' => 'Katar',
+ 'UserCountry_country_re' => 'Reunion',
+ 'UserCountry_country_ro' => 'Rumänien',
+ 'UserCountry_country_ru' => 'Russische Förderation',
+ 'UserCountry_country_rs' => 'Serbien',
+ 'UserCountry_country_rw' => 'Ruanda',
+ 'UserCountry_country_sa' => 'Saudi Arabien',
+ 'UserCountry_country_sb' => 'Salomonen',
+ 'UserCountry_country_sc' => 'Seychellen',
+ 'UserCountry_country_sd' => 'Sudan',
+ 'UserCountry_country_se' => 'Schweden',
+ 'UserCountry_country_sf' => 'Finnland',
+ 'UserCountry_country_sg' => 'Singapur',
+ 'UserCountry_country_sh' => 'St. Helena',
+ 'UserCountry_country_si' => 'Slowenien',
+ 'UserCountry_country_sj' => 'Svalbard',
+ 'UserCountry_country_sk' => 'Slowakei',
+ 'UserCountry_country_sl' => 'Sierra Leone',
+ 'UserCountry_country_sm' => 'San Marino',
+ 'UserCountry_country_sn' => 'Senegal',
+ 'UserCountry_country_so' => 'Somalia',
+ 'UserCountry_country_sr' => 'Suriname',
+ 'UserCountry_country_st' => 'São Tomé und Príncipe',
+ 'UserCountry_country_su' => 'Sowjetunion',
+ 'UserCountry_country_sv' => 'El Salvador',
+ 'UserCountry_country_sy' => 'Syrien',
+ 'UserCountry_country_sz' => 'Swaziland',
+ 'UserCountry_country_ta' => 'Tristan da Cunha',
+ 'UserCountry_country_tc' => 'Turks- und Caicosinseln',
+ 'UserCountry_country_td' => 'Tschad',
+ 'UserCountry_country_tf' => 'Französischen Süd- und Antarktisgebiete',
+ 'UserCountry_country_tg' => 'Togo',
+ 'UserCountry_country_th' => 'Thailand',
+ 'UserCountry_country_tj' => 'Tadschikistan',
+ 'UserCountry_country_tk' => 'Tokelau',
+ 'UserCountry_country_tl' => 'Osttimor',
+ 'UserCountry_country_tm' => 'Turkmenistan',
+ 'UserCountry_country_tn' => 'Tunesien',
+ 'UserCountry_country_to' => 'Tonga',
+ 'UserCountry_country_tp' => 'Osttimor',
+ 'UserCountry_country_tr' => 'Türkei',
+ 'UserCountry_country_tt' => 'Trinidad und Tobago',
+ 'UserCountry_country_tv' => 'Tuvalu',
+ 'UserCountry_country_tw' => 'Taiwan',
+ 'UserCountry_country_tz' => 'Tansania',
+ 'UserCountry_country_ua' => 'Ukraine',
+ 'UserCountry_country_ug' => 'Uganda',
+ 'UserCountry_country_uk' => 'Vereinigtes Königreich',
+ 'UserCountry_country_um' => 'Kleinere Inselbesitzungen der Vereinigten Staaten',
+ 'UserCountry_country_us' => 'USA',
+ 'UserCountry_country_uy' => 'Uruguay',
+ 'UserCountry_country_uz' => 'Usbekistan',
+ 'UserCountry_country_va' => 'Vatikan',
+ 'UserCountry_country_vc' => 'St. Vincent und die Grenadinen',
+ 'UserCountry_country_ve' => 'Venezuela',
+ 'UserCountry_country_vg' => 'Britische Jungferninseln',
+ 'UserCountry_country_vi' => 'Amerikanische Jungferninseln',
+ 'UserCountry_country_vn' => 'Vietnam',
+ 'UserCountry_country_vu' => 'Vanuatu',
+ 'UserCountry_country_wf' => 'Wallis und Futuna',
+ 'UserCountry_country_ws' => 'Samoa',
+ 'UserCountry_country_ye' => 'Jemen',
+ 'UserCountry_country_yt' => 'Mayotte',
+ 'UserCountry_country_yu' => 'Jugoslawien',
+ 'UserCountry_country_za' => 'Südafrika',
+ 'UserCountry_country_zm' => 'Sambia',
+ 'UserCountry_country_zr' => 'Demokratische Republik Kongo (ehem. Zaire)',
+ 'UserCountry_country_zw' => 'Simbabwe',
+ 'UserCountry_continent_eur' => 'Europa',
+ 'UserCountry_continent_afr' => 'Afrika',
+ 'UserCountry_continent_asi' => 'Asien',
+ 'UserCountry_continent_ams' => 'Südamerika',
+ 'UserCountry_continent_amn' => 'Nordamerika',
+ 'UserCountry_continent_oce' => 'Ozeanien',
+ 'UserCountry_PluginDescription' => 'Berichtet über das Herkunftsland Ihrer Besucher.',
+ 'UserLanguage_WidgetLanguage' => 'Besuchersprachen',
+ 'UserLanguage_SubmenuLanguage' => 'Sprachen',
+ 'UserLanguage_Language' => 'Sprachen',
+ 'UserLanguage_Language_aa' => 'Afar',
+ 'UserLanguage_Language_ab' => 'Abchasisch',
+ 'UserLanguage_Language_ae' => 'Avestisch',
+ 'UserLanguage_Language_af' => 'Afrikaans',
+ 'UserLanguage_Language_ak' => 'Akan',
+ 'UserLanguage_Language_am' => 'Amharisch',
+ 'UserLanguage_Language_an' => 'Aragonesisch',
+ 'UserLanguage_Language_ar' => 'Arabisch',
+ 'UserLanguage_Language_as' => 'Assamesisch',
+ 'UserLanguage_Language_av' => 'Awarisch',
+ 'UserLanguage_Language_ay' => 'Aymara',
+ 'UserLanguage_Language_az' => 'Aserbaidschanisch',
+ 'UserLanguage_Language_ba' => 'Baschkirisch',
+ 'UserLanguage_Language_be' => 'Weissrussisch',
+ 'UserLanguage_Language_bg' => 'Bulgarisch',
+ 'UserLanguage_Language_bh' => 'Bihari',
+ 'UserLanguage_Language_bi' => 'Bislama',
+ 'UserLanguage_Language_bm' => 'Bambara',
+ 'UserLanguage_Language_bn' => 'Bengalisch',
+ 'UserLanguage_Language_bo' => 'Tibetisch',
+ 'UserLanguage_Language_br' => 'Bretonisch',
+ 'UserLanguage_Language_bs' => 'Bosnisch',
+ 'UserLanguage_Language_ca' => 'Katalanisch',
+ 'UserLanguage_Language_ce' => 'Tschetschenisch',
+ 'UserLanguage_Language_ch' => 'Chamorro',
+ 'UserLanguage_Language_co' => 'Korsisch',
+ 'UserLanguage_Language_cr' => 'Cree',
+ 'UserLanguage_Language_cs' => 'Tschechisch',
+ 'UserLanguage_Language_cu' => 'Altkirchenslawisch',
+ 'UserLanguage_Language_cv' => 'Tschuwaschisch',
+ 'UserLanguage_Language_cy' => 'Walisisch',
+ 'UserLanguage_Language_da' => 'Dänisch',
+ 'UserLanguage_Language_de' => 'Deutsch',
+ 'UserLanguage_Language_dv' => 'Divehi',
+ 'UserLanguage_Language_dz' => 'Dzongkha',
+ 'UserLanguage_Language_ee' => 'Ewe',
+ 'UserLanguage_Language_el' => 'Griechisch',
+ 'UserLanguage_Language_en' => 'Englisch',
+ 'UserLanguage_Language_eo' => 'Esperanto',
+ 'UserLanguage_Language_es' => 'Spanisch',
+ 'UserLanguage_Language_et' => 'Estnisch',
+ 'UserLanguage_Language_eu' => 'Baskisch',
+ 'UserLanguage_Language_fa' => 'Persisch',
+ 'UserLanguage_Language_ff' => 'Fulfulde',
+ 'UserLanguage_Language_fi' => 'Finnisch',
+ 'UserLanguage_Language_fj' => 'Fidschi',
+ 'UserLanguage_Language_fo' => 'Färöisch',
+ 'UserLanguage_Language_fr' => 'Französisch',
+ 'UserLanguage_Language_fy' => 'Westfrisisch',
+ 'UserLanguage_Language_ga' => 'Irisch',
+ 'UserLanguage_Language_gd' => 'Schottisch-Gälisch',
+ 'UserLanguage_Language_gl' => 'Galicisch',
+ 'UserLanguage_Language_gn' => 'Guaraní',
+ 'UserLanguage_Language_gu' => 'Gujarati',
+ 'UserLanguage_Language_gv' => 'Manx',
+ 'UserLanguage_Language_ha' => 'Hausa',
+ 'UserLanguage_Language_he' => 'Hebräisch',
+ 'UserLanguage_Language_hi' => 'Hindi',
+ 'UserLanguage_Language_ho' => 'Hiri Motu',
+ 'UserLanguage_Language_hr' => 'Kroatisch',
+ 'UserLanguage_Language_ht' => 'Haitianisch',
+ 'UserLanguage_Language_hu' => 'Ungarisch',
+ 'UserLanguage_Language_hy' => 'Armenisch',
+ 'UserLanguage_Language_hz' => 'Otjiherero',
+ 'UserLanguage_Language_ia' => 'Interlingua',
+ 'UserLanguage_Language_id' => 'Indonesisch',
+ 'UserLanguage_Language_ie' => 'Interlingue',
+ 'UserLanguage_Language_ig' => 'Igbo',
+ 'UserLanguage_Language_ii' => 'Sichuan Yi',
+ 'UserLanguage_Language_ik' => 'Inupiaq',
+ 'UserLanguage_Language_io' => 'Ido',
+ 'UserLanguage_Language_is' => 'Isländisch',
+ 'UserLanguage_Language_it' => 'Italienisch',
+ 'UserLanguage_Language_iu' => 'Inuktitut',
+ 'UserLanguage_Language_ja' => 'Japanisch',
+ 'UserLanguage_Language_jv' => 'Javanisch',
+ 'UserLanguage_Language_ka' => 'Georgisch',
+ 'UserLanguage_Language_kg' => 'Kikongo',
+ 'UserLanguage_Language_ki' => 'Kikuyu',
+ 'UserLanguage_Language_kj' => 'Kwanyama',
+ 'UserLanguage_Language_kk' => 'Kasachisch',
+ 'UserLanguage_Language_kl' => 'Kalaallisut',
+ 'UserLanguage_Language_km' => 'Khmer',
+ 'UserLanguage_Language_kn' => 'Kannada',
+ 'UserLanguage_Language_ko' => 'Koreanisch',
+ 'UserLanguage_Language_kr' => 'Kanuri',
+ 'UserLanguage_Language_ks' => 'Kashmiri',
+ 'UserLanguage_Language_ku' => 'Kurdisch',
+ 'UserLanguage_Language_kv' => 'Komi',
+ 'UserLanguage_Language_kw' => 'Kornisch',
+ 'UserLanguage_Language_ky' => 'Kirgisisch',
+ 'UserLanguage_Language_la' => 'Latein',
+ 'UserLanguage_Language_lb' => 'Luxemburgisch',
+ 'UserLanguage_Language_lg' => 'Luganda',
+ 'UserLanguage_Language_li' => 'Limburgisch',
+ 'UserLanguage_Language_ln' => 'Lingála',
+ 'UserLanguage_Language_lo' => 'Laotisch',
+ 'UserLanguage_Language_lt' => 'Lithauisch',
+ 'UserLanguage_Language_lu' => 'Tschiluba',
+ 'UserLanguage_Language_lv' => 'Lettisch',
+ 'UserLanguage_Language_mg' => 'Malagasy',
+ 'UserLanguage_Language_mh' => 'Marshallesisch',
+ 'UserLanguage_Language_mi' => 'Maorisch',
+ 'UserLanguage_Language_mk' => 'Mazedonisch',
+ 'UserLanguage_Language_ml' => 'Malayalam',
+ 'UserLanguage_Language_mn' => 'Mongolisch',
+ 'UserLanguage_Language_mr' => 'Marathi',
+ 'UserLanguage_Language_ms' => 'Malaiisch',
+ 'UserLanguage_Language_mt' => 'Maltesisch',
+ 'UserLanguage_Language_my' => 'Burmanisch',
+ 'UserLanguage_Language_na' => 'Nauruisch',
+ 'UserLanguage_Language_nb' => 'Norwegisch Bokmål',
+ 'UserLanguage_Language_nd' => '(Nord) Ndebele',
+ 'UserLanguage_Language_ne' => 'Nepali',
+ 'UserLanguage_Language_ng' => 'Ndonga',
+ 'UserLanguage_Language_nl' => 'Niederländisch',
+ 'UserLanguage_Language_nn' => 'Norwegisch Nynorsk',
+ 'UserLanguage_Language_no' => 'Norwegisch',
+ 'UserLanguage_Language_nr' => '(Süd) Ndebele',
+ 'UserLanguage_Language_nv' => 'Navajo',
+ 'UserLanguage_Language_ny' => 'Chichewa',
+ 'UserLanguage_Language_oc' => 'Okzitanisch',
+ 'UserLanguage_Language_oj' => 'Ojibwe',
+ 'UserLanguage_Language_om' => 'Oromo',
+ 'UserLanguage_Language_or' => 'Oriya',
+ 'UserLanguage_Language_os' => 'Ossetisch',
+ 'UserLanguage_Language_pa' => 'Panjabi',
+ 'UserLanguage_Language_pi' => 'Pali',
+ 'UserLanguage_Language_pl' => 'Polnisch',
+ 'UserLanguage_Language_ps' => 'Pashtunisch',
+ 'UserLanguage_Language_pt' => 'Portugiesisch',
+ 'UserLanguage_Language_qu' => 'Quechua',
+ 'UserLanguage_Language_rm' => 'Rätoromanisch',
+ 'UserLanguage_Language_rn' => 'Kirundi',
+ 'UserLanguage_Language_ro' => 'Rumänisch',
+ 'UserLanguage_Language_ru' => 'Russisch',
+ 'UserLanguage_Language_rw' => 'Kinyarwanda',
+ 'UserLanguage_Language_sa' => 'Sanskrit',
+ 'UserLanguage_Language_sc' => 'Sardisch',
+ 'UserLanguage_Language_sd' => 'Sindhi',
+ 'UserLanguage_Language_se' => 'Nordsamisch',
+ 'UserLanguage_Language_sg' => 'Sango',
+ 'UserLanguage_Language_sh' => 'Serbokroatisch',
+ 'UserLanguage_Language_si' => 'Singhalesisch',
+ 'UserLanguage_Language_sk' => 'Slovakisch',
+ 'UserLanguage_Language_sl' => 'Slovenisch',
+ 'UserLanguage_Language_sm' => 'Samoisch',
+ 'UserLanguage_Language_sn' => 'Shona',
+ 'UserLanguage_Language_so' => 'Somali',
+ 'UserLanguage_Language_sq' => 'Albanisch',
+ 'UserLanguage_Language_sr' => 'Serbisch',
+ 'UserLanguage_Language_ss' => 'Siswati',
+ 'UserLanguage_Language_st' => 'Süd-Sotho',
+ 'UserLanguage_Language_su' => 'Sundanesisch',
+ 'UserLanguage_Language_sv' => 'Schwedisch',
+ 'UserLanguage_Language_sw' => 'Swahili',
+ 'UserLanguage_Language_ta' => 'Tamil',
+ 'UserLanguage_Language_te' => 'Telugu',
+ 'UserLanguage_Language_tg' => 'Tadschikisch',
+ 'UserLanguage_Language_th' => 'Thailändisch',
+ 'UserLanguage_Language_ti' => 'Tigrinya',
+ 'UserLanguage_Language_tk' => 'Turkmenisch',
+ 'UserLanguage_Language_tl' => 'Tagalog',
+ 'UserLanguage_Language_tn' => 'Setswana',
+ 'UserLanguage_Language_to' => 'Tongaisch',
+ 'UserLanguage_Language_tr' => 'Türkisch',
+ 'UserLanguage_Language_ts' => 'Xitsonga',
+ 'UserLanguage_Language_tt' => 'Tatarisch',
+ 'UserLanguage_Language_tw' => 'Twi',
+ 'UserLanguage_Language_ty' => 'Tahitianisch',
+ 'UserLanguage_Language_ug' => 'Uigurisch',
+ 'UserLanguage_Language_uk' => 'Ukrainisch',
+ 'UserLanguage_Language_ur' => 'Urdu',
+ 'UserLanguage_Language_uz' => 'Uzbekisch',
+ 'UserLanguage_Language_ve' => 'Tshivenda',
+ 'UserLanguage_Language_vi' => 'Vietnamesisch',
+ 'UserLanguage_Language_vo' => 'Volapük',
+ 'UserLanguage_Language_wa' => 'Wallonisch',
+ 'UserLanguage_Language_wo' => 'Wolof',
+ 'UserLanguage_Language_xh' => 'IsiXhosa',
+ 'UserLanguage_Language_yi' => 'Jiddisch',
+ 'UserLanguage_Language_yo' => 'Yoruba',
+ 'UserLanguage_Language_za' => 'Zhuang',
+ 'UserLanguage_Language_zh' => 'Chinesisch',
+ 'UserLanguage_Language_zu' => 'IsiZulu',
+ 'UserSettings_VisitorSettings' => 'Besuchereinstellungen',
+ 'UserSettings_BrowserFamilies' => 'Browserfamilien',
+ 'UserSettings_Browsers' => 'Browser',
+ 'UserSettings_Plugins' => 'Plugins',
+ 'UserSettings_Configurations' => 'Konfigurationen',
+ 'UserSettings_OperatingSystems' => 'Betriebssysteme',
+ 'UserSettings_Resolutions' => 'Auflösungen',
+ 'UserSettings_WideScreen' => 'Breitbild',
+ 'UserSettings_ColumnBrowserFamily' => 'Browserfamilie',
+ 'UserSettings_ColumnBrowser' => 'Browser',
+ 'UserSettings_ColumnPlugin' => 'Plugin',
+ 'UserSettings_ColumnConfiguration' => 'Konfiguration',
+ 'UserSettings_ColumnOperatingSystem' => 'Betriebssystem',
+ 'UserSettings_ColumnResolution' => 'Auflösung',
+ 'UserSettings_ColumnTypeOfScreen' => 'Bildschirmtyp',
+ 'UserSettings_WidgetResolutions' => 'Bildschirmauflösungen',
+ 'UserSettings_WidgetBrowsers' => 'Besucher Browser',
+ 'UserSettings_WidgetPlugins' => 'Liste der Plugins',
+ 'UserSettings_WidgetWidescreen' => 'Normal / Breitbild',
+ 'UserSettings_WidgetBrowserFamilies' => 'Browser nach Familie',
+ 'UserSettings_WidgetOperatingSystems' => 'Betriebssysteme',
+ 'UserSettings_WidgetGlobalVisitors' => 'Globale Besucherkonfiguration',
+ 'UserSettings_SubmenuSettings' => 'Einstellungen',
+ 'UserSettings_PluginDescription' => 'Bericht über verschiedene Benutzereinstellungen: Browser, Browserfamilie, Betriebssystem, Plugins, Auflösung, Einstellungen.',
+ 'UsersManager_UsersManagement' => 'Benutzerverwaltung',
+ 'UsersManager_UsersManagementMainDescription' => 'Benutzer erstellen oder bearbeiten, Rechte können dann oben gesetzt werden.',
+ 'UsersManager_ManageAccess' => 'Zugriffsverwaltung',
+ 'UsersManager_MainDescription' => 'Hier kann Zugriff auf bestimmte Webseiten innerhalb von Piwik erteilt werden. Es ist auch möglich Zugriff für alle Webseiten auf einmal zu setzen.',
+ 'UsersManager_Sites' => 'Seiten',
+ 'UsersManager_AllWebsites' => 'Alle Webseiten',
+ 'UsersManager_ApplyToAllWebsites' => 'Für alle Webseiten anwenden',
+ 'UsersManager_User' => 'Benutzer',
+ 'UsersManager_PrivNone' => 'Kein Zugriff',
+ 'UsersManager_PrivView' => 'Ansicht',
+ 'UsersManager_PrivAdmin' => 'Administrator',
+ 'UsersManager_ChangeAllConfirm' => 'Sollen \'%s\' die Berechtigungen für alle Webseiten wirklich geändert werden?',
+ 'UsersManager_Login' => 'Anmelden',
+ 'UsersManager_Password' => 'Passwort',
+ 'UsersManager_Email' => 'E-Mail',
+ 'UsersManager_Alias' => 'Alias',
+ 'UsersManager_Token' => 'Authentifizierungs-Token',
+ 'UsersManager_Edit' => 'Bearbeiten',
+ 'UsersManager_AddUser' => 'Neuer Benutzer',
+ 'UsersManager_MenuUsers' => 'Benutzer',
+ 'UsersManager_DeleteConfirm_js' => 'Soll der Benutzer %s wirklich gelöscht werden?',
+ 'UsersManager_ExceptionLoginExists' => 'Benutzername \'%s\' existiert bereits.',
+ 'UsersManager_ExceptionEmailExists' => 'Ein Benutzer mit der E-Mail-Adresse \'%s\' existiert bereits.',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'Das Login muss zwischen %s und %s Zeichen lang sein und darf nur Buchstaben, Zahlen oder die Zeichen \'_\' oder \'-\' oder \'.\' enthalten.',
+ 'UsersManager_ExceptionInvalidPassword' => 'Das Passwort muss zwischen 6 und 26 Zeichen lang sein.',
+ 'UsersManager_ExceptionInvalidEmail' => 'Die E-Mail-Adresse scheint nicht gültig zu sein.',
+ 'UsersManager_ExceptionDeleteDoesNotExist' => 'Benutzer \'%s\' existiert nicht und kann daher nicht gelöscht werden.',
+ 'UsersManager_ExceptionAdminAnonymous' => 'Das \'admin\'-Recht kann nicht dem Benutzer \'anonymous\' vergeben werden.',
+ 'UsersManager_ExceptionEditAnonymous' => 'Der anonyme Benutzer kann nicht bearbeitet oder gelöscht werden. Er wird von Piwik benutzt um einen Benutzer zu simulieren, der sich noch nicht angemeldet hat. Zum Beispiel könnte das Statistik-Plugin öffentlich gemacht werden, indem dem Benutzer \'anonymous\' das Recht \'view\' dafür vergeben würde.',
+ 'UsersManager_ExceptionSuperUser' => 'Der angeforderte Benutzer ist der Super-Benutzer und kann über das API nicht angefragt, editiert oder gelöscht werden. Die Angaben zum Super-Benutzer können in der Piwik-Konfigurationsdatei manuell editiert werden.',
+ 'UsersManager_ExceptionUserDoesNotExist' => 'Der Benutzer \'%s\' existiert nicht.',
+ 'UsersManager_ExceptionAccessValues' => 'Der Parameter access muss einen der folgenden Werte enthalten: [ %s ]',
+ 'UsersManager_PluginDescription' => 'Benutzerverwaltung: Benutzer hinzufügen, Benutzer aktualisieren, Berechtigungen verwalten. Alle Änderungen sind auch über die API möglich.',
+ 'VisitFrequency_Evolution' => 'Entwicklung über die Zeit',
+ 'VisitFrequency_ColumnReturningVisits' => 'Wiederkehrende Besuche',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Aktionen von wiederkehrenden Besuchen',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Maximale Aktionen von einem wiederkehrenden Besuch',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Von wiederkehrenden Besuchen verbrachte Gesamtzeit (in Sekunden)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Absprungsrate für wiederkehrende Besuche',
+ 'VisitFrequency_ReturnVisits' => '%s wiederkehrende Besucher',
+ 'VisitFrequency_ReturnActions' => '%s Aktionen von wiederkehrenden Besuchern',
+ 'VisitFrequency_ReturnMaxActions' => '%s max. Aktionen von wiederkehrenden Besuchern',
+ 'VisitFrequency_ReturnTotalTime' => '%s verbrauchte Zeit aller wiederkehrenden Besucher',
+ 'VisitFrequency_ReturnBounceRate' => '%s wiederkehrende Besuche sind abgesprungen (haben die Seite nach einer Seite verlassen)',
+ 'VisitFrequency_WidgetOverview' => 'Frequenzübersicht',
+ 'VisitFrequency_WidgetGraphReturning' => 'Grafik der wiederkehrenden Besucher',
+ 'VisitFrequency_SubmenuFrequency' => 'Frequenz',
+ 'VisitFrequency_PluginDescription' => 'Zeigt verschiedene Statistiken über Besucher und wiederkehrende Besucher.',
+ 'VisitorInterest_VisitsPerDuration' => 'Besuche pro Besuchsdauer',
+ 'VisitorInterest_VisitsPerNbOfPages' => 'Besuche pro Seitenanzahl',
+ 'VisitorInterest_ColumnVisitDuration' => 'Besuchsdauer',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Seiten pro Besuch',
+ 'VisitorInterest_WidgetLengths' => 'Besuchslänge',
+ 'VisitorInterest_WidgetPages' => 'Seiten pro Besuch',
+ 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Häufigkeit und Loyalität',
+ 'VisitorInterest_PlusXMin' => '%s min',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
+ 'VisitorInterest_OnePage' => '1 Seite',
+ 'VisitorInterest_NPages' => '%s Seiten',
+ 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
+ 'VisitorInterest_PluginDescription' => 'Besucherinteresse: Anzahl der besuchten Seiten, Verweildauer auf der Webseite.',
+ 'VisitsSummary_NbVisits' => '%s Besuche',
+ 'VisitsSummary_NbUniqueVisitors' => '%s eindeutige Besucher',
+ 'VisitsSummary_NbActions' => '%s Aktionen (Seitenbesuche)',
+ 'VisitsSummary_TotalTime' => '%s Zeit aller Besucher',
+ 'VisitsSummary_MaxNbActions' => '%s max. Aktionen pro Besuch',
+ 'VisitsSummary_NbVisitsBounced' => '%s Besucher sind abgesprungen (haben die Seite nach einer Seite verlassen)',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Entwicklung über die letzten %s',
+ 'VisitsSummary_Report' => 'Report',
+ 'VisitsSummary_GenerateTime' => '%s Sekunden um die Seite zu generieren',
+ 'VisitsSummary_GenerateQueries' => '%s Abfragen durchgeführt',
+ 'VisitsSummary_WidgetLastVisits' => 'Grafik der letzten Besucher',
+ 'VisitsSummary_WidgetVisits' => 'Besucherübersicht',
+ 'VisitsSummary_WidgetLastVisitors' => 'Grafik der eindeutigen Besucher',
+ 'VisitsSummary_WidgetOverviewGraph' => 'Übersicht mit Grafik',
+ 'VisitsSummary_SubmenuOverview' => 'Übersicht',
+ 'VisitsSummary_PluginDescription' => 'Allgemeine Informationen: Besuche, eindeutige Besucher, Anzahl der Aktionen, etc.',
+ 'VisitsSummary_VisitsSummary' => 'Besucherüberblick',
+ 'VisitsSummary_NbActionsDescription' => '%s Aktionen (Seitenbesuche, Download und ausgehende Verweise)',
+ 'VisitTime_LocalTime' => 'Besuche nach lokaler Zeit des Users',
+ 'VisitTime_ServerTime' => 'Besuche nach lokaler Zeit des Servers',
+ 'VisitTime_ColumnServerTime' => 'Server-Zeit',
+ 'VisitTime_ColumnLocalTime' => 'Ortszeit',
+ 'VisitTime_WidgetLocalTime' => 'Besuche nach lokaler Zeit des Users',
+ 'VisitTime_WidgetServerTime' => 'Besuche nach lokaler Zeit des Servers',
+ 'VisitTime_SubmenuTimes' => 'Zeiten',
+ 'VisitTime_NHour' => '%sh',
+ 'VisitTime_PluginDescription' => 'Lokale Zeit des Besuchers und Serverzeit. Serverzeiten können hilfreich sein um Wartungszeiträume auf der Webseite festzulegen.',
+ 'Widgetize_PluginDescription' => 'Dieses Plugin macht es sehr einfach Piwik Widgets für einen Blog, eine Webseite oder IGoogle und Netvibes zu exportieren.',
+ 'General_DashboardForASpecificWebsite' => 'Dashboard für eine spezifische Webseite',
+ 'General_AllWebsitesDashboard' => 'Dashboard aller Webseiten',
+ 'General_NotValid' => '%s ist nicht gültig',
+ 'General_Username' => 'Benutzername',
+ 'General_Default' => 'Standard',
+ 'General_GoTo' => 'Gehe zu %s',
+ 'General_YourChangesHaveBeenSaved' => 'Ihre Änderungen wurden gespeichert.',
+ 'General_Today' => 'Heute',
+ 'General_Yesterday' => 'Gestern',
+ 'General_CurrentWeek' => 'Aktuelle Woche',
+ 'General_CurrentMonth' => 'Aktueller Monat',
+ 'General_CurrentYear' => 'Aktuelles Jahr',
+ 'General_PageBounceRateDefinition' => 'Der Anteil der Besuche die auf dieser Seite begannen, die Webseite aber direkt wieder verlassen haben.',
+ 'General_ColumnExitRate' => 'Absprungrate',
+ 'General_PageExitRateDefinition' => 'Der Anteil der Besuche auf dieser Seite, die die Webseite direkt wieder verlassen haben.',
+ 'General_ColumnBounces' => 'Absprünge',
+ 'General_BouncesDefinition' => 'Anzahl an Besuchen die auf dieser Seite begannen, die Webseite aber direkt wieder verließen.',
+ 'General_ColumnEntrances' => 'Eingänge',
+ 'General_EntrancesDefinition' => 'Anzahl an Besuchen die auf dieser Seite begannen.',
+ 'General_ColumnExits' => 'Absprünge',
+ 'General_ExitsDefinition' => 'Anzahl an Besuchen die auf dieser Seite endeten.',
+ 'General_ColumnAverageTimeOnPage' => 'Durchschn. Zeit auf Seite',
+ 'General_AverageTimeOnPageDefinition' => 'Die durchschnittliche Zeit die Besucher auf dieser Seite verbrachten.',
+ 'General_DaysHours' => '%1$s Tage %2$s Stunden',
+ 'General_HoursMinutes' => '%1$s Stunden %2$s Minuten',
+ 'General_MinutesSeconds' => '%1$s Minuten %2$ss',
+ 'General_Seconds' => '%ss',
+ 'General_GeneralSettings' => 'Haupteinstellungen',
+ 'General_AllowPiwikArchivingToTriggerBrowser' => 'Erlaube Piwik die Archivierung zu starten wenn Berichte vom Browser angezeigt werden.',
+ 'General_ArchivingInlineHelp' => 'Für Seiten mit mittlerem bis hohem Trafficaufkommen wird empfohlen die durch den Browser ausgelöste Archivierung zu deaktivieren. Stattdessen wird empfohlen, dass Sie einen Cronjob aufsetzen, der die Berichte einmal pro Stunde abarbeitet.',
+ 'General_ArchivingTriggerDescription' => 'Für größere Piwik-Installationen sollten sie %seinen Cronjob erstellen%s der die Berichte automatisch abarbeitet.',
+ 'General_SeeTheOfficialDocumentationForMoreInformation' => 'Sehen Sie die %sOffizielle Dokumentation%s für weitere Informationen.',
+ 'General_ReportsForTodayWillBeProcessedAtMostEvery' => 'Verarbeitung von Berichten für heute geschieht maximal alle ',
+ 'General_NSeconds' => '%s Sekunden',
+ 'General_SmallTrafficYouCanLeaveDefault' => 'Für Seiten mit wenig Traffic können Sie den Standard von %s Sekunden beibehalten und alle Berichte in Echtzeit anzeigen.',
+ 'General_MediumToHighTrafficItIsRecommendedTo' => 'Für Seiten mit mittlerem bis hohem Trafficaufkommen empfehlen wir Berichte für den heutigen Tag maximal jede halbe Stunde (%s Sekunden) oder jede Stunde (%s Sekunden) abzuarbeiten.',
+ 'General_DisplayGoals' => 'Zeige Ziele',
+ 'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin' => '%s ist verfügbar. Bitte benachrichtigen Sie den Seitenadministrator.',
+ 'General_ConfigFileIsNotWritable' => 'Die Piwik Konfigurationsdatei %s ist nicht schreibbar, ihre Änderungen werden nicht gespeichert. %s Bitte ändern Sie die Zugriffsrechte der Konfigurationsdatei um diese beschreibbar zu machen.',
+ 'Actions_SubmenuPagesEntry' => 'Eingangsseiten',
+ 'Actions_SubmenuPagesExit' => 'Absprungsseiten',
+ 'CoreAdminHome_MenuGeneralSettings' => 'Haupteinstellungen',
+ 'CoreAdminHome_Administration' => 'Administration',
+ 'CoreHome_WebAnalyticsReports' => 'Web Analytik Berichte',
+ 'Goals_Goals' => 'Ziele',
+ 'Goals_Overview' => 'Übersicht',
+ 'Goals_WhereThe' => 'wo die',
+ 'Installation_PleaseFixTheFollowingErrors' => 'Bitte beheben Sie die folgenden Fehler',
+ 'Installation_Timezone' => 'Zeitzone der Webseite',
+ 'LanguagesManager_AboutPiwikTranslations' => 'Über Piwik Übersetzungen',
+ 'Live_Last30Minutes' => 'Letzte 30 Minuten',
+ 'Login_InvalidNonceOrReferer' => 'Der Sicherheitsschlüssel des Formulars ist ungültig oder abgelaufen. Bitte aktualisieren Sie das Formular und überprüfen Sie, dass Cookies aktiviert sind.',
+ 'MultiSites_Evolution' => 'Entwicklung',
+ 'SitesManager_SuperUserCan' => 'The Superuser kann ebenfalls %sglobale Einstellungen%s für neue Webseiten vornehmen.',
+ 'SitesManager_ExcludedIps' => 'Ignorierte IPs',
+ 'SitesManager_GlobalListExcludedIps' => 'Globale Liste ignorierter IPs',
+ 'SitesManager_ListOfIpsToBeExcludedOnAllWebsites' => 'Die untenstehenden IPs werden auf allen Webseiten ignoriert.',
+ 'SitesManager_ExcludedParameters' => 'Ignorierte Parameter',
+ 'SitesManager_GlobalListExcludedQueryParameters' => 'Globale Liste von GET-Parametern die ignoriert werden.',
+ 'SitesManager_ListOfQueryParametersToBeExcludedOnAllWebsites' => 'Die untenstehenden GET-Parameter werden von allen URLs aller Webseiten ignoriert.',
+ 'SitesManager_ListOfQueryParametersToExclude' => 'Geben die eine Liste von GET-Parametern an, eine pro Zeile, welche vom Seiten-URLs Bericht ignoriert werden sollen.',
+ 'SitesManager_PiwikWillAutomaticallyExcludeCommonSessionParameters' => 'Piwik filtert automatisch typische session parameter (%s).',
+ 'SitesManager_HelpExcludedIps' => 'Geben Sie eine Liste von IPs an, eine pro Zeile, welche von Piwik beim Erfassen von Besuchen ignoriert werden sollen. Es können Wildcards genutzt werden, z.B. %1$s oder %2$s',
+ 'SitesManager_YourCurrentIpAddressIs' => 'Ihre aktuelle IP-Addresse ist %s.',
+ 'SitesManager_SelectACity' => 'Wählen Sie eine Stadt',
+ 'SitesManager_ChooseCityInSameTimezoneAsYou' => 'Wählen Sie eine Stadt die sich in der gleichen Zeitzone wie Sie befindet.',
+ 'SitesManager_ChangingYourTimezoneWillOnlyAffectDataForward' => 'Das Ändern ihrer Zeitzone wird nur Daten ab diesem Zeitpunkt betreffen und nicht rückwirkend angepasst.',
+ 'SitesManager_AdvancedTimezoneSupportNotFound' => 'Erweiterte Zeitzonenunterstütung wurde in Ihrer PHP-Installation nicht gefunden (unterstützt in PHP>=5.2). Sie können manuell eine Abweichung zu UTC eintragen.',
+ 'SitesManager_UTCTimeIs' => 'UTC-Zeit ist %s.',
+ 'SitesManager_Timezone' => 'Zeitzone ',
+ 'SitesManager_GlobalWebsitesSettings' => 'Globale Webseiteneinstellungen',
+ 'SitesManager_DefaultTimezoneForNewWebsites' => 'Standardzeitzone für neue Webseiten',
+ 'SitesManager_SelectDefaultTimezone' => 'Sie können eine Zeitzone auswählen welche Standardmäßig für neue Webseiten ausgewählt wird.',
+ 'SitesManager_Currency' => 'Währung',
+ 'SitesManager_CurrencySymbolWillBeUsedForGoals' => 'Das Währungssymbol wird direkt neben den Einnahmen durch Ziele angezeigt.',
+ 'SitesManager_DefaultCurrencyForNewWebsites' => 'Standardwährung für neue Webseiten',
+ 'SitesManager_SelectDefaultCurrency' => 'Sie können eine Währung auswählen welche Standardmäßig für neue Webseiten ausgewählt wird.',
+ 'SitesManager_Save_js' => 'Speichern',
+ 'SitesManager_Cancel_js' => 'Abbrechen',
+ 'UsersManager_TheSuperUserAliasCannotBeChanged' => 'Das Alias des Superusers kann nicht geändert werden.',
+ 'UsersManager_ReportToLoadByDefault' => 'Bericht der Standardmäßig geladen wird',
+ 'UsersManager_ReportDateToLoadByDefault' => 'Berichtsdatum welches Standardmäßig geladen wird',
+ 'UsersManager_ForAnonymousUsersReportDateToLoadByDefault' => 'Bericht der für Gast-Besucher ("anonymous") Standardmäßig geladen wird ',
+ 'UsersManager_ExcludeVisitsViaCookie' => 'Schließen Sie Ihre Besuche mit einem Cookie aus',
+ 'UsersManager_YourVisitsAreIgnoredOnDomain' => '%sIhre Besuche werden von Piwik unter der Addresse %s ignoriert %s (das Piwik Cookie zum Ignorieren von Besuchen wurde in Ihrem Browser gefunden).',
+ 'UsersManager_YourVisitsAreNotIgnored' => '%sIhre Besuche werden von Piwik nicht ignoriert %s (das Piwik Cookie zum Ignorieren von Besuchen wurde nicht in Ihrem Browser gefunden).',
+ 'UsersManager_ClickHereToDeleteTheCookie' => 'Klicken Sie hier um das Cookie zu löschen und Ihre Besuche wieder zu zählen',
+ 'UsersManager_ClickHereToSetTheCookieOnDomain' => 'Klicken Sie hier um eine Cookie zu setzen, welches Ihre Besuche auf Seiten die von Piwik unter %s gezählt werden zu ignorieren',
+ 'UsersManager_MenuUserSettings' => 'Benutzereinstellungen',
+ 'UsersManager_MenuAnonymousUserSettings' => 'Gast-Besucher ("anonymous") Einstellungen',
+ 'UsersManager_NoteNoAnonymousUserAccessSettingsWontBeUsed' => 'Bemerkung: Sie haben keine Webseite die der Gast ("anonymous") Besucher besuchen kann. Die folgenden Einstellungen werden nicht benutzt.',
+ 'UsersManager_WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess' => 'Wenn Benutzer nicht eingeloggt sind und Piwik besuchen, sollten sie weitergeleitet werden auf',
+ 'UsersManager_ChangePassword' => 'Ändere Passwort',
+ 'UsersManager_IfYouWouldLikeToChangeThePasswordTypeANewOne' => 'Wenn Sie Ihr Passwort ändern möchten, geben Sie ein Neues ein, ansonsten lassen dieses Feld frei.',
+ 'UsersManager_TypeYourPasswordAgain' => 'Geben Sie Ihr Passwort erneut ein.',
+ 'UsersManager_TheLoginScreen' => 'Der Loginbildschirm',
+ 'UsersManager_YourUsernameCannotBeChanged' => 'Ihr Benutzername kann nicht geändert werden.',
+ 'VisitorInterest_Engagement' => 'Engagement',
+); \ No newline at end of file
diff --git a/lang/el.php b/lang/el.php
index 1b656b949f..803f71685e 100644
--- a/lang/el.php
+++ b/lang/el.php
@@ -1,22 +1,29 @@
<?php
+
+setlocale(LC_TIME, 'el_GR.UTF-8');
+
$translations = array(
'General_Locale' => 'el_GR.UTF-8',
- 'General_TranslatorName' => 'Jim Black www.jblack.info, Γεώργιος Τέλλος OnSite.Net VoIP & IT Solutions',
- 'General_TranslatorEmail' => 'jimaek@hotmail.com, info@onsite.net.gr',
+ 'General_TranslatorName' => 'Jim Black www.jblack.info, Γεώργιος Τέλλος OnSite.Net VoIP & IT Solutions, Παναγιώτης Παπάζογλου Δρ. Δασολόγος-Περιβαλλοντολόγος',
+ 'General_TranslatorEmail' => 'jimaek@hotmail.com, info@onsite.net.gr, papaz_p@yahoo.com',
'General_EnglishLanguageName' => 'Hellenic',
'General_OriginalLanguageName' => 'Ελληνικά',
'General_HelloUser' => 'Γεια σου, %s!',
'General_OpenSourceWebAnalytics' => 'Λογισμικό Ανάλυσης Ιστοσελίδων',
- 'General_YourDashboard' => 'Κεντρικός Πίνακας',
+ 'General_Dashboard' => 'Κεντρικός Πίνακας',
+ 'General_DashboardForASpecificWebsite' => 'Κεντρικός πίνακας για συγκεκριμένη ιστοσελίδα',
+ 'General_MultiSitesSummary' => 'Όλες οι ιστοσελίδες',
+ 'General_AllWebsitesDashboard' => 'Κεντρικός πίνακας όλων των ιστοσελίδων',
'General_API' => 'API',
- 'General_Widgets' => 'Widgets',
+ 'General_Widgets' => 'Μικροεφαρμογές',
'General_Settings' => 'Ρυθμίσεις',
'General_GiveUsYourFeedback' => 'Πείτε μας τις παρατηρήσεις σας!',
'General_Unknown' => 'Άγνωστο',
- 'General_Required' => '%s required',
+ 'General_Required' => '%s απαιτούνται',
+ 'General_NotValid' => '%s δεν είναι έγκυρο',
'General_Error' => 'Σφάλμα',
'General_Warning' => 'Προειδοποίηση',
- 'General_BackToHomepage' => 'Πίσω στην αρχική σελίδα του Piwik',
+ 'General_BackToHomepage' => 'Επιστροφή στην αρχική σελίδα του Piwik',
'General_Yes' => 'Ναι',
'General_No' => 'Όχι',
'General_Delete' => 'Διαγραφή',
@@ -24,71 +31,92 @@ $translations = array(
'General_Ok' => 'Εντάξει',
'General_Close' => 'Κλείσιμο',
'General_Logout' => 'Αποσύνδεση',
- 'General_Done' => 'Έγινε',
+ 'General_Username' => 'Όνομα χρήστη',
+ 'General_Done' => 'Ολοκληρώθηκε',
+ 'General_Details' => 'Λεπτομέρειες',
+ 'General_Default' => 'Προεπιλογή',
'General_LoadingData' => 'Φόρτωση δεδομένων...',
- 'General_ErrorRequest' => 'Ούπς&hellip; ίσως πρόβλημα με τη σύνδεση, παρακαλώ ξαναπροσπαθήστε.',
+ 'General_Loading' => 'Φόρτωση...',
+ 'General_YourChangesHaveBeenSaved' => 'Οι αλλαγές σας αποθηκεύτηκαν.',
+ 'General_ErrorRequest' => 'Ούπς&hellip;, πιθανό πρόβλημα με τη σύνδεση. Ξαναπροσπαθήστε.',
'General_Next' => 'Επόμενο',
'General_Previous' => 'Προηγούμενο',
'General_Search' => 'Αναζήτηση',
'General_Others' => 'Άλλα',
'General_Table' => 'Πίνακας',
- 'General_Piechart' => 'Γράφημα πίτας',
+ 'General_Piechart' => 'Διάγραμμα πίτας',
'General_TagCloud' => 'Σύννεφο λέξεων',
- 'General_VBarGraph' => 'Κάθετο γράφημα με μπάρες',
+ 'General_VBarGraph' => 'Διάγραμμα με κάθετες στήλες',
'General_Export' => 'Εξαγωγή',
+ 'General_ExportAsImage_js' => 'Εξαγωγή ως εικόνα',
+ 'General_SaveImageOnYourComputer_js' => 'Για να αποθηκεύσετε την εικόνα στον υπολογιστή σας, δεξί κλικ στην εικόνα και επιλέξτε «Αποθήκευση εικόνας ως...»',
'General_Refresh' => 'Ανανέωση της σελίδας',
+ 'General_Today' => 'Σήμερα',
+ 'General_Yesterday' => 'Χθες',
+ 'General_CurrentWeek' => 'Τρέχουσα Εβδομάδα',
+ 'General_CurrentMonth' => 'Τρέχων Μήνας',
+ 'General_CurrentYear' => 'Τρέχον Έτος',
'General_Visitors' => 'Επισκέπτες',
'General_ColumnNbUniqVisitors' => 'Μοναδικοί επισκέπτες',
'General_ColumnNbVisits' => 'Επισκέψεις',
+ 'General_ColumnNbActions' => 'Δραστηριότητες',
+ 'General_ColumnMaxActions' => 'Μέγιστος αριθμός δραστηριοτήτων σε μια επίσκεψη',
+ 'General_ColumnSumVisitLength' => 'Συνολικός δαπανηθής χρόνος επισκεπτών (σε δευτερόλεπτα)',
'General_ColumnLabel' => 'Ετικέτα',
- 'General_ColumnActionsPerVisit' => 'Ενέργειες ανά επίσκεψη',
+ 'General_ColumnActionsPerVisit' => 'Δραστηριότητες ανά επίσκεψη',
'General_ColumnAvgTimeOnSite' => 'Μέσος χρόνος στην ιστοσελίδα',
'General_ColumnBounceRate' => 'Ρυθμός αναπήδησης',
- 'General_ColumnPageviews' => 'Θεάσεις σελίδων',
- 'General_ColumnUniquePageviews' => 'Μοναδικές θεάσεις σελίδων',
+ 'General_ColumnPageviews' => 'Προβολές σελίδων',
+ 'General_ColumnUniquePageviews' => 'Μοναδικές προβολές σελίδων',
+ 'General_ColumnValuePerVisit' => 'Τιμή ανά Επίσκεψη',
+ 'General_ColumnVisitsWithConversions' => 'Επισκέψει με Μετατροπές',
'General_Save' => 'Αποθήκευση',
+ 'General_ForExampleShort' => 'π.χ.',
'General_Website' => 'Ιστοσελίδα',
- 'General_NoDataForGraph' => 'Ανεπαρκή δεδομένα για γράφημα',
+ 'General_GeneralSettings' => 'Γενικές Ρυθμίσεις',
+ 'General_AllowPiwikArchivingToTriggerBrowser' => 'Επιτρέπετε η ενεργοποίηση της αρχειοθέτησης του Piwik όταν προβάλονται αναφορές από τον φυλλομετρητή',
+ 'General_ArchivingInlineHelp' => 'Για μεσαίας ή μεγάλης επισκεψιμότητας ιστοσελίδες, προτείνεται να απενεργοποιήσετε την αρχειοθέτηση από τον φυλλομετρητή. Αντί για αυτό, σας προτείνουμε να εγκαταστήσετε μια εργασία cron για να δημιουργείτε αναφορές Piwik κάθε ώρα.',
+ 'General_ArchivingTriggerDescription' => 'Προτείνετε για μεγάλες εγκαταστάσεις του Piwik. Χρειάζεται να %sεγκαταστήσετε μια εργασία cron%s για να δημιουργείτε τις αναφορές αυτόματα.',
+ 'General_SeeTheOfficialDocumentationForMoreInformation' => 'Δείτε την %sεπίσημη τεκμηρίωση%s για περισσότερες πληροφορίες.',
+ 'General_ReportsForTodayWillBeProcessedAtMostEvery' => 'Οι αναφορές για σήμερα θα προχωρήσουν στο περισσότερο κάθε',
+ 'General_NSeconds' => '%s δευτερόλεπτα',
+ 'General_SmallTrafficYouCanLeaveDefault' => 'Για μικρής επισκεψιμότητας ιστοσελίδες, μπορείτε να αφήσετε τα προεπιλεγμένα %s δευτερόλεπτα και να έχετε πρόσβαση σε όλες τις αναφορές σε πραγματικό χρόνο',
+ 'General_MediumToHighTrafficItIsRecommendedTo' => 'Για μεσαίας ή μεγάλης επισκεψιμότητας ιστοσελίδες, προτείνεται να δημιουργείτε αναφορές για σήμερα στο περισσότερο κάθε μισή ώρα (%s δευτερόλεπτα) ή κάθε ώρα (%s δευτερόλεπτα).',
+ 'General_RequiresFlash' => 'Η προβολή Γραφικών στο Piwik προϋποθέτει Flash',
+ 'General_GraphHelp' => 'Περισσότερες πληροφορίες για την προβολή γραφικών στο Piwik.',
+ 'General_NoDataForGraph' => 'Ανεπαρκή δεδομένα για διάγραμμα',
'General_NoDataForTagCloud' => 'Ανεπαρκή δεδομένα για σύννεφο λέξεων.',
'General_DisplayNormalTable' => 'Εμφάνιση κανονικού πίνακα',
'General_DisplayMoreData' => 'Εμφάνιση περισσότερων δεδομένων',
- 'General_PiwikIsACollaborativeProject' => 'Έκδοση %s Piwik %s . %s Υπό δοκιμή %s επικοινωνία εδώ!%s.',
- 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Βλέπετε την έκδοση παρουσίασης του %s; %sκατεβάστε%s την πλήρη έκδοση! Δείτε εδώ %s ',
- 'General_Loading' => 'Φόρτωση...',
- 'General_ExportAsImage' => 'Εξαγωγή ως εικόνα',
- 'General_SaveImageOnYourComputer' => 'Για να αποθηκεύσετε την εικόνα στον υπολογιστή,δεξί κλικ πάνω στην εικόνα και επιλέξτε "Αποθήκευση εικόνας ως..."',
- 'General_ColumnNbActions' => 'Ενέργειες',
- 'General_ColumnMaxActions' => 'Μέγιστες ενέργειες σε μια επίσκεψη',
- 'General_ColumnSumVisitLength' => 'Συνολικός χρόνος ξοδεμένος από τους επισκέπτες(σε δευτερόλεπτα)',
- 'General_ColumnValuePerVisit' => 'Τιμή ανά επίσκεψη',
- 'General_ColumnVisitsWithConversions' => 'Τιμή με μετατροπές',
- 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Το Piwik %s είναι ένα ομαδικό πρότζεκτ. %s Εάν σας αρέσει το Piwik, μπορείτε να βοηθήσετε! Δείτε εδώ %s Πως να συμβάλω στο Piwik;%s',
- 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s είναι διαθέσιμο. %s Παρακαλώ ενημερώστε το τώρα!%s (δείτε %s αλλαγές%s).',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => 'Το %1$s Piwik %2$s είναι ένα πρόγραμμα συνεργασίας. %3$s Αν σας αρέσει το Piwik, μπορείτε να βοηθείσετε! Δείτε %4$sπως να συμμετέχετε στο Piwik%5$s',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Βλέπετε την έκδοση παρουσίασης του %s; %sλάβετε%s την πλήρη έκδοση! Δείτε το %s ',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Είναι διαθέσιμο το Piwik %s. %s Άμεση ενημέρωση τώρα!%s (δείτε τις %s αλλαγές%s).',
+ 'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin' => '%s είναι διαθέσιμη. Ενημερώστε τον διαχειριστή.',
'General_BackToPiwik' => 'Πίσω στο Piwik',
'General_ShortMonth_1' => 'Ιαν',
'General_ShortMonth_2' => 'Φεβ',
- 'General_ShortMonth_3' => 'Μρ',
+ 'General_ShortMonth_3' => 'Μαρ',
'General_ShortMonth_4' => 'Απρ',
- 'General_ShortMonth_5' => 'Μαι',
- 'General_ShortMonth_6' => 'Ιον',
- 'General_ShortMonth_7' => 'Ιολ',
- 'General_ShortMonth_8' => 'Αυγ',
+ 'General_ShortMonth_5' => 'Μάη',
+ 'General_ShortMonth_6' => 'Ιουν',
+ 'General_ShortMonth_7' => 'Ιουλ',
+ 'General_ShortMonth_8' => 'Αύγ',
'General_ShortMonth_9' => 'Σεπ',
'General_ShortMonth_10' => 'Οκτ',
'General_ShortMonth_11' => 'Νοε',
'General_ShortMonth_12' => 'Δεκ',
- 'General_LongMonth_1' => 'Ιανουάριος',
- 'General_LongMonth_2' => 'Φεβρουάριος ',
- 'General_LongMonth_3' => 'Μάρτιος ',
- 'General_LongMonth_4' => 'Απρίλιος ',
- 'General_LongMonth_5' => 'Μάιος ',
- 'General_LongMonth_6' => 'Ιούνιος ',
- 'General_LongMonth_7' => 'Ιούλιος ',
- 'General_LongMonth_8' => 'Αύγουστος ',
- 'General_LongMonth_9' => 'Σεπτέμβριος ',
- 'General_LongMonth_10' => 'Οκτώβριος ',
- 'General_LongMonth_11' => 'Νοέμβριος ',
- 'General_LongMonth_12' => 'Δεκέμβριος',
+ 'General_LongMonth_1' => 'Ιανουαρίου',
+ 'General_LongMonth_2' => 'Φεβρουαρίου',
+ 'General_LongMonth_3' => 'Μαρτίου',
+ 'General_LongMonth_4' => 'Απριλίου',
+ 'General_LongMonth_5' => 'Μαΐου',
+ 'General_LongMonth_6' => 'Ιουνίου',
+ 'General_LongMonth_7' => 'Ιουλίου',
+ 'General_LongMonth_8' => 'Αυγούστου',
+ 'General_LongMonth_9' => 'Σεπτεμβρίου',
+ 'General_LongMonth_10' => 'Οκτωβρίου',
+ 'General_LongMonth_11' => 'Νοεμβρίου',
+ 'General_LongMonth_12' => 'Δεκεμβρίου',
'General_ShortDay_1' => 'Δε',
'General_ShortDay_2' => 'Τρ',
'General_ShortDay_3' => 'Τε',
@@ -103,26 +131,55 @@ $translations = array(
'General_LongDay_5' => 'Παρασκευή',
'General_LongDay_6' => 'Σάββατο',
'General_LongDay_7' => 'Κυριακή',
- 'API_QuickDocumentation' => '<h2>Συνοπτική τεκμηρίωση του API</h2><p>Αν δεν έχετε δεδομένα κίνησης για σήμερα μπορείτε να <a href=\'misc/generateVisits.php\' target=_blank>προσθέσετε ενδεικτικά δεδομένα</a> χρησιμοποιώντας την γεννήτρια επισκέψεων.</p><p>Μπορείτε να δοκιμάσετε τις διάφορες διαθέσιμες μορφές για κάθε μέθοδο. Είναι πολύ εύκολο να εξάγετε ότι δεδομένα θέλετε από το piwik!</p><p><b>Για περισσότερες πληροφορίες ρίξτε μια ματιά στη διεύθυνση <a href=\'http://dev.piwik.org/trac/wiki/API\'>Επίσημη τεκμηρίωση API</a> ή <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API Reference</a>.</b></P><h2>Αυθεντικοποίηση χρήστη</h2><p>Αν θέλετε να <b>καλείτε τα δεδομένα μέσα στα scripts σας, μέσω crontab, κτλ. </b> πρέπει να προσθέσετε την παράμετρο <code><u>&token_auth=%s</u></code> στα URL που κάνουν κλήσεις στο API και θέλουν αυθεντικοποίηση.</p><p>Αυτό το token_auth είναι μυστικό όσο και το όνομα χρήστη και ο κωδικός σας, <b>μη τον μοιράζεστε!</p>',
- 'API_LoadedAPIs' => 'Φορτώθηκαν επιτυχώς %s APIs',
- 'Actions_Actions' => 'Ενέργειες',
+ 'General_ExceptionDatabaseVersion' => 'Η έκδοσή %s είναι %s αλλά το Piwik απαιτεί τουλάχιστον %s.',
+ 'General_ExceptionIncompatibleClientServerVersions' => 'Η έκδοση πελάτη σας %1$s είναι %2$s η οποία είναι ασύμβατη με την έκδοση διακομιστή %3$s.',
+ 'General_ExceptionMissingFile' => 'Απολεσθέν αρχείο: %s',
+ 'General_ExceptionFilesizeMismatch' => 'Αταίριαστο μέγεθος αρχείου: %1$s (αναμενόμενο: %2$s, βρέθηκε: %3$s)',
+ 'General_ExceptionFileIntegrity' => 'Ο έλεγχος ακεραιότητας απέτυχε: %s',
+ 'General_ExceptionNonceMismatch' => 'Αδύνατη η πιστοποίηση τεκμηρίου ασφάλειας σε αυτή τη φόρμα.',
+ 'General_WarningFileIntegritySkipped' => 'Ανιχνεύτηκε περιβάλλον ανάπτυξης. Ο έλεγχος ακεραιότητας αρχείου παραβλέφθηκε.',
+ 'General_WarningFileIntegrityNoManifest' => 'Ο έλεγχος ακεραιότητας αρχείου δεν μπορεί να πραγματοποιηθεί επειδή λείπει το αρχείο manifest.inc.php.',
+ 'General_WarningFileIntegrityNoMd5file' => 'Ο έλεγχος ακεραιότητας αρχείου δεν μπορεί να ολοκληρωθεί γιατί είναι ανενεργή η συνάρτηση md5_file().',
+ 'General_FileIntegrityWarningExplanation' => 'Ο έλεγχος ακεραιότητας αρχείου απέτυχε και ανέφερε κάποια σφάλματα. Αυτό συμβαίνει πιθανόν λόγω μερικούς ή αποτυχημένης αποστολής ορισμένων αρχείων του Piwik. Πρέπει να τα αποστείλετε ξανά όλα και ανανεώστε αυτή τη σελίδα μέχρι να μην δείχνει σφάλματα.',
+ 'Actions_PluginDescription' => 'Αναφέρει για τις προβολές σελίδων, οι εξωτερικοί σύνδεσμοι και οι λήψεις. Η ανίχνευση των εξωτερικών συνδέσμων και των λήψεων είναι αυτόματη!',
+ 'Actions_Actions' => 'Δραστηριότητες',
'Actions_SubmenuPages' => 'Σελίδες',
+ 'Actions_SubmenuPageTitles' => 'Τίτλοι σελίδων',
'Actions_SubmenuOutlinks' => 'Δεσμοί εξόδου',
- 'Actions_SubmenuDownloads' => 'Μεταφορτώσεις',
- 'CoreHome_NoPrivileges' => 'You are logged in as \'%s\' but it seems you don\'t have any permission set in Piwik.<br />Ask your Piwik administrator to give you \'view\' access to a website.',
- 'CoreHome_JavascriptDisabled' => 'JavaScript must be enabled in order for you to use Piwik in standard view.<br />However, it seems JavaScript is either disabled or not supported by your browser.<br />To use standard view, enable JavaScript by changing your browser options, then %1stry again%2s.<br />',
+ 'Actions_SubmenuDownloads' => 'Λήψεις',
+ 'Actions_ColumnClicks' => 'Κλικ',
+ 'Actions_ColumnUniqueClicks' => 'Μοναδικά κλικ',
+ 'Actions_ColumnDownloads' => 'Λήψεις',
+ 'Actions_ColumnUniqueDownloads' => 'Μοναδικές λήψεις',
+ 'Actions_ColumnPageName' => 'Ονομασία σελίδας',
+ 'Actions_ColumnPageURL' => 'URL σελίδας',
+ 'Actions_ColumnClickedURL' => 'URL επιλογής',
+ 'Actions_ColumnDownloadURL' => 'URL λήψης',
+ 'AnonymizeIP_PluginDescription' => 'Δίνει ανωνυμία στις διευθύνσεις IP των επισκεπτών για να ακολουθείται η νομοθεσία περί Ιδιωτικού Απορρήτου.',
+ 'API_PluginDescription' => 'Όλα τα δεδομένα στο Piwik είναι διαθέσιμα μέσω απλών APIs. Αυτό το πρόσθετο είναι το σημείο εισόδου της υπηρεσίας ιστού που μπορείτε να καλέσετε τα δεδομένα Ανάλυσης Ιστού σε xml, json, php, csv, κλπ.',
+ 'API_QuickDocumentation' => '<h2>Συνοπτική τεκμηρίωση του API</h2><p>Αν δεν έχετε δεδομένα επισκεψιμότητας για σήμερα μπορείτε να <a href=\'misc/generateVisits.php\' target=_blank>προσθέσετε ενδεικτικά δεδομένα</a> χρησιμοποιώντας τη γεννήτρια επισκέψεων.</p><p>Μπορείτε να δοκιμάσετε τις διάφορες διαθέσιμες μορφές για κάθε μέθοδο. Είναι πολύ εύκολο να εξάγετε ότι δεδομένα θέλετε από το piwik!</p><p><b>Για περισσότερες πληροφορίες ρίξτε μια ματιά στη διεύθυνση <a href=\'http://dev.piwik.org/trac/wiki/API\'>Επίσημη τεκμηρίωση API</a> ή <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>Τεκμηρίωση API</a>.</b></P><h2>Αυθεντικοποίηση χρήστη</h2><p>Αν θέλετε να <b>καλείτε τα δεδομένα μέσα στα scripts σας, μέσω crontab, κτλ. </b> πρέπει να προσθέσετε την παράμετρο <code><u>&token_auth=%s</u></code> στα URL που κάνουν κλήσεις στο API και θέλουν αυθεντικοποίηση.</p><p>Αυτό το token_auth είναι μυστικό όσο και το όνομα χρήστη και ο κωδικός σας, <b>μη τον μοιράζεστε!</p>',
+ 'API_LoadedAPIs' => 'Φορτώθηκαν επιτυχώς %s APIs',
+ 'CoreAdminHome_PluginDescription' => 'Περιοχή διαχείρισης του Piwik.',
+ 'CoreAdminHome_MenuGeneralSettings' => 'Γενικές ρυθμίσεις',
+ 'CoreHome_PluginDescription' => 'Δομή Αναφορών Ανάλυσης Ιστού.',
+ 'CoreHome_NoPrivileges' => 'Έχετε συνδεθεί ως «%s» αλλά φαίνεται ότι δεν σας έχουν ορίσει κανένα δικαίωμα στο Piwik.<br />Ρωτήστε τον διαχειριστή του Piwik για να σας δώσει δικαίωμα «προβολής» σε μια σελίδα.',
+ 'CoreHome_JavascriptDisabled' => 'Πρέπει να είναι ενεργοποιημένη η JavaScript ώστε να μπορείτε να χρησιμοποιήσετε το Piwik σε κανονική προβολή.<br />Ωστόσο, φαίνεται ότι η JavaScript είτε είναι απενεργοποιήμένη ή δεν υποστηρίζεται από τον φυλλομετρητή σας.<br />Για χρήση της κανονικής προβολής, ενεργοποιήστε τη JavaScript αλλάζοντας τις ρυθμίσεςι του φυλλομετρητή σας και %1sδοκιμάστε ξανά%2s.<br />',
'CoreHome_TableNoData' => 'Ανεπαρκή δεδομένα για πίνακα.',
'CoreHome_CategoryNoData' => 'Ανεπαρκή δεδομένα στη κατηγορία. Δοκιμάστε να συμπεριλάβετε όλο το πλήθος.',
'CoreHome_ShowJSCode' => 'Εμφάνιση του κώδικα της Javascript προς εισαγωγή',
'CoreHome_IncludeAllPopulation_js' => 'Συμπερίληψη όλου του πλήθους',
'CoreHome_ExcludeLowPopulation_js' => 'Εξαίρεση χαμηλού πλήθους',
- 'CoreHome_PageOf_js' => '%s of %s',
+ 'CoreHome_PageOf_js' => '%s από %s',
'CoreHome_Loading_js' => 'Φόρτωση...',
- 'CoreHome_LocalizedDateFormat' => '%A %d %B %Y',
- 'CoreHome_PeriodDay' => 'Μέρα',
+ 'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
+ 'CoreHome_PeriodDay' => 'Ημέρα',
'CoreHome_PeriodWeek' => 'Εβδομάδα',
'CoreHome_PeriodMonth' => 'Μήνας',
- 'CoreHome_PeriodYear' => 'Χρόνος',
+ 'CoreHome_PeriodYear' => 'Έτος',
+ 'CoreHome_PeriodDays' => 'ημερών',
+ 'CoreHome_PeriodWeeks' => 'εβδομάδων',
+ 'CoreHome_PeriodMonths' => 'μηνών',
+ 'CoreHome_PeriodYears' => 'ετών',
'CoreHome_DaySu_js' => 'Κυ',
'CoreHome_DayMo_js' => 'Δε',
'CoreHome_DayTu_js' => 'Τρ',
@@ -130,6 +187,32 @@ $translations = array(
'CoreHome_DayTh_js' => 'Πε',
'CoreHome_DayFr_js' => 'Πα',
'CoreHome_DaySa_js' => 'Σα',
+ 'CoreHome_ShortDay_1_js' => 'Κυρ',
+ 'CoreHome_ShortDay_2_js' => 'Δευ',
+ 'CoreHome_ShortDay_3_js' => 'Τρι',
+ 'CoreHome_ShortDay_4_js' => 'Τετ',
+ 'CoreHome_ShortDay_5_js' => 'Πεμ',
+ 'CoreHome_ShortDay_6_js' => 'Παρ',
+ 'CoreHome_ShortDay_7_js' => 'Σαβ',
+ 'CoreHome_LongDay_1_js' => 'Κυριακή',
+ 'CoreHome_LongDay_2_js' => 'Δευτέρα',
+ 'CoreHome_LongDay_3_js' => 'Τρίτη',
+ 'CoreHome_LongDay_4_js' => 'Τετάρτη',
+ 'CoreHome_LongDay_5_js' => 'Πέμπτη',
+ 'CoreHome_LongDay_6_js' => 'Παρασκευή',
+ 'CoreHome_LongDay_7_js' => 'Σάββατο',
+ 'CoreHome_ShortMonth_1_js' => 'Ιαν',
+ 'CoreHome_ShortMonth_2_js' => 'Φεβ',
+ 'CoreHome_ShortMonth_3_js' => 'Μαρ',
+ 'CoreHome_ShortMonth_4_js' => 'Απρ',
+ 'CoreHome_ShortMonth_5_js' => 'Μαι',
+ 'CoreHome_ShortMonth_6_js' => 'Ιουν',
+ 'CoreHome_ShortMonth_7_js' => 'Ιουλ',
+ 'CoreHome_ShortMonth_8_js' => 'Αυγ',
+ 'CoreHome_ShortMonth_9_js' => 'Σεπ',
+ 'CoreHome_ShortMonth_10_js' => 'Οκτ',
+ 'CoreHome_ShortMonth_11_js' => 'Νοε',
+ 'CoreHome_ShortMonth_12_js' => 'Δεκ',
'CoreHome_MonthJanuary_js' => 'Ιανουάριος',
'CoreHome_MonthFebruary_js' => 'Φεβρουάριος',
'CoreHome_MonthMarch_js' => 'Μάρτιος',
@@ -142,7 +225,8 @@ $translations = array(
'CoreHome_MonthOctober_js' => 'Οκτώβριος',
'CoreHome_MonthNovember_js' => 'Νοέμβριος',
'CoreHome_MonthDecember_js' => 'Δεκέμβριος',
- 'CorePluginsAdmin_Plugins' => 'Plugins',
+ 'CorePluginsAdmin_PluginDescription' => 'Περιβάλλον εργασίας Διαχείρισης Προσθέτων.',
+ 'CorePluginsAdmin_Plugins' => 'Πρόσθετα',
'CorePluginsAdmin_PluginsManagement' => 'Διαχείριση προσθέτων',
'CorePluginsAdmin_MainDescription' => 'Τα πρόσθετα (Plugins) επεκτείνουν και διευρύνουν την λειτουργικότητα του Piwik. Αφού εγκατασταθεί ένα πρόσθετο, μπορείτε να το ενεργοποιήσετε ή να το απενεργοποιήσετε εδώ.',
'CorePluginsAdmin_Plugin' => 'Πρόσθετο',
@@ -158,556 +242,817 @@ $translations = array(
'CorePluginsAdmin_Deactivate' => 'Απενεργοποίηση',
'CorePluginsAdmin_Activate' => 'Ενεργοποίηση',
'CorePluginsAdmin_MenuPlugins' => 'Πρόσθετα',
- 'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; Ενημέρωση',
- 'CoreUpdater_UpdateRequired' => 'Απαραίτητη ενημέρωση',
+ 'CoreUpdater_PluginDescription' => 'Μηχανισμός ενημέρωσης Piwik',
+ 'CoreUpdater_UpdateTitle' => 'Ενημέρωση',
+ 'CoreUpdater_DatabaseUpgradeRequired' => 'Απαιτείται Αναβάθμιση της Βάσης Δεδομένων',
'CoreUpdater_YourDatabaseIsOutOfDate' => 'Η βάση δεδομένων του Piwik είναι παλιά και πρέπει να αναβαθμιστεί προτού συνεχίσετε.',
- 'CoreUpdater_PiwikWillBeUpgradedToVersionX' => 'Το Piwik θα αναβαθμιστεί στην έκδοση %s.',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Η βάση δεδομένων Piwik θα αναβαθμιστεί από την έκδοση %1$s στην έκδοση %2$s.',
'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Τα ακόλουθα πρόσθετα θα αναβαθμιστούν: %s.',
- 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Η διαδικασία αναβάθμισης μπορεί να πάρει λίγο χρόνο, παρακαλώ περιμένετε.',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Σημαντική επισήμανση για μεγάλες εγκαταστάσεις Piwik',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'Αν έχετε μια μεγάλη βάση δεδομένων Piwik, οι ενημερώσεις ίσως κρατήσουν αρκετό χρόνο στο φυλλομετρητή. Σε αυτή τη περίπτωση, μπορείτε να εκτελέσετε της ενημερώσεις από τη γραμμή εντολών: %s',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => 'Αν δεν μπορείτε να χρησιμοποιήσετε τη γραμμή εντολών για την ενημέρωση και αν το Piwik αποτύχει να αναβαθμιστεί (λόγω λήξης χρόνου της βάσης δεδομένων, του φυλλομετρητή ή όποια άλλη αιτία), μπορείτε να εκτελέσετε της ερωτήματα SQL χειροκίνητα για να ενημερώσετε το Piwik.',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => 'Πατήστε εδώ για να δείτε και να αντιγράψετε τη λίστα των ερωτημάτων που θα εκτελεστούν',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => 'Σημείωση: αν εκτελέσετε χειροκίνητα αυτά τα ερωτήματα, αναμένετεαι ότι ορισμένα από αυτά θα αποτύχουν. Σε αυτή την περίπτωση, αγνοήστε τα σφάλματα και εκτελέσετε τα επόμενα στη σειρά.',
+ 'CoreUpdater_ReadyToGo' => 'Έτοιμοι για να συνεχίσετε;',
+ 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Η διαδικασία αναβάθμισης μπορεί να πάρει λίγο χρόνο, υπομονή.',
'CoreUpdater_UpgradePiwik' => 'Αναβάθμιση Piwik',
- 'CoreUpdater_HelpMessageContent' => 'Ελέγξτε τα %s Piwik FAQ %s για συνήθη σφάλματα κατά τη διαδικασία της αναβάθμισης. %s Ρωτήστε τον διαχειριστή του συστήματος και ζητήστε βοήθεια με το σφάλμα το οποίο κατά πάσα πιθανότητα είναι συναφή με τον διακομιστή και την MySQL.',
+ 'CoreUpdater_ErrorDIYHelp' => 'Αν είστε προχωρημένος χρήστης και εμφανιστεί σφάλμα στην αναβάθμιση της βάσης δεδομένων:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'Αναγνωρίστε και διορθώστε την προέλευση του προβλήματος (π.χ., memory_limit ή max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'εκτελέστε τα εναπομείνατα ερωτήματα στην ενημέρωση που απέτυχαν',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'ανημερώστε χειροκίνητα τον πίνακα «option» στη βάση δεδομένων του Piwik, ορίστε την τιμή του version_core στην έκδοση της αποτυχημένης ενημέρωσης',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'επαναλάβετε την ενημέρωση (από τον φυλλομετρητή ή τη γραμμή εντολών) για να συνεχίσετε με τις υπόλοιπες ενημερώσεις',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'αναφέρετε το πρόβλημα (και την επίλυσή του) ώστε να βελτιωθεί το Piwik',
+ 'CoreUpdater_HelpMessageContent' => 'Ελέγξτε τις %s Piwik FAQ %s για συνήθη σφάλματα κατά τη διαδικασία της αναβάθμισης. %s Ρωτήστε τον διαχειριστή του συστήματος και ζητήστε βοήθεια με το σφάλμα το οποίο κατά πάσα πιθανότητα είναι συναφή με τον διακομιστή και την MySQL.',
'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Κρίσιμο σφάλμα κατά τη διαδικασία αναβάθμισης:',
- 'CoreUpdater_HelpMessageIntroductionWhenError' => 'Το παραπάνω είναι το μήνυμα λάθους του πυρήνα. Λογικά πρέπει να βοηθάει την επεξήγηση της αιτίας, αλλά αν θέλετε περισσότερες πληροφορίες:',
- 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Η αναβάθμιση ολοκληρώθηκε με επιτυχία, αλλά υπήρξαν κάποια θέματα κατά τη διάρκεια. Παρακαλώ διαβάστε τις παραπάνω περιγραφές για τις λεπτομέριες. Για περισσότερη βοήθεια:',
+ 'CoreUpdater_HelpMessageIntroductionWhenError' => 'Το παραπάνω είναι το μύνημα λάθους του πυρήνα. Λογικά πρέπει να βοηθάει την επεξήγηση της αιτίας, αλλά αν θέλετε περισσότερες πληροφορίες:',
+ 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Η αναβάθμιση ολοκληρώθηκε με επιτυχία, αλλά υπήρξαν κάποια θέματα κατά τη διάρκεια. Παρακαλώ διαβάστε τις παραπάνω περιγραφές για τις λεπτομέρειες. Για περισσότερη βοήθεια:',
'CoreUpdater_UpgradeComplete' => 'Η αναβάθμιση ολοκληρώθηκε!',
'CoreUpdater_WarningMessages' => 'Προειδοποιητικά μηνύματα:',
'CoreUpdater_ErrorDuringPluginsUpdates' => 'Σφάλμα κατά την αναβάθμιση των πρόσθετων:',
'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Απενεργοποιήθηκαν τα παρακάτω πρόσθετα: %s',
'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Το Piwik αναβαθμίστηκε επιτυχώς!',
'CoreUpdater_ContinueToPiwik' => 'Συνέχεια στο Piwik',
+ 'CoreUpdater_UpdateAutomatically' => 'Αυτόματη ενημέρωση',
+ 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Υπάρχει νέα έκδοση του Piwik διαθέσιμη για λήψη',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Μπορείτε να αναβαθμίσετε στην έκδοση %s αυτόματα ή λάβετε το πακέτο και εγκαταστήστε τη χειροκίνητα:',
+ 'CoreUpdater_DownloadX' => 'Λήψη %s',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Η Αναβάθμιση με Ένα Κλικ ακυρώθηκε. Αν δεν μπορείτε να διορθώσετε το παραπάνω σφάλμα, σας προτείνουμε να αναβαθμίσετε το Piwik χειροκίνητα. %s Διαβάστε την %sΤεκμηρίωση Αναβάθμισης%s για να ξεκινήσετε!',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Λήψη αναβάθμισης από %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Αποσυμπίεση της αναβάθμισης',
+ 'CoreUpdater_VerifyingUnpackedFiles' => 'Επιβεβαίωση των ασυμπίεστων αρχείων',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Δημιουργία εφεδρείας του αρχείου ρυθμίσεων στο %s',
+ 'CoreUpdater_InstallingTheLatestVersion' => 'Εγκατάσταση της τελευταίας έκδοσης',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Το Piwik αναβαθμίστηκε επιτυχώς!',
+ 'CoreUpdater_EmptyDatabaseError' => 'Η βάση δεδομένων %s είναι άδεια. Πρέπει να επεξεργαστείτε ή να διαγράψετε το αρχείο ρυθμίσεων του Piwik.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Η έκδοση του Piwik %s που έχετε είναι η πιο πρόσφατη.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Μη συμβατό συμπιεσμένο αρχείο: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Άδειο συμπιεσμένο αρχείο.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Το συμπιεσμένο αρχείο δεν είναι πλήρες: μερικά αρχεία λείπουν (π.χ. %s).',
+ 'Dashboard_PluginDescription' => 'Ο Κεντρικός σας Πίνακας των Στατιστικών Ιστού. Μπορείτε να προσαρμόσετε τον Κεντρικό σας Πίνακα: προσθήκη νέων μικροεφαρμογών, αλλάγή της διάταξης των μικροεφαρμογών σας. Κάθε χρήστης μπορεί να έχει πρόσβαση στον δικό του προσαρμοσμένο Κεντρικό Πίνακα.',
+ 'Dashboard_Dashboard' => 'Κεντρικός Πίνακας',
+ 'Dashboard_AddWidget' => 'Προσθήκη μικροεφαρμογής...',
+ 'Dashboard_DeleteWidgetConfirm' => 'Είστε σίγουρος ότι θέλετε να αφαιρέσετε αυτή τη μικροεφαρμόγή από τον κεντρικό πίνακα;',
+ 'Dashboard_SelectWidget' => 'Επιλέξτε τη μικροεφαρμογή για προσθήκη στον κεντρικό πίνακα',
+ 'Dashboard_AddPreviewedWidget' => 'Προσθήκη της μικροεφαρμογής της προεπισκόπησης στο πίνακα',
+ 'Dashboard_WidgetPreview' => 'Προεπισκόπηση Μικροεφαρμογή',
+ 'Dashboard_Close_js' => 'Κλείσιμο',
+ 'Dashboard_TitleWidgetInDashboard_js' => 'Η Μικροεφαρμογή είναι ήδη στον κεντρικό πίνακα',
+ 'Dashboard_TitleClickToAdd_js' => 'Πατήστε για προσθήκη στον κεντρικό πίνακα',
+ 'Dashboard_LoadingWidget_js' => 'Φόρτωση μικροεφαρμογής, περιμένετε...',
+ 'Dashboard_WidgetNotFound_js' => 'Η Μικροεφαρμογή δεν βρέθηκε',
+ 'DBStats_PluginDescription' => 'Αυτό το πρόσθετο αναφέρει της βάσης δεδομένων MySQL από τους πίνακες του Piwik.',
'DBStats_DatabaseUsage' => 'Χρήση βάσης δεδομένων',
- 'DBStats_MainDescription' => 'Το Piwik αποθηκεύει όλα τα δεδομένα της ανάλυσης στη βάση δεδομένων της Mysql . Τώρα, οι πίνακες του Piwik χρησιμοποιούν %s.',
+ 'DBStats_MainDescription' => 'Το Piwik αποθηκεύει όλα τα δεδομένα της ανάλυσης στη βάση δεδομένων της Mysql. Τώρα, οι πίνακες του Piwik χρησιμοποιούν %s.',
+ 'DBStats_LearnMore' => 'Για να μάθαιτε περισσότερα για τη διαχείριση δεδομένων του Piwik και πως να κάνετε το Piwik να λειτουργεί καλά για ιστοσελίδες μέσης και υψηλής επισκεψιμότητας, δείτε την τεκμηρίωση %s.',
'DBStats_Table' => 'Πίνακας',
- 'DBStats_RowNumber' => 'Αριθμός σειρών',
+ 'DBStats_RowCount' => 'Αριθμός σειρών',
'DBStats_DataSize' => 'Μέγεθος δεδομένων',
'DBStats_IndexSize' => 'Μέγεθος ευρετηρίου',
'DBStats_TotalSize' => 'Συνολικό μέγεθος',
- 'Dashboard_Dashboard' => 'Πίνακας',
- 'Dashboard_AddWidget' => 'Προσθήκη widget...',
- 'Dashboard_DeleteWidgetConfirm' => 'Είστε σίγουρος ότι θέλετε να αφαιρέσετε αυτό το widget από τον πίνακα?',
- 'Dashboard_SelectWidget' => 'Επιλέξτε το widget για προσθήκη στο πίνακα',
- 'Dashboard_AddPreviewedWidget' => 'Προσθήκη του widget της προεπισκόπησης στο πίνακα',
- 'Dashboard_WidgetPreview' => 'Προεπισκόπηση Widget',
- 'Dashboard_TitleWidgetInDashboard_js' => 'Το Widget είναι ήδη στο πίνακα',
- 'Dashboard_TitleClickToAdd_js' => 'Πατήστε για προσθήκη στο πίνακα',
- 'Dashboard_LoadingPreview_js' => 'Φόρτωση προεπισκόπησης, παρακαλώ περιμένετε...',
- 'Dashboard_LoadingWidget_js' => 'Φόρτωση widget, παρακαλώ περιμένετε...',
- 'Dashboard_WidgetNotFound_js' => 'Το Widget δεν βρέθηκε',
+ 'ExampleAPI_PluginDescription' => 'Πρόσθετο παραδείγματος: Πως να δημιουργήσετε ένα API για το πρόσθετό σας, να εξάγετε τα δεδομένα σας σε πολλές μόρφές χωρίς κάποιον ιδιαίτερο κώδικα;',
+ 'ExampleFeedburner_PluginDescription' => 'Πρόσθετο Παραδείγματος: Πως να προβληθεί η εγγραφή στο Feedburner σε μια Μικροεφαρμογή στον Κεντρικό Πίνακα;',
+ 'ExampleRssWidget_PluginDescription' => 'Πρόσθετο Παραδείγματος: Πως να δημιουργήσετε μια νέα μικροεφαρμογή που διαβάζει μια τροφοδοσία RSS;',
+ 'ExampleUI_PluginDescription' => 'Πρόσθετο Παραδείγματος: Αυτό το πρόσθετο προβάλει πως να δουλεύετε με το περιβάλλον του Piwik: δημιουργία πινάκων, διαγραμμάτων, κλπ.',
+ 'Feedback_PluginDescription' => 'Στείλτε τις Επισημάνσεις σας στην Ομάδα του Piwik. Μοιραστείτε τις ιδέες σας και τις προτάσεις σας με μας!',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Έχετε να αναφέρετε ένα πρόβλημα ή ένα αίτημα για χαρακτηριστικό;',
+ 'Feedback_ViewAnswersToFAQ' => 'Δείτε απαντήσεις στις %s Συχνά Απαντημένες Ερωτήσεις%s',
+ 'Feedback_WhyAreMyVisitsNoTracked' => 'Γιατί δεν παρακολουθούνται οι επισκέψεις στην ιστοσελίδα μου;',
+ 'Feedback_HowToExclude' => 'Πως αποτρέπω την παρακολούθηση των επισκέψεών μου;',
+ 'Feedback_WhyWrongCountry' => 'Γιατί το Piwik προβάλει την επίσκεψή μου από λάθος χώρα;',
+ 'Feedback_HowToAnonymizeIP' => 'Πως μπορώ να δώσω μάσκα στις διευθύνσεις IP των επισκεπτών στη βάση δεδομένων μου;',
+ 'Feedback_VisitTheForums' => 'Επισκευτείτε τις %s Δημόσιες Συζητήσεις%s',
+ 'Feedback_LearnWaysToParticipate' => 'Μάθετε όλους του τρόπους που μπορείτε να %sσυμμετέχετε%s',
+ 'Feedback_SpecialRequest' => 'Έχετε κάποιο ειδικό αίτημα για την ομάδα του Piwik;',
+ 'Feedback_ContactThePiwikTeam' => 'Επικοινωνήστε με την ομάδα του Piwik!',
+ 'Feedback_IWantTo' => 'Θέλω να:',
+ 'Feedback_CategoryShareStory' => 'Μοιραστείτε μια επιτυχή ιστορία του Piwik',
+ 'Feedback_CategorySponsor' => 'Χορηγός του Piwik',
+ 'Feedback_CategoryHire' => 'Προσλάβετε έναν σύμβουλο του Piwik',
+ 'Feedback_CategorySecurity' => 'Αναφέρετε ένα θέμα ασφαλείας',
+ 'Feedback_MyEmailAddress' => 'Η ηλεκτρονική μου διεύθυνση:',
+ 'Feedback_MyMessage' => 'Το μήνυμά μου:',
+ 'Feedback_DetailsPlease' => '(να περιληφθούν λεπτομέρειες)',
+ 'Feedback_SendFeedback' => 'Στείλτε Επισημάνσεις',
+ 'Feedback_ManuallySendEmailTo' => 'Στείλτε χειροκίνητα το μήνυμά σας στον/στην',
+ 'Feedback_MessageSent' => 'Το μήνυμά σας εστάλη στην ομάδα του Piwik.',
+ 'Feedback_ThankYou' => 'Ευχαριστούμε που βοηθήσατε να κάνουμε το Piwik καλύτερο!',
+ 'Feedback_ThePiwikTeam' => 'Η Ομάδα του Piwik',
+ 'Feedback_ExceptionBodyLength' => 'Το μήνυμα πρέπει να είναι τουλάχιστον %s χαρακτήρες.',
+ 'Feedback_ExceptionNoUrls' => 'Το μήνυμα δεν μπορεί να περιέχει URL, για αποφυγεί κακόβουλων μηνυμάτων.',
+ 'Goals_PluginDescription' => 'Δημιουργήστε Στόχους και δείτε αναφορές για τις μετατροπές των στόχων σας: εξέλιξη στο χρόνο, πρόσοδος ανά επίσκεψη, μετατροπές ανά αναφορέα, ανά κλειδί, κλπ.',
+ 'Goals_ColumnConversions' => 'Μετατροπές',
+ 'Goals_ColumnConversionRate' => 'Βαθμός μετατροπής',
+ 'Goals_ColumnRevenue' => 'Πρόσοδος',
+ 'Goals_OverallRevenue' => '%s καθολική πρόσοδος',
+ 'Goals_OverallConversionRate' => '%s καθολικός βαθμός προσόδου (επισκέψεις με έναν πλήρη στόχο)',
+ 'Goals_Conversions' => '%s μετατροπές',
+ 'Goals_ConversionRate' => '%s βαθμός μετατροπής',
+ 'Goals_NoGoalsNeedAccess' => 'Μόνο ο Διαχειριστής ή ένας Υπερχρήστης μπορεί να προσθέσει Στόχους γιαν μια ιστοσελίδα. Ρωτήστε τον Διαχειριστή του Piwik για να ορίσει έναν Στόχο για την ιστοσελίδα σας.<br>Οι Στόχοι Παρακολούθησης είναι ένας καλός τρόπος που βοηθάει να καταλάβετε και μεγιστοποιήσετε την απόδοση της ιστοσελίδας σας!',
+ 'Goals_AddNewGoal' => 'Προσθήκη νέου Στόχου',
+ 'Goals_AddNewGoalOrEditExistingGoal' => '%sΠροσθέστε έναν νέο Στόχο%s ή %sΕπεξεργαστείτε%s υπάρχοντες Στόχους',
+ 'Goals_AddGoal_js' => 'Προσθήκη Στόχου',
+ 'Goals_UpdateGoal_js' => 'Ενημέρωση Στόχου',
+ 'Goals_DeleteGoalConfirm_js' => 'Είστε σίγουροι ότι θέλετε να διαγράψετε το Στόχο %s;',
+ 'Goals_GoalName' => 'Ονομασία Στόχου',
+ 'Goals_GoalIsTriggered' => 'Ο στόχος να ενεργοποιείται',
+ 'Goals_GoalIsTriggeredWhen' => 'Ο Στόχος ενεργοποιείτε όταν',
+ 'Goals_WhenVisitors' => 'όταν οι επισκέψεις αφορούν',
+ 'Goals_Manually' => 'χειροκίνητα',
+ 'Goals_ManuallyTriggeredUsingJavascriptFunction' => 'Ο Στόχος ενεργοποιείτε χειροκίνητα με χρήση του Javascript API trackGoal()',
+ 'Goals_VisitUrl' => 'ένα δοθέν URL (σελίδα ή ομάδα σελίδων)',
+ 'Goals_Download' => 'τη λήψη ενός αρχείου',
+ 'Goals_ClickOutlink' => 'το πάτημα Συνδέσμου σε εξωτερική ιστοσελίδα',
+ 'Goals_Optional' => '(προαιρετικό)',
+ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => 'όπου η επισκεπτόμενη σελίδα περιέχει μια κλήση στη μέθοδο Javascript piwikTracker.trackGoal() (%sμάθετε περισσότερα%s)',
+ 'Goals_DefaultRevenue' => 'Η προεπιλεγμένη πρόσοδος του στόχου είναι',
+ 'Goals_DefaultRevenueHelp' => 'Για παράδειγμα, μια Φόρμα Επικοινωνίας που υποβλήθηκε από έναν επισκέπτη μπορεί να αξίζει 10€ κατά μέσο όρο. Το Piwik θα σας βοηθήσει να καταλάβετε πως λειτουργούν τα τμήματα των χρηστών σας.',
+ 'Goals_ConversionsOverview' => 'Επισκόπηση μετατροπών',
+ 'Goals_BestCountries' => 'Οι καλύτερες χώρες μετατροπής είναι:',
+ 'Goals_BestKeywords' => 'Οι κορυφαίες λέξεις-κλειδιά μετατροπής είναι:',
+ 'Goals_BestReferers' => 'Οι καλύτεροι αναφορείς ιστοσελίδων μετατροπής είναι:',
+ 'Goals_ReturningVisitorsConversionRateIs' => 'Ο βαθμός μετατροπής επιστρεφόμενων επισκεπτών είναι %s',
+ 'Goals_NewVisitorsConversionRateIs' => 'Ο βαθμός μετατροπής νέων επισκεπτών είναι %s',
+ 'Goals_Contains' => 'περιέχει %s',
+ 'Goals_IsExactly' => 'είναι ακριβώς %s',
+ 'Goals_MatchesExpression' => 'ταιριάζει στην έκφραση %s',
+ 'Goals_CaseSensitive' => 'Ταίριασμα πεζών-κεφαλαίων',
+ 'Goals_Pattern' => 'Υπόδειγμα',
+ 'Installation_PluginDescription' => 'Διαδικασία εγκατάστασης του Piwik. Η Εγκατάσταση γίνεται συνήθως μόνο μια φορά. Αν το αρχείο ρυθμίσεων config/config.inc.php έχει διαγραφεί, η εγκατάσταση θα ξεκινήσει από την αρχή.',
'Installation_Installation' => 'Εγκατάσταση',
'Installation_InstallationStatus' => 'Κατάσταση εγκατάστασης',
- 'Installation_PercentDone' => '%s %% Έγινε',
- 'Installation_NoConfigFound' => 'The Piwik configuration file couldn\'t be found and you are trying to access a Piwik page.<br /><b>&nbsp;&nbsp;&raquo; You can <a href=\'index.php\'>install Piwik now</a></b><br /><small>If you installed Piwik before and have some tables in your DB, don\'t worry, you can reuse the same tables and keep your existing data!</small>',
- 'Installation_MysqlSetup' => 'Mysql database setup',
- 'Installation_MysqlErrorConnect' => 'Σφάλμα κατά την προσπάθεια σύνδεσης με της βάση δεδομένων της Mysql',
- 'Installation_JsTag' => 'Javascript tag',
- 'Installation_JsTagHelp' => '<p>Για να γίνει σωστή καταμέτρηση όλων των επισκεπτών, πρέπει να εισάγετε τον κώδικα Javascript σε όλες σας τις σελίδες.</p><p>Οι σελίδες σας δεν είναι ανάγκη να είναι γραμμένες σε PHP, το Piwik θα δουλέψει σε σελίδες όλων των ειδών (είτε είναι HTML, ASP, Perl ή οποιαδήποτε άλλη γλώσσα προγραμματισμού).</p><p>Ορίστε ο κώδικας που πρέπει να εισάγετε: (αντιγράψτε και επικολλήστε σε όλες τις σελίδες σας) </p>',
+ 'Installation_PercentDone' => '%s %% Ολοκληρώθηκε',
+ 'Installation_NoConfigFound' => 'Το αρχείο ρυθμίσεων του Piwik δεν βρέθηκε και προσπαθείτε να ανοίξετε μια σελίδα Piwik.<br /><b>&nbsp;&nbsp;&raquo; Μπορείτε να <a href=\'index.php\'>εγκαταστήσετε το Piwik τώρα</a></b><br /><small>αν έχετε εγκαταστήσει το Piwik προηγούμενα και έχετε κάποιους πίνακες στη βάση δεδομένων σας, μην ανησυχείτε, μπορείτε να χρησιμοποιήσετε ξανά τους ίδους πίνακες και να διατηρείσετε τα υπάρχοντα δεδομένα σας!</small>',
+ 'Installation_DatabaseSetup' => 'Εγκατάσταση βάσης δεδομένων',
+ 'Installation_DatabaseSetupServer' => 'Διακομιστής βάσης δεδομένων',
+ 'Installation_DatabaseSetupLogin' => 'Όνομα χρήστη',
+ 'Installation_DatabaseSetupPassword' => 'Κωδικός πρόσβασης',
+ 'Installation_DatabaseSetupDatabaseName' => 'Ονομασία βάσης δεδομένων',
+ 'Installation_DatabaseSetupTablePrefix' => 'Πρόθεμα πινάκων',
+ 'Installation_DatabaseSetupAdapter' => 'Προσαρμογέας',
+ 'Installation_DatabaseErrorConnect' => 'Σφάλμα κατά την προσπάθεια σύνδεσης στο διακομιστή βάσεων δεδομένων',
+ 'Installation_DatabaseCheck' => 'Έλεγχος βάσης δεδομένων',
+ 'Installation_DatabaseServerVersion' => 'Έκδοση διακομιστή βάσεων δεδομένων',
+ 'Installation_DatabaseClientVersion' => 'Έκδοση πελάτη βάσεων δεδομένων',
+ 'Installation_DatabaseCreation' => 'Δημιουργία βάσεων δεδομένων',
+ 'Installation_PleaseFixTheFollowingErrors' => 'Διορθώστε τα ακόλουθα σφάλματα',
+ 'Installation_JsTag' => 'Ετικέτα Javascript',
+ 'Installation_JsTagHelp' => '<p>Για να γίνει σωστή καταμέτρηση όλων των επισκεπτών, πρέπει να εισάγετε τον κώδικα Javascript σε όλες σας τις σελίδες.</p><p>Οι σελίδες σας δεν είναι ανάγκη να είναι γραμμένες σε PHP, το Piwik θα δουλέψει σε σελίδες όλων των ειδών (είτε είναι HTML, ASP, Perl ή οποιαδήποτε άλλη γλώσσα προγραμματισμού).</p><p>Ορίστε ο κώδικας που πρέπει να εισάγετε: (αντιγράψτε και επικολλήστε σε όλες τις σελίδες σας)</p>',
+ 'Installation_JsTagHelpTitle' => 'Πως να εισάγετε την ετικέτα στις ιστοσελίδες σας;',
+ 'Installation_LargePiwikInstances' => 'Βοήθεια για μεγάλες περιπτώσεις Piwik',
+ 'Installation_JsTagArchivingHelp' => 'Για μεσσαίας και μεγάλης επισκεψιμότητας ιστοσελίδες, δείτε το άρθρο: <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">Πως να εγκαταστήσετε τη σελίδα αυτόματης αρχειοθέτησης</a> για να κάνετε το Piwik να τρέχει πραγματικά γρήγορα!',
'Installation_Congratulations' => 'Συγχαρητήρια',
'Installation_CongratulationsHelp' => '<p>Συγχαρητήρια! Η εγκατάσταση του Piwik έχει ολοκληρωθεί.</p><p>Σιγουρευτείτε ότι ο κώδικας Javascript έχει εισηχθεί στις ιστοσελίδες και περιμένετε για τους πρώτους επισκέπτες σας!</p>',
'Installation_ContinueToPiwik' => 'Συνέχεια στο Piwik',
'Installation_SetupWebsite' => 'Ρύθμιση μιας ιστοσελίδας',
+ 'Installation_SetupWebSiteName' => 'ονομασία ιστοσελίδας',
+ 'Installation_SetupWebSiteURL' => 'URL ιστοσελίδας',
+ 'Installation_Timezone' => 'Ζώνη ώρας ιστοσελίδας',
'Installation_SetupWebsiteError' => 'Συνέβη ένα σφάλμα κατά της προσθήκη του ιστοχώρου',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Η ιστοσελίδα %s δημιουργήθηκε με επιτυχία!',
'Installation_GeneralSetup' => 'Γενικές ρυθμίσεις',
'Installation_GeneralSetupSuccess' => 'Οι γενικές ρυθμίσεις πραγματοποιήθηκαν με επιτυχία',
+ 'Installation_SuperUserLogin' => 'Σύνδεση υπερχρήστη',
+ 'Installation_Password' => 'Κωδικός πρόσβασης',
+ 'Installation_PasswordRepeat' => 'Επανάληψη κωδικού πρόσβασης',
+ 'Installation_Email' => 'Ηλεκτρονική διεύθυνση',
+ 'Installation_SecurityNewsletter' => 'Ενεργοποίηση αλληλογραφίας για τις βασικές αναβαθμίσεις του Piwik και ειδοποιήσεις ασφάλειας',
+ 'Installation_CommunityNewsletter' => 'Ενεργοποίηση αλληλογραφίας για ενημερώσεις της κοινότητας (νέα πρόσθετα, νέα χαρακτηριστικά, κλπ.)',
+ 'Installation_PasswordDoNotMatch' => 'ο κωδικός δεν ταιριάζει',
+ 'Installation_SubmitGo' => 'Υποβολή!',
+ 'Installation_Requirements' => 'Απαιτήσεις Piwik',
+ 'Installation_Optional' => 'Προαιρετικά',
+ 'Installation_Legend' => 'Υπόμνημα',
+ 'Installation_Extension' => 'επέκταση',
'Installation_SystemCheck' => 'Έλεγχος συστήματος',
'Installation_SystemCheckPhp' => 'Έκδοση PHP',
- 'Installation_SystemCheckPdo' => 'Επέκταση Pdo',
- 'Installation_SystemCheckPdoMysql' => 'Επέκταση Pdo_Mysql',
- 'Installation_SystemCheckPdoError' => 'Πρέπει να ενεργοποιήσετε τις επεκτάσεις PDO και PDO_MYSQL στο αρχείο php.ini',
- 'Installation_SystemCheckPdoHelp' => 'Σε ένα διακομιστή με Γουίντοουζ μπορείτε να προσθέσετε τις ακόλουθες γραμμές στο αρχείο php.ini %s <br /><br />Σε ένα διακομιστή με Λίνουξ μπορείτε να κάνετε compile την php με την ακόλουθη παράμετρο %s Μέσα στο αρχείο php.ini, προσθέστε τις ακόλουθες γραμμές %s<br /><br />Περισσότερες πληροφορίες μπορείτε να δείτε στον <a style="color:red" href="http://php.net/pdo">ιστοχώρο της PHP</a>.',
+ 'Installation_SystemCheckExtensions' => 'Άλλες απαιτούμενες επεκτάσεις',
+ 'Installation_SystemCheckDatabaseHelp' => 'Το Piwik απαιτεί είτε την επέκταση mysqli ή τις επεκτάσεις PDO και pdo_mysql.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'Σε διακομιστή Linux μπορείτε να εγκαταστήσετε την php με τις ακόλουθες επιλογές: %1\$s\n Στο αρχείο php.ini, προσθέστε τις ακόλουθες γραμμές: %2\$s',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Περισσότερες πληροφορίες στο: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> και <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'Σε διακομιστή Windows μπορείτε να προσθέσετε τις ακόλουθες γραμμές στο αρχείο php.ini: %s',
+ 'Installation_SystemCheckSplHelp' => 'Πρέπει να ρυθμίσετε και ξαναεγκαταστήσετε την PHP με τη Βασική Βιβλιοθήκη PHP (SPL) ενεργοποιήμένη (ως προεπιλογή).',
+ 'Installation_SystemCheckZlibHelp' => 'Πρέπει να ρυθμίσετε και ξαναεγκαταστήσετε την PHP με ενεργοποιημένη την υποστήριξη «zlib», --with-zlib.',
+ 'Installation_SystemCheckIconvHelp' => 'Πρέπει να ρυθμίσετε και ξαναεγκαταστήσετε την PHP με ενεργοποιημένη την υποστήριξη «iconv», --with-iconv.',
+ 'Installation_SystemCheckDomHelp' => 'Το DOM είναι τμήμα του πυρήνα PHP. Ίσως να χρειάζεται να εγκαταστήσετε το πρότυπο dom, π.χ.: php-5-dom.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'Πρέπει να ρυθμίσετε και ξαναεγκαταστήσετε την PHP με ενεργοποιημένη την επέκταση «json» ή «xml».',
+ 'Installation_SystemCheckJsonSite' => 'Περισσότερες πληροφορίες στο: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Κάποια πρόσθετα τρίτων και βιβλιοθήκες απαιτούν την επέκταση «xml».',
+ 'Installation_SystemCheckXmlSite' => 'Περισσότερες πληροοφορίες στο: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
'Installation_SystemCheckWriteDirs' => 'Υποφάκελοι με δικαίωμα εγγραφής',
- 'Installation_SystemCheckWriteDirsHelp' => 'Για να διορθώσετε αυτό το σφάλμα στο Λίνουξ σύστημά σας δοκιμάστε να πληκτρολογήσετε τις ακόλουθες εντολές',
+ 'Installation_SystemCheckWriteDirsHelp' => 'Για να διορθώσετε αυτό το σφάλμα στο Linux σύστημά σας δοκιμάστε να πληκτρολογήσετε τις ακόλουθες εντολές',
'Installation_SystemCheckMemoryLimit' => 'Όριο μνήμης',
- 'Installation_SystemCheckMemoryLimitHelp' => 'On a high traffic website, the archiving process may require more memory than currently allowed.<br />See the directive memory_limit in your php.ini file if necessary.',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'Σε μια ιστοσελίδα υψηλής επισκεψιμότητας, η διαδικασία αρχειοθέτησης ίσως απαιτεί περισσότερη μνήμη από την επιτρεπόμενη.<br />Δείτε την οδηγία memory_limit στο αρχέιο php.ini αν είναι απαραίτητο.',
+ 'Installation_SystemCheckOpenURL' => 'Άνοιγμα URL',
+ 'Installation_SystemCheckOpenURLHelp' => 'Εγγραφές Newsletter, ειδοποιήσεις ενημερώσεων και οι ενημερώσεις ενός κλικ απαιτούν την επέκτασση «curl», ενεργοποιήστε το allow_url_fopen=On ή το fsockopen().',
'Installation_SystemCheckGD' => 'GD &gt; 2.x (γραφικά)',
- 'Installation_SystemCheckGDHelp' => 'Οι κορυφογραμμές (μικρά γραφήματα) δεν θα δουλεύουν.',
- 'Installation_SystemCheckTimeLimit' => 'set_time_limit() επιτρέπεται',
- 'Installation_SystemCheckTimeLimitHelp' => 'Σε ιστοχώρους με μεγάλη κίνηση, όταν διενεργείται η αποθήκευση ασφαλείας μπορεί να δαπανήσει περισσότερο χρόνο από ότι είναι προς το παρόν επιτρεπτό.<br />Δείτε την οδηγία max_execution_time στο αρχείο php.ini αν είναι απαραίτητο',
- 'Installation_SystemCheckMail' => 'mail() επιτρέπεται',
+ 'Installation_SystemCheckGDHelp' => 'Οι κορυφογραμμές (μικρά γραφήματα) δεν θα λειτουργούν.',
+ 'Installation_SystemCheckFunctions' => 'Απαιτούμενες συναρτήσεις',
+ 'Installation_SystemCheckTimeLimitHelp' => 'Σε ιστοσελίδες με μεγάλη επισκεψιμότητα, όταν διενεργείται η αποθήκευση ασφαλείας μπορεί να δαπανήθει περισσότερος χρόνος από ότι είναι προς το παρόν επιτρεπτό.<br />Δείτε την οδηγία max_execution_time στο αρχείο php.ini αν είναι απαραίτητο',
+ 'Installation_SystemCheckMailHelp' => 'Τα μηνύματα με τις παρατηρήσεις σας και για τους Ξεχασμένους Κωδικούς δεν θα στέλνονται αν δεν είναι ενεργοποιημένη η συνάρτηση mail().',
+ 'Installation_SystemCheckParseIniFileHelp' => 'Αυτή η εσωτερική συνάρτηση έχει απενεργοποιηθεί στον διακομιστή σας. Το Piwik θα προσπαθήσει να εξομοιώσει αυτή τη συνάρτηση αλλά ίσως προκύψουν περαιτέρω περιορισμοί ασφάλειας. Η απόδοση της ανίχνευσης θα επηρεαστεί.',
+ 'Installation_SystemCheckDebugBacktraceHelp' => 'Η εντολή View::factory δεν θα μπορεί να δημιουργήσει προβολές για το κληθέν πρότυπο.',
+ 'Installation_SystemCheckCreateFunctionHelp' => 'Το Piwik χρησιμοποιεί ανώνυμες συναρτήσεις για ανακλήσεις.',
+ 'Installation_SystemCheckMbstring' => 'mbstring',
+ 'Installation_SystemCheckMbstringHelp' => 'Πρέπει να ορίσετε την μεταβλητή mbstring.func_overload στο «0».',
+ 'Installation_SystemCheckFileIntegrity' => 'Ακεραιότητα αρχείων',
'Installation_SystemCheckError' => 'Συνέβη ένα σφάλμα – πρέπει να διορθωθεί πριν συνεχίσετε',
'Installation_SystemCheckWarning' => 'Το Piwik θα δουλεύει κανονικά αλλά θα λείπουν κάποιες λειτουργίες',
+ 'Installation_SystemCheckProtocol' => 'Πρωτόκολλο',
+ 'Installation_SystemCheckProtocolHelp' => 'Αν είστε πίσω από ανάστροφο proxy, προσθέστε αυτές τις γραμμές στο αρχείο config/config.ini.php στον τομέα [General]:',
+ 'Installation_SystemCheckIpv4' => 'IPv4',
+ 'Installation_SystemCheckIpv4Help' => 'Πρέπει να απενεργοποιήσετε το IPv6 στις ρυθμίσεις του διακομιστή σας.',
'Installation_Tables' => 'Δημιουργία πινάκων',
- 'Installation_TablesWarning' => 'Κάποιοι <span id="linkToggle">Πίνακες του Piwik</span> είναι ήδη εγκατεστημένοι στη βάση δεδομένων',
+ 'Installation_TablesWithSameNamesFound' => 'Μερικοί πίνακες %s στη βάση δεδομένων σας %s έχουν τα ίδια ονόματα με τους πίνακες που προσπαθεί να δημιουργήσει το Piwik',
'Installation_TablesFound' => 'Οι ακόλουθοι πίνακες βρέθηκαν εντός της βάσης δεδομένων',
'Installation_TablesWarningHelp' => 'Επιλέξτε να χρησιμοποιήσετε την υπάρχουσα βάση δεδομένων ή επιλέξτε να κάνετε μία καθαρή εγκατάσταση έτσι ώστε να καθαρίσει η βάση δεδομένων από όλα τα δεδομένα.',
'Installation_TablesReuse' => 'Χρήση υπαρχόντων πινάκων',
'Installation_TablesDelete' => 'Διαγραφή των πινάκων που ανιχνεύθηκαν',
- 'Installation_TablesDeletedSuccess' => 'Υπάρχον πίνακες του Piwik διαγράφηκαν με επιτυχία',
+ 'Installation_TablesDeletedSuccess' => 'Οι υπάρχοντες πίνακες του Piwik διαγράφηκαν με επιτυχία',
'Installation_TablesCreatedSuccess' => 'Οι πίνακες δημιουργήθηκαν επιτυχώς!',
'Installation_DatabaseCreatedSuccess' => 'Η βάση δεδομένων %s δημιουργήθηκε επιτυχώς!',
- 'Installation_TablesDeleteConfirm' => 'Είστε σίγουρος ότι θέλετε να διαγράψετε όλους τους πίνακες του Piwik από αυτή τη βάση δεδομένων?',
+ 'Installation_GoBackAndDefinePrefix' => 'Επιστρέψτε και ορίστε ένα Πρόθεμα για τους Πίνακες του Piwik',
+ 'Installation_ConfirmDeleteExistingTables' => 'Θέλετε σίγουρα να διαγράψετε τους πίνακες: %s από τη βάση δεδομένων σας; ΠΡΟΕΙΔΟΠΟΙΗΣΗ: ΤΑ ΔΕΔΟΜΕΝΑ ΑΠΟ ΑΥΤΟΥΣ ΤΟΥ ΠΙΝΑΚΕΣ ΔΕΝ ΘΑ ΜΠΟΡΟΥΝ ΝΑ ΑΝΑΚΤΗΘΟΥΝ!',
'Installation_Welcome' => 'Καλωσορίσατε!',
'Installation_WelcomeHelp' => '<p>Το Piwik είναι ένα λογισμικό ανοιχτού κώδικα ανάλυσης ιστοσελίδων που συλλέγει τις πληροφορίες που θέλετε από του επισκέπτες σας.</p><p>Αυτή η διαδικασία είναι χωρισμένη σε %s απλά βήματα και θα πάρει περίπου 5 λεπτά.</p>',
+ 'Installation_ConfigurationHelp' => 'Οι ρυθμίσες του Piwik φαίνεται ότι έχουν πρόβλημα. Μπορείτε να απομακρύνετε το config/config.ini.php και να συνεχίσετε την εγκατάσταση ή διορθώστε τις ρυθμίσεις σύνδεσης της βάσης δεδομένων.',
+ 'Installation_ErrorInvalidState' => 'Σφάλμα: φαίνεται ότι προσπαθείτε να παραλείψετε ένα βήμα από τη διαδικασία εγκατάστασης ή τα cookies είναι απενεργοποιημένα ή έχει ήδη δημιουργηθεί το αρχείο ρυθμίσεων του Piwik. %sΣιγουρευτείτε ότι τα cookies είναι ενεργοποιημένα%s και επιστρέψτε %s στην πρώτη σελίδα της εγκατάστασης %s.',
+ 'LanguagesManager_PluginDescription' => 'Αυτό το πρόσθετο θα προβάλει μια λίστα με τις διαθέσιμες γλώσσες για το περιβάλλον του Piwik. Η επιλεχθείσα γλώσσα θα αποθηκευτεί στις προτιμήσεις κάθε χρήστη.',
+ 'LanguagesManager_AboutPiwikTranslations' => 'Σχετικά με τις μεταφράσεις του Piwik',
+ 'Live_PluginDescription' => 'Κατασκοπεύστε τους επισκέπτες σας, ζωντανά και σε πραγματικό χρόνο!',
+ 'Live_VisitorLog' => 'Καταγραφή Επισκεπτών',
+ 'Live_Date' => 'Ημερομηνία',
+ 'Live_Time' => 'Ώρα',
+ 'Live_Referrer_URL' => 'URL Αναφορέα',
+ 'Login_PluginDescription' => 'Το πρόσθετο Πιστοποίησης χρήστη, διαβάζει τα απαραίτητα από το αρχείο config/config.inc.php για τον υπερχρήστη και από τη βάση δεδομένων για τους άλλους χρήστες. Μπορεί εύκολα να αντικατασταθεί και να προταθεί ένας νέος μηχανισμός πιστοποίησης (OpenID, htaccess, custom Auth, κλπ.).',
'Login_LoginPasswordNotCorrect' => 'Το όνομα χρήστη και ο κωδικός δεν είναι σωστά',
- 'Login_Login' => 'Όνομα χρήστη',
'Login_Password' => 'Κωδικός',
- 'Login_LoginOrEmail' => 'Χρήστης ή E-mail',
+ 'Login_PasswordRepeat' => 'Κωδικός (επανάληψη)',
+ 'Login_ChangePassword' => 'Αλλαγή κωδικού',
+ 'Login_LoginOrEmail' => 'Χρήστης ή Ηλεκτρονική διεύθυνση',
'Login_LogIn' => 'Σύνδεση',
'Login_Logout' => 'Αποσύνδεση',
- 'Login_LostYourPassword' => 'Ξεχάσατε τον κωδικό σας?',
+ 'Login_LostYourPassword' => 'Ξεχάσατε τον κωδικό σας;',
'Login_RemindPassword' => 'Υπενθύμιση κωδικού',
+ 'Login_PasswordResetToken' => 'Τεκμήριο επαναφοράς κωδικού',
'Login_PasswordReminder' => 'Παρακαλώ συμπληρώστε το όνομα χρήστη και την ηλεκτρονική σας διεύθυνση. Θα λάβετε ένα μήνυμα που θα περιέχει ένα νέο κωδικό.',
+ 'Login_PasswordsDoNotMatch' => 'Οι κωδικοί δεν ταιριάζουν.',
+ 'Login_PasswordSuccessfullyChanged' => 'Ο κωδικός άλλαξε με επιτυχία!',
'Login_InvalidUsernameEmail' => 'Λανθασμένο όνομα χρήστη ή/και λάθος ηλεκτρονική διεύθυνση',
+ 'Login_InvalidNonceOrReferer' => 'Το κλειδί ασφαλείας της φόρμας είναι άκυρο ή έχει λήξει. Επαναφορτώστε πάλι τη φόρμα και ελέξτε αν είναι ενεργοποιημένα τα cookies.',
+ 'Login_InvalidOrExpiredToken' => 'Το τεκμήριο είναι άκυρο ή έχει λήξει',
'Login_MailTopicPasswordRecovery' => 'Ανάκτηση κωδικού',
'Login_MailPasswordRecoveryBody' => 'Γεια σας %1s, \n\n Ο νέος σας κωδικός είναι: %2s \n\n Συνδεθείτε εδώ: %3s',
- 'Login_PasswordSent' => 'Ο κωδικός σας μόλις απεστάλη. Ελέγξτε τα μηνύματά σας.',
- 'Login_ContactAdmin' => 'Πιθανή αιτία: ο διακομιστής έχει απενεργοποιημένη τη διαδικασία mail() <br />Παρακαλώ επικοινωνήστε με τον διαχειριστή.',
+ 'Login_PasswordSent' => 'Ο κωδικός σας μόλις απεστάλη. Ελέγξτε την αλληλογραφία σας.',
+ 'Login_ContactAdmin' => 'Πιθανή αιτία: ο διακομιστής έχει απενεργοποιημένη τη συνάρτηση mail() <br />Επικοινωνήστε με τον διαχειριστή.',
+ 'MultiSites_PluginDescription' => 'Προβάλει ενεργή περίληψη/στατιστικά πολλών ιστοσελίδων. Προς το παρόν διατηρείτε ως πρόσθετο του πυρήνα του Piwik.',
+ 'Provider_PluginDescription' => 'Αναφέρει τον Παροχέα των επισκεπτών.',
'Provider_WidgetProviders' => 'Πάροχοι',
+ 'Provider_ColumnProvider' => 'Πάροχος',
'Provider_SubmenuLocationsProvider' => 'Τοποθεσίες & πάροχοι',
- 'Referers_Referers' => 'Referers',
+ 'Referers_PluginDescription' => 'Αναφέρει τα δεδομένα των Αναφορέων: Μηχανές Αναζήτησης, Λέξεις-κλειδιά, Ιστοσελίδες, Ανίχνευση Εκστρατειών, Άμεση είσοδος.',
+ 'Referers_Referers' => 'Αναφορείς',
'Referers_SearchEngines' => 'Μηχανές αναζήτησης',
- 'Referers_Keywords' => 'Λέξεις κλειδιά',
+ 'Referers_Keywords' => 'Λέξεις-κλειδιά',
'Referers_DirectEntry' => 'Απευθείας είσοδος',
- 'Referers_Websites' => 'Ιστοχώροι',
+ 'Referers_Websites' => 'Ιστοσελίδες',
'Referers_Campaigns' => 'Εκστρατείες',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%s (από %s)',
'Referers_Evolution' => 'Εξέλιξη εντός περιόδου',
- 'Referers_Type' => 'Referer Type',
+ 'Referers_Type' => 'Τύπος αναφορέα',
+ 'Referers_ColumnRefererType' => 'Τύπος Αναφορέα',
+ 'Referers_ColumnSearchEngine' => 'Μηχανή Αναζήτησης',
+ 'Referers_ColumnWebsite' => 'Ιστοσελίδα',
+ 'Referers_ColumnWebsitePage' => 'Σελίδα Ιστοσελίδας',
+ 'Referers_ColumnKeyword' => 'Λέξη-κλειδί',
+ 'Referers_ColumnCampaign' => 'Εκστρατεία',
+ 'Referers_DetailsByRefererType' => 'Λεπτομέρειες για τον Τύπο Αναφορέα',
'Referers_TypeDirectEntries' => '%s απευθείας είσοδοι',
'Referers_TypeSearchEngines' => '%s από μηχανές αναζήτησης',
'Referers_TypeWebsites' => '%s από ιστοσελίδες',
'Referers_TypeCampaigns' => '%s από εκστρατείες',
- 'Referers_Other' => 'Άλλο',
- 'Referers_OtherDistinctSearchEngines' => '%s διακριτές μηχανές αναζήτησης',
- 'Referers_OtherDistinctKeywords' => '%s διακριτές λέξεις κλειδιά',
- 'Referers_OtherDistinctWebsites' => '%1s διακριτές ιστοσελίδες (χρήση %2s διακριτών url)',
- 'Referers_OtherDistinctCampaigns' => '%s διακριτές εκστρατείες',
- 'Referers_TagCloud' => 'Έξοδος σύννεφου λέξεων',
+ 'Referers_Distinct' => 'Διαχωρισμός Αναφορέων ανά Τύπο Αναφορέα',
+ 'Referers_DistinctSearchEngines' => 'διαχωρισμός μηχανών αναζήτησης',
+ 'Referers_DistinctKeywords' => 'διαχωρισμός λέξεων-κλειδιών',
+ 'Referers_DistinctCampaigns' => 'διαχωρισμός εκστρατειών',
+ 'Referers_DistinctWebsites' => 'διαχωρισμός σελίδων',
+ 'Referers_UsingNDistinctUrls' => '(χρήσηusing %2s urls διαχωρισμού)',
'Referers_SubmenuEvolution' => 'Εξέλιξη',
- 'Referers_SubmenuSearchEngines' => 'Μηχανές αναζήτησης & λέξεις κλειδιά',
- 'Referers_SubmenuWebsites' => 'Ιστοχώροι',
+ 'Referers_SubmenuSearchEngines' => 'Μηχανές αναζήτησης & λέξεις-κλειδιά',
+ 'Referers_SubmenuWebsites' => 'Ιστοσελίδες',
'Referers_SubmenuCampaigns' => 'Εκστρατείες',
- 'Referers_WidgetKeywords' => 'Λίστα λέξεων κλειδιών',
+ 'Referers_WidgetKeywords' => 'Λίστα λέξεων-κλειδιών',
'Referers_WidgetCampaigns' => 'Λίστα εκστρατειών',
- 'Referers_WidgetExternalWebsites' => 'Λίστα εξωτερικών ιστοχώρων',
+ 'Referers_WidgetExternalWebsites' => 'Λίστα εξωτερικών ιστοσελίδων',
'Referers_WidgetSearchEngines' => 'Καλύτερες μηχανές αναζήτησης',
'Referers_WidgetOverview' => 'Συνολική εικόνα',
- 'SitesManager_Sites' => 'Ιστοχώροι',
- 'SitesManager_WebsitesManagement' => 'Διαχείριση ιστοχώρων',
- 'SitesManager_MainDescription' => 'Το σύστημα αναλυτικών αναφορών χρειάζεται ιστοχώρους! Προσθέστε, ενημερώστε, διαγράψτε ιστοχώρους και εμφανίστε τον κώδικα Javascript που θα εισηχθεί στις ιστοσελίδες σας.',
- 'SitesManager_JsCode' => 'Κώδικας Javascript',
- 'SitesManager_JsCodeHelp' => 'Να ο κώδικας της Javascript για εισαγωγή σε όλες τις σελίδες σας',
- 'SitesManager_ShowJsCode' => 'εμφάνιση κώδικα',
- 'SitesManager_NoWebsites' => 'Δεν έχετε κάποιο ιστοχώρο για να διαχειριστείτε.',
- 'SitesManager_AddSite' => 'Προσθήκη ιστοχώρου',
- 'SitesManager_Id' => 'Id',
+ 'SecurityInfo_PluginDescription' => 'Βασισμένο στο PhpSecInfo από την Κοινοπραξία Ασφάλειας της PHP, αυτό το πρόσθετο παρέχει πληροφορίες ασφάλειας για το περιβάλλον PHP και προσφέρει προτάσεις για βελτίωση. Είναι ένα εργαλείο προσέγγισης πολυεπίπεδης ασφάλειας. Δεν αντικαθιστά πρακτικές ασφαλούς ανάπτυξης ούτε ελέγχει τον κώδικα/εφαρμογή.',
+ 'SecurityInfo_Security' => 'Ασφάλεια',
+ 'SecurityInfo_SecurityInformation' => 'Πληροφορίες ασφάλειας PHP',
+ 'SecurityInfo_Test' => 'Έλεγχος',
+ 'SecurityInfo_Result' => 'Αποτέλεσμα',
+ 'SitesManager_PluginDescription' => 'Διαχείριση Ιστοσελίδων στο Piwik: Προσθήκη μιας νέας ιστοσελίδας, Επεξεργαστείτε μια υπάρχουσα, Προβάλετε τον κώδικα Javascript που πρέπει να περιληφθεί στις σελίδες σας. Όλες οι δραστηριότητες είναι επίσης διαθέσιμες μέσω του API.',
+ 'SitesManager_Sites' => 'Ιστοσελίδες',
+ 'SitesManager_WebsitesManagement' => 'Διαχείριση ιστοσελίδων',
+ 'SitesManager_MainDescription' => 'Το σύστημα αναλυτικών αναφορών χρειάζεται ιστοσελίδες! Προσθέστε, ενημερώστε, διαγράψτε ιστοσελίδες και εμφανίστε τον κώδικα Javascript που θα εισηχθεί στις ιστοσελίδες σας.',
+ 'SitesManager_JsTrackingTag' => 'Ετικέτα Παρακολούθησης JavaScript',
+ 'SitesManager_JsTrackingTagHelp' => 'Εδώ είναι η ετικέτα Παρακολούθησης JavaScript για να συμπεριληφθεί στις σελίδες σας',
+ 'SitesManager_ShowTrackingTag' => 'προβολή ετικέτας παρακολούθησης',
+ 'SitesManager_NoWebsites' => 'Δεν έχετε κάποια ιστοσελίδα για να διαχειριστείτε.',
+ 'SitesManager_AddSite' => 'Προσθήκη ιστοσελίδας',
+ 'SitesManager_AliasUrlHelp' => 'Προτείνεται, αλλά δεν απαιτείται, να ορίσετε τα διάφορα URLs που χρησιμοποιούν οι επισκέπτες σας στη συγκεκριμένη ιστοσελίδα.\nΤα URLs με μάσκα για μια ιστοσελίδα δεν θα εμφανίζονται στο μενού Αναφορείς > Αναφορά ιστοσελίδων.\nΣημειώστε ότι δεν είναι απαραίτητο να ορίσετε τα URLs με και χωρίς «www» καθώς το Piwik τα θεωρεί και τα δύο ως δεδομένα.',
+ 'SitesManager_Id' => 'Ταυτότητα',
'SitesManager_Name' => 'Όνομα',
'SitesManager_Urls' => 'URLs',
- 'SitesManager_MenuSites' => 'Ιστοχώροι',
- 'SitesManager_DeleteConfirm_js' => 'Είστε σίγουρος ότι θέλετε να διαγράψετε τον ιστοχώρο %s?',
- 'SitesManager_ExceptionDeleteSite' => 'Δεν είναι δυνατό να διαγράψετε αυτό τον ιστοχώρο διότι είναι ο μοναδικός εγγεγραμμένος. Προσθέστε πρώτα ένα νέο ιστοχώρο και μετά διαγράψτε τον πρώτο.',
- 'SitesManager_ExceptionNoUrl' => 'Πρέπει να συμπληρώσετε τουλάχιστον ένα URL για τον ιστοχώρο σας.',
- 'SitesManager_ExceptionEmptyName' => 'Το όνομα του ιστοχώρου δεν πρέπει να είναι κενό.',
- 'SitesManager_ExceptionInvalidUrl' => 'Το url \'%s\' δεν είναι ένα έγγυρο URL.',
+ 'SitesManager_MenuSites' => 'Ιστοσελίδες',
+ 'SitesManager_DeleteConfirm_js' => 'Είστε σίγουρος ότι θέλετε να διαγράψετε την ιστοσελίδα %s?',
+ 'SitesManager_ExceptionDeleteSite' => 'Δεν είναι δυνατό να διαγράψετε αυτή την ιστοσελίδα διότι είναι η μοναδική εγγεγραμμένη. Προσθέστε πρώτα μια νέα ιστοσελίδα και μετά διαγράψτε την πρώτη.',
+ 'SitesManager_ExceptionNoUrl' => 'Πρέπει να συμπληρώσετε τουλάχιστον ένα URL για την ιστοσελίδα σας.',
+ 'SitesManager_ExceptionEmptyName' => 'Το όνομα της ιστοσελίδας δεν πρέπει να είναι κενό.',
+ 'SitesManager_ExceptionInvalidUrl' => 'Το url «%s» δεν είναι ένα έγκυρο URL.',
+ 'SitesManager_SuperUserCan' => 'Ο Υπερχρήστης μπορεί επίσης να %sορίσει καθολικές ρυθμίσεις%s για νέες ιστοσελίδες.',
+ 'SitesManager_ExcludedIps' => 'Αποκλεισμένες IPs',
+ 'SitesManager_GlobalListExcludedIps' => 'Γενικός κατάλογος Αποκλεισμένων IPs',
+ 'SitesManager_ListOfIpsToBeExcludedOnAllWebsites' => 'Οι IPs παρακάτω θα αποκλειστούν από την ανίχνευση σε όλες τις ιστοσελίδες.',
+ 'SitesManager_ExcludedParameters' => 'Αποκλεισμένες Παράμετροι',
+ 'SitesManager_GlobalListExcludedQueryParameters' => 'Καθολικός κατάλογος από παραμέτρους Ερωτήματος URL για αποκλεισμό',
+ 'SitesManager_ListOfQueryParametersToBeExcludedOnAllWebsites' => 'Οι παράμετροι Ερωτήματος URLs παρακάτω θα αποκλειστούν από URLs σε όλες τις ιστοσελίδες.',
+ 'SitesManager_ListOfQueryParametersToExclude' => 'Εισάγετε τον κατάλογο των Παραμέτρων Ερωτημάτων URL, ένα ανά γραμμή, για να αποκλειστεί από τις αναφορές Σελίδας URLs.',
+ 'SitesManager_PiwikWillAutomaticallyExcludeCommonSessionParameters' => 'Το Piwik θα αποκλείσει αυτόματα τις παραμέτρους κοινής συνεδρίας (%s).',
+ 'SitesManager_HelpExcludedIps' => 'Εισάγετε τον κατάλογο των IPs, ένα ανά γραμμή, που επιθυμείτε να αποκλείσετε από την ανίχνευση του Piwik. Μπορείτε να χρησιμοποιήσετε χαρακτήρες μπαλαντέρ, π.χ. %1$s ή %2$s ',
+ 'SitesManager_YourCurrentIpAddressIs' => 'Η τρέχουσα διεύθυνση IP είναι %s',
+ 'SitesManager_SelectACity' => 'Επιλέξτε πόλη',
+ 'SitesManager_ChooseCityInSameTimezoneAsYou' => 'Επιλέξτε μια πόλη στην ίδια ζώνη ώρας όπως εσείς.',
+ 'SitesManager_ChangingYourTimezoneWillOnlyAffectDataForward' => 'Αλλάζοντας τη ζώνη ώρας σας θα επηρεάσει μόνο τα δεδομένα που θα ακολουθήσουν και δεν θα εφαρμοστεί αναδρομικά.',
+ 'SitesManager_AdvancedTimezoneSupportNotFound' => 'Η προηγμένη υποστήριξη για ζώνες ώρας δεν βρέθηκε στην PHP σας (υποστηρίζεται από την έκδοση 5.2 ή νεότερη). Μπορείτε να επιλέξετε διαφορά ώρας χειροκίνητα.',
+ 'SitesManager_UTCTimeIs' => 'Ο Παγκόσμιος χρόνος είναι %s.',
+ 'SitesManager_Timezone' => 'Ζώνη ώρας',
+ 'SitesManager_GlobalWebsitesSettings' => 'Καθολικές ρυθμίσεις ιστοσελίδων',
+ 'SitesManager_DefaultTimezone' => 'Προεπιλεγμένη Ζώνη ώρας',
+ 'SitesManager_SelectDefaultTimezone' => 'Μπορείτε να επιλέξετε τη ζώνη ώρας η οποία θα είναι προεπιλογή για τις νέες ιστοσελίδες.',
+ 'SitesManager_Currency' => 'Νόμισμα',
+ 'SitesManager_CurrencySymbolWillBeUsedForGoals' => 'Το σύμβολο το Νομίσματος θα εμφανιστεί δίπλα στις Προσόδους των Στόχων.',
+ 'SitesManager_DefaultCurrency' => 'Προεπιλεγμένο Νόμισμα',
+ 'SitesManager_SelectDefaultCurrency' => 'Μπορείτε να επιλέξετε το νόμισμα το οποίο θα είναι προεπιλογή για τις νέες ιστοσελίδες.',
+ 'TranslationsAdmin_PluginDescription' => 'Βοηθήστε να μεταφραστεί το Piwik στη γλώσσα σας.',
'TranslationsAdmin_MenuTranslations' => 'Μεταφράσεις',
'TranslationsAdmin_MenuLanguages' => 'Γλώσσες',
'TranslationsAdmin_Plugin' => 'Πρόσθετο',
'TranslationsAdmin_Definition' => 'Ορισμός',
'TranslationsAdmin_DefaultString' => 'Προεπιλεγμένο αλφαριθμητικό (Αγγλικά)',
- 'TranslationsAdmin_TranslationString' => 'Μεταφρασμένο αλφαριθμητικό (ενεργή γλώσσα: %s)',
+ 'TranslationsAdmin_TranslationString' => 'Μεταφρασμένο αλφαριθμητικό (τρέχουσα γλώσσα: %s)',
'TranslationsAdmin_Translations' => 'Μεταφράσεις',
- 'TranslationsAdmin_FixPermissions' => 'Παρακαλώ διορθώστε τα δικαιώματα του συστήματος αρχείων',
+ 'TranslationsAdmin_FixPermissions' => 'Διορθώστε τα δικαιώματα του συστήματος αρχείων',
'TranslationsAdmin_AvailableLanguages' => 'Διαθέσιμες γλώσσες',
'TranslationsAdmin_AddLanguage' => 'Προσθήκη γλώσσας',
'TranslationsAdmin_LanguageCode' => 'Κωδικός γλώσσας',
'TranslationsAdmin_Export' => 'Εξαγωγή γλώσσας',
'TranslationsAdmin_Import' => 'Εισαγωγή γλώσσας',
+ 'UserCountry_PluginDescription' => 'Αναφέρει τη Χώρα των επισκεπτών.',
'UserCountry_Country' => 'Χώρα',
'UserCountry_Continent' => 'Ήπειρος',
'UserCountry_DistinctCountries' => '%s διακεκριμένες χώρες',
'UserCountry_SubmenuLocations' => 'Τοποθεσίες',
'UserCountry_WidgetContinents' => 'Ήπειροι επισκεπτών',
'UserCountry_WidgetCountries' => 'Χώρες επισκεπτών',
- 'UserCountry_country_ac' => 'Ascension Islands',
- 'UserCountry_country_ad' => 'Andorra',
- 'UserCountry_country_ae' => 'United Arab Emirates',
- 'UserCountry_country_af' => 'Afghanistan',
- 'UserCountry_country_ag' => 'Antigua and Barbuda',
- 'UserCountry_country_ai' => 'Anguilla',
- 'UserCountry_country_al' => 'Albania',
- 'UserCountry_country_am' => 'Armenia',
- 'UserCountry_country_an' => 'Netherlands Antilles',
- 'UserCountry_country_ao' => 'Angola',
- 'UserCountry_country_aq' => 'Antarctica',
- 'UserCountry_country_ar' => 'Argentina',
- 'UserCountry_country_as' => 'American Samoa',
- 'UserCountry_country_at' => 'Austria',
- 'UserCountry_country_au' => 'Australia',
- 'UserCountry_country_aw' => 'Aruba',
- 'UserCountry_country_az' => 'Azerbaijan',
- 'UserCountry_country_ba' => 'Bosnia and Herzegovina',
- 'UserCountry_country_bb' => 'Barbados',
- 'UserCountry_country_bd' => 'Bangladesh',
- 'UserCountry_country_be' => 'Belgium',
- 'UserCountry_country_bf' => 'Burkina Faso',
- 'UserCountry_country_bg' => 'Bulgaria',
- 'UserCountry_country_bh' => 'Bahrain',
- 'UserCountry_country_bi' => 'Burundi',
- 'UserCountry_country_bj' => 'Benin',
- 'UserCountry_country_bm' => 'Bermuda',
- 'UserCountry_country_bn' => 'Bruneo',
- 'UserCountry_country_bo' => 'Bolivia',
- 'UserCountry_country_br' => 'Brazil',
- 'UserCountry_country_bs' => 'Bahamas',
- 'UserCountry_country_bt' => 'Bhutan',
- 'UserCountry_country_bv' => 'Bouvet Island',
- 'UserCountry_country_bw' => 'Botswana',
- 'UserCountry_country_by' => 'Belarus',
- 'UserCountry_country_bz' => 'Belize',
- 'UserCountry_country_ca' => 'Canada',
- 'UserCountry_country_cc' => 'Cocos (Keeling) Islands',
- 'UserCountry_country_cd' => 'Congo, The Democratic Republic of the',
- 'UserCountry_country_cf' => 'Central African Republic',
- 'UserCountry_country_cg' => 'Congo',
- 'UserCountry_country_ch' => 'Switzerland',
- 'UserCountry_country_ci' => 'Cote D\'Ivoire',
- 'UserCountry_country_ck' => 'Cook Islands',
- 'UserCountry_country_cl' => 'Chile',
- 'UserCountry_country_cm' => 'Cameroon',
- 'UserCountry_country_cn' => 'China',
- 'UserCountry_country_co' => 'Colombia',
- 'UserCountry_country_cr' => 'Costa Rica',
- 'UserCountry_country_cs' => 'Serbia Montenegro',
- 'UserCountry_country_cu' => 'Cuba',
- 'UserCountry_country_cv' => 'Cape Verde',
- 'UserCountry_country_cx' => 'Christmas Island',
- 'UserCountry_country_cy' => 'Cyprus',
- 'UserCountry_country_cz' => 'Czech Republic',
- 'UserCountry_country_de' => 'Germany',
- 'UserCountry_country_dj' => 'Djibouti',
- 'UserCountry_country_dk' => 'Denmark',
- 'UserCountry_country_dm' => 'Dominica',
- 'UserCountry_country_do' => 'Dominican Republic',
- 'UserCountry_country_dz' => 'Algeria',
- 'UserCountry_country_ec' => 'Ecuador',
- 'UserCountry_country_ee' => 'Estonia',
- 'UserCountry_country_eg' => 'Egypt',
- 'UserCountry_country_eh' => 'Western Sahara',
- 'UserCountry_country_er' => 'Eritrea',
- 'UserCountry_country_es' => 'Spain',
- 'UserCountry_country_et' => 'Ethiopia',
- 'UserCountry_country_fi' => 'Finland',
- 'UserCountry_country_fj' => 'Fiji',
- 'UserCountry_country_fk' => 'Falkland Islands (Malvinas)',
- 'UserCountry_country_fm' => 'Micronesia, Federated States of',
- 'UserCountry_country_fo' => 'Faroe Islands',
- 'UserCountry_country_fr' => 'France',
- 'UserCountry_country_ga' => 'Gabon',
- 'UserCountry_country_gd' => 'Grenada',
- 'UserCountry_country_ge' => 'Georgia',
- 'UserCountry_country_gf' => 'French Guyana',
- 'UserCountry_country_gg' => 'Guernsey',
- 'UserCountry_country_gh' => 'Ghana',
- 'UserCountry_country_gi' => 'Gibraltar',
- 'UserCountry_country_gl' => 'Greenland',
- 'UserCountry_country_gm' => 'Gambia',
- 'UserCountry_country_gn' => 'Guinea',
- 'UserCountry_country_gp' => 'Guadeloupe',
- 'UserCountry_country_gq' => 'Equatorial Guinea',
+ 'UserCountry_country_ac' => 'Νησιά Αναλήψεως',
+ 'UserCountry_country_ad' => 'Ανδόρρα',
+ 'UserCountry_country_ae' => 'Ηνημένα Αραβικά Εμιράτα',
+ 'UserCountry_country_af' => 'Αφγανιστάν',
+ 'UserCountry_country_ag' => 'Αντίκουα και Μπαρμπούτα',
+ 'UserCountry_country_ai' => 'Ανγκουίλα',
+ 'UserCountry_country_al' => 'Αλβανία',
+ 'UserCountry_country_am' => 'Αρμενία',
+ 'UserCountry_country_an' => 'Ολλανδικές Αντίλλες',
+ 'UserCountry_country_ao' => 'Ανγκόλα',
+ 'UserCountry_country_aq' => 'Ανταρκτική',
+ 'UserCountry_country_ar' => 'Αργεντινή',
+ 'UserCountry_country_as' => 'Αμερικανική Σαμόα',
+ 'UserCountry_country_at' => 'Αυστρία',
+ 'UserCountry_country_au' => 'Αυστραλία',
+ 'UserCountry_country_aw' => 'Αρούμπα',
+ 'UserCountry_country_ax' => 'Νήσοι Άλαντ',
+ 'UserCountry_country_az' => 'Αζερμπαϊτζαν',
+ 'UserCountry_country_ba' => 'Βοσνία-Ερζεγοβίνη',
+ 'UserCountry_country_bb' => 'Μπαρμπαντος',
+ 'UserCountry_country_bd' => 'Μπαγκλαντές',
+ 'UserCountry_country_be' => 'Βέλγιο',
+ 'UserCountry_country_bf' => 'Μπουρκίνα Φάσο',
+ 'UserCountry_country_bg' => 'Βουλγαρία',
+ 'UserCountry_country_bh' => 'Μπαχρέιν',
+ 'UserCountry_country_bi' => 'Μπουρούντι',
+ 'UserCountry_country_bj' => 'Μπενίν',
+ 'UserCountry_country_bl' => 'Άγιος Βαρθολομαίος',
+ 'UserCountry_country_bm' => 'Βερμούδα',
+ 'UserCountry_country_bn' => 'Μπρούνεο',
+ 'UserCountry_country_bo' => 'Βολιβία',
+ 'UserCountry_country_br' => 'Βραζιλία',
+ 'UserCountry_country_bs' => 'Μπαχάμες',
+ 'UserCountry_country_bt' => 'Μπουτάν',
+ 'UserCountry_country_bu' => 'Μπούρμα',
+ 'UserCountry_country_bv' => 'Νήσος Μπουβέ',
+ 'UserCountry_country_bw' => 'Μποτσβανα',
+ 'UserCountry_country_by' => 'Λευκορωσία',
+ 'UserCountry_country_bz' => 'Μπελιζέ',
+ 'UserCountry_country_ca' => 'Καναδάς',
+ 'UserCountry_country_cc' => 'Νήσοι Κόκος (Κίλινγκ)',
+ 'UserCountry_country_cd' => 'Δημοκρατία του Κονγκό',
+ 'UserCountry_country_cf' => 'Κεντροαφρικανική Δημοκρατία',
+ 'UserCountry_country_cg' => 'Κόνγκο',
+ 'UserCountry_country_ch' => 'Ελβετία',
+ 'UserCountry_country_ci' => 'Ακτή Ελεφαντοστού',
+ 'UserCountry_country_ck' => 'Νήσοι Κουκ',
+ 'UserCountry_country_cl' => 'Χιλή',
+ 'UserCountry_country_cm' => 'Καμερούν',
+ 'UserCountry_country_cn' => 'Κίνα',
+ 'UserCountry_country_co' => 'Κολομβία',
+ 'UserCountry_country_cp' => 'Νήσος Κλίππερτον',
+ 'UserCountry_country_cr' => 'Κόστα Ρίκα',
+ 'UserCountry_country_cs' => 'Σερβία-Μαυροβούνιο',
+ 'UserCountry_country_cu' => 'Κούβα',
+ 'UserCountry_country_cv' => 'Πράσινο Ακρωτήρι',
+ 'UserCountry_country_cx' => 'Νήσος Χριστουγέννων',
+ 'UserCountry_country_cy' => 'Κύπρος',
+ 'UserCountry_country_cz' => 'Τσεχία',
+ 'UserCountry_country_de' => 'Γερμανία',
+ 'UserCountry_country_dg' => 'Ντιέγκο Γκαρσία',
+ 'UserCountry_country_dj' => 'Τσιμπουτί',
+ 'UserCountry_country_dk' => 'Δανία',
+ 'UserCountry_country_dm' => 'Δομινίκη',
+ 'UserCountry_country_do' => 'Δομινικανική Δημοκρατία',
+ 'UserCountry_country_dz' => 'Αλγερία',
+ 'UserCountry_country_ea' => 'Θέουτα και Μελίλια',
+ 'UserCountry_country_ec' => 'Ισημερινός',
+ 'UserCountry_country_ee' => 'Εσθονία',
+ 'UserCountry_country_eg' => 'Αίγυπτος',
+ 'UserCountry_country_eh' => 'Δυτική Σαχάρα',
+ 'UserCountry_country_er' => 'Ερυθρέα',
+ 'UserCountry_country_es' => 'Ισπανία',
+ 'UserCountry_country_et' => 'Αιθιοπία',
+ 'UserCountry_country_eu' => 'Ευρωπαϊκή Ένωση',
+ 'UserCountry_country_fi' => 'Φιλλανδία',
+ 'UserCountry_country_fj' => 'Φίτζι',
+ 'UserCountry_country_fk' => 'Νήσοι Φόκλαντ (Μαλβίνες)',
+ 'UserCountry_country_fm' => 'Μικρονησία',
+ 'UserCountry_country_fo' => 'Νήσοι Φαρόε',
+ 'UserCountry_country_fr' => 'Γαλλία',
+ 'UserCountry_country_fx' => 'Μητροπολιτική Γαλλία',
+ 'UserCountry_country_ga' => 'Γκαμπόν',
+ 'UserCountry_country_gb' => 'Μεγάλη Βρετανία',
+ 'UserCountry_country_gd' => 'Γρενάδα',
+ 'UserCountry_country_ge' => 'Γεωργία',
+ 'UserCountry_country_gf' => 'Γαλλική Γουιάνα',
+ 'UserCountry_country_gg' => 'Γκουέρνσι',
+ 'UserCountry_country_gh' => 'Γκάνα',
+ 'UserCountry_country_gi' => 'Γιβραλτάρ',
+ 'UserCountry_country_gl' => 'Γροιλανδία',
+ 'UserCountry_country_gm' => 'Γκάμπια',
+ 'UserCountry_country_gn' => 'Γουινέα',
+ 'UserCountry_country_gp' => 'Γουαδελούπη',
+ 'UserCountry_country_gq' => 'Ισημερινή Γουινέα',
'UserCountry_country_gr' => 'Ελλάδα',
- 'UserCountry_country_gs' => 'South Georgia and the South Sandwich Islands',
- 'UserCountry_country_gt' => 'Guatemala',
- 'UserCountry_country_gu' => 'Guam',
- 'UserCountry_country_gw' => 'Guinea-Bissau',
- 'UserCountry_country_gy' => 'Guyana',
- 'UserCountry_country_hk' => 'Hong Kong',
- 'UserCountry_country_hm' => 'Heard Island and McDonald Islands',
- 'UserCountry_country_hn' => 'Honduras',
- 'UserCountry_country_hr' => 'Croatia',
- 'UserCountry_country_ht' => 'Haiti',
- 'UserCountry_country_hu' => 'Hungary',
- 'UserCountry_country_id' => 'Indonesia',
- 'UserCountry_country_ie' => 'Ireland',
- 'UserCountry_country_il' => 'Israel',
- 'UserCountry_country_im' => 'Man Island',
- 'UserCountry_country_in' => 'India',
- 'UserCountry_country_io' => 'British Indian Ocean Territory',
- 'UserCountry_country_iq' => 'Iraq',
- 'UserCountry_country_ir' => 'Iran, Islamic Republic of',
- 'UserCountry_country_is' => 'Iceland',
- 'UserCountry_country_it' => 'Italy',
- 'UserCountry_country_je' => 'Jersey',
- 'UserCountry_country_jm' => 'Jamaica',
- 'UserCountry_country_jo' => 'Jordan',
- 'UserCountry_country_jp' => 'Japan',
- 'UserCountry_country_ke' => 'Kenya',
- 'UserCountry_country_kg' => 'Kyrgyzstan',
- 'UserCountry_country_kh' => 'Cambodia',
- 'UserCountry_country_ki' => 'Kiribati',
- 'UserCountry_country_km' => 'Comoros',
- 'UserCountry_country_kn' => 'Saint Kitts and Nevis',
- 'UserCountry_country_kp' => 'Korea, Democratic People\'s Republic of',
- 'UserCountry_country_kr' => 'Korea, Republic of',
- 'UserCountry_country_kw' => 'Kuwait',
- 'UserCountry_country_ky' => 'Cayman Islands',
- 'UserCountry_country_kz' => 'Kazakhstan',
- 'UserCountry_country_la' => 'Laos',
- 'UserCountry_country_lb' => 'Lebanon',
- 'UserCountry_country_lc' => 'Saint Lucia',
- 'UserCountry_country_li' => 'Liechtenstein',
- 'UserCountry_country_lk' => 'Sri Lanka',
- 'UserCountry_country_lr' => 'Liberia',
- 'UserCountry_country_ls' => 'Lesotho',
- 'UserCountry_country_lt' => 'Lithuania',
- 'UserCountry_country_lu' => 'Luxembourg',
- 'UserCountry_country_lv' => 'Latvia',
- 'UserCountry_country_ly' => 'Libya',
- 'UserCountry_country_ma' => 'Morocco',
- 'UserCountry_country_mc' => 'Monaco',
- 'UserCountry_country_md' => 'Moldova, Republic of',
- 'UserCountry_country_mg' => 'Madagascar',
- 'UserCountry_country_mh' => 'Marshall Islands',
- 'UserCountry_country_mk' => 'Fyrom',
- 'UserCountry_country_ml' => 'Mali',
- 'UserCountry_country_mm' => 'Myanmar',
- 'UserCountry_country_mn' => 'Mongolia',
- 'UserCountry_country_mo' => 'Macau',
- 'UserCountry_country_mp' => 'Northern Mariana Islands',
- 'UserCountry_country_mq' => 'Martinique',
- 'UserCountry_country_mr' => 'Mauritania',
- 'UserCountry_country_ms' => 'Montserrat',
- 'UserCountry_country_mt' => 'Malta',
- 'UserCountry_country_mu' => 'Mauritius',
- 'UserCountry_country_mv' => 'Maldives',
- 'UserCountry_country_mw' => 'Malawi',
- 'UserCountry_country_mx' => 'Mexico',
- 'UserCountry_country_my' => 'Malaysia',
- 'UserCountry_country_mz' => 'Mozambique',
- 'UserCountry_country_na' => 'Namibia',
- 'UserCountry_country_nc' => 'New Caledonia',
- 'UserCountry_country_ne' => 'Niger',
- 'UserCountry_country_nf' => 'Norfolk Island',
- 'UserCountry_country_ng' => 'Nigeria',
- 'UserCountry_country_ni' => 'Nicaragua',
- 'UserCountry_country_nl' => 'Netherlands',
- 'UserCountry_country_no' => 'Norway',
- 'UserCountry_country_np' => 'Nepal',
- 'UserCountry_country_nr' => 'Nauru',
- 'UserCountry_country_nu' => 'Niue',
- 'UserCountry_country_nz' => 'New Zealand',
- 'UserCountry_country_om' => 'Oman',
- 'UserCountry_country_pa' => 'Panama',
- 'UserCountry_country_pe' => 'Peru',
- 'UserCountry_country_pf' => 'French Polynesia',
- 'UserCountry_country_pg' => 'Papua New Guinea',
- 'UserCountry_country_ph' => 'Philippines',
- 'UserCountry_country_pk' => 'Pakistan',
- 'UserCountry_country_pl' => 'Poland',
- 'UserCountry_country_pm' => 'Saint Pierre and Miquelon',
- 'UserCountry_country_pn' => 'Pitcairn',
- 'UserCountry_country_pr' => 'Puerto Rico',
- 'UserCountry_country_ps' => 'Palestinian Territory',
- 'UserCountry_country_pt' => 'Portugal',
- 'UserCountry_country_pw' => 'Palau',
- 'UserCountry_country_py' => 'Paraguay',
- 'UserCountry_country_qa' => 'Qatar',
- 'UserCountry_country_re' => 'Reunion Island',
- 'UserCountry_country_ro' => 'Romania',
- 'UserCountry_country_ru' => 'Russia',
- 'UserCountry_country_rs' => 'Serbia',
- 'UserCountry_country_rw' => 'Rwanda',
- 'UserCountry_country_sa' => 'Saudi Arabia',
- 'UserCountry_country_sb' => 'Solomon Islands',
- 'UserCountry_country_sc' => 'Seychelles',
- 'UserCountry_country_sd' => 'Sudan',
- 'UserCountry_country_se' => 'Sweden',
- 'UserCountry_country_sg' => 'Singapore',
- 'UserCountry_country_sh' => 'Saint Helena',
- 'UserCountry_country_si' => 'Slovenia',
- 'UserCountry_country_sj' => 'Svalbard',
- 'UserCountry_country_sk' => 'Slovakia',
- 'UserCountry_country_sl' => 'Sierra Leone',
- 'UserCountry_country_sm' => 'San Marino',
- 'UserCountry_country_sn' => 'Senegal',
- 'UserCountry_country_so' => 'Somalia',
- 'UserCountry_country_sr' => 'Suriname',
- 'UserCountry_country_st' => 'Sao Tome and Principe',
- 'UserCountry_country_su' => 'Old U.S.S.R',
- 'UserCountry_country_sv' => 'El Salvador',
- 'UserCountry_country_sy' => 'Syrian Arab Republic',
- 'UserCountry_country_sz' => 'Swaziland',
- 'UserCountry_country_tc' => 'Turks and Caicos Islands',
- 'UserCountry_country_td' => 'Chad',
- 'UserCountry_country_tf' => 'French Southern Territories',
- 'UserCountry_country_tg' => 'Togo',
- 'UserCountry_country_th' => 'Thailand',
- 'UserCountry_country_tj' => 'Tajikistan',
- 'UserCountry_country_tk' => 'Tokelau',
- 'UserCountry_country_tm' => 'Turkmenistan',
- 'UserCountry_country_tn' => 'Tunisia',
- 'UserCountry_country_to' => 'Tonga',
- 'UserCountry_country_tp' => 'East Timor',
- 'UserCountry_country_tr' => 'Turkey',
- 'UserCountry_country_tt' => 'Trinidad and Tobago',
- 'UserCountry_country_tv' => 'Tuvalu',
- 'UserCountry_country_tw' => 'Taiwan',
- 'UserCountry_country_tz' => 'Tanzania, United Republic of',
- 'UserCountry_country_ua' => 'Ukraine',
- 'UserCountry_country_ug' => 'Uganda',
- 'UserCountry_country_uk' => 'United Kingdom',
- 'UserCountry_country_gb' => 'Great Britain',
- 'UserCountry_country_um' => 'United States Minor Outlying Islands',
- 'UserCountry_country_us' => 'United States',
- 'UserCountry_country_uy' => 'Uruguay',
- 'UserCountry_country_uz' => 'Uzbekistan',
- 'UserCountry_country_va' => 'Vatican City',
- 'UserCountry_country_vc' => 'Saint Vincent and the Grenadines',
- 'UserCountry_country_ve' => 'Venezuela',
- 'UserCountry_country_vg' => 'Virgin Islands, British',
- 'UserCountry_country_vi' => 'Virgin Islands, U.S.',
- 'UserCountry_country_vn' => 'Vietnam',
- 'UserCountry_country_vu' => 'Vanuatu',
- 'UserCountry_country_wf' => 'Wallis and Futuna',
- 'UserCountry_country_ws' => 'Samoa',
- 'UserCountry_country_ye' => 'Yemen',
- 'UserCountry_country_yt' => 'Mayotte',
- 'UserCountry_country_yu' => 'Yugoslavia',
- 'UserCountry_country_za' => 'South Africa',
- 'UserCountry_country_zm' => 'Zambia',
- 'UserCountry_country_zr' => 'Zaire',
- 'UserCountry_country_zw' => 'Zimbabwe',
+ 'UserCountry_country_gs' => 'Νότια Γεωργία και Νότιοι Νήσοι Σάντουιτς',
+ 'UserCountry_country_gt' => 'Γουατεμάλα',
+ 'UserCountry_country_gu' => 'Γκουάμ',
+ 'UserCountry_country_gw' => 'Γουινέα-Μπισάου',
+ 'UserCountry_country_gy' => 'Γκουγιάνα',
+ 'UserCountry_country_hk' => 'Χονγκ-Κονγκ',
+ 'UserCountry_country_hm' => 'Νήσος Χέρντ και Νήσοι Μακντόναλντς',
+ 'UserCountry_country_hn' => 'Ονδούρες',
+ 'UserCountry_country_hr' => 'Κροατία',
+ 'UserCountry_country_ht' => 'Αϊτή',
+ 'UserCountry_country_hu' => 'Ουγγαρία',
+ 'UserCountry_country_ic' => 'Κανάριες Νήσοι',
+ 'UserCountry_country_id' => 'Ινδονησία',
+ 'UserCountry_country_ie' => 'Ιρλανδία',
+ 'UserCountry_country_il' => 'Ισραήλ',
+ 'UserCountry_country_im' => 'Νήοσς Μαν',
+ 'UserCountry_country_in' => 'Ινδία',
+ 'UserCountry_country_io' => 'Επικράτεια Βρετανικού Ινδικού Ωκεανού',
+ 'UserCountry_country_iq' => 'Ιράκ',
+ 'UserCountry_country_ir' => 'Ιράν',
+ 'UserCountry_country_is' => 'Ισλανδία',
+ 'UserCountry_country_it' => 'Ιταλία',
+ 'UserCountry_country_je' => 'Τζέρσει',
+ 'UserCountry_country_jm' => 'Τζαμάικα',
+ 'UserCountry_country_jo' => 'Ιορδανία',
+ 'UserCountry_country_jp' => 'Ιαπωνία',
+ 'UserCountry_country_ke' => 'Κένυα',
+ 'UserCountry_country_kg' => 'Κιργκιζστάν',
+ 'UserCountry_country_kh' => 'Καμπότξη',
+ 'UserCountry_country_ki' => 'Κιριμπάτι',
+ 'UserCountry_country_km' => 'Κομόρος',
+ 'UserCountry_country_kn' => 'Άγιοι Κίτς και Μέβις',
+ 'UserCountry_country_kp' => 'Βόρειος Κορέα',
+ 'UserCountry_country_kr' => 'Νότιος Κορέα',
+ 'UserCountry_country_kw' => 'ΚΟυβέιτ',
+ 'UserCountry_country_ky' => 'Νήσοι Κέιμάν',
+ 'UserCountry_country_kz' => 'Καζακστάν',
+ 'UserCountry_country_la' => 'Λάος',
+ 'UserCountry_country_lb' => 'Λίβανος',
+ 'UserCountry_country_lc' => 'Αγία Λουκία',
+ 'UserCountry_country_li' => 'Λιχτενστάιν',
+ 'UserCountry_country_lk' => 'Σρι Λάνκα',
+ 'UserCountry_country_lr' => 'Λιβερία',
+ 'UserCountry_country_ls' => 'Λεσότο',
+ 'UserCountry_country_lt' => 'Λιθουανία',
+ 'UserCountry_country_lu' => 'Λουξεμβούργο',
+ 'UserCountry_country_lv' => 'Λετονία',
+ 'UserCountry_country_ly' => 'Λιβύη',
+ 'UserCountry_country_ma' => 'Μαρόκο',
+ 'UserCountry_country_mc' => 'Μονάκό',
+ 'UserCountry_country_md' => 'Μολδαβία',
+ 'UserCountry_country_me' => 'Μαυροβούνιο',
+ 'UserCountry_country_mf' => 'Άγιος Μαρτίνος',
+ 'UserCountry_country_mg' => 'Μαδαγασκάρη',
+ 'UserCountry_country_mh' => 'Νήσοι Μάρσαλ',
+ 'UserCountry_country_mk' => 'Π.Γ.Δ.Μ.',
+ 'UserCountry_country_ml' => 'Μαλί',
+ 'UserCountry_country_mm' => 'Μιανμάρ',
+ 'UserCountry_country_mn' => 'Μονγκολία',
+ 'UserCountry_country_mo' => 'Μακάου',
+ 'UserCountry_country_mp' => 'Νήσοι Βόρειας Μαριάννα',
+ 'UserCountry_country_mq' => 'Μαρτινίκη',
+ 'UserCountry_country_mr' => 'Μαυριτανία',
+ 'UserCountry_country_ms' => 'Μονσεράτ',
+ 'UserCountry_country_mt' => 'Μάλτα',
+ 'UserCountry_country_mu' => 'Μαυρίκιος',
+ 'UserCountry_country_mv' => 'Μαλβίδες',
+ 'UserCountry_country_mw' => 'Μαλάουι',
+ 'UserCountry_country_mx' => 'Μεξικό',
+ 'UserCountry_country_my' => 'Μαλαισία',
+ 'UserCountry_country_mz' => 'Μοζαμβίκη',
+ 'UserCountry_country_na' => 'Μαμίμπια',
+ 'UserCountry_country_nc' => 'Νέα Καλιδονία',
+ 'UserCountry_country_ne' => 'Νίγηρας',
+ 'UserCountry_country_nf' => 'Νήσος Νόρφολκ',
+ 'UserCountry_country_ng' => 'Νιγηρία',
+ 'UserCountry_country_ni' => 'Νικαράγουα',
+ 'UserCountry_country_nl' => 'Ολλανδία',
+ 'UserCountry_country_no' => 'Νορβηγία',
+ 'UserCountry_country_np' => 'Νεπάλ',
+ 'UserCountry_country_nr' => 'Ναούρού',
+ 'UserCountry_country_nt' => 'Ουδέτερη Ζώνη',
+ 'UserCountry_country_nu' => 'Νιούε',
+ 'UserCountry_country_nz' => 'Νέα Ζηλανδία',
+ 'UserCountry_country_om' => 'Ομάν',
+ 'UserCountry_country_pa' => 'Παναμάς',
+ 'UserCountry_country_pe' => 'Περού',
+ 'UserCountry_country_pf' => 'Γαλλική Πολυνησία',
+ 'UserCountry_country_pg' => 'Παπούα Νέα Γουινέα',
+ 'UserCountry_country_ph' => 'Φιλιππίνες',
+ 'UserCountry_country_pk' => 'Πακιστάν',
+ 'UserCountry_country_pl' => 'Πολωνία',
+ 'UserCountry_country_pm' => 'Άγιος Πέτρος και Μικελάν',
+ 'UserCountry_country_pn' => 'Νήσοι Πίτκερν',
+ 'UserCountry_country_pr' => 'Πουέρτο Ρίκο',
+ 'UserCountry_country_ps' => 'Παλαιστινιακή Αρχή',
+ 'UserCountry_country_pt' => 'Πορτογαλία',
+ 'UserCountry_country_pw' => 'Παλάου',
+ 'UserCountry_country_py' => 'Παραγουάη',
+ 'UserCountry_country_qa' => 'Κατάρ',
+ 'UserCountry_country_re' => 'Νήσος Ρεϊνιόν',
+ 'UserCountry_country_ro' => 'Ρουμανία',
+ 'UserCountry_country_ru' => 'Ρωσία',
+ 'UserCountry_country_rs' => 'Σερβία',
+ 'UserCountry_country_rw' => 'Ρουάντα',
+ 'UserCountry_country_sa' => 'Σαουδική Αραβία',
+ 'UserCountry_country_sb' => 'Νήσοι Σολωμόντα',
+ 'UserCountry_country_sc' => 'Σεϋχέλλες',
+ 'UserCountry_country_sd' => 'Σουδάν',
+ 'UserCountry_country_se' => 'Σουηδία',
+ 'UserCountry_country_sf' => 'Φιλανδία',
+ 'UserCountry_country_sg' => 'Σιγκαπούρη',
+ 'UserCountry_country_sh' => 'Αγία Ελένη',
+ 'UserCountry_country_si' => 'Σλοβενία',
+ 'UserCountry_country_sj' => 'Νήσοι Σβαλμπάρντ',
+ 'UserCountry_country_sk' => 'Σλοβακία',
+ 'UserCountry_country_sl' => 'Σιέρρα Λεόνε',
+ 'UserCountry_country_sm' => 'Σαν Μαρίνο',
+ 'UserCountry_country_sn' => 'Σενεγάλη',
+ 'UserCountry_country_so' => 'Σομαλία',
+ 'UserCountry_country_sr' => 'Σουρινάμ',
+ 'UserCountry_country_st' => 'Άγιος Θωμάς και Πρίγκιπας',
+ 'UserCountry_country_su' => 'Παλαιά Ε.Σ.Σ.Δ.',
+ 'UserCountry_country_sv' => 'Ελ Σαλβαδόρ',
+ 'UserCountry_country_sy' => 'Συριακή Αραβική Δημοκρατία',
+ 'UserCountry_country_sz' => 'Σουαζιλάνδη',
+ 'UserCountry_country_ta' => 'Τριστάν ντα Κούνια',
+ 'UserCountry_country_tc' => 'Νήσοι Ταρκ και Κάικος',
+ 'UserCountry_country_td' => 'Τσαντ',
+ 'UserCountry_country_tf' => 'Νότια και Ανταρκτικά Γαλλικά Εδάφη',
+ 'UserCountry_country_tg' => 'Τόγκο',
+ 'UserCountry_country_th' => 'Ταϊλάνδη',
+ 'UserCountry_country_tj' => 'Τατζικιστάν',
+ 'UserCountry_country_tk' => 'Τόκελαν',
+ 'UserCountry_country_tl' => 'Ανατολικό Τιμόρ',
+ 'UserCountry_country_tm' => 'Τουρκμενιστάν',
+ 'UserCountry_country_tn' => 'Τυνησία',
+ 'UserCountry_country_to' => 'Τόνγκα',
+ 'UserCountry_country_tp' => 'Ανατολικό Τιμόρ',
+ 'UserCountry_country_tr' => 'Τουρκία',
+ 'UserCountry_country_tt' => 'Τρινιδάδ και Τομπάκο',
+ 'UserCountry_country_tv' => 'Τουβαλού',
+ 'UserCountry_country_tw' => 'Ταϊβάν',
+ 'UserCountry_country_tz' => 'Τανζανία',
+ 'UserCountry_country_ua' => 'Ουκρανία',
+ 'UserCountry_country_ug' => 'Ουγκάντα',
+ 'UserCountry_country_uk' => 'Ηνωμένο Βασίλειο',
+ 'UserCountry_country_um' => 'Μικρές Απομονωμένες Νήσοι Η.Π.Α.',
+ 'UserCountry_country_us' => 'Ηνωμένες Πολιτείες Αμερικής',
+ 'UserCountry_country_uy' => 'Ουρουγουάη',
+ 'UserCountry_country_uz' => 'Ουζμπεκιστάν',
+ 'UserCountry_country_va' => 'Βατικανό',
+ 'UserCountry_country_vc' => 'Άγιος Βικέντιος και Γρεναδίνες',
+ 'UserCountry_country_ve' => 'Βενεζουέλα',
+ 'UserCountry_country_vg' => 'Βρετανικές Παρθένες Νήσοι',
+ 'UserCountry_country_vi' => 'Παρθένες Νήσοι Η.Π.Α.',
+ 'UserCountry_country_vn' => 'Βιετνάμ',
+ 'UserCountry_country_vu' => 'Βανουάτου',
+ 'UserCountry_country_wf' => 'Γουάλλις και Φουτούνα',
+ 'UserCountry_country_ws' => 'Σαμόα',
+ 'UserCountry_country_ye' => 'Υεμένη',
+ 'UserCountry_country_yt' => 'Μαγιότ',
+ 'UserCountry_country_yu' => 'Γιουγκοσλαβία',
+ 'UserCountry_country_za' => 'Νότια Αφρική',
+ 'UserCountry_country_zm' => 'Ζάμπια',
+ 'UserCountry_country_zr' => 'Ζαίρ',
+ 'UserCountry_country_zw' => 'Ζιμπάμπουε',
'UserCountry_continent_eur' => 'Ευρώπη',
'UserCountry_continent_afr' => 'Αφρική',
'UserCountry_continent_asi' => 'Ασία',
'UserCountry_continent_ams' => 'Νοτια και Κεντρική Αμερική',
'UserCountry_continent_amn' => 'Βόρεια Αμερική',
'UserCountry_continent_oce' => 'Οκεανία',
- 'UserSettings_BrowserFamilies' => 'Οικογένειες περιηγητών',
- 'UserSettings_Browsers' => 'Περιηγητές',
+ 'UserSettings_PluginDescription' => 'Αναφέρει διάφορες Ρυθμίσεις Χρήστη: Φυλλομετρητής, Ομάδα Φυλλομετρητών, Λειτουργικό Σύστημα, Πρόσθετα, Ανάλυση, Γενικές Ρυθμίσεις.',
+ 'UserSettings_VisitorSettings' => 'Ρυθμίσεις επισκέπτη',
+ 'UserSettings_BrowserFamilies' => 'Ομάδες φυλλομετρητών',
+ 'UserSettings_Browsers' => 'Φυλλομετρητές',
'UserSettings_Plugins' => 'Πρόσθετα',
'UserSettings_Configurations' => 'Ρυθμίσεις',
- 'UserSettings_OperatinsSystems' => 'Λειτουργικά συστήματα',
- 'UserSettings_Resolutions' => 'Αναλύσεις',
- 'UserSettings_WideScreen' => 'Ευρεία οθόνη',
+ 'UserSettings_OperatingSystems' => 'Λειτουργικά συστήματα',
+ 'UserSettings_Resolutions' => 'Αναλύσεις οθόνης',
+ 'UserSettings_WideScreen' => 'Τύποι οθόνης',
+ 'UserSettings_ColumnBrowserFamily' => 'Οικογένεια φυλλομετρητών',
+ 'UserSettings_ColumnBrowser' => 'Φυλλομετρητής',
+ 'UserSettings_ColumnPlugin' => 'Πρόσθετο',
+ 'UserSettings_ColumnConfiguration' => 'Ρύθμιση',
+ 'UserSettings_ColumnOperatingSystem' => 'Λειτουργικό σύστημα',
+ 'UserSettings_ColumnResolution' => 'Ανάλυση',
+ 'UserSettings_ColumnTypeOfScreen' => 'Τύπος οθόνης',
'UserSettings_WidgetResolutions' => 'Αναλύσεις οθόνης',
- 'UserSettings_WidgetBrowsers' => 'Περιηγητές επισκεπτών',
+ 'UserSettings_WidgetBrowsers' => 'Φυλλομετρητές επισκεπτών',
'UserSettings_WidgetPlugins' => 'Λίστα προσθέτων',
- 'UserSettings_WidgetWidescreen' => 'Κανονική / Ευρεία',
- 'UserSettings_WidgetBrowserFamilies' => 'Περιηγητές ανά οικογένεια',
+ 'UserSettings_WidgetWidescreen' => 'Κανονική / Ευρεία οθόνη',
+ 'UserSettings_WidgetBrowserFamilies' => 'Φυλλομετρητές ανά οικογένεια',
'UserSettings_WidgetOperatingSystems' => 'Λειτουργικά συστήματα',
'UserSettings_WidgetGlobalVisitors' => 'Γενικές ρυθμίσεις χρηστών',
'UserSettings_SubmenuSettings' => 'Ρυθμίσεις',
- 'VisitsSummary_NbVisits' => '%s επισκέψεις',
- 'VisitsSummary_NbUniqueVisitors' => '%s μοναδικοί επισκέπτες',
- 'VisitsSummary_NbActions' => '%s ενέργειες (θεάσεις σελίδων)',
- 'VisitsSummary_TotalTime' => '%s συνολικός χρόνος δαπανήθηκε από τους επισκέπτες',
- 'VisitsSummary_MaxNbActions' => '%s μέγιστες ενέργειες εντός μίας επίσκεψης',
- 'VisitsSummary_NbBounced' => '%s επισκέπτες εκτινάχθηκαν (έφυγαν από την πρώτη σελίδα)',
- 'VisitsSummary_Evolution' => 'Εξέλιξη εντός τελευταίων 30 %s',
- 'VisitsSummary_Report' => 'Αναφορά',
- 'VisitsSummary_GenerateTime' => '%s δευτερόλεπτα για τη δημιουργία της σελίδας',
- 'VisitsSummary_GenerateQueries' => '%s επερωτήσεις εκτελέστηκαν',
- 'VisitsSummary_WidgetLastVisits' => 'Γράφημα τελευταίων επισκέψεων',
- 'VisitsSummary_WidgetVisits' => 'Εικόνα επισκέψεων',
- 'VisitsSummary_WidgetLastVisitors' => 'Γράφημα τελευταίων μοναδικών επισκεπτών',
- 'VisitsSummary_WidgetOverviewGraph' => 'Εικόνα με γράφημα',
- 'VisitsSummary_SubmenuOverview' => 'Εικόνα',
- 'VisitFrequency_Evolution' => 'Εξέλιξη εντός της περιόδου',
- 'VisitFrequency_ReturnVisits' => '%s επιστρεφόμενες επισκέψεις',
- 'VisitFrequency_ReturnActions' => '%s ενέργειες από τις επιστρεφόμενες επισκέψεις ',
- 'VisitFrequency_ReturnMaxActions' => '%s μέγιστες ενέργειες από μία επιστρεφόμενη επίσκεψη',
- 'VisitFrequency_ReturnTotalTime' => '%s συνολικός χρόνος δαπανήθηκε από τις επιστρεφόμενες επισκέψεις ',
- 'VisitFrequency_ReturnBounces' => '%s φορές που μία επιστρεφόμενη επίσκεψη αναπήδησε (έφυγε από την πρώτη σελίδα)',
- 'VisitFrequency_WidgetOverview' => 'Εικόνα συχνότητας',
- 'VisitFrequency_WidgetGraphReturning' => 'Γράφημα επιστρεφόμενων επισκέψεων',
- 'VisitFrequency_SubmenuFrequency' => 'Συχνότητα',
- 'VisitTime_LocalTime' => 'Επισκέψεις ανά τοπική ώρα',
- 'VisitTime_ServerTime' => 'Επισκέψεις ανά ώρα διακομιστή',
- 'VisitTime_WidgetLocalTime' => 'Επισκέψεις ανά τοπική ώρα',
- 'VisitTime_WidgetServerTime' => 'Επισκέψεις ανά ώρα διακομιστή',
- 'VisitTime_SubmenuTimes' => 'Χρόνοι',
- 'VisitTime_NHour' => '%sh',
- 'VisitorInterest_VisitsPerDuration' => 'Επισκέψεις ανά διάρκεια',
- 'VisitorInterest_VisitsPerNbOfPages' => 'Επισκέψεις ανά αριθμό σελίδων',
- 'VisitorInterest_WidgetLengths' => 'Διάρκεια επισκέψεων',
- 'VisitorInterest_WidgetPages' => 'Σελίδες ανά επίσκεψη',
- 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Συχνότητα & αφοσίωση',
- 'VisitorInterest_PlusXMin' => '%s λεπ',
- 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s λεπ',
- 'VisitorInterest_OnePage' => '1 σελίδα',
- 'VisitorInterest_NPages' => '%s σελίδες',
- 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
- 'Login_LoginPasswordNotCorrect' => 'Το όνομα χρήστη και ο κωδικός δεν είναι σωστά',
- 'Login_Login' => 'Όνομα χρήστη',
- 'Login_Password' => 'Κωδικός',
- 'Login_LoginOrEmail' => 'Χρήστης ή E-mail',
- 'Login_LogIn' => 'Σύνδεση',
- 'Login_Logout' => 'Αποσύνδεση',
- 'Login_LostYourPassword' => 'Ξεχάσατε τον κωδικό σας?',
- 'Login_RemindPassword' => 'Υπενθύμιση κωδικού',
- 'Login_PasswordReminder' => 'Παρακαλώ συμπληρώστε το όνομα χρήστη και την ηλεκτρονική σας διεύθυνση. Θα λάβετε ένα μήνυμα που θα περιέχει ένα νέο κωδικό.',
- 'Login_InvalidUsernameEmail' => 'Λανθασμένο όνομα χρήστη ή/και λάθος ηλεκτρονική διεύθυνση',
- 'Login_MailTopicPasswordRecovery' => 'Ανάκτηση κωδικού',
- 'Login_MailPasswordRecoveryBody' => 'Γεια σας %1s, \n\n Ο νέος σας κωδικός είναι: %2s \n\n Συνδεθείτε εδώ: %3s',
- 'Login_PasswordSent' => 'Ο κωδικός σας μόλις απεστάλη. Ελέγξτε τα μηνύματά σας.',
- 'Login_ContactAdmin' => 'Πιθανή αιτία: ο διακομιστής έχει απενεργοποιημένη τη διαδικασία mail() <br />Παρακαλώ επικοινωνήστε με τον διαχειριστή.',
+ 'UsersManager_PluginDescription' => 'Διαχείριση Χρηστών στο Piwik: προσθήκη ενός νέου Χρήστη, επεξεργασία ενός υπάρχοντος χρήστη, αναβαθμίστε τα δικαιώματα. Όλες οι δραστηριότητες είναι επίσης διαθέσιμες μέσω του API.',
'UsersManager_UsersManagement' => 'Διαχείριση χρηστών',
'UsersManager_UsersManagementMainDescription' => 'Δημιουργήστε νέους χρήστες ή ενημερώστε τους υπάρχοντες. Μπορείτε επίσης να αλλάξετε τα δικαιώματά τους (παραπάνω).',
'UsersManager_ManageAccess' => 'Διαχείριση πρόσβασης',
- 'UsersManager_MainDescription' => 'Ρυθμίστε ποιοι χρήστες θα έχουν πρόσβαση σε ποιους ιστοχώρους. Μπορείτε επίσης να ρυθμίσετε τα δικαιώματα για όλους τους ιστοχώρους με μία κίνηση.',
- 'UsersManager_Sites' => 'ιστοχώροι',
- 'UsersManager_AllWebsites' => 'Όλοι οι ιστοχώροι',
- 'UsersManager_ApplyToAllWebsites' => 'Εφαρμογή σε όλους τους ιστοχώρους',
+ 'UsersManager_MainDescription' => 'Ρυθμίστε ποιοι χρήστες θα έχουν πρόσβαση σε ποιες ιστοσελίδες. Μπορείτε επίσης να ρυθμίσετε τα δικαιώματα για όλες τις ιστοσελίδες με μία κίνηση.',
+ 'UsersManager_Sites' => 'Ιστοσελίδες',
+ 'UsersManager_AllWebsites' => 'Όλες οι ιστοσελίδες',
+ 'UsersManager_ApplyToAllWebsites' => 'Εφαρμογή σε όλες τις ιστοσελίδες',
'UsersManager_User' => 'Χρήστης',
'UsersManager_PrivNone' => 'Χωρίς πρόσβαση',
- 'UsersManager_PrivView' => 'Εμφάνιση',
+ 'UsersManager_PrivView' => 'Προβολή',
'UsersManager_PrivAdmin' => 'Διαχείριση',
- 'UsersManager_ChangeAllConfirm' => 'Είστε σίγουρος ότι θέλετε να αλλάξετε \'%s\' δικαιώματα σε όλες τις ιστοσελίδες?',
- 'UsersManager_Login' => 'Σύνδεση',
+ 'UsersManager_ChangeAllConfirm' => 'Είστε σίγουρος ότι θέλετε να αλλάξετε «%s» δικαιώματα σε όλες τις ιστοσελίδες;',
'UsersManager_Password' => 'Κωδικός',
- 'UsersManager_Email' => 'Email',
- 'UsersManager_Alias' => 'Alias',
- 'UsersManager_Token' => 'token_auth',
+ 'UsersManager_Email' => 'Ηλεκτρονική Διεύθυνση',
+ 'UsersManager_Alias' => 'Ψευδώνυμο',
+ 'UsersManager_TheSuperUserAliasCannotBeChanged' => 'Η μάσκα του Υπερχρήστη δεν μπορεί να αλλάξει.',
+ 'UsersManager_ReportToLoadByDefault' => 'Αναφέρεται να φορτώνει ως προεπιλογή',
+ 'UsersManager_ReportDateToLoadByDefault' => 'Αναφέρεται την ημερομηνία για να φορτώνεται ως προεπιλογή',
+ 'UsersManager_ForAnonymousUsersReportDateToLoadByDefault' => 'Για ανώνυμους χρήστες, αναφέρεται την ημερομηνία για να φορτώνεται ως προεπιλογή',
+ 'UsersManager_ExcludeVisitsViaCookie' => 'Αποκλείστε τις επισκέψεις σας με χρήση cookie',
+ 'UsersManager_YourVisitsAreIgnored' => '%sΟι επισκέψεις σας αγνοούνται από το Piwik%s (βρέθηκε cookie αγνόησης του Piwik στον φυλλομετρητή σας).',
+ 'UsersManager_YourVisitsAreNotIgnored' => '%sΟι επισκέψεις δεν αγνοούνται από το Piwik%s (δεν βρέθηκε cookie αγνόησης του Piwik στον φυλλομετρητή σας).',
+ 'UsersManager_ClickHereToDeleteTheCookie' => 'Πατήστε εδώ για να διαγράψετε το cookie και αφήστε το Piwik να καταγράφει τις εκισκέψεις σας',
+ 'UsersManager_ClickHereToSetTheCookie' => 'Πατήστε εδώ για να βάλετε ένα cookie το οποίο θα αποτρέψει την καταγραφή των επισκέψεών σας στις ιστοσελίδες σας από το Piwik',
'UsersManager_Edit' => 'Επεξεργασία',
'UsersManager_AddUser' => 'Προσθήκη νέου χρήστη',
'UsersManager_MenuUsers' => 'Χρήστες',
- 'UsersManager_DeleteConfirm_js' => 'Είστε σίγουρος ότι θέλετε να διαγράψετε την χρήστη %s?',
- 'UsersManager_ExceptionLoginExists' => 'Ο χρήστης \'%s\' υπάρχει ήδη.',
- 'UsersManager_ExceptionEmailExists' => 'Χρήστης με το email \'%s\' υπάρχει ήδη.',
- 'UsersManager_ExceptionInvalidLogin' => 'Το όνομα χρήστη πρέπει να είναι τουλάχιστον 3 χαρακτήρες και πρέπει να περιέχει μόνο λατινικά γράμματα και αριθμούς',
+ 'UsersManager_MenuUserSettings' => 'Ρυθμίσεις χρήστη',
+ 'UsersManager_MenuAnonymousUserSettings' => 'Ρυθμίσεις ανώνυμου χρήστη',
+ 'UsersManager_NoteNoAnonymousUserAccessSettingsWontBeUsed' => 'Σημείωση: Δεν έχετε κάποια ιστοσελίδα που ο ανώνυμος χρήστης μπορεί να έχει πρόσβαση. Οι ακόλουθες ρυθμίσεις δεν θα χρησιμοποιηθούν.',
+ 'UsersManager_WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess' => 'Όταν οι χρήστες δεν έχουν συνδεθεί και επισκέπτονται το Piwik, θα έχουν πρόσβαση',
+ 'UsersManager_ChangePassword' => 'Αλλαγή κωδικού πρόσβασης',
+ 'UsersManager_IfYouWouldLikeToChangeThePasswordTypeANewOne' => 'Αν θέλετε να αλλάξετε τον κωδικός πρόσβασης, γράψτε έναν νέο. Διαφορετικά αφήστε το κενό.',
+ 'UsersManager_TypeYourPasswordAgain' => 'Γράψτε τον νέο σας κωδικό ξανά.',
+ 'UsersManager_TheLoginScreen' => 'Η οθόνη σύνδεσης',
+ 'UsersManager_DeleteConfirm_js' => 'Είστε σίγουρος ότι θέλετε να διαγράψετε τον/ην χρήστη %s;',
+ 'UsersManager_YourUsernameCannotBeChanged' => 'Το όνομα χρήστη δεν μπορεί να αλλαχτεί.',
+ 'UsersManager_ExceptionLoginExists' => 'Ο χρήστης «%s» υπάρχει ήδη.',
+ 'UsersManager_ExceptionEmailExists' => 'Χρήστης με την ηλεκτρονική διεύθυνση «%s» υπάρχει ήδη.',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'Το όνομα χρήστη πρέπει να είναι τουλάχιστον 3 χαρακτήρες και πρέπει να περιέχει μόνο λατινικά γράμματα και αριθμούς',
'UsersManager_ExceptionInvalidPassword' => 'Το μήκος του κωδικού πρέπει να είναι από 6 χαρακτήρες ως 26.',
- 'UsersManager_ExceptionInvalidEmail' => 'Το email δεν φαίνεται να είναι σωστό.',
- 'UsersManager_ExceptionDeleteDoesNotExist' => 'Ο χρήστης \'%s\' δεν υπάρχει και άρα δεν μπορεί να διαγραφεί.',
- 'UsersManager_ExceptionAdminAnonymous' => 'Δεν μπορείτε να δώσετε διακαιώματα διαχειριστή στον \'anonymous\' χρήστη.',
- 'UsersManager_ExceptionEditAnonymous' => 'Ο anonymous χρήστης δεν μπορεί να διαγραφεί ή να δεχθεί τροποποίηση. Χρησιμοποιείται από το Piwik για τον ορισμό του χρήστη που δεν έχει συνδεθεί ακόμα. Για παράδειγμα, μπορείτε να κάνετε τα στατιστικά σας δημόσια δίνοντας δικαίωμα \'προβολή\' στον χρήστη \'anonymous\'.',
- 'UsersManager_ExceptionUserDoesNotExist' => 'Ο χρήστης \'%s\' δεν υπάρχει.',
- 'UsersManager_ExceptionAccessValues' => 'The parameter access must have one of the following values : [ %s ]',
+ 'UsersManager_ExceptionInvalidEmail' => 'Η ηλεκτρονική διεύθυνση δεν φαίνεται να είναι σωστή.',
+ 'UsersManager_ExceptionDeleteDoesNotExist' => 'Ο χρήστης «%s» δεν υπάρχει και άρα δεν μπορεί να διαγραφεί.',
+ 'UsersManager_ExceptionAdminAnonymous' => 'Δεν μπορείτε να δώσετε διακαιώματα διαχειριστή στον «ανώνυμο» χρήστη.',
+ 'UsersManager_ExceptionEditAnonymous' => 'Ο ανώνυμος χρήστης δεν μπορεί να διαγραφεί ή να δεχθεί τροποποίηση. Χρησιμοποιείται από το Piwik για τον ορισμό του χρήστη που δεν έχει συνδεθεί ακόμα. Για παράδειγμα, μπορείτε να κάνετε τα στατιστικά σας δημόσια δίνοντας δικαίωμα «προβολής» στον «ανώνυμο» χρήστη.',
+ 'UsersManager_ExceptionSuperUser' => 'Ο αιτούμενος χρήστης είναι ο Υπέρχρήστης και δεν μπορεί να ερωτηθεί, επεξεργαστεί ή διαγραφεί από το API. Μπορείτε να επεξεργαστείτε τις λεπτομέρειές του χειροκίνητα στο αρχείο ρυθμίσεων του Piwik.',
+ 'UsersManager_ExceptionUserDoesNotExist' => 'Ο χρήστης «%s» δεν υπάρχει.',
+ 'UsersManager_ExceptionAccessValues' => 'Η πρόσβαση παραμέτρου πρέπει να έχει τις ακόλουθες τιμές : [ %s ]',
+ 'VisitFrequency_PluginDescription' => 'Αναφέρει διάφορα στατιστικά για τον Επιστρεφόμενο Επισκέπτη αντί το Πρωτοεμφανιζόμενου επισκέπτη.',
'VisitFrequency_Evolution' => 'Εξέλιξη εντός της περιόδου',
+ 'VisitFrequency_ColumnReturningVisits' => 'Επιστρεφόμενες επισκέψεις',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Δραστηριότητες από Επιστρεφόμενες Επισκέψεις',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Μέγιστος αριθμός δραστηριοτήτων ανά Επιστρεφόμενη Επίσκεψη',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Συνολικός χρόνος που ξοδεύτηκε ανά Επιστρεφόμενη Επίσκεψη (σε δευτερόλεπτα)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Βαθμός απομάκρυνσης για Επιστρεφόμενες Επισκέψεις',
'VisitFrequency_ReturnVisits' => '%s επιστρεφόμενες επισκέψεις',
'VisitFrequency_ReturnActions' => '%s ενέργειες από τις επιστρεφόμενες επισκέψεις ',
- 'VisitFrequency_ReturnMaxActions' => '%s μέγιστες ενέργειες από μία επιστρεφόμενη επίσκεψη',
- 'VisitFrequency_ReturnTotalTime' => '%s συνολικός χρόνος δαπανήθηκε από τις επιστρεφόμενες επισκέψεις ',
- 'VisitFrequency_ReturnBounces' => '%s φορές που μία επιστρεφόμενη επίσκεψη αναπήδησε (έφυγε από την πρώτη σελίδα)',
- 'VisitFrequency_WidgetOverview' => 'Εικόνα συχνότητας',
+ 'VisitFrequency_ReturnMaxActions' => '%s είναι ο μέγιστος αριθμός ενεργειεών από μία επιστρεφόμενη επίσκεψη',
+ 'VisitFrequency_ReturnTotalTime' => '%s είναι ο συνολικός δαπανηθής χρόνος από τις επιστρεφόμενες επισκέψεις ',
+ 'VisitFrequency_ReturnBounceRate' => '%s επιστρεφόμενες επισκέψεις έχουν απομακρυνθεί (αφήσαν την ιστοσελίδα μετά από μια σελίδα)',
+ 'VisitFrequency_WidgetOverview' => 'Επισκόπηση συχνότητας',
'VisitFrequency_WidgetGraphReturning' => 'Γράφημα επιστρεφόμενων επισκέψεων',
'VisitFrequency_SubmenuFrequency' => 'Συχνότητα',
- 'VisitTime_LocalTime' => 'Επισκέψεις ανά τοπική ώρα',
- 'VisitTime_ServerTime' => 'Επισκέψεις ανά ώρα διακομιστή',
- 'VisitTime_WidgetLocalTime' => 'Επισκέψεις ανά τοπική ώρα',
- 'VisitTime_WidgetServerTime' => 'Επισκέψεις ανά ώρα διακομιστή',
- 'VisitTime_SubmenuTimes' => 'Χρόνοι',
- 'VisitTime_NHour' => '%sh',
+ 'VisitorInterest_PluginDescription' => 'Αναφέρει το Ενδιαφέρον Επισκέπτη: αριθμός προσβηθέντων σελίδων, δαπανηθής χρόνος στην Ιστοσελίδα.',
'VisitorInterest_VisitsPerDuration' => 'Επισκέψεις ανά διάρκεια',
'VisitorInterest_VisitsPerNbOfPages' => 'Επισκέψεις ανά αριθμό σελίδων',
+ 'VisitorInterest_ColumnVisitDuration' => 'Διάρκεια επίσκεψης',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Σελίδες ανά επίσκεψη',
'VisitorInterest_WidgetLengths' => 'Διάρκεια επισκέψεων',
'VisitorInterest_WidgetPages' => 'Σελίδες ανά επίσκεψη',
'VisitorInterest_SubmenuFrequencyLoyalty' => 'Συχνότητα & αφοσίωση',
'VisitorInterest_PlusXMin' => '%s λεπ',
- 'VisitorInterest_BetweenXYMinutes' => '%1s-%2s λεπ',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s λεπ',
'VisitorInterest_OnePage' => '1 σελίδα',
'VisitorInterest_NPages' => '%s σελίδες',
- 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
+ 'VisitorInterest_BetweenXYSeconds' => '%1s-%2sδ',
+ 'VisitsSummary_PluginDescription' => 'Αναφέρει τους γενικούς αριθμούς στατιστικών: επισκέψεις, μοναδικοί επισκέπτες, αριθμος δραστηριοτήτων, Βαθμός Αναπήδησης, κλπ.',
+ 'VisitsSummary_VisitsSummary' => 'Περίληψη επισκέψεων',
'VisitsSummary_NbVisits' => '%s επισκέψεις',
'VisitsSummary_NbUniqueVisitors' => '%s μοναδικοί επισκέπτες',
- 'VisitsSummary_NbActions' => '%s ενέργειες (θεάσεις σελίδων)',
- 'VisitsSummary_TotalTime' => '%s συνολικός χρόνος δαπανήθηκε από τους επισκέπτες',
- 'VisitsSummary_MaxNbActions' => '%s μέγιστες ενέργειες εντός μίας επίσκεψης',
- 'VisitsSummary_NbBounced' => '%s επισκέπτες εκτινάχθηκαν (έφυγαν από την πρώτη σελίδα)',
- 'VisitsSummary_Evolution' => 'Εξέλιξη εντός τελευταίων 30 %ss',
+ 'VisitsSummary_NbActions' => '%s δραστηριότητες (προβολές σελίδας)',
+ 'VisitsSummary_TotalTime' => '%s είναι ο συνολικός δαπανηθής χρόνος επισκεπτών',
+ 'VisitsSummary_MaxNbActions' => '%s είναι ο μέγιστος αριθμός ενεργειών σε μία επίσκεψη',
+ 'VisitsSummary_NbVisitsBounced' => '%s των επισκεπτών απομακρύνθηκαν (έφυγαν από την πρώτη σελίδα)',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Εξέλιξη εντός τελευταίων 30 %s',
'VisitsSummary_Report' => 'Αναφορά',
'VisitsSummary_GenerateTime' => '%s δευτερόλεπτα για τη δημιουργία της σελίδας',
- 'VisitsSummary_GenerateQueries' => '%s επερωτήσεις εκτελέστηκαν',
- 'VisitsSummary_WidgetLastVisits' => 'Γράφημα τελευταίων επισκέψεων',
- 'VisitsSummary_WidgetVisits' => 'Εικόνα επισκέψεων',
- 'VisitsSummary_WidgetLastVisitors' => 'Γράφημα τελευταίων μοναδικών επισκεπτών',
- 'VisitsSummary_WidgetOverviewGraph' => 'Εικόνα με γράφημα',
- 'VisitsSummary_SubmenuOverview' => 'Εικόνα',
+ 'VisitsSummary_GenerateQueries' => '%s ερωτήματα εκτελέστηκαν',
+ 'VisitsSummary_WidgetLastVisits' => 'Διάγραμμα τελευταίων επισκέψεων',
+ 'VisitsSummary_WidgetVisits' => 'Επισκόπηση επισκέψεων',
+ 'VisitsSummary_WidgetLastVisitors' => 'Διάγραμμα τελευταίων μοναδικών επισκεπτών',
+ 'VisitsSummary_WidgetOverviewGraph' => 'Επισκόπηση με διάγραμμα',
+ 'VisitsSummary_SubmenuOverview' => 'Επισκόπηση',
+ 'VisitTime_PluginDescription' => 'Αναφέρει τον Τοπικό Χρόνο και το Χρόνο Διακομιστή. Η πληροφορία του Χρόνου Διακομιστή μπορεί να είναι χρήσιμος για τον προγραμματισμό συντήρησης της Ιστοσελίδας.',
+ 'VisitTime_LocalTime' => 'Επισκέψεις ανά τοπική ώρα',
+ 'VisitTime_ServerTime' => 'Επισκέψεις ανά ώρα διακομιστή',
+ 'VisitTime_ColumnServerTime' => 'Χρόνος διακομιστή',
+ 'VisitTime_ColumnLocalTime' => 'Τοπική ώρα',
+ 'VisitTime_WidgetLocalTime' => 'Επισκέψεις ανά τοπική ώρα',
+ 'VisitTime_WidgetServerTime' => 'Επισκέψεις ανά ώρα διακομιστή',
+ 'VisitTime_SubmenuTimes' => 'Χρόνοι',
+ 'VisitTime_NHour' => '%sω',
+ 'Widgetize_PluginDescription' => 'Το πρόσθετο κάνει πολύ εύκολη την εξαγωγή οποιασδήποτε Μικροεφαρμογής Piwik στο Ιστολόγιό σας, την Ιστοσελίδα σας ή το Igoogle και το Netvibes!',
+ 'General_GoTo' => 'Μετάβαση στο %s',
+ 'General_PageBounceRateDefinition' => 'Το ποσοστό των επισκέψεων που ξεκίνησαν σε αυτή τη σελίδα και έφυγαν από την ιστοσελίδα αμέσως.',
+ 'General_ColumnExitRate' => 'Βαθμός εξόδου',
+ 'General_PageExitRateDefinition' => 'Το ποσοστό των επισκέψεων σε αυτή τη σελίδα που έφυγαν από την ιστοσελίδα αμέσως.',
+ 'General_ColumnBounces' => 'Αναπηδήσεις',
+ 'General_BouncesDefinition' => 'Αριθμός επισκεωεων που ξεκίνσηαν σε αυτή τη σελίδα και έφυγαν από την ιστοσελίδα αμέσως.',
+ 'General_ColumnEntrances' => 'Είσοδοι',
+ 'General_EntrancesDefinition' => 'Αριθμός επισκέψεων που ξεκίνησαν σε αυτή τη σελίδα.',
+ 'General_ColumnExits' => 'Έξοδοι',
+ 'General_ExitsDefinition' => 'Αριθμός επισκέωεων που τελείωσαν σε αυτή τη σελίδα.',
+ 'General_ColumnAverageTimeOnPage' => 'Μέσος χρόνος στη σελίδα',
+ 'General_AverageTimeOnPageDefinition' => 'Ο μέσος χρόνος που ξοδεύουν οι επισκέπτες σε αυτή τη σελίδα.',
+ 'General_DaysHours' => '%1$s μέρες %2$s ώρες',
+ 'General_HoursMinutes' => '%1$s ώρες %2$s λεπτά',
+ 'General_MinutesSeconds' => '%1$s λεπτά %2$s δευτερόλεπτα',
+ 'General_Seconds' => '%s δευτερόλεπτα',
+ 'General_DisplayGoals' => 'Προβολή Στόχων',
+ 'General_ConfigFileIsNotWritable' => 'Το αρχείο ρυθμίσεων %s του Piwik δεν είναι εγγράψιμο. Οι αλλαγές σας δεν θα αποθηκευτούν. %s Αλλάξτε τα δικαιώματα στο αρχείο ρυθμίσεων για να το κάνετε εγγράψιμο.',
+ 'Actions_SubmenuPagesEntry' => 'Σελίδες εισόδου',
+ 'Actions_SubmenuPagesExit' => 'Σελίδες εξόδου',
+ 'CoreAdminHome_Administration' => 'Διαχείριση',
+ 'CoreHome_WebAnalyticsReports' => 'Αναφορές Στατιστικών Ιστού',
+ 'Dashboard_AddPreviewedWidget_js' => 'Προσθήκη προεπισκοπούμενης μικροεφαρμογής στον κεντρινό πίνακα',
+ 'Dashboard_WidgetPreview_js' => 'Προεπισκόπηση μικροεφαρμογής',
+ 'ExamplePlugin_PluginDescription' => 'Πρόσθετο Παραδείγματο: Αυτό το πρόσθετο δείχνει πως να δημιουργήσετε ένα πολύ απλό πρόσθετο, που εξάγει δύο μικροεφαρμογές στον Κεντρικό Πίνακα.',
+ 'ExamplePlugin_exampleWidgets' => 'Μικροεφαρμογές Παραδείγματος',
+ 'ExamplePlugin_exampleWidget' => 'Μικροεφαρμογή Παραδείγματος',
+ 'ExamplePlugin_blogPiwikRss' => 'Ιστολόγιο RSS Piwik',
+ 'ExamplePlugin_photostreamMatt' => 'Φωτυογραφίες του Matt',
+ 'Goals_Goals' => 'Στόχοι',
+ 'Goals_Overview' => 'Επισκόπηση',
+ 'Goals_WhereThe' => 'όπου το',
+ 'Live_Last30Minutes' => 'Τελευταία 30 λεπτά',
+ 'MultiSites_Evolution' => 'Πρόοδος',
+ 'SitesManager_DefaultTimezoneForNewWebsites' => 'Προεπιλεγμένη Ζώνη ώρας για νέες ιστοσελίδες',
+ 'SitesManager_DefaultCurrencyForNewWebsites' => 'Προεπιλεγμένο Νόμισμα για νέες ιστοσελίδες',
+ 'SitesManager_Save_js' => 'Αποθήκευση',
+ 'SitesManager_Cancel_js' => 'Άκυρο',
+ 'UsersManager_YourVisitsAreIgnoredOnDomain' => '%sΟι επισκέψεις σας παραβλέπονται από το Piwik στο %s %s (το Piwik παραβλέπει το cookie που βρέθηκα στον φυλλομετρητή σας).',
+ 'UsersManager_ClickHereToSetTheCookieOnDomain' => 'Πατήστε εδώ για να ορίσετε ένα cookie που θα αποκλείει τις επισκέψεις σας στις ιστοσελίδες που ανιχνέυονται από το Piwik στο %s',
+ 'VisitorInterest_Engagement' => 'Συμπλοκή',
+ 'VisitsSummary_NbActionsDescription' => '%s δραστηριότητες (προβολές σελίδας, λήψεις και εξωτερικοί σύνδεσμοι)',
); \ No newline at end of file
diff --git a/lang/en.php b/lang/en.php
index a5c0e6649b..421ce1b82e 100644
--- a/lang/en.php
+++ b/lang/en.php
@@ -5,15 +5,19 @@ $translations = array(
'General_TranslatorEmail' => 'hello@piwik.org',
'General_EnglishLanguageName' => 'English',
'General_OriginalLanguageName' => 'English',
- 'General_HelloUser' => 'Hello, %s!',
+ 'General_HelloUser' => 'Hello, %s!',
'General_OpenSourceWebAnalytics' => 'Open Source Web Analytics',
- 'General_YourDashboard' => 'Your Dashboard',
+ 'General_Dashboard' => 'Dashboard',
+ 'General_DashboardForASpecificWebsite' => 'Dashboard for a specific website',
+ 'General_MultiSitesSummary' => 'All Websites',
+ 'General_AllWebsitesDashboard' => 'All Websites dashboard',
'General_API' => 'API',
'General_Widgets' => 'Widgets',
- 'General_Settings' => 'Settings',
+ 'General_Settings' => 'Settings',
'General_GiveUsYourFeedback' => 'Give us Feedback!',
'General_Unknown' => 'Unknown',
'General_Required' => '%s required',
+ 'General_NotValid' => '%s is not valid',
'General_Error' => 'Error',
'General_Warning' => 'Warning',
'General_BackToHomepage' => 'Back to Piwik homepage',
@@ -23,10 +27,16 @@ $translations = array(
'General_Edit' => 'Edit',
'General_Ok' => 'Ok',
'General_Close' => 'Close',
+ 'General_OrCancel' => 'or %s Cancel %s',
'General_Logout' => 'Sign out',
+ 'General_Username' => 'Username',
'General_Done' => 'Done',
+ 'General_Details' => 'Details',
+ 'General_Default' => 'Default',
'General_LoadingData' => 'Loading data...',
'General_Loading' => 'Loading...',
+ 'General_GoTo' => 'Go to %s',
+ 'General_YourChangesHaveBeenSaved' => 'Your changes have been saved.',
'General_ErrorRequest' => 'Oops&hellip; problem during the request, please try again.',
'General_Next' => 'Next',
'General_Previous' => 'Previous',
@@ -40,6 +50,11 @@ $translations = array(
'General_ExportAsImage_js' => 'Export as Image',
'General_SaveImageOnYourComputer_js' => 'To save the image on your computer, right click on the image and select "Save Image As..."',
'General_Refresh' => 'Refresh the page',
+ 'General_Today' => 'Today',
+ 'General_Yesterday' => 'Yesterday',
+ 'General_CurrentWeek' => 'Current Week',
+ 'General_CurrentMonth' => 'Current Month',
+ 'General_CurrentYear' => 'Current Year',
'General_Visitors' => 'Visitors',
'General_ColumnNbUniqVisitors' => 'Unique visitors',
'General_ColumnNbVisits' => 'Visits',
@@ -50,21 +65,48 @@ $translations = array(
'General_ColumnActionsPerVisit' => 'Actions per Visit',
'General_ColumnAvgTimeOnSite' => 'Avg. Time on Website',
'General_ColumnBounceRate' => 'Bounce Rate',
+ 'General_PageBounceRateDefinition' => 'The percentage of visits that started on this page, and left the website straight away.',
+ 'General_ColumnExitRate' => 'Exit rate',
+ 'General_PageExitRateDefinition' => 'The percentage of visits on this page that left the website straight away.',
'General_ColumnPageviews' => 'Pageviews',
'General_ColumnUniquePageviews' => 'Unique Pageviews',
+ 'General_ColumnBounces' => 'Bounces',
+ 'General_BouncesDefinition' => 'Number of visits that started on this page and left the website straight away.',
+ 'General_ColumnEntrances' => 'Entrances',
+ 'General_EntrancesDefinition' => 'Number of visits that started on this page.',
+ 'General_ColumnExits' => 'Exits',
+ 'General_ExitsDefinition' => 'Number of visits that ended on this page.',
+ 'General_ColumnAverageTimeOnPage' => 'Avg. time on page',
+ 'General_AverageTimeOnPageDefinition' => 'The average amount of time visitors spent on this page.',
'General_ColumnValuePerVisit' => 'Value per Visit',
'General_ColumnVisitsWithConversions' => 'Visits with Conversions',
+ 'General_DaysHours' => '%1$s days %2$s hours',
+ 'General_HoursMinutes' => '%1$s hours %2$s min',
+ 'General_MinutesSeconds' => '%1$s min %2$ss',
+ 'General_Seconds' => '%ss',
'General_Save' => 'Save',
+ 'General_ForExampleShort' => 'eg.',
'General_Website' => 'Website',
+ 'General_GeneralSettings' => 'General Settings',
+ 'General_AllowPiwikArchivingToTriggerBrowser' => 'Allow Piwik archiving to trigger when reports are viewed from the browser',
+ 'General_ArchivingInlineHelp' => 'For medium to high traffic websites, it is recommended to disable Piwik archiving to trigger from the browser. Instead, we recommend that you setup a cron job to process Piwik reports every hour.',
+ 'General_ArchivingTriggerDescription' => 'Recommended for larger Piwik installs, you need to %ssetup a cron job%s to process the reports automatically.',
+ 'General_SeeTheOfficialDocumentationForMoreInformation' => 'See the %sofficial documentation%s for more information.',
+ 'General_ReportsForTodayWillBeProcessedAtMostEvery' => 'Reports for today will be processed at most every',
+ 'General_NSeconds' => '%s seconds',
+ 'General_SmallTrafficYouCanLeaveDefault' => 'For small traffic websites, you can leave the default %s seconds, and access all reports in real time.',
+ 'General_MediumToHighTrafficItIsRecommendedTo' => 'For medium to high traffic websites, we recommend to process reports for today at most every half hour (%s seconds) or every hour (%s seconds).',
'General_RequiresFlash' => 'Displaying Graphs in Piwik requires Flash',
'General_GraphHelp' => 'More information about displaying graphs in Piwik.',
'General_NoDataForGraph' => 'No data for this graph.',
'General_NoDataForTagCloud' => 'No data for this tag cloud.',
'General_DisplayNormalTable' => 'Display normal table',
'General_DisplayMoreData' => 'Display more data',
- 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s is a collaborative project. %s If you like Piwik, you can help! Check out %s How to contribute to Piwik?%s ',
- 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'You are currently viewing the demo of %s; %sdownload%s the full version! Check out %s',
- 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s is available. %s Please update now!%s (see %s changes%s).',
+ 'General_DisplayGoals' => 'Display Goals',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%1$s Piwik %2$s is a collaborative project. %3$s If you\'re a fan of Piwik, you can help! Check out %4$s How to participate in Piwik?%5$s',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'You are currently viewing the demo of %1$s; %2$sdownload%3$s the full version! Check out %4$s',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %1$s is available. %2$s Please update now!%3$s (see %4$s changes%5$s).',
+ 'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin' => '%s is available. Please notify the site administrator.',
'General_BackToPiwik' => 'Back to Piwik',
'General_ShortMonth_1' => 'Jan',
'General_ShortMonth_2' => 'Feb',
@@ -104,33 +146,74 @@ $translations = array(
'General_LongDay_5' => 'Friday',
'General_LongDay_6' => 'Saturday',
'General_LongDay_7' => 'Sunday',
- 'General_ExceptionDatabaseVersion' => 'Your %s version is %s but Piwik requires at least %s.',
- 'CorePluginsAdmin_Plugins' => 'Plugins',
- 'CorePluginsAdmin_PluginsManagement' => 'Plugins Management',
- 'CorePluginsAdmin_MainDescription' => 'Plugins extend and expand the functionality of Piwik. Once a plugin is installed, you may activate it or deactivate it here.',
- 'CorePluginsAdmin_Plugin' => 'Plugin',
- 'CorePluginsAdmin_Version' => 'Version',
- 'CorePluginsAdmin_Description' => 'Description',
- 'CorePluginsAdmin_Status' => 'Status',
- 'CorePluginsAdmin_Action' => 'Action',
- 'CorePluginsAdmin_PluginHomepage' => 'Plugin Homepage',
- 'CorePluginsAdmin_Activated' => 'Activated',
- 'CorePluginsAdmin_Active' => 'Active',
- 'CorePluginsAdmin_Inactive' => 'Inactive',
- 'CorePluginsAdmin_ActivatedHelp' => 'This plugin cannot be deactivated',
- 'CorePluginsAdmin_Deactivate' => 'Deactivate',
- 'CorePluginsAdmin_Activate' => 'Activate',
- 'CorePluginsAdmin_MenuPlugins' => 'Plugins',
- 'API_QuickDocumentation' => '<h2>API quick documentation</h2><p>If you don\'t have data for today you can first <a href=\'misc/generateVisits.php\' target=_blank>generate some data</a> using the Visits Generator script.</p><p>You can try the different formats available for every method. It is very easy to extract any data you want from Piwik!</p><p><b>For more information have a look at the <a href=\'http://dev.piwik.org/trac/wiki/API\'>official API Documentation</a> or the <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API Reference</a>.</b></P><h2>User authentication</h2><p>If you want to <b>request the data in your scripts, in a crontab, etc. </b> you need to add the parameter <code><u>&token_auth=%s</u></code> to the API calls URLs that require authentication.</p><p>This token_auth is as secret as your login and password, <b>do not share it!</p>',
- 'API_LoadedAPIs' => 'Loaded successfully %s APIs',
+ 'General_ConfigFileIsNotWritable' => 'The Piwik configuration file %s is not writable, your changes will not be saved. %s Please change permissions of the config file to make it writable.',
+ 'General_ExceptionDatabaseVersion' => 'Your %1$s version is %2$s but Piwik requires at least %3$s.',
+ 'General_ExceptionIncompatibleClientServerVersions' => 'Your %1$s client version is %2$s which is incompatible with server version %3$s.',
+ 'General_ExceptionMissingFile' => 'Missing file: %s',
+ 'General_ExceptionFilesizeMismatch' => 'File size mismatch: %1$s (expected length: %2$s, found: %3$s)',
+ 'General_ExceptionFileIntegrity' => 'Integrity check failed: %s',
+ 'General_ExceptionNonceMismatch' => 'Could not verify the security token on this form.',
+ 'General_ExceptionVariableNotFound' => 'The required variable \'%s\' is not correct or has not been found in the API Request.',
+ 'General_ExceptionMethodNotFound' => 'The method \'%s\' does not exist or is not available in the module \'%s\'.',
+ 'General_ExceptionSubtableNotFoundInArchive' => 'You are requesting a precise subTable but there is not such data in the Archive.',
+ 'General_ExceptionInvalidRendererFormat' => 'Renderer format \'%s\' not valid. Try any of the following instead: %s.',
+ 'General_ExceptionInvalidPeriod' => 'The period \'%s\' is not supported. Try any of the following instead: %s',
+ 'General_ExceptionInvalidDateRange' => 'The date \'%s\' is not a correct date range. It should have the following format: %s.',
+ 'General_ExceptionGoalNotFound' => 'The goal id = %s couldn\'t be found.',
+ 'General_ExceptionInvalidGoalPattern' => 'Pattern type %s not valid.',
+ 'General_ExceptionInvalidIdsite' => 'The \'idsite\' in the request is invalid.',
+ 'General_ExceptionUndeletableFile' => 'Unable to delete %s',
+ 'General_ExceptionPrivilege' => 'You can\'t access this resource as it requires a %s access.',
+ 'General_ExceptionPrivilegeAtLeastOneWebsite' => 'You can\'t access this resource as it requires an %s access for at least one website.',
+ 'General_ExceptionPrivilegeAccessWebsite' => 'You can\'t access this resource as it requires an %s access for the website id = %d.',
+ 'General_ExceptionInvalidArchiveTimeToLive' => 'Today archive time to live must be a number of seconds greater than zero',
+ 'General_ExceptionConfigurationFileNotFound' => 'The configuration file {%s} has not been found.',
+ 'General_ExceptionUnreadableFileDisabledMethod' => 'The configuration file {%s} could not be read. Your host may have disabled %s.',
+ 'General_ExceptionInvalidToken' => 'Token is not valid.',
+ 'General_ExceptionInvalidDateFormat' => 'Date format must be: %s or any keyword supported by the %s function (see %s for more information)',
+ 'General_ExceptionLanguageFileNotFound' => 'Language file \'%s\' not found.',
+ 'General_WarningFileIntegritySkipped' => 'Development environment detected. File integrity check skipped.',
+ 'General_WarningFileIntegrityNoManifest' => 'File integrity check could not be performed due to missing manifest.inc.php.',
+ 'General_WarningFileIntegrityNoMd5file' => 'File integrity check could not be completed due to missing md5_file() function.',
+ 'General_FileIntegrityWarningExplanation' => 'File integrity check failed and reported some errors. This is most likely due to a partial or failed upload of some of the Piwik files. You should reupload all the Piwik files and refresh this page until it shows no error.',
+ 'Actions_PluginDescription' => 'Reports about the page views, the outlinks and downloads. Outlinks and Downloads tracking is automatic!',
+ 'Actions_Actions' => 'Actions',
+ 'Actions_SubmenuPages' => 'Pages',
+ 'Actions_SubmenuPagesEntry' => 'Entry pages',
+ 'Actions_SubmenuPagesExit' => 'Exit pages',
+ 'Actions_SubmenuPageTitles' => 'Page titles',
+ 'Actions_SubmenuOutlinks' => 'Outlinks',
+ 'Actions_SubmenuDownloads' => 'Downloads',
+ 'Actions_ColumnClicks' => 'Clicks',
+ 'Actions_ColumnUniqueClicks' => 'Unique Clicks',
+ 'Actions_ColumnDownloads' => 'Downloads',
+ 'Actions_ColumnUniqueDownloads' => 'Unique Downloads',
+ 'Actions_ColumnPageName' => 'Page Name',
+ 'Actions_ColumnPageURL' => 'Page URL',
+ 'Actions_ColumnClickedURL' => 'Clicked URL',
+ 'Actions_ColumnDownloadURL' => 'Download URL',
+ 'AnonymizeIP_PluginDescription' => 'Anonymize the last byte of visitors IP addresses to comply with your local privacy laws/guidelines.',
+ 'API_PluginDescription' => 'All the data in Piwik is available through simple APIs. This plugin is the web service entry point, that you can call to get your Web Analytics data in xml, json, php, csv, etc.',
+ 'API_QuickDocumentationTitle' => 'API quick documentation',
+ 'API_GenerateVisits' => 'If you don\'t have data for today you can first generate some data using the %s plugin. You can enable the %s plugin, then click on the \'Visitor Generator\' menu in the Piwik Admin area. ',
+ 'API_MoreInformation' => 'For more information about the Piwik APIs, please have a look at the %s Introduction to Piwik API %s and the %s Piwik API Reference %s.',
+ 'API_UserAuthentication' => 'User authentication',
+ 'API_UsingTokenAuth' => 'If you want to %s request data within a script, a crontab, etc. %s you need to add the parameter %s to the API calls URLs that require authentication.',
+ 'API_KeepTokenSecret' => 'This token_auth is as secret as your login and password, %s do not share it%s!',
+ 'API_LoadedAPIs' => 'Successfully loaded %s APIs',
+ 'CoreAdminHome_PluginDescription' => 'Administration area of Piwik.',
+ 'CoreAdminHome_MenuGeneralSettings' => 'General settings',
+ 'CoreAdminHome_Administration' => 'Administration',
+ 'CoreHome_PluginDescription' => 'Web Analytics Reports Structure.',
+ 'CoreHome_WebAnalyticsReports' => 'Web Analytics Reports',
'CoreHome_NoPrivileges' => 'You are logged in as \'%s\' but it seems you don\'t have any permission set in Piwik.<br />Ask your Piwik administrator to give you \'view\' access to a website.',
- 'CoreHome_JavascriptDisabled' => 'JavaScript must be enabled in order for you to use Piwik in standard view.<br />However, it seems JavaScript is either disabled or not supported by your browser.<br />To use standard view, enable JavaScript by changing your browser options, then %stry again%s.<br />',
+ 'CoreHome_JavascriptDisabled' => 'JavaScript must be enabled in order for you to use Piwik in standard view.<br />However, it seems JavaScript is either disabled or not supported by your browser.<br />To use standard view, enable JavaScript by changing your browser options, then %1$stry again%2$s.<br />',
'CoreHome_TableNoData' => 'No data for this table.',
'CoreHome_CategoryNoData' => 'No data in this category. Try to "Include all population".',
'CoreHome_ShowJSCode' => 'Show the JavaScript code to insert',
'CoreHome_IncludeAllPopulation_js' => 'Include all population',
'CoreHome_ExcludeLowPopulation_js' => 'Exclude low population',
- 'CoreHome_PageOf_js' => '%s of %s',
+ 'CoreHome_PageOf_js' => '%1$s of %2$s',
'CoreHome_Loading_js' => 'Loading...',
'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
'CoreHome_PeriodDay' => 'Day',
@@ -148,6 +231,32 @@ $translations = array(
'CoreHome_DayTh_js' => 'Th',
'CoreHome_DayFr_js' => 'Fr',
'CoreHome_DaySa_js' => 'Sa',
+ 'CoreHome_ShortDay_1_js' => 'Sun',
+ 'CoreHome_ShortDay_2_js' => 'Mon',
+ 'CoreHome_ShortDay_3_js' => 'Tue',
+ 'CoreHome_ShortDay_4_js' => 'Wed',
+ 'CoreHome_ShortDay_5_js' => 'Thu',
+ 'CoreHome_ShortDay_6_js' => 'Fri',
+ 'CoreHome_ShortDay_7_js' => 'Sat',
+ 'CoreHome_LongDay_1_js' => 'Sunday',
+ 'CoreHome_LongDay_2_js' => 'Monday',
+ 'CoreHome_LongDay_3_js' => 'Tuesday',
+ 'CoreHome_LongDay_4_js' => 'Wednesday',
+ 'CoreHome_LongDay_5_js' => 'Thursday',
+ 'CoreHome_LongDay_6_js' => 'Friday',
+ 'CoreHome_LongDay_7_js' => 'Saturday',
+ 'CoreHome_ShortMonth_1_js' => 'Jan',
+ 'CoreHome_ShortMonth_2_js' => 'Feb',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Apr',
+ 'CoreHome_ShortMonth_5_js' => 'May',
+ 'CoreHome_ShortMonth_6_js' => 'Jun',
+ 'CoreHome_ShortMonth_7_js' => 'Jul',
+ 'CoreHome_ShortMonth_8_js' => 'Aug',
+ 'CoreHome_ShortMonth_9_js' => 'Sep',
+ 'CoreHome_ShortMonth_10_js' => 'Oct',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dec',
'CoreHome_MonthJanuary_js' => 'January',
'CoreHome_MonthFebruary_js' => 'February',
'CoreHome_MonthMarch_js' => 'March',
@@ -160,12 +269,35 @@ $translations = array(
'CoreHome_MonthOctober_js' => 'October',
'CoreHome_MonthNovember_js' => 'November',
'CoreHome_MonthDecember_js' => 'December',
+ 'CorePluginsAdmin_PluginDescription' => 'Plugins Administration Interface.',
+ 'CorePluginsAdmin_Plugins' => 'Plugins',
+ 'CorePluginsAdmin_PluginsManagement' => 'Plugins Management',
+ 'CorePluginsAdmin_MainDescription' => 'Plugins extend and expand the functionality of Piwik. Once a plugin is installed, you may activate it or deactivate it here.',
+ 'CorePluginsAdmin_Plugin' => 'Plugin',
+ 'CorePluginsAdmin_Version' => 'Version',
+ 'CorePluginsAdmin_Description' => 'Description',
+ 'CorePluginsAdmin_Status' => 'Status',
+ 'CorePluginsAdmin_Action' => 'Action',
+ 'CorePluginsAdmin_PluginHomepage' => 'Plugin Homepage',
+ 'CorePluginsAdmin_Activated' => 'Activated',
+ 'CorePluginsAdmin_Active' => 'Active',
+ 'CorePluginsAdmin_Inactive' => 'Inactive',
+ 'CorePluginsAdmin_ActivatedHelp' => 'This plugin cannot be deactivated',
+ 'CorePluginsAdmin_Deactivate' => 'Deactivate',
+ 'CorePluginsAdmin_Activate' => 'Activate',
+ 'CorePluginsAdmin_MenuPlugins' => 'Plugins',
+ 'CoreUpdater_PluginDescription' => 'Piwik updating mechanism',
'CoreUpdater_UpdateTitle' => 'Update',
'CoreUpdater_DatabaseUpgradeRequired' => 'Database Upgrade Required',
'CoreUpdater_YourDatabaseIsOutOfDate' => 'Your Piwik database is out-of-date, and must be upgraded before you can continue.',
- 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik database will be upgraded from version %s to the new version %s.',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik database will be upgraded from version %1$s to the new version %2$s.',
'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'The following plugins will be updated: %s.',
- 'CoreUpdater_TheUpgradeProcessMayFail' => 'If you have a large Piwik database, updates might take too long to run in the browser. In this situation, you can execute the updates from your command line: <code>$ php path/to/piwik/index.php</code>',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Important note for large Piwik installations',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'If you have a large Piwik database, updates might take too long to run in the browser. In this situation, you can execute the updates from your command line: %s',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => 'If you are not able to use the command line updater and if Piwik fails to upgrade (due to a timeout of the database, a browser timeout, or any other issue), you could manually execute the SQL queries to update Piwik.',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => 'Click here to view and copy the list of SQL queries that will get executed',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => 'Note: if you manually execute these queries, it is expected that some of them fail. In this case, simply ignore the errors, and run the next ones in the list.',
+ 'CoreUpdater_ReadyToGo' => 'Ready to go?',
'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'The database upgrade process may take a while, so please be patient.',
'CoreUpdater_UpgradePiwik' => 'Upgrade Piwik',
'CoreUpdater_ErrorDIYHelp' => 'If you are an advanced user and encounter an error in the database upgrade:',
@@ -174,7 +306,7 @@ $translations = array(
'CoreUpdater_ErrorDIYHelp_3' => 'manually update the `option` table in your Piwik database, setting the value of version_core to the version of the failed update',
'CoreUpdater_ErrorDIYHelp_4' => 're-run the updater (through the browser or command-line) to continue with the remaining updates',
'CoreUpdater_ErrorDIYHelp_5' => 'report the problem (and solution) so that Piwik can be improved',
- 'CoreUpdater_HelpMessageContent' => 'Check the %s Piwik FAQ %s which explains most common errors during update. %s Ask your system administrator - they may be able to help you with the error which is most likely related to your server or MySQL setup.',
+ 'CoreUpdater_HelpMessageContent' => 'Check the %1$s Piwik FAQ %2$s which explains most common errors during update. %3$s Ask your system administrator - they may be able to help you with the error which is most likely related to your server or MySQL setup.',
'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Critical Error during the update process:',
'CoreUpdater_HelpMessageIntroductionWhenError' => 'The above is the core error message. It should help explain the cause, but if you require further help please:',
'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'The update completed successfuly, however there were issues during the process. Please read the above descriptions for details. For further help:',
@@ -188,7 +320,7 @@ $translations = array(
'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'There is a new version of Piwik available for update',
'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'You can update to version %s automatically or download the package and install it manually:',
'CoreUpdater_DownloadX' => 'Download %s',
- 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Piwik One Click Update has been cancelled. If you can\'t fix the above error message, it is recommended that you manually update Piwik. %s Please check out the %sUpdate documentation%s to get started!',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Piwik One Click Update has been cancelled. If you can\'t fix the above error message, it is recommended that you manually update Piwik. %1$s Please check out the %2$sUpdate documentation%3$s to get started!',
'CoreUpdater_DownloadingUpdateFromX' => 'Downloading update from %s',
'CoreUpdater_UnpackingTheUpdate' => 'Unpacking the update',
'CoreUpdater_VerifyingUnpackedFiles' => 'Verifying the unpacked files',
@@ -200,19 +332,7 @@ $translations = array(
'CoreUpdater_ExceptionArchiveIncompatible' => 'Incompatible archive: %s',
'CoreUpdater_ExceptionArchiveEmpty' => 'Empty archive.',
'CoreUpdater_ExceptionArchiveIncomplete' => 'Archive is incomplete: some files are missing (eg. %s).',
- 'Actions_Actions' => 'Actions',
- 'Actions_SubmenuPages' => 'Pages',
- 'Actions_SubmenuPageTitles' => 'Page titles',
- 'Actions_SubmenuOutlinks' => 'Outlinks',
- 'Actions_SubmenuDownloads' => 'Downloads',
- 'Actions_ColumnClicks' => 'Clicks',
- 'Actions_ColumnUniqueClicks' => 'Unique Clicks',
- 'Actions_ColumnDownloads' => 'Downloads',
- 'Actions_ColumnUniqueDownloads' => 'Unique Downloads',
- 'Actions_ColumnPageName' => 'Page Name',
- 'Actions_ColumnPageURL' => 'Page URL',
- 'Actions_ColumnClickedURL' => 'Clicked URL',
- 'Actions_ColumnDownloadURL' => 'Download URL',
+ 'Dashboard_PluginDescription' => 'Your Web Analytics Dashboard. You can customize Your Dashboard: add new widgets, change the order of your widgets. Each user can access his own custom Dashboard.',
'Dashboard_Dashboard' => 'Dashboard',
'Dashboard_AddWidget' => 'Add a widget...',
'Dashboard_DeleteWidgetConfirm' => 'Are you sure you want to delete this widget from the dashboard?',
@@ -224,13 +344,246 @@ $translations = array(
'Dashboard_TitleClickToAdd_js' => 'Click to add to dashboard',
'Dashboard_LoadingWidget_js' => 'Loading widget, please wait...',
'Dashboard_WidgetNotFound_js' => 'Widget not found',
+ 'DBStats_PluginDescription' => 'This plugin reports the MySQL database usage by Piwik tables.',
+ 'DBStats_DatabaseUsage' => 'Database usage',
+ 'DBStats_MainDescription' => 'Piwik is storing all your web analytics data in the MySQL database. Currently, Piwik tables are using %s.',
+ 'DBStats_LearnMore' => 'To learn more about how Piwik processes data and how to make Piwik work well for medium and high traffic websites, check out the documentation %s.',
+ 'DBStats_Table' => 'Table',
+ 'DBStats_RowCount' => 'Row count',
+ 'DBStats_DataSize' => 'Data size',
+ 'DBStats_IndexSize' => 'Index size',
+ 'DBStats_TotalSize' => 'Total size',
+ 'ExampleAPI_PluginDescription' => 'Example Plugin: How to create an API for your plugin, to export your data in multiple formats without any special coding?',
+ 'ExampleFeedburner_PluginDescription' => 'Example Plugin: How to display your Feedburner subscriber in a Widget in the Dashboard?',
+ 'ExampleRssWidget_PluginDescription' => 'Example Plugin: How to create a new widget that reads a RSS feed?',
+ 'ExampleUI_PluginDescription' => 'Example Plugin: This plugin shows how to work with the Piwik UI: create tables, graphs, etc.',
+ 'Feedback_PluginDescription' => 'Send your Feedback to the Piwik Team. Share your ideas and suggestions with us!',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Do you have a bug to report or a feature request?',
+ 'Feedback_ViewAnswersToFAQ' => 'View answers to %s Frequently Asked Questions%s',
+ 'Feedback_WhyAreMyVisitsNoTracked' => 'Why aren\'t visits to my website being tracked?',
+ 'Feedback_HowToExclude' => 'How do I exclude tracking of my visits?',
+ 'Feedback_WhyWrongCountry' => 'Why does Piwik show my visit from the wrong country?',
+ 'Feedback_HowToAnonymizeIP' => 'How do I mask visitor IP addresses in my database?',
+ 'Feedback_VisitTheForums' => 'Visit the %s Forums%s',
+ 'Feedback_LearnWaysToParticipate' => 'Learn about all the ways you can %s participate%s',
+ 'Feedback_SpecialRequest' => 'Do you have a special request for the Piwik team?',
+ 'Feedback_ContactThePiwikTeam' => 'Contact the Piwik team!',
+ 'Feedback_IWantTo' => 'I want to:',
+ 'Feedback_CategoryShareStory' => 'Share a Piwik success story',
+ 'Feedback_CategorySponsor' => 'Sponsor Piwik',
+ 'Feedback_CategoryHire' => 'Hire a Piwik consultant',
+ 'Feedback_CategorySecurity' => 'Report a security issue',
+ 'Feedback_MyEmailAddress' => 'My email address:',
+ 'Feedback_MyMessage' => 'My message:',
+ 'Feedback_DetailsPlease' => '(please include details)',
+ 'Feedback_SendFeedback' => 'Send Feedback',
+ 'Feedback_ManuallySendEmailTo' => 'Please manually send your message to',
+ 'Feedback_MessageSent' => 'Your message was sent to the Piwik team.',
+ 'Feedback_ThankYou' => 'Thank you for helping us to make Piwik better!',
+ 'Feedback_ThePiwikTeam' => 'The Piwik Team',
+ 'Feedback_ExceptionBodyLength' => 'Message must be at least %s characters long.',
+ 'Feedback_ExceptionNoUrls' => 'The message cannot contain a URL, to avoid spam messages.',
+ 'Goals_Goals' => 'Goals',
+ 'Goals_Overview' => 'Overview',
+ 'Goals_GoalsOverview' => 'Goals overview',
+ 'Goals_GoalsManagement' => 'Goals management',
+ 'Goals_ConversionsOverviewBySegment' => 'Conversions overview by segment',
+ 'Goals_GoalConversionsBySegment' => 'Goal %s conversions by segment',
+ 'Goals_ViewGoalsBySegment' => 'View goals by %s',
+ 'Goals_PluginDescription' => 'Create Goals and see reports about your goal conversions: evolution over time, revenue per visit, conversions per referer, per keyword, etc.',
+ 'Goals_ColumnConversions' => 'Conversions',
+ 'Goals_ColumnConversionRate' => 'Conversion Rate',
+ 'Goals_ColumnRevenue' => 'Revenue',
+ 'Goals_GoalX' => 'Goal %s',
+ 'Goals_OverallRevenue' => '%s overall revenue',
+ 'Goals_OverallConversionRate' => '%s overall conversion rate (visits with a completed goal)',
+ 'Goals_Conversions' => '%s conversions',
+ 'Goals_ConversionRate' => '%s conversion rate',
+ 'Goals_NoGoalsNeedAccess' => 'Only an Administrator or the Super User can add Goals for a given website. Please ask your Piwik administrator to set up a Goal for your website. <br>Tracking Goals is a great way to help understand and maximize your website performance!',
+ 'Goals_AddNewGoal' => 'Add a new Goal',
+ 'Goals_AddNewGoalOrEditExistingGoal' => '%sAdd a new Goal%s or %sEdit%s existing Goals',
+ 'Goals_AddGoal_js' => 'Add Goal',
+ 'Goals_UpdateGoal_js' => 'Update Goal',
+ 'Goals_DeleteGoalConfirm_js' => 'Are you sure you want to delete the Goal %s?',
+ 'Goals_CreateNewGOal' => 'Create a new Goal',
+ 'Goals_ViewAndEditGoals' => 'View and Edit Goals',
+ 'Goals_GoalName' => 'Goal Name',
+ 'Goals_GoalIsTriggered' => 'Goal is triggered',
+ 'Goals_GoalIsTriggeredWhen' => 'Goal is triggered when',
+ 'Goals_WhenVisitors' => 'when visitors',
+ 'Goals_WhereThe' => 'where the',
+ 'Goals_Manually' => 'manually',
+ 'Goals_ManuallyTriggeredUsingJavascriptFunction' => 'Goal is manually triggered using the Javascript API trackGoal()',
+ 'Goals_VisitUrl' => 'Visit a given URL (page or group of pages)',
+ 'Goals_URL' => 'URL',
+ 'Goals_Filename' => 'filename',
+ 'Goals_ExternalWebsiteUrl' => 'external website URL',
+ 'Goals_Download' => 'Download a file',
+ 'Goals_ClickOutlink' => 'Click on a Link to an external website',
+ 'Goals_Optional' => '(optional)',
+ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => 'where the visited page contains a call to the JavaScript piwikTracker.trackGoal() method (%slearn more%s)',
+ 'Goals_DefaultRevenue' => 'Goal default revenue is',
+ 'Goals_DefaultRevenueHelp' => 'For example, a Contact Form submitted by a visitor may be worth $10 on average. Piwik will help you understand how well your visitors segments are performing.',
+ 'Goals_ConversionsOverview' => 'Conversions Overview',
+ 'Goals_BestCountries' => 'Your best converting countries are:',
+ 'Goals_BestKeywords' => 'Your top converting keywords are:',
+ 'Goals_BestReferers' => 'Your best converting websites referers are:',
+ 'Goals_ReturningVisitorsConversionRateIs' => 'Returning visitors conversion rate is %s',
+ 'Goals_NewVisitorsConversionRateIs' => 'New visitors conversion rate is %s',
+ 'Goals_Contains' => 'contains %s',
+ 'Goals_IsExactly' => 'is exactly %s',
+ 'Goals_MatchesExpression' => 'matches the expression %s',
+ 'Goals_CaseSensitive' => 'Case sensitive match',
+ 'Goals_Pattern' => 'Pattern',
+ 'Goals_ExceptionInvalidMatchingString' => 'If you choose \'exact match\', the matching string must be a URL starting with %s. For example, \'%s\'.',
+ 'Goals_LearnMoreAboutGoalTrackingDocumentation' => 'Learn more about %s Tracking Goals in Piwik%s in the user documentation.',
+ 'Installation_PluginDescription' => 'Installation process of Piwik. The Installation is usually done once only. If the configuration file config/config.inc.php is deleted, the installation will start again.',
+ 'Installation_Installation' => 'Installation',
+ 'Installation_InstallationStatus' => 'Installation status',
+ 'Installation_PercentDone' => '%s %% Done',
+ 'Installation_NoConfigFound' => 'The Piwik configuration file couldn\'t be found and you are trying to access a Piwik page.<br /><b>&nbsp;&nbsp;&raquo; You can <a href=\'index.php\'>install Piwik now</a></b><br /><small>If you installed Piwik before and have some tables in your DB, don\'t worry, you can reuse the same tables and keep your existing data!</small>',
+ 'Installation_DatabaseSetup' => 'Database setup',
+ 'Installation_DatabaseSetupServer' => 'database server',
+ 'Installation_DatabaseSetupLogin' => 'login',
+ 'Installation_DatabaseSetupPassword' => 'password',
+ 'Installation_DatabaseSetupDatabaseName' => 'database name',
+ 'Installation_DatabaseSetupTablePrefix' => 'table prefix',
+ 'Installation_DatabaseSetupAdapter' => 'adapter',
+ 'Installation_DatabaseErrorConnect' => 'Error while trying to connect to the database server',
+ 'Installation_DatabaseCheck' => 'Database check',
+ 'Installation_DatabaseServerVersion' => 'Database server version',
+ 'Installation_DatabaseClientVersion' => 'Database client version',
+ 'Installation_DatabaseCreation' => 'Database creation',
+ 'Installation_PleaseFixTheFollowingErrors' => 'Please fix the following errors',
+ 'Installation_JsTag' => 'JavaScript tag',
+ 'Installation_JsTagHelp' => '<p>To count all visitors, you must insert the JavaScript code on all of your pages.</p><p>Your pages do not have to be made with PHP, Piwik will work on all kinds of pages (whether it is HTML, ASP, Perl or any other languages).</p><p>Here is the code you have to insert: (copy and paste on all your pages) </p>',
+ 'Installation_JsTagHelpTitle' => 'How to insert the tag in your websites?',
+ 'Installation_LargePiwikInstances' => 'Help for large Piwik instances',
+ 'Installation_JsTagArchivingHelp' => 'For medium and high traffic websites, check out the <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">How to setup auto archiving page</a> to make Piwik run really fast!',
+ 'Installation_Congratulations' => 'Congratulations',
+ 'Installation_CongratulationsHelp' => '<p>Congratulations! Your Piwik installation is complete.</p><p>Make sure your JavaScript code is entered on your pages, and wait for your first visitors!</p>',
+ 'Installation_ContinueToPiwik' => 'Continue to Piwik',
+ 'Installation_SetupWebsite' => 'Setup a website',
+ 'Installation_SetupWebSiteName' => 'website name',
+ 'Installation_SetupWebSiteURL' => 'website URL',
+ 'Installation_Timezone' => 'website time zone',
+ 'Installation_SetupWebsiteError' => 'There was an error when adding the website',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Website %s created with success!',
+ 'Installation_GeneralSetup' => 'General Setup',
+ 'Installation_GeneralSetupSuccess' => 'General Setup configured with success',
+ 'Installation_SuperUserLogin' => 'super user login',
+ 'Installation_Password' => 'password',
+ 'Installation_PasswordRepeat' => 'password (repeat)',
+ 'Installation_Email' => 'email',
+ 'Installation_SecurityNewsletter' => 'email me with major Piwik upgrades and security alerts',
+ 'Installation_CommunityNewsletter' => 'email me with community updates (new plugins, new features, etc.)',
+ 'Installation_PasswordDoNotMatch' => 'password do not match',
+ 'Installation_SubmitGo' => 'Go!',
+ 'Installation_Requirements' => 'Piwik Requirements',
+ 'Installation_Optional' => 'Optional',
+ 'Installation_Legend' => 'Legend',
+ 'Installation_Extension' => 'extension',
+ 'Installation_SystemCheck' => 'System check',
+ 'Installation_SystemCheckPhp' => 'PHP version',
+ 'Installation_SystemCheckExtensions' => 'Other required extensions',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik requires either the mysqli extension or both the PDO and pdo_mysql extensions.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => "On a Linux server you can compile php with the following options: %1\$s\nIn your php.ini, add the following lines: %2\$s",
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'More information on: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> and <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'On a Windows server you can add the following lines to your php.ini: %s',
+ 'Installation_SystemCheckSplHelp' => 'You need to configure and rebuild PHP with the Standard PHP Library (SPL) enabled (by default).',
+ 'Installation_SystemCheckZlibHelp' => 'You need to configure and rebuild PHP with "zlib" support enabled, --with-zlib.',
+ 'Installation_SystemCheckIconvHelp' => 'You need to configure and rebuild PHP with "iconv" support enabled, --with-iconv.',
+ 'Installation_SystemCheckDomHelp' => 'DOM is part of PHP core. You probably need to install the dom module, e.g., php-5-dom.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'You need to configure and rebuild PHP with either "json" or "xml" extensions enabled.',
+ 'Installation_SystemCheckJsonSite' => 'More information on: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Some third-party plugins and developer libraries may require the "xml" extension.',
+ 'Installation_SystemCheckXmlSite' => 'More information on: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckWriteDirs' => 'Directories with write access',
+ 'Installation_SystemCheckWriteDirsHelp' => 'To fix this error on your Linux system, try typing in the following command(s)',
+ 'Installation_SystemCheckMemoryLimit' => 'Memory limit',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'On a high traffic website, the archiving process may require more memory than currently allowed. If necessary, change the memory_limit directive in your php.ini file.',
+ 'Installation_SystemCheckOpenURL' => 'Open URL',
+ 'Installation_SystemCheckOpenURLHelp' => 'Newsletter subscriptions, update notifications, and one-click updates requires the "curl" extension, allow_url_fopen=On, or fsockopen() enabled.',
+ 'Installation_SystemCheckGD' => 'GD &gt; 2.x (graphics)',
+ 'Installation_SystemCheckGDHelp' => 'The sparklines (small graphs) will not work.',
+ 'Installation_SystemCheckFunctions' => 'Required functions',
+ 'Installation_SystemCheckTimeLimitHelp' => 'On a high traffic website, executing the archiving process may require more time than currently allowed. If necessary, change the max_execution_time directive in your php.ini file.',
+ 'Installation_SystemCheckMailHelp' => 'Feedback and Lost Password messages will not be sent without mail().',
+ 'Installation_SystemCheckParseIniFileHelp' => 'This built-in function has been disabled on your host. Piwik will attempt to emulate this function but may encounter further security restrictions. Tracker performance will also be impacted.',
+ 'Installation_SystemCheckDebugBacktraceHelp' => 'View::factory won\'t be able to create views for the calling module.',
+ 'Installation_SystemCheckCreateFunctionHelp' => 'Piwik uses anonymous functions for callbacks.',
+ 'Installation_SystemCheckEvalHelp' => 'Required by HTML QuickForm and Smarty templating system.',
+ 'Installation_SystemCheckMbstring' => 'mbstring',
+ 'Installation_SystemCheckMbstringHelp' => 'You should set mbstring.func_overload to "0".',
+ 'Installation_SystemCheckFileIntegrity' => 'File integrity',
+ 'Installation_SystemCheckError' => 'An error occured - must be fixed before you proceed',
+ 'Installation_SystemCheckWarning' => 'Piwik will work normally but some features may be missing',
+ 'Installation_SystemCheckProtocol' => 'Protocol',
+ 'Installation_SystemCheckProtocolHelp' => 'If you are behind a reverse proxy, add these lines to config/config.ini.php under the [General] section:',
+ 'Installation_SystemCheckIpv4' => 'IPv4',
+ 'Installation_SystemCheckIpv4Help' => 'You should disable IPv6 in your web server configuration.',
+ 'Installation_Tables' => 'Creating the tables',
+ 'Installation_TablesWithSameNamesFound' => 'Some %1$s tables in your database %2$s have the same names as the tables Piwik is trying to create',
+ 'Installation_TablesFound' => 'The following tables have been found in the database',
+ 'Installation_TablesWarningHelp' => 'Either choose to reuse the existing database tables or select a clean install to erase all existing data in the database.',
+ 'Installation_TablesReuse' => 'Reuse the existing tables',
+ 'Installation_TablesDelete' => 'Delete the detected tables',
+ 'Installation_TablesDeletedSuccess' => 'Existing Piwik tables deleted with success',
+ 'Installation_TablesCreatedSuccess' => 'Tables created with success!',
+ 'Installation_DatabaseCreatedSuccess' => 'Database %s created with success!',
+ 'Installation_GoBackAndDefinePrefix' => 'Go back and define a Prefix for the Piwik Tables',
+ 'Installation_ConfirmDeleteExistingTables' => 'Are you sure you want to delete the tables: %s from your database? WARNING: DATA FROM THESE TABLES CANNOT BE RECOVERED!',
+ 'Installation_Welcome' => 'Welcome!',
+ 'Installation_WelcomeHelp' => '<p>Piwik is an open source web analytics software that makes it easy to get the information you want from your visitors.</p><p>This process is split up into %s easy steps and will take around 5 minutes.</p>',
+ 'Installation_ConfigurationHelp' => 'Your Piwik configuration file appears to be misconfigured. You can either remove config/config.ini.php and resume installation, or correct the database connection settings.',
+ 'Installation_ErrorInvalidState' => 'Error: it seems you tried to skip a step of the Installation process, or your cookies are disabled, or the Piwik configuration file was already created. %1$sMake sure your cookies are enabled%2$s and go back %3$s to the first page of the installation %4$s.',
+ 'LanguagesManager_PluginDescription' => 'This plugin will display a list of the available languages for the Piwik interface. The language selected will be saved in the preferences for each user.',
+ 'LanguagesManager_AboutPiwikTranslations' => 'About Piwik translations',
+ 'Live_PluginDescription' => 'Spy on your visitors, live, in real-time!',
+ 'Live_VisitorLog' => 'Visitor Log',
+ 'Live_Date' => 'Date',
+ 'Live_Time' => 'Time',
+ 'Live_Referrer_URL' => 'Referrer URL',
+ 'Live_Last30Minutes' => 'Last 30 minutes',
+ 'Login_PluginDescription' => 'Login Authentication plugin, reading the credentials from the config/config.inc.php file for the Super User, and from the Database for the other users. Can be easily replaced to introduce a new Authentication mechanism (OpenID, htaccess, custom Auth, etc.).',
+ 'Login_LoginPasswordNotCorrect' => 'Username &amp; Password not correct',
+ 'Login_Password' => 'Password',
+ 'Login_PasswordRepeat' => 'Password (repeat)',
+ 'Login_ChangePassword' => 'Change password',
+ 'Login_LoginOrEmail' => 'Username or E-mail',
+ 'Login_LogIn' => 'Sign in',
+ 'Login_Logout' => 'Sign out',
+ 'Login_LostYourPassword' => 'Lost your password?',
+ 'Login_RemindPassword' => 'Send password reset',
+ 'Login_PasswordResetToken' => 'Password reset token',
+ 'Login_PasswordReminder' => 'Please enter your username or e-mail address. You will receive an e-mail with information to reset your password.',
+ 'Login_PasswordsDoNotMatch' => 'Passwords do not match.',
+ 'Login_PasswordSuccessfullyChanged' => 'Password successfully changed!',
+ 'Login_InvalidUsernameEmail' => 'Invalid username and/or e-mail address',
+ 'Login_InvalidNonceOrReferer' => 'Form security key is invalid or has expired. Please reload the form and check that your cookies are enabled.',
+ 'Login_InvalidOrExpiredToken' => 'Token is invalid or has expired.',
+ 'Login_MailTopicPasswordRecovery' => 'Password recovery',
+ 'Login_MailPasswordRecoveryBody' => "Hi %1\$s,\n\nA password reset request was received from %2\$s.\n\nTo reset your password:\n\n1) Go to the Password Reset Form at:\n\t%3\$s\n\n2) Enter the following token:\n\t%4\$s\n\n3) Fill out the form (entering your new password twice) and submit.\n\nNote: this token will expire in 24 hrs.",
+ 'Login_PasswordSent' => 'Information to reset your password has been sent. Check your e-mail.',
+ 'Login_ContactAdmin' => 'Possible reason: your host may have disabled the mail() function. <br />Please contact your Piwik administrator.',
+ 'Login_ExceptionPasswordMD5HashExpected' => 'The password parameter is expected to be a MD5 hash of the password.',
+ 'Login_ExceptionInvalidSuperUserAuthenticationMethod' => 'The Super User cannot be authenticated using the \'%s\' mechanism.',
+ 'MultiSites_PluginDescription' => 'Displays multi-site executive summary/statistics. Currently maintained as a core Piwik plugin.',
+ 'MultiSites_Evolution' => 'Evolution',
+ 'Provider_PluginDescription' => 'Reports the Provider of the visitors.',
+ 'Provider_WidgetProviders' => 'Providers',
+ 'Provider_ColumnProvider' => 'Provider',
+ 'Provider_SubmenuLocationsProvider' => 'Locations &amp; Provider',
+ 'Referers_PluginDescription' => 'Reports the Referers data: Search Engines, Keywords, Websites, Campaign Tracking, Direct Entry.',
'Referers_Referers' => 'Referers',
'Referers_SearchEngines' => 'Search Engines',
'Referers_Keywords' => 'Keywords',
'Referers_DirectEntry' => 'Direct Entry',
'Referers_Websites' => 'Websites',
'Referers_Campaigns' => 'Campaigns',
- 'Referers_MetricsFromRefererTypeGraphLegend' => '%s (from %s)',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%1$s (from %2$s)',
'Referers_Evolution' => 'Evolution over the period',
'Referers_Type' => 'Referer Type',
'Referers_ColumnRefererType' => 'Referer Type',
@@ -249,9 +602,9 @@ $translations = array(
'Referers_DistinctKeywords' => 'distinct keywords',
'Referers_DistinctCampaigns' => 'distinct campaigns',
'Referers_DistinctWebsites' => 'distinct websites',
- 'Referers_UsingNDistinctUrls' => ' (using %2s distinct urls)',
+ 'Referers_UsingNDistinctUrls' => ' (using %s distinct urls)',
'Referers_SubmenuEvolution' => 'Evolution',
- 'Referers_SubmenuSearchEngines' => 'Search engines & keywords',
+ 'Referers_SubmenuSearchEngines' => 'Search Engines &amp; Keywords',
'Referers_SubmenuWebsites' => 'Websites',
'Referers_SubmenuCampaigns' => 'Campaigns',
'Referers_WidgetKeywords' => 'List of Keywords',
@@ -259,32 +612,78 @@ $translations = array(
'Referers_WidgetExternalWebsites' => 'List of external Websites',
'Referers_WidgetSearchEngines' => 'Best search engines',
'Referers_WidgetOverview' => 'Overview',
- 'UserSettings_VisitorSettings' => 'Visitor Settings',
- 'UserSettings_BrowserFamilies' => 'Browser families',
- 'UserSettings_Browsers' => 'Browsers',
- 'UserSettings_Plugins' => 'Plugins',
- 'UserSettings_Configurations' => 'Configurations',
- 'UserSettings_OperatinsSystems' => 'Operating systems',
- 'UserSettings_Resolutions' => 'Resolutions',
- 'UserSettings_WideScreen' => 'Wide Screen',
- 'UserSettings_ColumnBrowserFamily' => 'Browser family',
- 'UserSettings_ColumnBrowser' => 'Browser',
- 'UserSettings_ColumnPlugin' => 'Plugin',
- 'UserSettings_ColumnConfiguration' => 'Configuration',
- 'UserSettings_ColumnOperatinsSystem' => 'Operating system',
- 'UserSettings_ColumnResolution' => 'Resolution',
- 'UserSettings_ColumnTypeOfScreen' => 'Type of screen',
- 'UserSettings_WidgetResolutions' => 'Screen resolutions',
- 'UserSettings_WidgetBrowsers' => 'Visitor browsers',
- 'UserSettings_WidgetPlugins' => 'List of Plugins',
- 'UserSettings_WidgetWidescreen' => 'Normal / Widescreen',
- 'UserSettings_WidgetBrowserFamilies' => 'Browsers by family',
- 'UserSettings_WidgetOperatingSystems' => 'Operating systems',
- 'UserSettings_WidgetGlobalVisitors' => 'Global visitors configuration',
- 'UserSettings_SubmenuSettings' => 'Settings',
+ 'SecurityInfo_PluginDescription' => 'Based on PhpSecInfo from the PHP Security Consortium, this plugin provides security information about your PHP environment and offers suggestions for improvement. It is a tool in a multilayered security approach. It does not replace secure development practices nor audit the code/application.',
+ 'SecurityInfo_Security' => 'Security',
+ 'SecurityInfo_SecurityInformation' => 'PHP Security Information',
+ 'SecurityInfo_Test' => 'Test',
+ 'SecurityInfo_Result' => 'Result',
+ 'SitesManager_PluginDescription' => 'Websites Management in Piwik: Add a new Website, Edit an existing one, Show the Javascript code to include on your pages. All the actions are also available through the API.',
+ 'SitesManager_Sites' => 'Websites',
+ 'SitesManager_WebsitesManagement' => 'Websites Management',
+ 'SitesManager_MainDescription' => 'Your Web Analytics reports need Websites! Add, update, delete Websites, and show the JavaScript to insert in your pages.',
+ 'SitesManager_JsTrackingTag' => 'JavaScript Tracking Tag',
+ 'SitesManager_JsTrackingTagHelp' => 'Here is the JavaScript Tracking tag to include on all your pages',
+ 'SitesManager_ShowTrackingTag' => 'show tracking tag',
+ 'SitesManager_NoWebsites' => 'You don\'t have any website to administrate.',
+ 'SitesManager_AddSite' => 'Add a new website',
+ 'SitesManager_AliasUrlHelp' => "It is recommended, but not required, to specify the various URLs, one per line, that your visitors use to access this website.\nAlias URLs for a website will not appear in the Referers > Websites report.\nNote that it is not necessary to specify the URLs with and without 'www' as Piwik automatically considers both.",
+ 'SitesManager_Id' => 'Id',
+ 'SitesManager_Name' => 'Name',
+ 'SitesManager_Urls' => 'URLs',
+ 'SitesManager_MenuSites' => 'Websites',
+ 'SitesManager_DeleteConfirm_js' => 'Are you sure you want to delete the website %s?',
+ 'SitesManager_ExceptionDeleteSite' => 'It is not possible to delete this website as it is the only registered website. Add a new website first, then delete this one.',
+ 'SitesManager_ExceptionNoUrl' => 'You must specify at least one URL for the website.',
+ 'SitesManager_ExceptionEmptyName' => 'The website name can\'t be empty.',
+ 'SitesManager_ExceptionInvalidUrl' => 'The url \'%s\' is not a valid URL.',
+ 'SitesManager_ExceptionInvalidTimezone' => 'The timezone "%s" is not valid. Please enter a valid timezone.',
+ 'SitesManager_ExceptionInvalidCurrency' => 'The currency "%s" is not valid. Please enter a valid currency symbol (eg. %s)',
+ 'SitesManager_ExceptionInvalidIPFormat' => 'The IP to exclude "%s" does not have a valid IP format (eg. %s).',
+ 'SitesManager_SuperUserCan' => 'The Super User can also %s specify global settings%s for new websites.',
+ 'SitesManager_ExcludedIps' => 'Excluded IPs',
+ 'SitesManager_GlobalListExcludedIps' => 'Global list of Excluded IPs',
+ 'SitesManager_ListOfIpsToBeExcludedOnAllWebsites' => 'The IPs below will be excluded from being tracked on all websites.',
+ 'SitesManager_ExcludedParameters' => 'Excluded Parameters',
+ 'SitesManager_GlobalListExcludedQueryParameters' => 'Global list of Query URL parameters to exclude',
+ 'SitesManager_ListOfQueryParametersToBeExcludedOnAllWebsites' => 'The Query URLs parameters below will be excluded from URLs on all websites.',
+ 'SitesManager_ListOfQueryParametersToExclude' => 'Enter the list of URL Query Parameters, one per line, to exclude from the Page URLs reports.',
+ 'SitesManager_PiwikWillAutomaticallyExcludeCommonSessionParameters' => 'Piwik will automatically exclude the common session parameters (%s).',
+ 'SitesManager_HelpExcludedIps' => 'Enter the list of IPs, one per line, that you wish to exclude from being tracked by Piwik. You can use wildcards, eg. %1$s or %2$s',
+ 'SitesManager_YourCurrentIpAddressIs' => 'Your current IP address is %s',
+ 'SitesManager_SelectACity' => 'Select a city',
+ 'SitesManager_ChooseCityInSameTimezoneAsYou' => 'Choose a city in the same time zone as you.',
+ 'SitesManager_ChangingYourTimezoneWillOnlyAffectDataForward' => 'Changing your time zone will only affect data going forward, and will not be applied retroactively.',
+ 'SitesManager_AdvancedTimezoneSupportNotFound' => 'Advanced timezones support was not found in your PHP (supported in PHP>=5.2). You can still choose a manual UTC offset.',
+ 'SitesManager_UTCTimeIs' => 'UTC time is %s.',
+ 'SitesManager_Timezone' => 'Time zone',
+ 'SitesManager_GlobalWebsitesSettings' => 'Global websites settings',
+ 'SitesManager_DefaultTimezoneForNewWebsites' => 'Default Time zone for new websites',
+ 'SitesManager_SelectDefaultTimezone' => 'You can select the time zone to select by default for new websites.',
+ 'SitesManager_Currency' => 'Currency',
+ 'SitesManager_CurrencySymbolWillBeUsedForGoals' => 'The Currency symbol will be displayed next to Goals revenues.',
+ 'SitesManager_DefaultCurrencyForNewWebsites' => 'Default Currency for new websites',
+ 'SitesManager_SelectDefaultCurrency' => 'You can select the currency to set by default for new websites.',
+ 'SitesManager_Save_js' => 'Save',
+ 'SitesManager_Cancel_js' => 'Cancel',
+ 'TranslationsAdmin_PluginDescription' => 'Help translate Piwik into your language.',
+ 'TranslationsAdmin_MenuTranslations' => 'Translations',
+ 'TranslationsAdmin_MenuLanguages' => 'Languages',
+ 'TranslationsAdmin_Plugin' => 'Plugin',
+ 'TranslationsAdmin_Definition' => 'Definition',
+ 'TranslationsAdmin_DefaultString' => 'Default string (English)',
+ 'TranslationsAdmin_TranslationString' => 'Translation string (current language: %s)',
+ 'TranslationsAdmin_Translations' => 'Translations',
+ 'TranslationsAdmin_FixPermissions' => 'Please fix filesystem permissions',
+ 'TranslationsAdmin_AvailableLanguages' => 'Available languages',
+ 'TranslationsAdmin_AddLanguage' => 'Add language',
+ 'TranslationsAdmin_LanguageCode' => 'Language code',
+ 'TranslationsAdmin_Export' => 'Export language',
+ 'TranslationsAdmin_Import' => 'Import language',
+ 'UserCountry_PluginDescription' => 'Reports the Country of the visitors.',
'UserCountry_Country' => 'Country',
'UserCountry_Continent' => 'Continent',
'UserCountry_DistinctCountries' => '%s distinct countries',
+ 'UserCountry_Location' => 'Location',
'UserCountry_SubmenuLocations' => 'Locations',
'UserCountry_WidgetContinents' => 'Visitor continents',
'UserCountry_WidgetCountries' => 'Visitor countries',
@@ -557,76 +956,31 @@ $translations = array(
'UserCountry_continent_ams' => 'South and Central America',
'UserCountry_continent_amn' => 'North America',
'UserCountry_continent_oce' => 'Oceania',
- 'VisitsSummary_VisitsSummary' => 'Visits Summary',
- 'VisitsSummary_NbVisits' => '%s visits',
- 'VisitsSummary_NbUniqueVisitors' => '%s unique visitors',
- 'VisitsSummary_NbActions' => '%s actions (page views)',
- 'VisitsSummary_TotalTime' => '%s total time spent by the visitors',
- 'VisitsSummary_MaxNbActions' => '%s max actions in one visit',
- 'VisitsSummary_NbVisitsBounced' => '%s visits have bounced (left the website after one page)',
- 'VisitsSummary_EvolutionOverLastPeriods' => 'Evolution over the last %s',
- 'VisitsSummary_Report' => 'Report',
- 'VisitsSummary_GenerateTime' => '%s seconds to generate the page',
- 'VisitsSummary_GenerateQueries' => '%s queries executed',
- 'VisitsSummary_WidgetLastVisits' => 'Last visits graph',
- 'VisitsSummary_WidgetVisits' => 'Visits overview',
- 'VisitsSummary_WidgetLastVisitors' => 'Last unique visitors graph',
- 'VisitsSummary_WidgetOverviewGraph' => 'Overview with graph',
- 'VisitsSummary_SubmenuOverview' => 'Overview',
- 'VisitFrequency_Evolution' => 'Evolution over the period',
- 'VisitFrequency_ColumnReturningVisits' => 'Returning Visits',
- 'VisitFrequency_ColumnActionsByReturningVisits' => 'Actions by Returning Visits',
- 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Maximum Actions by a Returning Visit',
- 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Total time spent by Returning Visits (in seconds)',
- 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Bounce rate for Returning Visits',
- 'VisitFrequency_ReturnVisits' => '%s returning visits',
- 'VisitFrequency_ReturnActions' => '%s actions by the returning visits',
- 'VisitFrequency_ReturnMaxActions' => '%s maximum actions by a returning visit',
- 'VisitFrequency_ReturnTotalTime' => '%s total time spent by returning visits',
- 'VisitFrequency_ReturnBounceRate' => '%s returning visits have bounced (left the website after one page)',
- 'VisitFrequency_WidgetOverview' => 'Frequency overview',
- 'VisitFrequency_WidgetGraphReturning' => 'Graph returning visits',
- 'VisitFrequency_SubmenuFrequency' => 'Frequency',
- 'VisitTime_LocalTime' => 'Visits per local time',
- 'VisitTime_ServerTime' => 'Visits per server time',
- 'VisitTime_ColumnServerTime' => 'Server time',
- 'VisitTime_ColumnLocalTime' => 'Local time',
- 'VisitTime_WidgetLocalTime' => 'Visits by local time',
- 'VisitTime_WidgetServerTime' => 'Visits by server time',
- 'VisitTime_SubmenuTimes' => 'Times',
- 'VisitTime_NHour' => '%sh',
- 'VisitorInterest_VisitsPerDuration' => 'Visits per visit duration',
- 'VisitorInterest_VisitsPerNbOfPages' => 'Visits per number of pages',
- 'VisitorInterest_ColumnVisitDuration' => 'Visit duration',
- 'VisitorInterest_ColumnPagesPerVisit' => 'Pages per visit',
- 'VisitorInterest_WidgetLengths' => 'Length of Visits',
- 'VisitorInterest_WidgetPages' => 'Pages per visit',
- 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Frequency & Loyalty',
- 'VisitorInterest_PlusXMin' => '%s min',
- 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
- 'VisitorInterest_OnePage' => '1 page',
- 'VisitorInterest_NPages' => '%s pages',
- 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
- 'Login_LoginPasswordNotCorrect' => 'Username & Password not correct',
- 'Login_Login' => 'Username',
- 'Login_Password' => 'Password',
- 'Login_PasswordRepeat' => 'Password (repeat)',
- 'Login_ChangePassword' => 'Change password',
- 'Login_LoginOrEmail' => 'Login or E-mail',
- 'Login_LogIn' => 'Sign in',
- 'Login_Logout' => 'Sign out',
- 'Login_LostYourPassword' => 'Lost your password?',
- 'Login_RemindPassword' => 'Send password reset',
- 'Login_PasswordResetToken' => 'Password reset token',
- 'Login_PasswordReminder' => 'Please enter your username or e-mail address. You will receive an e-mail with information to reset your password.',
- 'Login_PasswordsDoNotMatch' => 'Passwords do not match.',
- 'Login_PasswordSuccessfullyChanged' => 'Password successfully changed!',
- 'Login_InvalidUsernameEmail' => 'Invalid username and/or e-mail address',
- 'Login_InvalidOrExpiredToken' => 'Token is invalid or has expired',
- 'Login_MailTopicPasswordRecovery' => 'Password recovery',
- 'Login_MailPasswordRecoveryBody' => "Hi %s,\n\nA password reset request was received from %s.\n\nTo reset your password:\n\n1) Go to the Password Reset Form at:\n\t%s\n\n2) Enter the following token:\n\t%s\n\n3) Fill out the form (entering your new password twice) and submit.\n\nNote: this token will expire in 24 hrs.\n",
- 'Login_PasswordSent' => 'Information to reset your password has been sent. Check your e-mail.',
- 'Login_ContactAdmin' => 'Possible reason: your host may have disabled the mail() function. <br />Please contact your Piwik administrator.',
+ 'UserSettings_PluginDescription' => 'Reports various User Settings: Browser, Browser Family, Operating System, Plugins, Resolution, Global Settings.',
+ 'UserSettings_VisitorSettings' => 'Visitor Settings',
+ 'UserSettings_BrowserFamilies' => 'Browser families',
+ 'UserSettings_Browsers' => 'Browsers',
+ 'UserSettings_Plugins' => 'Plugins',
+ 'UserSettings_Configurations' => 'Configurations',
+ 'UserSettings_OperatingSystems' => 'Operating systems',
+ 'UserSettings_Resolutions' => 'Resolutions',
+ 'UserSettings_WideScreen' => 'Wide Screen',
+ 'UserSettings_ColumnBrowserFamily' => 'Browser family',
+ 'UserSettings_ColumnBrowser' => 'Browser',
+ 'UserSettings_ColumnPlugin' => 'Plugin',
+ 'UserSettings_ColumnConfiguration' => 'Configuration',
+ 'UserSettings_ColumnOperatingSystem' => 'Operating system',
+ 'UserSettings_ColumnResolution' => 'Resolution',
+ 'UserSettings_ColumnTypeOfScreen' => 'Type of screen',
+ 'UserSettings_WidgetResolutions' => 'Screen resolutions',
+ 'UserSettings_WidgetBrowsers' => 'Visitor browsers',
+ 'UserSettings_WidgetPlugins' => 'List of Plugins',
+ 'UserSettings_WidgetWidescreen' => 'Normal / Widescreen',
+ 'UserSettings_WidgetBrowserFamilies' => 'Browsers by family',
+ 'UserSettings_WidgetOperatingSystems' => 'Operating systems',
+ 'UserSettings_WidgetGlobalVisitors' => 'Global visitors configuration',
+ 'UserSettings_SubmenuSettings' => 'Settings',
+ 'UsersManager_PluginDescription' => 'Users Management in Piwik: add a new User, edit an existing one, update the permissions. All the actions are also available through the API.',
'UsersManager_UsersManagement' => 'Users Management',
'UsersManager_UsersManagementMainDescription' => 'Create new users or update the existing users. You can then set their permissions above.',
'UsersManager_ManageAccess' => 'Manage access',
@@ -639,17 +993,34 @@ $translations = array(
'UsersManager_PrivView' => 'View',
'UsersManager_PrivAdmin' => 'Admin',
'UsersManager_ChangeAllConfirm' => 'Are you sure you want to change \'%s\' permissions on all the websites?',
- 'UsersManager_Login' => 'Login',
'UsersManager_Password' => 'Password',
'UsersManager_Email' => 'Email',
'UsersManager_Alias' => 'Alias',
+ 'UsersManager_TheSuperUserAliasCannotBeChanged' => 'The Super User alias cannot be changed.',
+ 'UsersManager_ReportToLoadByDefault' => 'Report to load by default',
+ 'UsersManager_ReportDateToLoadByDefault' => 'Report date to load by default',
+ 'UsersManager_ForAnonymousUsersReportDateToLoadByDefault' => 'For anonymous users, report date to load by default',
+ 'UsersManager_ExcludeVisitsViaCookie' => 'Exclude your visits using a cookie',
+ 'UsersManager_YourVisitsAreIgnoredOnDomain' => '%sYour visits are ignored by Piwik on %s %s (the Piwik ignore cookie was found in your browser).',
+ 'UsersManager_YourVisitsAreNotIgnored' => '%sYour visits are not ignored by Piwik%s (the Piwik ignore cookie was not found in your browser).',
+ 'UsersManager_ClickHereToDeleteTheCookie' => 'Click here to delete the cookie and have Piwik track your visits',
+ 'UsersManager_ClickHereToSetTheCookieOnDomain' => 'Click here to set a cookie that will exclude your visits on websites tracked by Piwik on %s',
'UsersManager_Edit' => 'Edit',
'UsersManager_AddUser' => 'Add a new user',
'UsersManager_MenuUsers' => 'Users',
+ 'UsersManager_MenuUserSettings' => 'User settings',
+ 'UsersManager_MenuAnonymousUserSettings' => 'Anonymous user settings',
+ 'UsersManager_NoteNoAnonymousUserAccessSettingsWontBeUsed' => 'Note: You do not have any website that the anonymous user can access, the following settings won\'t be used.',
+ 'UsersManager_WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess' => 'When users are not logged in and visit Piwik, they should access',
+ 'UsersManager_ChangePassword' => 'Change password',
+ 'UsersManager_IfYouWouldLikeToChangeThePasswordTypeANewOne' => 'If you would like to change the password type a new one. Otherwise leave this blank.',
+ 'UsersManager_TypeYourPasswordAgain' => 'Type your new password again.',
+ 'UsersManager_TheLoginScreen' => 'The login screen',
'UsersManager_DeleteConfirm_js' => 'Are you sure you want to delete the user %s?',
+ 'UsersManager_YourUsernameCannotBeChanged' => 'Your username cannot be changed.',
'UsersManager_ExceptionLoginExists' => 'Login \'%s\' already exists.',
'UsersManager_ExceptionEmailExists' => 'User with email \'%s\' already exists.',
- 'UsersManager_ExceptionInvalidLoginFormat' => 'The login must be between %s and %s characters long and contain only letters, numbers, or the characters \'_\' or \'-\' or \'.\'',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'The login must be between %1$s and %2$s characters long and contain only letters, numbers, or the characters \'_\' or \'-\' or \'.\'',
'UsersManager_ExceptionInvalidPassword' => 'The password length must be between 6 and 26 characters.',
'UsersManager_ExceptionInvalidEmail' => 'The email doesn\'t have a valid format.',
'UsersManager_ExceptionDeleteDoesNotExist' => 'User \'%s\' doesn\'t exist therefore it can\'t be deleted.',
@@ -658,122 +1029,76 @@ $translations = array(
'UsersManager_ExceptionSuperUser' => 'Requested user is the Super User and cannot be queried, edited or deleted via the API. You can manually edit the Super User details in your Piwik configuration file.',
'UsersManager_ExceptionUserDoesNotExist' => 'User \'%s\' doesn\'t exist.',
'UsersManager_ExceptionAccessValues' => 'The parameter access must have one of the following values : [ %s ]',
- 'SitesManager_Sites' => 'Websites',
- 'SitesManager_WebsitesManagement' => 'Websites Management',
- 'SitesManager_MainDescription' => 'Your Web Analytics reports need Websites! Add, update, delete Websites, and show the JavaScript to insert in your pages.',
- 'SitesManager_JsTrackingTag' => 'JavaScript Tracking Tag',
- 'SitesManager_JsTrackingTagHelp' => 'Here is the JavaScript Tracking tag to include on all your pages',
- 'SitesManager_ShowTrackingTag' => 'show tracking tag',
- 'SitesManager_NoWebsites' => 'You don\'t have any website to administrate.',
- 'SitesManager_AddSite' => 'Add a new website',
- 'SitesManager_Id' => 'Id',
- 'SitesManager_Name' => 'Name',
- 'SitesManager_Urls' => 'URLs',
- 'SitesManager_MenuSites' => 'Websites',
- 'SitesManager_DeleteConfirm_js' => 'Are you sure you want to delete the website %s?',
- 'SitesManager_ExceptionDeleteSite' => 'It is not possible to delete this website as it is the only registered website. Add a new website first, then delete this one.',
- 'SitesManager_ExceptionNoUrl' => 'You must specify at least one URL for the website.',
- 'SitesManager_ExceptionEmptyName' => 'The website name can\'t be empty.',
- 'SitesManager_ExceptionInvalidUrl' => 'The url \'%s\' is not a valid URL.',
- 'Installation_Installation' => 'Installation',
- 'Installation_InstallationStatus' => 'Installation status',
- 'Installation_PercentDone' => '%s %% Done',
- 'Installation_NoConfigFound' => 'The Piwik configuration file couldn\'t be found and you are trying to access a Piwik page.<br /><b>&nbsp;&nbsp;&raquo; You can <a href=\'index.php\'>install Piwik now</a></b><br /><small>If you installed Piwik before and have some tables in your DB, don\'t worry, you can reuse the same tables and keep your existing data!</small>',
- 'Installation_DatabaseSetup' => 'Database setup',
- 'Installation_DatabaseErrorConnect' => 'Error while trying to connect to the database server',
- 'Installation_ConnectionCharacterSetNotUtf8' => 'Client connection to the database server is not UTF8',
- 'Installation_JsTag' => 'JavaScript tag',
- 'Installation_JsTagHelp' => '<p>To count all visitors, you must insert the JavaScript code on all of your pages.</p><p>Your pages do not have to be made with PHP, Piwik will work on all kinds of pages (whether it is HTML, ASP, Perl or any other languages).</p><p>Here is the code you have to insert: (copy and paste on all your pages) </p>',
- 'Installation_JsTagQuicHelpk' => 'Quick Help',
- 'Installation_JsTagArchivingHelp' => 'For medium and high traffic websites, check out the <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">How to setup auto archiving page</a> to make Piwik run really fast!',
- 'Installation_Congratulations' => 'Congratulations',
- 'Installation_CongratulationsHelp' => '<p>Congratulations! Your Piwik installation is complete.</p><p>Make sure your JavaScript code is entered on your pages, and wait for your first visitors!</p>',
- 'Installation_ContinueToPiwik' => 'Continue to Piwik',
- 'Installation_SetupWebsite' => 'Setup a website',
- 'Installation_SetupWebsiteError' => 'There was an error when adding the website',
- 'Installation_SetupWebsiteSetupSuccess' => 'Website %s created with success!',
- 'Installation_GeneralSetup' => 'General Setup',
- 'Installation_GeneralSetupSuccess' => 'General Setup configured with success',
- 'Installation_SuperUserLogin' => 'super user login',
- 'Installation_Password' => 'password',
- 'Installation_PasswordRepeat' => 'password (repeat)',
- 'Installation_Email' => 'email',
- 'Installation_SecurityNewsletter' => 'email me with major Piwik upgrades and security alerts',
- 'Installation_CommunityNewsletter' => 'email me with community updates (new plugins, new features, etc.)',
- 'Installation_PasswordDoNotMatch' => 'password do not match',
- 'Installation_SubmitGo' => 'Go!',
- 'Installation_Requirements' => 'Piwik Requirements',
- 'Installation_Optional' => 'Optional',
- 'Installation_Legend' => 'Legend',
- 'Installation_Extension' => 'extension',
- 'Installation_SystemCheck' => 'System check',
- 'Installation_SystemCheckPhp' => 'PHP version',
- 'Installation_SystemCheckExtensions' => 'Other required extensions',
- 'Installation_SystemCheckDatabaseHelp' => 'Piwik requires either the mysqli extension or both the PDO and pdo_mysql extensions.',
- 'Installation_SystemCheckPdoAndMysqliHelp' => "On a Linux server you can compile php with the following options: %s\nIn your php.ini, add the following lines: %s",
- 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'More information on: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> and <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
- 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'On a Windows server you can add the following lines to your php.ini: %s',
- 'Installation_SystemCheckSplHelp' => 'You need to configure and rebuild PHP with the Standard PHP Library (SPL) enabled (by default).',
- 'Installation_SystemCheckZlibHelp' => 'You need to configure and rebuild PHP with "zlib" support enabled, --with-zlib.',
- 'Installation_SystemCheckIconvHelp' => 'You need to configure and rebuild PHP with "iconv" support enabled, --with-iconv.',
- 'Installation_SystemCheckDomHelp' => 'DOM is part of PHP core. You probably need to install the dom module, e.g., php-5-dom.',
- 'Installation_SystemCheckJson' => 'JSON',
- 'Installation_SystemCheckJsonHelp' => 'You need to configure and rebuild PHP with either "json" or "xml" extensions enabled.',
- 'Installation_SystemCheckJsonSite' => 'More information on: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
- 'Installation_SystemCheckXml' => 'XML',
- 'Installation_SystemCheckXmlHelp' => 'Some third-party plugins and developer libraries may require the "xml" extension.',
- 'Installation_SystemCheckXmlSite' => 'More information on: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
- 'Installation_SystemCheckWriteDirs' => 'Directories with write access',
- 'Installation_SystemCheckWriteDirsHelp' => 'To fix this error on your Linux system, try typing in the following command(s)',
- 'Installation_SystemCheckMemoryLimit' => 'Memory limit',
- 'Installation_SystemCheckMemoryLimitHelp' => 'On a high traffic website, the archiving process may require more memory than currently allowed. If necessary, change the memory_limit directive in your php.ini file.',
- 'Installation_SystemCheckOpenURL' => 'Open URL',
- 'Installation_SystemCheckOpenURLHelp' => 'Newsletter subscriptions, update notifications, and one-click updates requires the "curl" extension, allow_url_fopen=On, or fsockopen() enabled.',
- 'Installation_SystemCheckGD' => 'GD &gt; 2.x (graphics)',
- 'Installation_SystemCheckGDHelp' => 'The sparklines (small graphs) will not work.',
- 'Installation_SystemCheckFunctions' => 'Required functions',
- 'Installation_SystemCheckTimeLimitHelp' => 'On a high traffic website, executing the archiving process may require more time than currently allowed. If necessary, change the max_execution_time directive in your php.ini file.',
- 'Installation_SystemCheckMailHelp' => 'Feedback and Lost Password messages will not be sent without mail().',
- 'Installation_SystemCheckError' => 'An error occured - must be fixed before you proceed',
- 'Installation_SystemCheckWarning' => 'Piwik will work normally but some features may be missing',
- 'Installation_Tables' => 'Creating the tables',
- 'Installation_TablesWithSameNamesFound' => 'Some %s tables in your database %s have the same names as the tables Piwik is trying to create',
- 'Installation_TablesFound' => 'The following tables have been found in the database',
- 'Installation_TablesWarningHelp' => 'Either choose to reuse the existing database tables or select a clean install to erase all existing data in the database.',
- 'Installation_TablesReuse' => 'Reuse the existing tables',
- 'Installation_TablesDelete' => 'Delete the detected tables',
- 'Installation_TablesDeletedSuccess' => 'Existing Piwik tables deleted with success',
- 'Installation_TablesCreatedSuccess' => 'Tables created with success!',
- 'Installation_DatabaseCreatedSuccess' => 'Database %s created with success!',
- 'Installation_GoBackAndDefinePrefix' => 'Go back and define a Prefix for the Piwik Tables',
- 'Installation_ConfirmDeleteExistingTables' => 'Are you sure you want to delete the tables: %s from your database? WARNING: DATA FROM THESE TABLES CANNOT BE RECOVERED!',
- 'Installation_Welcome' => 'Welcome!',
- 'Installation_WelcomeHelp' => '<p>Piwik is an open source web analytics software that makes it easy to get the information you want from your visitors.</p><p>This process is split up into %s easy steps and will take around 5 minutes.</p>',
- 'Installation_ErrorInvalidState' => 'Error: it seems you try to skip a step of the Installation process, or your cookies are disabled, or the Piwik configuration file is already created. %sMake sure your cookies are enabled%s and go back %s to the first page of the installation %s.',
- 'Provider_WidgetProviders' => 'Providers',
- 'Provider_ColumnProvider' => 'Provider',
- 'Provider_SubmenuLocationsProvider' => 'Locations & provider',
- 'Goals_ColumnConversions' => 'Conversions',
- 'Goals_ColumnConversionRate' => 'Conversion Rate',
- 'Goals_ColumnRevenue' => 'Revenue',
- 'DBStats_DatabaseUsage' => 'Database usage',
- 'DBStats_MainDescription' => 'Piwik is storing all your web analytics data in the MySQL database. Currently, Piwik tables are using %s.',
- 'DBStats_Table' => 'Table',
- 'DBStats_RowNumber' => 'Row number',
- 'DBStats_DataSize' => 'Data size',
- 'DBStats_IndexSize' => 'Index size',
- 'DBStats_TotalSize' => 'Total size',
- 'TranslationsAdmin_MenuTranslations' => 'Translations',
- 'TranslationsAdmin_MenuLanguages' => 'Languages',
- 'TranslationsAdmin_Plugin' => 'Plugin',
- 'TranslationsAdmin_Definition' => 'Definition',
- 'TranslationsAdmin_DefaultString' => 'Default string (English)',
- 'TranslationsAdmin_TranslationString' => 'Translation string (current language: %s)',
- 'TranslationsAdmin_Translations' => 'Translations',
- 'TranslationsAdmin_FixPermissions' => 'Please fix filesystem permissions',
- 'TranslationsAdmin_AvailableLanguages' => 'Available languages',
- 'TranslationsAdmin_AddLanguage' => 'Add language',
- 'TranslationsAdmin_LanguageCode' => 'Language code',
- 'TranslationsAdmin_Export' => 'Export language',
- 'TranslationsAdmin_Import' => 'Import language',
+ 'UsersManager_ExceptionPasswordMD5HashExpected' => 'UsersManager.getTokenAuth is expecting a MD5-hashed password (32 chars long string). Please call the md5() function on the password before calling this method.',
+ 'VisitFrequency_PluginDescription' => 'Reports various statistics about the Returning Visitor versus the First time visitor.',
+ 'VisitFrequency_Evolution' => 'Evolution over the period',
+ 'VisitFrequency_ColumnReturningVisits' => 'Returning Visits',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Actions by Returning Visits',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Maximum Actions by a Returning Visit',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Total time spent by Returning Visits (in seconds)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Bounce rate for Returning Visits',
+ 'VisitFrequency_ReturnVisits' => '%s returning visits',
+ 'VisitFrequency_ReturnActions' => '%s actions by the returning visits',
+ 'VisitFrequency_ReturnMaxActions' => '%s maximum actions by a returning visit',
+ 'VisitFrequency_ReturnTotalTime' => '%s total time spent by returning visits',
+ 'VisitFrequency_ReturnBounceRate' => '%s returning visits have bounced (left the website after one page)',
+ 'VisitFrequency_WidgetOverview' => 'Frequency overview',
+ 'VisitFrequency_WidgetGraphReturning' => 'Graph returning visits',
+ 'VisitFrequency_SubmenuFrequency' => 'Frequency',
+ 'VisitorGenerator_PluginDescription' => 'Plugin to create fake visits. This can be used by Piwik users or developers as an easy way to generate fake data to populate Piwik reports.',
+ 'VisitorGenerator_VisitorGenerator' => 'Visitor Generator',
+ 'VisitorGenerator_Warning' => 'You are about to generate fake visits which will be recorded in your Piwik database.',
+ 'VisitorGenerator_NotReversible' => 'It will %s not%s be possible to easily delete these visits from the piwik logs.',
+ 'VisitorGenerator_AreYouSure' => 'Are you sure you want to generate fake visits?',
+ 'VisitorGenerator_ChoiceYes' => 'Yes, I am sure!',
+ 'VisitorGenerator_Submit' => 'Submit',
+ 'VisitorGenerator_SelectWebsite' => 'Select Website',
+ 'VisitorGenerator_Visitors' => 'Visitors',
+ 'VisitorGenerator_MinVisitors' => 'Minimum Visitors',
+ 'VisitorGenerator_MaxVisitors' => 'Maximum Visitors',
+ 'VisitorGenerator_NbActions' => 'Number of Actions',
+ 'VisitorGenerator_ActionsPerVisit' => 'Actions per visit',
+ 'VisitorGenerator_NbRequestsPerSec' => 'Requests per second',
+ 'VisitorGenerator_DaysToCompute' => 'Days to compute',
+ 'VisitorGenerator_Date' => 'Date',
+ 'VisitorInterest_PluginDescription' => 'Reports about the Visitor Interest: number of pages viewed, time spent on the Website.',
+ 'VisitorInterest_VisitsPerDuration' => 'Visits per visit duration',
+ 'VisitorInterest_VisitsPerNbOfPages' => 'Visits per number of pages',
+ 'VisitorInterest_ColumnVisitDuration' => 'Visit duration',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Pages per visit',
+ 'VisitorInterest_WidgetLengths' => 'Length of Visits',
+ 'VisitorInterest_WidgetPages' => 'Pages per visit',
+ 'VisitorInterest_Engagement' => 'Engagement',
+ 'VisitorInterest_PlusXMin' => '%s min',
+ 'VisitorInterest_BetweenXYMinutes' => '%1$s-%2$s min',
+ 'VisitorInterest_OnePage' => '1 page',
+ 'VisitorInterest_NPages' => '%s pages',
+ 'VisitorInterest_BetweenXYSeconds' => '%1$s-%2$ss',
+ 'VisitsSummary_PluginDescription' => 'Reports the general Analytics numbers: visits, unique visitors, number of actions, Bounce Rate, etc.',
+ 'VisitsSummary_VisitsSummary' => 'Visits Summary',
+ 'VisitsSummary_NbVisits' => '%s visits',
+ 'VisitsSummary_NbUniqueVisitors' => '%s unique visitors',
+ 'VisitsSummary_NbActionsDescription' => '%s actions (page views, downloads and outlinks)',
+ 'VisitsSummary_TotalTime' => '%s total time spent by the visitors',
+ 'VisitsSummary_MaxNbActions' => '%s max actions in one visit',
+ 'VisitsSummary_NbVisitsBounced' => '%s visits have bounced (left the website after one page)',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Evolution over the last %s',
+ 'VisitsSummary_Report' => 'Report',
+ 'VisitsSummary_GenerateTime' => '%s seconds to generate the page',
+ 'VisitsSummary_GenerateQueries' => '%s queries executed',
+ 'VisitsSummary_WidgetLastVisits' => 'Last visits graph',
+ 'VisitsSummary_WidgetVisits' => 'Visits overview',
+ 'VisitsSummary_WidgetLastVisitors' => 'Last unique visitors graph',
+ 'VisitsSummary_WidgetOverviewGraph' => 'Overview with graph',
+ 'VisitsSummary_SubmenuOverview' => 'Overview',
+ 'VisitTime_PluginDescription' => 'Reports the Local and Server time. Server time information can be useful to schedule a maintenance on the Website.',
+ 'VisitTime_LocalTime' => 'Visits per local time',
+ 'VisitTime_ServerTime' => 'Visits per server time',
+ 'VisitTime_ColumnServerTime' => 'Server time',
+ 'VisitTime_ColumnLocalTime' => 'Local time',
+ 'VisitTime_WidgetLocalTime' => 'Visits by local time',
+ 'VisitTime_WidgetServerTime' => 'Visits by server time',
+ 'VisitTime_SubmenuTimes' => 'Times',
+ 'VisitTime_NHour' => '%sh',
+ 'Widgetize_PluginDescription' => 'The plugin makes it very easy to export any Piwik Widget in your Blog, Website or on Igoogle and Netvibes!',
);
diff --git a/lang/es.php b/lang/es.php
index 4fb09e60dc..830868f749 100644
--- a/lang/es.php
+++ b/lang/es.php
@@ -1,16 +1,24 @@
<?php
+
+setlocale(LC_TIME, 'es_ES.UTF-8');
+
$translations = array(
'General_Locale' => 'es_ES.UTF-8',
- 'General_TranslatorName' => 'Marcos Alberto Sanmartín Pereira, Alejandro Escario',
- 'General_TranslatorEmail' => 'ahriman89@gmail.com, escarion@gmail.com',
+ 'General_TranslatorName' => 'Marcos Alberto Sanmartín Pereira
+
+David Ernesto Soto Vásquez',
+ 'General_TranslatorEmail' => 'ahriman89@gmail.com
+
+ddiods@hotmail.com',
'General_EnglishLanguageName' => 'Spanish',
'General_OriginalLanguageName' => 'Español',
- 'General_HelloUser' => '¡Hola, %s!',
+ 'General_HelloUser' => '¡Hola, %s!',
'General_OpenSourceWebAnalytics' => 'Análisis Web de Código Abierto',
- 'General_YourDashboard' => 'Tu Panel',
+ 'General_Dashboard' => 'Tu Panel',
+ 'General_MultiSitesSummary' => 'Todos los sitios web',
'General_API' => 'API',
'General_Widgets' => 'Widgets',
- 'General_Settings' => 'Configuración',
+ 'General_Settings' => 'Configuración',
'General_GiveUsYourFeedback' => '¡Envíanos comentarios!',
'General_Unknown' => 'Desconocido',
'General_Required' => '%s necesario',
@@ -44,7 +52,7 @@ $translations = array(
'General_ColumnNbUniqVisitors' => 'Visitantes únicos',
'General_ColumnNbVisits' => 'Visitas',
'General_ColumnNbActions' => 'Acciones',
- 'General_ColumnMaxActions' => 'acciones máximas en una visita',
+ 'General_ColumnMaxActions' => 'Acciones máximas en una visita',
'General_ColumnSumVisitLength' => 'Tiempo total de los visitantes en el sitio (en segundos)',
'General_ColumnLabel' => 'Etiqueta',
'General_ColumnActionsPerVisit' => 'Acciones por visita',
@@ -56,13 +64,15 @@ $translations = array(
'General_ColumnVisitsWithConversions' => 'Visitas con conversiones',
'General_Save' => 'Guardar',
'General_Website' => 'Sitio web',
+ 'General_RequiresFlash' => 'Visualización de gráficos en Piwik requiere Flash',
+ 'General_GraphHelp' => 'Más información sobre la visualización de gráficos en Piwik.',
'General_NoDataForGraph' => 'No hay datos para esta gráfica.',
'General_NoDataForTagCloud' => 'No hay datos para esta nube de etiquetas.',
'General_DisplayNormalTable' => 'Mostrar la tabla normal',
'General_DisplayMoreData' => 'Mostrar más datos',
- 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s es un proyecto colaborativo. %s ¡Si te gusta Piwik, puedes ayudar! Comprueba %s ¿Cómo contribuir con Piwik?%s ',
- 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Estás viendo en este momento la demo de %s; ¡%sdescarga%s la versión completa! Comprueba %s',
- 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s está disponible. %s ¡Por favor, actualice ahora!%s (ver %s cambios%s).',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%1$s Piwik %2$s es un proyecto colaborativo. %3$s ¡Si te gusta Piwik, puedes ayudar! Comprueba %4$s ¿Cómo contribuir con Piwik?%5$s ',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Estás viendo en este momento la demo de %1$s; ¡%2$sdescarga%3$s la versión completa! Comprueba %4$s',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %1$s está disponible. %2$s ¡Por favor, actualice ahora!%3$s (ver %4$s cambios%5$s).',
'General_BackToPiwik' => 'Volver a Piwik',
'General_ShortMonth_1' => 'Ene',
'General_ShortMonth_2' => 'Feb',
@@ -83,7 +93,7 @@ $translations = array(
'General_LongMonth_5' => 'Mayo',
'General_LongMonth_6' => 'Junio',
'General_LongMonth_7' => 'Julio',
- 'General_LongMonth_8' => 'Agost',
+ 'General_LongMonth_8' => 'Agosto',
'General_LongMonth_9' => 'Septiembre',
'General_LongMonth_10' => 'Octubre',
'General_LongMonth_11' => 'Noviembre',
@@ -102,6 +112,7 @@ $translations = array(
'General_LongDay_5' => 'Viernes',
'General_LongDay_6' => 'Sábado',
'General_LongDay_7' => 'Domingo',
+ 'General_ExceptionDatabaseVersion' => 'Su versión %1$s es %2$s pero Piwik requiere al menos %3$s.',
'CorePluginsAdmin_Plugins' => 'Plugins',
'CorePluginsAdmin_PluginsManagement' => 'Administración de Plugins',
'CorePluginsAdmin_MainDescription' => 'Los plugins extienden y amplian las funcionalidades de Piwik. Una vez que el plugin esté instalado, usted puede activarlo o desactivarlo desde aquí.',
@@ -127,7 +138,7 @@ $translations = array(
'CoreHome_ShowJSCode' => 'Mostrar el código JavaScript para insertar',
'CoreHome_IncludeAllPopulation_js' => 'Incluir toda la población',
'CoreHome_ExcludeLowPopulation_js' => 'Excluir baja población',
- 'CoreHome_PageOf_js' => '%s de %s',
+ 'CoreHome_PageOf_js' => '%1$s de %2$s',
'CoreHome_Loading_js' => 'Cargando...',
'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
'CoreHome_PeriodDay' => 'Día',
@@ -138,13 +149,39 @@ $translations = array(
'CoreHome_PeriodWeeks' => 'semanas',
'CoreHome_PeriodMonths' => 'meses',
'CoreHome_PeriodYears' => 'años',
- 'CoreHome_DaySu_js' => 'D',
- 'CoreHome_DayMo_js' => 'L',
- 'CoreHome_DayTu_js' => 'M',
- 'CoreHome_DayWe_js' => 'X',
- 'CoreHome_DayTh_js' => 'J',
- 'CoreHome_DayFr_js' => 'V',
- 'CoreHome_DaySa_js' => 'S',
+ 'CoreHome_DaySu_js' => 'Do',
+ 'CoreHome_DayMo_js' => 'Lu',
+ 'CoreHome_DayTu_js' => 'Ma',
+ 'CoreHome_DayWe_js' => 'Mi',
+ 'CoreHome_DayTh_js' => 'Ju',
+ 'CoreHome_DayFr_js' => 'Vi',
+ 'CoreHome_DaySa_js' => 'Sá',
+ 'CoreHome_ShortDay_1_js' => 'Dom',
+ 'CoreHome_ShortDay_2_js' => 'Lun',
+ 'CoreHome_ShortDay_3_js' => 'Mar',
+ 'CoreHome_ShortDay_4_js' => 'Mié',
+ 'CoreHome_ShortDay_5_js' => 'Juv',
+ 'CoreHome_ShortDay_6_js' => 'Vie',
+ 'CoreHome_ShortDay_7_js' => 'Sáb',
+ 'CoreHome_LongDay_1_js' => 'Domingo',
+ 'CoreHome_LongDay_2_js' => 'Lunes',
+ 'CoreHome_LongDay_3_js' => 'Martes',
+ 'CoreHome_LongDay_4_js' => 'Miércoles',
+ 'CoreHome_LongDay_5_js' => 'Jueves',
+ 'CoreHome_LongDay_6_js' => 'Viernes',
+ 'CoreHome_LongDay_7_js' => 'Sábado',
+ 'CoreHome_ShortMonth_1_js' => 'Ene',
+ 'CoreHome_ShortMonth_2_js' => 'Feb',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Abr',
+ 'CoreHome_ShortMonth_5_js' => 'May',
+ 'CoreHome_ShortMonth_6_js' => 'Jun',
+ 'CoreHome_ShortMonth_7_js' => 'Jul',
+ 'CoreHome_ShortMonth_8_js' => 'Ago',
+ 'CoreHome_ShortMonth_9_js' => 'Sep',
+ 'CoreHome_ShortMonth_10_js' => 'Oct',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dic',
'CoreHome_MonthJanuary_js' => 'Enero',
'CoreHome_MonthFebruary_js' => 'Febrero',
'CoreHome_MonthMarch_js' => 'Marzo',
@@ -157,14 +194,21 @@ $translations = array(
'CoreHome_MonthOctober_js' => 'Octubre',
'CoreHome_MonthNovember_js' => 'Noviembre',
'CoreHome_MonthDecember_js' => 'Diciembre',
- 'CoreUpdater_UpdateTitle' => 'Actualización de Piwik &rsaquo;',
+ 'CoreUpdater_UpdateTitle' => 'Actualizar',
'CoreUpdater_DatabaseUpgradeRequired' => 'La base de datos necesita actualizarse',
'CoreUpdater_YourDatabaseIsOutOfDate' => 'Su base de datos de Piwik está obsoleta, y debe ser actualizada antes de poder continuar.',
- 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'La base de datos de Piwik será actualizada desde la versión %s a la nueva versión %s.',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'La base de datos de Piwik será actualizada desde la versión %1$s a la nueva versión %2$s.',
'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Los siguientes plugins serán actualizados: %s.',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'Si tiene una base de datos grande de Piwik, las actualizaciones podrían llevar mucho tiempo para ejecutarse en el navegador. En esta situación, puede ejecutar las actualizaciones desde la línea de comandos: %s',
'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'El proceso de actualización de la base de datos puede llevar un tiempo, así que por favor sea paciente.',
'CoreUpdater_UpgradePiwik' => 'Actualizar Piwik',
- 'CoreUpdater_HelpMessageContent' => 'Comprueba la %s Piwik FAQ %s que explica los errores más comunes durante la actualización. %s Pregúntele a su administrador del sistema - que puede ser capaz de ayudarle con el error, que es más probable que sea en relación a su servidor o la configuración de MySQL.',
+ 'CoreUpdater_ErrorDIYHelp' => 'Si usted es un usuario avanzado y encuentra un error en la actualización de la base de datos:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'identificar y corregir el origen del problema (por ejemplo, memory_limit o max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'ejecutar las consultas restantes que fallaron en la actualización',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'actualizar manualmente la tabla `option` en su base de datos Piwik, estableciendo el valor de version_core a la versión de la actualización fallida',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'volver a ejecutar el actualizador (a través del navegador o la línea de comandos) para continuar con el resto de actualizaciones',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'reportar el problema (y solución) de modo que Piwik pueda ser mejorado',
+ 'CoreUpdater_HelpMessageContent' => 'Comprueba la %1$s Piwik FAQ %2$s que explica los errores más comunes durante la actualización. %3$s Pregúntele a su administrador del sistema - que puede ser capaz de ayudarle con el error, que es más probable que sea en relación a su servidor o la configuración de MySQL.',
'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Error crítico durante el proceso de actualización:',
'CoreUpdater_HelpMessageIntroductionWhenError' => 'Lo anterior es un mensaje de error del núcleo. Debe ayudarle a explicar la causa, pero si necesita más ayuda, por favor:',
'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Actualización completada con éxito, sin embargo hubo problemas durante el proceso. Por favor, lea las descripciones anteriores para obtener más detalles. Para obtener más ayuda:',
@@ -178,23 +222,29 @@ $translations = array(
'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Hay una nueva versión de Piwik disponible para actualizar',
'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Puede actualizar automáticamente a la versión %s o descargar el paquete e instalarlo manualmente:',
'CoreUpdater_DownloadX' => 'Descarga %s',
- 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'La actualización con Un Clic de Piwik se ha cancelado. Si no puede solucionar el mensaje de error anterior, se recomienda que actualice Piwik manualmente. %s ¡Por favor, consulte la %sdocumentación de actualización%s para empezar!',
- 'CoreUpdate_DownloadingUpdateFromX' => 'Descargando actualización desde %s',
- 'CoreUpdate_UnpackingTheUpdate' => 'Desempaquetando la actualización',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'La actualización con Un Clic de Piwik se ha cancelado. Si no puede solucionar el mensaje de error anterior, se recomienda que actualice Piwik manualmente. %1$s ¡Por favor, consulte la %2$sdocumentación de actualización%3$s para empezar!',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Descargando actualización desde %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Desempaquetando la actualización',
'CoreUpdater_VerifyingUnpackedFiles' => 'Verificando los archivos desempaquetados',
'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Creando una copia de seguridad del archivo de configuración en %s',
'CoreUpdater_InstallingTheLatestVersion' => 'Instalando la última versión',
'CoreUpdater_PiwikUpdatedSuccessfully' => '¡Piwik actualizado con éxito!',
'CoreUpdater_EmptyDatabaseError' => 'La base de datos %s está vacía. Debes modificar o eliminar tu archivo de configuración de Piwik.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Su versión Piwik %s está al día.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Archivo incompatible: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Archivo vacío.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Archivo incompleto: faltan algunos archivos (por ejemplo, %s).',
'Actions_Actions' => 'Acciones',
'Actions_SubmenuPages' => 'Páginas',
+ 'Actions_SubmenuPageTitles' => 'Títulos de páginas',
'Actions_SubmenuOutlinks' => 'Enlaces externos',
'Actions_SubmenuDownloads' => 'Descargas',
'Actions_ColumnClicks' => 'Clics',
- 'Actions_ColumnUniqueClicks' => ' Clics únicos',
+ 'Actions_ColumnUniqueClicks' => 'Clics únicos',
'Actions_ColumnDownloads' => 'Descargas',
'Actions_ColumnUniqueDownloads' => 'Descargas Únicas',
'Actions_ColumnPageName' => 'Páginas',
+ 'Actions_ColumnPageURL' => 'URL de página',
'Actions_ColumnClickedURL' => 'URLs cliqueadas',
'Actions_ColumnDownloadURL' => 'URLs de descargas',
'Dashboard_Dashboard' => 'Panel',
@@ -214,7 +264,7 @@ $translations = array(
'Referers_DirectEntry' => 'Entrada directa',
'Referers_Websites' => 'Sitios web',
'Referers_Campaigns' => 'Campañas',
- 'Referers_MetricsFromRefererTypeGraphLegend' => '%1s (desde %2s)',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%1$s (desde %2$s)',
'Referers_Evolution' => 'Evolución en el periodo',
'Referers_Type' => 'Tipo de referencia',
'Referers_ColumnRefererType' => 'Tipo de referencia',
@@ -233,10 +283,10 @@ $translations = array(
'Referers_DistinctKeywords' => 'palabras clave distintas',
'Referers_DistinctCampaigns' => 'campañas distintas',
'Referers_DistinctWebsites' => 'páginas web distintas',
- 'Referers_UsingNDistinctUrls' => ' (usando %2s URLs diferentes)',
+ 'Referers_UsingNDistinctUrls' => ' (usando %1s URLs diferentes)',
'Referers_SubmenuEvolution' => 'Evolución',
'Referers_SubmenuSearchEngines' => 'Motores de búsqueda y palabras clave',
- 'Referers_SubmenuWebsites' => 'Páginas web',
+ 'Referers_SubmenuWebsites' => 'Sitios web',
'Referers_SubmenuCampaigns' => 'Campañas',
'Referers_WidgetKeywords' => 'Lista de Palabras clave',
'Referers_WidgetCampaigns' => 'Lista de Campañas',
@@ -248,14 +298,14 @@ $translations = array(
'UserSettings_Browsers' => 'Navegadores',
'UserSettings_Plugins' => 'Plugins',
'UserSettings_Configurations' => 'Configuración',
- 'UserSettings_OperatinsSystems' => 'Sistemas operativos',
+ 'UserSettings_OperatingSystems' => 'Sistemas operativos',
'UserSettings_Resolutions' => 'Resoluciones',
'UserSettings_WideScreen' => 'Pantalla panorámica',
'UserSettings_ColumnBrowserFamily' => 'Buscadores por familia',
'UserSettings_ColumnBrowser' => 'Navegador',
'UserSettings_ColumnPlugin' => 'Plugin',
'UserSettings_ColumnConfiguration' => 'Configuración',
- 'UserSettings_ColumnOperatinsSystem' => 'Sistemas operativos',
+ 'UserSettings_ColumnOperatingSystem' => 'Sistemas operativos',
'UserSettings_ColumnResolution' => 'Resoluciones',
'UserSettings_ColumnTypeOfScreen' => 'Tipo de pantalla',
'UserSettings_WidgetResolutions' => 'Resoluciones de pantalla',
@@ -541,6 +591,7 @@ $translations = array(
'UserCountry_continent_ams' => 'América del Sur y Central',
'UserCountry_continent_amn' => 'América del Norte',
'UserCountry_continent_oce' => 'Oceanía',
+ 'VisitsSummary_VisitsSummary' => 'Resumen de visitas',
'VisitsSummary_NbVisits' => '%s visitas',
'VisitsSummary_NbUniqueVisitors' => '%s visitas únicas',
'VisitsSummary_NbActions' => '%s acciones (páginas vistas)',
@@ -586,20 +637,26 @@ $translations = array(
'VisitorInterest_WidgetPages' => 'Páginas por visita',
'VisitorInterest_SubmenuFrequencyLoyalty' => 'Frecuencia y Fidelidad',
'VisitorInterest_PlusXMin' => '%s min',
- 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%2s min',
'VisitorInterest_OnePage' => '1 página',
'VisitorInterest_NPages' => '%s páginas',
'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
'Login_LoginPasswordNotCorrect' => 'Usuario y contraseña incorrectos',
'Login_Login' => 'Usuario',
'Login_Password' => 'Contraseña',
+ 'Login_PasswordRepeat' => 'Contraseña (repetir)',
+ 'Login_ChangePassword' => 'Cambiar contraseña',
'Login_LoginOrEmail' => 'Usuario o E-mail',
'Login_LogIn' => 'Conectar',
'Login_Logout' => 'Desconectar',
'Login_LostYourPassword' => '¿Olvidó la contraseña?',
'Login_RemindPassword' => 'Recordar Contraseña',
+ 'Login_PasswordResetToken' => 'Indicio de restablecimiento de contraseña',
'Login_PasswordReminder' => 'Por favor, introduzca su nombre de usuario o dirección de email. Recibirá una nueva contraseña por email',
+ 'Login_PasswordsDoNotMatch' => 'Las contraseñas no coinciden.',
+ 'Login_PasswordSuccessfullyChanged' => '¡Contraseña cambiada correctamente!',
'Login_InvalidUsernameEmail' => 'Nombre de usuario y/o email incorrectos',
+ 'Login_InvalidOrExpiredToken' => 'El indicio no es válido o ha caducado',
'Login_MailTopicPasswordRecovery' => 'Recuperar contraseña',
'Login_MailPasswordRecoveryBody' => 'Hola %1s, \n\n Tu nueva contraseña es: %2s \n\n Puedes conectarte ahora en: %3s',
'Login_PasswordSent' => 'La contraseña acaba de ser enviada. Comprueba tu email.',
@@ -626,7 +683,7 @@ $translations = array(
'UsersManager_DeleteConfirm_js' => '¿Está seguro que desea eliminar al usuario %s?',
'UsersManager_ExceptionLoginExists' => 'El usuario \'%s\' ya existe.',
'UsersManager_ExceptionEmailExists' => 'Ya existe un usuario con el email \'%s\'.',
- 'UsersManager_ExceptionInvalidLoginFormat' => 'El nombre de usuario debe ser entre %s y %s caracteres de largo y contener solo letras, números o los caracteres \'_\' o \'-\' o \'.\'',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'El nombre de usuario debe ser entre %1$ y %2$s caracteres de largo y contener solo letras, números o los caracteres \'_\' o \'-\' o \'.\'',
'UsersManager_ExceptionInvalidPassword' => 'La longitud de la contraseña debe tener entre 6 y 26 caracteres.',
'UsersManager_ExceptionInvalidEmail' => 'El email no tiene un formato válido.',
'UsersManager_ExceptionDeleteDoesNotExist' => 'El usuario \'%s\' no existe, por lo tanto, no puede ser borrado.',
@@ -643,6 +700,11 @@ $translations = array(
'SitesManager_ShowTrackingTag' => 'mostrar código de seguimiento',
'SitesManager_NoWebsites' => 'Usted no tiene ningún sitio web que administrar.',
'SitesManager_AddSite' => 'Añadir un nuevo Sitio',
+ 'SitesManager_AliasUrlHelp' => 'Se recomienda, pero no es obligatorio, especificar las diferentes URLs que sus visitantes utilizan para acceder a este sitio web.
+
+Los alias de las URLs para un sitio web no aparecerán en el informe Referencias > Sitios web.
+
+Tenga en cuenta que no es necesario especificar las direcciones URL con y sin \'www\' ya que Piwik considera automáticamente ambas.',
'SitesManager_Id' => 'Id',
'SitesManager_Name' => 'Nombre',
'SitesManager_Urls' => 'URLs',
@@ -656,15 +718,34 @@ $translations = array(
'Installation_InstallationStatus' => 'Estado de la instalación',
'Installation_PercentDone' => '%s %% Hecho',
'Installation_NoConfigFound' => 'El archivo de configuración de Piwik no se ha encontrado y está intentando acceder a una página de Piwik.<br /><b>&nbsp;&nbsp;&raquo; Puede <a href=\'index.php\'>instalar Piwik ahora</a></b><br /><small>¡Si ha instalado Piwik antes y tiene algunas tablas en su BD, no se preocupe, usted puede reutilizar las mismas tablas y mantener sus datos existentes!</small>',
- 'Installation_MysqlSetup' => 'Configuración de base de datos MySQL',
- 'Installation_MysqlErrorConnect' => 'Error al intentar conectarse a la base de datos MySQL',
+ 'Installation_DatabaseSetup' => 'Configuración de la base de datos',
+ 'Installation_DatabaseSetupServer' => 'servidor de la base de datos',
+ 'Installation_DatabaseSetupLogin' => 'usuario',
+ 'Installation_DatabaseSetupPassword' => 'contraseña',
+ 'Installation_DatabaseSetupDatabaseName' => 'nombre de la base de datos',
+ 'Installation_DatabaseSetupTablePrefix' => 'prefijo de tabla',
+ 'Installation_DatabaseSetupAdapter' => 'adaptador',
+ 'Installation_DatabaseErrorConnect' => 'Error al intentar conectarse al servidor de la base de datos',
+ 'Installation_DatabaseCheck' => 'Comprobar base de datos',
+ 'Installation_DatabaseServerVersion' => 'Versión del servidor de la base de datos',
+ 'Installation_DatabaseCreation' => 'Creación de la base de datos',
+ 'Installation_DatabaseClientCharset' => 'Juego de caracteres del cliente de la bade de datos',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'Conexión de cliente con el servidor de la base de datos no se establece a UTF8 por defecto. Esto no es problema crítico: <b>Piwik debería funcionar correctamente</b>. Sin embargo, por coherencia, se recomienda que se realice una de las siguientes cosas: <ul style="list-style: disc;margin-left:10px"><li>en su piwik config/config.ini.php, añadir <code>charset = utf8</code> debajo de la sección [database] en su archivo de configuración de Piwik <code>config/config.ini.php</code></li><li>recompile libmysql --with-charset=utf8</li></ul>',
+ 'Installation_DatabaseTimezone' => 'Zona horaria de la base de datos',
+ 'Installation_TimezoneMismatch' => 'PHP date.timezone no es lo mismo que la zona horaria del servidor de la base de datos. Esto podría causar problemas con los informes que no muestran datos correctos para de las horas del día. Más información en %s',
'Installation_JsTag' => 'Etiqueta JavaScript',
'Installation_JsTagHelp' => '<p>Para contar todos los visitantes, debe insertar el código JavaScript en todas sus páginas.</p><p>Sus páginas no tienen que ser hechas con PHP, Piwik trabajará sobre todo tipo de páginas (si es HTML, ASP, Perl o cualquier otro lenguaje).</p><p>Aquí está el código que debes introducir: (copia y pega en todas tus páginas) </p>',
+ 'Installation_JsTagHelpTitle' => '¿Cómo insertar la etiqueta en sus sitios web?',
+ 'Installation_LargePiwikInstances' => 'Ayuda para las grandes instancias de Piwik',
+ 'Installation_JsTagArchivingHelp' => 'Para los sitios web de mediano y grande tráfico, eche un vistazo a <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">¡Cómo configurar auto archivado de páginas</a> para hacer que Piwik funcione más rápido!',
'Installation_Congratulations' => 'Enhorabuena',
'Installation_CongratulationsHelp' => '<p>¡Enhorabuena! La instalación de Piwik está completada.</p><p>¡Asegúrese de que el código JavaScript está introducido en sus páginas, y espere a sus primeros visitantes!</p>',
'Installation_ContinueToPiwik' => 'Ir a Piwik',
'Installation_SetupWebsite' => 'Configurar una página web',
+ 'Installation_SetupWebSiteName' => 'nombre del sitio web',
+ 'Installation_SetupWebSiteURL' => 'URL del sitio web',
'Installation_SetupWebsiteError' => 'Se ha producido un error al añadir el sitio web',
+ 'Installation_SetupWebsiteSetupSuccess' => '¡Sitio web %s creado con éxito!',
'Installation_GeneralSetup' => 'Configuración general',
'Installation_GeneralSetupSuccess' => 'Configuración general realizada con éxito',
'Installation_SuperUserLogin' => 'Nombre de super usuario',
@@ -678,17 +759,32 @@ $translations = array(
'Installation_Requirements' => 'Requisitos de Piwik',
'Installation_Optional' => 'Opcional',
'Installation_Legend' => 'Leyenda',
+ 'Installation_Extension' => 'extensión',
'Installation_SystemCheck' => 'Comprobación del sistema',
'Installation_SystemCheckPhp' => 'Versión PHP',
'Installation_SystemCheckExtensions' => 'Extensiones requeridas',
- 'Installation_SystemCheckPdoHelp' => 'Necesitas habilitar la extensión PDO en tu archivo php.ini.',
- 'Installation_SystemCheckPdoMysqlHelp' => 'Necesitas habilitar la extensión PDO_MYSQL en tu archivo php.ini.',
- 'Installation_SystemCheckSplHelp' => 'Necesitas configurar y reconstruir PHP con la Librería Estándar de PHP habilitada (por defecto).',
- 'Installation_SystemCheckZlibHelp' => 'Necesitas configurar y reconstruir PHP con el soporte zlib habilitado, --with-zlib.',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik requiere o bien la extensión mysqli o ambas extensiones PDO y pdo_mysql.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'En un servidor Linux puede compilar php con las siguientes opciones: %s
+
+En su php.ini, añada las siguientes líneas: %s',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Más información en: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> y <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'En un servidor Windows puede añadir las siguientes líneas a su php.ini: %s',
+ 'Installation_SystemCheckSplHelp' => 'Necesita configurar y reconstruir PHP con la Librería Estándar de PHP habilitada (por defecto).',
+ 'Installation_SystemCheckZlibHelp' => 'Necesita configurar y reconstruir PHP con el soporte "zlib" habilitado, --with-zlib.',
+ 'Installation_SystemCheckIconvHelp' => 'Necesita configurar y reconstruir PHP con soporte "iconv" habilitado, --with-iconv.',
+ 'Installation_SystemCheckDomHelp' => 'DOM es parte del núcleo de PHP. Usted probablemente necesitará instalar el módulo dom, por ejemplo, php-5-dom.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'Necesita configurar y reconstruir PHP con cualquiera de las extensiones "json" o "xml" habilitadas.',
+ 'Installation_SystemCheckJsonSite' => 'Más información en: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Algunos plugins de terceros y las bibliotecas de desarrolladores podrán necesitar la extensión "xml".',
+ 'Installation_SystemCheckXmlSite' => 'Más información en: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
'Installation_SystemCheckWriteDirs' => 'Directorios con acceso de escritura',
'Installation_SystemCheckWriteDirsHelp' => 'Para arreglar este error en su sistema Linux, intente tecleando los siguientes comandos',
'Installation_SystemCheckMemoryLimit' => 'Límite de memoria',
- 'Installation_SystemCheckMemoryLimitHelp' => 'On a high traffic website, the archiving process may require more memory than currently allowed.<br />See the directive memory_limit in your php.ini file if necessary.',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'En un sitio web de alto tráfico, el proceso de archivo puede requerir más memoria de la que se permite actualmente.<br />Véase la Directiva memory_limit en su archivo php.ini si es necesario.',
+ 'Installation_SystemCheckOpenURL' => 'Abrir URL',
+ 'Installation_SystemCheckOpenURLHelp' => 'Suscripciones a boletines, notificaciones de actualización, y actualizaciones con un clic necesitan la extensión "curl", allow_url_fopen=On, o fsockopen() habilitado.',
'Installation_SystemCheckGD' => 'GD &gt; 2.x (gráficas)',
'Installation_SystemCheckGDHelp' => 'Las "sparklines" (gráficas pequeñas) no funcionarán.',
'Installation_SystemCheckFunctions' => 'Funciones requeridas',
@@ -696,8 +792,10 @@ $translations = array(
'Installation_SystemCheckMailHelp' => 'Los mensajes de Feedback y Recuperar Contraseña no se enviarán sin mail().',
'Installation_SystemCheckError' => 'Se ha producido un error - debe ser arreglado antes de continuar',
'Installation_SystemCheckWarning' => 'Piwik funcionará normalmente, pero algunas características pueden faltar',
+ 'Installation_SystemCheckProtocol' => 'Protocolo',
+ 'Installation_SystemCheckProtocolHelp' => 'Si está detrás de un proxy, añada estas líneas a config/config.ini.php debajo de la sección [General]:',
'Installation_Tables' => 'Creando las tablas',
- 'Installation_TablesWithSameNamesFound' => 'Algunas %s tablas en su base de datos %s tienen el mismo nombre como las tablas que Piwik está intentando crear.',
+ 'Installation_TablesWithSameNamesFound' => 'Algunas %1$s tablas en su base de datos %2$s tienen el mismo nombre como las tablas que Piwik está intentando crear.',
'Installation_TablesFound' => 'Las siguientes tablas se han encontrado en la base de datos',
'Installation_TablesWarningHelp' => 'O bien optar por la reutilización de las tablas de bases de datos existentes o seleccionar una instalación limpia para borrar todos los datos existentes en la base de datos.',
'Installation_TablesReuse' => 'Reutilizar las tablas ya existentes',
@@ -709,7 +807,7 @@ $translations = array(
'Installation_ConfirmDeleteExistingTables' => '¿Está seguro de que desea borrar las tablas: %s de su base de datos? ADVERTENCIA: ¡LOS DATOS DE ESTAS TABLAS NO SE PUEDEN RECUPERAR!',
'Installation_Welcome' => '¡Bienvenido!',
'Installation_WelcomeHelp' => '<p>Piwik es un software de análisis web de código abierto que facilita el obtener la información que desea de sus visitantes.</p><p>Este proceso se divide en %s sencillos pasos que le llevarán en torno a 5 minutos.</p>',
- 'Installation_ErrorInvalidState' => 'Error: parece que trata de saltar un paso del proceso de instalación, o sus cookies están desactivadas, o el archivo de configuración de Piwik ya está creado. %sAsegúrese de que las cookies están activadas%s y vuelva %s a la primera página de la instalación %s.',
+ 'Installation_ErrorInvalidState' => 'Error: parece que trata de saltar un paso del proceso de instalación, o sus cookies están desactivadas, o el archivo de configuración de Piwik ya está creado. %1$sAsegúrese de que las cookies están activadas%2$s y vuelva %3$s a la primera página de la instalación %4$s.',
'Provider_WidgetProviders' => 'Proveedores',
'Provider_ColumnProvider' => 'Proveedor',
'Provider_SubmenuLocationsProvider' => 'Localizaciones y proveedores',
@@ -718,8 +816,9 @@ $translations = array(
'Goals_ColumnRevenue' => 'Ingresos',
'DBStats_DatabaseUsage' => 'Uso de la base de datos',
'DBStats_MainDescription' => 'Piwik está almacenando todos sus datos de análisis web en la base de datos MySQL. Actualmente, las tablas de Piwik están usando %s.',
+ 'DBStats_LearnMore' => 'Para aprender más sobre cómo Piwik procesa los datos y cómo hacer que Piwik funcione bien para sitios web de mediano y grande trafico, eche un vistazo a la documentación %s.',
'DBStats_Table' => 'Tabla',
- 'DBStats_RowNumber' => 'Número de fila',
+ 'DBStats_RowCount' => 'Número de fila',
'DBStats_DataSize' => 'Tamaño de los datos',
'DBStats_IndexSize' => 'Índice de tamaño',
'DBStats_TotalSize' => 'Tamaño total',
@@ -736,4 +835,140 @@ $translations = array(
'TranslationsAdmin_LanguageCode' => 'Código de idioma',
'TranslationsAdmin_Export' => 'Exportar idioma',
'TranslationsAdmin_Import' => 'Importar idioma',
-);
+ 'SecurityInfo_Security' => 'Seguridad',
+ 'SecurityInfo_SecurityInformation' => 'Información de seguridad PHP',
+ 'SecurityInfo_PluginDescription' => 'Basado en PhpSecInfo del PHP Security Consortium, este plugin proporciona información de seguridad sobre su entorno de PHP y ofrece sugerencias para mejorar. Es una herramienta en un enfoque de seguridad de varias capas. No sustituye a las prácticas de desarrollo seguro, ni la auditoría del código/aplicación.',
+ 'SecurityInfo_Test' => 'Prueba',
+ 'SecurityInfo_Result' => 'Resultado',
+ 'Live_VisitorLog' => 'Registro del visitante',
+ 'Live_Date' => 'Fecha',
+ 'Live_Time' => 'Hora',
+ 'Live_Referrer_URL' => 'URL de referencia',
+ 'General_Details' => 'Detalles',
+ 'General_ExportAsImage_js' => 'Exportar como Imagen',
+ 'General_SaveImageOnYourComputer_js' => 'Para grabar la imagen en tu computadora, dar clic derecho en la imagen y selecciona "Grabar Imagen Como..."',
+ 'General_ForExampleShort' => 'Ej.',
+ 'General_ExceptionIncompatibleClientServerVersions' => 'La version de su cliente %1$s %2$s es incompatible con la version del servidor %3$s',
+ 'General_ExceptionMissingFile' => 'Falta archivo:%s',
+ 'General_ExceptionFilesizeMismatch' => 'Tamaño de archivo incorrecto: %1$s (se esperaba %2$s, se encontró:%2$s)',
+ 'General_ExceptionFileIntegrity' => 'Falló la verificación de integridad: %s',
+ 'General_ExceptionNonceMismatch' => 'No se puede verificar la llave de seguridad en este formulario.',
+ 'General_WarningFileIntegritySkipped' => 'Entorno de desarrollo detectado. Se desactivó la verificación de integridad de archivos.',
+ 'General_WarningFileIntegrityNoManifest' => 'La verificación de integridad de archivos no se pudo realizar debido a que falta manifest.inc.php.',
+ 'General_WarningFileIntegrityNoMd5file' => 'La verificación de integridad no pudo ser completada debido a que falta la función md5_file().',
+ 'General_FileIntegrityWarningExplanation' => 'Falló la verificación de integridad y reportó algunos errores. Esto se debe generalmente a una carga parcial o falta de algunos de los archivos de Piwik. Debería volver a subir los archivos de Piwik y refrescar la página hasta que no muestre errores.',
+ 'Actions_PluginDescription' => 'Reportes de páginas vistas, enlaces externos y descargas. Los Enlaces Externos y las Descargas se rastrean automáticamente!',
+ 'AnonymizeIP_PluginDescription' => 'Esconder la dirección IP del visitante para cumplir las leyes/directrices de privacidad de su localidad.',
+ 'API_PluginDescription' => 'Todos los datos de Piwik esta disponible via una simple APIs. Este plugin es el punto de entrada de servicio web, que puede llamar para obtener los datos de su Análisis Web en xml, json, php, csv, etc',
+ 'ExampleAPI_PluginDescription' => 'Plugin de Ejemplo: Como crear una API para tu plugin, para exportar datos en múltiples formatos sin ninguna codificación especial?',
+ 'CoreAdminHome_PluginDescription' => 'Área de Administración para Piwik',
+ 'CoreHome_PluginDescription' => 'Estructura de Reportes de Análisis Web',
+ 'CorePluginsAdmin_PluginDescription' => 'Interface de Administración de Plugins',
+ 'CoreUpdater_PluginDescription' => 'mecanismo de actualización de Piwik',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Nota importante para grandes instalaciones de Piwik',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => 'Si no puede utilizar el actualizador de linea de comandos y si la actualización de Piwik fallara (debido a un tiempo de espera excesivo de la base de datos, del explorador o cualquier otro motivo), usted puede ejecutar manualmente las sentencias SQL para actualizar Piwik',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => 'Clic aqui para ver y copiar la lista de sentencias SQL que será ejecutada',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => 'Nota: si ejecuta estas sentencias manualmente, es normal que alguna de ellas falle. En este caso, solo ignore el error, y ejecute la siguiente sentencia de la lista.',
+ 'CoreUpdater_ReadyToGo' => 'Listo?',
+ 'Dashboard_PluginDescription' => 'Tu Panel de Análisis Web. Puedes personalizar su Panel: agregar nuevos widgets, cambiar el orden de tus widgets. Cada usuario puede acceder a su propio Panel personalizado.',
+ 'DBStats_PluginDescription' => 'Este plugin reporta el uso de la base de datos MySQL de las tablas de Piwik.',
+ 'ExampleFeedburner_PluginDescription' => 'Plugin de Ejemplo: Como mostrar tu suscripción de Feedburner en un widget en tu Panel?',
+ 'ExamplePlugin_PluginDescription' => 'Plugin de Ejemplo: Este plugin te muestra como crear un plugin muy simple, que exporta dos widgets en tu Panel.',
+ 'ExamplePlugin_exampleWidgets' => 'Widgets de Ejemplo',
+ 'ExamplePlugin_exampleWidget' => 'Widget de ejemplo',
+ 'ExamplePlugin_blogPiwikRss' => 'Blog Piwik RSS',
+ 'ExamplePlugin_photostreamMatt' => 'Fotos de Matt',
+ 'ExampleRssWidget_PluginDescription' => 'Plugin de ejemplo: ¿Cómo crear un nuevo widget que lea RSS?',
+ 'ExampleUI_PluginDescription' => 'Plugin de ejemplo: Este plugin muestra como trabaja el Piwik UI: crear tablas, gráficos, etc.',
+ 'Feedback_PluginDescription' => 'Enviar tus comentarios al equipo de Piwik. Comparte tus ideas y sugerencias con nosotros!',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Tienes un error que reportar o una nueva característica?',
+ 'Feedback_ViewAnswersToFAQ' => 'Ver respuestas a %s Preguntas mas Frecuentes%s',
+ 'Feedback_WhyAreMyVisitsNoTracked' => '¿Porque no se rastrean las visitas a mi sitio web?',
+ 'Feedback_HowToExclude' => 'Como excluyo mis visitas del rastreo?',
+ 'Feedback_WhyWrongCountry' => 'Porque Piwik muestra mis visitas en un país equivocado?',
+ 'Feedback_HowToAnonymizeIP' => '¿Cómo puedo ocultar las direcciones IP de los visitante en mi base de datos?',
+ 'Feedback_VisitTheForums' => 'Visita el %sForo%s',
+ 'Feedback_LearnWaysToParticipate' => 'Aprende sobre todas las formas de %sparticipar%s',
+ 'Feedback_SpecialRequest' => 'Tienes una petición especial para el equipo de Piwik?',
+ 'Feedback_ContactThePiwikTeam' => 'Contacta al equipo de Piwik!',
+ 'Feedback_IWantTo' => 'Yo quiero:',
+ 'Feedback_CategoryShareStory' => 'Compartir a Piwik mi historia de éxito',
+ 'Feedback_CategorySponsor' => 'Auspiciar Piwik',
+ 'Feedback_CategoryHire' => 'Contratar un consultor Piwik',
+ 'Feedback_CategorySecurity' => 'Informar de un problema de seguridad',
+ 'Feedback_MyEmailAddress' => 'Mi email:',
+ 'Feedback_MyMessage' => 'Mi mensaje:',
+ 'Feedback_DetailsPlease' => '(por favor incluya detalles)',
+ 'Feedback_SendFeedback' => 'Enviar comentario',
+ 'Feedback_ManuallySendEmailTo' => 'Por favor envíe su mensaje manualmente a',
+ 'Feedback_MessageSent' => 'Tu mensaje fue enviado al equipo de Piwik',
+ 'Feedback_ThankYou' => 'Gracias por ayudarnos a hacer un mejor Piwik',
+ 'Feedback_ThePiwikTeam' => 'El Equipo de Piwik',
+ 'Feedback_ExceptionBodyLength' => 'El mensaje debe tener al menos %s caracteres de largo',
+ 'Feedback_ExceptionNoUrls' => 'Este mensaje no puede contener URL, para evitar mensajes de spam.',
+ 'Goals_PluginDescription' => 'Crear Objetivos y ver informes acerca de las conversiones de su objetivo: evolución en el tiempo, los ingresos por visita, conversiones por referente, por palabra clave, etc',
+ 'Goals_OverallRevenue' => '%s ingresos totales',
+ 'Goals_OverallConversionRate' => '%s tasa global de la conversión (visitas con un objetivo terminado)',
+ 'Goals_Conversions' => '%s conversiones',
+ 'Goals_ConversionRate' => '%s tasa de conversiones',
+ 'Goals_NoGoalsNeedAccess' => 'Solo un Administrador o un Super Usuario puede agregar Objetivos para un determinado sitio web. Por favor pregunte a su administrador Piwik como colocar un Objetivo en su sitio web.<br>Seguir los Objetivos es una excelente forma de ayudar a entender y maximizar el rendimiento de su sitio web.',
+ 'Goals_AddNewGoal' => 'Agregar un nuevo Objetivo',
+ 'Goals_AddNewGoalOrEditExistingGoal' => '%sAgregar un nuevo Objetivo%s o %sEditar%s Objetivos existentes.',
+ 'Goals_AddGoal_js' => 'Agregar Objetivo',
+ 'Goals_UpdateGoal_js' => 'Actualizar Objetivo',
+ 'Goals_DeleteGoalConfirm_js' => 'Esta seguro que desea eliminar el Objetivo %s?',
+ 'Goals_GoalName' => 'Nombre del Objetivo',
+ 'Goals_GoalIsTriggered' => 'Objetivo activado',
+ 'Goals_GoalIsTriggeredWhen' => 'Objetivo activado cuando',
+ 'Goals_WhenVisitors' => 'cuando los visitantes',
+ 'Goals_Manually' => 'manualmente',
+ 'Goals_ManuallyTriggeredUsingJavascriptFunction' => 'Los Objetivos son manualmente activados usando la API Javascript trackGoal()',
+ 'Goals_VisitUrl' => 'Visita una URL (página o grupo de páginas)',
+ 'Goals_Download' => 'Descargar un archivo',
+ 'Goals_ClickOutlink' => 'Clic en un Enlace a un sitio web externo',
+ 'Goals_Optional' => '(opcional)',
+ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => 'donde las paginas visitadas contienen una llamada al método JavaScript piwikTracker.trackGoal() (%ssaber mas%s)',
+ 'Goals_DefaultRevenue' => 'Objetivo de ingreso por defecto es',
+ 'Goals_DefaultRevenueHelp' => 'Por ejemplo, un Formulario de Contacto enviado por un visitante puede valer 10 dolares en promedio. Piwik va a ayudar a entender que tan bien estan trabajando sus segmentos de visitantes.',
+ 'Goals_ConversionsOverview' => 'Información de Conversiones',
+ 'Goals_BestCountries' => 'Tus mejores países son:',
+ 'Goals_BestKeywords' => 'Tus mejores palabras de busqueda son:',
+ 'Goals_BestReferers' => 'Tus mejores palabras de busqueda son:',
+ 'Goals_ReturningVisitorsConversionRateIs' => 'La tasa de visitantes que retornan es %s',
+ 'Goals_NewVisitorsConversionRateIs' => 'La tasa de visitantes nuevos es %s',
+ 'Goals_Contains' => 'contiene %s',
+ 'Goals_IsExactly' => 'es exactamente %s',
+ 'Goals_MatchesExpression' => 'coincide con la expresión %s',
+ 'Goals_CaseSensitive' => 'Coincidir mayúsculas y minúsculas',
+ 'Goals_Pattern' => 'Patrón',
+ 'Installation_PluginDescription' => 'Proceso de instalación de Piwik. La Instalación es usualmente hecha solo una vez. Si el archivo de configuración config/config.ini.php se elimina, la instalación comenzará de nuevo.',
+ 'Installation_DatabaseClientVersion' => 'Version de cliente de la base de datos',
+ 'Installation_SystemCheckParseIniFileHelp' => 'Esta función integrada se ha desactivado en su host. Piwik intentará emular esta función, pero puede encontrar más restricciones de seguridad.',
+ 'Installation_SystemCheckDebugBacktraceHelp' => 'View::factory no estará disponible para crear vistas para el módulo de llamadas. ',
+ 'Installation_SystemCheckCreateFunctionHelp' => 'Piwik utiliza funciones anónimas para devoluciones de llamada.',
+ 'Installation_SystemCheckMbstring' => 'mbstring',
+ 'Installation_SystemCheckMbstringHelp' => 'Deberia colocar mbstring.func_overload en "0".',
+ 'Installation_SystemCheckFileIntegrity' => 'Integridad de archivos',
+ 'Installation_SystemCheckIpv4' => 'IPv4',
+ 'Installation_SystemCheckIpv4Help' => 'Deberia desactivar IPv6 en la configuración de su servidor web.',
+ 'Installation_ConfigurationHelp' => 'Su archivo de configuración de Piwik parece estar desconfigurado. Puede remover el archivo config/config.ini.php y seguir la instalación, o corregir la configuración de conexión de la base de datos.',
+ 'LanguagesManager_PluginDescription' => 'Este plugin mostrará una lista de idiomas para la interface de Piwik. Esta selección de idioma será grabada en las preferencias de cada usuario.',
+ 'Live_PluginDescription' => 'Espiar a tus visitantes, en vivo, en tiempo real!',
+ 'Login_PluginDescription' => 'Plugin de Autenticación de Ingreso, leyendo las credenciales desde el archivo config/config.inc.php para el Super Usuario, y desde la base de datos para los usuarios. Puede ser facilmente reemplazado para introducir un nuevo mecanismo de Autenticación (OpenID, htaccess, Custom Auth, etc).',
+ 'MultiSites_PluginDescription' => 'Muestra resumen y/o estadísticas ejecutivas multisitio. Actualmente mantenido como un plugin del núcleo de Piwik',
+ 'Provider_PluginDescription' => 'Reporta el Proveedor de los Visitantes.',
+ 'Referers_PluginDescription' => 'Reporte los datos de las Referencias: Motores de búsqueda, Palabras Clave, Sitios, Campañas, Entrada Directa.',
+ 'SitesManager_PluginDescription' => 'Administrador de Sitios en Piwik: Agregar un Nuevo Sitio, Mostrar el código Javascript que se incluirá en las páginas. Todas las acciones también están disponibles en la API.',
+ 'TranslationsAdmin_PluginDescription' => 'Ayuda a traducir Piwik en tu idioma.',
+ 'UserCountry_PluginDescription' => 'Reporta el País de tus visitantes.',
+ 'UserSettings_PluginDescription' => 'Reporta varias configuraciones de usuario: Navegador, Familia del Navegador, Sistema Operativo, Plugins, Resolución, Configuracion General.',
+ 'UsersManager_PluginDescription' => 'Administración de Usuarios en Piwik: agregar nuevo Usuario, editar uno existente, actualizar permisos. Todas las acciones están también disponibles en la API.',
+ 'VisitFrequency_PluginDescription' => 'Reporta varias estadisticas sobre los Visitante que ha vuelto versus los Visitantes Nuevos. ',
+ 'VisitorInterest_PluginDescription' => 'Reportes sobre el Interes de los Visitantes: número de paginas vistas, tiempo que estuvieron en el sitio web.',
+ 'VisitsSummary_PluginDescription' => 'Reporta los Números Generales del Análisis: visita, visitantes únicos, número de acciones, porcentaje de abandono, etc.
+
+',
+ 'VisitsSummary_NbActionsDescription' => '%s acciones (paginas vistas, descargas y enlaces externos)',
+ 'VisitTime_PluginDescription' => 'Reporta el tiempo Local y del Servidor. La información del tiempo del Servidor puede ser útil para programar un mantenimiento al sitio web.',
+ 'Widgetize_PluginDescription' => 'Este plugin hace muy fácil exportar cualquier Widget de Piwik a tu blog, sitio web o a iGoogle y Netvibes!',
+); \ No newline at end of file
diff --git a/lang/et.php b/lang/et.php
index 3e29e22b28..ef7fa0bec7 100644
--- a/lang/et.php
+++ b/lang/et.php
@@ -76,13 +76,39 @@ $translations = array(
'CoreHome_PeriodWeek' => 'Nädal',
'CoreHome_PeriodMonth' => 'Kuu',
'CoreHome_PeriodYear' => 'Aasta',
- 'CoreHome_DaySu_js' => 'Pü',
- 'CoreHome_DayMo_js' => 'Es',
- 'CoreHome_DayTu_js' => 'Te',
- 'CoreHome_DayWe_js' => 'Ko',
- 'CoreHome_DayTh_js' => 'Ne',
- 'CoreHome_DayFr_js' => 'Re',
- 'CoreHome_DaySa_js' => 'La',
+ 'CoreHome_DaySu_js' => 'P',
+ 'CoreHome_DayMo_js' => 'E',
+ 'CoreHome_DayTu_js' => 'T',
+ 'CoreHome_DayWe_js' => 'K',
+ 'CoreHome_DayTh_js' => 'N',
+ 'CoreHome_DayFr_js' => 'R',
+ 'CoreHome_DaySa_js' => 'L',
+ 'CoreHome_ShortDay_1_js' => 'Pühap',
+ 'CoreHome_ShortDay_2_js' => 'Esmasp',
+ 'CoreHome_ShortDay_3_js' => 'Teisip',
+ 'CoreHome_ShortDay_4_js' => 'Kolmap',
+ 'CoreHome_ShortDay_5_js' => 'Neljap',
+ 'CoreHome_ShortDay_6_js' => 'Reede',
+ 'CoreHome_ShortDay_7_js' => 'Laup',
+ 'CoreHome_LongDay_1_js' => 'Pühapäev',
+ 'CoreHome_LongDay_2_js' => 'Esmaspäev',
+ 'CoreHome_LongDay_3_js' => 'Teisipäev',
+ 'CoreHome_LongDay_4_js' => 'Kolmapäev',
+ 'CoreHome_LongDay_5_js' => 'Neljapäev',
+ 'CoreHome_LongDay_6_js' => 'Reede',
+ 'CoreHome_LongDay_7_js' => 'Laupäev',
+ 'CoreHome_ShortMonth_1_js' => 'Jaan',
+ 'CoreHome_ShortMonth_2_js' => 'Veebr',
+ 'CoreHome_ShortMonth_3_js' => 'Märts',
+ 'CoreHome_ShortMonth_4_js' => 'Apr',
+ 'CoreHome_ShortMonth_5_js' => 'Mai',
+ 'CoreHome_ShortMonth_6_js' => 'Juuni',
+ 'CoreHome_ShortMonth_7_js' => 'Juuli',
+ 'CoreHome_ShortMonth_8_js' => 'Aug',
+ 'CoreHome_ShortMonth_9_js' => 'Sept',
+ 'CoreHome_ShortMonth_10_js' => 'Okt',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dets',
'CoreHome_MonthJanuary_js' => 'Jaanuar',
'CoreHome_MonthFebruary_js' => 'Veebruar',
'CoreHome_MonthMarch_js' => 'Märts',
@@ -165,7 +191,7 @@ $translations = array(
'UserSettings_Browsers' => 'Veebisirvijad',
'UserSettings_Plugins' => 'Pluginad',
'UserSettings_Configurations' => 'Konfiguratsioonid',
- 'UserSettings_OperatinsSystems' => 'Operatsioonisüsteemid',
+ 'UserSettings_OperatingSystems' => 'Operatsioonisüsteemid',
'UserSettings_Resolutions' => 'Resolutsioonid',
'UserSettings_WideScreen' => 'Laiekraan',
'UserSettings_WidgetResolutions' => 'Ekraani resolutsioonid',
@@ -487,7 +513,6 @@ $translations = array(
'Login_PasswordReminder' => 'Palun sisesta kasutaja või e-mail address. Sulle saadetakse salasõna e-mailiga.',
'Login_InvalidUsernameEmail' => 'Vale kasutajanimi ja/või e-maili address',
'Login_MailTopicPasswordRecovery' => 'Salasõna taastamine',
- 'Login_MailPasswordRecoveryBody' => 'Tere %1s, \n\n Sinu uus salasõna on: %2s \n\n Saad nüüd sisse logida siit: %3s',
'Login_PasswordSent' => 'Salasõna saadetud. Kontrolli oma e-maili.',
'Login_ContactAdmin' => 'Võimalik põhjus: sinu majutusel on mail() funktsioon välja lülitatud. <br />Palun kontakteeru administraatoriga.',
'UsersManager_UsersManagement' => 'Kasutajate haldamine',
diff --git a/lang/eu.php b/lang/eu.php
new file mode 100644
index 0000000000..7b6b7fc04c
--- /dev/null
+++ b/lang/eu.php
@@ -0,0 +1,836 @@
+<?php
+$translations = array(
+ 'General_Locale' => 'eu_ES.UTF-8',
+ 'General_TranslatorName' => 'Librezale.org',
+ 'General_TranslatorEmail' => 'librezale@librezale.org',
+ 'General_EnglishLanguageName' => 'Basque',
+ 'General_OriginalLanguageName' => 'Euskara',
+ 'General_HelloUser' => 'Kaixo %s!',
+ 'General_OpenSourceWebAnalytics' => 'Kode irekiko web analitikak',
+ 'General_Dashboard' => 'Arbela',
+ 'General_MultiSitesSummary' => 'Webgune guztiak',
+ 'General_API' => 'APIa',
+ 'General_Widgets' => 'Widget-ak',
+ 'General_Settings' => 'Ezarpenak',
+ 'General_GiveUsYourFeedback' => 'Emaiguzu zure iritzia!',
+ 'General_Unknown' => 'Ezezaguna',
+ 'General_Required' => '%s behar da',
+ 'General_Error' => 'Errorea',
+ 'General_Warning' => 'Abisua',
+ 'General_BackToHomepage' => 'Atzera Piwik hasiera-orrira',
+ 'General_Yes' => 'Bai',
+ 'General_No' => 'Ez',
+ 'General_Delete' => 'Ezabatu',
+ 'General_Edit' => 'Editatu',
+ 'General_Ok' => 'Ados',
+ 'General_Close' => 'Itxi',
+ 'General_Logout' => 'Amaitu saioa',
+ 'General_Done' => 'Eginda',
+ 'General_LoadingData' => 'Datuak kargatzen...',
+ 'General_Loading' => 'Kargatzen...',
+ 'General_ErrorRequest' => 'Kontxo&hellip; arazoa egon da eskaeran, saiatu berriro mesedez.',
+ 'General_Next' => 'Hurrengoa',
+ 'General_Previous' => 'Aurrekoa',
+ 'General_Search' => 'Bilatu',
+ 'General_Others' => 'Besteak',
+ 'General_Table' => 'Taula',
+ 'General_Piechart' => 'Tarta-diagrama',
+ 'General_TagCloud' => 'Etiketa-hodeia',
+ 'General_VBarGraph' => 'Barra-diagrama bertikala',
+ 'General_Export' => 'Esportatu',
+ 'General_ExportAsImage_js' => 'Esportatu irudi gisa',
+ 'General_SaveImageOnYourComputer_js' => 'Irudia zure ordenagailuan gordetzeko, egin eskuin-klika irudian eta hautatu "Gorde irudia honela..."',
+ 'General_Refresh' => 'Berritu orria',
+ 'General_Visitors' => 'Bisitariak',
+ 'General_ColumnNbUniqVisitors' => 'Bisitari desberdinak',
+ 'General_ColumnNbVisits' => 'Bisitak',
+ 'General_ColumnNbActions' => 'Ekintzak',
+ 'General_ColumnMaxActions' => 'Bisita bateko gehienezko ekintzak',
+ 'General_ColumnSumVisitLength' => 'Bisitariek guztira igarotako denbora (segundotan)',
+ 'General_ColumnLabel' => 'Etiketa',
+ 'General_ColumnActionsPerVisit' => 'Ekintzak bisitako',
+ 'General_ColumnAvgTimeOnSite' => 'B.b.ko denbora webgunean',
+ 'General_ColumnBounceRate' => 'Errebotatze-tasa',
+ 'General_ColumnPageviews' => 'Orri-bistaratzeak',
+ 'General_ColumnUniquePageviews' => 'Orri-bistaratze desberdinak',
+ 'General_ColumnValuePerVisit' => 'Balioa bisitako',
+ 'General_ColumnVisitsWithConversions' => 'Bihurketak dituzten bisitak',
+ 'General_Save' => 'Gorde',
+ 'General_Website' => 'Webgunea',
+ 'General_RequiresFlash' => 'Piwik-en grafikoak bistaratzeko Flash behar da',
+ 'General_GraphHelp' => 'Piwik-en grafikoak bistaratzeko informazio gehiago.',
+ 'General_NoDataForGraph' => 'Daturik ez grafiko honentzat.',
+ 'General_NoDataForTagCloud' => 'Daturik ez etiketa-hodei honentzat.',
+ 'General_DisplayNormalTable' => 'Bistaratu taula normala',
+ 'General_DisplayMoreData' => 'Bistaratu datu gehiago',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s auzolaneko proiektua da. %s Piwik gustoko baduzu, laguntza eman dezakezu! Emaiozu begirada: %s Nola lagundu Piwik-en?%s ',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Une honetan %s(r)en demoa ikusten ari zara; %sdownload%s bertsio osoa! Eskuratu %s',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s eskura dago. %s Eguneratu orain!%s (ikusi %s aldaketak%s).',
+ 'General_BackToPiwik' => 'Itzuli Piwik-era',
+ 'General_ShortMonth_1' => 'urt',
+ 'General_ShortMonth_2' => 'ots',
+ 'General_ShortMonth_3' => 'mar',
+ 'General_ShortMonth_4' => 'api',
+ 'General_ShortMonth_5' => 'mai',
+ 'General_ShortMonth_6' => 'eka',
+ 'General_ShortMonth_7' => 'uzt',
+ 'General_ShortMonth_8' => 'abu',
+ 'General_ShortMonth_9' => 'ira',
+ 'General_ShortMonth_10' => 'urr',
+ 'General_ShortMonth_11' => 'aza',
+ 'General_ShortMonth_12' => 'abe',
+ 'General_LongMonth_1' => 'urtarrila',
+ 'General_LongMonth_2' => 'otsaila',
+ 'General_LongMonth_3' => 'martxoa',
+ 'General_LongMonth_4' => 'apirila',
+ 'General_LongMonth_5' => 'maiatza',
+ 'General_LongMonth_6' => 'ekaina',
+ 'General_LongMonth_7' => 'uztaila',
+ 'General_LongMonth_8' => 'abuztua',
+ 'General_LongMonth_9' => 'iraila',
+ 'General_LongMonth_10' => 'urria',
+ 'General_LongMonth_11' => 'azaroa',
+ 'General_LongMonth_12' => 'abendua',
+ 'General_ShortDay_1' => 'al.',
+ 'General_ShortDay_2' => 'ar.',
+ 'General_ShortDay_3' => 'az.',
+ 'General_ShortDay_4' => 'og.',
+ 'General_ShortDay_5' => 'ol.',
+ 'General_ShortDay_6' => 'lr.',
+ 'General_ShortDay_7' => 'ig.',
+ 'General_LongDay_1' => 'astelehena',
+ 'General_LongDay_2' => 'asteartea',
+ 'General_LongDay_3' => 'asteazkena',
+ 'General_LongDay_4' => 'osteguna',
+ 'General_LongDay_5' => 'ostirala',
+ 'General_LongDay_6' => 'larunbata',
+ 'General_LongDay_7' => 'igandea',
+ 'General_ExceptionDatabaseVersion' => 'Zure %s bertsioa %s da baina Piwik-ek gutxienez %s behar du.',
+ 'CorePluginsAdmin_Plugins' => 'Pluginak',
+ 'CorePluginsAdmin_PluginsManagement' => 'Pluginen kudeaketa',
+ 'CorePluginsAdmin_MainDescription' => 'Piwik-en funtzionaltasunak hedatu eta zabaltzen dituzte pluginek. Plugin bat instalatu ondoren, hemendik gaitu edo ezgaitu dezakezu.',
+ 'CorePluginsAdmin_Plugin' => 'Plugina',
+ 'CorePluginsAdmin_Version' => 'Bertsioa',
+ 'CorePluginsAdmin_Description' => 'Azalpena',
+ 'CorePluginsAdmin_Status' => 'Egoera',
+ 'CorePluginsAdmin_Action' => 'Ekintza',
+ 'CorePluginsAdmin_PluginHomepage' => 'Pluginaren hasiera-orria',
+ 'CorePluginsAdmin_Activated' => 'Gaituta',
+ 'CorePluginsAdmin_Active' => 'Gaituta',
+ 'CorePluginsAdmin_Inactive' => 'Ezgaituta',
+ 'CorePluginsAdmin_ActivatedHelp' => 'Plugin hau ezin da ezgaitu',
+ 'CorePluginsAdmin_Deactivate' => 'Ezgaitu',
+ 'CorePluginsAdmin_Activate' => 'Gaitu',
+ 'CorePluginsAdmin_MenuPlugins' => 'Pluginak',
+ 'API_QuickDocumentation' => '<h2>APIaren dokumentazio laburra</h2><p>Gaurko egunerako daturik ez badaukazu, <a href=\'misc/generateVisits.php\' target=_blank>zenbait datu sor ditzakezu</a> bisitak sortzeko script-a erabilita.</p><p>Metodo bakoitzerako eskura dauden formatuak proba ditzakezu. Oso erraza da Piwik-etik nahi duzun edozein datu erauztea!</p><p><b>Argibide gehiagorako emaiozu begirada <a href=\'http://dev.piwik.org/trac/wiki/API\'>APIare dokumentazio ofiziala</a>ri edo <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API erreferentzia</a>ri.</b></P><h2>Erabiltzaileen autentikazioa</h2><p><b>Datuak zure script-etan, crontab-ean, ... eskatu</b> nahi badituzu, <code><u>&token_auth=%s</u></code> parametroa gehitu behar duzu autentikazioa behar duten API deietako URLetan.</p><p>token_auth hau zure erabiltzaile-izen eta pasahitza bezain sekretuak dira, beraz <b>ez partekatu!</p>',
+ 'API_LoadedAPIs' => '%s API ondo kargatu dira',
+ 'CoreHome_NoPrivileges' => '\'%s\' bezala saioa hasita daukazu baina Piwik-en baimenik ezarri gabe daukazula dirudi.<br />Eskaiozu zure Piwik kudeatzaileari \'view\' atzipena emateko.',
+ 'CoreHome_JavascriptDisabled' => 'JavaScript-ek gaituta egon behar du Piwik ikuspegi estandarrean erabiltzeko.<br />Badirudi ordea JavaScript desgaituta dagoela edo zure nabigatzaileak ez duela onartzen.<br />Ikuspegi estandarra erabiltzeako, gaitu JavaScript zure nabigatzailearen aukeretan eta ondoren %ssaiatu berriro%s.<br />',
+ 'CoreHome_TableNoData' => 'Daturik ez taula honentzat.',
+ 'CoreHome_CategoryNoData' => 'Daturik ez kategoria honetan. Saiatu "Sartu populazio guztia" aukerarekin.',
+ 'CoreHome_ShowJSCode' => 'Erakutsi txertatu beharreko JavaScript kodea',
+ 'CoreHome_IncludeAllPopulation_js' => 'Sartu populazio guztia',
+ 'CoreHome_ExcludeLowPopulation_js' => 'Baztertu populazio txikia',
+ 'CoreHome_PageOf_js' => '%s / %s',
+ 'CoreHome_Loading_js' => 'Kargatzen...',
+ 'CoreHome_DayFormat' => '%longDay%, %longYear%(e)ko %longMonth%ren %day%a',
+ 'CoreHome_PeriodDay' => 'Eguna',
+ 'CoreHome_PeriodWeek' => 'Astea',
+ 'CoreHome_PeriodMonth' => 'Hilabetea',
+ 'CoreHome_PeriodYear' => 'Urtea',
+ 'CoreHome_PeriodDays' => 'egun',
+ 'CoreHome_PeriodWeeks' => 'aste',
+ 'CoreHome_PeriodMonths' => 'hilabete',
+ 'CoreHome_PeriodYears' => 'urte',
+ 'CoreHome_DaySu_js' => 'ig',
+ 'CoreHome_DayMo_js' => 'al',
+ 'CoreHome_DayTu_js' => 'ar',
+ 'CoreHome_DayWe_js' => 'az',
+ 'CoreHome_DayTh_js' => 'og',
+ 'CoreHome_DayFr_js' => 'ol',
+ 'CoreHome_DaySa_js' => 'lr',
+ 'CoreHome_ShortDay_1_js' => 'ig.',
+ 'CoreHome_ShortDay_2_js' => 'al.',
+ 'CoreHome_ShortDay_3_js' => 'ar.',
+ 'CoreHome_ShortDay_4_js' => 'az.',
+ 'CoreHome_ShortDay_5_js' => 'og.',
+ 'CoreHome_ShortDay_6_js' => 'ol.',
+ 'CoreHome_ShortDay_7_js' => 'lr.',
+ 'CoreHome_LongDay_1_js' => 'igandea',
+ 'CoreHome_LongDay_2_js' => 'astelehena',
+ 'CoreHome_LongDay_3_js' => 'asteartea',
+ 'CoreHome_LongDay_4_js' => 'asteazkena',
+ 'CoreHome_LongDay_5_js' => 'osteguna',
+ 'CoreHome_LongDay_6_js' => 'ostirala',
+ 'CoreHome_LongDay_7_js' => 'larunbata',
+ 'CoreHome_ShortMonth_1_js' => 'urtj',
+ 'CoreHome_ShortMonth_2_js' => 'ots',
+ 'CoreHome_ShortMonth_3_js' => 'mar',
+ 'CoreHome_ShortMonth_4_js' => 'api',
+ 'CoreHome_ShortMonth_5_js' => 'mai',
+ 'CoreHome_ShortMonth_6_js' => 'eka',
+ 'CoreHome_ShortMonth_7_js' => 'uzt',
+ 'CoreHome_ShortMonth_8_js' => 'abu',
+ 'CoreHome_ShortMonth_9_js' => 'ira',
+ 'CoreHome_ShortMonth_10_js' => 'urr',
+ 'CoreHome_ShortMonth_11_js' => 'aza',
+ 'CoreHome_ShortMonth_12_js' => 'abe',
+ 'CoreHome_MonthJanuary_js' => 'urtarrila',
+ 'CoreHome_MonthFebruary_js' => 'otsaila',
+ 'CoreHome_MonthMarch_js' => 'martxoa',
+ 'CoreHome_MonthApril_js' => 'apirila',
+ 'CoreHome_MonthMay_js' => 'maiatza',
+ 'CoreHome_MonthJune_js' => 'ekaina',
+ 'CoreHome_MonthJuly_js' => 'uztaila',
+ 'CoreHome_MonthAugust_js' => 'abuztua',
+ 'CoreHome_MonthSeptember_js' => 'iraila',
+ 'CoreHome_MonthOctober_js' => 'urria',
+ 'CoreHome_MonthNovember_js' => 'azaroa',
+ 'CoreHome_MonthDecember_js' => 'abendua',
+ 'CoreUpdater_UpdateTitle' => 'Eguneratu',
+ 'CoreUpdater_DatabaseUpgradeRequired' => 'Datu-basearen bertsio-berritzea beharrezkoa',
+ 'CoreUpdater_YourDatabaseIsOutOfDate' => 'Zure Piwik datu-basea zaharkituta dago eta jarraitu aurretik bertsio-berritu behar da.',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik datu-basea %s bertsiotik %s bertsio berrira bertsio-berrituko da.',
+ 'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Ondorengo pluginak eguneratuko dira: %s.',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'Piwik datu-base handia badaukazu, eguneraketek oso luze jo dezakete nabigatzailean exekutatuta. Egoera honetan komando-lerrotik exekuta ditzakezu eguneraketak: %s',
+ 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Datu-basea bertsio-berritzeko prozesuak denbora bat har lezake, izan pazientzia beraz.',
+ 'CoreUpdater_UpgradePiwik' => 'Bertsio-berritu Piwik',
+ 'CoreUpdater_ErrorDIYHelp' => 'Erabiltzaile aurreratua bazara eta datu-basearen bertsio-berritzean errore bat aurkitzen baduzu:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'identifikatu eta zuzendu arazoaren iturburua (adibidez, memory_limit edo max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'exekutatu falta diren galderak huts egin duen eguneraketan',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'eguneratu eskuz zure Piwik datu-baseko `option` taula, version_core-ren balioa huts egin duen eguneraketara ezarriz',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'exekutatu berriro eguneratzailea (nabigatzailearen bidez edo komando-lerrotik) falta diren eguneraketekin jarraitzeko',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'eman arazoaren (eta soluzioaren) berri, Piwik hobetu dadin',
+ 'CoreUpdater_HelpMessageContent' => 'Emaiozu begirada %s Piwik FAQari %s, zeinak eguneraketetan gerta litezkeen ohiko erroreak azaltzen dituen. %s Galdeiozu zure sistemaren kudeatzaileari - ziurrenik laguntzeko moduan izango da, errorea zerbitzariarekin edo MySQLren konfigurazioari lotuta egon baitaiteke.',
+ 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Errore kritikoa eguneraketa prozesuan:',
+ 'CoreUpdater_HelpMessageIntroductionWhenError' => 'Goikoa muinare errore-mezua da. Arrazoia azaltzen lagun lezake, baina laguntza gehiago behar izanez gero:',
+ 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Eguneraketa ondo burutu da, baina arazoak egon dira prozesuan zehar. Mesedez irakur ezazu goiko azalpenak xehetasun gehiagorako. Laguntza gehiago jasotzeko:',
+ 'CoreUpdater_UpgradeComplete' => 'Bertsio-berritzea burututa!',
+ 'CoreUpdater_WarningMessages' => 'Abisuak:',
+ 'CoreUpdater_ErrorDuringPluginsUpdates' => 'Errorea pluginak eguneratzean:',
+ 'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Ondorengo pluginak automatikoki ezgaitu ditugu: %s',
+ 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik ondo eguneratu da!',
+ 'CoreUpdater_ContinueToPiwik' => 'Jarraitu Piwik-era',
+ 'CoreUpdater_UpdateAutomatically' => 'Eguneratu automatikoki',
+ 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Piwik-en bertsio berria eskura dago eguneratzeko',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => '%s bertsiora automatikoi egunera dezakezu edo paketea deskargatu eta eskuz instalatu:',
+ 'CoreUpdater_DownloadX' => 'Deskargatu %s',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Piwik-en klik bakarreko eguneraketa utzi egin da. Goiko errore-mezua ezin baduzu konpondu, Piwik eskuz eguneratzea gomendatzen da. %s Emaiozu begirada bat %seguneraketen dokumentazioari%s konponbidea bilatzeko!',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Eguneraketa deskargatzen: %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Eguneraketa despaketatzen',
+ 'CoreUpdater_VerifyingUnpackedFiles' => 'Despaketatutako fitxategiak egiaztatzen',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Konfigurazio-fitxategiaren babeskopia sortzen %s kokalekuan',
+ 'CoreUpdater_InstallingTheLatestVersion' => 'Azkenengo bertsioa instalatzen',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik ondo eguneratu da!',
+ 'CoreUpdater_EmptyDatabaseError' => '%s datu-basea hutsik dago. Zure Piwik konfigurazio-fitxategi editatu edo ezabatu behar duzu.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Zure Piwik %s bertsioa eguneratuta dago.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Artxibo bateraezina: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Artxibo hutsa.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Artxiboa osatu gabe dago: fitxategi batzuk falta dira (adib. %s).',
+ 'Actions_Actions' => 'Ekintzak',
+ 'Actions_SubmenuPages' => 'Orriak',
+ 'Actions_SubmenuPageTitles' => 'Orrien izenburuak',
+ 'Actions_SubmenuOutlinks' => 'Kanpo-loturak',
+ 'Actions_SubmenuDownloads' => 'Deskargak',
+ 'Actions_ColumnClicks' => 'Klikak',
+ 'Actions_ColumnUniqueClicks' => 'Klik desberdinak',
+ 'Actions_ColumnDownloads' => 'Deskargak',
+ 'Actions_ColumnUniqueDownloads' => 'Deskarga desberdinak',
+ 'Actions_ColumnPageName' => 'Orriaren izena',
+ 'Actions_ColumnPageURL' => 'Orriaren URLa',
+ 'Actions_ColumnClickedURL' => 'Klik egindako URLa',
+ 'Actions_ColumnDownloadURL' => 'Deskargaren URLa',
+ 'Dashboard_Dashboard' => 'Arbela',
+ 'Dashboard_AddWidget' => 'Gehitu widget-a...',
+ 'Dashboard_DeleteWidgetConfirm' => 'Ziur zaude widget hau arbeletik ezabatu nahi duzula?',
+ 'Dashboard_SelectWidget' => 'Hautatu arbelean gehitzeko widget-a',
+ 'Dashboard_AddPreviewedWidget_js' => 'Gehitu arbelean aurrebistako widget-a',
+ 'Dashboard_WidgetPreview_js' => 'Widget-aren aurrebista',
+ 'Dashboard_Close_js' => 'Itxi',
+ 'Dashboard_TitleWidgetInDashboard_js' => 'Widget-a arbelan dago',
+ 'Dashboard_TitleClickToAdd_js' => 'Egin klik arbelean gehitzeko',
+ 'Dashboard_LoadingWidget_js' => 'Widget-a kargatzen, itxaron mesedez...',
+ 'Dashboard_WidgetNotFound_js' => 'Ez da widget-a aurkitu',
+ 'Referers_Referers' => 'Erreferenteak',
+ 'Referers_SearchEngines' => 'Bilaketa-motorrak',
+ 'Referers_Keywords' => 'Gako-hitzak',
+ 'Referers_DirectEntry' => 'Sarrera zuzena',
+ 'Referers_Websites' => 'Webguneak',
+ 'Referers_Campaigns' => 'Kanpainak',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%s (%s)',
+ 'Referers_Evolution' => 'Bilakaera periodoan zehar',
+ 'Referers_Type' => 'Erreferente mota',
+ 'Referers_ColumnRefererType' => 'Erreferente mota',
+ 'Referers_ColumnSearchEngine' => 'Bilaketa-motorra',
+ 'Referers_ColumnWebsite' => 'Webgunea',
+ 'Referers_ColumnWebsitePage' => 'Webguneko orria',
+ 'Referers_ColumnKeyword' => 'Gako-hitza',
+ 'Referers_ColumnCampaign' => 'Kanpaina',
+ 'Referers_DetailsByRefererType' => 'Xehetasunak erreferente motako',
+ 'Referers_TypeDirectEntries' => '%s sarbide zuzen',
+ 'Referers_TypeSearchEngines' => '%s bilaketa-motorretatik',
+ 'Referers_TypeWebsites' => '%s webguneetatik',
+ 'Referers_TypeCampaigns' => '%s kanpainetatik',
+ 'Referers_Distinct' => 'Erreferente desberdinak erreferente motagatik',
+ 'Referers_DistinctSearchEngines' => 'bilaketa-motor desberdin',
+ 'Referers_DistinctKeywords' => 'gako-hitz desberdin',
+ 'Referers_DistinctCampaigns' => 'kanpaina desberdin',
+ 'Referers_DistinctWebsites' => 'webgune desberdin',
+ 'Referers_UsingNDistinctUrls' => ' (%2s url desberdin erabiliz)',
+ 'Referers_SubmenuEvolution' => 'Bilakaera',
+ 'Referers_SubmenuSearchEngines' => 'Bilaketa-motorrak eta gako-hitzak',
+ 'Referers_SubmenuWebsites' => 'Webguneak',
+ 'Referers_SubmenuCampaigns' => 'Kanpainak',
+ 'Referers_WidgetKeywords' => 'Gako-hitzen zerrenda',
+ 'Referers_WidgetCampaigns' => 'Kanpainen zerrenda',
+ 'Referers_WidgetExternalWebsites' => 'Kanpoko webguneen zerrenda',
+ 'Referers_WidgetSearchEngines' => 'Gehien erabilitako bilaketa-motorrak',
+ 'Referers_WidgetOverview' => 'Orokorra',
+ 'UserSettings_VisitorSettings' => 'Bisitariaren ezarpenak',
+ 'UserSettings_BrowserFamilies' => 'Nabigatzaile-familiak',
+ 'UserSettings_Browsers' => 'Nabigatzaileak',
+ 'UserSettings_Plugins' => 'Pluginak',
+ 'UserSettings_Configurations' => 'Konfigurazioak',
+ 'UserSettings_OperatingSystems' => 'Sistema eragileak',
+ 'UserSettings_Resolutions' => 'Bereizmenak',
+ 'UserSettings_WideScreen' => 'Pantaila panoramikoa',
+ 'UserSettings_ColumnBrowserFamily' => 'Nabigatzaile-familia',
+ 'UserSettings_ColumnBrowser' => 'Nabigatzailea',
+ 'UserSettings_ColumnPlugin' => 'Plugina',
+ 'UserSettings_ColumnConfiguration' => 'Konfigurazioa',
+ 'UserSettings_ColumnOperatingSystem' => 'Sistema eragilea',
+ 'UserSettings_ColumnResolution' => 'Bereizmena',
+ 'UserSettings_ColumnTypeOfScreen' => 'Pantaila mota',
+ 'UserSettings_WidgetResolutions' => 'Pantailaren bereizmenak',
+ 'UserSettings_WidgetBrowsers' => 'Bisitarien nabigatzaileak',
+ 'UserSettings_WidgetPlugins' => 'Pluginen zerrenda',
+ 'UserSettings_WidgetWidescreen' => 'Normala / Panoramikoa',
+ 'UserSettings_WidgetBrowserFamilies' => 'Nabigatzaileak familiaka',
+ 'UserSettings_WidgetOperatingSystems' => 'Sistema eragileak',
+ 'UserSettings_WidgetGlobalVisitors' => 'Bisitarien konfigurazioa',
+ 'UserSettings_SubmenuSettings' => 'Ezarpenak',
+ 'UserCountry_Country' => 'Herrialdea',
+ 'UserCountry_Continent' => 'Kontinentea',
+ 'UserCountry_DistinctCountries' => '%s herrialde desberdin',
+ 'UserCountry_SubmenuLocations' => 'Kokalekuak',
+ 'UserCountry_WidgetContinents' => 'Bisitarien kontinenteak',
+ 'UserCountry_WidgetCountries' => 'Bisitarien herrialdeak',
+ 'UserCountry_country_ac' => 'Ascension uharteak',
+ 'UserCountry_country_ad' => 'Andorra',
+ 'UserCountry_country_ae' => 'Arabiar Emirerri Batuak',
+ 'UserCountry_country_af' => 'Afghanistan',
+ 'UserCountry_country_ag' => 'Antigua eta Barbuda',
+ 'UserCountry_country_ai' => 'Anguilla',
+ 'UserCountry_country_al' => 'Albania',
+ 'UserCountry_country_am' => 'Armenia',
+ 'UserCountry_country_an' => 'Holandarren Antillak',
+ 'UserCountry_country_ao' => 'Angola',
+ 'UserCountry_country_aq' => 'Antartika',
+ 'UserCountry_country_ar' => 'Argentina',
+ 'UserCountry_country_as' => 'Samoa amerikarra',
+ 'UserCountry_country_at' => 'Austria',
+ 'UserCountry_country_au' => 'Australia',
+ 'UserCountry_country_aw' => 'Aruba',
+ 'UserCountry_country_ax' => 'Aland uharteak',
+ 'UserCountry_country_az' => 'Azerbaijan',
+ 'UserCountry_country_ba' => 'Bosnia-Herzegovina',
+ 'UserCountry_country_bb' => 'Barbados',
+ 'UserCountry_country_bd' => 'Bangladesh',
+ 'UserCountry_country_be' => 'Belgika',
+ 'UserCountry_country_bf' => 'Burkina Faso',
+ 'UserCountry_country_bg' => 'Bulgaria',
+ 'UserCountry_country_bh' => 'Bahrain',
+ 'UserCountry_country_bi' => 'Burundi',
+ 'UserCountry_country_bj' => 'Benin',
+ 'UserCountry_country_bl' => 'Saint Barthelemy',
+ 'UserCountry_country_bm' => 'Bermuda',
+ 'UserCountry_country_bn' => 'Bruneo',
+ 'UserCountry_country_bo' => 'Bolivia',
+ 'UserCountry_country_br' => 'Brasil',
+ 'UserCountry_country_bs' => 'Bahamak',
+ 'UserCountry_country_bt' => 'Bhutan',
+ 'UserCountry_country_bu' => 'Burma',
+ 'UserCountry_country_bv' => 'Bouvet uhartea',
+ 'UserCountry_country_bw' => 'Botswana',
+ 'UserCountry_country_by' => 'Bielorrusia',
+ 'UserCountry_country_bz' => 'Belize',
+ 'UserCountry_country_ca' => 'Kanada',
+ 'UserCountry_country_cc' => 'Cocos (Keeling) uharteak',
+ 'UserCountry_country_cd' => 'Kongo',
+ 'UserCountry_country_cf' => 'Afrika Erdiko Errepublika',
+ 'UserCountry_country_cg' => 'Kongo',
+ 'UserCountry_country_ch' => 'Suitza',
+ 'UserCountry_country_ci' => 'Boli Kosta',
+ 'UserCountry_country_ck' => 'Cook uharteak',
+ 'UserCountry_country_cl' => 'Txile',
+ 'UserCountry_country_cm' => 'Kamerun',
+ 'UserCountry_country_cn' => 'Txina',
+ 'UserCountry_country_co' => 'Kolonbia',
+ 'UserCountry_country_cp' => 'Clipperton uhartea',
+ 'UserCountry_country_cr' => 'Costa Rica',
+ 'UserCountry_country_cs' => 'Serbia Montenegro',
+ 'UserCountry_country_cu' => 'Kuba',
+ 'UserCountry_country_cv' => 'Cabo Verde',
+ 'UserCountry_country_cx' => 'Christmas uhartea',
+ 'UserCountry_country_cy' => 'Zipre',
+ 'UserCountry_country_cz' => 'Txekia',
+ 'UserCountry_country_de' => 'Alemania',
+ 'UserCountry_country_dg' => 'Diego Garcia',
+ 'UserCountry_country_dj' => 'Djibuti',
+ 'UserCountry_country_dk' => 'Danimarka',
+ 'UserCountry_country_dm' => 'Dominika',
+ 'UserCountry_country_do' => 'Dominikar Errepublika',
+ 'UserCountry_country_dz' => 'Aljeria',
+ 'UserCountry_country_ea' => 'Ceuta, Melilla',
+ 'UserCountry_country_ec' => 'Ekuador',
+ 'UserCountry_country_ee' => 'Estonia',
+ 'UserCountry_country_eg' => 'Egipto',
+ 'UserCountry_country_eh' => 'Mendebaldeko Sahara',
+ 'UserCountry_country_er' => 'Eritrea',
+ 'UserCountry_country_es' => 'Espainia',
+ 'UserCountry_country_et' => 'Etiopia',
+ 'UserCountry_country_eu' => 'Europar Batasuna',
+ 'UserCountry_country_fi' => 'Finlandia',
+ 'UserCountry_country_fj' => 'Fiji',
+ 'UserCountry_country_fk' => 'Falkland uharteak (Malvinak)',
+ 'UserCountry_country_fm' => 'Mikronesia',
+ 'UserCountry_country_fo' => 'Faroe uharteak',
+ 'UserCountry_country_fr' => 'Frantzia',
+ 'UserCountry_country_fx' => 'Frantzia, Metropolia',
+ 'UserCountry_country_ga' => 'Gabon',
+ 'UserCountry_country_gb' => 'Britainia Handia',
+ 'UserCountry_country_gd' => 'Grenada',
+ 'UserCountry_country_ge' => 'Georgia',
+ 'UserCountry_country_gf' => 'Guyana Frantsesa',
+ 'UserCountry_country_gg' => 'Guernsey',
+ 'UserCountry_country_gh' => 'Ghana',
+ 'UserCountry_country_gi' => 'Gibraltar',
+ 'UserCountry_country_gl' => 'Groenlandia',
+ 'UserCountry_country_gm' => 'Gambia',
+ 'UserCountry_country_gn' => 'Ginea',
+ 'UserCountry_country_gp' => 'Guadalupe',
+ 'UserCountry_country_gq' => 'Ekuatore Ginea',
+ 'UserCountry_country_gr' => 'Grezia',
+ 'UserCountry_country_gs' => 'Hegoaldeko Georgia eta Hegoaldeko Sandwich uharteak',
+ 'UserCountry_country_gt' => 'Guatemala',
+ 'UserCountry_country_gu' => 'Guam',
+ 'UserCountry_country_gw' => 'Ginea Bissau',
+ 'UserCountry_country_gy' => 'Guyana',
+ 'UserCountry_country_hk' => 'Hong Kong',
+ 'UserCountry_country_hm' => 'Heard eta McDonald uharteak',
+ 'UserCountry_country_hn' => 'Honduras',
+ 'UserCountry_country_hr' => 'Kroazia',
+ 'UserCountry_country_ht' => 'Haiti',
+ 'UserCountry_country_hu' => 'Hungaria',
+ 'UserCountry_country_ic' => 'Kanariar uharteak',
+ 'UserCountry_country_id' => 'Indonesia',
+ 'UserCountry_country_ie' => 'Irlanda',
+ 'UserCountry_country_il' => 'Israel',
+ 'UserCountry_country_im' => 'Man uhartea',
+ 'UserCountry_country_in' => 'India',
+ 'UserCountry_country_io' => 'British Indian Ocean Territory',
+ 'UserCountry_country_iq' => 'Irak',
+ 'UserCountry_country_ir' => 'Iran',
+ 'UserCountry_country_is' => 'Islandia',
+ 'UserCountry_country_it' => 'Italia',
+ 'UserCountry_country_je' => 'Jersey',
+ 'UserCountry_country_jm' => 'Jamaika',
+ 'UserCountry_country_jo' => 'Jordan',
+ 'UserCountry_country_jp' => 'Japonia',
+ 'UserCountry_country_ke' => 'Kenia',
+ 'UserCountry_country_kg' => 'Kirgizistan',
+ 'UserCountry_country_kh' => 'Kanbodia',
+ 'UserCountry_country_ki' => 'Kiribati',
+ 'UserCountry_country_km' => 'Komoreak',
+ 'UserCountry_country_kn' => 'Saint Kitts eta Nevis',
+ 'UserCountry_country_kp' => 'Korea',
+ 'UserCountry_country_kr' => 'Korea',
+ 'UserCountry_country_kw' => 'Kuwait',
+ 'UserCountry_country_ky' => 'Cayman uharteak',
+ 'UserCountry_country_kz' => 'Kazakhstan',
+ 'UserCountry_country_la' => 'Laos',
+ 'UserCountry_country_lb' => 'Libano',
+ 'UserCountry_country_lc' => 'Santa Luzia',
+ 'UserCountry_country_li' => 'Liechtestein',
+ 'UserCountry_country_lk' => 'Sri Lanka',
+ 'UserCountry_country_lr' => 'Liberia',
+ 'UserCountry_country_ls' => 'Lesotho',
+ 'UserCountry_country_lt' => 'Lituania',
+ 'UserCountry_country_lu' => 'Luxenburgo',
+ 'UserCountry_country_lv' => 'Letonia',
+ 'UserCountry_country_ly' => 'Libia',
+ 'UserCountry_country_ma' => 'Maroko',
+ 'UserCountry_country_mc' => 'Monako',
+ 'UserCountry_country_md' => 'Moldavia',
+ 'UserCountry_country_me' => 'Montenegro',
+ 'UserCountry_country_mf' => 'Saint Martin',
+ 'UserCountry_country_mg' => 'Madagaskar',
+ 'UserCountry_country_mh' => 'Marshall Uharteak',
+ 'UserCountry_country_mk' => 'Mazedonia',
+ 'UserCountry_country_ml' => 'Mali',
+ 'UserCountry_country_mm' => 'Myanmar',
+ 'UserCountry_country_mn' => 'Mongolia',
+ 'UserCountry_country_mo' => 'Macau',
+ 'UserCountry_country_mp' => 'Northern Mariana Islands',
+ 'UserCountry_country_mq' => 'Martinika',
+ 'UserCountry_country_mr' => 'Mauritania',
+ 'UserCountry_country_ms' => 'Montserrat',
+ 'UserCountry_country_mt' => 'Malta',
+ 'UserCountry_country_mu' => 'Maurizio',
+ 'UserCountry_country_mv' => 'Maldivak',
+ 'UserCountry_country_mw' => 'Malawi',
+ 'UserCountry_country_mx' => 'Mexiko',
+ 'UserCountry_country_my' => 'Malaysia',
+ 'UserCountry_country_mz' => 'Mozambike',
+ 'UserCountry_country_na' => 'Namibia',
+ 'UserCountry_country_nc' => 'Kaledonia Berria',
+ 'UserCountry_country_ne' => 'Niger',
+ 'UserCountry_country_nf' => 'Norfolk uhartea',
+ 'UserCountry_country_ng' => 'Nigeria',
+ 'UserCountry_country_ni' => 'Nikaragua',
+ 'UserCountry_country_nl' => 'Herbehereak',
+ 'UserCountry_country_no' => 'Norbegia',
+ 'UserCountry_country_np' => 'Nepal',
+ 'UserCountry_country_nr' => 'Nauru',
+ 'UserCountry_country_nt' => 'Eremu Neutroa',
+ 'UserCountry_country_nu' => 'Niue',
+ 'UserCountry_country_nz' => 'Zeelanda Berria',
+ 'UserCountry_country_om' => 'Oman',
+ 'UserCountry_country_pa' => 'Panama',
+ 'UserCountry_country_pe' => 'Peru',
+ 'UserCountry_country_pf' => 'Polinesia Frantsesa',
+ 'UserCountry_country_pg' => 'Papua Ginea Berria',
+ 'UserCountry_country_ph' => 'Filipinak',
+ 'UserCountry_country_pk' => 'Pakistan',
+ 'UserCountry_country_pl' => 'Polonia',
+ 'UserCountry_country_pm' => 'Saint-Pierre eta Mikelune',
+ 'UserCountry_country_pn' => 'Pitcairn',
+ 'UserCountry_country_pr' => 'Puerto Rico',
+ 'UserCountry_country_ps' => 'Palestinako lurralde okupatua',
+ 'UserCountry_country_pt' => 'Portugal',
+ 'UserCountry_country_pw' => 'Palau',
+ 'UserCountry_country_py' => 'Paraguai',
+ 'UserCountry_country_qa' => 'Qatar',
+ 'UserCountry_country_re' => 'Reunion',
+ 'UserCountry_country_ro' => 'Errumania',
+ 'UserCountry_country_ru' => 'Errusia',
+ 'UserCountry_country_rs' => 'Serbia',
+ 'UserCountry_country_rw' => 'Ruanda',
+ 'UserCountry_country_sa' => 'Saudi Arabia',
+ 'UserCountry_country_sb' => 'Solomon Uharteak',
+ 'UserCountry_country_sc' => 'Seychelleak',
+ 'UserCountry_country_sd' => 'Sudan',
+ 'UserCountry_country_se' => 'Suedia',
+ 'UserCountry_country_sf' => 'Finlandia',
+ 'UserCountry_country_sg' => 'Singapur',
+ 'UserCountry_country_sh' => 'Santa Helena',
+ 'UserCountry_country_si' => 'Eslovenia',
+ 'UserCountry_country_sj' => 'Svalbard',
+ 'UserCountry_country_sk' => 'Eslovakia',
+ 'UserCountry_country_sl' => 'Sierra Leona',
+ 'UserCountry_country_sm' => 'San Marino',
+ 'UserCountry_country_sn' => 'Senegal',
+ 'UserCountry_country_so' => 'Somalia',
+ 'UserCountry_country_sr' => 'Surinam',
+ 'UserCountry_country_st' => 'Sao Tome eta Principe',
+ 'UserCountry_country_su' => 'Old U.S.S.R',
+ 'UserCountry_country_sv' => 'El Salvador',
+ 'UserCountry_country_sy' => 'Siria',
+ 'UserCountry_country_sz' => 'Swazilandia',
+ 'UserCountry_country_ta' => 'Tristan da Cunha',
+ 'UserCountry_country_tc' => 'Turks eta Caico uharteak',
+ 'UserCountry_country_td' => 'Txad',
+ 'UserCountry_country_tf' => 'Hegoaldeko lurralde frantsesak',
+ 'UserCountry_country_tg' => 'Togo',
+ 'UserCountry_country_th' => 'Thailandia',
+ 'UserCountry_country_tj' => 'Tajikistan',
+ 'UserCountry_country_tk' => 'Tokelau',
+ 'UserCountry_country_tl' => 'Ekialdeko Timor',
+ 'UserCountry_country_tm' => 'Turkmenistan',
+ 'UserCountry_country_tn' => 'Tunisia',
+ 'UserCountry_country_to' => 'Tonga',
+ 'UserCountry_country_tp' => 'Ekialdeko Timor',
+ 'UserCountry_country_tr' => 'Turkia',
+ 'UserCountry_country_tt' => 'Trinidad eta Tobago',
+ 'UserCountry_country_tv' => 'Tuvalu',
+ 'UserCountry_country_tw' => 'Taiwan',
+ 'UserCountry_country_tz' => 'Tanzania',
+ 'UserCountry_country_ua' => 'Ukraina',
+ 'UserCountry_country_ug' => 'Uganda',
+ 'UserCountry_country_uk' => 'Erresuma Batua',
+ 'UserCountry_country_um' => 'Estatu Batuetako kanpoaldeko uharte txikiak',
+ 'UserCountry_country_us' => 'Ameriketako Estatu Batuak',
+ 'UserCountry_country_uy' => 'Uruguai',
+ 'UserCountry_country_uz' => 'Uzbekistan',
+ 'UserCountry_country_va' => 'Vatikanoa',
+ 'UserCountry_country_vc' => 'Saint Vincent eta Granadinak',
+ 'UserCountry_country_ve' => 'Venezuela',
+ 'UserCountry_country_vg' => 'Birjina uharteak (britainiarrak)',
+ 'UserCountry_country_vi' => 'Birjina uharteak (amerikarrak)',
+ 'UserCountry_country_vn' => 'Vietnam',
+ 'UserCountry_country_vu' => 'Vanuatu',
+ 'UserCountry_country_wf' => 'Wallis eta Futuna',
+ 'UserCountry_country_ws' => 'Samoa',
+ 'UserCountry_country_ye' => 'Yemen',
+ 'UserCountry_country_yt' => 'Mayotte',
+ 'UserCountry_country_yu' => 'Yugoslavia',
+ 'UserCountry_country_za' => 'Hegoafrika',
+ 'UserCountry_country_zm' => 'Zambia',
+ 'UserCountry_country_zr' => 'Zaire',
+ 'UserCountry_country_zw' => 'Zimbabwe',
+ 'UserCountry_continent_eur' => 'Europa',
+ 'UserCountry_continent_afr' => 'Afrika',
+ 'UserCountry_continent_asi' => 'Asia',
+ 'UserCountry_continent_ams' => 'Hegoamerika eta ertamerika',
+ 'UserCountry_continent_amn' => 'Iparramerika',
+ 'UserCountry_continent_oce' => 'Ozeania',
+ 'VisitsSummary_VisitsSummary' => 'Bisiten laburpena',
+ 'VisitsSummary_NbVisits' => '%s bisita',
+ 'VisitsSummary_NbUniqueVisitors' => '%s bisitari desberdin',
+ 'VisitsSummary_NbActions' => '%s ekintza (ikusitako orriak)',
+ 'VisitsSummary_TotalTime' => '%s bisitariek guztira igarotako denbora',
+ 'VisitsSummary_MaxNbActions' => '%s ekintza gehienez bisita batean',
+ 'VisitsSummary_NbVisitsBounced' => '%s bisita errebotatu dira (webgunea utzi dute orri bat ikusi ondoren)',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Bilakaera azken %san zehar',
+ 'VisitsSummary_Report' => 'Txostena',
+ 'VisitsSummary_GenerateTime' => '%s segundo orria sortzeko',
+ 'VisitsSummary_GenerateQueries' => '%s galdera exekutatuta',
+ 'VisitsSummary_WidgetLastVisits' => 'Azken bisiten grafikoa',
+ 'VisitsSummary_WidgetVisits' => 'Bisiten ikuspegi orokorra',
+ 'VisitsSummary_WidgetLastVisitors' => 'Azken bisitari desberdinen grafikoa',
+ 'VisitsSummary_WidgetOverviewGraph' => 'Ikuspegi orokorra grafikoarekin',
+ 'VisitsSummary_SubmenuOverview' => 'Orokorra',
+ 'VisitFrequency_Evolution' => 'Bilakaera periodoan zehar',
+ 'VisitFrequency_ColumnReturningVisits' => 'Itzulerako bisitak',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Itzulerako bisiten ekintzak',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Itzulerako bisitako gehienezko ekintzak',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Itzulerako bisitek guztira igarotako (segundotan)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Itzulerako bisiten errebotatze-tasa',
+ 'VisitFrequency_ReturnVisits' => '%s itzulerako bisita',
+ 'VisitFrequency_ReturnActions' => '%s ekintza itzulerako bisitek',
+ 'VisitFrequency_ReturnMaxActions' => '%s ekintza gehienez itzulerako bisitek',
+ 'VisitFrequency_ReturnTotalTime' => '%s itzulerako bisitek guztira igarotako denbora',
+ 'VisitFrequency_ReturnBounceRate' => '%s itzulerako bisita errebotatu dira (webgunea utzi dute orri bat ikusi ondoren)',
+ 'VisitFrequency_WidgetOverview' => 'Maiztasunaren ikuspegi orokorra',
+ 'VisitFrequency_WidgetGraphReturning' => 'Itzulerako bisiten grafikoa',
+ 'VisitFrequency_SubmenuFrequency' => 'Maiztasuna',
+ 'VisitTime_LocalTime' => 'Ordu lokaleko bisitak',
+ 'VisitTime_ServerTime' => 'Zerbitzariaren orduko bisitak',
+ 'VisitTime_ColumnServerTime' => 'Zerbitzariaren ordua',
+ 'VisitTime_ColumnLocalTime' => 'Ordu lokala',
+ 'VisitTime_WidgetLocalTime' => 'Ordu lokaleko bisitak',
+ 'VisitTime_WidgetServerTime' => 'Zerbitzariaren orduko bisitak',
+ 'VisitTime_SubmenuTimes' => 'Orduak',
+ 'VisitTime_NHour' => '%sh',
+ 'VisitorInterest_VisitsPerDuration' => 'Bisitak bisitaren iraupeneko',
+ 'VisitorInterest_VisitsPerNbOfPages' => 'Bisitak orri kopuruko',
+ 'VisitorInterest_ColumnVisitDuration' => 'Bisitaren iraupena',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Orriak bisitako',
+ 'VisitorInterest_WidgetLengths' => 'Bisiten iraupena',
+ 'VisitorInterest_WidgetPages' => 'Orriak bisitako',
+ 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Maiztasuna eta leialtasuna',
+ 'VisitorInterest_PlusXMin' => '%s min',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
+ 'VisitorInterest_OnePage' => 'orri bat',
+ 'VisitorInterest_NPages' => '%s orri',
+ 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
+ 'Login_LoginPasswordNotCorrect' => 'Erabiltzaile-izena eta pasahitza ez datoz bat',
+ 'Login_Login' => 'Erabiltzaile-izena',
+ 'Login_Password' => 'Pasahitza',
+ 'Login_PasswordRepeat' => 'Pasahitza (errepikatu)',
+ 'Login_ChangePassword' => 'Aldatu pasahitza',
+ 'Login_LoginOrEmail' => 'Erabiltzaile-izena edo e-posta',
+ 'Login_LogIn' => 'Hasi saioa',
+ 'Login_Logout' => 'Amaitu saioa',
+ 'Login_LostYourPassword' => 'Pasahitza galdu duzu?',
+ 'Login_RemindPassword' => 'Bidali pasahitz berrezartzea',
+ 'Login_PasswordResetToken' => 'Pasahitza berrezartzeko tokena',
+ 'Login_PasswordReminder' => 'Idatzi zure erabiltzaile-izen edo e-posta. Mezu elektroniko bat jasoko duzu zure pasahitza berrezartzeko informazioarekin.',
+ 'Login_PasswordsDoNotMatch' => 'Pasahitzak ez datoz bat.',
+ 'Login_PasswordSuccessfullyChanged' => 'Pasahitza ondo aldatu da!',
+ 'Login_InvalidUsernameEmail' => 'Erabiltzaile-izen edo helbide elektroniko baliogabea',
+ 'Login_InvalidOrExpiredToken' => 'Tokena baliogabea da edo iraungi egin da',
+ 'Login_MailTopicPasswordRecovery' => 'Pasahitza berreskuratzea',
+ 'Login_MailPasswordRecoveryBody' => "Kaixo %s,\n\nPasahitza berrezartzeko eskaria jaso da %s helbidetik.\n\nZure pasahitza berrezartzeko:\n\n1) Zoaz pasahitza berrezartzeko inprimakira:\n\t%s\n\n2) Idatz ezazu ondorengo tokena:\n\t%s\n\n3) Bete eta bidal ezazu inprimakia (zure pasahitz berria birritan sartuz) inprimakia.\n\nOharra: tokena 24 ordutan iraungiko da.\n",
+ 'Login_PasswordSent' => 'Zure pasahitza berrezartzeko informazioa bidali da. Begira ezazu zure posta elektronikoa.',
+ 'Login_ContactAdmin' => 'Arrazoi posiblea: zure ostalariak mail() funtzioa ezgaituta izan dezake.<br />Jar zaitez harremanetan zure Piwik kudeatzailearekin.',
+ 'UsersManager_UsersManagement' => 'Erabiltzaileen kudeaketa',
+ 'UsersManager_UsersManagementMainDescription' => 'Sortu erabiltzaile berriak edo eguneratu daudenak. Ondoren hauen baimenak goian ezar ditzakezu.',
+ 'UsersManager_ManageAccess' => 'Kudeatu atzipena',
+ 'UsersManager_MainDescription' => 'Erabaki zein erabiltzailek atzi dezaketen Piwik zure webguneetan. Webgune guztietarako baimenak ere ezar ditzakezu ekintza bakarrean.',
+ 'UsersManager_Sites' => 'Webguneak',
+ 'UsersManager_AllWebsites' => 'Webgune guztiak',
+ 'UsersManager_ApplyToAllWebsites' => 'Aplikatu webgune guztiei',
+ 'UsersManager_User' => 'Erabiltzailea',
+ 'UsersManager_PrivNone' => 'Atzipenik ez',
+ 'UsersManager_PrivView' => 'Ikusi',
+ 'UsersManager_PrivAdmin' => 'Kudeatu',
+ 'UsersManager_ChangeAllConfirm' => 'Ziur zaude \'%s\'(r)en baimenak aldatu nahi dituzula webgune guztietan?',
+ 'UsersManager_Login' => 'Erabiltzaile-izena',
+ 'UsersManager_Password' => 'Pasahitza',
+ 'UsersManager_Email' => 'E-posta',
+ 'UsersManager_Alias' => 'Alias',
+ 'UsersManager_Edit' => 'Editatu',
+ 'UsersManager_AddUser' => 'Gehitu erabiltzaile berria',
+ 'UsersManager_MenuUsers' => 'Erabiltzaileak',
+ 'UsersManager_DeleteConfirm_js' => 'Ziur zaude %s erabiltzailea ezabatu nahi duzula?',
+ 'UsersManager_ExceptionLoginExists' => '\'%s\' erabiltzaile-izena badago.',
+ 'UsersManager_ExceptionEmailExists' => '\'%s\' helbide elektronikoa duen erabiltzailea badago.',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'Erabiltzaile-izenak %s eta %s karaktere artekoa izan behar du luzeran eta letrak, zenbakiak edo \'_\' edo \'-\' edo \'.\' karaktereak izan ditzake soilik.',
+ 'UsersManager_ExceptionInvalidPassword' => 'Pasahitzaren luzerak 6 eta 26 karaktere artekoa izan behar du.',
+ 'UsersManager_ExceptionInvalidEmail' => 'Helbide elektronikoaren formatua baliogabea da.',
+ 'UsersManager_ExceptionDeleteDoesNotExist' => '\'%s\' erabiltzailea ez dago beraz ezin da ezabatu.',
+ 'UsersManager_ExceptionAdminAnonymous' => 'Ezin diozu \'admin\' atzipena eman \'anonymous\' erabiltzaileari.',
+ 'UsersManager_ExceptionEditAnonymous' => 'anonymous erabiltzailea ezin da editatu edo ezabatu. Saioa hasi gabeko erabiltzaileak definitzeko erabiltzen du Piwik-ek. Adibidez, estatistikak publiko egiteko \'ikusi\' atzipena eman besterik ez duzu \'anonymous\' erabiltzailearentzat.',
+ 'UsersManager_ExceptionSuperUser' => 'Eskatutako erabiltzailea Superrerabiltzailea da eta ezin zaizkio galderak egin, editatu edo ezabatu APIaren bidez. Superrerabiltzailearen xehetasunak eskuz edita ditzakezu zure Piwik konfigurazio-fitxategian.',
+ 'UsersManager_ExceptionUserDoesNotExist' => '\'%s\' erabiltzailea ez dago.',
+ 'UsersManager_ExceptionAccessValues' => 'access parametroak ondorengo balioetako bat izan behar du: [ %s ]',
+ 'SitesManager_Sites' => 'Webguneak',
+ 'SitesManager_WebsitesManagement' => 'Webguneen kudeaketa',
+ 'SitesManager_MainDescription' => 'Zure web analitiken txostenek webguneak behar dituzte! Gehitu, eguneratu, ezabatu webguneak eta erakutsi zure orrietan txertatu beharreko JavaScript kodea.',
+ 'SitesManager_JsTrackingTag' => 'JavaScript jarraipen-etiketa',
+ 'SitesManager_JsTrackingTagHelp' => 'Hemen da zure orri guztietan txertatu beharreko JavaScript jarraipen-etiketa',
+ 'SitesManager_ShowTrackingTag' => 'erakutsi jarraipen-etiketa',
+ 'SitesManager_NoWebsites' => 'Ez daukazu kudeatzeko webgunerik.',
+ 'SitesManager_AddSite' => 'Gehitu webgune berria',
+ 'SitesManager_AliasUrlHelp' => 'Gomendagarria da, baina ez beharrezkoa, bisitariek webgune hau atzitzeko erabiltzen dituzten URL ezberdinak zehaztea.
+Webgune baterako alias URLak ez dira agertuko Erreferenteak > Webguneak txostenean.
+Konturatu ez dela beharrezkoa URLak \'www\'-rekin edo gabe zehaztea, Piwik-ek automatikoki biak hartzen baititu kontuan.',
+ 'SitesManager_Id' => 'Id',
+ 'SitesManager_Name' => 'Izena',
+ 'SitesManager_Urls' => 'URLak',
+ 'SitesManager_MenuSites' => 'Webguneak',
+ 'SitesManager_DeleteConfirm_js' => 'Ziur zaude %s webgunea ezabatu nahi duzula?',
+ 'SitesManager_ExceptionDeleteSite' => 'Ezin da webgune hau ezabatu erregistratutako bakarra delako. Gehitu webgune berri bat lehenik eta ezabatu hau ondoren.',
+ 'SitesManager_ExceptionNoUrl' => 'Webgunearentzat URL bat zehaztu behar duzu gutxienez.',
+ 'SitesManager_ExceptionEmptyName' => 'Webgunearen izenak ezin du hutsa izan.',
+ 'SitesManager_ExceptionInvalidUrl' => '\'%s\' URLa ez da baliozko URL bat.',
+ 'Installation_Installation' => 'Instalazioa',
+ 'Installation_InstallationStatus' => 'Instalazioaren egoera',
+ 'Installation_PercentDone' => '%% %s eginda',
+ 'Installation_NoConfigFound' => 'Piwik konfigurazio-fitxategia ezin izan da aurkitu eta Piwik orri bat atzitzen saiatzen ari zara.<br /><b>&nbsp;&nbsp;&raquo; <a href=\'index.php\'>Piwik orain instalatu</a> dezakezu</b><br /><small>Aurretik Piwik instalatu eta datu-basean taulak badituzu, ez kezkatu, taula berdinak berrerabil ditzakezu eta dauden datuak mantendu!</small>',
+ 'Installation_DatabaseSetup' => 'Datu-basearen konfigurazioa',
+ 'Installation_DatabaseSetupServer' => 'datu-basearen zerbitzaria',
+ 'Installation_DatabaseSetupLogin' => 'erabiltzaile-izena',
+ 'Installation_DatabaseSetupPassword' => 'pasahitza',
+ 'Installation_DatabaseSetupDatabaseName' => 'datu-basearen izena',
+ 'Installation_DatabaseSetupTablePrefix' => 'taularen aurrizkia',
+ 'Installation_DatabaseSetupAdapter' => 'egokitzailea',
+ 'Installation_DatabaseErrorConnect' => 'Errorea datu-basearen zerbitzariarekin konektatzen saiatzean',
+ 'Installation_DatabaseCheck' => 'Datu-basearen egiaztapena',
+ 'Installation_DatabaseServerVersion' => 'Datu-basearen zerbitzariaren bertsioa',
+ 'Installation_DatabaseCreation' => 'Datu-basea sortzea',
+ 'Installation_DatabaseClientCharset' => 'Datu-baseko bezeroaren karaktere-kodeketa',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'Datu-base zerbitzarirako konexioa ez dago UTF8 bezala lehenetsita. Ez da hil ala biziko arazoa: <b>Piwik-ek ondo funtzionatu behar luke</b>. Halere, konsistentzia mantentzeagatik, ondorengoetako bat egitea gomendatzen da: <ul style="list-style: disc;margin-left:10px"><li>Zure Piwik konfigurazio-fitxategian <code>config/config.ini.php</code>, <code>charset = utf8</code> gehitzea [database] atalean</li><li>libmysql --with-charset=utf8 aukerarekin birkonpilatzea</li></ul>',
+ 'Installation_DatabaseTimezone' => 'Datu-basearen ordu-zonaldea',
+ 'Installation_TimezoneMismatch' => 'PHPko date.timezone ez da datu-base zerbitzariaren ordu-zonaldearen berdina. Honek arazoak sor ditzake txostenetan erakutsiko diren datuekin, eguneko orduak gaizki egon baitaitezke. Argibide gehiago: %s',
+ 'Installation_JsTag' => 'JavaScript etiketa',
+ 'Installation_JsTagHelp' => '<p>Bisitari guztiak kontatzeko, JavaScript kodea txertatu behar duzu zure orri guztietan.</p><p>Zure orriek ez dute PHPz eginak izan behar, Piwik ondo moldatuko da mota guztietako orrietan (HTML, ASP, Perl edo beste edozein lengoaiakoak izanda ere).</p><p>Hemen da txertatu behar duzun kodea: (kopiatu eta itsatsi zure orri guztietan)</p>',
+ 'Installation_JsTagHelpTitle' => 'Nola txertatu etiketa zure webguneetan?',
+ 'Installation_LargePiwikInstances' => 'Laguntza Piwik-en instalazio handientzat',
+ 'Installation_JsTagArchivingHelp' => 'Trafiko ertain eta handiko webguneetarako, eman begirada <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">Nola konfiguratu artxibatze automatikoko orria</a> dokumentuari Piwik azkar batean exekuta dadin!',
+ 'Installation_Congratulations' => 'Zorionak',
+ 'Installation_CongratulationsHelp' => '<p>Zorionak! Zure Piwik instalazioa osatu da.</p><p>Egiaztatu JavaScript kodea zure orrietan txertatuta dagoela eta ondoren itxaron lehenengo bisitei!</p>',
+ 'Installation_ContinueToPiwik' => 'Jarraitu Piwik-era',
+ 'Installation_SetupWebsite' => 'Konfiguratu webgunea',
+ 'Installation_SetupWebSiteName' => 'webgunearen izena',
+ 'Installation_SetupWebSiteURL' => 'webgunearen URLa',
+ 'Installation_SetupWebsiteError' => 'Errorea gertatu da webgunea gehitzean',
+ 'Installation_SetupWebsiteSetupSuccess' => '%s webgunea ondo sortu da!',
+ 'Installation_GeneralSetup' => 'Konfigurazio orokorra',
+ 'Installation_GeneralSetupSuccess' => 'Konfigurazio orokorra ondo burutu da',
+ 'Installation_SuperUserLogin' => 'supererabiltzaile-izena',
+ 'Installation_Password' => 'pasahitza',
+ 'Installation_PasswordRepeat' => 'pasahitza (errepikatu)',
+ 'Installation_Email' => 'helbide elektronikoa',
+ 'Installation_SecurityNewsletter' => 'bidal iezadazu e-posta Piwik-en bertsio-berritze eta segurtasun-alerta nagusienekin',
+ 'Installation_CommunityNewsletter' => 'bidal iezadazu e-posta komunitateko eguneraketekin (plugin berriak, ezaugarri berriak, ...)',
+ 'Installation_PasswordDoNotMatch' => 'pasahitzak ez datoz bat',
+ 'Installation_SubmitGo' => 'Joan!',
+ 'Installation_Requirements' => 'Piwik-en beharrak',
+ 'Installation_Optional' => 'Aukerazkoa',
+ 'Installation_Legend' => 'Legenda',
+ 'Installation_Extension' => 'hedapena',
+ 'Installation_SystemCheck' => 'Sistemaren egiaztapena',
+ 'Installation_SystemCheckPhp' => 'PHP bertsioa',
+ 'Installation_SystemCheckExtensions' => 'Beharrezko bestelako hedapenak',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik-ek mysqli hedapena edo PDO eta pdo_mysql hedapenak behar ditu.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => "Linux zerbitzari batean ondorengo aukerekin konpila dezakezu php:: %s\nGehitu ondorengo lerroak zure php.ini fitxategian: %s",
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Argibide gehiago: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> eta <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'Windows zerbitzari batean ondorengo lerroak gehi ditzakezu zure php.ini fitxategian: %s',
+ 'Installation_SystemCheckSplHelp' => 'Standard PHP Library (SPL) lehenetsita gaituta duela konfiguratu eta birkonpilatu behar duzu PHP.',
+ 'Installation_SystemCheckZlibHelp' => '"zlib" gaituta duela konfiguratu eta birkonpilatu behar duzu PHP, --with-zlib aukerarekin.',
+ 'Installation_SystemCheckIconvHelp' => '"iconv" gaituta duela konfiguratu eta birkonpilatu behar duzu PHP, --with-iconv aukerarekin.',
+ 'Installation_SystemCheckDomHelp' => 'PHPren muinaren parte da DOM. Beharbada dom modulua instalatu behar duzu, adibidez php-5-dom.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => '"json" edo "xml" hedapenak gaituta dituela konfiguratu eta birkonpilatu behar duzu PHP.',
+ 'Installation_SystemCheckJsonSite' => 'Argibide gehiago: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Hirugarrenen plugin eta liburutegiek "xml" hedapena beharko dute agian.',
+ 'Installation_SystemCheckXmlSite' => 'Argibide gehiago: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckWriteDirs' => 'Idazteko baimena duten direktorioak',
+ 'Installation_SystemCheckWriteDirsHelp' => 'Errore hau konpontzeko zure Linux sisteman, saiatu ondorengo komandoa(k) exekutatzen',
+ 'Installation_SystemCheckMemoryLimit' => 'Memoriaren muga',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'Trafiko handiko webgune batean, artxibatzeko prozesuak onartutako memoria baino gehiago har lezake. Beharrezkoa bada, aldatu memory_limit direktiba zure php.ini fitxategian.',
+ 'Installation_SystemCheckOpenURL' => 'Ireki URLa',
+ 'Installation_SystemCheckOpenURLHelp' => 'Buletinen harpidetzek, eguneraketen jakinarazpenek eta klik bakarreko eguneraketek "curl" hedapena, allow_url_fopen=On edo fsockopen() gaituta egotea behar dute.',
+ 'Installation_SystemCheckGD' => 'GD &gt; 2.x (grafikak)',
+ 'Installation_SystemCheckGDHelp' => 'Grafika txikiek ez dute funtzionatuko.',
+ 'Installation_SystemCheckFunctions' => 'Beharrezko funtzioak',
+ 'Installation_SystemCheckTimeLimitHelp' => 'Trafiko handiko webgune batean, artxibatzeko prozesuak onartutako denbora baino gehiago har lezake. Beharrezkoa bada, aldatu max_execution_time direktiba zure php.ini fitxategian.',
+ 'Installation_SystemCheckMailHelp' => 'Erreakzioak eta galdutako pasahitzen mezuak ezingo dira bidali mail() gabe.',
+ 'Installation_SystemCheckError' => 'Errorea gertatu da - aurrera jarraitu aurretik konpondu behar da',
+ 'Installation_SystemCheckWarning' => 'Piwik ondo ibiliko da baina zenbait ezaugarri falta litezke',
+ 'Installation_SystemCheckProtocol' => 'Protokoloa',
+ 'Installation_SystemCheckProtocolHelp' => 'Atzeranzko proxy baten atzean bazaude, gehitu ondorengo lerroak config/config.ini.php fitxategiko [General] atalean:',
+ 'Installation_Tables' => 'Taulak sortzen',
+ 'Installation_TablesWithSameNamesFound' => 'Zure %s datu-baseko zenbait taulek %s Piwik sortzen saiatzen ari den taulen izen berak dituzte',
+ 'Installation_TablesFound' => 'Ondorengo taulak aurkitu dira datu-basean',
+ 'Installation_TablesWarningHelp' => 'Aukeratu dagoen datu-baseko taulak berrerabiltzea edo hautatu instalazio garbia dauden datuak datu-basetik ezabatzeko.',
+ 'Installation_TablesReuse' => 'Berrerabili dauden taulak',
+ 'Installation_TablesDelete' => 'Ezabatu atzemandako taulak',
+ 'Installation_TablesDeletedSuccess' => 'Aurretik zeuden Piwik taulak ondo ezabatu dira',
+ 'Installation_TablesCreatedSuccess' => 'Taulak ondo sortu dira!',
+ 'Installation_DatabaseCreatedSuccess' => '%s datu-basea ondo sortu da!',
+ 'Installation_GoBackAndDefinePrefix' => 'Zoaz atzera eta definitu aurrizki bat Piwik-en taulentzat',
+ 'Installation_ConfirmDeleteExistingTables' => 'Ziur zaude ondorengo taulak: %s datu-basetik ezabatu nahi dituzula? OHARRA: TAULA HAUETAKO DATUAK EZINGO DIRA BERRESKURATU!',
+ 'Installation_Welcome' => 'Ongi etorri!',
+ 'Installation_WelcomeHelp' => '<p>Piwik kode irekiko web analitiken softwarea da, zure bisitariengandik nahi duzun informazioa erraz eskuratzeko.</p><p>Prozesu hau %s urrats errazetan dago banatuta eta bost minutu inguru hartuko ditu.</p>',
+ 'Installation_ErrorInvalidState' => 'Errorea: badirudi instalazio prozesuko urrats bat saltatu nahi duzula edo zure cookie-ak desgaituta daudela edo Piwik konfigurazio-fitxategia dagoeneko sortuta dagoela. %sZiurtatu zure cookie-ak gaituta daudela%s eta zoaz atzera %s instalazioaren lehenengo orrira %s.',
+ 'Provider_WidgetProviders' => 'Hornitzaileak',
+ 'Provider_ColumnProvider' => 'Hornitzailea',
+ 'Provider_SubmenuLocationsProvider' => 'Kokalekuak eta hornitzailea',
+ 'Goals_ColumnConversions' => 'Bihurketa',
+ 'Goals_ColumnConversionRate' => 'Bihurketa-tasa',
+ 'Goals_ColumnRevenue' => 'Etekina',
+ 'DBStats_DatabaseUsage' => 'Datu-basearen erabilera',
+ 'DBStats_MainDescription' => 'Zure web analitiken datu guztiak MySQL datu-basean biltegiratzen ari da Piwik. Une honetan Piwik-en taulek tamaina hau hartzen dute: %s.',
+ 'DBStats_LearnMore' => 'Piwik-ek datuak nola prozesatzen dituen eta Piwik trafiko ertain eta handikjo webguneetarako nola moldatu jakiteko, emaiozu begirada dokumentazioari: %s.',
+ 'DBStats_Table' => 'Taula',
+ 'DBStats_RowCount' => 'Errenkada kopurua',
+ 'DBStats_DataSize' => 'Datuen tamaina',
+ 'DBStats_IndexSize' => 'Indizearen tamaina',
+ 'DBStats_TotalSize' => 'Tamaina osoa',
+ 'TranslationsAdmin_MenuTranslations' => 'Itzulpenak',
+ 'TranslationsAdmin_MenuLanguages' => 'Hizkuntzak',
+ 'TranslationsAdmin_Plugin' => 'Plugina',
+ 'TranslationsAdmin_Definition' => 'Definizioa',
+ 'TranslationsAdmin_DefaultString' => 'Lehenetsitako katea (Ingelesa)',
+ 'TranslationsAdmin_TranslationString' => 'Itzulitako katea (uneko hizkuntza: %s)',
+ 'TranslationsAdmin_Translations' => 'Itzulpenak',
+ 'TranslationsAdmin_FixPermissions' => 'Mesedez konpondu fitxategi-sistemaren baimenak',
+ 'TranslationsAdmin_AvailableLanguages' => 'Eskura dauden hizkuntzak',
+ 'TranslationsAdmin_AddLanguage' => 'Gehitu hizkuntza',
+ 'TranslationsAdmin_LanguageCode' => 'Hizkuntza-kodea',
+ 'TranslationsAdmin_Export' => 'Esportatu hizkuntza',
+ 'TranslationsAdmin_Import' => 'Inportatu hizkuntza',
+ 'SecurityInfo_Security' => 'Segurtasuna',
+ 'SecurityInfo_SecurityInformation' => 'PHP segurtasun-informazioa',
+ 'SecurityInfo_PluginDescription' => 'PHP Security Consortium-en PhpSecInfo-n oinarrituta, plugin honen zure PHP ingurunearen segurtasun-informazioa ematen du eta hobekuntzak egiteko gomendioak ematen ditu. Hainbat geruzetan oinarritutako hurbilpena darabilen segurtasun tresna da. Ez ditu garapen-praktika seguruak edo kodearen/aplikazioaren auditoriak ordezkatzen.',
+ 'SecurityInfo_Test' => 'Probatu',
+ 'SecurityInfo_Result' => 'Emaitza',
+ 'Live_VisitorLog' => 'Bisitariaren loga',
+ 'Live_Date' => 'Data',
+ 'Live_Time' => 'Ordua',
+ 'Live_Referrer_URL' => 'URL erreferentea',
+);
diff --git a/lang/fi.php b/lang/fi.php
index 489f8a428c..a28fc3a435 100644
--- a/lang/fi.php
+++ b/lang/fi.php
@@ -1,735 +1,774 @@
-<?php
+<?php
$translations = array(
- 'General_Locale' => 'fi_FI.UTF-8',
- 'General_TranslatorName' => 'Olli Jarva (http://olli.jarva.fi/)',
- 'General_TranslatorEmail' => 'olli@jarva.fi',
- 'General_EnglishLanguageName' => 'Finnish',
- 'General_OriginalLanguageName' => 'Suomi',
- 'General_HelloUser' => 'Hei, %s!',
- 'General_OpenSourceWebAnalytics' => 'Vapaa verkkoanalysaattori',
- 'General_YourDashboard' => 'Työpöytä',
- 'General_API' => 'API',
- 'General_Widgets' => 'Vimpaimet',
- 'General_Settings' => 'Asetukset',
- 'General_GiveUsYourFeedback' => 'Anna palautetta!',
- 'General_Unknown' => 'Tuntematon',
- 'General_Required' => '%s vaaditaan',
- 'General_Error' => 'Virhe',
- 'General_Warning' => 'Varoitus',
- 'General_BackToHomepage' => 'Takaisin Piwikin etusivulle',
- 'General_Yes' => 'Kyllä',
- 'General_No' => 'Ei',
- 'General_Delete' => 'Poista',
- 'General_Edit' => 'Muokkaa',
- 'General_Ok' => 'Ok',
- 'General_Close' => 'Sulje',
- 'General_Logout' => 'Kirjaudu ulos',
- 'General_Done' => 'Valmis',
- 'General_LoadingData' => 'Ladataan tietoja...',
- 'General_Loading' => 'Ladataan...',
- 'General_ErrorRequest' => 'Oops&hellip; virhe pyynnön käsittelyssä, yritä uudelleen.',
- 'General_Next' => 'Seuraava',
- 'General_Previous' => 'Edellinen',
- 'General_Search' => 'Hae',
- 'General_Others' => 'Muut',
- 'General_Table' => 'Taulukko',
- 'General_Piechart' => 'Ympyräkaavio',
- 'General_TagCloud' => 'Avainsanapilvi',
- 'General_VBarGraph' => 'Pystygraafi',
- 'General_Export' => 'Vie',
- 'General_ExportAsImage' => 'Vie kuvaksi',
- 'General_SaveImageOnYourComputer' => 'Tallenna kuva koneelle painamalla kuvaa oikealla napilla ja valitse "Tallenna kuva nimellä..."',
- 'General_Refresh' => 'Päivitä sivu',
- 'General_Visitors' => 'Kävijät',
- 'General_ColumnNbUniqVisitors' => 'Yksilölliset kävijät',
- 'General_ColumnNbVisits' => 'Käynnit',
- 'General_ColumnNbActions' => 'Toiminnot',
- 'General_ColumnMaxActions' => 'Toimintoja enintään / käynti',
- 'General_ColumnSumVisitLength' => 'Kaikkien kävijöiden aika yhteensä (sekunteja)',
- 'General_ColumnLabel' => 'Etiketti',
- 'General_ColumnActionsPerVisit' => 'Toimintoja / käynti',
- 'General_ColumnAvgTimeOnSite' => 'Keskimääräinen aika sivulla',
- 'General_ColumnBounceRate' => 'Lähtemissuhde',
- 'General_ColumnPageviews' => 'Sivukatseluita',
- 'General_ColumnUniquePageviews' => 'Yksilöllisiä sivukatseluita',
- 'General_ColumnValuePerVisit' => 'Käynnin arvo',
- 'General_ColumnVisitsWithConversions' => 'Käyntejä, joissa keskusteluja',
- 'General_Save' => 'Tallenna',
- 'General_Website' => 'Verkkosivu',
- 'General_NoDataForGraph' => 'Ei tietoja tähän kuvaajaan',
- 'General_NoDataForTagCloud' => 'Ei tietoja tähän avainsanapilveen',
- 'General_DisplayNormalTable' => 'Näytä normaali taulukko',
- 'General_DisplayMoreData' => 'Näytä lisää tietoja',
- 'General_PiwikIsACollaborativeProjectYouCanContribute' => "%s Piwik %s on yhteistyöprojekti. %s Jos pidät Piwikistä, voit auttaa! Katso %s miten voit auttaa Piwikiä%s ",
- 'General_YouAreCurrentlyViewingDemoOfPiwik' => "Katsot demoversiota %s; %slataa%s kokoversio! Katso %s",
- 'General_PiwikXIsAvailablePleaseUpdateNow' => "Piwik %s on saatavilla. %s Päivitä nyt!%s (katso %s muutokset%s).",
- 'General_BackToPiwik' => "Takaisin Piwikiin",
- 'General_ShortMonth_1' => "Tam",
- 'General_ShortMonth_2' => "Hel",
- 'General_ShortMonth_3' => "Maa",
- 'General_ShortMonth_4' => "Huh",
- 'General_ShortMonth_5' => "Tou",
- 'General_ShortMonth_6' => "Kes",
- 'General_ShortMonth_7' => "Hei",
- 'General_ShortMonth_8' => "Elo",
- 'General_ShortMonth_9' => "Syy",
- 'General_ShortMonth_10' => "Lok",
- 'General_ShortMonth_11' => "Mar",
- 'General_ShortMonth_12' => "Jou",
- 'General_LongMonth_1' => "Tammikuu",
- 'General_LongMonth_2' => "Helmikuu",
- 'General_LongMonth_3' => "Maaliskuu",
- 'General_LongMonth_4' => "Huhtikuu",
- 'General_LongMonth_5' => "Toukokuu",
- 'General_LongMonth_6' => "Kesäkuu",
- 'General_LongMonth_7' => "Heinäkuu",
- 'General_LongMonth_8' => "Elokuu",
- 'General_LongMonth_9' => "Syyskuu",
- 'General_LongMonth_10' => "Lokakuu",
- 'General_LongMonth_11' => "Marraskuu",
- 'General_LongMonth_12' => "Joulukuu",
- 'General_ShortDay_1' => "Ma",
- 'General_ShortDay_2' => "Ti",
- 'General_ShortDay_3' => "Ke",
- 'General_ShortDay_4' => "To",
- 'General_ShortDay_5' => "Pe",
- 'General_ShortDay_6' => "La",
- 'General_ShortDay_7' => "Su",
- 'General_LongDay_1' => "Maanantai",
- 'General_LongDay_2' => "Tiistai",
- 'General_LongDay_3' => "Keskivikko",
- 'General_LongDay_4' => "Torstai",
- 'General_LongDay_5' => "Perjantai",
- 'General_LongDay_6' => "Lauantai",
- 'General_LongDay_7' => "Sunnuntai",
- 'CorePluginsAdmin_Plugins' => 'Lisäosat',
- 'CorePluginsAdmin_PluginsManagement' => 'Lisäosien hallinta',
- 'CorePluginsAdmin_MainDescription' => 'Lisäosilla voi laajentaa ja parantaa Piwikin toiminnallisuutta. Kun lisäosa on asennettu, voit aktivoida ja poistaa käytöstä sen täällä.',
- 'CorePluginsAdmin_Plugin' => 'Lisäosa',
- 'CorePluginsAdmin_Version' => 'Versio',
- 'CorePluginsAdmin_Description' => 'Kuvaus',
- 'CorePluginsAdmin_Status' => 'Tila',
- 'CorePluginsAdmin_Action' => 'Toiminto',
- 'CorePluginsAdmin_PluginHomepage' => 'Lisäosan kotisivu',
- 'CorePluginsAdmin_Activated' => 'Aktivoitu',
- 'CorePluginsAdmin_Active' => 'Käytössä',
- 'CorePluginsAdmin_Inactive' => 'Ei käytössä',
- 'CorePluginsAdmin_ActivatedHelp' => 'Lisäosaa ei voi poistaa käytöstä',
- 'CorePluginsAdmin_Deactivate' => 'Poistettu käytöstä',
- 'CorePluginsAdmin_Activate' => 'Aktivoi',
- 'CorePluginsAdmin_MenuPlugins' => 'Lisäosat',
- 'API_QuickDocumentation' => '<h2>API quick documentation</h2><p>If you don\'t have data for today you can first <a href=\'misc/generateVisits.php\' target=_blank>generate some data</a> using the Visits Generator script.</p><p>You can try the different formats available for every method. It is very easy to extract any data you want from piwik!</p><p><b>For more information have a look at the <a href=\'http://dev.piwik.org/trac/wiki/API\'>official API Documentation</a> or the <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API Reference</a>.</b></P><h2>User authentication</h2><p>If you want to <b>request the data in your scripts, in a crontab, etc. </b> you need to add the parameter <code><u>&token_auth=%s</u></code> to the API calls URLs that require authentication.</p><p>This token_auth is as secret as your login and password, <b>do not share it!</p>',
- 'API_LoadedAPIs' => 'Loaded successfully %s APIs',
- 'CoreHome_NoPrivileges' => 'You are logged in as \'%s\' but it seems you don\'t have any permission set in Piwik.<br />Ask your Piwik administrator to give you \'view\' access to a website.',
- 'CoreHome_JavascriptDisabled' => 'JavaScript must be enabled in order for you to use Piwik in standard view.<br />However, it seems JavaScript is either disabled or not supported by your browser.<br />To use standard view, enable JavaScript by changing your browser options, then %1stry again%2s.<br />',
- 'CoreHome_TableNoData' => 'No data for this table.',
- 'CoreHome_CategoryNoData' => 'No data in this category. Try to "Include all population".',
- 'CoreHome_ShowJSCode' => 'Show the javascript code to insert',
- 'CoreHome_IncludeAllPopulation_js' => 'Include all population',
- 'CoreHome_ExcludeLowPopulation_js' => 'Exclude low population',
- 'CoreHome_PageOf_js' => '%s of %s',
- 'CoreHome_Loading_js' => 'Loading...',
- 'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
- 'CoreHome_PeriodDay' => 'Päivä',
- 'CoreHome_PeriodWeek' => 'Viikko',
- 'CoreHome_PeriodMonth' => 'Kuukausi',
- 'CoreHome_PeriodYear' => 'Vuosi',
- 'CoreHome_PeriodDays' => 'päivät',
- 'CoreHome_PeriodWeeks' => 'viikot',
- 'CoreHome_PeriodMonths' => 'kuukaudet',
- 'CoreHome_PeriodYears' => 'vuodet',
- 'CoreHome_DaySu_js' => 'Su',
- 'CoreHome_DayMo_js' => 'Ma',
- 'CoreHome_DayTu_js' => 'Ti',
- 'CoreHome_DayWe_js' => 'Ke',
- 'CoreHome_DayTh_js' => 'To',
- 'CoreHome_DayFr_js' => 'Pe',
- 'CoreHome_DaySa_js' => 'La',
- 'CoreHome_MonthJanuary_js' => 'Tammikuu',
- 'CoreHome_MonthFebruary_js' => 'Helmikuu',
- 'CoreHome_MonthMarch_js' => 'Maaliskuu',
- 'CoreHome_MonthApril_js' => 'Huhtikuu',
- 'CoreHome_MonthMay_js' => 'Toukokuu',
- 'CoreHome_MonthJune_js' => 'Kesäkuu',
- 'CoreHome_MonthJuly_js' => 'Heinäkuu',
- 'CoreHome_MonthAugust_js' => 'Elokuu',
- 'CoreHome_MonthSeptember_js' => 'Syyskuu',
- 'CoreHome_MonthOctober_js' => 'Lokakuu',
- 'CoreHome_MonthNovember_js' => 'Marraskuu',
- 'CoreHome_MonthDecember_js' => 'Joulukuu',
- 'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; Päivitys',
- 'CoreUpdater_DatabaseUpgradeRequired' => 'Tietokannan päivitys tarvitaan',
- 'CoreUpdater_YourDatabaseIsOutOfDate' => 'Piwikin tietokanta on vanhentunut ja se tulee päivittää ennen jatkamista.',
- 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwikin tietokanta päivitetään versiosta %s versioon %s.',
- 'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Seuraavat lisäosat päivitetään: %s.',
- 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Tietokannan päivitys vie aikaa, ole kärsivällinen.',
- 'CoreUpdater_UpgradePiwik' => 'Päivitä Piwik',
- 'CoreUpdater_HelpMessageContent' => 'Tarkista %s Piwikin FAQ:sta%s yleisimmät virheet. %s Kysy järjestelmän ylläpitäjältä - he voivat auttaa virheissä, jotka johtuvat luultavasti palvelimesta tai tietokannasta.',
- 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Kriittinen virhe päivitysprosessissa:',
- 'CoreUpdater_HelpMessageIntroductionWhenError' => 'Alla on ytimen virheviesti: Sen pitäisi auttaa virheen etsimisessä, mutta jos tarvitset lisää apua:',
- 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Päivitys valmistui onnistuneesti, mutta prosessin aikana tapahtui virheitä. Ole hyvä ja lue alla olevat kuvaukset. Lisää apua:',
- 'CoreUpdater_UpgradeComplete' => 'Päivitys valmis!',
- 'CoreUpdater_WarningMessages' => 'Varoitusviestit:',
- 'CoreUpdater_ErrorDuringPluginsUpdates' => 'Virhe lisäosien päivityksessä:',
- 'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Seuraavat lisäosat on automaattisesti poistettu käytöstä: %s',
- 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik on päivitetty onnistuneesti!',
- 'CoreUpdater_ContinueToPiwik' => 'Jatka Piwikiin',
- 'CoreUpdater_UpdateAutomatically' => "Päivitä automaattisesti",
- 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => "Piwikistä on uusi versio",
- 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => "Voit päivittää versioon %s automaattisesti tai ladata paketin ja asentaa sen manuaalisesti:",
- 'CoreUpdater_DownloadX' => "Lataa %s",
- 'CoreUpdater_UpdateHasBeenCancelledExplanation' => "Piwikin yhden klikkauksen päivitys on peruutettu. Jos et voi korjata alla oelvaa virhettä, on suositeltavaa päivittää Piwik manuaalisesti. %s Ole hyvä ja tarkista %sPäivitysdokumentaatio%s",
- 'CoreUpdate_DownloadingUpdateFromX' => "Ladataan päivitystä osoitteesta %s",
- 'CoreUpdate_UnpackingTheUpdate' => "Puretaan päivitystä",
- 'CoreUpdater_VerifyingUnpackedFiles' => "Tarkistetaan purettuja tiedostoja",
- 'CoreUpdater_CreatingBackupOfConfigurationFile' => "Luodaan varmuuskopiota asetustiedostosta: %s",
- 'CoreUpdater_InstallingTheLatestVersion' => "Asennetaan uusinta versiota",
- 'CoreUpdater_PiwikUpdatedSuccessfully' => "Piwik päivitettiin onnistuneesti!",
- 'Actions_Actions' => 'Toiminnot',
- 'Actions_SubmenuPages' => 'Sivut',
- 'Actions_SubmenuOutlinks' => 'Lähtevät linkit',
- 'Actions_SubmenuDownloads' => 'Lataukset',
- 'Actions_ColumnClicks' => 'Klikkaukset',
- 'Actions_ColumnUniqueClicks' => 'Uniikit klikkaukset',
- 'Actions_ColumnDownloads' => 'Lataukset',
- 'Actions_ColumnUniqueDownloads' => 'Uniikit lataukset',
- 'Actions_ColumnPageName' => 'Sivun nimi',
- 'Actions_ColumnClickedURL' => 'Klikattu URL',
- 'Actions_ColumnDownloadURL' => 'Ladattu URL',
- 'Dashboard_Dashboard' => 'Työpöytä',
- 'Dashboard_AddWidget' => 'Lisää vimpain...',
- 'Dashboard_DeleteWidgetConfirm' => 'Haluatko varmasti poistaa vimpaimen työpöydältä?',
- 'Dashboard_SelectWidget' => 'Valitse työpöydälle lisättävä vimpain',
- 'Dashboard_AddPreviewedWidget_js' => 'Lisää esikatseltu vimpain työpöydälle',
- 'Dashboard_WidgetPreview_js' => 'Vimpaimen esikatselu',
- 'Dashboard_Close_js' => 'Sulje',
- 'Dashboard_TitleWidgetInDashboard_js' => 'Vimpain on jo työpöydällä',
- 'Dashboard_TitleClickToAdd_js' => 'Klikkaa lisätäksesi työpöydälle',
- 'Dashboard_LoadingWidget_js' => 'Ladataan vimpainta, odota...',
- 'Dashboard_WidgetNotFound_js' => 'Vimpainta ei löydy',
- 'Referers_Referers' => 'Viittaajat',
- 'Referers_SearchEngines' => 'Hakukoneet',
- 'Referers_Keywords' => 'Hakusanat',
- 'Referers_DirectEntry' => 'Suoraan',
- 'Referers_Websites' => 'Verkkosivut',
- 'Referers_Campaigns' => 'Kampanjat',
- 'Referers_MetricsFromRefererTypeGraphLegend' => '%1s (%2s)',
- 'Referers_Evolution' => 'Muutos aikavälillä',
- 'Referers_Type' => 'Viittaajan tyyppi',
- 'Referers_ColumnRefererType' => 'Tyyppi',
- 'Referers_ColumnSearchEngine' => 'Hakukone',
- 'Referers_ColumnWebsite' => 'Verkkosivu',
- 'Referers_ColumnWebsitePage' => 'Verkkosivu',
- 'Referers_ColumnKeyword' => 'Hakusana',
- 'Referers_ColumnCampaign' => 'Kampanja',
- 'Referers_DetailsByRefererType' => 'Tiedot viittajan tyypin mukaan',
- 'Referers_TypeDirectEntries' => '%s suoraa saapumista',
- 'Referers_TypeSearchEngines' => '%s hakukoneista',
- 'Referers_TypeWebsites' => '%s verkkosivuilta',
- 'Referers_TypeCampaigns' => '%s kampanjoista',
- 'Referers_Distinct' => 'Yksilöllisiä viittaajia viittaustyypin mukaan',
- 'Referers_DistinctSearchEngines' => 'yksilöllistä hakukonetta',
- 'Referers_DistinctKeywords' => 'yksilöllistä hakusanaa',
- 'Referers_DistinctCampaigns' => 'yksilöllistä kampanjaa',
- 'Referers_DistinctWebsites' => 'yksilöllistä verkkosivua',
- 'Referers_UsingNDistinctUrls' => ' (käyttäen %2s yksilöllistä osoitetta)',
- 'Referers_SubmenuEvolution' => 'Kehitys',
- 'Referers_SubmenuSearchEngines' => 'Search engines & keywords',
- 'Referers_SubmenuWebsites' => 'Verkkosivut',
- 'Referers_SubmenuCampaigns' => 'Kampanjat',
- 'Referers_WidgetKeywords' => 'Lista hakusanoista',
- 'Referers_WidgetCampaigns' => 'Lista kampanjoista',
- 'Referers_WidgetExternalWebsites' => 'Lista ulkoisista verkkosivuista',
- 'Referers_WidgetSearchEngines' => 'Parhaat hakukoneet',
- 'Referers_WidgetOverview' => 'Yleiskatsaus',
- 'UserSettings_VisitorSettings' => 'Kävijöiden asetukset',
- 'UserSettings_BrowserFamilies' => 'Selainluokat',
- 'UserSettings_Browsers' => 'Selaimet',
- 'UserSettings_Plugins' => 'Lisäosat',
- 'UserSettings_Configurations' => 'Asetukset',
- 'UserSettings_OperatinsSystems' => 'Käyttöjärjestelmä',
- 'UserSettings_Resolutions' => 'Resoluutio',
- 'UserSettings_WideScreen' => 'Laajakulma',
- 'UserSettings_ColumnBrowserFamily' => 'Selainperhe',
- 'UserSettings_ColumnBrowser' => 'Selain',
- 'UserSettings_ColumnPlugin' => 'Lisäosa',
- 'UserSettings_ColumnConfiguration' => 'Asetukset',
- 'UserSettings_ColumnOperatinsSystem' => 'Käyttöjärjestelmä',
- 'UserSettings_ColumnResolution' => 'Resoluutio',
- 'UserSettings_ColumnTypeOfScreen' => 'Näytön tyyppi',
- 'UserSettings_WidgetResolutions' => 'Näytön resoluutio',
- 'UserSettings_WidgetBrowsers' => 'Kävijöiden selaimet',
- 'UserSettings_WidgetPlugins' => 'Lista lisäosista',
- 'UserSettings_WidgetWidescreen' => 'Normaali / laajakuva',
- 'UserSettings_WidgetBrowserFamilies' => 'Selaimet perheittäin',
- 'UserSettings_WidgetOperatingSystems' => 'Käyttöjärjestelmät',
- 'UserSettings_WidgetGlobalVisitors' => 'Kaikkien kävijöiden asetukset',
- 'UserSettings_SubmenuSettings' => 'Asetukset',
- 'UserCountry_Country' => 'Maa',
- 'UserCountry_Continent' => 'Maanosa',
- 'UserCountry_DistinctCountries' => '%s uniikkia maata',
- 'UserCountry_SubmenuLocations' => 'Sijainnit',
- 'UserCountry_WidgetContinents' => 'Kävijöiden maanosat',
- 'UserCountry_WidgetCountries' => 'Kävijöiden maat',
- 'UserCountry_country_ac' => 'Ascension Islands', #todo
- 'UserCountry_country_ad' => 'Andorra',
- 'UserCountry_country_ae' => 'United Arab Emirates',
- 'UserCountry_country_af' => 'Afghanistan',
- 'UserCountry_country_ag' => 'Antigua and Barbuda',
- 'UserCountry_country_ai' => 'Anguilla',
- 'UserCountry_country_al' => 'Albania',
- 'UserCountry_country_am' => 'Armenia',
- 'UserCountry_country_an' => 'Netherlands Antilles',
- 'UserCountry_country_ao' => 'Angola',
- 'UserCountry_country_aq' => 'Antarctica',
- 'UserCountry_country_ar' => 'Argentina',
- 'UserCountry_country_as' => 'American Samoa',
- 'UserCountry_country_at' => 'Austria',
- 'UserCountry_country_au' => 'Australia',
- 'UserCountry_country_aw' => 'Aruba',
- 'UserCountry_country_ax' => 'Aland Islands',
- 'UserCountry_country_az' => 'Azerbaijan',
- 'UserCountry_country_ba' => 'Bosnia and Herzegovina',
- 'UserCountry_country_bb' => 'Barbados',
- 'UserCountry_country_bd' => 'Bangladesh',
- 'UserCountry_country_be' => 'Belgium',
- 'UserCountry_country_bf' => 'Burkina Faso',
- 'UserCountry_country_bg' => 'Bulgaria',
- 'UserCountry_country_bh' => 'Bahrain',
- 'UserCountry_country_bi' => 'Burundi',
- 'UserCountry_country_bj' => 'Benin',
- 'UserCountry_country_bl' => 'Saint Barthelemy',
- 'UserCountry_country_bm' => 'Bermuda',
- 'UserCountry_country_bn' => 'Bruneo',
- 'UserCountry_country_bo' => 'Bolivia',
- 'UserCountry_country_br' => 'Brazil',
- 'UserCountry_country_bs' => 'Bahamas',
- 'UserCountry_country_bt' => 'Bhutan',
- 'UserCountry_country_bu' => 'Burma',
- 'UserCountry_country_bv' => 'Bouvet Island',
- 'UserCountry_country_bw' => 'Botswana',
- 'UserCountry_country_by' => 'Belarus',
- 'UserCountry_country_bz' => 'Belize',
- 'UserCountry_country_ca' => 'Canada',
- 'UserCountry_country_cc' => 'Cocos (Keeling) Islands',
- 'UserCountry_country_cd' => 'Congo, The Democratic Republic of the',
- 'UserCountry_country_cf' => 'Central African Republic',
- 'UserCountry_country_cg' => 'Congo',
- 'UserCountry_country_ch' => 'Switzerland',
- 'UserCountry_country_ci' => 'Cote D\'Ivoire',
- 'UserCountry_country_ck' => 'Cook Islands',
- 'UserCountry_country_cl' => 'Chile',
- 'UserCountry_country_cm' => 'Cameroon',
- 'UserCountry_country_cn' => 'China',
- 'UserCountry_country_co' => 'Colombia',
- 'UserCountry_country_cp' => 'Clipperton Island',
- 'UserCountry_country_cr' => 'Costa Rica',
- 'UserCountry_country_cs' => 'Serbia Montenegro',
- 'UserCountry_country_cu' => 'Cuba',
- 'UserCountry_country_cv' => 'Cape Verde',
- 'UserCountry_country_cx' => 'Christmas Island',
- 'UserCountry_country_cy' => 'Cyprus',
- 'UserCountry_country_cz' => 'Czech Republic',
- 'UserCountry_country_de' => 'Germany',
- 'UserCountry_country_dg' => 'Diego Garcia',
- 'UserCountry_country_dj' => 'Djibouti',
- 'UserCountry_country_dk' => 'Denmark',
- 'UserCountry_country_dm' => 'Dominica',
- 'UserCountry_country_do' => 'Dominican Republic',
- 'UserCountry_country_dz' => 'Algeria',
- 'UserCountry_country_ea' => 'Ceuta, Melilla',
- 'UserCountry_country_ec' => 'Ecuador',
- 'UserCountry_country_ee' => 'Estonia',
- 'UserCountry_country_eg' => 'Egypt',
- 'UserCountry_country_eh' => 'Western Sahara',
- 'UserCountry_country_er' => 'Eritrea',
- 'UserCountry_country_es' => 'Spain',
- 'UserCountry_country_et' => 'Ethiopia',
- 'UserCountry_country_eu' => 'European Union',
- 'UserCountry_country_fi' => 'Finland',
- 'UserCountry_country_fj' => 'Fiji',
- 'UserCountry_country_fk' => 'Falkland Islands (Malvinas)',
- 'UserCountry_country_fm' => 'Micronesia, Federated States of',
- 'UserCountry_country_fo' => 'Faroe Islands',
- 'UserCountry_country_fr' => 'France',
- 'UserCountry_country_fx' => 'France, Metropolitan',
- 'UserCountry_country_ga' => 'Gabon',
- 'UserCountry_country_gb' => 'Great Britain',
- 'UserCountry_country_gd' => 'Grenada',
- 'UserCountry_country_ge' => 'Georgia',
- 'UserCountry_country_gf' => 'French Guyana',
- 'UserCountry_country_gg' => 'Guernsey',
- 'UserCountry_country_gh' => 'Ghana',
- 'UserCountry_country_gi' => 'Gibraltar',
- 'UserCountry_country_gl' => 'Greenland',
- 'UserCountry_country_gm' => 'Gambia',
- 'UserCountry_country_gn' => 'Guinea',
- 'UserCountry_country_gp' => 'Guadeloupe',
- 'UserCountry_country_gq' => 'Equatorial Guinea',
- 'UserCountry_country_gr' => 'Greece',
- 'UserCountry_country_gs' => 'South Georgia and the South Sandwich Islands',
- 'UserCountry_country_gt' => 'Guatemala',
- 'UserCountry_country_gu' => 'Guam',
- 'UserCountry_country_gw' => 'Guinea-Bissau',
- 'UserCountry_country_gy' => 'Guyana',
- 'UserCountry_country_hk' => 'Hong Kong',
- 'UserCountry_country_hm' => 'Heard Island and McDonald Islands',
- 'UserCountry_country_hn' => 'Honduras',
- 'UserCountry_country_hr' => 'Croatia',
- 'UserCountry_country_ht' => 'Haiti',
- 'UserCountry_country_hu' => 'Hungary',
- 'UserCountry_country_ic' => 'Canary Islands',
- 'UserCountry_country_id' => 'Indonesia',
- 'UserCountry_country_ie' => 'Ireland',
- 'UserCountry_country_il' => 'Israel',
- 'UserCountry_country_im' => 'Man Island',
- 'UserCountry_country_in' => 'India',
- 'UserCountry_country_io' => 'British Indian Ocean Territory',
- 'UserCountry_country_iq' => 'Iraq',
- 'UserCountry_country_ir' => 'Iran, Islamic Republic of',
- 'UserCountry_country_is' => 'Iceland',
- 'UserCountry_country_it' => 'Italy',
- 'UserCountry_country_je' => 'Jersey',
- 'UserCountry_country_jm' => 'Jamaica',
- 'UserCountry_country_jo' => 'Jordan',
- 'UserCountry_country_jp' => 'Japan',
- 'UserCountry_country_ke' => 'Kenya',
- 'UserCountry_country_kg' => 'Kyrgyzstan',
- 'UserCountry_country_kh' => 'Cambodia',
- 'UserCountry_country_ki' => 'Kiribati',
- 'UserCountry_country_km' => 'Comoros',
- 'UserCountry_country_kn' => 'Saint Kitts and Nevis',
- 'UserCountry_country_kp' => 'Korea, Democratic People\'s Republic of',
- 'UserCountry_country_kr' => 'Korea, Republic of',
- 'UserCountry_country_kw' => 'Kuwait',
- 'UserCountry_country_ky' => 'Cayman Islands',
- 'UserCountry_country_kz' => 'Kazakhstan',
- 'UserCountry_country_la' => 'Laos',
- 'UserCountry_country_lb' => 'Lebanon',
- 'UserCountry_country_lc' => 'Saint Lucia',
- 'UserCountry_country_li' => 'Liechtenstein',
- 'UserCountry_country_lk' => 'Sri Lanka',
- 'UserCountry_country_lr' => 'Liberia',
- 'UserCountry_country_ls' => 'Lesotho',
- 'UserCountry_country_lt' => 'Lithuania',
- 'UserCountry_country_lu' => 'Luxembourg',
- 'UserCountry_country_lv' => 'Latvia',
- 'UserCountry_country_ly' => 'Libya',
- 'UserCountry_country_ma' => 'Morocco',
- 'UserCountry_country_mc' => 'Monaco',
- 'UserCountry_country_md' => 'Moldova, Republic of',
- 'UserCountry_country_me' => 'Montenegro',
- 'UserCountry_country_mf' => 'Saint Martin',
- 'UserCountry_country_mg' => 'Madagascar',
- 'UserCountry_country_mh' => 'Marshall Islands',
- 'UserCountry_country_mk' => 'Macedonia',
- 'UserCountry_country_ml' => 'Mali',
- 'UserCountry_country_mm' => 'Myanmar',
- 'UserCountry_country_mn' => 'Mongolia',
- 'UserCountry_country_mo' => 'Macau',
- 'UserCountry_country_mp' => 'Northern Mariana Islands',
- 'UserCountry_country_mq' => 'Martinique',
- 'UserCountry_country_mr' => 'Mauritania',
- 'UserCountry_country_ms' => 'Montserrat',
- 'UserCountry_country_mt' => 'Malta',
- 'UserCountry_country_mu' => 'Mauritius',
- 'UserCountry_country_mv' => 'Maldives',
- 'UserCountry_country_mw' => 'Malawi',
- 'UserCountry_country_mx' => 'Mexico',
- 'UserCountry_country_my' => 'Malaysia',
- 'UserCountry_country_mz' => 'Mozambique',
- 'UserCountry_country_na' => 'Namibia',
- 'UserCountry_country_nc' => 'New Caledonia',
- 'UserCountry_country_ne' => 'Niger',
- 'UserCountry_country_nf' => 'Norfolk Island',
- 'UserCountry_country_ng' => 'Nigeria',
- 'UserCountry_country_ni' => 'Nicaragua',
- 'UserCountry_country_nl' => 'Netherlands',
- 'UserCountry_country_no' => 'Norway',
- 'UserCountry_country_np' => 'Nepal',
- 'UserCountry_country_nr' => 'Nauru',
- 'UserCountry_country_nt' => 'Neutral Zone',
- 'UserCountry_country_nu' => 'Niue',
- 'UserCountry_country_nz' => 'New Zealand',
- 'UserCountry_country_om' => 'Oman',
- 'UserCountry_country_pa' => 'Panama',
- 'UserCountry_country_pe' => 'Peru',
- 'UserCountry_country_pf' => 'French Polynesia',
- 'UserCountry_country_pg' => 'Papua New Guinea',
- 'UserCountry_country_ph' => 'Philippines',
- 'UserCountry_country_pk' => 'Pakistan',
- 'UserCountry_country_pl' => 'Poland',
- 'UserCountry_country_pm' => 'Saint Pierre and Miquelon',
- 'UserCountry_country_pn' => 'Pitcairn',
- 'UserCountry_country_pr' => 'Puerto Rico',
- 'UserCountry_country_ps' => 'Palestinian Territory',
- 'UserCountry_country_pt' => 'Portugal',
- 'UserCountry_country_pw' => 'Palau',
- 'UserCountry_country_py' => 'Paraguay',
- 'UserCountry_country_qa' => 'Qatar',
- 'UserCountry_country_re' => 'Reunion Island',
- 'UserCountry_country_ro' => 'Romania',
- 'UserCountry_country_ru' => 'Russia',
- 'UserCountry_country_rs' => 'Serbia',
- 'UserCountry_country_rw' => 'Rwanda',
- 'UserCountry_country_sa' => 'Saudi Arabia',
- 'UserCountry_country_sb' => 'Solomon Islands',
- 'UserCountry_country_sc' => 'Seychelles',
- 'UserCountry_country_sd' => 'Sudan',
- 'UserCountry_country_se' => 'Sweden',
- 'UserCountry_country_sf' => 'Finland',
- 'UserCountry_country_sg' => 'Singapore',
- 'UserCountry_country_sh' => 'Saint Helena',
- 'UserCountry_country_si' => 'Slovenia',
- 'UserCountry_country_sj' => 'Svalbard',
- 'UserCountry_country_sk' => 'Slovakia',
- 'UserCountry_country_sl' => 'Sierra Leone',
- 'UserCountry_country_sm' => 'San Marino',
- 'UserCountry_country_sn' => 'Senegal',
- 'UserCountry_country_so' => 'Somalia',
- 'UserCountry_country_sr' => 'Suriname',
- 'UserCountry_country_st' => 'Sao Tome and Principe',
- 'UserCountry_country_su' => 'Old U.S.S.R',
- 'UserCountry_country_sv' => 'El Salvador',
- 'UserCountry_country_sy' => 'Syrian Arab Republic',
- 'UserCountry_country_sz' => 'Swaziland',
- 'UserCountry_country_ta' => 'Tristan da Cunha',
- 'UserCountry_country_tc' => 'Turks and Caicos Islands',
- 'UserCountry_country_td' => 'Chad',
- 'UserCountry_country_tf' => 'French Southern Territories',
- 'UserCountry_country_tg' => 'Togo',
- 'UserCountry_country_th' => 'Thailand',
- 'UserCountry_country_tj' => 'Tajikistan',
- 'UserCountry_country_tk' => 'Tokelau',
- 'UserCountry_country_tl' => 'East Timor',
- 'UserCountry_country_tm' => 'Turkmenistan',
- 'UserCountry_country_tn' => 'Tunisia',
- 'UserCountry_country_to' => 'Tonga',
- 'UserCountry_country_tp' => 'East Timor',
- 'UserCountry_country_tr' => 'Turkey',
- 'UserCountry_country_tt' => 'Trinidad and Tobago',
- 'UserCountry_country_tv' => 'Tuvalu',
- 'UserCountry_country_tw' => 'Taiwan',
- 'UserCountry_country_tz' => 'Tanzania, United Republic of',
- 'UserCountry_country_ua' => 'Ukraine',
- 'UserCountry_country_ug' => 'Uganda',
- 'UserCountry_country_uk' => 'United Kingdom',
- 'UserCountry_country_um' => 'United States Minor Outlying Islands',
- 'UserCountry_country_us' => 'United States',
- 'UserCountry_country_uy' => 'Uruguay',
- 'UserCountry_country_uz' => 'Uzbekistan',
- 'UserCountry_country_va' => 'Vatican City',
- 'UserCountry_country_vc' => 'Saint Vincent and the Grenadines',
- 'UserCountry_country_ve' => 'Venezuela',
- 'UserCountry_country_vg' => 'Virgin Islands, British',
- 'UserCountry_country_vi' => 'Virgin Islands, U.S.',
- 'UserCountry_country_vn' => 'Vietnam',
- 'UserCountry_country_vu' => 'Vanuatu',
- 'UserCountry_country_wf' => 'Wallis and Futuna',
- 'UserCountry_country_ws' => 'Samoa',
- 'UserCountry_country_ye' => 'Yemen',
- 'UserCountry_country_yt' => 'Mayotte',
- 'UserCountry_country_yu' => 'Yugoslavia',
- 'UserCountry_country_za' => 'South Africa',
- 'UserCountry_country_zm' => 'Zambia',
- 'UserCountry_country_zr' => 'Zaire',
- 'UserCountry_country_zw' => 'Zimbabwe',
- 'UserCountry_continent_eur' => 'Europe',
- 'UserCountry_continent_afr' => 'Africa',
- 'UserCountry_continent_asi' => 'Asia',
- 'UserCountry_continent_ams' => 'South and Central America',
- 'UserCountry_continent_amn' => 'North America',
- 'UserCountry_continent_oce' => 'Oceania',
- 'VisitsSummary_NbVisits' => '%s käyntiä',
- 'VisitsSummary_NbUniqueVisitors' => '%s uniikia kävijää',
- 'VisitsSummary_NbActions' => '%s toimintoa (katsottua sivua)',
- 'VisitsSummary_TotalTime' => '%s aikaa käytetty sivuilla',
- 'VisitsSummary_MaxNbActions' => '%s toimintoa maksimissaan yhdellä käynnillä',
- 'VisitsSummary_NbVisitsBounced' => '%s lyhyttä käyntiä (vain yksi ladattu sivu)',
- 'VisitsSummary_EvolutionOverLastPeriods' => 'Muutos edellisen %s aikana',
- 'VisitsSummary_Report' => 'Raportti',
- 'VisitsSummary_GenerateTime' => '%s sekuntia sivun luomiseen',
- 'VisitsSummary_GenerateQueries' => '%s kyselyä ajettu',
- 'VisitsSummary_WidgetLastVisits' => 'Edelliset käynnit',
- 'VisitsSummary_WidgetVisits' => 'Käyntien yleiskatsaus',
- 'VisitsSummary_WidgetLastVisitors' => 'Edelliset uniikit kävijät',
- 'VisitsSummary_WidgetOverviewGraph' => 'Yleiskatsaus graafilla',
- 'VisitsSummary_SubmenuOverview' => 'Yleiskatsaus',
- 'VisitFrequency_Evolution' => 'Muutos aikajaksolla',
- 'VisitFrequency_ColumnReturningVisits' => 'Palaavat käynnit',
- 'VisitFrequency_ColumnActionsByReturningVisits' => 'Toimintoja palaavilta käyttäjiltä',
- 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Maksimimäärä toimintoja palaavalta käyttäjältä',
- 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Palaavat käyttäjät käyttivät aikaa (sekuntia)',
- 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Lyhyitä käyntejä palaavilta käyttäjiltä',
- 'VisitFrequency_ReturnVisits' => '%s palaavaa käyntiä',
- 'VisitFrequency_ReturnActions' => '%s toimintoa palaavilta käyttäjiltä',
- 'VisitFrequency_ReturnMaxActions' => '%s maksimimäärä toimintoja palaavalta kävijältä',
- 'VisitFrequency_ReturnTotalTime' => '%s aikaa yhteensä palaavilla käynneillä',
- 'VisitFrequency_ReturnBounceRate' => '%s palaavista käynneistä oli lyhyitä (vain yksi sivunlataus)',
- 'VisitFrequency_WidgetOverview' => 'Yleiskatsaus yleisyydestä',
- 'VisitFrequency_WidgetGraphReturning' => 'Palaavat käyttäjät',
- 'VisitFrequency_SubmenuFrequency' => 'Yleisyys',
- 'VisitTime_LocalTime' => 'Käyntejä (paikallinen aika)',
- 'VisitTime_ServerTime' => 'Käyntejä (palvelimen aika)',
- 'VisitTime_ColumnServerTime' => 'Palvelimen aika',
- 'VisitTime_ColumnLocalTime' => 'Paikallinen aika',
- 'VisitTime_WidgetLocalTime' => 'Käyntejä (paikallinen aika)',
- 'VisitTime_WidgetServerTime' => 'Käyntejä (palvelimen aika)',
- 'VisitTime_SubmenuTimes' => 'Ajat',
- 'VisitTime_NHour' => '%sh',
- 'VisitorInterest_VisitsPerDuration' => 'Käynnit pituuden mukaan',
- 'VisitorInterest_VisitsPerNbOfPages' => 'Käynnit sivujen mukaan',
- 'VisitorInterest_ColumnVisitDuration' => 'Käyntien kesto',
- 'VisitorInterest_ColumnPagesPerVisit' => 'Sivuja / käynti',
- 'VisitorInterest_WidgetLengths' => 'Käynnin pituus',
- 'VisitorInterest_WidgetPages' => 'Sivuja / käynti',
- 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Yleisyys & lojaalius',
- 'VisitorInterest_PlusXMin' => '%s min',
- 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
- 'VisitorInterest_OnePage' => '1 sivu',
- 'VisitorInterest_NPages' => '%s sivua',
- 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
- 'Login_LoginPasswordNotCorrect' => 'Käyttäjätunnus tai salasana väärin',
- 'Login_Login' => 'Käyttäjätunnus',
- 'Login_Password' => 'Salasana',
- 'Login_LoginOrEmail' => 'Käyttäjätunnus tai sähköposti',
- 'Login_LogIn' => 'Kirjaudu sisään',
- 'Login_Logout' => 'Kirjaudu ulos',
- 'Login_LostYourPassword' => 'Unohtuiko salasana?',
- 'Login_RemindPassword' => 'Salasanamuistutus',
- 'Login_PasswordReminder' => 'Kirjoita käyttäjätunnus tai sähköpostiosoite. Saat uuden salasanan sähköpostilla.',
- 'Login_InvalidUsernameEmail' => 'Virheellinen käyttäjätunnus ja/tai sähköpostiosoite',
- 'Login_MailTopicPasswordRecovery' => 'Salasanan palautus',
- 'Login_MailPasswordRecoveryBody' => 'Hei %1s, \n\n Uusi salasanasi on : %2s \n\n Voit kirjautua sisään: %3s',
- 'Login_PasswordSent' => 'Salasana on lähetetty. Tarkista sähköpostisi.',
- 'Login_ContactAdmin' => 'Mahdollisia syitä: palvelin ei välttämättä salli sähköpostien lähetystä (mail()-funktiota).<br/>Ota yhteyttä Piwikin ylläpitäjään.',
- 'UsersManager_UsersManagement' => 'Käyttäjien hallinta',
- 'UsersManager_UsersManagementMainDescription' => 'Lisää uusia käyttäjiä tai päivitä olemassaolevia. Voit asettaa oikeudet alla.',
- 'UsersManager_ManageAccess' => 'Hallitse oikeuksia',
- 'UsersManager_MainDescription' => 'Määrittele, millä käyttäjillä on oikeus verkkosivulle. Voit asettaa oikeuksia kaikille sivuille yhdellä kertaa.',
- 'UsersManager_Sites' => 'Sivut',
- 'UsersManager_AllWebsites' => 'Kaikki sivut',
- 'UsersManager_ApplyToAllWebsites' => 'Päivitä kaikille sivuille',
- 'UsersManager_User' => 'Käyttäjä',
- 'UsersManager_PrivNone' => 'Ei käyttöoikeutta',
- 'UsersManager_PrivView' => 'Katsomisoikeus',
- 'UsersManager_PrivAdmin' => 'Hallinnointioikeus',
- 'UsersManager_ChangeAllConfirm' => 'Haluatko varmasti vaihtaa käyttäjän \'%s\' oikeudet kaikille sivuille?',
- 'UsersManager_Login' => 'Tunnus',
- 'UsersManager_Password' => 'Salasana',
- 'UsersManager_Email' => 'Sähköposti',
- 'UsersManager_Alias' => 'Alias',
- 'UsersManager_Token' => 'token_auth',
- 'UsersManager_Edit' => 'Muokkaa',
- 'UsersManager_AddUser' => 'Lisää uusi käyttäjä',
- 'UsersManager_MenuUsers' => 'Käyttäjät',
- 'UsersManager_DeleteConfirm_js' => 'Haluatko varmasti poistaa käyttäjän %s?',
- 'UsersManager_ExceptionLoginExists' => 'Tunnus \'%s\' on jo olemassa.',
- 'UsersManager_ExceptionEmailExists' => 'Käyttäjä sähköpostilla \'%s\' on jo olemassa.',
- 'UsersManager_ExceptionInvalidLoginFormat' => 'Tunnus täytyy olla %s-%s merkkiä pitkä ja saa siältää vain kirjaimia, numeroita ja merkkejä \'_\', \'-\' ja \'.\'',
- 'UsersManager_ExceptionInvalidPassword' => 'Salasanan pitää olla 6-26 merkkiä pitkä.',
- 'UsersManager_ExceptionInvalidEmail' => 'Sähköposti ei ole kelvollinen.',
- 'UsersManager_ExceptionDeleteDoesNotExist' => 'Käyttäjää \'%s\' ei ole eikä sitä siksi voida poistaa.',
- 'UsersManager_ExceptionAdminAnonymous' => 'Et voi sallia ylläpito-oikeuksia anonyymikäyttäjälle.',
- 'UsersManager_ExceptionEditAnonymous' => 'Anonyymikäyttäjää ei voi muokata tai poistaa. Se on Piwikin sisäinen tunnus käyttäjälle, joka ei ole kirjautunut sisään. Voit esimerkiksi julkaista tilastoja kaikille sallimalla anonyymikäyttäjälle katsomisoikeuden.',
- 'UsersManager_ExceptionSuperUser' => 'Pyydetty käyttäjä on pääkäyttäjä. Pääkäyttäjää ei voi muokata tai poistaa API:n kautta. Voit manuaalisesti muokata pääkäyttäjää Piwikin asetustiedostosta.',
- 'UsersManager_ExceptionUserDoesNotExist' => 'Käyttäjää \'%s\' ei ole olemassa.',
- 'UsersManager_ExceptionAccessValues' => 'Oikeuksien täytyy olla yksi seuraavista arvoista: [ %s ]',
- 'SitesManager_Sites' => 'Sivut',
- 'SitesManager_WebsitesManagement' => 'Verkkosivujen hallinta',
- 'SitesManager_MainDescription' => 'Verkkosivujen analysointi tarvitsee verkkosivuja! Lisää, päivitä ja poista verkkosivuja ja katso sivuille lisättävä Javascript-koodi.',
- 'SitesManager_JsCode' => 'Javascript-koodi',
- 'SitesManager_JsCodeHelp' => 'Lisää tämä javascript-koodi kaikille sivuillesi',
- 'SitesManager_ShowJsCode' => 'näytä koodi',
- 'SitesManager_NoWebsites' => 'Sinulla ei ole yhtään verkkosivua hallinnoitavana.',
- 'SitesManager_AddSite' => 'Lisää uusi sivu',
- 'SitesManager_Id' => 'Id',
- 'SitesManager_Name' => 'Nimi',
- 'SitesManager_Urls' => 'URL',
- 'SitesManager_MenuSites' => 'Sivut',
- 'SitesManager_DeleteConfirm_js' => 'Haluatko varmasti poistaa sivun %s?',
- 'SitesManager_ExceptionDeleteSite' => 'Sivua ei voi poistaa, sillä se on ainoa rekisteröity sivu. Lisää ensin uusi sivu.',
- 'SitesManager_ExceptionNoUrl' => 'Sivuilla täytyy olla vähintään yksi verkkosivu.',
- 'SitesManager_ExceptionEmptyName' => 'Sivun nimi ei voi olla tyhjä.',
- 'SitesManager_ExceptionInvalidUrl' => 'Sivun url \'%s\' ei ole oikein muotoiltu URL.',
- 'Installation_Installation' => 'Asennus',
- 'Installation_InstallationStatus' => 'Asennuksen tila',
- 'Installation_PercentDone' => '%s %% valmiina',
- 'Installation_NoConfigFound' => 'Piwikin asetustiedostoa ei löydy ja yrität siirtyä Piwikin sivuille.<br /><b>&nbsp;&nbsp;&raquo; Voit <a href=\'index.php\'>asentaa Piwikin nyt</a></b><br /><small>Jos asensit Piwikin aikaisemmin ja tietokannassa on jo tietoja, älä murehdi, tietoja ei hävitetä.</small>',
- 'Installation_MysqlSetup' => 'MySQL-tietokannan asennus',
- 'Installation_MysqlErrorConnect' => 'Virhe MySQL-tietokantaan yhdistämisessä',
- 'Installation_JsTag' => 'Javascript-koodi',
- 'Installation_JsTagHelp' => '<p>Lisää tämä koodi kaikille sivuillesi laskeaksesi kävijät.</p><p>Sivujen ei tarvitse olla tehty PHP:llä. Piwik toimii kaikilla sivuilla (esim. HTML, ASP, Perl tai mikä tahansa muu kieli).</p><p>Tässä on koodi, joka sivuille pitää lisätä: (kopioi ja liitä kaikille sivuille)</p>',
- 'Installation_Congratulations' => 'Onnittelut',
- 'Installation_CongratulationsHelp' => '<p>Onnittelut! Piwikin asennus on valmis.</p><p>Varmista, että javascript-koodi on lisätty sivuille ja odota ensimmäisiä vierailijoita!</p>',
- 'Installation_ContinueToPiwik' => 'Jatka Piwikiin',
- 'Installation_SetupWebsite' => 'Lisää verkkosivu',
- 'Installation_SetupWebsiteError' => 'Virhe verkkosivun lisäämisessä',
- 'Installation_GeneralSetup' => 'Yleiset asetukset',
- 'Installation_GeneralSetupSuccess' => 'Yleiset asetukset asetettu onnistuneesti',
- 'Installation_SuperUserLogin' => 'pääkäyttäjän tunnus',
- 'Installation_Password' => 'salasana',
- 'Installation_PasswordRepeat' => 'salasana (uudelleen)',
- 'Installation_Email' => 'sähköposti',
- 'Installation_SecurityNewsletter' => 'lähetä sähköpostia Piwikin suurista päivityksistä ja turvallisuushälytyksistä',
- 'Installation_CommunityNewsletter' => 'lähetä sähköpostia kaikista päivityksistä (uusista lisäosista, ominaisuuksista jne.)',
- 'Installation_PasswordDoNotMatch' => 'salasanat eivät täsmää',
- 'Installation_SubmitGo' => 'Mene!',
- 'Installation_SystemCheck' => 'Järjestelmän asetukset',
- 'Installation_SystemCheckPhp' => 'PHP:n versio',
- 'Installation_SystemCheckPdo' => 'Pdo-lisäosa',
- 'Installation_SystemCheckPdoMysql' => 'Pdo_Mysql-lisäosa',
- 'Installation_SystemCheckPdoError' => 'Tarvitset PDO- ja PDO_MYSQL-lisäosat php.ini-tiedostoon.',
- 'Installation_SystemCheckPdoHelp' => 'Windows-palvelimella voit lisätä seuraavat tiedostot php.ini-tiedostoosi %s<br /><br />Linux-palvelimella voit kääntää PHP:n seuraavilla asetuksilla: %s. Lisää php.ini-tiedostoon seuraavat rivit: %s<br /><br />Lisätietoa <a style="color:red" href="http://php.net/pdo">PHP:n kotisivuilla</a>.',
- 'Installation_SystemCheckWriteDirs' => 'Tiedostot kirjoitusoikeudella',
- 'Installation_SystemCheckWriteDirsHelp' => 'Aja Linux-järjestelmässä seuraavat komennot:',
- 'Installation_SystemCheckMemoryLimit' => 'Muistirajoitus',
- 'Installation_SystemCheckMemoryLimitHelp' => 'Jos verkkosivuilla on paljon liikennettä, arkistointiprosessi saattaa vaatia enemmän muistia.<br />Muokkaa asetusta memory_limit php.ini-tiedostossa tarvittaessa.',
- 'Installation_SystemCheckGD' => 'GD &gt; 2.x (grafiikat)',
- 'Installation_SystemCheckGDHelp' => 'Pienet graafit eivät toimi.',
- 'Installation_SystemCheckTimeLimit' => 'set_time_limit() sallittu',
- 'Installation_SystemCheckTimeLimitHelp' => 'Jos verkkosivuilla on paljon liikennettä, arkistointiprosessi saattaa vaatia enemmän aikaa.<br />Muokkaa asetusta max_execution_time php.ini-tiedostossa tarvittaessa.',
- 'Installation_SystemCheckMail' => 'mail() sallittu',
- 'Installation_SystemCheckError' => 'Tapahtui virhe - täytyy korjata ennen jatkamista',
- 'Installation_SystemCheckWarning' => 'Piwik toimii normaalisti, mutta osa ominaisuuksista puuttuu',
- 'Installation_Tables' => 'Luodaan taulut',
- 'Installation_TablesWithSameNamesFound' => 'Osalla %s tauluista tietokannassa %s on sama nimi kuin tauluilla, joita Piwik yrittää luoda.',
- 'Installation_TablesFound' => 'Seuraavat taulut löytyivät tietokannasta',
- 'Installation_TablesWarningHelp' => 'Valitse joko nykyisten taulujen käyttö tai luo taulut uudelleen (vanhat tiedot menetetään).',
- 'Installation_TablesReuse' => 'Käytä nykyisiä tauluja',
- 'Installation_TablesDelete' => 'Poista löydetyt taulut',
- 'Installation_TablesDeletedSuccess' => 'Löytyneet taulut on poistettu onnistuneesti',
- 'Installation_TablesCreatedSuccess' => 'Taulut luotu onnistuneesti!',
- 'Installation_DatabaseCreatedSuccess' => 'Tietokanta %s luotu onnistuneesti!',
- 'Installation_GoBackAndDefinePrefix' => 'Siirry takaisin ja määritä alkuliite (prefix) Piwikin tauluille',
- 'Installation_ConfirmDeleteExistingTables' => 'Haluatko varmasti poistaa seuraavat taulut tietokannasta: %s? VAROITUS: TAULUJEN TIETOJA EI VOI PALAUTTAA EIKÄ POISTAMISTA VOI KUMOTA!',
- 'Installation_Welcome' => 'Tervetuloa!',
- 'Installation_WelcomeHelp' => '<p>Piwik on vapaan lähdekoodin verkkosivujen analysointityökalu, joka tekee kävijöiden tietojen keräämisen ja analysoinnin helpoksi.</p><p>Tämä prosessi on jaettu %s helppoon osaan ja vie aikaa noin viisi minuuttia.</p>',
- 'Installation_ErrorInvalidState' => 'Virhe: yrität ohittaa vaiheen asennusprosessista tai keksit (cookies) ei ole sallittu. %sVarmista, että keksit on sallittu%s ja mene takaisin %s asennuksen ensimmäiselle sivulle %s.',
- 'Provider_WidgetProviders' => 'Palveluntarjoajat',
- 'Provider_ColumnProvider' => 'Palveluntarjoajat',
- 'Provider_SubmenuLocationsProvider' => 'Sijainnit & palveluntarjoajat',
- 'Goals_ColumnConversions' => 'Muutokset',
- 'Goals_ColumnConversionRate' => 'Muutosnopeus',
- 'Goals_ColumnRevenue' => 'Tulot',
- 'DBStats_DatabaseUsage' => 'Tietokannan käyttö',
- 'DBStats_MainDescription' => 'Piwik tallentaa kaikki tiedot MySQL-tietokantaan. Piwikin taulut käyttävät %s.',
- 'DBStats_Table' => 'Taulu',
- 'DBStats_RowNumber' => 'Rivien määrä',
- 'DBStats_DataSize' => 'Tietojen koko',
- 'DBStats_IndexSize' => 'Indeksien koko',
- 'DBStats_TotalSize' => 'Koko yhteensä',
- 'TranslationsAdmin_MenuTranslations' => 'Käännökset',
- 'TranslationsAdmin_MenuLanguages' => 'Kielet',
- 'TranslationsAdmin_Plugin' => 'Lisäosa',
- 'TranslationsAdmin_Definition' => 'Kuvaus',
- 'TranslationsAdmin_DefaultString' => 'Oletusmerkkijono (englanniksi)',
- 'TranslationsAdmin_TranslationString' => 'Käännettävä merkkijono (nykyinen kieli: %s)',
- 'TranslationsAdmin_Translations' => 'Käännökset',
- 'TranslationsAdmin_FixPermissions' => 'Tarkista tiedostojärjestelmän oikeudet',
- 'TranslationsAdmin_AvailableLanguages' => 'Saatavilla olevat kielet',
- 'TranslationsAdmin_AddLanguage' => 'Lisää kieli',
- 'TranslationsAdmin_LanguageCode' => 'Kielikoodi',
- 'TranslationsAdmin_Export' => 'Vie kieli',
- 'TranslationsAdmin_Import' => 'Tuo kieli',
+ 'General_Locale' => 'fi_FI.UTF-8',
+ 'General_TranslatorName' => 'Olli Jarva (http://olli.jarva.fi/)',
+ 'General_TranslatorEmail' => 'olli@jarva.fi',
+ 'General_EnglishLanguageName' => 'Finnish',
+ 'General_OriginalLanguageName' => 'Suomi',
+ 'General_HelloUser' => 'Hei, %s!',
+ 'General_OpenSourceWebAnalytics' => 'Vapaa verkkoanalysaattori',
+ 'General_YourDashboard' => 'Työpöytä',
+ 'General_API' => 'API',
+ 'General_Widgets' => 'Vimpaimet',
+ 'General_Settings' => 'Asetukset',
+ 'General_GiveUsYourFeedback' => 'Anna palautetta!',
+ 'General_Unknown' => 'Tuntematon',
+ 'General_Required' => '%s vaaditaan',
+ 'General_Error' => 'Virhe',
+ 'General_Warning' => 'Varoitus',
+ 'General_BackToHomepage' => 'Takaisin Piwikin etusivulle',
+ 'General_Yes' => 'Kyllä',
+ 'General_No' => 'Ei',
+ 'General_Delete' => 'Poista',
+ 'General_Edit' => 'Muokkaa',
+ 'General_Ok' => 'Ok',
+ 'General_Close' => 'Sulje',
+ 'General_Logout' => 'Kirjaudu ulos',
+ 'General_Done' => 'Valmis',
+ 'General_LoadingData' => 'Ladataan tietoja...',
+ 'General_Loading' => 'Ladataan...',
+ 'General_ErrorRequest' => 'Oops&hellip; virhe pyynnön käsittelyssä, yritä uudelleen.',
+ 'General_Next' => 'Seuraava',
+ 'General_Previous' => 'Edellinen',
+ 'General_Search' => 'Hae',
+ 'General_Others' => 'Muut',
+ 'General_Table' => 'Taulukko',
+ 'General_Piechart' => 'Ympyräkaavio',
+ 'General_TagCloud' => 'Avainsanapilvi',
+ 'General_VBarGraph' => 'Pystygraafi',
+ 'General_Export' => 'Vie',
+ 'General_ExportAsImage' => 'Vie kuvaksi',
+ 'General_SaveImageOnYourComputer' => 'Tallenna kuva koneelle painamalla kuvaa oikealla napilla ja valitse "Tallenna kuva nimellä..."',
+ 'General_Refresh' => 'Päivitä sivu',
+ 'General_Visitors' => 'Kävijät',
+ 'General_ColumnNbUniqVisitors' => 'Yksilölliset kävijät',
+ 'General_ColumnNbVisits' => 'Käynnit',
+ 'General_ColumnNbActions' => 'Toiminnot',
+ 'General_ColumnMaxActions' => 'Toimintoja enintään / käynti',
+ 'General_ColumnSumVisitLength' => 'Kaikkien kävijöiden aika yhteensä (sekunteja)',
+ 'General_ColumnLabel' => 'Etiketti',
+ 'General_ColumnActionsPerVisit' => 'Toimintoja / käynti',
+ 'General_ColumnAvgTimeOnSite' => 'Keskimääräinen aika sivulla',
+ 'General_ColumnBounceRate' => 'Lähtemissuhde',
+ 'General_ColumnPageviews' => 'Sivukatseluita',
+ 'General_ColumnUniquePageviews' => 'Yksilöllisiä sivukatseluita',
+ 'General_ColumnValuePerVisit' => 'Käynnin arvo',
+ 'General_ColumnVisitsWithConversions' => 'Käyntejä, joissa keskusteluja',
+ 'General_Save' => 'Tallenna',
+ 'General_Website' => 'Verkkosivu',
+ 'General_NoDataForGraph' => 'Ei tietoja tähän kuvaajaan',
+ 'General_NoDataForTagCloud' => 'Ei tietoja tähän avainsanapilveen',
+ 'General_DisplayNormalTable' => 'Näytä normaali taulukko',
+ 'General_DisplayMoreData' => 'Näytä lisää tietoja',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s on yhteistyöprojekti. %s Jos pidät Piwikistä, voit auttaa! Katso %s miten voit auttaa Piwikiä%s ',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Katsot demoversiota %s; %slataa%s kokoversio! Katso %s',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s on saatavilla. %s Päivitä nyt!%s (katso %s muutokset%s).',
+ 'General_BackToPiwik' => 'Takaisin Piwikiin',
+ 'General_ShortMonth_1' => 'Tam',
+ 'General_ShortMonth_2' => 'Hel',
+ 'General_ShortMonth_3' => 'Maa',
+ 'General_ShortMonth_4' => 'Huh',
+ 'General_ShortMonth_5' => 'Tou',
+ 'General_ShortMonth_6' => 'Kes',
+ 'General_ShortMonth_7' => 'Hei',
+ 'General_ShortMonth_8' => 'Elo',
+ 'General_ShortMonth_9' => 'Syy',
+ 'General_ShortMonth_10' => 'Lok',
+ 'General_ShortMonth_11' => 'Mar',
+ 'General_ShortMonth_12' => 'Jou',
+ 'General_LongMonth_1' => 'Tammikuu',
+ 'General_LongMonth_2' => 'Helmikuu',
+ 'General_LongMonth_3' => 'Maaliskuu',
+ 'General_LongMonth_4' => 'Huhtikuu',
+ 'General_LongMonth_5' => 'Toukokuu',
+ 'General_LongMonth_6' => 'Kesäkuu',
+ 'General_LongMonth_7' => 'Heinäkuu',
+ 'General_LongMonth_8' => 'Elokuu',
+ 'General_LongMonth_9' => 'Syyskuu',
+ 'General_LongMonth_10' => 'Lokakuu',
+ 'General_LongMonth_11' => 'Marraskuu',
+ 'General_LongMonth_12' => 'Joulukuu',
+ 'General_ShortDay_1' => 'Ma',
+ 'General_ShortDay_2' => 'Ti',
+ 'General_ShortDay_3' => 'Ke',
+ 'General_ShortDay_4' => 'To',
+ 'General_ShortDay_5' => 'Pe',
+ 'General_ShortDay_6' => 'La',
+ 'General_ShortDay_7' => 'Su',
+ 'General_LongDay_1' => 'Maanantai',
+ 'General_LongDay_2' => 'Tiistai',
+ 'General_LongDay_3' => 'Keskivikko',
+ 'General_LongDay_4' => 'Torstai',
+ 'General_LongDay_5' => 'Perjantai',
+ 'General_LongDay_6' => 'Lauantai',
+ 'General_LongDay_7' => 'Sunnuntai',
+ 'Core_ExceptionDatabaseVersion' => '%s versio on %s mutta Piwik tarvitsee vähintään version %s.',
+ 'CorePluginsAdmin_Plugins' => 'Lisäosat',
+ 'CorePluginsAdmin_PluginsManagement' => 'Lisäosien hallinta',
+ 'CorePluginsAdmin_MainDescription' => 'Lisäosilla voi laajentaa ja parantaa Piwikin toiminnallisuutta. Kun lisäosa on asennettu, voit aktivoida ja poistaa käytöstä sen täällä.',
+ 'CorePluginsAdmin_Plugin' => 'Lisäosa',
+ 'CorePluginsAdmin_Version' => 'Versio',
+ 'CorePluginsAdmin_Description' => 'Kuvaus',
+ 'CorePluginsAdmin_Status' => 'Tila',
+ 'CorePluginsAdmin_Action' => 'Toiminto',
+ 'CorePluginsAdmin_PluginHomepage' => 'Lisäosan kotisivu',
+ 'CorePluginsAdmin_Activated' => 'Aktivoitu',
+ 'CorePluginsAdmin_Active' => 'Käytössä',
+ 'CorePluginsAdmin_Inactive' => 'Ei käytössä',
+ 'CorePluginsAdmin_ActivatedHelp' => 'Lisäosaa ei voi poistaa käytöstä',
+ 'CorePluginsAdmin_Deactivate' => 'Poistettu käytöstä',
+ 'CorePluginsAdmin_Activate' => 'Aktivoi',
+ 'CorePluginsAdmin_MenuPlugins' => 'Lisäosat',
+ 'API_QuickDocumentation' => "<h2>API:n pikadokumentaatio</h2><p>Jos käytössäsi ei ole dataa, voit <a href='misc/generateVisits.php' target=_blank>generoida testidataa</a> ohjelmalla.</p><p>Voit kokeilla eri formaatteja jokaisella metodilla. Tietojen hakeminen piwikistä on erittäin helppoa!</p><p><b>Lisätietoa löytyy <a href='http://dev.piwik.org/trac/wiki/API'>virallisesta API-dokumentaatiosta</a> tai <a href='http://dev.piwik.org/trac/wiki/API/Reference'>API-referenssistä</a>.</b></P><h2>Autentikointi</h2><p>Jos haluat <b>hakea tietoja ohjelmastasi, crontabista jne.</b> kyselyyn täytyy lisätä parametri <code><u>&token_auth=%s</u></code> osoitteille, joilla tarvitaan autentikointi.</p><p>token_auth on salaisuus, kuten käyttäjätunnus ja salasana, joten <b>älä jaa sit�!</p>",
+ 'API_LoadedAPIs' => 'Ladattiin %s APIa',
+ 'CoreHome_NoPrivileges' => 'Olet kirjautunut sisään käyttäjänä %s, mutta sinulla ei ole mitään oikeuksia Piwikiin.<br />Pyydä oman Piwikisi ylläpitäjää antamaan katseluoikeus sivustoon.',
+ 'CoreHome_JavascriptDisabled' => 'Standardinäkymän käyttäminen edellyttää javascriptin sallimista.<br />Javascript on joko poistettu käytöstä tai selaimesi ei tue Javascriptiä.<br />Ota javascript käyttöön, jotta voit käyttää standardinäkymää. %1sYritä uudelleen%2s.<br />',
+ 'CoreHome_TableNoData' => 'Ei tietoja tähän taulukkoon.',
+ 'CoreHome_CategoryNoData' => 'Tässä kategoriassa ei ole tietoja. Kokeile linkkiä "Kaikki esiintymät".',
+ 'CoreHome_ShowJSCode' => 'Näytä lisättävä Javascript-koodi',
+ 'CoreHome_IncludeAllPopulation_js' => 'Kaikki esiintymät',
+ 'CoreHome_ExcludeLowPopulation_js' => 'Poista harvat esiintymät',
+ 'CoreHome_PageOf_js' => '%s of %s',
+ 'CoreHome_Loading_js' => 'Ladataan...',
+ 'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
+ 'CoreHome_PeriodDay' => 'Päivä',
+ 'CoreHome_PeriodWeek' => 'Viikko',
+ 'CoreHome_PeriodMonth' => 'Kuukausi',
+ 'CoreHome_PeriodYear' => 'Vuosi',
+ 'CoreHome_PeriodDays' => 'päivät',
+ 'CoreHome_PeriodWeeks' => 'viikot',
+ 'CoreHome_PeriodMonths' => 'kuukaudet',
+ 'CoreHome_PeriodYears' => 'vuodet',
+ 'CoreHome_DaySu_js' => 'Su',
+ 'CoreHome_DayMo_js' => 'Ma',
+ 'CoreHome_DayTu_js' => 'Ti',
+ 'CoreHome_DayWe_js' => 'Ke',
+ 'CoreHome_DayTh_js' => 'To',
+ 'CoreHome_DayFr_js' => 'Pe',
+ 'CoreHome_DaySa_js' => 'La',
+ 'CoreHome_MonthJanuary_js' => 'Tammikuu',
+ 'CoreHome_MonthFebruary_js' => 'Helmikuu',
+ 'CoreHome_MonthMarch_js' => 'Maaliskuu',
+ 'CoreHome_MonthApril_js' => 'Huhtikuu',
+ 'CoreHome_MonthMay_js' => 'Toukokuu',
+ 'CoreHome_MonthJune_js' => 'Kesäkuu',
+ 'CoreHome_MonthJuly_js' => 'Heinäkuu',
+ 'CoreHome_MonthAugust_js' => 'Elokuu',
+ 'CoreHome_MonthSeptember_js' => 'Syyskuu',
+ 'CoreHome_MonthOctober_js' => 'Lokakuu',
+ 'CoreHome_MonthNovember_js' => 'Marraskuu',
+ 'CoreHome_MonthDecember_js' => 'Joulukuu',
+ 'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; Päivitys',
+ 'CoreUpdater_DatabaseUpgradeRequired' => 'Tietokannan päivitys tarvitaan',
+ 'CoreUpdater_YourDatabaseIsOutOfDate' => 'Piwikin tietokanta on vanhentunut ja se tulee päivittää ennen jatkamista.',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwikin tietokanta päivitetään versiosta %s versioon %s.',
+ 'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Seuraavat lisäosat päivitetään: %s.',
+ 'CoreUpdater_TheUpgradeProcessMayFail' => 'Jos Piwik-tietokantasi on iso, päivitys saattaa kestää liian kauan. Jos yhteys aikakatkaistaan, voit ajaa päivityksen komentoriviltä komennolla <cod$ php path/to/piwik/index.php</code>.',
+ 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Tietokannan päivitys vie aikaa, ole kärsivällinen.',
+ 'CoreUpdater_UpgradePiwik' => 'Päivitä Piwik',
+ 'CoreUpdater_ErrorDIYHelp' => 'Jos olet edistynyt käyttäjä ja tietokannan päivityksessä tapahtuu virhe:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'etsi ja korjaa ongelman lähde (esim. memory_limit tai max_execution_time',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'aja jäljelle jääneet kyselyt epäonnistuneesta päivityksestä',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'päivitä manuaalisesti `option`-taulu Piwikin tietokannasta. Aseta version_core epäonnistuneen päivityksen versioksi',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'aja päivitys uudelleen (selaimella tai komentoriviltä), jotta jäljellä olevat päivitykset ajetaan',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'raportoi ongelma (ja ratkaisu), jotta piwikiä voidaan parantaa',
+ 'CoreUpdater_HelpMessageContent' => 'Tarkista %s Piwikin FAQ:sta%s yleisimmät virheet. %s Kysy järjestelmän ylläpitäjältä - he voivat auttaa virheissä, jotka johtuvat luultavasti palvelimesta tai tietokannasta.',
+ 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Kriittinen virhe päivitysprosessissa:',
+ 'CoreUpdater_HelpMessageIntroductionWhenError' => 'Alla on ytimen virheviesti: Sen pitäisi auttaa virheen etsimisessä, mutta jos tarvitset lisää apua:',
+ 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Päivitys valmistui onnistuneesti, mutta prosessin aikana tapahtui virheitä. Ole hyvä ja lue alla olevat kuvaukset. Lisää apua:',
+ 'CoreUpdater_UpgradeComplete' => 'Päivitys valmis!',
+ 'CoreUpdater_WarningMessages' => 'Varoitusviestit:',
+ 'CoreUpdater_ErrorDuringPluginsUpdates' => 'Virhe lisäosien päivityksessä:',
+ 'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Seuraavat lisäosat on automaattisesti poistettu käytöstä: %s',
+ 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik on päivitetty onnistuneesti!',
+ 'CoreUpdater_ContinueToPiwik' => 'Jatka Piwikiin',
+ 'CoreUpdater_UpdateAutomatically' => 'Päivitä automaattisesti',
+ 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Piwikistä on uusi versio',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Voit päivittää versioon %s automaattisesti tai ladata paketin ja asentaa sen manuaalisesti:',
+ 'CoreUpdater_DownloadX' => 'Lataa %s',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Piwikin yhden klikkauksen päivitys on peruutettu. Jos et voi korjata alla oelvaa virhettä, on suositeltavaa päivittää Piwik manuaalisesti. %s Ole hyvä ja tarkista %sPäivitysdokumentaatio%s',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Ladataan päivitystä osoitteesta %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Puretaan päivitystä',
+ 'CoreUpdater_VerifyingUnpackedFiles' => 'Tarkistetaan purettuja tiedostoja',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Luodaan varmuuskopiota asetustiedostosta: %s',
+ 'CoreUpdater_InstallingTheLatestVersion' => 'Asennetaan uusinta versiota',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik päivitettiin onnistuneesti!',
+ 'CoreUpdater_EmptyDatabaseError' => 'Tietokanta %s on tyhjä. Sinun täytyy muokata tai poistaa Piwikin asetustiedosto.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Piwikin versiosi %s on ajantasalla.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Virheellinen arkisto: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Tyhjä arkistotiedosto.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Arkisto on viallinen: osa tiedostoista puuttuu (esim. %s).',
+ 'Actions_Actions' => 'Toiminnot',
+ 'Actions_SubmenuPages' => 'Sivut',
+ 'Actions_SubmenuOutlinks' => 'Lähtevät linkit',
+ 'Actions_SubmenuDownloads' => 'Lataukset',
+ 'Actions_ColumnClicks' => 'Klikkaukset',
+ 'Actions_ColumnUniqueClicks' => 'Uniikit klikkaukset',
+ 'Actions_ColumnDownloads' => 'Lataukset',
+ 'Actions_ColumnUniqueDownloads' => 'Uniikit lataukset',
+ 'Actions_ColumnPageName' => 'Sivun nimi',
+ 'Actions_ColumnClickedURL' => 'Klikattu URL',
+ 'Actions_ColumnDownloadURL' => 'Ladattu URL',
+ 'Dashboard_Dashboard' => 'Työpöytä',
+ 'Dashboard_AddWidget' => 'Lisää vimpain...',
+ 'Dashboard_DeleteWidgetConfirm' => 'Haluatko varmasti poistaa vimpaimen työpöydältä?',
+ 'Dashboard_SelectWidget' => 'Valitse työpöydälle lisättävä vimpain',
+ 'Dashboard_AddPreviewedWidget_js' => 'Lisää esikatseltu vimpain työpöydälle',
+ 'Dashboard_WidgetPreview_js' => 'Vimpaimen esikatselu',
+ 'Dashboard_Close_js' => 'Sulje',
+ 'Dashboard_TitleWidgetInDashboard_js' => 'Vimpain on jo työpöydällä',
+ 'Dashboard_TitleClickToAdd_js' => 'Klikkaa lisätäksesi työpöydälle',
+ 'Dashboard_LoadingWidget_js' => 'Ladataan vimpainta, odota...',
+ 'Dashboard_WidgetNotFound_js' => 'Vimpainta ei löydy',
+ 'Referers_Referers' => 'Viittaajat',
+ 'Referers_SearchEngines' => 'Hakukoneet',
+ 'Referers_Keywords' => 'Hakusanat',
+ 'Referers_DirectEntry' => 'Suoraan',
+ 'Referers_Websites' => 'Verkkosivut',
+ 'Referers_Campaigns' => 'Kampanjat',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%1s (%2s)',
+ 'Referers_Evolution' => 'Muutos aikavälillä',
+ 'Referers_Type' => 'Viittaajan tyyppi',
+ 'Referers_ColumnRefererType' => 'Tyyppi',
+ 'Referers_ColumnSearchEngine' => 'Hakukone',
+ 'Referers_ColumnWebsite' => 'Verkkosivu',
+ 'Referers_ColumnWebsitePage' => 'Verkkosivu',
+ 'Referers_ColumnKeyword' => 'Hakusana',
+ 'Referers_ColumnCampaign' => 'Kampanja',
+ 'Referers_DetailsByRefererType' => 'Tiedot viittajan tyypin mukaan',
+ 'Referers_TypeDirectEntries' => '%s suoraa saapumista',
+ 'Referers_TypeSearchEngines' => '%s hakukoneista',
+ 'Referers_TypeWebsites' => '%s verkkosivuilta',
+ 'Referers_TypeCampaigns' => '%s kampanjoista',
+ 'Referers_Distinct' => 'Yksilöllisiä viittaajia viittaustyypin mukaan',
+ 'Referers_DistinctSearchEngines' => 'yksilöllistä hakukonetta',
+ 'Referers_DistinctKeywords' => 'yksilöllistä hakusanaa',
+ 'Referers_DistinctCampaigns' => 'yksilöllistä kampanjaa',
+ 'Referers_DistinctWebsites' => 'yksilöllistä verkkosivua',
+ 'Referers_UsingNDistinctUrls' => ' (käyttäen %2s yksilöllistä osoitetta)',
+ 'Referers_SubmenuEvolution' => 'Kehitys',
+ 'Referers_SubmenuSearchEngines' => 'Search engines & keywords',
+ 'Referers_SubmenuWebsites' => 'Verkkosivut',
+ 'Referers_SubmenuCampaigns' => 'Kampanjat',
+ 'Referers_WidgetKeywords' => 'Lista hakusanoista',
+ 'Referers_WidgetCampaigns' => 'Lista kampanjoista',
+ 'Referers_WidgetExternalWebsites' => 'Lista ulkoisista verkkosivuista',
+ 'Referers_WidgetSearchEngines' => 'Parhaat hakukoneet',
+ 'Referers_WidgetOverview' => 'Yleiskatsaus',
+ 'UserSettings_VisitorSettings' => 'Kävijöiden asetukset',
+ 'UserSettings_BrowserFamilies' => 'Selainluokat',
+ 'UserSettings_Browsers' => 'Selaimet',
+ 'UserSettings_Plugins' => 'Lisäosat',
+ 'UserSettings_Configurations' => 'Asetukset',
+ 'UserSettings_OperatingSystems' => 'Käyttöjärjestelmä',
+ 'UserSettings_Resolutions' => 'Resoluutio',
+ 'UserSettings_WideScreen' => 'Laajakulma',
+ 'UserSettings_ColumnBrowserFamily' => 'Selainperhe',
+ 'UserSettings_ColumnBrowser' => 'Selain',
+ 'UserSettings_ColumnPlugin' => 'Lisäosa',
+ 'UserSettings_ColumnConfiguration' => 'Asetukset',
+ 'UserSettings_ColumnOperatingSystem' => 'Käyttöjärjestelmä',
+ 'UserSettings_ColumnResolution' => 'Resoluutio',
+ 'UserSettings_ColumnTypeOfScreen' => 'Näytön tyyppi',
+ 'UserSettings_WidgetResolutions' => 'Näytön resoluutio',
+ 'UserSettings_WidgetBrowsers' => 'Kävijöiden selaimet',
+ 'UserSettings_WidgetPlugins' => 'Lista lisäosista',
+ 'UserSettings_WidgetWidescreen' => 'Normaali / laajakuva',
+ 'UserSettings_WidgetBrowserFamilies' => 'Selaimet perheittäin',
+ 'UserSettings_WidgetOperatingSystems' => 'Käyttöjärjestelmät',
+ 'UserSettings_WidgetGlobalVisitors' => 'Kaikkien kävijöiden asetukset',
+ 'UserSettings_SubmenuSettings' => 'Asetukset',
+ 'UserCountry_Country' => 'Maa',
+ 'UserCountry_Continent' => 'Maanosa',
+ 'UserCountry_DistinctCountries' => '%s uniikkia maata',
+ 'UserCountry_SubmenuLocations' => 'Sijainnit',
+ 'UserCountry_WidgetContinents' => 'Kävijöiden maanosat',
+ 'UserCountry_WidgetCountries' => 'Kävijöiden maat',
+ 'UserCountry_country_ac' => 'Ascension Islands',
+ 'UserCountry_country_ad' => 'Andorra',
+ 'UserCountry_country_ae' => 'Yhdistyneet arabiemiirikunnat',
+ 'UserCountry_country_af' => 'Afganistan',
+ 'UserCountry_country_ag' => 'Antigua and Barbuda',
+ 'UserCountry_country_ai' => 'Anguilla',
+ 'UserCountry_country_al' => 'Albania',
+ 'UserCountry_country_am' => 'Armenia',
+ 'UserCountry_country_an' => 'Netherlands Antilles',
+ 'UserCountry_country_ao' => 'Angola',
+ 'UserCountry_country_aq' => 'Antarctica',
+ 'UserCountry_country_ar' => 'Argentiina',
+ 'UserCountry_country_as' => 'American Samoa',
+ 'UserCountry_country_at' => 'Itävalta',
+ 'UserCountry_country_au' => 'Australia',
+ 'UserCountry_country_aw' => 'Aruba',
+ 'UserCountry_country_ax' => 'Aland Islands',
+ 'UserCountry_country_az' => 'Azerbaijan',
+ 'UserCountry_country_ba' => 'Bosnia and Herzegovina',
+ 'UserCountry_country_bb' => 'Barbados',
+ 'UserCountry_country_bd' => 'Bangladesh',
+ 'UserCountry_country_be' => 'Belgia',
+ 'UserCountry_country_bf' => 'Burkina Faso',
+ 'UserCountry_country_bg' => 'Bulgaria',
+ 'UserCountry_country_bh' => 'Bahrain',
+ 'UserCountry_country_bi' => 'Burundi',
+ 'UserCountry_country_bj' => 'Benin',
+ 'UserCountry_country_bl' => 'Saint Barthelemy',
+ 'UserCountry_country_bm' => 'Bermuda',
+ 'UserCountry_country_bn' => 'Bruneo',
+ 'UserCountry_country_bo' => 'Bolivia',
+ 'UserCountry_country_br' => 'Brasilia',
+ 'UserCountry_country_bs' => 'Bahamas',
+ 'UserCountry_country_bt' => 'Bhutan',
+ 'UserCountry_country_bu' => 'Burma',
+ 'UserCountry_country_bv' => 'Bouvet Island',
+ 'UserCountry_country_bw' => 'Botswana',
+ 'UserCountry_country_by' => 'Belarus',
+ 'UserCountry_country_bz' => 'Belize',
+ 'UserCountry_country_ca' => 'Kanada',
+ 'UserCountry_country_cc' => 'Cocos (Keeling) Islands',
+ 'UserCountry_country_cd' => 'Congo, The Democratic Republic of the',
+ 'UserCountry_country_cf' => 'Central African Republic',
+ 'UserCountry_country_cg' => 'Kongo',
+ 'UserCountry_country_ch' => 'Sveitsi',
+ 'UserCountry_country_ci' => "Cote D'Ivoire",
+ 'UserCountry_country_ck' => 'Cook Islands',
+ 'UserCountry_country_cl' => 'Chile',
+ 'UserCountry_country_cm' => 'Kameron',
+ 'UserCountry_country_cn' => 'Kiina',
+ 'UserCountry_country_co' => 'Kolumbia',
+ 'UserCountry_country_cp' => 'Clipperton Island',
+ 'UserCountry_country_cr' => 'Costa Rica',
+ 'UserCountry_country_cs' => 'Serbia Montenegro',
+ 'UserCountry_country_cu' => 'Kuuba',
+ 'UserCountry_country_cv' => 'Cape Verde',
+ 'UserCountry_country_cx' => 'Christmas Island',
+ 'UserCountry_country_cy' => 'Cyprus',
+ 'UserCountry_country_cz' => 'Czech Republic',
+ 'UserCountry_country_de' => 'Saksa',
+ 'UserCountry_country_dg' => 'Diego Garcia',
+ 'UserCountry_country_dj' => 'Djibouti',
+ 'UserCountry_country_dk' => 'Tanska',
+ 'UserCountry_country_dm' => 'Dominika',
+ 'UserCountry_country_do' => 'Dominikaaninen tasavalta',
+ 'UserCountry_country_dz' => 'Algeria',
+ 'UserCountry_country_ea' => 'Ceuta, Melilla',
+ 'UserCountry_country_ec' => 'Ecuador',
+ 'UserCountry_country_ee' => 'Viro',
+ 'UserCountry_country_eg' => 'Egypti',
+ 'UserCountry_country_eh' => 'Länsi-Sahara',
+ 'UserCountry_country_er' => 'Eritrea',
+ 'UserCountry_country_es' => 'Espanja',
+ 'UserCountry_country_et' => 'Ethiopia',
+ 'UserCountry_country_eu' => 'Euroopan Unioni',
+ 'UserCountry_country_fi' => 'Suomi',
+ 'UserCountry_country_fj' => 'Fiji',
+ 'UserCountry_country_fk' => 'Falkland-saaret',
+ 'UserCountry_country_fm' => 'Mikronesia',
+ 'UserCountry_country_fo' => 'Faroe Islands',
+ 'UserCountry_country_fr' => 'Ranska',
+ 'UserCountry_country_fx' => 'France, Metropolitan',
+ 'UserCountry_country_ga' => 'Gabon',
+ 'UserCountry_country_gb' => 'Iso-Britannia',
+ 'UserCountry_country_gd' => 'Grenada',
+ 'UserCountry_country_ge' => 'Georgia',
+ 'UserCountry_country_gf' => 'Ranskan Guinea',
+ 'UserCountry_country_gg' => 'Guernsey',
+ 'UserCountry_country_gh' => 'Ghana',
+ 'UserCountry_country_gi' => 'Gibraltar',
+ 'UserCountry_country_gl' => 'Gröönlanti',
+ 'UserCountry_country_gm' => 'Gambia',
+ 'UserCountry_country_gn' => 'Guinea',
+ 'UserCountry_country_gp' => 'Guadeloupe',
+ 'UserCountry_country_gq' => 'Equatorial Guinea',
+ 'UserCountry_country_gr' => 'Kreikka',
+ 'UserCountry_country_gs' => 'South Georgia and the South Sandwich Islands',
+ 'UserCountry_country_gt' => 'Guatemala',
+ 'UserCountry_country_gu' => 'Guam',
+ 'UserCountry_country_gw' => 'Guinea-Bissau',
+ 'UserCountry_country_gy' => 'Guyana',
+ 'UserCountry_country_hk' => 'Hong Kong',
+ 'UserCountry_country_hm' => 'Heard Island and McDonald Islands',
+ 'UserCountry_country_hn' => 'Honduras',
+ 'UserCountry_country_hr' => 'Kroatia',
+ 'UserCountry_country_ht' => 'Haiti',
+ 'UserCountry_country_hu' => 'Unkari',
+ 'UserCountry_country_ic' => 'Canary Islands',
+ 'UserCountry_country_id' => 'Indonesia',
+ 'UserCountry_country_ie' => 'Irlanti',
+ 'UserCountry_country_il' => 'Israel',
+ 'UserCountry_country_im' => 'Man Island',
+ 'UserCountry_country_in' => 'Intia',
+ 'UserCountry_country_io' => 'British Indian Ocean Territory',
+ 'UserCountry_country_iq' => 'Irak',
+ 'UserCountry_country_ir' => 'Iran',
+ 'UserCountry_country_is' => 'Islanti',
+ 'UserCountry_country_it' => 'Italy',
+ 'UserCountry_country_je' => 'Jersey',
+ 'UserCountry_country_jm' => 'Jamaica',
+ 'UserCountry_country_jo' => 'Jordan',
+ 'UserCountry_country_jp' => 'Japani',
+ 'UserCountry_country_ke' => 'Kenia',
+ 'UserCountry_country_kg' => 'Kyrgyzstan',
+ 'UserCountry_country_kh' => 'Kambodia',
+ 'UserCountry_country_ki' => 'Kiribati',
+ 'UserCountry_country_km' => 'Comoros',
+ 'UserCountry_country_kn' => 'Saint Kitts and Nevis',
+ 'UserCountry_country_kp' => 'Etelä-Korea',
+ 'UserCountry_country_kr' => 'Pohjois-Korea',
+ 'UserCountry_country_kw' => 'Kuwait',
+ 'UserCountry_country_ky' => 'Cayman Islands',
+ 'UserCountry_country_kz' => 'Kazakhstan',
+ 'UserCountry_country_la' => 'Laos',
+ 'UserCountry_country_lb' => 'Lebanon',
+ 'UserCountry_country_lc' => 'Saint Lucia',
+ 'UserCountry_country_li' => 'Liechtenstein',
+ 'UserCountry_country_lk' => 'Sri Lanka',
+ 'UserCountry_country_lr' => 'Liberia',
+ 'UserCountry_country_ls' => 'Lesotho',
+ 'UserCountry_country_lt' => 'Lithuania',
+ 'UserCountry_country_lu' => 'Luxemburg',
+ 'UserCountry_country_lv' => 'Latvia',
+ 'UserCountry_country_ly' => 'Libya',
+ 'UserCountry_country_ma' => 'Marokko',
+ 'UserCountry_country_mc' => 'Monako',
+ 'UserCountry_country_md' => 'Moldova, Republic of',
+ 'UserCountry_country_me' => 'Montenegro',
+ 'UserCountry_country_mf' => 'Saint Martin',
+ 'UserCountry_country_mg' => 'Madagaskar',
+ 'UserCountry_country_mh' => 'Marshall Islands',
+ 'UserCountry_country_mk' => 'Macedonia',
+ 'UserCountry_country_ml' => 'Mali',
+ 'UserCountry_country_mm' => 'Myanmar',
+ 'UserCountry_country_mn' => 'Mongolia',
+ 'UserCountry_country_mo' => 'Makau',
+ 'UserCountry_country_mp' => 'Northern Mariana Islands',
+ 'UserCountry_country_mq' => 'Martinique',
+ 'UserCountry_country_mr' => 'Mauritania',
+ 'UserCountry_country_ms' => 'Montserrat',
+ 'UserCountry_country_mt' => 'Malta',
+ 'UserCountry_country_mu' => 'Mauritius',
+ 'UserCountry_country_mv' => 'Maldives',
+ 'UserCountry_country_mw' => 'Malawi',
+ 'UserCountry_country_mx' => 'Meksiko',
+ 'UserCountry_country_my' => 'Malesia',
+ 'UserCountry_country_mz' => 'Mosambik',
+ 'UserCountry_country_na' => 'Namibia',
+ 'UserCountry_country_nc' => 'Uusi Kaledonia',
+ 'UserCountry_country_ne' => 'Nigeria',
+ 'UserCountry_country_nf' => 'Norfolk Island',
+ 'UserCountry_country_ng' => 'Nigeria',
+ 'UserCountry_country_ni' => 'Nicaragua',
+ 'UserCountry_country_nl' => 'Alankomaat',
+ 'UserCountry_country_no' => 'Norja',
+ 'UserCountry_country_np' => 'Nepal',
+ 'UserCountry_country_nr' => 'Nauru',
+ 'UserCountry_country_nt' => 'Neutraali alue',
+ 'UserCountry_country_nu' => 'Niue',
+ 'UserCountry_country_nz' => 'Uusi Seelanti',
+ 'UserCountry_country_om' => 'Oman',
+ 'UserCountry_country_pa' => 'Panama',
+ 'UserCountry_country_pe' => 'Peru',
+ 'UserCountry_country_pf' => 'French Polynesia',
+ 'UserCountry_country_pg' => 'Papua New Guinea',
+ 'UserCountry_country_ph' => 'Philippiinit',
+ 'UserCountry_country_pk' => 'Pakistan',
+ 'UserCountry_country_pl' => 'Puola',
+ 'UserCountry_country_pm' => 'Saint Pierre and Miquelon',
+ 'UserCountry_country_pn' => 'Pitcairn',
+ 'UserCountry_country_pr' => 'Puerto Rico',
+ 'UserCountry_country_ps' => 'Palestinian Territory',
+ 'UserCountry_country_pt' => 'Portugali',
+ 'UserCountry_country_pw' => 'Palau',
+ 'UserCountry_country_py' => 'Paraguay',
+ 'UserCountry_country_qa' => 'Qatar',
+ 'UserCountry_country_re' => 'Reunion Island',
+ 'UserCountry_country_ro' => 'Romania',
+ 'UserCountry_country_ru' => 'Venäjä',
+ 'UserCountry_country_rs' => 'Serbia',
+ 'UserCountry_country_rw' => 'Ruanda',
+ 'UserCountry_country_sa' => 'Saudiarabia',
+ 'UserCountry_country_sb' => 'Solomon Islands',
+ 'UserCountry_country_sc' => 'Seychelles',
+ 'UserCountry_country_sd' => 'Sudan',
+ 'UserCountry_country_se' => 'Ruotsi',
+ 'UserCountry_country_sf' => 'Suomi',
+ 'UserCountry_country_sg' => 'Singapore',
+ 'UserCountry_country_sh' => 'Saint Helena',
+ 'UserCountry_country_si' => 'Slovenia',
+ 'UserCountry_country_sj' => 'Svalbard',
+ 'UserCountry_country_sk' => 'Slovakia',
+ 'UserCountry_country_sl' => 'Sierra Leone',
+ 'UserCountry_country_sm' => 'San Marino',
+ 'UserCountry_country_sn' => 'Senegal',
+ 'UserCountry_country_so' => 'Somalia',
+ 'UserCountry_country_sr' => 'Suriname',
+ 'UserCountry_country_st' => 'Sao Tome and Principe',
+ 'UserCountry_country_su' => 'Entinen Neuvostoliitto',
+ 'UserCountry_country_sv' => 'El Salvador',
+ 'UserCountry_country_sy' => 'Syrian Arab Republic',
+ 'UserCountry_country_sz' => 'Swasimaa',
+ 'UserCountry_country_ta' => 'Tristan da Cunha',
+ 'UserCountry_country_tc' => 'Turks and Caicos Islands',
+ 'UserCountry_country_td' => 'Chad',
+ 'UserCountry_country_tf' => 'French Southern Territories',
+ 'UserCountry_country_tg' => 'Togo',
+ 'UserCountry_country_th' => 'Thaimaa',
+ 'UserCountry_country_tj' => 'Tajikistan',
+ 'UserCountry_country_tk' => 'Tokelau',
+ 'UserCountry_country_tl' => 'East Timor',
+ 'UserCountry_country_tm' => 'Turkmenistan',
+ 'UserCountry_country_tn' => 'Tunisia',
+ 'UserCountry_country_to' => 'Tonga',
+ 'UserCountry_country_tp' => 'Itä-Timor',
+ 'UserCountry_country_tr' => 'Turkki',
+ 'UserCountry_country_tt' => 'Trinidad ja Tobago',
+ 'UserCountry_country_tv' => 'Tuvalu',
+ 'UserCountry_country_tw' => 'Taiwan',
+ 'UserCountry_country_tz' => 'Tansania',
+ 'UserCountry_country_ua' => 'Ukraine',
+ 'UserCountry_country_ug' => 'Uganda',
+ 'UserCountry_country_uk' => 'Iso-Britannia',
+ 'UserCountry_country_um' => 'United States Minor Outlying Islands',
+ 'UserCountry_country_us' => 'Yhdysvallat',
+ 'UserCountry_country_uy' => 'Uruguay',
+ 'UserCountry_country_uz' => 'Uzbekistan',
+ 'UserCountry_country_va' => 'Vatikaani',
+ 'UserCountry_country_vc' => 'Saint Vincent and the Grenadines',
+ 'UserCountry_country_ve' => 'Venetsuela',
+ 'UserCountry_country_vg' => 'Virgin Islands, British',
+ 'UserCountry_country_vi' => 'Virgin Islands, U.S.',
+ 'UserCountry_country_vn' => 'Vietnam',
+ 'UserCountry_country_vu' => 'Vanuatu',
+ 'UserCountry_country_wf' => 'Wallis and Futuna',
+ 'UserCountry_country_ws' => 'Samoa',
+ 'UserCountry_country_ye' => 'Jemen',
+ 'UserCountry_country_yt' => 'Mayotte',
+ 'UserCountry_country_yu' => 'Jugoslavia',
+ 'UserCountry_country_za' => 'Etelä-Afrikka',
+ 'UserCountry_country_zm' => 'Sambia',
+ 'UserCountry_country_zr' => 'Zaire',
+ 'UserCountry_country_zw' => 'Zimbabwe',
+ 'UserCountry_continent_eur' => 'Eurooppa',
+ 'UserCountry_continent_afr' => 'Afrikka',
+ 'UserCountry_continent_asi' => 'Aasia',
+ 'UserCountry_continent_ams' => 'Etelä- ja Keski-Amerikka',
+ 'UserCountry_continent_amn' => 'Pohjois-Amerikka',
+ 'UserCountry_continent_oce' => 'Oseania',
+ 'VisitsSummary_VisitsSummary' => 'Yhteenveto käynneistä',
+ 'VisitsSummary_NbVisits' => '%s käyntiä',
+ 'VisitsSummary_NbUniqueVisitors' => '%s uniikia kävijää',
+ 'VisitsSummary_NbActions' => '%s toimintoa (katsottua sivua)',
+ 'VisitsSummary_TotalTime' => '%s aikaa käytetty sivuilla',
+ 'VisitsSummary_MaxNbActions' => '%s toimintoa maksimissaan yhdellä käynnillä',
+ 'VisitsSummary_NbVisitsBounced' => '%s lyhyttä käyntiä (vain yksi ladattu sivu)',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Muutos edellisen %s aikana',
+ 'VisitsSummary_Report' => 'Raportti',
+ 'VisitsSummary_GenerateTime' => '%s sekuntia sivun luomiseen',
+ 'VisitsSummary_GenerateQueries' => '%s kyselyä ajettu',
+ 'VisitsSummary_WidgetLastVisits' => 'Edelliset käynnit',
+ 'VisitsSummary_WidgetVisits' => 'Käyntien yleiskatsaus',
+ 'VisitsSummary_WidgetLastVisitors' => 'Edelliset uniikit kävijät',
+ 'VisitsSummary_WidgetOverviewGraph' => 'Yleiskatsaus graafilla',
+ 'VisitsSummary_SubmenuOverview' => 'Yleiskatsaus',
+ 'VisitFrequency_Evolution' => 'Muutos aikajaksolla',
+ 'VisitFrequency_ColumnReturningVisits' => 'Palaavat käynnit',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Toimintoja palaavilta käyttäjiltä',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Maksimimäärä toimintoja palaavalta käyttäjältä',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Palaavat käyttäjät käyttivät aikaa (sekuntia)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Lyhyitä käyntejä palaavilta käyttäjiltä',
+ 'VisitFrequency_ReturnVisits' => '%s palaavaa käyntiä',
+ 'VisitFrequency_ReturnActions' => '%s toimintoa palaavilta käyttäjiltä',
+ 'VisitFrequency_ReturnMaxActions' => '%s maksimimäärä toimintoja palaavalta kävijältä',
+ 'VisitFrequency_ReturnTotalTime' => '%s aikaa yhteensä palaavilla käynneillä',
+ 'VisitFrequency_ReturnBounceRate' => '%s palaavista käynneistä oli lyhyitä (vain yksi sivunlataus)',
+ 'VisitFrequency_WidgetOverview' => 'Yleiskatsaus yleisyydestä',
+ 'VisitFrequency_WidgetGraphReturning' => 'Palaavat käyttäjät',
+ 'VisitFrequency_SubmenuFrequency' => 'Yleisyys',
+ 'VisitTime_LocalTime' => 'Käyntejä (paikallinen aika)',
+ 'VisitTime_ServerTime' => 'Käyntejä (palvelimen aika)',
+ 'VisitTime_ColumnServerTime' => 'Palvelimen aika',
+ 'VisitTime_ColumnLocalTime' => 'Paikallinen aika',
+ 'VisitTime_WidgetLocalTime' => 'Käyntejä (paikallinen aika)',
+ 'VisitTime_WidgetServerTime' => 'Käyntejä (palvelimen aika)',
+ 'VisitTime_SubmenuTimes' => 'Ajat',
+ 'VisitTime_NHour' => '%sh',
+ 'VisitorInterest_VisitsPerDuration' => 'Käynnit pituuden mukaan',
+ 'VisitorInterest_VisitsPerNbOfPages' => 'Käynnit sivujen mukaan',
+ 'VisitorInterest_ColumnVisitDuration' => 'Käyntien kesto',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Sivuja / käynti',
+ 'VisitorInterest_WidgetLengths' => 'Käynnin pituus',
+ 'VisitorInterest_WidgetPages' => 'Sivuja / käynti',
+ 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Yleisyys & lojaalius',
+ 'VisitorInterest_PlusXMin' => '%s min',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
+ 'VisitorInterest_OnePage' => '1 sivu',
+ 'VisitorInterest_NPages' => '%s sivua',
+ 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
+ 'Login_LoginPasswordNotCorrect' => 'Käyttäjätunnus tai salasana väärin',
+ 'Login_Login' => 'Käyttäjätunnus',
+ 'Login_Password' => 'Salasana',
+ 'Login_PasswordRepeat' => 'Salasana (uudelleen)',
+ 'Login_ChangePassword' => 'Vaihda salasana',
+ 'Login_LoginOrEmail' => 'Käyttäjätunnus tai sähköposti',
+ 'Login_LogIn' => 'Kirjaudu sisään',
+ 'Login_Logout' => 'Kirjaudu ulos',
+ 'Login_LostYourPassword' => 'Unohtuiko salasana?',
+ 'Login_RemindPassword' => 'Salasanamuistutus',
+ 'Login_PasswordResetToken' => 'Salasanan nollaus',
+ 'Login_PasswordReminder' => 'Kirjoita käyttäjätunnus tai sähköpostiosoite. Saat uuden salasanan sähköpostilla.',
+ 'Login_PasswordsDoNotMatch' => 'Salasanat eivät täsmää.',
+ 'Login_PasswordSuccessfullyChanged' => 'Salasana vaihdettiin onnistuneesti!',
+ 'Login_InvalidUsernameEmail' => 'Virheellinen käyttäjätunnus ja/tai sähköpostiosoite',
+ 'Login_InvalidOrExpiredToken' => 'Virheellinen tai vanhentunut tunnistautuminen',
+ 'Login_MailTopicPasswordRecovery' => 'Salasanan palautus',
+ 'Login_PasswordSent' => 'Salasana on lähetetty. Tarkista sähköpostisi.',
+ 'Login_ContactAdmin' => 'Mahdollisia syitä: palvelin ei välttämättä salli sähköpostien lähetystä (mail()-funktiota).<br/>Ota yhteyttä Piwikin ylläpitäjään.',
+ 'UsersManager_UsersManagement' => 'Käyttäjien hallinta',
+ 'UsersManager_UsersManagementMainDescription' => 'Lisää uusia käyttäjiä tai päivitä olemassaolevia. Voit asettaa oikeudet alla.',
+ 'UsersManager_ManageAccess' => 'Hallitse oikeuksia',
+ 'UsersManager_MainDescription' => 'Määrittele, millä käyttäjillä on oikeus verkkosivulle. Voit asettaa oikeuksia kaikille sivuille yhdellä kertaa.',
+ 'UsersManager_Sites' => 'Sivut',
+ 'UsersManager_AllWebsites' => 'Kaikki sivut',
+ 'UsersManager_ApplyToAllWebsites' => 'Päivitä kaikille sivuille',
+ 'UsersManager_User' => 'Käyttäjä',
+ 'UsersManager_PrivNone' => 'Ei käyttöoikeutta',
+ 'UsersManager_PrivView' => 'Katsomisoikeus',
+ 'UsersManager_PrivAdmin' => 'Hallinnointioikeus',
+ 'UsersManager_ChangeAllConfirm' => 'Haluatko varmasti vaihtaa käyttäjän "%s" oikeudet kaikille sivuille?',
+ 'UsersManager_Login' => 'Tunnus',
+ 'UsersManager_Password' => 'Salasana',
+ 'UsersManager_Email' => 'Sähköposti',
+ 'UsersManager_Alias' => 'Alias',
+ 'UsersManager_Edit' => 'Muokkaa',
+ 'UsersManager_AddUser' => 'Lisää uusi käyttäjä',
+ 'UsersManager_MenuUsers' => 'Käyttäjät',
+ 'UsersManager_DeleteConfirm_js' => 'Haluatko varmasti poistaa käyttäjän %s?',
+ 'UsersManager_ExceptionLoginExists' => "Tunnus '%s' on jo olemassa.",
+ 'UsersManager_ExceptionEmailExists' => "Käyttäjä sähköpostilla '%s' on jo olemassa.",
+ 'UsersManager_ExceptionInvalidLoginFormat' => "Tunnus täytyy olla %s-%s merkkiä pitkä ja saa siältää vain kirjaimia, numeroita ja merkkejä '_', '-' ja '.'",
+ 'UsersManager_ExceptionInvalidPassword' => 'Salasanan pitää olla 6-26 merkkiä pitkä.',
+ 'UsersManager_ExceptionInvalidEmail' => 'Sähköposti ei ole kelvollinen.',
+ 'UsersManager_ExceptionDeleteDoesNotExist' => "Käyttäjää '%s' ei ole eikä sitä siksi voida poistaa.",
+ 'UsersManager_ExceptionAdminAnonymous' => 'Et voi sallia ylläpito-oikeuksia anonyymikäyttäjälle.',
+ 'UsersManager_ExceptionEditAnonymous' => 'Anonyymikäyttäjää ei voi muokata tai poistaa. Se on Piwikin sisäinen tunnus käyttäjälle, joka ei ole kirjautunut sisään. Voit esimerkiksi julkaista tilastoja kaikille sallimalla anonyymikäyttäjälle katsomisoikeuden.',
+ 'UsersManager_ExceptionSuperUser' => 'Pyydetty käyttäjä on pääkäyttäjä. Pääkäyttäjää ei voi muokata tai poistaa API:n kautta. Voit manuaalisesti muokata pääkäyttäjää Piwikin asetustiedostosta.',
+ 'UsersManager_ExceptionUserDoesNotExist' => "Käyttäjää '%s' ei ole olemassa.",
+ 'UsersManager_ExceptionAccessValues' => 'Oikeuksien täytyy olla yksi seuraavista arvoista: [ %s ]',
+ 'SitesManager_Sites' => 'Sivut',
+ 'SitesManager_WebsitesManagement' => 'Verkkosivujen hallinta',
+ 'SitesManager_MainDescription' => 'Verkkosivujen analysointi tarvitsee verkkosivuja! Lisää, päivitä ja poista verkkosivuja ja katso sivuille lisättävä Javascript-koodi.',
+ 'SitesManager_JsTrackingTag' => 'JavaScript-seurantakoodi',
+ 'SitesManager_JsTrackingTagHelp' => 'Lisää tämä javascript-seurantakoodi kaikille seurattaville sivuille',
+ 'SitesManager_ShowTrackingTag' => 'näytä seurantakoodi',
+ 'SitesManager_NoWebsites' => 'Sinulla ei ole yhtään verkkosivua hallinnoitavana.',
+ 'SitesManager_AddSite' => 'Lisää uusi sivu',
+ 'SitesManager_Id' => 'Id',
+ 'SitesManager_Name' => 'Nimi',
+ 'SitesManager_Urls' => 'URL',
+ 'SitesManager_MenuSites' => 'Sivut',
+ 'SitesManager_DeleteConfirm_js' => 'Haluatko varmasti poistaa sivun %s?',
+ 'SitesManager_ExceptionDeleteSite' => 'Sivua ei voi poistaa, sillä se on ainoa rekisteröity sivu. Lisää ensin uusi sivu.',
+ 'SitesManager_ExceptionNoUrl' => 'Sivuilla täytyy olla vähintään yksi verkkosivu.',
+ 'SitesManager_ExceptionEmptyName' => 'Sivun nimi ei voi olla tyhjä.',
+ 'SitesManager_ExceptionInvalidUrl' => "Sivun url '%s' ei ole oikein muotoiltu URL.",
+ 'Installation_Installation' => 'Asennus',
+ 'Installation_InstallationStatus' => 'Asennuksen tila',
+ 'Installation_PercentDone' => '%s %% valmiina',
+ 'Installation_NoConfigFound' => "Piwikin asetustiedostoa ei löydy ja yrität siirtyä Piwikin sivuille.<br /><b>&nbsp;&nbsp;&raquo; Voit <a href='index.php'>asentaa Piwikin nyt</a></b><br /><small>Jos asensit Piwikin aikaisemmin ja tietokannassa on jo tietoja, älä murehdi, tietoja ei hävitetä.</small>",
+ 'Installation_DatabaseSetup' => 'Tietokannan asetukset',
+ 'Installation_DatabaseErrorConnect' => 'Virhe tietokantayhteyden avaamisessa',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'Tietokantayhteys ei ole UTF8-muodossa',
+ 'Installation_JsTag' => 'Javascript-koodi',
+ 'Installation_JsTagHelp' => '<p>Lisää tämä koodi kaikille sivuillesi laskeaksesi kävijät.</p><p>Sivujen ei tarvitse olla tehty PHP:llä. Piwik toimii kaikilla sivuilla (esim. HTML, ASP, Perl tai mikä tahansa muu kieli).</p><p>Tässä on koodi, joka sivuille pitää lisätä: (kopioi ja liitä kaikille sivuille)</p>',
+ 'Installation_JsTagQuicHelpk' => 'Pikaopas',
+ 'Installation_JsTagArchivingHelp' => 'Korkean liikenteen sivuille on suositeltavaa <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">ottaa käyttöön arkistointi</a>, jotta Piwik toimisi nopeasti.',
+ 'Installation_Congratulations' => 'Onnittelut',
+ 'Installation_CongratulationsHelp' => '<p>Onnittelut! Piwikin asennus on valmis.</p><p>Varmista, että javascript-koodi on lisätty sivuille ja odota ensimmäisiä vierailijoita!</p>',
+ 'Installation_ContinueToPiwik' => 'Jatka Piwikiin',
+ 'Installation_SetupWebsite' => 'Lisää verkkosivu',
+ 'Installation_SetupWebsiteError' => 'Virhe verkkosivun lisäämisessä',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Sivu %s luotiin onnistuneesti!',
+ 'Installation_GeneralSetup' => 'Yleiset asetukset',
+ 'Installation_GeneralSetupSuccess' => 'Yleiset asetukset asetettu onnistuneesti',
+ 'Installation_SuperUserLogin' => 'pääkäyttäjän tunnus',
+ 'Installation_Password' => 'salasana',
+ 'Installation_PasswordRepeat' => 'salasana (uudelleen)',
+ 'Installation_Email' => 'sähköposti',
+ 'Installation_SecurityNewsletter' => 'lähetä sähköpostia Piwikin suurista päivityksistä ja turvallisuushälytyksistä',
+ 'Installation_CommunityNewsletter' => 'lähetä sähköpostia kaikista päivityksistä (uusista lisäosista, ominaisuuksista jne.)',
+ 'Installation_PasswordDoNotMatch' => 'salasanat eivät täsmää',
+ 'Installation_SubmitGo' => 'Mene!',
+ 'Installation_Requirements' => 'Piwikin vaatimukset',
+ 'Installation_Optional' => 'Optionaalinen',
+ 'Installation_Legend' => 'Kuvaus',
+ 'Installation_Extension' => 'lisäosa',
+ 'Installation_SystemCheck' => 'Järjestelmän asetukset',
+ 'Installation_SystemCheckPhp' => 'PHP:n versio',
+ 'Installation_SystemCheckExtensions' => 'Muut vaaditut lisäosat',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik vaatii joko mysqli-lisäosan tai sekä PDO- että pdo_mysql-lisäosat..',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'Linux-palvelimella voit kääntää PHP:n seuraavilla asetuksilla: %s
+Lisää php.ini-tiedostoon seuraavat rivit: %s',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Lisätietoa: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> ja <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'Windows-palvelimella php.ini-tiedostoon tulee lisätä seuraavat rivit: %s',
+ 'Installation_SystemCheckSplHelp' => 'PHP pitää olla asennettuna "Standard PHP Library (SPL)"-asetuksen kanssa.',
+ 'Installation_SystemCheckZlibHelp' => 'PHP pitää olla asennettuna zlib-lisäosan kanssa, --with-zlib.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'PHP pitää olla asennettuna json- tai xml-lisäosan kanssa.',
+ 'Installation_SystemCheckJsonSite' => 'Lisätietoa: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Osa kolmansien osapuolten lisäosista ja kehityskirjastoista vaatii "xml"-lisäosan.',
+ 'Installation_SystemCheckXmlSite' => 'Lisätietoa: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckWriteDirs' => 'Tiedostot kirjoitusoikeudella',
+ 'Installation_SystemCheckWriteDirsHelp' => 'Aja Linux-järjestelmässä seuraavat komennot:',
+ 'Installation_SystemCheckMemoryLimit' => 'Muistirajoitus',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'Jos verkkosivuilla on paljon liikennettä, arkistointiprosessi saattaa vaatia enemmän muistia.<br />Muokkaa asetusta memory_limit php.ini-tiedostossa tarvittaessa.',
+ 'Installation_SystemCheckOpenURL' => 'Avaa osoite',
+ 'Installation_SystemCheckOpenURLHelp' => 'Uutiskirje, päivitysilmoitukset ja yhden klikkauksen päivitykset vaativat "curl"-lisäosan ja asetuksen allow_url_fopen=On tai funktion fsockopen().',
+ 'Installation_SystemCheckGD' => 'GD &gt; 2.x (grafiikat)',
+ 'Installation_SystemCheckGDHelp' => 'Pienet graafit eivät toimi.',
+ 'Installation_SystemCheckFunctions' => 'Vaaditut funktiot',
+ 'Installation_SystemCheckTimeLimitHelp' => 'Jos verkkosivuilla on paljon liikennettä, arkistointiprosessi saattaa vaatia enemmän aikaa.<br />Muokkaa asetusta max_execution_time php.ini-tiedostossa tarvittaessa.',
+ 'Installation_SystemCheckMailHelp' => 'Palautetta ja unohtuneiden salasanojen muistutuksia ei voida lähettää ilman funktiota mail().',
+ 'Installation_SystemCheckError' => 'Tapahtui virhe - täytyy korjata ennen jatkamista',
+ 'Installation_SystemCheckWarning' => 'Piwik toimii normaalisti, mutta osa ominaisuuksista puuttuu',
+ 'Installation_Tables' => 'Luodaan taulut',
+ 'Installation_TablesWithSameNamesFound' => 'Osalla %s tauluista tietokannassa %s on sama nimi kuin tauluilla, joita Piwik yrittää luoda.',
+ 'Installation_TablesFound' => 'Seuraavat taulut löytyivät tietokannasta',
+ 'Installation_TablesWarningHelp' => 'Valitse joko nykyisten taulujen käyttö tai luo taulut uudelleen (vanhat tiedot menetetään).',
+ 'Installation_TablesReuse' => 'Käytä nykyisiä tauluja',
+ 'Installation_TablesDelete' => 'Poista löydetyt taulut',
+ 'Installation_TablesDeletedSuccess' => 'Löytyneet taulut on poistettu onnistuneesti',
+ 'Installation_TablesCreatedSuccess' => 'Taulut luotu onnistuneesti!',
+ 'Installation_DatabaseCreatedSuccess' => 'Tietokanta %s luotu onnistuneesti!',
+ 'Installation_GoBackAndDefinePrefix' => 'Siirry takaisin ja määritä alkuliite (prefix) Piwikin tauluille',
+ 'Installation_ConfirmDeleteExistingTables' => 'Haluatko varmasti poistaa seuraavat taulut tietokannasta: %s? VAROITUS: TAULUJEN TIETOJA EI VOI PALAUTTAA EIKÄ POISTAMISTA VOI KUMOTA!',
+ 'Installation_Welcome' => 'Tervetuloa!',
+ 'Installation_WelcomeHelp' => '<p>Piwik on vapaan lähdekoodin verkkosivujen analysointityökalu, joka tekee kävijöiden tietojen keräämisen ja analysoinnin helpoksi.</p><p>Tämä prosessi on jaettu %s helppoon osaan ja vie aikaa noin viisi minuuttia.</p>',
+ 'Installation_ErrorInvalidState' => 'Virhe: yrität ohittaa vaiheen asennusprosessista tai keksit (cookies) ei ole sallittu. %sVarmista, että keksit on sallittu%s ja mene takaisin %s asennuksen ensimmäiselle sivulle %s.',
+ 'Provider_WidgetProviders' => 'Palveluntarjoajat',
+ 'Provider_ColumnProvider' => 'Palveluntarjoajat',
+ 'Provider_SubmenuLocationsProvider' => 'Sijainnit & palveluntarjoajat',
+ 'Goals_ColumnConversions' => 'Muutokset',
+ 'Goals_ColumnConversionRate' => 'Muutosnopeus',
+ 'Goals_ColumnRevenue' => 'Tulot',
+ 'DBStats_DatabaseUsage' => 'Tietokannan käyttö',
+ 'DBStats_MainDescription' => 'Piwik tallentaa kaikki tiedot MySQL-tietokantaan. Piwikin taulut käyttävät %s.',
+ 'DBStats_Table' => 'Taulu',
+ 'DBStats_RowNumber' => 'Rivien määrä',
+ 'DBStats_DataSize' => 'Tietojen koko',
+ 'DBStats_IndexSize' => 'Indeksien koko',
+ 'DBStats_TotalSize' => 'Koko yhteensä',
+ 'TranslationsAdmin_MenuTranslations' => 'Käännökset',
+ 'TranslationsAdmin_MenuLanguages' => 'Kielet',
+ 'TranslationsAdmin_Plugin' => 'Lisäosa',
+ 'TranslationsAdmin_Definition' => 'Kuvaus',
+ 'TranslationsAdmin_DefaultString' => 'Oletusmerkkijono (englanniksi)',
+ 'TranslationsAdmin_TranslationString' => 'Käännettävä merkkijono (nykyinen kieli: %s)',
+ 'TranslationsAdmin_Translations' => 'Käännökset',
+ 'TranslationsAdmin_FixPermissions' => 'Tarkista tiedostojärjestelmän oikeudet',
+ 'TranslationsAdmin_AvailableLanguages' => 'Saatavilla olevat kielet',
+ 'TranslationsAdmin_AddLanguage' => 'Lisää kieli',
+ 'TranslationsAdmin_LanguageCode' => 'Kielikoodi',
+ 'TranslationsAdmin_Export' => 'Vie kieli',
+ 'TranslationsAdmin_Import' => 'Tuo kieli'
);
+?>
diff --git a/lang/fr.php b/lang/fr.php
index 6d5f39b2d0..5c907edab7 100644
--- a/lang/fr.php
+++ b/lang/fr.php
@@ -1,4 +1,7 @@
<?php
+
+setlocale(LC_TIME, 'fr_FR.UTF-8');
+
$translations = array(
'General_Locale' => 'fr_FR.UTF-8',
'General_TranslatorName' => 'Vincent BIRET',
@@ -7,13 +10,17 @@ $translations = array(
'General_OriginalLanguageName' => 'Français',
'General_HelloUser' => 'Bonjour, %s',
'General_OpenSourceWebAnalytics' => 'Analyse web libre',
- 'General_YourDashboard' => 'Votre tableau de bord',
+ 'General_Dashboard' => 'Tableau de bord',
+ 'General_DashboardForASpecificWebsite' => 'Tableau de bord pour un site particulier',
+ 'General_MultiSitesSummary' => 'Tous les sites web',
+ 'General_AllWebsitesDashboard' => 'Tableau de bord de tous les sites',
'General_API' => 'API',
'General_Widgets' => 'Widgets',
'General_Settings' => 'Paramètres',
'General_GiveUsYourFeedback' => 'Envoyez-nous vos commentaires !',
'General_Unknown' => 'Inconnu',
'General_Required' => '%s requis',
+ 'General_NotValid' => '%s n\'est pas valide',
'General_Error' => 'Erreur',
'General_Warning' => 'Attention',
'General_BackToHomepage' => 'Retour à la page d\'accueil Piwik',
@@ -24,9 +31,13 @@ $translations = array(
'General_Ok' => 'Ok',
'General_Close' => 'Fermer',
'General_Logout' => 'Déconnexion',
+ 'General_Username' => 'Nom d\'utilisateur',
'General_Done' => 'Fait',
+ 'General_Details' => 'Détails',
+ 'General_Default' => 'Par défaut',
'General_LoadingData' => 'Chargement des données...',
'General_Loading' => 'Chargement...',
+ 'General_YourChangesHaveBeenSaved' => 'Vos modifications ont été enregistrées.',
'General_ErrorRequest' => 'Oups ! Problème rencontré durant la requête, veuillez réessayer.',
'General_Next' => 'Suivant',
'General_Previous' => 'Précédent',
@@ -37,9 +48,14 @@ $translations = array(
'General_TagCloud' => 'Nuage de tags',
'General_VBarGraph' => 'Histogramme vertical',
'General_Export' => 'Exporter',
- 'General_ExportAsImage' => 'Exporter au format Image',
+ 'General_ExportAsImage_js' => 'Exporter au format Image',
'General_SaveImageOnYourComputer' => 'Pour enregistrer l\'image sur votre ordinateur, faites un clic droit sur l\'image et sélectionnez "Enregistrer l\'image sous..."',
'General_Refresh' => 'Rafraîchir la page',
+ 'General_Today' => 'Aujourd\'hui',
+ 'General_Yesterday' => 'Hier',
+ 'General_CurrentWeek' => 'Semaine courante',
+ 'General_CurrentMonth' => 'Mois courant',
+ 'General_CurrentYear' => 'Année courante',
'General_Visitors' => 'Visiteurs',
'General_ColumnNbUniqVisitors' => 'Visiteurs uniques',
'General_ColumnNbVisits' => 'Visites',
@@ -55,7 +71,19 @@ $translations = array(
'General_ColumnValuePerVisit' => 'Valeur par Visite',
'General_ColumnVisitsWithConversions' => 'Visites avec Conversions',
'General_Save' => 'Enregistrer',
- 'General_Website' => 'Site :',
+ 'General_ForExampleShort' => 'ex.',
+ 'General_Website' => 'Site',
+ 'General_GeneralSettings' => 'Paramètres généraux',
+ 'General_AllowPiwikArchivingToTriggerBrowser' => 'Autoriser l\'archivage de Piwik à se déclencher lorsque les rapports sont visionnés depuis le navigateur',
+ 'General_ArchivingInlineHelp' => 'Pour les site à trafic moyen et fort il est recommandé de désactiver l\'archivage de Piwik depuis le navigateur. Nous vous recommandons de mettre en place une tâche cron qui génère les rapports toutes les heures.',
+ 'General_ArchivingTriggerDescription' => 'Recommandé pour les installations importantes de Piwik, vous devriez %smettre en place une tâche cron%s pour générer les rapports automatiquement.',
+ 'General_SeeTheOfficialDocumentationForMoreInformation' => 'Consultez la %s documentation officielle%s pour plus d\'information.',
+ 'General_ReportsForTodayWillBeProcessedAtMostEvery' => 'Les rapports d\'aujourd\'hui seront traités au plus tous (toutes) les',
+ 'General_NSeconds' => '%s secondes',
+ 'General_SmallTrafficYouCanLeaveDefault' => 'Pour les sites à faible trafic, vous pouvez laisser le délais %s secondes par défaut, et ainsi accéder aux rapports en temps réel.',
+ 'General_MediumToHighTrafficItIsRecommendedTo' => 'Pour les sites à trafic moyen, nous vous recommandons de générer les rapports tout au plus chaque demie-heure (%s secondes).',
+ 'General_RequiresFlash' => 'L\'affichage des Graphs dans Piwik requiert Flash',
+ 'General_GraphHelp' => 'Plus d\'informations à propos de l\'affichage des graphs dans Piwik.',
'General_NoDataForGraph' => 'Aucune donnée pour ce graphique',
'General_NoDataForTagCloud' => 'Aucune donnée pour ce nuage de tags.',
'General_DisplayNormalTable' => 'Voir tableau normal',
@@ -63,6 +91,7 @@ $translations = array(
'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s est un projet collaboratif. %s Si vous aimez Piwik, vous pouvez nous aider! Allez voir %s Comment contribuer à Piwik?%s ',
'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Vous êtes dans la démo de %s; %stéléchargez%s la version complète ! Visitez %s.',
'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s est maintenant disponible. %s Merci de mettre à jour!%s (voir %s les modifications%s).',
+ 'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin' => '%s est disponible. Merci de prévenir l\'administrateur du site.',
'General_BackToPiwik' => 'Retourner à Piwik',
'General_ShortMonth_1' => 'Jan',
'General_ShortMonth_2' => 'Fév',
@@ -102,34 +131,46 @@ $translations = array(
'General_LongDay_5' => 'Vendredi',
'General_LongDay_6' => 'Samedi',
'General_LongDay_7' => 'Dimanche',
- 'Core_ExceptionDatabaseVersion' => 'Votre version de %s est %s mais Piwik a besoin au minimum de la version %s.',
- 'CorePluginsAdmin_Plugins' => 'Plugins',
- 'CorePluginsAdmin_PluginsManagement' => 'Gestionnaire de plugins',
- 'CorePluginsAdmin_MainDescription' => 'Les plugins étendent et ajoutent des fonctionnalités à Piwik. Une fois un plugin installé, vous pouvez l\'activer ou le désactiver ici.',
- 'CorePluginsAdmin_Plugin' => 'Plugin',
- 'CorePluginsAdmin_Version' => 'Version',
- 'CorePluginsAdmin_Description' => 'Description',
- 'CorePluginsAdmin_Status' => 'État',
- 'CorePluginsAdmin_Action' => 'Action',
- 'CorePluginsAdmin_PluginHomepage' => 'Page d\'accueil du plugin',
- 'CorePluginsAdmin_Activated' => 'Activé',
- 'CorePluginsAdmin_Active' => 'Actif',
- 'CorePluginsAdmin_Inactive' => 'Inactif',
- 'CorePluginsAdmin_ActivatedHelp' => 'Ce plugin ne peut être désactivé',
- 'CorePluginsAdmin_Deactivate' => 'Désactiver',
- 'CorePluginsAdmin_Activate' => 'Activer',
- 'CorePluginsAdmin_MenuPlugins' => 'Plugins',
+ 'General_ExceptionDatabaseVersion' => 'Votre version de %s est %s mais Piwik a besoin au minimum de la version %s.',
+ 'General_ExceptionIncompatibleClientServerVersions' => 'La version de votre client %1$s est %2$s ce qui est incompatible avec le serveur de version %3$s.',
+ 'General_ExceptionMissingFile' => 'Fichier manquant: %s',
+ 'General_ExceptionFilesizeMismatch' => 'Différence de taille de fichier : %1$s (longueur attendue: %2$s, rencontrée: %3$s)',
+ 'General_ExceptionFileIntegrity' => 'Echec du contrôle d\'intégrité : %s',
+ 'General_ExceptionNonceMismatch' => 'Impossible de vérifier le token de sécurité pour ce formulaire.',
+ 'General_WarningFileIntegritySkipped' => 'Environnement de développement détecté. Contrôle d\'intégrité ignoré.',
+ 'General_WarningFileIntegrityNoManifest' => 'Le contrôle d\'intégrité n\'a pu être effectué à cause du fichier manifest.inc.php qui est manquant.',
+ 'General_WarningFileIntegrityNoMd5file' => 'Le contrôle d\'intégrité n\'a pu être effectué à cause de la fonction md5_file() qui est manquante.',
+ 'General_FileIntegrityWarningExplanation' => 'Le contrôle d\'intégrité a échoué et a rapporté des erreurs. Cela est probablement du à un envoi de fichier partiel ou en échec des fichiers de Piwik. Vous devriez envoyer de nouveau les fichiers de Piwik et rafraichir cette page jusqu\'à ce qu\'elle n\'affiche plus aucune erreur.',
+ 'Actions_PluginDescription' => 'Effectue des rapports sur les affichages de pages, les liens sortants et les téléchargements. Le suivi des liens sortants et des téléchargements est automatique!',
+ 'Actions_Actions' => 'Actions',
+ 'Actions_SubmenuPages' => 'Pages',
+ 'Actions_SubmenuPageTitles' => 'Titres des pages',
+ 'Actions_SubmenuOutlinks' => 'Liens sortants',
+ 'Actions_SubmenuDownloads' => 'Téléchargements',
+ 'Actions_ColumnClicks' => 'Clics',
+ 'Actions_ColumnUniqueClicks' => 'Clics uniques',
+ 'Actions_ColumnDownloads' => 'Téléchargements',
+ 'Actions_ColumnUniqueDownloads' => 'Téléchargements uniques',
+ 'Actions_ColumnPageName' => 'Nom de la page',
+ 'Actions_ColumnPageURL' => 'Url de la page',
+ 'Actions_ColumnClickedURL' => 'Url cliquées',
+ 'Actions_ColumnDownloadURL' => 'Url de téléchargement',
+ 'AnonymizeIP_PluginDescription' => 'Masque les adresses IP des visiteurs pour remplir les conditions légales et politiques locales.',
+ 'API_PluginDescription' => 'Toutes les données de Piwik sont disponibles au travers de simples APIs. Ce plugin est le point d\'entrée du web service, ainsi vous pouvez obtenir vos données Statistiques Web en xml, json, php, csv, etc.',
'API_QuickDocumentation' => '<h2>Documentation rapide de l\'API</h2><p>Si vous n\'avez pas de données pour ajourd\'hui, vous pouvez d\'abord <a href=\'misc/generateVisits.php\' target=_blank>générer des données</a> en utilisant le Générateur de Visites.</p><p>Vous pouvez essayer les différents formats disponibles pour chaque méthode. Il est très facile d\'extraire n\'importe quelle donnée que vous voulez de Piwik!</p><p><b>Pour plus d\'informations visitez la <a href=\'http://dev.piwik.org/trac/wiki/API\'>Documentation officielle de l\'API</a> or the <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>Référence API</a>.</b></P><h2>Identification</h2><p>Si vous voulez <b>utiliser les données dans vos scripts, dans une crontab, etc. </b> vous devez ajouter le paramètre <code><u>&token_auth=%s</u></code> to the API calls URLs that require authentication.</p><p>Cette token_auth est aussi secrètes que votre nom d\'utilisateur ou votre mot de passe, <b>ne la partagez pas!</p>',
'API_LoadedAPIs' => '%s API chargées avec succès',
- 'CoreHome_NoPrivileges' => 'Vous êtes connecté en tant que \'%s\' mais il semble que vous n\'ayez aucune permission dans Piwik.<br />Demandez à votre administrateur Piwik de vous accorder l\'accès type \'view\' à un site Internet.',
- 'CoreHome_JavascriptDisabled' => 'JavaScript doit être activé dans votre navigateur pour pouvoir utiliser Piwik en mode standard.<br />Il semble que JavaScript soit désactivé ou qu\'il ne soit pas supporté par votre navigateur.<br />Pour utiliser Piwik en mode standard activez JS via les options de votre navigateur et essayez à nouveau.<br />',
- 'CoreHome_TableNoData' => 'Aucune donnée pour ce tableau.',
- 'CoreHome_CategoryNoData' => 'Aucune donnée pour cette catégorie. Essayez en cliquant sur "Inclure toute la population".',
- 'CoreHome_ShowJSCode' => 'Afficher le tag JavaScript à insérer',
+ 'CoreAdminHome_PluginDescription' => 'Zone d\'administration de Piwik.',
+ 'CoreAdminHome_MenuGeneralSettings' => 'Paramètres généraux',
+ 'CoreHome_PluginDescription' => 'Structure des rapports statistiques web.',
+ 'CoreHome_NoPrivileges' => 'Vous êtes connecté en tant que \'%s\' mais vous n\'avez apparemment aucune permission de définie dans Piwik.<br />Demandez à votre administrateur Piwik de vous donner l\'accès \'voir\' à un site web.',
+ 'CoreHome_JavascriptDisabled' => 'JavaScript doit être activé pour que vous puissiez utiliser Piwik de manière basique.<br />Cependant, il semble que JasvaScript ne soit pas supporté ou soit désactivé sur votre navigateur.<br />Pour utiliser l\'interface basique, activez JavaScript en modifiant les options de votre navigateur, ensuite %1$sessayez encore%2$s.<br />',
+ 'CoreHome_TableNoData' => 'Aucune donnée pour cette table.',
+ 'CoreHome_CategoryNoData' => 'Aucune donnée pour cette catégorie. Essayez "d\'inclure toute la population".',
+ 'CoreHome_ShowJSCode' => 'Afficher le code JavaScript à insérer',
'CoreHome_IncludeAllPopulation_js' => 'Inclure toute la population',
- 'CoreHome_ExcludeLowPopulation_js' => 'Exclure les petites populations des statistiques',
- 'CoreHome_PageOf_js' => '%s de %s',
- 'CoreHome_Loading_js' => 'Chargement...',
+ 'CoreHome_ExcludeLowPopulation_js' => 'Exclure les populations mineures',
+ 'CoreHome_PageOf_js' => '%1$s de %2$s',
+ 'CoreHome_Loading_js' => 'Chargement en cours...',
'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
'CoreHome_PeriodDay' => 'Jour',
'CoreHome_PeriodWeek' => 'Semaine',
@@ -137,7 +178,7 @@ $translations = array(
'CoreHome_PeriodYear' => 'Année',
'CoreHome_PeriodDays' => 'jours',
'CoreHome_PeriodWeeks' => 'semaines',
- 'CoreHome_PeriodMonths' => 'mois',
+ 'CoreHome_PeriodMonths' => 'moirs',
'CoreHome_PeriodYears' => 'années',
'CoreHome_DaySu_js' => 'Di',
'CoreHome_DayMo_js' => 'Lu',
@@ -146,6 +187,32 @@ $translations = array(
'CoreHome_DayTh_js' => 'Je',
'CoreHome_DayFr_js' => 'Ve',
'CoreHome_DaySa_js' => 'Sa',
+ 'CoreHome_ShortDay_1_js' => 'Dim',
+ 'CoreHome_ShortDay_2_js' => 'Lun',
+ 'CoreHome_ShortDay_3_js' => 'Mar',
+ 'CoreHome_ShortDay_4_js' => 'Mer',
+ 'CoreHome_ShortDay_5_js' => 'Jeu',
+ 'CoreHome_ShortDay_6_js' => 'Ven',
+ 'CoreHome_ShortDay_7_js' => 'Sam',
+ 'CoreHome_LongDay_1_js' => 'Dimanche',
+ 'CoreHome_LongDay_2_js' => 'Lundi',
+ 'CoreHome_LongDay_3_js' => 'Mardi',
+ 'CoreHome_LongDay_4_js' => 'Mercredi',
+ 'CoreHome_LongDay_5_js' => 'Jeudi',
+ 'CoreHome_LongDay_6_js' => 'Vendredi',
+ 'CoreHome_LongDay_7_js' => 'Samedi',
+ 'CoreHome_ShortMonth_1_js' => 'Jan',
+ 'CoreHome_ShortMonth_2_js' => 'Fév',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Avr',
+ 'CoreHome_ShortMonth_5_js' => 'Mai',
+ 'CoreHome_ShortMonth_6_js' => 'Jun',
+ 'CoreHome_ShortMonth_7_js' => 'Jul',
+ 'CoreHome_ShortMonth_8_js' => 'Aoû',
+ 'CoreHome_ShortMonth_9_js' => 'Sep',
+ 'CoreHome_ShortMonth_10_js' => 'Oct',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Déc',
'CoreHome_MonthJanuary_js' => 'Janvier',
'CoreHome_MonthFebruary_js' => 'Février',
'CoreHome_MonthMarch_js' => 'Mars',
@@ -158,18 +225,41 @@ $translations = array(
'CoreHome_MonthOctober_js' => 'Octobre',
'CoreHome_MonthNovember_js' => 'Novembre',
'CoreHome_MonthDecember_js' => 'Décembre',
- 'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; Mise à jour',
+ 'CorePluginsAdmin_PluginDescription' => 'Interface d\'administration des plugins.',
+ 'CorePluginsAdmin_Plugins' => 'Plugins',
+ 'CorePluginsAdmin_PluginsManagement' => 'Gestionnaire de plugins',
+ 'CorePluginsAdmin_MainDescription' => 'Les plugins étendent et ajoutent des fonctionnalités à Piwik. Une fois un plugin installé, vous pouvez l\'activer ou le désactiver ici.',
+ 'CorePluginsAdmin_Plugin' => 'Plugin',
+ 'CorePluginsAdmin_Version' => 'Version',
+ 'CorePluginsAdmin_Description' => 'Description',
+ 'CorePluginsAdmin_Status' => 'État',
+ 'CorePluginsAdmin_Action' => 'Action',
+ 'CorePluginsAdmin_PluginHomepage' => 'Page d\'accueil du plugin',
+ 'CorePluginsAdmin_Activated' => 'Activé',
+ 'CorePluginsAdmin_Active' => 'Actif',
+ 'CorePluginsAdmin_Inactive' => 'Inactif',
+ 'CorePluginsAdmin_ActivatedHelp' => 'Ce plugin ne peut être désactivé',
+ 'CorePluginsAdmin_Deactivate' => 'Désactiver',
+ 'CorePluginsAdmin_Activate' => 'Activer',
+ 'CorePluginsAdmin_MenuPlugins' => 'Plugins',
+ 'CoreUpdater_PluginDescription' => 'Mécanisme de mise à jour Piwik',
+ 'CoreUpdater_UpdateTitle' => 'Mise à jour',
'CoreUpdater_DatabaseUpgradeRequired' => 'Mise à jour de la base de données requise',
'CoreUpdater_YourDatabaseIsOutOfDate' => 'Votre base de données est expirée et doit être mise à jour avant de pouvoir continuer.',
'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'La base de données de Piwik sera mise à jour depuis la version %s vers la version %s.',
'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Les plugins suivants seront mis à jour : %s.',
- 'CoreUpdater_TheUpgradeProcessMayFail' => 'Si votre base de données Piwik est trop volumineuse, la mise à jour pourra être trop longue pour l\'effectuer depuis le navigateur. dans ce cas exécutez depuis la ligne de commande : <code>$ php path/to/piwik/index.php</code>',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Note importante pour les installations Piwik de taille importante',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'Si votre base de données Piwik est trop volumineuse, la mise à jour pourra être trop longue pour l\'effectuer depuis le navigateur. dans ce cas exécutez depuis la ligne de commande : %s',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => 'Si vous n\'aviez pas la possibilité d\'utiliser la console (CLI) et si Piwik échouait à se mettre à jour (à cause du délais d\'expiration de la base de données, du navigateur ou n\'importe quel autre problème), vous pourriez exécuter manuellement les requêtes SQL pour mettre à jour Piwik.',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => 'Cliquez ici pour visualiser la liste des commandes SQL qui vont être exécutées',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => 'Note: si vous exécutez manuellement ces requêtes, il se peut que certaines d\'entre elles échouent. Dans ce cas, ignorez simplement les erreurs, et exécutez les suivantes dans la liste.',
+ 'CoreUpdater_ReadyToGo' => 'Prêt à démarrer?',
'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Le procédé de mise à jour peut être long, veuillez patienter.',
'CoreUpdater_UpgradePiwik' => 'Mettez Piwik à jour',
'CoreUpdater_ErrorDIYHelp' => 'Si vous êtes un utilisateur avancé et que vous rencontrez une erreur lors de la mise à jour de la base de données :',
'CoreUpdater_ErrorDIYHelp_1' => 'identifiez la source exacte du problème (ex, memory_limit ou max_execution_time)',
'CoreUpdater_ErrorDIYHelp_2' => 'exécutez les requêtes restantes qui ont échoué',
- 'CoreUpdater_ErrorDIYHelp_3' => 'mettez à jour manuellement la table `otpion` de votre base de données Piwik, en spécifiant la valeur de version_core à la version de celle de l\'échec de la mise à jour',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'mettez à jour manuellement la table `option` de votre base de données Piwik, en spécifiant la valeur de version_core à la version de celle de l\'échec de la mise à jour',
'CoreUpdater_ErrorDIYHelp_4' => 'ré-exécutez le gestionnaire de mise à jour (en commande ou via le navigateur) pour continuer l\'installation des mises à jour restantes',
'CoreUpdater_ErrorDIYHelp_5' => 'rapportez le problème et la solution à Piwik, de cette manière il pourra être vérifié et distribué',
'CoreUpdater_HelpMessageContent' => 'Consultez la %s FAQ Piwik %s qui tente d\'expliquer les erreurs les plus communes lors des mises à jour. $s Demandez à votre administrateur système, il pourrait être capable de vous aider à corriger l\'erreur qui est fort probablement reliée à votre serveur ou configuration MySQL.',
@@ -190,7 +280,7 @@ $translations = array(
'CoreUpdater_DownloadingUpdateFromX' => 'Téléchargement de la mise à jour depuis %s',
'CoreUpdater_UnpackingTheUpdate' => 'Décompression de la mise à jour',
'CoreUpdater_VerifyingUnpackedFiles' => 'Vérification des fichiers décompressés',
- 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Création d\'un backup du fichier de configuration dans le répertoire %s',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Création d\'une sauvegarde du fichier de configuration dans le répertoire %s',
'CoreUpdater_InstallingTheLatestVersion' => 'Installation de la dernière version',
'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik a été mis à jour avec succès!',
'CoreUpdater_EmptyDatabaseError' => 'La base de données %s est vide. Vous devez éditer ou supprimer votre fichier de configuration Piwik.',
@@ -198,28 +288,232 @@ $translations = array(
'CoreUpdater_ExceptionArchiveIncompatible' => 'Archive incompatible: %s',
'CoreUpdater_ExceptionArchiveEmpty' => 'Archive vide.',
'CoreUpdater_ExceptionArchiveIncomplete' => 'L\'archive est incomplète: des fichiers sont manquants (ex. %s).',
- 'Actions_Actions' => 'Actions',
- 'Actions_SubmenuPages' => 'Pages',
- 'Actions_SubmenuOutlinks' => 'Liens de sortie',
- 'Actions_SubmenuDownloads' => 'Téléchargements',
- 'Actions_ColumnClicks' => 'Clics',
- 'Actions_ColumnUniqueClicks' => 'Clics uniques',
- 'Actions_ColumnDownloads' => 'Téléchargements',
- 'Actions_ColumnUniqueDownloads' => 'Téléchargements uniques',
- 'Actions_ColumnPageName' => 'Nom de la page',
- 'Actions_ColumnClickedURL' => 'URL sélectionnée',
- 'Actions_ColumnDownloadURL' => 'URL de téléchargement',
+ 'Dashboard_PluginDescription' => 'Votre tableau de bord de statistiques web. Vous pouvez personnaliser votre tableau de bord: ajoutez de nouveau widgets, changez l\'ordre de vos widgets. Chaque utilisateur peut accéder à son propre tableau de bord.',
'Dashboard_Dashboard' => 'Tableau de bord',
'Dashboard_AddWidget' => 'Ajouter un widget...',
'Dashboard_DeleteWidgetConfirm' => 'Êtes-vous sûr de vouloir supprimer ce widget du tableau de bord?',
'Dashboard_SelectWidget' => 'Sélectionnez le widget à ajouter au tableau de bord',
- 'Dashboard_AddPreviewedWidget' => 'Ajouter le widget visualisé au tableau de bord',
- 'Dashboard_WidgetPreview' => 'Prévisualisation du Widget',
+ 'Dashboard_AddPreviewedWidget_js' => 'Ajouter le widget visualisé au tableau de bord',
+ 'Dashboard_WidgetPreview_js' => 'Prévisualisation du Widget',
'Dashboard_Close_js' => 'Fermer',
'Dashboard_TitleWidgetInDashboard_js' => 'Widget déjà présent sur le tableau de bord',
'Dashboard_TitleClickToAdd_js' => 'Cliquez pour ajouter au tableau de bord',
'Dashboard_LoadingWidget_js' => 'Chargement du widget, patientez svp...',
'Dashboard_WidgetNotFound_js' => 'Widget introuvable',
+ 'DBStats_PluginDescription' => 'Ce plugin effectue des rapports sur l\'utilisation de la base de données MySQL par les tables de Piwik.',
+ 'DBStats_DatabaseUsage' => 'Utilisation de la base de données',
+ 'DBStats_MainDescription' => 'Piwik stocke toutes vos donnés de statistiques web dans la base de données MySQL. En ce moment les tables de Piwik utilisent %s.',
+ 'DBStats_LearnMore' => 'Pour en apprendre plus à propos de la manière dont Piwik traite les données et sur comment faire fonctionner Piwik correctement pour les sites à moyen et fort trafic, consultez la documentation %s.',
+ 'DBStats_Table' => 'Table',
+ 'DBStats_RowCount' => 'Nombre de lignes',
+ 'DBStats_DataSize' => 'Taille des données',
+ 'DBStats_IndexSize' => 'Taille de l\'index',
+ 'DBStats_TotalSize' => 'Taille totale',
+ 'ExampleAPI_PluginDescription' => 'Plugin d\'exemple: Comment créer une API pour votre plugin, exporter vos données dans de multiples formats sans aucun développement spécial?',
+ 'ExampleFeedburner_PluginDescription' => 'Plugin d\'exemple: Comment afficher votre abonnement Feedburner dans un Widget dans le tableau de bord?',
+ 'ExampleRssWidget_PluginDescription' => 'Plugin d\'exemple: Comment créer un nouveau widget qui lit un flux RSS?',
+ 'ExampleUI_PluginDescription' => 'Plugin d\'exemple: Ce plugin montre comment fonctionne l\'interface utilisateur de Piwik: création de tables, graphs, etc.',
+ 'Feedback_PluginDescription' => 'Envoie vos retours à l\'Equipe Piwik. Partagez vos idées et suggestions avec nous!',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Avez vous un bug à rapporter ou une fonctionnalité à demander?',
+ 'Feedback_ViewAnswersToFAQ' => 'Voir les réponses de %s la FAQ %s',
+ 'Feedback_WhyAreMyVisitsNoTracked' => 'Pourquoi les visites de mes sites web ne sont pas enregistrées?',
+ 'Feedback_HowToExclude' => 'Comment puis-je exclure le suivi de mes visites?',
+ 'Feedback_WhyWrongCountry' => 'Pourquoi Piwik affiche un mauvais pays pour ma visite?',
+ 'Feedback_HowToAnonymizeIP' => 'Comment puis-je masquer les adresse IP de mes visiteurs de ma base de données?',
+ 'Feedback_VisitTheForums' => 'Visitez les %s Forums%s',
+ 'Feedback_LearnWaysToParticipate' => 'Renseignez vous sur les manières dont vous pouvez %s participer%s',
+ 'Feedback_SpecialRequest' => 'Avez vous une demande spéciale pour l\'Equipe Piwik? ',
+ 'Feedback_ContactThePiwikTeam' => 'Contactez l\'Equipe Piwik!',
+ 'Feedback_IWantTo' => 'Je veux:',
+ 'Feedback_CategoryShareStory' => 'Partager une réussite avec Piwik',
+ 'Feedback_CategorySponsor' => 'Sponsoriser Piwik',
+ 'Feedback_CategoryHire' => 'Employer un consultant Piwik',
+ 'Feedback_CategorySecurity' => 'Rapporter un problème de sécurité',
+ 'Feedback_MyEmailAddress' => 'Mon adresse e-mail:',
+ 'Feedback_MyMessage' => 'Mon message:',
+ 'Feedback_DetailsPlease' => '(merci d\'inclure les détails)',
+ 'Feedback_SendFeedback' => 'Envoyer le retour',
+ 'Feedback_ManuallySendEmailTo' => 'Merci d\'envoyer manuellement votre message à',
+ 'Feedback_MessageSent' => 'Votre message a été envoyé à l\'Equipe Piwik.',
+ 'Feedback_ThankYou' => 'Merci d\'avoir aidé à améliorer Piwik!',
+ 'Feedback_ThePiwikTeam' => 'L\'Equipe Piwik',
+ 'Feedback_ExceptionBodyLength' => 'Le message doit faire au moins %s caractères de longueur.',
+ 'Feedback_ExceptionNoUrls' => 'Le message ne peut contenir d\'URL pour éviter les problèmes de spam.',
+ 'Goals_PluginDescription' => 'Créer des objectifs et consulter les rapports sur vos conversions d\'objectifs: évolution au cours du temps, revenu par visite, conversion par référant, par mot clef, etc.',
+ 'Goals_ColumnConversions' => 'Conversions',
+ 'Goals_ColumnConversionRate' => 'Taux de Conversion',
+ 'Goals_ColumnRevenue' => 'Revenu',
+ 'Goals_OverallRevenue' => '%s revenu global',
+ 'Goals_OverallConversionRate' => '%s taux de conversion global (vites avec un objectif rempli)',
+ 'Goals_Conversions' => '%s conversions',
+ 'Goals_ConversionRate' => '%s taux de conversion',
+ 'Goals_NoGoalsNeedAccess' => 'Uniquement un administrateur ou le super utilisateur peut ajouter un objectif à un site web donné. Veuillez demander à votre administrateur Piwik de mettre en place un objectif pour votre site web. <br /> Les objectifs sont un bon moyen pour comprendre et optimiser les performances de vos sites web! ',
+ 'Goals_AddNewGoal' => 'Ajoutez un nouvel objectif',
+ 'Goals_AddNewGoalOrEditExistingGoal' => '%sAjouter un nouvel objectif%s or %sEditer%s des objectifs existants',
+ 'Goals_AddGoal_js' => 'Ajouter un objectif',
+ 'Goals_UpdateGoal_js' => 'Mettre à jour un objectif',
+ 'Goals_DeleteGoalConfirm_js' => 'Etes vous sûr de vouloir supprimer l\'objectif %s?',
+ 'Goals_GoalName' => 'Nom de l\'objectif',
+ 'Goals_GoalIsTriggered' => 'L\'objectif est déclenché',
+ 'Goals_GoalIsTriggeredWhen' => 'L\'objectif est déclenché quand',
+ 'Goals_WhenVisitors' => 'quand les visiteurs',
+ 'Goals_Manually' => 'manuellement',
+ 'Goals_ManuallyTriggeredUsingJavascriptFunction' => 'Les objectifs sont déclenchés manuellement en utilisant l\'API Javascript trackGoal()',
+ 'Goals_VisitUrl' => 'Visiter une URL donnée (page ou groupe de pages)',
+ 'Goals_Download' => 'Télécharger un fichier',
+ 'Goals_ClickOutlink' => 'Cliquez sur un Lien vers un site externe',
+ 'Goals_Optional' => '(optionnel)',
+ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => 'où la page visitée contient un appel à la méthode JavaScript piwikTracker.trackGoal() (%sapprenez-en plus%s)',
+ 'Goals_DefaultRevenue' => 'Le revenue par défaut de l\'objectif est ',
+ 'Goals_DefaultRevenueHelp' => 'Par exemple, un formulaire de contact soumis par un visiteur peut avoir une valeur de 10 € en moyenne. Piwik vous aidera à comprendre comment se comportent vos visiteurs.',
+ 'Goals_ConversionsOverview' => 'Vue globale des conversions',
+ 'Goals_BestCountries' => 'Vos meilleurs pays de conversion sont: ',
+ 'Goals_BestKeywords' => 'Vos meilleurs mots clefs sont: ',
+ 'Goals_BestReferers' => 'Vos meilleurs sites web de conversion sont: ',
+ 'Goals_ReturningVisitorsConversionRateIs' => 'Le taux de conversion des visiteurs déjà venus est %s',
+ 'Goals_NewVisitorsConversionRateIs' => 'Le taux de conversion des nouveaux visiteurs est %s',
+ 'Goals_Contains' => 'contient %s',
+ 'Goals_IsExactly' => 'est exactement %s',
+ 'Goals_MatchesExpression' => 'correspond à l\'expression %s',
+ 'Goals_CaseSensitive' => 'Correspondance sensible à la case',
+ 'Goals_Pattern' => 'Modèle',
+ 'Installation_PluginDescription' => 'Procédé d\'installation de Piwik. L\'installation est effectuée une unique fois. Si le fichier de configuration config/config.inc.php est supprimé, l\'installation recommencera.',
+ 'Installation_Installation' => 'Installation',
+ 'Installation_InstallationStatus' => 'Statut de l\'installation',
+ 'Installation_PercentDone' => '%s %% Fait',
+ 'Installation_NoConfigFound' => 'Le fichier de configuration de Piwik ne peut être trouvé et vous essayez d\'accéder à une page de Piwik.<br> <b>&nbsp;&nbsp;&raquo; Vous pouvez <a href=\'index.php\'>installer Piwik maintenant</a></b><br><small>Si vous avez déjà installé Piwik ne vous inquiétez pas Piwik réutilisera ces tables et leurs données.</small>',
+ 'Installation_DatabaseSetup' => 'Installation de la base de données',
+ 'Installation_DatabaseSetupServer' => 'serveur de la base de données',
+ 'Installation_DatabaseSetupLogin' => 'compte',
+ 'Installation_DatabaseSetupPassword' => 'mot de passe',
+ 'Installation_DatabaseSetupDatabaseName' => 'nom de la base',
+ 'Installation_DatabaseSetupTablePrefix' => 'préfixe des tables',
+ 'Installation_DatabaseSetupAdapter' => 'adaptateur',
+ 'Installation_DatabaseErrorConnect' => 'Erreur lors de la tentative de connexion au serveur de base de données',
+ 'Installation_DatabaseCheck' => 'Vérification de la base de données',
+ 'Installation_DatabaseServerVersion' => 'Version du serveur de base de données',
+ 'Installation_DatabaseClientVersion' => 'Version du client de base de données',
+ 'Installation_DatabaseCreation' => 'Création de la base de données',
+ 'Installation_PleaseFixTheFollowingErrors' => 'Merci de corriger les erreurs suivantes',
+ 'Installation_JsTag' => 'Tag JavaScript',
+ 'Installation_JsTagHelp' => '<p>Pour comptabiliser tous les visiteurs vous devez copier le tag sur toutes vos pages.</p><p>Vos pages n\'ont pas besoin d\'être en PHP, Piwik fonctionne avec tout type de pages (HTML, ASP, Perl ou n\'importe quel autre langage).</p><p>Ici se trouve le code à insérer : (copiez/collez dans toutes vos pages) </p>',
+ 'Installation_JsTagHelpTitle' => 'Comment insérer le tag dans vos sites web?',
+ 'Installation_LargePiwikInstances' => 'Aide pour les instances de Piwik volumineuses',
+ 'Installation_JsTagArchivingHelp' => 'Pour les sites à moyen et fort trafic, lisez <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">la page d\'explication sur comment mettre en place une page d\'auto archivage</a> pour que Piwik devienne réellement rapide!',
+ 'Installation_Congratulations' => 'Félicitations',
+ 'Installation_CongratulationsHelp' => '<p>Félicitations! Votre installation de Piwik est terminée.</p><p>Assurez vous que le code JavaScript est présent sur toutes vos pages et attendez vos premiers visiteurs!</p>',
+ 'Installation_ContinueToPiwik' => 'Continuer vers Piwik',
+ 'Installation_SetupWebsite' => 'Paramétrer un site',
+ 'Installation_SetupWebSiteName' => 'nom du site web',
+ 'Installation_SetupWebSiteURL' => 'Url du site web',
+ 'Installation_Timezone' => 'fuseau horaire du site web',
+ 'Installation_SetupWebsiteError' => 'Une erreur a été rencontrée pendant l\'ajout du site',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Site %s créé avec succès!',
+ 'Installation_GeneralSetup' => 'Paramètres généraux',
+ 'Installation_GeneralSetupSuccess' => 'Paramètres généraux configurés avec succès',
+ 'Installation_SuperUserLogin' => 'login du super user',
+ 'Installation_Password' => 'mot de passe',
+ 'Installation_PasswordRepeat' => 'mot de passe (à nouveau)',
+ 'Installation_Email' => 'courriel',
+ 'Installation_SecurityNewsletter' => 'Envoyez moi un courriel pour les mises à jour de versions majeures de piwik ou pour les alertes de sécurité',
+ 'Installation_CommunityNewsletter' => 'Envoyez moi un courriel pour les nouveautés de la communauté (nouveaux plugins, nouvelles fonctionnalités, etc.)',
+ 'Installation_PasswordDoNotMatch' => 'Le mot de passe ne concorde pas',
+ 'Installation_SubmitGo' => 'Go!',
+ 'Installation_Requirements' => 'Pré-requis Piwik',
+ 'Installation_Optional' => 'Optionnel',
+ 'Installation_Legend' => 'Légendes',
+ 'Installation_Extension' => 'extension',
+ 'Installation_SystemCheck' => 'Vérification du système',
+ 'Installation_SystemCheckPhp' => 'Version PHP',
+ 'Installation_SystemCheckExtensions' => 'Extensions requises',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik requiert ou l\'extension mysqli ou les extensions pdo et pdo_mysql.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'Sur un serveur linux vous pouvez compiler PHP avec les options suivantes : %s
+
+ Dans votre php.ini, ajoutez les lignes suivantes: %s',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Plus d\'informations sur: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> et <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'Sur un serveur windows vous pouvez ajouter les lignes suivantes à votre php.ini: %s',
+ 'Installation_SystemCheckSplHelp' => 'Vous devez configurer et recompiler PHP avec la librairie standard (par défaut).',
+ 'Installation_SystemCheckZlibHelp' => 'Vous devez reconfigurer et recompiler PHP avec le support zlib, --with-zlib.',
+ 'Installation_SystemCheckIconvHelp' => 'Vous devez configurer PHP et le recompiler avec le support "iconv" activé, --with-iconv.',
+ 'Installation_SystemCheckDomHelp' => 'DOM est une partie du coeur de PHP. Vous avez probablement besoin d\'installer le module dom ex, php-5-dom.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'Vous devez recompiler PHP avec l\'extension "json" ou "xml" activée.',
+ 'Installation_SystemCheckJsonSite' => 'Plus d\'informations sur : <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Des plugins et librairies tierces pourront avoir besoin de l\'extension XML.',
+ 'Installation_SystemCheckXmlSite' => 'Plus d\'informations sur: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckWriteDirs' => 'Répertoires avec les droits d\'accès en écriture',
+ 'Installation_SystemCheckWriteDirsHelp' => 'Pour corriger les erreurs sur votre système Linux essayez de taper les commandes suivantes',
+ 'Installation_SystemCheckMemoryLimit' => 'Limite mémoire',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'Sur un site à trafic important le processus d\'archivage peut prendre plus de mémoire que la limite actuelle autorisée.<br />Référez vous à la configuration memory_limit de votre php.ini si nécessaire.',
+ 'Installation_SystemCheckOpenURL' => 'Ouvrez l\'URL',
+ 'Installation_SystemCheckOpenURLHelp' => 'Abonnements à la newsletter, notifications des mises à jour, et mise à jour en un click requièrent l\'extension curl, allow_url_fopen=On, ou fsockopen() activé.',
+ 'Installation_SystemCheckGD' => 'GD &gt; 2.x (graphiques)',
+ 'Installation_SystemCheckGDHelp' => 'Les sparklines (petits graphs) ne fonctionneront pas.',
+ 'Installation_SystemCheckFunctions' => 'Fonctions requises',
+ 'Installation_SystemCheckTimeLimitHelp' => 'Sur un site à trafic important le processus d\'archivage peut prendre plus de temps qu\'il n\'est déjà autorisé.<br /> Référez vous à la configuration max_execution_time de votre php.ini si nécessaire.',
+ 'Installation_SystemCheckMailHelp' => 'Les Feedback (commentaires) et mots de passe perdus ne pourront être envoyés sans la fonciton mail().',
+ 'Installation_SystemCheckParseIniFileHelp' => 'Cette fonction incluse a été désactivée sur votre serveur. Piwik va essayer d\'émuler cette fonction mais il est possible que vous rencontriez des restrictions de sécurité par la suite. Les performances seront aussi impactées.',
+ 'Installation_SystemCheckDebugBacktraceHelp' => 'View::factory ne pourra pas créer des vues pour le module appelé.',
+ 'Installation_SystemCheckCreateFunctionHelp' => 'Piwik utilise des fonctions anonymes pour les callbacks.',
+ 'Installation_SystemCheckMbstring' => 'mbstring',
+ 'Installation_SystemCheckMbstringHelp' => 'Vous devriez paramètrer mbstring.func_overload à "0".',
+ 'Installation_SystemCheckFileIntegrity' => 'Intégrité du fichier',
+ 'Installation_SystemCheckError' => 'Une erreur s\'est produite — elle doit être corrigée avant de pouvoir continuer',
+ 'Installation_SystemCheckWarning' => 'Piwik fonctionnera normalement mais certaines fonctionnalités seront manquantes',
+ 'Installation_SystemCheckProtocol' => 'Protocole',
+ 'Installation_SystemCheckProtocolHelp' => 'Si Piwik se situe derrière un proxy inversé ajoutez ces lignes dans config/config.ini.php sous la section [General]:',
+ 'Installation_SystemCheckIpv4' => 'IPv4',
+ 'Installation_SystemCheckIpv4Help' => 'Vous devriez désactiver IPv6 dans la configuration de votre server.',
+ 'Installation_Tables' => 'Création des tables',
+ 'Installation_TablesWithSameNamesFound' => 'Environ %s tables dans votre base de données %s ont le même nom que celles que Piwik essaie de créer.',
+ 'Installation_TablesFound' => 'Les tables suivantes ont été trouvées dans la base de données',
+ 'Installation_TablesWarningHelp' => 'Vous pouvez choisir de réutiliser les tables de la base de données existante ou sélectionner une nouvelle installation pour effacer toutes les données existantes dans la base de données.',
+ 'Installation_TablesReuse' => 'Réutiliser les tables existantes',
+ 'Installation_TablesDelete' => 'Supprimer les tables détectées',
+ 'Installation_TablesDeletedSuccess' => 'Tables Piwik existantes supprimées avec succès',
+ 'Installation_TablesCreatedSuccess' => 'Tables crées avec succès!',
+ 'Installation_DatabaseCreatedSuccess' => 'Base de données %s crée avec succès !',
+ 'Installation_GoBackAndDefinePrefix' => 'Retournez à la page précédente et définissez le préfixe pour les tables Piwik',
+ 'Installation_ConfirmDeleteExistingTables' => 'Etes vous sûr de vouloir supprimer les tables : %s de votre base de données? ATTENTION: LES DONNEES SERONT DEFINITIVEMENT PERDUES!',
+ 'Installation_Welcome' => 'Bienvenue!',
+ 'Installation_WelcomeHelp' => '<p>Piwik est une application d\'analyse du web Open Source qui vous permet d\'obtenir facilement les informations que vous désirez sur vos visiteurs.</p> <p>Ce procédé est divisé en %s étapes faciles et vous prendra 5 minutes environ.</p>',
+ 'Installation_ConfigurationHelp' => 'Votre configuration de Piwik semble être erronée. Vous pouvez ou bien supprimer config/config.inc.php et reprendre l\'installation ou corriger les paramètres de connexion.',
+ 'Installation_ErrorInvalidState' => 'Erreur: il semble que vous essayez de sauter une étape du processus d\'installation, ou vous avez désactivé les cookies, ou le fichier de configuration de Piwik est déjà créé. %sAssurez vous que les cookies sont bien activés%s et retournez %s à la première page d\'installation %s.',
+ 'LanguagesManager_PluginDescription' => 'Ce plugin affichera la liste des langues disponibles pour l\'interface de Piwik. Le langage sélectionné sera sauvegardé dans les préférences de chaque utilisateur.',
+ 'LanguagesManager_AboutPiwikTranslations' => 'A propos des traductions de Piwik',
+ 'Live_PluginDescription' => 'Espionnez vos visiteurs, en temps réel!',
+ 'Live_VisitorLog' => 'Log visiteur',
+ 'Live_Date' => 'Date',
+ 'Live_Time' => 'Temps',
+ 'Live_Referrer_URL' => 'URL du référant',
+ 'Login_PluginDescription' => 'Plugin de login, lisant les identifiants du fichier config/config.inc.php pour le the Super Utilisateur, et depuis la base de données pour les autres utilisateurs. Peut être facilement remplacé pour introduire un nouveau système d\'authentification (OpenID, htaccess, custom Auth, etc.).',
+ 'Login_LoginPasswordNotCorrect' => 'Mot de passe et nom d\'utilisateur incorrects.',
+ 'Login_Password' => 'Mot de passe',
+ 'Login_PasswordRepeat' => 'Mot de passe (répétez)',
+ 'Login_ChangePassword' => 'Modifier le mot de passe',
+ 'Login_LoginOrEmail' => 'Nom d\'utilisateur ou courriel',
+ 'Login_LogIn' => 'Connexion',
+ 'Login_Logout' => 'Déconnexion',
+ 'Login_LostYourPassword' => 'Mot de passe perdu ?',
+ 'Login_RemindPassword' => 'Rappeler le mot de passe',
+ 'Login_PasswordResetToken' => 'Clef de remise à zéro du mot de passe',
+ 'Login_PasswordReminder' => 'Entrez un nom d\'utilisateur ou un courriel valide, vous recevrez votre nouveau mot de passe par courriel.',
+ 'Login_PasswordsDoNotMatch' => 'Les mots de passe ne correspondent pas.',
+ 'Login_PasswordSuccessfullyChanged' => 'Mot de passe modifié avec succès!',
+ 'Login_InvalidUsernameEmail' => 'Nom d\'utilisateur et/ou courriel invalide.',
+ 'Login_InvalidNonceOrReferer' => 'La clef de sécurité du formulaire est invalide ou a expiré. Merci de recharger le formulaire et de vérifier que vous avez activé les cookies.',
+ 'Login_InvalidOrExpiredToken' => 'La Clef est invalide ou a expiré',
+ 'Login_MailTopicPasswordRecovery' => 'Récupération du mot de passe',
+ 'Login_MailPasswordRecoveryBody' => 'Hi %1s, \n\n Votre nouveau mot de passe est : %2s \n\n Vous pouvez vous connecter maintenant ici : %3s',
+ 'Login_PasswordSent' => 'Le mot de passe vient juste d\'être envoyé. Veuillez vérifier vos courriels.',
+ 'Login_ContactAdmin' => 'Raison possible : Votre hébergeur peut avoir désactivé la fonction mail(). <br /> Veuillez contacter votre administrateur Piwik.',
+ 'MultiSites_PluginDescription' => 'Affiche le sommaire/les statistiques multi-site. Actuellement maintenu comme un plugin Piwik cœur.',
+ 'Provider_PluginDescription' => 'Effectue des rapports sur les FAI des visiteurs.',
+ 'Provider_WidgetProviders' => 'Fournisseurs d\'accès à Internet',
+ 'Provider_ColumnProvider' => 'FAI',
+ 'Provider_SubmenuLocationsProvider' => 'Situation géographique et FAI',
+ 'Referers_PluginDescription' => 'Effectue des rapports sur les données des référents: moteurs de recherche, mots clefs, sites web, suivi de campagne, entrée directe. ',
'Referers_Referers' => 'Référents',
'Referers_SearchEngines' => 'Moteurs de recherche',
'Referers_Keywords' => 'Mots-clés',
@@ -255,29 +549,69 @@ $translations = array(
'Referers_WidgetExternalWebsites' => 'Liste des sites Internet externes',
'Referers_WidgetSearchEngines' => 'Meilleurs moteurs de recherche',
'Referers_WidgetOverview' => 'Récapitulatif',
- 'UserSettings_VisitorSettings' => 'Paramètres visiteur',
- 'UserSettings_BrowserFamilies' => 'Familles de navigateurs',
- 'UserSettings_Browsers' => 'Navigateurs',
- 'UserSettings_Plugins' => 'Plugins',
- 'UserSettings_Configurations' => 'Configurations',
- 'UserSettings_OperatinsSystems' => 'Système d\'exploitation',
- 'UserSettings_Resolutions' => 'Résolutions',
- 'UserSettings_WideScreen' => 'Largeur d\'écran',
- 'UserSettings_ColumnBrowserFamily' => 'Famille de navigateur',
- 'UserSettings_ColumnBrowser' => 'navigateur',
- 'UserSettings_ColumnPlugin' => 'Plugin',
- 'UserSettings_ColumnConfiguration' => 'Configuration',
- 'UserSettings_ColumnOperatinsSystem' => 'Système d\'exploitation',
- 'UserSettings_ColumnResolution' => 'Résolution',
- 'UserSettings_ColumnTypeOfScreen' => 'Type d\'écran',
- 'UserSettings_WidgetResolutions' => 'Résolutions d\'écran',
- 'UserSettings_WidgetBrowsers' => 'Navigateurs du visiteur',
- 'UserSettings_WidgetPlugins' => 'Liste de Plugins',
- 'UserSettings_WidgetWidescreen' => 'Normal / Écran large',
- 'UserSettings_WidgetBrowserFamilies' => 'Navigateurs par famille',
- 'UserSettings_WidgetOperatingSystems' => 'Systèmes d\'exploitation',
- 'UserSettings_WidgetGlobalVisitors' => 'Configuration globale des visiteurs',
- 'UserSettings_SubmenuSettings' => 'Paramètres',
+ 'SecurityInfo_PluginDescription' => 'Basé sur PhpSecInfo du Consortium de Sécurité de PHP, ce plugin fournit des information de sécurité à propos de votre environnement PHP et donne des suggestions pour son amélioration. C\'est un outil d\'approche sécurité multi-couches. Cela ne remplace ni les pratiques de développement sécurisé ni les audit du code.',
+ 'SecurityInfo_Security' => 'Sécurité',
+ 'SecurityInfo_SecurityInformation' => 'Information de sécurité de PHP',
+ 'SecurityInfo_Test' => 'Test',
+ 'SecurityInfo_Result' => 'Résultat',
+ 'SitesManager_PluginDescription' => 'Gestion des sites web dans Piwik: Ajoute un nouveau site web, modifie un existant, affiche le code JavaScript à inclure dans vos pages. Toutes les actions sont disponibles au travers de l\'API.',
+ 'SitesManager_Sites' => 'Sites',
+ 'SitesManager_WebsitesManagement' => 'Gestion des sites',
+ 'SitesManager_MainDescription' => 'Piwik a besoin de sites pour générer des rapports ! Ajoutez, éditez et supprimez des sites, et voyez le code JavaScript à inclure dans vos pages.',
+ 'SitesManager_JsTrackingTag' => 'Code JavaScript de suivit',
+ 'SitesManager_JsTrackingTagHelp' => 'Ci-dessous le code JavaScript à inclure dans toutes vos pages ',
+ 'SitesManager_ShowTrackingTag' => 'Afficher le code',
+ 'SitesManager_NoWebsites' => 'Vous n\'avez aucun site Internet à administrer.',
+ 'SitesManager_AddSite' => 'Ajouter un site',
+ 'SitesManager_AliasUrlHelp' => 'Il est recommandé, mais pas requis, de spécifier les URL différentes que vos utilisateurs utilisent pour accéder au site web. Les URL d\'alias pour un site n\'apparaitront pas dans Référents > Sites Internet. Il n\'est pas nécessaire d\'entrer les URL avec et sans les www, Piwik les traite automatiquement.',
+ 'SitesManager_Id' => 'Id',
+ 'SitesManager_Name' => 'Nom',
+ 'SitesManager_Urls' => 'URLs',
+ 'SitesManager_MenuSites' => 'Sites',
+ 'SitesManager_DeleteConfirm_js' => 'Êtes-vous sûr de vouloir supprimer le site %s?',
+ 'SitesManager_ExceptionDeleteSite' => 'Impossible de supprimer le site car c\'est le seul site enregistré dans Piwik. Vous pouvez d\'abord en ajouter un nouveau, puis supprimez celui-ci.',
+ 'SitesManager_ExceptionNoUrl' => 'Vous devez spécifier au moins une url pour le site.',
+ 'SitesManager_ExceptionEmptyName' => 'Le nom du site ne peut être vide.',
+ 'SitesManager_ExceptionInvalidUrl' => 'L\'url \'%s\' est invalide.',
+ 'SitesManager_SuperUserCan' => 'Le super utilisateur peut aussi %s spécifier les paramètres généraux%s pour les nouveaux sites web.',
+ 'SitesManager_ExcludedIps' => 'IPs Exclues',
+ 'SitesManager_GlobalListExcludedIps' => 'Liste globale des IPs Exclues',
+ 'SitesManager_ListOfIpsToBeExcludedOnAllWebsites' => 'Les adresses IP ci-dessous seront exclues des statistiques sur tous les sites web.',
+ 'SitesManager_ExcludedParameters' => 'Paramètres Exclus',
+ 'SitesManager_GlobalListExcludedQueryParameters' => 'Liste globale des paramètres Url des requêtes à exclure',
+ 'SitesManager_ListOfQueryParametersToBeExcludedOnAllWebsites' => 'Les paramètres ci-dessous seront exclus des statistiques de tous les sites web.',
+ 'SitesManager_ListOfQueryParametersToExclude' => 'Entrez la liste des paramètres Url, un par ligne, à exclure des rapports des Url de pages.',
+ 'SitesManager_PiwikWillAutomaticallyExcludeCommonSessionParameters' => 'Piwik exclura automatiquement les paramètres de session communs (%s).',
+ 'SitesManager_HelpExcludedIps' => 'Entrez une liste d\'adresses IP, une par ligne, que vous souhaitez exclure des statistiques Piwik. Vous pouvez utiliser des caractères jokers ex %1$s ou %2$s',
+ 'SitesManager_YourCurrentIpAddressIs' => 'Votre adresse IP actuelle est %s',
+ 'SitesManager_SelectACity' => 'Sélectionnez une ville',
+ 'SitesManager_ChooseCityInSameTimezoneAsYou' => 'Choisissez une ville qui se trouve dans le même fuseau horaire que vous.',
+ 'SitesManager_ChangingYourTimezoneWillOnlyAffectDataForward' => 'Le fait de modifier votre fuseau horaire affectera uniquement les nouvelles données, ce n\'est pas rétroactif.',
+ 'SitesManager_AdvancedTimezoneSupportNotFound' => 'Le support avancé des fuseaux horaires n\'a pu être trouvé dans votre configuration de PHP (supporté dans PHP>=5.2). Vous pouvez toujours choisir manuellement un décalage UTC.',
+ 'SitesManager_UTCTimeIs' => 'l\'heure UTC est %s.',
+ 'SitesManager_Timezone' => 'Fuseau horaire',
+ 'SitesManager_GlobalWebsitesSettings' => 'Paramètres généraux des sites web',
+ 'SitesManager_DefaultTimezoneForNewWebsites' => 'Fuseau horaire par défaut pour les nouveaux sites web',
+ 'SitesManager_SelectDefaultTimezone' => 'Vous pouvez sélectionner le fuseau horaire par défaut pour les nouveaux sites web.',
+ 'SitesManager_Currency' => 'Devise',
+ 'SitesManager_CurrencySymbolWillBeUsedForGoals' => 'Le symbole de la devise sera affiché à côté des revenus des Objectifs',
+ 'SitesManager_DefaultCurrencyForNewWebsites' => 'Devise par défaut pour les nouveaux sites web',
+ 'SitesManager_SelectDefaultCurrency' => 'Vous pouvez sélectionner la devise par défaut pour les nouveaux sites web.',
+ 'TranslationsAdmin_PluginDescription' => 'Aidez à traduire Piwik dans votre langue.',
+ 'TranslationsAdmin_MenuTranslations' => 'Traductions',
+ 'TranslationsAdmin_MenuLanguages' => 'Langues',
+ 'TranslationsAdmin_Plugin' => 'Plugin',
+ 'TranslationsAdmin_Definition' => 'Définition',
+ 'TranslationsAdmin_DefaultString' => 'Chaine par défaut (English)',
+ 'TranslationsAdmin_TranslationString' => 'Traduction (Langue actuelle : %s)',
+ 'TranslationsAdmin_Translations' => 'Traductions',
+ 'TranslationsAdmin_FixPermissions' => 'Veuillez définir les propriétés des fichiers systèmes',
+ 'TranslationsAdmin_AvailableLanguages' => 'Langues disponibles',
+ 'TranslationsAdmin_AddLanguage' => 'Ajouter langue',
+ 'TranslationsAdmin_LanguageCode' => 'Code langue',
+ 'TranslationsAdmin_Export' => 'Exporter langue',
+ 'TranslationsAdmin_Import' => 'Importer langue',
+ 'UserCountry_PluginDescription' => 'Effectue des rapports sur les pays des visiteurs.',
'UserCountry_Country' => 'Pays',
'UserCountry_Continent' => 'Continent',
'UserCountry_DistinctCountries' => '%s pays différents',
@@ -288,30 +622,30 @@ $translations = array(
'UserCountry_country_ad' => 'Andorre',
'UserCountry_country_ae' => 'Émirats arabes unis',
'UserCountry_country_af' => 'Afghanistan',
- 'UserCountry_country_ag' => 'Antigua et Barbuda',
+ 'UserCountry_country_ag' => 'Antigua-et-Barbuda',
'UserCountry_country_ai' => 'Anguilla',
'UserCountry_country_al' => 'Albanie',
- 'UserCountry_country_am' => 'Armenie',
+ 'UserCountry_country_am' => 'Arménie',
'UserCountry_country_an' => 'Antilles Néerlandaises',
'UserCountry_country_ao' => 'Angola',
'UserCountry_country_aq' => 'Antarctique',
'UserCountry_country_ar' => 'Argentine',
- 'UserCountry_country_as' => 'Samoa Amercicaines',
+ 'UserCountry_country_as' => 'Samoa Américaines',
'UserCountry_country_at' => 'Autriche',
'UserCountry_country_au' => 'Australie',
'UserCountry_country_aw' => 'Aruba',
'UserCountry_country_ax' => 'État libre associé d\'Åland',
- 'UserCountry_country_az' => 'Azerbaijan',
- 'UserCountry_country_ba' => 'Bosnie-Herzegovine',
+ 'UserCountry_country_az' => 'Azerbaïdjan',
+ 'UserCountry_country_ba' => 'Bosnie-Herzégovine',
'UserCountry_country_bb' => 'La Barbade',
'UserCountry_country_bd' => 'Bangladesh',
'UserCountry_country_be' => 'Belgique',
'UserCountry_country_bf' => 'Burkina Faso',
'UserCountry_country_bg' => 'Bulgarie',
- 'UserCountry_country_bh' => 'Bahrein',
+ 'UserCountry_country_bh' => 'Bahreïn',
'UserCountry_country_bi' => 'Burundi',
'UserCountry_country_bj' => 'Bénin',
- 'UserCountry_country_bl' => 'Saint Barthelemy',
+ 'UserCountry_country_bl' => 'Saint Barthélemy',
'UserCountry_country_bm' => 'Bermudes',
'UserCountry_country_bn' => 'Brunei',
'UserCountry_country_bo' => 'Bolivie',
@@ -332,24 +666,24 @@ $translations = array(
'UserCountry_country_ci' => 'Cote D\'Ivoire',
'UserCountry_country_ck' => 'Iles Cook',
'UserCountry_country_cl' => 'Chili',
- 'UserCountry_country_cm' => 'Cameroon',
+ 'UserCountry_country_cm' => 'Cameroun',
'UserCountry_country_cn' => 'Chine',
'UserCountry_country_co' => 'Colombie',
'UserCountry_country_cp' => 'Ile de La Passion',
'UserCountry_country_cr' => 'Costa Rica',
- 'UserCountry_country_cs' => 'Serbie Montenegro',
+ 'UserCountry_country_cs' => 'Serbie Monténégro',
'UserCountry_country_cu' => 'Cuba',
'UserCountry_country_cv' => 'Cap Vert',
'UserCountry_country_cx' => 'Ile Christmas',
- 'UserCountry_country_cy' => 'Chypres',
- 'UserCountry_country_cz' => 'Republique Tchèque',
+ 'UserCountry_country_cy' => 'Chypre',
+ 'UserCountry_country_cz' => 'République Tchèque',
'UserCountry_country_de' => 'Allemagne',
'UserCountry_country_dg' => 'Diego Garcia',
'UserCountry_country_dj' => 'Djibouti',
'UserCountry_country_dk' => 'Danemark',
'UserCountry_country_dm' => 'Dominique',
- 'UserCountry_country_do' => 'Republique Dominicaine',
- 'UserCountry_country_dz' => 'Algerie',
+ 'UserCountry_country_do' => 'République Dominicaine',
+ 'UserCountry_country_dz' => 'Algérie',
'UserCountry_country_ea' => 'Ceuta, Melilla',
'UserCountry_country_ec' => 'Équateur',
'UserCountry_country_ee' => 'Estonie',
@@ -360,17 +694,17 @@ $translations = array(
'UserCountry_country_et' => 'Ethiopie',
'UserCountry_country_eu' => 'Union Européenne',
'UserCountry_country_fi' => 'Finlande',
- 'UserCountry_country_fj' => 'Fiji',
+ 'UserCountry_country_fj' => 'Fidji',
'UserCountry_country_fk' => 'Iles Falkland',
'UserCountry_country_fm' => 'Micronesia, Federated States of',
'UserCountry_country_fo' => 'Iles Faroe',
'UserCountry_country_fr' => 'France',
- 'UserCountry_country_fx' => 'France metropolitaine',
+ 'UserCountry_country_fx' => 'France métropolitaine',
'UserCountry_country_ga' => 'Gabon',
'UserCountry_country_gb' => 'Grande Bretagne',
'UserCountry_country_gd' => 'Grenade',
- 'UserCountry_country_ge' => 'Georgie',
- 'UserCountry_country_gf' => 'Guyanne Française',
+ 'UserCountry_country_ge' => 'Géorgie',
+ 'UserCountry_country_gf' => 'Guyane Française',
'UserCountry_country_gg' => 'Ile de Guernesey',
'UserCountry_country_gh' => 'Ghana',
'UserCountry_country_gi' => 'Gibraltar',
@@ -384,20 +718,20 @@ $translations = array(
'UserCountry_country_gt' => 'Guatemala',
'UserCountry_country_gu' => 'Guam',
'UserCountry_country_gw' => 'Guinée-Bissau',
- 'UserCountry_country_gy' => 'Guyanne',
+ 'UserCountry_country_gy' => 'Guyane',
'UserCountry_country_hk' => 'Hong Kong',
'UserCountry_country_hm' => 'Iles heard et Mac Donald',
'UserCountry_country_hn' => 'Honduras',
'UserCountry_country_hr' => 'Croatie',
- 'UserCountry_country_ht' => 'Haiti',
+ 'UserCountry_country_ht' => 'Haïti',
'UserCountry_country_hu' => 'Hongrie',
'UserCountry_country_ic' => 'Iles Canaries',
- 'UserCountry_country_id' => 'Indonesie',
+ 'UserCountry_country_id' => 'Indonésie',
'UserCountry_country_ie' => 'Irlande',
- 'UserCountry_country_il' => 'Israel',
+ 'UserCountry_country_il' => 'Israël',
'UserCountry_country_im' => 'Iles de Man',
'UserCountry_country_in' => 'Inde',
- 'UserCountry_country_io' => 'Océan indien (Territoire Britanique)',
+ 'UserCountry_country_io' => 'Océan indien (Territoire Britannique)',
'UserCountry_country_iq' => 'Irak',
'UserCountry_country_ir' => 'Iran, République Islamique de',
'UserCountry_country_is' => 'Islande',
@@ -407,15 +741,15 @@ $translations = array(
'UserCountry_country_jo' => 'Jordanie',
'UserCountry_country_jp' => 'Japon',
'UserCountry_country_ke' => 'Kenya',
- 'UserCountry_country_kg' => 'Kyrgyzstan',
+ 'UserCountry_country_kg' => 'Kirghizstan',
'UserCountry_country_kh' => 'Kampuchea (ex Cambodge)',
'UserCountry_country_ki' => 'Kiribati',
'UserCountry_country_km' => 'Comores',
'UserCountry_country_kn' => 'Saint Christophe Nieves Ang.',
'UserCountry_country_kp' => 'Corée du Nord',
'UserCountry_country_kr' => 'Corée du Sud',
- 'UserCountry_country_kw' => 'Koweit',
- 'UserCountry_country_ky' => 'Iles Caimans',
+ 'UserCountry_country_kw' => 'Koweït',
+ 'UserCountry_country_ky' => 'Iles Caïmans',
'UserCountry_country_kz' => 'Kazakhstan',
'UserCountry_country_la' => 'Laos',
'UserCountry_country_lb' => 'Liban',
@@ -430,12 +764,12 @@ $translations = array(
'UserCountry_country_ly' => 'Lybie',
'UserCountry_country_ma' => 'Maroc',
'UserCountry_country_mc' => 'Monaco',
- 'UserCountry_country_md' => 'Moldava',
+ 'UserCountry_country_md' => 'Moldavie',
'UserCountry_country_me' => 'Monténégro',
'UserCountry_country_mf' => 'Saint Martin',
'UserCountry_country_mg' => 'Madagascar',
'UserCountry_country_mh' => 'Iles Marshall',
- 'UserCountry_country_mk' => 'Macédonie',
+ 'UserCountry_country_mk' => 'Macédoine',
'UserCountry_country_ml' => 'Mali',
'UserCountry_country_mm' => 'Myanmar',
'UserCountry_country_mn' => 'Mongolie',
@@ -482,18 +816,18 @@ $translations = array(
'UserCountry_country_qa' => 'Qatar',
'UserCountry_country_re' => 'La Réunion',
'UserCountry_country_ro' => 'Roumanie',
- 'UserCountry_country_ru' => 'Russia',
- 'UserCountry_country_rs' => 'Serbia',
+ 'UserCountry_country_ru' => 'Russie',
+ 'UserCountry_country_rs' => 'Serbie',
'UserCountry_country_rw' => 'Rwanda',
'UserCountry_country_sa' => 'Arabie Saoudite',
- 'UserCountry_country_sb' => 'Iles Solomon',
+ 'UserCountry_country_sb' => 'Iles Salomon',
'UserCountry_country_sc' => 'Seychelles',
'UserCountry_country_sd' => 'Soudan',
'UserCountry_country_se' => 'Suède',
'UserCountry_country_sf' => 'Finlande',
'UserCountry_country_sg' => 'Singapour',
'UserCountry_country_sh' => 'Sainte Hélène',
- 'UserCountry_country_si' => 'Slovenie',
+ 'UserCountry_country_si' => 'Slovénie',
'UserCountry_country_sj' => 'Svalbard et Ile Jan Mayen',
'UserCountry_country_sk' => 'Slovaquie',
'UserCountry_country_sl' => 'Sierra Leone',
@@ -512,10 +846,10 @@ $translations = array(
'UserCountry_country_tf' => 'Terres australes et antarctiques françaises',
'UserCountry_country_tg' => 'Togo',
'UserCountry_country_th' => 'Thaïlande',
- 'UserCountry_country_tj' => 'Tajikistan',
+ 'UserCountry_country_tj' => 'Tadjikistan',
'UserCountry_country_tk' => 'Tokelaou',
'UserCountry_country_tl' => 'Timor Oriental',
- 'UserCountry_country_tm' => 'Turkmenistan',
+ 'UserCountry_country_tm' => 'Turkménistan',
'UserCountry_country_tn' => 'Tunisie',
'UserCountry_country_to' => 'Tonga',
'UserCountry_country_tp' => 'Timor Oriental',
@@ -530,7 +864,7 @@ $translations = array(
'UserCountry_country_um' => 'Îles mineures éloignées des États-Unis',
'UserCountry_country_us' => 'Etats Unis',
'UserCountry_country_uy' => 'Uruguay',
- 'UserCountry_country_uz' => 'Ouzbekistan',
+ 'UserCountry_country_uz' => 'Ouzbékistan',
'UserCountry_country_va' => 'Vatican',
'UserCountry_country_vc' => 'Saint Vincent et Grenadines',
'UserCountry_country_ve' => 'Venezuela',
@@ -538,14 +872,14 @@ $translations = array(
'UserCountry_country_vi' => 'Iles Vierges U.S.',
'UserCountry_country_vn' => 'Vietnam',
'UserCountry_country_vu' => 'Vanuatu',
- 'UserCountry_country_wf' => 'Wallis and Futuna',
+ 'UserCountry_country_wf' => 'Wallis et Futuna',
'UserCountry_country_ws' => 'Samoa Occidentales',
- 'UserCountry_country_ye' => 'Yemen',
+ 'UserCountry_country_ye' => 'Yémen',
'UserCountry_country_yt' => 'Mayotte',
- 'UserCountry_country_yu' => 'Yugoslavie',
+ 'UserCountry_country_yu' => 'Yougoslavie',
'UserCountry_country_za' => 'Afrique du Sud',
'UserCountry_country_zm' => 'Zambie',
- 'UserCountry_country_zr' => 'Zaire',
+ 'UserCountry_country_zr' => 'Zaïre',
'UserCountry_country_zw' => 'Zimbabwe',
'UserCountry_continent_eur' => 'Europe',
'UserCountry_continent_afr' => 'Afrique',
@@ -553,76 +887,31 @@ $translations = array(
'UserCountry_continent_ams' => 'Amérique du sud et centrale',
'UserCountry_continent_amn' => 'Amérique du nord',
'UserCountry_continent_oce' => 'Océanie',
- 'VisitsSummary_VisitsSummary' => 'Récapitulatif des visites',
- 'VisitsSummary_NbVisits' => '%s visites',
- 'VisitsSummary_NbUniqueVisitors' => '%s visiteurs uniques',
- 'VisitsSummary_NbActions' => '%s actions (pages vues)',
- 'VisitsSummary_TotalTime' => '%s temps total passé par les visiteurs',
- 'VisitsSummary_MaxNbActions' => '%s actions maximums en une visite',
- 'VisitsSummary_NbVisitsBounced' => '%s visiteurs ont survolé (quitté le site après une page)',
- 'VisitsSummary_EvolutionOverLastPeriods' => 'Évolution sur les 30 derniers %s',
- 'VisitsSummary_Report' => 'Rapport',
- 'VisitsSummary_GenerateTime' => '%s secondes pour générer la page',
- 'VisitsSummary_GenerateQueries' => '%s requêtes exécutées',
- 'VisitsSummary_WidgetLastVisits' => 'Graphique des dernières visites',
- 'VisitsSummary_WidgetVisits' => 'Récapitulatif des visites',
- 'VisitsSummary_WidgetLastVisitors' => 'Graphique des derniers visiteurs uniques',
- 'VisitsSummary_WidgetOverviewGraph' => 'Graphique récapitulatif',
- 'VisitsSummary_SubmenuOverview' => 'Récapitulatif',
- 'VisitFrequency_Evolution' => 'Évolution sur la période',
- 'VisitFrequency_ColumnReturningVisits' => 'Visites retour',
- 'VisitFrequency_ColumnActionsByReturningVisits' => 'Actions des visites retour',
- 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Nombre maximum d\'actions par une visite retour',
- 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Temps total passé par les visites retour (en secondes)',
- 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Pourcentage de survolement par les visites retour',
- 'VisitFrequency_ReturnVisits' => '%s visites de visiteurs connus',
- 'VisitFrequency_ReturnActions' => '%s actions de visites de visiteurs connus',
- 'VisitFrequency_ReturnMaxActions' => '%s actions maximums par visite de visiteur connus',
- 'VisitFrequency_ReturnTotalTime' => '%s temps total passé par des visiteurs connus',
- 'VisitFrequency_ReturnBounceRate' => '%s visiteurs connus ont survolé (quitté le site après une page)',
- 'VisitFrequency_WidgetOverview' => 'Récapitulatif de la Fréquence',
- 'VisitFrequency_WidgetGraphReturning' => 'Graphique de visites de visiteurs connus',
- 'VisitFrequency_SubmenuFrequency' => 'Fréquence',
- 'VisitTime_LocalTime' => 'Visites par heure locale',
- 'VisitTime_ServerTime' => 'Visites par heure du serveur',
- 'VisitTime_ColumnServerTime' => 'Heure serveur',
- 'VisitTime_ColumnLocalTime' => 'Heure locale',
- 'VisitTime_WidgetLocalTime' => 'Visites par fuseau horaire local',
- 'VisitTime_WidgetServerTime' => 'Visites par fuseau horaire du serveur',
- 'VisitTime_SubmenuTimes' => 'Horaires',
- 'VisitTime_NHour' => '%sh',
- 'VisitorInterest_VisitsPerDuration' => 'Visites par durée de la visite',
- 'VisitorInterest_VisitsPerNbOfPages' => 'Visites par nombre de pages',
- 'VisitorInterest_ColumnVisitDuration' => 'Durée de la visite',
- 'VisitorInterest_ColumnPagesPerVisit' => 'Pages par visite',
- 'VisitorInterest_WidgetLengths' => 'Durée des visites',
- 'VisitorInterest_WidgetPages' => 'Pages par visite',
- 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Fréquence et Fidélité',
- 'VisitorInterest_PlusXMin' => '%s min',
- 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
- 'VisitorInterest_OnePage' => '1 page',
- 'VisitorInterest_NPages' => '%s pages',
- 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
- 'Login_LoginPasswordNotCorrect' => 'Mot de passe et nom d\'utilisateur incorrects.',
- 'Login_Login' => 'Nom d\'utilisateur',
- 'Login_Password' => 'Mot de passe',
- 'Login_PasswordRepeat' => 'Mot de passe (répétez)',
- 'Login_ChangePassword' => 'Modifier le mot de passe',
- 'Login_LoginOrEmail' => 'Nom d\'utilisateur ou courriel',
- 'Login_LogIn' => 'Connexion',
- 'Login_Logout' => 'Déconnexion',
- 'Login_LostYourPassword' => 'Mot de passe perdu ?',
- 'Login_RemindPassword' => 'Rappeler le mot de passe',
- 'Login_PasswordResetToken' => 'Clef de remise à zéro du mot de passe',
- 'Login_PasswordReminder' => 'Entrez un nom d\'utilisateur ou un courriel valide, vous recevrez votre nouveau mot de passe par courriel.',
- 'Login_PasswordsDoNotMatch' => 'Les mots de passe ne correspondent pas.',
- 'Login_PasswordSuccessfullyChanged' => 'Mot de passe modifié avec succès!',
- 'Login_InvalidUsernameEmail' => 'Nom d\'utilisateur et/ou courriel invalide.',
- 'Login_InvalidOrExpiredToken' => 'La Clef est invalide ou a expiré',
- 'Login_MailTopicPasswordRecovery' => 'Récupération du mot de passe',
- 'Login_MailPasswordRecoveryBody' => 'Hi %1s, \n\n Votre nouveau mot de passe est : %2s \n\n Vous pouvez vous connecter maintenant ici : %3s',
- 'Login_PasswordSent' => 'Le mot de passe vient juste d\'être envoyé. Veuillez vérifier vos courriels.',
- 'Login_ContactAdmin' => 'Raison possible : Votre hébergeur peut avoir désactivé la fonction mail(). <br /> Veuillez contacter votre administrateur Piwik.',
+ 'UserSettings_PluginDescription' => 'Effectue des rapports variés sur les paramètres utilisateurs: navigateur, famille du navigateur, système d\'exploitation, plugins, résolution, paramètres généraux.',
+ 'UserSettings_VisitorSettings' => 'Paramètres visiteur',
+ 'UserSettings_BrowserFamilies' => 'Familles de navigateurs',
+ 'UserSettings_Browsers' => 'Navigateurs',
+ 'UserSettings_Plugins' => 'Plugins',
+ 'UserSettings_Configurations' => 'Configurations',
+ 'UserSettings_OperatingSystems' => 'Système d\'exploitation',
+ 'UserSettings_Resolutions' => 'Résolutions',
+ 'UserSettings_WideScreen' => 'Largeur d\'écran',
+ 'UserSettings_ColumnBrowserFamily' => 'Famille de navigateur',
+ 'UserSettings_ColumnBrowser' => 'navigateur',
+ 'UserSettings_ColumnPlugin' => 'Plugin',
+ 'UserSettings_ColumnConfiguration' => 'Configuration',
+ 'UserSettings_ColumnOperatingSystem' => 'Système d\'exploitation',
+ 'UserSettings_ColumnResolution' => 'Résolution',
+ 'UserSettings_ColumnTypeOfScreen' => 'Type d\'écran',
+ 'UserSettings_WidgetResolutions' => 'Résolutions d\'écran',
+ 'UserSettings_WidgetBrowsers' => 'Navigateurs du visiteur',
+ 'UserSettings_WidgetPlugins' => 'Liste de Plugins',
+ 'UserSettings_WidgetWidescreen' => 'Normal / Écran large',
+ 'UserSettings_WidgetBrowserFamilies' => 'Navigateurs par famille',
+ 'UserSettings_WidgetOperatingSystems' => 'Systèmes d\'exploitation',
+ 'UserSettings_WidgetGlobalVisitors' => 'Configuration globale des visiteurs',
+ 'UserSettings_SubmenuSettings' => 'Paramètres',
+ 'UsersManager_PluginDescription' => 'Gestion des utilisateurs dans Piwik: ajouter un nouvel utilisateur, en éditer, mettre à jour les permissions. Toutes les actions sont aussi disponibles au travers de l\'API.',
'UsersManager_UsersManagement' => 'Gestion des utilisateurs',
'UsersManager_UsersManagementMainDescription' => 'Créez de nouveaux utilisateurs ou modifiez-les. Vous pourrez ensuite changez leurs permissions ci-dessus.',
'UsersManager_ManageAccess' => 'Gestion des accès utilisateurs',
@@ -635,139 +924,132 @@ $translations = array(
'UsersManager_PrivView' => 'Consultation',
'UsersManager_PrivAdmin' => 'Administration',
'UsersManager_ChangeAllConfirm' => 'Êtes-vous sûr de vouloir changer les permissions de \'%s\' sur tous les sites Internet?',
- 'UsersManager_Login' => 'Nom d\'utilisateur',
'UsersManager_Password' => 'Mot de passe',
'UsersManager_Email' => 'Courriel',
'UsersManager_Alias' => 'Alias',
+ 'UsersManager_TheSuperUserAliasCannotBeChanged' => 'L\'alias du super utilisateur ne peut $etre changé.',
+ 'UsersManager_ReportToLoadByDefault' => 'Rapport à charger par défaut',
+ 'UsersManager_ReportDateToLoadByDefault' => 'Date du rapport à charger par défaut',
+ 'UsersManager_ForAnonymousUsersReportDateToLoadByDefault' => 'Pour les utilisateurs anonymes, date du rapport à charger par défaut',
+ 'UsersManager_ExcludeVisitsViaCookie' => 'Excluez vos visites en utilisant un cookie',
+ 'UsersManager_YourVisitsAreIgnored' => '%sVos visites sont ignorées par Piwik%s (le cookie d\'exclusion de Piwik a été trouvé sur votre navigateur).',
+ 'UsersManager_YourVisitsAreNotIgnored' => '%sVos visites sont prises en compte par Piwik%s (le cookie d\'exclusion de Piwik n\'a pas été trouvé sur votre navigateur).',
+ 'UsersManager_ClickHereToDeleteTheCookie' => 'Cliquez ici pour supprimer le cookie et pour que Piwik prenne en compte vos visites',
+ 'UsersManager_ClickHereToSetTheCookie' => 'Cliquez ici pour mettre en place un cookie qui permettra à Piwik d\'ignorer vos visites sur vos sites',
'UsersManager_Edit' => 'Éditer',
'UsersManager_AddUser' => 'Ajouter un nouvel utilisateur',
'UsersManager_MenuUsers' => 'Utilisateurs',
- 'UsersManager_DeleteConfirm_js' => 'Êtes-vous sûr de vouloir supprimer l\'utilisateur %s ?',
- 'UsersManager_ExceptionLoginExists' => 'Le nom d\'utilisateur \'%s\' existe déjà.',
- 'UsersManager_ExceptionEmailExists' => 'Un utilisateur avec l\'adresse courriel \'%s\' existe déjà.',
- 'UsersManager_ExceptionInvalidLoginFormat' => 'Le login doit mesurer au moins 3 charactères et contenir uniquement des lettres, des chiffres ou \'_\' ou \'-\' ou \'.\'',
+ 'UsersManager_MenuUserSettings' => 'Paramètres utilisateurs',
+ 'UsersManager_MenuAnonymousUserSettings' => 'Paramètres utilisateurs anonymes',
+ 'UsersManager_NoteNoAnonymousUserAccessSettingsWontBeUsed' => 'Note: Vous n\'avez aucun site web sont l\'accès est accordé à l\'utilisateur anonyme, les paramètres suivants resteront inutilisés.',
+ 'UsersManager_WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess' => 'Quand les utilisateurs ne sont pas connectés et accèdent à Piwik, il verront',
+ 'UsersManager_ChangePassword' => 'Modifier le mot de passe',
+ 'UsersManager_IfYouWouldLikeToChangeThePasswordTypeANewOne' => 'Si vous souhaitez modifier votre mot de passe tapez en un nouveau. Sinon laissez le champ vide.',
+ 'UsersManager_TypeYourPasswordAgain' => 'Tapez à nouveau votre nouveau mot de passe.',
+ 'UsersManager_TheLoginScreen' => 'L\'interface de connexion',
+ 'UsersManager_DeleteConfirm_js' => 'Etes vous sûr de vouloir supprimer l\'utilisateur %s?',
+ 'UsersManager_YourUsernameCannotBeChanged' => 'Votre nom d\'utilisateur a été modifié.',
+ 'UsersManager_ExceptionLoginExists' => 'Le login \'%s\' existe déjà.',
+ 'UsersManager_ExceptionEmailExists' => 'L\'utilisateur avec l\'e-mail \'%s\' existe déjà.',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'Le login doit mesurer au moins 3 caractères et contenir uniquement des lettres, des chiffres ou \'_\' ou \'-\' ou \'.\'',
'UsersManager_ExceptionInvalidPassword' => 'Le mot de passe doit faire entre 6 et 26 caractères.',
'UsersManager_ExceptionInvalidEmail' => 'L\'adresse courriel est invalide.',
'UsersManager_ExceptionDeleteDoesNotExist' => 'L\'utilisateur \'%s\' est inexistant, il n\'a pu être supprimé.',
'UsersManager_ExceptionAdminAnonymous' => 'Vous ne pouvez pas autoriser l\'accès administrateur à l\'utilisateur Anonyme.',
- 'UsersManager_ExceptionEditAnonymous' => 'L\'utilisateur Anonyme ne peut être édité ou supprimé. Il est utilisé pour identifier un utilisateur qui ne s\'est pas encoré connecté. Par exemple vous pouvez rendre vos statistiques publiques en accordant l\'accès \'vue\' à l\'utilisateur \'anonyme\'.',
+ 'UsersManager_ExceptionEditAnonymous' => 'L\'utilisateur Anonyme ne peut être édité ou supprimé. Il est utilisé pour identifier un utilisateur qui ne s\'est pas encore connecté. Par exemple vous pouvez rendre vos statistiques publiques en accordant l\'accès \'vue\' à l\'utilisateur \'anonyme\'.',
'UsersManager_ExceptionSuperUser' => 'L\'utilisateur demandé est le Super Utilisateur qui ne peut être sélectionné, édité ou supprimé depuis l\'API. Vous pouvez l\'éditer manuellement depuis le fichier de configuration.',
'UsersManager_ExceptionUserDoesNotExist' => 'L\'utilisateur \'%s\' est inexistant.',
'UsersManager_ExceptionAccessValues' => 'Le paramètre access doit contenir une des valeurs suivantes : [ %s ]',
- 'SitesManager_Sites' => 'Sites',
- 'SitesManager_WebsitesManagement' => 'Gestion des sites',
- 'SitesManager_MainDescription' => 'Piwik a besoin de sites pour générer des rapports ! Ajoutez, éditez et supprimez des sites, et voyez le code JavaScript à inclure dans vos pages.',
- 'SitesManager_JsTrackingTag' => 'Code JavaScript de suivit',
- 'SitesManager_JsTrackingTagHelp' => 'Ci-dessous le code JavaScript à inclure dans toutes vos pages ',
- 'SitesManager_ShowTrackingTag' => 'Afficher le code',
- 'SitesManager_NoWebsites' => 'Vous n\'avez aucun site Internet à administrer.',
- 'SitesManager_AddSite' => 'Ajouter un site',
- 'SitesManager_Id' => 'Id',
- 'SitesManager_Name' => 'Nom',
- 'SitesManager_Urls' => 'URLs',
- 'SitesManager_MenuSites' => 'Sites',
- 'SitesManager_DeleteConfirm_js' => 'Êtes-vous sûr de vouloir supprimer le site %s?',
- 'SitesManager_ExceptionDeleteSite' => 'Impossible de supprimer le site car c\'est le seul site enregistré dans Piwik. Vous pouvez d\'abord en ajouter un nouveau, puis supprimez celui-ci.',
- 'SitesManager_ExceptionNoUrl' => 'Vous devez spécifier au moins une url pour le site.',
- 'SitesManager_ExceptionEmptyName' => 'Le nom du site ne peut être vide.',
- 'SitesManager_ExceptionInvalidUrl' => 'L\'url \'%s\' est invalide.',
- 'Installation_Installation' => 'Installation',
- 'Installation_InstallationStatus' => 'Statut de l\'installation',
- 'Installation_PercentDone' => '%s %% Fait',
- 'Installation_NoConfigFound' => 'Le fichier de configuration de Piwik ne peut être trouvé et vous essayez d\'accéder à une page de Piwik.<br> <b>&nbsp;&nbsp;&raquo; Vous pouvez <a href=\'index.php\'>installer Piwik maintenant</a></b><br><small>Si vous avez déjà installé Piwik ne vous inquiétez pas Piwik réutilisera ces tables et leurs données.</small>',
- 'Installation_DatabaseSetup' => 'Installation de la base de données',
- 'Installation_DatabaseErrorConnect' => 'Erreur lors de la tentative de connexion au serveur de base de données',
- 'Installation_ConnectionCharacterSetNotUtf8' => 'La connexion au serveur de base de données n\'est pas en UTF8',
- 'Installation_JsTag' => 'Tag JavaScript',
- 'Installation_JsTagHelp' => '<p>Pour comptabiliser tous les visiteurs vous devez copier le tag sur toutes vos pages.</p><p>Vos pages n\'ont pas besoin d\'être en PHP, Piwik fonctionne avec tout type de pages (HTML, ASP, Perl ou n\'importe quel autre langage).</p><p>Ici se trouve le code à insérer : (copiez/collez dans toutes vos pages) </p>',
- 'Installation_JsTagQuicHelpk' => 'Aide rapide',
- 'Installation_JsTagArchivingHelp' => 'Pour les sites à moyen et fort trafic, lisez <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">la page d\'explication sur comment mettre en place une page d\'auto archivage</a> pour que Piwik devienne réellement rapide!',
- 'Installation_Congratulations' => 'Félicitations',
- 'Installation_CongratulationsHelp' => '<p>Félicictations! Votre installation de Piwik est terminée.</p><p>Assurez vous que le code JavaScript est présent sur toutes vos pages et attendez vos premiers visiteurs!</p>',
- 'Installation_ContinueToPiwik' => 'Continuer vers Piwik',
- 'Installation_SetupWebsite' => 'Paramètrer un site',
- 'Installation_SetupWebsiteError' => 'Une erreur a été recontrée pendant l\'ajout du site',
- 'Installation_SetupWebsiteSetupSuccess' => 'Site %s créé avec succès!',
- 'Installation_GeneralSetup' => 'Paramètres généraux',
- 'Installation_GeneralSetupSuccess' => 'Paramètres génraux configurés avec succès',
- 'Installation_SuperUserLogin' => 'login du super user',
- 'Installation_Password' => 'mot de passe',
- 'Installation_PasswordRepeat' => 'mot de passe (à nouveau)',
- 'Installation_Email' => 'courriel',
- 'Installation_SecurityNewsletter' => 'Envoyez moi un courriel pour les mises à jour de versions majeures de piwik ou pour les alertes de sécurité',
- 'Installation_CommunityNewsletter' => 'Envoyez moi un courriel pour les nouveautés de la communauté (nouveaux plugins, nouvelles fonctionnalités, etc.)',
- 'Installation_PasswordDoNotMatch' => 'Le mot de passe ne concorde pas',
- 'Installation_SubmitGo' => 'Go!',
- 'Installation_Requirements' => 'Pré-requis Piwik',
- 'Installation_Optional' => 'Optionel',
- 'Installation_Legend' => 'Légendes',
- 'Installation_Extension' => 'extension',
- 'Installation_SystemCheck' => 'Vérification du système',
- 'Installation_SystemCheckPhp' => 'Version PHP',
- 'Installation_SystemCheckExtensions' => 'Extensions requises',
- 'Installation_SystemCheckDatabaseHelp' => 'Piwik requiert ou l\'extension mysqli ou les extensions pdo et pdo_mysql.',
- 'Installation_SystemCheckPdoAndMysqliHelp' => "Sur un serveur linux vous pouvez compiler PHP avec les options suivantes : %s\n Dans votre php.ini, ajoutez les lignes suivantes: %s",
- 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Plus d\'informations sur: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> et <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
- 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'Sur un serveur windows vous pouvez ajouter les lignes suivantes à votre php.ini: %s',
- 'Installation_SystemCheckSplHelp' => 'Vous devez configurer et recompiler PHP avec la librairie standart (par défaut).',
- 'Installation_SystemCheckZlibHelp' => 'Vous devez reconfigurer et recompiler PHP avec le support zlib, --with-zlib.',
- 'Installation_SystemCheckJson' => 'JSON',
- 'Installation_SystemCheckJsonHelp' => 'Vous devez recompiler PHP avec l\'extension "json" ou "xml" activée.',
- 'Installation_SystemCheckJsonSite' => 'Plus d\'informations sur : <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
- 'Installation_SystemCheckXml' => 'XML',
- 'Installation_SystemCheckXmlHelp' => 'Des plugins et librairies tierces pourront avoir besoin de l\'extension XML.',
- 'Installation_SystemCheckXmlSite' => 'Plus d\'informations sur: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
- 'Installation_SystemCheckWriteDirs' => 'Répertoires avec les droits d\'accès en écriture',
- 'Installation_SystemCheckWriteDirsHelp' => 'Pour corriger les erreurs sur votre système Linux essayez de taper les commandes suivantes',
- 'Installation_SystemCheckMemoryLimit' => 'Limite mémoire',
- 'Installation_SystemCheckMemoryLimitHelp' => 'Sur un site à trafic important le processus d\'archivage peut prendre plus de mémoire que la limite actuelle autorisée.<br />Référez vous à la configuration memory_limit de votre php.ini si nécessaire.',
- 'Installation_SystemCheckOpenURL' => 'Ouvrez l\'URL',
- 'Installation_SystemCheckOpenURLHelp' => 'Abonnements à la newsletter, notifications des mises à jour, et mise à jour en un click requièrent l\'extension curl, allow_url_fopen=On, ou fsockopen() activé.',
- 'Installation_SystemCheckGD' => 'GD &gt; 2.x (graphiques)',
- 'Installation_SystemCheckGDHelp' => 'Les sparklines (petits graphs) ne fonctionneront pas.',
- 'Installation_SystemCheckFunctions' => 'Fonctions requises',
- 'Installation_SystemCheckTimeLimitHelp' => 'Sur un site à trafic important le processus d\'archivage peut prendre plus de temps qu\'il n\'est déjà autorisé.<br /> Référez vous à la configuration max_execution_time de votre php.ini si nécessaire.',
- 'Installation_SystemCheckMailHelp' => 'Les Feedback (commentaires) et mots de passe perdus ne pourront être envoyés sans la fonciton mail().',
- 'Installation_SystemCheckError' => 'Une erreur s\'est produite — elle doit être corrigée avant de pouvoir continuer',
- 'Installation_SystemCheckWarning' => 'Piwik fonctionnera normalement mais certaines fonctionnalités seront manquantes',
- 'Installation_Tables' => 'Création des tables',
- 'Installation_TablesWithSameNamesFound' => 'Environ %s tables dans votre base de données %s ont le même nom que celles que Piwik essaie de créer.',
- 'Installation_TablesFound' => 'Les tables suivantes ont été trouvées dans la base de données',
- 'Installation_TablesWarningHelp' => 'Vous pouvez choisir de réutiliser les tables de la base de données existante ou sélectionner une nouvelle installation pour effacer toutes les données existantes dans la base de données.',
- 'Installation_TablesReuse' => 'Réutiliser les tables existantes',
- 'Installation_TablesDelete' => 'Supprimer les tables détectées',
- 'Installation_TablesDeletedSuccess' => 'Tables Piwik existantes supprimées avec succès',
- 'Installation_TablesCreatedSuccess' => 'Tables crées avec succès!',
- 'Installation_DatabaseCreatedSuccess' => 'Base de données %s crée avec succès !',
- 'Installation_GoBackAndDefinePrefix' => 'Retournez à la page précédente et définissez le préfixe pour les tables Piwik',
- 'Installation_ConfirmDeleteExistingTables' => 'Etes vous sûr de vouloir supprimer les tables : %s de votre base de données? ATTENTION: LES DONNEES SERONT DEFINITIVEMENT PERDUES!',
- 'Installation_Welcome' => 'Bienvenue!',
- 'Installation_WelcomeHelp' => '<p>Piwik est une application d\'analyse du web Open Source qui vous permet d\'obtenir facilement les informations que vous désirez sur vos visiteurs.</p> <p>Ce procédé est divisé en %s étapes faciles et vous prendra 5 minutes environ.</p>',
- 'Installation_ErrorInvalidState' => 'Erreur: il semble que vous essayez de sauter une étape du processus d\'installation, ou vous avez désactivé les coookies, ou le fichier de configuration de Piwik est déjà créé. %sAssurez vous que les cookies sont bien activés%s et retournez %s à la première page d\'installation %s.',
- 'Provider_WidgetProviders' => 'Fournisseurs d\'accès à Internet',
- 'Provider_ColumnProvider' => 'FAI',
- 'Provider_SubmenuLocationsProvider' => 'Situation géographique et FAI',
- 'Goals_ColumnConversions' => 'Conversions',
- 'Goals_ColumnConversionRate' => 'Taux de Conversion',
- 'Goals_ColumnRevenue' => 'Revenu',
- 'DBStats_DatabaseUsage' => 'Utilisation de la base de données',
- 'DBStats_MainDescription' => 'Piwil conserve toutes vos analyses web dans la base de données MySQL. Présentement, les tables utilisent %s.',
- 'DBStats_Table' => 'Table',
- 'DBStats_RowNumber' => 'Numéro de rangée',
- 'DBStats_DataSize' => 'Taille des données',
- 'DBStats_IndexSize' => 'Taille de l\'index',
- 'DBStats_TotalSize' => 'Taille totale',
- 'TranslationsAdmin_MenuTranslations' => 'Traductions',
- 'TranslationsAdmin_MenuLanguages' => 'Langues',
- 'TranslationsAdmin_Plugin' => 'Plugin',
- 'TranslationsAdmin_Definition' => 'Définition',
- 'TranslationsAdmin_DefaultString' => 'Chaine par défaut (English)',
- 'TranslationsAdmin_TranslationString' => 'Traduction (Langue actuelle : %s)',
- 'TranslationsAdmin_Translations' => 'Traductions',
- 'TranslationsAdmin_FixPermissions' => 'Veuillez définir les propriétés des fichiers systèmes',
- 'TranslationsAdmin_AvailableLanguages' => 'Langues disponibles',
- 'TranslationsAdmin_AddLanguage' => 'Ajouter langue',
- 'TranslationsAdmin_LanguageCode' => 'Code langue',
- 'TranslationsAdmin_Export' => 'Exporter langue',
- 'TranslationsAdmin_Import' => 'Importer langue',
-);
+ 'VisitFrequency_PluginDescription' => 'Effectue des rapports sur les visiteurs déjà venus vis à vis des nouveaux visiteurs.',
+ 'VisitFrequency_Evolution' => 'Évolution sur la période',
+ 'VisitFrequency_ColumnReturningVisits' => 'Visites retour',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Actions des visites retour',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Nombre maximum d\'actions par une visite retour',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Temps total passé par les visites retour (en secondes)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Pourcentage de rebond par les visites retour',
+ 'VisitFrequency_ReturnVisits' => '%s visites de visiteurs connus',
+ 'VisitFrequency_ReturnActions' => '%s actions de visites de visiteurs connus',
+ 'VisitFrequency_ReturnMaxActions' => '%s actions maximums par visite de visiteur connus',
+ 'VisitFrequency_ReturnTotalTime' => '%s temps total passé par des visiteurs connus',
+ 'VisitFrequency_ReturnBounceRate' => '%s visiteurs connus ont survolé (quitté le site après une page)',
+ 'VisitFrequency_WidgetOverview' => 'Récapitulatif de la Fréquence',
+ 'VisitFrequency_WidgetGraphReturning' => 'Graphique de visites de visiteurs connus',
+ 'VisitFrequency_SubmenuFrequency' => 'Fréquence',
+ 'VisitorInterest_PluginDescription' => 'Effectue des rapports à propos des intérêts des visiteurs: nombre de pages vues, temps passé sur le site.',
+ 'VisitorInterest_VisitsPerDuration' => 'Visites par durée de la visite',
+ 'VisitorInterest_VisitsPerNbOfPages' => 'Visites par nombre de pages',
+ 'VisitorInterest_ColumnVisitDuration' => 'Durée de la visite',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Pages par visite',
+ 'VisitorInterest_WidgetLengths' => 'Durée des visites',
+ 'VisitorInterest_WidgetPages' => 'Pages par visite',
+ 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Fréquence et Fidélité',
+ 'VisitorInterest_PlusXMin' => '%s min',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
+ 'VisitorInterest_OnePage' => '1 page',
+ 'VisitorInterest_NPages' => '%s pages',
+ 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
+ 'VisitsSummary_PluginDescription' => 'Effectue des rapports sur les valeurs générales des statistiques: visites, visiteurs uniques, nombre d\'actions, taux de rebond, etc.',
+ 'VisitsSummary_VisitsSummary' => 'Récapitulatif des visites',
+ 'VisitsSummary_NbVisits' => '%s visites',
+ 'VisitsSummary_NbUniqueVisitors' => '%s visiteurs uniques',
+ 'VisitsSummary_NbActionsDescription' => '%s actions (pages vues, téléchargements et liens de sortie)',
+ 'VisitsSummary_TotalTime' => '%s temps total passé par les visiteurs',
+ 'VisitsSummary_MaxNbActions' => '%s actions maximums en une visite',
+ 'VisitsSummary_NbVisitsBounced' => '%s visiteurs ont survolé (quitté le site après une page)',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Évolution sur les 30 derniers %s',
+ 'VisitsSummary_Report' => 'Rapport',
+ 'VisitsSummary_GenerateTime' => '%s secondes pour générer la page',
+ 'VisitsSummary_GenerateQueries' => '%s requêtes exécutées',
+ 'VisitsSummary_WidgetLastVisits' => 'Graphique des dernières visites',
+ 'VisitsSummary_WidgetVisits' => 'Récapitulatif des visites',
+ 'VisitsSummary_WidgetLastVisitors' => 'Graphique des derniers visiteurs uniques',
+ 'VisitsSummary_WidgetOverviewGraph' => 'Graphique récapitulatif',
+ 'VisitsSummary_SubmenuOverview' => 'Récapitulatif',
+ 'VisitTime_PluginDescription' => 'Effectue des rapports sur la date locale et serveur. Les informations serveur peuvent être utiles pour planifier une maintenance sur un site web.',
+ 'VisitTime_LocalTime' => 'Visites par heure locale',
+ 'VisitTime_ServerTime' => 'Visites par heure du serveur',
+ 'VisitTime_ColumnServerTime' => 'Heure serveur',
+ 'VisitTime_ColumnLocalTime' => 'Heure locale',
+ 'VisitTime_WidgetLocalTime' => 'Visites par fuseau horaire local',
+ 'VisitTime_WidgetServerTime' => 'Visites par fuseau horaire du serveur',
+ 'VisitTime_SubmenuTimes' => 'Horaires',
+ 'VisitTime_NHour' => '%sh',
+ 'Widgetize_PluginDescription' => 'Le plugin rend l\'export de n\'importe quel Widget Piwik dans votre blog, site web ou sur Igoogle et Netvibes!',
+ 'General_SaveImageOnYourComputer_js' => 'Pour sauvegarder l\'image sur votre ordinateur faites un clic droit dessus et sélectionnez "Enregistrer l\'image sous..."',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'La mise à jour de Piwik en un clic a été désactivée. Si vous ne pouvez pas corriger la cause du message d\'erreur ci-dessous, il est recommandé que vous fassiez manuellement la mise à jour de Piwik. %1$sConsultez la documentation%2$s de la mise à jour%3$s pour commencer!',
+ 'ExamplePlugin_PluginDescription' => 'Plugin d\'exemple: ce plugin décrit comment créer un plugin très simple qui exporte 2 widgets du tableau de bord',
+ 'ExamplePlugin_exampleWidgets' => 'Widgets d\'exemple',
+ 'ExamplePlugin_exampleWidget' => 'Widget d\'exemple',
+ 'ExamplePlugin_blogPiwikRss' => 'Flux RSS du blog Piwik',
+ 'ExamplePlugin_photostreamMatt' => 'Photos de Matt',
+ 'General_GoTo' => 'Rendez vous à %s',
+ 'General_PageBounceRateDefinition' => 'Pourcentage de visites qui ont commencé sur cette page et se sont terminées juste après.',
+ 'General_ColumnExitRate' => 'Taux de sortie',
+ 'General_PageExitRateDefinition' => 'Pourcentage de visites sur cette page qui ont quitté le site juste après.',
+ 'General_ColumnBounces' => 'Rebonds',
+ 'General_BouncesDefinition' => 'Nombre de visites qui ont commencé sur cette page et se sont terminées juste après.',
+ 'General_ColumnEntrances' => 'Entrées',
+ 'General_EntrancesDefinition' => 'Nombre de visites qui ont commencé sur cette page',
+ 'General_ColumnExits' => 'Sorties',
+ 'General_ExitsDefinition' => 'Nombre de visites qui ont terminé sur cette page',
+ 'General_ColumnAverageTimeOnPage' => 'Temps moyen sur la page',
+ 'General_AverageTimeOnPageDefinition' => 'Le temps moyen passé par les visiteurs sur cette page',
+ 'General_DaysHours' => '%1$s jours %2$s heures',
+ 'General_HoursMinutes' => '%1$s heures %2$s min',
+ 'General_MinutesSeconds' => '%1$s min %2$ss',
+ 'General_Seconds' => '%ss',
+ 'General_DisplayGoals' => 'Afficher les objectifs',
+ 'General_ConfigFileIsNotWritable' => 'Le fichier de configuration de Piwik %s n\'a pas la permission d\'écriture, vos modifications ne seront pas sauvegardées. %s Merci de modifier les permissions du fichier de configuration de manière à le rendre accessible en écriture.',
+ 'Actions_SubmenuPagesEntry' => 'Pages d\'entrée',
+ 'Actions_SubmenuPagesExit' => 'Page de sortie',
+ 'CoreAdminHome_Administration' => 'Administration',
+ 'CoreHome_WebAnalyticsReports' => 'Rapports des statistiques web.',
+ 'Goals_Goals' => 'Objectifs',
+ 'Goals_Overview' => 'Vue d\'ensemble',
+ 'Goals_WhereThe' => 'où le',
+ 'Live_Last30Minutes' => 'Les dernières 30 minutes',
+ 'MultiSites_Evolution' => 'Evolution',
+ 'UsersManager_YourVisitsAreIgnoredOnDomain' => '%sVos visites sont ignorées par Piwik sur %s %s(Le cookie d\'exclusion de Piwik est présent sur votre navigateur)',
+ 'UsersManager_ClickHereToSetTheCookieOnDomain' => 'Cliquez ici pour mettre en place un cookie qui exclura vos visites sur ceux de vos sites web qui sont analysés par Piwik sur %s',
+ 'VisitorInterest_Engagement' => 'Engagement',
+); \ No newline at end of file
diff --git a/lang/gl.php b/lang/gl.php
index 960aaecb5f..a941f08a6d 100644
--- a/lang/gl.php
+++ b/lang/gl.php
@@ -117,7 +117,7 @@ $translations = array(
'UserSettings_Browsers' => 'Navegadores',
'UserSettings_Plugins' => 'Plugins',
'UserSettings_Configurations' => 'Configuracións',
- 'UserSettings_OperatinsSystems' => 'Sistemas Operativos',
+ 'UserSettings_OperatingSystems' => 'Sistemas Operativos',
'UserSettings_Resolutions' => 'Resolucións',
'UserSettings_WideScreen' => 'Pantalla panorámica',
'UserSettings_WidgetResolutions' => 'Resolucións de pantalla',
@@ -433,7 +433,6 @@ $translations = array(
'Login_PasswordReminder' => 'Por favor, introduzca o seu nome de usuario ou enderezo de correo electrónico. Recibirá un novo contrasinal por correo electrónico',
'Login_InvalidUsernameEmail' => 'O nome do usuario ou o enderezo de correo electrónicoo son incorrectos',
'Login_MailTopicPasswordRecovery' => 'Recuperar contrasinal',
- 'Login_MailPasswordRecoveryBody' => 'Ola %1s,\n\nO teu novo contrasinal é: %2s\n\n Podes conectarte agora en: %3s',
'Login_PasswordSent' => 'O contrasinal acaba de ser enviado. Comprobe o seu correo electrónico.',
'Login_ContactAdmin' => 'Posible razón: o seu aloxamento pode ter deshabilitado a función mail().<br>Por favor contacte co seu administrador de piwik.',
'UsersManager_ManageAccess' => 'Administrar o acceso',
diff --git a/lang/hu.php b/lang/hu.php
index c91ab1532d..4ac7ca9200 100644
--- a/lang/hu.php
+++ b/lang/hu.php
@@ -145,6 +145,32 @@ $translations = array(
'CoreHome_DayTh_js' => 'Cs',
'CoreHome_DayFr_js' => 'P',
'CoreHome_DaySa_js' => 'Szo',
+ 'CoreHome_ShortDay_1_js' => 'Vas',
+ 'CoreHome_ShortDay_2_js' => 'Hét',
+ 'CoreHome_ShortDay_3_js' => 'Ked',
+ 'CoreHome_ShortDay_4_js' => 'Sze',
+ 'CoreHome_ShortDay_5_js' => 'Csü',
+ 'CoreHome_ShortDay_6_js' => 'Pén',
+ 'CoreHome_ShortDay_7_js' => 'Szo',
+ 'CoreHome_LongDay_1_js' => 'Vasámap',
+ 'CoreHome_LongDay_2_js' => 'Hétfö',
+ 'CoreHome_LongDay_3_js' => 'Kedd',
+ 'CoreHome_LongDay_4_js' => 'Szerda',
+ 'CoreHome_LongDay_5_js' => 'Csütörtök',
+ 'CoreHome_LongDay_6_js' => 'Péntek',
+ 'CoreHome_LongDay_7_js' => 'Szombat',
+ 'CoreHome_ShortMonth_1_js' => 'Jan',
+ 'CoreHome_ShortMonth_2_js' => 'Feb',
+ 'CoreHome_ShortMonth_3_js' => 'Már',
+ 'CoreHome_ShortMonth_4_js' => 'Ápr',
+ 'CoreHome_ShortMonth_5_js' => 'Máj',
+ 'CoreHome_ShortMonth_6_js' => 'Jún',
+ 'CoreHome_ShortMonth_7_js' => 'Júl',
+ 'CoreHome_ShortMonth_8_js' => 'Aug',
+ 'CoreHome_ShortMonth_9_js' => 'Szep',
+ 'CoreHome_ShortMonth_10_js' => 'Okt',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dec',
'CoreHome_MonthJanuary_js' => 'Január',
'CoreHome_MonthFebruary_js' => 'Február',
'CoreHome_MonthMarch_js' => 'Március',
@@ -247,14 +273,14 @@ $translations = array(
'UserSettings_Browsers' => 'Böngészők',
'UserSettings_Plugins' => 'Bővítmények',
'UserSettings_Configurations' => 'Konfigurációk',
- 'UserSettings_OperatinsSystems' => 'Operációs rendszerek',
+ 'UserSettings_OperatingSystems' => 'Operációs rendszerek',
'UserSettings_Resolutions' => 'Felbontások',
'UserSettings_WideScreen' => 'Képernyő oldalarányai',
'UserSettings_ColumnBrowserFamily' => 'Böngészőcsalád',
'UserSettings_ColumnBrowser' => 'Böngésző',
'UserSettings_ColumnPlugin' => 'Bővítmény',
'UserSettings_ColumnConfiguration' => 'Konfiguráció',
- 'UserSettings_ColumnOperatinsSystem' => 'Operációs rendszer',
+ 'UserSettings_ColumnOperatingSystem' => 'Operációs rendszer',
'UserSettings_ColumnResolution' => 'Felbontás',
'UserSettings_ColumnTypeOfScreen' => 'Képernyő típusa',
'UserSettings_WidgetResolutions' => 'Képernyőfelbontások',
@@ -585,7 +611,6 @@ $translations = array(
'Login_PasswordReminder' => 'Kérlek add meg a felhasználó neved vagy e-mail címed. Küldünk egy új jelszót levélben!',
'Login_InvalidUsernameEmail' => 'Helytelen felhasználó és/vagy e-mail cím',
'Login_MailTopicPasswordRecovery' => 'Jelszó újrakérése',
- 'Login_MailPasswordRecoveryBody' => 'Hello %1s, \n\n Az új jelszavad: %2s \n\n Mostmár be tudsz lépni itt: %3s',
'Login_PasswordSent' => 'A jelszó elküldve, kérjük ellenőrizd a postaládád.',
'Login_ContactAdmin' => 'Lehetséges ok: talán a szolgáltatód tiltja a levélküldés funkciót. <br />Kérjük lépj kapcsolatba a Piwik rendszergazdáddal.',
'UsersManager_UsersManagement' => 'Felhasználói menedzsment',
diff --git a/lang/it.php b/lang/it.php
index 86fdd2a3a1..054141d811 100644
--- a/lang/it.php
+++ b/lang/it.php
@@ -1,11 +1,8 @@
<?php
-
-setlocale(LC_TIME, 'it_IT.UTF-8');
-
$translations = array(
'General_Locale' => 'it_IT.UTF-8',
- 'General_TranslatorName' => 'Yusef Maali, Giovdi',
- 'General_TranslatorEmail' => 'contact@yusefmaali.net, francesco@pixelstyle.it',
+ 'General_TranslatorName' => 'Alessandro Coscia, Giovdi, Yusef Maali',
+ 'General_TranslatorEmail' => 'php_staff@yahoo.it, francesco@pixelstyle.it, contact@yusefmaali.net',
'General_EnglishLanguageName' => 'Italian',
'General_OriginalLanguageName' => 'Italiano',
'General_HelloUser' => 'Bentornato, %s!',
@@ -105,24 +102,44 @@ $translations = array(
'General_LongDay_5' => 'Venerd&igrave;',
'General_LongDay_6' => 'Sabato',
'General_LongDay_7' => 'Domenica',
- 'CorePluginsAdmin_Plugins' => 'Plugins',
- 'CorePluginsAdmin_PluginsManagement' => 'Amministra Plugins',
- 'CorePluginsAdmin_MainDescription' => 'I Plugins estendono le funzionalit&agrave; di Piwik. Una volta installati, &egrave; possivile attivarli o disattivarli qui (non tutti sono in italiano).',
- 'CorePluginsAdmin_Plugin' => 'Plugin',
- 'CorePluginsAdmin_Version' => 'Versione',
- 'CorePluginsAdmin_Description' => 'Descrizione',
- 'CorePluginsAdmin_Status' => 'Stato',
- 'CorePluginsAdmin_Action' => 'Azione',
- 'CorePluginsAdmin_PluginHomepage' => 'Homepage Plugins',
- 'CorePluginsAdmin_Activated' => 'Attivato',
- 'CorePluginsAdmin_Active' => 'Attivo',
- 'CorePluginsAdmin_Inactive' => 'Inattivo',
- 'CorePluginsAdmin_ActivatedHelp' => 'Questo plugin non pu&ograve; essere disattivato',
- 'CorePluginsAdmin_Deactivate' => 'Disattiva',
- 'CorePluginsAdmin_Activate' => 'Attiva',
- 'CorePluginsAdmin_MenuPlugins' => 'Plugins',
+ 'General_Dashboard' => 'Dashboard',
+ 'General_MultiSitesSummary' => 'Tutti i siti',
+ 'General_Details' => 'Dettagli',
+ 'General_ExportAsImage_js' => 'Esporta come Immagine',
+ 'General_SaveImageOnYourComputer_js' => 'Per salvare l\'immagine sul tuo computer, clicca di destro sull\'immagine e seleziona "Salva immagine con nome..."',
+ 'General_ForExampleShort' => 'es.',
+ 'General_RequiresFlash' => 'Per vedere i grafici in Piwik &egrave; richiesto Flash',
+ 'General_GraphHelp' => 'Maggiori informazioni su come vedere grafici in Piwik.',
+ 'General_ExceptionDatabaseVersion' => 'La tua %1$s versione &egrave; %2$s ma Piwik ha bisogno di almeno %3$s.',
+ 'General_ExceptionIncompatibleClientServerVersions' => 'La tua %1$s versione del client &egrave; %2$s la quale non &egrave; compatibile con la versione del server %3$s.',
+ 'General_ExceptionMissingFile' => 'Manca il file: %s',
+ 'General_ExceptionFilesizeMismatch' => 'Discordanza di dimensione file: %1$s (dimensione attesa: %2$s, trovata: %3$s)',
+ 'General_ExceptionFileIntegrity' => 'Test di integrità fallito: %s',
+ 'General_ExceptionNonceMismatch' => 'Non &egrave; possibile verificare il token di sicurezza di questo form.',
+ 'General_WarningFileIntegritySkipped' => 'Individuato ambiente di sviluppo. Controllo dell\'integrit&agrave; dei file saltato.',
+ 'General_WarningFileIntegrityNoManifest' => 'Il controllo dell\'integrit&agrave; dei file non pu&ograve; essere eseguito per la mancanza del file manifest.inc.php',
+ 'General_WarningFileIntegrityNoMd5file' => 'Il controllo dell\'integrit&agrave; dei file non pu&ograve; essere eseguito per la mancanza della funzione md5_file().',
+ 'General_FileIntegrityWarningExplanation' => 'Il controllo dell\'integrit&agrave; dei file &egrave; fallito ed ha riportato alcuni errori. Ci&ograve; &egrave; molto probabilmente dovuto al parzioale o fallito upload di alcuni file di Piwik. Dovresti riprovare a rifare l\'upload di tutti i file di Piwik e aggiornare questa pagina fino a quando non mostrer&agrave; errori.',
'API_QuickDocumentation' => '<h2>Guida Veloce alle API</h2><p>Se non sono disponibili dati per la giornata odierna &egrave; possibile <a href=\'misc/generateVisits.php\' target=_blank>generare delle visite</a> usando lo script Visits Generator.</p><p>&Egrave; possibile provare i differenti formati disponibili per ogni metodo. Estrarre tutti i dati che desideri con Piwik &egrave; veramente facile!</p><p><b>Per maggiori informazioni consulta la <a href=\'http://dev.piwik.org/trac/wiki/API\'>Documentazione Ufficiale delle API</a> o il relativo <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>Manuale Completo</a>.</b></p><h2>Autenticazione degli utenti</h2><p>Se si vogliono <b>utilizzare i dati nei propri script, in un crontab, ecc... </b> si deve aggiungere il parametro <code><u>&token_auth=%s</u></code> alle chiamate delle API che abbiano bisogno di autenticazione.</p><p>Il token_auth &egrave; segreto tanto quanto il nome utente e la password, <b>non deve essere condiviso!</p>',
'API_LoadedAPIs' => 'Sono state caricate con successo %s APIs',
+ 'API_PluginDescription' => 'Tutti i dati in Piwik sono disponibili tramite semplici API. Questo plugin &egrave; il punto di accesso web service che puoi chiamare per avere le tue statistiche in xml, json, php, csv, ecc...',
+ 'ExampleAPI_PluginDescription' => 'Plugin di esempio: Come creare API per il tuo plugin per esportare i dati in formati multipli senza uno sforzo speciale nello sviluppo?',
+ 'Actions_Actions' => 'Azioni',
+ 'Actions_SubmenuPages' => 'Pagine viste',
+ 'Actions_SubmenuOutlinks' => 'Link Esterni',
+ 'Actions_SubmenuDownloads' => 'Downloads',
+ 'Actions_ColumnClicks' => 'Clicks',
+ 'Actions_ColumnUniqueClicks' => 'Clicks Unici',
+ 'Actions_ColumnDownloads' => 'Downloads',
+ 'Actions_ColumnUniqueDownloads' => 'Downloads Unici',
+ 'Actions_ColumnPageName' => 'Nome pagina',
+ 'Actions_ColumnClickedURL' => 'URL Click',
+ 'Actions_ColumnDownloadURL' => 'URL Download',
+ 'Actions_PluginDescription' => 'Report riguardo le pagine viste, i link in uscita e i downloads. Il tracciamento dei link in uscita e dei downloads &egrave; automatico!',
+ 'Actions_SubmenuPageTitles' => 'Titoli delle pagine',
+ 'Actions_ColumnPageURL' => 'URL della pagina',
+ 'AnonymizeIP_PluginDescription' => 'Rende anonimi gli ip dei tuoi visitatori per conformarsi alle leggilo o lineguida locali.',
+ 'CoreAdminHome_PluginDescription' => 'Area di amministrazione Piwik.',
'CoreHome_NoPrivileges' => 'Ti sei autenticato come "%s" ma sembra che tu non abbia alcun permesso per operare in Piwik.<br />Chiedi all\'amministratore di sistema di assegnarti i permessi di tipo "view" per accedere alle statistiche.',
'CoreHome_JavascriptDisabled' => 'I JavaScript devono essere abilitati per poter utilizzare Piwik.<br />Nel tuo browser sembra che i JavaScript sono disattivati o non sono supportati.<br />Per usare Piwik a pieno, abilita i JavaScript cambiando le impostazioni del tuo browser e %1sprova di nuovo%2s.<br />',
'CoreHome_TableNoData' => 'Non ci sono dati per questa tabella.',
@@ -141,13 +158,39 @@ $translations = array(
'CoreHome_PeriodWeeks' => 'settimane',
'CoreHome_PeriodMonths' => 'mesi',
'CoreHome_PeriodYears' => 'anni',
- 'CoreHome_DaySu_js' => 'Dom',
- 'CoreHome_DayMo_js' => 'Lun',
- 'CoreHome_DayTu_js' => 'Mar',
- 'CoreHome_DayWe_js' => 'Mer',
+ 'CoreHome_DaySu_js' => 'Do',
+ 'CoreHome_DayMo_js' => 'Lu',
+ 'CoreHome_DayTu_js' => 'Ma',
+ 'CoreHome_DayWe_js' => 'Me',
'CoreHome_DayTh_js' => 'Gio',
- 'CoreHome_DayFr_js' => 'Ven',
- 'CoreHome_DaySa_js' => 'Sab',
+ 'CoreHome_DayFr_js' => 'Ve',
+ 'CoreHome_DaySa_js' => 'Sa',
+ 'CoreHome_ShortDay_1_js' => 'Dom',
+ 'CoreHome_ShortDay_2_js' => 'Lun',
+ 'CoreHome_ShortDay_3_js' => 'Mar',
+ 'CoreHome_ShortDay_4_js' => 'Mer',
+ 'CoreHome_ShortDay_5_js' => 'Gio',
+ 'CoreHome_ShortDay_6_js' => 'Ven',
+ 'CoreHome_ShortDay_7_js' => 'Sab',
+ 'CoreHome_LongDay_1_js' => 'Domenica',
+ 'CoreHome_LongDay_2_js' => 'Lunedì',
+ 'CoreHome_LongDay_3_js' => 'Martedì',
+ 'CoreHome_LongDay_4_js' => 'Mercoledì',
+ 'CoreHome_LongDay_5_js' => 'Giovedì',
+ 'CoreHome_LongDay_6_js' => 'Venerdì',
+ 'CoreHome_LongDay_7_js' => 'Sabato',
+ 'CoreHome_ShortMonth_1_js' => 'Gen',
+ 'CoreHome_ShortMonth_2_js' => 'Feb',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Apr',
+ 'CoreHome_ShortMonth_5_js' => 'Mag',
+ 'CoreHome_ShortMonth_6_js' => 'Giu',
+ 'CoreHome_ShortMonth_7_js' => 'Lug',
+ 'CoreHome_ShortMonth_8_js' => 'Ago',
+ 'CoreHome_ShortMonth_9_js' => 'Set',
+ 'CoreHome_ShortMonth_10_js' => 'Ott',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dic',
'CoreHome_MonthJanuary_js' => 'Gennaio',
'CoreHome_MonthFebruary_js' => 'Febbraio',
'CoreHome_MonthMarch_js' => 'Marzo',
@@ -160,6 +203,24 @@ $translations = array(
'CoreHome_MonthOctober_js' => 'Ottobre',
'CoreHome_MonthNovember_js' => 'Novembre',
'CoreHome_MonthDecember_js' => 'Dicembre',
+ 'CoreHome_PluginDescription' => 'Struttura di base per i report di Web Analytics.',
+ 'CorePluginsAdmin_Plugins' => 'Plugins',
+ 'CorePluginsAdmin_PluginsManagement' => 'Amministra Plugins',
+ 'CorePluginsAdmin_MainDescription' => 'I Plugins estendono le funzionalit&agrave; di Piwik. Una volta installati, &egrave; possivile attivarli o disattivarli qui (non tutti sono in italiano).',
+ 'CorePluginsAdmin_Plugin' => 'Plugin',
+ 'CorePluginsAdmin_Version' => 'Versione',
+ 'CorePluginsAdmin_Description' => 'Descrizione',
+ 'CorePluginsAdmin_Status' => 'Stato',
+ 'CorePluginsAdmin_Action' => 'Azione',
+ 'CorePluginsAdmin_PluginHomepage' => 'Homepage Plugins',
+ 'CorePluginsAdmin_Activated' => 'Attivato',
+ 'CorePluginsAdmin_Active' => 'Attivo',
+ 'CorePluginsAdmin_Inactive' => 'Inattivo',
+ 'CorePluginsAdmin_ActivatedHelp' => 'Questo plugin non pu&ograve; essere disattivato',
+ 'CorePluginsAdmin_Deactivate' => 'Disattiva',
+ 'CorePluginsAdmin_Activate' => 'Attiva',
+ 'CorePluginsAdmin_MenuPlugins' => 'Plugins',
+ 'CorePluginsAdmin_PluginDescription' => 'Interfaccia di amministrazione plugins.',
'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; Aggiornamenti',
'CoreUpdater_DatabaseUpgradeRequired' => 'Aggiornamento del Database richiesto',
'CoreUpdater_YourDatabaseIsOutOfDate' => 'Il tuo Database Piwik &egrave; obsoleto e deve essere aggiornato prima di continuare.',
@@ -182,23 +243,40 @@ $translations = array(
'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Puoi aggiornare alla versione %s in automatico o scaricare il pacchetto e installarlo manualmente:',
'CoreUpdater_DownloadX' => 'Scarica %s',
'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Il "Piwik One Click Update" &egrave; stato cancellato. Se non riesci a sistemare il problema causato dal messaggio di errore indicato, &egrave; consigliabile aggiornare manualmente Piwik. %s Controlla il %sManuale di aggiornamento%s per iniziare!',
- 'CoreUpdate_DownloadingUpdateFromX' => 'Sto scaricando l\'aggiornamento da %s',
- 'CoreUpdate_UnpackingTheUpdate' => 'Sto scompattando dell\'aggiornamento',
'CoreUpdater_VerifyingUnpackedFiles' => 'Sto verificando i file scompattati',
'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Sto creando un backup del file di configurazione in %s',
'CoreUpdater_InstallingTheLatestVersion' => 'Sto installando l\'ultima versione',
'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik &egrave; stato aggiornato con successo!',
- 'Actions_Actions' => 'Azioni',
- 'Actions_SubmenuPages' => 'Pagine viste',
- 'Actions_SubmenuOutlinks' => 'Link Esterni',
- 'Actions_SubmenuDownloads' => 'Downloads',
- 'Actions_ColumnClicks' => 'Clicks',
- 'Actions_ColumnUniqueClicks' => 'Clicks Unici',
- 'Actions_ColumnDownloads' => 'Downloads',
- 'Actions_ColumnUniqueDownloads' => 'Downloads Unici',
- 'Actions_ColumnPageName' => 'Nome pagina',
- 'Actions_ColumnClickedURL' => 'URL Click',
- 'Actions_ColumnDownloadURL' => 'URL Download',
+ 'CoreUpdater_EmptyDatabaseError' => 'Piwik &egrave; stato aggiornato con successo!',
+ 'CoreUpdater_PluginDescription' => 'Meccanismo di aggiornamento di Piwik',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Nota importante per grandi installazioni di Piwik',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'Se hai un database Piwik molto grande, gli aggiornamenti potrebbero essere troppo lunghi per essere eseguiti dal browser. In questo caso, puoi eseguire l\'aggiornamento da riga di comando: %s',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => 'Se non puoi usare l\'aggiornamento da riga di comando e Piwik non riesce ad aggiornarsi (per un timeout del database, timout del browser o qualsiasi altro problema), puoi eseguire manualmente le query SQL per aggiornare Piwik.',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => 'Clicca qui per vedere e copiare la lista di query SQL che dovranno essere eseguite',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => 'Nota: se esegui manualmente queste query, puoi aspettarti che alcune di queste falliranno. In questo caso, semplicemente ignorale, ed esegui la successiva della lista.',
+ 'CoreUpdater_ReadyToGo' => 'Pronto a partire?',
+ 'CoreUpdater_ErrorDIYHelp' => 'Se sei un utente avanzato e incontri un errore nell\'aggiornamento del database:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'identifica e correggi la causa del problema (es. memory_limit o max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'esegui le query fallite rimanenti nell\'aggiornamento.',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'aggiorna manualmente la tabella \'option\' nel tuo database Piwik, settando il valore di version_core alla versione dell\'aggiornamento fallito',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'ri-esegui l\'aggiornamento (tramite il browser o da riga di comando) per continuare con gli aggiornamenti rimanenti',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'riporta l\'errore (e la soluzione) cos&igrave; che Piwik possa migliorare',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Scaricando gli aggiornamenti da %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Decomprimendo gli aggiornamenti',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'La tua versione di Piwik %s &egrave; aggiornata.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Archivio incompatibile: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Archivio vuoto.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'L\'archivio &egrave; incompleto: alcuni file mancano (es. %s).',
+ 'DBStats_DatabaseUsage' => 'Uso del Database',
+ 'DBStats_MainDescription' => 'Piwik sta salvando tutti i dati statistici nel Database MySQL. Attualmente, le tabelle di Piwik stanno usando %s.',
+ 'DBStats_Table' => 'Tabella',
+ 'DBStats_RowNumber' => 'Numero di righe',
+ 'DBStats_DataSize' => 'Dimensione dei dati',
+ 'DBStats_IndexSize' => 'Dimensione degli indici',
+ 'DBStats_TotalSize' => 'Dimensione totale',
+ 'DBStats_PluginDescription' => 'Questo plugin riporta l\'uso di MySQL da parte delle tabelle di Piwik.',
+ 'DBStats_LearnMore' => 'Per apprendere i dettagli su come Piwik processa i dati, e su come far funzionare bene Piwik per siti a medio e alto traffico, dai un\'occhiata alla documentazione %s.',
+ 'DBStats_RowCount' => 'Conteggio delle righe',
'Dashboard_Dashboard' => 'Dashboard',
'Dashboard_AddWidget' => 'Aggiungi widget...',
'Dashboard_DeleteWidgetConfirm' => 'Sei sicuro di voler eliminare il widget dalla dashboard?',
@@ -210,6 +288,226 @@ $translations = array(
'Dashboard_TitleClickToAdd_js' => 'Clicca per aggiungere nella dashboard',
'Dashboard_LoadingWidget_js' => 'Caricamento widget, attendere...',
'Dashboard_WidgetNotFound_js' => 'Widget non trovato',
+ 'Dashboard_PluginDescription' => 'La tua Dashboard di Web Analytics. Puoi personalizzare la TUA Dashboard: puoi aggiungere nuovi widget e cambiarne l\'ordine.Ogni utente pu&ograve; accedere alla propria Dashboard personalizzata.',
+ 'ExampleFeedburner_PluginDescription' => 'Plugin di esempio: Come mostrare gli iscritti di Feedburner in un widget nella Dashboard?',
+ 'ExamplePlugin_PluginDescription' => 'Plugin di esempio: Questo plugin mostra come crearne uno molto semplice, che espone due widget nella Dashboar.',
+ 'ExamplePlugin_exampleWidgets' => 'Widget di esempio',
+ 'ExamplePlugin_exampleWidget' => 'Widget di esempio',
+ 'ExamplePlugin_blogPiwikRss' => 'RSS del Blog Piwik',
+ 'ExamplePlugin_photostreamMatt' => 'Le foto di Matt',
+ 'ExampleRssWidget_PluginDescription' => 'Plugin di esempio: Come creare un nuovo widget che legge un feed RSS?',
+ 'ExampleUI_PluginDescription' => 'Plugin di esempio: Questo plugin mostra come lavorare con Piwik UI: creare tabelle, grafici, ecc.',
+ 'Feedback_PluginDescription' => 'manda i tuoi suggerimenti al Team Piwik. Condividi le tue idee e suggerimenti con noi!',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Hai un bug da segnalare o una richiesta di funzionalit&agrave;?',
+ 'Feedback_ViewAnswersToFAQ' => 'Guarda le risposte fra le %s FAQ (Domande frequenti) %s',
+ 'Feedback_WhyAreMyVisitsNoTracked' => 'Perch&egrave; i visitatori del mio sito non sono tracciati?',
+ 'Feedback_HowToExclude' => 'Come posso escludere il tracciamento delle mie visite?',
+ 'Feedback_WhyWrongCountry' => 'Perch&egrave; Piwik mostra le mie visite dallo stato sbagliato?',
+ 'Feedback_HowToAnonymizeIP' => 'Come posso mascherare gli IP dei miei visitatori nel mio database?',
+ 'Feedback_VisitTheForums' => 'Visita il %s Forum %s',
+ 'Feedback_LearnWaysToParticipate' => 'Impara tutti i modi attraverso i quali puoi %s partecipare %s',
+ 'Feedback_SpecialRequest' => 'Hai una richiesta speciale per il team Piwik?',
+ 'Feedback_ContactThePiwikTeam' => 'Contatta il team Piwik!',
+ 'Feedback_IWantTo' => 'Vorre: ',
+ 'Feedback_CategoryShareStory' => 'Condividi una storia di successo Piwik:',
+ 'Feedback_CategorySponsor' => 'Sponsorizza Piwik',
+ 'Feedback_CategoryHire' => 'Ingaggia un consulente Piwik',
+ 'Feedback_CategorySecurity' => 'Segnala un problema di sicurezza',
+ 'Feedback_MyEmailAddress' => 'Il mio indirizzo email:',
+ 'Feedback_MyMessage' => 'Il mio messaggio:',
+ 'Feedback_DetailsPlease' => '(perfavore includi i dettagli)',
+ 'Feedback_SendFeedback' => 'Invia',
+ 'Feedback_ManuallySendEmailTo' => 'Perfavore invia manualmente il messaggio a',
+ 'Feedback_MessageSent' => 'Il tuo messaggio &egrave; stato inviato al team Piwik.',
+ 'Feedback_ThankYou' => 'Grazie per aiutarci a rendere Piwik migliore!',
+ 'Feedback_ThePiwikTeam' => 'Il Team Piwik',
+ 'Feedback_ExceptionBodyLength' => 'Il messaggio deve essere lungo almeno %s caratteri.',
+ 'Feedback_ExceptionNoUrls' => 'Il messaggio non pu&ograve; contenere URL, per evitare messaggi di SPAM.',
+ 'Goals_ColumnConversions' => 'Conversioni',
+ 'Goals_ColumnConversionRate' => 'Tasso di conversioni',
+ 'Goals_ColumnRevenue' => 'Ricavo',
+ 'Goals_PluginDescription' => 'Crea degli obiettivi e guarda i report sulle conversioni: evoluzioni durante il tempo, guadagno per visita, conversioni per referer, per parola chiave, ecc.',
+ 'Goals_OverallRevenue' => '%s ricavo complessivo',
+ 'Goals_OverallConversionRate' => '%s rapporto di conversione complessivo (visite con un obiettivo completato)',
+ 'Goals_Conversions' => '%s conversioni',
+ 'Goals_ConversionRate' => '%s rapporto di conversione',
+ 'Goals_NoGoalsNeedAccess' => 'Solo un Amministratore o il Super Utente possono aggiungere Obiettivi per un sito. Chiedi a tuo amministratore di Piwik di settare un Obiettivo per il tuo sito.<br/>
+Tracciare gli obiettivi &egrave; un ottimo aiuto per capire e massimizzare le prestazioni del tuo sito!',
+ 'Goals_AddNewGoal' => 'Aggiungi un nuovo obiettivo',
+ 'Goals_AddNewGoalOrEditExistingGoal' => '%sAggiungi un nuovo obiettivo%s o %sModifica%s un obiettivo esistente',
+ 'Goals_AddGoal_js' => 'Aggiungi un obiettivo',
+ 'Goals_UpdateGoal_js' => 'Aggiorna un obiettivo',
+ 'Goals_DeleteGoalConfirm_js' => 'Sei sicuro di voler cancellare l\'obiettivo %s?',
+ 'Goals_GoalName' => 'Nome Obiettivo',
+ 'Goals_GoalIsTriggered' => 'L\'obiettivo &egrave; innescato',
+ 'Goals_GoalIsTriggeredWhen' => 'L\'obiettivo &egrave; innescato quando',
+ 'Goals_WhenVisitors' => 'quando i visitatori',
+ 'Goals_Manually' => 'manualmente',
+ 'Goals_ManuallyTriggeredUsingJavascriptFunction' => 'L\'obiettivo &egrave; innescato usando l\'API Javascript trackGoal()',
+ 'Goals_VisitUrl' => 'Visitano una specifica URL (pagina o gruppo di pagine)',
+ 'Goals_Download' => 'Scaricano un file',
+ 'Goals_ClickOutlink' => 'Cliccano su un Link a un sito esterno',
+ 'Goals_Optional' => '(opzionale)',
+ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => 'dove la pagina visitata contiene una chiamata al metodo Javascript piwikTracker.trackGoal() (%smaggiori dettagli%s)',
+ 'Goals_DefaultRevenue' => 'Il ricavo predefinito per l\'obiettivo &egrave;',
+ 'Goals_DefaultRevenueHelp' => 'Per esempio, un Form di Contatto inviato da un visitatore pu&ograve; valere mediamente $10. Piwik pu%ograve; aiutarti a capire quanto rendono i tuoi visitatori.',
+ 'Goals_ConversionsOverview' => 'Visione d\'insieme sulle Conversioni',
+ 'Goals_BestCountries' => 'I tuoi stati che convertono meglio sono:',
+ 'Goals_BestKeywords' => 'Le tue keyword che convertono meglio sono:',
+ 'Goals_BestReferers' => 'I tuoi referer che convertono meglio sono:',
+ 'Goals_ReturningVisitorsConversionRateIs' => 'Il rapporto di conversione dei visitatori che tornano &egrave; %s',
+ 'Goals_NewVisitorsConversionRateIs' => 'Il rapporto di conversione dei nuovi visitatori &egrave; %s',
+ 'Goals_Contains' => 'contiene %s',
+ 'Goals_IsExactly' => '&egrave; esattamente %s',
+ 'Goals_MatchesExpression' => 'soddisfa l\'espressione %s',
+ 'Goals_CaseSensitive' => 'Match sensibile alle maiuscole e minuscole',
+ 'Goals_Pattern' => 'Pattern',
+ 'Installation_Installation' => 'Installazione',
+ 'Installation_InstallationStatus' => 'Stato dell\'installazione',
+ 'Installation_PercentDone' => '%s %% Fatto',
+ 'Installation_NoConfigFound' => 'Il file di configurazione di Piwik non &egrave; stato trovato e stai tentando l\'accesso ad una pagina di Piwik.<br /><b>&nbsp;&nbsp;&raquo; Puoi <a href=\'index.php\'>installare Piwik ora.</a></b><br /><small>Se hai gi&agrave; installato in precedenza Piwik e nel tuo Database sono presenti delle tabelle della vecchia installazione, non preoccuparti, puoi riutilizzarle e salvare i dati gi&agrave; esistenti!</small>',
+ 'Installation_MysqlSetup' => 'Configurazione Database MySQL',
+ 'Installation_MysqlErrorConnect' => 'Si &egrave; verificato un errore durante la connessione al Database MySQL',
+ 'Installation_JsTag' => 'Codice JavaScript',
+ 'Installation_JsTagHelp' => '<p>Per conteggiare tutti i visitatori, devi inserire il codice JavaScript in tutte le pagine del sito.</p><p>Non &egrave; necessario che siano scritte in PHP, Piwik supporta tutti i tipi di pagine (HTML, ASP, Perl o un qualunque altro linguaggio).</p><p>Questo &egrave; il codice da inserire: (copia e incolla in tutte le tue pagine) </p>',
+ 'Installation_Congratulations' => 'Congratulazioni',
+ 'Installation_CongratulationsHelp' => '<p>Congratulazioni! L\'installazione di Piwik &egrave; stata completata.</p><p>Assicurati che il codice JavaScript sia inserito in tutte le pagine del sito e aspetta i tuoi primi visitatori!</p>',
+ 'Installation_ContinueToPiwik' => 'Vai a Piwik',
+ 'Installation_SetupWebsite' => 'Configura un sito web',
+ 'Installation_SetupWebsiteError' => 'C\'&egrave; stato un errore durante l\'aggiunta del sito web',
+ 'Installation_GeneralSetup' => 'Configurazione di base',
+ 'Installation_GeneralSetupSuccess' => 'Configurazione di base terminata con successo',
+ 'Installation_SuperUserLogin' => 'Nome utente amministratore',
+ 'Installation_Password' => 'Password',
+ 'Installation_PasswordRepeat' => 'Password (ripeti)',
+ 'Installation_Email' => 'E-mail',
+ 'Installation_SecurityNewsletter' => 'Informami via e-mail sugli aggiornamenti pi&ugrave; importanti di Piwik',
+ 'Installation_CommunityNewsletter' => 'Informami via e-mail sugli aggiornamenti della community (nuovi plugins, caratteristiche, ecc.)',
+ 'Installation_PasswordDoNotMatch' => 'Le Password non coincidono',
+ 'Installation_SubmitGo' => 'Vai!',
+ 'Installation_Requirements' => 'Requisiti di Piwik',
+ 'Installation_Optional' => 'Opzionale',
+ 'Installation_Legend' => 'Legenda',
+ 'Installation_SystemCheck' => 'Controllo del Sistema',
+ 'Installation_SystemCheckPhp' => 'Versione PHP',
+ 'Installation_SystemCheckExtensions' => 'Estensioni Richieste',
+ 'Installation_SystemCheckPdoHelp' => 'Devi abilitare l\'estensione PDO nel tuo file php.ini.',
+ 'Installation_SystemCheckPdoMysqlHelp' => 'Devi abilitare l\'estensione PDO_MYSQL nel tuo file php.ini.',
+ 'Installation_SystemCheckSplHelp' => 'Devi configurare e ricostruire il PHP con la libreria Standard PHP abilitata (di default).',
+ 'Installation_SystemCheckZlibHelp' => 'Devi configurare e ricostruire il PHP con il supporto zlib abilitato, --with-zlib.',
+ 'Installation_SystemCheckWriteDirs' => 'Directories con permessi di scrittura',
+ 'Installation_SystemCheckWriteDirsHelp' => 'Per correggere questo errore in Linux, prova ad eseguire il seguente comando/i',
+ 'Installation_SystemCheckMemoryLimit' => 'Memoria massima',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'Su un sito web con grande traffico, il processo di archiviazione potrebbe richiedere pi&ugrave; memoria di quella attualmente consentita.<br />Controlla la direttiva memory_limmit nel tuo file php.ini se necessario.',
+ 'Installation_SystemCheckGD' => 'Libreria grafica GD &gt; 2.x',
+ 'Installation_SystemCheckGDHelp' => 'Gli sparklines (piccoli grafici affianco al testo) non saranno disponibili.',
+ 'Installation_SystemCheckFunctions' => 'Funzioni richieste',
+ 'Installation_SystemCheckTimeLimitHelp' => 'Su un sito web con grande traffico, il processo di archiviazione potrebbe richiedere pi&ugrave; tempo di quello attualmente consentito.<br />Controlla la direttiva max_execution_time nel tuo file php.ini se necessario.',
+ 'Installation_SystemCheckMailHelp' => 'Feedback e Password perdute non saranno inviate senza la funzione mail() disponibile.',
+ 'Installation_SystemCheckError' => 'Si &egrave; verificato un errore - deve essere corretto prima di proseguire',
+ 'Installation_SystemCheckWarning' => 'Piwik non sar&agrave; pienamente funzionante, ma alcune funzioni potrebbero essere mancanti.',
+ 'Installation_Tables' => 'Sto creando le tabelle',
+ 'Installation_TablesWithSameNamesFound' => 'Alcune %s tabelle nel tuo Database %s hanno lo stesso nome delle tabelle che Piwik sta cercando di creare.',
+ 'Installation_TablesFound' => 'Le seguenti tabelle sono state create nel Database',
+ 'Installation_TablesWarningHelp' => 'Scegliere se riusare le tabelle esistenti nel Database (da una precedente installazione di Piwik) o procedere con un nuova installazione cancellando tutti i dati esistenti.',
+ 'Installation_TablesReuse' => 'Riusa le tabelle esistenti',
+ 'Installation_TablesDelete' => 'Cancella le tabelle individuate',
+ 'Installation_TablesDeletedSuccess' => 'Le tabelle di Piwik esistenti sono state eliminate con successo',
+ 'Installation_TablesCreatedSuccess' => 'Tabelle create con successo!',
+ 'Installation_DatabaseCreatedSuccess' => 'Database %s creato con successo!',
+ 'Installation_GoBackAndDefinePrefix' => 'Torna indietro e definisci un nuovo prefisso per le tabelle di Piwik',
+ 'Installation_ConfirmDeleteExistingTables' => 'Sei sicuro di voler cancellare le tabelle %s dal tuo Database? ATTENZIONE: I DATI NON POTRANNO ESSERE RECUPERATI!',
+ 'Installation_Welcome' => 'Benvenuto!',
+ 'Installation_WelcomeHelp' => '<p>Piwik &egrave; un software open source che ti permette di analizzare facilmente le informazioni dei visitatori che visitano i tuoi siti web.</p><p>Questa procedura si divide in %s semplici passaggi e si completa nel giro di 5 minuti.</p>',
+ 'Installation_ErrorInvalidState' => 'Errore: sembra che stai tentando di saltare un passaggio del processo di installazione, i tuoi Cookies sono disabilitati o il file di configurazione Piwik &egrave; stato gi&agrave; creato. %sControlla che i Cookies siano attivati%s e %s ripeti l\'installazione dal primo passaggio %s.',
+ 'Installation_PluginDescription' => 'Processo di installazione di Piwik. L\'installazione &egrave; di solito fatta una sola volta. Se il file di configurazione (config/config.inc.php) viene cancellato, l\'installazione partir&agrave; di nuovo.',
+ 'Installation_DatabaseSetup' => 'Setup database',
+ 'Installation_DatabaseSetupServer' => 'database server',
+ 'Installation_DatabaseSetupLogin' => 'login',
+ 'Installation_DatabaseSetupPassword' => 'password',
+ 'Installation_DatabaseSetupDatabaseName' => 'Nome database',
+ 'Installation_DatabaseSetupTablePrefix' => 'Prefisso tabelle',
+ 'Installation_DatabaseSetupAdapter' => 'Adattatore',
+ 'Installation_DatabaseErrorConnect' => 'Errore durante la connessione al server del database',
+ 'Installation_DatabaseCheck' => 'Controllo database',
+ 'Installation_DatabaseServerVersion' => 'Versione del server del database',
+ 'Installation_DatabaseClientVersion' => 'Versione del client del database',
+ 'Installation_DatabaseCreation' => 'Creazione del database',
+ 'Installation_DatabaseClientCharset' => 'Set dei caratteri del client del database',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'La connessione del client del databse non &egrave; settata come predefinito a UTF8. Questo non &egrave; un problema grave:
+<b>Piwik funzioner&agrave; correttamente</b>. Tuttavia per coerenza, &egrave; raccomandabile che tu faccia una delle seguenti cose:
+<ul style="list-style: disc;margin-left:10px"><li>nel tuo config/config.ini.php, aggiungi <code>charset = utf8</code> sotto la sezione [database] del tuo file di configurazione Piwik <code>config/config.ini.php</code></li><li>ricompila libmysql --with-charset=utf8</li></ul>',
+ 'Installation_DatabaseTimezone' => 'Timezone del database',
+ 'Installation_TimezoneMismatch' => 'date.timezone di PHP non &egrave; lo stesso del timezone del database server. Ci&ograve; potrebbe causare problemi con i report, non mostrando i dati per la giusta ora del giorno. Maggiori informazioni qui %s',
+ 'Installation_JsTagHelpTitle' => 'Come inserire il codice sul tuo sito?',
+ 'Installation_LargePiwikInstances' => 'Aiuto per grandi installazioni di Piwik',
+ 'Installation_JsTagArchivingHelp' => 'Per siti a traffico medio/alto, dai un occhio a <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">How to setup auto archiving page</a> per far andare Piwik molto veloce!',
+ 'Installation_SetupWebSiteName' => 'nome del sito',
+ 'Installation_SetupWebSiteURL' => 'URL del sito',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Sito %s creato con successo!',
+ 'Installation_Extension' => 'estensione',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik necessita dell\'estensione mysqli o in alternativa entrambi il PDO e l\'estensione pdo_mysql',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'Su un server Linux puoi compilare PHP con le seguenti opzioni: %1$s Nel tuo php.ini, aggiungi le seguenti linee: %2$s',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Maggiori informazioni a riguardo: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> e <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'Su un server Windows puoi aggiungere le seguenti linee al tuoi php.ini: %s',
+ 'Installation_SystemCheckIconvHelp' => 'Hai bisogno di configurare e fare rebuild di PHP con il supporto a "iconv" abilitato, --with-iconv',
+ 'Installation_SystemCheckDomHelp' => 'DOM &egrave; parte del core di PHP. Probabilmente hai bisogno di installare il modulo dom, es. php-5-dom.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'Hai bisogno di configurare e fare rebuild di PHP con l\'estensione json o xml abilitate.',
+ 'Installation_SystemCheckJsonSite' => 'Maggiori informazioni: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Alcuni plugin e librerie di terze parti potrebbero richiedere l\'estensione XML.',
+ 'Installation_SystemCheckXmlSite' => 'Maggiori informazioni: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckOpenURL' => 'Apri URL',
+ 'Installation_SystemCheckOpenURLHelp' => 'Iscrizione alla newsletter, notifiche per gli aggiornamenti, e \'one-click updates\' (aggiornamenti con un solo click) richiedono l\'estensione \'curl\', allow_url_fopen=On, o fsockopen() abilitato.',
+ 'Installation_SystemCheckParseIniFileHelp' => 'Questa funzione &egrave; stata disabilitata sul tuo host. Piwik prover&agrave; a simularla ma potrebbe incontrare altre restrizioni di sicurezza. Anche le prestazioni del tracciatore potrebbero risentirne.',
+ 'Installation_SystemCheckDebugBacktraceHelp' => 'View::factory non pu&ograve; creare viste (view) per il modulo chiamante.',
+ 'Installation_SystemCheckCreateFunctionHelp' => 'Piwik usa funzioni anonime per i callbacks.',
+ 'Installation_SystemCheckMbstring' => 'mbstring',
+ 'Installation_SystemCheckMbstringHelp' => 'Dovresti settare mbstring.func_overload a "0"',
+ 'Installation_SystemCheckFileIntegrity' => 'Integrit&agrave; dei file',
+ 'Installation_SystemCheckProtocol' => 'Protocollo',
+ 'Installation_SystemCheckProtocolHelp' => 'Se sei dietro a un reverse proxy, aggiungi queste linee al config/config.ini.php sotto la sezione [General]:',
+ 'Installation_SystemCheckIpv4' => 'IPv4',
+ 'Installation_SystemCheckIpv4Help' => 'Dovresti disabilitare IPv6 nelle configurazioni del tuo server.',
+ 'Installation_ConfigurationHelp' => 'Il tuo file di configurazioni Piwik sembra essere configurato male. Puoi rimuovere il file config/config.ini.php e ricominciare l\'installazione, o correggere i dati di connessione al database.',
+ 'LanguagesManager_PluginDescription' => 'Questo plugin mostrer&agrave; la lista delle lingue disponibili per l\'interfaccia Piwik. La lingua selezionata sar&agrave; salvata nelle preferenze per ciascun utente.',
+ 'Live_PluginDescription' => 'Spia i tuoi visitatori, dal vivo, in tempo reale!',
+ 'Live_VisitorLog' => 'Log Visitatori',
+ 'Live_Date' => 'Data',
+ 'Live_Time' => 'Orario',
+ 'Live_Referrer_URL' => 'URL del referer',
+ 'Login_LoginPasswordNotCorrect' => 'Username & Password non corretti',
+ 'Login_Login' => 'Username',
+ 'Login_Password' => 'Password',
+ 'Login_LoginOrEmail' => 'Login o E-mail',
+ 'Login_LogIn' => 'Entra',
+ 'Login_Logout' => 'Esci',
+ 'Login_LostYourPassword' => 'Hai perso la password?',
+ 'Login_RemindPassword' => 'Ricorda password',
+ 'Login_PasswordReminder' => 'Per favore, inserisci il tuo username o l\'indirizzo e-mail. Riceverai una nuova password via e-mail.',
+ 'Login_InvalidUsernameEmail' => 'Username e/o indirizzo e-mail non validi',
+ 'Login_MailTopicPasswordRecovery' => 'Recupero Password',
+ 'Login_PasswordSent' => 'La password &egrave; stata inviata. Controlla la tua casella e-mail.',
+ 'Login_ContactAdmin' => 'Possibile ragione: il tuo host potrebbe non avere attive le funzionalit&agrave; di e-mail.<br />Per favore, contatta l\'amministratore del server.',
+ 'Login_PluginDescription' => 'Plugin di Autenticazione Login, legge le credenziali dal file config/config.inc.php per il Super Utente, e dal Database per gli altri utenti. Pu&ograve; facilmente essere rimpiazzato per introdurre un nuovo meccanismo di Autenticazione (OpenID, htaccess, Auth personalizzata, ecc.).',
+ 'Login_PasswordRepeat' => 'Password (ripeti)',
+ 'Login_ChangePassword' => 'Cambio password',
+ 'Login_PasswordResetToken' => 'Azzeramento token della password',
+ 'Login_PasswordsDoNotMatch' => 'La password non combacia.',
+ 'Login_PasswordSuccessfullyChanged' => 'Password cambiata correttamente.',
+ 'Login_InvalidOrExpiredToken' => 'Il token non &egrave; valido o &egrave; scaduto',
+ 'Login_MailPasswordRecoveryBody' => 'Ciao %1$s, una richiesta di reset della password &egrave; stata ricevuta da %2$s. Per resettare la tua password:
+ 1) Vai al form per resettare la password qui: %3$s
+ 2) Inserisci il seguente token %4$s
+ 3) Completa il form (inserendo la tua passowrd due volte) e invia.
+Nota: questo token scadr&agrave; in 24 ore.',
+ 'MultiSites_PluginDescription' => 'Mostra un sommario delle statistiche per il multi-sito.
+Attualmente mantenuto come un plugin Piwik del core.',
+ 'Provider_WidgetProviders' => 'Providers',
+ 'Provider_ColumnProvider' => 'Provider',
+ 'Provider_SubmenuLocationsProvider' => 'Localit&agrave; & provider',
+ 'Provider_PluginDescription' => 'Riporta i Provider dei visitatori.',
'Referers_Referers' => 'Referenti',
'Referers_SearchEngines' => 'Motori di ricerca',
'Referers_Keywords' => 'Parole chiave',
@@ -245,29 +543,45 @@ $translations = array(
'Referers_WidgetExternalWebsites' => 'Lista di Siti web esterni',
'Referers_WidgetSearchEngines' => 'Motori di ricerca migliori',
'Referers_WidgetOverview' => 'Riepilogo',
- 'UserSettings_VisitorSettings' => 'Impostazioni visitatori',
- 'UserSettings_BrowserFamilies' => 'Famiglie dei Browsers',
- 'UserSettings_Browsers' => 'Browsers',
- 'UserSettings_Plugins' => 'Plugins',
- 'UserSettings_Configurations' => 'Configurazioni',
- 'UserSettings_OperatinsSystems' => 'Sistemi Operativi',
- 'UserSettings_Resolutions' => 'Risoluzioni',
- 'UserSettings_WideScreen' => 'Schermo panoramico',
- 'UserSettings_ColumnBrowserFamily' => 'Famiglia del Browser',
- 'UserSettings_ColumnBrowser' => 'Browser',
- 'UserSettings_ColumnPlugin' => 'Plugin',
- 'UserSettings_ColumnConfiguration' => 'Configurazione',
- 'UserSettings_ColumnOperatinsSystem' => 'Sistema operativo',
- 'UserSettings_ColumnResolution' => 'Risoluzione',
- 'UserSettings_ColumnTypeOfScreen' => 'Tipo di schermo',
- 'UserSettings_WidgetResolutions' => 'Risoluzione schermo',
- 'UserSettings_WidgetBrowsers' => 'Browser dei visitatori',
- 'UserSettings_WidgetPlugins' => 'Lista dei Plugins',
- 'UserSettings_WidgetWidescreen' => 'Normale / Schermo Panoramico',
- 'UserSettings_WidgetBrowserFamilies' => 'Browsers per Famiglia',
- 'UserSettings_WidgetOperatingSystems' => 'Sistemi Operativi',
- 'UserSettings_WidgetGlobalVisitors' => 'Riepilogo config. visitatori',
- 'UserSettings_SubmenuSettings' => 'Impostazioni',
+ 'Referers_PluginDescription' => 'Riporta i dati dei referer: Motori di ricerca, Parole chiave, siti web, tracciamento campagne, entrate dirette.',
+ 'SecurityInfo_PluginDescription' => 'Basato sul PhpSecInfo del PHP Security Consortium, questo plugin offre informazioni sulla sicurezza del tuo ambiente PHP e offre suggerimenti per migliorarla. Questo &egrave; un tool per un approccio alla sicurezza multi-strato. Questo non rimpiazza le pratiche di sviluppo sicuro e non controlla il codice e l\'applicazione.',
+ 'SecurityInfo_Security' => 'Sicurezza',
+ 'SecurityInfo_SecurityInformation' => 'Informazioni di sicurezza PHP',
+ 'SecurityInfo_Test' => 'Testa',
+ 'SecurityInfo_Result' => 'Risultato',
+ 'SitesManager_Sites' => 'Siti',
+ 'SitesManager_WebsitesManagement' => 'Gestisci siti web',
+ 'SitesManager_MainDescription' => 'Per generare i report dei tuoi siti web, devi configurarli in Piwik!<br />Aggiungi, aggiorna, cancella i siti web e visualizza il codice JavaScript da inserire nelle tue pagine.',
+ 'SitesManager_JsTrackingTag' => 'Codice JavaScript',
+ 'SitesManager_JsTrackingTagHelp' => 'Qui &egrave; visualizzato il codice JavaScript da includere in tutte le pagine che vuoi vengano controllate da Piwik',
+ 'SitesManager_ShowTrackingTag' => 'vedi codice',
+ 'SitesManager_NoWebsites' => 'Non hai configurato alcun sito web da amministrare.',
+ 'SitesManager_AddSite' => 'Aggiungi un nuovo sito web',
+ 'SitesManager_Id' => 'Id',
+ 'SitesManager_Name' => 'Nome',
+ 'SitesManager_Urls' => 'Indirizzi',
+ 'SitesManager_MenuSites' => 'Siti',
+ 'SitesManager_DeleteConfirm_js' => 'Sei sicuro di voler cancellare il sito web %s?',
+ 'SitesManager_ExceptionDeleteSite' => 'Non &egrave; possibile cancellare questo sito web perch&eacute; &egrave; l\'unico registrato. Aggiungi prima un nuovo sito, quindi puoi cancellare questo.',
+ 'SitesManager_ExceptionNoUrl' => 'Devi specificare almeno un URL per questo sito.',
+ 'SitesManager_ExceptionEmptyName' => 'Il nome del sito non pu&ograve; essere vuoto.',
+ 'SitesManager_ExceptionInvalidUrl' => 'L\'indirizzo "%s" non &egrave; un URL valido.',
+ 'SitesManager_PluginDescription' => 'Gestione dei siti in Piwik: Aggiungi nuovi siti, modificane uno esistente, mostra il codice da includere nelle tue pagine. Tutte le azioni sono disponibili anche dalle API.',
+ 'SitesManager_AliasUrlHelp' => 'E\' raccomandato, ma non necessario, di specificare le diverse URL che i tuoi utenti usano per accedere al sito. Gli URL alias di un sito non compariranno tra i siti Referer. Nota che non &egrave; necessario specificare le URL con e senza \'www\' perch&egrave; Piwik lo considerer&agrava; entrambi automaticamente.',
+ 'TranslationsAdmin_MenuTranslations' => 'Traduzioni',
+ 'TranslationsAdmin_MenuLanguages' => 'Lingue',
+ 'TranslationsAdmin_Plugin' => 'Plugin',
+ 'TranslationsAdmin_Definition' => 'Definizioni',
+ 'TranslationsAdmin_DefaultString' => 'Testo di Default (Inglese)',
+ 'TranslationsAdmin_TranslationString' => 'Testo tradotto (Lingua corrente: %s)',
+ 'TranslationsAdmin_Translations' => 'Traduzioni',
+ 'TranslationsAdmin_FixPermissions' => 'Per favore sistema i permessi del filesystem',
+ 'TranslationsAdmin_AvailableLanguages' => 'Lingue disponibili',
+ 'TranslationsAdmin_AddLanguage' => 'Aggiungi una lingua',
+ 'TranslationsAdmin_LanguageCode' => 'Codice della lingua',
+ 'TranslationsAdmin_Export' => 'Esporta lingua',
+ 'TranslationsAdmin_Import' => 'Importa lingua',
+ 'TranslationsAdmin_PluginDescription' => 'Aiuta a tradurre Piwik nella tua lingua.',
'UserCountry_Country' => 'Paese',
'UserCountry_Continent' => 'Continente',
'UserCountry_DistinctCountries' => '%s continenti',
@@ -543,21 +857,63 @@ $translations = array(
'UserCountry_continent_ams' => 'America Centro-Meridionale',
'UserCountry_continent_amn' => 'America del Nord',
'UserCountry_continent_oce' => 'Oceania',
- 'VisitsSummary_NbVisits' => '%s visite',
- 'VisitsSummary_NbUniqueVisitors' => '%s visitatori unici',
- 'VisitsSummary_NbActions' => '%s pagine sono state visualizzate',
- 'VisitsSummary_TotalTime' => '%s &egrave; il tempo totale delle visite',
- 'VisitsSummary_MaxNbActions' => '%s &egrave; il massimo delle pagine viste in 1 visita',
- 'VisitsSummary_NbVisitsBounced' => 'Il %s dei visitatori hanno visto 1 sola pagina',
- 'VisitsSummary_EvolutionOverLastPeriods' => 'Evoluzione negli ultimi %s',
- 'VisitsSummary_Report' => 'Report',
- 'VisitsSummary_GenerateTime' => '%s secondi per generare la pagina',
- 'VisitsSummary_GenerateQueries' => '%s queries eseguite',
- 'VisitsSummary_WidgetLastVisits' => 'Grafico ultime visite',
- 'VisitsSummary_WidgetVisits' => 'Riepilogo visite',
- 'VisitsSummary_WidgetLastVisitors' => 'Grafico ultimi visitatori unici',
- 'VisitsSummary_WidgetOverviewGraph' => 'Riepilogo con grafico',
- 'VisitsSummary_SubmenuOverview' => 'Riepilogo',
+ 'UserCountry_PluginDescription' => 'Mostra gli stati dei tuoi visitatori.',
+ 'UserSettings_VisitorSettings' => 'Impostazioni visitatori',
+ 'UserSettings_BrowserFamilies' => 'Famiglie dei Browsers',
+ 'UserSettings_Browsers' => 'Browsers',
+ 'UserSettings_Plugins' => 'Plugins',
+ 'UserSettings_Configurations' => 'Configurazioni',
+ 'UserSettings_OperatingSystems' => 'Sistemi Operativi',
+ 'UserSettings_Resolutions' => 'Risoluzioni',
+ 'UserSettings_WideScreen' => 'Schermo panoramico',
+ 'UserSettings_ColumnBrowserFamily' => 'Famiglia del Browser',
+ 'UserSettings_ColumnBrowser' => 'Browser',
+ 'UserSettings_ColumnPlugin' => 'Plugin',
+ 'UserSettings_ColumnConfiguration' => 'Configurazione',
+ 'UserSettings_ColumnOperatingSystem' => 'Sistema operativo',
+ 'UserSettings_ColumnResolution' => 'Risoluzione',
+ 'UserSettings_ColumnTypeOfScreen' => 'Tipo di schermo',
+ 'UserSettings_WidgetResolutions' => 'Risoluzione schermo',
+ 'UserSettings_WidgetBrowsers' => 'Browser dei visitatori',
+ 'UserSettings_WidgetPlugins' => 'Lista dei Plugins',
+ 'UserSettings_WidgetWidescreen' => 'Normale / Schermo Panoramico',
+ 'UserSettings_WidgetBrowserFamilies' => 'Browsers per Famiglia',
+ 'UserSettings_WidgetOperatingSystems' => 'Sistemi Operativi',
+ 'UserSettings_WidgetGlobalVisitors' => 'Riepilogo config. visitatori',
+ 'UserSettings_SubmenuSettings' => 'Impostazioni',
+ 'UserSettings_PluginDescription' => 'Mostra vari settaggi per gli utenti: Browser, Famiglia del Browser, Sistema Operativo, Plugins, Risoluzione Schermo, Settaggi Globali.',
+ 'UsersManager_UsersManagement' => 'Gestione utenti',
+ 'UsersManager_UsersManagementMainDescription' => 'Crea nuovi utenti o aggiorna quelli esistenti. Puoi anche scegliere quali operazioni permettere tramite la tabella qui sopra.',
+ 'UsersManager_ManageAccess' => 'Amministra l\'accesso',
+ 'UsersManager_MainDescription' => 'Decidi quali utenti possono accedere alle statistiche Piwik dei siti web. Puoi anche impostare i permessi di tutti i siti in una volta sola.',
+ 'UsersManager_Sites' => 'Siti',
+ 'UsersManager_AllWebsites' => 'Tutti i siti',
+ 'UsersManager_ApplyToAllWebsites' => 'Applica a tutti i siti',
+ 'UsersManager_User' => 'Utente',
+ 'UsersManager_PrivNone' => 'Nessun privilegio',
+ 'UsersManager_PrivView' => 'Visualizza statistiche',
+ 'UsersManager_PrivAdmin' => 'Amministra Piwik',
+ 'UsersManager_ChangeAllConfirm' => 'Sei sicuro di voler cambiare i permessi di \'%s\' in tutti i siti?',
+ 'UsersManager_Login' => 'Login',
+ 'UsersManager_Password' => 'Password',
+ 'UsersManager_Email' => 'Email',
+ 'UsersManager_Alias' => 'Alias',
+ 'UsersManager_Edit' => 'Modifica',
+ 'UsersManager_AddUser' => 'Aggiungi un nuovo utente',
+ 'UsersManager_MenuUsers' => 'Utenti',
+ 'UsersManager_DeleteConfirm_js' => 'Sei sicuro di voler cancellare l\'utente \'%s\'?',
+ 'UsersManager_ExceptionLoginExists' => 'Utente "%s" gi&agrave; esistente.',
+ 'UsersManager_ExceptionEmailExists' => 'Utente con l\'e-mail "%s\" &egrave; gi&agrave; esistente.',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'Il nome utente deve essere lungo tra %s e %s caratteri e contenere solo lettere, numeri o i caratteri \'_\' oppure \'-\' oppure \'.\'',
+ 'UsersManager_ExceptionInvalidPassword' => 'La password deve essere lunga tra 6 e 26 caratteri.',
+ 'UsersManager_ExceptionInvalidEmail' => 'L\'e-mail inserita non &egrave; valida.',
+ 'UsersManager_ExceptionDeleteDoesNotExist' => 'L\'utente "%s" non esiste, di conseguenza non pu&ograve; essere eliminato.',
+ 'UsersManager_ExceptionAdminAnonymous' => 'Non puoi dare privilegi da amministratore agli utenti anonimi.',
+ 'UsersManager_ExceptionEditAnonymous' => 'Gli utenti anonimi non possono essere modificati o cancellati. Questo profilo &egrave; utilizzato da Piwik per definire un utente che non ha effettuato l\'accesso. Per esempio, se vuoi rendere pubbiche le tue statistiche, puoi dare il privilegio "Visualizza" al profilo degli utenti anonimi.',
+ 'UsersManager_ExceptionSuperUser' => 'L\'utente richesto &egrave; un Super User e non pu&oacute; essere richiamato, modificato o cancellato via API. Puoi modificare i dettagli dell\'utente nel file di configurazione di Piwik.',
+ 'UsersManager_ExceptionUserDoesNotExist' => 'L\'utente "%s" non esiste.',
+ 'UsersManager_ExceptionAccessValues' => 'Il parametro per l\'accesso deve avere uno dei seguenti valori: [ %s ]',
+ 'UsersManager_PluginDescription' => 'Gestione degli utenti in Piwik: agginta nuovi utenti, modifica di esistenti, aggiornamento dei permessi. Tutte le azioni sono anche disponibili tramite API.',
'VisitFrequency_Evolution' => 'Evoluzione nel periodo',
'VisitFrequency_ColumnReturningVisits' => 'Visite ricorrenti',
'VisitFrequency_ColumnActionsByReturningVisits' => 'Azioni eseguite dalle visite ricorrenti',
@@ -572,6 +928,7 @@ $translations = array(
'VisitFrequency_WidgetOverview' => 'Riepilogo visite ricorrenti',
'VisitFrequency_WidgetGraphReturning' => 'Grafico visite ricorrenti',
'VisitFrequency_SubmenuFrequency' => 'Frequenze',
+ 'VisitFrequency_PluginDescription' => 'Riporta varie statistiche riguardo i Visitatori che Ritornano controntati con i Nuovi Visitatori.',
'VisitTime_LocalTime' => 'Visite per ora locale',
'VisitTime_ServerTime' => 'Visite per ora del server',
'VisitTime_ColumnServerTime' => 'Ora del server',
@@ -580,6 +937,7 @@ $translations = array(
'VisitTime_WidgetServerTime' => 'Visite per ora del server',
'VisitTime_SubmenuTimes' => 'Visite per orario',
'VisitTime_NHour' => '%sh',
+ 'VisitTime_PluginDescription' => 'Mostra l\'orario Locale e del Server. L\'orario del server pu&ograve; essere utile per schedulare il mantenimento del sito.',
'VisitorInterest_VisitsPerDuration' => 'Visite per durata della visita',
'VisitorInterest_VisitsPerNbOfPages' => 'Visite per numero di pagine',
'VisitorInterest_ColumnVisitDuration' => 'Durata della visita',
@@ -592,151 +950,24 @@ $translations = array(
'VisitorInterest_OnePage' => '1 pagina',
'VisitorInterest_NPages' => '%s pagine',
'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
- 'Login_LoginPasswordNotCorrect' => 'Username & Password non corretti',
- 'Login_Login' => 'Username',
- 'Login_Password' => 'Password',
- 'Login_LoginOrEmail' => 'Login o E-mail',
- 'Login_LogIn' => 'Entra',
- 'Login_Logout' => 'Esci',
- 'Login_LostYourPassword' => 'Hai perso la password?',
- 'Login_RemindPassword' => 'Ricorda password',
- 'Login_PasswordReminder' => 'Per favore, inserisci il tuo username o l\'indirizzo e-mail. Riceverai una nuova password via e-mail.',
- 'Login_InvalidUsernameEmail' => 'Username e/o indirizzo e-mail non validi',
- 'Login_MailTopicPasswordRecovery' => 'Recupero Password',
- 'Login_MailPasswordRecoveryBody' => 'Ciao %1s, \n\n La tua nuova password &egrave;: %2s \n\n Ora puoi effettuare il login qui: %3s',
- 'Login_PasswordSent' => 'La password &egrave; stata inviata. Controlla la tua casella e-mail.',
- 'Login_ContactAdmin' => 'Possibile ragione: il tuo host potrebbe non avere attive le funzionalit&agrave; di e-mail.<br />Per favore, contatta l\'amministratore del server.',
- 'UsersManager_UsersManagement' => 'Gestione utenti',
- 'UsersManager_UsersManagementMainDescription' => 'Crea nuovi utenti o aggiorna quelli esistenti. Puoi anche scegliere quali operazioni permettere tramite la tabella qui sopra.',
- 'UsersManager_ManageAccess' => 'Amministra l\'accesso',
- 'UsersManager_MainDescription' => 'Decidi quali utenti possono accedere alle statistiche Piwik dei siti web. Puoi anche impostare i permessi di tutti i siti in una volta sola.',
- 'UsersManager_Sites' => 'Siti',
- 'UsersManager_AllWebsites' => 'Tutti i siti',
- 'UsersManager_ApplyToAllWebsites' => 'Applica a tutti i siti',
- 'UsersManager_User' => 'Utente',
- 'UsersManager_PrivNone' => 'Nessun privilegio',
- 'UsersManager_PrivView' => 'Visualizza statistiche',
- 'UsersManager_PrivAdmin' => 'Amministra Piwik',
- 'UsersManager_ChangeAllConfirm' => 'Sei sicuro di voler cambiare i permessi di \'%s\' in tutti i siti?',
- 'UsersManager_Login' => 'Login',
- 'UsersManager_Password' => 'Password',
- 'UsersManager_Email' => 'Email',
- 'UsersManager_Alias' => 'Alias',
- 'UsersManager_Edit' => 'Modifica',
- 'UsersManager_AddUser' => 'Aggiungi un nuovo utente',
- 'UsersManager_MenuUsers' => 'Utenti',
- 'UsersManager_DeleteConfirm_js' => 'Sei sicuro di voler cancellare l\'utente \'%s\'?',
- 'UsersManager_ExceptionLoginExists' => 'Utente "%s" gi&agrave; esistente.',
- 'UsersManager_ExceptionEmailExists' => 'Utente con l\'e-mail "%s\" &egrave; gi&agrave; esistente.',
- 'UsersManager_ExceptionInvalidLoginFormat' => 'Il nome utente deve essere lungo tra %s e %s caratteri e contenere solo lettere, numeri o i caratteri \'_\' oppure \'-\' oppure \'.\'',
- 'UsersManager_ExceptionInvalidPassword' => 'La password deve essere lunga tra 6 e 26 caratteri.',
- 'UsersManager_ExceptionInvalidEmail' => 'L\'e-mail inserita non &egrave; valida.',
- 'UsersManager_ExceptionDeleteDoesNotExist' => 'L\'utente "%s" non esiste, di conseguenza non pu&ograve; essere eliminato.',
- 'UsersManager_ExceptionAdminAnonymous' => 'Non puoi dare privilegi da amministratore agli utenti anonimi.',
- 'UsersManager_ExceptionEditAnonymous' => 'Gli utenti anonimi non possono essere modificati o cancellati. Questo profilo &egrave; utilizzato da Piwik per definire un utente che non ha effettuato l\'accesso. Per esempio, se vuoi rendere pubbiche le tue statistiche, puoi dare il privilegio "Visualizza" al profilo degli utenti anonimi.',
- 'UsersManager_ExceptionSuperUser' => 'L\'utente richesto &egrave; un Super User e non pu&oacute; essere richiamato, modificato o cancellato via API. Puoi modificare i dettagli dell\'utente nel file di configurazione di Piwik.',
- 'UsersManager_ExceptionUserDoesNotExist' => 'L\'utente "%s" non esiste.',
- 'UsersManager_ExceptionAccessValues' => 'Il parametro per l\'accesso deve avere uno dei seguenti valori: [ %s ]',
- 'SitesManager_Sites' => 'Siti',
- 'SitesManager_WebsitesManagement' => 'Gestisci siti web',
- 'SitesManager_MainDescription' => 'Per generare i report dei tuoi siti web, devi configurarli in Piwik!<br />Aggiungi, aggiorna, cancella i siti web e visualizza il codice JavaScript da inserire nelle tue pagine.',
- 'SitesManager_JsTrackingTag' => 'Codice JavaScript',
- 'SitesManager_JsTrackingTagHelp' => 'Qui &egrave; visualizzato il codice JavaScript da includere in tutte le pagine che vuoi vengano controllate da Piwik',
- 'SitesManager_ShowTrackingTag' => 'vedi codice',
- 'SitesManager_NoWebsites' => 'Non hai configurato alcun sito web da amministrare.',
- 'SitesManager_AddSite' => 'Aggiungi un nuovo sito web',
- 'SitesManager_Id' => 'Id',
- 'SitesManager_Name' => 'Nome',
- 'SitesManager_Urls' => 'Indirizzi',
- 'SitesManager_MenuSites' => 'Siti',
- 'SitesManager_DeleteConfirm_js' => 'Sei sicuro di voler cancellare il sito web %s?',
- 'SitesManager_ExceptionDeleteSite' => 'Non &egrave; possibile cancellare questo sito web perch&eacute; &egrave; l\'unico registrato. Aggiungi prima un nuovo sito, quindi puoi cancellare questo.',
- 'SitesManager_ExceptionNoUrl' => 'Devi specificare almeno un URL per questo sito.',
- 'SitesManager_ExceptionEmptyName' => 'Il nome del sito non pu&ograve; essere vuoto.',
- 'SitesManager_ExceptionInvalidUrl' => 'L\'indirizzo "%s" non &egrave; un URL valido.',
- 'Installation_Installation' => 'Installazione',
- 'Installation_InstallationStatus' => 'Stato dell\'installazione',
- 'Installation_PercentDone' => '%s %% Fatto',
- 'Installation_NoConfigFound' => 'Il file di configurazione di Piwik non &egrave; stato trovato e stai tentando l\'accesso ad una pagina di Piwik.<br /><b>&nbsp;&nbsp;&raquo; Puoi <a href=\'index.php\'>installare Piwik ora.</a></b><br /><small>Se hai gi&agrave; installato in precedenza Piwik e nel tuo Database sono presenti delle tabelle della vecchia installazione, non preoccuparti, puoi riutilizzarle e salvare i dati gi&agrave; esistenti!</small>',
- 'Installation_MysqlSetup' => 'Configurazione Database MySQL',
- 'Installation_MysqlErrorConnect' => 'Si &egrave; verificato un errore durante la connessione al Database MySQL',
- 'Installation_JsTag' => 'Codice JavaScript',
- 'Installation_JsTagHelp' => '<p>Per conteggiare tutti i visitatori, devi inserire il codice JavaScript in tutte le pagine del sito.</p><p>Non &egrave; necessario che siano scritte in PHP, Piwik supporta tutti i tipi di pagine (HTML, ASP, Perl o un qualunque altro linguaggio).</p><p>Questo &egrave; il codice da inserire: (copia e incolla in tutte le tue pagine) </p>',
- 'Installation_Congratulations' => 'Congratulazioni',
- 'Installation_CongratulationsHelp' => '<p>Congratulazioni! L\'installazione di Piwik &egrave; stata completata.</p><p>Assicurati che il codice JavaScript sia inserito in tutte le pagine del sito e aspetta i tuoi primi visitatori!</p>',
- 'Installation_ContinueToPiwik' => 'Vai a Piwik',
- 'Installation_SetupWebsite' => 'Configura un sito web',
- 'Installation_SetupWebsiteError' => 'C\'&egrave; stato un errore durante l\'aggiunta del sito web',
- 'Installation_GeneralSetup' => 'Configurazione di base',
- 'Installation_GeneralSetupSuccess' => 'Configurazione di base terminata con successo',
- 'Installation_SuperUserLogin' => 'Nome utente amministratore',
- 'Installation_Password' => 'Password',
- 'Installation_PasswordRepeat' => 'Password (ripeti)',
- 'Installation_Email' => 'E-mail',
- 'Installation_SecurityNewsletter' => 'Informami via e-mail sugli aggiornamenti pi&ugrave; importanti di Piwik',
- 'Installation_CommunityNewsletter' => 'Informami via e-mail sugli aggiornamenti della community (nuovi plugins, caratteristiche, ecc.)',
- 'Installation_PasswordDoNotMatch' => 'Le Password non coincidono',
- 'Installation_SubmitGo' => 'Vai!',
- 'Installation_Requirements' => 'Requisiti di Piwik',
- 'Installation_Optional' => 'Opzionale',
- 'Installation_Legend' => 'Legenda',
- 'Installation_SystemCheck' => 'Controllo del Sistema',
- 'Installation_SystemCheckPhp' => 'Versione PHP',
- 'Installation_SystemCheckExtensions' => 'Estensioni Richieste',
- 'Installation_SystemCheckPdoHelp' => 'Devi abilitare l\'estensione PDO nel tuo file php.ini.',
- 'Installation_SystemCheckPdoMysqlHelp' => 'Devi abilitare l\'estensione PDO_MYSQL nel tuo file php.ini.',
- 'Installation_SystemCheckSplHelp' => 'Devi configurare e ricostruire il PHP con la libreria Standard PHP abilitata (di default).',
- 'Installation_SystemCheckZlibHelp' => 'Devi configurare e ricostruire il PHP con il supporto zlib abilitato, --with-zlib.',
- 'Installation_SystemCheckWriteDirs' => 'Directories con permessi di scrittura',
- 'Installation_SystemCheckWriteDirsHelp' => 'Per correggere questo errore in Linux, prova ad eseguire il seguente comando/i',
- 'Installation_SystemCheckMemoryLimit' => 'Memoria massima',
- 'Installation_SystemCheckMemoryLimitHelp' => 'Su un sito web con grande traffico, il processo di archiviazione potrebbe richiedere pi&ugrave; memoria di quella attualmente consentita.<br />Controlla la direttiva memory_limmit nel tuo file php.ini se necessario.',
- 'Installation_SystemCheckGD' => 'Libreria grafica GD &gt; 2.x',
- 'Installation_SystemCheckGDHelp' => 'Gli sparklines (piccoli grafici affianco al testo) non saranno disponibili.',
- 'Installation_SystemCheckFunctions' => 'Funzioni richieste',
- 'Installation_SystemCheckTimeLimitHelp' => 'Su un sito web con grande traffico, il processo di archiviazione potrebbe richiedere pi&ugrave; tempo di quello attualmente consentito.<br />Controlla la direttiva max_execution_time nel tuo file php.ini se necessario.',
- 'Installation_SystemCheckMailHelp' => 'Feedback e Password perdute non saranno inviate senza la funzione mail() disponibile.',
- 'Installation_SystemCheckError' => 'Si &egrave; verificato un errore - deve essere corretto prima di proseguire',
- 'Installation_SystemCheckWarning' => 'Piwik non sar&agrave; pienamente funzionante, ma alcune funzioni potrebbero essere mancanti.',
- 'Installation_Tables' => 'Sto creando le tabelle',
- 'Installation_TablesWithSameNamesFound' => 'Alcune %s tabelle nel tuo Database %s hanno lo stesso nome delle tabelle che Piwik sta cercando di creare.',
- 'Installation_TablesFound' => 'Le seguenti tabelle sono state create nel Database',
- 'Installation_TablesWarningHelp' => 'Scegliere se riusare le tabelle esistenti nel Database (da una precedente installazione di Piwik) o procedere con un nuova installazione cancellando tutti i dati esistenti.',
- 'Installation_TablesReuse' => 'Riusa le tabelle esistenti',
- 'Installation_TablesDelete' => 'Cancella le tabelle individuate',
- 'Installation_TablesDeletedSuccess' => 'Le tabelle di Piwik esistenti sono state eliminate con successo',
- 'Installation_TablesCreatedSuccess' => 'Tabelle create con successo!',
- 'Installation_DatabaseCreatedSuccess' => 'Database %s creato con successo!',
- 'Installation_GoBackAndDefinePrefix' => 'Torna indietro e definisci un nuovo prefisso per le tabelle di Piwik',
- 'Installation_ConfirmDeleteExistingTables' => 'Sei sicuro di voler cancellare le tabelle %s dal tuo Database? ATTENZIONE: I DATI NON POTRANNO ESSERE RECUPERATI!',
- 'Installation_Welcome' => 'Benvenuto!',
- 'Installation_WelcomeHelp' => '<p>Piwik &egrave; un software open source che ti permette di analizzare facilmente le informazioni dei visitatori che visitano i tuoi siti web.</p><p>Questa procedura si divide in %s semplici passaggi e si completa nel giro di 5 minuti.</p>',
- 'Installation_ErrorInvalidState' => 'Errore: sembra che stai tentando di saltare un passaggio del processo di installazione, i tuoi Cookies sono disabilitati o il file di configurazione Piwik &egrave; stato gi&agrave; creato. %sControlla che i Cookies siano attivati%s e %s ripeti l\'installazione dal primo passaggio %s.',
- 'Provider_WidgetProviders' => 'Providers',
- 'Provider_ColumnProvider' => 'Provider',
- 'Provider_SubmenuLocationsProvider' => 'Localit&agrave; & provider',
- 'Goals_ColumnConversions' => 'Conversioni',
- 'Goals_ColumnConversionRate' => 'Tasso di conversioni',
- 'Goals_ColumnRevenue' => 'Ricavo',
- 'DBStats_DatabaseUsage' => 'Uso del Database',
- 'DBStats_MainDescription' => 'Piwik sta salvando tutti i dati statistici nel Database MySQL. Attualmente, le tabelle di Piwik stanno usando %s.',
- 'DBStats_Table' => 'Tabella',
- 'DBStats_RowNumber' => 'Numero di righe',
- 'DBStats_DataSize' => 'Dimensione dei dati',
- 'DBStats_IndexSize' => 'Dimensione degli indici',
- 'DBStats_TotalSize' => 'Dimensione totale',
- 'TranslationsAdmin_MenuTranslations' => 'Traduzioni',
- 'TranslationsAdmin_MenuLanguages' => 'Lingue',
- 'TranslationsAdmin_Plugin' => 'Plugin',
- 'TranslationsAdmin_Definition' => 'Definizioni',
- 'TranslationsAdmin_DefaultString' => 'Testo di Default (Inglese)',
- 'TranslationsAdmin_TranslationString' => 'Testo tradotto (Lingua corrente: %s)',
- 'TranslationsAdmin_Translations' => 'Traduzioni',
- 'TranslationsAdmin_FixPermissions' => 'Per favore sistema i permessi del filesystem',
- 'TranslationsAdmin_AvailableLanguages' => 'Lingue disponibili',
- 'TranslationsAdmin_AddLanguage' => 'Aggiungi una lingua',
- 'TranslationsAdmin_LanguageCode' => 'Codice della lingua',
- 'TranslationsAdmin_Export' => 'Esporta lingua',
- 'TranslationsAdmin_Import' => 'Importa lingua',
- 'CoreUpdater_EmptyDatabaseError' => 'Piwik &egrave; stato aggiornato con successo!',
-);
+ 'VisitorInterest_PluginDescription' => 'Report riguardo l\'interesse dei visitatori: numero di pagine viste e tempo speso sul sito.',
+ 'VisitsSummary_NbVisits' => '%s visite',
+ 'VisitsSummary_NbUniqueVisitors' => '%s visitatori unici',
+ 'VisitsSummary_NbActions' => '%s pagine sono state visualizzate',
+ 'VisitsSummary_TotalTime' => '%s &egrave; il tempo totale delle visite',
+ 'VisitsSummary_MaxNbActions' => '%s &egrave; il massimo delle pagine viste in 1 visita',
+ 'VisitsSummary_NbVisitsBounced' => 'Il %s dei visitatori hanno visto 1 sola pagina',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Evoluzione negli ultimi %s',
+ 'VisitsSummary_Report' => 'Report',
+ 'VisitsSummary_GenerateTime' => '%s secondi per generare la pagina',
+ 'VisitsSummary_GenerateQueries' => '%s queries eseguite',
+ 'VisitsSummary_WidgetLastVisits' => 'Grafico ultime visite',
+ 'VisitsSummary_WidgetVisits' => 'Riepilogo visite',
+ 'VisitsSummary_WidgetLastVisitors' => 'Grafico ultimi visitatori unici',
+ 'VisitsSummary_WidgetOverviewGraph' => 'Riepilogo con grafico',
+ 'VisitsSummary_SubmenuOverview' => 'Riepilogo',
+ 'VisitsSummary_PluginDescription' => 'Riporta i dati generali di Web Analytics: visite, visite uniche, numero di azioni, frequenza di rimbalzo, ecc.',
+ 'VisitsSummary_VisitsSummary' => 'Sommario delle visite',
+ 'VisitsSummary_NbActionsDescription' => '%s azioni (pagine viste, download e link esterni)',
+ 'Widgetize_PluginDescription' => 'Il plugin rende molto facile esportare qualsiasi Widget Piwik nel tuo Blog, Sito Web o su IGoogle e Netvibes!',
+); \ No newline at end of file
diff --git a/lang/ja.php b/lang/ja.php
index de5a879df5..be2c42e656 100644
--- a/lang/ja.php
+++ b/lang/ja.php
@@ -78,6 +78,32 @@ $translations = array(
'CoreHome_DayTh_js' => '木',
'CoreHome_DayFr_js' => '金',
'CoreHome_DaySa_js' => '土',
+ 'CoreHome_ShortDay_1_js' => '日',
+ 'CoreHome_ShortDay_2_js' => '月',
+ 'CoreHome_ShortDay_3_js' => '火',
+ 'CoreHome_ShortDay_4_js' => '水',
+ 'CoreHome_ShortDay_5_js' => '木',
+ 'CoreHome_ShortDay_6_js' => '金',
+ 'CoreHome_ShortDay_7_js' => '土',
+ 'CoreHome_LongDay_1_js' => '日曜日',
+ 'CoreHome_LongDay_2_js' => '月曜日',
+ 'CoreHome_LongDay_3_js' => '火曜日',
+ 'CoreHome_LongDay_4_js' => '水曜日',
+ 'CoreHome_LongDay_5_js' => '木曜日',
+ 'CoreHome_LongDay_6_js' => '金曜日',
+ 'CoreHome_LongDay_7_js' => '土曜日',
+ 'CoreHome_ShortMonth_1_js' => '1月',
+ 'CoreHome_ShortMonth_2_js' => '2月',
+ 'CoreHome_ShortMonth_3_js' => '3月',
+ 'CoreHome_ShortMonth_4_js' => '4月',
+ 'CoreHome_ShortMonth_5_js' => '5月',
+ 'CoreHome_ShortMonth_6_js' => '6月',
+ 'CoreHome_ShortMonth_7_js' => '7月',
+ 'CoreHome_ShortMonth_8_js' => '8月',
+ 'CoreHome_ShortMonth_9_js' => '9月',
+ 'CoreHome_ShortMonth_10_js' => '10月',
+ 'CoreHome_ShortMonth_11_js' => '11月',
+ 'CoreHome_ShortMonth_12_js' => '12月',
'CoreHome_MonthJanuary_js' => '1月',
'CoreHome_MonthFebruary_js' => '2月',
'CoreHome_MonthMarch_js' => '3月',
@@ -155,7 +181,7 @@ $translations = array(
'UserSettings_Browsers' => 'ブラウザ',
'UserSettings_Plugins' => 'プラグイン',
'UserSettings_Configurations' => '環境設定',
- 'UserSettings_OperatinsSystems' => 'OS',
+ 'UserSettings_OperatingSystems' => 'OS',
'UserSettings_Resolutions' => '解像度',
'UserSettings_WideScreen' => 'ワイド画面',
'UserSettings_WidgetResolutions' => '画面解像度',
@@ -475,7 +501,6 @@ $translations = array(
'Login_PasswordReminder' => 'ユーザ名かメールアドレスを入力してください。 新しいパスワードがメールで送信されます。',
'Login_InvalidUsernameEmail' => 'ユーザ名かメールアドレスが無効です',
'Login_MailTopicPasswordRecovery' => 'パスワードの再発行',
- 'Login_MailPasswordRecoveryBody' => '%1s さん\n\n あなたの新しいパスワード: %2s \n\n ログインURL: %3s',
'Login_PasswordSent' => 'パスワードが送信されました。 メールを確認してください。',
'Login_ContactAdmin' => '考えられる理由: ホストで mail() 関数が無効にされている可能性があります。<br />Piwik 管理者にご連絡ください。',
'UsersManager_UsersManagement' => 'ユーザの管理',
diff --git a/lang/ko.php b/lang/ko.php
index 4a6ff3e6a4..c1cb6a0c0b 100644
--- a/lang/ko.php
+++ b/lang/ko.php
@@ -145,6 +145,32 @@ $translations = array(
'CoreHome_DayTh_js' => '목',
'CoreHome_DayFr_js' => '금',
'CoreHome_DaySa_js' => '토',
+ 'CoreHome_ShortDay_1_js' => '일',
+ 'CoreHome_ShortDay_2_js' => '월',
+ 'CoreHome_ShortDay_3_js' => '화',
+ 'CoreHome_ShortDay_4_js' => '수',
+ 'CoreHome_ShortDay_5_js' => '목',
+ 'CoreHome_ShortDay_6_js' => '금',
+ 'CoreHome_ShortDay_7_js' => '토',
+ 'CoreHome_LongDay_1_js' => '일',
+ 'CoreHome_LongDay_2_js' => '월',
+ 'CoreHome_LongDay_3_js' => '화',
+ 'CoreHome_LongDay_4_js' => '수',
+ 'CoreHome_LongDay_5_js' => '목',
+ 'CoreHome_LongDay_6_js' => '금',
+ 'CoreHome_LongDay_7_js' => '토',
+ 'CoreHome_ShortMonth_1_js' => '1월',
+ 'CoreHome_ShortMonth_2_js' => '2월',
+ 'CoreHome_ShortMonth_3_js' => '3월',
+ 'CoreHome_ShortMonth_4_js' => '4월',
+ 'CoreHome_ShortMonth_5_js' => '5월',
+ 'CoreHome_ShortMonth_6_js' => '6월',
+ 'CoreHome_ShortMonth_7_js' => '7월',
+ 'CoreHome_ShortMonth_8_js' => '8월',
+ 'CoreHome_ShortMonth_9_js' => '9월',
+ 'CoreHome_ShortMonth_10_js' => '10월',
+ 'CoreHome_ShortMonth_11_js' => '11월',
+ 'CoreHome_ShortMonth_12_js' => '12월',
'CoreHome_MonthJanuary_js' => '1월',
'CoreHome_MonthFebruary_js' => '2월',
'CoreHome_MonthMarch_js' => '3월',
@@ -248,14 +274,14 @@ $translations = array(
'UserSettings_Browsers' => '브라우저',
'UserSettings_Plugins' => '플러그인',
'UserSettings_Configurations' => '구성',
- 'UserSettings_OperatinsSystems' => '운영체제',
+ 'UserSettings_OperatingSystems' => '운영체제',
'UserSettings_Resolutions' => '해상도',
'UserSettings_WideScreen' => '와이드 스크린',
'UserSettings_ColumnBrowserFamily' => '브라우저 타입',
'UserSettings_ColumnBrowser' => '브라우저',
'UserSettings_ColumnPlugin' => '플러그인',
'UserSettings_ColumnConfiguration' => '구성',
- 'UserSettings_ColumnOperatinsSystem' => '운영체제',
+ 'UserSettings_ColumnOperatingSystem' => '운영체제',
'UserSettings_ColumnResolution' => '해상도',
'UserSettings_ColumnTypeOfScreen' => '스크린 타입',
'UserSettings_WidgetResolutions' => '스크린 해상도',
@@ -601,7 +627,6 @@ $translations = array(
'Login_PasswordReminder' => '사용자명 또는 이메일 주소를 입력하세요. 새 비밀번호를 이메일을 통해 받게될 것입니다.',
'Login_InvalidUsernameEmail' => '잘못된 사용자명 그리고/또는 이메일 주소',
'Login_MailTopicPasswordRecovery' => '비밀번호 복구',
- 'Login_MailPasswordRecoveryBody' => '안녕하세요, %1s 님. \n\n 새 비밀번호는: %2s \n\n 이제 로그인 할 수 있습니다: %3s',
'Login_PasswordSent' => '비밀번호는 방금 전송되었습니다. 이메일을 확인하세요.',
'Login_ContactAdmin' => '가능한 이유: 호스트가 메일 기능을 비활성화했을 수 있습니다. <br />당신의 Piwik 관리자에게 연락해보세요.',
'UsersManager_UsersManagement' => '사용자 관리',
diff --git a/lang/lt.php b/lang/lt.php
index cbd26e3c3a..6bcf1daae7 100644
--- a/lang/lt.php
+++ b/lang/lt.php
@@ -1,10 +1,7 @@
<?php
-
-setlocale(LC_TIME, 'lt_LT.UTF-8');
-
$translations = array(
'General_Locale' => 'lt_LT.UTF-8',
- 'General_TranslatorName' => 'Donatas Stonys',
+ 'General_TranslatorName' => 'Donatas Stonys (TeraxIT.com)',
'General_TranslatorEmail' => 'info@teraxit.com',
'General_EnglishLanguageName' => 'Lithuanian',
'General_OriginalLanguageName' => 'Lietuvių',
@@ -16,7 +13,7 @@ $translations = array(
'General_Settings' => 'Nuostatos',
'General_GiveUsYourFeedback' => 'Jūsų atsiliepimai!',
'General_Unknown' => 'Nežinoma',
- 'General_Required' => '%s Reikalinga',
+ 'General_Required' => '%s reikalinga',
'General_Error' => 'Klaida',
'General_Warning' => 'Įspėjimas',
'General_BackToHomepage' => 'Atgal į pradinį puslapį',
@@ -34,10 +31,10 @@ $translations = array(
'General_Next' => 'Pirmyn',
'General_Previous' => 'Atgal',
'General_Search' => 'Ieškoti',
- 'General_Others' => 'Kiti',
+ 'General_Others' => 'Kita',
'General_Table' => 'Lentelė',
'General_Piechart' => 'Skritulinė diagrama',
- 'General_TagCloud' => '',
+ 'General_TagCloud' => 'Žymių debesis',
'General_VBarGraph' => 'Vertikalių stulpelių grafikas',
'General_Export' => 'Eksportuoti',
'General_ExportAsImage' => 'Eksportuoti kaip paveikslėlį',
@@ -48,24 +45,24 @@ $translations = array(
'General_ColumnNbVisits' => 'Apsilankymai',
'General_ColumnNbActions' => 'Veiksmai',
'General_ColumnMaxActions' => 'Daugiausia veiksmų per apsilankymą',
- 'General_ColumnSumVisitLength' => 'Bendras laikas praleistas visų lankytojų (sekundėmis)',
+ 'General_ColumnSumVisitLength' => 'Bendras visų lankytojų praleistas laikas (sekundėmis)',
'General_ColumnLabel' => 'Žymė',
'General_ColumnActionsPerVisit' => 'Veiksmų per apsilankymą',
'General_ColumnAvgTimeOnSite' => 'Vidutinis laikas svetainėje',
- 'General_ColumnBounceRate' => '',
+ 'General_ColumnBounceRate' => 'Šoklumo reitingas',
'General_ColumnPageviews' => 'Puslapio peržiūros',
- 'General_ColumnUniquePageviews' => 'Unikalios puslapio peržiuros',
- 'General_ColumnValuePerVisit' => 'Vizito vertė',
- 'General_ColumnVisitsWithConversions' => '',
+ 'General_ColumnUniquePageviews' => 'Unikalios puslapio peržiūros',
+ 'General_ColumnValuePerVisit' => 'Apsilankymo vertė',
+ 'General_ColumnVisitsWithConversions' => 'Apsilankymai su konversija',
'General_Save' => 'Išsaugoti',
'General_Website' => 'Svetainė',
- 'General_NoDataForGraph' => 'Duomenų nėra',
- 'General_NoDataForTagCloud' => '',
+ 'General_NoDataForGraph' => 'Šiam grafikui duomenų nėra',
+ 'General_NoDataForTagCloud' => 'Šiam žymių debesiui duomenų nėra',
'General_DisplayNormalTable' => 'Rodyti normalią lentelę',
- 'General_DisplayMoreData' => 'Daugau informacijos',
+ 'General_DisplayMoreData' => 'Rodyti daugiau informacijos',
'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s yra bendras projektas. %s Jei Jums patinka Piwik, Jūs taip pat galite prisijungti! %s Kaip prisidėti prie Piwik? %s ',
'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Šiuo metu matote demo versiją %s; %sAtsisiųskite%s pilną versiją! Išsamiau %s',
- 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Išleista %s Piwik. %s Atnaujinkite dabar!%s (peržiūrėti %s pasikeitimus%s).',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Išleista Piwik %s versija. %s Atnaujinkite dabar!%s (peržiūrėti %s pasikeitimus%s).',
'General_BackToPiwik' => 'Atgal į Piwik',
'General_ShortMonth_1' => 'Sau',
'General_ShortMonth_2' => 'Vas',
@@ -105,8 +102,24 @@ $translations = array(
'General_LongDay_5' => 'Penktadienis',
'General_LongDay_6' => 'Šeštadienis',
'General_LongDay_7' => 'Sekmadienis',
- 'API_QuickDocumentation' => '<h2>Trumpa API sąsajos dokumentacija</h2><p>Jei neturite šios dienos duomenų, <a href=\'misc/generateVisits.php\' target=_blank>galite sugeneruoti duomenis</a> pasinaudoję Apsilankymų Generatoriaus scenarijumi. </p><p>Kiekvienam metodui galite išbandyti skirtingus formatus. Tikrai nesudėtinga išgauti duomenis, kurie Jums reikalingi iš Piwik!</p><p><b>Daugiau informacijos rasite <a href=\'http://dev.piwik.org/trac/wiki/API\'>oficialioje API sąsajos dokumentacijoje</a> arba <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API sąsajos žinyne</a>.</b></P><h2>Naudotojo autentifikavimas</h2><p>Jei norite <b>naudoti duomenų užklausas savo scenarijuose, crontab\'uose ir t.t. </b> turėtumėte pridėti parametrą <code><u>&token_auth=%s</u></code>į API sąsają besikreipiančiuose universaliuose adresuose (URL). </p><p>token_auth yra toks pat slaptas, kaip ir Jūsų slaptažodis, <b>todėl neviešinkite jo!</p>',
- 'API_LoadedAPIs' => 'Sėkmingai įkrautos API sąsajos (%s).',
+ 'General_ExportAsImage_js' => 'Eksportuoti kaip paveikslėlį',
+ 'General_SaveImageOnYourComputer_js' => 'Norėdami išsaugoti paveikslėlį savo kompiuteryje, spustelėkite dešiniuoju pelytės klavišu ant paveikslėlio ir pasirinkite "Išsaugoti paveikslėlį kaip..."',
+ 'General_RequiresFlash' => 'Grafikų atvaizdavimui reikalingas Flash',
+ 'General_GraphHelp' => 'Daugiau informacijos apie grafikų atvaizdavimą',
+ 'General_ExceptionDatabaseVersion' => 'Jūsų %s versija yra %s, tačiau Piwik reikalinga bent jau %s.',
+ 'General_Dashboard' => 'Skydelis',
+ 'General_MultiSitesSummary' => 'Visos svetainės',
+ 'General_Details' => 'Išsamiau',
+ 'General_ForExampleShort' => 'pvz.',
+ 'General_ExceptionIncompatibleClientServerVersions' => 'Jūsų %1$s kliento versija yra %2$s, kuri yra nesuderinama su serverio %3$s versija.',
+ 'General_ExceptionMissingFile' => 'Trūksta failo: %s',
+ 'General_ExceptionFilesizeMismatch' => 'Nesutampa failo dydis: %1$s (turi būti: %2$s, rasta: %3$s)',
+ 'General_ExceptionFileIntegrity' => 'Nesėkminga vientisumo patikra: %s',
+ 'General_ExceptionNonceMismatch' => 'Negalima patikrinti šios formos saugos rakto.',
+ 'General_WarningFileIntegritySkipped' => 'Aptikta tobulinimo aplinka. Praleidžiamas vientisumo tikrinimas.',
+ 'General_WarningFileIntegrityNoManifest' => 'Failo vientisumo patikra negali būti atlikta dėl nesamo manifest.inc.php failo.',
+ 'General_WarningFileIntegrityNoMd5file' => 'Failo vientisumo patikra negali būti atlikta dėl nesamos md5_file() funkcijos.',
+ 'General_FileIntegrityWarningExplanation' => 'Failo vientisumo patikra nutraukta ir pateikiama klaidų ataskaita. Tikėtina, jog tai įtakoja nepilnas arba nutrauktas Piwik failų įkėlimas į serverį. Prašome pabandyti pakartotinai perkelti Piwik failus ir atnaujinti šį puslapį kol nebebus rodomi klaidų pranešimai.',
'Actions_Actions' => 'Veiksmai',
'Actions_SubmenuPages' => 'Puslapiai',
'Actions_SubmenuOutlinks' => 'Išorinės nuorodos',
@@ -118,10 +131,19 @@ $translations = array(
'Actions_ColumnPageName' => 'Puslapio pavadinimas',
'Actions_ColumnClickedURL' => 'Paspausti URL',
'Actions_ColumnDownloadURL' => 'Atsisiuntimų URL',
- 'CoreHome_NoPrivileges' => 'Jūs prisijungėte, \'%s\' tačiau neturite nustatytų leidimų.<br />Kreipkitės į savo Piwik administratorių, kad Jums būtų suteiktos "matyti" teisės.',
+ 'Actions_SubmenuPageTitles' => 'Puslapių antraštės',
+ 'Actions_ColumnPageURL' => 'Puslapio URL',
+ 'Actions_PluginDescription' => 'Puslapių peržiūros, išorinių nuorodų ir atsisiuntimų ataskaitos. Išorinių nuorodų ir atsisiuntimų stebėjimas yra įgalinamas automatiškai!',
+ 'AnonymizeIP_PluginDescription' => 'Paslėpkite savo lankytojų IP adresus, jei to reikalauja Jūsų vidaus taisyklės ar įstatymai.',
+ 'API_QuickDocumentation' => '<h2>Trumpa API sąsajos dokumentacija</h2><p>Jei neturite šios dienos duomenų, <a href=\'misc/generateVisits.php\' target=_blank>galite sugeneruoti duomenis</a> pasinaudoję Apsilankymų Generatoriaus scenarijumi. </p><p>Kiekvienam metodui galite išbandyti skirtingus formatus. Tikrai nesudėtinga išgauti duomenis, kurie Jums reikalingi iš Piwik!</p><p><b>Daugiau informacijos rasite <a href=\'http://dev.piwik.org/trac/wiki/API\'>oficialioje API sąsajos dokumentacijoje</a> arba <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API sąsajos žinyne</a>.</b></P><h2>Naudotojo identifikavimas</h2><p>Jei norite <b>naudoti duomenų užklausas savo scenarijuose, crontab\'uose ir t.t. </b> turėtumėte pridėti parametrą <code><u>&token_auth=%s</u></code>į API sąsają besikreipiančiuose universaliuose adresuose (URL). </p><p>token_auth yra toks pat slaptas, kaip ir Jūsų slaptažodis, <b>todėl neviešinkite jo!</p>',
+ 'API_LoadedAPIs' => 'Sėkmingai įkrautos API sąsajos (%s).',
+ 'API_PluginDescription' => 'Visi duomenys Piwik pasiekiami per paprastas API sąsajas. Šis papildinys - tai žiniatinklio tarnybos įėjimo taškas, kuriuo galite naudotis norėdami gauti savo žiniatinklio analizatoriaus duomenis xml, json, php, csv ir kitais formatais.',
+ 'ExampleAPI_PluginDescription' => 'Pavyzdinis papildinys: Kaip sukurti API sąsają jūsų papildiniui, kad būtų galima eksportuoti duomenis daugeliu formatų be papildomo programavimo?',
+ 'CoreAdminHome_PluginDescription' => 'Piwik administravimo sritis',
+ 'CoreHome_NoPrivileges' => 'Jūs prisijungėte kaip \'%s\' tačiau panašu, jog neturite nustatytų leidimų.<br />Kreipkitės į savo Piwik administratorių, kuris Jums suteiks peržiūros teises.',
'CoreHome_JavascriptDisabled' => 'JavaScript turi būti įjungtas normaliam Piwik veikimui.<br />Panašu, kad JavaScript yra išjungtas arba Jūsų naršyklė jo nepalaiko.<br />Prašome įjungti JavaScript savo naršyklės nuostatose ir %1stpabandyti dar kartą%2s.<br />',
- 'CoreHome_TableNoData' => 'Nėra duomenų.',
- 'CoreHome_CategoryNoData' => 'Nėra duomenų šioje kategorijoje. Pabandykite "Įtraukti visą populiaciją"',
+ 'CoreHome_TableNoData' => 'Šiai lentelei duomenų nėra.',
+ 'CoreHome_CategoryNoData' => 'Šioje kategorijoje duomenų nėra. Pabandykite "Įtraukti visą populiaciją"',
'CoreHome_ShowJSCode' => 'Parodyti JavaScript kodą įvedimui',
'CoreHome_IncludeAllPopulation_js' => 'Įtraukti visą populiaciją',
'CoreHome_ExcludeLowPopulation_js' => 'Neįtraukti menkos populiacijos',
@@ -155,13 +177,40 @@ $translations = array(
'CoreHome_MonthOctober_js' => 'Spalis',
'CoreHome_MonthNovember_js' => 'Lapkritis',
'CoreHome_MonthDecember_js' => 'Gruodis',
+ 'CoreHome_ShortDay_1_js' => 'Sek',
+ 'CoreHome_ShortDay_2_js' => 'Pir',
+ 'CoreHome_ShortDay_3_js' => 'Ant',
+ 'CoreHome_ShortDay_4_js' => 'Tre',
+ 'CoreHome_ShortDay_5_js' => 'Ket',
+ 'CoreHome_ShortDay_6_js' => 'Pen',
+ 'CoreHome_ShortDay_7_js' => 'Šeš',
+ 'CoreHome_LongDay_1_js' => 'Sekmadienis',
+ 'CoreHome_LongDay_2_js' => 'Pirmadienis',
+ 'CoreHome_LongDay_3_js' => 'Antradienis',
+ 'CoreHome_LongDay_4_js' => 'Trečiadienis',
+ 'CoreHome_LongDay_5_js' => 'Ketvirtadienis',
+ 'CoreHome_LongDay_6_js' => 'Penktadienis',
+ 'CoreHome_LongDay_7_js' => 'Šeštadienis',
+ 'CoreHome_ShortMonth_1_js' => 'Sau',
+ 'CoreHome_ShortMonth_2_js' => 'Vas',
+ 'CoreHome_ShortMonth_3_js' => 'Kov',
+ 'CoreHome_ShortMonth_4_js' => 'Bal',
+ 'CoreHome_ShortMonth_5_js' => 'Geg',
+ 'CoreHome_ShortMonth_6_js' => 'Bir',
+ 'CoreHome_ShortMonth_7_js' => 'Lie',
+ 'CoreHome_ShortMonth_8_js' => 'Rgp',
+ 'CoreHome_ShortMonth_9_js' => 'Rgs',
+ 'CoreHome_ShortMonth_10_js' => 'Spa',
+ 'CoreHome_ShortMonth_11_js' => 'Lap',
+ 'CoreHome_ShortMonth_12_js' => 'Grd',
+ 'CoreHome_PluginDescription' => 'Žiniatinklio analizatoriaus ataskaitų struktūra.',
'CorePluginsAdmin_Plugins' => 'Papildiniai',
'CorePluginsAdmin_PluginsManagement' => 'Papildinių valdymas',
'CorePluginsAdmin_MainDescription' => 'Papildiniai suteikia Piwik papildomų galimybių. Įdiegę papildinį, čia galite jį aktyvinti arba pasyvinti',
'CorePluginsAdmin_Plugin' => 'Papildinys',
'CorePluginsAdmin_Version' => 'Versija',
'CorePluginsAdmin_Description' => 'Aprašymas',
- 'CorePluginsAdmin_Status' => 'Būklė',
+ 'CorePluginsAdmin_Status' => 'Būsena',
'CorePluginsAdmin_Action' => 'Veiksmas',
'CorePluginsAdmin_PluginHomepage' => 'Papildinio svetainė',
'CorePluginsAdmin_Activated' => 'Aktyvintas',
@@ -171,42 +220,57 @@ $translations = array(
'CorePluginsAdmin_Deactivate' => 'Pasyvinti',
'CorePluginsAdmin_Activate' => 'Aktyvinti',
'CorePluginsAdmin_MenuPlugins' => 'Papildiniai',
- 'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; Naujinimas',
+ 'CorePluginsAdmin_PluginDescription' => 'Papildinių administravimo sąsaja.',
+ 'CoreUpdater_UpdateTitle' => 'Naujinimas',
'CoreUpdater_DatabaseUpgradeRequired' => 'Reikalingas duombazės atnaujinimas',
'CoreUpdater_YourDatabaseIsOutOfDate' => 'Norint tęsti, reikia atnaujinti Piwik duombazę ',
- 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik duombazė bus atnaujinta nuo versijos %s iki versijos %s. ',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik duombazė bus atnaujinta iš %s į %s versiją.',
'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Bus atnaujinti šie papildiniai: %s.',
'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Duombazės naujinimo procesas gali užtrukti, todėl prašome luktelėti.',
'CoreUpdater_UpgradePiwik' => 'Naujinti Piwik',
- 'CoreUpdater_HelpMessageContent' => 'Peržiūrėkite %s Piwik DUK, %s kur paaiškinamos dažniausiai pasitaikančios problemos naujinant. %s Jūsų sistemos administratorius gali padėti išspręsti daugumą jų, kadangi jos dažniausiai susijusios su serverio arba MySQL nustatymais.',
+ 'CoreUpdater_HelpMessageContent' => 'Peržiūrėkite %s Piwik DUK, %s kur paaiškinamos dažniausiai pasitaikančios naujinimo problemos. %s Jūsų sistemos administratorius gali padėti išspręsti daugumą jų, kadangi jos dažniausiai susijusios su serverio arba MySQL nustatymais.',
'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Kritinė klaida atnaujinimo metu:',
'CoreUpdater_HelpMessageIntroductionWhenError' => 'Aukščiau nurodytas klaidos aprašymas. Jei reikia daugiau pagalbos:',
'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Piwik atnaujinta, tačiau su išlygomis. Prašome perskaityti aukščiau pateikiamą aprašymą. Jei reikia daugiau pagalbos:',
'CoreUpdater_UpgradeComplete' => 'Naujinimas baigtas!',
- 'CoreUpdater_WarningMessages' => 'Įspėjimai:',
+ 'CoreUpdater_WarningMessages' => 'Įspėjamieji pranešimai:',
'CoreUpdater_ErrorDuringPluginsUpdates' => 'Klaida atnaujinant papildinius:',
'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Automatiškai pasyvinome šiuos papildinius: %s',
- 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik pilnai atnaujinta!',
+ 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik sėkmingai atnaujinta!',
'CoreUpdater_ContinueToPiwik' => 'Grįžti į Piwik',
'CoreUpdater_UpdateAutomatically' => 'Naujinti automatiškai',
'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Pasirodė nauja Piwik versija',
- 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Galite atnaujinti iki versijos %s automatiškai arba atsisiųsti paketą ir atnaujinti Piwik rankiniu būdu:',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Galite atnaujinti iki %s versijos automatiškai arba atsisiųsti paketą ir atnaujinti Piwik rankiniu būdu:',
'CoreUpdater_DownloadX' => 'Atsisiųsti %s',
'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Piwik automatinis atnaujinimas atšauktas. Jei negalite ištaisyti nurodytos klaidos, rekomenduojame atnaujinti Piwik rankiniu būdu. %s Peržiūrėkite %sNaujinimo dokumentaciją%s prieš pradedant!',
'CoreUpdater_VerifyingUnpackedFiles' => 'Tikrinami išskleisti failai',
'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Sukuriama atsarginė konfigūracijos failų kopija %s',
'CoreUpdater_InstallingTheLatestVersion' => 'Įdiegiama naujausia versija',
- 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik pilnai atnaujinta!',
- 'DBStats_DatabaseUsage' => 'Duombazės naudojimas',
- 'DBStats_MainDescription' => 'Piwik saugo visus Jūsų duomenis MySQL duombazėje. Šiuo metu Piwik lentelės naudoja %s.',
- 'DBStats_Table' => 'Lentelė',
- 'DBStats_RowNumber' => 'Eilučių skaičius',
- 'DBStats_DataSize' => 'Informacijos kiekis',
- 'DBStats_IndexSize' => 'Indekso dydis',
- 'DBStats_TotalSize' => 'Bendras dydis',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik sėkmingai atnaujinta!',
+ 'CoreUpdater_TheUpgradeProcessMayFail' => 'Jei Jūsų Piwik duombazė didelė, atnaujinimas naršyklėje gali užtrukti per ilgai. Tokiu atveju galite paleisti atnaujinimus iš komandinės eilutės: <code>$ php kelias/iki/piwik/index.php</code>',
+ 'CoreUpdater_ErrorDIYHelp' => 'Jei Jūs esate patyręs vartotojas ir susidūrėte su problema atnaujinant duombazę:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'nustatykite ir pakoreguokite problemos šaltinį (pvz., memory_limit arba max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'paleiskite likusias užklausas nepavykusiame naujinime',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'rankiniu būdu papildykite `option` lentelę Piwik duombazėje, nustatydami version_core reikšmę į nepavykusio naujinimo versijos numerį',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'paleiskite naujinimo procesą iš naujo (naršyklėje arba iš komandinės eilutės) ir pratęskite likusius atnaujinimus',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'praneškite apie problemą (ir sprendimą), kad Piwik būtų patobulintas',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Atsisiunčiamas atnaujinimas iš %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Išskleidžiama',
+ 'CoreUpdater_EmptyDatabaseError' => 'Duombazė %s yra tuščia. Privalote paredaguoti arba pašalinti savo Piwik konfigūracijos failą.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Jūsų Piwik versija %s yra naujausia.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Nesuderinamas archyvas: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Tuščias archyvas',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Archyvas nepilnas: trūksta kai kurių failų (pvz. %s).',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'Jei Jūsų Piwik duombazė yra didelė, atnaujinimas naršyklėje gali užtrukti per ilgai. Tokiu atveju, galite paleisti atnaujinimus per komandinę eilutę: %s',
+ 'CoreUpdater_PluginDescription' => 'Piwik naujinimo įranga',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Svarbi pastaba apie didelius Piwik diegimus',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => 'Jei negalite pasinaudoti komandine eilute Piwik atnaujinti ar Piwik tiesiog neatsinaujina (dėl nutrūkusios sesijos, prarasto ryšio su duombaze ar kurios nors kitos priežasties), galite rankiniu būdu įvykdyti SQL užklausas Piwik atnaujinimui.',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => 'Spauskite čia SQL užklausų, kurias reikia įvykdyti, sąrašui gauti.',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => 'Pastaba: jei rankiniu būdu įvykdysite šias užklausas, gali būti, jog kai kurios iš jų praneš apie klaidas ir nebus įvykdytos. Paprasčiausias ignoruokite klaidas ir vykdykite sekančias užklausas esančias sąraše.',
+ 'CoreUpdater_ReadyToGo' => 'Pasiruošę pradėti?',
'Dashboard_Dashboard' => 'Skydelis',
'Dashboard_AddWidget' => 'Pridėti valdiklį...',
- 'Dashboard_DeleteWidgetConfirm' => 'Ar tikrai norite ištrinti šį valdiklį iš skydelio?',
+ 'Dashboard_DeleteWidgetConfirm' => 'Ar tikrai norite pašalinti šį valdiklį iš skydelio?',
'Dashboard_SelectWidget' => 'Pasirinkite valdiklį, kurį norite įdėti į skydelį',
'Dashboard_AddPreviewedWidget_js' => 'Įdėti peržiūrėtą valdiklį į skydelį',
'Dashboard_WidgetPreview_js' => 'Valdiklio peržiūra',
@@ -215,9 +279,89 @@ $translations = array(
'Dashboard_TitleClickToAdd_js' => 'Spustelėkite įdėjimui į skydelį',
'Dashboard_LoadingWidget_js' => 'Įkeliamas valdiklis, luktelėkite...',
'Dashboard_WidgetNotFound_js' => 'Valdiklis nerastas',
- 'Goals_ColumnConversions' => 'Perskaičiavimai',
- 'Goals_ColumnConversionRate' => 'Tarifas',
+ 'Dashboard_PluginDescription' => 'Jūsų žiniatinklio analizatoriaus skydelis. Galite pritaikyti skydelį savo poreikiams: pridėti naujų valdiklių, pakeisti jų išdėstymo tvarką. Kiekvienas naudotojas gali susikurti savo asmeninį skydelį.',
+ 'DBStats_DatabaseUsage' => 'Duombazės naudojimas',
+ 'DBStats_MainDescription' => 'Piwik saugo visus Jūsų duomenis MySQL duombazėje. Šiuo metu Piwik lentelės naudoja %s.',
+ 'DBStats_Table' => 'Lentelė',
+ 'DBStats_RowNumber' => 'Eilučių skaičius',
+ 'DBStats_DataSize' => 'Informacijos kiekis',
+ 'DBStats_IndexSize' => 'Indekso dydis',
+ 'DBStats_TotalSize' => 'Bendras dydis',
+ 'DBStats_LearnMore' => 'Norint geriau susipažinti su Piwik duomenų apdorojimu bei kaip priversti Piwik veikti geriau vidutinės ir didelės apkrovos svetainėse, siūlome pastudijuoti dokumentaciją %s.',
+ 'DBStats_PluginDescription' => 'Šis papildinys informuoja apie MySQL duombazės užimtumą.',
+ 'DBStats_RowCount' => 'Eilučių kiekis',
+ 'ExampleFeedburner_PluginDescription' => 'Pavyzdinis papildinys: Kaip pavaizduoti jūsų Feedburner prenumeratą skydelio valdiklyje?',
+ 'ExamplePlugin_exampleWidget' => 'Pavyzdinis valdiklis',
+ 'ExamplePlugin_blogPiwikRss' => 'Piwik Blogas RSS',
+ 'ExamplePlugin_photostreamMatt' => 'Mato nuotraukos',
+ 'ExamplePlugin_exampleWidgets' => 'Pavyzdiniai valdikliai',
+ 'ExamplePlugin_PluginDescription' => 'Pavyzdinis papildinys: Šis papildinys parodys kaip sukurti labai paprastą papildinį, kuris eksportuos du valdiklius į skydelį.',
+ 'ExampleRssWidget_PluginDescription' => 'Pavyzdinis papildinys: Kaip sukurti naują valdiklį, kuris skaito RSS santraukas?',
+ 'ExampleUI_PluginDescription' => 'Pavyzdinis papildinys: Šis papildinys parodys kaip dirbti su Piwik UI: kurti lenteles, grafikus ir pan.',
+ 'Feedback_PluginDescription' => 'Siųskite savo atsiliepimus Piwik komandai. Dalinkitės savo idėjomis ir pasiūlymais su mumis!',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Norite pranešti apie aptiktą klaidą arba paprašyti naujų ypatybių?',
+ 'Feedback_ViewAnswersToFAQ' => 'Peržiūrėkite atsakymus į %s dažniausiai užduodamus klausimus%s ',
+ 'Feedback_WhyAreMyVisitsNoTracked' => 'Kodėl nestebimi apsilankymai mano svetainėje?',
+ 'Feedback_HowToExclude' => 'Kaip neįtraukti savo apsilankymų?',
+ 'Feedback_WhyWrongCountry' => 'Kodėl Piwik rodo mano apsilankymus ne iš tos šalies?',
+ 'Feedback_HowToAnonymizeIP' => 'Kaip paslėpti lankytojų IP adresus mano duombazėje?',
+ 'Feedback_VisitTheForums' => 'Apsilankykite %s forumuose%s',
+ 'Feedback_LearnWaysToParticipate' => 'Sužinokite kaip galite %s prisijungti%s',
+ 'Feedback_SpecialRequest' => 'Gal turite specialių pageidavimų Piwik komandai?',
+ 'Feedback_ContactThePiwikTeam' => 'Susisiekite su Piwik komanda!',
+ 'Feedback_IWantTo' => 'Aš noriu:',
+ 'Feedback_CategoryShareStory' => 'Pasidalinkite Piwik sėkmės istorija',
+ 'Feedback_CategorySponsor' => 'Paremkite Piwik',
+ 'Feedback_CategoryHire' => 'Nusisamdykite Piwik konsultantą',
+ 'Feedback_CategorySecurity' => 'Praneškite apie saugumo spragą',
+ 'Feedback_MyEmailAddress' => 'Mano el. pašto adresas:',
+ 'Feedback_MyMessage' => 'Mano žinutė:',
+ 'Feedback_DetailsPlease' => '(prašome detaliau)',
+ 'Feedback_SendFeedback' => 'Siųsti atsiliepimą',
+ 'Feedback_ManuallySendEmailTo' => 'Prašome išsiųsti rankiniu būdu',
+ 'Feedback_MessageSent' => 'Jūsų žinutė buvo nusiųsta Piwik komandai.',
+ 'Feedback_ThankYou' => 'Dėkojame už pagalbą kuriant tobulesnį Piwik!',
+ 'Feedback_ThePiwikTeam' => 'Piwik komanda',
+ 'Feedback_ExceptionBodyLength' => 'Žinutė privalo būti mažiausiai %s simbolių ilgio.',
+ 'Feedback_ExceptionNoUrls' => 'Žinutės tekste negali būti interneto adresų (URL) siekiant išvengti brukalų.',
+ 'Goals_ColumnConversions' => 'Konversijos',
+ 'Goals_ColumnConversionRate' => 'Konversijos tarifas',
'Goals_ColumnRevenue' => 'Pajamos',
+ 'Goals_PluginDescription' => '',
+ 'Goals_OverallRevenue' => '',
+ 'Goals_OverallConversionRate' => '',
+ 'Goals_Conversions' => '',
+ 'Goals_ConversionRate' => '',
+ 'Goals_NoGoalsNeedAccess' => '',
+ 'Goals_AddNewGoal' => 'Pridėti naują uždavinį',
+ 'Goals_AddNewGoalOrEditExistingGoal' => '',
+ 'Goals_AddGoal_js' => 'Pridėti uždavinį',
+ 'Goals_UpdateGoal_js' => 'Atnaujinti uždavinį',
+ 'Goals_DeleteGoalConfirm_js' => 'Ar tikrai norite ištrinti uždavinį %s?',
+ 'Goals_GoalName' => 'Uždavinio pavadinimas',
+ 'Goals_GoalIsTriggered' => '',
+ 'Goals_GoalIsTriggeredWhen' => '',
+ 'Goals_WhenVisitors' => '',
+ 'Goals_Manually' => 'rankiniu būdu',
+ 'Goals_ManuallyTriggeredUsingJavascriptFunction' => '',
+ 'Goals_VisitUrl' => '',
+ 'Goals_Download' => 'Atsisiųsti failą',
+ 'Goals_ClickOutlink' => 'Paspauskite ant nuorodos į išorinį puslapį',
+ 'Goals_Optional' => '(papildoma)',
+ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => '',
+ 'Goals_DefaultRevenue' => '',
+ 'Goals_DefaultRevenueHelp' => '',
+ 'Goals_ConversionsOverview' => '',
+ 'Goals_BestCountries' => '',
+ 'Goals_BestKeywords' => '',
+ 'Goals_BestReferers' => '',
+ 'Goals_ReturningVisitorsConversionRateIs' => '',
+ 'Goals_NewVisitorsConversionRateIs' => '',
+ 'Goals_Contains' => '',
+ 'Goals_IsExactly' => '',
+ 'Goals_MatchesExpression' => '',
+ 'Goals_CaseSensitive' => '',
+ 'Goals_Pattern' => '',
'Installation_Installation' => 'Įdiegimas',
'Installation_InstallationStatus' => 'Įdiegimo būklė',
'Installation_PercentDone' => '%s %% Atlikta',
@@ -227,7 +371,7 @@ $translations = array(
'Installation_JsTag' => 'JavaScript gairė (tag)',
'Installation_JsTagHelp' => '<p>Norint suskaičiuoti visus svetainės lankytojus, privalote įrašyti JavaScript kodą visuose svetainės puslapiuose.</p><p>Svetainė nebūtinai turi būti sukurta PHP kalba. Piwik veiks visų rūšių svetainėse (HTML, ASP, Perl ar bet kuri kita kalba)</p><p>Štai kodas, kurį turite įrašyti: (nukopijuokite ir įklijuokite visuose svetainės puslapiuose) </p>',
'Installation_Congratulations' => 'Sveikiname',
- 'Installation_CongratulationsHelp' => '<p>Sveikiname! Piwik instaliacija baigta.</p><p>Įsitikinkite, kad JavaScript kodas yra įrašytas visuose puslapiuose ir laukite pirmųjų lankytojų!</p>',
+ 'Installation_CongratulationsHelp' => '<p>Sveikiname! Piwik diegimas baigtas.</p><p>Įsitikinkite, kad JavaScript žymė (tag) yra įrašyta visuose puslapiuose ir laukite pirmųjų lankytojų!</p>',
'Installation_ContinueToPiwik' => 'Grįžti į Piwik',
'Installation_SetupWebsite' => 'Svetainės nustatymai',
'Installation_SetupWebsiteError' => 'Rasta klaidų pridedant svetainę',
@@ -248,15 +392,15 @@ $translations = array(
'Installation_SystemCheckPdoError' => 'Turite įgalinti PDO and PDO_MYSQL plėtinius (extensions) php.ini faile.',
'Installation_SystemCheckPdoHelp' => 'Windows serveryje galite įrašyti šias eilutes php.ini faile %s <br /><br />Linux serveryje galite kompiliuoti php su šiomis reikšmėmis %s Php.ini faile įrašykite šias eilutes %s<br /><br />Daugiau informacijos rasite <a style="color:red" href="http://php.net/pdo">PHP svetainėje</a>.',
'Installation_SystemCheckWriteDirs' => 'Katalogai su rašymo teisėmis',
- 'Installation_SystemCheckWriteDirsHelp' => 'Norint ištaisyti šią klaidą Linux sistemoje, išbandykite šią komandą (-as)',
+ 'Installation_SystemCheckWriteDirsHelp' => 'Šios klaidos pataisymui Linux sistemoje, išbandykite šią komandą (-as)',
'Installation_SystemCheckMemoryLimit' => 'Atminties limitas',
- 'Installation_SystemCheckMemoryLimitHelp' => 'Didelio srauto svetainėse archyvavimas gali reikalauti daugiau atminties nei šiuo metu yra.<br />Pasitikrinkite reikšmę memory_limit savo php.ini faile, jeigu būtina.',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'Didelio lankytojų srauto svetainėse archyvavimas gali reikalauti daugiau atminties nei šiuo metu yra.<br />Pasitikrinkite reikšmę memory_limit savo php.ini faile, jeigu būtina.',
'Installation_SystemCheckGD' => 'GD &gt; 2.x (grafika)',
'Installation_SystemCheckGDHelp' => 'Mažos diagramos neveiks.',
'Installation_SystemCheckTimeLimit' => 'set_time_limit() leidžiama',
- 'Installation_SystemCheckTimeLimitHelp' => 'Didelio srauto svetainėse archyvavimo proceso aktyvavimas gali reikalauti daugiau laiko nei šiuo metu leidžiama.<br />Pasitikrinkite reikšmę max_execution_time savo php.ini faile, jeigu būtina.',
+ 'Installation_SystemCheckTimeLimitHelp' => 'Didelio lankytojų srauto svetainėse archyvavimo proceso aktyvavimas gali reikalauti daugiau laiko nei šiuo metu leidžiama.<br />Pasitikrinkite reikšmę max_execution_time savo php.ini faile, jeigu būtina.',
'Installation_SystemCheckMail' => 'mail() leidžiama',
- 'Installation_SystemCheckError' => 'Rasta klaida turi būti ištaisyta norint tęsti',
+ 'Installation_SystemCheckError' => 'Rasta klaida turi būti ištaisyta prieš tęsiant',
'Installation_SystemCheckWarning' => 'Piwik funkcionuos normaliai, tačiau kai kurios savybės gali būti prarastos',
'Installation_Tables' => 'Kuriamos lentelės',
'Installation_TablesWithSameNamesFound' => 'Kai kurios %s lentelės Jūsų duombazėje %s pavadintos taip pat, kaip lentelės, kurias Piwik bando sukurti',
@@ -267,11 +411,75 @@ $translations = array(
'Installation_TablesDeletedSuccess' => 'Esamos Piwik lentelės ištrintos sėkmingai',
'Installation_TablesCreatedSuccess' => 'Lentelės sukurtos sėkmingai!',
'Installation_DatabaseCreatedSuccess' => 'Duombazė %s sukurta sėkmingai!',
- 'Installation_GoBackAndDefinePrefix' => 'Grįžti atgal Piwik lentelių priešdėliui nurodyti',
- 'Installation_ConfirmDeleteExistingTables' => 'Ar tikrai norite ištrinti lenteles: %s duombazėje? ĮSPĖJIMAS: DUOMENYS ŠIOSE LENTELĖS NEGALĖS BŪTI ATKURTI!',
+ 'Installation_GoBackAndDefinePrefix' => 'Grįžkite atgal ir nurodykite Piwik lentelių priešdėlį',
+ 'Installation_ConfirmDeleteExistingTables' => 'Ar tikrai norite ištrinti lenteles: %s duombazėje? ĮSPĖJIMAS: ŠIŲ LENTELIŲ DUOMENYS TAPS NEATKURIAMAIS!',
'Installation_Welcome' => 'Sveiki!',
'Installation_WelcomeHelp' => '<p>Piwik yra atvirojo kodo programa, kuri leidžia lengvai rinkti informaciją apie Jūsų lankytojus.</p><p>Šis procesas padalintas į %s lengvus žingsnius, kurie užims apie 5 minutes.</p>',
- 'Installation_ErrorInvalidState' => 'Klaida: Panašu, kad bandote praleisti Įdiegimo procesą, arba Jūsų naršyklėje išjungti slapukai, arba Piwik konfigūracinis failas jau yra sukurtas. %sĮsitikinkite, kad slapukai įjungti%s ir grįžkite %s į pradinį įdiegimo puslapį %s.',
+ 'Installation_ErrorInvalidState' => 'Klaida: Panašu, kad bandote praleisti įdiegimo procesą, arba Jūsų naršyklėje išjungti slapukai, arba Piwik konfigūracinis failas jau yra sukurtas. %sĮsitikinkite, kad slapukai įjungti%s ir grįžkite %s į pradinį įdiegimo puslapį %s.',
+ 'Installation_DatabaseSetup' => 'Duombazės sąranka',
+ 'Installation_DatabaseErrorConnect' => 'Klaida jungiantis prie duombazės serverio',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'Kliento ryšys su duombaze yra ne UTF-8 formato',
+ 'Installation_JsTagQuicHelpk' => 'Greita pagalba',
+ 'Installation_JsTagArchivingHelp' => 'Vidutinio ir aukšto lankytojų srauto svetainėms, rekomenduojame pasidomėti <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">Kaip sukurti automatiškai archyvuojantį puslapį</a> ir priversti Piwik veikti dar greičiau!',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Svetainė %s sukurta sėkmingai!',
+ 'Installation_Requirements' => 'Piwik reikalavimai sistemai',
+ 'Installation_Optional' => 'Pasirenkama',
+ 'Installation_Legend' => 'Sutartinis ženklas',
+ 'Installation_Extension' => 'plėtinys',
+ 'Installation_SystemCheckExtensions' => 'Kiti reikalingi plėtiniai',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik reikalingas mysqli plėtinys arba abu PDO ir pdo_mysql plėtiniai',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'Linux serveryje galite sukompiliuoti php su šiais nustatymais: %s į Jūsų php.ini failą įterpkite šias eilutes: %s',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Daugiau informacijos: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> and <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'Windows serveryje galite įterpti šias eilutes į Jūsų php.ini failą: %s',
+ 'Installation_SystemCheckSplHelp' => 'Jums reikia sukonfigūruoti ir perdaryti PHP su įjungtu Standard PHP Library (SPL) (pagal nutylėjimą).',
+ 'Installation_SystemCheckZlibHelp' => 'Jums reikia sukonfigūruoti ir perdaryti PHP su įjungta "zlib" funkcija, --with-zlib.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'Jums reikia sukonfigūruoti ir perdaryti PHP su "json" arba "xml" plėtiniu.',
+ 'Installation_SystemCheckJsonSite' => 'Daugiau informacijos: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Kai kurie trečiųjų šalių papildiniai ir plėtotojų bibliotekos gali reikalauti "xml" plėtinio.',
+ 'Installation_SystemCheckXmlSite' => 'Daugiau informacijos: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckOpenURL' => 'Open URL',
+ 'Installation_SystemCheckOpenURLHelp' => 'Naujienlaiškių prenumeratos, atnaujinimų pranešimai ir "vieno spustelėjimo" naujinimai reikalauja "curl" plėtinio, allow_url_fopen=On, arba aktyvuoto fsockopen()',
+ 'Installation_SystemCheckFunctions' => 'Reikalingos funkcijos',
+ 'Installation_SystemCheckMailHelp' => 'Atsiliepimų ir prarastų slpatažodžių pranešimai nebus siunčiami be mail() funkcijos.',
+ 'Installation_DatabaseSetupServer' => 'duomenų bazių serveris',
+ 'Installation_DatabaseSetupLogin' => 'prisijungimas',
+ 'Installation_DatabaseSetupPassword' => 'slaptažodis',
+ 'Installation_DatabaseSetupDatabaseName' => 'duomenų bazės pavadinimas',
+ 'Installation_DatabaseSetupTablePrefix' => 'lentelės priešdėlis',
+ 'Installation_DatabaseSetupAdapter' => 'suderintuvas',
+ 'Installation_DatabaseCheck' => 'Duomenų bazės patikra',
+ 'Installation_DatabaseServerVersion' => 'Duomenų bazių serverio versija',
+ 'Installation_DatabaseCreation' => 'Duomenų bazės sukūrimas',
+ 'Installation_DatabaseClientCharset' => 'Duomenų bazės kliento koduotės',
+ 'Installation_DatabaseTimezone' => 'Duomenų bazės laiko juosta',
+ 'Installation_TimezoneMismatch' => 'PHP date.timezone - tai ne tas pats, kas duomenų bazės serverio laiko juosta. Tai gali įtakoti teisingo laiko nerodymą ataskaitose. Daugiau informacijos %s',
+ 'Installation_JsTagHelpTitle' => 'Kaip įterpti žymę į Jūsų svetaines?',
+ 'Installation_LargePiwikInstances' => 'Pagalba dideliems Piwik pavyzdžiams',
+ 'Installation_SetupWebSiteName' => 'svetainės pavadinimas',
+ 'Installation_SetupWebSiteURL' => 'svetainės URL',
+ 'Installation_SystemCheckIconvHelp' => 'Jums reikia sukonfigūruoti ir perdaryti PHP su įjungtu "iconv" palaikymu, --with-iconv.',
+ 'Installation_SystemCheckDomHelp' => 'DOM yra PHP branduolio dalis. Greičiausiai, Jums reikia įdiegti dom modulį, pvz., php-5-dom.',
+ 'Installation_PluginDescription' => 'Piwik diegimo procesas. Diegimas paprastai atliekamas vieną kartą. Jei konfigūracijos failas config/config.inc.php ištrinamas, bus paleistas papildomas diegimas.',
+ 'Installation_DatabaseClientVersion' => 'Duomenų bazės kliento versija',
+ 'Installation_SystemCheckParseIniFileHelp' => 'Ši integruota funkcija yra išjungta Jūsų serveryje. Piwik pabandys emuliuoti šią funkciją, tačiau galimi saugumo suvaržymai ateityje. Stebėjimo sparta taip pat gali būti paveikta.',
+ 'Installation_SystemCheckDebugBacktraceHelp' => '',
+ 'Installation_SystemCheckCreateFunctionHelp' => '',
+ 'Installation_SystemCheckMbstring' => 'mbstring',
+ 'Installation_SystemCheckMbstringHelp' => 'Privalote nustatyti mbstring.func_overload reikšmę "0"',
+ 'Installation_SystemCheckFileIntegrity' => 'Failo vientisumas',
+ 'Installation_SystemCheckProtocol' => 'Protokolas',
+ 'Installation_SystemCheckProtocolHelp' => 'Jei esate už atvirkštinio įgaliotojo serverio (reverse proxy), pridėkite šias eilutes config/config.ini.php faile po [General] skiltimi:',
+ 'Installation_SystemCheckIpv4' => 'IPv4',
+ 'Installation_SystemCheckIpv4Help' => 'Privalote išjungti IPv6 savo žiniatinklio serverio konfigūracijoje.',
+ 'Installation_ConfigurationHelp' => 'Jūsų Piwik konfigūracijos failas sukonfigūruotas netinkamai. Jūs galite ištrinti config/config.ini.php failą arba pakartoti diegimą, arba pakoreguoti susijungimo su duomenų baze nustatymus.',
+ 'LanguagesManager_PluginDescription' => 'Šis papildinys pateikia visų prieinamų kalbų Piwik vartotojo sąsajai sąrašą. Kiekvienas naudotojas gali pasirinkti savo kalbą.',
+ 'Live_PluginDescription' => 'Sekite savo lankytojus gyvai, realiu laiku!',
+ 'Live_VisitorLog' => 'Apsilankymų žurnalas',
+ 'Live_Date' => 'Data',
+ 'Live_Time' => 'Laikas',
+ 'Live_Referrer_URL' => 'Persiunčiančiojo URL',
'Login_LoginPasswordNotCorrect' => 'Naudotojo vardas ir slaptažodis neteisingi',
'Login_Login' => 'Naudotojo vardas',
'Login_Password' => 'Slaptažodis',
@@ -286,9 +494,17 @@ $translations = array(
'Login_MailPasswordRecoveryBody' => 'Sveiki %1s, \n\n Jūsų naujas slaptažodis: %2s \n\n Dabar galite prisijungti: %3s',
'Login_PasswordSent' => 'Slaptažodis nusiųstas. Pasitikrinkite el. paštą.',
'Login_ContactAdmin' => 'Galima priežastis: Jūsų pagr. kompiuteryje (serveryje) gali būti išjungta mail() funkcija.<br />Prašome susisiekti su savo Piwik administratoriumi.',
- 'Provider_WidgetProviders' => 'Tiekėjai',
- 'Provider_ColumnProvider' => 'Tiekėjas',
- 'Provider_SubmenuLocationsProvider' => 'Vietovės ir tiekėjas',
+ 'Login_PasswordRepeat' => 'Slaptažodis (pakartoti)',
+ 'Login_ChangePassword' => 'Pakeisti slaptažodį',
+ 'Login_PasswordResetToken' => 'Slaptažodžio keitimo talonas',
+ 'Login_PasswordsDoNotMatch' => 'Slaptažodžiai nesutampa',
+ 'Login_PasswordSuccessfullyChanged' => 'Slaptažodis pakeistas sėkmingai!',
+ 'Login_InvalidOrExpiredToken' => 'Netinkamas arba pasibaigęs talonas',
+ 'Login_PluginDescription' => 'Prisijungimo autentifikacijos papildinys, nuskaitantis prisijungimo informaciją iš config/config.inc.php failo Super User\'iui, ir iš duomenų bazės kitiems naudotojams. Galima lengvai pakeisti kitais autentifikacijos mechanizmais (OpenID, htaccess, custom Auth ir t.t.)',
+ 'Provider_WidgetProviders' => 'IP tiekėjai',
+ 'Provider_ColumnProvider' => 'IP tiekėjas',
+ 'Provider_SubmenuLocationsProvider' => 'Vietovės ir IP tiekėjas',
+ 'Provider_PluginDescription' => 'Nurodo lankytojų interneto paslaugų tiekėją.',
'Referers_Referers' => 'Šaltiniai',
'Referers_SearchEngines' => 'Paieškos sistemos',
'Referers_Keywords' => 'Raktiniai žodžiai',
@@ -314,7 +530,7 @@ $translations = array(
'Referers_DistinctKeywords' => 'atskirti raktinius žodžius',
'Referers_DistinctCampaigns' => 'atskirti kampanijas',
'Referers_DistinctWebsites' => 'atskirti svetaines',
- 'Referers_UsingNDistinctUrls' => '(using %2s distinct urls)',
+ 'Referers_UsingNDistinctUrls' => '(naudojant %2s skirtingus URL)',
'Referers_SubmenuEvolution' => 'Raida',
'Referers_SubmenuSearchEngines' => 'Paieškos sistemos ir raktiniai žodžiai',
'Referers_SubmenuWebsites' => 'Svetainės',
@@ -324,6 +540,12 @@ $translations = array(
'Referers_WidgetExternalWebsites' => 'Išorinių svetainių sąrašas',
'Referers_WidgetSearchEngines' => 'Geriausios paieškos sistemos',
'Referers_WidgetOverview' => 'Bendras vaizdas',
+ 'Referers_PluginDescription' => 'Nurodo šaltinio duomenis: paieškos variklius, raktinius žodžius, svetaines, tiesioginius apsilankymus ir t.t.',
+ 'SecurityInfo_PluginDescription' => 'Sukurtas pagal PhpSecInfo iš PHP Saugumo Konsorciumo, šis papildinys pateikia saugumo informaciją apie Jūsų PHP aplinką bei pateikia pasiūlymus kaip ją pagerinti.',
+ 'SecurityInfo_Security' => 'Saugumas',
+ 'SecurityInfo_SecurityInformation' => 'PHP saugumo informacija',
+ 'SecurityInfo_Test' => 'Testas',
+ 'SecurityInfo_Result' => 'Rezultatas',
'SitesManager_Sites' => 'Svetainės',
'SitesManager_WebsitesManagement' => 'Svetainių valdymas',
'SitesManager_MainDescription' => 'Pridėkite, atnaujinkite, šalinkite svetaines ir gaukite JavaScript kodą.',
@@ -341,10 +563,12 @@ $translations = array(
'SitesManager_ExceptionNoUrl' => 'Turite nurodyti bent vieną adresą (URL) svetainei.',
'SitesManager_ExceptionEmptyName' => 'Svetainės pavadinimas negali būti tuščias.',
'SitesManager_ExceptionInvalidUrl' => 'Adresas (URL) \'%s\' netinkamas.',
+ 'SitesManager_AliasUrlHelp' => 'Rekomenduojama, nors ir nebūtina, nurodyti įvarius URLs, kuriais lankytojai pasiekia šią svetainę. Alternatyvių vardų URLs svetainei nebus atvaizduojama Šaltiniai > Svetainių ataskaitos. Nebūtina nurodyti URL su ar be \'www\', kadangi Piwik automatiškai palaiko abu.',
+ 'SitesManager_PluginDescription' => 'Svetainių administravimas: Pridėkite naujas svetaines, redaguokite esamas, gaukite Javascript kodą įkėlimui į savo svetainę. Visi šie veiksmai taip pat pasiekiami per API sąsają.',
'TranslationsAdmin_MenuTranslations' => 'Vertimai',
'TranslationsAdmin_MenuLanguages' => 'Kalbos',
'TranslationsAdmin_Plugin' => 'Papildinys',
- 'TranslationsAdmin_Definition' => 'Apibrėžtis',
+ 'TranslationsAdmin_Definition' => 'Apibrėžimas',
'TranslationsAdmin_DefaultString' => 'Numatytoji reikšmė (English)',
'TranslationsAdmin_TranslationString' => 'Vertimas (dabartinė kalba: %s)',
'TranslationsAdmin_Translations' => 'Vertimai',
@@ -354,6 +578,7 @@ $translations = array(
'TranslationsAdmin_LanguageCode' => 'Kalbos kodas',
'TranslationsAdmin_Export' => 'Eksportuoti kalbą',
'TranslationsAdmin_Import' => 'Importuoti kalbą',
+ 'TranslationsAdmin_PluginDescription' => 'Padėkite versti Piwik į Jūsų kalbą.',
'UserCountry_Country' => 'Šalis',
'UserCountry_Continent' => 'Kontinentas',
'UserCountry_DistinctCountries' => '%s atskirti šalis',
@@ -361,101 +586,101 @@ $translations = array(
'UserCountry_WidgetContinents' => 'Lankytojų kontinentai',
'UserCountry_WidgetCountries' => 'Lankytojų šalys',
'UserCountry_country_ac' => 'Ascension Islands',
- 'UserCountry_country_ad' => 'Andorra',
- 'UserCountry_country_ae' => 'United Arab Emirates',
- 'UserCountry_country_af' => 'Afghanistan',
+ 'UserCountry_country_ad' => 'Andora',
+ 'UserCountry_country_ae' => 'Jungtiniai Arabų Emyratai',
+ 'UserCountry_country_af' => 'Afganistanas',
'UserCountry_country_ag' => 'Antigua and Barbuda',
'UserCountry_country_ai' => 'Anguilla',
- 'UserCountry_country_al' => 'Albania',
- 'UserCountry_country_am' => 'Armenia',
+ 'UserCountry_country_al' => 'Albanija',
+ 'UserCountry_country_am' => 'Armenija',
'UserCountry_country_an' => 'Netherlands Antilles',
'UserCountry_country_ao' => 'Angola',
'UserCountry_country_aq' => 'Antarctica',
'UserCountry_country_ar' => 'Argentina',
'UserCountry_country_as' => 'American Samoa',
- 'UserCountry_country_at' => 'Austria',
- 'UserCountry_country_au' => 'Australia',
+ 'UserCountry_country_at' => 'Austrija',
+ 'UserCountry_country_au' => 'Australija',
'UserCountry_country_aw' => 'Aruba',
'UserCountry_country_ax' => 'Aland Islands',
- 'UserCountry_country_az' => 'Azerbaijan',
- 'UserCountry_country_ba' => 'Bosnia and Herzegovina',
- 'UserCountry_country_bb' => 'Barbados',
- 'UserCountry_country_bd' => 'Bangladesh',
- 'UserCountry_country_be' => 'Belgium',
+ 'UserCountry_country_az' => 'Azerbaidžanas',
+ 'UserCountry_country_ba' => 'Bosnija ir Hercogovina',
+ 'UserCountry_country_bb' => 'Barbadosas',
+ 'UserCountry_country_bd' => 'Bangladešas',
+ 'UserCountry_country_be' => 'Belgija',
'UserCountry_country_bf' => 'Burkina Faso',
- 'UserCountry_country_bg' => 'Bulgaria',
+ 'UserCountry_country_bg' => 'Bulgarija',
'UserCountry_country_bh' => 'Bahrain',
- 'UserCountry_country_bi' => 'Burundi',
+ 'UserCountry_country_bi' => 'Burundis',
'UserCountry_country_bj' => 'Benin',
'UserCountry_country_bl' => 'Saint Barthelemy',
- 'UserCountry_country_bm' => 'Bermuda',
+ 'UserCountry_country_bm' => 'Bermudai',
'UserCountry_country_bn' => 'Bruneo',
- 'UserCountry_country_bo' => 'Bolivia',
- 'UserCountry_country_br' => 'Brazil',
- 'UserCountry_country_bs' => 'Bahamas',
- 'UserCountry_country_bt' => 'Bhutan',
+ 'UserCountry_country_bo' => 'Bolivija',
+ 'UserCountry_country_br' => 'Brazilija',
+ 'UserCountry_country_bs' => 'Bahamai',
+ 'UserCountry_country_bt' => 'Butanas',
'UserCountry_country_bu' => 'Burma',
'UserCountry_country_bv' => 'Bouvet Island',
- 'UserCountry_country_bw' => 'Botswana',
- 'UserCountry_country_by' => 'Belarus',
+ 'UserCountry_country_bw' => 'Botsvana',
+ 'UserCountry_country_by' => 'Baltarusij',
'UserCountry_country_bz' => 'Belize',
- 'UserCountry_country_ca' => 'Canada',
+ 'UserCountry_country_ca' => 'Kanada',
'UserCountry_country_cc' => 'Cocos (Keeling) Islands',
- 'UserCountry_country_cd' => 'Congo, The Democratic Republic of the',
+ 'UserCountry_country_cd' => 'Kongo Demokratinė Respublika',
'UserCountry_country_cf' => 'Central African Republic',
- 'UserCountry_country_cg' => 'Congo',
- 'UserCountry_country_ch' => 'Switzerland',
+ 'UserCountry_country_cg' => 'Kongas',
+ 'UserCountry_country_ch' => 'Šveicarija',
'UserCountry_country_ci' => 'Cote D\'Ivoire',
'UserCountry_country_ck' => 'Cook Islands',
- 'UserCountry_country_cl' => 'Chile',
- 'UserCountry_country_cm' => 'Cameroon',
- 'UserCountry_country_cn' => 'China',
- 'UserCountry_country_co' => 'Colombia',
+ 'UserCountry_country_cl' => 'Čilė',
+ 'UserCountry_country_cm' => 'Kamerūnas',
+ 'UserCountry_country_cn' => 'Kinija',
+ 'UserCountry_country_co' => 'Kolumbija',
'UserCountry_country_cp' => 'Clipperton Island',
- 'UserCountry_country_cr' => 'Costa Rica',
+ 'UserCountry_country_cr' => 'Kosta Rika',
'UserCountry_country_cs' => 'Serbia Montenegro',
- 'UserCountry_country_cu' => 'Cuba',
+ 'UserCountry_country_cu' => 'Kuba',
'UserCountry_country_cv' => 'Cape Verde',
- 'UserCountry_country_cx' => 'Christmas Island',
- 'UserCountry_country_cy' => 'Cyprus',
- 'UserCountry_country_cz' => 'Czech Republic',
- 'UserCountry_country_de' => 'Germany',
+ 'UserCountry_country_cx' => 'Kalėdų sala',
+ 'UserCountry_country_cy' => 'Kipras',
+ 'UserCountry_country_cz' => 'Čekijos Respublika',
+ 'UserCountry_country_de' => 'Vokietija',
'UserCountry_country_dg' => 'Diego Garcia',
'UserCountry_country_dj' => 'Djibouti',
- 'UserCountry_country_dk' => 'Denmark',
- 'UserCountry_country_dm' => 'Dominica',
+ 'UserCountry_country_dk' => 'Danija',
+ 'UserCountry_country_dm' => 'Dominika',
'UserCountry_country_do' => 'Dominican Republic',
- 'UserCountry_country_dz' => 'Algeria',
+ 'UserCountry_country_dz' => 'Alžyras',
'UserCountry_country_ea' => 'Ceuta, Melilla',
'UserCountry_country_ec' => 'Ecuador',
'UserCountry_country_ee' => 'Estija',
- 'UserCountry_country_eg' => 'Egypt',
+ 'UserCountry_country_eg' => 'Egiptas',
'UserCountry_country_eh' => 'Western Sahara',
'UserCountry_country_er' => 'Eritrea',
- 'UserCountry_country_es' => 'Spain',
- 'UserCountry_country_et' => 'Ethiopia',
+ 'UserCountry_country_es' => 'Ispanija',
+ 'UserCountry_country_et' => 'Etiopija',
'UserCountry_country_eu' => 'Europos Sąjunga',
- 'UserCountry_country_fi' => 'Finland',
- 'UserCountry_country_fj' => 'Fiji',
+ 'UserCountry_country_fi' => 'Suomija',
+ 'UserCountry_country_fj' => 'Fidžis',
'UserCountry_country_fk' => 'Falkland Islands (Malvinas)',
'UserCountry_country_fm' => 'Micronesia, Federated States of',
'UserCountry_country_fo' => 'Faroe Islands',
- 'UserCountry_country_fr' => 'France',
+ 'UserCountry_country_fr' => 'Prancūzija',
'UserCountry_country_fx' => 'France, Metropolitan',
'UserCountry_country_ga' => 'Gabon',
- 'UserCountry_country_gb' => 'Great Britain',
+ 'UserCountry_country_gb' => 'Didžioji Britanija',
'UserCountry_country_gd' => 'Grenada',
'UserCountry_country_ge' => 'Gruzija',
'UserCountry_country_gf' => 'French Guyana',
'UserCountry_country_gg' => 'Guernsey',
- 'UserCountry_country_gh' => 'Ghana',
- 'UserCountry_country_gi' => 'Gibraltar',
+ 'UserCountry_country_gh' => 'Gana',
+ 'UserCountry_country_gi' => 'Gibraltaras',
'UserCountry_country_gl' => 'Greenland',
- 'UserCountry_country_gm' => 'Gambia',
- 'UserCountry_country_gn' => 'Guinea',
- 'UserCountry_country_gp' => 'Guadeloupe',
+ 'UserCountry_country_gm' => 'Gambija',
+ 'UserCountry_country_gn' => 'Gvinėja',
+ 'UserCountry_country_gp' => 'Gvadelupė',
'UserCountry_country_gq' => 'Equatorial Guinea',
- 'UserCountry_country_gr' => 'Greece',
+ 'UserCountry_country_gr' => 'Graikija',
'UserCountry_country_gs' => 'South Georgia and the South Sandwich Islands',
'UserCountry_country_gt' => 'Guatemala',
'UserCountry_country_gu' => 'Guam',
@@ -463,25 +688,25 @@ $translations = array(
'UserCountry_country_gy' => 'Guyana',
'UserCountry_country_hk' => 'Hong Kong',
'UserCountry_country_hm' => 'Heard Island and McDonald Islands',
- 'UserCountry_country_hn' => 'Honduras',
- 'UserCountry_country_hr' => 'Croatia',
- 'UserCountry_country_ht' => 'Haiti',
+ 'UserCountry_country_hn' => 'Hondūras',
+ 'UserCountry_country_hr' => 'Kroatija',
+ 'UserCountry_country_ht' => 'Haitis',
'UserCountry_country_hu' => 'Hungary',
'UserCountry_country_ic' => 'Canary Islands',
- 'UserCountry_country_id' => 'Indonesia',
- 'UserCountry_country_ie' => 'Ireland',
- 'UserCountry_country_il' => 'Israel',
+ 'UserCountry_country_id' => 'Indonezija',
+ 'UserCountry_country_ie' => 'Airija',
+ 'UserCountry_country_il' => 'Izraelis',
'UserCountry_country_im' => 'Man Island',
- 'UserCountry_country_in' => 'India',
+ 'UserCountry_country_in' => 'Indija',
'UserCountry_country_io' => 'British Indian Ocean Territory',
- 'UserCountry_country_iq' => 'Iraq',
+ 'UserCountry_country_iq' => 'Irakas',
'UserCountry_country_ir' => 'Iran, Islamic Republic of',
- 'UserCountry_country_is' => 'Iceland',
- 'UserCountry_country_it' => 'Italy',
+ 'UserCountry_country_is' => 'Islandija',
+ 'UserCountry_country_it' => 'Italija',
'UserCountry_country_je' => 'Jersey',
- 'UserCountry_country_jm' => 'Jamaica',
- 'UserCountry_country_jo' => 'Jordan',
- 'UserCountry_country_jp' => 'Japan',
+ 'UserCountry_country_jm' => 'Jamaika',
+ 'UserCountry_country_jo' => 'Jordanas',
+ 'UserCountry_country_jp' => 'Japonija',
'UserCountry_country_ke' => 'Kenya',
'UserCountry_country_kg' => 'Kyrgyzstan',
'UserCountry_country_kh' => 'Cambodia',
@@ -629,6 +854,7 @@ $translations = array(
'UserCountry_continent_ams' => 'Pietų ir Centrinė Amerika',
'UserCountry_continent_amn' => 'Šiaurės Amerika',
'UserCountry_continent_oce' => 'Okeanija',
+ 'UserCountry_PluginDescription' => 'Nurodo lankytojų šalis.',
'UserSettings_VisitorSettings' => 'Lankytojų nustatymai',
'UserSettings_BrowserFamilies' => 'Naršyklių šeimos',
'UserSettings_Browsers' => 'Naršyklės',
@@ -650,8 +876,11 @@ $translations = array(
'UserSettings_WidgetWidescreen' => 'Normalus / Plačiaekranis',
'UserSettings_WidgetBrowserFamilies' => 'Naršyklės pagal šeimą',
'UserSettings_WidgetOperatingSystems' => 'Operacinės sistemos',
- 'UserSettings_WidgetGlobalVisitors' => 'Bendra lankytojų konfigūracija',
+ 'UserSettings_WidgetGlobalVisitors' => 'Bendri lankytojų nustatymai',
'UserSettings_SubmenuSettings' => 'Nustatymai',
+ 'UserSettings_PluginDescription' => 'Parodo įvairius lankytojo nustatymus: naršyklę, naršyklės šeimą, operacinę sistemą, papildinius, ekrano raišką, skiriamąją gebą, globalius nustatymus.',
+ 'UserSettings_OperatingSystems' => 'Operacinės sistemos',
+ 'UserSettings_ColumnOperatingSystem' => 'Operacinė sistema',
'UsersManager_UsersManagement' => 'Naudotojų valdymas',
'UsersManager_UsersManagementMainDescription' => 'Kurkite naujus naudotojus arba keiskite jau esančius. Po to aukščiau galite parinkti jiems leidimus.',
'UsersManager_ManageAccess' => 'Administruoti teises',
@@ -682,31 +911,25 @@ $translations = array(
'UsersManager_ExceptionEditAnonymous' => 'Naudotojas \'anonimas\' negali būti keičiamas ar šalinamas. Jis naudojamas nustatyti naudotoją, kuris dar neprisijungęs. Pavyzdžiui, Jūs galite padaryti savo statistinius duomenis viešais suteikdami \'matyti\' teises naudotojui \'anonimas\'.',
'UsersManager_ExceptionSuperUser' => 'Pageidaujamas naudotojas yra Super Naudotojas, todėl negali būti klausiamas, keičiamas ar šalinamas per API sąsają. Super Naudotojo duomenis galite keisti rankiniu būdu Piwik konfigūraciniame faile.',
'UsersManager_ExceptionUserDoesNotExist' => 'Naudotojas \'%s\' neegzistuoja.',
- 'UsersManager_ExceptionAccessValues' => 'The parameter access must have one of the following values : [ %s ]',
+ 'UsersManager_ExceptionAccessValues' => 'Parametras access privalo turėti vieną iš šių reikšmių: [ %s ]',
+ 'UsersManager_PluginDescription' => 'Piwik naudotojų administravimas: pridėkite naudotoją, redaguokite esamą, atnaujinkite leidimus. Visi veiksmai taip pat pasiekiami per API sąsają.',
'VisitFrequency_Evolution' => 'Raida periodu',
'VisitFrequency_ColumnReturningVisits' => 'Sugrįžtančių apsilankymai',
'VisitFrequency_ColumnActionsByReturningVisits' => 'Sugrįžtančių veiksmai',
'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Daugiausia sugrįžtančių veiksmų',
'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Bendras laikas praleistas sugrįžtančių (sekundėmis)',
- 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Atsitiktinumų koeficientas tarp sugrįžtančių',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Šoklumo reitingas tarp sugrįžtančių',
'VisitFrequency_ReturnVisits' => '%s sugrįžtančių apsilankymai',
'VisitFrequency_ReturnActions' => '%s sugrįžtančių veiksmai',
'VisitFrequency_ReturnMaxActions' => '%s daugiausia sugrįžtančių veiksmų',
'VisitFrequency_ReturnTotalTime' => '%s bendras laikas praleistas sugrįžtančių',
- 'VisitFrequency_ReturnBounceRate' => '%s atsitiktinumų koeficientas tarp sugrįžtančių (paliko svetainę po pirmojo puslapio)',
+ 'VisitFrequency_ReturnBounceRate' => '%s šoklumo reitingas tarp sugrįžtančių (paliko svetainę po pirmojo puslapio)',
'VisitFrequency_WidgetOverview' => 'Pasikartojimų peržiūra',
'VisitFrequency_WidgetGraphReturning' => 'Sugrįžtančių grafikas',
'VisitFrequency_SubmenuFrequency' => 'Pasikartojimai',
- 'VisitTime_LocalTime' => 'Apsilankymai vietiniu laiku',
- 'VisitTime_ServerTime' => 'Apsilankymai serverio laiku',
- 'VisitTime_ColumnServerTime' => 'Serverio laikas',
- 'VisitTime_ColumnLocalTime' => 'Vietinis laikas',
- 'VisitTime_WidgetLocalTime' => 'Apsilankymai vietiniu laiku',
- 'VisitTime_WidgetServerTime' => 'Apsilankymai serverio laiku',
- 'VisitTime_SubmenuTimes' => 'Laikai',
- 'VisitTime_NHour' => '%sh',
- 'VisitorInterest_VisitsPerDuration' => 'Visits per visit duration',
- 'VisitorInterest_VisitsPerNbOfPages' => 'Visits per number of pages',
+ 'VisitFrequency_PluginDescription' => 'Parodo įvairią statistiką apie sugrįžtančius bei pirmą kartą apsilankančius lankytojus.',
+ 'VisitorInterest_VisitsPerDuration' => 'Apsilankymai pagal apsilankymų trukmę',
+ 'VisitorInterest_VisitsPerNbOfPages' => 'Apsilankymai pagal puslapių kiekį',
'VisitorInterest_ColumnVisitDuration' => 'Apsilankymo trukmė',
'VisitorInterest_ColumnPagesPerVisit' => 'Puslapių per apsilankymą',
'VisitorInterest_WidgetLengths' => 'Apsilankymų trukmė',
@@ -717,6 +940,7 @@ $translations = array(
'VisitorInterest_OnePage' => '1 puslapis',
'VisitorInterest_NPages' => '%s puslapiai',
'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
+ 'VisitorInterest_PluginDescription' => 'Parodo lankytojų susidomėjimą: aplankytus puslapius, svetainėje praleistą laiką.',
'VisitsSummary_NbVisits' => '%s apsilankymai',
'VisitsSummary_NbUniqueVisitors' => '%s unikalūs lankytojai',
'VisitsSummary_NbActions' => '%s veiksmai (puslapių peržiūros)',
@@ -732,7 +956,17 @@ $translations = array(
'VisitsSummary_WidgetLastVisitors' => 'Paskutinių unikalių lankytojų diagrama',
'VisitsSummary_WidgetOverviewGraph' => 'Peržiūra su diagrama',
'VisitsSummary_SubmenuOverview' => 'Peržiūra',
- 'ExamplePlugin_exampleWidget' => 'Pavyzdinis valdiklis',
- 'ExamplePlugin_blogPiwikRss' => 'Piwik Blogas RSS',
- 'ExamplePlugin_photostreamMatt' => 'Mato nuotraukos',
-);
+ 'VisitsSummary_VisitsSummary' => 'Apsilankymų suvestinė',
+ 'VisitsSummary_PluginDescription' => 'Parodo pagrindinius analizatoriaus duomenis: apsilankymus, unikalius lankytojus, veiksmų kiekį, šoklumo koeficientą ir t.t.',
+ 'VisitsSummary_NbActionsDescription' => '%s veiksmai (puslapio peržiūros, atsisiuntimai ir išorinės nuorodos)',
+ 'VisitTime_LocalTime' => 'Apsilankymai vietiniu laiku',
+ 'VisitTime_ServerTime' => 'Apsilankymai serverio laiku',
+ 'VisitTime_ColumnServerTime' => 'Serverio laikas',
+ 'VisitTime_ColumnLocalTime' => 'Vietinis laikas',
+ 'VisitTime_WidgetLocalTime' => 'Apsilankymai vietiniu laiku',
+ 'VisitTime_WidgetServerTime' => 'Apsilankymai serverio laiku',
+ 'VisitTime_SubmenuTimes' => 'Laikai',
+ 'VisitTime_NHour' => '%sh',
+ 'VisitTime_PluginDescription' => 'Ataskaitos lokaliu ir serverio laiku.',
+ 'Widgetize_PluginDescription' => 'Šis papildinys leidžia itin paprastai eksportuoti bet kurį Piwik valdiklį į Jūsų interneto dienoraštį, svetainę ar į Igoogle bei Netvibes!',
+); \ No newline at end of file
diff --git a/lang/nb.php b/lang/nb.php
index 25b681b4f6..313ffeaf35 100644
--- a/lang/nb.php
+++ b/lang/nb.php
@@ -12,7 +12,7 @@ $translations = array(
'General_OpenSourceWebAnalytics' => 'Åpen kildekode nettstatistikk',
'General_YourDashboard' => 'Ditt kontrollpanel',
'General_API' => 'API',
- 'General_Widgets' => 'Widgets',
+ 'General_Widgets' => 'Element',
'General_Settings' => 'Innstillinger',
'General_GiveUsYourFeedback' => 'Gi oss tilbakemeldinger!',
'General_Unknown' => 'Ukjent',
@@ -29,7 +29,7 @@ $translations = array(
'General_Logout' => 'Logg ut',
'General_Done' => 'Ferdig',
'General_LoadingData' => 'Laster data ...',
- 'General_ErrorRequest' => 'Oops&hellip; problem oppstod, prøv igjen.',
+ 'General_ErrorRequest' => 'Oops&hellip; problem oppstod under forespørsel, prøv igjen.',
'General_Next' => 'Neste',
'General_Previous' => 'Forrige',
'General_Search' => 'Søk',
@@ -51,39 +51,39 @@ $translations = array(
'General_ColumnUniquePageviews' => 'Unike sidevisninger',
'General_Save' => 'Lagre',
'General_Website' => 'Nettsted',
- 'General_NoDataForGraph' => 'Ingen data for denne grafen',
+ 'General_NoDataForGraph' => 'Ingen data for denne grafen.',
'General_NoDataForTagCloud' => 'Ingen data for denne merkelappskyen.',
'General_DisplayNormalTable' => 'Vis normal tabell',
- 'General_DisplayMoreData' => 'Vis mer informasjon',
+ 'General_DisplayMoreData' => 'Vis mer data',
'General_PiwikIsACollaborativeProject' => '%s Piwik %s er et åpent prosjekt og fremdeles i Beta. %s Hvis du vil hjelpe, vennligst %s kontakt oss%s.',
- 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Du bruker nå en demo av %s; %sdownload%s full fersjon! Se %s',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Du bruker nå en demo av %1$s; %2$sdownload%3$s den fullstendige utgaven! Se %4$s',
'API_QuickDocumentation' => '',
- 'API_LoadedAPIs' => 'Lastet %s API-et.',
+ 'API_LoadedAPIs' => 'Lastet %s API',
'Actions_Actions' => 'Handlinger',
'Actions_SubmenuPages' => 'Sider',
'Actions_SubmenuOutlinks' => 'Utlenker',
'Actions_SubmenuDownloads' => 'Nedlastinger',
'CoreHome_NoPrivileges' => 'Du er logget inn som \'%s\' men det ser ikke ut som du har noen tilganger i Piwik.<br />Spør din Piwik administrator for å gi deg lesetilgang.',
- 'CoreHome_JavascriptDisabled' => 'JavaSript må være aktivert for at du skal kunne bruke Piwik sin standardvisning. Det ser ut som JavaScript er enten deaktiver eller ikke støttet av din nettleser.<br />For å bruke standardvisning, aktiver JavaScript i innstillingene for din nettleser, og %1stry again%2s.<br />',
+ 'CoreHome_JavascriptDisabled' => 'JavaScript må være aktivert for at du skal kunne bruke Piwik sin standardvisning. Det ser ut som JavaScript er enten deaktiver eller ikke støttet av din nettleser.<br />For å bruke standardvisning, aktiver JavaScript i innstillingene for din nettleser, og %1stry again%2s.<br />',
'CoreHome_TableNoData' => 'Ingen data for denne tabellen.',
'CoreHome_CategoryNoData' => 'Ingen data i denne kategorien. Prøv å velge "Inkluder hele populasjon".',
'CoreHome_ShowJSCode' => 'Vis JavaScript-koden til å sette inn på din nettside.',
'CoreHome_IncludeAllPopulation_js' => 'Inkluder hele populasjon',
'CoreHome_ExcludeLowPopulation_js' => 'Eksluder lav populasjon',
- 'CoreHome_PageOf_js' => '%s av %s',
+ 'CoreHome_PageOf_js' => '%1$s av %2$s',
'CoreHome_Loading_js' => 'Laster ...',
'CoreHome_LocalizedDateFormat' => '%A %d %B %Y',
'CoreHome_PeriodDay' => 'Dag',
'CoreHome_PeriodWeek' => 'Uke',
'CoreHome_PeriodMonth' => 'Måned',
'CoreHome_PeriodYear' => 'År',
- 'CoreHome_DaySu_js' => 'Søn',
- 'CoreHome_DayMo_js' => 'Man',
- 'CoreHome_DayTu_js' => 'Tirs',
- 'CoreHome_DayWe_js' => 'Ons',
- 'CoreHome_DayTh_js' => 'Tors',
- 'CoreHome_DayFr_js' => 'Fre',
- 'CoreHome_DaySa_js' => 'Lør',
+ 'CoreHome_DaySu_js' => 'Sø',
+ 'CoreHome_DayMo_js' => 'Ma',
+ 'CoreHome_DayTu_js' => 'Ti',
+ 'CoreHome_DayWe_js' => 'On',
+ 'CoreHome_DayTh_js' => 'To',
+ 'CoreHome_DayFr_js' => 'Fr',
+ 'CoreHome_DaySa_js' => 'Lø',
'CoreHome_MonthJanuary_js' => 'Januar',
'CoreHome_MonthFebruary_js' => 'Februar',
'CoreHome_MonthMarch_js' => 'Mars',
@@ -112,7 +112,7 @@ $translations = array(
'CorePluginsAdmin_Deactivate' => 'Slå av',
'CorePluginsAdmin_Activate' => 'Slå på',
'CorePluginsAdmin_MenuPlugins' => 'Tillegg',
- 'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; Oppdatering',
+ 'CoreUpdater_UpdateTitle' => 'Oppdater',
'CoreUpdater_UpdateRequired' => 'Oppgradering er påkrevd',
'CoreUpdater_YourDatabaseIsOutOfDate' => 'Piwik-databasen din er utdatert og må oppgraderes før du kan fortsette.',
'CoreUpdater_PiwikWillBeUpgradedToVersionX' => 'Piwik vil nå bli oppgradert til versjon %s.',
@@ -149,19 +149,19 @@ $translations = array(
'Installation_Installation' => 'Installasjon',
'Installation_InstallationStatus' => 'Installasjonsstatus',
'Installation_PercentDone' => '%s %% ferdig',
- 'Installation_NoConfigFound' => 'Piwik-konfigurasjonsfil kunne ikke bli funnet og du prøver å få tilgang til Piwik. <br /><b>&nbsp;&nbsp;&raquo;Du kan <a href=\'index.php\'>installere Piwik nå</a></b><br /><small>Hvus du prøvde å installere Piwik tidligere, og har noen tabeller i databasen, gamle data blir liggende!</small>',
+ 'Installation_NoConfigFound' => 'Klarte ikke finne konfigurasjonsfilen for Piwik, og du prøver å få tilgang til en Piwik-side. <br /><b>&nbsp;&nbsp;&raquo;Du kan <a href=\'index.php\'>installere Piwik nå</a></b><br /><small>Hvis du prøvde å installere Piwik tidligere og har noen tabeller i databasen, kan du ta det med ro. Du kan bruke de gamle tabellene og beholde dine eksisterende data!</small>',
'Installation_MysqlSetup' => 'MySQL database oppsett',
'Installation_MysqlErrorConnect' => 'Feil ved tilkobling til databasen
',
- 'Installation_JsTag' => 'Javascript-kode',
- 'Installation_JsTagHelp' => '<p>For å telle alle besøkende, du må plasse JavaScript-koden på alle dine sider.</p><p>Dine sider trenger ikke være laget med PHP, Piwik vil virke på alle typer sider (uansett om det er HTML, ASP, Perl eller noe annet språk).</p><p>Her er koden du må sette inn: (kopier og lim på alle dine sider)</p>',
+ 'Installation_JsTag' => 'JavaScript-kode',
+ 'Installation_JsTagHelp' => '<p>For å telle alle besøkende, du må plassere JavaScript-koden på alle dine sider.</p><p>Dine sider trenger ikke være laget med PHP, Piwik vil virke på alle typer sider (uansett om det er HTML, ASP, Perl eller noe annet språk).</p><p>Her er koden du må sette inn: (kopier og lim på alle dine sider)</p>',
'Installation_Congratulations' => 'Gratulerer',
'Installation_CongratulationsHelp' => '<p>Gratulerer! Din Piwik installasjon er fullført.</p><p>Sørg for at JavaScript-koden er lagt inn på dine sider, og vent på dine første besøkende!</p>',
'Installation_ContinueToPiwik' => 'Fortsett til Piwik',
'Installation_SetupWebsite' => 'Legg til et nettsted',
- 'Installation_SetupWebsiteError' => 'Det skjedde en feil mens nettstedet ble lagt til.',
+ 'Installation_SetupWebsiteError' => 'Det skjedde en feil da nettstedet ble lagt til.',
'Installation_GeneralSetup' => 'Generelt oppsett',
- 'Installation_GeneralSetupSuccess' => 'Generelt oppsett ble vellykket lagret
+ 'Installation_GeneralSetupSuccess' => 'Generelt oppsett ble lagret
',
'Installation_SystemCheck' => 'Systemsjekk',
'Installation_SystemCheckPhp' => 'PHP-versjon',
@@ -243,7 +243,8 @@ $translations = array(
'SitesManager_Name' => 'Navn',
'SitesManager_Urls' => 'URL-er',
'SitesManager_MenuSites' => 'Nettsteder',
- 'SitesManager_DeleteConfirm_js' => 'Er du sikker på at du ønsker å slette følgende nettsted? %s
+ 'SitesManager_DeleteConfirm_js' => 'Er du sikker på at du ønsker å slette nettstedet %s?
+
',
'SitesManager_ExceptionDeleteSite' => 'Det er ikke mulig å slette dette nettstedet, da det er det eneste registrerte nettstedet. Legg til et nytt nettsted, og deretter slett dette.',
'SitesManager_ExceptionNoUrl' => 'Du må spesifisere minst en URL til nettstedet.',
@@ -557,7 +558,7 @@ $translations = array(
'UsersManager_Edit' => 'Endre',
'UsersManager_AddUser' => 'Legg til ny bruker',
'UsersManager_MenuUsers' => 'Brukere',
- 'UsersManager_DeleteConfirm_js' => 'Er du sikker på at du vil slette %s?',
+ 'UsersManager_DeleteConfirm_js' => 'Er du sikker på at du vil slette brukeren %s?',
'UsersManager_ExceptionLoginExists' => 'Brukernavn \'%s\' eksisterer allerede.',
'UsersManager_ExceptionEmailExists' => 'Bruker med e-post \'%s\' eksisterer allerede.',
'UsersManager_ExceptionInvalidPassword' => 'Lengden på passordet må være mellom 6 og 26 tegn.',
@@ -604,7 +605,7 @@ $translations = array(
'VisitsSummary_GenerateQueries' => '%s spørringer kjørt',
'VisitsSummary_WidgetLastVisits' => 'Graf over siste besøk',
'VisitsSummary_WidgetVisits' => 'Besøksoversikt',
- 'VisitsSummary_WidgetLastVisitors' => 'Graf over siste unike besøkende',
+ 'VisitsSummary_WidgetLastVisitors' => 'Grafikk over siste unike besøkende',
'VisitsSummary_WidgetOverviewGraph' => 'Oversikt med grafikk',
'VisitsSummary_SubmenuOverview' => 'Oversikt',
'General_Loading' => 'Laster ...',
@@ -615,8 +616,8 @@ $translations = array(
'General_ColumnSumVisitLength' => 'Total tid brukt av besøkende (i sekunder)',
'General_ColumnValuePerVisit' => 'Verdi per besøk',
'General_ColumnVisitsWithConversions' => 'Besøk med konvertering',
- 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s er et samarbeidsprosjekt. %s Hvis du liker Piwik, må du gjerne hjelpe til! Les mer på %sHow to contribute to Piwik?%s ',
- 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s er tilgjengelig. %s Oppgrader nå!%s (se %s endringer%s).',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%1$s Piwik %2$s er et samarbeidsprosjekt. %s%s Hvis du liker Piwik, kan du hjelpe til! Les mer på %4$s How to participate in Piwik?%5$s ',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %1$s er tilgjengelig. %2$s Oppdater nå!%3$s (se %4$s endringer%5$s).',
'General_BackToPiwik' => 'Tilbake til Piwik',
'General_ShortMonth_1' => 'Jan',
'General_ShortMonth_2' => 'Feb',
@@ -662,7 +663,7 @@ $translations = array(
'CoreHome_PeriodMonths' => 'måneder',
'CoreHome_PeriodYears' => 'år',
'CoreUpdater_DatabaseUpgradeRequired' => 'Databaseoppgradering er nødvendig',
- 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik-databasen blir oppgradert fra versjon %s til versjon %s.',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik-databasen blir oppgradert fra versjon %1$s til versjon %2$s .',
'CoreUpdater_UpdateAutomatically' => 'Oppdater automatisk',
'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Du kan oppdatere til en ny versjon av Piwik.',
'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Du kan oppdatere til versjon %s automatisk eller laste ned pakken og installere manuelt.',
@@ -684,7 +685,7 @@ $translations = array(
'Dashboard_AddPreviewedWidget_js' => 'Legg til forhåndsvist element til kontrollpanelet.',
'Dashboard_WidgetPreview_js' => 'Forhåndsvisning av element',
'Dashboard_Close_js' => 'Lukk',
- 'Referers_MetricsFromRefererTypeGraphLegend' => '%1s (fra %2s)',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%1$s (fra %2$s)',
'Referers_ColumnRefererType' => 'Henvisingstype',
'Referers_ColumnSearchEngine' => 'Søkemotor',
'Referers_ColumnWebsite' => 'Nettsted',
@@ -749,7 +750,7 @@ $translations = array(
'Installation_TablesWithSameNamesFound' => 'Noen %s tabeller i databasen din %s har samme navn som de tabellene Piwik prøver å opprette',
'Installation_GoBackAndDefinePrefix' => 'Gå tilbake og definer et prefiks for Piwik-tabellene',
'Installation_ConfirmDeleteExistingTables' => 'Er du sikker på at du vil slette tabellene %s fra databasen din? ADVARSEL: DATA FRA DISSE TABELLENE KAN IKKE GJENOPPRETTES!',
- 'Installation_ErrorInvalidState' => 'Feil: Det ser ut som om du prøver å hoppe over et steg i installasjonsprosessen eller informasjonskapsler (cookies) er deaktivert eller Piwik sin konfigurasjon er allerede opprettet. %s Forsikre deg om at du har aktivert informasjonskapsler %s og gå tilbake %s til første side av installasjonen %s.',
+ 'Installation_ErrorInvalidState' => 'Feil: Det ser ut som om du prøver å hoppe over et steg i installasjonsprosessen eller informasjonskapsler (cookies) er deaktivert eller Piwik sin konfigurasjon er allerede opprettet. %1$sForsikre deg om at du har aktivert informasjonskapsler%2$s og gå tilbake %3$s til første side av installasjonen %4$s.',
'Provider_ColumnProvider' => 'Tilbyder',
'Goals_ColumnConversions' => 'Konvertering',
'Goals_ColumnConversionRate' => 'Konverteringsrate',
@@ -776,4 +777,305 @@ $translations = array(
'Installation_SystemCheckWinPdoHelp' => 'På en Windows-tjener kan du legge til følgende linjer i din php.ini-fil: %s',
'Installation_SystemCheckOpenURL' => 'Åpne URL',
'Installation_SystemCheckOpenURLHelp' => 'Nyhetsbrev abonnement, oppdatering påminninger og en-klikk-oppdatering krever Curl-utvidelsen, "allow_url_fopen=On" eller at fsockopen() er aktivert.',
+ 'CoreHome_PluginDescription' => 'Struktur for nettstatistikkrapporter.',
+ 'CoreHome_ShortDay_1_js' => 'Søn',
+ 'CoreHome_ShortDay_2_js' => 'Man',
+ 'CoreHome_ShortDay_3_js' => 'Tir',
+ 'CoreHome_ShortDay_4_js' => 'Ons',
+ 'CoreHome_ShortDay_5_js' => 'Tor',
+ 'CoreHome_ShortDay_6_js' => 'Fre',
+ 'CoreHome_ShortDay_7_js' => 'Lør',
+ 'CoreHome_LongDay_1_js' => 'Søndag',
+ 'CoreHome_LongDay_2_js' => 'Mandag',
+ 'CoreHome_LongDay_3_js' => 'Tirsdag',
+ 'CoreHome_LongDay_4_js' => 'Onsdag',
+ 'CoreHome_LongDay_5_js' => 'Torsdag',
+ 'CoreHome_LongDay_6_js' => 'Fredag',
+ 'CoreHome_LongDay_7_js' => 'Lørdag',
+ 'CoreHome_ShortMonth_1_js' => 'Jan',
+ 'CoreHome_ShortMonth_2_js' => 'Feb',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Apr',
+ 'CoreHome_ShortMonth_5_js' => 'Mai',
+ 'CoreHome_ShortMonth_6_js' => 'Jun',
+ 'CoreHome_ShortMonth_7_js' => 'Jul',
+ 'CoreHome_ShortMonth_8_js' => 'Aug',
+ 'CoreHome_ShortMonth_9_js' => 'Sep',
+ 'CoreHome_ShortMonth_10_js' => 'Okt',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dec',
+ 'CorePluginsAdmin_PluginDescription' => 'Grensesnitt for administrasjon av tillegg',
+ 'CoreUpdater_PluginDescription' => 'Piwik-oppdateringsmekanisme',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Viktig merknad for store Piwik-installasjoner',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => '',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => '',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => '',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => '',
+ 'CoreUpdater_ReadyToGo' => '',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Laster ned oppdatering fra %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Pakker ut oppdateringen',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Din Piwik versjon %s er siste utgave.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Inkompatibelt arkiv: %s ',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Tomt arkiv.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Arkivet er ikke komplett - noen file mangler (f.eks. %s).',
+ 'DBStats_PluginDescription' => 'Dette tillegget rapporterer MySQL-databasebruk for Piwik-tabeller.',
+ 'DBStats_LearnMore' => 'For å lære mer om hvordan Piwik behandler data og hvordan få Piwik til å virke bra for nettsteder med medium og høy trafikk, les dokumentasjonen %s.',
+ 'DBStats_RowCount' => 'Antall rader',
+ 'Dashboard_PluginDescription' => 'Ditt nettanalyse-kontrollpanel. Du kan tilpasse kontrollpanelet: Legge til nye element, endre rekkefølgene for dine element. Hver bruker kan tilpasse sitt eget kontrollpanel.',
+ 'Installation_PluginDescription' => '',
+ 'Installation_DatabaseSetup' => 'Databaseinnstillinger',
+ 'Installation_DatabaseSetupServer' => 'databasetjener',
+ 'Installation_DatabaseSetupLogin' => 'brukernavn',
+ 'Installation_DatabaseSetupPassword' => 'passord',
+ 'Installation_DatabaseSetupDatabaseName' => 'databasenavn',
+ 'Installation_DatabaseSetupTablePrefix' => 'tabellprefiks',
+ 'Installation_DatabaseSetupAdapter' => 'adapter',
+ 'Installation_DatabaseErrorConnect' => 'Klarte ikke koble til databasetjeneren',
+ 'Installation_DatabaseCheck' => 'Databasesjekk',
+ 'Installation_DatabaseServerVersion' => 'Databasetjener-versjon',
+ 'Installation_DatabaseClientVersion' => 'Databaseklient-versjon',
+ 'Installation_DatabaseCreation' => 'Databaseopprettelse',
+ 'Installation_PleaseFixTheFollowingErrors' => 'Fiks følgende feil',
+ 'Installation_JsTagHelpTitle' => 'Hvordan plassere koden på dine nettsteder?',
+ 'Installation_LargePiwikInstances' => 'Hjelp for store Piwik-instanser',
+ 'Installation_JsTagArchivingHelp' => '',
+ 'Installation_SetupWebSiteName' => 'navn på nettsted',
+ 'Installation_SetupWebSiteURL' => 'URL for nettsted',
+ 'Installation_Timezone' => 'tidssone for nettsted',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Nettstedet %s ble opprettet.',
+ 'Installation_Extension' => 'utvidelse',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik krever enten mysqli utvidelsen eller både PDO og pdo_mysql utvidelsene.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => '',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => '',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => '',
+ 'Installation_SystemCheckIconvHelp' => 'Du må konfigurere og bygge PHP på nytt med iconv-støtte aktivert, --with-iconv.',
+ 'Installation_SystemCheckDomHelp' => 'DOM er del av PHP-kjernen. Du trenger sannsynligvis å installere DOM-modulen, dvs php5-dom.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'Du må konfigurere og bygge PHP på nytt med enten json eller xml utvidelsene aktivert.',
+ 'Installation_SystemCheckJsonSite' => 'Mer informasjon på: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Noen tredjepartstillegg eller utvilkerbibliotek kan krever xml-utvidelsen.',
+ 'Installation_SystemCheckXmlSite' => 'Mer informasjon på: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckParseIniFileHelp' => '',
+ 'Installation_SystemCheckDebugBacktraceHelp' => '',
+ 'Installation_SystemCheckCreateFunctionHelp' => '',
+ 'Installation_SystemCheckMbstring' => 'mbstring',
+ 'Installation_SystemCheckMbstringHelp' => '',
+ 'Installation_SystemCheckFileIntegrity' => 'Filintegritet',
+ 'Installation_SystemCheckProtocol' => 'Protokoll',
+ 'Installation_SystemCheckProtocolHelp' => '',
+ 'Installation_SystemCheckIpv4' => 'IPv4',
+ 'Installation_SystemCheckIpv4Help' => 'Du bør deaktivere IPv6 i oppsettet for din netttjener.',
+ 'Installation_ConfigurationHelp' => '',
+ 'LanguagesManager_PluginDescription' => 'Dette tillegg viser en liste med tilgjengelige språk for Piwik-grensesnittet. Språket som velges lagres i innstillingene for hver bruker.',
+ 'LanguagesManager_AboutPiwikTranslations' => 'Om Piwik-oversettelser',
+ 'Live_PluginDescription' => 'Spioner på dine besøkende, live, i sanntid!',
+ 'Live_VisitorLog' => 'Logg over besøkende',
+ 'Live_Date' => 'Dato',
+ 'Live_Time' => 'Tid',
+ 'Live_Referrer_URL' => 'Henvisnings-URL',
+ 'Login_PluginDescription' => '',
+ 'Login_PasswordRepeat' => 'Passord (gjenta)',
+ 'Login_ChangePassword' => 'Endre passord',
+ 'Login_PasswordResetToken' => '',
+ 'Login_PasswordsDoNotMatch' => 'Passordene stemmer ikke overens.',
+ 'Login_PasswordSuccessfullyChanged' => 'Passord endret.',
+ 'Login_InvalidNonceOrReferer' => '',
+ 'Login_InvalidOrExpiredToken' => '',
+ 'Provider_PluginDescription' => 'Rapporterer tilbyderen for de besøkende.',
+ 'Referers_PluginDescription' => 'Rapporterer henviserdata: Søkemotorer, nøkkelord, nettsteder, kampanjesporing, direkte inngang.',
+ 'SitesManager_PluginDescription' => '',
+ 'SitesManager_AliasUrlHelp' => '',
+ 'SitesManager_SuperUserCan' => 'Superbrukeren kan også %s oppgi globale innstillinger%s for nye nettsteder.',
+ 'SitesManager_ExcludedIps' => 'Ekskluderte IP-adresser',
+ 'SitesManager_GlobalListExcludedIps' => 'Global liste over ekskluderte IP-adresser',
+ 'SitesManager_ListOfIpsToBeExcludedOnAllWebsites' => 'IP-adressene nedenfor blir ekskludert fra sporing på alle nettsteder.',
+ 'SitesManager_ExcludedParameters' => 'Ekskluderte parametre',
+ 'SitesManager_GlobalListExcludedQueryParameters' => 'Global liste over URL-spørreparametre som skal ekskluderes',
+ 'SitesManager_ListOfQueryParametersToBeExcludedOnAllWebsites' => 'URL-spørreparametrene nedenfor blir ekskludert fra alle side URL-rapporter.',
+ 'SitesManager_ListOfQueryParametersToExclude' => '',
+ 'SitesManager_PiwikWillAutomaticallyExcludeCommonSessionParameters' => '',
+ 'SitesManager_HelpExcludedIps' => '',
+ 'SitesManager_YourCurrentIpAddressIs' => 'Din nåværende IP-adresse er %s',
+ 'SitesManager_SelectACity' => 'Velg en by',
+ 'SitesManager_ChooseCityInSameTimezoneAsYou' => 'Velg en by i samme tidssone som deg.',
+ 'SitesManager_ChangingYourTimezoneWillOnlyAffectDataForward' => '',
+ 'SitesManager_AdvancedTimezoneSupportNotFound' => '',
+ 'SitesManager_UTCTimeIs' => 'UTC-tid er %s.',
+ 'SitesManager_Timezone' => 'Tidssone',
+ 'SitesManager_GlobalWebsitesSettings' => 'Globale nettstedinnstillinger',
+ 'SitesManager_DefaultTimezoneForNewWebsites' => 'Standard tidssone for nye nettsteder',
+ 'SitesManager_SelectDefaultTimezone' => 'Du kan velge standard tidssone for nye nettsteder.',
+ 'SitesManager_Currency' => 'Valuta',
+ 'SitesManager_CurrencySymbolWillBeUsedForGoals' => 'Valuta-symbolet vises ved siden av omsetningsmål.',
+ 'SitesManager_DefaultCurrencyForNewWebsites' => 'Standard valuta for nye nettsteder',
+ 'SitesManager_SelectDefaultCurrency' => 'Du kan velge standard valuta for nye nettsteder.',
+ 'TranslationsAdmin_PluginDescription' => 'Hjelp til å oversette Piwik til ditt språk.',
+ 'UserCountry_PluginDescription' => 'Rapporterer landet for de besøkende.',
+ 'UserSettings_PluginDescription' => 'Rapporterer forskjellige brukerinnstillinger: Nettleser, nettleserfamilie, operativsystem, tillegg, oppløsning, globale innstillinger.',
+ 'UserSettings_OperatingSystems' => 'Operativsystem',
+ 'UserSettings_ColumnOperatingSystem' => 'Operativsystem',
+ 'UsersManager_PluginDescription' => 'Brukeradministrasjon i Piwik: Legg til en ny bruker, endre en eksisterende bruker, oppdatere rettighetene. Alle handlingene er også tilgjengelig gjennom API-et.',
+ 'UsersManager_TheSuperUserAliasCannotBeChanged' => 'Superbruker-aliaset kan ikke endres.',
+ 'UsersManager_ReportToLoadByDefault' => 'Rapport som skal lastes som standard',
+ 'UsersManager_ReportDateToLoadByDefault' => 'Rapportdato som skal lastes som standard',
+ 'UsersManager_ForAnonymousUsersReportDateToLoadByDefault' => 'Rapportdato som skal lastes som standard for anonyme brukere',
+ 'UsersManager_ExcludeVisitsViaCookie' => 'Ekskluder dine besøk med en informasjonskapsel',
+ 'UsersManager_YourVisitsAreIgnored' => '%sDine besøk blir ignorert av Piwik%s (informasjonskapselen for ekskludering fra Piwik ble funnet i din nettleser).',
+ 'UsersManager_YourVisitsAreNotIgnored' => '%sDine besøk blir ikke ignorert av Piwik%s (informasjonskapselen for ekskludering fra Piwik ble ikke funnet i din nettleser).',
+ 'UsersManager_ClickHereToDeleteTheCookie' => 'Klikk her for å slette informasjonskapselen og la Piwik spore dine besøk.',
+ 'UsersManager_ClickHereToSetTheCookie' => 'Klikk her for å lage en informasjonskapsel som vil ekskludere dine besøk på nettsteder som spores av Piwik',
+ 'UsersManager_MenuUserSettings' => 'Brukerinnstillinger',
+ 'UsersManager_MenuAnonymousUserSettings' => 'Innstillinger for anonym bruker',
+ 'UsersManager_NoteNoAnonymousUserAccessSettingsWontBeUsed' => 'Merk: Du har ingen nettsteder hvor anonyme brukere har tilgang så de følgende innstillingene blir ikke brukt.',
+ 'UsersManager_WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess' => 'Brukere som ikke er logget og besøker Piwik, skal sendes til',
+ 'UsersManager_ChangePassword' => 'Endre passord',
+ 'UsersManager_IfYouWouldLikeToChangeThePasswordTypeANewOne' => 'Hvis du vil endre passordet, skriv inn et nytt. Hvis ikke, lar du feltet være tomt.',
+ 'UsersManager_TypeYourPasswordAgain' => 'Skriv inn ditt nye passord på nytt.',
+ 'UsersManager_TheLoginScreen' => 'Innloggingsside',
+ 'UsersManager_YourUsernameCannotBeChanged' => 'Brukernavnet ditt kan ikke endres.',
+ 'VisitsSummary_PluginDescription' => '',
+ 'VisitsSummary_VisitsSummary' => 'Besøksammendrag',
+ 'VisitsSummary_NbActionsDescription' => '%s handlinger (sidevisninger, nedlastinger og utlenker)',
+ 'General_Dashboard' => 'Kontrollpanel',
+ 'General_DashboardForASpecificWebsite' => 'Kontrollpanel en gitt nettsted',
+ 'General_MultiSitesSummary' => 'Alle nettsteder',
+ 'General_AllWebsitesDashboard' => 'Kontrollpanel for alle nettsteder',
+ 'General_NotValid' => '%s er ikke gyldig',
+ 'General_Username' => 'Brukernavn',
+ 'General_Details' => 'Detaljer',
+ 'General_Default' => 'Standard',
+ 'General_YourChangesHaveBeenSaved' => 'Din endringer er lagret.',
+ 'General_ExportAsImage_js' => 'Eksporter som bilde',
+ 'General_SaveImageOnYourComputer_js' => 'For å lagre bildet på din datamaskin, høyreklikk på bildet og velg "Lagre bilde som ..."',
+ 'General_Today' => 'I dag',
+ 'General_Yesterday' => 'I går',
+ 'General_CurrentWeek' => 'Gjeldende uke',
+ 'General_CurrentMonth' => 'Gjeldende måned',
+ 'General_CurrentYear' => 'Gjeldende år',
+ 'General_ForExampleShort' => 'f.eks.',
+ 'General_GeneralSettings' => 'Generelle innstillinger',
+ 'General_AllowPiwikArchivingToTriggerBrowser' => 'Tillatt at Piwik-arkivering utløses når rapporter vises i nettleseren',
+ 'General_ArchivingInlineHelp' => '',
+ 'General_ArchivingTriggerDescription' => 'For større Piwik-installasjoner anbefales det at du setter opp en %scron-jobb%s for å behandle rapporter automatisk.',
+ 'General_SeeTheOfficialDocumentationForMoreInformation' => 'Se %sden offisielle dokumentasjonen%s for mer informasjon.',
+ 'General_ReportsForTodayWillBeProcessedAtMostEvery' => 'Rapporter for i dag blir behandlet ikke oftere enn hvert',
+ 'General_NSeconds' => '%s sekund',
+ 'General_SmallTrafficYouCanLeaveDefault' => '',
+ 'General_MediumToHighTrafficItIsRecommendedTo' => '',
+ 'General_RequiresFlash' => 'Visning av grafikk i Piwik krever Flash',
+ 'General_GraphHelp' => 'Mer informasjon om visning av grafikk i Piwik',
+ 'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin' => '%s er tilgjengelig. Gjør nettstedets administrator oppmerksom på dette.',
+ 'General_ExceptionDatabaseVersion' => '',
+ 'General_ExceptionIncompatibleClientServerVersions' => '',
+ 'General_ExceptionMissingFile' => '',
+ 'General_ExceptionFilesizeMismatch' => '',
+ 'General_ExceptionFileIntegrity' => '',
+ 'General_ExceptionNonceMismatch' => '',
+ 'General_WarningFileIntegritySkipped' => '',
+ 'General_WarningFileIntegrityNoManifest' => '',
+ 'General_WarningFileIntegrityNoMd5file' => '',
+ 'General_FileIntegrityWarningExplanation' => '',
+ 'CoreAdminHome_PluginDescription' => 'Administrasjonsområdet for Piwik.',
+ 'CoreAdminHome_MenuGeneralSettings' => 'Generelle innstillinger',
+ 'Actions_PluginDescription' => 'Rapporterer om sidevisinger, utlenker og nedlastinger. Sporing av utlenker og nedlastinger skjer automatisk.',
+ 'Actions_SubmenuPageTitles' => 'Sidetitler',
+ 'Actions_ColumnPageURL' => 'URL for side',
+ 'API_PluginDescription' => '',
+ 'ExampleAPI_PluginDescription' => '',
+ 'Feedback_PluginDescription' => 'Send din tilbakemelding til Piwik-laget. Del din ideer og forslag med oss!',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Har du en feil å rapportere eller ny funksjonalitet du ønsker deg?',
+ 'Feedback_ViewAnswersToFAQ' => 'Se svar på %s ofte stilte spørsmål%s.',
+ 'Feedback_WhyAreMyVisitsNoTracked' => 'Hvorfor spores ikke besøk på mitt nettsted?',
+ 'Feedback_HowToExclude' => 'Hvordan ekskluderer jeg sporing av mine besøk?',
+ 'Feedback_WhyWrongCountry' => 'Hvorfor viser Piwik mine besøk fra feil land?',
+ 'Feedback_HowToAnonymizeIP' => 'Hvordan maskerer jeg besøkendes IP-adresser i min database?',
+ 'Feedback_VisitTheForums' => 'Besøk %sforumet%s',
+ 'Feedback_LearnWaysToParticipate' => 'Lær om alle måtene du kan %s bidra%s',
+ 'Feedback_SpecialRequest' => 'Har du en spesiell forespørsel til Piwik-laget?',
+ 'Feedback_ContactThePiwikTeam' => 'Kontakt Piwik-laget!',
+ 'Feedback_IWantTo' => 'Jeg vil:',
+ 'Feedback_CategoryShareStory' => 'Dele en Piwik-suksesshistorie',
+ 'Feedback_CategorySponsor' => 'Sponse Piwik',
+ 'Feedback_CategoryHire' => 'Leie inn en Piwik-konsulent',
+ 'Feedback_CategorySecurity' => 'Rapportere et sikkerhetsproblem',
+ 'Feedback_MyEmailAddress' => 'Min e-postadresse:',
+ 'Feedback_MyMessage' => 'Min melding:',
+ 'Feedback_DetailsPlease' => '(inkluder alle detaljer)',
+ 'Feedback_SendFeedback' => 'Send tilbakemelding',
+ 'Feedback_ManuallySendEmailTo' => 'Send meldingen manuelt til',
+ 'Feedback_MessageSent' => 'Din melding ble sendt til Piwik-laget',
+ 'Feedback_ThankYou' => 'Takk for at du hjelper oss å lage Piwik bedre!',
+ 'Feedback_ThePiwikTeam' => 'Piwik-laget',
+ 'Feedback_ExceptionBodyLength' => 'Meldingen må være minst %s tegn lang.',
+ 'Feedback_ExceptionNoUrls' => 'Meldingen kan ikke inneholde en URL (for å unngå spam)',
+ 'General_GoTo' => 'Gå til %s',
+ 'General_PageBounceRateDefinition' => '',
+ 'General_ColumnExitRate' => '',
+ 'General_PageExitRateDefinition' => '',
+ 'General_ColumnBounces' => 'Sprett',
+ 'General_BouncesDefinition' => 'Antall besøk som startet på denne siden og forlot nettstedet med en gang.',
+ 'General_ColumnEntrances' => 'Innganger',
+ 'General_EntrancesDefinition' => 'Antall besøk som startet på denne siden.',
+ 'General_ColumnExits' => 'Utganger',
+ 'General_ExitsDefinition' => 'Antall besøk som sluttet på denne siden.',
+ 'General_ColumnAverageTimeOnPage' => 'Gj. tid på side',
+ 'General_AverageTimeOnPageDefinition' => 'Den gjennomsnittlige tiden besøkende tilbringer på denne siden.',
+ 'General_DaysHours' => '%1$s dager %2$s timer',
+ 'General_HoursMinutes' => '%1$s timer %2$s min',
+ 'General_MinutesSeconds' => '%1$s min %2$ss',
+ 'General_Seconds' => '%ss',
+ 'General_DisplayGoals' => 'Vis mål',
+ 'General_ConfigFileIsNotWritable' => '',
+ 'Actions_SubmenuPagesEntry' => 'Innganssider',
+ 'Actions_SubmenuPagesExit' => 'Utgangssider',
+ 'CoreAdminHome_Administration' => 'Administrasjon',
+ 'CoreHome_WebAnalyticsReports' => 'Nettstatistikkrapporter',
+ 'Goals_Goals' => 'Mål',
+ 'Goals_Overview' => 'Oversikt',
+ 'Goals_PluginDescription' => '',
+ 'Goals_OverallRevenue' => '',
+ 'Goals_OverallConversionRate' => '',
+ 'Goals_Conversions' => '',
+ 'Goals_ConversionRate' => '',
+ 'Goals_NoGoalsNeedAccess' => '',
+ 'Goals_AddNewGoal' => 'Legg til et nytt mål',
+ 'Goals_AddNewGoalOrEditExistingGoal' => '',
+ 'Goals_AddGoal_js' => 'Legg til mål',
+ 'Goals_UpdateGoal_js' => 'Oppdater mål',
+ 'Goals_DeleteGoalConfirm_js' => '',
+ 'Goals_GoalName' => 'Målnavn',
+ 'Goals_GoalIsTriggered' => '',
+ 'Goals_GoalIsTriggeredWhen' => '',
+ 'Goals_WhenVisitors' => '',
+ 'Goals_WhereThe' => '',
+ 'Goals_Manually' => '',
+ 'Goals_ManuallyTriggeredUsingJavascriptFunction' => '',
+ 'Goals_VisitUrl' => '',
+ 'Goals_Download' => 'Last ned en fil',
+ 'Goals_ClickOutlink' => '',
+ 'Goals_Optional' => '',
+ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => '',
+ 'Goals_DefaultRevenue' => '',
+ 'Goals_DefaultRevenueHelp' => '',
+ 'Goals_ConversionsOverview' => '',
+ 'Goals_BestCountries' => '',
+ 'Goals_BestKeywords' => '',
+ 'Goals_BestReferers' => '',
+ 'Goals_ReturningVisitorsConversionRateIs' => '',
+ 'Goals_NewVisitorsConversionRateIs' => '',
+ 'Goals_Contains' => '',
+ 'Goals_IsExactly' => '',
+ 'Goals_MatchesExpression' => '',
+ 'Goals_CaseSensitive' => '',
+ 'Goals_Pattern' => 'Mønster',
+ 'Live_Last30Minutes' => 'Siste 30 minutter',
+ 'MultiSites_PluginDescription' => '',
+ 'MultiSites_Evolution' => 'Utvikling',
+ 'SitesManager_Save_js' => 'Lagre',
+ 'SitesManager_Cancel_js' => 'Avbryt',
+ 'UsersManager_YourVisitsAreIgnoredOnDomain' => '%sDine besøk blir ignorert av Piwik%s (informasjonskapselen for ekskludering fra Piwik ble funnet i din nettleser).',
+ 'UsersManager_ClickHereToSetTheCookieOnDomain' => 'Klikk her for å sette en informasjonskapsel som vil ekskludere dine besøk på nettsteder som spores av Piwik på %s',
+ 'VisitorInterest_PluginDescription' => '',
+ 'VisitorInterest_Engagement' => 'Engasjement',
); \ No newline at end of file
diff --git a/lang/nl.php b/lang/nl.php
index 5d8f32ef9f..8bc6f9a8c8 100644
--- a/lang/nl.php
+++ b/lang/nl.php
@@ -1,15 +1,12 @@
<?php
-
-setlocale(LC_TIME, 'nl_NL.UTF-8');
-
$translations = array(
'General_Locale' => 'nl_NL.UTF-8',
- 'General_TranslatorName' => 'Martijn van Laar',
- 'General_TranslatorEmail' => 'martijn@mvanlaar.net',
+ 'General_TranslatorName' => 'Martijn van Laar, Hannes Bossuyt',
+ 'General_TranslatorEmail' => 'martijn@mvanlaar.net, hannes@randomize.be',
'General_EnglishLanguageName' => 'Dutch',
'General_OriginalLanguageName' => 'Nederlands',
'General_Unknown' => 'Onbekend',
- 'General_Required' => 'verplicht',
+ 'General_Required' => '%s vereist',
'General_Error' => 'fout',
'General_Warning' => 'let op',
'General_BackToHomepage' => 'Terug naar de Piwik homepage',
@@ -57,12 +54,92 @@ $translations = array(
'General_DisplayNormalTable' => 'Geef een normale tabel weer',
'General_DisplayMoreData' => 'Geef meer data weer',
'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Je kijkt op dit moment naar een demo van %s; %sdownload%s de volledige versie! Kijk naar %s',
- 'API_QuickDocumentation' => '<h2>API beknopte documentatie</h2><p>Wanneer u geen data voor vandaag heeft, kunt u eerst <a href=\'misc/generateVisits.php\' target=_blank>wat data genereren</a> door middel van het Bezoek Generator script.</p><p>U kunt voor elke methode een ander formaat proberen. Het is heel eenvoudig data uit piwik te halen!</p><p><b>Voor meer informatie bekijk de <a href=\'http://dev.piwik.org/trac/wiki/API\'>officiele API Documentatie</a> of de <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API Reference</a>.</b></P><h2>Gebruiker herkenning</h2><p>Wanneer u <b>de data van uw scripts opvraagt middels een crontab, etc. </b> u dient de volgende parameter <code><u>&token_auth=%s</u></code> toe te voegen aan de API oproep URLs die identificatie vereisen.</p><p>Deze token_auth is zo persoonlijk als uw login en password, <b>deel deze informatie niet met anderen!</p>',
- 'API_LoadedAPIs' => 'Succesvol %s APIs geladen',
+ 'General_Loading' => 'Laden...',
+ 'General_ExportAsImage' => 'Exporteer als afbeelding',
+ 'General_SaveImageOnYourComputer' => 'Om de afbeelding op te slaan op uw computer, klik rechts op de afbeelding en selecteer "Sla afbeelding op als..."',
+ 'General_ColumnNbActions' => 'Acties',
+ 'General_ColumnMaxActions' => 'Maximaal aantal acties per bezoek.',
+ 'General_ColumnSumVisitLength' => 'Totale tijd gespendeerd door de bezoekers (in seconden)',
+ 'General_ColumnValuePerVisit' => 'Waarde per bezoek',
+ 'General_ColumnVisitsWithConversions' => 'Bezoekers met conversies',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s is een samenwerkings project. %s Als je Piwik handig vindt, dan kun je helpen! Zoek uit %s Hoe je kan meehelpen aan Piwik.%s',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %s is beschikbaar. %s Gelieve nu te updaten! %s \'zie %s wijzigingen%s)',
+ 'General_BackToPiwik' => 'Terug naar Piwik',
+ 'General_ShortMonth_1' => 'Jan',
+ 'General_ShortMonth_2' => 'Feb',
+ 'General_ShortMonth_3' => 'Mrt',
+ 'General_ShortMonth_4' => 'Apr',
+ 'General_ShortMonth_5' => 'Mei',
+ 'General_ShortMonth_6' => 'Jun',
+ 'General_ShortMonth_7' => 'Jul',
+ 'General_ShortMonth_8' => 'Aug',
+ 'General_ShortMonth_9' => 'Sep',
+ 'General_ShortMonth_10' => 'Okt',
+ 'General_ShortMonth_11' => 'Nov',
+ 'General_ShortMonth_12' => 'Dec',
+ 'General_LongMonth_1' => 'Januari',
+ 'General_LongMonth_2' => 'Februari',
+ 'General_LongMonth_3' => 'Maart',
+ 'General_LongMonth_4' => 'April',
+ 'General_LongMonth_5' => 'Mei',
+ 'General_LongMonth_6' => 'Juni',
+ 'General_LongMonth_7' => 'Juli',
+ 'General_LongMonth_8' => 'Augustus',
+ 'General_LongMonth_9' => 'September',
+ 'General_LongMonth_10' => 'Oktober',
+ 'General_LongMonth_11' => 'November',
+ 'General_LongMonth_12' => 'December',
+ 'General_ShortDay_1' => 'Ma',
+ 'General_ShortDay_2' => 'Di',
+ 'General_ShortDay_3' => 'Wo',
+ 'General_ShortDay_4' => 'Do',
+ 'General_ShortDay_5' => 'Vr',
+ 'General_ShortDay_6' => 'Za',
+ 'General_ShortDay_7' => 'Zo',
+ 'General_LongDay_1' => 'Maandag',
+ 'General_LongDay_2' => 'Dinsdag',
+ 'General_LongDay_3' => 'Woensdag',
+ 'General_LongDay_4' => 'Donderdag',
+ 'General_LongDay_5' => 'Vrijdag',
+ 'General_LongDay_6' => 'Zaterdag',
+ 'General_LongDay_7' => 'Zondag',
+ 'General_Dashboard' => 'Dashboard',
+ 'General_MultiSitesSummary' => 'Alle Websites',
+ 'General_ExportAsImage_js' => 'Exporteer als afbeelding',
+ 'General_SaveImageOnYourComputer_js' => 'Om deze afbeelding te bewaren op je computer, rechtsklik op de afbeelding en kies "Afbeelding opslaan als..."',
+ 'General_RequiresFlash' => 'Flash is vereist om grafieken weer te geven in Piwik',
+ 'General_GraphHelp' => 'Meer informatie over grafieken weergeven in Piwik.',
+ 'General_ExceptionDatabaseVersion' => 'Je %s versie is %s maar Piwik vereist ten minste %s.',
+ 'General_Details' => 'Details',
+ 'General_ForExampleShort' => 'bijv.',
+ 'General_ExceptionIncompatibleClientServerVersions' => 'Je %1$s cliënt versie is %2$s maar is niet compatibel met server versie %3$s',
+ 'General_ExceptionMissingFile' => 'Bestand niet gevonden: %s',
+ 'General_ExceptionFilesizeMismatch' => 'Bestandsgrootte klopt niet: %1$s (verwachte grootte: %2$s, gevonden: %3$s)',
+ 'General_ExceptionFileIntegrity' => 'Integriteit test mislukt: %s ',
+ 'General_ExceptionNonceMismatch' => 'Kan het security token in dit formulier niet verifiëren.',
+ 'General_WarningFileIntegritySkipped' => 'Ontwikkel omgeving gedetecteerd. Bestand integriteit controle overgeslagen',
+ 'General_WarningFileIntegrityNoManifest' => 'Bestand integriteit controle kon niet worden uitgevoerd vanwege ontbrekend manifest.inc.php',
+ 'General_WarningFileIntegrityNoMd5file' => 'Bestand integriteit controle kon niet worden voltooid vanwege ontbrekende md5_file() functie.',
+ 'General_FileIntegrityWarningExplanation' => 'Bestand integriteit controle mislukt en er zijn fouten ontdekt. Dit komt waarschijnlijk door een gedeeltelijke of mislukte upload van enkele Piwik bestanden. We raden u aan alle Piwik bestanden opnieuw te uploaden en deze pagina te vernieuwen tot er geen fouten meer weergegeven worden.',
'Actions_Actions' => 'Acties',
'Actions_SubmenuPages' => 'Pagina\'s',
'Actions_SubmenuOutlinks' => 'Externe links',
'Actions_SubmenuDownloads' => 'Downloads',
+ 'Actions_PluginDescription' => 'Raporteert over de pagina weergaves, uitgaande links en downloads. Dit wordt automatisch bijgehouden. ',
+ 'Actions_SubmenuPageTitles' => 'Pagina titels',
+ 'Actions_ColumnClicks' => 'Kliks',
+ 'Actions_ColumnUniqueClicks' => 'Unieke kliks',
+ 'Actions_ColumnDownloads' => 'Downloads',
+ 'Actions_ColumnUniqueDownloads' => 'Unieke downloads',
+ 'Actions_ColumnPageName' => 'Pagina naam',
+ 'Actions_ColumnPageURL' => 'Pagina URL',
+ 'Actions_ColumnClickedURL' => 'Aangeklikte URL',
+ 'Actions_ColumnDownloadURL' => 'Download link',
+ 'API_QuickDocumentation' => '<h2>API beknopte documentatie</h2><p>Wanneer u geen data voor vandaag heeft, kunt u eerst <a href=\'misc/generateVisits.php\' target=_blank>wat data genereren</a> door middel van het Bezoek Generator script.</p><p>U kunt voor elke methode een ander formaat proberen. Het is heel eenvoudig data uit piwik te halen!</p><p><b>Voor meer informatie bekijk de <a href=\'http://dev.piwik.org/trac/wiki/API\'>officiele API Documentatie</a> of de <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API Reference</a>.</b></P><h2>Gebruiker herkenning</h2><p>Wanneer u <b>de data van uw scripts opvraagt middels een crontab, etc. </b> u dient de volgende parameter <code><u>&token_auth=%s</u></code> toe te voegen aan de API oproep URLs die identificatie vereisen.</p><p>Deze token_auth is zo persoonlijk als uw login en password, <b>deel deze informatie niet met anderen!</p>',
+ 'API_LoadedAPIs' => 'Succesvol %s APIs geladen',
+ 'API_PluginDescription' => 'Alle data in Piwik is beschikbaar via simpele Apis. Deze plugin is de web service beginpunt, dat je kunt aanroepen om je Web Analytics data te ontvangen in xml, json, php, csv, enz.',
+ 'ExampleAPI_PluginDescription' => 'Voorbeeld Plugin: Hoe maak je een API voor jouw plugin, om data te exporteren in verschillende formaten, zonder extra programmeerwerk?',
+ 'CoreAdminHome_PluginDescription' => 'Administratie gedeelte van Piwik',
'CoreHome_NoPrivileges' => 'U bent ingelogd als \'%s\' maar het lijkt er op dat u niet voldoende rechten bezit Piwik te gebruiken.<br />Vraag uw Piwik administrator om \'kijkers rechten\' voor een website.',
'CoreHome_JavascriptDisabled' => 'JavaScript moet geactiveerd zijn om Piwik in de standaard modus te gebruiken.<br />Het lijkt er op dat JavaScript of uitgeschakeld is of niet ondersteund wordt door uw browser.<br />Om de standaard modus te gebruiken, activeer JavaScript in uw browser instellingen, probeer het daarna %1snogmaals%2s.<br />',
'CoreHome_TableNoData' => 'Geen data voor deze tabel gevonden.',
@@ -82,7 +159,7 @@ $translations = array(
'CoreHome_DayTu_js' => 'Di',
'CoreHome_DayWe_js' => 'Wo',
'CoreHome_DayTh_js' => 'Do',
- 'CoreHome_DayFr_js' => 'Vry',
+ 'CoreHome_DayFr_js' => 'Vr',
'CoreHome_DaySa_js' => 'Za',
'CoreHome_MonthJanuary_js' => 'januari',
'CoreHome_MonthFebruary_js' => 'februari',
@@ -90,12 +167,44 @@ $translations = array(
'CoreHome_MonthApril_js' => 'april',
'CoreHome_MonthMay_js' => 'mei',
'CoreHome_MonthJune_js' => 'juni',
- 'CoreHome_MonthJuly_js' => 'july',
+ 'CoreHome_MonthJuly_js' => 'juli',
'CoreHome_MonthAugust_js' => 'augustus',
'CoreHome_MonthSeptember_js' => 'september',
'CoreHome_MonthOctober_js' => 'oktober',
'CoreHome_MonthNovember_js' => 'november',
'CoreHome_MonthDecember_js' => 'december',
+ 'CoreHome_PluginDescription' => 'Web Analyze rapporteer structuur ',
+ 'CoreHome_DayFormat' => '',
+ 'CoreHome_PeriodDays' => 'dagen',
+ 'CoreHome_PeriodWeeks' => 'weken',
+ 'CoreHome_PeriodMonths' => 'maanden',
+ 'CoreHome_PeriodYears' => 'jaren',
+ 'CoreHome_ShortDay_1_js' => 'Zon',
+ 'CoreHome_ShortDay_2_js' => 'Maan',
+ 'CoreHome_ShortDay_3_js' => 'Din',
+ 'CoreHome_ShortDay_4_js' => 'Woe',
+ 'CoreHome_ShortDay_5_js' => 'Don',
+ 'CoreHome_ShortDay_6_js' => 'Vrij',
+ 'CoreHome_ShortDay_7_js' => 'Zat',
+ 'CoreHome_LongDay_1_js' => 'Zondag',
+ 'CoreHome_LongDay_2_js' => 'Maandag',
+ 'CoreHome_LongDay_3_js' => 'Dinsdag',
+ 'CoreHome_LongDay_4_js' => 'Woensdag',
+ 'CoreHome_LongDay_5_js' => 'Donderdag',
+ 'CoreHome_LongDay_6_js' => 'Vrijdag',
+ 'CoreHome_LongDay_7_js' => 'Zaterdag',
+ 'CoreHome_ShortMonth_1_js' => 'Jan',
+ 'CoreHome_ShortMonth_2_js' => 'Feb',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Apr',
+ 'CoreHome_ShortMonth_5_js' => 'Mei',
+ 'CoreHome_ShortMonth_6_js' => 'Jun',
+ 'CoreHome_ShortMonth_7_js' => 'Jul',
+ 'CoreHome_ShortMonth_8_js' => 'Aug',
+ 'CoreHome_ShortMonth_9_js' => 'Sep',
+ 'CoreHome_ShortMonth_10_js' => 'Okt',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dec',
'CorePluginsAdmin_Plugins' => 'Plugins',
'CorePluginsAdmin_PluginsManagement' => 'Plugin manager',
'CorePluginsAdmin_MainDescription' => 'Met plugins breidt u de functionaliteit van piwik uit. Wanneer een plugin ge&iuml;nstalleerd is, kan deze hier aan- en uitgeschakeld worden.',
@@ -112,6 +221,7 @@ $translations = array(
'CorePluginsAdmin_Deactivate' => 'Uitschakelen',
'CorePluginsAdmin_Activate' => 'Inschakelen',
'CorePluginsAdmin_MenuPlugins' => 'Plugins',
+ 'CorePluginsAdmin_PluginDescription' => 'Plugin admin interface',
'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; Update',
'CoreUpdater_UpdateRequired' => 'Upgrade vereist',
'CoreUpdater_YourDatabaseIsOutOfDate' => 'Uw Piwik database is niet up to date en zal ge-upgrade moeten worden om verder te kunnen gaan.',
@@ -129,13 +239,37 @@ $translations = array(
'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'We hebben de volgende plugins ge-deactiveerd',
'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik upgrade was succesvol!',
'CoreUpdater_ContinueToPiwik' => 'Ga verder naar Piwik',
- 'DBStats_DatabaseUsage' => 'Database gebruik',
- 'DBStats_MainDescription' => 'Piwik slaat alle analyse data op in een MySQL database. Momenteel is de omvang van deze database %s.',
- 'DBStats_Table' => 'Tabel',
- 'DBStats_RowNumber' => 'Rij nummer',
- 'DBStats_DataSize' => 'Data omvang',
- 'DBStats_IndexSize' => 'Index grootte',
- 'DBStats_TotalSize' => 'Totale grootte',
+ 'CoreUpdater_PluginDescription' => 'Piwik updating mechanisme',
+ 'CoreUpdater_DatabaseUpgradeRequired' => 'Database upgrade vereist',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik Database zal geüpgraded worden van versie %1$s naar de nieuwe versie %2$s ',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Belangrijke mededeling voor grote Piwik installaties',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'Als je een grote Piwik database hebt, kunnen de updates te lang duren om in de browser te worden uitgevoerd. In dat geval, kun je de updates uitvoeren vanaf de opdrachtprompt: %s',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => 'Als je de opdrachtprompt updater niet kan gebruiken en piwik kan niet upgraden (vanwege een timeout van de database, een browser timeout of een ander probleem), dan kun je de SQL queries manueel uitvoeren om Piwik te updaten.',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => 'Klik hier voor een lijst van de SQL query\'s dat zullen worden uitgevoerd.',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => 'Opmerking: Als je deze query\'s manueel uitvoert, sommige zullen niet kunnen worden uitgevoerd. In dat geval kun je de fouten negeren en de volgende in de lijst uitvoeren. ',
+ 'CoreUpdater_ReadyToGo' => 'Klaar om te starten?',
+ 'CoreUpdater_ErrorDIYHelp' => 'Als je een geavanceerd gebruiker bent en een probleem optreed in de database upgrade:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'Zoek en corrigeer de bron van het probleem (bijv. memory_limit of max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'Voer de overige query\'s uit in de niet voltooide update.',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'Update manueel de \'option\' tabel in uw Piwik database, en zet de waarde version_core naar de versie van de mislukte update',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'Voer de updater opnieuw uit (via de browser of de opdrachtpromt) om verder te gaan met de overige updates.',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'Meld het probleem (en oplossing) zo dat Piwik kan worden verbeterd.',
+ 'CoreUpdater_UpdateAutomatically' => 'Update automatisch.',
+ 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Er is een nieuwe versie van Piwik beschikbaar als update',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'U kunt automatisch updaten naar versie %s of het pakket downloaden en manueel installeren.',
+ 'CoreUpdater_DownloadX' => 'Download %s',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Piwik One Click Update is geannuleerd. Als je het bovenstaande foutbericht niet kan oplossen, is het aanbevolen dat je Piwik manueel update. %1$s Gelieve de update documentatie te lezen om te starten! ',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Bezig met downloaden van de update van %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Bezig met het uitpakken van de update',
+ 'CoreUpdater_VerifyingUnpackedFiles' => 'Bezig met verifiëren van de uitgepakte bestanden',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Bezig met het maken van een backup van het configuratie bestand in %s',
+ 'CoreUpdater_InstallingTheLatestVersion' => 'Bezig met de laatste versie te installeren',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik is succesvol geüpdatet! ',
+ 'CoreUpdater_EmptyDatabaseError' => 'Database %s is leeg. U moet uw Piwik configuratiebestand bewerken of verwijderen.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Uw Piwik versie %s is up to date',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Incompatibel archief: %s ',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Leeg archief.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Archief is onvolledig. Sommige bestanden ontbreken (zoals %s)',
'Dashboard_Dashboard' => 'Dashboard',
'Dashboard_AddWidget' => 'Voeg een widget toe...',
'Dashboard_DeleteWidgetConfirm' => 'Weet u zeker dat u deze widget van het dashboard wilt verwijderen?',
@@ -147,268 +281,92 @@ $translations = array(
'Dashboard_LoadingPreview_js' => 'Bezig voorvertoning te laden, even geduld a.u.b...',
'Dashboard_LoadingWidget_js' => 'Bezig widget te laden, even geduld a.u.b...',
'Dashboard_WidgetNotFound_js' => 'Widget niet gevonden',
- 'GeoIP_Country' => 'Land',
- 'GeoIP_Continent' => 'Continent',
- 'GeoIP_DistinctCountries' => '%s unieke landen',
- 'GeoIP_SubmenuLocations' => 'Locaties',
- 'GeoIP_WidgetContinents' => 'Bezoeker continenten',
- 'GeoIP_WidgetCountries' => 'Bezoeker landen',
- 'GeoIP_country_' => 'Data niet beschikbaar',
- 'GeoIP_country_ac' => 'Ascension eilanden',
- 'GeoIP_country_ad' => 'Andorra',
- 'GeoIP_country_ae' => 'Verenigde Emiraten',
- 'GeoIP_country_af' => 'Afghanistan',
- 'GeoIP_country_ag' => 'Antigua en Brabuda',
- 'GeoIP_country_ai' => 'Anguilla',
- 'GeoIP_country_al' => 'Albani&euml;',
- 'GeoIP_country_am' => 'Armeni&euml;',
- 'GeoIP_country_an' => 'Nederlandse Antillen',
- 'GeoIP_country_ao' => 'Angola',
- 'GeoIP_country_aq' => 'Antartica',
- 'GeoIP_country_ar' => 'Argentini&euml;',
- 'GeoIP_country_as' => 'Samoa',
- 'GeoIP_country_at' => 'Oostenrijk',
- 'GeoIP_country_au' => 'Australi&euml;',
- 'GeoIP_country_aw' => 'Aruba',
- 'GeoIP_country_az' => 'Azerbeijan',
- 'GeoIP_country_ba' => 'Bosni&euml; en Herzegovina',
- 'GeoIP_country_bb' => 'Barbados',
- 'GeoIP_country_bd' => 'Bangladesh',
- 'GeoIP_country_be' => 'Belgi&euml;',
- 'GeoIP_country_bf' => 'Burkina Faso',
- 'GeoIP_country_bg' => 'Bulgari&euml;',
- 'GeoIP_country_bh' => 'Bahrain',
- 'GeoIP_country_bi' => 'Burundi',
- 'GeoIP_country_bj' => 'Benin',
- 'GeoIP_country_bm' => 'Bermuda',
- 'GeoIP_country_bn' => 'Bruneo',
- 'GeoIP_country_bo' => 'Bolivi&euml;',
- 'GeoIP_country_br' => 'Barzili&euml;',
- 'GeoIP_country_bs' => 'Bahamas',
- 'GeoIP_country_bt' => 'Bhutan',
- 'GeoIP_country_bv' => 'Bouvet eiland',
- 'GeoIP_country_bw' => 'Botswana',
- 'GeoIP_country_by' => 'Belarus',
- 'GeoIP_country_bz' => 'Blize',
- 'GeoIP_country_ca' => 'Canada',
- 'GeoIP_country_cc' => 'Cocos eilanden',
- 'GeoIP_country_cd' => 'Congo',
- 'GeoIP_country_cf' => 'Centraal Afrika',
- 'GeoIP_country_cg' => 'Congo',
- 'GeoIP_country_ch' => 'Zwitserland',
- 'GeoIP_country_ci' => 'Ivoorkust',
- 'GeoIP_country_ck' => 'Cook eilanden',
- 'GeoIP_country_cl' => 'Chili',
- 'GeoIP_country_cm' => 'Kameroen',
- 'GeoIP_country_cn' => 'China',
- 'GeoIP_country_co' => 'Colombia',
- 'GeoIP_country_cr' => 'Costa Rica',
- 'GeoIP_country_cs' => 'Montenegro',
- 'GeoIP_country_cu' => 'Cuba',
- 'GeoIP_country_cv' => 'Kaap de goed hoop',
- 'GeoIP_country_cx' => 'Paaseilanden',
- 'GeoIP_country_cy' => 'Cyprus',
- 'GeoIP_country_cz' => 'Tsjechi&euml;',
- 'GeoIP_country_de' => 'Duitsland',
- 'GeoIP_country_dj' => 'Djibouti',
- 'GeoIP_country_dk' => 'Denemarken',
- 'GeoIP_country_dm' => 'Dominica',
- 'GeoIP_country_do' => 'Dominicaanse republiek',
- 'GeoIP_country_dz' => 'Algerij&euml;',
- 'GeoIP_country_ec' => 'Ecuador',
- 'GeoIP_country_ee' => 'Estonia',
- 'GeoIP_country_eg' => 'Egypte',
- 'GeoIP_country_eh' => 'West Sahara',
- 'GeoIP_country_er' => 'Eritrea',
- 'GeoIP_country_es' => 'Spanje',
- 'GeoIP_country_et' => 'Ethiopi&euml;',
- 'GeoIP_country_fi' => 'Finland',
- 'GeoIP_country_fj' => 'Fiji',
- 'GeoIP_country_fk' => 'Falkland Eilanden',
- 'GeoIP_country_fm' => 'Micronesia',
- 'GeoIP_country_fo' => 'Farao Eilanden',
- 'GeoIP_country_fr' => 'Frankrijk',
- 'GeoIP_country_ga' => 'Gabon',
- 'GeoIP_country_gd' => 'Grenada',
- 'GeoIP_country_ge' => 'Georgi&euml;',
- 'GeoIP_country_gf' => 'Frans Guinea',
- 'GeoIP_country_gg' => 'Guernsey',
- 'GeoIP_country_gh' => 'Ghana',
- 'GeoIP_country_gi' => 'Gibraltar',
- 'GeoIP_country_gl' => 'Groenland',
- 'GeoIP_country_gm' => 'Gambia',
- 'GeoIP_country_gn' => 'Guinea',
- 'GeoIP_country_gp' => 'Guadeloupe',
- 'GeoIP_country_gq' => 'Equatoriaal Guinea',
- 'GeoIP_country_gr' => 'Griekenland',
- 'GeoIP_country_gs' => 'Zuid Georgi&euml; ',
- 'GeoIP_country_gt' => 'Guatemala',
- 'GeoIP_country_gu' => 'Guam',
- 'GeoIP_country_gw' => 'Guinea-Bissau',
- 'GeoIP_country_gy' => 'Guyana',
- 'GeoIP_country_hk' => 'Hong Kong',
- 'GeoIP_country_hm' => 'Heard eiland en McDonald eilanden',
- 'GeoIP_country_hn' => 'Honduras',
- 'GeoIP_country_hr' => 'Kroati&euml;',
- 'GeoIP_country_ht' => 'Haiti',
- 'GeoIP_country_hu' => 'Hongarij&euml;',
- 'GeoIP_country_id' => 'Indonesi&euml;',
- 'GeoIP_country_ie' => 'Ierland',
- 'GeoIP_country_il' => 'Isra&euml;l',
- 'GeoIP_country_im' => 'Man eiland',
- 'GeoIP_country_in' => 'India',
- 'GeoIP_country_io' => 'Brits Indisch territoriale wateren',
- 'GeoIP_country_iq' => 'Irak',
- 'GeoIP_country_ir' => 'Iran',
- 'GeoIP_country_is' => 'IJsland',
- 'GeoIP_country_it' => 'Itali&euml;',
- 'GeoIP_country_je' => 'Jersey',
- 'GeoIP_country_jm' => 'Jamaica',
- 'GeoIP_country_jo' => 'Jordaan',
- 'GeoIP_country_jp' => 'Japan',
- 'GeoIP_country_ke' => 'Kenia',
- 'GeoIP_country_kg' => 'Kyrgyzstan',
- 'GeoIP_country_kh' => 'Cambodja',
- 'GeoIP_country_ki' => 'Kiribati',
- 'GeoIP_country_km' => 'Comoros',
- 'GeoIP_country_kn' => 'Sint Kitts en Nevis',
- 'GeoIP_country_kp' => 'Noord Korea',
- 'GeoIP_country_kr' => 'Zuid Korea',
- 'GeoIP_country_kw' => 'Koeweit',
- 'GeoIP_country_ky' => 'Kaaiman eilanden',
- 'GeoIP_country_kz' => 'Kazachstan',
- 'GeoIP_country_la' => 'Laos',
- 'GeoIP_country_lb' => 'Libanon',
- 'GeoIP_country_lc' => 'Sint Lucia',
- 'GeoIP_country_li' => 'Liechtenstein',
- 'GeoIP_country_lk' => 'Sri Lanka',
- 'GeoIP_country_lr' => 'Libi&euml;',
- 'GeoIP_country_ls' => 'Lesbos',
- 'GeoIP_country_lt' => 'Litouwen',
- 'GeoIP_country_lu' => 'Luxemburg',
- 'GeoIP_country_lv' => 'Letland',
- 'GeoIP_country_ly' => 'Libi&euml;',
- 'GeoIP_country_ma' => 'Marokko',
- 'GeoIP_country_mc' => 'Monaco',
- 'GeoIP_country_md' => 'Moldavi&euml;',
- 'GeoIP_country_mg' => 'Madagaskar',
- 'GeoIP_country_mh' => '',
- 'GeoIP_country_mk' => 'Macedoni&euml;',
- 'GeoIP_country_ml' => 'Mali',
- 'GeoIP_country_mm' => 'Myanmar',
- 'GeoIP_country_mn' => 'Mongoli&euml;',
- 'GeoIP_country_mo' => 'Macau',
- 'GeoIP_country_mp' => 'Noordelijk Marina eilanden',
- 'GeoIP_country_mq' => 'Martinique',
- 'GeoIP_country_mr' => 'Mauritania',
- 'GeoIP_country_ms' => 'Montserrat',
- 'GeoIP_country_mt' => 'Malta',
- 'GeoIP_country_mu' => 'Mauristius',
- 'GeoIP_country_mv' => 'Malledieven',
- 'GeoIP_country_mw' => 'Malawi',
- 'GeoIP_country_mx' => 'Mexico',
- 'GeoIP_country_my' => 'Maleisi&euml;',
- 'GeoIP_country_mz' => 'Mozambique',
- 'GeoIP_country_na' => 'Namibi&euml;',
- 'GeoIP_country_nc' => 'Nieuw Caledonia',
- 'GeoIP_country_ne' => 'Niger',
- 'GeoIP_country_nf' => 'Norfolk eiland',
- 'GeoIP_country_ng' => 'Nigeria',
- 'GeoIP_country_ni' => 'Nicaragua',
- 'GeoIP_country_nl' => 'Nederland',
- 'GeoIP_country_no' => 'Noorwegen',
- 'GeoIP_country_np' => 'Nepal',
- 'GeoIP_country_nr' => 'Nauru',
- 'GeoIP_country_nu' => 'Niue',
- 'GeoIP_country_nz' => 'Nieuw Zeeland',
- 'GeoIP_country_om' => 'Oman',
- 'GeoIP_country_pa' => 'Panama',
- 'GeoIP_country_pe' => 'Peru',
- 'GeoIP_country_pf' => 'Frans Polynesi&euml;',
- 'GeoIP_country_pg' => 'Papua Nieuw Guinea',
- 'GeoIP_country_ph' => 'Filipijnen',
- 'GeoIP_country_pk' => 'Pakistan',
- 'GeoIP_country_pl' => 'Polen',
- 'GeoIP_country_pm' => 'Sint Petersburg',
- 'GeoIP_country_pn' => 'Pitcairn',
- 'GeoIP_country_pr' => 'Puerto Rico',
- 'GeoIP_country_ps' => 'Palestijnen',
- 'GeoIP_country_pt' => 'Portugal',
- 'GeoIP_country_pw' => 'Palau',
- 'GeoIP_country_py' => 'Paraguay',
- 'GeoIP_country_qa' => 'Qatar',
- 'GeoIP_country_re' => 'Reunie eiland',
- 'GeoIP_country_ro' => 'Roemeni&euml;',
- 'GeoIP_country_ru' => 'Rusland',
- 'GeoIP_country_rs' => 'Rusland',
- 'GeoIP_country_rw' => 'Rwanda',
- 'GeoIP_country_sa' => 'Saudi Arabi&euml;',
- 'GeoIP_country_sb' => 'Solomon Eilanden',
- 'GeoIP_country_sc' => 'Seychelles',
- 'GeoIP_country_sd' => 'Sudan',
- 'GeoIP_country_se' => 'Zweden',
- 'GeoIP_country_sg' => 'Singapore',
- 'GeoIP_country_sh' => 'Sint Helena',
- 'GeoIP_country_si' => 'Sloveni&euml;',
- 'GeoIP_country_sj' => 'Svalbard',
- 'GeoIP_country_sk' => 'Slovaki&euml;',
- 'GeoIP_country_sl' => 'Sierra Leone',
- 'GeoIP_country_sm' => 'San Marino',
- 'GeoIP_country_sn' => 'Senegal',
- 'GeoIP_country_so' => 'Somali&euml;',
- 'GeoIP_country_sr' => 'Suriname',
- 'GeoIP_country_st' => 'Sao Tome en Principe',
- 'GeoIP_country_su' => 'Voormalig rusland',
- 'GeoIP_country_sv' => 'El Salvador',
- 'GeoIP_country_sy' => 'Syrische republiek',
- 'GeoIP_country_sz' => 'Swaziland',
- 'GeoIP_country_tc' => 'Turkse en Caicos Eilanden',
- 'GeoIP_country_td' => 'Chad',
- 'GeoIP_country_tf' => 'Franse territorialen',
- 'GeoIP_country_tg' => 'Togo',
- 'GeoIP_country_th' => 'Thailand',
- 'GeoIP_country_tj' => 'Tsjikistan',
- 'GeoIP_country_tk' => 'Tokelau',
- 'GeoIP_country_tm' => 'Turkmenistan',
- 'GeoIP_country_tn' => 'Tunisi&euml;',
- 'GeoIP_country_to' => 'Tonga',
- 'GeoIP_country_tp' => 'Oost Timor',
- 'GeoIP_country_tr' => 'Turkije',
- 'GeoIP_country_tt' => 'Trinidad en Tobago',
- 'GeoIP_country_tv' => 'Tuvalu',
- 'GeoIP_country_tw' => 'Taiwan',
- 'GeoIP_country_tz' => 'Tanzani&euml;',
- 'GeoIP_country_ua' => 'Oekra&iuml;ne',
- 'GeoIP_country_ug' => 'Uganda',
- 'GeoIP_country_uk' => 'Verenigd Koningkrijk',
- 'GeoIP_country_gb' => 'Groot britanni&euml;',
- 'GeoIP_country_um' => 'Eilanden van de Verenigde Staten',
- 'GeoIP_country_us' => 'Verenigde Staten',
- 'GeoIP_country_uy' => 'Uruguay',
- 'GeoIP_country_uz' => 'Uzbekistan',
- 'GeoIP_country_va' => 'Vaticaanstad',
- 'GeoIP_country_vc' => 'Sint Vincent en de Grenadinen',
- 'GeoIP_country_ve' => 'Venezuela',
- 'GeoIP_country_vg' => 'Britse Maagden eilanden',
- 'GeoIP_country_vi' => 'Maagden eilanden',
- 'GeoIP_country_vn' => 'Vietnam',
- 'GeoIP_country_vu' => 'Vanuatu',
- 'GeoIP_country_wf' => 'Wallis en Futuna',
- 'GeoIP_country_ws' => 'Samoa',
- 'GeoIP_country_ye' => 'Jemen',
- 'GeoIP_country_yt' => 'Mayotte',
- 'GeoIP_country_yu' => 'Joegoslavi&euml;',
- 'GeoIP_country_za' => 'Zuid Afrika',
- 'GeoIP_country_zm' => 'Zambia',
- 'GeoIP_country_zr' => 'Zaire',
- 'GeoIP_country_zw' => 'Zimbabwe',
- 'GeoIP_continent_' => 'Data niet bechikbaar',
- 'GeoIP_continent_eur' => 'Europa',
- 'GeoIP_continent_afr' => 'Afrika',
- 'GeoIP_continent_asi' => 'Asi&euml;',
- 'GeoIP_continent_ams' => 'Zuid- en Centraal Amerika',
- 'GeoIP_continent_amn' => 'Noord Amerika',
- 'GeoIP_continent_oce' => 'Oceanie',
+ 'Dashboard_PluginDescription' => 'Uw Web analyze Dashboard. U kunt uw dashboard aanpassen: nieuwe widgets toevoegen of de volgorde aanpassen. Iedere gebruiker heeft toegang tot zijn eigen Dashboard',
+ 'Dashboard_AddPreviewedWidget_js' => 'Voeg widget toe aan dashboard.',
+ 'Dashboard_WidgetPreview_js' => 'Widget voorbeeld',
+ 'Dashboard_Close_js' => 'Sluiten',
+ 'DBStats_DatabaseUsage' => 'Database gebruik',
+ 'DBStats_MainDescription' => 'Piwik slaat alle analyse data op in een MySQL database. Momenteel is de omvang van deze database %s.',
+ 'DBStats_Table' => 'Tabel',
+ 'DBStats_RowNumber' => 'Rij nummer',
+ 'DBStats_DataSize' => 'Data omvang',
+ 'DBStats_IndexSize' => 'Index grootte',
+ 'DBStats_TotalSize' => 'Totale grootte',
+ 'DBStats_PluginDescription' => 'Deze plugin toont het MySQL database verbruik door de Piwik tabellen.',
+ 'DBStats_LearnMore' => 'Om meer te weten over hoe Piwik data verwerkt en hoe Piwik goed te laten werken voor middelgrote en grote website\'s, zie de documentatie %s.',
+ 'DBStats_RowCount' => 'Aantal rijen',
+ 'ExampleFeedburner_PluginDescription' => 'Voorbeeld plugin: Hoe je Feedburner subscribers weergeven in een Widget in het Dashboard?',
+ 'ExamplePlugin_PluginDescription' => 'Voorbeeld plugin: Deze plugin toont hoe een simpele plugin te maken, dat twee widgets exporteert in het Dashboard.',
+ 'ExamplePlugin_exampleWidgets' => 'Voorbeeld Widgets.',
+ 'ExamplePlugin_exampleWidget' => 'Voorbeeld Widget',
+ 'ExamplePlugin_blogPiwikRss' => 'Blog Piwik RSS',
+ 'ExamplePlugin_photostreamMatt' => 'Matt\'s foto\'s ',
+ 'ExampleRssWidget_PluginDescription' => 'Voorbeeld plugin: Hoe een nieuwe widget te maken dat een RSS feed leest?',
+ 'ExampleUI_PluginDescription' => 'Voorbeeld plugin: Deze plugin toont hoe tewerken met de Piwik UI: tabellen aanmaken, grafieken, enz...',
+ 'Feedback_PluginDescription' => 'Stuur uw feedback naar het Piwik team. Deel uw ideeën en suggesties met ons! ',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Heeft u een bug melding of een feature verzoek?',
+ 'Feedback_ViewAnswersToFAQ' => 'Bekijk de antwoorden op %s veelgestelde vragen.',
+ 'Feedback_WhyAreMyVisitsNoTracked' => 'Waarom worden bezoeken op mijn websites niet bijgehouden?',
+ 'Feedback_HowToExclude' => 'Hoe sluit ik bezoeken uit?',
+ 'Feedback_WhyWrongCountry' => 'Waarom toont Piwik mijn bezoek uit een ander land?',
+ 'Feedback_HowToAnonymizeIP' => 'Hoe verberg ik bezoekers ip adressen in mijn database?',
+ 'Feedback_VisitTheForums' => 'Bezoek de %s Forums %s',
+ 'Feedback_LearnWaysToParticipate' => 'Leer over alle mogelijkheden hoe je kan %shelpen.%s ',
+ 'Feedback_SpecialRequest' => 'Heeft u een speciaal verzoek voor het Piwik team?',
+ 'Feedback_ContactThePiwikTeam' => 'Contacteer het Piwik team!',
+ 'Feedback_IWantTo' => 'Ik wil:',
+ 'Feedback_CategoryShareStory' => 'Deel een Piwik succes verhaal:',
+ 'Feedback_CategorySponsor' => 'Sponsor Piwik:',
+ 'Feedback_CategoryHire' => 'Neem een Piwik consultant in dienst',
+ 'Feedback_CategorySecurity' => 'Meld een veiligheids probleem',
+ 'Feedback_MyEmailAddress' => 'Mijn email adres:',
+ 'Feedback_MyMessage' => 'Mijn bericht:',
+ 'Feedback_DetailsPlease' => '(gelieve details in te voegen)',
+ 'Feedback_SendFeedback' => 'Stuur Feedback',
+ 'Feedback_ManuallySendEmailTo' => 'Gelieve uw bericht manueel te zenden naar',
+ 'Feedback_MessageSent' => 'Uw bericht is verzonden naar het Piwik team.',
+ 'Feedback_ThankYou' => 'Bedankt om ons te helpen Piwik beter te maken!',
+ 'Feedback_ThePiwikTeam' => 'Het Piwik Team.',
+ 'Feedback_ExceptionBodyLength' => 'Het bericht moet tenminste %s tekens bevatten.',
+ 'Feedback_ExceptionNoUrls' => 'Het bericht mag geen URL bevatten, om spam berichten te vermijden',
+ 'Goals_PluginDescription' => 'Maak Doelstellingen aan en zie rapporten over uw doelstelling conversies: evaluatie met de tijd, inkomsten per bezoek, inkomsten per referer, per sleutelwoord, enz.',
+ 'Goals_ColumnConversions' => 'Conversies',
+ 'Goals_ColumnConversionRate' => 'Conversie omzet',
+ 'Goals_ColumnRevenue' => 'Inkomsten',
+ 'Goals_OverallRevenue' => '%s totale inkomsten',
+ 'Goals_OverallConversionRate' => '%s totaal inkomsten rate (bezoeken met een voltooide doelstelling)',
+ 'Goals_Conversions' => '%s conversies',
+ 'Goals_ConversionRate' => '',
+ 'Goals_NoGoalsNeedAccess' => 'Alleen een beheerder of Super gebruiker kan doelstellingen toevoegen voor een website. Gelieve je Piwik beheerder te vragen een doelstelling op te zetten voor je website. <br> Doelstellingen bijhouden is een goede manier om je website prestaties te begrijpen en maximaliseren!',
+ 'Goals_AddNewGoal' => 'Voeg een nieuwe doelstelling toe',
+ 'Goals_AddNewGoalOrEditExistingGoal' => '%sVoeg een nieuwe Doelstelling toe%s of %spas een bestaande doelstelling aan%s',
+ 'Goals_AddGoal_js' => 'Voeg doelstelling toe',
+ 'Goals_UpdateGoal_js' => 'Update doelstelling',
+ 'Goals_DeleteGoalConfirm_js' => 'Weet u zeker dat u deze doelstelling wil verwijderen %s? ',
+ 'Goals_GoalName' => 'Doelstelling naam',
+ 'Goals_GoalIsTriggered' => 'Doelstelling is geactiveerd',
+ 'Goals_GoalIsTriggeredWhen' => 'Doelstelling is geactiveerd wanneer',
+ 'Goals_WhenVisitors' => 'wanneer bezoekers',
+ 'Goals_Manually' => 'manueel',
+ 'Goals_ManuallyTriggeredUsingJavascriptFunction' => 'Doelstelling is manueel gactiveerd door de Javascript API trackGoal()',
+ 'Goals_VisitUrl' => 'Bezoek een gegeven url (pagina of groet van pagina\'s)',
+ 'Goals_Download' => 'Download een bestand',
+ 'Goals_ClickOutlink' => 'Klik op een link naar een xterne website',
+ 'Goals_Optional' => '(optioneel)',
+ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => 'Wanneer een bezochte pagina een oproep bevat naar de javascript piwikTracker.trackGoal() methode (%smeer info%s)',
+ 'Goals_DefaultRevenue' => 'Doelstelling standaard omzet is',
+ 'Goals_DefaultRevenueHelp' => 'Bijvoorbeeld, een Contact formulier dat is verzonden door een bezoeker kan gemiddeld 10$ waard zijn. Piwik zal je helpen begrijpen hoe goed je bezoekers gedeelten presteren.',
+ 'Goals_ConversionsOverview' => 'Omzet overzicht',
+ 'Goals_BestCountries' => 'Uw beste omzet landen zijn:',
+ 'Goals_BestKeywords' => 'Uw beste omzet sleutelwoorden zijn:',
+ 'Goals_BestReferers' => 'Uw beste omzet website\'s refers zijn:',
+ 'Goals_ReturningVisitorsConversionRateIs' => 'Terugkerende bezoekers omzet is %s',
+ 'Goals_NewVisitorsConversionRateIs' => 'Nieuwe bezoekers omzet is %s',
+ 'Goals_Contains' => 'bevat %s',
+ 'Goals_IsExactly' => 'is exact %s',
+ 'Goals_MatchesExpression' => 'Voldoet aan de expressie %s',
+ 'Goals_CaseSensitive' => 'is hoofdletter gevoelig',
+ 'Goals_Pattern' => 'patroon',
'Installation_Installation' => 'Installatie',
'Installation_InstallationStatus' => 'Installatie status',
'Installation_PercentDone' => '%s %% Gereed',
@@ -454,22 +412,108 @@ $translations = array(
'Installation_WelcomeHelp' => '<p>Piwik is een open source web analytics software pakket die u op simpele wijze de gegevens van uw bezoekers presenteert.</p><p>Dit proces is opgedeeld in %s simpele stappen welke ongeveer 5 minuten in beslag nemen.</p>',
'Installation_CongratulationsHelp' => '<p>Gefeliciteerd! Uw Piwik installatie is voltooid.</p><p>Controleer of de javascript code geplaatst is op uw paginas, en wacht op de eerste bezoekers!</p>',
'Installation_DatabaseCreatedSuccess' => 'Database %s successvol aangemaakt',
- 'Login_LoginPasswordNotCorrect' => 'Login & Password niet correct',
- 'Login_Login' => 'Login',
- 'Login_Password' => 'Password',
+ 'Installation_PluginDescription' => 'Installatie proces van Piwik. De installatie wordt meestal maar éénmaal uitgevoerd. Als het configuratie bestand config/config.inc.php is verwijderd, zal de installatie opnieuw beginnen.',
+ 'Installation_DatabaseSetup' => 'Database setup',
+ 'Installation_DatabaseSetupServer' => 'database server',
+ 'Installation_DatabaseSetupLogin' => 'login',
+ 'Installation_DatabaseSetupPassword' => 'wachtwoord',
+ 'Installation_DatabaseSetupDatabaseName' => 'database naam',
+ 'Installation_DatabaseSetupTablePrefix' => 'tabel voorvoegsel',
+ 'Installation_DatabaseSetupAdapter' => 'adapter',
+ 'Installation_DatabaseErrorConnect' => 'Fout opgetreden tijdens het verbinding maken met database server.',
+ 'Installation_DatabaseCheck' => 'Database controle.',
+ 'Installation_DatabaseServerVersion' => 'Database server versie',
+ 'Installation_DatabaseClientVersion' => 'Database cliënt versie',
+ 'Installation_DatabaseCreation' => 'Database creatie',
+ 'Installation_DatabaseClientCharset' => 'Database cliënt karakter set.',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'cliënt connectie naar de database server is standaard niet UTF8. Dit is not een kritiek probleem:<b>Piwik zal correct werken</b>. Maar voor de consistentie is het aanbevolen dat u één van de volgende stappen onderneemt: <ul style="list-style: disc;margin-left:10px"><li>in uw piwik config/config.ini.php, voeg <code>charset = utf8</code> onder de [database] sectie of uw Piwik configuratie bestand <code>config/config.ini.php</code> toe</li><li>hercompileer libmysql --with-charset=utf8</li></ul> ',
+ 'Installation_DatabaseTimezone' => 'Database tijdzone',
+ 'Installation_TimezoneMismatch' => 'PHP date.timezone is niet hetzelfde als database server tijdzone. Dit kan problemen opleveren met rapporten die data onjuist weergeven voor de uren van de dag. Meer informatie op %s',
+ 'Installation_JsTagHelpTitle' => 'Hoe de tag invoegen in jouw website?',
+ 'Installation_LargePiwikInstances' => 'Hulp voor grote Piwik instanties ',
+ 'Installation_JsTagArchivingHelp' => 'Voor middelgrote en grote websites, lees <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">How to setup auto archiving page</a> om Piwik echt snel te maken!',
+ 'Installation_ContinueToPiwik' => 'Ga verder naar Piwik',
+ 'Installation_SetupWebSiteName' => 'Website naam',
+ 'Installation_SetupWebSiteURL' => 'Website url',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Website %s succesvol gecreëerd! ',
+ 'Installation_SuperUserLogin' => 'super gebruiker login',
+ 'Installation_Password' => 'wachtwoord',
+ 'Installation_PasswordRepeat' => 'wachtwoord (herhaal)',
+ 'Installation_Email' => 'email',
+ 'Installation_SecurityNewsletter' => 'stuur mij e-mails over grote Piwik upgrades en beveiliging waarschuwingen ',
+ 'Installation_CommunityNewsletter' => 'stuur mij e-mails met community updates (nieuwe plugins, nieuwe features, enz) ',
+ 'Installation_PasswordDoNotMatch' => 'Wachtwoord komt niet overeen',
+ 'Installation_SubmitGo' => 'Start!',
+ 'Installation_Requirements' => 'Piwik vereisten',
+ 'Installation_Optional' => 'optioneel',
+ 'Installation_Legend' => 'legende',
+ 'Installation_Extension' => 'extensie',
+ 'Installation_SystemCheckExtensions' => 'andere vereiste extensies',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik vereist ofwel de mysqli extensie of de PDO en pdo_mysql extensie',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'Op en Linux server kun je php compileren met de volgende opties: %1$s in uw php.ini, voeg de volgende regels toe: %2$s',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Meer informatie op: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> en <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>. ',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'Op een Windows server kun je de volgende regels toevoegen aan je php.ini: %s',
+ 'Installation_SystemCheckSplHelp' => 'U moet PHP opnieuw configureren en opnieuw comileren met de standard PHP LIbrary (SPL) ingeschakeld (standaard)',
+ 'Installation_SystemCheckZlibHelp' => 'U moet PHP configureren met zlib support ingeschakeld, --with-zlib.',
+ 'Installation_SystemCheckIconvHelp' => 'U moet PHP configureren met iconv support ingeschakeld --with-iconv.',
+ 'Installation_SystemCheckDomHelp' => 'DOM is een onderdeel van de PHP core. U moet mogelijk de dom module installeren, bijv. php-5-dom',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'U moet PHP configureren met ofwel json ofwel xml extensies ingeschakeld.',
+ 'Installation_SystemCheckJsonSite' => 'Meer informatie op: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Enkele third-party plugins en ontwikkel bibliotheken vereisen de xml extensie',
+ 'Installation_SystemCheckXmlSite' => 'Meer informatie op: <a style="color:red" href="http://php.net/xml">PHP XML</a>. ',
+ 'Installation_SystemCheckOpenURL' => 'Open URL',
+ 'Installation_SystemCheckOpenURLHelp' => 'Nieuwsbrief inschrijvingen, update notificaties, en one-click updates vereisen de "curl" extensie, allow_url_fopen=On, of fsockopen() ingeschakeld.',
+ 'Installation_SystemCheckFunctions' => 'Vereiste functies',
+ 'Installation_SystemCheckMailHelp' => 'Feedback en vergeten wachtwoord berichten zullen niet worden verzonden zonder mail()',
+ 'Installation_SystemCheckParseIniFileHelp' => 'Deze ingebouwde functie is uitgeschakeld op uw host. Piwik zal proberen deze functie te emuleren maar dit kan andere veiligheidsbeperkingen oplopen. De Tracker prestaties zullen ook veranderen.',
+ 'Installation_SystemCheckDebugBacktraceHelp' => 'View::factory zal niet in staat zijn views te creëeren voor de aangeroepen module',
+ 'Installation_SystemCheckCreateFunctionHelp' => 'Piwik gebruikt anonieme functies voor aanroepen.',
+ 'Installation_SystemCheckMbstring' => 'mbstring',
+ 'Installation_SystemCheckMbstringHelp' => 'U moet mbstring.func_overload ztten op "0"',
+ 'Installation_SystemCheckFileIntegrity' => 'Bestand integriteit',
+ 'Installation_SystemCheckProtocol' => 'Protocol',
+ 'Installation_SystemCheckProtocolHelp' => 'Als u achter een reverse proxy zit, voeg deze lijnen toe aan config/config.php onder de [General] sectie:',
+ 'Installation_SystemCheckIpv4' => 'IPv4',
+ 'Installation_SystemCheckIpv4Help' => 'Het is beter dat u IPv6 uitschakelt in uw webserver configuratie.',
+ 'Installation_TablesWithSameNamesFound' => 'Enkele %1$s tabellen in uw database %2$s hebben dezelfde naam als de tabellen die Piwik probeert aan te maken.',
+ 'Installation_GoBackAndDefinePrefix' => 'Ga terug en definieer een voorvoegsel voor de Piwik tabellen ',
+ 'Installation_ConfirmDeleteExistingTables' => 'Bent u zeker dat u de tabellen wilt verwijderen: %s uit uw datbase? WAARSCHUWING: DATA VAN DEZE TABELLEN KAN NIET WORDEN HERSTELD!',
+ 'Installation_ConfigurationHelp' => 'Uw Piwik configuratie bestand is waarschijnlijk slecht geconfigureerd. U kunt ofwel config/config.ini.php verwijderen en verder gaan met de installatie, of de database connectie instellingen corrigeren.',
+ 'Installation_ErrorInvalidState' => 'Fout: Het lijkt erop dat u probeerde een stap van het installatieproces over te slaan, of dat cookies uitgeschakeld zijn, of dat uw Piwik configuratie bestand al reeds was aangemaakt. %1$s Zorg ervoor dat uw cookies zijn ingeschakeld%2$s en ga terug %3$s naar de eerste pagina van de installatie %4$s.',
+ 'LanguagesManager_PluginDescription' => 'Deze plugin zal een lijst weergeven van de beschikbare talen voor de Piwik interface. De geselecteerde taal zal opgeslagen worden in de voorkeuren voor elke gebruiker. ',
+ 'Live_PluginDescription' => 'Spioneer uw bezoekers, live, in real-time!',
+ 'Live_VisitorLog' => 'Bezoekers Logboek',
+ 'Live_Date' => 'Datum',
+ 'Live_Time' => 'Tijd',
+ 'Live_Referrer_URL' => 'Referrer URL',
+ 'Login_LoginPasswordNotCorrect' => 'Gebruikersnaam & Wachtwoord niet correct',
+ 'Login_Login' => 'Gebruikersnaam',
+ 'Login_Password' => 'Wachtwoord',
'Login_LoginOrEmail' => 'Login of E-mail',
'Login_LogIn' => 'Log in',
'Login_Logout' => 'Uitloggen',
- 'Login_LostYourPassword' => 'Password vergeten?',
- 'Login_RemindPassword' => 'Password reminder',
+ 'Login_LostYourPassword' => 'Wachtwoord vergeten?',
+ 'Login_RemindPassword' => 'Stuur wachtwoord reset',
'Login_PasswordReminder' => 'Vul uw gebruikersnaam of e-mail adres in. U zal middels een e-mail een nieuw password ontvangen.',
'Login_InvalidUsernameEmail' => 'Ongeldige gebruikersnaam en/of e-mail adres',
- 'Login_MailTopicPasswordRecovery' => 'Uw password',
- 'Login_MailPasswordRecoveryBody' => 'Hallo %1s,\n\nUw nieuwe password is: %2s\n\nU kunt nu inloggen op: %3s',
- 'Login_PasswordSent' => 'Uw password is verzonden. Controleer uw e-mail.',
+ 'Login_MailTopicPasswordRecovery' => 'Wachtwoord terughalen',
+ 'Login_MailPasswordRecoveryBody' => 'Hallo %1s,\n\nUw nieuwe wachtwoord is: %2s\n\nU kunt nu inloggen op: %3s',
+ 'Login_PasswordSent' => 'Uw wachtwoord is verzonden. Controleer uw e-mail.',
'Login_ContactAdmin' => 'Mogelijke reden: uw host heeft mogelijk de mail() functie geblokkeerd. <br />Neem contact op met uw Piwik administrator.',
+ 'Login_PluginDescription' => 'Login authenticatie plugin, leest de logingegevens uit het config/config.inc.php bestand voor de Super Gebruiker en van de Database voor andere gebruikers. Dat kan eenvoudig word vervangen om een nieuw Authenticatie mechanisme te introduceren (OpenID, htaccess, eigen Auth, enz.).',
+ 'Login_PasswordRepeat' => 'Wachtwoord (herhaal)',
+ 'Login_ChangePassword' => 'Wijzig wachtwoord',
+ 'Login_PasswordResetToken' => 'Wachtwoord reset token',
+ 'Login_PasswordsDoNotMatch' => 'Wachtwoorden komen niet overeen',
+ 'Login_PasswordSuccessfullyChanged' => 'Wachtwoord succesvol aangepast!',
+ 'Login_InvalidOrExpiredToken' => 'Token is ongeldig of is verlopen',
+ 'MultiSites_PluginDescription' => 'Toont de multi-site uitvoering van de samenvatting/statistieken. Momenteel onderhouden als een core plugin van Piwik.',
'Provider_WidgetProviders' => 'Providers',
'Provider_SubmenuLocationsProvider' => 'Lokatie & provider',
+ 'Provider_PluginDescription' => 'Rapporteer de provider van de bezoekers',
+ 'Provider_ColumnProvider' => 'Provider',
'Referers_Referers' => 'Referenties',
'Referers_SearchEngines' => 'Zoek machines',
'Referers_Keywords' => 'Zoek termen',
@@ -499,6 +543,26 @@ $translations = array(
'Referers_WidgetExternalWebsites' => 'Top websites',
'Referers_WidgetSearchEngines' => 'Top zoekmachines',
'Referers_WidgetOverview' => 'Overzicht',
+ 'Referers_PluginDescription' => 'Rapporteert de referers data: zoekmachines, sleutelwoorden, websites, Campagne volgen, directe ingangen.',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%1$s (van %2$s)',
+ 'Referers_ColumnRefererType' => 'Bezoekers afkomst',
+ 'Referers_ColumnSearchEngine' => 'Zoekmachine',
+ 'Referers_ColumnWebsite' => 'Website',
+ 'Referers_ColumnWebsitePage' => 'Website pagina',
+ 'Referers_ColumnKeyword' => 'Sleutelwoord',
+ 'Referers_ColumnCampaign' => 'Campagne',
+ 'Referers_DetailsByRefererType' => 'Details volgens bezoekers afkomst',
+ 'Referers_Distinct' => 'Verschillende bezoekers volgens bezoekers afkomst.',
+ 'Referers_DistinctSearchEngines' => 'Verschillende zoek machines.',
+ 'Referers_DistinctKeywords' => 'Verschillende sleutelwoorden.',
+ 'Referers_DistinctCampaigns' => 'Verschillende campagnes',
+ 'Referers_DistinctWebsites' => 'verschillende websites',
+ 'Referers_UsingNDistinctUrls' => '(gebruikt %1s verschillende URL\'s)',
+ 'SecurityInfo_PluginDescription' => 'Gebasseerd op PhpSecInfo van de PHP Security Consortium, deze plugin geeft veiligheid informatie over uw PHP omgeving en geeft suggesties voor verbetering. Het is een tool in een multi lagen veiligheids aanpak. Het vervangt niet de veilige ontwikkel richtlijnen of de audit code/applicatie ',
+ 'SecurityInfo_Security' => 'Veiligheid',
+ 'SecurityInfo_SecurityInformation' => 'Php veiligheid informatie',
+ 'SecurityInfo_Test' => 'Test',
+ 'SecurityInfo_Result' => 'Resultaat',
'SitesManager_Sites' => 'Websites',
'SitesManager_WebsitesManagement' => 'Website manager',
'SitesManager_MainDescription' => 'Voeg toe, actualiseer en verwijder. Ook het javascript voor op uw website is hier te vinden.',
@@ -516,6 +580,11 @@ $translations = array(
'SitesManager_ExceptionNoUrl' => 'U moet minimaal &eacute;&eacute;n url bepalen voor deze website.',
'SitesManager_ExceptionEmptyName' => 'De website dient een naam te hebben.',
'SitesManager_ExceptionInvalidUrl' => 'deze url \'%s\' is niet geldig.',
+ 'SitesManager_PluginDescription' => 'Website beheer in Piwik: Voeg een nieuwe website toe, pas een bestaande aan, toon de javascript code om te embedden in uw pagina\'s. Alle acties zijn ook beschikbaar via de API',
+ 'SitesManager_JsTrackingTag' => 'Javascript Tracking Tag',
+ 'SitesManager_JsTrackingTagHelp' => 'Hier is de Javascript Tracking tag om te embedden in al uw pagina\'s',
+ 'SitesManager_ShowTrackingTag' => 'toon tracking tag',
+ 'SitesManager_AliasUrlHelp' => 'Het is aangeraden, maar niet vereist, om de verschillende URL\'s te melden dat uw bezoekers gebruiken om deze website te bereiken. Alias URL\'s voor een website zal niet worden weergegeven in de Referers > website rapporten. Merk op dat het niet nodig is om URL\'s met of zonder WWW, omdat Piwik dit automatisch detecteert. ',
'TranslationsAdmin_MenuTranslations' => 'Vertalingen',
'TranslationsAdmin_MenuLanguages' => 'Talen',
'TranslationsAdmin_Plugin' => 'Plugin',
@@ -529,6 +598,7 @@ $translations = array(
'TranslationsAdmin_LanguageCode' => 'Taal code',
'TranslationsAdmin_Export' => 'Exporteer taal',
'TranslationsAdmin_Import' => 'Importeer taal',
+ 'TranslationsAdmin_PluginDescription' => 'Help Piwik te vertalen in jouw taal.',
'UserCountry_Country' => 'Land',
'UserCountry_Continent' => 'Continent',
'UserCountry_DistinctCountries' => '%s unieke landen',
@@ -789,13 +859,29 @@ $translations = array(
'UserCountry_continent_oce' => 'Oceanie',
'UserCountry_country_ru' => 'Rusland',
'UserCountry_country_rs' => 'Siberi&euml;',
+ 'UserCountry_PluginDescription' => 'Rapporteert het land van de bezoekers.',
+ 'UserCountry_country_ax' => '',
+ 'UserCountry_country_bl' => 'Saint Barthelemy',
+ 'UserCountry_country_bu' => 'Burma',
+ 'UserCountry_country_cp' => '',
+ 'UserCountry_country_dg' => 'Diego Garcia',
+ 'UserCountry_country_ea' => 'Ceuta, Melilla',
+ 'UserCountry_country_eu' => 'Europese Unie',
+ 'UserCountry_country_fx' => 'Frankrijk, Metropolitan',
+ 'UserCountry_country_ic' => 'Canarische eilanden',
+ 'UserCountry_country_me' => 'Montenegro',
+ 'UserCountry_country_mf' => 'Saint Martin',
+ 'UserCountry_country_nt' => 'Neutrale zone',
+ 'UserCountry_country_sf' => '',
+ 'UserCountry_country_ta' => 'Tristan da Cunha',
+ 'UserCountry_country_tl' => 'East Timor',
'UserSettings_BrowserFamilies' => 'Browser per type',
'UserSettings_Browsers' => 'Browser per versie',
'UserSettings_Plugins' => 'Ge&iuml;nstalleerde plugins',
'UserSettings_Configurations' => 'Configuraties',
- 'UserSettings_OperatinsSystems' => 'Besturings systemen',
+ 'UserSettings_OperatingSystems' => 'Besturings systemen',
'UserSettings_Resolutions' => 'Scherm resoluties',
- 'UserSettings_WideScreen' => 'Scherm configuratie',
+ 'UserSettings_WideScreen' => 'Breedbeeld',
'UserSettings_WidgetResolutions' => 'Scherm resoluties',
'UserSettings_WidgetBrowsers' => 'Browser per versie',
'UserSettings_WidgetPlugins' => 'Ge&iuml;nstalleerde plugins',
@@ -804,6 +890,15 @@ $translations = array(
'UserSettings_WidgetOperatingSystems' => 'Besturings systemen',
'UserSettings_WidgetGlobalVisitors' => 'Configuraties',
'UserSettings_SubmenuSettings' => 'Instellingen',
+ 'UserSettings_PluginDescription' => 'Rapporteert verschillende gebruikers instellingen: Brower, Browser familie, Besturingssysteem, Plugins, Resolutie, Globale Instellingen.',
+ 'UserSettings_VisitorSettings' => 'Bezoekers Instellingen',
+ 'UserSettings_ColumnBrowserFamily' => 'Browser per Type',
+ 'UserSettings_ColumnBrowser' => 'Browser',
+ 'UserSettings_ColumnPlugin' => 'Plugin',
+ 'UserSettings_ColumnConfiguration' => 'Configuratie',
+ 'UserSettings_ColumnOperatingSystem' => 'Besturingssysteem',
+ 'UserSettings_ColumnResolution' => 'Resolutie',
+ 'UserSettings_ColumnTypeOfScreen' => 'Schermtype',
'UsersManager_UsersManagement' => 'Gebruiker manager',
'UsersManager_UsersManagementMainDescription' => 'Cre&euml;er nieuwe, of actualiseer bestaande gebruikers',
'UsersManager_ManageAccess' => 'Toegangs-beheer',
@@ -828,13 +923,16 @@ $translations = array(
'UsersManager_ExceptionLoginExists' => 'Login \'%s\' bestaat reeds.',
'UsersManager_ExceptionEmailExists' => 'Er is reeds een gebruiker met \'%s\' als email adres.',
'UsersManager_ExceptionInvalidLogin' => 'Login mag enkel letters, nummers of de volgende karakters bevatten \'_\' or \'-\' or \'.\'',
- 'UsersManager_ExceptionInvalidPassword' => 'Het password moet een lengte hebben tussen 6 en 26 karakters.',
+ 'UsersManager_ExceptionInvalidPassword' => 'Het wachtwoord moet een lengte hebben tussen 6 en 26 karakters.',
'UsersManager_ExceptionInvalidEmail' => 'Het email adres is ongeldig.',
'UsersManager_ExceptionDeleteDoesNotExist' => 'Gebruiker \'%s\' bestaat niet en kan dus niet verwijderd worden.',
'UsersManager_ExceptionAdminAnonymous' => 'U kunt geen admin rechten toekennen aan de anonieme gebruiker.',
'UsersManager_ExceptionEditAnonymous' => 'De anonieme gebruiker kan niet gewijzigd of verwijderd worden. Deze wordt door Piwik gebruikt om te bepalen of een gebruiker al dan niet is ingelogd. U kunt bijvoorbeeld uw statistieken publiekelijk maken door de anonieme gebruiker \'kijkers rechten\' te geven.',
'UsersManager_ExceptionUserDoesNotExist' => 'Gebruiker \'%s\' bestaat niet.',
'UsersManager_ExceptionAccessValues' => 'De parameter toegang moet &eacute;&eacute;n van de volgede waarden bevatten : [ %s ]',
+ 'UsersManager_PluginDescription' => 'Gebruikers beheer in Piwik: voeg een nieuwe gebruiker toe, pas een bestaande aan, pas de permissies aan. Alle acties zijn ook beschikbaar via de API',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'De gebruikersnaam moet tussen de %1$s en %2$s karakters lang zijn en mag alleen letters, cijfers of de karaketers _ , - , . bevatten ',
+ 'UsersManager_ExceptionSuperUser' => 'Vereiste gebruikers is de Super Gebruiker en kan niet worden opgevraagd, bewerkt of verwijderd via de API. U kunt de Super Gebruiker aanpassen in uw Piwik configuratie bestand.',
'VisitFrequency_Evolution' => 'Recente ontwikkelingen',
'VisitFrequency_ReturnVisits' => '%s terugkerende bezoekers',
'VisitFrequency_ReturnActions' => '%s acties door de terugkerende bezoekers',
@@ -844,12 +942,13 @@ $translations = array(
'VisitFrequency_WidgetOverview' => 'Frequentie overzicht',
'VisitFrequency_WidgetGraphReturning' => 'Terugkerende bezoekers',
'VisitFrequency_SubmenuFrequency' => 'Frequentie',
- 'VisitTime_LocalTime' => 'Uur van de dag (tijdzone bezoeker)',
- 'VisitTime_ServerTime' => 'Uur van de dag (tijdzone server)',
- 'VisitTime_WidgetLocalTime' => 'Uur van de dag (tijdzone bezoeker)',
- 'VisitTime_WidgetServerTime' => 'Uur van de dag (tijdzone server)',
- 'VisitTime_SubmenuTimes' => 'Uur van de dag',
- 'VisitTime_NHour' => '%s uur',
+ 'VisitFrequency_PluginDescription' => 'Rappporteert verschillende statistieken over terugkerende bezoekers vs Eerste bezoeken.',
+ 'VisitFrequency_ColumnReturningVisits' => 'Terugkerende bezoeken.',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Acties bij terugkerende bezoeken.',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Maximum acties bij een terugkerend bezoek.',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Totale tijd gespendeerd door terugkerende bezoekers (in seconden)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Bounce Rate voor terugkerende bezoeken',
+ 'VisitFrequency_ReturnBounceRate' => '%s terugkerende bezoeken die de website verlieten na één pagina.',
'VisitorInterest_VisitsPerDuration' => 'Duur bezoek',
'VisitorInterest_VisitsPerNbOfPages' => 'Pagina\'s per bezoek',
'VisitorInterest_WidgetLengths' => 'Lengte bezoek',
@@ -860,6 +959,9 @@ $translations = array(
'VisitorInterest_OnePage' => '1 pagina',
'VisitorInterest_NPages' => '%s pagina\'s',
'VisitorInterest_BetweenXYSeconds' => '%1s-%2s sec.',
+ 'VisitorInterest_PluginDescription' => 'Rapporteert de bezoekers interesses: aantal pagina\'s bekeken, tijd gespendeerd op de website.',
+ 'VisitorInterest_ColumnVisitDuration' => 'Duur bezoek',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Pagina\'s per bezoek',
'VisitsSummary_NbVisits' => '%s bezoeken',
'VisitsSummary_NbUniqueVisitors' => '%s unieke bezoekers',
'VisitsSummary_NbActions' => '%s acties',
@@ -875,53 +977,19 @@ $translations = array(
'VisitsSummary_WidgetLastVisitors' => 'Recente unieke bezoekers',
'VisitsSummary_WidgetOverviewGraph' => 'Totalen',
'VisitsSummary_SubmenuOverview' => 'Totalen',
- 'General_Loading' => 'Laden...',
- 'General_ExportAsImage' => 'Exporteer als afbeelding',
- 'General_SaveImageOnYourComputer' => 'Om de afbeelding op te slaan op uw computer, klik rechts op de afbeelding en selecteer "Sla afbeelding op als..."',
- 'General_ColumnNbActions' => 'Acties',
- 'General_ColumnMaxActions' => 'Maximaal aantal acties per bezoek.',
- 'General_ColumnSumVisitLength' => '',
- 'General_ColumnValuePerVisit' => 'Waarde per bezoek',
- 'General_ColumnVisitsWithConversions' => '',
- 'General_PiwikIsACollaborativeProjectYouCanContribute' => '',
- 'General_PiwikXIsAvailablePleaseUpdateNow' => '',
- 'General_BackToPiwik' => 'Terug naar Piwik',
- 'General_ShortMonth_1' => 'Jan',
- 'General_ShortMonth_2' => 'Feb',
- 'General_ShortMonth_3' => 'Mrt',
- 'General_ShortMonth_4' => 'Apr',
- 'General_ShortMonth_5' => 'Mei',
- 'General_ShortMonth_6' => 'Jun',
- 'General_ShortMonth_7' => 'Jul',
- 'General_ShortMonth_8' => 'Aug',
- 'General_ShortMonth_9' => 'Sep',
- 'General_ShortMonth_10' => 'Okt',
- 'General_ShortMonth_11' => 'Nov',
- 'General_ShortMonth_12' => 'Dec',
- 'General_LongMonth_1' => 'Januari',
- 'General_LongMonth_2' => 'Februari',
- 'General_LongMonth_3' => 'Maart',
- 'General_LongMonth_4' => 'April',
- 'General_LongMonth_5' => 'Mei',
- 'General_LongMonth_6' => 'Juni',
- 'General_LongMonth_7' => 'Juli',
- 'General_LongMonth_8' => 'Augustus',
- 'General_LongMonth_9' => 'September',
- 'General_LongMonth_10' => 'Oktober',
- 'General_LongMonth_11' => 'November',
- 'General_LongMonth_12' => 'December',
- 'General_ShortDay_1' => 'Ma',
- 'General_ShortDay_2' => 'Di',
- 'General_ShortDay_3' => 'Wo',
- 'General_ShortDay_4' => 'Do',
- 'General_ShortDay_5' => 'Vr',
- 'General_ShortDay_6' => 'Za',
- 'General_ShortDay_7' => 'Zo',
- 'General_LongDay_1' => 'Maandag',
- 'General_LongDay_2' => 'Dinsdag',
- 'General_LongDay_3' => 'Woensdag',
- 'General_LongDay_4' => 'Donderdag',
- 'General_LongDay_5' => 'Vrijdag',
- 'General_LongDay_6' => 'Zaterdag',
- 'General_LongDay_7' => 'Zondag',
+ 'VisitsSummary_PluginDescription' => 'Rapporteert de algemene Analyse nummers: bezoeken, unieke bezoeken, aantal acties, terugkeeer aandeel, enz.',
+ 'VisitsSummary_VisitsSummary' => 'Bezoekers samenvatting',
+ 'VisitsSummary_NbActionsDescription' => '%s acties (^pagina weergaves, downloads en externe links)',
+ 'VisitsSummary_NbVisitsBounced' => '%s bezoekers hebben de website verlaten na één pagina',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Evolutie over de laatste %s',
+ 'VisitTime_LocalTime' => 'Uur van de dag (tijdzone bezoeker)',
+ 'VisitTime_ServerTime' => 'Uur van de dag (tijdzone server)',
+ 'VisitTime_WidgetLocalTime' => 'Uur van de dag (tijdzone bezoeker)',
+ 'VisitTime_WidgetServerTime' => 'Uur van de dag (tijdzone server)',
+ 'VisitTime_SubmenuTimes' => 'Uur van de dag',
+ 'VisitTime_NHour' => '%s uur',
+ 'VisitTime_PluginDescription' => 'Rapporteert de lokale en server tijd. Server tijd informatie kan nuttig zijn om onderhoud te bepalen op de website.',
+ 'VisitTime_ColumnServerTime' => 'Server tijd',
+ 'VisitTime_ColumnLocalTime' => 'Lokale tijd',
+ 'Widgetize_PluginDescription' => 'Deze plugin maakt het zeer gemakkelijk om elke Piwik widget te exporteren in uw blog, website, of op iGoogle en Netvibes.',
); \ No newline at end of file
diff --git a/lang/pl.php b/lang/pl.php
index 5227e35824..513a6bdbc6 100644
--- a/lang/pl.php
+++ b/lang/pl.php
@@ -1,15 +1,16 @@
<?php
$translations = array(
'General_Locale' => 'pl_PL.UTF-8',
- 'General_TranslatorName' => 'Maciej Zawadziński',
- 'General_TranslatorEmail' => 'maciej@brandnewmedia.pl',
+ 'General_TranslatorName' => 'Marcin Kowol, Maciej Zawadziński, Artur Warchoł',
+ 'General_TranslatorEmail' => 'marcin@kowol.pl, maciej@brandnewmedia.pl',
'General_EnglishLanguageName' => 'Polish',
'General_OriginalLanguageName' => 'Polski',
'General_HelloUser' => 'Witaj, %s!',
- 'General_OpenSourceWebAnalytics' => 'Open Source Web Analytics',
- 'General_YourDashboard' => 'Twój panel',
+ 'General_OpenSourceWebAnalytics' => 'Statystyki internetowe Open Source',
+ 'General_Dashboard' => 'Twój panel',
+ 'General_MultiSitesSummary' => 'Wszystkie witryny',
'General_API' => 'API',
- 'General_Widgets' => 'Widgety',
+ 'General_Widgets' => 'Widżety',
'General_Settings' => 'Ustawienia',
'General_GiveUsYourFeedback' => 'Napisz do nas!',
'General_Unknown' => 'Nieznany',
@@ -25,35 +26,181 @@ $translations = array(
'General_Close' => 'Zamknij',
'General_Logout' => 'Wyloguj',
'General_Done' => 'Gotowe',
+ 'General_Details' => 'Szczegóły',
'General_LoadingData' => 'Wczytywanie danych...',
+ 'General_Loading' => 'Wczytywanie...',
'General_ErrorRequest' => 'Oops&hellip; problem podczas żądania, spróbuj ponownie.',
- 'General_Next' => 'Następny',
- 'General_Previous' => 'Poprzedni',
+ 'General_Next' => 'Dalej',
+ 'General_Previous' => 'Wstecz',
'General_Search' => 'Szukaj',
'General_Others' => 'Inne',
'General_Table' => 'Tabela',
'General_Piechart' => 'Wykres kołowy',
- 'General_TagCloud' => 'Chmurka tagów',
+ 'General_TagCloud' => 'Chmura tagów',
'General_VBarGraph' => 'Poziomy wykres słupkowy',
- 'General_Export' => 'Export',
+ 'General_Export' => 'Eksport',
+ 'General_ExportAsImage_js' => 'Eksport jako grafika',
+ 'General_SaveImageOnYourComputer_js' => 'Aby zapisać obrazek na swoim komputerze, kliknij na nim prawym przyciskiem myszy i wybierz "Zapisz obrazek jako..."',
'General_Refresh' => 'Odśwież stronę',
'General_Visitors' => 'Odwiedzający',
'General_ColumnNbUniqVisitors' => 'Unikalni użytkownicy',
'General_ColumnNbVisits' => 'Wizyty',
+ 'General_ColumnNbActions' => 'Akcje',
+ 'General_ColumnMaxActions' => 'Największa liczba akcji podczas jednej wizyty',
+ 'General_ColumnSumVisitLength' => 'Suma czasu spędzonego w witrynie przez użytkwoników (w sekundach)',
'General_ColumnLabel' => 'Etykiety',
- 'General_ColumnActionsPerVisit' => 'Akcji na wizytę',
- 'General_ColumnAvgTimeOnSite' => 'Średni czas na stronie',
- 'General_ColumnBounceRate' => 'Bounce Rate',
- 'General_ColumnPageviews' => 'Wyświetleń',
+ 'General_ColumnActionsPerVisit' => 'Akcje podczas jednej wizyty',
+ 'General_ColumnAvgTimeOnSite' => 'Średni czas spędzony na stronie',
+ 'General_ColumnBounceRate' => 'Współczynnik odrzuceń',
+ 'General_ColumnPageviews' => 'Wyświetlenia',
'General_ColumnUniquePageviews' => 'Unikalnych wyświetleń',
+ 'General_ColumnValuePerVisit' => 'Wartość wizyty',
+ 'General_ColumnVisitsWithConversions' => 'Wizyty z konwersjami',
'General_Save' => 'Zapisz',
+ 'General_ForExampleShort' => 'np.',
'General_Website' => 'Witryna',
+ 'General_RequiresFlash' => 'Wyświetlanie grafik przez Piwika wymaga Flasha',
+ 'General_GraphHelp' => 'Więcej informacji na temat wyświetlania grafik przez Piwika.',
'General_NoDataForGraph' => 'Brak danych dla wykresu',
- 'General_NoDataForTagCloud' => 'No data for this tag cloud.',
+ 'General_NoDataForTagCloud' => 'Brak danych dla chmury tagów.',
'General_DisplayNormalTable' => 'Wyświetl normalną tabelę',
'General_DisplayMoreData' => 'Wyświetl więcej...',
- 'General_PiwikIsACollaborativeProject' => "%s Piwik %s jest wspólnym projektem w fazie beta. Jeżeli chcesz nam pomóc, prosimy %s %s skontaktuj się z nami!%s.",
- 'General_YouAreCurrentlyViewingDemoOfPiwik' => "You are currently viewing the demo of %s; %sdownload%s the full version! Check out %s",
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%1$s Piwik %2$s jest wspólnie opracowywanym projektem. %3$s Jeśli Piwik jest Ci przydatny, możesz pomóc! Sprawdź %4$s jak wziąć udział w projekcie Piwik',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => "Aktualnie oglądasz demo %s; %sdownload%s pełną wersję! Sprawdź %s",
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwik %1$s jest dostępny. %2$s Zaktualizuj go teraz!%3$s (zobacz %4$s zmiany%5$s).',
+ 'General_BackToPiwik' => 'Wróć do Piwika',
+ 'General_ShortMonth_1' => 'Sty',
+ 'General_ShortMonth_2' => 'Lut',
+ 'General_ShortMonth_3' => 'Mar',
+ 'General_ShortMonth_4' => 'Kwi',
+ 'General_ShortMonth_5' => 'Maj',
+ 'General_ShortMonth_6' => 'Cze',
+ 'General_ShortMonth_7' => 'Lip',
+ 'General_ShortMonth_8' => 'Sie',
+ 'General_ShortMonth_9' => 'Wrz',
+ 'General_ShortMonth_10' => 'Paź',
+ 'General_ShortMonth_11' => 'Lis',
+ 'General_ShortMonth_12' => 'Gru',
+ 'General_LongMonth_1' => 'Styczeń',
+ 'General_LongMonth_2' => 'Luty',
+ 'General_LongMonth_3' => 'Marzec',
+ 'General_LongMonth_4' => 'Kwiecień',
+ 'General_LongMonth_5' => 'Maj',
+ 'General_LongMonth_6' => 'Czerwiec',
+ 'General_LongMonth_7' => 'Lipiec',
+ 'General_LongMonth_8' => 'Sierpień',
+ 'General_LongMonth_9' => 'Wrzesień',
+ 'General_LongMonth_10' => 'Październik',
+ 'General_LongMonth_11' => 'Listopad',
+ 'General_LongMonth_12' => 'Grudzień',
+ 'General_ShortDay_1' => 'Pon',
+ 'General_ShortDay_2' => 'Wt',
+ 'General_ShortDay_3' => 'Śr',
+ 'General_ShortDay_4' => 'Czw',
+ 'General_ShortDay_5' => 'Pi',
+ 'General_ShortDay_6' => 'Sob',
+ 'General_ShortDay_7' => 'Niedz',
+ 'General_LongDay_1' => 'Poniedziałek',
+ 'General_LongDay_2' => 'Wtorek',
+ 'General_LongDay_3' => 'Środa',
+ 'General_LongDay_4' => 'Czwartek',
+ 'General_LongDay_5' => 'Piątek',
+ 'General_LongDay_6' => 'Sobota',
+ 'General_LongDay_7' => 'Niedziela',
+ 'General_ExceptionDatabaseVersion' => 'Your %1$s version is %2$s but Piwik requires at least %3$s.',
+ 'General_ExceptionIncompatibleClientServerVersions' => 'Your %1$s client version is %2$s which is incompatible with server version %3$s.',
+ 'General_ExceptionMissingFile' => 'Missing file: %s',
+ 'General_ExceptionFilesizeMismatch' => 'File size mismatch: %1$s (expected length: %2$s, found: %3$s)',
+ 'General_ExceptionFileIntegrity' => 'Integrity check failed: %s',
+ 'General_ExceptionNonceMismatch' => 'Could not verify the security token on this form.',
+ 'General_WarningFileIntegritySkipped' => 'Development environment detected. File integrity check skipped.',
+ 'General_WarningFileIntegrityNoManifest' => 'File integrity check could not be performed due to missing manifest.inc.php.',
+ 'General_WarningFileIntegrityNoMd5file' => 'File integrity check could not be completed due to missing md5_file() function.',
+ 'General_FileIntegrityWarningExplanation' => 'File integrity check failed and reported some errors. This is most likely due to a partial or failed upload of some of the Piwik files. You should reupload all the Piwik files and refresh this page until it shows no error.',
+ 'Actions_PluginDescription' => 'Reports about the page views, the outlinks and downloads. Outlinks and Downloads tracking is automatic!',
+ 'Actions_Actions' => 'Akcje',
+ 'Actions_SubmenuPages' => 'Strony',
+ 'Actions_SubmenuPageTitles' => 'Tytuły stron',
+ 'Actions_SubmenuOutlinks' => 'Odnośniki wychodzące',
+ 'Actions_SubmenuDownloads' => 'Ściąganięcia plików',
+ 'Actions_ColumnClicks' => 'Kliknięcia',
+ 'Actions_ColumnUniqueClicks' => 'Unikalne kliknięcia',
+ 'Actions_ColumnDownloads' => 'Ściągane pliki',
+ 'Actions_ColumnUniqueDownloads' => 'Unikalne ściągnięcia plików',
+ 'Actions_ColumnPageName' => 'Nazwa strony',
+ 'Actions_ColumnPageURL' => 'Adres strony',
+ 'Actions_ColumnClickedURL' => 'Kliknięte adresy',
+ 'Actions_ColumnDownloadURL' => 'Ściągnięte adresy',
+ 'AnonymizeIP_PluginDescription' => 'Anonymize visitor IP addresses to comply with your local privacy laws/guidelines.',
+ 'API_PluginDescription' => 'All the data in Piwik is available through simple APIs. This plugin is the web service entry point, that you can call to get your Web Analytics data in xml, json, php, csv, etc.',
+ 'API_QuickDocumentation' => '<h2>API quick documentation</h2><p>If you don\'t have data for today you can first <a href=\'misc/generateVisits.php\' target=_blank>generate some data</a> using the Visits Generator script.</p><p>You can try the different formats available for every method. It is very easy to extract any data you want from Piwik!</p><p><b>For more information have a look at the <a href=\'http://dev.piwik.org/trac/wiki/API\'>official API Documentation</a> or the <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API Reference</a>.</b></P><h2>User authentication</h2><p>If you want to <b>request the data in your scripts, in a crontab, etc. </b> you need to add the parameter <code><u>&amp;token_auth=%s</u></code> to the API calls URLs that require authentication.</p><p>This token_auth is as secret as your login and password, <b>do not share it!</p>',
+ 'API_LoadedAPIs' => 'Loaded successfully %s APIs',
+ 'CoreAdminHome_PluginDescription' => 'Administration area of Piwik.',
+ 'CoreHome_PluginDescription' => 'Web Analytics Reports Structure.',
+ 'CoreHome_NoPrivileges' => 'You are logged in as \'%s\' but it seems you don\'t have any permission set in Piwik.<br />Ask your Piwik administrator to give you \'view\' access to a website.',
+ 'CoreHome_JavascriptDisabled' => 'JavaScript must be enabled in order for you to use Piwik in standard view.<br />However, it seems JavaScript is either disabled or not supported by your browser.<br />To use standard view, enable JavaScript by changing your browser options, then %1$stry again%2$s.<br />',
+ 'CoreHome_TableNoData' => 'Brak danych dla tabeli.',
+ 'CoreHome_CategoryNoData' => 'No data in this category. Try to "Include all population".',
+ 'CoreHome_ShowJSCode' => 'Show the JavaScript code to insert',
+ 'CoreHome_IncludeAllPopulation_js' => 'Include all population',
+ 'CoreHome_ExcludeLowPopulation_js' => 'Exclude low population',
+ 'CoreHome_PageOf_js' => '%1$s z %2$s',
+ 'CoreHome_Loading_js' => 'Loading...',
+ 'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
+ 'CoreHome_PeriodDay' => 'Dzień',
+ 'CoreHome_PeriodWeek' => 'Tydzień',
+ 'CoreHome_PeriodMonth' => 'Miesiąc',
+ 'CoreHome_PeriodYear' => 'Rok',
+ 'CoreHome_PeriodDays' => 'dni',
+ 'CoreHome_PeriodWeeks' => 'tygodnie',
+ 'CoreHome_PeriodMonths' => 'miesiące',
+ 'CoreHome_PeriodYears' => 'lata',
+ 'CoreHome_DaySu_js' => 'Su',
+ 'CoreHome_DayMo_js' => 'Mo',
+ 'CoreHome_DayTu_js' => 'Tu',
+ 'CoreHome_DayWe_js' => 'We',
+ 'CoreHome_DayTh_js' => 'Th',
+ 'CoreHome_DayFr_js' => 'Fr',
+ 'CoreHome_DaySa_js' => 'Sa',
+ 'CoreHome_ShortDay_1_js' => 'Sun',
+ 'CoreHome_ShortDay_2_js' => 'Mon',
+ 'CoreHome_ShortDay_3_js' => 'Tue',
+ 'CoreHome_ShortDay_4_js' => 'Wed',
+ 'CoreHome_ShortDay_5_js' => 'Thu',
+ 'CoreHome_ShortDay_6_js' => 'Fri',
+ 'CoreHome_ShortDay_7_js' => 'Sat',
+ 'CoreHome_LongDay_1_js' => 'Sunday',
+ 'CoreHome_LongDay_2_js' => 'Monday',
+ 'CoreHome_LongDay_3_js' => 'Tuesday',
+ 'CoreHome_LongDay_4_js' => 'Wednesday',
+ 'CoreHome_LongDay_5_js' => 'Thursday',
+ 'CoreHome_LongDay_6_js' => 'Friday',
+ 'CoreHome_LongDay_7_js' => 'Saturday',
+ 'CoreHome_ShortMonth_1_js' => 'Jan',
+ 'CoreHome_ShortMonth_2_js' => 'Feb',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Apr',
+ 'CoreHome_ShortMonth_5_js' => 'May',
+ 'CoreHome_ShortMonth_6_js' => 'Jun',
+ 'CoreHome_ShortMonth_7_js' => 'Jul',
+ 'CoreHome_ShortMonth_8_js' => 'Aug',
+ 'CoreHome_ShortMonth_9_js' => 'Sep',
+ 'CoreHome_ShortMonth_10_js' => 'Oct',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dec',
+ 'CoreHome_MonthJanuary_js' => 'January',
+ 'CoreHome_MonthFebruary_js' => 'February',
+ 'CoreHome_MonthMarch_js' => 'March',
+ 'CoreHome_MonthApril_js' => 'April',
+ 'CoreHome_MonthMay_js' => 'May',
+ 'CoreHome_MonthJune_js' => 'June',
+ 'CoreHome_MonthJuly_js' => 'July',
+ 'CoreHome_MonthAugust_js' => 'August',
+ 'CoreHome_MonthSeptember_js' => 'September',
+ 'CoreHome_MonthOctober_js' => 'October',
+ 'CoreHome_MonthNovember_js' => 'November',
+ 'CoreHome_MonthDecember_js' => 'December',
+ 'CorePluginsAdmin_PluginDescription' => 'Interfejs administracyjny wtyczek.',
'CorePluginsAdmin_Plugins' => 'Wtyczki',
'CorePluginsAdmin_PluginsManagement' => 'Zarządzanie wtyczkami',
'CorePluginsAdmin_MainDescription' => 'Plugins extend and expand the functionality of Piwik. Once a plugin is installed, you may activate it or deactivate it here.',
@@ -70,50 +217,28 @@ $translations = array(
'CorePluginsAdmin_Deactivate' => 'Deaktywuj',
'CorePluginsAdmin_Activate' => 'Aktywuj',
'CorePluginsAdmin_MenuPlugins' => 'Wtyczki',
- 'API_QuickDocumentation' => '<h2>API szybka dokumentacja</h2><p>Jeżeli wciąż nie masz dzisiejszych danych możesz <a href=\'misc/generateVisits.php\' target=_blank>wygenerować pierwsze dane</a> używając skryptu generatora wizyt.</p><p>Możesz wypróbować różne formaty dla dostępnych metod. Bardzo łatwo można pobrać dane które potrzebujesz!</p><p><b>Więcej informacji możesz znaleźć na <a href=\'http://dev.piwik.org/trac/wiki/API\'>Oficjalna dokumentacja API</a> albo <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>API odnośniki</a>.</b></P><h2>Autentyfikacja użytkownika</h2><p>Jeżeli chcesz umieścić <b>żądania danych twoich skryptów w crontab, etc. </b> musisz dodać parametr<code><u>&token_auth=%s</u></code> do wywołań URLi w API URLs - wymagana autoryzacja.</p><p>Ten token_auth jest tajny tak jak twoje hasło i nazwa użytkownika <b>nie ujawniaj go!</p>',
- 'API_LoadedAPIs' => 'Wczytywanie zakończone poprawnie %s APIs',
- 'CoreHome_NoPrivileges' => 'You are logged in as \'%s\' but it seems you don\'t have any permission set in Piwik.<br />Ask your Piwik administrator to give you \'view\' access to a website.',
- 'CoreHome_JavascriptDisabled' => 'JavaScript must be enabled in order for you to use Piwik in standard view.<br>However, it seems JavaScript is either disabled or not supported by your browser.<br>To use standard view, enable JavaScript by changing your browser options, then %1stry again%2s.<br>',
- 'CoreHome_TableNoData' => 'Brak danych dla tabeli.',
- 'CoreHome_CategoryNoData' => 'Brak danych w tej kategorii. Spróbuj użyć "Włącznie cała populacja".',
- 'CoreHome_ShowJSCode' => 'Pokaż kod javascript do wklejenia',
- 'CoreHome_IncludeAllPopulation_js' => 'Włącznie cała populacja',
- 'CoreHome_ExcludeLowPopulation_js' => 'Wyłączając małą populację',
- 'CoreHome_PageOf_js' => '%s z %s',
- 'CoreHome_Loading_js' => 'Wczytywanie...',
- 'CoreHome_LocalizedDateFormat' => '%A %d %B %Y',
- 'CoreHome_PeriodDay' => 'Dzień',
- 'CoreHome_PeriodWeek' => 'Tydzień',
- 'CoreHome_PeriodMonth' => 'Miesiąc',
- 'CoreHome_PeriodYear' => 'Rok',
- 'CoreHome_DaySu_js' => 'Nie',
- 'CoreHome_DayMo_js' => 'Pon',
- 'CoreHome_DayTu_js' => 'Wto',
- 'CoreHome_DayWe_js' => 'śro',
- 'CoreHome_DayTh_js' => 'Czw',
- 'CoreHome_DayFr_js' => 'Pią',
- 'CoreHome_DaySa_js' => 'Sob',
- 'CoreHome_MonthJanuary_js' => 'Styczeń',
- 'CoreHome_MonthFebruary_js' => 'Luty',
- 'CoreHome_MonthMarch_js' => 'Marzec',
- 'CoreHome_MonthApril_js' => 'Kwiecień',
- 'CoreHome_MonthMay_js' => 'Maj',
- 'CoreHome_MonthJune_js' => 'Czerwiec',
- 'CoreHome_MonthJuly_js' => 'Lipiec',
- 'CoreHome_MonthAugust_js' => 'Sierpień',
- 'CoreHome_MonthSeptember_js' => 'Wrzesień',
- 'CoreHome_MonthOctober_js' => 'Październik',
- 'CoreHome_MonthNovember_js' => 'Listopad',
- 'CoreHome_MonthDecember_js' => 'Grudzień',
- 'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; Update',
- 'CoreUpdater_UpdateRequired' => 'Wymagana aktualizacja',
+ 'CoreUpdater_PluginDescription' => 'Piwik updating mechanism',
+ 'CoreUpdater_UpdateTitle' => 'Update',
+ 'CoreUpdater_DatabaseUpgradeRequired' => 'Database Upgrade Required',
'CoreUpdater_YourDatabaseIsOutOfDate' => 'Your Piwik database is out-of-date, and must be upgraded before you can continue.',
- 'CoreUpdater_PiwikWillBeUpgradedToVersionX' => 'Piwik will be upgraded to version %s.',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Piwik database will be upgraded from version %1$s to the new version %2$s.',
'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'The following plugins will be upgraded: %s.',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Important note for large Piwik installations',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'If you have a large Piwik database, updates might take too long to run in the browser. In this situation, you can execute the updates from your command line: %s',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => 'If you are not able to use the command line updater and if Piwik fails to upgrade (due to a timeout of the database, a browser timeout, or any other issue), you could manually execute the SQL queries to update Piwik.',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => 'Click here to view and copy the list of SQL queries that will get executed',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => 'Note: if you manually execute these queries, it is expected that some of them fail. In this case, simply ignore the errors, and run the next ones in the list.',
+ 'CoreUpdater_ReadyToGo' => 'Ready to go?',
'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'The upgrade process may take a while, so please be patient.',
'CoreUpdater_UpgradePiwik' => 'Aktualizuj Piwik',
- 'CoreUpdater_HelpMessageContent' => 'Check the %s Piwik FAQ %s which has tried to explain most common errors during upgrade. %s Ask your system administrator - they may be able to help you with the error which is most likely related to your server or MySQL setup.',
- 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Critical Error during the upgrade process:',
+ 'CoreUpdater_ErrorDIYHelp' => 'If you are an advanced user and encounter an error in the database upgrade:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'identify and correct the source of the problem (e.g., memory_limit or max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'execute the remaining queries in the update that failed',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'manually update the `option` table in your Piwik database, setting the value of version_core to the version of the failed update',
+ 'CoreUpdater_ErrorDIYHelp_4' => 're-run the updater (through the browser or command-line) to continue with the remaining updates',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'report the problem (and solution) so that Piwik can be improved',
+ 'CoreUpdater_HelpMessageContent' => 'Check the %1$s Piwik FAQ %2$s which explains most common errors during update. %3$s Ask your system administrator - they may be able to help you with the error which is most likely related to your server or MySQL setup.',
+ 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Critical Error during the update process:',
'CoreUpdater_HelpMessageIntroductionWhenError' => 'The above is the core error message. It should help explain the cause, but if you require further help please:',
'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'The upgrade completed successfuly, however there were issues during the process. Please read the above descriptions for details. For further help:',
'CoreUpdater_UpgradeComplete' => 'Aktualizacja zakończon!',
@@ -122,63 +247,321 @@ $translations = array(
'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'We automatically deactivated the following plugins: %s',
'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik has been successfully upgraded!',
'CoreUpdater_ContinueToPiwik' => 'Continue to Piwik',
- 'Actions_Actions' => 'Akcje',
- 'Actions_SubmenuPages' => 'Strony',
- 'Actions_SubmenuOutlinks' => 'Zewnętrzne linki',
- 'Actions_SubmenuDownloads' => 'Pobrania',
+ 'CoreUpdater_UpdateAutomatically' => 'Update Automatically',
+ 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'There is a new version of Piwik available for update',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'You can update to version %s automatically or download the package and install it manually:',
+ 'CoreUpdater_DownloadX' => 'Download %s',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Piwik One Click Update has been cancelled. If you can\'t fix the above error message, it is recommended that you manually update Piwik. %1$s Please check out the %2$sUpdate documentation%3$s to get started!',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Downloading update from %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Unpacking the update',
+ 'CoreUpdater_VerifyingUnpackedFiles' => 'Verifying the unpacked files',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Creating a backup of the configuration file in %s',
+ 'CoreUpdater_InstallingTheLatestVersion' => 'Installing the latest version',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik updated successfully!',
+ 'CoreUpdater_EmptyDatabaseError' => 'Database %s is empty. You must edit or remove your Piwik configuration file.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Your Piwik version %s is up to date.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Incompatible archive: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Empty archive.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Archive is incomplete: some files are missing (eg. %s).',
+ 'Dashboard_PluginDescription' => 'Your Web Analytics Dashboard. You can customize Your Dashboard: add new widgets, change the order of your widgets. Each user can access his own custom Dashboard.',
'Dashboard_Dashboard' => 'Panel',
'Dashboard_AddWidget' => 'Dodaj jako widget...',
'Dashboard_DeleteWidgetConfirm' => 'Czy napewno chcesz skasować widget z panelu',
'Dashboard_SelectWidget' => 'Wybierz widget by dodać do panelu',
- 'Dashboard_AddPreviewedWidget' => 'Dodaj przeglądnięte widget\'y do panelu',
- 'Dashboard_WidgetPreview' => 'Widget podgląd',
+ 'Dashboard_AddPreviewedWidget_js' => 'Dodaj przeglądnięte widget\'y do panelu',
+ 'Dashboard_WidgetPreview_js' => 'Widget podgląd',
+ 'Dashboard_Close_js' => 'Zamknij',
'Dashboard_TitleWidgetInDashboard_js' => 'Widget jest już dostępny na panelu',
'Dashboard_TitleClickToAdd_js' => 'Kliknij by dodać do panelu',
- 'Dashboard_LoadingPreview_js' => 'Wczytywanie podglądu, proszę czekać...',
'Dashboard_LoadingWidget_js' => 'Wczytywanie widget\'u, proszę czekać...',
'Dashboard_WidgetNotFound_js' => 'Widget nieznaleziony',
- 'Referers_Referers' => 'Referers',
+ 'DBStats_PluginDescription' => 'This plugin reports the MySQL database usage by Piwik tables.',
+ 'DBStats_DatabaseUsage' => 'Database usage',
+ 'DBStats_MainDescription' => 'Piwik is storing all your web analytics data in the MySQL database. Currently, Piwik tables are using %s.',
+ 'DBStats_LearnMore' => 'To learn more about how Piwik processes data and how to make Piwik work well for medium and high traffic websites, check out the documentation %s.',
+ 'DBStats_Table' => 'Table',
+ 'DBStats_RowCount' => 'Row count',
+ 'DBStats_DataSize' => 'Data size',
+ 'DBStats_IndexSize' => 'Index size',
+ 'DBStats_TotalSize' => 'Total size',
+ 'ExampleAPI_PluginDescription' => 'Example Plugin: How to create an API for your plugin, to export your data in multiple formats without any special coding?',
+ 'ExampleFeedburner_PluginDescription' => 'Example Plugin: How to display your Feedburner subscriber in a Widget in the Dashboard?',
+ 'ExampleRssWidget_PluginDescription' => 'Example Plugin: How to create a new widget that reads a RSS feed?',
+ 'ExampleUI_PluginDescription' => 'Example Plugin: This plugin shows how to work with the Piwik UI: create tables, graphs, etc.',
+ 'Feedback_PluginDescription' => 'Send your Feedback to the Piwik Team. Share your ideas and suggestions with us!',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Do you have a bug to report or a feature request?',
+ 'Feedback_ViewAnswersToFAQ' => 'View answers to %s Frequently Asked Questions%s',
+ 'Feedback_WhyAreMyVisitsNoTracked' => 'Why aren\'t visits to my website being tracked?',
+ 'Feedback_HowToExclude' => 'How do I exclude tracking of my visits?',
+ 'Feedback_WhyWrongCountry' => 'Why does Piwik show my visit from the wrong country?',
+ 'Feedback_HowToAnonymizeIP' => 'How do I mask visitor IP addresses in my database?',
+ 'Feedback_VisitTheForums' => 'Visit the %s Forums%s',
+ 'Feedback_LearnWaysToParticipate' => 'Learn about all the ways you can %s participate%s',
+ 'Feedback_SpecialRequest' => 'Do you have a special request for the Piwik team? ',
+ 'Feedback_ContactThePiwikTeam' => 'Contact the Piwik team!',
+ 'Feedback_IWantTo' => 'I want to:',
+ 'Feedback_CategoryShareStory' => 'Share a Piwik success story',
+ 'Feedback_CategorySponsor' => 'Sponsor Piwik',
+ 'Feedback_CategoryHire' => 'Hire a Piwik consultant',
+ 'Feedback_CategorySecurity' => 'Report a security issue',
+ 'Feedback_MyEmailAddress' => 'My email address:',
+ 'Feedback_MyMessage' => 'My message:',
+ 'Feedback_DetailsPlease' => '(please include details)',
+ 'Feedback_SendFeedback' => 'Send Feedback',
+ 'Feedback_ManuallySendEmailTo' => 'Please manually send your message to',
+ 'Feedback_MessageSent' => 'Your message was sent to the Piwik team.',
+ 'Feedback_ThankYou' => 'Thank you for helping us to make Piwik better!',
+ 'Feedback_ThePiwikTeam' => 'The Piwik Team',
+ 'Feedback_ExceptionBodyLength' => 'Message must be at least %s characters long.',
+ 'Feedback_ExceptionNoUrls' => 'The message cannot contain a URL, to avoid spam messages.',
+ 'Goals_PluginDescription' => 'Twórz cele i przeglądaj raporty z konwersji: rozwój w czasie, przychód z wizyty, konwersja dla odnośnika, dla słowa kluczowego itp.',
+ 'Goals_ColumnConversions' => 'Konwersje',
+ 'Goals_ColumnConversionRate' => 'Współczynnik konwersji',
+ 'Goals_ColumnRevenue' => 'Przychód',
+ 'Goals_OverallRevenue' => '%s overall revenue',
+ 'Goals_OverallConversionRate' => '%s overall conversion rate (visits with a completed goal)',
+ 'Goals_Conversions' => '%s conversions',
+ 'Goals_ConversionRate' => '%s conversion rate',
+ 'Goals_NoGoalsNeedAccess' => 'Only an Administrator or the Super User can add Goals for a given website. Please ask your Piwik administrator to set up a Goal for your website. <br>Tracking Goals is a great way to help understand and maximize your website performance! ',
+ 'Goals_AddNewGoal' => 'Dodaj nowy cel',
+ 'Goals_AddNewGoalOrEditExistingGoal' => '%sAdd a new Goal%s lub %sEdit% istniejący cel',
+ 'Goals_AddGoal_js' => 'Dodaj cel',
+ 'Goals_UpdateGoal_js' => 'Aktualizuj cel',
+ 'Goals_DeleteGoalConfirm_js' => 'Are you sure you want to delete the Goal %s?',
+ 'Goals_GoalName' => 'Nazwa celu',
+ 'Goals_GoalIsTriggered' => 'Goal is triggered',
+ 'Goals_GoalIsTriggeredWhen' => 'Goal is triggered when',
+ 'Goals_WhenVisitors' => 'when visitors',
+ 'Goals_Manually' => 'manually',
+ 'Goals_ManuallyTriggeredUsingJavascriptFunction' => 'Goal is manually triggered using the Javascript API trackGoal()',
+ 'Goals_VisitUrl' => 'Visit a given URL (page or group of pages)',
+ 'Goals_Download' => 'Download a file',
+ 'Goals_ClickOutlink' => 'Click on a Link to an external website',
+ 'Goals_Optional' => '(optional)',
+ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => 'where the visited page contains a call to the JavaScript piwikTracker.trackGoal() method (%slearn more%s)',
+ 'Goals_DefaultRevenue' => 'Goal default revenue is ',
+ 'Goals_DefaultRevenueHelp' => 'For example, a Contact Form submitted by a visitor may be worth $10 on average. Piwik will help you understand how well your visitors segments are performing.',
+ 'Goals_ConversionsOverview' => 'Conversions Overview',
+ 'Goals_BestCountries' => 'Your best converting countries are: ',
+ 'Goals_BestKeywords' => 'Your top converting keywords are: ',
+ 'Goals_BestReferers' => 'Your best converting websites referers are: ',
+ 'Goals_ReturningVisitorsConversionRateIs' => 'Returning visitors conversion rate is %s',
+ 'Goals_NewVisitorsConversionRateIs' => 'New visitors conversion rate is %s',
+ 'Goals_Contains' => 'contains %s',
+ 'Goals_IsExactly' => 'is exactly %s',
+ 'Goals_MatchesExpression' => 'matches the expression %s',
+ 'Goals_CaseSensitive' => 'Case sensitive match',
+ 'Goals_Pattern' => 'Pattern',
+ 'Installation_PluginDescription' => 'Installation process of Piwik. The Installation is usually done once only. If the configuration file config/config.inc.php is deleted, the installation will start again.',
+ 'Installation_Installation' => 'Installation',
+ 'Installation_InstallationStatus' => 'Installation status',
+ 'Installation_PercentDone' => '%s %% Done',
+ 'Installation_NoConfigFound' => 'The Piwik configuration file couldn\'t be found and you are trying to access a Piwik page.<br /><b>&nbsp;&nbsp;&raquo; You can <a href=\'index.php\'>install Piwik now</a></b><br /><small>If you installed Piwik before and have some tables in your DB, don\'t worry, you can reuse the same tables and keep your existing data!</small>',
+ 'Installation_DatabaseSetup' => 'Database setup',
+ 'Installation_DatabaseSetupServer' => 'database server',
+ 'Installation_DatabaseSetupLogin' => 'login',
+ 'Installation_DatabaseSetupPassword' => 'password',
+ 'Installation_DatabaseSetupDatabaseName' => 'database name',
+ 'Installation_DatabaseSetupTablePrefix' => 'table prefix',
+ 'Installation_DatabaseSetupAdapter' => 'adapter',
+ 'Installation_DatabaseErrorConnect' => 'Error while trying to connect to the database server',
+ 'Installation_DatabaseCheck' => 'Database check',
+ 'Installation_DatabaseServerVersion' => 'Database server version',
+ 'Installation_DatabaseClientVersion' => 'Database client version',
+ 'Installation_DatabaseCreation' => 'Database creation',
+ 'Installation_DatabaseClientCharset' => 'Database client character set',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'Client connection to the database server is not set to UTF8 by default. This is not critical issue: <b>Piwik should work correctly</b>. However for consistency, it is recommended that you do one of the following: <ul style="list-style: disc;margin-left:10px"><li>in your piwik config/config.ini.php, add <code>charset = utf8</code> under the [database] section of your Piwik configuration file <code>config/config.ini.php</code></li><li>recompile libmysql --with-charset=utf8</li></ul>',
+ 'Installation_DatabaseTimezone' => 'Database timezone',
+ 'Installation_TimezoneMismatch' => 'PHP date.timezone is not the same as the database server timezone. This might cause issues with reports not showing data for the right hours of the day. More information at %s',
+ 'Installation_JsTag' => 'JavaScript tag',
+ 'Installation_JsTagHelp' => '<p>To count all visitors, you must insert the JavaScript code on all of your pages.</p><p>Your pages do not have to be made with PHP, Piwik will work on all kinds of pages (whether it is HTML, ASP, Perl or any other languages).</p><p>Here is the code you have to insert: (copy and paste on all your pages) </p>',
+ 'Installation_JsTagHelpTitle' => 'How to insert the tag in your websites?',
+ 'Installation_LargePiwikInstances' => 'Help for large Piwik instances',
+ 'Installation_JsTagArchivingHelp' => 'For medium and high traffic websites, check out the <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">How to setup auto archiving page</a> to make Piwik run really fast!',
+ 'Installation_Congratulations' => 'Congratulations',
+ 'Installation_CongratulationsHelp' => '<p>Congratulations! Your Piwik installation is complete.</p><p>Make sure your JavaScript code is entered on your pages, and wait for your first visitors!</p>',
+ 'Installation_ContinueToPiwik' => 'Continue to Piwik',
+ 'Installation_SetupWebsite' => 'Setup a website',
+ 'Installation_SetupWebSiteName' => 'website name',
+ 'Installation_SetupWebSiteURL' => 'website URL',
+ 'Installation_SetupWebsiteError' => 'There was an error when adding the website',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Website %s created with success!',
+ 'Installation_GeneralSetup' => 'General Setup',
+ 'Installation_GeneralSetupSuccess' => 'General Setup configured with success',
+ 'Installation_SuperUserLogin' => 'super user login',
+ 'Installation_Password' => 'password',
+ 'Installation_PasswordRepeat' => 'password (repeat)',
+ 'Installation_Email' => 'email',
+ 'Installation_SecurityNewsletter' => 'email me with major Piwik upgrades and security alerts',
+ 'Installation_CommunityNewsletter' => 'email me with community updates (new plugins, new features, etc.)',
+ 'Installation_PasswordDoNotMatch' => 'password do not match',
+ 'Installation_SubmitGo' => 'Go!',
+ 'Installation_Requirements' => 'Piwik Requirements',
+ 'Installation_Optional' => 'Optional',
+ 'Installation_Legend' => 'Legend',
+ 'Installation_Extension' => 'extension',
+ 'Installation_SystemCheck' => 'System check',
+ 'Installation_SystemCheckPhp' => 'PHP version',
+ 'Installation_SystemCheckExtensions' => 'Other required extensions',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik requires either the mysqli extension or both the PDO and pdo_mysql extensions.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => "On a Linux server you can compile php with the following options: %1\$s\nIn your php.ini, add the following lines: %2\$s",
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'More information on: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> and <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'On a Windows server you can add the following lines to your php.ini: %s',
+ 'Installation_SystemCheckSplHelp' => 'You need to configure and rebuild PHP with the Standard PHP Library (SPL) enabled (by default).',
+ 'Installation_SystemCheckZlibHelp' => 'You need to configure and rebuild PHP with "zlib" support enabled, --with-zlib.',
+ 'Installation_SystemCheckIconvHelp' => 'You need to configure and rebuild PHP with "iconv" support enabled, --with-iconv.',
+ 'Installation_SystemCheckDomHelp' => 'DOM is part of PHP core. You probably need to install the dom module, e.g., php-5-dom.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'You need to configure and rebuild PHP with either "json" or "xml" extensions enabled.',
+ 'Installation_SystemCheckJsonSite' => 'More information on: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Some third-party plugins and developer libraries may require the "xml" extension.',
+ 'Installation_SystemCheckXmlSite' => 'More information on: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckWriteDirs' => 'Directories with write access',
+ 'Installation_SystemCheckWriteDirsHelp' => 'To fix this error on your Linux system, try typing in the following command(s)',
+ 'Installation_SystemCheckMemoryLimit' => 'Memory limit',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'On a high traffic website, the archiving process may require more memory than currently allowed. If necessary, change the memory_limit directive in your php.ini file.',
+ 'Installation_SystemCheckOpenURL' => 'Open URL',
+ 'Installation_SystemCheckOpenURLHelp' => 'Newsletter subscriptions, update notifications, and one-click updates requires the "curl" extension, allow_url_fopen=On, or fsockopen() enabled.',
+ 'Installation_SystemCheckGD' => 'GD &gt; 2.x (graphics)',
+ 'Installation_SystemCheckGDHelp' => 'The sparklines (small graphs) will not work.',
+ 'Installation_SystemCheckFunctions' => 'Required functions',
+ 'Installation_SystemCheckTimeLimitHelp' => 'On a high traffic website, executing the archiving process may require more time than currently allowed. If necessary, change the max_execution_time directive in your php.ini file.',
+ 'Installation_SystemCheckMailHelp' => 'Feedback and Lost Password messages will not be sent without mail().',
+ 'Installation_SystemCheckParseIniFileHelp' => 'This built-in function has been disabled on your host. Piwik will attempt to emulate this function but may encounter further security restrictions. Tracker performance will also be impacted.',
+ 'Installation_SystemCheckDebugBacktraceHelp' => 'View::factory won\'t be able to create views for the calling module.',
+ 'Installation_SystemCheckCreateFunctionHelp' => 'Piwik uses anonymous functions for callbacks.',
+ 'Installation_SystemCheckMbstring' => 'mbstring',
+ 'Installation_SystemCheckMbstringHelp' => 'You should set mbstring.func_overload to "0".',
+ 'Installation_SystemCheckFileIntegrity' => 'File integrity',
+ 'Installation_SystemCheckError' => 'An error occured - must be fixed before you proceed',
+ 'Installation_SystemCheckWarning' => 'Piwik will work normally but some features may be missing',
+ 'Installation_SystemCheckProtocol' => 'Protocol',
+ 'Installation_SystemCheckProtocolHelp' => 'If you are behind a reverse proxy, add these lines to config/config.ini.php under the [General] section:',
+ 'Installation_SystemCheckIpv4' => 'IPv4',
+ 'Installation_SystemCheckIpv4Help' => 'You should disable IPv6 in your web server configuration.',
+ 'Installation_Tables' => 'Creating the tables',
+ 'Installation_TablesWithSameNamesFound' => 'Some %1$s tables in your database %2$s have the same names as the tables Piwik is trying to create',
+ 'Installation_TablesFound' => 'The following tables have been found in the database',
+ 'Installation_TablesWarningHelp' => 'Either choose to reuse the existing database tables or select a clean install to erase all existing data in the database.',
+ 'Installation_TablesReuse' => 'Reuse the existing tables',
+ 'Installation_TablesDelete' => 'Delete the detected tables',
+ 'Installation_TablesDeletedSuccess' => 'Existing Piwik tables deleted with success',
+ 'Installation_TablesCreatedSuccess' => 'Tables created with success!',
+ 'Installation_DatabaseCreatedSuccess' => 'Database %s created with success!',
+ 'Installation_GoBackAndDefinePrefix' => 'Go back and define a Prefix for the Piwik Tables',
+ 'Installation_ConfirmDeleteExistingTables' => 'Are you sure you want to delete the tables: %s from your database? WARNING: DATA FROM THESE TABLES CANNOT BE RECOVERED!',
+ 'Installation_Welcome' => 'Welcome!',
+ 'Installation_WelcomeHelp' => '<p>Piwik is an open source web analytics software that makes it easy to get the information you want from your visitors.</p><p>This process is split up into %s easy steps and will take around 5 minutes.</p>',
+ 'Installation_ConfigurationHelp' => 'Your Piwik configuration file appears to be misconfigured. You can either remove config/config.ini.php and resume installation, or correct the database connection settings.',
+ 'Installation_ErrorInvalidState' => 'Error: it seems you tried to skip a step of the Installation process, or your cookies are disabled, or the Piwik configuration file was already created. %1$sMake sure your cookies are enabled%2$s and go back %3$s to the first page of the installation %4$s.',
+ 'LanguagesManager_PluginDescription' => 'This plugin will display a list of the available languages for the Piwik interface. The language selected will be saved in the preferences for each user.',
+ 'Live_PluginDescription' => 'Spy on your visitors, live, in real-time!',
+ 'Live_VisitorLog' => 'Log użytkowników',
+ 'Live_Date' => 'Data',
+ 'Live_Time' => 'Czas',
+ 'Live_Referrer_URL' => 'Adres wejścia',
+ 'Login_PluginDescription' => 'Login Authentication plugin, reading the credentials from the config/config.inc.php file for the Super User, and from the Database for the other users. Can be easily replaced to introduce a new Authentication mechanism (OpenID, htaccess, custom Auth, etc.).',
+ 'Login_LoginPasswordNotCorrect' => 'Username &amp; Password not correct',
+ 'Login_Login' => 'Nazwa użytkownika',
+ 'Login_Password' => 'Hasło',
+ 'Login_PasswordRepeat' => 'Password (repeat)',
+ 'Login_ChangePassword' => 'Change password',
+ 'Login_LoginOrEmail' => 'Login or E-mail',
+ 'Login_LogIn' => 'Zaloguj',
+ 'Login_Logout' => 'Wyloguj',
+ 'Login_LostYourPassword' => 'Zapomniałeś hasła?',
+ 'Login_RemindPassword' => 'Send password reset',
+ 'Login_PasswordResetToken' => 'Password reset token',
+ 'Login_PasswordReminder' => 'Please enter your username or e-mail address. You will receive an e-mail with information to reset your password.',
+ 'Login_PasswordsDoNotMatch' => 'Passwords do not match.',
+ 'Login_PasswordSuccessfullyChanged' => 'Password successfully changed!',
+ 'Login_InvalidUsernameEmail' => 'Invalid username and/or e-mail address',
+ 'Login_InvalidOrExpiredToken' => 'Token is invalid or has expired',
+ 'Login_MailTopicPasswordRecovery' => 'Password recovery',
+ 'Login_MailPasswordRecoveryBody' => "Hi %1\$s,\n\nA password reset request was received from %2\$s.\n\nTo reset your password:\n\n1) Go to the Password Reset Form at:\n\t%3\$s\n\n2) Enter the following token:\n\t%4\$s\n\n3) Fill out the form (entering your new password twice) and submit.\n\nNote: this token will expire in 24 hrs.",
+ 'Login_PasswordSent' => 'Information to reset your password has been sent. Check your e-mail.',
+ 'Login_ContactAdmin' => 'Possible reason: your host may have disabled the mail() function. <br />Please contact your Piwik administrator.',
+ 'MultiSites_PluginDescription' => 'Displays multi-site executive summary/statistics. Currently maintained as a core Piwik plugin.',
+ 'Provider_PluginDescription' => 'Reports the Provider of the visitors.',
+ 'Provider_WidgetProviders' => 'Providers',
+ 'Provider_ColumnProvider' => 'Provider',
+ 'Provider_SubmenuLocationsProvider' => 'Locations &amp; Provider',
+ 'Referers_PluginDescription' => 'Reports the Referers data: Search Engines, Keywords, Websites, Campaign Tracking, Direct Entry. ',
+ 'Referers_Referers' => 'Odsyłacze',
'Referers_SearchEngines' => 'Wyszukiwarki',
'Referers_Keywords' => 'Słowa kluczowe',
'Referers_DirectEntry' => 'Bezpośrednie wywołania',
'Referers_Websites' => 'Strony',
'Referers_Campaigns' => 'Kampanie',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%1$s (from %2$s)',
'Referers_Evolution' => 'Rozwój cyklu',
'Referers_Type' => 'Rodzaj odnośnika',
+ 'Referers_ColumnRefererType' => 'Źródło',
+ 'Referers_ColumnSearchEngine' => 'Wyszukiwarka',
+ 'Referers_ColumnWebsite' => 'Witryna',
+ 'Referers_ColumnWebsitePage' => 'Strona',
+ 'Referers_ColumnKeyword' => 'Słowo kluczowe',
+ 'Referers_ColumnCampaign' => 'Kampania',
+ 'Referers_DetailsByRefererType' => 'Szczegóły źródeł',
'Referers_TypeDirectEntries' => '%s bezpośrednich wejść',
'Referers_TypeSearchEngines' => '%s z wyszukiwarek',
'Referers_TypeWebsites' => '%s ze stron',
'Referers_TypeCampaigns' => '%s z kampanii',
- 'Referers_Other' => 'Inne',
- 'Referers_OtherDistinctSearchEngines' => '%s niepowtarzalne wyszukiwarki',
- 'Referers_OtherDistinctKeywords' => '%s niepowtarzalne słowa kluczowe',
- 'Referers_OtherDistinctWebsites' => '%1s niepowtarzalne strony (używające %2s niepowtarzalnych url\'i)',
- 'Referers_OtherDistinctCampaigns' => '%s niepowtarzalne kampanie',
- 'Referers_TagCloud' => 'Wynik chmurki tag\'ów',
+ 'Referers_Distinct' => 'Inne',
+ 'Referers_DistinctSearchEngines' => '%s niepowtarzalne wyszukiwarki',
+ 'Referers_DistinctKeywords' => '%s niepowtarzalne słowa kluczowe',
+ 'Referers_DistinctCampaigns' => '%s niepowtarzalne kampanie',
+ 'Referers_DistinctWebsites' => '%1s niepowtarzalne strony (używające %2s niepowtarzalnych url\'i)',
+ 'Referers_UsingNDistinctUrls' => ' (using %1s distinct urls)',
'Referers_SubmenuEvolution' => 'Rozwój',
'Referers_SubmenuSearchEngines' => 'Wyszukiwarki i słowa kluczowe',
'Referers_SubmenuWebsites' => 'Strony',
'Referers_SubmenuCampaigns' => 'Kampanie',
- 'Referers_WidgetKeywords' => 'Lista słów kluczowych',
+ 'Referers_WidgetKeywords' => 'Słowa kluczowe z wyszukiwarek',
'Referers_WidgetCampaigns' => 'Lista kampanii',
'Referers_WidgetExternalWebsites' => 'Lista zewnętrznych stron',
'Referers_WidgetSearchEngines' => 'Najpopularniejsze wyszukiwarki',
- 'Referers_WidgetOverview' => 'Przegląd',
- 'UserSettings_BrowserFamilies' => 'Rodzina przeglądarek',
- 'UserSettings_Browsers' => 'Przeglądarki',
- 'UserSettings_Plugins' => 'Plugin\'y',
- 'UserSettings_Configurations' => 'Konfiguracja',
- 'UserSettings_OperatinsSystems' => 'Systemy operacyjne',
- 'UserSettings_Resolutions' => 'Rozdzielczość',
- 'UserSettings_WideScreen' => 'Ekran panoramiczny',
- 'UserSettings_WidgetResolutions' => 'Rozdzielczość ekrany',
- 'UserSettings_WidgetBrowsers' => 'Przeglądarki gości',
- 'UserSettings_WidgetPlugins' => 'Lista wtyczek',
- 'UserSettings_WidgetWidescreen' => 'Standardowe / Panoramiczne',
- 'UserSettings_WidgetBrowserFamilies' => 'Przeglądarki na rodziny',
- 'UserSettings_WidgetOperatingSystems' => 'Systemy operacyjne',
- 'UserSettings_WidgetGlobalVisitors' => 'Konfiguracja główna wizyt',
- 'UserSettings_SubmenuSettings' => 'Ustawienia',
+ 'Referers_WidgetOverview' => 'Źródła odwiedzin',
+ 'SecurityInfo_PluginDescription' => 'Based on PhpSecInfo from the PHP Security Consortium, this plugin provides security information about your PHP environment and offers suggestions for improvement. It is a tool in a multilayered security approach. It does not replace secure development practices nor audit the code/application.',
+ 'SecurityInfo_Security' => 'Security',
+ 'SecurityInfo_SecurityInformation' => 'PHP Security Information',
+ 'SecurityInfo_Test' => 'Test',
+ 'SecurityInfo_Result' => 'Result',
+ 'SitesManager_PluginDescription' => 'Websites Management in Piwik: Add a new Website, Edit an existing one, Show the Javascript code to include on your pages. All the actions are also available through the API.',
+ 'SitesManager_Sites' => 'Websites',
+ 'SitesManager_WebsitesManagement' => 'Websites Management',
+ 'SitesManager_MainDescription' => 'Your Web Analytics reports need Websites! Add, update, delete Websites, and show the JavaScript to insert in your pages.',
+ 'SitesManager_JsTrackingTag' => 'JavaScript Tracking Tag',
+ 'SitesManager_JsTrackingTagHelp' => 'Here is the JavaScript Tracking tag to include on all your pages',
+ 'SitesManager_ShowTrackingTag' => 'show tracking tag',
+ 'SitesManager_NoWebsites' => 'You don\'t have any website to administrate.',
+ 'SitesManager_AddSite' => 'Add a new website',
+ 'SitesManager_AliasUrlHelp' => "It is recommended, but not required, to specify the various URLs that your visitors use to access this website.\nAlias URLs for a website will not appear in the Referers > Websites report.\nNote that it is not necessary to specify the URLs with and without 'www' as Piwik automatically considers both.",
+ 'SitesManager_Id' => 'Id',
+ 'SitesManager_Name' => 'Name',
+ 'SitesManager_Urls' => 'URLs',
+ 'SitesManager_MenuSites' => 'Websites',
+ 'SitesManager_DeleteConfirm_js' => 'Are you sure you want to delete the website %s?',
+ 'SitesManager_ExceptionDeleteSite' => 'It is not possible to delete this website as it is the only registered website. Add a new website first, then delete this one.',
+ 'SitesManager_ExceptionNoUrl' => 'You must specify at least one URL for the website.',
+ 'SitesManager_ExceptionEmptyName' => 'The website name can\'t be empty.',
+ 'SitesManager_ExceptionInvalidUrl' => 'The url \'%s\' is not a valid URL.',
+ 'TranslationsAdmin_PluginDescription' => 'Help translate Piwik into your language.',
+ 'TranslationsAdmin_MenuTranslations' => 'Translations',
+ 'TranslationsAdmin_MenuLanguages' => 'Languages',
+ 'TranslationsAdmin_Plugin' => 'Wtyczka',
+ 'TranslationsAdmin_Definition' => 'Definition',
+ 'TranslationsAdmin_DefaultString' => 'Default string (English)',
+ 'TranslationsAdmin_TranslationString' => 'Translation string (current language: %s)',
+ 'TranslationsAdmin_Translations' => 'Translations',
+ 'TranslationsAdmin_FixPermissions' => 'Please fix filesystem permissions',
+ 'TranslationsAdmin_AvailableLanguages' => 'Available languages',
+ 'TranslationsAdmin_AddLanguage' => 'Add language',
+ 'TranslationsAdmin_LanguageCode' => 'Language code',
+ 'TranslationsAdmin_Export' => 'Export language',
+ 'TranslationsAdmin_Import' => 'Import language',
+ 'UserCountry_PluginDescription' => 'Reports the Country of the visitors.',
'UserCountry_Country' => 'Kraj',
'UserCountry_Continent' => 'Kontynent',
'UserCountry_DistinctCountries' => '%s unikalnych krajów',
@@ -187,8 +570,8 @@ $translations = array(
'UserCountry_WidgetCountries' => 'kraje gości',
'UserCountry_country_ac' => 'Ascension Islands',
'UserCountry_country_ad' => 'Andorra',
- 'UserCountry_country_ae' => 'Zjednoczone Emiraty Arabskie',
- 'UserCountry_country_af' => 'Afganistan',
+ 'UserCountry_country_ae' => 'United Arab Emirates',
+ 'UserCountry_country_af' => 'Afghanistan',
'UserCountry_country_ag' => 'Antigua and Barbuda',
'UserCountry_country_ai' => 'Anguilla',
'UserCountry_country_al' => 'Albania',
@@ -196,70 +579,79 @@ $translations = array(
'UserCountry_country_an' => 'Netherlands Antilles',
'UserCountry_country_ao' => 'Angola',
'UserCountry_country_aq' => 'Antarctica',
- 'UserCountry_country_ar' => 'Argentyna',
+ 'UserCountry_country_ar' => 'Argentina',
'UserCountry_country_as' => 'American Samoa',
'UserCountry_country_at' => 'Austria',
'UserCountry_country_au' => 'Australia',
'UserCountry_country_aw' => 'Aruba',
+ 'UserCountry_country_ax' => 'Aland Islands',
'UserCountry_country_az' => 'Azerbaijan',
- 'UserCountry_country_ba' => 'Bośnia and Hercegowina',
+ 'UserCountry_country_ba' => 'Bosnia and Herzegovina',
'UserCountry_country_bb' => 'Barbados',
'UserCountry_country_bd' => 'Bangladesh',
- 'UserCountry_country_be' => 'Belgia',
+ 'UserCountry_country_be' => 'Belgium',
'UserCountry_country_bf' => 'Burkina Faso',
- 'UserCountry_country_bg' => 'Bułgaria',
+ 'UserCountry_country_bg' => 'Bulgaria',
'UserCountry_country_bh' => 'Bahrain',
'UserCountry_country_bi' => 'Burundi',
'UserCountry_country_bj' => 'Benin',
+ 'UserCountry_country_bl' => 'Saint Barthelemy',
'UserCountry_country_bm' => 'Bermuda',
'UserCountry_country_bn' => 'Bruneo',
'UserCountry_country_bo' => 'Bolivia',
- 'UserCountry_country_br' => 'Brazylia',
+ 'UserCountry_country_br' => 'Brazil',
'UserCountry_country_bs' => 'Bahamas',
'UserCountry_country_bt' => 'Bhutan',
+ 'UserCountry_country_bu' => 'Burma',
'UserCountry_country_bv' => 'Bouvet Island',
'UserCountry_country_bw' => 'Botswana',
'UserCountry_country_by' => 'Belarus',
'UserCountry_country_bz' => 'Belize',
- 'UserCountry_country_ca' => 'Kanada',
+ 'UserCountry_country_ca' => 'Canada',
'UserCountry_country_cc' => 'Cocos (Keeling) Islands',
'UserCountry_country_cd' => 'Congo, The Democratic Republic of the',
'UserCountry_country_cf' => 'Central African Republic',
- 'UserCountry_country_cg' => 'Kongo',
- 'UserCountry_country_ch' => 'Szwajcaria',
+ 'UserCountry_country_cg' => 'Congo',
+ 'UserCountry_country_ch' => 'Switzerland',
'UserCountry_country_ci' => 'Cote D\'Ivoire',
'UserCountry_country_ck' => 'Cook Islands',
'UserCountry_country_cl' => 'Chile',
'UserCountry_country_cm' => 'Cameroon',
- 'UserCountry_country_cn' => 'Chiny',
- 'UserCountry_country_co' => 'Kolumbia',
+ 'UserCountry_country_cn' => 'China',
+ 'UserCountry_country_co' => 'Colombia',
+ 'UserCountry_country_cp' => 'Clipperton Island',
'UserCountry_country_cr' => 'Costa Rica',
'UserCountry_country_cs' => 'Serbia Montenegro',
- 'UserCountry_country_cu' => 'Kuba',
+ 'UserCountry_country_cu' => 'Cuba',
'UserCountry_country_cv' => 'Cape Verde',
'UserCountry_country_cx' => 'Christmas Island',
- 'UserCountry_country_cy' => 'Cypr',
- 'UserCountry_country_cz' => 'Czechy',
- 'UserCountry_country_de' => 'Niemcy',
+ 'UserCountry_country_cy' => 'Cyprus',
+ 'UserCountry_country_cz' => 'Czech Republic',
+ 'UserCountry_country_de' => 'Germany',
+ 'UserCountry_country_dg' => 'Diego Garcia',
'UserCountry_country_dj' => 'Djibouti',
- 'UserCountry_country_dk' => 'Dania',
+ 'UserCountry_country_dk' => 'Denmark',
'UserCountry_country_dm' => 'Dominica',
'UserCountry_country_do' => 'Dominican Republic',
'UserCountry_country_dz' => 'Algeria',
- 'UserCountry_country_ec' => 'Ekwador',
+ 'UserCountry_country_ea' => 'Ceuta, Melilla',
+ 'UserCountry_country_ec' => 'Ecuador',
'UserCountry_country_ee' => 'Estonia',
- 'UserCountry_country_eg' => 'Egipt',
+ 'UserCountry_country_eg' => 'Egypt',
'UserCountry_country_eh' => 'Western Sahara',
'UserCountry_country_er' => 'Eritrea',
- 'UserCountry_country_es' => 'Hiszpania',
+ 'UserCountry_country_es' => 'Spain',
'UserCountry_country_et' => 'Ethiopia',
- 'UserCountry_country_fi' => 'Finlandia',
+ 'UserCountry_country_eu' => 'European Union',
+ 'UserCountry_country_fi' => 'Finland',
'UserCountry_country_fj' => 'Fiji',
'UserCountry_country_fk' => 'Falkland Islands (Malvinas)',
'UserCountry_country_fm' => 'Micronesia, Federated States of',
'UserCountry_country_fo' => 'Faroe Islands',
- 'UserCountry_country_fr' => 'Francja',
+ 'UserCountry_country_fr' => 'France',
+ 'UserCountry_country_fx' => 'France, Metropolitan',
'UserCountry_country_ga' => 'Gabon',
+ 'UserCountry_country_gb' => 'Great Britain',
'UserCountry_country_gd' => 'Grenada',
'UserCountry_country_ge' => 'Georgia',
'UserCountry_country_gf' => 'French Guyana',
@@ -271,7 +663,7 @@ $translations = array(
'UserCountry_country_gn' => 'Guinea',
'UserCountry_country_gp' => 'Guadeloupe',
'UserCountry_country_gq' => 'Equatorial Guinea',
- 'UserCountry_country_gr' => 'Grecja',
+ 'UserCountry_country_gr' => 'Greece',
'UserCountry_country_gs' => 'South Georgia and the South Sandwich Islands',
'UserCountry_country_gt' => 'Guatemala',
'UserCountry_country_gu' => 'Guam',
@@ -282,21 +674,22 @@ $translations = array(
'UserCountry_country_hn' => 'Honduras',
'UserCountry_country_hr' => 'Croatia',
'UserCountry_country_ht' => 'Haiti',
- 'UserCountry_country_hu' => 'Węgry',
- 'UserCountry_country_id' => 'Indonezja',
- 'UserCountry_country_ie' => 'Irlandia',
- 'UserCountry_country_il' => 'Izrael',
+ 'UserCountry_country_hu' => 'Hungary',
+ 'UserCountry_country_ic' => 'Canary Islands',
+ 'UserCountry_country_id' => 'Indonesia',
+ 'UserCountry_country_ie' => 'Ireland',
+ 'UserCountry_country_il' => 'Israel',
'UserCountry_country_im' => 'Man Island',
- 'UserCountry_country_in' => 'Indie',
+ 'UserCountry_country_in' => 'India',
'UserCountry_country_io' => 'British Indian Ocean Territory',
- 'UserCountry_country_iq' => 'Irak',
+ 'UserCountry_country_iq' => 'Iraq',
'UserCountry_country_ir' => 'Iran, Islamic Republic of',
'UserCountry_country_is' => 'Iceland',
- 'UserCountry_country_it' => 'Włochy',
+ 'UserCountry_country_it' => 'Italy',
'UserCountry_country_je' => 'Jersey',
'UserCountry_country_jm' => 'Jamaica',
'UserCountry_country_jo' => 'Jordan',
- 'UserCountry_country_jp' => 'Japonia',
+ 'UserCountry_country_jp' => 'Japan',
'UserCountry_country_ke' => 'Kenya',
'UserCountry_country_kg' => 'Kyrgyzstan',
'UserCountry_country_kh' => 'Cambodia',
@@ -307,7 +700,7 @@ $translations = array(
'UserCountry_country_kr' => 'Korea, Republic of',
'UserCountry_country_kw' => 'Kuwait',
'UserCountry_country_ky' => 'Cayman Islands',
- 'UserCountry_country_kz' => 'Kazachstan',
+ 'UserCountry_country_kz' => 'Kazakhstan',
'UserCountry_country_la' => 'Laos',
'UserCountry_country_lb' => 'Lebanon',
'UserCountry_country_lc' => 'Saint Lucia',
@@ -315,13 +708,15 @@ $translations = array(
'UserCountry_country_lk' => 'Sri Lanka',
'UserCountry_country_lr' => 'Liberia',
'UserCountry_country_ls' => 'Lesotho',
- 'UserCountry_country_lt' => 'Litwa',
+ 'UserCountry_country_lt' => 'Lithuania',
'UserCountry_country_lu' => 'Luxembourg',
- 'UserCountry_country_lv' => 'Łotwa',
+ 'UserCountry_country_lv' => 'Latvia',
'UserCountry_country_ly' => 'Libya',
'UserCountry_country_ma' => 'Morocco',
'UserCountry_country_mc' => 'Monaco',
'UserCountry_country_md' => 'Moldova, Republic of',
+ 'UserCountry_country_me' => 'Montenegro',
+ 'UserCountry_country_mf' => 'Saint Martin',
'UserCountry_country_mg' => 'Madagascar',
'UserCountry_country_mh' => 'Marshall Islands',
'UserCountry_country_mk' => 'Macedonia',
@@ -337,7 +732,7 @@ $translations = array(
'UserCountry_country_mu' => 'Mauritius',
'UserCountry_country_mv' => 'Maldives',
'UserCountry_country_mw' => 'Malawi',
- 'UserCountry_country_mx' => 'Meksyk',
+ 'UserCountry_country_mx' => 'Mexico',
'UserCountry_country_my' => 'Malaysia',
'UserCountry_country_mz' => 'Mozambique',
'UserCountry_country_na' => 'Namibia',
@@ -347,11 +742,12 @@ $translations = array(
'UserCountry_country_ng' => 'Nigeria',
'UserCountry_country_ni' => 'Nicaragua',
'UserCountry_country_nl' => 'Netherlands',
- 'UserCountry_country_no' => 'Norwegia',
+ 'UserCountry_country_no' => 'Norway',
'UserCountry_country_np' => 'Nepal',
'UserCountry_country_nr' => 'Nauru',
+ 'UserCountry_country_nt' => 'Neutral Zone',
'UserCountry_country_nu' => 'Niue',
- 'UserCountry_country_nz' => 'Nowa Zelandia',
+ 'UserCountry_country_nz' => 'New Zealand',
'UserCountry_country_om' => 'Oman',
'UserCountry_country_pa' => 'Panama',
'UserCountry_country_pe' => 'Peru',
@@ -359,30 +755,31 @@ $translations = array(
'UserCountry_country_pg' => 'Papua New Guinea',
'UserCountry_country_ph' => 'Philippines',
'UserCountry_country_pk' => 'Pakistan',
- 'UserCountry_country_pl' => 'Polska',
+ 'UserCountry_country_pl' => 'Poland',
'UserCountry_country_pm' => 'Saint Pierre and Miquelon',
'UserCountry_country_pn' => 'Pitcairn',
'UserCountry_country_pr' => 'Puerto Rico',
'UserCountry_country_ps' => 'Palestinian Territory',
- 'UserCountry_country_pt' => 'Portugalia',
+ 'UserCountry_country_pt' => 'Portugal',
'UserCountry_country_pw' => 'Palau',
'UserCountry_country_py' => 'Paraguay',
'UserCountry_country_qa' => 'Qatar',
'UserCountry_country_re' => 'Reunion Island',
- 'UserCountry_country_ro' => 'Rumunia',
- 'UserCountry_country_ru' => 'Rosja',
+ 'UserCountry_country_ro' => 'Romania',
+ 'UserCountry_country_ru' => 'Russia',
'UserCountry_country_rs' => 'Serbia',
'UserCountry_country_rw' => 'Rwanda',
'UserCountry_country_sa' => 'Saudi Arabia',
'UserCountry_country_sb' => 'Solomon Islands',
'UserCountry_country_sc' => 'Seychelles',
'UserCountry_country_sd' => 'Sudan',
- 'UserCountry_country_se' => 'Szwecja',
+ 'UserCountry_country_se' => 'Sweden',
+ 'UserCountry_country_sf' => 'Finland',
'UserCountry_country_sg' => 'Singapore',
'UserCountry_country_sh' => 'Saint Helena',
- 'UserCountry_country_si' => 'Słowenia',
+ 'UserCountry_country_si' => 'Slovenia',
'UserCountry_country_sj' => 'Svalbard',
- 'UserCountry_country_sk' => 'Słowacja',
+ 'UserCountry_country_sk' => 'Slovakia',
'UserCountry_country_sl' => 'Sierra Leone',
'UserCountry_country_sm' => 'San Marino',
'UserCountry_country_sn' => 'Senegal',
@@ -393,26 +790,27 @@ $translations = array(
'UserCountry_country_sv' => 'El Salvador',
'UserCountry_country_sy' => 'Syrian Arab Republic',
'UserCountry_country_sz' => 'Swaziland',
+ 'UserCountry_country_ta' => 'Tristan da Cunha',
'UserCountry_country_tc' => 'Turks and Caicos Islands',
'UserCountry_country_td' => 'Chad',
'UserCountry_country_tf' => 'French Southern Territories',
'UserCountry_country_tg' => 'Togo',
- 'UserCountry_country_th' => 'Tajlandia',
+ 'UserCountry_country_th' => 'Thailand',
'UserCountry_country_tj' => 'Tajikistan',
'UserCountry_country_tk' => 'Tokelau',
+ 'UserCountry_country_tl' => 'East Timor',
'UserCountry_country_tm' => 'Turkmenistan',
'UserCountry_country_tn' => 'Tunisia',
'UserCountry_country_to' => 'Tonga',
'UserCountry_country_tp' => 'East Timor',
- 'UserCountry_country_tr' => 'Turcja',
+ 'UserCountry_country_tr' => 'Turkey',
'UserCountry_country_tt' => 'Trinidad and Tobago',
'UserCountry_country_tv' => 'Tuvalu',
'UserCountry_country_tw' => 'Taiwan',
'UserCountry_country_tz' => 'Tanzania, United Republic of',
- 'UserCountry_country_ua' => 'Ukraina',
+ 'UserCountry_country_ua' => 'Ukraine',
'UserCountry_country_ug' => 'Uganda',
'UserCountry_country_uk' => 'United Kingdom',
- 'UserCountry_country_gb' => 'Great Britain',
'UserCountry_country_um' => 'United States Minor Outlying Islands',
'UserCountry_country_us' => 'United States',
'UserCountry_country_uy' => 'Uruguay',
@@ -433,178 +831,121 @@ $translations = array(
'UserCountry_country_zm' => 'Zambia',
'UserCountry_country_zr' => 'Zaire',
'UserCountry_country_zw' => 'Zimbabwe',
- 'UserCountry_continent_eur' => 'Europa',
- 'UserCountry_continent_afr' => 'Afryka',
- 'UserCountry_continent_asi' => 'Azja',
- 'UserCountry_continent_ams' => 'Południowa i środkowa Ameryka',
- 'UserCountry_continent_amn' => 'Północna Ameryka',
+ 'UserCountry_continent_eur' => 'Europe',
+ 'UserCountry_continent_afr' => 'Africa',
+ 'UserCountry_continent_asi' => 'Asia',
+ 'UserCountry_continent_ams' => 'South and Central America',
+ 'UserCountry_continent_amn' => 'North America',
'UserCountry_continent_oce' => 'Oceania',
- 'VisitsSummary_NbVisits' => '%s wizyt',
- 'VisitsSummary_NbUniqueVisitors' => '%s unikalnych gości',
- 'VisitsSummary_NbActions' => '%s akcje (odsłony strony)',
- 'VisitsSummary_TotalTime' => '%s całkowity czas spędzony na stronie',
- 'VisitsSummary_MaxNbActions' => '%s maksymalne akcje podczas jednej wizyty',
- 'VisitsSummary_NbBounced' => '%s goście odrzucający (opuścili stronę po obejrzeniu jednej strony)',
- 'VisitsSummary_Evolution' => 'Postęp ostatnich 30 %s',
- 'VisitsSummary_Report' => 'Raport',
- 'VisitsSummary_GenerateTime' => 'Czas wygenerowania strony: %s sekund',
- 'VisitsSummary_GenerateQueries' => '%s wykonanych zapytań',
- 'VisitsSummary_WidgetLastVisits' => 'Wykres ostatnich wizyty',
- 'VisitsSummary_WidgetVisits' => 'przegląd wizyt',
- 'VisitsSummary_WidgetLastVisitors' => 'Wykres ostatnich unikalnych gości',
- 'VisitsSummary_WidgetOverviewGraph' => 'Wykres z przeglądem',
- 'VisitsSummary_SubmenuOverview' => 'Przegląd',
- 'VisitFrequency_Evolution' => 'Rozwój na cykl',
- 'VisitFrequency_ReturnVisits' => '%s wizyt ponownych',
- 'VisitFrequency_ReturnActions' => '%s akcji przy ponownych wizytach',
- 'VisitFrequency_ReturnMaxActions' => '%s maksymalnych akcji przy ponownych wizytach',
- 'VisitFrequency_ReturnTotalTime' => '%s całkowity czas spędzony przy ponownych wizytach',
- 'VisitFrequency_ReturnBounces' => '%s czasy ponownych odrzuconych wizyt (wyjścia ze strony po obejrzeniu jednej strony)',
- 'VisitFrequency_WidgetOverview' => 'Częstotliwość przeglądu',
- 'VisitFrequency_WidgetGraphReturning' => 'Wykres ponownych wizyt',
- 'VisitFrequency_SubmenuFrequency' => 'częstotliwość',
- 'VisitTime_LocalTime' => 'Wizyt czasu lokalnego',
- 'VisitTime_ServerTime' => 'Wizyt czasu serwera',
- 'VisitTime_WidgetLocalTime' => 'Wizyty czasu lokalnego',
- 'VisitTime_WidgetServerTime' => 'Wizyty czasu serwera',
- 'VisitTime_SubmenuTimes' => 'Czasy',
- 'VisitTime_NHour' => '%sh',
- 'VisitorInterest_VisitsPerDuration' => 'Wizyt na czas wizyty',
- 'VisitorInterest_VisitsPerNbOfPages' => 'Wizyt na ilość stron',
- 'VisitorInterest_WidgetLengths' => 'Długość wizyty',
- 'VisitorInterest_WidgetPages' => 'Strion na wizytę',
- 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Częstotliwość i lojalność',
- 'VisitorInterest_PlusXMin' => '%s min',
- 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
- 'VisitorInterest_OnePage' => '1 strona',
- 'VisitorInterest_NPages' => '%s stron',
- 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
- 'Login_LoginPasswordNotCorrect' => 'Nazwa użytkownika i hasło niepoprawne',
- 'Login_Login' => 'Nazwa użytkownika',
- 'Login_Password' => 'Hasło',
- 'Login_LoginOrEmail' => 'Nazwa użytkownika albo email',
- 'Login_LogIn' => 'Zaloguj',
- 'Login_Logout' => 'Wyloguj',
- 'Login_LostYourPassword' => 'Zapomniałeś hasło?',
- 'Login_RemindPassword' => 'Przypomnij hasło',
- 'Login_PasswordReminder' => 'Wprowadź nazwę użytkownika albo adres email. Otrzymasz nowe email z nowym hasłem.',
- 'Login_InvalidUsernameEmail' => 'Nieprawidłowa nazwa użytkownika i/lub adress e-mail',
- 'Login_MailTopicPasswordRecovery' => 'Odzyskiwanie hasła',
- 'Login_MailPasswordRecoveryBody' => 'Witaj %1s, \n\n Twoje nowe hasło to: %2s \n\n Możesz się teraz zalogować: %3s',
- 'Login_PasswordSent' => 'Hasło zostało wysłane - sprawdź email.',
- 'Login_ContactAdmin' => 'Możliwości: Twój host może może mieć zablokowaną funkcję mail(). <br>Skontakuj się z administratorem Piwik\'a.',
- 'UsersManager_UsersManagement' => 'Zarządzanie użytkownikami',
- 'UsersManager_UsersManagementMainDescription' => 'Twórz nowych użytkowników lub aktualizuj już istniejących. Powyżej będziesz mógł ustawić odpowiednie uprawnienia dla każdego użytkownika.',
- 'UsersManager_ManageAccess' => 'Zarządzaj dostępem',
- 'UsersManager_MainDescription' => 'Decyduj którzy użytkownicy mają dostęp do Piwik\'a na twojej witrynie. Możesz również ustawiać uprawnienia dla wszystkich witryn za jednym razem.',
- 'UsersManager_Sites' => 'Strony',
- 'UsersManager_AllWebsites' => 'Wszystkie strony',
- 'UsersManager_ApplyToAllWebsites' => 'Zastosuj do wszystkich stron',
- 'UsersManager_User' => 'Użytkownik',
- 'UsersManager_PrivNone' => 'Brak dostępu',
- 'UsersManager_PrivView' => 'Widok',
+ 'UserSettings_PluginDescription' => 'Reports various User Settings: Browser, Browser Family, Operating System, Plugins, Resolution, Global Settings.',
+ 'UserSettings_VisitorSettings' => 'Visitor Settings',
+ 'UserSettings_BrowserFamilies' => 'Rodzina przeglądarek',
+ 'UserSettings_Browsers' => 'Przeglądarki',
+ 'UserSettings_Plugins' => 'Wtyczki',
+ 'UserSettings_Configurations' => 'Konfiguracja',
+ 'UserSettings_OperatingSystems' => 'Systemy operacyjne',
+ 'UserSettings_Resolutions' => 'Rozdzielczość',
+ 'UserSettings_WideScreen' => 'Wyświetlacze: zwykłe/panoramiczne',
+ 'UserSettings_ColumnBrowserFamily' => 'Rodzina przeglądarek',
+ 'UserSettings_ColumnBrowser' => 'Przeglądarka',
+ 'UserSettings_ColumnPlugin' => 'Wtyczki',
+ 'UserSettings_ColumnConfiguration' => 'Konfiguracja',
+ 'UserSettings_ColumnOperatingSystem' => 'System operacyjny',
+ 'UserSettings_ColumnResolution' => 'Rozdzielczość',
+ 'UserSettings_ColumnTypeOfScreen' => 'Rodzaj wyświetlacza',
+ 'UserSettings_WidgetResolutions' => 'Rozdzielczość',
+ 'UserSettings_WidgetBrowsers' => 'Przeglądarki użytkowników',
+ 'UserSettings_WidgetPlugins' => 'Lista wtyczek',
+ 'UserSettings_WidgetWidescreen' => 'Zwykłe/Panoramiczne',
+ 'UserSettings_WidgetBrowserFamilies' => 'Przeglądarki na rodziny',
+ 'UserSettings_WidgetOperatingSystems' => 'Systemy operacyjne',
+ 'UserSettings_WidgetGlobalVisitors' => 'Konfiguracja główna wizyt',
+ 'UserSettings_SubmenuSettings' => 'Ustawienia',
+ 'UsersManager_PluginDescription' => 'Users Management in Piwik: add a new User, edit an existing one, update the permissions. All the actions are also available through the API.',
+ 'UsersManager_UsersManagement' => 'Users Management',
+ 'UsersManager_UsersManagementMainDescription' => 'Create new users or update the existing users. You can then set their permissions above.',
+ 'UsersManager_ManageAccess' => 'Manage access',
+ 'UsersManager_MainDescription' => 'Decide which users have which Piwik access on your Websites. You can also set the permissions on all the Websites at once.',
+ 'UsersManager_Sites' => 'Websites',
+ 'UsersManager_AllWebsites' => 'All websites',
+ 'UsersManager_ApplyToAllWebsites' => 'Apply to all websites',
+ 'UsersManager_User' => 'User',
+ 'UsersManager_PrivNone' => 'No access',
+ 'UsersManager_PrivView' => 'View',
'UsersManager_PrivAdmin' => 'Admin',
'UsersManager_ChangeAllConfirm' => 'Czy jesteś pewien że chcesz zmienić \'%s\' prawa na wszystkich stronach?',
'UsersManager_Login' => 'Nazwa użytkownika',
'UsersManager_Password' => 'Hasło',
'UsersManager_Email' => 'Email',
'UsersManager_Alias' => 'Alias',
- 'UsersManager_Token' => 'token_auth',
'UsersManager_Edit' => 'Edycja',
'UsersManager_AddUser' => 'Dodaj nowego użytkownika',
'UsersManager_MenuUsers' => 'Użytkownicy',
'UsersManager_DeleteConfirm_js' => 'Czy jesteś pewien czy chcesz skasować użytkownika %s?',
'UsersManager_ExceptionLoginExists' => 'Nazwa użytkownika \'%s\' już istnieje.',
'UsersManager_ExceptionEmailExists' => 'Użytkownik z emailem \'%s\' już istnieje.',
- 'UsersManager_ExceptionInvalidLogin' => 'Nazwa użytkownika może zawierać tylko litery, cyfry i znaki \'_\' albo \'-\' albo \'.\'',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'The login must be between %1$s and %2$s characters long and contain only letters, numbers, or the characters \'_\' or \'-\' or \'.\'',
'UsersManager_ExceptionInvalidPassword' => 'Długość hasła musi być pomiędzy 6 i 26 znaków.',
'UsersManager_ExceptionInvalidEmail' => 'Email ma niepoprawny format.',
'UsersManager_ExceptionDeleteDoesNotExist' => 'Użytkownik \'%s\' nie istnieje lub nie może być skasowany.',
'UsersManager_ExceptionAdminAnonymous' => 'Nie możesz przydzielić statusu \'admin\' dla użytkownika \'anonymous\'.',
'UsersManager_ExceptionEditAnonymous' => 'Użytkownik anonimowy nie może być zmieniony lub skasowany. Używany jest przez Piwik to do definicji użytkownika nie zalogowanego. Dla przykładu możesz ustawić swoje statystyki do wglądu dla wszystkich poprzez przyznanie prawa wglądu użytkownikowi anonimowemu \'anonymous\'.',
+ 'UsersManager_ExceptionSuperUser' => 'Requested user is the Super User and cannot be queried, edited or deleted via the API. You can manually edit the Super User details in your Piwik configuration file.',
'UsersManager_ExceptionUserDoesNotExist' => 'Użytkownik \'%s\' nie istnieje.',
'UsersManager_ExceptionAccessValues' => 'Parametr dostępu musi zawierać jedna z następujących wartości : [ %s ]',
- 'SitesManager_Sites' => 'Strony',
- 'SitesManager_WebsitesManagement' => 'Zarządzanie witrynami',
- 'SitesManager_MainDescription' => 'Raporty analizy potrzebują witryn! Dodawaj, aktualizuj, usuwaj witryny, a następnie wyświetlaj i wstawiaj kod Javascript na swojej stronie.',
- 'SitesManager_JsCode' => 'Kod Javascript',
- 'SitesManager_JsCodeHelp' => 'Tutaj jest kod javascript, który należy umieścić na wszystkich twoich stronach',
- 'SitesManager_ShowJsCode' => 'Pokaż kod',
- 'SitesManager_NoWebsites' => 'Nie masz żadnej witryny do zarządzania.',
- 'SitesManager_AddSite' => 'Dodaj nową witrynę',
- 'SitesManager_Id' => 'Id',
- 'SitesManager_Name' => 'nazwa',
- 'SitesManager_Urls' => 'URL\'e',
- 'SitesManager_MenuSites' => 'Witryny',
- 'SitesManager_DeleteConfirm_js' => 'Czy jesteś pewien że chcesz skasować witrynę %s?',
- 'SitesManager_ExceptionDeleteSite' => 'Nie jest możliwe skasowanie tej witryny, ponieważ to jest jedyna zarejestrowana witryna. Dodaj nową witrynę i wtedy skasuj jedną.',
- 'SitesManager_ExceptionNoUrl' => 'Musisz określić przynajmniej jeden URL do twojej witryny.',
- 'SitesManager_ExceptionEmptyName' => 'Nazwa witryny nie może być pusta.',
- 'SitesManager_ExceptionInvalidUrl' => 'URL \'%s\' nie jest poprawnym URL\'em.',
- 'Installation_Installation' => 'Instalacja',
- 'Installation_InstallationStatus' => 'Status instalacji',
- 'Installation_PercentDone' => '%s %% Gotowe',
- 'Installation_NoConfigFound' => 'Plik konfiguracji Piwik\'a nie został odnaleziony a ty próbujesz się dostać do Piwik\'a.<br><b>&nbsp;&nbsp;&raquo; Możesz <a href=\'index.php\'>zainstalować Piwik\'a teraz</a></b><br><small>Jeżeli instalowałeś Piwik\'a wcześniej i istnieją tabele w twojej bazie, nie martw się możesz użyć ponownie te same tabele i zachować istniejące dane!</small>',
- 'Installation_MysqlSetup' => 'Instalacja bazy Mysql',
- 'Installation_MysqlErrorConnect' => 'Błąd podczas próby połączenia z bazą Mysql',
- 'Installation_JsTag' => 'Javascript tag',
- 'Installation_JsTagHelp' => '<p>By zliczyć wszystich gości, musiż dołączyć kod javascript code na wszystkich stronach.</p><p>Twoje strony nie muszą być stworzone w PHP, Piwik współpracuje z wszystkimi rodzajami stron (HTML, ASP, Perl czy inny język).</p><p>Tutaj znajduje się kod który musisz wkleić: (kopij i wklej na wszystkich twoich stronach) </p>',
- 'Installation_Congratulations' => 'Gratulacje',
- 'Installation_CongratulationsHelp' => '<p>Gratulacje! Twója instalacja Piwik\'a została zakończona.</p><p>Upewnij się że kod javascript został wprowadzony do twoich stron i czekaj na pierwsza wizytę!</p>',
- 'Installation_GoToPiwik' => 'Idź do Piwik\'a',
- 'Installation_SetupWebsite' => 'Ustaw witrynę',
- 'Installation_SetupWebsiteError' => 'Wystąpił błąd podczas dodawania witryny',
- 'Installation_GeneralSetup' => 'Ustawienia główne',
- 'Installation_GeneralSetupSuccess' => 'Ustawienia główne skonfigurowano poprawnie',
- 'Installation_SystemCheck' => 'Weryfikacja systemu',
- 'Installation_SystemCheckPhp' => 'Wersja PHP',
- 'Installation_SystemCheckPdo' => 'Rozszerzenie Pdo',
- 'Installation_SystemCheckPdoMysql' => 'Rozszerzenie Pdo_Mysql',
- 'Installation_SystemCheckPdoError' => 'Musisz włączyć PDO i PDO_MYSQL rozszerzenia w pliku php.ini.',
- 'Installation_SystemCheckPdoHelp' => 'Na serwerach windows musisz dodać następującą linijkę w your php.ini %s <br><br>Na serwerach Linux musisz skompilować php z opcją %s W pliku php.ini, dodaj następujące linie %s<br><br>Więcej informacji znajdziesz na <a style="color:red" href="http://php.net/pdo">PHP.net</a>.',
- 'Installation_SystemCheckWriteDirs' => 'Katalog z prawem do zapisu',
- 'Installation_SystemCheckWriteDirsHelp' => 'By naprawić ten błąd na serwerach Linux spróbuj wykonać następujące polecenia',
- 'Installation_SystemCheckMemoryLimit' => 'Limit pamięci',
- 'Installation_SystemCheckMemoryLimitHelp' => 'Na stronach z dużym ruchem, proces archiwizacji może wymagać więcej pamięci niż jest aktualnie przydzielone.<br> Sprawdź dyrektywę memory_limit w pliku php.ini jeżeli to będzie konieczne.',
- 'Installation_SystemCheckGD' => 'GD &gt; 2.x (grafika)',
- 'Installation_SystemCheckGDHelp' => 'Sparklines (mały graf) nie pracuje.',
- 'Installation_SystemCheckTimeLimit' => 'set_time_limit() dozwolone',
- 'Installation_SystemCheckTimeLimitHelp' => 'Na stronach z dużym ruchem, proces archiwizacji może wymagać więcej czasu niż jest aktualnie przydzielone.<br>Sprawdź dyrektywę max_execution_time w pliku php.ini jeżeli to będzie konieczne.',
- 'Installation_SystemCheckMail' => 'mail() dozwolone',
- 'Installation_SystemCheckError' => 'Wystąpił błąd - zanim będziesz kontynuował zweryfikuj błąd',
- 'Installation_SystemCheckWarning' => 'Piwik będzie pracował normalnie aczkolwiek pewne właściwości będą niedostępne ',
- 'Installation_Tables' => 'Tworzenie tabel',
- 'Installation_TablesWarning' => 'Pewne <span id="linkToggle">tabele Piwik\'a</span> istnieją w bazie',
- 'Installation_TablesFound' => 'Następujące tabele zostały znalezione w bazie',
- 'Installation_TablesWarningHelp' => 'Jakikolwiek wybór by użyć table w istniejącej bazie czy wybranie opcji czyszczenia instalacji wykazuje istniejące w bazie.',
- 'Installation_TablesReuse' => 'Użyj istniejące tabele',
- 'Installation_TablesDelete' => 'Skasuj wykryte tabele',
- 'Installation_TablesDeletedSuccess' => 'Istniejące tabele Piwik\'a skasowano poprawnie',
- 'Installation_TablesCreatedSuccess' => 'Tabele stworzone z powodzeniem!',
- 'Installation_DatabaseCreatedSuccess' => 'Database %s created with success!',
- 'Installation_TablesDeleteConfirm' => 'Czy jesteś przekonany ze chcesz skasować wszystkie tabele Piwik\'az tej bazy?',
- 'Installation_Welcome' => 'Witka!',
- 'Installation_WelcomeHelp' => '<p>Piwik to wolne (open source) oprogramowanie do analizy ruchu na stronach internetowych, który w łatwy sposób pobierze informacje o wizytach na twojej stronie.</p><p>Proces jest podzielony na %s łatwe kroki i zajmie około 5 minut.</p>',
- 'Provider_WidgetProviders' => 'Dostawca',
- 'Provider_SubmenuLocationsProvider' => 'Lokalizacje i dostawca',
- 'DBStats_DatabaseUsage' => 'Database usage',
- 'DBStats_MainDescription' => 'Piwik is storing all your web analytics data in the Mysql database. Currently, Piwik tables are using %s.',
- 'DBStats_Table' => 'Tabela',
- 'DBStats_RowNumber' => 'Row number',
- 'DBStats_DataSize' => 'Data size',
- 'DBStats_IndexSize' => 'Index size',
- 'DBStats_TotalSize' => 'Total size',
- 'TranslationsAdmin_MenuTranslations' => 'Tłumaczenia',
- 'TranslationsAdmin_MenuLanguages' => 'Języki',
- 'TranslationsAdmin_Plugin' => 'Plugin\'y',
- 'TranslationsAdmin_Definition' => 'Definicje',
- 'TranslationsAdmin_DefaultString' => 'Domyślny tekst',
- 'TranslationsAdmin_TranslationString' => 'Tekst tłumaczenia (aktualny język: %s)',
- 'TranslationsAdmin_Translations' => 'Tłumaczenia',
- 'TranslationsAdmin_FixPermissions' => 'Sprawdź prawa zapisu',
- 'TranslationsAdmin_AvailableLanguages' => 'Dostępne języki',
- 'TranslationsAdmin_AddLanguage' => 'Dodaj język',
- 'TranslationsAdmin_LanguageCode' => 'Kod języka',
- 'TranslationsAdmin_Export' => 'Eksportuj język',
- 'TranslationsAdmin_Import' => 'Importuj język',
+ 'VisitFrequency_PluginDescription' => 'Reports various statistics about the Returning Visitor versus the First time visitor.',
+ 'VisitFrequency_Evolution' => 'Rozwój na cykl',
+ 'VisitFrequency_ColumnReturningVisits' => 'Ponowne wizyty',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Actions by Returning Visits',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Maximum Actions by a Returning Visit',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Total time spent by Returning Visits (in seconds)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Bounce rate for Returning Visits',
+ 'VisitFrequency_ReturnVisits' => '%s wizyt ponownych',
+ 'VisitFrequency_ReturnActions' => '%s akcji przy ponownych wizytach',
+ 'VisitFrequency_ReturnMaxActions' => '%s maksymalnych akcji przy ponownych wizytach',
+ 'VisitFrequency_ReturnTotalTime' => '%s całkowity czas spędzony przy ponownych wizytach',
+ 'VisitFrequency_ReturnBounceRate' => '%s czasy ponownych odrzuconych wizyt (wyjścia ze strony po obejrzeniu jednej strony)',
+ 'VisitFrequency_WidgetOverview' => 'Przegląd poracających',
+ 'VisitFrequency_WidgetGraphReturning' => 'Użytkownicy powracający',
+ 'VisitFrequency_SubmenuFrequency' => 'częstotliwość',
+ 'VisitorInterest_PluginDescription' => 'Reports about the Visitor Interest: number of pages viewed, time spent on the Website.',
+ 'VisitorInterest_VisitsPerDuration' => 'Wizyt na czas wizyty',
+ 'VisitorInterest_VisitsPerNbOfPages' => 'Wizyt na ilość stron',
+ 'VisitorInterest_ColumnVisitDuration' => 'Długość wizyty',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Ilość przejrzanych podstron',
+ 'VisitorInterest_WidgetLengths' => 'Średni czas odwiedzin',
+ 'VisitorInterest_WidgetPages' => 'Stron na wizytę',
+ 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Częstotliwość i lojalność',
+ 'VisitorInterest_PlusXMin' => '%s min',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
+ 'VisitorInterest_OnePage' => '1 strona',
+ 'VisitorInterest_NPages' => '%s stron',
+ 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
+ 'VisitsSummary_PluginDescription' => 'Reports the general Analytics numbers: visits, unique visitors, number of actions, Bounce Rate, etc.',
+ 'VisitsSummary_VisitsSummary' => 'Visits Summary',
+ 'VisitsSummary_NbVisits' => '%s wizyt',
+ 'VisitsSummary_NbUniqueVisitors' => '%s unikalnych użytkowników',
+ 'VisitsSummary_NbActionsDescription' => '%s akcje (przeglądanie, ściąganie plików i linki wychodzące)',
+ 'VisitsSummary_TotalTime' => '%s całkowity czas spędzony na stronie',
+ 'VisitsSummary_MaxNbActions' => '%s największa liczba wykonanych akcji podczas jednej wizyty',
+ 'VisitsSummary_NbVisitsBounced' => '%s odrzuceń (porzucono witrynę po obejrzeniu jednej strony)',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Zmiany: ostatnie %s',
+ 'VisitsSummary_Report' => 'Raport',
+ 'VisitsSummary_GenerateTime' => 'Czas wygenerowania strony: %s sekund',
+ 'VisitsSummary_GenerateQueries' => '%s wykonanych zapytań',
+ 'VisitsSummary_WidgetLastVisits' => 'Odwiedziny w ostatnim miesiącu',
+ 'VisitsSummary_WidgetVisits' => 'Przegląd wizyt',
+ 'VisitsSummary_WidgetLastVisitors' => 'Wykres ostatnich unikalnych użytkowników',
+ 'VisitsSummary_WidgetOverviewGraph' => 'Wykres z przeglądem',
+ 'VisitsSummary_SubmenuOverview' => 'Przegląd',
+ 'VisitTime_PluginDescription' => 'Reports the Local and Server time. Server time information can be useful to schedule a maintenance on the Website.',
+ 'VisitTime_LocalTime' => 'Odwiedziny (czas lokalny)',
+ 'VisitTime_ServerTime' => 'Odwiedziny (czas serwera)',
+ 'VisitTime_ColumnServerTime' => 'Czas serwera',
+ 'VisitTime_ColumnLocalTime' => 'Czas lokalny',
+ 'VisitTime_WidgetLocalTime' => 'Odwiedziny (czas lokalny)',
+ 'VisitTime_WidgetServerTime' => 'Odwiedziny (czas serwera)',
+ 'VisitTime_SubmenuTimes' => 'Czasy',
+ 'VisitTime_NHour' => '%sh',
+ 'Widgetize_PluginDescription' => 'The plugin makes it very easy to export any Piwik Widget in your Blog, Website or on Igoogle and Netvibes!',
);
diff --git a/lang/pt-br.php b/lang/pt-br.php
new file mode 100644
index 0000000000..a2c1af9d93
--- /dev/null
+++ b/lang/pt-br.php
@@ -0,0 +1,1096 @@
+<?php
+
+setlocale(LC_TIME, 'pt_BR.UTF-8');
+
+$translations = array(
+ 'General_Locale' => 'pt_BR.UTF-8',
+ 'General_TranslatorName' => 'Marcos Napier, Marcela Ferraro
+
+',
+ 'General_TranslatorEmail' => 'marcusbacus@gmail.com, mah_ferraro@yahoo.com.br',
+ 'General_EnglishLanguageName' => 'Brazilian Portuguese',
+ 'General_OriginalLanguageName' => 'Portugu&ecirc;s brasileiro',
+ 'General_Unknown' => 'Desconhecido',
+ 'General_Required' => '%s necess&aacute;rio',
+ 'General_Error' => 'Erro',
+ 'General_Warning' => 'Aviso',
+ 'General_BackToHomepage' => 'Voltar a p&aacute;gina do Piwik',
+ 'General_Yes' => 'Sim',
+ 'General_No' => 'N&atilde;o',
+ 'General_Delete' => 'Apagar',
+ 'General_Edit' => 'Editar',
+ 'General_Ok' => 'Ok',
+ 'General_Close' => 'Fechar',
+ 'General_Logout' => 'Sair',
+ 'General_Done' => 'Pronto',
+ 'General_LoadingData' => 'Carregando dados...',
+ 'General_ErrorRequest' => 'Oops&hellip; problema durante a sua requisi&ccedil;&atilde;o, por favor, tente novamente.',
+ 'General_Next' => 'Pr&oacute;ximo',
+ 'General_Previous' => 'Anterior',
+ 'General_Search' => 'Pesquisar',
+ 'General_Others' => 'Outros',
+ 'General_Table' => 'Tabela',
+ 'General_Piechart' => 'Gr&aacute;fico Pizza',
+ 'General_TagCloud' => 'N&uacute;vem de Tag',
+ 'General_VBarGraph' => 'Gr&aacute;fico de barras verticais',
+ 'General_GraphData' => 'Dados do Gr&aacute;fico',
+ 'General_Refresh' => 'Atualizar P&aacute;gina',
+ 'General_ColumnNbUniqVisitors' => 'Visitantes &Uacute;nicos',
+ 'General_ColumnNbVisits' => 'Visitas',
+ 'General_ColumnLabel' => 'R&oacute;tulo',
+ 'General_Save' => 'Salvar',
+ 'General_NoDataForGraph' => 'Sem dados para este gr&aacute;fico',
+ 'General_HelloUser' => 'Olá, %s!',
+ 'General_OpenSourceWebAnalytics' => 'Open Source Web Analytics',
+ 'General_YourDashboard' => 'Seu Painel',
+ 'General_API' => 'API',
+ 'General_Widgets' => 'Widgets',
+ 'General_Settings' => 'Configurações',
+ 'General_GiveUsYourFeedback' => 'Dê o seu feedback!',
+ 'General_Loading' => 'Carregando...',
+ 'General_Export' => 'Exportar',
+ 'General_ExportAsImage' => 'Exportar como imagem',
+ 'General_SaveImageOnYourComputer' => 'Para salvar a imagem no seu computador, dê um clique com o botão direito na imagem e selecione "Salvar Imagem Como..."',
+ 'General_Visitors' => 'Visitantes',
+ 'General_ColumnNbActions' => 'Ações',
+ 'General_ColumnMaxActions' => 'Ações máximas em uma visita',
+ 'General_ColumnSumVisitLength' => 'Tempo total gasto pelos visitantes (em segundos)',
+ 'General_ColumnActionsPerVisit' => 'Ações por visita',
+ 'General_ColumnAvgTimeOnSite' => 'Tempo médio no site',
+ 'General_ColumnBounceRate' => 'Taxa de saída',
+ 'General_ColumnPageviews' => 'Exibições da página',
+ 'General_ColumnUniquePageviews' => 'Exbições únicas da página',
+ 'General_ColumnValuePerVisit' => 'Valor por visita',
+ 'General_ColumnVisitsWithConversions' => 'Visitas com conversões',
+ 'General_Website' => 'Website',
+ 'General_NoDataForTagCloud' => 'Sem dados para esta nuvem de tags',
+ 'General_DisplayNormalTable' => 'Mostrar tabela normal',
+ 'General_DisplayMoreData' => 'Mostrar mais dados',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s é um projeto colaborativo. %s Se você gostou do Piwik, você pode ajudar! Veja como %s contribuir para o Piwik%s ',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Você está atualmente vendo o demo de %s; %sfaça o download% da versão completa! Veja como %s',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Piwiki %s está disponível. %s Por favor atualize agora!%s (veja %sas mudanças%s).',
+ 'General_BackToPiwik' => 'Volta ao Piwik',
+ 'General_ShortMonth_1' => 'Jan',
+ 'General_ShortMonth_2' => 'Fev',
+ 'General_ShortMonth_3' => 'Mar',
+ 'General_ShortMonth_4' => 'Abr',
+ 'General_ShortMonth_5' => 'Mai',
+ 'General_ShortMonth_6' => 'Jun',
+ 'General_ShortMonth_7' => 'Jul',
+ 'General_ShortMonth_8' => 'Ago',
+ 'General_ShortMonth_9' => 'Set',
+ 'General_ShortMonth_10' => 'Out',
+ 'General_ShortMonth_11' => 'Nov',
+ 'General_ShortMonth_12' => 'Dez',
+ 'General_LongMonth_1' => 'Janeiro',
+ 'General_LongMonth_2' => 'Fevereiro',
+ 'General_LongMonth_3' => 'Março',
+ 'General_LongMonth_4' => 'Abril',
+ 'General_LongMonth_5' => 'Maio',
+ 'General_LongMonth_6' => 'Junho',
+ 'General_LongMonth_7' => 'Julho',
+ 'General_LongMonth_8' => 'Agosto',
+ 'General_LongMonth_9' => 'Setembro',
+ 'General_LongMonth_10' => 'Outubro',
+ 'General_LongMonth_11' => 'Novembro',
+ 'General_LongMonth_12' => 'Dezembro',
+ 'General_ShortDay_1' => 'Seg',
+ 'General_ShortDay_2' => 'Ter',
+ 'General_ShortDay_3' => 'Qua',
+ 'General_ShortDay_4' => 'Qui',
+ 'General_ShortDay_5' => 'Sex',
+ 'General_ShortDay_6' => 'Sáb',
+ 'General_ShortDay_7' => 'Dom',
+ 'General_LongDay_1' => 'Segunda',
+ 'General_LongDay_2' => 'Terça',
+ 'General_LongDay_3' => 'Quarta',
+ 'General_LongDay_4' => 'Quinta',
+ 'General_LongDay_5' => 'Sexta',
+ 'General_LongDay_6' => 'Sábado',
+ 'General_LongDay_7' => 'Domingo',
+ 'API_QuickDocumentation' => '<h2>Documenta&ccedil;&atilde;o r&aacute;pida da API</h2><p>Se voc&ecirc; n&atilde;o possui informa&ccedil;&otilde;es de hoje voc&ecirc; pode primeiro <a href=\'misc/generateVisits.php\' target=_blank>gerar alguns dados</a> usando o script Gerador de Visitantes.</p><p>Voc&ecirc; pode tentar formatos diferentes dispon&iacute;veis para cada m&eacute;todo. É muito f&aacute;cil extrair qualquer informa&ccedil;&atilde;o que desejar das estat&iacute;sticas!</p><p><b>Para mais informa&ccedil;&otilde;es leia mais em <a href=\'http://dev.piwik.org/trac/wiki/API\'>Documenta&ccedil;&atilde;o Oficial da API</a> ou o guia <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>Refer&ecirc;ncia da API</a>.</b></P><h2>Autentica&ccedil;&atilde;o do usu&aacute;rio</h2><p>se voc&ecirc; deseja <b>requisitar dados das estat&iacute;sticas no seus scripts, num crontab, etc. </b> voc&ecirc; precisa adicionar o par&acirc;metro <code><u>&token_auth=%s</u></code> para as chamadas da API via URL que requerem autentica&ccedil;&atilde;o.</p><p>Este token_auth &eacute; t&atilde;o secreto quanto o seu usu&aacute;rio e senha, <b>n&atilde;o compartilhe!</p>',
+ 'API_LoadedAPIs' => '%s APIs carregadas com sucesso',
+ 'Actions_SubmenuPages' => 'P&aacute;ginas',
+ 'Actions_SubmenuOutlinks' => 'Links Externos',
+ 'Actions_SubmenuDownloads' => 'Downloads',
+ 'Actions_Actions' => 'Ações',
+ 'Actions_ColumnClicks' => 'Cliques',
+ 'Actions_ColumnUniqueClicks' => 'Cliques únicos',
+ 'Actions_ColumnDownloads' => 'Downloads',
+ 'Actions_ColumnUniqueDownloads' => 'Downloads Únicos',
+ 'Actions_ColumnPageName' => 'Nome da página',
+ 'Actions_ColumnClickedURL' => 'URL clicado',
+ 'Actions_ColumnDownloadURL' => 'Download URL',
+ 'CoreHome_NoPrivileges' => 'Voc&ecirc; est&aacute; logado como \'%s\' mas parece que voc&ecirc; n&atilde;o tem permiss&atilde;o atribu&iacute;das.<br />Solicite ao administrador que conceda permiss&atilde;o de acesso \'view\' ao website.',
+ 'CoreHome_JavascriptDisabled' => 'O JavaScript precisa estar ativado para que voc&ecirc; possa usar o Piwik no modo padr&atilde;o.<br />No entanto, parece que o JavaScript est&aacute; desabilitado ou n&atilde;o &eacute; suportado pelo seu navegador.<br />Para a visualiza&ccedil;&atilde;o padr&atilde;o, habilite o JavaScript mudando as op&ccedil;&otilde;es do seu navegador, depois %1stente novamente%2s.<br />',
+ 'CoreHome_TableNoData' => 'Sem dados para esta tabela.',
+ 'CoreHome_CategoryNoData' => 'Sem dados nesta categoria. Tente o "Incluir toda a popula&ccedil;&atilde;o".',
+ 'CoreHome_ShowJSCode' => 'Mostra o código JavaScript a inserir',
+ 'CoreHome_IncludeAllPopulation_js' => 'Incluir toda a popula&ccedil;&atilde;o',
+ 'CoreHome_ExcludeLowPopulation_js' => 'Excluir a baixa popula&ccedil;&atilde;o',
+ 'CoreHome_PageOf_js' => '%s de %s',
+ 'CoreHome_Loading_js' => 'Carregando...',
+ 'CoreHome_LocalizedDateFormat' => '%A %d %B %Y',
+ 'CoreHome_PeriodDay' => 'Dia',
+ 'CoreHome_PeriodWeek' => 'Semana',
+ 'CoreHome_PeriodMonth' => 'M&ecirc;s',
+ 'CoreHome_PeriodYear' => 'Ano',
+ 'CoreHome_DaySu_js' => 'Dom',
+ 'CoreHome_DayMo_js' => 'Seg',
+ 'CoreHome_DayTu_js' => 'Ter',
+ 'CoreHome_DayWe_js' => 'Qua',
+ 'CoreHome_DayTh_js' => 'Qui',
+ 'CoreHome_DayFr_js' => 'Sex',
+ 'CoreHome_DaySa_js' => 'Sáb',
+ 'CoreHome_MonthJanuary_js' => 'Janeiro',
+ 'CoreHome_MonthFebruary_js' => 'Fevereiro',
+ 'CoreHome_MonthMarch_js' => 'Mar&ccedil;o',
+ 'CoreHome_MonthApril_js' => 'Abril',
+ 'CoreHome_MonthMay_js' => 'Maio',
+ 'CoreHome_MonthJune_js' => 'Junho',
+ 'CoreHome_MonthJuly_js' => 'Julho',
+ 'CoreHome_MonthAugust_js' => 'Agosto',
+ 'CoreHome_MonthSeptember_js' => 'Setembro',
+ 'CoreHome_MonthOctober_js' => 'Outubro',
+ 'CoreHome_MonthNovember_js' => 'Novembro',
+ 'CoreHome_MonthDecember_js' => 'Dezembro',
+ 'CoreHome_DayFormat' => '%longDia% %dia% %longMes% %longAno%',
+ 'CoreHome_PeriodDays' => 'dias',
+ 'CoreHome_PeriodWeeks' => 'semanas',
+ 'CoreHome_PeriodMonths' => 'meses',
+ 'CoreHome_PeriodYears' => 'anos',
+ 'CorePluginsAdmin_Plugins' => 'Plugins',
+ 'CorePluginsAdmin_PluginsManagement' => 'Gerenciamento de plugins',
+ 'CorePluginsAdmin_MainDescription' => 'Plugins estendem e expandem a funcionalidade do Piwik. Uma vez que um plugin for instalado, você pode ativá-lo ou desativá-lo aqui.',
+ 'CorePluginsAdmin_Plugin' => 'Plugin',
+ 'CorePluginsAdmin_Version' => 'Versão',
+ 'CorePluginsAdmin_Description' => 'Descrição',
+ 'CorePluginsAdmin_Status' => 'Status',
+ 'CorePluginsAdmin_Action' => 'Ação',
+ 'CorePluginsAdmin_PluginHomepage' => 'Página do Plugin',
+ 'CorePluginsAdmin_Activated' => 'Ativado',
+ 'CorePluginsAdmin_Active' => 'Ativo',
+ 'CorePluginsAdmin_Inactive' => 'Inativo',
+ 'CorePluginsAdmin_ActivatedHelp' => 'Este plugin não pode ser desativado',
+ 'CorePluginsAdmin_Deactivate' => 'Desativar',
+ 'CorePluginsAdmin_Activate' => 'Ativar',
+ 'CorePluginsAdmin_MenuPlugins' => 'Plugins',
+ 'CoreUpdater_UpdateTitle' => 'Atualiza',
+ 'CoreUpdater_DatabaseUpgradeRequired' => 'Atualização do banco de dados requerida',
+ 'CoreUpdater_YourDatabaseIsOutOfDate' => 'Seu banco de dados do Piwik está desatualizado e deve ser atualizado antes de continuar.',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'O banco de dados do Piwik será atualizado da versão %s para a nova versão %s.',
+ 'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Os seguintes plugins serão atualizados: %s.',
+ 'CoreUpdater_TheUpgradeProcessMayFail' => 'Se o seu banco de dados é muito grande, as atualizações podem levar um longo tempo para serem executadas no navegador. Nesta situação, você pode executar as atualizações através da linha de comando: <code>$ php path/to/piwik/index.php</code>',
+ 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'O processo de atualização do banco de dados pode levar algum tempo, por favor seja paciente.',
+ 'CoreUpdater_UpgradePiwik' => 'Atualiza o Piwik',
+ 'CoreUpdater_ErrorDIYHelp' => 'Se você é um usuário avançado e encontrou um erro na atualização do banco de dados:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'identifique e corrija a fonte do problema (ex: memory_limit ou max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'Executar as queries remanescentes que falharam na atualização',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'Atualiza manualmente a tabela `option` no banco de dados Piwik, ajustando o valor de version_core para a versão da atualização que falhou',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'roda novamente o script de atualização (através do navegador ou da linha de comando) para continuar com as atualizações restantes',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'relate o problema (e solução) para que o Piwik possa ser melhorado',
+ 'CoreUpdater_HelpMessageContent' => 'Verifique o %s Piwik FAQ %s que explica os erros mais comuns durante a atualização. %s Pergunte ao seu administrador do sistema - Ele pode ser capaz de lhe ajudar com o erro que muito provavelmente é relacionado com o seu servidor ou o setup do MySQL.',
+ 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Erro crítico durante o processo de atualização:',
+ 'CoreUpdater_HelpMessageIntroductionWhenError' => 'Acima está a mensagem de erro principal. Ela deve ajudar a explicar a causa, mas se você precisar de mais ajuda por favor:',
+ 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'A atualização se completou com sucesso, contudo houve alguns problemas durante o processo. Por favor leia a descrição acima para os detalhes. Para mais ajuda:',
+ 'CoreUpdater_UpgradeComplete' => 'Atualização completa!',
+ 'CoreUpdater_WarningMessages' => 'Mensagens de alerta:',
+ 'CoreUpdater_ErrorDuringPluginsUpdates' => 'Erros durante atualização de plugins:',
+ 'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Nós automaticamente desativamos os seguintes plugins: %s',
+ 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik foi atualizado com sucesso!',
+ 'CoreUpdater_ContinueToPiwik' => 'Continua no Piwik',
+ 'CoreUpdater_UpdateAutomatically' => 'Atualiza automaticamente',
+ 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Há uma nova versão do Piwik disponível para atualização',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Você pode atualizar para a versão %s automaticamente ou baixar o pacote e instalar manualmente:',
+ 'CoreUpdater_DownloadX' => 'Dowload %s',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'O Piwik One Click Update foi cancelado. Se você não pode consertar a mensagem de erro acima, é recomendado que você atualize manualmente o Piwik. %s Por favor cheque a %sDocumentaçao de atualização%s para começar!',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Baixando atualização de %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Descompactando a atualização',
+ 'CoreUpdater_VerifyingUnpackedFiles' => 'Verificando os arquivos descompactados',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Criando uma cópia dos arquivos de configuração em %s',
+ 'CoreUpdater_InstallingTheLatestVersion' => 'Instalando a versão mais recente',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik atualizado com sucesso!',
+ 'CoreUpdater_EmptyDatabaseError' => 'O banco de dados %s está vazio. Você deve editar ou remover o seu arquivo de configuração do Piwik.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Sua versão %s do Piwik está atualizada.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Arquivo incompatível: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Arquivo vazio.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Arquivo está incompleto: alguns arquivos estão faltando (ex. %s).',
+ 'DBStats_DatabaseUsage' => 'Uso do banco de dados',
+ 'DBStats_MainDescription' => 'O Piwik está armazenando todos os dados de análise de tráfego no banco de dados MySQL. Atualmente, as tabelas do Piwik estão usando %s.',
+ 'DBStats_Table' => 'Tabela',
+ 'DBStats_RowNumber' => 'Número da linha',
+ 'DBStats_DataSize' => 'Tamanho dos dados',
+ 'DBStats_IndexSize' => 'Tamanho do índice',
+ 'DBStats_TotalSize' => 'Tamanho total',
+ 'Dashboard_AddWidget' => 'Adicionar um widget...',
+ 'Dashboard_DeleteWidgetConfirm' => 'Tem certeza que deseja excluir este widget do seu Painel?',
+ 'Dashboard_SelectWidget' => 'Selecione o widget a adicionar ao painel',
+ 'Dashboard_AddPreviewedWidget' => 'Add previewed widget to the dashboard',
+ 'Dashboard_WidgetPreview' => 'Widget preview',
+ 'Dashboard_TitleWidgetInDashboard_js' => 'Widget já está no painel de ferramentas',
+ 'Dashboard_TitleClickToAdd_js' => 'Clique para adicionar ao painel de ferramentas',
+ 'Dashboard_LoadingPreview_js' => 'Carregando preview, aguarde...',
+ 'Dashboard_LoadingWidget_js' => 'Carregando widget, aguarde...',
+ 'Dashboard_WidgetNotFound_js' => 'Widget n&atilde;o encontrado',
+ 'Dashboard_Dashboard' => 'Painel de Ferramentas',
+ 'Dashboard_AddPreviewedWidget_js' => 'Adicionar o widget visualizado no preview ao painel',
+ 'Dashboard_WidgetPreview_js' => 'Visualização do Widget',
+ 'Dashboard_Close_js' => 'Fechar',
+ 'Goals_ColumnConversions' => 'Conversões',
+ 'Goals_ColumnConversionRate' => 'Taxa de Conversão',
+ 'Goals_ColumnRevenue' => 'Lucro',
+ 'Installation_Installation' => 'Instalação',
+ 'Installation_InstallationStatus' => 'Status da Instala&ccedil;&atilde;o',
+ 'Installation_PercentDone' => '%s %% Completo',
+ 'Installation_NoConfigFound' => 'O arquivo de configura&ccedil;&atilde;o de relat&oacute;rios n&atilde;o pode ser encontrado e voc&ecirc; est&aacute; tentando acessar uma p&aacute;gina do Piwik.<br /><b>&nbsp;&nbsp;&raquo; Você poderá <a href=\'index.php\'>instalar o Piwik agora</a></b><br /><small>Se voc&ecirc; instalou o Piwik antes e possui algumas tabelas em seu banco de dados, n&atilde;o se preocupe, voc&ecirc; poder&aacute; reutilizar as mesmas tabelas e manter os dados existentes!</small>',
+ 'Installation_MysqlSetup' => 'Configura&ccedil;&atilde;o do banco de dados Mysql',
+ 'Installation_MysqlErrorConnect' => 'Erro ao tentar se conectar ao banco de dados Mysql',
+ 'Installation_JsTag' => 'Tag JavaScript',
+ 'Installation_JsTagHelp' => '<p>Para contar todos os seus visitantes, voc&ecirc; precisa inserir o c&oacute;digo javascript em todas as suas p&aacute;ginas.</p><p>Suas p&aacute;ginas n&atilde;o precisam ser em PHP, Piwik ir&aacute; funcionar em todos os tipos de p&aacute;ginas (seja em HTML, ASP, Perl ou qualquer outra linguagem).</p><p>Este &eacute; o c&oacute;digo que voc&ecirc; deve inserir: (copie e cole em todas as suas p&aacute;ginas) </p>',
+ 'Installation_Congratulations' => 'Parab&eacute;ns',
+ 'Installation_CongratulationsHelp' => '<p>Parab&eacute;ns! A sua instala&ccedil;&atilde;o do Piwik está completa.</p><p>Certifique-se de ter colocado o c&oacute;digo JavaScript em todas as suas p&aacute;ginas, e aguarde os seus primeiros visitantes!</p>',
+ 'Installation_GoToPiwik' => 'Ir para Piwik',
+ 'Installation_SetupWebsite' => 'Configurar um website',
+ 'Installation_SetupWebsiteError' => 'Ocorreu um erro ao tentar adicionar o website',
+ 'Installation_GeneralSetup' => 'Configura&ccedil;&otilde;es Gerais',
+ 'Installation_GeneralSetupSuccess' => 'Configura&ccedil;&otilde;es Gerais efetuadas com sucesso',
+ 'Installation_SystemCheck' => 'Checagem do Sistema',
+ 'Installation_SystemCheckPhp' => 'Vers&atilde;o do PHP',
+ 'Installation_SystemCheckPdo' => 'Extens&atilde;o Pdo',
+ 'Installation_SystemCheckPdoMysql' => 'Extens&atilde;o Pdo_Mysql',
+ 'Installation_SystemCheckPdoError' => 'Voc&ecirc; precisa habilitar as extens&otilde;es PDO e PDO_MYSQL no seu arquivo php.ini.',
+ 'Installation_SystemCheckPdoHelp' => 'Em um servidor windows voc&ecirc; pode adicionar as seguintes linhas no seu arquivo php.ini %s <br /><br />Em um servidor Linux voc&ecirc; pode compilar o PHP com as seguintes op&ccedil;&otilde;es %s No seu arquivo php.ini, adicione as seguintes linhas %s<br /><br />Mais informa&ccedil;&otilde;es em <a style="color:red" href="http://php.net/pdo">PHP website</a>.',
+ 'Installation_SystemCheckWriteDirs' => 'Diret&oacute;rios com permiss&atilde;o de escrita',
+ 'Installation_SystemCheckWriteDirsHelp' => 'Para resolver este problema no seu sistema Linux, tente digitar os seguintes comando(s)',
+ 'Installation_SystemCheckMemoryLimit' => 'Limite de Mem&oacute;ria',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'Em um site com alto tr&aacute;fego, o processo de arquivamento pode exigir mais mem&oacute;ria do que o atualmente permitido. Se necessário, mude a diretiva memory_limit no seu arquivo php.ini.',
+ 'Installation_SystemCheckGD' => 'GD &gt; 2.x (gr&aacute;ficos)',
+ 'Installation_SystemCheckGDHelp' => 'Os sparklines (gr&aacute;ficos pequenos) n&atilde;o ir&atilde;o funcionar.',
+ 'Installation_SystemCheckTimeLimit' => 'set_time_limit() permitido',
+ 'Installation_SystemCheckTimeLimitHelp' => 'Em um site com alto tr&aacute;fego, executar o processo de arquivamento pode exigir mais mem&oacute;ria do que o atualmente permitido. Se necessário, altere a diretiva max_execution_time no seu arquivo php.ini.',
+ 'Installation_SystemCheckMail' => 'mail() permitido',
+ 'Installation_SystemCheckError' => 'Ocorreu um erro - precisa ser reparado antes de voc&ecirc; poder prosseguir',
+ 'Installation_SystemCheckWarning' => 'Piwik vai funcionar corretamente mas alguns recursos podem não estar disponíveis',
+ 'Installation_Tables' => 'Criando as tabelas',
+ 'Installation_TablesWarning' => 'Algumas <span id="linkToggle">tabelas Piwik</span> j&aacute; est&atilde;o instaladas no banco de dados',
+ 'Installation_TablesFound' => 'As seguintes tabelas foram encontradas no banco de dados',
+ 'Installation_TablesWarningHelp' => 'Escolha reutilizar as tabelas existentes ou selecione uma nova instalação para apagar todas as informa&ccedil;&otilde;es no banco de dados.',
+ 'Installation_TablesReuse' => 'Reutilizar as tabelas existentes',
+ 'Installation_TablesDelete' => 'Excluir as tabelas encontradas',
+ 'Installation_TablesDeletedSuccess' => 'Tabelas Piwik exclu&iacute;das com sucesso',
+ 'Installation_TablesCreatedSuccess' => 'Tabelas criadas com sucesso!',
+ 'Installation_TablesDeleteConfirm' => 'Voc&ecirc; tem certeza que deseja excluir todas as tabelas Piwik deste banco de dados?',
+ 'Installation_Welcome' => 'Bem vindo!',
+ 'Installation_WelcomeHelp' => '<p>Piwik &eacute; um analisador de tr&aacute;fego open source que torna f&aacute;cil obter informa&ccedil;&otilde;es sobre os seus visitantes.</p><p>Este processo &eacute; dividido em %s passos f&aacute;ceis e ir&aacute; demorar por volta de 5 minutos.</p>',
+ 'Installation_DatabaseSetup' => 'Setup do banco de dados',
+ 'Installation_DatabaseErrorConnect' => 'Erro enquanto tentando conectar ao servidor do banco de dados',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'A conexão do cliente ao servidor do banco de dados não é UTF8',
+ 'Installation_JsTagQuicHelpk' => 'Ajuda rápida',
+ 'Installation_JsTagArchivingHelp' => 'Para sites com médio e alto tráfego, verifique o documento <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">How to setup auto archiving page</a> para rodar o Piwik realmente rápido!',
+ 'Installation_ContinueToPiwik' => 'Continuar no Piwik',
+ 'Installation_SetupWebsiteSetupSuccess' => 'Website %s criado com sucesso!',
+ 'Installation_SuperUserLogin' => 'login super usuário',
+ 'Installation_Password' => 'senha',
+ 'Installation_PasswordRepeat' => 'senha (repetir)',
+ 'Installation_Email' => 'email',
+ 'Installation_SecurityNewsletter' => 'envie-me um email quando houver alertas de segurança e atualizações importantes',
+ 'Installation_CommunityNewsletter' => 'envie-me um email com atualizações da comunidade (novos plugins, novas funções, etc.)',
+ 'Installation_PasswordDoNotMatch' => 'senha não confere',
+ 'Installation_SubmitGo' => 'Ir!',
+ 'Installation_Requirements' => 'Requerimentos do Piwik',
+ 'Installation_Optional' => 'Opcional',
+ 'Installation_Legend' => 'Legenda',
+ 'Installation_Extension' => 'extensão',
+ 'Installation_SystemCheckExtensions' => 'Outras extensões requeridas',
+ 'Installation_SystemCheckDatabaseHelp' => 'O Piwik requer ou a extensão mysqli ou ambas as extensões PDO e pdo_mysql.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'Num servidor Linux você poderá compilar o php com as seguintes opções: %s No seu php.ini, adicione as seguintes linhas: %s',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Mais informações em: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> e <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'Num servidor Windows você poderá adicionar as seguintes linhas ao seu php.ini: %s',
+ 'Installation_SystemCheckSplHelp' => 'Você precisa configurar e remontar o PHP com a Standard PHP Library (SPL) habilitada (por padrão).',
+ 'Installation_SystemCheckZlibHelp' => 'Você precisa configurar e remontar o PHP com suporte "zlib" ativado, --with-zlib.',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'Você precisa configurar e remontar o PHP com as extensões "json" ou "xml" habilitadas.',
+ 'Installation_SystemCheckJsonSite' => 'Mais informações em: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Alguns plugins de terceiros e bibliotecas de desenvolvedores podem requerer a extensão "xml".',
+ 'Installation_SystemCheckXmlSite' => 'Mais informações em: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckOpenURL' => 'Abre URL',
+ 'Installation_SystemCheckOpenURLHelp' => 'Assinaturas de newsletters e notificações de atualização e atualizações em um clique requerem a extensão "curl", allow_url_fopen=On, ou fsockopen() ativada.',
+ 'Installation_SystemCheckFunctions' => 'Funções requeridas',
+ 'Installation_SystemCheckMailHelp' => 'Mensagens de feedback e senha perdida não serão enviadas sem mail().',
+ 'Installation_TablesWithSameNamesFound' => 'Algumas tabelas %s no seu banco de dados %s tem o mesmo nome das tabelas que o Piwik está tentando criar',
+ 'Installation_DatabaseCreatedSuccess' => 'Banco de dados %s criado com sucesso!',
+ 'Installation_GoBackAndDefinePrefix' => 'Volte e defina um prefixo para as tabelas Piwik',
+ 'Installation_ConfirmDeleteExistingTables' => 'Tem certeza que quer apagar as tabelas: %s do seu banco de dados? AVISO: DADOS DESTAS TABELAS NÃO PODERÃO SER RECUPERADOS!',
+ 'Installation_ErrorInvalidState' => 'Erro: parece que você está tentando pular um passo do processo de instalação, ou seus cookies estão desligados, ou o arquivo de configuração do Piwik já foi criado. %sTenha certeza de que seus cookies estão ativados%s e volte %spara a página inicial da instalação%s.',
+ 'Login_LoginPasswordNotCorrect' => 'Nome de usuário e senha incorretos',
+ 'Login_Login' => 'Nome de Usuário',
+ 'Login_Password' => 'Senha',
+ 'Login_LoginOrEmail' => 'Nome de Usu&aacute;rio ou E-mail',
+ 'Login_LogIn' => 'Entrar',
+ 'Login_Logout' => 'Sair',
+ 'Login_LostYourPassword' => 'Esqueceu a sua senha?',
+ 'Login_RemindPassword' => 'Lembrar senha',
+ 'Login_PasswordReminder' => 'Por favor digite o seu nome de usu&aacute;rio ou endereço de e-mail. Voc&ecirc; receber&aacute; uma nova senha via e-mail com informações para resetar a sua senha.',
+ 'Login_InvalidUsernameEmail' => 'Nome de usu&aacute;rio e/ou e-mail inv&aacute;lido',
+ 'Login_MailTopicPasswordRecovery' => 'Recuperação de senha',
+ 'Login_MailPasswordRecoveryBody' => 'Olá %s, um pedido de recuperação de senha foi recebido de %s. Para resetar sua senha: 1) Vá até o formulário de recuperação de senha em: %s 2) Entre com o seguinte token: %s 3) Preencha o formulário (colocando sua nova senha duas vezes) e envie. Observação: este token irá expirar em 24 horas.',
+ 'Login_PasswordSent' => 'Informações para resetar sua senha foram enviadas. Verifique seu e-mail.',
+ 'Login_ContactAdmin' => 'Poss&iacute;vel raz&atilde;o: o seu host desabilitou a fun&ccedil;&atilde;o mail(). <br />Por favor contacte o administrador do Piwik.',
+ 'Login_PasswordRepeat' => 'Senha (repetir)',
+ 'Login_ChangePassword' => 'Troca senha',
+ 'Login_PasswordResetToken' => 'Token de lembrança de senha',
+ 'Login_PasswordsDoNotMatch' => 'Senhas não conferem.',
+ 'Login_PasswordSuccessfullyChanged' => 'Senha trocada com sucesso!',
+ 'Login_InvalidOrExpiredToken' => 'Token inválido ou expirado',
+ 'Provider_WidgetProviders' => 'Provedores',
+ 'Provider_SubmenuLocationsProvider' => 'Lugares e Provedores',
+ 'Provider_ColumnProvider' => 'Provedor',
+ 'Referers_SearchEngines' => 'Sistemas de Busca',
+ 'Referers_Keywords' => 'Palavras Chaves',
+ 'Referers_DirectEntry' => 'Entrada Direta',
+ 'Referers_Websites' => 'Websites',
+ 'Referers_Newsletters' => 'Newsletters',
+ 'Referers_Campaigns' => 'Campanhas',
+ 'Referers_Evolution' => 'Evolu&ccedil;&atilde;o no per&iacute;odo',
+ 'Referers_Type' => 'Tipo de Referer',
+ 'Referers_TypeDirectEntries' => '%s entradas diretas',
+ 'Referers_TypeSearchEngines' => '%s de sistema de buscas',
+ 'Referers_TypeWebsites' => '%s de websites',
+ 'Referers_TypeNewsletters' => '%s de newsletters',
+ 'Referers_TypeCampaigns' => '%s de campanhas',
+ 'Referers_Other' => 'Outro',
+ 'Referers_OtherDistinctSearchEngines' => '%s sistema de buscas distintos',
+ 'Referers_OtherDistinctKeywords' => '%s palvras chaves distintas',
+ 'Referers_OtherDistinctWebsites' => '%1s websites distintos (usando %2s urls distintas)',
+ 'Referers_OtherDistinctCampaigns' => '%s campanhas distintas',
+ 'Referers_TagCloud' => 'Sa&iacute;da da Nuvem de Tag',
+ 'Referers_SubmenuEvolution' => 'Evolu&ccedil;&atilde;o',
+ 'Referers_SubmenuSearchEngines' => 'Sistemas de Buscas e Palavras Chaves',
+ 'Referers_SubmenuWebsites' => 'Websites',
+ 'Referers_SubmenuCampaigns' => 'Campanhas',
+ 'Referers_WidgetKeywords' => 'Lista de Palavras Chave',
+ 'Referers_WidgetCampaigns' => 'Lista de Campanhas',
+ 'Referers_WidgetExternalWebsites' => 'Lista de Websites externos',
+ 'Referers_WidgetSearchEngines' => 'Melhores Sistemas de Busca',
+ 'Referers_WidgetOverview' => 'Vis&atilde;o Geral',
+ 'Referers_Referers' => 'referentes',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%s (de %s)',
+ 'Referers_ColumnRefererType' => 'Tipo de Referer',
+ 'Referers_ColumnSearchEngine' => 'Sistema de Busca',
+ 'Referers_ColumnWebsite' => 'Website',
+ 'Referers_ColumnWebsitePage' => 'Página da Web',
+ 'Referers_ColumnKeyword' => 'Palavra chave',
+ 'Referers_ColumnCampaign' => 'campanha',
+ 'Referers_DetailsByRefererType' => 'Detalhes por tipo de Referer',
+ 'Referers_Distinct' => 'Referers distintos por tipo de Referer',
+ 'Referers_DistinctSearchEngines' => 'Sistemas de busca distintos',
+ 'Referers_DistinctKeywords' => 'Palavras chave distintas',
+ 'Referers_DistinctCampaigns' => 'Campanhas distintas',
+ 'Referers_DistinctWebsites' => 'Websites distintos',
+ 'Referers_UsingNDistinctUrls' => '(usando %2s URLs distintos)',
+ 'SitesManager_Sites' => 'Websites',
+ 'SitesManager_JsCode' => 'C&oacute;digo Javascript',
+ 'SitesManager_JsCodeHelp' => 'Este &eacute; o c&oacute;digo javascript que voc&ecirc; deve incluir em todas as suas p&aacute;ginas',
+ 'SitesManager_ShowJsCode' => 'mostrar c&oacute;digo',
+ 'SitesManager_NoWebsites' => 'Voc&ecirc; n&atilde;o tem nenhum site para administrar.',
+ 'SitesManager_AddSite' => 'Adicionar novo Site',
+ 'SitesManager_Id' => 'Id',
+ 'SitesManager_Name' => 'Nome',
+ 'SitesManager_Urls' => 'URLs',
+ 'SitesManager_MenuSites' => 'Websites',
+ 'SitesManager_DeleteConfirm_js' => 'Tem certeza que deseja excluir o website %s?',
+ 'SitesManager_ExceptionDeleteSite' => 'N&atilde;o &eacute; poss&iacute;vel excluir este website j&aacute; que ele &eacute; o &uacute;nico website registrado. Adiicone um novo website primeiro, depois exclua este.',
+ 'SitesManager_ExceptionNoUrl' => 'Voc&ecirc; precisa especificar no m&iacute;nimo uma URL para o site.',
+ 'SitesManager_ExceptionEmptyName' => 'O nome do site n&atilde;o pode ficar vazio.',
+ 'SitesManager_ExceptionInvalidUrl' => 'A URL \'%s\' n&atilde;o &eacute; uma URL v&aacute;lida.',
+ 'SitesManager_WebsitesManagement' => 'Gerenciamento de Sites',
+ 'SitesManager_MainDescription' => 'Seus relatórios de Web Analytics precisam de websites! Adiciona, atualiza, elimina websites, e mostra o JavaScript necessário para inserir em suas páginas.',
+ 'SitesManager_JsTrackingTag' => 'Tag de rastreamento JavaScript',
+ 'SitesManager_JsTrackingTagHelp' => 'Aqui está a tag de rastreamento JavaScript a ser incluída em todas as suas páginas',
+ 'SitesManager_ShowTrackingTag' => 'mostra tag de rastreamento',
+ 'TranslationsAdmin_MenuTranslations' => 'Traduções',
+ 'TranslationsAdmin_MenuLanguages' => 'Idiomas',
+ 'TranslationsAdmin_Plugin' => 'Plugin',
+ 'TranslationsAdmin_Definition' => 'Defini&ccedil;&atilde;o',
+ 'TranslationsAdmin_DefaultString' => 'String Padr&atilde;o (Ingl&ecirc;s)',
+ 'TranslationsAdmin_TranslationString' => 'String de tradu&ccedil;&atilde;o (idioma atual: %s)',
+ 'TranslationsAdmin_Translations' => 'Tradu&ccedil;&otilde;es',
+ 'TranslationsAdmin_FixPermissions' => 'Por favor, conserte as permiss&otilde;es do sistema de arquivos',
+ 'TranslationsAdmin_AvailableLanguages' => 'Idiomas dispon&iacute;veis',
+ 'TranslationsAdmin_AddLanguage' => 'Adicionar Idioma',
+ 'TranslationsAdmin_LanguageCode' => 'C&oacute;digo do Idioma',
+ 'TranslationsAdmin_Export' => 'Exportar Idioma',
+ 'TranslationsAdmin_Import' => 'Importar Idioma',
+ 'UserCountry_Country' => 'Pa&iacute;s',
+ 'UserCountry_Continent' => 'Continente',
+ 'UserCountry_DistinctCountries' => '%s pa&iacute;ses distintos',
+ 'UserCountry_SubmenuLocations' => 'Locais',
+ 'UserCountry_WidgetContinents' => 'Continente dos Visitantes',
+ 'UserCountry_WidgetCountries' => 'Pa&iacute;s dos Visitantes',
+ 'UserCountry_country_ac' => 'Ascension Islands',
+ 'UserCountry_country_ad' => 'Andorra',
+ 'UserCountry_country_ae' => 'Emirados Árabes Unidos',
+ 'UserCountry_country_af' => 'Afeganistão',
+ 'UserCountry_country_ag' => 'Antigua e Barbuda',
+ 'UserCountry_country_ai' => 'Anguilla',
+ 'UserCountry_country_al' => 'Albânia',
+ 'UserCountry_country_am' => 'Armênia',
+ 'UserCountry_country_an' => 'Antilhas Holandesas',
+ 'UserCountry_country_ao' => 'Angola',
+ 'UserCountry_country_aq' => 'Antártida',
+ 'UserCountry_country_ar' => 'Argentina',
+ 'UserCountry_country_as' => 'Samoa Americana',
+ 'UserCountry_country_at' => 'Áustria',
+ 'UserCountry_country_au' => 'Austrália',
+ 'UserCountry_country_aw' => 'Aruba',
+ 'UserCountry_country_az' => 'Azerbaijão',
+ 'UserCountry_country_ba' => 'Bósnia Herzegovina',
+ 'UserCountry_country_bb' => 'Barbados',
+ 'UserCountry_country_bd' => 'Bangladesh',
+ 'UserCountry_country_be' => 'Bélgica',
+ 'UserCountry_country_bf' => 'Burkina Faso',
+ 'UserCountry_country_bg' => 'Bulgária',
+ 'UserCountry_country_bh' => 'Bahrein',
+ 'UserCountry_country_bi' => 'Burundi',
+ 'UserCountry_country_bj' => 'Benin',
+ 'UserCountry_country_bm' => 'Bermuda',
+ 'UserCountry_country_bn' => 'Brunei',
+ 'UserCountry_country_bo' => 'Bolívia',
+ 'UserCountry_country_br' => 'Brasil',
+ 'UserCountry_country_bs' => 'Bahamas',
+ 'UserCountry_country_bt' => 'Butão',
+ 'UserCountry_country_bv' => 'Bouvet Island',
+ 'UserCountry_country_bw' => 'Botswana',
+ 'UserCountry_country_by' => 'Bielorússia',
+ 'UserCountry_country_bz' => 'Belize',
+ 'UserCountry_country_ca' => 'Canadá',
+ 'UserCountry_country_cc' => 'Cocos (Keeling) Islands',
+ 'UserCountry_country_cd' => 'Congo, República Democrática do',
+ 'UserCountry_country_cf' => 'República Centro-Africana',
+ 'UserCountry_country_cg' => 'Congo',
+ 'UserCountry_country_ch' => 'Suíça',
+ 'UserCountry_country_ci' => 'Costa do Marfim',
+ 'UserCountry_country_ck' => 'Ilhas Cook',
+ 'UserCountry_country_cl' => 'Chile',
+ 'UserCountry_country_cm' => 'Camarões',
+ 'UserCountry_country_cn' => 'China',
+ 'UserCountry_country_co' => 'Colômbia',
+ 'UserCountry_country_cr' => 'Costa Rica',
+ 'UserCountry_country_cs' => 'Sérvia e Montenegro',
+ 'UserCountry_country_cu' => 'Cuba',
+ 'UserCountry_country_cv' => 'Cabo Verde',
+ 'UserCountry_country_cx' => 'Ilha Christmas',
+ 'UserCountry_country_cy' => 'Chipre',
+ 'UserCountry_country_cz' => 'República Tcheca',
+ 'UserCountry_country_de' => 'Alemanha',
+ 'UserCountry_country_dj' => 'Djibouti',
+ 'UserCountry_country_dk' => 'Dinamarca',
+ 'UserCountry_country_dm' => 'Dominica',
+ 'UserCountry_country_do' => 'República Dominicana',
+ 'UserCountry_country_dz' => 'Argélia',
+ 'UserCountry_country_ec' => 'Equador',
+ 'UserCountry_country_ee' => 'Estônia',
+ 'UserCountry_country_eg' => 'Egito',
+ 'UserCountry_country_eh' => 'Saara Ocidental',
+ 'UserCountry_country_er' => 'Eritréia',
+ 'UserCountry_country_es' => 'Espanha',
+ 'UserCountry_country_et' => 'Etiópia',
+ 'UserCountry_country_fi' => 'Finlândia',
+ 'UserCountry_country_fj' => 'Fiji',
+ 'UserCountry_country_fk' => 'Ilhas Falkland (Malvinas)',
+ 'UserCountry_country_fm' => 'Micronesia, Estados Federados da',
+ 'UserCountry_country_fo' => 'Ilhas Faroe',
+ 'UserCountry_country_fr' => 'França',
+ 'UserCountry_country_ga' => 'Gabão',
+ 'UserCountry_country_gd' => 'Granada',
+ 'UserCountry_country_ge' => 'Geórgia',
+ 'UserCountry_country_gf' => 'Guiana Francesa',
+ 'UserCountry_country_gg' => 'Guernsey',
+ 'UserCountry_country_gh' => 'Gana',
+ 'UserCountry_country_gi' => 'Gibraltar',
+ 'UserCountry_country_gl' => 'Groenlândia',
+ 'UserCountry_country_gm' => 'Gâmbia',
+ 'UserCountry_country_gn' => 'Guiné',
+ 'UserCountry_country_gp' => 'Guadalupe',
+ 'UserCountry_country_gq' => 'Guiné Equatorial',
+ 'UserCountry_country_gr' => 'Grécia',
+ 'UserCountry_country_gs' => 'South Georgia e Ilhas South Sandwich',
+ 'UserCountry_country_gt' => 'Guatemala',
+ 'UserCountry_country_gu' => 'Guam',
+ 'UserCountry_country_gw' => 'Guiné-Bissau',
+ 'UserCountry_country_gy' => 'Guiana',
+ 'UserCountry_country_hk' => 'Hong Kong',
+ 'UserCountry_country_hm' => 'Ilha Heard e Ilhas McDonald',
+ 'UserCountry_country_hn' => 'Honduras',
+ 'UserCountry_country_hr' => 'Croácia',
+ 'UserCountry_country_ht' => 'Haiti',
+ 'UserCountry_country_hu' => 'Hungria',
+ 'UserCountry_country_id' => 'Indonésia',
+ 'UserCountry_country_ie' => 'Irlanda',
+ 'UserCountry_country_il' => 'Israel',
+ 'UserCountry_country_im' => 'Ilha de Man',
+ 'UserCountry_country_in' => 'Índia',
+ 'UserCountry_country_io' => 'Território Oceânico das Índias Britânicas',
+ 'UserCountry_country_iq' => 'Iraque',
+ 'UserCountry_country_ir' => 'Irã, República Islâmica do',
+ 'UserCountry_country_is' => 'Islândia',
+ 'UserCountry_country_it' => 'Itália',
+ 'UserCountry_country_je' => 'Jersey',
+ 'UserCountry_country_jm' => 'Jamaica',
+ 'UserCountry_country_jo' => 'Jordânia',
+ 'UserCountry_country_jp' => 'Japão',
+ 'UserCountry_country_ke' => 'Quênia',
+ 'UserCountry_country_kg' => 'Kirguistão',
+ 'UserCountry_country_kh' => 'Camboja',
+ 'UserCountry_country_ki' => 'Kiribati',
+ 'UserCountry_country_km' => 'Comoros',
+ 'UserCountry_country_kn' => 'Saint Kitts e Nevis',
+ 'UserCountry_country_kp' => 'Coréia, República Democrática Popular da',
+ 'UserCountry_country_kr' => 'Coréia, República da',
+ 'UserCountry_country_kw' => 'Kuwait',
+ 'UserCountry_country_ky' => 'Ilhas Cayman',
+ 'UserCountry_country_kz' => 'Cazaquistão',
+ 'UserCountry_country_la' => 'Laos',
+ 'UserCountry_country_lb' => 'Líbano',
+ 'UserCountry_country_lc' => 'Santa Lúcia',
+ 'UserCountry_country_li' => 'Liechtenstein',
+ 'UserCountry_country_lk' => 'Sri Lanka',
+ 'UserCountry_country_lr' => 'Libéria',
+ 'UserCountry_country_ls' => 'Lesoto',
+ 'UserCountry_country_lt' => 'Lituânia',
+ 'UserCountry_country_lu' => 'Luxemburgo',
+ 'UserCountry_country_lv' => 'Letônia',
+ 'UserCountry_country_ly' => 'Líbia',
+ 'UserCountry_country_ma' => 'Marrocos',
+ 'UserCountry_country_mc' => 'Mônaco',
+ 'UserCountry_country_md' => 'Moldávia, República da',
+ 'UserCountry_country_mg' => 'Madagascar',
+ 'UserCountry_country_mh' => 'Ilhas Marshall',
+ 'UserCountry_country_mk' => 'Macedônia',
+ 'UserCountry_country_ml' => 'Mali',
+ 'UserCountry_country_mm' => 'Myanmar',
+ 'UserCountry_country_mn' => 'Mongólia',
+ 'UserCountry_country_mo' => 'Macau',
+ 'UserCountry_country_mp' => 'Ilhas Marianas do Norte',
+ 'UserCountry_country_mq' => 'Martinica',
+ 'UserCountry_country_mr' => 'Mauritânia',
+ 'UserCountry_country_ms' => 'Montserrat',
+ 'UserCountry_country_mt' => 'Malta',
+ 'UserCountry_country_mu' => 'Ilhas Maurício',
+ 'UserCountry_country_mv' => 'Maldivas',
+ 'UserCountry_country_mw' => 'Malawi',
+ 'UserCountry_country_mx' => 'México',
+ 'UserCountry_country_my' => 'Malásia',
+ 'UserCountry_country_mz' => 'Moçambique',
+ 'UserCountry_country_na' => 'Namíbia',
+ 'UserCountry_country_nc' => 'Nova Caledônia',
+ 'UserCountry_country_ne' => 'Niger',
+ 'UserCountry_country_nf' => 'Norfolk Island',
+ 'UserCountry_country_ng' => 'Nigéria',
+ 'UserCountry_country_ni' => 'Nicarágua',
+ 'UserCountry_country_nl' => 'Holanda',
+ 'UserCountry_country_no' => 'Noruega',
+ 'UserCountry_country_np' => 'Nepal',
+ 'UserCountry_country_nr' => 'Nauru',
+ 'UserCountry_country_nu' => 'Niue',
+ 'UserCountry_country_nz' => 'Nova Zelândia',
+ 'UserCountry_country_om' => 'Omã',
+ 'UserCountry_country_pa' => 'Panamá',
+ 'UserCountry_country_pe' => 'Peru',
+ 'UserCountry_country_pf' => 'Polinésia Francesa',
+ 'UserCountry_country_pg' => 'Papua Nova Guiné',
+ 'UserCountry_country_ph' => 'Filipinas',
+ 'UserCountry_country_pk' => 'Paquistão',
+ 'UserCountry_country_pl' => 'Polônia',
+ 'UserCountry_country_pm' => 'Saint Pierre e Miquelon',
+ 'UserCountry_country_pn' => 'Pitcairn',
+ 'UserCountry_country_pr' => 'Porto Rico',
+ 'UserCountry_country_ps' => 'Território Palestino',
+ 'UserCountry_country_pt' => 'Portugal',
+ 'UserCountry_country_pw' => 'Palau',
+ 'UserCountry_country_py' => 'Paraguai',
+ 'UserCountry_country_qa' => 'Qatar',
+ 'UserCountry_country_re' => 'Ilhas Reunião',
+ 'UserCountry_country_ro' => 'Romênia',
+ 'UserCountry_country_rw' => 'Ruanda',
+ 'UserCountry_country_sa' => 'Arábia Saudita',
+ 'UserCountry_country_sb' => 'Ilhas Salomão',
+ 'UserCountry_country_sc' => 'Seychelles',
+ 'UserCountry_country_sd' => 'Sudão',
+ 'UserCountry_country_se' => 'Suécia',
+ 'UserCountry_country_sg' => 'Cingapura',
+ 'UserCountry_country_sh' => 'Santa Helena',
+ 'UserCountry_country_si' => 'Eslovênia',
+ 'UserCountry_country_sj' => 'Svalbard',
+ 'UserCountry_country_sk' => 'Eslováquia',
+ 'UserCountry_country_sl' => 'Serra Leoa',
+ 'UserCountry_country_sm' => 'San Marino',
+ 'UserCountry_country_sn' => 'Senegal',
+ 'UserCountry_country_so' => 'Somália',
+ 'UserCountry_country_sr' => 'Suriname',
+ 'UserCountry_country_st' => 'São Tome e Príncipe',
+ 'UserCountry_country_su' => 'Antiga U.R.S.S.',
+ 'UserCountry_country_sv' => 'El Salvador',
+ 'UserCountry_country_sy' => 'República Árabe da Síria',
+ 'UserCountry_country_sz' => 'Suazilândia',
+ 'UserCountry_country_tc' => 'Ilhas Turks e Caicos',
+ 'UserCountry_country_td' => 'Chade',
+ 'UserCountry_country_tf' => 'Territ&oacute;rios Franceses do Sul',
+ 'UserCountry_country_tg' => 'Togo',
+ 'UserCountry_country_th' => 'Tailândia',
+ 'UserCountry_country_tj' => 'Tadjiquistão',
+ 'UserCountry_country_tk' => 'Tokelau',
+ 'UserCountry_country_tm' => 'Turkmenistão',
+ 'UserCountry_country_tn' => 'Tunísia',
+ 'UserCountry_country_to' => 'Tonga',
+ 'UserCountry_country_tp' => 'Timor Leste',
+ 'UserCountry_country_tr' => 'Turquia',
+ 'UserCountry_country_tt' => 'Trinidade e Tobago',
+ 'UserCountry_country_tv' => 'Tuvalu',
+ 'UserCountry_country_tw' => 'Taiwan',
+ 'UserCountry_country_tz' => 'Tanzânia, República Unida da',
+ 'UserCountry_country_ua' => 'Ucrânia',
+ 'UserCountry_country_ug' => 'Uganda',
+ 'UserCountry_country_uk' => 'Reino Unido',
+ 'UserCountry_country_gb' => 'Grã Bretanha',
+ 'UserCountry_country_um' => 'United States Minor Outlying Islands',
+ 'UserCountry_country_us' => 'Estados Unidos da América',
+ 'UserCountry_country_uy' => 'Uruguai',
+ 'UserCountry_country_uz' => 'Uzbequistão',
+ 'UserCountry_country_va' => 'Cidade do Vaticano',
+ 'UserCountry_country_vc' => 'Saint Vincent e Grenadines',
+ 'UserCountry_country_ve' => 'Venezuela',
+ 'UserCountry_country_vg' => 'Ilhas Virgens Britânicas',
+ 'UserCountry_country_vi' => 'Ilhas Virgens Americanas',
+ 'UserCountry_country_vn' => 'Vietnã',
+ 'UserCountry_country_vu' => 'Vanuatu',
+ 'UserCountry_country_wf' => 'Wallis e Futuna',
+ 'UserCountry_country_ws' => 'Samoa',
+ 'UserCountry_country_ye' => 'Iêmen',
+ 'UserCountry_country_yt' => 'Mayotte',
+ 'UserCountry_country_yu' => 'Iugoslávia',
+ 'UserCountry_country_za' => 'África do Sul',
+ 'UserCountry_country_zm' => 'Zâmbia',
+ 'UserCountry_country_zr' => 'Zaire',
+ 'UserCountry_country_zw' => 'Zimbabue',
+ 'UserCountry_continent_eur' => 'Europa',
+ 'UserCountry_continent_afr' => 'África',
+ 'UserCountry_continent_asi' => 'Ásia',
+ 'UserCountry_continent_ams' => 'América do Sul e Central',
+ 'UserCountry_continent_amn' => 'América do Norte',
+ 'UserCountry_continent_oce' => 'Oceania',
+ 'UserCountry_country_ax' => 'Ilhas Aland',
+ 'UserCountry_country_bl' => 'Saint Barthelemy',
+ 'UserCountry_country_bu' => 'Birmânia',
+ 'UserCountry_country_cp' => 'Ilha Clipperton',
+ 'UserCountry_country_dg' => 'Diego Garcia',
+ 'UserCountry_country_ea' => 'Ceuta, Melilla',
+ 'UserCountry_country_eu' => 'União Européia',
+ 'UserCountry_country_fx' => 'França, região Metropolitana',
+ 'UserCountry_country_ic' => 'Ilhas Canárias',
+ 'UserCountry_country_me' => 'Montenegro',
+ 'UserCountry_country_mf' => 'Saint Martin',
+ 'UserCountry_country_nt' => 'Zona Neutra',
+ 'UserCountry_country_ru' => 'Rússia',
+ 'UserCountry_country_rs' => 'Sérvia',
+ 'UserCountry_country_sf' => 'Finlândia',
+ 'UserCountry_country_ta' => 'Tristão da Cunha',
+ 'UserCountry_country_tl' => 'Timor Leste',
+ 'UserSettings_BrowserFamilies' => 'Fam&iacute;lia de Navegadores',
+ 'UserSettings_Browsers' => 'Navegadores',
+ 'UserSettings_Plugins' => 'Plugins',
+ 'UserSettings_Configurations' => 'Configura&ccedil;&otilde;es',
+ 'UserSettings_OperatinsSystems' => 'Sistemas Operacionais',
+ 'UserSettings_Resolutions' => 'Resolu&ccedil;&otilde;es',
+ 'UserSettings_WideScreen' => 'Wide Screen',
+ 'UserSettings_WidgetResolutions' => 'Resolu&ccedil;&otilde;es de Tela',
+ 'UserSettings_WidgetBrowsers' => 'Navegador dos Visitantes',
+ 'UserSettings_WidgetPlugins' => 'Lista de Plugins',
+ 'UserSettings_WidgetWidescreen' => 'Normal / Widescreen',
+ 'UserSettings_WidgetBrowserFamilies' => 'Navegadores por Fam&iacute;lia',
+ 'UserSettings_WidgetOperatingSystems' => 'Sistemas Operacionais',
+ 'UserSettings_WidgetGlobalVisitors' => 'Configura&ccedil;&atilde;o Global de Visitante',
+ 'UserSettings_SubmenuSettings' => 'Configura&ccedil;&otilde;es',
+ 'UserSettings_VisitorSettings' => 'Configurações dos visitantes',
+ 'UserSettings_ColumnBrowserFamily' => 'Família do Navegador',
+ 'UserSettings_ColumnBrowser' => 'Navegador',
+ 'UserSettings_ColumnPlugin' => 'Plugin',
+ 'UserSettings_ColumnConfiguration' => 'Configuração',
+ 'UserSettings_ColumnOperatinsSystem' => 'Sistema Operacional',
+ 'UserSettings_ColumnResolution' => 'Resolução',
+ 'UserSettings_ColumnTypeOfScreen' => 'Tipo de tela',
+ 'UsersManager_ManageAccess' => 'Gerenciar acesso',
+ 'UsersManager_Sites' => 'Websites',
+ 'UsersManager_AllWebsites' => 'Todos os websites',
+ 'UsersManager_ApplyToAllWebsites' => 'Aplicar a todos os websites',
+ 'UsersManager_User' => 'Usur&aacute;rio',
+ 'UsersManager_PrivNone' => 'Sem acesso',
+ 'UsersManager_PrivView' => 'Ver',
+ 'UsersManager_PrivAdmin' => 'Admin',
+ 'UsersManager_ChangeAllConfirm' => 'Voc&ecirc; tem certeza que deseja alterar as permissões de %s em todos os websites?',
+ 'UsersManager_Login' => 'Usu&aacute;rio',
+ 'UsersManager_Password' => 'Senha',
+ 'UsersManager_Email' => 'Email',
+ 'UsersManager_Alias' => 'Apelido',
+ 'UsersManager_Token' => 'token_auth',
+ 'UsersManager_Edit' => 'Editar',
+ 'UsersManager_AddUser' => 'Adicionar novo usu&aacute;rio',
+ 'UsersManager_MenuUsers' => 'Usu&aacute;rios',
+ 'UsersManager_DeleteConfirm_js' => 'Tem certeza que deseja apagar o usu&aacute;rio %s?',
+ 'UsersManager_ExceptionLoginExists' => 'Usu&aacute;rio \'%s\' j&aacute; existe.',
+ 'UsersManager_ExceptionEmailExists' => 'Usu&aacute;rio com o e-mail \'%s\' j&aacute; existe.',
+ 'UsersManager_ExceptionInvalidPassword' => 'A senha deve conter entre 6 e 26 caracteres.',
+ 'UsersManager_ExceptionInvalidEmail' => 'O e-mail n&atilde;o tem um formato v&aacute;lido.',
+ 'UsersManager_ExceptionDeleteDoesNotExist' => 'O usu&aacute;rio \'%s\' n&atilde;o existe assim n&atilde;o &eacute; poss&iacute;vel exclu&iacute;-lo.',
+ 'UsersManager_ExceptionAdminAnonymous' => 'Voc&ecirc; n&atilde;o pode conceder acesso \'admin\' para o usu&aacute;rio \'anonymous\' .',
+ 'UsersManager_ExceptionEditAnonymous' => 'O usu&aacute;rio anonymous n&atilde;o pode ser editado ou apagado. Ele &eacute; usado pelo sistema para definir um usu&aacute;rio que ainda n&atilde;o n&atilde;o entrou. Por examplo, voc&ecirc; pode tornar as estat&iacute;sticas p&uacute;blicas concedendo acesso \'view\' para o usu&aacute;rio \'anonymous\'.',
+ 'UsersManager_ExceptionUserDoesNotExist' => 'Usu&aacute;rio \'%s\' n&atilde;o existe.',
+ 'UsersManager_ExceptionAccessValues' => 'O par&acirc;metro de acesso deve conter os seguintes valores: [ %s ]',
+ 'UsersManager_UsersManagement' => 'Gerenciamento de usuários',
+ 'UsersManager_UsersManagementMainDescription' => 'Crie novos usuários ou atualize os usuários existentes. Você poderá então ajustar as permissões deles acima.',
+ 'UsersManager_MainDescription' => 'Decida quais usuários terão acesso ao Piwik nos seus websites. Você pode também ajustar as permissões em todos os websites de uma só vez.',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'O login deve conter entre %s e %s caracteres e conter apenas letras, números ou os caracteres \'_\' ou\'.\'',
+ 'UsersManager_ExceptionSuperUser' => 'O usuário requisitado é o Super Usuário e não pode ser alterado, editado ou apagado através da API. Você pode editar manualmente os detalhes do Super Usuário no seu arquivo de configurações do Piwik.',
+ 'VisitFrequency_Evolution' => 'Evolu&ccedil;&atilde;o no Per&iacute;odo',
+ 'VisitFrequency_ReturnVisits' => '%s visitantes de retorno',
+ 'VisitFrequency_ReturnActions' => '%s a&ccedil;&otilde;es por visitante de retorno',
+ 'VisitFrequency_ReturnMaxActions' => '%s máximo de ações por um visitante de retorno',
+ 'VisitFrequency_ReturnTotalTime' => '%s tempo total gasto por visitantes de retorno',
+ 'VisitFrequency_ReturnBounces' => '%s vezes que um visitante desisitiu (deixou o site ap&oacute;s a primeira p&aacute;gina)',
+ 'VisitFrequency_WidgetOverview' => 'Vis&atilde;o Geral da Frequ&ecirc;ncia',
+ 'VisitFrequency_WidgetGraphReturning' => 'Gr&aacute;fico de Visitantes de Retorno',
+ 'VisitFrequency_SubmenuFrequency' => 'Frequ&ecirc;ncia',
+ 'VisitFrequency_ColumnReturningVisits' => 'Visitantes de Retorno',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Ações de Visitantes de Retorno',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Máximo de Ações por um Visitante de Retorno',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Tempo total gasto por Visitantes de Retorno (em segundos)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Taxa da saída para Visitantes de Retorno',
+ 'VisitFrequency_ReturnBounceRate' => '%s visitantes de retorno deixaram o website após uma página',
+ 'VisitTime_LocalTime' => 'Visitas pelo hor&aacute;rio local',
+ 'VisitTime_ServerTime' => 'Visitas pelo hor&aacute;rio do servidor',
+ 'VisitTime_WidgetLocalTime' => 'Visitas pelo horário local',
+ 'VisitTime_WidgetServerTime' => 'Visitas pelo horário do servidor',
+ 'VisitTime_SubmenuTimes' => 'Hor&aacute;rios',
+ 'VisitTime_NHour' => '%sh',
+ 'VisitTime_ColumnServerTime' => 'Horário do servidor',
+ 'VisitTime_ColumnLocalTime' => 'Horário local',
+ 'VisitorInterest_VisitsPerDuration' => 'Visitas por duração de visitas',
+ 'VisitorInterest_VisitsPerNbOfPages' => 'Visitas pelo n&uacute;mero de p&aacute;ginas',
+ 'VisitorInterest_WidgetLengths' => 'Dura&ccedil;&atilde;o das Visitas',
+ 'VisitorInterest_WidgetPages' => 'P&aacute;ginas por Visita',
+ 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Frequ&ecirc;ncia e Lealdade',
+ 'VisitorInterest_PlusXMin' => '%s min',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
+ 'VisitorInterest_OnePage' => '1 página',
+ 'VisitorInterest_NPages' => '%s páginas',
+ 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
+ 'VisitorInterest_ColumnVisitDuration' => 'Duração da visita',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Páginas por visita',
+ 'VisitsSummary_NbVisits' => '%s visitas',
+ 'VisitsSummary_NbUniqueVisitors' => '%s visitantes &uacute;nicos',
+ 'VisitsSummary_NbActions' => '%s ações (page views)',
+ 'VisitsSummary_TotalTime' => '%s tempo total gasto pelos visitantes',
+ 'VisitsSummary_MaxNbActions' => '%s a&ccedil;&otilde;es m&aacute;ximas em uma visita',
+ 'VisitsSummary_NbBounced' => '%s visitantes que desistiram (sa&iacute;ram do site ap&oacute;s a primeira p&aacute;gina)',
+ 'VisitsSummary_Evolution' => 'Evolu&ccedil;&atilde;o nos &uacute;ltimos 30 %s',
+ 'VisitsSummary_Report' => 'Relat&oacute;rio',
+ 'VisitsSummary_GenerateTime' => '%s segundos para gerar a p&aacute;gina',
+ 'VisitsSummary_GenerateQueries' => '%s consultas executadas',
+ 'VisitsSummary_WidgetLastVisits' => 'Gr&aacute;fico dos &uacute;ltimos visitantes',
+ 'VisitsSummary_WidgetVisits' => 'Vis&atilde;o Geral dos Visitantes',
+ 'VisitsSummary_WidgetLastVisitors' => 'Gr&aacute;fico dos &uacute;ltimos visitantes &uacute;nicos',
+ 'VisitsSummary_WidgetOverviewGraph' => 'Vis&atilde;o Geral com Gr&aacute;fico',
+ 'VisitsSummary_SubmenuOverview' => 'Vis&atilde;o Geral',
+ 'VisitsSummary_VisitsSummary' => 'Resumo dos Visitantes',
+ 'VisitsSummary_NbVisitsBounced' => '%s visitantes saíram (deixaram o website após uma página)',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Evolução nos/nas últimos(as) %s',
+ 'General_Dashboard' => 'Painel de Ferramentas',
+ 'General_DashboardForASpecificWebsite' => 'Painel de Ferramentas para um site especifico',
+ 'General_MultiSitesSummary' => 'Todos os sites',
+ 'General_AllWebsitesDashboard' => 'Painel de Ferramentas de Todos os sites',
+ 'General_NotValid' => '%s não é válido',
+ 'General_Username' => 'Nome de Usuário',
+ 'General_Details' => 'Detalhes',
+ 'General_Default' => 'Padrão',
+ 'General_GoTo' => 'Ir para %s',
+ 'General_YourChangesHaveBeenSaved' => 'Suas alterações foram salvas',
+ 'General_ExportAsImage_js' => 'Exportar como imagem',
+ 'General_SaveImageOnYourComputer_js' => 'Para salvar a imagem em seu computador, clique com o direito na imagem e selecione "Salvar Imagem Como..."',
+ 'General_Today' => 'Hoje',
+ 'General_Yesterday' => 'Ontem',
+ 'General_CurrentWeek' => 'Semana atual',
+ 'General_CurrentMonth' => 'Mês atual',
+ 'General_CurrentYear' => 'Ano atual',
+ 'General_PageBounceRateDefinition' => 'A porcentagem de visitas que entraram na página, e deixaram imediatamente',
+ 'General_ColumnExitRate' => 'Taxa de saída',
+ 'General_PageExitRateDefinition' => 'A porcentagem de visitas que entraram na página, e deixaram imediatamente',
+ 'General_ColumnBounces' => 'Saídas',
+ 'General_BouncesDefinition' => 'A porcentagem de visitas que entraram na página, e deixaram imediatamente',
+ 'General_ColumnEntrances' => 'Entradas',
+ 'General_EntrancesDefinition' => 'Número de visitas que começaram nessa página',
+ 'General_ColumnExits' => 'Saídas',
+ 'General_ExitsDefinition' => 'Número de visitas que terminaram nessa página',
+ 'General_ColumnAverageTimeOnPage' => 'Média de tempo na página',
+ 'General_AverageTimeOnPageDefinition' => 'Quantidade média de tempo que visitantes gastam nessa página',
+ 'General_DaysHours' => '%1$s dias %2$s horas',
+ 'General_HoursMinutes' => '%1$s horas %2$s minutos',
+ 'General_MinutesSeconds' => '%1$s minutos %2$s segundos',
+ 'General_Seconds' => '%s segundos',
+ 'General_ForExampleShort' => 'ex.',
+ 'General_GeneralSettings' => 'Configurações Gerais',
+ 'General_AllowPiwikArchivingToTriggerBrowser' => 'Permitir que o Piwik salve numa trigger quando relatórios são vistos do navegador',
+ 'General_ArchivingInlineHelp' => 'Para sites com tráfego de médio a alto, é recomendado desabilitar a trigger que salva do navegador. Em vez disso, nós recomendamos que instale um cron job para processar os relatorios Piwik a cada hora.',
+ 'General_ArchivingTriggerDescription' => 'Recomendado para grandes instalações Piwik, você precisa instalar um cron job para processar os relatórios automaticamente.',
+ 'General_SeeTheOfficialDocumentationForMoreInformation' => 'Veja a %s documentação oficial%s para mais informações.',
+ 'General_ReportsForTodayWillBeProcessedAtMostEvery' => 'Relatórios de hoje serão processados no máximo a cada',
+ 'General_NSeconds' => '%s segundos',
+ 'General_SmallTrafficYouCanLeaveDefault' => 'Para sites com tráfego baixo, você pode deixar o padrão de %s segundos, e acessar todos os relatórios em tempo real.',
+ 'General_MediumToHighTrafficItIsRecommendedTo' => 'Para sites com tráfego de médio a alto, nós recomendamos processar relatórios diariamente no máximo a cada meia hora(%s segundos)ou toda hora (%s segundos).',
+ 'General_RequiresFlash' => 'Mostrar gráficos no Piwik requer Flash',
+ 'General_GraphHelp' => 'Mais informações sobre mostrar gráficos em Piwik.',
+ 'General_DisplayGoals' => 'Mostrar metas',
+ 'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin' => '%s está disponível. Por favor notifique o administrador do site.',
+ 'General_ConfigFileIsNotWritable' => 'O arquivo %s de configuração Piwik não é editável, suas mudanças não serão salvas. %s por favor mude as permissões da configuração do arquivo para fazê-lo editável. ',
+ 'General_ExceptionDatabaseVersion' => 'Sua %1$s versão é %2$s mas o Piwik requer no mínimo %3$s.',
+ 'General_ExceptionIncompatibleClientServerVersions' => 'Sua %1$s client version é %2$s que é incompatível com a versão do servidor %3$s.',
+ 'General_ExceptionMissingFile' => 'Arquivo faltando: %s.',
+ 'General_ExceptionFilesizeMismatch' => 'Tamanho do arquivo incompatível: %1$s (esperado: %2$s, encontrado: %3$s)',
+ 'General_ExceptionFileIntegrity' => 'Check de inegridade falhou: %s.',
+ 'General_ExceptionNonceMismatch' => 'Não conseguiria verificar a segurança tomada nesse modelo.',
+ 'General_WarningFileIntegritySkipped' => 'Ambiente de desenvolvimento encontrado. Check de integridade de arquivo pulado.',
+ 'General_WarningFileIntegrityNoManifest' => 'O check de integridade do arquivo não pode ser feita enquanto estiver faltando manifest.inc.php.',
+ 'General_WarningFileIntegrityNoMd5file' => 'O check de integridade do arquivo não pode ser completado enquanto estiver faltando a função md5_file().',
+ 'General_FileIntegrityWarningExplanation' => 'O check de integridade do arquivo falhou e reportou alguns erros. Isso é mais provável devido a uma parcial ou upload falho de algum arquivo Piwik. Você deveria refazer o upload de todos os arquivos Piwik e atualizar a página até que nenhum erro seja exibido.',
+ 'API_PluginDescription' => 'Todos os dados no Piwik estão disponíveis através de APIs simples. Esse plugin é o ponto de entrada para o web service, que você pode chamar para ter seus dados Web Analytics em xml, json, php, csv, etc.',
+ 'ExampleAPI_PluginDescription' => 'Plugin Exemplo: Como criar uma API para seu plugin, para exportar seus dados em multiplos formatos sem nenhum código especial?',
+ 'Actions_PluginDescription' => 'Relatórios sobre visualização de páginas, links externos e downaloads. Rastramentos de links externos e downloads é automático!',
+ 'Actions_SubmenuPagesEntry' => 'Páginas de entrada',
+ 'Actions_SubmenuPagesExit' => 'Páginas de saída',
+ 'Actions_SubmenuPageTitles' => 'Títulos das páginas',
+ 'Actions_ColumnPageURL' => 'URL da página',
+ 'AnonymizeIP_PluginDescription' => 'Anonimize o último byte do endereço IP dos visitantes para obedecer suas leis/guias locais de privacidade.',
+ 'CoreAdminHome_PluginDescription' => 'Área Administrativa do Piwik.',
+ 'CoreAdminHome_MenuGeneralSettings' => 'Configurações Gerais',
+ 'CoreAdminHome_Administration' => 'Administração',
+ 'CoreHome_PluginDescription' => 'Estrutura de Relatórios Web Analytics',
+ 'CoreHome_WebAnalyticsReports' => 'Relatórios Web Analytics ',
+ 'CoreHome_ShortDay_1_js' => 'Dom',
+ 'CoreHome_ShortDay_2_js' => 'Seg',
+ 'CoreHome_ShortDay_3_js' => 'Ter',
+ 'CoreHome_ShortDay_4_js' => 'Qua',
+ 'CoreHome_ShortDay_5_js' => 'Qui',
+ 'CoreHome_ShortDay_6_js' => 'Sex',
+ 'CoreHome_ShortDay_7_js' => 'Sáb',
+ 'CoreHome_LongDay_1_js' => 'Domingo',
+ 'CoreHome_LongDay_2_js' => 'Segunda',
+ 'CoreHome_LongDay_3_js' => 'Terça',
+ 'CoreHome_LongDay_4_js' => 'Quarta',
+ 'CoreHome_LongDay_5_js' => 'Quinta',
+ 'CoreHome_LongDay_6_js' => 'Sexta',
+ 'CoreHome_LongDay_7_js' => 'Sábado',
+ 'CoreHome_ShortMonth_1_js' => 'Jan',
+ 'CoreHome_ShortMonth_2_js' => 'Fev',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Abr',
+ 'CoreHome_ShortMonth_5_js' => 'Mai',
+ 'CoreHome_ShortMonth_6_js' => 'Jun',
+ 'CoreHome_ShortMonth_7_js' => 'Jul',
+ 'CoreHome_ShortMonth_8_js' => 'Ago',
+ 'CoreHome_ShortMonth_9_js' => 'Set',
+ 'CoreHome_ShortMonth_10_js' => 'Out',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dez',
+ 'CorePluginsAdmin_PluginDescription' => 'Interface de Administração de Plugins',
+ 'CoreUpdater_PluginDescription' => 'Mecanismo de update Piwik',
+ 'CoreUpdater_NoteForLargePiwikInstances' => 'Nota importante para grandes instalações Piwik',
+ 'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand' => 'Se você tem um grande banco de dados Piwik, atualizações podem levar muito tempo para rodar no navegador. Nesse caso, você pode executar as atualizações da sua linha de comando: %s',
+ 'CoreUpdater_YouCouldManuallyExecuteSqlQueries' => 'Se você não tem permissão para atualizar pela linha de comando e se o Piwik falhou em atualizar (devido a um timeout do banco de dados, timeout do navegador, ou outro problema), você poderá manualmente executar as queries SQL para atualizar o Piwik.',
+ 'CoreUpdater_ClickHereToViewSqlQueries' => 'Clique aqui para ver e copiar a lista de queries SQL que serão executadas',
+ 'CoreUpdater_NoteItIsExpectedThatQueriesFail' => 'Nota: se você executar manualmente essas queries, é esperado que algumas delas falhem. Nesse caso, simplesmente ignore os erros, e rode os próximos da lista.',
+ 'CoreUpdater_ReadyToGo' => 'Pronto(a) para ir?',
+ 'DBStats_PluginDescription' => 'Esse plugin relata o banco de dados MySQL usado pelas tabelas Piwik.',
+ 'DBStats_LearnMore' => 'Apara aprender mais sobre como o Piwik processa os dados e como fazer o Piwik trabalhar bem para sites de médio e alto tráfego, confira a documentação %s.',
+ 'DBStats_RowCount' => 'Contagem de linhas',
+ 'Dashboard_PluginDescription' => 'Seu painel de ferramentas',
+ 'ExampleFeedburner_PluginDescription' => 'Plugin Exemplo: Como mostrar seu assinante Feedburner em um widget no painel de ferramentas?',
+ 'ExamplePlugin_PluginDescription' => 'Plugin Exemplo: Esse plugin mostra como criar um plugin muito simples que exporta dois widgets no painel de ferramentas',
+ 'ExamplePlugin_exampleWidgets' => 'Widgets Exemplo',
+ 'ExamplePlugin_exampleWidget' => 'Widget exemplo',
+ 'ExamplePlugin_blogPiwikRss' => 'Blog Piwik RSS',
+ 'ExamplePlugin_photostreamMatt' => 'Fotos de Matt',
+ 'ExampleRssWidget_PluginDescription' => 'Plugin Exemplo: Como criar um novo widget que lê um RSS feed?',
+ 'ExampleUI_PluginDescription' => 'Plugin Exemplo: Esse plugin mostra como trabalhar com o Piwik UI: criar tabelas, gráficos, etc.',
+ 'Feedback_PluginDescription' => 'Envie seu FeedBack para a Equipe Piwik. Compartilhe suas ideias e sugestões conosco!',
+ 'Feedback_DoYouHaveBugReportOrFeatureRequest' => 'Você tem algum bug pra relatar ou alguma caracteristica para pedir?',
+ 'Feedback_ViewAnswersToFAQ' => 'Ver respostas para %s as questões mais perguntadas.',
+ 'Feedback_WhyAreMyVisitsNoTracked' => 'Porque as visitas no meu website não estão sendo rastreadas?',
+ 'Feedback_HowToExclude' => 'Como excluir rastreamento de minhas visitas?',
+ 'Feedback_WhyWrongCountry' => 'Porque o Piwik mostra minha visita de um país errado?',
+ 'Feedback_HowToAnonymizeIP' => 'Como eu posso mascarar o endereço IP do visitante em meu banco de dados?',
+ 'Feedback_VisitTheForums' => 'Visite o %s Foruns %s',
+ 'Feedback_LearnWaysToParticipate' => 'Aprenda sobre todas as maneiras que você pode %s participar %s',
+ 'Feedback_SpecialRequest' => 'Você tem algum pedido especial para a equipe do Piwik?',
+ 'Feedback_ContactThePiwikTeam' => 'Entre em contato com a equipe Piwik!',
+ 'Feedback_IWantTo' => 'Eu quero:',
+ 'Feedback_CategoryShareStory' => 'Compartilhe uma história Piwik de sucesso',
+ 'Feedback_CategorySponsor' => 'Patrocinador Piwik',
+ 'Feedback_CategoryHire' => 'Contrate um consultor Piwik',
+ 'Feedback_CategorySecurity' => 'Relate um erro de segurança',
+ 'Feedback_MyEmailAddress' => 'Meu endereço de email:',
+ 'Feedback_MyMessage' => 'Minha mensagem:',
+ 'Feedback_DetailsPlease' => '(por favor inclua detalhes)',
+ 'Feedback_SendFeedback' => 'Envie FeedBack',
+ 'Feedback_ManuallySendEmailTo' => 'Por favor envie manualmente sua mensagem para',
+ 'Feedback_MessageSent' => 'Sua mensagem foi enviada para a equipe Piwik',
+ 'Feedback_ThankYou' => 'Obrigado por nos ajudar a fazer o Piwik melhor!',
+ 'Feedback_ThePiwikTeam' => 'A Equipe Piwik',
+ 'Feedback_ExceptionBodyLength' => 'A mensagem deve ter pelo menos %s caracteres.',
+ 'Feedback_ExceptionNoUrls' => 'A mensagem não pode conter uma URL para evitar mensagens spam.',
+ 'Goals_Goals' => 'Metas',
+ 'Goals_Overview' => 'Visão Geral',
+ 'Goals_PluginDescription' => 'Crie metas e veja relatórios sobre suas metas de conversão: evolução sobre o tempo, lucro por visita, conversões por referencia, por palavra-chave, etc.',
+ 'Goals_OverallRevenue' => '%s lucro total',
+ 'Goals_OverallConversionRate' => '%s taxa total de conversão(visitas com uma meta completa)',
+ 'Goals_Conversions' => '%s conversões',
+ 'Goals_ConversionRate' => '%s taxa de conversão',
+ 'Goals_NoGoalsNeedAccess' => 'Apenas um Administrador ou um Super Usuário podem adicionar metas para um dado website. Por favor peça a um administrador Piwik topara setar uma meta para seu website. <br>Rastrear metas é uma grande maneira de ajudar a entender e maximizar a performance de seu website!',
+ 'Goals_AddNewGoal' => 'Adicionar nova meta',
+ 'Goals_AddNewGoalOrEditExistingGoal' => '%sAdicionar nova meta%s ou %sEditar%s metas existentes',
+ 'Goals_AddGoal_js' => 'Adicionar meta',
+ 'Goals_UpdateGoal_js' => 'Atualizar meta',
+ 'Goals_DeleteGoalConfirm_js' => 'Tem certeza que deseja deletar a meta %s?',
+ 'Goals_GoalName' => 'Nome da meta',
+ 'Goals_GoalIsTriggered' => 'Meta está triggered',
+ 'Goals_GoalIsTriggeredWhen' => 'Meta está triggered quando',
+ 'Goals_WhenVisitors' => 'quando visitantes',
+ 'Goals_WhereThe' => 'onde o(a)',
+ 'Goals_Manually' => 'manualmente',
+ 'Goals_ManuallyTriggeredUsingJavascriptFunction' => 'A meta é manualmente triggered usando a API do Javascript trackGoal()',
+ 'Goals_VisitUrl' => 'Visitar a URL dada(página ou grupo de páginas)',
+ 'Goals_Download' => 'Baixar um arquivo',
+ 'Goals_ClickOutlink' => 'Clique num link para um website externo',
+ 'Goals_Optional' => '(opcional)',
+ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore' => 'onde a página visitada contem um chamado para o JavaScript piwikTracker.trackGoal() metodo (%slearn more%s)',
+ 'Goals_DefaultRevenue' => 'O lucro padrão da meta é',
+ 'Goals_DefaultRevenueHelp' => 'Por exemplo, um Form Contato submetido por um visitante pode valer $10 em média. Piwik ajudará a entender quão bem o segmento de seus visitantes está funcionando.',
+ 'Goals_ConversionsOverview' => 'Visão geral de conversões',
+ 'Goals_BestCountries' => 'Seus melhores países conversores são:',
+ 'Goals_BestKeywords' => 'Suas palavras-chave top de conversão são:',
+ 'Goals_BestReferers' => 'Seus melhores sites de conversão são:',
+ 'Goals_ReturningVisitorsConversionRateIs' => 'Taxa de retorno de visitantes convertidos é %s',
+ 'Goals_NewVisitorsConversionRateIs' => 'Taxa de conversão de novos usuários é %s',
+ 'Goals_Contains' => 'contem %s',
+ 'Goals_IsExactly' => 'é exatamente %s',
+ 'Goals_MatchesExpression' => 'corresponde com a expressão %s',
+ 'Goals_CaseSensitive' => 'Equivalencia case sensitive',
+ 'Goals_Pattern' => 'modelo',
+ 'Installation_PluginDescription' => 'Processo de instalação do Piwik. A instalação normalmente é feita apenas uma vez. Se o arquivo de configuração config/config.inc.php é deletado, a instalação começará novamente.',
+ 'Installation_DatabaseSetupServer' => 'servidor de banco de dados',
+ 'Installation_DatabaseSetupLogin' => 'login',
+ 'Installation_DatabaseSetupPassword' => 'senha',
+ 'Installation_DatabaseSetupDatabaseName' => 'nome do banco de dados',
+ 'Installation_DatabaseSetupTablePrefix' => 'prefixo da tabela',
+ 'Installation_DatabaseSetupAdapter' => 'adaptador',
+ 'Installation_DatabaseCheck' => 'check do banco de dados',
+ 'Installation_DatabaseServerVersion' => 'versão do servidor de banco de dados',
+ 'Installation_DatabaseClientVersion' => 'versão do banco de dados client',
+ 'Installation_DatabaseCreation' => 'Criação do banco de dados',
+ 'Installation_PleaseFixTheFollowingErrors' => 'Por favor, corrija os seguintes erros',
+ 'Installation_JsTagHelpTitle' => 'Como inserir a tag em seus websites?',
+ 'Installation_LargePiwikInstances' => 'Ajuda para instancias Piwik grandes',
+ 'Installation_SetupWebSiteName' => 'nome do website',
+ 'Installation_SetupWebSiteURL' => 'URL do website',
+ 'Installation_Timezone' => 'fuso-horário do website',
+ 'Installation_SystemCheckIconvHelp' => 'Você precisa configurar e reconstruir PHP com suporte "iconv" habilitado, --with-iconv.',
+ 'Installation_SystemCheckDomHelp' => 'DOM é parte no núcleo do PHP. Você provavelmente precisa instalar o módulo dom, ex: php-5-dom.',
+ 'Installation_SystemCheckParseIniFileHelp' => 'Essa função built-in foi desabilitada em seu host. Piwik tentará simular essa função mas poderá encontrar algumas restrições de segurança. Rastreador de performance também será impactado.',
+ 'Installation_SystemCheckDebugBacktraceHelp' => 'View Factory não será permitida para criar views pelo módulo chamado.',
+ 'Installation_SystemCheckCreateFunctionHelp' => 'Piwik usa funções anônimas para callbacks',
+ 'Installation_SystemCheckMbstring' => 'mbstring',
+ 'Installation_SystemCheckMbstringHelp' => 'Você deveria setar mbstring.func_overload para "O".',
+ 'Installation_SystemCheckFileIntegrity' => 'Integridade de arquivo.',
+ 'Installation_SystemCheckProtocol' => 'Protocolo',
+ 'Installation_SystemCheckProtocolHelp' => 'Se você está atras de um proxy reverso, adicione estas linhas ao config/config.ini.php abaixo da [General] sessão:',
+ 'Installation_SystemCheckIpv4' => 'IPv4',
+ 'Installation_SystemCheckIpv4Help' => 'Você deveria desabilitar IPv6 na configuração de seu servidor web.',
+ 'Installation_ConfigurationHelp' => 'Seu arquivo de configuração Piwik parece estar desconfigurado. Você pode ou remover config/config.ini.php e fechar a instalação, ou corrigir as configurações de conexão com banco de dados.',
+ 'LanguagesManager_PluginDescription' => 'Esse plugin mostrará uma lista de idiomas disponíveis para a interface do Piwik. O idioma selecionado salvará as preferencias para cada usuário.',
+ 'LanguagesManager_AboutPiwikTranslations' => 'Sobre traduções Piwik.',
+ 'Live_PluginDescription' => 'Espie seus visitantes, ao vivo, em tempo real!',
+ 'Live_VisitorLog' => 'Log de visitantes',
+ 'Live_Date' => 'Data',
+ 'Live_Time' => 'Tempo',
+ 'Live_Referrer_URL' => 'URL referente',
+ 'Live_Last30Minutes' => 'últimos 30 minutos',
+ 'Login_PluginDescription' => 'Plugin de autenticação de login, lendo as credenciais do arquivo config/config.inc.php para o Super Usuário, e do banco de dados para outros usuários. Pode ser facilmente substituido para introduzir um novo mecanismo (OpenID, htaccess, custom Auth, etc).',
+ 'Login_InvalidNonceOrReferer' => 'Chave de segurança inválida ou expirada. Favor atualizar o form e checar se os cookies estão habilitados.',
+ 'MultiSites_PluginDescription' => 'Mostra sumários/estatísticas executivas multi-site. No momento, mantida como plugin núcleo do Piwik.',
+ 'MultiSites_Evolution' => 'Evolução',
+ 'Provider_PluginDescription' => 'Relata o provedor dos visitantes.',
+ 'Referers_PluginDescription' => 'Relata os dados referentes: mecanismos de pesquisa, palavras-chave, websites, campanha de rastreamento, entrada direta.',
+ 'SecurityInfo_PluginDescription' => 'Baseada no PhpSecInfo do Consórsio de Segurança do PHP, esse plugin prove segurança da informação sobre seu ambiente PHP and oferece sugestões de melhoria. É uma ferramenta em uma aproximação segura multi camadas. Isso não substitui praticas de segurança no desenvolvimento nem auditar o código/aplicação.',
+ 'SecurityInfo_Security' => 'Segurança',
+ 'SecurityInfo_SecurityInformation' => 'Segurança da Informação PHP',
+ 'SecurityInfo_Test' => 'Teste',
+ 'SecurityInfo_Result' => 'Resultado',
+ 'SitesManager_PluginDescription' => 'Gerenciamento de websites no Piwik: adiciona um novo website, edita um existente, mostra código JavaScript para incluir em suas páginas. Todas as ações também estão disponíveis através da API.',
+ 'SitesManager_AliasUrlHelp' => 'É recomendado, mas não necessário, especificar as várias URLs que seus visitantes usam para acessar esse site, uma por linha. Pseudônimos de URLs para websites não aparecerão em Referencias > relatórios de websites. Note que não é necessário especificar as URLs com ou sem \'www\' como o Piwik considera automaticamente ambos.',
+ 'SitesManager_SuperUserCan' => 'O Super Usuário pode também %s especificar configurações globais %s para novos websites',
+ 'SitesManager_ExcludedIps' => 'IPs excluidos',
+ 'SitesManager_GlobalListExcludedIps' => 'Lista global de IPs excluidos',
+ 'SitesManager_ListOfIpsToBeExcludedOnAllWebsites' => 'Os IPs abaixo serão excluidos por terem sido rastreados em todos os websites.',
+ 'SitesManager_ExcludedParameters' => 'Parâmetros Excluídos',
+ 'SitesManager_GlobalListExcludedQueryParameters' => 'Lista global de parâmetros Query URL para excluir',
+ 'SitesManager_ListOfQueryParametersToBeExcludedOnAllWebsites' => 'Os parâmetros Query URL abaixo serão excluidos das URLs em todos os websites',
+ 'SitesManager_ListOfQueryParametersToExclude' => 'Entre com a lista de parâmetros URL Query, uma por linha, para excluir os relátorios das páginas URL',
+ 'SitesManager_PiwikWillAutomaticallyExcludeCommonSessionParameters' => 'Piwik excluirá automaticamente a sessão comum de parâmetros (%s).',
+ 'SitesManager_HelpExcludedIps' => 'Entre com a lista de IPs, um por linha, que você deseja excluir por ter sido rastreado pelo Piwik. Você pode usar wildcards, ex: %1$s ou %2$s',
+ 'SitesManager_YourCurrentIpAddressIs' => 'Seu endereço de IP atual é %s',
+ 'SitesManager_SelectACity' => 'Selecione uma cidade',
+ 'SitesManager_ChooseCityInSameTimezoneAsYou' => 'Escolha uma cidade no mesmo fuso-horário que você',
+ 'SitesManager_ChangingYourTimezoneWillOnlyAffectDataForward' => 'Ao mudar seu fuso-horário apenas afetará os dados que vierem depois, não será aplicado retroativamente.',
+ 'SitesManager_AdvancedTimezoneSupportNotFound' => 'Suporte a fusos-horários avançados não encontrado em seu PHP (suportado no PHP >=5.2). Você pode ainda escolher um offset de UTC manual.',
+ 'SitesManager_UTCTimeIs' => 'UTC tempo é %s.',
+ 'SitesManager_Timezone' => 'Fuso horário',
+ 'SitesManager_GlobalWebsitesSettings' => 'Configurações globais de websites',
+ 'SitesManager_DefaultTimezoneForNewWebsites' => 'Fuso-horário padrão para novos websites',
+ 'SitesManager_SelectDefaultTimezone' => 'Você pode selecionar o fuso-horário para ser selecionado como padrão pra novos websites.',
+ 'SitesManager_Currency' => 'Moeda Corrente',
+ 'SitesManager_CurrencySymbolWillBeUsedForGoals' => 'O símbolo da moeda corrente será mostrado próximo às metas de lucro.',
+ 'SitesManager_DefaultCurrencyForNewWebsites' => 'Moeda corrente padrão para novos websites',
+ 'SitesManager_SelectDefaultCurrency' => 'Você pode selecionar a moeda corrente para ser setada como padrão para novos websites',
+ 'SitesManager_Save_js' => 'Salvar',
+ 'SitesManager_Cancel_js' => 'Cancelar',
+ 'TranslationsAdmin_PluginDescription' => 'Ajude a traduzir o Piwik para seu idioma.',
+ 'UserCountry_PluginDescription' => 'Relata o país dos visitantes',
+ 'UserSettings_PluginDescription' => 'Relatórios diversas configurações de usuário: navegador, navegador família, sistema operacional, plugins, resolução, configurações globais.',
+ 'UserSettings_OperatingSystems' => 'Sistemas Operacionais',
+ 'UserSettings_ColumnOperatingSystem' => 'Sistema Operacional',
+ 'UsersManager_PluginDescription' => 'Gerenciamento de Usuários no Piwik: adicionar novo usuário, editar um existente, atualizar permissões. Todas as ações também estão disponíveis na API.',
+ 'UsersManager_TheSuperUserAliasCannotBeChanged' => 'O pseudônimo do Super Usuário não pode ser alterado.',
+ 'UsersManager_ReportToLoadByDefault' => 'Relate para carregar por padrão',
+ 'UsersManager_ReportDateToLoadByDefault' => 'Relate data para carregar por padrão',
+ 'UsersManager_ForAnonymousUsersReportDateToLoadByDefault' => 'Para usuários anônimos, reportar dara para carregar por padrão',
+ 'UsersManager_ExcludeVisitsViaCookie' => 'Excluir suas visitas usando cookie',
+ 'UsersManager_YourVisitsAreIgnoredOnDomain' => '%s Suas visitas são ignoradas pelo Piwik em %s %s (o Piwik ignora o cookie encontrado em seu navegador).',
+ 'UsersManager_YourVisitsAreNotIgnored' => '%sSuas visitas não são ignoradas pelo Piwik%s (o Piwik ignora o cookie não encotrado em seu navegador)',
+ 'UsersManager_ClickHereToDeleteTheCookie' => 'Clique aqui para deletar o cookie e deixar o Piwik rastrear suas visitas',
+ 'UsersManager_ClickHereToSetTheCookieOnDomain' => 'Clique aqui para setar um cookie que excluirá suas visitas em websites rastrados pelo Piwik em %s',
+ 'UsersManager_MenuUserSettings' => 'Configurações de usuário',
+ 'UsersManager_MenuAnonymousUserSettings' => 'Configurações de usuário anônimo',
+ 'UsersManager_NoteNoAnonymousUserAccessSettingsWontBeUsed' => 'Nota: Você não tem nenhum website que um usuário anônimo pode acessar, as seguintes configurações não serão usadas.',
+ 'UsersManager_WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess' => 'Quando usuários não estão logados e visitam o Piwik, eles deveriam acessar',
+ 'UsersManager_ChangePassword' => 'Mudar senha',
+ 'UsersManager_IfYouWouldLikeToChangeThePasswordTypeANewOne' => 'Se você gostaria de mudar a senha, digite uma nova. Senão, deixe em branco.',
+ 'UsersManager_TypeYourPasswordAgain' => 'Digite a nova senha novamente.',
+ 'UsersManager_TheLoginScreen' => 'Tela de login',
+ 'UsersManager_YourUsernameCannotBeChanged' => 'Seu nome de usuário não pode ser alterado.',
+ 'VisitFrequency_PluginDescription' => 'Reportar diferentes estatísticas sobre os visitantes que retornam versus os visitantes pela primeira vez.',
+ 'VisitorInterest_PluginDescription' => 'Relatórios sobre o interesse do visitante: número de páginas visualizadas, tempo gasto no website.',
+ 'VisitorInterest_Engagement' => 'Compromisso',
+ 'VisitsSummary_PluginDescription' => 'Relata os números gerais Analytics: visitas, visitantes únicos, número de ações, taxas, etc.',
+ 'VisitsSummary_NbActionsDescription' => '%s ações (visualizações de páginas, downloads e links externos)',
+ 'VisitTime_PluginDescription' => 'Relata a hora local e a hora do servidor. Informação de hora do servidor pode ser útil para relacionar a manutenção do website.',
+ 'Widgetize_PluginDescription' => 'O plugin faz ficar muito fácil exportar qualquer widget Piwik para seu blog, website ou em Igoogle e Netvibes!',
+); \ No newline at end of file
diff --git a/lang/pt.php b/lang/pt.php
index caf402ddd5..992c820def 100644
--- a/lang/pt.php
+++ b/lang/pt.php
@@ -64,9 +64,35 @@ $translations = array(
'CoreHome_DayTh_js' => 'Qui',
'CoreHome_DayFr_js' => 'Sex',
'CoreHome_DaySa_js' => 'Sab',
+ 'CoreHome_ShortDay_1_js' => 'Dom',
+ 'CoreHome_ShortDay_2_js' => 'Seg',
+ 'CoreHome_ShortDay_3_js' => 'Ter',
+ 'CoreHome_ShortDay_4_js' => 'Qua',
+ 'CoreHome_ShortDay_5_js' => 'Qui',
+ 'CoreHome_ShortDay_6_js' => 'Sex',
+ 'CoreHome_ShortDay_7_js' => 'Sab',
+ 'CoreHome_LongDay_1_js' => 'Domingo',
+ 'CoreHome_LongDay_2_js' => 'Segunda-feira',
+ 'CoreHome_LongDay_3_js' => 'Terça-feira',
+ 'CoreHome_LongDay_4_js' => 'Quarta-feira',
+ 'CoreHome_LongDay_5_js' => 'Quinta-feira',
+ 'CoreHome_LongDay_6_js' => 'Sexta-feira',
+ 'CoreHome_LongDay_7_js' => 'Sabado',
+ 'CoreHome_ShortMonth_1_js' => 'Jan',
+ 'CoreHome_ShortMonth_2_js' => 'Fev',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Abr',
+ 'CoreHome_ShortMonth_5_js' => 'Mai',
+ 'CoreHome_ShortMonth_6_js' => 'Jun',
+ 'CoreHome_ShortMonth_7_js' => 'Jul',
+ 'CoreHome_ShortMonth_8_js' => 'Ago',
+ 'CoreHome_ShortMonth_9_js' => 'Set',
+ 'CoreHome_ShortMonth_10_js' => 'Out',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dez',
'CoreHome_MonthJanuary_js' => 'Janeiro',
'CoreHome_MonthFebruary_js' => 'Fevereiro',
- 'CoreHome_MonthMarch_js' => 'Mar&ccedil;o',
+ 'CoreHome_MonthMarch_js' => 'Março',
'CoreHome_MonthApril_js' => 'Abril',
'CoreHome_MonthMay_js' => 'Maio',
'CoreHome_MonthJune_js' => 'Junho',
@@ -121,7 +147,7 @@ $translations = array(
'UserSettings_Browsers' => 'Navegadores',
'UserSettings_Plugins' => 'Plugins',
'UserSettings_Configurations' => 'Configura&ccedil;&otilde;es',
- 'UserSettings_OperatinsSystems' => 'Sistemas Operacionais',
+ 'UserSettings_OperatingSystems' => 'Sistemas Operacionais',
'UserSettings_Resolutions' => 'Resolu&ccedil;&otilde;es',
'UserSettings_WideScreen' => 'Wide Screen',
'UserSettings_WidgetResolutions' => 'Resolu&ccedil;&otilde;es de Tela',
@@ -441,7 +467,6 @@ $translations = array(
'Login_PasswordReminder' => 'Por favor digite o seu nome de usu&aacute;rio ou e-mail. Voc&ecirc; receber&aacute; uma nova senha via e-mail.',
'Login_InvalidUsernameEmail' => 'Nome de usu&aacute;rio e/ou e-mail inv&aacute;lido',
'Login_MailTopicPasswordRecovery' => 'Recuperar senha',
- 'Login_MailPasswordRecoveryBody' => 'Ol&aacute; %1s, \n\n A sua nova senha &eacute;: %2s \n\n Voc&ecirc; pode entrar agora em: %3s',
'Login_PasswordSent' => 'A senha foi enviada. Cheque o seu e-mail.',
'Login_ContactAdmin' => 'Poss&iacute;vel raz&atilde;o: o seu host desabilitou a fun&ccedil;&atilde;o mail(). <br />Por favor contate o administrador.',
'UsersManager_ManageAccess' => 'Gerenciar acesso',
diff --git a/lang/ro.php b/lang/ro.php
index 6046e82c3e..8f514c926c 100644
--- a/lang/ro.php
+++ b/lang/ro.php
@@ -88,20 +88,46 @@ $translations = array(
'CoreHome_PeriodWeek' => 'Saptamana',
'CoreHome_PeriodMonth' => 'Luna',
'CoreHome_PeriodYear' => 'An',
- 'CoreHome_DaySu_js' => 'Dum',
- 'CoreHome_DayMo_js' => 'Lun',
- 'CoreHome_DayTu_js' => 'Mar',
- 'CoreHome_DayWe_js' => 'Mie',
- 'CoreHome_DayTh_js' => 'Joi',
- 'CoreHome_DayFr_js' => 'Vin',
- 'CoreHome_DaySa_js' => 'Sam',
+ 'CoreHome_DaySu_js' => 'Du',
+ 'CoreHome_DayMo_js' => 'Lu',
+ 'CoreHome_DayTu_js' => 'Ma',
+ 'CoreHome_DayWe_js' => 'Mi',
+ 'CoreHome_DayTh_js' => 'Jo',
+ 'CoreHome_DayFr_js' => 'Vi',
+ 'CoreHome_DaySa_js' => 'Sâ',
+ 'CoreHome_ShortDay_1_js' => 'Dum',
+ 'CoreHome_ShortDay_2_js' => 'Lun',
+ 'CoreHome_ShortDay_3_js' => 'Mar',
+ 'CoreHome_ShortDay_4_js' => 'Mie',
+ 'CoreHome_ShortDay_5_js' => 'Joi',
+ 'CoreHome_ShortDay_6_js' => 'Vin',
+ 'CoreHome_ShortDay_7_js' => 'Sâm',
+ 'CoreHome_LongDay_1_js' => 'Duminică',
+ 'CoreHome_LongDay_2_js' => 'Luni',
+ 'CoreHome_LongDay_3_js' => 'Marţi',
+ 'CoreHome_LongDay_4_js' => 'Miercuri',
+ 'CoreHome_LongDay_5_js' => 'Joi',
+ 'CoreHome_LongDay_6_js' => 'Vineri',
+ 'CoreHome_LongDay_7_js' => 'Sâmbătă',
+ 'CoreHome_ShortMonth_1_js' => 'Ian',
+ 'CoreHome_ShortMonth_2_js' => 'Feb',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Apr',
+ 'CoreHome_ShortMonth_5_js' => 'Mai',
+ 'CoreHome_ShortMonth_6_js' => 'Iun',
+ 'CoreHome_ShortMonth_7_js' => 'Iul',
+ 'CoreHome_ShortMonth_8_js' => 'Aug',
+ 'CoreHome_ShortMonth_9_js' => 'Sep',
+ 'CoreHome_ShortMonth_10_js' => 'Oct',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dec',
'CoreHome_MonthJanuary_js' => 'Ianuarie',
'CoreHome_MonthFebruary_js' => 'Februarie',
'CoreHome_MonthMarch_js' => 'Martie',
'CoreHome_MonthApril_js' => 'Aprilie',
'CoreHome_MonthMay_js' => 'Mai',
- 'CoreHome_MonthJune_js' => 'Junie',
- 'CoreHome_MonthJuly_js' => 'Julie',
+ 'CoreHome_MonthJune_js' => 'Iunie',
+ 'CoreHome_MonthJuly_js' => 'Iulie',
'CoreHome_MonthAugust_js' => 'August',
'CoreHome_MonthSeptember_js' => 'Septembrie',
'CoreHome_MonthOctober_js' => 'Octombrie',
@@ -181,7 +207,7 @@ $translations = array(
'UserSettings_Browsers' => 'Browsere',
'UserSettings_Plugins' => 'Pluginuri',
'UserSettings_Configurations' => 'Configurare',
- 'UserSettings_OperatinsSystems' => 'Sisteme operare',
+ 'UserSettings_OperatingSystems' => 'Sisteme operare',
'UserSettings_Resolutions' => 'Rezolutii',
'UserSettings_WideScreen' => 'Ecran extins',
'UserSettings_WidgetResolutions' => 'Rezolutii ecran',
@@ -518,9 +544,8 @@ $translations = array(
'Login_PasswordReminder' => 'Introduce-ti nume si adresa de mail. Vei primi parola pe adresa de mail indicata.',
'Login_InvalidUsernameEmail' => 'Nume/adresa mail invalida',
'Login_MailTopicPasswordRecovery' => 'Recuperare parola',
- 'Login_MailPasswordRecoveryBody' => 'Salut %1s, \n\n noua parola este: %2s \n\n logheaza-te la: %3s',
'Login_PasswordSent' => 'Parola a fost trimisa. Verifica emailul.',
- 'Login_ContactAdmin' => 'Motiv posibil: gazda ta poate avea dezactivata functia email . <br />Contactati adminstratorul.',
+ 'Login_ContactAdmin' => 'Motiv posibil: gazda ta poate avea dezactivata functia email . <br/>Contactati adminstratorul.',
'UsersManager_UsersManagement' => 'Management useri',
'UsersManager_UsersManagementMainDescription' => 'Creaza user nou sau actualizeaza userul existent. Poti seta permisiunile lor.',
'UsersManager_ManageAccess' => 'Manageriaza accesul',
diff --git a/lang/ru.php b/lang/ru.php
index 8dd07f29c3..6a70a393c5 100644
--- a/lang/ru.php
+++ b/lang/ru.php
@@ -1,4 +1,7 @@
<?php
+
+setlocale(LC_TIME, 'ru_RU.UTF-8');
+
$translations = array(
'General_Locale' => 'ru_RU.UTF-8',
'General_TranslatorName' => 'Vadim Nekhai (http://onix.name/)',
@@ -11,7 +14,7 @@ $translations = array(
'General_API' => 'API функции',
'General_Widgets' => 'Виджеты',
'General_Settings' => 'Настройки',
- 'General_GiveUsYourFeedback' => 'Обратная связь',
+ 'General_GiveUsYourFeedback' => 'Обратная связь',
'General_Unknown' => 'Неизвестно',
'General_Required' => '%s необходимо',
'General_Error' => 'Ошибка',
@@ -103,7 +106,7 @@ $translations = array(
'General_LongDay_6' => 'Суббота',
'General_LongDay_7' => 'Воскресенье',
'CorePluginsAdmin_Plugins' => 'Плагины',
- 'CorePluginsAdmin_PluginsManagement' => 'Управление плагинами',
+ 'CorePluginsAdmin_PluginsManagement' => 'Управление плагинами',
'CorePluginsAdmin_MainDescription' => 'Плагины расширяют функциональность Piwik. После установки плагина Вы можете активировать или деактивировать его здесь.',
'CorePluginsAdmin_Plugin' => 'Плагин',
'CorePluginsAdmin_Version' => 'Версия',
@@ -145,6 +148,32 @@ $translations = array(
'CoreHome_DayTh_js' => 'Чт',
'CoreHome_DayFr_js' => 'Пт',
'CoreHome_DaySa_js' => 'Сб',
+ 'CoreHome_ShortDay_1_js' => 'вск',
+ 'CoreHome_ShortDay_2_js' => 'пнд',
+ 'CoreHome_ShortDay_3_js' => 'втр',
+ 'CoreHome_ShortDay_4_js' => 'срд',
+ 'CoreHome_ShortDay_5_js' => 'чтв',
+ 'CoreHome_ShortDay_6_js' => 'птн',
+ 'CoreHome_ShortDay_7_js' => 'сбт',
+ 'CoreHome_LongDay_1_js' => 'воскресенье',
+ 'CoreHome_LongDay_2_js' => 'понедельник',
+ 'CoreHome_LongDay_3_js' => 'вторник',
+ 'CoreHome_LongDay_4_js' => 'среда',
+ 'CoreHome_LongDay_5_js' => 'четверг',
+ 'CoreHome_LongDay_6_js' => 'пятница',
+ 'CoreHome_LongDay_7_js' => 'суббота',
+ 'CoreHome_ShortMonth_1_js' => 'Янв',
+ 'CoreHome_ShortMonth_2_js' => 'Фев',
+ 'CoreHome_ShortMonth_3_js' => 'Мар',
+ 'CoreHome_ShortMonth_4_js' => 'Апр',
+ 'CoreHome_ShortMonth_5_js' => 'Май',
+ 'CoreHome_ShortMonth_6_js' => 'Июн',
+ 'CoreHome_ShortMonth_7_js' => 'Июл',
+ 'CoreHome_ShortMonth_8_js' => 'Авг',
+ 'CoreHome_ShortMonth_9_js' => 'Сен',
+ 'CoreHome_ShortMonth_10_js' => 'Окт',
+ 'CoreHome_ShortMonth_11_js' => 'Ноя',
+ 'CoreHome_ShortMonth_12_js' => 'Дек',
'CoreHome_MonthJanuary_js' => 'Январь',
'CoreHome_MonthFebruary_js' => 'Февраль',
'CoreHome_MonthMarch_js' => 'Март',
@@ -186,7 +215,8 @@ $translations = array(
'CoreUpdater_InstallingTheLatestVersion' => 'Установка последней версии',
'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik обновлен успешно!',
'CoreUpdater_EmptyDatabaseError' => 'База данных %s пуста. Вам необходимо править вручную или удалить файл конфигурации Piwik.',
- 'Actions_Actions' => 'Действия',
+ 'Actions_Actions' => 'Действия',
+ 'Actions_SubmenuPageTitles' => 'Заголовки',
'Actions_SubmenuPages' => 'Страницы',
'Actions_SubmenuOutlinks' => 'Внешн. ссылки',
'Actions_SubmenuDownloads' => 'Загрузки',
@@ -222,7 +252,7 @@ $translations = array(
'Referers_ColumnWebsite' => 'Вебсайт',
'Referers_ColumnWebsitePage' => 'Страница вебсайта',
'Referers_ColumnKeyword' => 'Ключевое слово',
- 'Referers_ColumnCampaign' => 'Кампания',
+ 'Referers_ColumnCampaign' => 'Кампания',
'Referers_DetailsByRefererType' => 'Детали по типу реферала',
'Referers_TypeDirectEntries' => '%s прямых входов',
'Referers_TypeSearchEngines' => '%s входов из поисковых движков',
@@ -248,14 +278,14 @@ $translations = array(
'UserSettings_Browsers' => 'По браузерам',
'UserSettings_Plugins' => 'Плагины',
'UserSettings_Configurations' => 'По конфигурации',
- 'UserSettings_OperatinsSystems' => 'По операционным системам',
+ 'UserSettings_OperatingSystems' => 'По операционным системам',
'UserSettings_Resolutions' => 'По разрешению мониторов',
'UserSettings_WideScreen' => 'По ширине экрана',
'UserSettings_ColumnBrowserFamily' => 'Семейство браузеров',
'UserSettings_ColumnBrowser' => 'Браузер',
'UserSettings_ColumnPlugin' => 'Плагин',
'UserSettings_ColumnConfiguration' => 'Конфигурация',
- 'UserSettings_ColumnOperatinsSystem' => 'Операционная система',
+ 'UserSettings_ColumnOperatingSystem' => 'Операционная система',
'UserSettings_ColumnResolution' => 'Разрешение',
'UserSettings_ColumnTypeOfScreen' => 'Тип экрана',
'UserSettings_WidgetResolutions' => 'По разрешению мониторов',
@@ -593,6 +623,8 @@ $translations = array(
'Login_LoginPasswordNotCorrect' => 'Логин или пароль неверны',
'Login_Login' => 'Логин',
'Login_Password' => 'Пароль',
+ 'Login_PasswordSuccessfullyChanged' => 'Пароль изменен!',
+ 'Login_InvalidOrExpiredToken' => 'Код неправильный или просрочен.',
'Login_LoginOrEmail' => 'Логин или E-mail',
'Login_LogIn' => 'Войти',
'Login_Logout' => 'Выйти',
@@ -601,9 +633,11 @@ $translations = array(
'Login_PasswordReminder' => 'Пожалуйста, введите свой логин или e-mail. Новый пароль прийдет вам по e-mail.',
'Login_InvalidUsernameEmail' => 'Неверное имя пользователя и/или e-mail',
'Login_MailTopicPasswordRecovery' => 'Восстановление пароля',
- 'Login_MailPasswordRecoveryBody' => 'Здравствуйте, %1s, \n\n Ваш новый пароль: %2s \n\n Теперь вы можете войти: %3s',
- 'Login_PasswordSent' => 'Пароль уже выслан, проверьте свою почту.',
+ 'Login_PasswordSent' => 'Пароль выслан, проверьте свою почту.',
'Login_ContactAdmin' => 'Возможная причина: функция mail() отключена. <br />Пожалуйста, свяжитесь с администратором.',
+ 'Login_PasswordResetToken' => 'Код смены пароля',
+ 'Login_PasswordRepeat' => 'Пароль (повторно)',
+ 'Login_ChangePassword' => 'Сменить',
'UsersManager_UsersManagement' => 'Управление пользователями',
'UsersManager_UsersManagementMainDescription' => 'Создание новых пользователей или редактирование существующих. Также Вы можете задать права доступа для пользователя.',
'UsersManager_ManageAccess' => 'Управление правами доступа',
@@ -652,6 +686,7 @@ $translations = array(
'SitesManager_ExceptionNoUrl' => 'Вы должны указать хотя бы один URL для этого сайта.',
'SitesManager_ExceptionEmptyName' => 'Название сайта не может быть пустое.',
'SitesManager_ExceptionInvalidUrl' => 'URL \'%s\' не верен.',
+ 'SitesManager_JsCodeHelp' => 'Встройте этот код в свои страницы перед тегом &lt;/body&gt;',
'Installation_Installation' => 'Установка',
'Installation_InstallationStatus' => 'Статус установки',
'Installation_PercentDone' => '%s %% Завершено',
@@ -736,4 +771,67 @@ $translations = array(
'TranslationsAdmin_LanguageCode' => 'Код языка',
'TranslationsAdmin_Export' => 'Экспорт языкового файла',
'TranslationsAdmin_Import' => 'Импорт языкового файла',
+ 'Live_VisitorLog' => 'Журнал',
+ 'UsersManager_PluginDescription' => 'Управление пользователями в Piwik: добавление новых пользователей, редактирование существующих, обновление прав доступа. Все действия доступны также через API.',
+ 'General_Dashboard' => 'Информ. панель',
+ 'General_MultiSitesSummary' => 'Сводная статистика',
+ 'General_Details' => 'Детали',
+ 'General_ExportAsImage_js' => 'Экспортировать как изображение',
+ 'General_SaveImageOnYourComputer_js' => 'Чтобы сохранить изображение на компьютер кликните правой кнопкой мыши и выберите пункт "Сохранить изображение как..."',
+ 'General_ForExampleShort' => 'напр.',
+ 'General_RequiresFlash' => 'Отображение графиков в Piwik требует Flash',
+ 'General_GraphHelp' => 'Больше деталей об отображении графиков в Piwik.',
+ 'General_ExceptionDatabaseVersion' => 'Версия вашего %1$s - %2$s, но Piwik требует хотя бы %3$s.',
+ 'General_ExceptionIncompatibleClientServerVersions' => 'Версия вашего %1$s - %2$s, она не совместима с сервером версии %3$s.',
+ 'General_ExceptionMissingFile' => 'Отсутствует файл: %s',
+ 'General_ExceptionFilesizeMismatch' => 'Размер файла не совпадает: %1$s (ожидался: %2$s, обнаружен: %3$s)',
+ 'General_ExceptionFileIntegrity' => 'Проверка целостности не удалась: %s',
+ 'General_ExceptionNonceMismatch' => '',
+ 'General_WarningFileIntegritySkipped' => 'Обнаружена среда разработки. Проверка целостности отключена.',
+ 'General_WarningFileIntegrityNoManifest' => 'Проверка целостности не может быть проведена из-за отсутствия manifest.inc.php.',
+ 'General_WarningFileIntegrityNoMd5file' => 'Проверка целостности не может быть проведена из-за отсутствия функции md5_file().',
+ 'General_FileIntegrityWarningExplanation' => '',
+ 'VisitsSummary_PluginDescription' => '',
+ 'VisitsSummary_VisitsSummary' => '',
+ 'VisitsSummary_NbActionsDescription' => '%s действий (просмотры страниц, загрузки, внешние переходы)',
+ 'SitesManager_PluginDescription' => '',
+ 'SitesManager_AliasUrlHelp' => 'Рекомендуется, но необязательно, указывать все домены для сайта. Нет необходимости указывать варианты адрес с "www" и без него. Piwik автоматически учитывает оба.',
+ 'UsersManager_MenuUserSettings'=>'Мои настройки',
+ 'UsersManager_YourUsernameCannotBeChanged'=>'Имя пользователя не может быть изменено.',
+ 'UsersManager_ReportToLoadByDefault'=>'Показывать при входе',
+ 'UsersManager_TheSuperUserAliasCannotBeChanged'=>'Алиас администратора не может быть изменен.',
+ 'UsersManager_ReportDateToLoadByDefault'=>'Отчет по умолчанию за',
+ 'UsersManager_ChangePassword'=>'Смена пароля',
+ 'UsersManager_IfYouWouldLikeToChangeThePasswordTypeANewOne'=>'Если вы хотите сменить пароль, введите новый. Иначе оставьте поле пустым.',
+ 'UsersManager_TypeYourPasswordAgain'=>'Повторите новый пароль.',
+ 'UsersManager_ExcludeVisitsViaCookie'=>'Cookie исключения из статистики',
+ 'UsersManager_YourVisitsAreNotIgnored'=>'%sВаши визиты не игнорируются%s.',
+ 'UsersManager_ClickHereToSetTheCookie'=>'Кликните, чтобы установить cookie, которая исключит ваши визиты из отчетов.',
+ 'UsersManager_YourVisitsAreIgnored' => '%sВаши визиты исключены из отчетов Piwik%s (Piwik обнаружил соотвествующую cookie в вашем броузере).',
+ 'UsersManager_ClickHereToDeleteTheCookie' => 'Кликните, чтобы удалить cookie',
+ 'MenuAnonymousUserSettings'=>'Настройки анономных пользователей',
+ 'UsersManager_NoteNoAnonymousUserAccessSettingsWontBeUsed'=>'Внимание: У вас нет ни одного сайта, к статистике которых имеют доступ анонимные пользователи. Эти настройки не будут использоваться.',
+ 'UsersManager_WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess'=>'Анонимный пользователь при входе попадает на',
+ 'UsersManager_TheLoginScreen'=>'Страницу входа',
+ 'UsersManager_ForAnonymousUsersReportDateToLoadByDefault'=>'Отчет для анонимных пользователей отображается за',
+
+ 'General_Username'=>'Имя пользователя',
+ 'General_AllWebsitesDashboard'=>'Сводную статистику всех сайтов',
+ 'General_DashboardForASpecificWebsite'=>'Информ. панель для сайта',
+ 'General_Today' => 'Сегодня',
+ 'General_Yesterday' => 'Вчера',
+ 'General_CurrentWeek' => 'Эту неделю',
+ 'General_CurrentMonth' => 'Этот месяц',
+ 'General_CurrentYear' => 'Этот год',
+ 'General_GeneralSettings' => 'Основные настройки',
+ 'General_AllowPiwikArchivingToTriggerBrowser' => 'Позволить Piwik архивировать отчеты при посещении',
+ 'General_ArchivingInlineHelp' => 'Для сайтов средней и высокой нагруженности следует отключить срабатывание архивации при посещении. В таких случаях мы рекмоендуем проводить архивацию раз в час с помощью cron.',
+ 'General_ArchivingTriggerDescription' => 'Рекомендуется для нагруженных сайтов. Вам нужно %sнастроить cron%s для автоматической обработки отчетов.',
+ 'General_SeeTheOfficialDocumentationForMoreInformation' => 'Ознакомьтесь с %sдокументацией%s для подробностей.',
+ 'General_ReportsForTodayWillBeProcessedAtMostEvery' => 'Отчеты за сегодня будут обновляться не чаще',
+ 'General_NSeconds' => '%s секунд',
+ 'General_SmallTrafficYouCanLeaveDefault' => 'Для небольших сайтов вы можете оставить %s секунд, и получать отчеты в реальном времени.',
+ 'General_MediumToHighTrafficItIsRecommendedTo' => 'Для средних и крупных сайтов мы рекомендуем делать отчеты за сегодня каждые полчаса (%s секунд) или даже каждый час (%s секунд).',
+ 'General_Default' => 'По умолчанию',
+ 'CoreAdminHome_MenuGeneralSettings' => 'Основные настройки',
); \ No newline at end of file
diff --git a/lang/sk.php b/lang/sk.php
index c46fc57cfc..27195c9f58 100644
--- a/lang/sk.php
+++ b/lang/sk.php
@@ -507,7 +507,7 @@ $translations = array(
'VisitorInterest_WidgetPages' => 'Strany na návštevu',
'VisitorInterest_SubmenuFrequencyLoyalty' => 'Frekvencia & Lojalita',
'VisitorInterest_PlusXMin' => '%s min',
- 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%2s min',
'VisitorInterest_OnePage' => '1 stránka',
'VisitorInterest_NPages' => '%s stránok',
'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
@@ -763,4 +763,4 @@ $translations = array(
',
'SitesManager_JsTrackingTagHelp' => 'Tu je JavaScript sledovacia značka (tag) na vloženie do vašich stránok',
'SitesManager_ShowTrackingTag' => 'zobraziť sledovaciu značku',
-);
+); \ No newline at end of file
diff --git a/lang/sq.php b/lang/sq.php
new file mode 100644
index 0000000000..224ae42a99
--- /dev/null
+++ b/lang/sq.php
@@ -0,0 +1,795 @@
+<?php
+$translations = array(
+ 'General_Locale' => 'sq_AL.UTF-8',
+ 'General_TranslatorName' => 'Besnik Bleta',
+ 'General_TranslatorEmail' => 'besnik@programeshqip.org',
+ 'General_EnglishLanguageName' => 'Albanian',
+ 'General_OriginalLanguageName' => 'Shqip',
+ 'General_HelloUser' => 'Tungjatjeta, %s!',
+ 'General_OpenSourceWebAnalytics' => 'Analizë Web me Burim të Hapur',
+ 'General_YourDashboard' => 'Pulti Juaj',
+ 'General_API' => 'API',
+ 'General_Widgets' => 'Widget-e',
+ 'General_Settings' => 'Rregullime',
+ 'General_GiveUsYourFeedback' => 'Na jepni Përshtypjet!',
+ 'General_Unknown' => 'I panjohur',
+ 'General_Required' => '%s e domosdoshme',
+ 'General_Error' => 'Gabim',
+ 'General_Warning' => 'Sinjalizim',
+ 'General_BackToHomepage' => 'Mbrapsht te faqja hyrëse e Piwik-it',
+ 'General_Yes' => 'Po',
+ 'General_No' => 'Jo',
+ 'General_Delete' => 'Fshije',
+ 'General_Edit' => 'Përpunojeni',
+ 'General_Ok' => 'Ok',
+ 'General_Close' => 'Mbylle',
+ 'General_Logout' => 'Dilni',
+ 'General_Done' => 'U bë',
+ 'General_LoadingData' => 'Po ngarkohen të dhënat...',
+ 'General_Loading' => 'Po ngarkohet...',
+ 'General_ErrorRequest' => 'Oops&hellip; problem gjatë kërkesës, ju lutem riprovoni.',
+ 'General_Next' => 'Pasuesja',
+ 'General_Previous' => 'E mëparshmja',
+ 'General_Search' => 'Kërko',
+ 'General_Others' => 'Tjetër',
+ 'General_Table' => 'Tabelë',
+ 'General_Piechart' => 'Qarkore',
+ 'General_TagCloud' => 'Re Etiketash',
+ 'General_VBarGraph' => 'Grafikë me shtylla vertikale',
+ 'General_Export' => 'Eksporto',
+ 'General_ExportAsImage' => 'Eksportoje si Pamje',
+ 'General_SaveImageOnYourComputer' => 'Për ta ruajtur pamjen në kompjuterin tuaj, djathtasklikoni mbi të dhe përzgjidhni "Ruaje Pamjen Si..."',
+ 'General_Refresh' => 'Rifreskoje faqen',
+ 'General_Visitors' => 'Vizitorë',
+ 'General_ColumnNbUniqVisitors' => 'Vizitorë unikë',
+ 'General_ColumnNbVisits' => 'Vizita',
+ 'General_ColumnNbActions' => 'Veprime',
+ 'General_ColumnMaxActions' => 'Veprime maksimum në një vizitë',
+ 'General_ColumnSumVisitLength' => 'Kohë gjithsej e harxhuar nga vizitorët (në sekonda)',
+ 'General_ColumnLabel' => 'Etiketë',
+ 'General_ColumnActionsPerVisit' => 'Veprime për Vizitë',
+ 'General_ColumnAvgTimeOnSite' => 'Kohë Mesatare te Site-i Web',
+ 'General_ColumnBounceRate' => 'Mesatare Kthimesh',
+ 'General_ColumnPageviews' => 'Shikime faqesh',
+ 'General_ColumnUniquePageviews' => 'Shikime Unike faqesh',
+ 'General_ColumnValuePerVisit' => 'Vlerë për Vizitë',
+ 'General_ColumnVisitsWithConversions' => 'Vizita me Shndërrime',
+ 'General_Save' => 'Ruaje',
+ 'General_Website' => '"Site" Web',
+ 'General_NoDataForGraph' => 'Pa të dhëna për këtë grafik',
+ 'General_NoDataForTagCloud' => 'Pa të dhëna për këtë re etiketash.',
+ 'General_DisplayNormalTable' => 'Shfaq tabelë normale',
+ 'General_DisplayMoreData' => 'Shfaq më tepër të dhëna',
+ 'General_PiwikIsACollaborativeProjectYouCanContribute' => '%s Piwik %s është projekt bashkëpunimi. %s Po qe se e pëlqeni Piwik-un, mund të ndihmoni! Shihni se %s Si mund të ndihmoni te Piwik-u?%s ',
+ 'General_YouAreCurrentlyViewingDemoOfPiwik' => 'Tani për tani po shihni një provë të %s; %sshkarkoni%s versionin e plotë! Shiheni %s',
+ 'General_PiwikXIsAvailablePleaseUpdateNow' => 'Mund të kihet Piwik %s. %s Ju lutem, përditësojeni tani!%s (shihni %s ndryshimet%s).',
+ 'General_BackToPiwik' => 'Mbrapsht te Piwik-u',
+ 'General_ShortMonth_1' => 'Jan',
+ 'General_ShortMonth_2' => 'Shk',
+ 'General_ShortMonth_3' => 'Mar',
+ 'General_ShortMonth_4' => 'Pri',
+ 'General_ShortMonth_5' => 'Maj',
+ 'General_ShortMonth_6' => 'Qer',
+ 'General_ShortMonth_7' => 'Kor',
+ 'General_ShortMonth_8' => 'Gus',
+ 'General_ShortMonth_9' => 'Sht',
+ 'General_ShortMonth_10' => 'Tet',
+ 'General_ShortMonth_11' => 'Nën',
+ 'General_ShortMonth_12' => 'Dhj',
+ 'General_LongMonth_1' => 'Janar',
+ 'General_LongMonth_2' => 'Shkurt',
+ 'General_LongMonth_3' => 'Mars',
+ 'General_LongMonth_4' => 'Prill',
+ 'General_LongMonth_5' => 'Maj',
+ 'General_LongMonth_6' => 'Qershor',
+ 'General_LongMonth_7' => 'Korrik',
+ 'General_LongMonth_8' => 'Gusht',
+ 'General_LongMonth_9' => 'Shtator',
+ 'General_LongMonth_10' => 'Tetor',
+ 'General_LongMonth_11' => 'Nëntor',
+ 'General_LongMonth_12' => 'Dhjetor',
+ 'General_ShortDay_1' => 'Hën',
+ 'General_ShortDay_2' => 'Mar',
+ 'General_ShortDay_3' => 'Mër',
+ 'General_ShortDay_4' => 'Enj',
+ 'General_ShortDay_5' => 'Pre',
+ 'General_ShortDay_6' => 'Sht',
+ 'General_ShortDay_7' => 'Die',
+ 'General_LongDay_1' => 'E hënë',
+ 'General_LongDay_2' => 'E martë',
+ 'General_LongDay_3' => 'E mërkurë',
+ 'General_LongDay_4' => 'E enjte',
+ 'General_LongDay_5' => 'E premte',
+ 'General_LongDay_6' => 'E shtunë',
+ 'General_LongDay_7' => 'E dielë',
+ 'API_QuickDocumentation' => '<h2>Dokumentim i shpejtë për API-n</h2><p>Nëse nuk keni të dhëna për sot, mund të <a href=\'misc/generateVisits.php\' target=_blank>prodhoni ca të dhëna</a> së pari, duke përdorur programthin Gjenerator Vizitash.</p><p>për secilën metodë, mund të përdorni formatet e ndryshëm të mundshëm. Prej Piwik-ut është shumë e lehtë të nxirren çfarëdo të dhënash që doni!</p><p><b>Për më tepër, të dhëna hidhini një sy <a href=\'http://dev.piwik.org/trac/wiki/API\'>Dokumentimit zyrtar të API-t</a> ose <a href=\'http://dev.piwik.org/trac/wiki/API/Reference\'>Referencave për API-n</a>.</b></P><h2>Mirëfilltësim përdoruesi</h2><p>Nëse doni <b>të kërkoni të dhëna për programthin tuaj, për një crontab, etj. </b> lypset të shtoni parametrin <code><u>&token_auth=%s</u></code> te URL thirrjesh API që kanë nevojë për mirëfilltësim.</p><p>Ky token_auth është po aq sekret sa të dhënat tuaja për hyrje dhe fjalëkalimi juaj, <b>mos ia tregoni njeriu!</p>',
+ 'API_LoadedAPIs' => 'U ngarkua me sukses API %s',
+ 'Actions_Actions' => 'Veprime',
+ 'Actions_SubmenuPages' => 'Faqe',
+ 'Actions_SubmenuOutlinks' => 'Jashtëlidhje',
+ 'Actions_SubmenuDownloads' => 'Shkarkime',
+ 'Actions_ColumnClicks' => 'Klikime',
+ 'Actions_ColumnUniqueClicks' => 'Klikime Unike',
+ 'Actions_ColumnDownloads' => 'Shkarkime',
+ 'Actions_ColumnUniqueDownloads' => 'Shkarkime Unike',
+ 'Actions_ColumnPageName' => 'Emër Faqeje',
+ 'Actions_ColumnClickedURL' => 'URL të klikuara',
+ 'Actions_ColumnDownloadURL' => 'URL shkarkimesh',
+ 'CoreHome_NoPrivileges' => 'Jeni futur si \'%s\', por duket se nuk keni leje të rregulluara për te Piwik-u.<br />Kërkojini përgjegjësit tuaj për Piwik-un t\'ju japë të drejta \'parjeje\' për te "site"-i web.',
+ 'CoreHome_JavascriptDisabled' => 'Që të mund të përdorni Piwik-un nën parjen standarde, duhet aktivizuar JavaScript-i.<br />E megjithatë, duket se ose JavaScript-i është i çaktivizuar, ose nuk mbulohet nga shfletuesi juaj.<br />Që të përdorni parjen standarde, aktivizoni JavaScript-in duke ndryshuar përzgjedhjet te shfletuesi juaj, mandej %1sriprovoni%2s.<br />',
+ 'CoreHome_TableNoData' => 'Pa të dhëna për këtë tabelë.',
+ 'CoreHome_CategoryNoData' => 'Pa të dhëna për këtë kategori. Provoni të "Përfshini tërë popullatën".',
+ 'CoreHome_ShowJSCode' => 'Shfaqe kodin JavaScript që duhet futur',
+ 'CoreHome_IncludeAllPopulation_js' => 'Përfshi krejt popullatën',
+ 'CoreHome_ExcludeLowPopulation_js' => 'Përjashto popullatën e ulët',
+ 'CoreHome_PageOf_js' => '%s nga %s',
+ 'CoreHome_Loading_js' => 'Po ngarkohet...',
+ 'CoreHome_DayFormat' => '%longDay% %day% %longMonth% %longYear%',
+ 'CoreHome_PeriodDay' => 'Ditë',
+ 'CoreHome_PeriodWeek' => 'Javë',
+ 'CoreHome_PeriodMonth' => 'Muaj',
+ 'CoreHome_PeriodYear' => 'Vit',
+ 'CoreHome_PeriodDays' => 'ditë',
+ 'CoreHome_PeriodWeeks' => 'javë',
+ 'CoreHome_PeriodMonths' => 'muaj',
+ 'CoreHome_PeriodYears' => 'vite',
+ 'CoreHome_DaySu_js' => 'Di',
+ 'CoreHome_DayMo_js' => 'Hë',
+ 'CoreHome_DayTu_js' => 'Ma',
+ 'CoreHome_DayWe_js' => 'Më',
+ 'CoreHome_DayTh_js' => 'En',
+ 'CoreHome_DayFr_js' => 'Pr',
+ 'CoreHome_DaySa_js' => 'Sh',
+ 'CoreHome_MonthJanuary_js' => 'Janar',
+ 'CoreHome_MonthFebruary_js' => 'Shkurt',
+ 'CoreHome_MonthMarch_js' => 'Mars',
+ 'CoreHome_MonthApril_js' => 'Prill',
+ 'CoreHome_MonthMay_js' => 'Maj',
+ 'CoreHome_MonthJune_js' => 'Qershor',
+ 'CoreHome_MonthJuly_js' => 'Korrik',
+ 'CoreHome_MonthAugust_js' => 'Gusht',
+ 'CoreHome_MonthSeptember_js' => 'Shtator',
+ 'CoreHome_MonthOctober_js' => 'Tetor',
+ 'CoreHome_MonthNovember_js' => 'Nëntor',
+ 'CoreHome_MonthDecember_js' => 'Dhjetor',
+ 'CorePluginsAdmin_Plugins' => 'Shtojca',
+ 'CorePluginsAdmin_PluginsManagement' => 'Administrim Shtojcash',
+ 'CorePluginsAdmin_MainDescription' => 'Shtojcat zgjerojnë dhe thellojnë funksionet e Piwik-ut. Pasi një shtojcë të jetë instaluar, mund ta aktivizoni ose çaktivizoni prej këtu.',
+ 'CorePluginsAdmin_Plugin' => 'Shtojca',
+ 'CorePluginsAdmin_Version' => 'Version',
+ 'CorePluginsAdmin_Description' => 'Përshkrim',
+ 'CorePluginsAdmin_Status' => 'Gjendje',
+ 'CorePluginsAdmin_Action' => 'Veprim',
+ 'CorePluginsAdmin_PluginHomepage' => 'Faqe Hyrëse e Shtojcës',
+ 'CorePluginsAdmin_Activated' => 'E aktivizuar',
+ 'CorePluginsAdmin_Active' => 'Vepruese',
+ 'CorePluginsAdmin_Inactive' => 'Jovepruese',
+ 'CorePluginsAdmin_ActivatedHelp' => 'Kjo shtojcë nuk mund të çaktivizohet',
+ 'CorePluginsAdmin_Deactivate' => 'Çaktivizoje',
+ 'CorePluginsAdmin_Activate' => 'Aktivizoje',
+ 'CorePluginsAdmin_MenuPlugins' => 'Shtojca',
+ 'CoreUpdater_UpdateTitle' => 'Piwik &rsaquo; Përditësim',
+ 'CoreUpdater_DatabaseUpgradeRequired' => 'Lypset Përmirësim i Bazës së të Dhënave',
+ 'CoreUpdater_YourDatabaseIsOutOfDate' => 'Baza juaj e të dhënave për Piwik-un është e vjetruar, dhe duhet përmirësuar përpara se të mund të vazhdoni.',
+ 'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY' => 'Baza e të dhënave për Piwik-un do të përmirësohet prej versionit %s te versioni i ri %s.',
+ 'CoreUpdater_TheFollowingPluginsWillBeUpgradedX' => 'Shtojcat vijuese do të përditësohen: %s.',
+ 'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient' => 'Procesi i përditësimit të bazës së të dhënave mund të zgjasë ca, ndaj bëni durim.',
+ 'CoreUpdater_UpgradePiwik' => 'Përmirësojeni Piwik-un',
+ 'CoreUpdater_HelpMessageContent' => 'Hidhini një sy %s Piwik FAQ %s që shpjegojnë gabimet më të rëndomta gjatë përditësimesh. %s Pyesni përgjegjësin e sistemit tuaj - ai mund të jetë në gjendje të t\'ju ndihmojë për gabimin, i cili ka shumë të ngjarë të ketë lidhje me rregullimet e shërbyesit tuaj ose ato të MySQL-së.',
+ 'CoreUpdater_CriticalErrorDuringTheUpgradeProcess' => 'Gabim Kritik gjatë procesit të përditësimit:',
+ 'CoreUpdater_HelpMessageIntroductionWhenError' => 'Sa më sipër, është thelbi i mesazhit të gabimit. Do të ndihmonte të shpjegohej shkaku, por nëse keni nevojë për ndihmë të mëtejshme, ju lutem:',
+ 'CoreUpdater_HelpMessageIntroductionWhenWarning' => 'Përditësimi u plotësua me sukses, sidoqoftë pati ca kleçka gjatë procesit. Ju lutem, lexoni përshkrimet më sipër për hollësi. Për më tepër ndihmë:',
+ 'CoreUpdater_UpgradeComplete' => 'Përmirësim i plotësuar!',
+ 'CoreUpdater_WarningMessages' => 'Mesazhe sinjalizimi:',
+ 'CoreUpdater_ErrorDuringPluginsUpdates' => 'Gabim gjatë përditësimit të shtojcave:',
+ 'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins' => 'Çaktivizuam automatikisht shtojcat vijuese: %s',
+ 'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded' => 'Piwik-u u përmirësua me sukses!',
+ 'CoreUpdater_ContinueToPiwik' => 'Vazhdoni te Piwik-u',
+ 'CoreUpdater_UpdateAutomatically' => 'Përmirësoje Vetvetiu',
+ 'CoreUpdater_ThereIsNewVersionAvailableForUpdate' => 'Mund të kihet një version i ri, i përmirësuar, i Piwik-ut',
+ 'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage' => 'Mund ta përmirësoni automatikisht me versionin %s, ose të shkarkoni paketën dhe ta instaloni atë dorazi:',
+ 'CoreUpdater_DownloadX' => 'Shkarko %s',
+ 'CoreUpdater_UpdateHasBeenCancelledExplanation' => 'Përditësimi Piwik Me Një Klik u anulua. Nëse nuk ndreqni dot gabimin me mesazhin e mësipërm, këshillohet ta përditësoni Piwik-un dorazi. %s Ju lutem, shihni %sdokumentimin e Përditësimeve%s për t\'ia filluar!',
+ 'CoreUpdater_VerifyingUnpackedFiles' => 'Po verifikohen kartelat e shpaketuara',
+ 'CoreUpdater_CreatingBackupOfConfigurationFile' => 'Po krijohet një kopjeruajtje e kartelës së formësimit te %s',
+ 'CoreUpdater_InstallingTheLatestVersion' => 'Po instalohet versioni më i fundit',
+ 'CoreUpdater_PiwikUpdatedSuccessfully' => 'Piwik-u u përditësua me sukses!',
+ 'CoreUpdater_EmptyDatabaseError' => 'Baza e të dhënave %s është bosh. Kartelën tuaj të formësimit të Piwik-ut duhet ta përpunoni ose ta hiqni.',
+ 'CoreUpdater_ExceptionAlreadyLatestVersion' => 'Versioni juaj %s i Piwik-ut është i fundit.',
+ 'CoreUpdater_ExceptionArchiveIncompatible' => 'Arkivë e papërputhshme: %s',
+ 'CoreUpdater_ExceptionArchiveEmpty' => 'Arkivë bosh.',
+ 'CoreUpdater_ExceptionArchiveIncomplete' => 'Arkiva nuk është e plotë: mungojnë disa kartela (p.sh. %s).',
+ 'CoreUpdater_TheUpgradeProcessMayFail' => 'Po qe se keni një bazë të dhënash Piwik të madhe, përditësimet mund të duan shumë për të xhiruar në shfletues. Në një rast të tillë, përditësime mund t\'i kryeni përmes rreshti urdhrash: <code>$ php shtegu/për_te/piwik/index.php</code>',
+ 'CoreUpdater_ErrorDIYHelp' => 'Nëse jeni përdorues i përparuar dhe hasni gabim në përmirësimin e bazës së të dhënave:',
+ 'CoreUpdater_ErrorDIYHelp_1' => 'identifikoni dhe ndreqni burimin e problemit (p.sh., memory_limit ose max_execution_time)',
+ 'CoreUpdater_ErrorDIYHelp_2' => 'plotësoni kërkesat e mbetura te përditësimi që dështoi',
+ 'CoreUpdater_ErrorDIYHelp_3' => 'përditësojeni dorazi tabelën `option` te baza juaj e të dhënave për Piwik-un, duke caktuar si vlerë për version_core vlerën e përditësimit që dështoi',
+ 'CoreUpdater_ErrorDIYHelp_4' => 'rixhironi përditësuesin (nga shfletuesi ose rreshti i urdhrave) për të vazhduar me përditësimet e mbetura',
+ 'CoreUpdater_ErrorDIYHelp_5' => 'njoftoni për problemin (dhe zgjidhjen), që kështu Piwik-u të mund të përmirësohet',
+ 'CoreUpdater_DownloadingUpdateFromX' => 'Po shkarkohet përditësimi prej %s',
+ 'CoreUpdater_UnpackingTheUpdate' => 'Po shpaketohet përditësimi',
+ 'DBStats_DatabaseUsage' => 'Përdorim baze të dhënash',
+ 'DBStats_MainDescription' => 'Piwik-u po i depoziton krejt të dhënat tuaja për analizë web te baza e të dhënave MySQL. Tani për tani, tabelat e Piwik-ut po përdorin %s.',
+ 'DBStats_Table' => 'Tabelë',
+ 'DBStats_RowNumber' => 'Numër rreshtash',
+ 'DBStats_DataSize' => 'Madhësi të dhënash',
+ 'DBStats_IndexSize' => 'Madhësi treguesi',
+ 'DBStats_TotalSize' => 'Madhësi gjithsej',
+ 'Dashboard_Dashboard' => 'Pulti',
+ 'Dashboard_AddWidget' => 'Shtoni një "widget"...',
+ 'Dashboard_DeleteWidgetConfirm' => 'Jeni i sigurt se doni të fshihet ky "widget" prej pulti?',
+ 'Dashboard_SelectWidget' => 'Përzgjidhni "widget"-in që doni të shtoni te pulti',
+ 'Dashboard_AddPreviewedWidget_js' => 'Shtoje "widget"-in e paraparë te pulti',
+ 'Dashboard_WidgetPreview_js' => 'Paraparje "widget"-i',
+ 'Dashboard_Close_js' => 'Mbylle',
+ 'Dashboard_TitleWidgetInDashboard_js' => '"Widget" i pranishëm në pult',
+ 'Dashboard_TitleClickToAdd_js' => 'Klikoni për ta shtuar te pulti',
+ 'Dashboard_LoadingWidget_js' => '"Widget"-i po ngarkohet, ju lutem prisni...',
+ 'Dashboard_WidgetNotFound_js' => 'Nuk u gjet "widget"',
+ 'ExamplePlugin_exampleWidgets' => '"Widget"-e shembuj',
+ 'ExamplePlugin_exampleWidget' => 'Widget" shembull',
+ 'ExamplePlugin_blogPiwikRss' => 'RSS Blogu Piwik',
+ 'ExamplePlugin_photostreamMatt' => 'Foto të Matt-it',
+ 'Goals_ColumnConversions' => 'Shndërrime',
+ 'Goals_ColumnConversionRate' => 'Kurs Këmbimi',
+ 'Goals_ColumnRevenue' => 'Të ardhura',
+ 'Installation_Installation' => 'Instalim',
+ 'Installation_InstallationStatus' => 'Gjendje instalimi',
+ 'Installation_PercentDone' => 'Plotësuar %s %%',
+ 'Installation_NoConfigFound' => 'S\'u gjet dot kartela e formësimit të Piwik-ut dhe po provoni të hyni te një faqe Piwik-u.<br /><b>&nbsp;&nbsp;&raquo; Mund ta <a href=\'index.php\'>instaloni Piwik-un tani</a></b><br /><small>Nëse e kishit instaluar Piwik-un më parë dhe keni disa tabela te baza juaj e të dhënave, mos u shqetësoni, mund të ripërdorni po ato tabela dhe të mbani të dhënat tuaja ekzistuese!</small>',
+ 'Installation_MysqlSetup' => 'Rregullim baze të dhënash MySQL',
+ 'Installation_MysqlErrorConnect' => 'Gabim, ndërkohë që po provohej lidhja me bazën e të dhënave MySQL',
+ 'Installation_JsTag' => 'Etiketë JavaScript',
+ 'Installation_JsTagHelp' => '<p>Për numërimin e tërë vizitorëve, duhet të fusni kodin JavaScript në tërë faqet tuaj.</p><p>Nuk është e thënë që faqet tuaja duhet të jenë krijuar me PHP, Piwik-u do të funksionojë me tërë llojet e faqeve (HTML apo ASP, Perl ose cilëndo gjuhë tjetër).</p><p>Ja kodi që duhet të fusni: (kopjojeni dhe ngjiteni në tërë faqet tuaja) </p>',
+ 'Installation_Congratulations' => 'Urime',
+ 'Installation_CongratulationsHelp' => '<p>Urime! Instalimi juaj i Piwik-ut u plotësua.</p><p>Sigurohuni që keni futur kodin JavaScript te faqet tuaja, dhe prisni për vizitorët e parë!</p>',
+ 'Installation_ContinueToPiwik' => 'Vazhdo te Piwik-u',
+ 'Installation_SetupWebsite' => 'Caktoni një "site" web',
+ 'Installation_SetupWebsiteError' => 'Pati një gabim gjatë shtimit të një "site"-i web',
+ 'Installation_GeneralSetup' => 'Rregullim i Përgjithshëm',
+ 'Installation_GeneralSetupSuccess' => 'Rregullimi i Përgjithshëm u formësua me sukses',
+ 'Installation_SuperUserLogin' => 'emër hyrjeje për super përdoruesin',
+ 'Installation_Password' => 'fjalëkalim',
+ 'Installation_PasswordRepeat' => 'fjalëkalim (rijepeni)',
+ 'Installation_Email' => 'email',
+ 'Installation_SecurityNewsletter' => 'njoftomë me email për përditësime të rëndësishme të Piwik-ut dhe njoftime lidhur me sigurinë',
+ 'Installation_CommunityNewsletter' => 'njoftomë me email për përditësime nga bashkësia (shtojca të reja, veçori të reja, etj.)',
+ 'Installation_PasswordDoNotMatch' => 'fjalëkalimet nuk përputhen',
+ 'Installation_SubmitGo' => 'Jepi!',
+ 'Installation_Requirements' => 'Të domosdoshme për Piwik-un',
+ 'Installation_Optional' => 'Opsionale',
+ 'Installation_Legend' => 'Legjendë',
+ 'Installation_SystemCheck' => 'Kontroll sistemi',
+ 'Installation_SystemCheckPhp' => 'Version PHP-je',
+ 'Installation_SystemCheckExtensions' => 'Të tjera zgjerime të domosdoshme',
+ 'Installation_SystemCheckPdoHelp' => 'Lypset të aktivizoni zgjerimin PDO te kartela juaj php.ini.',
+ 'Installation_SystemCheckPdoMysqlHelp' => 'Lypset të aktivizoni zgjerimin PDO_MYSQL te kartela juaj php.ini.',
+ 'Installation_SystemCheckSplHelp' => 'Lypset të formësoni dhe krijoni PHP-në me Librarinë Standarde PHP të aktivizuar (si parazgjedhje).',
+ 'Installation_SystemCheckZlibHelp' => 'Lypset të formësoni dhe rikrijoni PHP-në me mbulim të zlib-it të aktivizuar, --with-zlib.',
+ 'Installation_SystemCheckWriteDirs' => 'Drejtori me hyrje shkrimi',
+ 'Installation_SystemCheckWriteDirsHelp' => 'Për ndreqjen e këtij gabimi në sistemin tuaj Linux, provoni të shtypni urdhrin(at) vijues',
+ 'Installation_SystemCheckMemoryLimit' => 'Kufi kujtese',
+ 'Installation_SystemCheckMemoryLimitHelp' => 'Në "site" web me shumë trafik, procesi i arkivimit mund të dojë më tepër kujtesë se sa i është dhënë tani. Në u dashtë, ndryshojeni parametrin memory_limit te kartela juaj php.ini.',
+ 'Installation_SystemCheckGD' => 'GD &gt; 2.x (grafikë)',
+ 'Installation_SystemCheckGDHelp' => '"Sparklines" (grafikë të veckël) nuk do të funksionojnë.',
+ 'Installation_SystemCheckFunctions' => 'Funksione të domosdoshëm',
+ 'Installation_SystemCheckTimeLimitHelp' => 'Në "site" web me shumë trafik, përmbushja e procesit të arkivimit mund të dojë më tepër kohë se sa i është dhënë tani. Në u dashtë, ndryshojeni parametrin max_execution_time te kartela juaj php.ini.',
+ 'Installation_SystemCheckMailHelp' => 'Mesazhet mbi Përshtypjet dhe Fjalëkalim të Humbur nuk kanë për t\'u dërguar pa mail().',
+ 'Installation_SystemCheckError' => 'Ndodhi një gabim - duhet të ndreqet përpara se të ecni më tej',
+ 'Installation_SystemCheckWarning' => 'Piwik-u do të punojë normalisht por mund t\'i mungojnë disa veçori',
+ 'Installation_Tables' => 'Krijim tabelash',
+ 'Installation_TablesWithSameNamesFound' => 'Disa tabela %s te baza juaj e të dhënave %s kanë të njëjtit emra si tabelat që Piwik-u po përpiqet të krijojë',
+ 'Installation_TablesFound' => 'Te baza e të dhënave u gjetën tabelat vijuese',
+ 'Installation_TablesWarningHelp' => 'Ose zgjidhni përdorimin sërish të tabelave ekzistuese të bazës së të dhënave, ose përzgjidhni instalimin nga e para për të fshirë tërë të dhënat ekzistuese te baza e të dhënave.',
+ 'Installation_TablesReuse' => 'Ripërdor tabelat ekzistuese',
+ 'Installation_TablesDelete' => 'Fshiji tabelat e pikasura',
+ 'Installation_TablesDeletedSuccess' => 'Tabelat ekzistuese të Piwik-ut u fshinë me sukses',
+ 'Installation_TablesCreatedSuccess' => 'Tabelat u krijuan me sukses!',
+ 'Installation_DatabaseCreatedSuccess' => 'Baza e të dhënave %s u krijua me sukses!',
+ 'Installation_GoBackAndDefinePrefix' => 'Kthehuni mbrapsht dhe përcaktoni një Prefiks për Tabelat e Piwik-ut',
+ 'Installation_ConfirmDeleteExistingTables' => 'Jeni i sigurt se doni të fshihen tabelat: %s prej bazës së të dhënave? KUJDES: NUK DO TË MUND TË RIKTHENI TË DHËNAT PREJ KËTYRE TABELAVE!',
+ 'Installation_Welcome' => 'Mirë se vini!',
+ 'Installation_WelcomeHelp' => '<p>Piwik-u është një program analize web, me burim të hapur, që e bën të lehtë të kihen të dhëna që dëshironi rreth vizitorëve tuaj.</p><p>Ky proces është ndarë në %s hapa të kollajtë dhe do të zgjasë rreth 5 minuta.</p>',
+ 'Installation_ErrorInvalidState' => 'Gabim: duket se po provoni të anashkaloni një hap të procesit të Instalimit, ose keni të çaktivizuara "cookies", ose kartela e formësimit të Piwik-ut është e krijuar tashmë. %sSigurohuni që "cookies" janë të aktivizuara%s dhe kthehuni mbrapsht %s te faqja e parë e instalimit %s.',
+ 'Installation_DatabaseSetup' => 'Rregullim baze të dhënash',
+ 'Installation_DatabaseErrorConnect' => 'Gabim gjatë provës për t\'u lidhur me shërbyesin e bazës së të dhënave',
+ 'Installation_ConnectionCharacterSetNotUtf8' => 'Lidhja e klientit te shërbyesi i bazës së të dhënave nuk po bëhet nën UTF8',
+ 'Installation_JsTagQuicHelpk' => 'Ndihmë e Shpejtë',
+ 'Installation_JsTagArchivingHelp' => 'Për "site"-e web me trafik mesatar ose të madh, shihni <a target="_blank" href="http://piwik.org/docs/setup-auto-archiving/">Si të rregullohet vetëarkivimi i faqeve</a>, për ta bërë Piwik-un të xhirojë vërtet shpejt!',
+ 'Installation_SetupWebsiteSetupSuccess' => '"Site"-i Web %s u shtua me sukses! ',
+ 'Installation_Extension' => 'zgjerim',
+ 'Installation_SystemCheckDatabaseHelp' => 'Piwik-u lyp ose zgjerimin mysqli, ose që të dy zgjerimet PDO dhe pdo_mysql.',
+ 'Installation_SystemCheckPdoAndMysqliHelp' => 'Në një shërbyes Linux mund ta përpiloni php-në me mundësitë vijuese: %s te php.ini juaj, shtoni rreshtat vijues: %s',
+ 'Installation_SystemCheckPhpPdoAndMysqliSite' => 'Më tepër të dhëna te: <a style="color:red" href="http://php.net/pdo">PHP PDO</a> dhe <a style="color:red" href="http://php.net/mysqli">MYSQLI</a>.',
+ 'Installation_SystemCheckWinPdoAndMysqliHelp' => 'Në një shërbyes Windows mund të shtoni rreshtat vijues te php.ini juaj: %s',
+ 'Installation_SystemCheckJson' => 'JSON',
+ 'Installation_SystemCheckJsonHelp' => 'Lypset të formësoni dhe rikrijoni PHP-në ose me zgjerimin "json", ose me atë "xml" të aktivizuar.',
+ 'Installation_SystemCheckJsonSite' => 'Më tepër të dhëna te: <a style="color:red" href="http://php.net/json">PHP JSON</a>.',
+ 'Installation_SystemCheckXml' => 'XML',
+ 'Installation_SystemCheckXmlHelp' => 'Disa shtojca dhe librari zhvillimi nga palë të treta mund të duan zgjerimin "xml"',
+ 'Installation_SystemCheckXmlSite' => 'Më tepër të dhëna te: <a style="color:red" href="http://php.net/xml">PHP XML</a>.',
+ 'Installation_SystemCheckOpenURL' => 'Hap URL',
+ 'Installation_SystemCheckOpenURLHelp' => 'Pajtimi në "newsletter", në njoftime përditësimesh, dhe përditësimi me një klikim e duan zgjerimin "curl", allow_url_fopen=On, ose fsockopen() të aktivizuar.',
+ 'Login_LoginPasswordNotCorrect' => 'Emër përdoruesi & Fjalëkalim jo të saktë',
+ 'Login_Login' => 'Emër përdoruesi',
+ 'Login_Password' => 'Fjalëkalim',
+ 'Login_PasswordRepeat' => 'Fjalëkalim (sërish)',
+ 'Login_ChangePassword' => 'Ndryshoni fjalëkalimin',
+ 'Login_LoginOrEmail' => 'Emër hyrjeje ose E-mail',
+ 'Login_LogIn' => 'Nënshkruani',
+ 'Login_Logout' => 'Çnënshkruani',
+ 'Login_LostYourPassword' => 'Humbët fjalëkalimin tuaj?',
+ 'Login_RemindPassword' => 'Dërgo ricaktim fjalëkalimi',
+ 'Login_PasswordResetToken' => '"Token" ricaktimi fjalëkalimi',
+ 'Login_PasswordReminder' => 'Ju lutem, jepni emrin tuaj të përdoruesit ose e-mail-in tuaj. Do të merrni një fjalëkalim të ri përmes e-mail-it.',
+ 'Login_PasswordsDoNotMatch' => 'Fjalëkalimet nuk përputhen.',
+ 'Login_PasswordSuccessfullyChanged' => 'Fjalëkalimi u ndryshua me sukses!',
+ 'Login_InvalidUsernameEmail' => 'Emër përdoruesi dhe/ose vendndodhje e-mail e pavlefshme',
+ 'Login_MailTopicPasswordRecovery' => 'Ricaktim fjalëkalimi',
+ 'Login_MailPasswordRecoveryBody' => 'Tungjatjeta %s,
+
+Kërkesa për ricaktim fjalëkalimi erdhi prej %s.
+
+Për ricaktimin e fjalëkalimit tuaj:
+
+1) Shkoni te Formulari për Ricaktim Fjalëkalimesh te:
+ %s
+
+2) Jepni elementin vijues:
+ %s
+
+3) Plotësoni formularin (duke e dhënë fjalëkalimin tuaj të ri dy herë) dhe parashtrojeni.
+
+Shënim: ky element do të skadojë brenda 24 orësh.
+',
+ 'Login_InvalidOrExpiredToken' => 'Elementi është i pavlefshëm ose ka skaduar',
+ 'Login_PasswordSent' => 'Hollësitë se si të ricaktoni fjalëkalimin tuaj u dërguan. Kontrolloni e-mail-et tuaj.',
+ 'Login_ContactAdmin' => 'Arsye e mundshme: streha juaj mund të ketë çaktivizuar funksionin mail(). <br />Ju lutem, lidhuni me përgjegjësin e Piwik-ut tuaj.',
+ 'Provider_WidgetProviders' => 'Mundësuesa',
+ 'Provider_ColumnProvider' => 'Mundësues',
+ 'Provider_SubmenuLocationsProvider' => 'Vende & mundësues',
+ 'Referers_Referers' => 'Referuesa',
+ 'Referers_SearchEngines' => 'Motorë Kërkimesh',
+ 'Referers_Keywords' => 'Fjalëkyça',
+ 'Referers_DirectEntry' => 'Zë i Drejtpërdrejtë',
+ 'Referers_Websites' => '"Site"-e Web',
+ 'Referers_Campaigns' => 'Fushata',
+ 'Referers_MetricsFromRefererTypeGraphLegend' => '%s (prej %s)',
+ 'Referers_Evolution' => 'Zhvillime përgjatë periudhës',
+ 'Referers_Type' => 'Lloj Referuesi',
+ 'Referers_ColumnRefererType' => 'Lloj Referuesi',
+ 'Referers_ColumnSearchEngine' => 'Motorë Kërkimesh',
+ 'Referers_ColumnWebsite' => '"Site" Web',
+ 'Referers_ColumnWebsitePage' => 'Faqe "site"-i Web',
+ 'Referers_ColumnKeyword' => 'Fjalëkyç',
+ 'Referers_ColumnCampaign' => 'Fushatë',
+ 'Referers_DetailsByRefererType' => 'Hollësi sipas Llojit të Referuesit',
+ 'Referers_TypeDirectEntries' => '%s zëra të drejtpërdrejtë',
+ 'Referers_TypeSearchEngines' => '%s prej motorësh kërkimi',
+ 'Referers_TypeWebsites' => '%s prej "site"-esh web',
+ 'Referers_TypeCampaigns' => '%s prej fushatash',
+ 'Referers_Distinct' => 'Referuesa të Dallueshëm sipas Llojit të Referuesit',
+ 'Referers_DistinctSearchEngines' => 'motorë kërkimesh të dallueshëm',
+ 'Referers_DistinctKeywords' => 'fjalëkyça të dallueshëm',
+ 'Referers_DistinctCampaigns' => 'fushata të dallueshme',
+ 'Referers_DistinctWebsites' => '"site"-e web të dallueshëm',
+ 'Referers_UsingNDistinctUrls' => '(po përdoren %2s url-ra të dallueshme)',
+ 'Referers_SubmenuEvolution' => 'Zhvillime',
+ 'Referers_SubmenuSearchEngines' => 'Motorë kërkimi & fjalëkyça',
+ 'Referers_SubmenuWebsites' => '"Site"-e Web',
+ 'Referers_SubmenuCampaigns' => 'Fushata',
+ 'Referers_WidgetKeywords' => 'Listë e Fjalëkyçave',
+ 'Referers_WidgetCampaigns' => 'Listë e Fushatave',
+ 'Referers_WidgetExternalWebsites' => 'Listë e "site"-eve Web të jashtëm',
+ 'Referers_WidgetSearchEngines' => 'Motorët më të mirë të kërkimit',
+ 'Referers_WidgetOverview' => 'Përmbledhje',
+ 'SitesManager_Sites' => '"Site"-e web',
+ 'SitesManager_WebsitesManagement' => 'Administrim "site"-esh web',
+ 'SitesManager_MainDescription' => 'Raportet tuaja të Analizuesit Web lypin "site"-e web! Shtoni, përditësoni, hiqni "site"-e web, dhe shfaqni JavaScript-in për futje në faqet tuaja.',
+ 'SitesManager_JsTrackingTag' => 'Etiketë Gjurmimi JavaScript',
+ 'SitesManager_JsTrackingTagHelp' => 'Kjo është etiketa e Gjurmimit JavaScript që të përfshihet në tërë faqet tuaja ',
+ 'SitesManager_ShowTrackingTag' => 'shfaq etiketë gjurmimi',
+ 'SitesManager_NoWebsites' => 'Nuk keni ndonjë "site" web për ta administruar.',
+ 'SitesManager_AddSite' => 'Shtoni "site" web të ri',
+ 'SitesManager_Id' => 'Id',
+ 'SitesManager_Name' => 'Emër',
+ 'SitesManager_Urls' => 'URL-ra',
+ 'SitesManager_MenuSites' => '"Site"-e web',
+ 'SitesManager_DeleteConfirm_js' => 'Jeni i sigurt se doni të hiqet "site"-i web %s?',
+ 'SitesManager_ExceptionDeleteSite' => 'Heqja e këtij "site"-i web nuk është e mundur, ngaqë është i vetmi "site" web i regjistruar. Së pari shtoni një "site" web të ri, mandej hiqni këtë këtu.',
+ 'SitesManager_ExceptionNoUrl' => 'Duhet të tregoni të paktën një URL për "site"-in web.',
+ 'SitesManager_ExceptionEmptyName' => '"Site"-i web s\'mund të jetë bosh.',
+ 'SitesManager_ExceptionInvalidUrl' => 'Url-ja \'%s\' nuk është URL e vlefshme.',
+ 'TranslationsAdmin_MenuTranslations' => 'Përkthime',
+ 'TranslationsAdmin_MenuLanguages' => 'Gjuhë',
+ 'TranslationsAdmin_Plugin' => 'Shtojca',
+ 'TranslationsAdmin_Definition' => 'Përkufizim',
+ 'TranslationsAdmin_DefaultString' => 'Vargu parazgjedhje (Anglisht)',
+ 'TranslationsAdmin_TranslationString' => 'Vargu i përkthyer (gjuha e tanishme: %s)',
+ 'TranslationsAdmin_Translations' => 'Përkthime',
+ 'TranslationsAdmin_FixPermissions' => 'Ju lutem rregulloni lejet për te sistemi i kartelave',
+ 'TranslationsAdmin_AvailableLanguages' => 'Gjuhë të passhme',
+ 'TranslationsAdmin_AddLanguage' => 'Shtoni gjuhë',
+ 'TranslationsAdmin_LanguageCode' => 'Kod gjuhe',
+ 'TranslationsAdmin_Export' => 'Eksporto gjuhë',
+ 'TranslationsAdmin_Import' => 'Importo gjuhë',
+ 'UserCountry_Country' => 'Vend',
+ 'UserCountry_Continent' => 'Kontinent',
+ 'UserCountry_DistinctCountries' => '%s vende ndaras',
+ 'UserCountry_SubmenuLocations' => 'Vende',
+ 'UserCountry_WidgetContinents' => 'Kontinente vizitorësh',
+ 'UserCountry_WidgetCountries' => 'Vende vizitorësh',
+ 'UserCountry_country_ac' => 'Ishujt Asension',
+ 'UserCountry_country_ad' => 'Andorra',
+ 'UserCountry_country_ae' => 'Emiratet e Bashkuara Arabe',
+ 'UserCountry_country_af' => 'Afganistan',
+ 'UserCountry_country_ag' => 'Antigua dhe Barbuda',
+ 'UserCountry_country_ai' => 'Anguila',
+ 'UserCountry_country_al' => 'Shqipëri',
+ 'UserCountry_country_am' => 'Armeni',
+ 'UserCountry_country_an' => 'Antilet Holandeze',
+ 'UserCountry_country_ao' => 'Angola',
+ 'UserCountry_country_aq' => 'Antarktida',
+ 'UserCountry_country_ar' => 'Argjntinë',
+ 'UserCountry_country_as' => 'Samoa Amerikane',
+ 'UserCountry_country_at' => 'Austri',
+ 'UserCountry_country_au' => 'Australi',
+ 'UserCountry_country_aw' => 'Aruba',
+ 'UserCountry_country_ax' => 'Ishujt Aland',
+ 'UserCountry_country_az' => 'Azerbaixhan',
+ 'UserCountry_country_ba' => 'Bosnjë dhe Hercegovinë',
+ 'UserCountry_country_bb' => 'Barbados',
+ 'UserCountry_country_bd' => 'Bangladesh',
+ 'UserCountry_country_be' => 'Belgjikë',
+ 'UserCountry_country_bf' => 'Burkina Faso',
+ 'UserCountry_country_bg' => 'Bullgari',
+ 'UserCountry_country_bh' => 'Bahrein',
+ 'UserCountry_country_bi' => 'Burundi',
+ 'UserCountry_country_bj' => 'Benin',
+ 'UserCountry_country_bl' => 'Shën Bartolome',
+ 'UserCountry_country_bm' => 'Bermuda',
+ 'UserCountry_country_bn' => 'Bruneo',
+ 'UserCountry_country_bo' => 'Bolivi',
+ 'UserCountry_country_br' => 'Brazil',
+ 'UserCountry_country_bs' => 'Bahamas',
+ 'UserCountry_country_bt' => 'Butan',
+ 'UserCountry_country_bu' => 'Burma',
+ 'UserCountry_country_bv' => 'Ishulli Buve',
+ 'UserCountry_country_bw' => 'Botsvana',
+ 'UserCountry_country_by' => 'Bjellorusi',
+ 'UserCountry_country_bz' => 'Belize',
+ 'UserCountry_country_ca' => 'Kanada',
+ 'UserCountry_country_cc' => 'Ishujt Kokos (Kiling)',
+ 'UserCountry_country_cd' => 'Repulika Demokratike e Kongos',
+ 'UserCountry_country_cf' => 'Republika e Afrikës Qendore',
+ 'UserCountry_country_cg' => 'Kongo',
+ 'UserCountry_country_ch' => 'Zvicër',
+ 'UserCountry_country_ci' => 'Bregu i Fildishtë',
+ 'UserCountry_country_ck' => 'Ishujt Kuk',
+ 'UserCountry_country_cl' => 'Kili',
+ 'UserCountry_country_cm' => 'Kamerun',
+ 'UserCountry_country_cn' => 'Kinë',
+ 'UserCountry_country_co' => 'Kolombi',
+ 'UserCountry_country_cp' => 'Ishulli Klipërton',
+ 'UserCountry_country_cr' => 'Kosta Rika',
+ 'UserCountry_country_cs' => 'Serbi Mal i Zi',
+ 'UserCountry_country_cu' => 'Kubë',
+ 'UserCountry_country_cv' => 'Kepi i Gjelbër',
+ 'UserCountry_country_cx' => 'Ishulli i Kërshnellave',
+ 'UserCountry_country_cy' => 'Qipro',
+ 'UserCountry_country_cz' => 'Republika Çeke',
+ 'UserCountry_country_de' => 'Gjermani',
+ 'UserCountry_country_dg' => 'Diego Garcia',
+ 'UserCountry_country_dj' => 'Xhiibut',
+ 'UserCountry_country_dk' => 'Danimarkë',
+ 'UserCountry_country_dm' => 'Dominika',
+ 'UserCountry_country_do' => 'Republika Dominikane',
+ 'UserCountry_country_dz' => 'Algjeri',
+ 'UserCountry_country_ea' => 'Ceuta, Melilla',
+ 'UserCountry_country_ec' => 'Ekuador',
+ 'UserCountry_country_ee' => 'Estoni',
+ 'UserCountry_country_eg' => 'Egjipt',
+ 'UserCountry_country_eh' => 'Sahara Perëndimore',
+ 'UserCountry_country_er' => 'Eritre',
+ 'UserCountry_country_es' => 'Spanjë',
+ 'UserCountry_country_et' => 'Etiopi',
+ 'UserCountry_country_eu' => 'Bashkimi Europian',
+ 'UserCountry_country_fi' => 'Finlandë',
+ 'UserCountry_country_fj' => 'Fixhi',
+ 'UserCountry_country_fk' => 'Ishujt Folkland (Malvinas)',
+ 'UserCountry_country_fm' => 'Shtetet Federale të Mikronezisë',
+ 'UserCountry_country_fo' => 'Ishujt Faroe',
+ 'UserCountry_country_fr' => 'Francë',
+ 'UserCountry_country_fx' => 'Franca Metropolitane',
+ 'UserCountry_country_ga' => 'Gabon',
+ 'UserCountry_country_gb' => 'Britani e Madhe',
+ 'UserCountry_country_gd' => 'Grenada',
+ 'UserCountry_country_ge' => 'Gjeorgjia',
+ 'UserCountry_country_gf' => 'Guajana Franceze',
+ 'UserCountry_country_gg' => 'Gernsi',
+ 'UserCountry_country_gh' => 'Gana',
+ 'UserCountry_country_gi' => 'Gjibraltar',
+ 'UserCountry_country_gl' => 'Groenlandë',
+ 'UserCountry_country_gm' => 'Gambia',
+ 'UserCountry_country_gn' => 'Guine',
+ 'UserCountry_country_gp' => 'Guadalup',
+ 'UserCountry_country_gq' => 'Guinea Ekuatoriale',
+ 'UserCountry_country_gr' => 'Greqi',
+ 'UserCountry_country_gs' => 'Xhorxhia Jugore dhe Ishujt Sanduiçi i Jugut',
+ 'UserCountry_country_gt' => 'Guatemalë',
+ 'UserCountry_country_gu' => 'Guam',
+ 'UserCountry_country_gw' => 'Guinea-Bisau',
+ 'UserCountry_country_gy' => 'Guajana',
+ 'UserCountry_country_hk' => 'Hong Kong',
+ 'UserCountry_country_hm' => 'Ishujt Heard dhe Ishujt McDonald',
+ 'UserCountry_country_hn' => 'Honduras',
+ 'UserCountry_country_hr' => 'Kroaci',
+ 'UserCountry_country_ht' => 'Haiti',
+ 'UserCountry_country_hu' => 'Hungari',
+ 'UserCountry_country_ic' => 'Ishujt Kanarie',
+ 'UserCountry_country_id' => 'Indonezi',
+ 'UserCountry_country_ie' => 'Irlandë',
+ 'UserCountry_country_il' => 'Izrael',
+ 'UserCountry_country_im' => 'Ishulli i Robit',
+ 'UserCountry_country_in' => 'Indi',
+ 'UserCountry_country_io' => 'Territoret Britanike në Oqeanin Indian',
+ 'UserCountry_country_iq' => 'Irak',
+ 'UserCountry_country_ir' => 'Republike Islamike e Iranit',
+ 'UserCountry_country_is' => 'Islandë',
+ 'UserCountry_country_it' => 'Itali',
+ 'UserCountry_country_je' => 'Xhersi',
+ 'UserCountry_country_jm' => 'Xhamaikë',
+ 'UserCountry_country_jo' => 'Jordani',
+ 'UserCountry_country_jp' => 'Japoni',
+ 'UserCountry_country_ke' => 'Kenia',
+ 'UserCountry_country_kg' => 'Kirgizstan',
+ 'UserCountry_country_kh' => 'Kamboxhia',
+ 'UserCountry_country_ki' => 'Kiribati',
+ 'UserCountry_country_km' => 'Komoros',
+ 'UserCountry_country_kn' => 'Shën Kits dhe Nevis',
+ 'UserCountry_country_kp' => 'Republika Demokratike Popullore e Koresë',
+ 'UserCountry_country_kr' => 'Republika e Koresë',
+ 'UserCountry_country_kw' => 'Kuvajt',
+ 'UserCountry_country_ky' => 'Ishujt Kajman',
+ 'UserCountry_country_kz' => 'Kazakistan',
+ 'UserCountry_country_la' => 'Laos',
+ 'UserCountry_country_lb' => 'Liban',
+ 'UserCountry_country_lc' => 'Shën Lucia',
+ 'UserCountry_country_li' => 'Lihtenshtein',
+ 'UserCountry_country_lk' => 'Sri Lanka',
+ 'UserCountry_country_lr' => 'Liberi',
+ 'UserCountry_country_ls' => 'Lesoto',
+ 'UserCountry_country_lt' => 'Lituani',
+ 'UserCountry_country_lu' => 'Luksemburg',
+ 'UserCountry_country_lv' => 'Letonia',
+ 'UserCountry_country_ly' => 'Libia',
+ 'UserCountry_country_ma' => 'Marok',
+ 'UserCountry_country_mc' => 'Monako',
+ 'UserCountry_country_md' => 'Republika e Moldavisë',
+ 'UserCountry_country_me' => 'Mal i Zi',
+ 'UserCountry_country_mf' => 'Shën Martin',
+ 'UserCountry_country_mg' => 'Madagaskar',
+ 'UserCountry_country_mh' => 'Ishujt Marshall',
+ 'UserCountry_country_mk' => 'Maqedoni',
+ 'UserCountry_country_ml' => 'Mali',
+ 'UserCountry_country_mm' => 'Mianmar',
+ 'UserCountry_country_mn' => 'Mongoli',
+ 'UserCountry_country_mo' => 'Makau',
+ 'UserCountry_country_mp' => 'Ishujt Veriorë Mariana',
+ 'UserCountry_country_mq' => 'Martinikë',
+ 'UserCountry_country_mr' => 'Mauritani',
+ 'UserCountry_country_ms' => 'Montserrat',
+ 'UserCountry_country_mt' => 'Maltë',
+ 'UserCountry_country_mu' => 'Mauricius',
+ 'UserCountry_country_mv' => 'Maldive',
+ 'UserCountry_country_mw' => 'Malaui',
+ 'UserCountry_country_mx' => 'Meksikë',
+ 'UserCountry_country_my' => 'Malajzi',
+ 'UserCountry_country_mz' => 'Mozambik',
+ 'UserCountry_country_na' => 'Namibi',
+ 'UserCountry_country_nc' => 'Kaledonia e Re',
+ 'UserCountry_country_ne' => 'Niger',
+ 'UserCountry_country_nf' => 'Ishujt Norfolk',
+ 'UserCountry_country_ng' => 'Nigeri',
+ 'UserCountry_country_ni' => 'Nikaragua',
+ 'UserCountry_country_nl' => 'Hollandë',
+ 'UserCountry_country_no' => 'Norvegji',
+ 'UserCountry_country_np' => 'Nepal',
+ 'UserCountry_country_nr' => 'Nauru',
+ 'UserCountry_country_nt' => 'Zonë Neutral',
+ 'UserCountry_country_nu' => 'Niue',
+ 'UserCountry_country_nz' => 'Zelandë e Re',
+ 'UserCountry_country_om' => 'Oman',
+ 'UserCountry_country_pa' => 'Panama',
+ 'UserCountry_country_pe' => 'Peru',
+ 'UserCountry_country_pf' => 'Polinezia Franceze',
+ 'UserCountry_country_pg' => 'Papua Nju Guinea',
+ 'UserCountry_country_ph' => 'Filipine',
+ 'UserCountry_country_pk' => 'Pakistan',
+ 'UserCountry_country_pl' => 'Poloni',
+ 'UserCountry_country_pm' => 'Shën Pier dhe Mikëlon',
+ 'UserCountry_country_pn' => 'Pitkern',
+ 'UserCountry_country_pr' => 'Porto Riko',
+ 'UserCountry_country_ps' => 'Territoret Palestineze',
+ 'UserCountry_country_pt' => 'Portugali',
+ 'UserCountry_country_pw' => 'Palau',
+ 'UserCountry_country_py' => 'Paraguaj',
+ 'UserCountry_country_qa' => 'Katar',
+ 'UserCountry_country_re' => 'Ishulli Reunion',
+ 'UserCountry_country_ro' => 'Rumani',
+ 'UserCountry_country_ru' => 'Rusi',
+ 'UserCountry_country_rs' => 'Serbi',
+ 'UserCountry_country_rw' => 'Ruandë',
+ 'UserCountry_country_sa' => 'Arabi Saudite',
+ 'UserCountry_country_sb' => 'Ishujt Solomon',
+ 'UserCountry_country_sc' => 'Sejshelle',
+ 'UserCountry_country_sd' => 'Sudan',
+ 'UserCountry_country_se' => 'Suedi',
+ 'UserCountry_country_sf' => 'Finlandë',
+ 'UserCountry_country_sg' => 'Singapor',
+ 'UserCountry_country_sh' => 'Shën Helena',
+ 'UserCountry_country_si' => 'Sloveni',
+ 'UserCountry_country_sj' => 'Svalbard',
+ 'UserCountry_country_sk' => 'Slovaki',
+ 'UserCountry_country_sl' => 'Sierra Leone',
+ 'UserCountry_country_sm' => 'San Marino',
+ 'UserCountry_country_sn' => 'Senegal',
+ 'UserCountry_country_so' => 'Somali',
+ 'UserCountry_country_sr' => 'Surinam',
+ 'UserCountry_country_st' => 'Sao Tome dhe Principe',
+ 'UserCountry_country_su' => 'Ish B.R.S.S',
+ 'UserCountry_country_sv' => 'Salvador',
+ 'UserCountry_country_sy' => 'Republika Arabe e Sirisë',
+ 'UserCountry_country_sz' => 'Svazilend',
+ 'UserCountry_country_ta' => 'Tristan da Kunja',
+ 'UserCountry_country_tc' => 'Ishujt Turks dhe Kaikos',
+ 'UserCountry_country_td' => 'Çhad',
+ 'UserCountry_country_tf' => 'Territoret Frënge Jugore',
+ 'UserCountry_country_tg' => 'Togo',
+ 'UserCountry_country_th' => 'Tailandë',
+ 'UserCountry_country_tj' => 'Taxhikistan',
+ 'UserCountry_country_tk' => 'Tokelau',
+ 'UserCountry_country_tl' => 'East Timor',
+ 'UserCountry_country_tm' => 'Turkmenistan',
+ 'UserCountry_country_tn' => 'Tunizi',
+ 'UserCountry_country_to' => 'Tonga',
+ 'UserCountry_country_tp' => 'East Timor',
+ 'UserCountry_country_tr' => 'Turqi',
+ 'UserCountry_country_tt' => 'Trinidad dhe Tobago',
+ 'UserCountry_country_tv' => 'Tuvalu',
+ 'UserCountry_country_tw' => 'Taivan',
+ 'UserCountry_country_tz' => 'Republika e Bashkuar e Tanzanisë',
+ 'UserCountry_country_ua' => 'Ukrainë',
+ 'UserCountry_country_ug' => 'Ugandë',
+ 'UserCountry_country_uk' => 'Mbretëri e Bashkuar',
+ 'UserCountry_country_um' => 'Ishujt e Vegjël të Përtejmë të Shteteve të Bashkuara',
+ 'UserCountry_country_us' => 'Shtetet e Bashkuara',
+ 'UserCountry_country_uy' => 'Uruguaj',
+ 'UserCountry_country_uz' => 'Uzbekistan',
+ 'UserCountry_country_va' => 'Vatikan',
+ 'UserCountry_country_vc' => 'Shën Vinçens dhe Grenadinet',
+ 'UserCountry_country_ve' => 'Venezuelë',
+ 'UserCountry_country_vg' => 'Ishujt e Virgjër Britanikë',
+ 'UserCountry_country_vi' => 'Ishujt e Virgjër, U.S.',
+ 'UserCountry_country_vn' => 'Vietnam',
+ 'UserCountry_country_vu' => 'Vanuatu',
+ 'UserCountry_country_wf' => 'Uallis dhe Futuna',
+ 'UserCountry_country_ws' => 'Samoa',
+ 'UserCountry_country_ye' => 'Jemen',
+ 'UserCountry_country_yt' => 'Majot',
+ 'UserCountry_country_yu' => 'Jugosllavi',
+ 'UserCountry_country_za' => 'Afrikë e Jugut',
+ 'UserCountry_country_zm' => 'Zambia',
+ 'UserCountry_country_zr' => 'Zaire',
+ 'UserCountry_country_zw' => 'Zimbabue',
+ 'UserCountry_continent_eur' => 'Europë',
+ 'UserCountry_continent_afr' => 'Afrikë',
+ 'UserCountry_continent_asi' => 'Azi',
+ 'UserCountry_continent_ams' => 'Amerika e Jugut dhe Qendrore',
+ 'UserCountry_continent_amn' => 'Amerika e Veriut',
+ 'UserCountry_continent_oce' => 'Oqeani',
+ 'UserSettings_VisitorSettings' => 'Rregullimet për Vizitor',
+ 'UserSettings_BrowserFamilies' => 'Familje shfletuesi',
+ 'UserSettings_Browsers' => 'Shfletuesa',
+ 'UserSettings_Plugins' => 'Shtojca',
+ 'UserSettings_Configurations' => 'Formësime',
+ 'UserSettings_OperatingSystems' => 'Sisteme operativë',
+ 'UserSettings_Resolutions' => 'Qartësi',
+ 'UserSettings_WideScreen' => 'Ekran së Gjeri',
+ 'UserSettings_ColumnBrowserFamily' => 'Familje shfletuesi',
+ 'UserSettings_ColumnBrowser' => 'Shfletues',
+ 'UserSettings_ColumnPlugin' => 'Shtojcë',
+ 'UserSettings_ColumnConfiguration' => 'Formësim',
+ 'UserSettings_ColumnOperatingSystem' => 'Sistem operativ',
+ 'UserSettings_ColumnResolution' => 'Qartësi',
+ 'UserSettings_ColumnTypeOfScreen' => 'Lloj ekrani',
+ 'UserSettings_WidgetResolutions' => 'Qartësi ekrani',
+ 'UserSettings_WidgetBrowsers' => 'Shfletuesa vizitorësh',
+ 'UserSettings_WidgetPlugins' => 'Listë e Shtojcave',
+ 'UserSettings_WidgetWidescreen' => 'Normal / Ekran së gjeri',
+ 'UserSettings_WidgetBrowserFamilies' => 'Shfletuesa sipas familjesh',
+ 'UserSettings_WidgetOperatingSystems' => 'Sisteme operativë',
+ 'UserSettings_WidgetGlobalVisitors' => 'Formësime globale vizitorësh',
+ 'UserSettings_SubmenuSettings' => 'Rregullime',
+ 'UsersManager_UsersManagement' => 'Administrim Përdoruesish',
+ 'UsersManager_UsersManagementMainDescription' => 'Krijoni përdoruesa të rinj ose përditësoni përdoruesat ekzistues. Mandej mund t\'u caktoni lejet më sipër.',
+ 'UsersManager_ManageAccess' => 'Administroni hyrjet',
+ 'UsersManager_MainDescription' => 'Vendosni cilët përdoruesa kanë hyrje Piwik në "site"-et tuaj web. Mundet edhe të caktoni njëherazi lejet mbi tërë "site"-et web.',
+ 'UsersManager_Sites' => '"Site"-e web',
+ 'UsersManager_AllWebsites' => 'Tërë "site"-et web',
+ 'UsersManager_ApplyToAllWebsites' => 'Zbatoje për tërë "site"-et web',
+ 'UsersManager_User' => 'Përdorues',
+ 'UsersManager_PrivNone' => 'Pa hyrje',
+ 'UsersManager_PrivView' => 'Parje',
+ 'UsersManager_PrivAdmin' => 'Admin',
+ 'UsersManager_ChangeAllConfirm' => 'Jeni i sigurt se doni të ndryshoni lejet e \'%s\' në tërë "site"-et web?',
+ 'UsersManager_Login' => 'Emër përdoruesi',
+ 'UsersManager_Password' => 'Fjalëkalim',
+ 'UsersManager_Email' => 'Email',
+ 'UsersManager_Alias' => 'Alias',
+ 'UsersManager_Edit' => 'Përpunim',
+ 'UsersManager_AddUser' => 'Shtoni përdorues të ri',
+ 'UsersManager_MenuUsers' => 'Përdoruesa',
+ 'UsersManager_DeleteConfirm_js' => 'Jeni i sigurt se doni të fshihet përdoruesi %s?',
+ 'UsersManager_ExceptionLoginExists' => 'Ka tashmë një hyrje për \'%s\'.',
+ 'UsersManager_ExceptionEmailExists' => 'Ka tashmë një përdorues me email-in \'%s\'.',
+ 'UsersManager_ExceptionInvalidLoginFormat' => 'Hyrja duhet të jetë ndërmjet %s dhe %s shenjash e gjatë, dhe duhet të përmbajë vetëm shkronja, numra, ose shenjat \'_\' ose \'-\' ose \'.\'',
+ 'UsersManager_ExceptionInvalidPassword' => 'Fjalëkalimi duhet të jetë nga 6 deri 26 shenja i gjatë.',
+ 'UsersManager_ExceptionInvalidEmail' => 'Email-i s\'është në format të vlefshëm.',
+ 'UsersManager_ExceptionDeleteDoesNotExist' => 'Përdoruesi \'%s\' s\'ekziston, ndaj s\'mund të fshihet.',
+ 'UsersManager_ExceptionAdminAnonymous' => 'S\'mund t\'i jepni hyrje \'administratori\' përdoruesit \'anonim\'.',
+ 'UsersManager_ExceptionEditAnonymous' => 'Përdoruesi anonim nuk mund të fshihet apo përpunohet të dhënat e tij. Përdoret nga Piwik-u për të përkufizuar një përdorues që nuk ka bërë ende hyrjen. Për shembull, mund t\'i bëni statistikat tuaja publike duke lejuar hyrje për \'parje\' për përdoruesin \'anonim\'.',
+ 'UsersManager_ExceptionSuperUser' => 'Përdoruesi i kërkuar është Super Përdoruesi dhe nuk i nënshtrohet kërkesave, as përpunohet apo fshihet përmes API-t. Hollësitë e Super Përdoruesit mund t\'i përpunoni dorazi te kartela juaj e formësimit të Piwik-ut.',
+ 'UsersManager_ExceptionUserDoesNotExist' => 'Përdoruesi \'%s\' s\'ekziston.',
+ 'UsersManager_ExceptionAccessValues' => 'Parametri duhet të ketë një nga vlerat vijuese : [ %s ]',
+ 'VisitFrequency_Evolution' => 'Zhvillime përgjatë periudhës',
+ 'VisitFrequency_ColumnReturningVisits' => 'Vizita Rikthim',
+ 'VisitFrequency_ColumnActionsByReturningVisits' => 'Veprime nga Vizita Rikthim',
+ 'VisitFrequency_ColumnMaximumActionsByAReturningVisit' => 'Maksimum Veprimesh nga një Vizitë Rikthim',
+ 'VisitFrequency_ColumnTotalTimeSpentByReturningVisits' => 'Kohë Gjithsej e harxhuar nga Vizita Rikthim (në sekonda)',
+ 'VisitFrequency_ColumnBounceRateForReturningVisits' => 'Mesatare kthimi për Vizita Rikthim',
+ 'VisitFrequency_ReturnVisits' => '%s vizita rikthim',
+ 'VisitFrequency_ReturnActions' => '%s veprime nga vizita rikthim',
+ 'VisitFrequency_ReturnMaxActions' => 'maksimumi %s veprime për një vizitë rikthim',
+ 'VisitFrequency_ReturnTotalTime' => '%s kohë gjithsej e harxhuar nga vizita rikthim',
+ 'VisitFrequency_ReturnBounceRate' => 'janë kthyer mbrapsht %s vizita rikthim (e kanë lënë "site"-in web pas një faqeje)',
+ 'VisitFrequency_WidgetOverview' => 'Përmbledhje shpeshtie',
+ 'VisitFrequency_WidgetGraphReturning' => 'Grafik vizitash Rikthim',
+ 'VisitFrequency_SubmenuFrequency' => 'Shpeshti',
+ 'VisitTime_LocalTime' => 'Vizita në kohën vendore',
+ 'VisitTime_ServerTime' => 'Vizita në kohën e shërbyesit',
+ 'VisitTime_ColumnServerTime' => 'Kohë shërbyesi',
+ 'VisitTime_ColumnLocalTime' => 'Kohë vendore',
+ 'VisitTime_WidgetLocalTime' => 'Vizita sipas kohës vendore',
+ 'VisitTime_WidgetServerTime' => 'Vizita sipas kohës së shërbyesit',
+ 'VisitTime_SubmenuTimes' => 'Kohë',
+ 'VisitTime_NHour' => '%sh',
+ 'VisitorInterest_VisitsPerDuration' => 'Vizita sipas kohëzgjatjes së vizitës',
+ 'VisitorInterest_VisitsPerNbOfPages' => 'Vizita sipas numrit të faqeve',
+ 'VisitorInterest_ColumnVisitDuration' => 'Kohëzgjatje vizite',
+ 'VisitorInterest_ColumnPagesPerVisit' => 'Faqe për vizitë',
+ 'VisitorInterest_WidgetLengths' => 'Gjatësi Vizitash',
+ 'VisitorInterest_WidgetPages' => 'Faqe për vizitë',
+ 'VisitorInterest_SubmenuFrequencyLoyalty' => 'Shpeshti & Besnikëri',
+ 'VisitorInterest_PlusXMin' => '%s min',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s min',
+ 'VisitorInterest_OnePage' => '1 faqe',
+ 'VisitorInterest_NPages' => '%s faqe',
+ 'VisitorInterest_BetweenXYSeconds' => '%1s-%2ss',
+ 'VisitsSummary_NbVisits' => '%s vizita',
+ 'VisitsSummary_NbUniqueVisitors' => '%s vizitorë unikë',
+ 'VisitsSummary_NbActions' => '%s veprime (parje faqesh)',
+ 'VisitsSummary_TotalTime' => '%s kohë gjithsej harxhuar nga vizitorët',
+ 'VisitsSummary_MaxNbActions' => 'maksimumi %s veprime në një vizitë',
+ 'VisitsSummary_NbVisitsBounced' => '%s vizita të kthyera mbrapsht (e lanë "site"-in web pas një faqeje)',
+ 'VisitsSummary_EvolutionOverLastPeriods' => 'Zhvillime përgjatë %s së fundit',
+ 'VisitsSummary_Report' => 'Raport',
+ 'VisitsSummary_GenerateTime' => '%s sekonda për prodhimin e faqes',
+ 'VisitsSummary_GenerateQueries' => '%s kërkesa të kryera',
+ 'VisitsSummary_WidgetLastVisits' => 'Grafik për vizitat e fundit',
+ 'VisitsSummary_WidgetVisits' => 'Përmbledhje vizitash',
+ 'VisitsSummary_WidgetLastVisitors' => 'Grafik për vizitorët e fundit unikë',
+ 'VisitsSummary_WidgetOverviewGraph' => 'Përmbledhje me grafik',
+ 'VisitsSummary_SubmenuOverview' => 'Përmbledhje',
+ 'VisitsSummary_VisitsSummary' => 'Përmbledhje Vizitash',
+);
diff --git a/lang/sr.php b/lang/sr.php
index bcccf95033..ae26757ddc 100644
--- a/lang/sr.php
+++ b/lang/sr.php
@@ -145,6 +145,32 @@ $translations = array(
'CoreHome_DayTh_js' => 'Če',
'CoreHome_DayFr_js' => 'Pe',
'CoreHome_DaySa_js' => 'Su',
+ 'CoreHome_ShortDay_1_js' => 'Ned',
+ 'CoreHome_ShortDay_2_js' => 'Pon',
+ 'CoreHome_ShortDay_3_js' => 'Uto',
+ 'CoreHome_ShortDay_4_js' => 'Sre',
+ 'CoreHome_ShortDay_5_js' => 'Čet',
+ 'CoreHome_ShortDay_6_js' => 'Pet',
+ 'CoreHome_ShortDay_7_js' => 'Sub',
+ 'CoreHome_LongDay_1_js' => 'Nedelja',
+ 'CoreHome_LongDay_2_js' => 'Ponedeljak',
+ 'CoreHome_LongDay_3_js' => 'Utorak',
+ 'CoreHome_LongDay_4_js' => 'Sreda',
+ 'CoreHome_LongDay_5_js' => 'Četvrtak',
+ 'CoreHome_LongDay_6_js' => 'Petak',
+ 'CoreHome_LongDay_7_js' => 'Subota',
+ 'CoreHome_ShortMonth_1_js' => 'Jan',
+ 'CoreHome_ShortMonth_2_js' => 'Feb',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Apr',
+ 'CoreHome_ShortMonth_5_js' => 'Maj',
+ 'CoreHome_ShortMonth_6_js' => 'Jun',
+ 'CoreHome_ShortMonth_7_js' => 'Jul',
+ 'CoreHome_ShortMonth_8_js' => 'Avg',
+ 'CoreHome_ShortMonth_9_js' => 'Sep',
+ 'CoreHome_ShortMonth_10_js' => 'Okt',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dec',
'CoreHome_MonthJanuary_js' => 'Januar',
'CoreHome_MonthFebruary_js' => 'Februar',
'CoreHome_MonthMarch_js' => 'Mart',
@@ -248,14 +274,14 @@ $translations = array(
'UserSettings_Browsers' => 'Web čitači',
'UserSettings_Plugins' => 'Dodaci',
'UserSettings_Configurations' => 'Podešavanja',
- 'UserSettings_OperatinsSystems' => 'Operativni sistemi',
+ 'UserSettings_OperatingSystems' => 'Operativni sistemi',
'UserSettings_Resolutions' => 'Rezolucije',
'UserSettings_WideScreen' => 'Širok ekran',
'UserSettings_ColumnBrowserFamily' => 'Tip Web čitača',
'UserSettings_ColumnBrowser' => 'Web čitači',
'UserSettings_ColumnPlugin' => 'Dodaci',
'UserSettings_ColumnConfiguration' => 'Podešavanja',
- 'UserSettings_ColumnOperatinsSystem' => 'Operativni sistem',
+ 'UserSettings_ColumnOperatingSystem' => 'Operativni sistem',
'UserSettings_ColumnResolution' => 'Rezolucija',
'UserSettings_ColumnTypeOfScreen' => 'Tip ekrana',
'UserSettings_WidgetResolutions' => 'Rezolucija ekrana',
diff --git a/lang/sv.php b/lang/sv.php
index a1620400a1..d5aa458d13 100644
--- a/lang/sv.php
+++ b/lang/sv.php
@@ -138,13 +138,39 @@ $translations = array(
'CoreHome_PeriodWeeks' => 'veckor',
'CoreHome_PeriodMonths' => 'm&aring;nader',
'CoreHome_PeriodYears' => '&aring;r',
- 'CoreHome_DaySu_js' => 'S&ouml;n',
- 'CoreHome_DayMo_js' => 'M&aring;n',
- 'CoreHome_DayTu_js' => 'Tis',
- 'CoreHome_DayWe_js' => 'Ons',
- 'CoreHome_DayTh_js' => 'Tor',
- 'CoreHome_DayFr_js' => 'Fre',
- 'CoreHome_DaySa_js' => 'L&ouml;r',
+ 'CoreHome_DaySu_js' => 'Sö',
+ 'CoreHome_DayMo_js' => 'Må',
+ 'CoreHome_DayTu_js' => 'Ti',
+ 'CoreHome_DayWe_js' => 'On',
+ 'CoreHome_DayTh_js' => 'To',
+ 'CoreHome_DayFr_js' => 'Fr',
+ 'CoreHome_DaySa_js' => 'Lö',
+ 'CoreHome_ShortDay_1_js' => 'Sön',
+ 'CoreHome_ShortDay_2_js' => 'Mån',
+ 'CoreHome_ShortDay_3_js' => 'Tis',
+ 'CoreHome_ShortDay_4_js' => 'Ons',
+ 'CoreHome_ShortDay_5_js' => 'Tor',
+ 'CoreHome_ShortDay_6_js' => 'Fre',
+ 'CoreHome_ShortDay_7_js' => 'Lör',
+ 'CoreHome_LongDay_1_js' => 'Söndag',
+ 'CoreHome_LongDay_2_js' => 'Måndag',
+ 'CoreHome_LongDay_3_js' => 'Tisdag',
+ 'CoreHome_LongDay_4_js' => 'Onsdag',
+ 'CoreHome_LongDay_5_js' => 'Torsdag',
+ 'CoreHome_LongDay_6_js' => 'Fredag',
+ 'CoreHome_LongDay_7_js' => 'Lördag',
+ 'CoreHome_ShortMonth_1_js' => 'Jan',
+ 'CoreHome_ShortMonth_2_js' => 'Feb',
+ 'CoreHome_ShortMonth_3_js' => 'Mar',
+ 'CoreHome_ShortMonth_4_js' => 'Apr',
+ 'CoreHome_ShortMonth_5_js' => 'Maj',
+ 'CoreHome_ShortMonth_6_js' => 'Jun',
+ 'CoreHome_ShortMonth_7_js' => 'Jul',
+ 'CoreHome_ShortMonth_8_js' => 'Aug',
+ 'CoreHome_ShortMonth_9_js' => 'Sep',
+ 'CoreHome_ShortMonth_10_js' => 'Okt',
+ 'CoreHome_ShortMonth_11_js' => 'Nov',
+ 'CoreHome_ShortMonth_12_js' => 'Dec',
'CoreHome_MonthJanuary_js' => 'Januari',
'CoreHome_MonthFebruary_js' => 'Februari',
'CoreHome_MonthMarch_js' => 'Mars',
@@ -247,14 +273,14 @@ $translations = array(
'UserSettings_Browsers' => 'Webbl&auml;sare',
'UserSettings_Plugins' => 'Till&auml;gg',
'UserSettings_Configurations' => 'Konfigurationer',
- 'UserSettings_OperatinsSystems' => 'Operativsystem',
+ 'UserSettings_OperatingSystems' => 'Operativsystem',
'UserSettings_Resolutions' => 'Sk&auml;rmuppl&ouml;sning',
'UserSettings_WideScreen' => 'Wide Screen',
'UserSettings_ColumnBrowserFamily' => 'Webbl&auml;sarfamilj',
'UserSettings_ColumnBrowser' => 'Webbl&auml;sare',
'UserSettings_ColumnPlugin' => 'Till&auml;gg',
'UserSettings_ColumnConfiguration' => 'Konfiguration',
- 'UserSettings_ColumnOperatinsSystem' => 'Operativsystem',
+ 'UserSettings_ColumnOperatingSystem' => 'Operativsystem',
'UserSettings_ColumnResolution' => 'Sk&auml;rmuppl&ouml;sning',
'UserSettings_ColumnTypeOfScreen' => 'Typ av sk&auml;rm',
'UserSettings_WidgetResolutions' => 'Sk&auml;rmuppl&ouml;sning',
@@ -600,7 +626,6 @@ $translations = array(
'Login_PasswordReminder' => 'V&auml;nligen fyll i ditt anv&auml;ndarnamn eller din e-postadress. Du kommer att f&aring; ett nytt l&ouml;senord skickat via e-post.',
'Login_InvalidUsernameEmail' => 'Felaktigt anv&auml;ndarnamn och/eller e-postadress',
'Login_MailTopicPasswordRecovery' => '&Aring;terst&auml;ll l&ouml;senord',
- 'Login_MailPasswordRecoveryBody' => 'Hej %1s, \n\n Ditt nya l&ouml;senord &auml;r: %2s \n\n Nu kan du logga in p&aring;: %3s',
'Login_PasswordSent' => 'L&ouml;senordet har skickats. Kontrollera din e-post.',
'Login_ContactAdmin' => 'M&ouml;jlig orsak: din v&auml;rd kan ha avaktiverat mail() funktionen. <br />Var v&auml;nlig kontakta din Piwik-administrat&ouml;r',
'UsersManager_UsersManagement' => 'Anv&auml;ndarhantering',
diff --git a/lang/th.php b/lang/th.php
index 9084d104a3..2ac6156982 100644
--- a/lang/th.php
+++ b/lang/th.php
@@ -730,7 +730,7 @@ $translations = array(
'VisitorInterest_WidgetPages' => 'หน้าต่อผู้เข้าชม',
'VisitorInterest_SubmenuFrequencyLoyalty' => 'ความถี่และความภักดี',
'VisitorInterest_PlusXMin' => '%sนาที',
- 'VisitorInterest_BetweenXYMinutes' => '%1s-%1sนาที',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%2sนาที',
'VisitorInterest_OnePage' => '1 หน้า',
'VisitorInterest_NPages' => '%s หน้า',
'VisitorInterest_BetweenXYSeconds' => '%1s-%2sวิ',
@@ -742,7 +742,7 @@ $translations = array(
'VisitsSummary_TotalTime' => '%s เวลาบนไซต์',
'VisitsSummary_MaxNbActions' => '%s หน้าสูงสุดในหนึ่งเข้าชม',
'VisitsSummary_NbBounced' => '%s หน้าที่ออกจากไซต์',
- 'VisitsSummary_Evolution' => 'วิวัฒนาการใน 30วันล่าสุด %s',
+ 'VisitsSummary_Evolution' => 'วิวัฒนาการใน 30วันล่าสุด %ss',
'VisitsSummary_Report' => 'รายงาน',
'VisitsSummary_GenerateTime' => '%s วินาทีที่ใช้',
'VisitsSummary_GenerateQueries' => '%s การค้นหา',
@@ -753,4 +753,4 @@ $translations = array(
'VisitsSummary_SubmenuOverview' => 'ภาพรวมผู้เข้าชม',
'VisitsSummary_NbVisitsBounced' => '%s ผู้เยี่ยมชมที่เด้ง(ออกจากเว็บไซต์หลังจากเปิดเพียงหน้าเดียว)',
'VisitsSummary_EvolutionOverLastPeriods' => 'วิวัฒนาการในช่วงเวลาล่าสุด %s',
-);
+); \ No newline at end of file
diff --git a/lang/uk.php b/lang/uk.php
index 4fc8c3d854..9fcfcfc473 100644
--- a/lang/uk.php
+++ b/lang/uk.php
@@ -644,7 +644,7 @@ $translations = array(
'VisitorInterest_WidgetPages' => 'Кількість сторінок за відвідування',
'VisitorInterest_SubmenuFrequencyLoyalty' => 'Частота та Лояльність',
'VisitorInterest_PlusXMin' => '%s хв',
- 'VisitorInterest_BetweenXYMinutes' => '%1s-%1s хв',
+ 'VisitorInterest_BetweenXYMinutes' => '%1s-%2s хв',
'VisitorInterest_OnePage' => 'одна сторінка',
'VisitorInterest_NPages' => '%s сторінок',
'VisitorInterest_BetweenXYSeconds' => '%1s-%2s сек.',
@@ -664,4 +664,4 @@ $translations = array(
'VisitsSummary_WidgetOverviewGraph' => 'Огляд з графіком',
'VisitsSummary_SubmenuOverview' => 'Огляд',
'VisitsSummary_EvolutionPeriods' => 'Динаміка протягом останніх 30 %s',
-);
+); \ No newline at end of file
diff --git a/lang/zh-cn.php b/lang/zh-cn.php
index 299880a635..153044f5d7 100644
--- a/lang/zh-cn.php
+++ b/lang/zh-cn.php
@@ -78,6 +78,32 @@ $translations = array(
'CoreHome_DayTh_js' => '四',
'CoreHome_DayFr_js' => '五',
'CoreHome_DaySa_js' => '六',
+ 'CoreHome_ShortDay_1_js' => '周日',
+ 'CoreHome_ShortDay_2_js' => '周一',
+ 'CoreHome_ShortDay_3_js' => '周二',
+ 'CoreHome_ShortDay_4_js' => '周三',
+ 'CoreHome_ShortDay_5_js' => '周四',
+ 'CoreHome_ShortDay_6_js' => '周五',
+ 'CoreHome_ShortDay_7_js' => '周六',
+ 'CoreHome_LongDay_1_js' => '星期日',
+ 'CoreHome_LongDay_2_js' => '星期一',
+ 'CoreHome_LongDay_3_js' => '星期二',
+ 'CoreHome_LongDay_4_js' => '星期三',
+ 'CoreHome_LongDay_5_js' => '星期四',
+ 'CoreHome_LongDay_6_js' => '星期五',
+ 'CoreHome_LongDay_7_js' => '星期六',
+ 'CoreHome_ShortMonth_1_js' => '一',
+ 'CoreHome_ShortMonth_2_js' => '二',
+ 'CoreHome_ShortMonth_3_js' => '三',
+ 'CoreHome_ShortMonth_4_js' => '四',
+ 'CoreHome_ShortMonth_5_js' => '五',
+ 'CoreHome_ShortMonth_6_js' => '六',
+ 'CoreHome_ShortMonth_7_js' => '七',
+ 'CoreHome_ShortMonth_8_js' => '八',
+ 'CoreHome_ShortMonth_9_js' => '九',
+ 'CoreHome_ShortMonth_10_js' => '十',
+ 'CoreHome_ShortMonth_11_js' => '十一',
+ 'CoreHome_ShortMonth_12_js' => '十二',
'CoreHome_MonthJanuary_js' => '一月',
'CoreHome_MonthFebruary_js' => '二月',
'CoreHome_MonthMarch_js' => '三月',
@@ -155,7 +181,7 @@ $translations = array(
'UserSettings_Browsers' => '使用浏览器',
'UserSettings_Plugins' => '浏览器插件',
'UserSettings_Configurations' => '客户端配置',
- 'UserSettings_OperatinsSystems' => '操作系统',
+ 'UserSettings_OperatingSystems' => '操作系统',
'UserSettings_Resolutions' => '分辨率',
'UserSettings_WideScreen' => '宽屏幕',
'UserSettings_WidgetResolutions' => '画面分辨率',
@@ -477,7 +503,6 @@ $translations = array(
'Login_PasswordReminder' => '请输入您的用户名称或 E-mail 地址! 您将透过 E-mail 接收到一组新密码!',
'Login_InvalidUsernameEmail' => '无效的使用者名称 和/或 E-mail 地址',
'Login_MailTopicPasswordRecovery' => '重取得密码',
- 'Login_MailPasswordRecoveryBody' => '%1s 您好, \n\n 您的新密码是: %2s \n\n 您现在可以登录了: %3s',
'Login_PasswordSent' => '密码刚刚已经发送! 请检查您的 E-mail 信箱!',
'Login_ContactAdmin' => '可能的原因:您的主机可能已经停用了 mail() 函数! <br />请联络您的 Piwik 管理员!',
'UsersManager_UsersManagement' => '用户管理',
diff --git a/lang/zh-tw.php b/lang/zh-tw.php
index 35b88b2515..31711974de 100644
--- a/lang/zh-tw.php
+++ b/lang/zh-tw.php
@@ -145,6 +145,32 @@ $translations = array(
'CoreHome_DayTh_js' => '四',
'CoreHome_DayFr_js' => '五',
'CoreHome_DaySa_js' => '六',
+ 'CoreHome_ShortDay_1_js' => '周日',
+ 'CoreHome_ShortDay_2_js' => '周一',
+ 'CoreHome_ShortDay_3_js' => '周二',
+ 'CoreHome_ShortDay_4_js' => '周三',
+ 'CoreHome_ShortDay_5_js' => '周四',
+ 'CoreHome_ShortDay_6_js' => '周五',
+ 'CoreHome_ShortDay_7_js' => '周六',
+ 'CoreHome_LongDay_1_js' => '星期日',
+ 'CoreHome_LongDay_2_js' => '星期一',
+ 'CoreHome_LongDay_3_js' => '星期二',
+ 'CoreHome_LongDay_4_js' => '星期三',
+ 'CoreHome_LongDay_5_js' => '星期四',
+ 'CoreHome_LongDay_6_js' => '星期五',
+ 'CoreHome_LongDay_7_js' => '星期六',
+ 'CoreHome_ShortMonth_1_js' => '一',
+ 'CoreHome_ShortMonth_2_js' => '二',
+ 'CoreHome_ShortMonth_3_js' => '三',
+ 'CoreHome_ShortMonth_4_js' => '四',
+ 'CoreHome_ShortMonth_5_js' => '五',
+ 'CoreHome_ShortMonth_6_js' => '六',
+ 'CoreHome_ShortMonth_7_js' => '七',
+ 'CoreHome_ShortMonth_8_js' => '八',
+ 'CoreHome_ShortMonth_9_js' => '九',
+ 'CoreHome_ShortMonth_10_js' => '十',
+ 'CoreHome_ShortMonth_11_js' => '十一',
+ 'CoreHome_ShortMonth_12_js' => '十二',
'CoreHome_MonthJanuary_js' => '一月',
'CoreHome_MonthFebruary_js' => '二月',
'CoreHome_MonthMarch_js' => '三月',
@@ -247,14 +273,14 @@ $translations = array(
'UserSettings_Browsers' => '使用瀏覽器',
'UserSettings_Plugins' => '瀏覽器外掛',
'UserSettings_Configurations' => '客端配置',
- 'UserSettings_OperatinsSystems' => '作業系統',
+ 'UserSettings_OperatingSystems' => '作業系統',
'UserSettings_Resolutions' => '解析度',
'UserSettings_WideScreen' => '寬螢幕',
'UserSettings_ColumnBrowserFamily' => '瀏覽器家族',
'UserSettings_ColumnBrowser' => '瀏覽器',
'UserSettings_ColumnPlugin' => '外掛',
'UserSettings_ColumnConfiguration' => '客端配置',
- 'UserSettings_ColumnOperatinsSystem' => '作業系統',
+ 'UserSettings_ColumnOperatingSystem' => '作業系統',
'UserSettings_ColumnResolution' => '解析度',
'UserSettings_ColumnTypeOfScreen' => '螢幕類型',
'UserSettings_WidgetResolutions' => '畫面解析度',
@@ -600,7 +626,6 @@ $translations = array(
'Login_PasswordReminder' => '請輸入您的使用者名稱或 E-mail 位址! 您將透過 E-mail 接收到一組新密碼!',
'Login_InvalidUsernameEmail' => '無效的使用者名稱 和/或 E-mail 位址',
'Login_MailTopicPasswordRecovery' => '重取得密碼',
- 'Login_MailPasswordRecoveryBody' => '%1s 您好, \n\n 您的新密碼是: %2s \n\n 您現在可以從此登入: %3s',
'Login_PasswordSent' => '密碼剛剛已經發送! 請檢查您的 E-mail 信箱!',
'Login_ContactAdmin' => '可能的原因:您的伺服主機可能已經停用了 mail() 函式! <br />請聯絡您的 Piwik 管理員!',
'UsersManager_UsersManagement' => '使用者管理',
diff --git a/libs/HTML/QuickForm.php b/libs/HTML/QuickForm.php
index df3fbdf079..de0318292c 100644
--- a/libs/HTML/QuickForm.php
+++ b/libs/HTML/QuickForm.php
@@ -26,11 +26,11 @@
/**
* PEAR and PEAR_Error classes, for error handling
*/
-require_once 'PEAR.php';
+require_once dirname(__FILE__) . '/../PEAR.php';
/**
* Base class for all HTML classes
*/
-require_once 'HTML/Common.php';
+require_once dirname(__FILE__) . '/Common.php';
/**
* Element types known to HTML_QuickForm
@@ -378,7 +378,7 @@ class HTML_QuickForm extends HTML_Common
*/
function registerRule($ruleName, $type, $data1, $data2 = null)
{
- include_once('HTML/QuickForm/RuleRegistry.php');
+ include_once(dirname(__FILE__) . '/QuickForm/RuleRegistry.php');
$registry =& HTML_QuickForm_RuleRegistry::singleton();
$registry->registerRule($ruleName, $type, $data1, $data2);
} // end func registerRule
@@ -593,7 +593,7 @@ class HTML_QuickForm extends HTML_Common
}
$className = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][1];
$includeFile = $GLOBALS['HTML_QUICKFORM_ELEMENT_TYPES'][$type][0];
- include_once($includeFile);
+ include_once(dirname(__FILE__) . '/../' . $includeFile);
$elementObject = new $className();
for ($i = 0; $i < 5; $i++) {
if (!isset($args[$i])) {
@@ -1376,7 +1376,7 @@ class HTML_QuickForm extends HTML_Common
return false;
}
// automatically register the rule if requested
- include_once 'HTML/QuickForm/RuleRegistry.php';
+ include_once dirname(__FILE__) . '/QuickForm/RuleRegistry.php';
$ruleName = false;
if (is_object($name) && is_a($name, 'html_quickform_rule')) {
$ruleName = !empty($name->name)? $name->name: strtolower(get_class($name));
@@ -1514,7 +1514,7 @@ class HTML_QuickForm extends HTML_Common
return false;
}
- include_once('HTML/QuickForm/RuleRegistry.php');
+ include_once(dirname(__FILE__) . '/QuickForm/RuleRegistry.php');
$registry = HTML_QuickForm_RuleRegistry::singleton();
foreach ($this->_rules as $target => $rules) {
@@ -1703,7 +1703,7 @@ class HTML_QuickForm extends HTML_Common
function &defaultRenderer()
{
if (!isset($GLOBALS['_HTML_QuickForm_default_renderer'])) {
- include_once('HTML/QuickForm/Renderer/Default.php');
+ include_once(dirname(__FILE__) . '/QuickForm/Renderer/Default.php');
$GLOBALS['_HTML_QuickForm_default_renderer'] = new HTML_QuickForm_Renderer_Default();
}
return $GLOBALS['_HTML_QuickForm_default_renderer'];
@@ -1748,7 +1748,7 @@ class HTML_QuickForm extends HTML_Common
return '';
}
- include_once('HTML/QuickForm/RuleRegistry.php');
+ include_once(dirname(__FILE__) . '/QuickForm/RuleRegistry.php');
$registry =& HTML_QuickForm_RuleRegistry::singleton();
$test = array();
$js_escape = array(
@@ -1860,7 +1860,7 @@ class HTML_QuickForm extends HTML_Common
*/
function toArray($collectHidden = false)
{
- include_once 'HTML/QuickForm/Renderer/Array.php';
+ include_once dirname(__FILE__) . '/QuickForm/Renderer/Array.php';
$renderer = new HTML_QuickForm_Renderer_Array($collectHidden);
$this->accept($renderer);
return $renderer->toArray();
diff --git a/libs/HTML/QuickForm/Renderer/Array.php b/libs/HTML/QuickForm/Renderer/Array.php
index 28f5893102..dfb04647f5 100644
--- a/libs/HTML/QuickForm/Renderer/Array.php
+++ b/libs/HTML/QuickForm/Renderer/Array.php
@@ -27,7 +27,7 @@
/**
* An abstract base class for QuickForm renderers
*/
-require_once 'HTML/QuickForm/Renderer.php';
+require_once dirname(__FILE__) . '/../Renderer.php';
/**
* A concrete renderer for HTML_QuickForm, makes an array of form contents
@@ -337,4 +337,4 @@ class HTML_QuickForm_Renderer_Array extends HTML_QuickForm_Renderer
}
}
}
-?> \ No newline at end of file
+?>
diff --git a/libs/HTML/QuickForm/Renderer/ArraySmarty.php b/libs/HTML/QuickForm/Renderer/ArraySmarty.php
index 89b59e7dee..d7433d0150 100644
--- a/libs/HTML/QuickForm/Renderer/ArraySmarty.php
+++ b/libs/HTML/QuickForm/Renderer/ArraySmarty.php
@@ -27,7 +27,7 @@
/**
* A concrete renderer for HTML_QuickForm, makes an array of form contents
*/
-require_once 'HTML/QuickForm/Renderer/Array.php';
+require_once dirname(__FILE__) . '/Array.php';
/**
* A static renderer for HTML_QuickForm, makes an array of form content
@@ -400,4 +400,4 @@ class HTML_QuickForm_Renderer_ArraySmarty extends HTML_QuickForm_Renderer_Array
$this->_error = $template;
} // end func setErrorTemplate
}
-?> \ No newline at end of file
+?>
diff --git a/libs/HTML/QuickForm/Renderer/Default.php b/libs/HTML/QuickForm/Renderer/Default.php
index 0801105ba8..0ec24a6454 100644
--- a/libs/HTML/QuickForm/Renderer/Default.php
+++ b/libs/HTML/QuickForm/Renderer/Default.php
@@ -26,7 +26,7 @@
/**
* An abstract base class for QuickForm renderers
*/
-require_once 'HTML/QuickForm/Renderer.php';
+require_once dirname(__FILE__) . '/../Renderer.php';
/**
* A concrete renderer for HTML_QuickForm, based on QuickForm 2.x built-in one
diff --git a/libs/HTML/QuickForm/Renderer/ITDynamic.php b/libs/HTML/QuickForm/Renderer/ITDynamic.php
index f554203dfa..de0dec577b 100644
--- a/libs/HTML/QuickForm/Renderer/ITDynamic.php
+++ b/libs/HTML/QuickForm/Renderer/ITDynamic.php
@@ -24,7 +24,7 @@
/**
* An abstract base class for QuickForm renderers
*/
-require_once 'HTML/QuickForm/Renderer.php';
+require_once dirname(__FILE__) . '/../Renderer.php';
/**
* A concrete renderer for HTML_QuickForm, using Integrated Templates.
diff --git a/libs/HTML/QuickForm/Renderer/ITStatic.php b/libs/HTML/QuickForm/Renderer/ITStatic.php
index 56c9d1fed2..94be06a1d5 100644
--- a/libs/HTML/QuickForm/Renderer/ITStatic.php
+++ b/libs/HTML/QuickForm/Renderer/ITStatic.php
@@ -25,7 +25,7 @@
/**
* An abstract base class for QuickForm renderers
*/
-require_once 'HTML/QuickForm/Renderer.php';
+require_once dirname(__FILE__) . '/../Renderer.php';
/**
* A static renderer for HTML_QuickForm compatible
@@ -501,4 +501,4 @@ class HTML_QuickForm_Renderer_ITStatic extends HTML_QuickForm_Renderer
return $ret;
}
} // end class HTML_QuickForm_Renderer_ITStatic
-?> \ No newline at end of file
+?>
diff --git a/libs/HTML/QuickForm/Renderer/Object.php b/libs/HTML/QuickForm/Renderer/Object.php
index eb84fd78e6..9613931835 100644
--- a/libs/HTML/QuickForm/Renderer/Object.php
+++ b/libs/HTML/QuickForm/Renderer/Object.php
@@ -24,7 +24,7 @@
/**
* An abstract base class for QuickForm renderers
*/
-require_once 'HTML/QuickForm/Renderer.php';
+require_once dirname(__FILE__) . '/../Renderer.php';
/**
* A concrete renderer for HTML_QuickForm, makes an object from form contents
@@ -138,7 +138,10 @@ class HTML_QuickForm_Renderer_Object extends HTML_QuickForm_Renderer
{
$hobj = new StdClass;
$hobj->header = $header->toHtml();
- $this->_obj->sections[$this->_sectionCount] = $hobj;
+ // $this->_obj->sections[$this->_sectionCount] = $hobj;
+ $tmp = $this->_obj->sections;
+ $tmp[$this->_sectionCount] = $hobj;
+ $this->_obj->sections = $tmp;
$this->_currentSection = $this->_sectionCount++;
}
@@ -231,11 +234,24 @@ class HTML_QuickForm_Renderer_Object extends HTML_QuickForm_Renderer
{
$name = $elObj->name;
if(is_object($this->_currentGroup) && $elObj->type != 'group') {
- $this->_currentGroup->elements[] = $elObj;
+ // $this->_currentGroup->elements[] = $elObj;
+ $tmp = $this->_currentGroup->elements;
+ $tmp[] = $elObj;
+ $this->_currentGroup->elements = $tmp;
} elseif (isset($this->_currentSection)) {
- $this->_obj->sections[$this->_currentSection]->elements[] = $elObj;
+ // $this->_obj->sections[$this->_currentSection]->elements[] = $elObj;
+ $tmpSections = $this->_obj->sections;
+ $tmpCurrentSection = $tmpSections[$this->_currentSection];
+ $tmpElements = $tmpCurrentSection->elements;
+ $tmpElements[] = $elObj;
+ $tmpCurrentSection->elements = $tmpElements;
+ $tmpSections[$this->_currentSection] = $tmpCurrentSection;
+ $this->_obj->sections = $tmpSections;
} else {
- $this->_obj->elements[] = $elObj;
+ // $this->_obj->elements[] = $elObj;
+ $tmp = $this->_obj->elements;
+ $tmp[] = $elObj;
+ $this->_obj->elements = $tmp;
}
}
diff --git a/libs/HTML/QuickForm/Renderer/ObjectFlexy.php b/libs/HTML/QuickForm/Renderer/ObjectFlexy.php
index 6a232ca04e..37d45e38d6 100644
--- a/libs/HTML/QuickForm/Renderer/ObjectFlexy.php
+++ b/libs/HTML/QuickForm/Renderer/ObjectFlexy.php
@@ -24,7 +24,7 @@
/**
* A concrete renderer for HTML_QuickForm, makes an object from form contents
*/
-require_once 'HTML/QuickForm/Renderer/Object.php';
+require_once dirname(__FILE__) . '/Object.php';
/**
* QuickForm renderer for Flexy template engine, static version.
@@ -116,7 +116,10 @@ class HTML_QuickForm_Renderer_ObjectFlexy extends HTML_QuickForm_Renderer_Object
if($name = $header->getName()) {
$this->_obj->header->$name = $header->toHtml();
} else {
- $this->_obj->header[$this->_sectionCount] = $header->toHtml();
+ // $this->_obj->header[$this->_sectionCount] = $header->toHtml();
+ $tmp = $this->_obj->header;
+ $tmp[$this->_sectionCount] = $header->toHtml();
+ $this->_obj->header = $tmp;
}
$this->_currentSection = $this->_sectionCount++;
} // end func renderHeader
diff --git a/libs/HTML/QuickForm/Renderer/QuickHtml.php b/libs/HTML/QuickForm/Renderer/QuickHtml.php
index ca067daa70..f71d3c109b 100644
--- a/libs/HTML/QuickForm/Renderer/QuickHtml.php
+++ b/libs/HTML/QuickForm/Renderer/QuickHtml.php
@@ -24,7 +24,7 @@
/**
* A concrete renderer for HTML_QuickForm, based on QuickForm 2.x built-in one
*/
-require_once 'HTML/QuickForm/Renderer/Default.php';
+require_once dirname(__FILE__) . '/Default.php';
/**
* A renderer that makes it quick and easy to create customized forms.
diff --git a/libs/HTML/QuickForm/Rule/Callback.php b/libs/HTML/QuickForm/Rule/Callback.php
index d6e9eab35e..8796dedaa0 100644
--- a/libs/HTML/QuickForm/Rule/Callback.php
+++ b/libs/HTML/QuickForm/Rule/Callback.php
@@ -24,7 +24,7 @@
/**
* Abstract base class for QuickForm validation rules
*/
-require_once 'HTML/QuickForm/Rule.php';
+require_once dirname(__FILE__) . '/../Rule.php';
/**
* Validates values using callback functions or methods
@@ -121,4 +121,4 @@ class HTML_QuickForm_Rule_Callback extends HTML_QuickForm_Rule
} // end func getValidationScript
} // end class HTML_QuickForm_Rule_Callback
-?> \ No newline at end of file
+?>
diff --git a/libs/HTML/QuickForm/Rule/Compare.php b/libs/HTML/QuickForm/Rule/Compare.php
index df4f86b795..6eeda4b65e 100644
--- a/libs/HTML/QuickForm/Rule/Compare.php
+++ b/libs/HTML/QuickForm/Rule/Compare.php
@@ -24,7 +24,7 @@
/**
* Abstract base class for QuickForm validation rules
*/
-require_once 'HTML/QuickForm/Rule.php';
+require_once dirname(__FILE__) . '/../Rule.php';
/**
* Rule to compare two form fields
diff --git a/libs/HTML/QuickForm/Rule/Email.php b/libs/HTML/QuickForm/Rule/Email.php
index 6f79653378..d9fc49ec62 100644
--- a/libs/HTML/QuickForm/Rule/Email.php
+++ b/libs/HTML/QuickForm/Rule/Email.php
@@ -24,7 +24,7 @@
/**
* Abstract base class for QuickForm validation rules
*/
-require_once 'HTML/QuickForm/Rule.php';
+require_once dirname(__FILE__) . '/../Rule.php';
/**
* Email validation rule
@@ -70,4 +70,4 @@ class HTML_QuickForm_Rule_Email extends HTML_QuickForm_Rule
} // end func getValidationScript
} // end class HTML_QuickForm_Rule_Email
-?> \ No newline at end of file
+?>
diff --git a/libs/HTML/QuickForm/Rule/Range.php b/libs/HTML/QuickForm/Rule/Range.php
index 97a8806dc6..e466e3d120 100644
--- a/libs/HTML/QuickForm/Rule/Range.php
+++ b/libs/HTML/QuickForm/Rule/Range.php
@@ -24,7 +24,7 @@
/**
* Abstract base class for QuickForm validation rules
*/
-require_once 'HTML/QuickForm/Rule.php';
+require_once dirname(__FILE__) . '/../Rule.php';
/**
* Checks that the length of value is within range
@@ -72,4 +72,4 @@ class HTML_QuickForm_Rule_Range extends HTML_QuickForm_Rule
} // end func getValidationScript
} // end class HTML_QuickForm_Rule_Range
-?> \ No newline at end of file
+?>
diff --git a/libs/HTML/QuickForm/Rule/Regex.php b/libs/HTML/QuickForm/Rule/Regex.php
index f496a3fb1c..a43aea22dc 100644
--- a/libs/HTML/QuickForm/Rule/Regex.php
+++ b/libs/HTML/QuickForm/Rule/Regex.php
@@ -24,7 +24,7 @@
/**
* Abstract base class for QuickForm validation rules
*/
-require_once 'HTML/QuickForm/Rule.php';
+require_once dirname(__FILE__) . '/../Rule.php';
/**
* Validates values using regular expressions
@@ -104,4 +104,4 @@ class HTML_QuickForm_Rule_Regex extends HTML_QuickForm_Rule
} // end func getValidationScript
} // end class HTML_QuickForm_Rule_Regex
-?> \ No newline at end of file
+?>
diff --git a/libs/HTML/QuickForm/Rule/Required.php b/libs/HTML/QuickForm/Rule/Required.php
index 28ccc604ac..e73af090b0 100644
--- a/libs/HTML/QuickForm/Rule/Required.php
+++ b/libs/HTML/QuickForm/Rule/Required.php
@@ -24,7 +24,7 @@
/**
* Abstract base class for QuickForm validation rules
*/
-require_once 'HTML/QuickForm/Rule.php';
+require_once dirname(__FILE__) . '/../Rule.php';
/**
* Required elements validation
diff --git a/libs/HTML/QuickForm/RuleRegistry.php b/libs/HTML/QuickForm/RuleRegistry.php
index 89e98144e6..c257fc328d 100644
--- a/libs/HTML/QuickForm/RuleRegistry.php
+++ b/libs/HTML/QuickForm/RuleRegistry.php
@@ -123,7 +123,7 @@ class HTML_QuickForm_RuleRegistry
if (!isset($this->_rules[$class])) {
if (!empty($path)) {
- include_once($path);
+ include_once(dirname(__FILE__) . '/../../' . $path);
}
$this->_rules[$class] = new $class();
}
diff --git a/libs/HTML/QuickForm/advcheckbox.php b/libs/HTML/QuickForm/advcheckbox.php
index 9951e79885..fada1e70ae 100644
--- a/libs/HTML/QuickForm/advcheckbox.php
+++ b/libs/HTML/QuickForm/advcheckbox.php
@@ -25,7 +25,7 @@
/**
* HTML class for a checkbox type field
*/
-require_once 'HTML/QuickForm/checkbox.php';
+require_once dirname(__FILE__) . '/checkbox.php';
/**
* HTML class for an advanced checkbox type field
diff --git a/libs/HTML/QuickForm/autocomplete.php b/libs/HTML/QuickForm/autocomplete.php
index 57d1e4311c..0275ceafb1 100644
--- a/libs/HTML/QuickForm/autocomplete.php
+++ b/libs/HTML/QuickForm/autocomplete.php
@@ -24,7 +24,7 @@
/**
* HTML class for a text field
*/
-require_once 'HTML/QuickForm/text.php';
+require_once dirname(__FILE__) . '/text.php';
/**
* HTML class for an autocomplete element
diff --git a/libs/HTML/QuickForm/button.php b/libs/HTML/QuickForm/button.php
index cae1888c18..d0ee0157f3 100644
--- a/libs/HTML/QuickForm/button.php
+++ b/libs/HTML/QuickForm/button.php
@@ -25,7 +25,7 @@
/**
* Base class for <input /> form elements
*/
-require_once 'HTML/QuickForm/input.php';
+require_once dirname(__FILE__) . '/input.php';
/**
* HTML class for an <input type="button" /> elements
diff --git a/libs/HTML/QuickForm/checkbox.php b/libs/HTML/QuickForm/checkbox.php
index 4cf1de238f..5bfc361a17 100644
--- a/libs/HTML/QuickForm/checkbox.php
+++ b/libs/HTML/QuickForm/checkbox.php
@@ -26,7 +26,7 @@
/**
* Base class for <input /> form elements
*/
-require_once 'HTML/QuickForm/input.php';
+require_once dirname(__FILE__) . '/input.php';
/**
* HTML class for a checkbox type field
diff --git a/libs/HTML/QuickForm/date.php b/libs/HTML/QuickForm/date.php
index 5fe3320aba..60811ab347 100644
--- a/libs/HTML/QuickForm/date.php
+++ b/libs/HTML/QuickForm/date.php
@@ -24,11 +24,11 @@
/**
* Class for a group of form elements
*/
-require_once 'HTML/QuickForm/group.php';
+require_once dirname(__FILE__) . '/group.php';
/**
* Class for <select></select> elements
*/
-require_once 'HTML/QuickForm/select.php';
+require_once dirname(__FILE__) . '/select.php';
/**
* Class for a group of elements used to input dates (and times).
@@ -494,7 +494,7 @@ class HTML_QuickForm_date extends HTML_QuickForm_group
function toHtml()
{
- include_once('HTML/QuickForm/Renderer/Default.php');
+ include_once(dirname(__FILE__) . '/Renderer/Default.php');
$renderer = new HTML_QuickForm_Renderer_Default();
$renderer->setElementTemplate('{element}');
parent::accept($renderer);
diff --git a/libs/HTML/QuickForm/element.php b/libs/HTML/QuickForm/element.php
index 3a5e2b97a6..93761f2740 100644
--- a/libs/HTML/QuickForm/element.php
+++ b/libs/HTML/QuickForm/element.php
@@ -26,7 +26,7 @@
/**
* Base class for all HTML classes
*/
-require_once 'HTML/Common.php';
+require_once dirname(__FILE__) . '/../Common.php';
/**
* Base class for form elements
@@ -491,4 +491,4 @@ class HTML_QuickForm_element extends HTML_Common
// }}}
} // end class HTML_QuickForm_element
-?> \ No newline at end of file
+?>
diff --git a/libs/HTML/QuickForm/file.php b/libs/HTML/QuickForm/file.php
index afdf585962..f271cc5a72 100644
--- a/libs/HTML/QuickForm/file.php
+++ b/libs/HTML/QuickForm/file.php
@@ -26,7 +26,7 @@
/**
* Base class for <input /> form elements
*/
-require_once 'HTML/QuickForm/input.php';
+require_once dirname(__FILE__) . '/input.php';
// register file-related rules
if (class_exists('HTML_QuickForm')) {
diff --git a/libs/HTML/QuickForm/group.php b/libs/HTML/QuickForm/group.php
index 6a538ea8f5..9ecda4958d 100644
--- a/libs/HTML/QuickForm/group.php
+++ b/libs/HTML/QuickForm/group.php
@@ -26,7 +26,7 @@
/**
* Base class for form elements
*/
-require_once 'HTML/QuickForm/element.php';
+require_once dirname(__FILE__) . '/element.php';
/**
* HTML class for a form element group
@@ -298,7 +298,7 @@ class HTML_QuickForm_group extends HTML_QuickForm_element
*/
function toHtml()
{
- include_once('HTML/QuickForm/Renderer/Default.php');
+ include_once(dirname(__FILE__) . '/Renderer/Default.php');
$renderer = new HTML_QuickForm_Renderer_Default();
$renderer->setElementTemplate('{element}');
$this->accept($renderer);
diff --git a/libs/HTML/QuickForm/header.php b/libs/HTML/QuickForm/header.php
index b1bd222003..49b5679fb9 100644
--- a/libs/HTML/QuickForm/header.php
+++ b/libs/HTML/QuickForm/header.php
@@ -24,7 +24,7 @@
/**
* HTML class for static data
*/
-require_once 'HTML/QuickForm/static.php';
+require_once dirname(__FILE__) . '/static.php';
/**
* A pseudo-element used for adding headers to form
diff --git a/libs/HTML/QuickForm/hidden.php b/libs/HTML/QuickForm/hidden.php
index e0bb7e1d1f..bd77c36ad5 100644
--- a/libs/HTML/QuickForm/hidden.php
+++ b/libs/HTML/QuickForm/hidden.php
@@ -25,7 +25,7 @@
/**
* Base class for <input /> form elements
*/
-require_once 'HTML/QuickForm/input.php';
+require_once dirname(__FILE__) . '/input.php';
/**
* HTML class for a hidden type element
diff --git a/libs/HTML/QuickForm/hiddenselect.php b/libs/HTML/QuickForm/hiddenselect.php
index 0c16e96494..56212db090 100644
--- a/libs/HTML/QuickForm/hiddenselect.php
+++ b/libs/HTML/QuickForm/hiddenselect.php
@@ -24,7 +24,7 @@
/**
* Class for <select></select> elements
*/
-require_once 'HTML/QuickForm/select.php';
+require_once dirname(__FILE__) . '/select.php';
/**
* Hidden select pseudo-element
diff --git a/libs/HTML/QuickForm/hierselect.php b/libs/HTML/QuickForm/hierselect.php
index fa92cc64a4..5889cca2d0 100644
--- a/libs/HTML/QuickForm/hierselect.php
+++ b/libs/HTML/QuickForm/hierselect.php
@@ -26,11 +26,11 @@
/**
* Class for a group of form elements
*/
-require_once 'HTML/QuickForm/group.php';
+require_once dirname(__FILE__) . '/group.php';
/**
* Class for <select></select> elements
*/
-require_once 'HTML/QuickForm/select.php';
+require_once dirname(__FILE__) . '/select.php';
/**
* Hierarchical select element
@@ -461,7 +461,7 @@ JAVASCRIPT;
$this->_js .= "_hs_defaults['" . $this->_escapeString($this->getName()) . "'] = " .
$this->_convertArrayToJavascript($values, false) . ";\n";
}
- include_once('HTML/QuickForm/Renderer/Default.php');
+ include_once(dirname(__FILE__) . '/Renderer/Default.php');
$renderer = new HTML_QuickForm_Renderer_Default();
$renderer->setElementTemplate('{element}');
parent::accept($renderer);
diff --git a/libs/HTML/QuickForm/html.php b/libs/HTML/QuickForm/html.php
index 7310f5f150..6cba2dabb2 100644
--- a/libs/HTML/QuickForm/html.php
+++ b/libs/HTML/QuickForm/html.php
@@ -24,7 +24,7 @@
/**
* HTML class for static data
*/
-require_once 'HTML/QuickForm/static.php';
+require_once dirname(__FILE__) . '/static.php';
/**
* A pseudo-element used for adding raw HTML to form
diff --git a/libs/HTML/QuickForm/image.php b/libs/HTML/QuickForm/image.php
index 52190ec446..d63169aa2b 100644
--- a/libs/HTML/QuickForm/image.php
+++ b/libs/HTML/QuickForm/image.php
@@ -25,7 +25,7 @@
/**
* Base class for <input /> form elements
*/
-require_once 'HTML/QuickForm/input.php';
+require_once dirname(__FILE__) . '/input.php';
/**
* HTML class for an <input type="image" /> element
diff --git a/libs/HTML/QuickForm/input.php b/libs/HTML/QuickForm/input.php
index 354f050f45..01407e0e63 100644
--- a/libs/HTML/QuickForm/input.php
+++ b/libs/HTML/QuickForm/input.php
@@ -25,7 +25,7 @@
/**
* Base class for form elements
*/
-require_once 'HTML/QuickForm/element.php';
+require_once dirname(__FILE__) . '/element.php';
/**
* Base class for <input /> form elements
diff --git a/libs/HTML/QuickForm/link.php b/libs/HTML/QuickForm/link.php
index d5d3d46c1f..7ae6638828 100644
--- a/libs/HTML/QuickForm/link.php
+++ b/libs/HTML/QuickForm/link.php
@@ -25,7 +25,7 @@
/**
* HTML class for static data
*/
-require_once 'HTML/QuickForm/static.php';
+require_once dirname(__FILE__) . '/static.php';
/**
* HTML class for a link type field
diff --git a/libs/HTML/QuickForm/password.php b/libs/HTML/QuickForm/password.php
index 7c6b3902d3..214b362202 100644
--- a/libs/HTML/QuickForm/password.php
+++ b/libs/HTML/QuickForm/password.php
@@ -25,7 +25,7 @@
/**
* Base class for <input /> form elements
*/
-require_once 'HTML/QuickForm/input.php';
+require_once dirname(__FILE__) . '/input.php';
/**
* HTML class for a password type field
diff --git a/libs/HTML/QuickForm/radio.php b/libs/HTML/QuickForm/radio.php
index c9d340fcbb..6f8af6e2f1 100644
--- a/libs/HTML/QuickForm/radio.php
+++ b/libs/HTML/QuickForm/radio.php
@@ -25,7 +25,7 @@
/**
* Base class for <input /> form elements
*/
-require_once 'HTML/QuickForm/input.php';
+require_once dirname(__FILE__) . '/input.php';
/**
* HTML class for a radio type element
diff --git a/libs/HTML/QuickForm/reset.php b/libs/HTML/QuickForm/reset.php
index bf2cbef908..41f8368b9a 100644
--- a/libs/HTML/QuickForm/reset.php
+++ b/libs/HTML/QuickForm/reset.php
@@ -25,7 +25,7 @@
/**
* Base class for <input /> form elements
*/
-require_once 'HTML/QuickForm/input.php';
+require_once dirname(__FILE__) . '/input.php';
/**
* HTML class for a reset type element
diff --git a/libs/HTML/QuickForm/select.php b/libs/HTML/QuickForm/select.php
index 1708fcadb6..7a94ce8bed 100644
--- a/libs/HTML/QuickForm/select.php
+++ b/libs/HTML/QuickForm/select.php
@@ -26,7 +26,7 @@
/**
* Base class for form elements
*/
-require_once 'HTML/QuickForm/element.php';
+require_once dirname(__FILE__) . '/element.php';
/**
* Class to dynamically create an HTML SELECT
@@ -299,8 +299,27 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
* @access public
* @return void
*/
- function addOption($text, $value, $attributes=null)
- {
+
+ // CLY - modification to allow optgroups
+ // function addOption($text, $value, $attributes=null)
+ function addOption($text, $value, $attributes=null, &$optGroup=null) {
+ // if text is an array, start an optgroup
+ if (is_array($text)) {
+ if (is_array($optGroup)) {
+ $optGroup[$value]['options'] = array();
+ $optGroup =& $optGroup[$value]['options'];
+ }
+ else {
+ $this->_options[$value]['options'] = array();
+ $optGroup =& $this->_options[$value]['options'];
+ };
+ foreach($text as $key=>$val) {
+ $this->addOption($val, $key, null, $optGroup);
+ }
+ // done all the options in the optgroup
+ return;
+ }
+ // end mod
if (null === $attributes) {
$attributes = array('value' => (string)$value);
} else {
@@ -316,7 +335,33 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
}
$this->_updateAttrArray($attributes, array('value' => (string)$value));
}
- $this->_options[] = array('text' => $text, 'attr' => $attributes);
+ // CLY - modification to allow optgroups
+ // if $optGroup is an array, add the option to it
+ if (is_array($optGroup)) {
+ $optGroup[$text]['attr'] = $attributes;
+ }
+ // if $optGroup is a string, add the option to the option group
+ // used if directly adding an option to an optgroup
+ elseif (is_string($optGroup)) {
+ $optGroups = explode($optGroup, ',');
+ $target =& $this->_options;
+ foreach($optGroups as $group) {
+ // create the option group if it does not exist
+ if (empty($target[$group]['options'])) {
+ $target[$group]['options'] = array();
+ }
+ $target =& $target[$group]['options'];
+ }
+ // foreach
+ // add the option
+ $target[$text]['attr'] = $attributes;
+ }
+ // else if there are attributes, add them to the option
+ elseif (is_array($attributes)) {
+ $this->_options[$text]['attr'] = $attributes;
+ }
+ // $this->_options[] = array('text' => $text, 'attr' => $attributes);
+ // end mod
} // end func addOption
// }}}
@@ -402,7 +447,7 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
function loadQuery(&$conn, $sql, $textCol=null, $valueCol=null, $values=null)
{
if (is_string($conn)) {
- require_once('DB.php');
+ require_once(dirname(__FILE__) . '/../../DB.php');
$dbConn = &DB::connect($conn, true);
if (DB::isError($dbConn)) {
return $dbConn;
@@ -493,7 +538,11 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
}
$strHtml .= $tabs . '<select' . $attrString . ">\n";
- $strValues = is_array($this->_values)? array_map('strval', $this->_values): array();
+ // CLY - modified to allow optgroups
+ foreach ($this->_options as $text=>$option) {
+ $strHtml .= $tabs . $this->_optionToHtml($text, $option);
+ }
+ /* $strValues = is_array($this->_values)? array_map('strval', $this->_values): array();
foreach ($this->_options as $option) {
if (!empty($strValues) && in_array($option['attr']['value'], $strValues, true)) {
$option['attr']['selected'] = 'selected';
@@ -501,7 +550,8 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
$strHtml .= $tabs . "\t<option" . $this->_getAttrString($option['attr']) . '>' .
$option['text'] . "</option>\n";
}
-
+ */
+ // end mod
return $strHtml . $tabs . '</select>';
}
} //end func toHtml
@@ -509,6 +559,40 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
// }}}
// {{{ getFrozenHtml()
+// CLY - new function to allow optgroups
+ /**
+ * Returns an OPTION in HTML
+ *
+ * This function is called recursively to support optgroups
+ *
+ * @param string $text Display text for the option
+ * @param array $option The option
+ * @since ??
+ * @access private
+ * @return string
+ */
+ // Creates the HTML for an option
+ function _optionToHtml($text, $option)
+ {
+ $tabs = $this->_getTabs();
+ // if an option has options it's an optgroup
+ if (isset($option['options'])) {
+ $strHtml = $tabs . "<optgroup label=\"$text\">\n";
+ foreach($option['options'] as $txt=>$opt) {
+ $strHtml .= $tabs . $this->_optionToHtml($txt, $opt);
+ }
+ $strHtml .= $tabs . "</optgroup>\n";
+ return($strHtml);
+ }
+ // else it's an option
+ else {
+ if (is_array($this->_values) && in_array((string)$option['attr']['value'], $this->_values)) {
+ $this->_updateAttrArray($option['attr'], array('selected' => 'selected'));
+ }
+ return("\t<option" . $this->_getAttrString($option['attr']) . ">$text</option>\n");
+ }
+ }
+
/**
* Returns the value of field without HTML tags
*
@@ -568,12 +652,17 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
if (is_array($value) && !empty($this->_options)) {
$cleanValue = null;
foreach ($value as $v) {
- for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) {
- if (0 == strcmp($v, $this->_options[$i]['attr']['value'])) {
- $cleanValue[] = $v;
- break;
- }
- }
+ // CLY - modified to allow optgroups
+ if ($this->_isInOptGroup($v, $this->_options)) {
+ $cleanValue[] = $v;
+ }
+// for ($i = 0, $optCount = count($this->_options); $i < $optCount; $i++) {
+// if (0 == strcmp($v, $this->_options[$i]['attr']['value'])) {
+// $cleanValue[] = $v;
+// break;
+// }
+// }
+ // end mod
}
} else {
$cleanValue = $value;
@@ -608,6 +697,22 @@ class HTML_QuickForm_select extends HTML_QuickForm_element {
return parent::onQuickFormEvent($event, $arg, $caller);
}
}
+
+ function _isInOptGroup($v, $opts) {
+ $isInOptGroup = false;
+ foreach ($opts as $opt) {
+ if (isset($opt['options'])) {
+ $isInOptGroup = $this->_isInOptGroup($v, $opt['options']);
+ }
+ else {
+ if ($v == $opt['attr']['value']) {
+ $isInOptGroup = true;
+ }
+ }
+ if ($isInOptGroup) break;
+ }
+ return $isInOptGroup;
+ }
// }}}
} //end class HTML_QuickForm_select
diff --git a/libs/HTML/QuickForm/static.php b/libs/HTML/QuickForm/static.php
index f5ce3cdca2..ef388cc456 100644
--- a/libs/HTML/QuickForm/static.php
+++ b/libs/HTML/QuickForm/static.php
@@ -24,7 +24,7 @@
/**
* Base class for form elements
*/
-require_once 'HTML/QuickForm/element.php';
+require_once dirname(__FILE__) . '/element.php';
/**
* HTML class for static data
diff --git a/libs/HTML/QuickForm/submit.php b/libs/HTML/QuickForm/submit.php
index a9fa99d65b..25a98e8a26 100644
--- a/libs/HTML/QuickForm/submit.php
+++ b/libs/HTML/QuickForm/submit.php
@@ -25,7 +25,7 @@
/**
* Base class for <input /> form elements
*/
-require_once 'HTML/QuickForm/input.php';
+require_once dirname(__FILE__) . '/input.php';
/**
* HTML class for a submit type element
diff --git a/libs/HTML/QuickForm/text.php b/libs/HTML/QuickForm/text.php
index 8d99735850..3240c41d5f 100644
--- a/libs/HTML/QuickForm/text.php
+++ b/libs/HTML/QuickForm/text.php
@@ -25,7 +25,7 @@
/**
* Base class for <input /> form elements
*/
-require_once 'HTML/QuickForm/input.php';
+require_once dirname(__FILE__) . '/input.php';
/**
* HTML class for a text field
diff --git a/libs/HTML/QuickForm/textarea.php b/libs/HTML/QuickForm/textarea.php
index a675e973bf..7aaac4c6ad 100644
--- a/libs/HTML/QuickForm/textarea.php
+++ b/libs/HTML/QuickForm/textarea.php
@@ -25,7 +25,7 @@
/**
* Base class for form elements
*/
-require_once 'HTML/QuickForm/element.php';
+require_once dirname(__FILE__) . '/element.php';
/**
* HTML class for a textarea type field
diff --git a/libs/HTML/QuickForm/xbutton.php b/libs/HTML/QuickForm/xbutton.php
index c795fa53bc..98524cca89 100644
--- a/libs/HTML/QuickForm/xbutton.php
+++ b/libs/HTML/QuickForm/xbutton.php
@@ -24,7 +24,7 @@
/**
* Base class for form elements
*/
-require_once 'HTML/QuickForm/element.php';
+require_once dirname(__FILE__) . '/element.php';
/**
* Class for HTML 4.0 <button> element
diff --git a/libs/PclZip/pclzip.lib.php b/libs/PclZip/pclzip.lib.php
index d4e00f573a..686aaa9f63 100644
--- a/libs/PclZip/pclzip.lib.php
+++ b/libs/PclZip/pclzip.lib.php
@@ -1,8 +1,8 @@
<?php
// --------------------------------------------------------------------------------
-// PhpConcept Library - Zip Module 2.8
+// PhpConcept Library - Zip Module 2.8.2
// --------------------------------------------------------------------------------
-// License GNU/LGPL - Vincent Blavet - March 2006
+// License GNU/LGPL - Vincent Blavet - August 2009
// http://www.phpconcept.net
// --------------------------------------------------------------------------------
//
@@ -22,14 +22,14 @@
// The use of this software is at the risk of the user.
//
// --------------------------------------------------------------------------------
-// $Id$
+// $Id: pclzip.lib.php,v 1.60 2009/09/30 21:01:04 vblavet Exp $
// --------------------------------------------------------------------------------
// ----- Constants
if (!defined('PCLZIP_READ_BLOCK_SIZE')) {
define( 'PCLZIP_READ_BLOCK_SIZE', 2048 );
}
-
+
// ----- File list separator
// In version 1.x of PclZip, the separator for file list is a space
// (which is not a very smart choice, specifically for windows paths !).
@@ -68,7 +68,7 @@
// ----- Optional threshold ratio for use of temporary files
// Pclzip sense the size of the file to add/extract and decide to
- // use or not temporary file. The algorythm is looking for
+ // use or not temporary file. The algorythm is looking for
// memory_limit of PHP and apply a ratio.
// threshold = memory_limit * ratio.
// Recommended values are under 0.5. Default 0.47.
@@ -83,7 +83,7 @@
// --------------------------------------------------------------------------------
// ----- Global variables
- $g_pclzip_version = "2.8";
+ $g_pclzip_version = "2.8.2";
// ----- Error codes
// -1 : Unable to open file in binary write mode
@@ -152,7 +152,7 @@
define( 'PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias
define( 'PCLZIP_OPT_TEMP_FILE_OFF', 77022 );
define( 'PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias
-
+
// ----- File description attributes
define( 'PCLZIP_ATT_FILE_NAME', 79001 );
define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 );
@@ -198,7 +198,7 @@
// ----- Internal error handling
var $error_code = 1;
var $error_string = '';
-
+
// ----- Current status of the magic_quotes_runtime
// This value store the php configuration for magic_quotes
// The class can then disable the magic_quotes and reset it after
@@ -214,12 +214,10 @@
// --------------------------------------------------------------------------------
function PclZip($p_zipname)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::PclZip', "zipname=$p_zipname");
// ----- Tests the zlib
if (!function_exists('gzopen'))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 1, "zlib extension seems to be missing");
die('Abort '.basename(__FILE__).' : Missing zlib extensions');
}
@@ -229,7 +227,6 @@
$this->magic_quotes_status = -1;
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 1);
return;
}
// --------------------------------------------------------------------------------
@@ -273,7 +270,6 @@
// --------------------------------------------------------------------------------
function create($p_filelist)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::create', "filelist='$p_filelist', ...");
$v_result=1;
// ----- Reset the error handler
@@ -285,7 +281,6 @@
// ----- Look for variable options arguments
$v_size = func_num_args();
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
// ----- Look for arguments
if ($v_size > 1) {
@@ -298,7 +293,6 @@
// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
@@ -315,7 +309,6 @@
//, PCLZIP_OPT_CRYPT => 'optional'
));
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
}
@@ -324,7 +317,6 @@
// Here we need to support the first historic synopsis of the
// method.
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
// ----- Get the first argument
$v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0];
@@ -336,12 +328,11 @@
else if ($v_size > 2) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER,
"Invalid number / type of arguments");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return 0;
}
}
}
-
+
// ----- Look for default option values
$this->privOptionDefaultThreshold($v_options);
@@ -350,16 +341,16 @@
$v_att_list = array();
$v_filedescr_list = array();
$p_result_list = array();
-
+
// ----- Look if the $p_filelist is really an array
if (is_array($p_filelist)) {
-
+
// ----- Look if the first element is also an array
// This will mean that this is a file description entry
if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
$v_att_list = $p_filelist;
}
-
+
// ----- The list is a list of string names
else {
$v_string_list = $p_filelist;
@@ -375,10 +366,9 @@
// ----- Invalid variable type for $p_filelist
else {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
-
+
// ----- Reformat the string list
if (sizeof($v_string_list) != 0) {
foreach ($v_string_list as $v_string) {
@@ -386,11 +376,10 @@
$v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Ignore an empty filename");
}
}
}
-
+
// ----- For each file in the list check the attributes
$v_supported_attributes
= array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
@@ -406,7 +395,6 @@
$v_options,
$v_supported_attributes);
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
}
@@ -414,19 +402,16 @@
// ----- Expand the filelist (expand directories)
$v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
// ----- Call the create fct
$v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options);
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
return $p_result_list;
}
// --------------------------------------------------------------------------------
@@ -468,7 +453,6 @@
// --------------------------------------------------------------------------------
function add($p_filelist)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::add', "filelist='$p_filelist', ...");
$v_result=1;
// ----- Reset the error handler
@@ -480,7 +464,6 @@
// ----- Look for variable options arguments
$v_size = func_num_args();
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
// ----- Look for arguments
if ($v_size > 1) {
@@ -493,7 +476,6 @@
// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options detected");
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
@@ -512,7 +494,6 @@
//, PCLZIP_OPT_CRYPT => 'optional'
));
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
}
@@ -521,7 +502,6 @@
// Here we need to support the first historic synopsis of the
// method.
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
// ----- Get the first argument
$v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0];
@@ -535,7 +515,6 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return 0;
}
}
@@ -549,16 +528,16 @@
$v_att_list = array();
$v_filedescr_list = array();
$p_result_list = array();
-
+
// ----- Look if the $p_filelist is really an array
if (is_array($p_filelist)) {
-
+
// ----- Look if the first element is also an array
// This will mean that this is a file description entry
if (isset($p_filelist[0]) && is_array($p_filelist[0])) {
$v_att_list = $p_filelist;
}
-
+
// ----- The list is a list of string names
else {
$v_string_list = $p_filelist;
@@ -574,17 +553,16 @@
// ----- Invalid variable type for $p_filelist
else {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
-
+
// ----- Reformat the string list
if (sizeof($v_string_list) != 0) {
foreach ($v_string_list as $v_string) {
$v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string;
}
}
-
+
// ----- For each file in the list check the attributes
$v_supported_attributes
= array ( PCLZIP_ATT_FILE_NAME => 'mandatory'
@@ -600,7 +578,6 @@
$v_options,
$v_supported_attributes);
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
}
@@ -608,19 +585,16 @@
// ----- Expand the filelist (expand directories)
$v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options);
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
// ----- Call the create fct
$v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options);
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_result_list);
return $p_result_list;
}
// --------------------------------------------------------------------------------
@@ -668,7 +642,6 @@
// --------------------------------------------------------------------------------
function listContent()
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::listContent', "");
$v_result=1;
// ----- Reset the error handler
@@ -676,7 +649,6 @@
// ----- Check archive
if (!$this->privCheckFormat()) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}
@@ -685,12 +657,10 @@
if (($v_result = $this->privList($p_list)) != 1)
{
unset($p_list);
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return(0);
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
return $p_list;
}
// --------------------------------------------------------------------------------
@@ -729,7 +699,6 @@
// --------------------------------------------------------------------------------
function extract()
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extract", "");
$v_result=1;
// ----- Reset the error handler
@@ -737,7 +706,6 @@
// ----- Check archive
if (!$this->privCheckFormat()) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}
@@ -750,7 +718,6 @@
// ----- Look for variable options arguments
$v_size = func_num_args();
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
// ----- Default values for option
$v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
@@ -762,7 +729,6 @@
// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
@@ -787,7 +753,6 @@
PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
));
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
@@ -814,7 +779,6 @@
// Here we need to support the first historic synopsis of the
// method.
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
// ----- Get the first argument
$v_path = $v_arg_list[0];
@@ -828,7 +792,6 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return 0;
}
}
@@ -838,7 +801,6 @@
$this->privOptionDefaultThreshold($v_options);
// ----- Trace
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");
// ----- Call the extracting fct
$p_list = array();
@@ -846,12 +808,10 @@
$v_remove_all_path, $v_options);
if ($v_result < 1) {
unset($p_list);
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return(0);
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
return $p_list;
}
// --------------------------------------------------------------------------------
@@ -896,7 +856,6 @@
//function extractByIndex($p_index, options...)
function extractByIndex($p_index)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::extractByIndex", "index='$p_index', ...");
$v_result=1;
// ----- Reset the error handler
@@ -904,7 +863,6 @@
// ----- Check archive
if (!$this->privCheckFormat()) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}
@@ -917,7 +875,6 @@
// ----- Look for variable options arguments
$v_size = func_num_args();
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
// ----- Default values for option
$v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
@@ -933,7 +890,6 @@
// ----- Look for first arg
if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Variable list of options");
// ----- Parse the options
$v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options,
@@ -953,7 +909,6 @@
PCLZIP_OPT_TEMP_FILE_OFF => 'optional'
));
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
@@ -976,10 +931,8 @@
}
if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) {
$v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING not set.");
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Option PCLZIP_OPT_EXTRACT_AS_STRING set.");
}
}
@@ -987,7 +940,6 @@
// Here we need to support the first historic synopsis of the
// method.
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Static synopsis");
// ----- Get the first argument
$v_path = $v_arg_list[0];
@@ -1001,14 +953,12 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return 0;
}
}
}
// ----- Trace
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "index='$p_index', path='$v_path', remove_path='$v_remove_path', remove_all_path='".($v_remove_path?'true':'false')."'");
// ----- Trick
// Here I want to reuse extractByRule(), so I need to parse the $p_index
@@ -1018,7 +968,6 @@
$v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick,
array (PCLZIP_OPT_BY_INDEX => 'optional' ));
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
$v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX];
@@ -1028,12 +977,10 @@
// ----- Call the extracting fct
if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return(0);
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
return $p_list;
}
// --------------------------------------------------------------------------------
@@ -1049,7 +996,7 @@
// Options :
// PCLZIP_OPT_BY_INDEX :
// PCLZIP_OPT_BY_NAME :
- // PCLZIP_OPT_BY_EREG :
+ // PCLZIP_OPT_BY_EREG :
// PCLZIP_OPT_BY_PREG :
// Return Values :
// 0 on failure,
@@ -1058,7 +1005,6 @@
// --------------------------------------------------------------------------------
function delete()
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::delete", "");
$v_result=1;
// ----- Reset the error handler
@@ -1066,7 +1012,6 @@
// ----- Check archive
if (!$this->privCheckFormat()) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}
@@ -1075,7 +1020,6 @@
// ----- Look for variable options arguments
$v_size = func_num_args();
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "$v_size arguments passed to the method");
// ----- Look for arguments
if ($v_size > 0) {
@@ -1089,7 +1033,6 @@
PCLZIP_OPT_BY_PREG => 'optional',
PCLZIP_OPT_BY_INDEX => 'optional' ));
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
}
@@ -1102,7 +1045,6 @@
if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) {
$this->privSwapBackMagicQuotes();
unset($v_list);
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0, PclZip::errorInfo());
return(0);
}
@@ -1110,7 +1052,6 @@
$this->privSwapBackMagicQuotes();
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_list);
return $v_list;
}
// --------------------------------------------------------------------------------
@@ -1123,12 +1064,10 @@
// --------------------------------------------------------------------------------
function deleteByIndex($p_index)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::deleteByIndex", "index='$p_index'");
-
+
$p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $p_list);
return $p_list;
}
// --------------------------------------------------------------------------------
@@ -1149,7 +1088,6 @@
// --------------------------------------------------------------------------------
function properties()
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::properties", "");
// ----- Reset the error handler
$this->privErrorReset();
@@ -1160,7 +1098,6 @@
// ----- Check archive
if (!$this->privCheckFormat()) {
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}
@@ -1174,16 +1111,14 @@
if (@is_file($this->zipname))
{
// ----- Open the zip file
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
{
$this->privSwapBackMagicQuotes();
-
+
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), 0);
return 0;
}
@@ -1192,7 +1127,6 @@
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return 0;
}
@@ -1209,7 +1143,6 @@
$this->privSwapBackMagicQuotes();
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_prop);
return $v_prop;
}
// --------------------------------------------------------------------------------
@@ -1228,7 +1161,6 @@
// --------------------------------------------------------------------------------
function duplicate($p_archive)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::duplicate", "");
$v_result = 1;
// ----- Reset the error handler
@@ -1237,7 +1169,6 @@
// ----- Look if the $p_archive is a PclZip object
if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip'))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is valid PclZip object '".$p_archive->zipname."'");
// ----- Duplicate the archive
$v_result = $this->privDuplicate($p_archive->zipname);
@@ -1246,7 +1177,6 @@
// ----- Look if the $p_archive is a string (so a filename)
else if (is_string($p_archive))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The parameter is a filename '$p_archive'");
// ----- Check that $p_archive is a valid zip file
// TBC : Should also check the archive format
@@ -1270,7 +1200,6 @@
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -1291,7 +1220,6 @@
// --------------------------------------------------------------------------------
function merge($p_archive_to_add)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::merge", "");
$v_result = 1;
// ----- Reset the error handler
@@ -1299,14 +1227,12 @@
// ----- Check archive
if (!$this->privCheckFormat()) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, 0);
return(0);
}
// ----- Look if the $p_archive_to_add is a PclZip object
if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip'))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is valid PclZip object");
// ----- Merge the archive
$v_result = $this->privMerge($p_archive_to_add);
@@ -1315,7 +1241,6 @@
// ----- Look if the $p_archive_to_add is a string (so a filename)
else if (is_string($p_archive_to_add))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The parameter is a filename");
// ----- Create a temporary archive
$v_object_archive = new PclZip($p_archive_to_add);
@@ -1333,7 +1258,6 @@
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -1448,7 +1372,6 @@
// --------------------------------------------------------------------------------
function privCheckFormat($p_level=0)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFormat", "");
$v_result = true;
// ----- Reset the file system cache
@@ -1461,7 +1384,6 @@
if (!is_file($this->zipname)) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
return(false);
}
@@ -1469,7 +1391,6 @@
if (!is_readable($this->zipname)) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, false, PclZip::errorInfo());
return(false);
}
@@ -1483,7 +1404,6 @@
// TBC
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -1505,13 +1425,11 @@
// --------------------------------------------------------------------------------
function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privParseOptions", "");
$v_result=1;
-
+
// ----- Read the options
$i=0;
while ($i<$p_size) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Looking for table index $i, option = '".PclZipUtilOptionText($p_options_list[$i])."(".$p_options_list[$i].")'");
// ----- Check if the option is supported
if (!isset($v_requested_options[$p_options_list[$i]])) {
@@ -1519,7 +1437,6 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -1535,13 +1452,11 @@
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Get the value
$v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
$i++;
break;
@@ -1549,28 +1464,24 @@
// ----- Check the number of parameters
if (($i+1) >= $p_size) {
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
-
+
// ----- Check for incompatible options
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
-
+
// ----- Check the value
$v_value = $p_options_list[$i+1];
if ((!is_integer($v_value)) || ($v_value<0)) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Get the value (and convert it in bytes)
$v_result_list[$p_options_list[$i]] = $v_value*1048576;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
$i++;
break;
@@ -1578,30 +1489,25 @@
// ----- Check for incompatible options
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
-
+
$v_result_list[$p_options_list[$i]] = true;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
break;
case PCLZIP_OPT_TEMP_FILE_OFF :
// ----- Check for incompatible options
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Check for incompatible options
if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
-
+
$v_result_list[$p_options_list[$i]] = true;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
break;
case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION :
@@ -1611,7 +1517,6 @@
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -1619,11 +1524,9 @@
if ( is_string($p_options_list[$i+1])
&& ($p_options_list[$i+1] != '')) {
$v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
$i++;
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." set with an empty value is ignored.");
}
break;
@@ -1635,7 +1538,6 @@
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -1651,15 +1553,16 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
$i++;
break;
// ----- Look for options that request an EREG or PREG expression
case PCLZIP_OPT_BY_EREG :
+ // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG
+ // to PCLZIP_OPT_BY_PREG
+ $p_options_list[$i] = PCLZIP_OPT_BY_PREG;
case PCLZIP_OPT_BY_PREG :
//case PCLZIP_OPT_CRYPT :
// ----- Check the number of parameters
@@ -1668,7 +1571,6 @@
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -1681,10 +1583,8 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
$i++;
break;
@@ -1701,7 +1601,6 @@
."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -1717,10 +1616,8 @@
."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
$i++;
break;
@@ -1732,14 +1629,12 @@
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Get the value
$v_work_list = array();
if (is_string($p_options_list[$i+1])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is a string '".$p_options_list[$i+1]."'");
// ----- Remove spaces
$p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', '');
@@ -1748,11 +1643,9 @@
$v_work_list = explode(",", $p_options_list[$i+1]);
}
else if (is_integer($p_options_list[$i+1])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an integer '".$p_options_list[$i+1]."'");
$v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1];
}
else if (is_array($p_options_list[$i+1])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Index value is an array");
$v_work_list = $p_options_list[$i+1];
}
else {
@@ -1760,10 +1653,9 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
-
+
// ----- Reduce the index list
// each index item in the list must be a couple with a start and
// an end value : [0,3], [5-5], [8-10], ...
@@ -1774,10 +1666,10 @@
// ----- Explode the item
$v_item_list = explode("-", $v_work_list[$j]);
$v_size_item_list = sizeof($v_item_list);
-
+
// ----- TBC : Here we might check that each item is a
// real integer ...
-
+
// ----- Look for single value
if ($v_size_item_list == 1) {
// ----- Set the option value
@@ -1794,15 +1686,12 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extracted index item = [".$v_result_list[$p_options_list[$i]][$j]['start'].",".$v_result_list[$p_options_list[$i]][$j]['end']."]");
// ----- Look for list sort
if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The list should be sorted ...");
$v_sort_flag=true;
// ----- TBC : An automatic sort should be writen ...
@@ -1810,16 +1699,14 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
$v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start'];
}
-
+
// ----- Sort the items
if ($v_sort_flag) {
// TBC : To Be Completed
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "List sorting is not yet write ...");
}
// ----- Next option
@@ -1834,7 +1721,6 @@
case PCLZIP_OPT_REPLACE_NEWER :
case PCLZIP_OPT_STOP_ON_ERROR :
$v_result_list[$p_options_list[$i]] = true;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
break;
// ----- Look for options that request an octal value
@@ -1845,13 +1731,11 @@
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Get the value
$v_result_list[$p_options_list[$i]] = $p_options_list[$i+1];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($p_options_list[$i])." = '".$v_result_list[$p_options_list[$i]]."'");
$i++;
break;
@@ -1872,13 +1756,11 @@
PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Get the value
$v_function_name = $p_options_list[$i+1];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "call-back ".PclZipUtilOptionText($p_options_list[$i])." = '".$v_function_name."'");
// ----- Check that the value is a valid existing function
if (!function_exists($v_function_name)) {
@@ -1886,7 +1768,6 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -1902,7 +1783,6 @@
.$p_options_list[$i]."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -1915,28 +1795,24 @@
for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
// ----- Look for mandatory option
if ($v_requested_options[$key] == 'mandatory') {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")");
// ----- Look if present
if (!isset($v_result_list[$key])) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}
}
}
-
+
// ----- Look for default values
if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3,"Calculate auto threshold");
-
+
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -1949,21 +1825,18 @@
// --------------------------------------------------------------------------------
function privOptionDefaultThreshold(&$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privOptionDefaultThreshold", "");
$v_result=1;
-
+
if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
|| isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
-
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3,"Create an auto-threshold for use of temporay files");
+
// ----- Get 'memory_limit' configuration value
$v_memory_limit = ini_get('memory_limit');
$v_memory_limit = trim($v_memory_limit);
$last = strtolower(substr($v_memory_limit, -1));
-
+
if($last == 'g')
//$v_memory_limit = $v_memory_limit*1024*1024*1024;
$v_memory_limit = $v_memory_limit*1073741824;
@@ -1972,20 +1845,16 @@
$v_memory_limit = $v_memory_limit*1048576;
if($last == 'k')
$v_memory_limit = $v_memory_limit*1024;
-
+
$p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO);
-
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3,"Current memory usage : ".memory_get_usage(TRUE)." bytes");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3,"Threshold value is : ".$p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]." bytes");
+
// ----- Sanity check : No threshold if value lower than 1M
if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3,"Unset the threshold (value ".$p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD].") because under 1Mo sanity check)");
unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]);
}
-
+
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -2000,19 +1869,17 @@
// --------------------------------------------------------------------------------
function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privFileDescrParseAtt", "");
$v_result=1;
-
+
// ----- For each file in the list check the attributes
foreach ($p_file_list as $v_key => $v_value) {
-
+
// ----- Check if the option is supported
if (!isset($v_requested_options[$v_key])) {
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -2021,16 +1888,13 @@
case PCLZIP_ATT_FILE_NAME :
if (!is_string($v_value)) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
$p_filedescr['filename'] = PclZipUtilPathReduction($v_value);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
-
+
if ($p_filedescr['filename'] == '') {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -2039,16 +1903,13 @@
case PCLZIP_ATT_FILE_NEW_SHORT_NAME :
if (!is_string($v_value)) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
$p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
if ($p_filedescr['new_short_name'] == '') {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
break;
@@ -2056,16 +1917,13 @@
case PCLZIP_ATT_FILE_NEW_FULL_NAME :
if (!is_string($v_value)) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
$p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
if ($p_filedescr['new_full_name'] == '') {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
break;
@@ -2074,28 +1932,23 @@
case PCLZIP_ATT_FILE_COMMENT :
if (!is_string($v_value)) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
$p_filedescr['comment'] = $v_value;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
break;
case PCLZIP_ATT_FILE_MTIME :
if (!is_integer($v_value)) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
$p_filedescr['mtime'] = $v_value;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
break;
case PCLZIP_ATT_FILE_CONTENT :
$p_filedescr['content'] = $v_value;
- ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "".PclZipUtilOptionText($v_key)." = '".$v_value."'");
break;
default :
@@ -2104,7 +1957,6 @@
"Unknown parameter '".$v_key."'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -2113,22 +1965,19 @@
for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) {
// ----- Look for mandatory option
if ($v_requested_options[$key] == 'mandatory') {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Detect a mandatory option : ".PclZipUtilOptionText($key)."(".$key.")");
// ----- Look if present
if (!isset($p_file_list[$key])) {
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}
}
}
-
+
// end foreach
}
-
+
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -2140,7 +1989,7 @@
// or a string to be added as file. For any other type of files (link, other)
// just ignore the item.
// Then prepare the information that will be stored for that file.
- // When its a folder, expand the folder with all the files that are in that
+ // When its a folder, expand the folder with all the files that are in that
// folder (recursively).
// Parameters :
// Return Values :
@@ -2149,70 +1998,59 @@
// --------------------------------------------------------------------------------
function privFileDescrExpand(&$p_filedescr_list, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privFileDescrExpand", "");
$v_result=1;
-
+
// ----- Create a result list
$v_result_list = array();
-
+
// ----- Look each entry
for ($i=0; $i<sizeof($p_filedescr_list); $i++) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Looking for file ".$i.".");
-
+
// ----- Get filedescr
$v_descr = $p_filedescr_list[$i];
-
+
// ----- Reduce the filename
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filedescr before reduction :'".$v_descr['filename']."'");
$v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false);
$v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filedescr after reduction :'".$v_descr['filename']."'");
-
+
// ----- Look for real file or folder
if (file_exists($v_descr['filename'])) {
if (@is_file($v_descr['filename'])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "This is a file");
$v_descr['type'] = 'file';
}
else if (@is_dir($v_descr['filename'])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "This is a folder");
$v_descr['type'] = 'folder';
}
else if (@is_link($v_descr['filename'])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Unsupported file type : link");
// skip
continue;
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Unsupported file type : unknown type");
// skip
continue;
}
}
-
+
// ----- Look for string added as file
else if (isset($v_descr['content'])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "This is a string added as a file");
$v_descr['type'] = 'virtual_file';
}
-
+
// ----- Missing file
else {
// ----- Error log
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_descr['filename']."' does not exist");
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
-
+
// ----- Calculate the stored filename
$this->privCalculateStoredFilename($v_descr, $p_options);
-
+
// ----- Add the descriptor in result list
$v_result_list[sizeof($v_result_list)] = $v_descr;
-
+
// ----- Look for folder
if ($v_descr['type'] == 'folder') {
// ----- List of items in folder
@@ -2220,20 +2058,20 @@
$v_dirlist_nb = 0;
if ($v_folder_handler = @opendir($v_descr['filename'])) {
while (($v_item_handler = @readdir($v_folder_handler)) !== false) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for '".$v_item_handler."' in the directory");
// ----- Skip '.' and '..'
if (($v_item_handler == '.') || ($v_item_handler == '..')) {
continue;
}
-
+
// ----- Compose the full filename
$v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler;
-
+
// ----- Look for different stored filename
// Because the name of the folder was changed, the name of the
// files/sub-folders also change
- if ($v_descr['stored_filename'] != $v_descr['filename']) {
+ if (($v_descr['stored_filename'] != $v_descr['filename'])
+ && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) {
if ($v_descr['stored_filename'] != '') {
$v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler;
}
@@ -2241,44 +2079,38 @@
$v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler;
}
}
-
+
$v_dirlist_nb++;
}
-
+
@closedir($v_folder_handler);
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to open dir '".$v_descr['filename']."' in read mode. Skipped.");
// TBC : unable to open folder in read mode
}
-
+
// ----- Expand each element of the list
if ($v_dirlist_nb != 0) {
// ----- Expand
if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
-
+
// ----- Concat the resulting list
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Merging result list (size '".sizeof($v_result_list)."') with dirlist (size '".sizeof($v_dirlist_descr)."')");
$v_result_list = array_merge($v_result_list, $v_dirlist_descr);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "merged result list is size '".sizeof($v_result_list)."'");
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Nothing in this folder to expand.");
}
-
+
// ----- Free local array
unset($v_dirlist_descr);
}
}
-
+
// ----- Get the result list
$p_filedescr_list = $v_result_list;
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -2291,10 +2123,9 @@
// --------------------------------------------------------------------------------
function privCreate($p_filedescr_list, &$p_result_list, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCreate", "list");
$v_result=1;
$v_list_detail = array();
-
+
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
@@ -2302,7 +2133,6 @@
if (($v_result = $this->privOpenFd('wb')) != 1)
{
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -2316,7 +2146,6 @@
$this->privSwapBackMagicQuotes();
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -2329,34 +2158,29 @@
// --------------------------------------------------------------------------------
function privAdd($p_filedescr_list, &$p_result_list, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAdd", "list");
$v_result=1;
$v_list_detail = array();
// ----- Look if the archive exists or is empty
if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, or is empty, create it.");
// ----- Do a create
$v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
// ----- Open the zip file
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_result=$this->privOpenFd('rb')) != 1)
{
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -2366,20 +2190,16 @@
{
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Go to beginning of File
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
// ----- Creates a temporay file
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
// ----- Open the temporary file in write mode
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
{
$this->privCloseFd();
@@ -2388,7 +2208,6 @@
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -2398,7 +2217,6 @@
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = fread($this->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
@@ -2421,20 +2239,17 @@
$this->privSwapBackMagicQuotes();
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Store the offset of the central dir
$v_offset = @ftell($this->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
// ----- Copy the block of file headers from the old archive
$v_size = $v_central_dir['size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @fread($v_zip_temp_fd, $v_read_size);
@fwrite($this->zip_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
@@ -2452,7 +2267,6 @@
$this->privSwapBackMagicQuotes();
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
$v_count++;
@@ -2485,7 +2299,6 @@
$this->privSwapBackMagicQuotes();
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -2513,7 +2326,6 @@
PclZipUtilRename($v_zip_temp_name, $this->zipname);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -2525,7 +2337,6 @@
// --------------------------------------------------------------------------------
function privOpenFd($p_mode)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privOpenFd", 'mode='.$p_mode);
$v_result=1;
// ----- Look if already open
@@ -2535,24 +2346,20 @@
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Open the zip file
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Open file in '.$p_mode.' mode');
if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0)
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -2564,7 +2371,6 @@
// --------------------------------------------------------------------------------
function privCloseFd()
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCloseFd", "");
$v_result=1;
if ($this->zip_fd != 0)
@@ -2572,7 +2378,6 @@
$this->zip_fd = 0;
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -2593,7 +2398,6 @@
// function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options)
function privAddList($p_filedescr_list, &$p_result_list, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddList", "list");
$v_result=1;
// ----- Add the files
@@ -2601,7 +2405,6 @@
if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1)
{
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -2615,7 +2418,6 @@
if ($v_header_list[$i]['status'] == 'ok') {
if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
$v_count++;
@@ -2641,12 +2443,10 @@
unset($v_header_list);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -2655,42 +2455,36 @@
// Function : privAddFileList()
// Description :
// Parameters :
- // $p_filedescr_list : An array containing the file description
+ // $p_filedescr_list : An array containing the file description
// or directory names to add in the zip
// $p_result_list : list of added files with their properties (specially the status field)
// Return Values :
// --------------------------------------------------------------------------------
function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFileList", "filedescr_list");
$v_result=1;
$v_header = array();
// ----- Recuperate the current number of elt in list
$v_nb = sizeof($p_result_list);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Before add, list have ".$v_nb." elements");
// ----- Loop on the files
for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) {
// ----- Format the filename
$p_filedescr_list[$j]['filename']
= PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false);
-
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Looking for file '".$p_filedescr_list[$j]['filename']."'");
+
// ----- Skip empty file names
// TBC : Can this be possible ? not checked in DescrParseAtt ?
if ($p_filedescr_list[$j]['filename'] == "") {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Skip empty filename");
continue;
}
// ----- Check the filename
if ( ($p_filedescr_list[$j]['type'] != 'virtual_file')
&& (!file_exists($p_filedescr_list[$j]['filename']))) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_filedescr_list[$j]['filename']."' does not exist");
PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exist");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -2709,7 +2503,6 @@
$v_result = $this->privAddFile($p_filedescr_list[$j], $v_header,
$p_options);
if ($v_result != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -2717,10 +2510,8 @@
$p_result_list[$v_nb++] = $v_header;
}
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "After add, list have ".$v_nb." elements");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -2733,9 +2524,8 @@
// --------------------------------------------------------------------------------
function privAddFile($p_filedescr, &$p_header, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFile", "filename='".$p_filedescr['filename']."'");
$v_result=1;
-
+
// ----- Working variable
$p_filename = $p_filedescr['filename'];
@@ -2745,19 +2535,16 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
-
- // ----- Look for a stored different filename
+
+ // ----- Look for a stored different filename
/* TBC : Removed
if (isset($p_filedescr['stored_filename'])) {
$v_stored_filename = $p_filedescr['stored_filename'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'Stored filename is NOT the same "'.$v_stored_filename.'"');
}
else {
$v_stored_filename = $p_filedescr['stored_filename'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'Stored filename is the same');
}
*/
@@ -2786,30 +2573,27 @@
$p_header['external'] = 0x00000000;
$p_header['size'] = filesize($p_filename);
}
-
+
// ----- Look for regular folder
else if ($p_filedescr['type']=='folder') {
$p_header['external'] = 0x00000010;
$p_header['mtime'] = filemtime($p_filename);
$p_header['size'] = filesize($p_filename);
}
-
+
// ----- Look for virtual file
else if ($p_filedescr['type'] == 'virtual_file') {
$p_header['external'] = 0x00000000;
$p_header['size'] = strlen($p_filedescr['content']);
}
-
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header external extension '".sprintf("0x%X",$p_header['external'])."'");
+
// ----- Look for filetime
if (isset($p_filedescr['mtime'])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3,"Overload mtime value with :'".$p_filedescr['mtime']."'");
$p_header['mtime'] = $p_filedescr['mtime'];
}
else if ($p_filedescr['type'] == 'virtual_file') {
$p_header['mtime'] = time();
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Virtual file : use current time '".$p_header['mtime']."' for mtime value.");
}
else {
$p_header['mtime'] = filemtime($p_filename);
@@ -2827,7 +2611,6 @@
// ----- Look for pre-add callback
if (isset($p_options[PCLZIP_CB_PRE_ADD])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_ADD]."()') is defined for the extraction");
// ----- Generate a local information
$v_local_header = array();
@@ -2836,7 +2619,8 @@
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
- eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
+// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);');
+ $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header);
if ($v_result == 0) {
// ----- Change the file status
$p_header['status'] = "skipped";
@@ -2847,7 +2631,6 @@
// Only some fields can be modified
if ($p_header['stored_filename'] != $v_local_header['stored_filename']) {
$p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New stored filename is '".$p_header['stored_filename']."'");
}
}
@@ -2855,7 +2638,7 @@
if ($p_header['stored_filename'] == "") {
$p_header['status'] = "filtered";
}
-
+
// ----- Check the path length
if (strlen($p_header['stored_filename']) > 0xFF) {
$p_header['status'] = 'filename_too_long';
@@ -2867,7 +2650,7 @@
// ----- Look for a file
if ($p_filedescr['type'] == 'file') {
// ----- Look for using temporary file to zip
- if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
+ if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
&& (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
|| (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
&& ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) {
@@ -2876,57 +2659,45 @@
return $v_result;
}
}
-
+
// ----- Use "in memory" zip algo
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2,"In memory compression.");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2,"Current memory usage : ".memory_get_usage(TRUE)." bytes");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2,"Current memory peak : ".memory_get_peak_usage(TRUE)." bytes");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a file");
// ----- Open the source file
if (($v_file = @fopen($p_filename, "rb")) == 0) {
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Read the file content
$v_content = @fread($v_file, $p_header['size']);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2,"Memory usage after reading file : ".memory_get_usage(TRUE)." bytes");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2,"Memory peak after reading file : ".memory_get_peak_usage(TRUE)." bytes");
// ----- Close the file
@fclose($v_file);
// ----- Calculate the CRC
$p_header['crc'] = @crc32($v_content);
-
+
// ----- Look for no compression
if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be compressed");
// ----- Set header parameters
$p_header['compressed_size'] = $p_header['size'];
$p_header['compression'] = 0;
}
-
+
// ----- Look for normal compression
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will be compressed");
// ----- Compress the content
$v_content = @gzdeflate($v_content);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2,"Memory usage after gzdeflate : ".memory_get_usage(TRUE)." bytes");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2,"Memory peak after gzdeflate : ".memory_get_peak_usage(TRUE)." bytes");
// ----- Set header parameters
$p_header['compressed_size'] = strlen($v_content);
$p_header['compression'] = 8;
}
-
+
// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
@fclose($v_file);
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -2939,24 +2710,21 @@
// ----- Look for a virtual file (a file from string)
else if ($p_filedescr['type'] == 'virtual_file') {
-
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Add by string");
+
$v_content = $p_filedescr['content'];
// ----- Calculate the CRC
$p_header['crc'] = @crc32($v_content);
-
+
// ----- Look for no compression
if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be compressed");
// ----- Set header parameters
$p_header['compressed_size'] = $p_header['size'];
$p_header['compression'] = 0;
}
-
+
// ----- Look for normal compression
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will be compressed");
// ----- Compress the content
$v_content = @gzdeflate($v_content);
@@ -2964,11 +2732,10 @@
$p_header['compressed_size'] = strlen($v_content);
$p_header['compression'] = 8;
}
-
+
// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
@fclose($v_file);
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -2978,7 +2745,6 @@
// ----- Look for a directory
else if ($p_filedescr['type'] == 'folder') {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a folder");
// ----- Look for directory last '/'
if (@substr($p_header['stored_filename'], -1) != '/') {
$p_header['stored_filename'] .= '/';
@@ -2992,7 +2758,6 @@
// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1)
{
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
}
@@ -3000,7 +2765,6 @@
// ----- Look for post-add callback
if (isset($p_options[PCLZIP_CB_POST_ADD])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_ADD]."()') is defined for the extraction");
// ----- Generate a local information
$v_local_header = array();
@@ -3009,7 +2773,8 @@
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
- eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);');
+// eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);');
+ $v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header);
if ($v_result == 0) {
// ----- Ignored
$v_result = 1;
@@ -3020,7 +2785,6 @@
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -3033,18 +2797,15 @@
// --------------------------------------------------------------------------------
function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privAddFileUsingTempFile", "filename='".$p_filedescr['filename']."'");
$v_result=PCLZIP_ERR_NO_ERROR;
-
+
// ----- Working variable
$p_filename = $p_filedescr['filename'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "'".$p_filename."' is a file");
// ----- Open the source file
if (($v_file = @fopen($p_filename, "rb")) == 0) {
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -3053,7 +2814,6 @@
if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) {
fclose($v_file);
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -3061,7 +2821,6 @@
$v_size = filesize($p_filename);
while ($v_size != 0) {
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read ".$v_read_size." bytes");
$v_buffer = @fread($v_file, $v_read_size);
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@gzputs($v_file_compressed, $v_buffer, $v_read_size);
@@ -3073,17 +2832,14 @@
@gzclose($v_file_compressed);
// ----- Check the minimum file size
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "gzip file size ".filesize($v_gzip_temp_name));
if (filesize($v_gzip_temp_name) < 18) {
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes');
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Extract the compressed attributes
if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) {
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -3092,28 +2848,17 @@
$v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data);
// ----- Check some parameters
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[id1]='.bin2hex($v_data_header['id1']));
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[id2]='.bin2hex($v_data_header['id2']));
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[cm]='.bin2hex($v_data_header['cm']));
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[flag]='.bin2hex($v_data_header['flag']));
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[mtime]='.$v_data_header['mtime']);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[xfl]='.bin2hex($v_data_header['xfl']));
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, '$v_data_header[os]='.bin2hex($v_data_header['os']));
$v_data_header['os'] = bin2hex($v_data_header['os']);
// ----- Read the gzip file footer
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File position after header ".ftell($v_file_compressed));
@fseek($v_file_compressed, filesize($v_gzip_temp_name)-8);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File position at beginning of footer ".ftell($v_file_compressed));
$v_binary_data = @fread($v_file_compressed, 8);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File position after footer ".ftell($v_file_compressed));
$v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data);
// ----- Set the attributes
$p_header['compression'] = ord($v_data_header['cm']);
//$p_header['mtime'] = $v_data_header['mtime'];
$p_header['crc'] = $v_data_footer['crc'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Compressed size ".(filesize($v_gzip_temp_name)-18));
$p_header['compressed_size'] = filesize($v_gzip_temp_name)-18;
// ----- Close the file
@@ -3121,7 +2866,6 @@
// ----- Call the header generation
if (($v_result = $this->privWriteFileHeader($p_header)) != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -3129,19 +2873,15 @@
if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0)
{
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
fseek($v_file_compressed, 10);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File position before reading compressed data ".ftell($v_file_compressed));
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, ' '.$p_header['compressed_size'].' bytes to read');
$v_size = $p_header['compressed_size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read ".$v_read_size." bytes");
$v_buffer = @fread($v_file_compressed, $v_read_size);
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($this->zip_fd, $v_buffer, $v_read_size);
@@ -3153,9 +2893,8 @@
// ----- Unlink the temporary file
@unlink($v_gzip_temp_name);
-
+
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -3170,9 +2909,8 @@
// --------------------------------------------------------------------------------
function privCalculateStoredFilename(&$p_filedescr, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCalculateStoredFilename", "filename='".$p_filedescr['filename']."'");
$v_result=1;
-
+
// ----- Working variables
$p_filename = $p_filedescr['filename'];
if (isset($p_options[PCLZIP_OPT_ADD_PATH])) {
@@ -3187,7 +2925,6 @@
else {
$p_remove_dir = '';
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Remove path ='".$p_remove_dir."'");
if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) {
$p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH];
}
@@ -3195,13 +2932,13 @@
$p_remove_all_dir = 0;
}
+
// ----- Look for full name change
if (isset($p_filedescr['new_full_name'])) {
// ----- Remove drive letter if any
$v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Changing full name of '".$p_filename."' for '".$v_stored_filename."'");
}
-
+
// ----- Look for path and/or short name change
else {
@@ -3214,7 +2951,6 @@
$v_dir = $v_path_info['dirname'].'/';
}
$v_stored_filename = $v_dir.$p_filedescr['new_short_name'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Changing short name of '".$p_filename."' for '".$v_stored_filename."'");
}
else {
// ----- Calculate the stored filename
@@ -3224,17 +2960,15 @@
// ----- Look for all path to remove
if ($p_remove_all_dir) {
$v_stored_filename = basename($p_filename);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove all path selected change '".$p_filename."' for '".$v_stored_filename."'");
}
// ----- Look for partial path remove
else if ($p_remove_dir != "") {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Partial path to remove");
if (substr($p_remove_dir, -1) != '/')
$p_remove_dir .= "/";
if ( (substr($p_filename, 0, 2) == "./")
|| (substr($p_remove_dir, 0, 2) == "./")) {
-
+
if ( (substr($p_filename, 0, 2) == "./")
&& (substr($p_remove_dir, 0, 2) != "./")) {
$p_remove_dir = "./".$p_remove_dir;
@@ -3250,37 +2984,31 @@
if ($v_compare > 0) {
if ($v_compare == 2) {
$v_stored_filename = "";
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Path to remove is the current folder");
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Remove path '$p_remove_dir' in file '$v_stored_filename'");
$v_stored_filename = substr($v_stored_filename,
strlen($p_remove_dir));
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Result is '$v_stored_filename'");
}
}
}
-
+
// ----- Remove drive letter if any
$v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename);
-
+
// ----- Look for path to add
if ($p_add_dir != "") {
if (substr($p_add_dir, -1) == "/")
$v_stored_filename = $p_add_dir.$v_stored_filename;
else
$v_stored_filename = $p_add_dir."/".$v_stored_filename;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Add path '$p_add_dir' in file '$p_filename' = '$v_stored_filename'");
}
}
// ----- Filename (reduce the path of stored name)
$v_stored_filename = PclZipUtilPathReduction($v_stored_filename);
$p_filedescr['stored_filename'] = $v_stored_filename;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Stored filename will be '".$p_filedescr['stored_filename']."', strlen ".strlen($p_filedescr['stored_filename']));
-
+
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -3293,15 +3021,12 @@
// --------------------------------------------------------------------------------
function privWriteFileHeader(&$p_header)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
$v_result=1;
// ----- Store the offset position of the file
$p_header['offset'] = ftell($this->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'File offset of the header :'.$p_header['offset']);
// ----- Transform UNIX mtime to DOS format mdate/mtime
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
$v_date = getdate($p_header['mtime']);
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
@@ -3329,7 +3054,6 @@
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -3342,21 +3066,17 @@
// --------------------------------------------------------------------------------
function privWriteCentralFileHeader(&$p_header)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralFileHeader", 'file="'.$p_header['filename'].'", stored as "'.$p_header['stored_filename'].'"');
$v_result=1;
// TBC
//for(reset($p_header); $key = key($p_header); next($p_header)) {
- // //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "header[$key] = ".$p_header[$key]);
//}
// ----- Transform UNIX mtime to DOS format mdate/mtime
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
$v_date = getdate($p_header['mtime']);
$v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2;
$v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment size : \''.$p_header['comment_len'].'\'');
// ----- Packed data
$v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50,
@@ -3387,7 +3107,6 @@
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -3400,7 +3119,6 @@
// --------------------------------------------------------------------------------
function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privWriteCentralHeader", 'nb_entries='.$p_nb_entries.', size='.$p_size.', offset='.$p_offset.', comment="'.$p_comment.'"');
$v_result=1;
// ----- Packed data
@@ -3418,7 +3136,6 @@
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -3431,24 +3148,21 @@
// --------------------------------------------------------------------------------
function privList(&$p_list)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privList", "list");
$v_result=1;
// ----- Magic quotes trick
$this->privDisableMagicQuotes();
// ----- Open the zip file
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0)
{
// ----- Magic quotes trick
$this->privSwapBackMagicQuotes();
-
+
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -3457,15 +3171,11 @@
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Go to beginning of Central Dir
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Offset : ".$v_central_dir['offset']."'");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_central_dir['offset']))
{
$this->privSwapBackMagicQuotes();
@@ -3474,10 +3184,8 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position in file : ".ftell($this->zip_fd)."'");
// ----- Read each entry
for ($i=0; $i<$v_central_dir['entries']; $i++)
@@ -3486,7 +3194,6 @@
if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1)
{
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
$v_header['index'] = $i;
@@ -3503,7 +3210,6 @@
$this->privSwapBackMagicQuotes();
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -3529,7 +3235,6 @@
// --------------------------------------------------------------------------------
function privConvertHeader2FileInfo($p_header, &$p_info)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privConvertHeader2FileInfo", "Filename='".$p_header['filename']."'");
$v_result=1;
// ----- Get the interesting attributes
@@ -3547,7 +3252,6 @@
$p_info['crc'] = $p_header['crc'];
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -3570,7 +3274,6 @@
// --------------------------------------------------------------------------------
function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privExtractByRule", "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
$v_result=1;
// ----- Magic quotes trick
@@ -3589,9 +3292,7 @@
// ----- Look for the path end '/'
while (substr($p_path, -1) == "/")
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Destination path [$p_path] ends by '/'");
$p_path = substr($p_path, 0, strlen($p_path)-1);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Modified to [$p_path]");
}
}
@@ -3603,11 +3304,9 @@
$p_remove_path_size = strlen($p_remove_path);
// ----- Open the zip file
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_result = $this->privOpenFd('rb')) != 1)
{
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -3619,7 +3318,6 @@
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -3630,12 +3328,9 @@
$j_start = 0;
for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry : '$i'");
// ----- Read next Central dir entry
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position before rewind : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Position after rewind : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_pos_entry))
{
// ----- Close the zip file
@@ -3646,10 +3341,8 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Position after fseek : ".ftell($this->zip_fd)."'");
// ----- Read the file header
$v_header = array();
@@ -3659,7 +3352,6 @@
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -3675,49 +3367,43 @@
// ----- Look for extract by name rule
if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
&& ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
// ----- Look if the filename is in the list
for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Compare with file '".$p_options[PCLZIP_OPT_BY_NAME][$j]."'");
// ----- Look for a directory
if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The searched item is a directory");
// ----- Look if the directory is in the filename path
if ( (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
&& (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
$v_extract = true;
}
}
// ----- Look for a filename
elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
$v_extract = true;
}
}
}
// ----- Look for extract by ereg rule
+ // ereg() is deprecated with PHP 5.3
+ /*
else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
&& ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
$v_extract = true;
}
}
+ */
// ----- Look for extract by preg rule
else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
&& ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
$v_extract = true;
}
}
@@ -3725,23 +3411,18 @@
// ----- Look for extract by index rule
else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
&& ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
-
+
// ----- Look if the index is in the list
for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in [".$p_options[PCLZIP_OPT_BY_INDEX][$j]['start'].",".$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']."]");
if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
$v_extract = true;
}
if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
$j_start = $j+1;
}
if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
break;
}
}
@@ -3749,7 +3430,6 @@
// ----- Look for no rule, which means extract all the archive
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with no rule (extract all)");
$v_extract = true;
}
@@ -3757,35 +3437,30 @@
if ( ($v_extract)
&& ( ($v_header['compression'] != 8)
&& ($v_header['compression'] != 0))) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported compression method (".$v_header['compression'].")");
$v_header['status'] = 'unsupported_compression';
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
$this->privSwapBackMagicQuotes();
-
+
PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION,
"Filename '".$v_header['stored_filename']."' is "
."compressed by an unsupported compression "
."method (".$v_header['compression'].") ");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}
-
+
// ----- Check encrypted files
if (($v_extract) && (($v_header['flag'] & 1) == 1)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unsupported file encryption");
$v_header['status'] = 'unsupported_encryption';
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
$this->privSwapBackMagicQuotes();
@@ -3794,35 +3469,29 @@
." filename '".$v_header['stored_filename']
."'");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}
// ----- Look for real extraction
if (($v_extract) && ($v_header['status'] != 'ok')) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "No need for extract");
$v_result = $this->privConvertHeader2FileInfo($v_header,
$p_file_list[$v_nb_extracted++]);
if ($v_result != 1) {
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
$v_extract = false;
}
-
+
// ----- Look for real extraction
if ($v_extract)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file '".$v_header['filename']."', index '$i'");
// ----- Go to the file position
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_header['offset']))
{
// ----- Close the zip file
@@ -3834,20 +3503,19 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
// ----- Look for extraction as string
if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) {
+ $v_string = '';
+
// ----- Extracting the file
- $v_result1 = $this->privExtractFileAsString($v_header, $v_string);
+ $v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options);
if ($v_result1 < 1) {
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
return $v_result1;
}
@@ -3858,7 +3526,6 @@
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -3867,7 +3534,7 @@
// ----- Next extracted file
$v_nb_extracted++;
-
+
// ----- Look for user callback abort
if ($v_result1 == 2) {
break;
@@ -3881,7 +3548,6 @@
if ($v_result1 < 1) {
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
return $v_result1;
}
@@ -3889,7 +3555,6 @@
if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) {
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -3908,7 +3573,6 @@
if ($v_result1 < 1) {
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result1);
return $v_result1;
}
@@ -3919,7 +3583,6 @@
$this->privCloseFd();
$this->privSwapBackMagicQuotes();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -3936,7 +3599,6 @@
$this->privSwapBackMagicQuotes();
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -3952,18 +3614,15 @@
// --------------------------------------------------------------------------------
function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFile', "path='$p_path', remove_path='$p_remove_path', remove_all_path='".($p_remove_all_path?'true':'false')."'");
$v_result=1;
// ----- Read the file header
if (($v_result = $this->privReadFileHeader($v_header)) != 1)
{
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
// ----- Check that the file header is coherent with $p_entry info
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
@@ -3974,15 +3633,12 @@
if ($p_remove_all_path == true) {
// ----- Look for folder entry that not need to be extracted
if (($p_entry['external']&0x00000010)==0x00000010) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The entry is a folder : need to be filtered");
$p_entry['status'] = "filtered";
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "All path is removed");
// ----- Get the basename of the path
$p_entry['filename'] = basename($p_entry['filename']);
}
@@ -3990,28 +3646,23 @@
// ----- Look for path to remove
else if ($p_remove_path != "")
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look for some path to remove");
if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The folder is the same as the removed path '".$p_entry['filename']."'");
// ----- Change the file status
$p_entry['status'] = "filtered";
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
$p_remove_path_size = strlen($p_remove_path);
if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found path '$p_remove_path' to remove in file '".$p_entry['filename']."'");
// ----- Remove the path
$p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Resulting file is '".$p_entry['filename']."'");
}
}
@@ -4019,28 +3670,24 @@
if ($p_path != '') {
$p_entry['filename'] = $p_path."/".$p_entry['filename'];
}
-
+
// ----- Check a base_dir_restriction
if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Check the extract directory restriction");
$v_inclusion
= PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION],
- $p_entry['filename']);
+ $p_entry['filename']);
if ($v_inclusion == 0) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_EXTRACT_DIR_RESTRICTION is selected, file is outside restriction");
PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION,
"Filename '".$p_entry['filename']."' is "
."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}
// ----- Look for pre-extract callback
if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");
// ----- Generate a local information
$v_local_header = array();
@@ -4049,16 +3696,16 @@
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
- eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
+// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
+ $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
if ($v_result == 0) {
// ----- Change the file status
$p_entry['status'] = "skipped";
$v_result = 1;
}
-
+
// ----- Look for abort result
if ($v_result == 2) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
// ----- This status is internal and will be changed in 'skipped'
$p_entry['status'] = "aborted";
$v_result = PCLZIP_ERR_USER_ABORTED;
@@ -4067,10 +3714,8 @@
// ----- Update the informations
// Only some fields can be modified
$p_entry['filename'] = $v_local_header['filename'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'");
// ----- Look if extraction should be done
if ($p_entry['status'] == 'ok') {
@@ -4078,35 +3723,30 @@
// ----- Look for specific actions while the file exist
if (file_exists($p_entry['filename']))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$p_entry['filename']."' already exists");
// ----- Look if file is a directory
if (is_dir($p_entry['filename']))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is a directory");
// ----- Change the file status
$p_entry['status'] = "already_a_directory";
-
+
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
// For historical reason first PclZip implementation does not stop
// when this kind of error occurs.
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY,
"Filename '".$p_entry['filename']."' is "
."already used by an existing directory");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}
// ----- Look if file is write protected
else if (!is_writeable($p_entry['filename']))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is write protected");
// ----- Change the file status
$p_entry['status'] = "write_protected";
@@ -4116,13 +3756,11 @@
// when this kind of error occurs.
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
"Filename '".$p_entry['filename']."' exists "
."and is write protected");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}
@@ -4130,14 +3768,11 @@
// ----- Look if the extracted file is older
else if (filemtime($p_entry['filename']) > $p_entry['mtime'])
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is newer (".date("l dS of F Y h:i:s A", filemtime($p_entry['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $p_entry['mtime']).")");
// ----- Change the file status
if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER]))
&& ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_REPLACE_NEWER is selected, file will be replaced");
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File will not be replaced");
$p_entry['status'] = "newer_exist";
// ----- Look for PCLZIP_OPT_STOP_ON_ERROR
@@ -4145,19 +3780,16 @@
// when this kind of error occurs.
if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR]))
&& ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "PCLZIP_OPT_STOP_ON_ERROR is selected, extraction will be stopped");
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL,
"Newer version of '".$p_entry['filename']."' exists "
."and option PCLZIP_OPT_REPLACE_NEWER is not selected");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Existing file '".$p_entry['filename']."' is older than the extrated one - will be replaced by the extracted one (".date("l dS of F Y h:i:s A", filemtime($p_entry['filename'])).") than the extracted file (".date("l dS of F Y h:i:s A", $p_entry['mtime']).")");
}
}
@@ -4171,13 +3803,11 @@
$v_dir_to_check = dirname($p_entry['filename']);
if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to create path for '".$p_entry['filename']."'");
-
+
// ----- Change the file status
$p_entry['status'] = "path_creation_fail";
-
+
// ----- Return
- ////--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
//return $v_result;
$v_result = 1;
}
@@ -4192,35 +3822,30 @@
{
// ----- Look for not compressed file
if ($p_entry['compression'] == 0) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
// ----- Opening destination file
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
// ----- Change the file status
$p_entry['status'] = "write_error";
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read '".$p_entry['size']."' bytes");
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
$v_size = $p_entry['compressed_size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read $v_read_size bytes");
$v_buffer = @fread($this->zip_fd, $v_read_size);
/* Try to speed up the code
$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($v_dest_file, $v_binary_data, $v_read_size);
*/
- @fwrite($v_dest_file, $v_buffer, $v_read_size);
+ @fwrite($v_dest_file, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
}
@@ -4228,24 +3853,21 @@
fclose($v_dest_file);
// ----- Change the file mtime
- touch($p_entry['filename'], $p_entry['mtime']);
-
+ @touch($p_entry['filename'], $p_entry['mtime']);
+
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file (Compression method ".$p_entry['compression'].")");
// ----- TBC
// Need to be finished
if (($p_entry['flag'] & 1) == 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File is encrypted");
PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.');
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Look for using temporary file to unzip
- if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
+ if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF]))
&& (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON])
|| (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD])
&& ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) {
@@ -4254,47 +3876,42 @@
return $v_result;
}
}
-
+
// ----- Look for extract in memory
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read '".$p_entry['compressed_size']."' compressed bytes");
-
+
// ----- Read the compressed file in a buffer (one shot)
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
-
+
// ----- Decompress the file
$v_file_content = @gzinflate($v_buffer);
unset($v_buffer);
if ($v_file_content === FALSE) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to inflate compressed file");
-
+
// ----- Change the file status
// TBC
$p_entry['status'] = "error";
-
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+
return $v_result;
}
-
+
// ----- Opening destination file
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
-
+
// ----- Change the file status
$p_entry['status'] = "write_error";
-
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
+
return $v_result;
}
-
+
// ----- Write the uncompressed data
@fwrite($v_dest_file, $v_file_content, $p_entry['size']);
unset($v_file_content);
-
+
// ----- Closing the destination file
@fclose($v_dest_file);
-
+
}
// ----- Change the file mtime
@@ -4303,24 +3920,21 @@
// ----- Look for chmod option
if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "chmod option activated '".$p_options[PCLZIP_OPT_SET_CHMOD]."'");
// ----- Change the mode of the file
@chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]);
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
}
}
- // ----- Change abort status
- if ($p_entry['status'] == "aborted") {
- $p_entry['status'] = "skipped";
- }
-
+ // ----- Change abort status
+ if ($p_entry['status'] == "aborted") {
+ $p_entry['status'] = "skipped";
+ }
+
// ----- Look for post-extract callback
elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
// ----- Generate a local information
$v_local_header = array();
@@ -4329,17 +3943,16 @@
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
- eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
+// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
+ $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
// ----- Look for abort result
if ($v_result == 2) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
$v_result = PCLZIP_ERR_USER_ABORTED;
}
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -4352,19 +3965,16 @@
// --------------------------------------------------------------------------------
function privExtractFileUsingTempFile(&$p_entry, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileUsingTempFile', "filename='".$p_entry['filename']."'");
$v_result=1;
-
+
// ----- Creates a temporary file
$v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz';
if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) {
fclose($v_file);
PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode');
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Start extraction of '".$p_entry['filename']."'");
// ----- Write gz file format header
$v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3));
@@ -4372,11 +3982,9 @@
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
$v_size = $p_entry['compressed_size'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Compressed Size :".$v_size."");
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read ".$v_read_size." bytes");
$v_buffer = @fread($this->zip_fd, $v_read_size);
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($v_dest_file, $v_buffer, $v_read_size);
@@ -4392,9 +4000,7 @@
// ----- Opening destination file
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Error while opening '".$p_entry['filename']."' in write binary mode");
$p_entry['status'] = "write_error";
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -4403,19 +4009,14 @@
@fclose($v_dest_file);
$p_entry['status'] = "read_error";
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode');
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, 'File size is '.filesize($v_gzip_temp_name));
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
// ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks
$v_size = $p_entry['size'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size :".$v_size."");
while ($v_size != 0) {
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Read ".$v_read_size." bytes");
$v_buffer = @gzread($v_src_file, $v_read_size);
//$v_binary_data = pack('a'.$v_read_size, $v_buffer);
@fwrite($v_dest_file, $v_buffer, $v_read_size);
@@ -4426,9 +4027,8 @@
// ----- Delete the temporary file
@unlink($v_gzip_temp_name);
-
+
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -4441,16 +4041,13 @@
// --------------------------------------------------------------------------------
function privExtractFileInOutput(&$p_entry, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileInOutput', "");
$v_result=1;
// ----- Read the file header
if (($v_result = $this->privReadFileHeader($v_header)) != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
// ----- Check that the file header is coherent with $p_entry info
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
@@ -4459,7 +4056,6 @@
// ----- Look for pre-extract callback
if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A pre-callback '".$p_options[PCLZIP_CB_PRE_EXTRACT]."()') is defined for the extraction");
// ----- Generate a local information
$v_local_header = array();
@@ -4468,7 +4064,8 @@
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
- eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
+// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
+ $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
if ($v_result == 0) {
// ----- Change the file status
$p_entry['status'] = "skipped";
@@ -4477,7 +4074,6 @@
// ----- Look for abort result
if ($v_result == 2) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
// ----- This status is internal and will be changed in 'skipped'
$p_entry['status'] = "aborted";
$v_result = PCLZIP_ERR_USER_ABORTED;
@@ -4486,11 +4082,9 @@
// ----- Update the informations
// Only some fields can be modified
$p_entry['filename'] = $v_local_header['filename'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "New filename is '".$p_entry['filename']."'");
}
// ----- Trace
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file (with path) '".$p_entry['filename']."', size '$v_header[size]'");
// ----- Look if extraction should be done
if ($p_entry['status'] == 'ok') {
@@ -4499,8 +4093,6 @@
if (!(($p_entry['external']&0x00000010)==0x00000010)) {
// ----- Look for not compressed file
if ($p_entry['compressed_size'] == $p_entry['size']) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
// ----- Read the file in a buffer (one shot)
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
@@ -4510,12 +4102,10 @@
unset($v_buffer);
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Reading '".$p_entry['size']."' bytes");
// ----- Read the compressed file in a buffer (one shot)
$v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']);
-
+
// ----- Decompress the file
$v_file_content = gzinflate($v_buffer);
unset($v_buffer);
@@ -4524,7 +4114,6 @@
echo $v_file_content;
unset($v_file_content);
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
}
}
@@ -4535,7 +4124,6 @@
// ----- Look for post-extract callback
elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "A post-callback '".$p_options[PCLZIP_CB_POST_EXTRACT]."()') is defined for the extraction");
// ----- Generate a local information
$v_local_header = array();
@@ -4544,16 +4132,15 @@
// ----- Call the callback
// Here I do not use call_user_func() because I need to send a reference to the
// header.
- eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
+// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
+ $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
// ----- Look for abort result
if ($v_result == 2) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "User callback abort the extraction");
$v_result = PCLZIP_ERR_USER_ABORTED;
}
}
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -4564,9 +4151,8 @@
// Parameters :
// Return Values :
// --------------------------------------------------------------------------------
- function privExtractFileAsString(&$p_entry, &$p_string)
+ function privExtractFileAsString(&$p_entry, &$p_string, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privExtractFileAsString', "p_entry['filename']='".$p_entry['filename']."'");
$v_result=1;
// ----- Read the file header
@@ -4574,52 +4160,110 @@
if (($v_result = $this->privReadFileHeader($v_header)) != 1)
{
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found file '".$v_header['filename']."', size '".$v_header['size']."'");
// ----- Check that the file header is coherent with $p_entry info
if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) {
// TBC
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting file in string (with path) '".$p_entry['filename']."', size '$v_header[size]'");
+ // ----- Look for pre-extract callback
+ if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) {
- // ----- Do the extraction (if not a folder)
- if (!(($p_entry['external']&0x00000010)==0x00000010))
- {
- // ----- Look for not compressed file
-// if ($p_entry['compressed_size'] == $p_entry['size'])
- if ($p_entry['compression'] == 0) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting an un-compressed file");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Reading '".$p_entry['size']."' bytes");
-
- // ----- Reading the file
- $p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);');
+ $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header);
+ if ($v_result == 0) {
+ // ----- Change the file status
+ $p_entry['status'] = "skipped";
+ $v_result = 1;
}
- else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extracting a compressed file (compression method '".$p_entry['compression']."')");
-
- // ----- Reading the file
- $v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
-
- // ----- Decompress the file
- if (($p_string = @gzinflate($v_data)) === FALSE) {
- // TBC
+
+ // ----- Look for abort result
+ if ($v_result == 2) {
+ // ----- This status is internal and will be changed in 'skipped'
+ $p_entry['status'] = "aborted";
+ $v_result = PCLZIP_ERR_USER_ABORTED;
+ }
+
+ // ----- Update the informations
+ // Only some fields can be modified
+ $p_entry['filename'] = $v_local_header['filename'];
+ }
+
+
+ // ----- Look if extraction should be done
+ if ($p_entry['status'] == 'ok') {
+
+ // ----- Do the extraction (if not a folder)
+ if (!(($p_entry['external']&0x00000010)==0x00000010)) {
+ // ----- Look for not compressed file
+ // if ($p_entry['compressed_size'] == $p_entry['size'])
+ if ($p_entry['compression'] == 0) {
+
+ // ----- Reading the file
+ $p_string = @fread($this->zip_fd, $p_entry['compressed_size']);
+ }
+ else {
+
+ // ----- Reading the file
+ $v_data = @fread($this->zip_fd, $p_entry['compressed_size']);
+
+ // ----- Decompress the file
+ if (($p_string = @gzinflate($v_data)) === FALSE) {
+ // TBC
+ }
}
+
+ // ----- Trace
+ }
+ else {
+ // TBC : error : can not extract a folder in a string
}
- // ----- Trace
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Extraction done");
}
- else {
- // TBC : error : can not extract a folder in a string
+
+ // ----- Change abort status
+ if ($p_entry['status'] == "aborted") {
+ $p_entry['status'] = "skipped";
+ }
+
+ // ----- Look for post-extract callback
+ elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) {
+
+ // ----- Generate a local information
+ $v_local_header = array();
+ $this->privConvertHeader2FileInfo($p_entry, $v_local_header);
+
+ // ----- Swap the content to header
+ $v_local_header['content'] = $p_string;
+ $p_string = '';
+
+ // ----- Call the callback
+ // Here I do not use call_user_func() because I need to send a reference to the
+ // header.
+// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);');
+ $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header);
+
+ // ----- Swap back the content to header
+ $p_string = $v_local_header['content'];
+ unset($v_local_header['content']);
+
+ // ----- Look for abort result
+ if ($v_result == 2) {
+ $v_result = PCLZIP_ERR_USER_ABORTED;
+ }
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -4632,25 +4276,20 @@
// --------------------------------------------------------------------------------
function privReadFileHeader(&$p_header)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadFileHeader", "");
$v_result=1;
// ----- Read the 4 bytes signature
$v_binary_data = @fread($this->zip_fd, 4);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
$v_data = unpack('Vid', $v_binary_data);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
// ----- Check signature
if ($v_data['id'] != 0x04034b50)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid File header");
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -4662,53 +4301,36 @@
{
$p_header['filename'] = "";
$p_header['status'] = "invalid_header";
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Extract the values
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header : '".$v_binary_data."'");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Header (Hex) : '".bin2hex($v_binary_data)."'");
$v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data);
// ----- Get filename
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "File name length : ".$v_data['filename_len']);
$p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename : \''.$p_header['filename'].'\'');
// ----- Get extra_fields
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extra field length : ".$v_data['extra_len']);
if ($v_data['extra_len'] != 0) {
$p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']);
}
else {
$p_header['extra'] = '';
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Extra field : \''.bin2hex($p_header['extra']).'\'');
// ----- Extract properties
$p_header['version_extracted'] = $v_data['version'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : ('.$p_header['version_extracted'].') \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\'');
$p_header['compression'] = $v_data['compression'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compression method : \''.$p_header['compression'].'\'');
$p_header['size'] = $v_data['size'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_header['size'].'\'');
$p_header['compressed_size'] = $v_data['compressed_size'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
$p_header['crc'] = $v_data['crc'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\'');
$p_header['flag'] = $v_data['flag'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag : \''.$p_header['flag'].'\'');
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag bit 11 (from right) : \''.($p_header['flag']&0x0400).'\'');
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Flag bit 11 (from left) : \''.($p_header['flag']&0x0020).'\'');
$p_header['filename_len'] = $v_data['filename_len'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Filename_len : \''.$p_header['filename_len'].'\'');
// ----- Recuperate date in UNIX format
$p_header['mdate'] = $v_data['mdate'];
@@ -4728,17 +4350,14 @@
// ----- Get UNIX date format
$p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
}
else
{
$p_header['mtime'] = time();
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
}
// TBC
//for(reset($v_data); $key = key($v_data); next($v_data)) {
- // //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Attribut[$key] = ".$v_data[$key]);
//}
// ----- Set the stored filename
@@ -4748,7 +4367,6 @@
$p_header['status'] = "ok";
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -4761,25 +4379,20 @@
// --------------------------------------------------------------------------------
function privReadCentralFileHeader(&$p_header)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadCentralFileHeader", "");
$v_result=1;
// ----- Read the 4 bytes signature
$v_binary_data = @fread($this->zip_fd, 4);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
$v_data = unpack('Vid', $v_binary_data);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
// ----- Check signature
if ($v_data['id'] != 0x02014b50)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid Central Dir File signature");
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -4791,53 +4404,36 @@
{
$p_header['filename'] = "";
$p_header['status'] = "invalid_header";
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid block size : ".strlen($v_binary_data));
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data));
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Extract the values
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header : '".$v_binary_data."'");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Header (Hex) : '".bin2hex($v_binary_data)."'");
$p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data);
// ----- Get filename
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "File name length : ".$p_header['filename_len']);
if ($p_header['filename_len'] != 0)
$p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']);
else
$p_header['filename'] = '';
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Filename : \''.$p_header['filename'].'\'');
// ----- Get extra
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Extra length : ".$p_header['extra_len']);
if ($p_header['extra_len'] != 0)
$p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']);
else
$p_header['extra'] = '';
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Extra : \''.$p_header['extra'].'\'');
// ----- Get comment
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Comment length : ".$p_header['comment_len']);
if ($p_header['comment_len'] != 0)
$p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']);
else
$p_header['comment'] = '';
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Comment : \''.$p_header['comment'].'\'');
// ----- Extract properties
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version : \''.($p_header['version']/10).'.'.($p_header['version']%10).'\'');
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Version need to extract : \''.($p_header['version_extracted']/10).'.'.($p_header['version_extracted']%10).'\'');
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Size : \''.$p_header['size'].'\'');
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Compressed Size : \''.$p_header['compressed_size'].'\'');
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'CRC : \''.sprintf("0x%X", $p_header['crc']).'\'');
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Flag : \''.$p_header['flag'].'\'');
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Offset : \''.$p_header['offset'].'\'');
// ----- Recuperate date in UNIX format
//if ($p_header['mdate'] && $p_header['mtime'])
@@ -4857,12 +4453,10 @@
// ----- Get UNIX date format
$p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
}
else
{
$p_header['mtime'] = time();
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Date is actual : \''.date("d/m/y H:i:s", $p_header['mtime']).'\'');
}
// ----- Set the stored filename
@@ -4872,18 +4466,13 @@
$p_header['status'] = 'ok';
// ----- Look if it is a directory
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Internal (Hex) : '".sprintf("Ox%04X", $p_header['internal'])."'");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "External (Hex) : '".sprintf("Ox%04X", $p_header['external'])."' (".(($p_header['external']&0x00000010)==0x00000010?'is a folder':'is a file').')');
if (substr($p_header['filename'], -1) == '/') {
//$p_header['external'] = 0x41FF0010;
$p_header['external'] = 0x00000010;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Force folder external : \''.sprintf("Ox%04X", $p_header['external']).'\'');
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Header of filename : \''.$p_header['filename'].'\'');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -4898,44 +4487,31 @@
// --------------------------------------------------------------------------------
function privCheckFileHeaders(&$p_local_header, &$p_central_header)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privCheckFileHeaders", "");
$v_result=1;
// ----- Check the static values
// TBC
if ($p_local_header['filename'] != $p_central_header['filename']) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename" : TBC To Be Completed');
}
if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "version_extracted" : TBC To Be Completed');
}
if ($p_local_header['flag'] != $p_central_header['flag']) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "flag" : TBC To Be Completed');
}
if ($p_local_header['compression'] != $p_central_header['compression']) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "compression" : TBC To Be Completed');
}
if ($p_local_header['mtime'] != $p_central_header['mtime']) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "mtime" : TBC To Be Completed');
}
if ($p_local_header['filename_len'] != $p_central_header['filename_len']) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Bad check "filename_len" : TBC To Be Completed');
}
-
+
// ----- Look for flag bit 3
if (($p_local_header['flag'] & 8) == 8) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Purpose bit flag bit 3 set !');
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'File size, compression size and crc found in central header');
$p_local_header['size'] = $p_central_header['size'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size : \''.$p_local_header['size'].'\'');
$p_local_header['compressed_size'] = $p_central_header['compressed_size'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Compressed Size : \''.$p_local_header['compressed_size'].'\'');
$p_local_header['crc'] = $p_central_header['crc'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'CRC : \''.sprintf("0x%X", $p_local_header['crc']).'\'');
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -4948,21 +4524,17 @@
// --------------------------------------------------------------------------------
function privReadEndCentralDir(&$p_central_dir)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privReadEndCentralDir", "");
$v_result=1;
// ----- Go to the end of the zip file
$v_size = filesize($this->zipname);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Size of the file :$v_size");
@fseek($this->zip_fd, $v_size);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position at end of zip file : \''.ftell($this->zip_fd).'\'');
if (@ftell($this->zip_fd) != $v_size)
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\'');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -4970,28 +4542,22 @@
// in this case the end of central dir is at 22 bytes of the file end
$v_found = 0;
if ($v_size > 26) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Look for central dir with no comment');
@fseek($this->zip_fd, $v_size-22);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after min central position : \''.ftell($this->zip_fd).'\'');
if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22))
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Read for bytes
$v_binary_data = @fread($this->zip_fd, 4);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Binary data is : '".sprintf("%08x", $v_binary_data)."'");
$v_data = @unpack('Vid', $v_binary_data);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Binary signature is : '".sprintf("0x%08x", $v_data['id'])."'");
// ----- Check signature
if ($v_data['id'] == 0x06054b50) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Found central dir at the default position.");
$v_found = 1;
}
@@ -5000,7 +4566,6 @@
// ----- Go back to the maximum possible size of the Central Dir End Record
if (!$v_found) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Start extended search of end central dir');
$v_maximum_size = 65557; // 0xFFFF + 22;
if ($v_maximum_size > $v_size)
$v_maximum_size = $v_size;
@@ -5011,10 +4576,8 @@
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\'');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Position after max central position : \''.ftell($this->zip_fd).'\'');
// ----- Read byte per byte in order to find the signature
$v_pos = ftell($this->zip_fd);
@@ -5025,12 +4588,14 @@
$v_byte = @fread($this->zip_fd, 1);
// ----- Add the byte
- $v_bytes = ($v_bytes << 8) | Ord($v_byte);
+ //$v_bytes = ($v_bytes << 8) | Ord($v_byte);
+ // Note we mask the old value down such that once shifted we can never end up with more than a 32bit number
+ // Otherwise on systems where we have 64bit integers the check below for the magic number will fail.
+ $v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte);
// ----- Compare the bytes
if ($v_bytes == 0x504b0506)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, 'Found End Central Dir signature at position : \''.ftell($this->zip_fd).'\'');
$v_pos++;
break;
}
@@ -5041,13 +4606,11 @@
// ----- Look if not found end of central dir
if ($v_pos == $v_size)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Unable to find End of Central Dir Record signature");
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}
@@ -5058,25 +4621,19 @@
// ----- Look for invalid block size
if (strlen($v_binary_data) != 18)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data));
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Extract the values
- ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record : '".$v_binary_data."'");
- ////--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Central Dir Record (Hex) : '".bin2hex($v_binary_data)."'");
$v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data);
// ----- Check the global size
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Comment length : ".$v_data['comment_size']);
if (($v_pos + $v_data['comment_size'] + 18) != $v_size) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "The central dir is not at the end of the archive. Some trailing bytes exists after the archive.");
// ----- Removed in release 2.2 see readme file
// The check of the file size is a little too strict.
@@ -5089,40 +4646,29 @@
.' Some trailing bytes exists after the archive.');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
}
// ----- Get comment
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment size : \''.$v_data['comment_size'].'\'');
if ($v_data['comment_size'] != 0) {
$p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']);
}
else
$p_central_dir['comment'] = '';
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Comment : \''.$p_central_dir['comment'].'\'');
$p_central_dir['entries'] = $v_data['entries'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries : \''.$p_central_dir['entries'].'\'');
$p_central_dir['disk_entries'] = $v_data['disk_entries'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Nb of entries for this disk : \''.$p_central_dir['disk_entries'].'\'');
$p_central_dir['offset'] = $v_data['offset'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Offset of Central Dir : \''.$p_central_dir['offset'].'\'');
$p_central_dir['size'] = $v_data['size'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Size of Central Dir : \''.$p_central_dir['size'].'\'');
$p_central_dir['disk'] = $v_data['disk'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Disk number : \''.$p_central_dir['disk'].'\'');
$p_central_dir['disk_start'] = $v_data['disk_start'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, 'Start disk number : \''.$p_central_dir['disk_start'].'\'');
// TBC
//for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) {
- // //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "central_dir[$key] = ".$p_central_dir[$key]);
//}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -5135,16 +4681,13 @@
// --------------------------------------------------------------------------------
function privDeleteByRule(&$p_result_list, &$p_options)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDeleteByRule", "");
$v_result=1;
$v_list_detail = array();
// ----- Open the zip file
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_result=$this->privOpenFd('rb')) != 1)
{
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -5153,21 +4696,16 @@
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privCloseFd();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Go to beginning of File
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in file : ".ftell($this->zip_fd)."'");
// ----- Scan all the files
// ----- Start at beginning of Central Dir
$v_pos_entry = $v_central_dir['offset'];
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_pos_entry))
{
// ----- Close the zip file
@@ -5177,17 +4715,14 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
// ----- Read each entry
$v_header_list = array();
$j_start = 0;
for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Read next file header entry (index '$i')");
// ----- Read the file header
$v_header_list[$v_nb_extracted] = array();
@@ -5196,11 +4731,9 @@
// ----- Close the zip file
$this->privCloseFd();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename (index '$i') : '".$v_header_list[$v_nb_extracted]['stored_filename']."'");
// ----- Store the index
$v_header_list[$v_nb_extracted]['index'] = $i;
@@ -5211,54 +4744,47 @@
// ----- Look for extract by name rule
if ( (isset($p_options[PCLZIP_OPT_BY_NAME]))
&& ($p_options[PCLZIP_OPT_BY_NAME] != 0)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByName'");
// ----- Look if the filename is in the list
for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Compare with file '".$p_options[PCLZIP_OPT_BY_NAME][$j]."'");
// ----- Look for a directory
if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The searched item is a directory");
// ----- Look if the directory is in the filename path
if ( (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j]))
&& (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The directory is in the file path");
$v_found = true;
}
elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */
&& ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The entry is the searched directory");
$v_found = true;
}
}
// ----- Look for a filename
elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "The file is the right one.");
$v_found = true;
}
}
}
// ----- Look for extract by ereg rule
+ // ereg() is deprecated with PHP 5.3
+ /*
else if ( (isset($p_options[PCLZIP_OPT_BY_EREG]))
&& ($p_options[PCLZIP_OPT_BY_EREG] != "")) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract by ereg '".$p_options[PCLZIP_OPT_BY_EREG]."'");
if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
$v_found = true;
}
}
+ */
// ----- Look for extract by preg rule
else if ( (isset($p_options[PCLZIP_OPT_BY_PREG]))
&& ($p_options[PCLZIP_OPT_BY_PREG] != "")) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByEreg'");
if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Filename match the regular expression");
$v_found = true;
}
}
@@ -5266,41 +4792,33 @@
// ----- Look for extract by index rule
else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX]))
&& ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Extract with rule 'ByIndex'");
// ----- Look if the index is in the list
for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Look if index '$i' is in [".$p_options[PCLZIP_OPT_BY_INDEX][$j]['start'].",".$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']."]");
if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Found as part of an index range");
$v_found = true;
}
if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Do not look this index range for next loop");
$j_start = $j+1;
}
if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Index range is greater than index, stop loop");
break;
}
}
}
else {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "No argument mean remove all file");
$v_found = true;
}
// ----- Look for deletion
if ($v_found)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' need to be deleted");
unset($v_header_list[$v_nb_extracted]);
}
else
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 2, "File '".$v_header_list[$v_nb_extracted]['stored_filename']."', index '$i' will not be deleted");
$v_nb_extracted++;
}
}
@@ -5315,24 +4833,18 @@
$v_temp_zip = new PclZip($v_zip_temp_name);
// ----- Open the temporary zip file in write mode
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary write mode");
if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) {
$this->privCloseFd();
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Look which file need to be kept
for ($i=0; $i<sizeof($v_header_list); $i++) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Keep entry index '$i' : '".$v_header_list[$i]['filename']."'");
// ----- Calculate the position of the header
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset='". $v_header_list[$i]['offset']."'");
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position before rewind : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after rewind : ".ftell($this->zip_fd)."'");
if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) {
// ----- Close the zip file
$this->privCloseFd();
@@ -5343,10 +4855,8 @@
PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position after fseek : ".ftell($this->zip_fd)."'");
// ----- Read the file header
$v_local_header = array();
@@ -5357,10 +4867,9 @@
@unlink($v_zip_temp_name);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
-
+
// ----- Check that local file header is same as central file header
if ($this->privCheckFileHeaders($v_local_header,
$v_header_list[$i]) != 1) {
@@ -5376,10 +4885,8 @@
@unlink($v_zip_temp_name);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset for this file is '".$v_header_list[$i]['offset']."'");
// ----- Read/write the data block
if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) {
@@ -5389,27 +4896,22 @@
@unlink($v_zip_temp_name);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
}
// ----- Store the offset of the central dir
$v_offset = @ftell($v_temp_zip->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "New offset of central dir : $v_offset");
// ----- Re-Create the Central Dir files header
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the new central directory");
for ($i=0; $i<sizeof($v_header_list); $i++) {
// ----- Create the file header
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Offset of file : ".$v_header_list[$i]['offset']);
if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) {
$v_temp_zip->privCloseFd();
$this->privCloseFd();
@unlink($v_zip_temp_name);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -5417,7 +4919,6 @@
$v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]);
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Creates the central directory footer");
// ----- Zip file comment
$v_comment = '';
@@ -5437,7 +4938,6 @@
@unlink($v_zip_temp_name);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -5453,22 +4953,20 @@
// TBC : I should test the result ...
//@rename($v_zip_temp_name, $this->zipname);
PclZipUtilRename($v_zip_temp_name, $this->zipname);
-
+
// ----- Destroy the temporary archive
unset($v_temp_zip);
}
-
+
// ----- Remove every files : reset the file
else if ($v_central_dir['entries'] != 0) {
$this->privCloseFd();
if (($v_result = $this->privOpenFd('wb')) != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -5476,7 +4974,6 @@
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -5496,25 +4993,21 @@
{
$v_result = 1;
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDirCheck", "entry='$p_dir', is_dir='".($p_is_dir?"true":"false")."'");
// ----- Remove the final '/'
if (($p_is_dir) && (substr($p_dir, -1)=='/'))
{
$p_dir = substr($p_dir, 0, strlen($p_dir)-1);
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Looking for entry '$p_dir'");
// ----- Check the directory availability
if ((is_dir($p_dir)) || ($p_dir == ""))
{
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, "'$p_dir' is a directory");
return 1;
}
// ----- Extract parent directory
$p_parent_dir = dirname($p_dir);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Parent directory is '$p_parent_dir'");
// ----- Just a check
if ($p_parent_dir != $p_dir)
@@ -5524,26 +5017,22 @@
{
if (($v_result = $this->privDirCheck($p_parent_dir)) != 1)
{
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
}
}
// ----- Create the directory
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Create directory '$p_dir'");
if (!@mkdir($p_dir, 0777))
{
// ----- Error log
PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'");
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result, "Directory '$p_dir' created");
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -5557,41 +5046,34 @@
// --------------------------------------------------------------------------------
function privMerge(&$p_archive_to_add)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privMerge", "archive='".$p_archive_to_add->zipname."'");
$v_result=1;
// ----- Look if the archive_to_add exists
if (!is_file($p_archive_to_add->zipname))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to add does not exist. End of merge.");
// ----- Nothing to merge, so merge is a success
$v_result = 1;
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Look if the archive exists
if (!is_file($this->zipname))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive does not exist, duplicate the archive_to_add.");
// ----- Do a duplicate
$v_result = $this->privDuplicate($p_archive_to_add->zipname);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Open the zip file
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_result=$this->privOpenFd('rb')) != 1)
{
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -5600,23 +5082,18 @@
if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1)
{
$this->privCloseFd();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Go to beginning of File
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
@rewind($this->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in zip : ".ftell($this->zip_fd)."'");
// ----- Open the archive_to_add file
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open archive_to_add in binary read mode");
if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1)
{
$this->privCloseFd();
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -5627,20 +5104,16 @@
$this->privCloseFd();
$p_archive_to_add->privCloseFd();
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Go to beginning of File
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
@rewind($p_archive_to_add->zip_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Position in archive_to_add : ".ftell($p_archive_to_add->zip_fd)."'");
// ----- Creates a temporay file
$v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp';
// ----- Open the temporary file in write mode
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0)
{
$this->privCloseFd();
@@ -5649,7 +5122,6 @@
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -5659,7 +5131,6 @@
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = fread($this->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
@@ -5670,7 +5141,6 @@
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
@@ -5678,14 +5148,12 @@
// ----- Store the offset of the central dir
$v_offset = @ftell($v_zip_temp_fd);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "New offset of central dir : $v_offset");
// ----- Copy the block of file headers from the old archive
$v_size = $v_central_dir['size'];
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @fread($this->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
@@ -5696,7 +5164,6 @@
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size);
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
@@ -5727,7 +5194,6 @@
unset($v_header_list);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
@@ -5753,7 +5219,6 @@
PclZipUtilRename($v_zip_temp_name, $this->zipname);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -5766,33 +5231,27 @@
// --------------------------------------------------------------------------------
function privDuplicate($p_archive_filename)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZip::privDuplicate", "archive_filename='$p_archive_filename'");
$v_result=1;
// ----- Look if the $p_archive_filename exists
if (!is_file($p_archive_filename))
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Archive to duplicate does not exist. End of duplicate.");
// ----- Nothing to duplicate, so duplicate is a success.
$v_result = 1;
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Open the zip file
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_result=$this->privOpenFd('wb')) != 1)
{
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Open the temporary file in write mode
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Open file in binary read mode");
if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0)
{
$this->privCloseFd();
@@ -5800,7 +5259,6 @@
PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode');
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, PclZip::errorCode(), PclZip::errorInfo());
return PclZip::errorCode();
}
@@ -5810,7 +5268,6 @@
while ($v_size != 0)
{
$v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Read $v_read_size bytes");
$v_buffer = fread($v_zip_temp_fd, $v_read_size);
@fwrite($this->zip_fd, $v_buffer, $v_read_size);
$v_size -= $v_read_size;
@@ -5823,7 +5280,6 @@
@fclose($v_zip_temp_fd);
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -5870,36 +5326,28 @@
// --------------------------------------------------------------------------------
function privDisableMagicQuotes()
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privDisableMagicQuotes', "");
$v_result=1;
// ----- Look if function exists
if ( (!function_exists("get_magic_quotes_runtime"))
|| (!function_exists("set_magic_quotes_runtime"))) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Functions *et_magic_quotes_runtime are not supported");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Look if already done
if ($this->magic_quotes_status != -1) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "magic_quote already disabled");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Get and memorize the magic_quote value
$this->magic_quotes_status = @get_magic_quotes_runtime();
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Current magic_quotes_runtime status is '".($this->magic_quotes_status==0?'disable':'enable')."'");
// ----- Disable magic_quotes
if ($this->magic_quotes_status == 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Disable magic_quotes");
@set_magic_quotes_runtime(0);
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -5912,32 +5360,25 @@
// --------------------------------------------------------------------------------
function privSwapBackMagicQuotes()
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, 'PclZip::privSwapBackMagicQuotes', "");
$v_result=1;
// ----- Look if function exists
if ( (!function_exists("get_magic_quotes_runtime"))
|| (!function_exists("set_magic_quotes_runtime"))) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Functions *et_magic_quotes_runtime are not supported");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Look if something to do
if ($this->magic_quotes_status != -1) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "magic_quote not modified");
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// ----- Swap back magic_quotes
if ($this->magic_quotes_status == 1) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Enable back magic_quotes");
@set_magic_quotes_runtime($this->magic_quotes_status);
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -5954,7 +5395,6 @@
// --------------------------------------------------------------------------------
function PclZipUtilPathReduction($p_dir)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathReduction", "dir='$p_dir'");
$v_result = "";
// ----- Look for not empty path
@@ -5981,7 +5421,6 @@
// ----- It is an invalid path, so the path is not modified
// TBC
$v_result = $p_dir;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 3, "Invalid path is unchanged");
$v_skip = 0;
}
}
@@ -6005,7 +5444,7 @@
}
}
}
-
+
// ----- Look for skip
if ($v_skip > 0) {
while ($v_skip > 0) {
@@ -6016,7 +5455,6 @@
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -6038,19 +5476,16 @@
// --------------------------------------------------------------------------------
function PclZipUtilPathInclusion($p_dir, $p_path)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilPathInclusion", "dir='$p_dir', path='$p_path'");
$v_result = 1;
-
+
// ----- Look for path beginning by ./
if ( ($p_dir == '.')
|| ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) {
$p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Replacing ./ by full path in p_dir '".$p_dir."'");
}
if ( ($p_path == '.')
|| ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) {
$p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Replacing ./ by full path in p_path '".$p_path."'");
}
// ----- Explode dir and path by directory separator
@@ -6063,7 +5498,6 @@
$i = 0;
$j = 0;
while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Working on dir($i)='".$v_list_dir[$i]."' and path($j)='".$v_list_path[$j]."'");
// ----- Look for empty dir (path reduction)
if ($v_list_dir[$i] == '') {
@@ -6077,7 +5511,6 @@
// ----- Compare the items
if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Items ($i,$j) are different");
$v_result = 0;
}
@@ -6088,11 +5521,9 @@
// ----- Look if everything seems to be the same
if ($v_result) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Look for tie break");
// ----- Skip all the empty items
while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++;
while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++;
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Looking on dir($i)='".($i < $v_list_dir_size?$v_list_dir[$i]:'')."' and path($j)='".($j < $v_list_path_size?$v_list_path[$j]:'')."'");
if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) {
// ----- There are exactly the same
@@ -6105,7 +5536,6 @@
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -6123,30 +5553,23 @@
// --------------------------------------------------------------------------------
function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilCopyBlock", "size=$p_size, mode=$p_mode");
$v_result = 1;
if ($p_mode==0)
{
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset before read :".(@ftell($p_src)));
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset before write :".(@ftell($p_dest)));
while ($p_size != 0)
{
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @fread($p_src, $v_read_size);
@fwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
}
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Src offset after read :".(@ftell($p_src)));
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Dest offset after write :".(@ftell($p_dest)));
}
else if ($p_mode==1)
{
while ($p_size != 0)
{
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @gzread($p_src, $v_read_size);
@fwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
@@ -6157,7 +5580,6 @@
while ($p_size != 0)
{
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @fread($p_src, $v_read_size);
@gzwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
@@ -6168,7 +5590,6 @@
while ($p_size != 0)
{
$v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE);
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 4, "Read $v_read_size bytes");
$v_buffer = @gzread($p_src, $v_read_size);
@gzwrite($p_dest, $v_buffer, $v_read_size);
$p_size -= $v_read_size;
@@ -6176,7 +5597,6 @@
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -6195,26 +5615,21 @@
// --------------------------------------------------------------------------------
function PclZipUtilRename($p_src, $p_dest)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilRename", "source=$p_src, destination=$p_dest");
$v_result = 1;
// ----- Try to rename the files
if (!@rename($p_src, $p_dest)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to rename file, try copy+unlink");
// ----- Try to copy & unlink the src
if (!@copy($p_src, $p_dest)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to copy file");
$v_result = 0;
}
else if (!@unlink($p_src)) {
- //--(MAGIC-PclTrace)--//PclTraceFctMessage(__FILE__, __LINE__, 5, "Fail to unlink old filename");
$v_result = 0;
}
}
// ----- Return
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
@@ -6230,8 +5645,7 @@
// --------------------------------------------------------------------------------
function PclZipUtilOptionText($p_option)
{
- //--(MAGIC-PclTrace)--//PclTraceFctStart(__FILE__, __LINE__, "PclZipUtilOptionText", "option='".$p_option."'");
-
+
$v_list = get_defined_constants();
for (reset($v_list); $v_key = key($v_list); next($v_list)) {
$v_prefix = substr($v_key, 0, 10);
@@ -6239,14 +5653,12 @@
|| ($v_prefix == 'PCLZIP_CB_')
|| ($v_prefix == 'PCLZIP_ATT'))
&& ($v_list[$v_key] == $p_option)) {
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_key);
return $v_key;
}
}
-
+
$v_result = 'Unknown';
- //--(MAGIC-PclTrace)--//PclTraceFctEnd(__FILE__, __LINE__, $v_result);
return $v_result;
}
// --------------------------------------------------------------------------------
diff --git a/libs/Smarty/Config_File.class.php b/libs/Smarty/Config_File.class.php
index 232db70043..ae0c3be315 100644
--- a/libs/Smarty/Config_File.class.php
+++ b/libs/Smarty/Config_File.class.php
@@ -22,7 +22,7 @@
* smarty-discussion-subscribe@googlegroups.com
*
* @link http://www.smarty.net/
- * @version 2.6.25
+ * @version 2.6.26
* @copyright Copyright: 2001-2005 New Digital Group, Inc.
* @author Andrei Zmievski <andrei@php.net>
* @access public
diff --git a/libs/Smarty/Smarty.class.php b/libs/Smarty/Smarty.class.php
index ea9a70de09..a3e2ed8a0f 100644
--- a/libs/Smarty/Smarty.class.php
+++ b/libs/Smarty/Smarty.class.php
@@ -27,7 +27,7 @@
* @author Monte Ohrt <monte at ohrt dot com>
* @author Andrei Zmievski <andrei@php.net>
* @package Smarty
- * @version 2.6.25
+ * @version 2.6.26
*/
/* $Id$ */
@@ -465,7 +465,7 @@ class Smarty
*
* @var string
*/
- var $_version = '2.6.25';
+ var $_version = '2.6.26';
/**
* current template inclusion depth
@@ -562,14 +562,6 @@ class Smarty
*/
var $_cache_including = false;
- /**
- * array of super globals internally
- *
- * @var array
- */
- var $_supers = array();
-
-
/**#@-*/
/**
* The class constructor.
@@ -578,18 +570,6 @@ class Smarty
{
$this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME']
: @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']);
-
- $this->_supers['get'] = $this->request_use_auto_globals ? $_GET : $GLOBALS['HTTP_GET_VARS'];
- $this->_supers['post'] = $this->request_use_auto_globals ? $_POST : $GLOBALS['HTTP_POST_VARS'];
- $this->_supers['server'] = $this->request_use_auto_globals ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
- if(isset($_SESSION))
- $this->_supers['session'] = $this->request_use_auto_globals ? $_SESSION : $GLOBALS['HTTP_SESSION_VARS'];
- else
- $this->_supers['session'] = array();
- $this->_supers['request'] = $this->request_use_auto_globals ? $_REQUEST : $GLOBALS['HTTP_REQUEST_VARS'];
- $this->_supers['cookies'] = $this->request_use_auto_globals ? $_COOKIE : $GLOBALS['HTTP_COOKIE_VARS'];
- $this->_supers['env'] = $this->request_use_auto_globals ? $_ENV : $GLOBALS['HTTP_ENV_VARS'];
-
}
/**
diff --git a/libs/Smarty/Smarty_Compiler.class.php b/libs/Smarty/Smarty_Compiler.class.php
index 2a1fb8630a..f6a278d4a4 100644
--- a/libs/Smarty/Smarty_Compiler.class.php
+++ b/libs/Smarty/Smarty_Compiler.class.php
@@ -21,7 +21,7 @@
* @link http://smarty.php.net/
* @author Monte Ohrt <monte at ohrt dot com>
* @author Andrei Zmievski <andrei@php.net>
- * @version 2.6.25
+ * @version 2.6.26
* @copyright 2001-2005 New Digital Group, Inc.
* @package Smarty
*/
@@ -2047,27 +2047,57 @@ class Smarty_Compiler extends Smarty {
break;
case 'get':
- $compiled_ref = "\$this->_supers['get']";
+ if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
+ $this->_syntax_error("(secure mode) super global access not permitted",
+ E_USER_WARNING, __FILE__, __LINE__);
+ return;
+ }
+ $compiled_ref = "\$_GET";
break;
case 'post':
- $compiled_ref = "\$this->_supers['post']";
+ if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
+ $this->_syntax_error("(secure mode) super global access not permitted",
+ E_USER_WARNING, __FILE__, __LINE__);
+ return;
+ }
+ $compiled_ref = "\$_POST";
break;
case 'cookies':
- $compiled_ref = "\$this->_supers['cookies']";
+ if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
+ $this->_syntax_error("(secure mode) super global access not permitted",
+ E_USER_WARNING, __FILE__, __LINE__);
+ return;
+ }
+ $compiled_ref = "\$_COOKIE";
break;
case 'env':
- $compiled_ref = "\$this->_supers['env']";
+ if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
+ $this->_syntax_error("(secure mode) super global access not permitted",
+ E_USER_WARNING, __FILE__, __LINE__);
+ return;
+ }
+ $compiled_ref = "\$_ENV";
break;
case 'server':
- $compiled_ref = "\$this->_supers['server']";
+ if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
+ $this->_syntax_error("(secure mode) super global access not permitted",
+ E_USER_WARNING, __FILE__, __LINE__);
+ return;
+ }
+ $compiled_ref = "\$_SERVER";
break;
case 'session':
- $compiled_ref = "\$this->_supers['session']";
+ if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
+ $this->_syntax_error("(secure mode) super global access not permitted",
+ E_USER_WARNING, __FILE__, __LINE__);
+ return;
+ }
+ $compiled_ref = "\$_SESSION";
break;
/*
@@ -2075,8 +2105,13 @@ class Smarty_Compiler extends Smarty {
* compiler.
*/
case 'request':
+ if ($this->security && !$this->security_settings['ALLOW_SUPER_GLOBALS']) {
+ $this->_syntax_error("(secure mode) super global access not permitted",
+ E_USER_WARNING, __FILE__, __LINE__);
+ return;
+ }
if ($this->request_use_auto_globals) {
- $compiled_ref = "\$this->_supers['request']";
+ $compiled_ref = "\$_REQUEST";
break;
} else {
$this->_init_smarty_vars = true;
diff --git a/libs/Smarty/plugins/function.cycle.php b/libs/Smarty/plugins/function.cycle.php
index fe78bb87da..80378b7f96 100644
--- a/libs/Smarty/plugins/function.cycle.php
+++ b/libs/Smarty/plugins/function.cycle.php
@@ -63,7 +63,11 @@ function smarty_function_cycle($params, &$smarty)
$cycle_vars[$name]['values'] = $params['values'];
}
- $cycle_vars[$name]['delimiter'] = (isset($params['delimiter'])) ? $params['delimiter'] : ',';
+ if (isset($params['delimiter'])) {
+ $cycle_vars[$name]['delimiter'] = $params['delimiter'];
+ } elseif (!isset($cycle_vars[$name]['delimiter'])) {
+ $cycle_vars[$name]['delimiter'] = ',';
+ }
if(is_array($cycle_vars[$name]['values'])) {
$cycle_array = $cycle_vars[$name]['values'];
diff --git a/libs/Smarty/plugins/function.math.php b/libs/Smarty/plugins/function.math.php
index bb78dac22c..6575e06001 100644
--- a/libs/Smarty/plugins/function.math.php
+++ b/libs/Smarty/plugins/function.math.php
@@ -37,7 +37,7 @@ function smarty_function_math($params, &$smarty)
}
// match all vars in equation, make sure all are passed
- preg_match_all("!(?:0x[a-fA-F0-9]+)|([a-zA-Z][a-zA-Z0-9_]+)!",$equation, $match);
+ preg_match_all("!(?:0x[a-fA-F0-9]+)|([a-zA-Z][a-zA-Z0-9_]*)!",$equation, $match);
$allowed_funcs = array('int','abs','ceil','cos','exp','floor','log','log10',
'max','min','pi','pow','rand','round','sin','sqrt','srand','tan');
@@ -82,4 +82,4 @@ function smarty_function_math($params, &$smarty)
/* vim: set expandtab: */
-?>
+?> \ No newline at end of file
diff --git a/libs/Smarty/plugins/outputfilter.trimwhitespace.php b/libs/Smarty/plugins/outputfilter.trimwhitespace.php
index 739fa39b02..f39acd0df1 100644
--- a/libs/Smarty/plugins/outputfilter.trimwhitespace.php
+++ b/libs/Smarty/plugins/outputfilter.trimwhitespace.php
@@ -62,6 +62,14 @@ function smarty_outputfilter_trimwhitespace($source, &$smarty)
}
function smarty_outputfilter_trimwhitespace_replace($search_str, $replace, &$subject) {
+ // If mbstring overloads substr and strlen functions, we have to
+ // override it's internal encoding
+ if (function_exists('mb_internal_encoding') &&
+ (((int) ini_get('mbstring.func_overload')) & 2)) {
+ $mbIntEnc = mb_internal_encoding();
+ mb_internal_encoding('ASCII');
+ }
+
$_len = strlen($search_str);
$_pos = 0;
for ($_i=0, $_count=count($replace); $_i<$_count; $_i++)
@@ -70,6 +78,9 @@ function smarty_outputfilter_trimwhitespace_replace($search_str, $replace, &$sub
else
break;
+ if (isset($mbIntEnc)) {
+ mb_internal_encoding($mbIntEnc);
+ }
}
?>
diff --git a/libs/UserAgentParser/README b/libs/UserAgentParser/README
index 9e3686ed5b..3e831ca981 100644
--- a/libs/UserAgentParser/README
+++ b/libs/UserAgentParser/README
@@ -5,15 +5,16 @@ UserAgentParser is NOT designed to parse bots user agent strings;
UserAgentParser will only be accurate when parsing user agents
coming from Javascript Enabled browsers!
-UserAgentParser is designed for simplicity and will accuratly detect
-most used web browsers, is regularly updated to detect newly OS and browsers.
+UserAgentParser is designed for simplicity, to accurately detect the
+most used web browsers, and be regularly updated to detect new OS and browsers.
Potential limitations:
-- it does NOT detect sub sub versions, ie. the "5" in 1.4.5 ; this is design decision to simplify the version number
-- it does NOT properly detect search engine, bots, etc. user agents, it's designed to detect browsers with javascript enabled.
+- it does NOT detect sub sub versions, ie. the "5" in 1.4.5; this is a design decision to simplify the version number
+- it does NOT detect search engine, bots, etc. user agents; it's designed to detect browsers with javascript enabled
+- it does NOT detect nested UA strings caused by some browser add-ons
Feature request:
- it could have the notion of operating system "types", ie "Windows".
It currently only has "Windows XP", "Windows Vista", etc.
-Feedback, patches: hello@piwik.org \ No newline at end of file
+Feedback, patches: hello@piwik.org
diff --git a/libs/UserAgentParser/UserAgentParser.php b/libs/UserAgentParser/UserAgentParser.php
index 4aa70356e2..a1c081f9fe 100644
--- a/libs/UserAgentParser/UserAgentParser.php
+++ b/libs/UserAgentParser/UserAgentParser.php
@@ -29,91 +29,213 @@ class UserAgentParser
// browser regex => browser ID
// if there are aliases, the common name should be last
static protected $browsers = array(
- 'opera' => 'OP',
- 'msie' => 'IE',
- 'microsoft internet explorer' => 'IE',
- 'internet explorer' => 'IE',
- 'netscape6' => 'NS',
- 'netscape' => 'NS',
- 'galeon' => 'GA',
- 'minefield' => 'FF',
- 'namoroka' => 'FF',
- 'shiretoko' => 'FF',
- 'bonecho' => 'FF',
- 'granparidiso' => 'FF',
- 'mozilla firebird' => 'FB',
- 'firebird' => 'FB',
- 'firefox' => 'FF',
- 'phoenix' => 'PX',
- 'seamonkey' => 'SM',
- 'camino' => 'CA',
- 'safari' => 'SF',
- 'chrome' => 'CH',
- 'k-meleon' => 'KM',
- 'mozilla' => 'MO',
- 'konqueror' => 'KO',
- 'blackberry' => 'BB',
- 'icab' => 'IC',
- 'lynx' => 'LX',
- 'links' => 'LI',
- 'ncsa mosaic' => 'MC',
- 'amaya' => 'AM',
- 'omniweb' => 'OW',
- 'hotjava' => 'HJ',
- 'browsex' => 'BX',
- 'amigavoyager' => 'AV',
- 'amiga-aweb' => 'AW',
- 'ibrowse' => 'IB',
- 'arora' => 'AR',
- 'iron' => 'IR',
- );
+ 'abrowse' => 'AB',
+ 'amaya' => 'AM',
+ 'amigavoyager' => 'AV',
+ 'amiga-aweb' => 'AW',
+ 'android' => 'AN',
+ 'arora' => 'AR',
+ 'beonex' => 'BE',
+ 'blackberry' => 'BB',
+ 'browsex' => 'BX',
+
+ // Camino (and earlier incarnation)
+ 'chimera' => 'CA',
+ 'camino' => 'CA',
+
+ 'cheshire' => 'CS',
+
+ // Chrome, Chromium, and ChromePlus
+ 'chrome' => 'CH',
+
+ 'cometbird' => 'CO',
+ 'dillo' => 'DI',
+ 'elinks' => 'EL',
+ 'epiphany' => 'EP',
+ 'fennec' => 'FE',
+
+ // Firefox (in its many incarnations and rebranded versions)
+ 'phoenix' => 'PX',
+ 'mozilla firebird' => 'FB',
+ 'firebird' => 'FB',
+ 'bonecho' => 'FF',
+ 'minefield' => 'FF',
+ 'namoroka' => 'FF',
+ 'shiretoko' => 'FF',
+ 'granparadiso' => 'FF',
+ 'iceweasel' => 'FF',
+ 'icecat' => 'FF',
+ 'firefox' => 'FF',
+
+ 'flock' => 'FL',
+ 'fluid' => 'FD',
+ 'galeon' => 'GA',
+ 'google earth' => 'GE',
+ 'hana' => 'HA',
+ 'hotjava' => 'HJ',
+ 'ibrowse' => 'IB',
+ 'icab' => 'IC',
+
+ // IE (including shells: Acoo, AOL, Avant, Crazy Browser, Green Browser, KKMAN, Maxathon)
+ 'msie' => 'IE',
+ 'microsoft internet explorer' => 'IE',
+ 'internet explorer' => 'IE',
+
+ 'iron' => 'IR',
+ 'kapiko' => 'KP',
+ 'kazehakase' => 'KZ',
+ 'k-meleon' => 'KM',
+ 'konqueror' => 'KO',
+ 'links' => 'LI',
+ 'lynx' => 'LX',
+ 'midori' => 'MI',
+
+ // SeaMonkey (formerly Mozilla Suite) (and rebranded versions)
+ 'mozilla' => 'MO',
+ 'gnuzilla' => 'SM',
+ 'iceape' => 'SM',
+ 'seamonkey' => 'SM',
+
+ // NCSA Mosaic (and incarnations)
+ 'mosaic' => 'MC',
+ 'ncsa mosaic' => 'MC',
+
+ // Netscape Navigator
+ 'navigator' => 'NS',
+ 'netscape6' => 'NS',
+ 'netscape' => 'NS',
+
+ 'omniweb' => 'OW',
+
+ // Opera
+ 'nitro) opera' => 'OP',
+ 'opera' => 'OP',
+
+ // Safari
+ 'safari' => 'SF',
+
+ 'webos' => 'WO',
+ 'webpro' => 'WP',
+ );
+
+ // browser family (by layout engine)
+ static protected $browserType = array(
+ 'ie' => array('IE'),
+ 'gecko' => array('NS', 'PX', 'FF', 'FB', 'CA', 'GA', 'KM', 'MO', 'SM', 'CO', 'FE', 'KP', 'KZ'),
+ 'khtml' => array('KO'),
+ 'webkit' => array('SF', 'CH', 'OW', 'AR', 'EP', 'FL', 'WO', 'AN', 'AB', 'IR', 'CS', 'FD', 'HA', 'MI', 'GE'),
+ 'opera' => array('OP'),
+ );
+
+ // WebKit version numbers to Apple Safari version numbers (if Version/X.Y.Z not present)
+ static protected $safariVersions = array(
+ '533.16' => array('5', '0'),
+ '533.4' => array('4', '1'),
+ '526.11.2' => array('4', '0'),
+ '525.26' => array('3', '2'),
+ '525.13' => array('3', '1'),
+ '522.11' => array('3', '0'),
+ '412' => array('2', '0'),
+ '312' => array('1', '3'),
+ '125' => array('1', '1'),
+ '85' => array('1', '0'),
+ '73' => array('0', '9'),
+ '48' => array('0', '8'),
+ );
+
+ // OmniWeb build numbers to OmniWeb version numbers (if Version/X.Y.Z not present)
+ static protected $omniWebVersions = array(
+ '622.10' => array('5', '10'),
+ '622.8' => array('5', '9'),
+ '622.3' => array('5', '8'),
+ '621' => array('5', '7'),
+ '613' => array('5', '6'),
+ '607' => array('5', '5'),
+ '563.34' => array('5', '1'),
+ '558.36' => array('5', '0'),
+ '496' => array('4', '5'),
+ );
// OS regex => OS ID
static protected $operatingSystems = array(
- 'iPod' => 'IPD',
- 'iPhone' => 'IPH',
- 'Nintendo Wii' => 'WII',
- 'PlayStation Portable' => 'PSP',
- 'PlayStation 3' => 'PS3',
- 'Android' => 'AND',
- 'PalmOS' => 'POS',
- 'Palm OS' => 'POS',
- 'BlackBerry' => 'BLB',
- 'Windows NT 6.1' => 'WI7',
- 'Windows 7' => 'WI7',
- 'Windows NT 6.0' => 'WVI',
- 'Windows Vista' => 'WVI',
- 'Windows NT 5.2' => 'WS3',
- 'Windows Server 2003' => 'WS3',
- 'Windows NT 5.1' => 'WXP',
- 'Windows XP' => 'WXP',
- 'Win98' => 'W98',
- 'Windows 98' => 'W98',
- 'Windows NT 5.0' => 'W2K',
- 'Windows 2000' => 'W2K',
- 'Windows NT 4.0' => 'WNT',
- 'WinNT' => 'WNT',
- 'Windows NT' => 'WNT',
- 'Win 9x 4.90' => 'WME',
- 'Windows ME' => 'WME',
- 'Win32' => 'W95',
- 'Win95' => 'W95',
- 'Windows 95' => 'W95',
- 'Mac_PowerPC' => 'MAC',
- 'Mac PPC' => 'MAC',
- 'PPC' => 'MAC',
- 'Mac PowerPC' => 'MAC',
- 'Mac OS' => 'MAC',
- 'Linux' => 'LIN',
- 'SunOS' => 'SOS',
- 'FreeBSD' => 'BSD',
- 'AIX' => 'AIX',
- 'IRIX' => 'IRI',
- 'HP-UX' => 'HPX',
- 'OS/2' => 'OS2',
- 'NetBSD' => 'NBS',
+ 'Android' => 'AND',
+ 'Linux' => 'LIN',
+
+ 'CYGWIN_NT-6.1' => 'WI7',
+ 'Windows NT 6.1' => 'WI7',
+ 'Windows 7' => 'WI7',
+ 'CYGWIN_NT-6.0' => 'WVI',
+ 'Windows NT 6.0' => 'WVI',
+ 'Windows Vista' => 'WVI',
+ 'CYGWIN_NT-5.2' => 'WS3',
+ 'Windows NT 5.2' => 'WS3',
+ 'Windows Server 2003 / XP x64' => 'WS3',
+ 'CYGWIN_NT-5.1' => 'WXP',
+ 'Windows NT 5.1' => 'WXP',
+ 'Windows XP' => 'WXP',
+ 'CYGWIN_NT-5.0' => 'W2K',
+ 'Windows NT 5.0' => 'W2K',
+ 'Windows 2000' => 'W2K',
+ 'CYGWIN_NT-4.0' => 'WNT',
+ 'Windows NT 4.0' => 'WNT',
+ 'WinNT' => 'WNT',
+ 'Windows NT' => 'WNT',
+ 'CYGWIN_ME-4.90' => 'WME',
+ 'Win 9x 4.90' => 'WME',
+ 'Windows ME' => 'WME',
+ 'CYGWIN_98-4.10' => 'W98',
+ 'Win98' => 'W98',
+ 'Windows 98' => 'W98',
+ 'CYGWIN_95-4.0' => 'W95',
+ 'Win32' => 'W95',
+ 'Win95' => 'W95',
+ 'Windows 95' => 'W95',
+
+ 'iPod' => 'IPD',
+ 'iPad' => 'IPA',
+ 'iPhone' => 'IPH',
+// 'iOS' => 'IOS',
+ 'Darwin' => 'MAC',
+ 'Macintosh' => 'MAC',
+ 'Power Macintosh' => 'MAC',
+ 'Mac_PowerPC' => 'MAC',
+ 'Mac PPC' => 'MAC',
+ 'PPC' => 'MAC',
+ 'Mac PowerPC' => 'MAC',
+ 'Mac OS' => 'MAC',
+
+ 'webOS' => 'WOS',
+ 'Palm webOS' => 'WOS',
+ 'PalmOS' => 'POS',
+ 'Palm OS' => 'POS',
+
+ 'BlackBerry' => 'BLB',
+
+ 'SunOS' => 'SOS',
+ 'AIX' => 'AIX',
+ 'HP-UX' => 'HPX',
+
+ 'FreeBSD' => 'BSD',
+ 'NetBSD' => 'NBS',
+ 'OpenBSD' => 'OBS',
+ 'DragonFly' => 'DFB',
+ 'Syllable' => 'SYL',
+
+ 'Nintendo Wii' => 'WII',
+ 'Nitro' => 'NDS',
+ 'Nintendo DS ' => 'NDS',
+ 'Nintendo DSi' => 'DSI',
+ 'PlayStation Portable' => 'PSP',
+ 'PlayStation 3' => 'PS3',
+
+ 'IRIX' => 'IRI',
+ 'OSF1' => 'T64',
+ 'OS/2' => 'OS2',
+ 'BEOS' => 'BEO',
+ 'Amiga' => 'AMI',
+ 'AmigaOS' => 'AMI',
);
-
+
static protected $browserIdToName;
static protected $browserIdToShortName;
static protected $operatingSystemsIdToName;
@@ -154,10 +276,12 @@ class UserAgentParser
*
* @param string $userAgent
* @return array false if the browser is "unknown", or
- * array( 'name' => '', // 2 letters ID, eg. FF
+ * array( 'id' => '', // 2 letters ID, eg. FF
+ * 'name' => '', // 2 letters ID, eg. FF
+ * 'short_name' => '', // 2 letters ID, eg. FF
* 'major_number' => '', // 2 in firefox 2.0.12
* 'minor_number' => '', // 0 in firefox 2.0.12
- * 'version' => '' // major_number.minor_number
+ * 'version' => '', // major_number.minor_number
* );
* @see self::$browsers for the list of OS
*/
@@ -172,31 +296,52 @@ class UserAgentParser
'major_number' => '',
'minor_number' => '',
'version' => '',
- );
+ );
+
+ $browsers = self::$browsers;
- $browser = implode('|', array_keys(self::$browsers));
+ // derivative browsers often clone the base browser's useragent
+ unset($browsers['firefox']);
+ unset($browsers['mozilla']);
+ unset($browsers['safari']);
+
+ $browsersPattern = str_replace(')', '\)', implode('|', array_keys($browsers)));
$results = array();
- // added fixes for Mozilla Suite and Chrome/Iron detection
- if (preg_match_all("/(mozilla)[\/\sa-z;.0-9-(]+rv:([0-9]+)([.0-9a-z]+)\) gecko\/[0-9]{8}$/i", $userAgent, $results)
- || preg_match_all("/(chrome|iron)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $results)
- || preg_match_all("/($browser)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $results)
+ // Misbehaving IE add-ons
+ $userAgent = preg_replace('/[; ]Mozilla\/[0-9.]+ \([^)]+\)/', '', $userAgent);
+
+ if (preg_match_all("/($browsersPattern)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $results)
+ || preg_match_all("/(firefox|safari)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $results)
+ || preg_match_all("/^(mozilla)\/([0-9]+)([\.0-9a-z-]+)?(?: \[[a-z]{2}\])? (?:\([^)]*\))$/i", $userAgent, $results)
+ || preg_match_all("/^(mozilla)\/[0-9]+(?:[\.0-9a-z-]+)?\s\(.* rv:([0-9]+)([.0-9a-z]+)\) gecko(\/[0-9]{8}|$)(?:.*)/i", $userAgent, $results)
)
{
- $count = count($results[0])-1;
+ // browser code (usually the first match)
+ $count = 0;
+ $info['id'] = self::$browsers[strtolower($results[1][0])];
- // browser code
- $info['id'] = self::$browsers[strtolower($results[1][$count])];
- $info['name'] = self::getBrowserNameFromId($info['id']);
- $info['short_name'] = self::getBrowserShortNameFromId($info['id']);
+ // sometimes there's a better match at the end
+ if(($info['id'] == 'IE' || $info['id'] == 'LX') && (count($results[0]) > 1)) {
+ $count = count($results[0]) - 1;
+ $info['id'] = self::$browsers[strtolower($results[1][$count])];
+ }
+
+ // Netscape fix
+ if($info['id'] == 'MO' && $count == 0) {
+ if(strpos($userAgent, 'PlayStation Portable') !== false) return false;
+ if(count($results) == 4) {
+ $info['id'] = 'NS';
+ }
+ }
- // Opera 10 fix
- if($info['id'] == 'OP' && preg_match_all("/(version)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $newResults)) {
+ // Version/X.Y.Z override
+ if(preg_match_all("/(version)[\/\sa-z(]*([0-9]+)([\.0-9a-z]+)?/i", $userAgent, $newResults)) {
$results = $newResults;
$count = count($results[0])-1;
}
-
+
// major version number (1 in mozilla 1.7)
$info['major_number'] = $results[2][$count];
@@ -218,7 +363,39 @@ class UserAgentParser
else {
$info['minor_number'] = '0';
}
- $info['version'] = $info['major_number'] . "." . $info['minor_number'];
+ $info['version'] = $info['major_number'] . '.' . $info['minor_number'];
+
+ // Safari fix
+ if($info['id'] == 'SF') {
+ foreach(self::$safariVersions as $buildVersion => $productVersion) {
+ if(version_compare($info['version'], $buildVersion) >= 0) {
+ $info['major_number'] = $productVersion[0];
+ $info['minor_number'] = $productVersion[1];
+ $info['version'] = $productVersion[0] . '.' . $productVersion[1];
+ break;
+ }
+ }
+ }
+
+ // OmniWeb fix
+ if($info['id'] == 'OW') {
+ foreach(self::$omniWebVersions as $buildVersion => $productVersion) {
+ if(version_compare($info['version'], $buildVersion) >= 0) {
+ $info['major_number'] = $productVersion[0];
+ $info['minor_number'] = $productVersion[1];
+ $info['version'] = $productVersion[0] . '.' . $productVersion[1];
+ break;
+ }
+ }
+ }
+
+ // SeaMonkey fix
+ if($info['id'] == 'MO' && $info['version'] == '1.9') {
+ $info['id'] = 'SM';
+ }
+
+ $info['name'] = self::getBrowserNameFromId($info['id']);
+ $info['short_name'] = self::getBrowserShortNameFromId($info['id']);
return $info;
}
@@ -233,19 +410,47 @@ class UserAgentParser
// init browser names and short names
self::$browserIdToName = array_map('ucwords',array_flip(self::$browsers));
- self::$browserIdToName['CH'] = "Google Chrome";
+ self::$browserIdToName['AB'] = 'ABrowse';
+ self::$browserIdToName['AV'] = 'AmigaVoyager';
+ self::$browserIdToName['AW'] = 'Amiga AWeb';
+ self::$browserIdToName['BB'] = 'BlackBerry';
+ self::$browserIdToName['BX'] = 'BrowseX';
+ self::$browserIdToName['CO'] = 'CometBird';
+ self::$browserIdToName['EL'] = 'ELinks';
+ self::$browserIdToName['FF'] = 'Firefox';
+ self::$browserIdToName['HJ'] = 'HotJava';
+ self::$browserIdToName['IB'] = 'IBrowse';
+ self::$browserIdToName['IC'] = 'iCab';
+ self::$browserIdToName['KM'] = 'K-Meleon';
+ self::$browserIdToName['MC'] = 'NCSA Mosaic';
+ self::$browserIdToName['OW'] = 'OmniWeb';
+ self::$browserIdToName['SF'] = 'Safari';
+ self::$browserIdToName['SM'] = 'SeaMonkey';
+ self::$browserIdToName['WO'] = 'Palm webOS';
+ self::$browserIdToName['WP'] = 'WebPro';
self::$browserIdToShortName = self::$browserIdToName;
- self::$browserIdToShortName['IE'] = "IE";
- self::$browserIdToShortName['FB'] = "Firebird";
+ self::$browserIdToShortName['AW'] = 'AWeb';
+ self::$browserIdToShortName['FB'] = 'Firebird';
+ self::$browserIdToShortName['IE'] = 'IE';
+ self::$browserIdToShortName['MC'] = 'Mosaic';
+ self::$browserIdToShortName['WO'] = 'webOS';
// init OS names and short names
- self::$operatingSystemsIdToName = array_flip(self::$operatingSystems);
+ self::$operatingSystemsIdToName = array_merge(array_flip(self::$operatingSystems), array(
+ 'IPD' => 'iPod',
+ 'IPA' => 'iPad',
+ 'WME' => 'Windows Me',
+ 'BEO' => 'BeOS',
+ 'T64' => 'Tru64',
+ 'NDS' => 'Nintendo DS',
+ ));
self::$operatingSystemsIdToShortName = array_merge(self::$operatingSystemsIdToName, array(
'PS3' => 'PS3',
'PSP' => 'PSP',
- 'IPH' => 'iPhone',
- 'WII' => 'WII',
+ 'WII' => 'Wii',
+ 'NDS' => 'DS',
+ 'DSI' => 'DSi',
'WI7' => 'Win 7',
'WVI' => 'Win Vista',
'WS3' => 'Win S2003',
@@ -254,22 +459,13 @@ class UserAgentParser
'W2K' => 'Win 2000',
'WNT' => 'Win NT',
'WME' => 'Win Me',
- 'W95' => 'Win 95',
+ 'W95' => 'Win 95',
'WCE' => 'Win CE',
- 'MAC' => 'Mac OS',
- 'LIN' => 'Linux',
- 'INC' => 'Inconnu',
- 'SOS' => 'SunOS',
- 'BSD' => 'FreeBSD',
- 'AIX' => 'AIX',
- 'IRI' => 'IRIX',
- 'HPX' => 'HPX',
- 'OS2' => 'OS/2',
- 'NBS' => 'NetBSD',
+ 'WOS' => 'webOS',
'UNK' => 'Unknown',
- ));
+ ));
}
-
+
static public function getBrowserNameFromId($browserId)
{
self::init();
@@ -278,7 +474,7 @@ class UserAgentParser
}
return false;
}
-
+
static public function getBrowserShortNameFromId($browserId)
{
self::init();
@@ -287,7 +483,22 @@ class UserAgentParser
}
return false;
}
-
+
+ static public function getBrowserFamilyFromId($browserId)
+ {
+ self::init();
+ $familyNameToUse = 'unknown';
+ foreach(self::$browserType as $familyName => $aBrowsers)
+ {
+ if(in_array($browserId, $aBrowsers))
+ {
+ $familyNameToUse = $familyName;
+ break;
+ }
+ }
+ return $familyNameToUse;
+ }
+
static public function getOperatingSystemNameFromId($osId)
{
self::init();
@@ -304,6 +515,5 @@ class UserAgentParser
return self::$operatingSystemsIdToShortName[$osId];
}
return false;
-
- }
+ }
}
diff --git a/libs/Zend/Auth.php b/libs/Zend/Auth.php
index d53602269e..47d474458a 100644
--- a/libs/Zend/Auth.php
+++ b/libs/Zend/Auth.php
@@ -14,16 +14,16 @@
*
* @category Zend
* @package Zend_Auth
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Auth.php 18039 2009-09-09 03:35:19Z ralph $
+ * @version $Id: Auth.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Auth
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth
@@ -87,7 +87,7 @@ class Zend_Auth
/**
* @see Zend_Auth_Storage_Session
*/
- require_once 'Zend/Auth/Storage/Session.php';
+ // require_once 'Zend/Auth/Storage/Session.php';
$this->setStorage(new Zend_Auth_Storage_Session());
}
@@ -119,11 +119,11 @@ class Zend_Auth
/**
* ZF-7546 - prevent multiple succesive calls from storing inconsistent results
* Ensure storage has clean state
- */
+ */
if ($this->hasIdentity()) {
$this->clearIdentity();
}
-
+
if ($result->isValid()) {
$this->getStorage()->write($result->getIdentity());
}
diff --git a/libs/Zend/Auth/Adapter/DbTable.php b/libs/Zend/Auth/Adapter/DbTable.php
index db64bcba9e..30bbd2478d 100644
--- a/libs/Zend/Auth/Adapter/DbTable.php
+++ b/libs/Zend/Auth/Adapter/DbTable.php
@@ -14,34 +14,34 @@
*
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Adapter
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: DbTable.php 18066 2009-09-10 18:47:53Z ralph $
+ * @version $Id: DbTable.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
-require_once 'Zend/Auth/Adapter/Interface.php';
+// require_once 'Zend/Auth/Adapter/Interface.php';
/**
* @see Zend_Db_Adapter_Abstract
*/
-require_once 'Zend/Db/Adapter/Abstract.php';
+// require_once 'Zend/Db/Adapter/Abstract.php';
/**
* @see Zend_Auth_Result
*/
-require_once 'Zend/Auth/Result.php';
+// require_once 'Zend/Auth/Result.php';
/**
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Adapter
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
@@ -58,7 +58,7 @@ class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
* @var Zend_Db_Select
*/
protected $_dbSelect = null;
-
+
/**
* $_tableName - the table name to check
*
@@ -185,7 +185,7 @@ class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
/**
* setCredentialTreatment() - allows the developer to pass a parameterized string that is
- * used to transform or treat the input credential data
+ * used to transform or treat the input credential data.
*
* In many cases, passwords and other sensitive data are encrypted, hashed, encoded,
* obscured, or otherwise treated through some function or algorithm. By specifying a
@@ -241,10 +241,10 @@ class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
if ($this->_dbSelect == null) {
$this->_dbSelect = $this->_zendDb->select();
}
-
+
return $this->_dbSelect;
}
-
+
/**
* getResultRowObject() - Returns the result row as a stdClass object
*
@@ -292,8 +292,8 @@ class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
/**
* authenticate() - defined by Zend_Auth_Adapter_Interface. This method is called to
- * attempt an authenication. Previous to this call, this adapter would have already
- * been configured with all nessissary information to successfully connect to a database
+ * attempt an authentication. Previous to this call, this adapter would have already
+ * been configured with all necessary information to successfully connect to a database
* table and attempt to find a record matching the provided identity.
*
* @throws Zend_Auth_Adapter_Exception if answering the authentication query is impossible
@@ -314,8 +314,9 @@ class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
}
/**
- * _authenticateSetup() - This method abstracts the steps involved with making sure
- * that this adapter was indeed setup properly with all required peices of information.
+ * _authenticateSetup() - This method abstracts the steps involved with
+ * making sure that this adapter was indeed setup properly with all
+ * required pieces of information.
*
* @throws Zend_Auth_Adapter_Exception - in the event that setup was not done properly
* @return true
@@ -340,7 +341,7 @@ class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception($exception);
}
@@ -391,7 +392,8 @@ class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
* performs a query against the database with that object.
*
* @param Zend_Db_Select $dbSelect
- * @throws Zend_Auth_Adapter_Exception - when a invalid select object is encoutered
+ * @throws Zend_Auth_Adapter_Exception - when an invalid select
+ * object is encountered
* @return array
*/
protected function _authenticateQuerySelect(Zend_Db_Select $dbSelect)
@@ -410,17 +412,17 @@ class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('The supplied parameters to Zend_Auth_Adapter_DbTable failed to '
. 'produce a valid sql statement, please check table and column names '
- . 'for validity.');
+ . 'for validity.', 0, $e);
}
return $resultIdentities;
}
/**
- * _authenticateValidateResultSet() - This method attempts to make certian that only one
- * record was returned in the result set
+ * _authenticateValidateResultSet() - This method attempts to make
+ * certain that only one record was returned in the resultset
*
* @param array $resultIdentities
* @return true|Zend_Auth_Result
@@ -442,8 +444,9 @@ class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
}
/**
- * _authenticateValidateResult() - This method attempts to validate that the record in the
- * result set is indeed a record that matched the identity provided to this adapter.
+ * _authenticateValidateResult() - This method attempts to validate that
+ * the record in the resultset is indeed a record that matched the
+ * identity provided to this adapter.
*
* @param array $resultIdentity
* @return Zend_Auth_Result
@@ -451,7 +454,7 @@ class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
protected function _authenticateValidateResult($resultIdentity)
{
$zendAuthCredentialMatchColumn = $this->_zendDb->foldCase('zend_auth_credential_match');
-
+
if ($resultIdentity[$zendAuthCredentialMatchColumn] != '1') {
$this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
$this->_authenticateResultInfo['messages'][] = 'Supplied credential is invalid.';
@@ -467,8 +470,8 @@ class Zend_Auth_Adapter_DbTable implements Zend_Auth_Adapter_Interface
}
/**
- * _authenticateCreateAuthResult() - This method creates a Zend_Auth_Result object
- * from the information that has been collected during the authenticate() attempt.
+ * _authenticateCreateAuthResult() - Creates a Zend_Auth_Result object from
+ * the information that has been collected during the authenticate() attempt.
*
* @return Zend_Auth_Result
*/
diff --git a/libs/Zend/Auth/Adapter/Digest.php b/libs/Zend/Auth/Adapter/Digest.php
index 259ae3f3cd..a099bef358 100644
--- a/libs/Zend/Auth/Adapter/Digest.php
+++ b/libs/Zend/Auth/Adapter/Digest.php
@@ -14,24 +14,24 @@
*
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Adapter
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Digest.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Digest.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
-require_once 'Zend/Auth/Adapter/Interface.php';
+// require_once 'Zend/Auth/Adapter/Interface.php';
/**
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Adapter
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_Digest implements Zend_Auth_Adapter_Interface
@@ -186,7 +186,7 @@ class Zend_Auth_Adapter_Digest implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception("Option '$optionRequired' must be set before authentication");
}
}
@@ -195,7 +195,7 @@ class Zend_Auth_Adapter_Digest implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception("Cannot open '$this->_filename' for reading");
}
diff --git a/libs/Zend/Auth/Adapter/Exception.php b/libs/Zend/Auth/Adapter/Exception.php
index 0b5a4d43cf..23282dddf2 100644
--- a/libs/Zend/Auth/Adapter/Exception.php
+++ b/libs/Zend/Auth/Adapter/Exception.php
@@ -14,24 +14,24 @@
*
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Adapter
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Auth_Exception
*/
-require_once 'Zend/Auth/Exception.php';
+// require_once 'Zend/Auth/Exception.php';
/**
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Adapter
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_Exception extends Zend_Auth_Exception
diff --git a/libs/Zend/Auth/Adapter/Http.php b/libs/Zend/Auth/Adapter/Http.php
index 466ce42597..d645d8db93 100644
--- a/libs/Zend/Auth/Adapter/Http.php
+++ b/libs/Zend/Auth/Adapter/Http.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Http.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Http.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
-require_once 'Zend/Auth/Adapter/Interface.php';
+// require_once 'Zend/Auth/Adapter/Interface.php';
/**
@@ -35,7 +35,7 @@ require_once 'Zend/Auth/Adapter/Interface.php';
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @todo Support auth-int
* @todo Track nonces, nonce-count, opaque for replay protection and stale support
@@ -171,7 +171,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception(__CLASS__ . ' requires the \'hash\' extension');
}
@@ -184,7 +184,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Config key \'accept_schemes\' is required');
}
@@ -194,7 +194,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('No supported schemes given in \'accept_schemes\'. Valid values: '
. implode(', ', $this->_supportedSchemes));
}
@@ -208,7 +208,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Config key \'realm\' is required, and must contain only printable '
. 'characters, excluding quotation marks and colons');
} else {
@@ -222,7 +222,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Config key \'digest_domains\' is required, and must contain '
. 'only printable characters, excluding quotation marks');
} else {
@@ -234,7 +234,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Config key \'nonce_timeout\' is required, and must be an '
. 'integer');
} else {
@@ -368,7 +368,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Request and Response objects must be set before calling '
. 'authenticate()');
}
@@ -403,7 +403,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
// challenge again the client
return $this->_challengeClient();
}
-
+
switch ($clientScheme) {
case 'basic':
$result = $this->_basicAuth($authHeader);
@@ -415,7 +415,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Unsupported authentication scheme');
}
@@ -502,14 +502,14 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('The value of the client Authorization header is required');
}
if (empty($this->_basicResolver)) {
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('A basicResolver object must be set before doing Basic '
. 'authentication');
}
@@ -521,7 +521,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Unable to base64_decode Authorization header value');
}
@@ -559,14 +559,14 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('The value of the client Authorization header is required');
}
if (empty($this->_digestResolver)) {
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('A digestResolver object must be set before doing Digest authentication');
}
@@ -625,7 +625,7 @@ class Zend_Auth_Adapter_Http implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Exception.php';
throw new Zend_Auth_Adapter_Exception('Client requested an unsupported qop option');
}
// Using hash() should make parameterizing the hash algorithm
diff --git a/libs/Zend/Auth/Adapter/Http/Resolver/Exception.php b/libs/Zend/Auth/Adapter/Http/Resolver/Exception.php
index cb7b18be0d..5a4c9bf358 100644
--- a/libs/Zend/Auth/Adapter/Http/Resolver/Exception.php
+++ b/libs/Zend/Auth/Adapter/Http/Resolver/Exception.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Auth_Exception
*/
-require_once 'Zend/Auth/Exception.php';
+// require_once 'Zend/Auth/Exception.php';
/**
@@ -33,7 +33,7 @@ require_once 'Zend/Auth/Exception.php';
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_Http_Resolver_Exception extends Zend_Auth_Exception
diff --git a/libs/Zend/Auth/Adapter/Http/Resolver/File.php b/libs/Zend/Auth/Adapter/Http/Resolver/File.php
index 39b548ca66..d17c2ecb37 100644
--- a/libs/Zend/Auth/Adapter/Http/Resolver/File.php
+++ b/libs/Zend/Auth/Adapter/Http/Resolver/File.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: File.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: File.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Auth_Adapter_Http_Resolver_Interface
*/
-require_once 'Zend/Auth/Adapter/Http/Resolver/Interface.php';
+// require_once 'Zend/Auth/Adapter/Http/Resolver/Interface.php';
/**
@@ -33,7 +33,7 @@ require_once 'Zend/Auth/Adapter/Http/Resolver/Interface.php';
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_Http_Resolver_File implements Zend_Auth_Adapter_Http_Resolver_Interface
@@ -71,7 +71,7 @@ class Zend_Auth_Adapter_Http_Resolver_File implements Zend_Auth_Adapter_Http_Res
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
- require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Path not readable: ' . $path);
}
$this->_file = $path;
@@ -116,13 +116,13 @@ class Zend_Auth_Adapter_Http_Resolver_File implements Zend_Auth_Adapter_Http_Res
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
- require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Username is required');
} else if (!ctype_print($username) || strpos($username, ':') !== false) {
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
- require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Username must consist only of printable characters, '
. 'excluding the colon');
}
@@ -130,13 +130,13 @@ class Zend_Auth_Adapter_Http_Resolver_File implements Zend_Auth_Adapter_Http_Res
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
- require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Realm is required');
} else if (!ctype_print($realm) || strpos($realm, ':') !== false) {
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
- require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Realm must consist only of printable characters, '
. 'excluding the colon.');
}
@@ -147,7 +147,7 @@ class Zend_Auth_Adapter_Http_Resolver_File implements Zend_Auth_Adapter_Http_Res
/**
* @see Zend_Auth_Adapter_Http_Resolver_Exception
*/
- require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ // require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
throw new Zend_Auth_Adapter_Http_Resolver_Exception('Unable to open password file: ' . $this->_file);
}
diff --git a/libs/Zend/Auth/Adapter/Http/Resolver/Interface.php b/libs/Zend/Auth/Adapter/Http/Resolver/Interface.php
index d36a0125a2..78c0343147 100644
--- a/libs/Zend/Auth/Adapter/Http/Resolver/Interface.php
+++ b/libs/Zend/Auth/Adapter/Http/Resolver/Interface.php
@@ -15,9 +15,9 @@
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -30,7 +30,7 @@
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter_Http
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Auth_Adapter_Http_Resolver_Interface
diff --git a/libs/Zend/Auth/Adapter/InfoCard.php b/libs/Zend/Auth/Adapter/InfoCard.php
index 1af3a08616..8f2572a571 100644
--- a/libs/Zend/Auth/Adapter/InfoCard.php
+++ b/libs/Zend/Auth/Adapter/InfoCard.php
@@ -15,25 +15,25 @@
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: InfoCard.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: InfoCard.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
-require_once 'Zend/Auth/Adapter/Interface.php';
+// require_once 'Zend/Auth/Adapter/Interface.php';
/**
* @see Zend_Auth_Result
*/
-require_once 'Zend/Auth/Result.php';
+// require_once 'Zend/Auth/Result.php';
/**
* @see Zend_InfoCard
*/
-require_once 'Zend/InfoCard.php';
+// require_once 'Zend/InfoCard.php';
/**
* A Zend_Auth Authentication Adapter allowing the use of Information Cards as an
@@ -42,7 +42,7 @@ require_once 'Zend/InfoCard.php';
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_InfoCard implements Zend_Auth_Adapter_Interface
diff --git a/libs/Zend/Auth/Adapter/Interface.php b/libs/Zend/Auth/Adapter/Interface.php
index 67cb6b8b02..3f8204842b 100644
--- a/libs/Zend/Auth/Adapter/Interface.php
+++ b/libs/Zend/Auth/Adapter/Interface.php
@@ -15,23 +15,23 @@
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Auth_Result
*/
-require_once 'Zend/Auth/Result.php';
+// require_once 'Zend/Auth/Result.php';
/**
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Auth_Adapter_Interface
diff --git a/libs/Zend/Auth/Adapter/Ldap.php b/libs/Zend/Auth/Adapter/Ldap.php
index 9c0fc7f785..20f31c1fe0 100644
--- a/libs/Zend/Auth/Adapter/Ldap.php
+++ b/libs/Zend/Auth/Adapter/Ldap.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Ldap.php 17976 2009-09-04 14:50:25Z sgehrig $
+ * @version $Id: Ldap.php 21320 2010-03-04 16:05:09Z sgehrig $
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
-require_once 'Zend/Auth/Adapter/Interface.php';
+// require_once 'Zend/Auth/Adapter/Interface.php';
/**
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
@@ -161,7 +161,7 @@ class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
/**
* setIdentity() - set the identity (username) to be used
*
- * Proxies to {@see setPassword()}
+ * Proxies to {@see setUsername()}
*
* Closes ZF-6813
*
@@ -199,7 +199,7 @@ class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Ldap
*/
- require_once 'Zend/Ldap.php';
+ // require_once 'Zend/Ldap.php';
$this->_ldap = new Zend_Ldap();
}
@@ -247,7 +247,7 @@ class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Ldap_Exception
*/
- require_once 'Zend/Ldap/Exception.php';
+ // require_once 'Zend/Ldap/Exception.php';
$messages = array();
$messages[0] = ''; // reserved
@@ -285,8 +285,8 @@ class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Auth_Adapter_Exception
*/
- require_once 'Zend/Auth/Adapter/Exception.php';
- throw new Zend_Auth_Adapter_Exception('Adapter options array not in array');
+ // require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('Adapter options array not an array');
}
$adapterOptions = $this->_prepareOptions($ldap, $options);
$dname = '';
@@ -314,6 +314,18 @@ class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
$canonicalName = $ldap->getCanonicalAccountName($username);
$ldap->bind($canonicalName, $password);
+ /*
+ * Fixes problem when authenticated user is not allowed to retrieve
+ * group-membership information or own account.
+ * This requires that the user specified with "username" and optionally
+ * "password" in the Zend_Ldap options is able to retrieve the required
+ * information.
+ */
+ $requireRebind = false;
+ if (isset($options['username'])) {
+ $ldap->bind();
+ $requireRebind = true;
+ }
$dn = $ldap->getCanonicalAccountName($canonicalName, Zend_Ldap::ACCTNAME_FORM_DN);
$groupResult = $this->_checkGroupMembership($ldap, $canonicalName, $dn, $adapterOptions);
@@ -322,6 +334,10 @@ class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
$messages[0] = '';
$messages[1] = '';
$messages[] = "$canonicalName authentication successful";
+ if ($requireRebind === true) {
+ // rebinding with authenticated user
+ $ldap->bind($dn, $password);
+ }
return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $canonicalName, $messages);
} else {
$messages[0] = 'Account is not a member of the specified group';
@@ -408,7 +424,6 @@ class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
}
}
}
-
$ldap->setOptions($options);
return $adapterOptions;
}
@@ -437,7 +452,7 @@ class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
/**
* @see Zend_Ldap_Filter
*/
- require_once 'Zend/Ldap/Filter.php';
+ // require_once 'Zend/Ldap/Filter.php';
$groupName = Zend_Ldap_Filter::equals($adapterOptions['groupAttr'], $adapterOptions['group']);
$membership = Zend_Ldap_Filter::equals($adapterOptions['memberAttr'], $user);
$group = Zend_Ldap_Filter::andFilter($groupName, $membership);
@@ -446,14 +461,6 @@ class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
$group = $group->addAnd($groupFilter);
}
- /*
- * Fixes problem when authenticated user is not allowed to retrieve
- * group-membership information.
- * This requires that the user specified with "username" and "password"
- * in the Zend_Ldap options is able to retrieve the required information.
- */
- $ldap->bind();
-
$result = $ldap->count($group, $adapterOptions['groupDn'], $adapterOptions['groupScope']);
if ($result === 1) {
@@ -466,13 +473,14 @@ class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
/**
* getAccountObject() - Returns the result entry as a stdClass object
*
- * This ressembles the feature {@see Zend_Auth_Adapter_DbTable::getResultRowObject()}.
+ * This resembles the feature {@see Zend_Auth_Adapter_DbTable::getResultRowObject()}.
* Closes ZF-6813
*
* @param array $returnAttribs
+ * @param array $omitAttribs
* @return stdClass|boolean
*/
- public function getAccountObject(array $returnAttribs = array())
+ public function getAccountObject(array $returnAttribs = array(), array $omitAttribs = array())
{
if (!$this->_authenticatedDn) {
return false;
@@ -480,8 +488,14 @@ class Zend_Auth_Adapter_Ldap implements Zend_Auth_Adapter_Interface
$returnObject = new stdClass();
+ $omitAttribs = array_map('strtolower', $omitAttribs);
+
$entry = $this->getLdap()->getEntry($this->_authenticatedDn, $returnAttribs, true);
foreach ($entry as $attr => $value) {
+ if (in_array($attr, $omitAttribs)) {
+ // skip attributes marked to be omitted
+ continue;
+ }
if (is_array($value)) {
$returnObject->$attr = (count($value) > 1) ? $value : $value[0];
} else {
diff --git a/libs/Zend/Auth/Adapter/OpenId.php b/libs/Zend/Auth/Adapter/OpenId.php
index 44e4684456..08f21d949b 100644
--- a/libs/Zend/Auth/Adapter/OpenId.php
+++ b/libs/Zend/Auth/Adapter/OpenId.php
@@ -15,22 +15,22 @@
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: OpenId.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: OpenId.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Auth_Adapter_Interface
*/
-require_once 'Zend/Auth/Adapter/Interface.php';
+// require_once 'Zend/Auth/Adapter/Interface.php';
/**
* @see Zend_OpenId_Consumer
*/
-require_once 'Zend/OpenId/Consumer.php';
+// require_once 'Zend/OpenId/Consumer.php';
/**
@@ -40,7 +40,7 @@ require_once 'Zend/OpenId/Consumer.php';
* @category Zend
* @package Zend_Auth
* @subpackage Zend_Auth_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Adapter_OpenId implements Zend_Auth_Adapter_Interface
diff --git a/libs/Zend/Auth/Exception.php b/libs/Zend/Auth/Exception.php
index c71f41c505..80334c1911 100644
--- a/libs/Zend/Auth/Exception.php
+++ b/libs/Zend/Auth/Exception.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Auth
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Exception
*/
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Auth
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Exception extends Zend_Exception
diff --git a/libs/Zend/Auth/Result.php b/libs/Zend/Auth/Result.php
index 18ba1023f9..964d44d80d 100644
--- a/libs/Zend/Auth/Result.php
+++ b/libs/Zend/Auth/Result.php
@@ -14,16 +14,16 @@
*
* @category Zend
* @package Zend_Auth
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Result.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Result.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Auth
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Result
diff --git a/libs/Zend/Auth/Storage/Exception.php b/libs/Zend/Auth/Storage/Exception.php
index 6f3af444c0..218c909c50 100644
--- a/libs/Zend/Auth/Storage/Exception.php
+++ b/libs/Zend/Auth/Storage/Exception.php
@@ -14,24 +14,24 @@
*
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Storage
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Auth_Exception
*/
-require_once 'Zend/Auth/Exception.php';
+// require_once 'Zend/Auth/Exception.php';
/**
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Storage
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Storage_Exception extends Zend_Auth_Exception
diff --git a/libs/Zend/Auth/Storage/Interface.php b/libs/Zend/Auth/Storage/Interface.php
index a604a0d8c6..9fedf01322 100644
--- a/libs/Zend/Auth/Storage/Interface.php
+++ b/libs/Zend/Auth/Storage/Interface.php
@@ -14,18 +14,17 @@
*
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Storage
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
-
/**
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Storage
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Auth_Storage_Interface
diff --git a/libs/Zend/Auth/Storage/NonPersistent.php b/libs/Zend/Auth/Storage/NonPersistent.php
index 6c544fff4b..1dd034b7ef 100644
--- a/libs/Zend/Auth/Storage/NonPersistent.php
+++ b/libs/Zend/Auth/Storage/NonPersistent.php
@@ -14,17 +14,17 @@
*
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Storage
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: NonPersistent.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: NonPersistent.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Auth_Storage_Interface
*/
-require_once 'Zend/Auth/Storage/Interface.php';
+// require_once 'Zend/Auth/Storage/Interface.php';
/**
@@ -36,8 +36,8 @@ require_once 'Zend/Auth/Storage/Interface.php';
*
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Storage
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Storage_NonPersistent implements Zend_Auth_Storage_Interface
@@ -47,7 +47,6 @@ class Zend_Auth_Storage_NonPersistent implements Zend_Auth_Storage_Interface
*/
protected $_data;
-
/**
* Returns true if and only if storage is empty
*
diff --git a/libs/Zend/Auth/Storage/Session.php b/libs/Zend/Auth/Storage/Session.php
index 14027968b0..a3775ce3d3 100644
--- a/libs/Zend/Auth/Storage/Session.php
+++ b/libs/Zend/Auth/Storage/Session.php
@@ -14,30 +14,30 @@
*
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Storage
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Session.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Session.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Auth_Storage_Interface
*/
-require_once 'Zend/Auth/Storage/Interface.php';
+// require_once 'Zend/Auth/Storage/Interface.php';
/**
* @see Zend_Session
*/
-require_once 'Zend/Session.php';
+// require_once 'Zend/Session.php';
/**
* @category Zend
* @package Zend_Auth
- * @subpackage Zend_Auth_Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Storage
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth_Storage_Session implements Zend_Auth_Storage_Interface
diff --git a/libs/Zend/Cache.php b/libs/Zend/Cache.php
index 1ea81411d8..761be75e17 100644
--- a/libs/Zend/Cache.php
+++ b/libs/Zend/Cache.php
@@ -14,15 +14,15 @@
*
* @category Zend
* @package Zend_Cache
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Cache.php 16200 2009-06-21 18:50:06Z thomas $
+ * @version $Id: Cache.php 21974 2010-04-23 17:10:17Z alexander $
*/
/**
* @package Zend_Cache
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Cache
@@ -40,15 +40,16 @@ abstract class Zend_Cache
*
* @var array
*/
- public static $standardBackends = array('File', 'Sqlite', 'Memcached', 'Apc', 'ZendPlatform', 'Xcache', 'TwoLevels');
+ public static $standardBackends = array('File', 'Sqlite', 'Memcached', 'Apc', 'ZendPlatform',
+ 'Xcache', 'TwoLevels', 'ZendServer_Disk', 'ZendServer_ShMem');
/**
* Standard backends which implement the ExtendedInterface
- *
+ *
* @var array
*/
public static $standardExtendedBackends = array('File', 'Apc', 'TwoLevels', 'Memcached', 'Sqlite');
-
+
/**
* Only for backward compatibily (may be removed in next major release)
*
@@ -73,7 +74,7 @@ abstract class Zend_Cache
const CLEANING_MODE_MATCHING_TAG = 'matchingTag';
const CLEANING_MODE_NOT_MATCHING_TAG = 'notMatchingTag';
const CLEANING_MODE_MATCHING_ANY_TAG = 'matchingAnyTag';
-
+
/**
* Factory
*
@@ -83,7 +84,7 @@ abstract class Zend_Cache
* @param array $backendOptions associative array of options for the corresponding backend constructor
* @param boolean $customFrontendNaming if true, the frontend argument is used as a complete class name ; if false, the frontend argument is used as the end of "Zend_Cache_Frontend_[...]" class name
* @param boolean $customBackendNaming if true, the backend argument is used as a complete class name ; if false, the backend argument is used as the end of "Zend_Cache_Backend_[...]" class name
- * @param boolean $autoload if true, there will no require_once for backend and frontend (usefull only for custom backends/frontends)
+ * @param boolean $autoload if true, there will no // require_once for backend and frontend (usefull only for custom backends/frontends)
* @throws Zend_Cache_Exception
* @return Zend_Cache_Core|Zend_Cache_Frontend
*/
@@ -110,7 +111,7 @@ abstract class Zend_Cache
$frontendObject->setBackend($backendObject);
return $frontendObject;
}
-
+
/**
* Frontend Constructor
*
@@ -129,7 +130,7 @@ abstract class Zend_Cache
// we use a standard backend
$backendClass = 'Zend_Cache_Backend_' . $backend;
// security controls are explicit
- require_once str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';
+ // require_once str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';
} else {
// we use a custom backend
if (!preg_match('~^[\w]+$~D', $backend)) {
@@ -146,12 +147,12 @@ abstract class Zend_Cache
if (!(self::_isReadable($file))) {
self::throwException("file $file not found in include_path");
}
- require_once $file;
+ // require_once $file;
}
}
return new $backendClass($backendOptions);
}
-
+
/**
* Backend Constructor
*
@@ -171,7 +172,7 @@ abstract class Zend_Cache
// For perfs reasons, with frontend == 'Core', we can interact with the Core itself
$frontendClass = 'Zend_Cache_' . ($frontend != 'Core' ? 'Frontend_' : '') . $frontend;
// security controls are explicit
- require_once str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php';
+ // require_once str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php';
} else {
// we use a custom frontend
if (!preg_match('~^[\w]+$~D', $frontend)) {
@@ -188,7 +189,7 @@ abstract class Zend_Cache
if (!(self::_isReadable($file))) {
self::throwException("file $file not found in include_path");
}
- require_once $file;
+ // require_once $file;
}
}
return new $frontendClass($frontendOptions);
@@ -201,11 +202,11 @@ abstract class Zend_Cache
* @param string $msg Message for the exception
* @throws Zend_Cache_Exception
*/
- public static function throwException($msg)
+ public static function throwException($msg, Exception $e = null)
{
// For perfs reasons, we use this dynamic inclusion
- require_once 'Zend/Cache/Exception.php';
- throw new Zend_Cache_Exception($msg);
+ // require_once 'Zend/Cache/Exception.php';
+ throw new Zend_Cache_Exception($msg, 0, $e);
}
/**
@@ -220,6 +221,10 @@ abstract class Zend_Cache
$name = str_replace(array('-', '_', '.'), ' ', $name);
$name = ucwords($name);
$name = str_replace(' ', '', $name);
+ if (stripos($name, 'ZendServer') === 0) {
+ $name = 'ZendServer_' . substr($name, strlen('ZendServer'));
+ }
+
return $name;
}
diff --git a/libs/Zend/Cache/Backend.php b/libs/Zend/Cache/Backend.php
index 052181972f..f71dae135a 100644
--- a/libs/Zend/Cache/Backend.php
+++ b/libs/Zend/Cache/Backend.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Backend.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Backend.php 20882 2010-02-03 18:19:44Z matthew $
*/
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend
@@ -140,77 +140,77 @@ class Zend_Cache_Backend
{
return true;
}
-
+
/**
* Determine system TMP directory and detect if we have read access
*
- * inspired from Zend_File_Transfer_Adapter_Abstract
+ * inspired from Zend_File_Transfer_Adapter_Abstract
*
* @return string
* @throws Zend_Cache_Exception if unable to determine directory
*/
public function getTmpDir()
{
- $tmpdir = array();
+ $tmpdir = array();
foreach (array($_ENV, $_SERVER) as $tab) {
- foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) {
- if (isset($tab[$key])) {
- if (($key == 'windir') or ($key == 'SystemRoot')) {
+ foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) {
+ if (isset($tab[$key])) {
+ if (($key == 'windir') or ($key == 'SystemRoot')) {
$dir = realpath($tab[$key] . '\\temp');
} else {
- $dir = realpath($tab[$key]);
+ $dir = realpath($tab[$key]);
+ }
+ if ($this->_isGoodTmpDir($dir)) {
+ return $dir;
}
- if ($this->_isGoodTmpDir($dir)) {
- return $dir;
- }
- }
- }
+ }
+ }
}
$upload = ini_get('upload_tmp_dir');
if ($upload) {
$dir = realpath($upload);
- if ($this->_isGoodTmpDir($dir)) {
- return $dir;
- }
+ if ($this->_isGoodTmpDir($dir)) {
+ return $dir;
+ }
}
if (function_exists('sys_get_temp_dir')) {
$dir = sys_get_temp_dir();
- if ($this->_isGoodTmpDir($dir)) {
- return $dir;
- }
+ if ($this->_isGoodTmpDir($dir)) {
+ return $dir;
+ }
}
// Attemp to detect by creating a temporary file
$tempFile = tempnam(md5(uniqid(rand(), TRUE)), '');
if ($tempFile) {
- $dir = realpath(dirname($tempFile));
+ $dir = realpath(dirname($tempFile));
unlink($tempFile);
if ($this->_isGoodTmpDir($dir)) {
return $dir;
}
}
if ($this->_isGoodTmpDir('/tmp')) {
- return '/tmp';
+ return '/tmp';
}
if ($this->_isGoodTmpDir('\\temp')) {
- return '\\temp';
+ return '\\temp';
}
Zend_Cache::throwException('Could not determine temp directory, please specify a cache_dir manually');
}
-
+
/**
* Verify if the given temporary directory is readable and writable
- *
+ *
* @param $dir temporary directory
* @return boolean true if the directory is ok
*/
protected function _isGoodTmpDir($dir)
{
- if (is_readable($dir)) {
- if (is_writable($dir)) {
- return true;
- }
- }
- return false;
+ if (is_readable($dir)) {
+ if (is_writable($dir)) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -226,23 +226,17 @@ class Zend_Cache_Backend
if (!isset($this->_directives['logging']) || !$this->_directives['logging']) {
return;
}
- try {
- /**
- * @see Zend_Log
- */
- require_once 'Zend/Log.php';
- } catch (Zend_Exception $e) {
- Zend_Cache::throwException('Logging feature is enabled but the Zend_Log class is not available');
- }
+
if (isset($this->_directives['logger'])) {
if ($this->_directives['logger'] instanceof Zend_Log) {
return;
- } else {
- Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
}
+ Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
}
+
// Create a default logger to the standard output stream
- require_once 'Zend/Log/Writer/Stream.php';
+ // require_once 'Zend/Log.php';
+ // require_once 'Zend/Log/Writer/Stream.php';
$logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
$this->_directives['logger'] = $logger;
}
@@ -261,7 +255,7 @@ class Zend_Cache_Backend
}
if (!isset($this->_directives['logger'])) {
- Zend_Cache::throwException('Logging is enabled but logger is not set.');
+ Zend_Cache::throwException('Logging is enabled but logger is not set.');
}
$logger = $this->_directives['logger'];
if (!$logger instanceof Zend_Log) {
diff --git a/libs/Zend/Cache/Backend/Apc.php b/libs/Zend/Cache/Backend/Apc.php
index fd99ae45ef..e25bd397bb 100644
--- a/libs/Zend/Cache/Backend/Apc.php
+++ b/libs/Zend/Cache/Backend/Apc.php
@@ -15,27 +15,27 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Apc.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Apc.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Cache_Backend_Interface
*/
-require_once 'Zend/Cache/Backend/ExtendedInterface.php';
+// require_once 'Zend/Cache/Backend/ExtendedInterface.php';
/**
* @see Zend_Cache_Backend
*/
-require_once 'Zend/Cache/Backend.php';
+// require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
@@ -166,18 +166,18 @@ class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Ba
* Return true if the automatic cleaning is available for the backend
*
* DEPRECATED : use getCapabilities() instead
- *
- * @deprecated
+ *
+ * @deprecated
* @return boolean
*/
public function isAutomaticCleaningAvailable()
{
return false;
}
-
+
/**
* Return the filling percentage of the backend storage
- *
+ *
* @throws Zend_Cache_Exception
* @return int integer between 0 and 100
*/
@@ -195,21 +195,21 @@ class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Ba
}
return ((int) (100. * ($memUsed / $memSize)));
}
-
+
/**
* Return an array of stored tags
*
* @return array array of stored tags (string)
*/
public function getTags()
- {
+ {
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
return array();
}
-
+
/**
* Return an array of stored cache ids which match given tags
- *
+ *
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
@@ -218,26 +218,26 @@ class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Ba
public function getIdsMatchingTags($tags = array())
{
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
- return array();
+ return array();
}
/**
* Return an array of stored cache ids which don't match given tags
- *
+ *
* In case of multiple tags, a logical OR is made between tags
*
* @param array $tags array of tags
* @return array array of not matching cache ids (string)
- */
+ */
public function getIdsNotMatchingTags($tags = array())
{
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
- return array();
+ return array();
}
-
+
/**
* Return an array of stored cache ids which match any given tags
- *
+ *
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
@@ -246,12 +246,12 @@ class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Ba
public function getIdsMatchingAnyTags($tags = array())
{
$this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
- return array();
+ return array();
}
-
+
/**
* Return an array of stored cache ids
- *
+ *
* @return array array of stored cache ids (string)
*/
public function getIds()
@@ -264,7 +264,7 @@ class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Ba
}
return $res;
}
-
+
/**
* Return an array of metadatas for the given cache id
*
@@ -272,7 +272,7 @@ class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Ba
* - expire : the expire timestamp
* - tags : a string array of tags
* - mtime : timestamp of last modification time
- *
+ *
* @param string $id cache id
* @return array array of metadatas (false if the cache id is not found)
*/
@@ -294,9 +294,9 @@ class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Ba
'mtime' => $mtime
);
}
- return false;
+ return false;
}
-
+
/**
* Give (if possible) an extra lifetime to the given cache id
*
@@ -318,17 +318,17 @@ class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Ba
$lifetime = $tmp[2];
$newLifetime = $lifetime - (time() - $mtime) + $extraLifetime;
if ($newLifetime <=0) {
- return false;
+ return false;
}
apc_store($id, array($data, time(), $newLifetime), $newLifetime);
return true;
}
return false;
}
-
+
/**
* Return an associative array of capabilities (booleans) of the backend
- *
+ *
* The array must include these keys :
* - automatic_cleaning (is automating cleaning necessary)
* - tags (are tags supported)
@@ -337,7 +337,7 @@ class Zend_Cache_Backend_Apc extends Zend_Cache_Backend implements Zend_Cache_Ba
* - priority does the backend deal with priority when saving
* - infinite_lifetime (is infinite lifetime can work with this backend)
* - get_list (is it possible to get the list of cache ids and the complete list of tags)
- *
+ *
* @return array associative of with capabilities
*/
public function getCapabilities()
diff --git a/libs/Zend/Cache/Backend/BlackHole.php b/libs/Zend/Cache/Backend/BlackHole.php
new file mode 100644
index 0000000000..3eb382eca2
--- /dev/null
+++ b/libs/Zend/Cache/Backend/BlackHole.php
@@ -0,0 +1,250 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Cache
+ * @subpackage Zend_Cache_Backend
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: BlackHole.php 17867 2009-08-28 09:42:11Z yoshida@zend.co.jp $
+ */
+
+/**
+ * @see Zend_Cache_Backend_Interface
+ */
+// require_once 'Zend/Cache/Backend/ExtendedInterface.php';
+
+/**
+ * @see Zend_Cache_Backend
+ */
+// require_once 'Zend/Cache/Backend.php';
+
+/**
+ * @package Zend_Cache
+ * @subpackage Zend_Cache_Backend
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Cache_Backend_BlackHole
+ extends Zend_Cache_Backend
+ implements Zend_Cache_Backend_ExtendedInterface
+{
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * @param string $id cache id
+ * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
+ * @return string|false cached datas
+ */
+ public function load($id, $doNotTestCacheValidity = false)
+ {
+ return false;
+ }
+
+ /**
+ * Test if a cache is available or not (for the given id)
+ *
+ * @param string $id cache id
+ * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+ */
+ public function test($id)
+ {
+ return false;
+ }
+
+ /**
+ * Save some string datas into a cache record
+ *
+ * Note : $data is always "string" (serialization is done by the
+ * core not by the backend)
+ *
+ * @param string $data Datas to cache
+ * @param string $id Cache id
+ * @param array $tags Array of strings, the cache record will be tagged by each string entry
+ * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
+ * @return boolean true if no problem
+ */
+ public function save($data, $id, $tags = array(), $specificLifetime = false)
+ {
+ return true;
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id cache id
+ * @return boolean true if no problem
+ */
+ public function remove($id)
+ {
+ return true;
+ }
+
+ /**
+ * Clean some cache records
+ *
+ * Available modes are :
+ * 'all' (default) => remove all cache entries ($tags is not used)
+ * 'old' => remove too old cache entries ($tags is not used)
+ * 'matchingTag' => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * 'notMatchingTag' => remove cache entries not matching one of the given tags
+ * ($tags can be an array of strings or a single string)
+ * 'matchingAnyTag' => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @param string $mode clean mode
+ * @param tags array $tags array of tags
+ * @return boolean true if no problem
+ */
+ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
+ {
+ return true;
+ }
+
+ /**
+ * Return an array of stored cache ids
+ *
+ * @return array array of stored cache ids (string)
+ */
+ public function getIds()
+ {
+ return array();
+ }
+
+ /**
+ * Return an array of stored tags
+ *
+ * @return array array of stored tags (string)
+ */
+ public function getTags()
+ {
+ return array();
+ }
+
+ /**
+ * Return an array of stored cache ids which match given tags
+ *
+ * In case of multiple tags, a logical AND is made between tags
+ *
+ * @param array $tags array of tags
+ * @return array array of matching cache ids (string)
+ */
+ public function getIdsMatchingTags($tags = array())
+ {
+ return array();
+ }
+
+ /**
+ * Return an array of stored cache ids which don't match given tags
+ *
+ * In case of multiple tags, a logical OR is made between tags
+ *
+ * @param array $tags array of tags
+ * @return array array of not matching cache ids (string)
+ */
+ public function getIdsNotMatchingTags($tags = array())
+ {
+ return array();
+ }
+
+ /**
+ * Return an array of stored cache ids which match any given tags
+ *
+ * In case of multiple tags, a logical AND is made between tags
+ *
+ * @param array $tags array of tags
+ * @return array array of any matching cache ids (string)
+ */
+ public function getIdsMatchingAnyTags($tags = array())
+ {
+ return array();
+ }
+
+ /**
+ * Return the filling percentage of the backend storage
+ *
+ * @return int integer between 0 and 100
+ * @throws Zend_Cache_Exception
+ */
+ public function getFillingPercentage()
+ {
+ return 0;
+ }
+
+ /**
+ * Return an array of metadatas for the given cache id
+ *
+ * The array must include these keys :
+ * - expire : the expire timestamp
+ * - tags : a string array of tags
+ * - mtime : timestamp of last modification time
+ *
+ * @param string $id cache id
+ * @return array array of metadatas (false if the cache id is not found)
+ */
+ public function getMetadatas($id)
+ {
+ return false;
+ }
+
+ /**
+ * Give (if possible) an extra lifetime to the given cache id
+ *
+ * @param string $id cache id
+ * @param int $extraLifetime
+ * @return boolean true if ok
+ */
+ public function touch($id, $extraLifetime)
+ {
+ return false;
+ }
+
+ /**
+ * Return an associative array of capabilities (booleans) of the backend
+ *
+ * The array must include these keys :
+ * - automatic_cleaning (is automating cleaning necessary)
+ * - tags (are tags supported)
+ * - expired_read (is it possible to read expired cache records
+ * (for doNotTestCacheValidity option for example))
+ * - priority does the backend deal with priority when saving
+ * - infinite_lifetime (is infinite lifetime can work with this backend)
+ * - get_list (is it possible to get the list of cache ids and the complete list of tags)
+ *
+ * @return array associative of with capabilities
+ */
+ public function getCapabilities()
+ {
+ return array(
+ 'automatic_cleaning' => true,
+ 'tags' => true,
+ 'expired_read' => true,
+ 'priority' => true,
+ 'infinite_lifetime' => true,
+ 'get_list' => true,
+ );
+ }
+
+ /**
+ * PUBLIC METHOD FOR UNIT TESTING ONLY !
+ *
+ * Force a cache record to expire
+ *
+ * @param string $id cache id
+ */
+ public function ___expire($id)
+ {
+ }
+}
diff --git a/libs/Zend/Cache/Backend/ExtendedInterface.php b/libs/Zend/Cache/Backend/ExtendedInterface.php
index 22e559b25b..f24ecc1091 100644
--- a/libs/Zend/Cache/Backend/ExtendedInterface.php
+++ b/libs/Zend/Cache/Backend/ExtendedInterface.php
@@ -15,20 +15,20 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: ExtendedInterface.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: ExtendedInterface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Cache_Backend_Interface
*/
-require_once 'Zend/Cache/Backend/Interface.php';
+// require_once 'Zend/Cache/Backend/Interface.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Cache_Backend_ExtendedInterface extends Zend_Cache_Backend_Interface
@@ -36,21 +36,21 @@ interface Zend_Cache_Backend_ExtendedInterface extends Zend_Cache_Backend_Interf
/**
* Return an array of stored cache ids
- *
+ *
* @return array array of stored cache ids (string)
*/
public function getIds();
-
+
/**
* Return an array of stored tags
*
* @return array array of stored tags (string)
*/
public function getTags();
-
+
/**
* Return an array of stored cache ids which match given tags
- *
+ *
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
@@ -60,24 +60,24 @@ interface Zend_Cache_Backend_ExtendedInterface extends Zend_Cache_Backend_Interf
/**
* Return an array of stored cache ids which don't match given tags
- *
+ *
* In case of multiple tags, a logical OR is made between tags
*
* @param array $tags array of tags
* @return array array of not matching cache ids (string)
- */
+ */
public function getIdsNotMatchingTags($tags = array());
/**
* Return an array of stored cache ids which match any given tags
- *
+ *
* In case of multiple tags, a logical AND is made between tags
*
* @param array $tags array of tags
* @return array array of any matching cache ids (string)
*/
public function getIdsMatchingAnyTags($tags = array());
-
+
/**
* Return the filling percentage of the backend storage
*
@@ -92,12 +92,12 @@ interface Zend_Cache_Backend_ExtendedInterface extends Zend_Cache_Backend_Interf
* - expire : the expire timestamp
* - tags : a string array of tags
* - mtime : timestamp of last modification time
- *
+ *
* @param string $id cache id
* @return array array of metadatas (false if the cache id is not found)
*/
public function getMetadatas($id);
-
+
/**
* Give (if possible) an extra lifetime to the given cache id
*
@@ -106,10 +106,10 @@ interface Zend_Cache_Backend_ExtendedInterface extends Zend_Cache_Backend_Interf
* @return boolean true if ok
*/
public function touch($id, $extraLifetime);
-
+
/**
* Return an associative array of capabilities (booleans) of the backend
- *
+ *
* The array must include these keys :
* - automatic_cleaning (is automating cleaning necessary)
* - tags (are tags supported)
@@ -118,9 +118,9 @@ interface Zend_Cache_Backend_ExtendedInterface extends Zend_Cache_Backend_Interf
* - priority does the backend deal with priority when saving
* - infinite_lifetime (is infinite lifetime can work with this backend)
* - get_list (is it possible to get the list of cache ids and the complete list of tags)
- *
+ *
* @return array associative of with capabilities
*/
public function getCapabilities();
-
+
}
diff --git a/libs/Zend/Cache/Backend/File.php b/libs/Zend/Cache/Backend/File.php
index 51e2697ad9..eeddfa5b80 100644
--- a/libs/Zend/Cache/Backend/File.php
+++ b/libs/Zend/Cache/Backend/File.php
@@ -15,26 +15,26 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: File.php 17868 2009-08-28 09:46:30Z yoshida@zend.co.jp $
+ * @version $Id: File.php 21642 2010-03-25 17:07:02Z mabe $
*/
/**
* @see Zend_Cache_Backend_Interface
*/
-require_once 'Zend/Cache/Backend/ExtendedInterface.php';
+// require_once 'Zend/Cache/Backend/ExtendedInterface.php';
/**
* @see Zend_Cache_Backend
*/
-require_once 'Zend/Cache/Backend.php';
+// require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_File extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
@@ -123,8 +123,8 @@ class Zend_Cache_Backend_File extends Zend_Cache_Backend implements Zend_Cache_B
$this->setCacheDir(self::getTmpDir() . DIRECTORY_SEPARATOR, false);
}
if (isset($this->_options['file_name_prefix'])) { // particular case for this option
- if (!preg_match('~^[\w]+$~', $this->_options['file_name_prefix'])) {
- Zend_Cache::throwException('Invalid file_name_prefix : must use only [a-zA-A0-9_]');
+ if (!preg_match('~^[a-zA-Z0-9_]+$~D', $this->_options['file_name_prefix'])) {
+ Zend_Cache::throwException('Invalid file_name_prefix : must use only [a-zA-Z0-9_]');
}
}
if ($this->_options['metadatas_array_max_size'] < 10) {
@@ -647,6 +647,7 @@ class Zend_Cache_Backend_File extends Zend_Cache_Backend implements Zend_Cache_B
$prefix = $this->_options['file_name_prefix'];
$glob = @glob($dir . $prefix . '--*');
if ($glob === false) {
+ // On some systems it is impossible to distinguish between empty match and an error.
return true;
}
foreach ($glob as $file) {
@@ -739,7 +740,8 @@ class Zend_Cache_Backend_File extends Zend_Cache_Backend implements Zend_Cache_B
$prefix = $this->_options['file_name_prefix'];
$glob = @glob($dir . $prefix . '--*');
if ($glob === false) {
- return true;
+ // On some systems it is impossible to distinguish between empty match and an error.
+ return array();
}
foreach ($glob as $file) {
if (is_file($file)) {
@@ -802,7 +804,12 @@ class Zend_Cache_Backend_File extends Zend_Cache_Backend implements Zend_Cache_B
}
if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) {
// Recursive call
- $result = array_unique(array_merge($result, $this->_get($file . DIRECTORY_SEPARATOR, $mode, $tags)));
+ $recursiveRs = $this->_get($file . DIRECTORY_SEPARATOR, $mode, $tags);
+ if ($recursiveRs === false) {
+ $this->_log('Zend_Cache_Backend_File::_get() / recursive call : can\'t list entries of "'.$file.'"');
+ } else {
+ $result = array_unique(array_merge($result, $recursiveRs));
+ }
}
}
return array_unique($result);
diff --git a/libs/Zend/Cache/Backend/Interface.php b/libs/Zend/Cache/Backend/Interface.php
index f2878f95ae..3e8c7d1211 100644
--- a/libs/Zend/Cache/Backend/Interface.php
+++ b/libs/Zend/Cache/Backend/Interface.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Cache_Backend_Interface
diff --git a/libs/Zend/Cache/Backend/Memcached.php b/libs/Zend/Cache/Backend/Memcached.php
index 86bbca3a1c..3c29bcce67 100644
--- a/libs/Zend/Cache/Backend/Memcached.php
+++ b/libs/Zend/Cache/Backend/Memcached.php
@@ -15,27 +15,27 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Memcached.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Memcached.php 22208 2010-05-20 16:59:02Z mabe $
*/
/**
* @see Zend_Cache_Backend_Interface
*/
-require_once 'Zend/Cache/Backend/ExtendedInterface.php';
+// require_once 'Zend/Cache/Backend/ExtendedInterface.php';
/**
* @see Zend_Cache_Backend
*/
-require_once 'Zend/Cache/Backend.php';
+// require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_Memcached extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
@@ -155,16 +155,16 @@ class Zend_Cache_Backend_Memcached extends Zend_Cache_Backend implements Zend_Ca
$server['failure_callback'] = self::DEFAULT_FAILURE_CALLBACK;
}
if ($this->_options['compatibility']) {
- // No status for compatibility mode (#ZF-5887)
- $this->_memcache->addServer($server['host'], $server['port'], $server['persistent'],
+ // No status for compatibility mode (#ZF-5887)
+ $this->_memcache->addServer($server['host'], $server['port'], $server['persistent'],
$server['weight'], $server['timeout'],
$server['retry_interval']);
- } else {
- $this->_memcache->addServer($server['host'], $server['port'], $server['persistent'],
+ } else {
+ $this->_memcache->addServer($server['host'], $server['port'], $server['persistent'],
$server['weight'], $server['timeout'],
$server['retry_interval'],
$server['status'], $server['failure_callback']);
- }
+ }
}
}
@@ -178,7 +178,7 @@ class Zend_Cache_Backend_Memcached extends Zend_Cache_Backend implements Zend_Ca
public function load($id, $doNotTestCacheValidity = false)
{
$tmp = $this->_memcache->get($id);
- if (is_array($tmp)) {
+ if (is_array($tmp) && isset($tmp[0])) {
return $tmp[0];
}
return false;
@@ -219,13 +219,14 @@ class Zend_Cache_Backend_Memcached extends Zend_Cache_Backend implements Zend_Ca
} else {
$flag = 0;
}
- // #ZF-5702 : we try add() first becase set() seems to be slower
- if (!($result = $this->_memcache->add($id, array($data, time(), $lifetime), $flag, $lifetime))) {
- $result = $this->_memcache->set($id, array($data, time(), $lifetime), $flag, $lifetime);
- }
+
+ // ZF-8856: using set because add needs a second request if item already exists
+ $result = @$this->_memcache->set($id, array($data, time(), $lifetime), $flag, $lifetime);
+
if (count($tags) > 0) {
- $this->_log("Zend_Cache_Backend_Memcached::save() : tags are unsupported by the Memcached backend");
+ $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND);
}
+
return $result;
}
@@ -237,7 +238,7 @@ class Zend_Cache_Backend_Memcached extends Zend_Cache_Backend implements Zend_Ca
*/
public function remove($id)
{
- return $this->_memcache->delete($id);
+ return $this->_memcache->delete($id, 0);
}
/**
@@ -380,25 +381,26 @@ class Zend_Cache_Backend_Memcached extends Zend_Cache_Backend implements Zend_Ca
{
$mems = $this->_memcache->getExtendedStats();
- $memSize = 0;
- $memUsed = 0;
+ $memSize = null;
+ $memUsed = null;
foreach ($mems as $key => $mem) {
- if ($mem === false) {
- Zend_Cache::throwException('can\'t get stat from ' . $key);
- } else {
- $eachSize = $mem['limit_maxbytes'];
- if ($eachSize == 0) {
- Zend_Cache::throwException('can\'t get memory size from ' . $key);
- }
-
- $eachUsed = $mem['bytes'];
- if ($eachUsed > $eachSize) {
- $eachUsed = $eachSize;
- }
-
- $memSize += $eachSize;
- $memUsed += $eachUsed;
- }
+ if ($mem === false) {
+ $this->_log('can\'t get stat from ' . $key);
+ continue;
+ }
+
+ $eachSize = $mem['limit_maxbytes'];
+ $eachUsed = $mem['bytes'];
+ if ($eachUsed > $eachSize) {
+ $eachUsed = $eachSize;
+ }
+
+ $memSize += $eachSize;
+ $memUsed += $eachUsed;
+ }
+
+ if ($memSize === null || $memUsed === null) {
+ Zend_Cache::throwException('Can\'t get filling percentage');
}
return ((int) (100. * ($memUsed / $memSize)));
@@ -466,7 +468,7 @@ class Zend_Cache_Backend_Memcached extends Zend_Cache_Backend implements Zend_Ca
}
// #ZF-5702 : we try replace() first becase set() seems to be slower
if (!($result = $this->_memcache->replace($id, array($data, time(), $newLifetime), $flag, $newLifetime))) {
- $result = $this->_memcache->set($id, array($data, time(), $newLifetime), $flag, $newLifetime);
+ $result = $this->_memcache->set($id, array($data, time(), $newLifetime), $flag, $newLifetime);
}
return $result;
}
diff --git a/libs/Zend/Cache/Backend/Sqlite.php b/libs/Zend/Cache/Backend/Sqlite.php
index 7430d7303b..3bb5ba91e3 100644
--- a/libs/Zend/Cache/Backend/Sqlite.php
+++ b/libs/Zend/Cache/Backend/Sqlite.php
@@ -15,26 +15,26 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Sqlite.php 17868 2009-08-28 09:46:30Z yoshida@zend.co.jp $
+ * @version $Id: Sqlite.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Cache_Backend_Interface
*/
-require_once 'Zend/Cache/Backend/ExtendedInterface.php';
+// require_once 'Zend/Cache/Backend/ExtendedInterface.php';
/**
* @see Zend_Cache_Backend
*/
-require_once 'Zend/Cache/Backend.php';
+// require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_Sqlite extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
diff --git a/libs/Zend/Cache/Backend/Static.php b/libs/Zend/Cache/Backend/Static.php
new file mode 100644
index 0000000000..19d83d5fd4
--- /dev/null
+++ b/libs/Zend/Cache/Backend/Static.php
@@ -0,0 +1,558 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Cache
+ * @subpackage Zend_Cache_Backend
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: BlackHole.php 17867 2009-08-28 09:42:11Z yoshida@zend.co.jp $
+ */
+
+/**
+ * @see Zend_Cache_Backend_Interface
+ */
+// require_once 'Zend/Cache/Backend/Interface.php';
+
+/**
+ * @see Zend_Cache_Backend
+ */
+// require_once 'Zend/Cache/Backend.php';
+
+/**
+ * @package Zend_Cache
+ * @subpackage Zend_Cache_Backend
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Cache_Backend_Static
+ extends Zend_Cache_Backend
+ implements Zend_Cache_Backend_Interface
+{
+ const INNER_CACHE_NAME = 'zend_cache_backend_static_tagcache';
+
+ /**
+ * Static backend options
+ * @var array
+ */
+ protected $_options = array(
+ 'public_dir' => null,
+ 'sub_dir' => 'html',
+ 'file_extension' => '.html',
+ 'index_filename' => 'index',
+ 'file_locking' => true,
+ 'cache_file_umask' => 0600,
+ 'cache_directory_umask' => 0700,
+ 'debug_header' => false,
+ 'tag_cache' => null,
+ 'disable_caching' => false
+ );
+
+ /**
+ * Cache for handling tags
+ * @var Zend_Cache_Core
+ */
+ protected $_tagCache = null;
+
+ /**
+ * Tagged items
+ * @var array
+ */
+ protected $_tagged = null;
+
+ /**
+ * Interceptor child method to handle the case where an Inner
+ * Cache object is being set since it's not supported by the
+ * standard backend interface
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return Zend_Cache_Backend_Static
+ */
+ public function setOption($name, $value)
+ {
+ if ($name == 'tag_cache') {
+ $this->setInnerCache($value);
+ } else {
+ parent::setOption($name, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * Retrieve any option via interception of the parent's statically held
+ * options including the local option for a tag cache.
+ *
+ * @param string $name
+ * @return mixed
+ */
+ public function getOption($name)
+ {
+ if ($name == 'tag_cache') {
+ return $this->getInnerCache();
+ } else {
+ if (in_array($name, $this->_options)) {
+ return $this->_options[$name];
+ }
+ if ($name == 'lifetime') {
+ return parent::getLifetime();
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * Note : return value is always "string" (unserialization is done by the core not by the backend)
+ *
+ * @param string $id Cache id
+ * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+ * @return string|false cached datas
+ */
+ public function load($id, $doNotTestCacheValidity = false)
+ {
+ if (empty($id)) {
+ $id = $this->_detectId();
+ } else {
+ $id = $this->_decodeId($id);
+ }
+ if (!$this->_verifyPath($id)) {
+ Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
+ }
+ if ($doNotTestCacheValidity) {
+ $this->_log("Zend_Cache_Backend_Static::load() : \$doNotTestCacheValidity=true is unsupported by the Static backend");
+ }
+
+ $fileName = basename($id);
+ if (empty($fileName)) {
+ $fileName = $this->_options['index_filename'];
+ }
+ $pathName = $this->_options['public_dir'] . dirname($id);
+ $file = rtrim($pathName, '/') . '/' . $fileName . $this->_options['file_extension'];
+ if (file_exists($file)) {
+ $content = file_get_contents($file);
+ return $content;
+ }
+
+ return false;
+ }
+
+ /**
+ * Test if a cache is available or not (for the given id)
+ *
+ * @param string $id cache id
+ * @return bool
+ */
+ public function test($id)
+ {
+ $id = $this->_decodeId($id);
+ if (!$this->_verifyPath($id)) {
+ Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
+ }
+
+ $fileName = basename($id);
+ if (empty($fileName)) {
+ $fileName = $this->_options['index_filename'];
+ }
+ if (is_null($this->_tagged) && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
+ $this->_tagged = $tagged;
+ } elseif (!$this->_tagged) {
+ return false;
+ }
+ $pathName = $this->_options['public_dir'] . dirname($id);
+
+ // Switch extension if needed
+ if (isset($this->_tagged[$id])) {
+ $extension = $this->_tagged[$id]['extension'];
+ } else {
+ $extension = $this->_options['file_extension'];
+ }
+ $file = $pathName . '/' . $fileName . $extension;
+ if (file_exists($file)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Save some string datas into a cache record
+ *
+ * Note : $data is always "string" (serialization is done by the
+ * core not by the backend)
+ *
+ * @param string $data Datas to cache
+ * @param string $id Cache id
+ * @param array $tags Array of strings, the cache record will be tagged by each string entry
+ * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
+ * @return boolean true if no problem
+ */
+ public function save($data, $id, $tags = array(), $specificLifetime = false)
+ {
+ if ($this->_options['disable_caching']) {
+ return true;
+ }
+ $extension = null;
+ if ($this->_isSerialized($data)) {
+ $data = unserialize($data);
+ $extension = '.' . ltrim($data[1], '.');
+ $data = $data[0];
+ }
+
+ clearstatcache();
+ if (is_null($id) || strlen($id) == 0) {
+ $id = $this->_detectId();
+ } else {
+ $id = $this->_decodeId($id);
+ }
+
+ $fileName = basename($id);
+ if (empty($fileName)) {
+ $fileName = $this->_options['index_filename'];
+ }
+
+ $pathName = realpath($this->_options['public_dir']) . dirname($id);
+ $this->_createDirectoriesFor($pathName);
+
+ if (is_null($id) || strlen($id) == 0) {
+ $dataUnserialized = unserialize($data);
+ $data = $dataUnserialized['data'];
+ }
+ $ext = $this->_options['file_extension'];
+ if ($extension) $ext = $extension;
+ $file = rtrim($pathName, '/') . '/' . $fileName . $ext;
+ if ($this->_options['file_locking']) {
+ $result = file_put_contents($file, $data, LOCK_EX);
+ } else {
+ $result = file_put_contents($file, $data);
+ }
+ @chmod($file, $this->_octdec($this->_options['cache_file_umask']));
+
+ if (is_null($this->_tagged) && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
+ $this->_tagged = $tagged;
+ } elseif (is_null($this->_tagged)) {
+ $this->_tagged = array();
+ }
+ if (!isset($this->_tagged[$id])) {
+ $this->_tagged[$id] = array();
+ }
+ if (!isset($this->_tagged[$id]['tags'])) {
+ $this->_tagged[$id]['tags'] = array();
+ }
+ $this->_tagged[$id]['tags'] = array_unique(array_merge($this->_tagged[$id]['tags'], $tags));
+ $this->_tagged[$id]['extension'] = $ext;
+ $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
+ return (bool) $result;
+ }
+
+ /**
+ * Recursively create the directories needed to write the static file
+ */
+ protected function _createDirectoriesFor($path)
+ {
+ $parts = explode('/', $path);
+ $directory = '';
+ foreach ($parts as $part) {
+ $directory = rtrim($directory, '/') . '/' . $part;
+ if (!is_dir($directory)) {
+ mkdir($directory, $this->_octdec($this->_options['cache_directory_umask']));
+ }
+ }
+ }
+
+ /**
+ * Detect serialization of data (cannot predict since this is the only way
+ * to obey the interface yet pass in another parameter).
+ *
+ * In future, ZF 2.0, check if we can just avoid the interface restraints.
+ *
+ * This format is the only valid one possible for the class, so it's simple
+ * to just run a regular expression for the starting serialized format.
+ */
+ protected function _isSerialized($data)
+ {
+ return preg_match("/a:2:\{i:0;s:\d+:\"/", $data);
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ public function remove($id)
+ {
+ if (!$this->_verifyPath($id)) {
+ Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
+ }
+ $fileName = basename($id);
+ if (is_null($this->_tagged) && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
+ $this->_tagged = $tagged;
+ } elseif (!$this->_tagged) {
+ return false;
+ }
+ if (isset($this->_tagged[$id])) {
+ $extension = $this->_tagged[$id]['extension'];
+ } else {
+ $extension = $this->_options['file_extension'];
+ }
+ if (empty($fileName)) {
+ $fileName = $this->_options['index_filename'];
+ }
+ $pathName = $this->_options['public_dir'] . dirname($id);
+ $file = realpath($pathName) . '/' . $fileName . $extension;
+ if (!file_exists($file)) {
+ return false;
+ }
+ return unlink($file);
+ }
+
+ /**
+ * Remove a cache record recursively for the given directory matching a
+ * REQUEST_URI based relative path (deletes the actual file matching this
+ * in addition to the matching directory)
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ public function removeRecursively($id)
+ {
+ if (!$this->_verifyPath($id)) {
+ Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
+ }
+ $fileName = basename($id);
+ if (empty($fileName)) {
+ $fileName = $this->_options['index_filename'];
+ }
+ $pathName = $this->_options['public_dir'] . dirname($id);
+ $file = $pathName . '/' . $fileName . $this->_options['file_extension'];
+ $directory = $pathName . '/' . $fileName;
+ if (file_exists($directory)) {
+ if (!is_writable($directory)) {
+ return false;
+ }
+ foreach (new DirectoryIterator($directory) as $file) {
+ if (true === $file->isFile()) {
+ if (false === unlink($file->getPathName())) {
+ return false;
+ }
+ }
+ }
+ rmdir(dirname($path));
+ }
+ if (file_exists($file)) {
+ if (!is_writable($file)) {
+ return false;
+ }
+ return unlink($file);
+ }
+ return true;
+ }
+
+ /**
+ * Clean some cache records
+ *
+ * Available modes are :
+ * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @param string $mode Clean mode
+ * @param array $tags Array of tags
+ * @return boolean true if no problem
+ */
+ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
+ {
+ $result = false;
+ switch ($mode) {
+ case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
+ case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
+ if (empty($tags)) {
+ throw new Zend_Exception('Cannot use tag matching modes as no tags were defined');
+ }
+ if (is_null($this->_tagged) && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
+ $this->_tagged = $tagged;
+ } elseif (!$this->_tagged) {
+ return true;
+ }
+ foreach ($tags as $tag) {
+ $urls = array_keys($this->_tagged);
+ foreach ($urls as $url) {
+ if (isset($this->_tagged[$url]['tags']) && in_array($tag, $this->_tagged[$url]['tags'])) {
+ $this->remove($url);
+ unset($this->_tagged[$url]);
+ }
+ }
+ }
+ $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
+ $result = true;
+ break;
+ case Zend_Cache::CLEANING_MODE_ALL:
+ if (is_null($this->_tagged)) {
+ $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME);
+ $this->_tagged = $tagged;
+ }
+ if (is_null($this->_tagged) || empty($this->_tagged)) {
+ return true;
+ }
+ $urls = array_keys($this->_tagged);
+ foreach ($urls as $url) {
+ $this->remove($url);
+ unset($this->_tagged[$url]);
+ }
+ $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
+ $result = true;
+ break;
+ case Zend_Cache::CLEANING_MODE_OLD:
+ $this->_log("Zend_Cache_Backend_Static : Selected Cleaning Mode Currently Unsupported By This Backend");
+ break;
+ case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
+ if (empty($tags)) {
+ throw new Zend_Exception('Cannot use tag matching modes as no tags were defined');
+ }
+ if (is_null($this->_tagged)) {
+ $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME);
+ $this->_tagged = $tagged;
+ }
+ if (is_null($this->_tagged) || empty($this->_tagged)) {
+ return true;
+ }
+ $urls = array_keys($this->_tagged);
+ foreach ($urls as $url) {
+ $difference = array_diff($tags, $this->_tagged[$url]['tags']);
+ if (count($tags) == count($difference)) {
+ $this->remove($url);
+ unset($this->_tagged[$url]);
+ }
+ }
+ $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
+ $result = true;
+ break;
+ default:
+ Zend_Cache::throwException('Invalid mode for clean() method');
+ break;
+ }
+ return $result;
+ }
+
+ /**
+ * Set an Inner Cache, used here primarily to store Tags associated
+ * with caches created by this backend. Note: If Tags are lost, the cache
+ * should be completely cleaned as the mapping of tags to caches will
+ * have been irrevocably lost.
+ *
+ * @param Zend_Cache_Core
+ * @return void
+ */
+ public function setInnerCache(Zend_Cache_Core $cache)
+ {
+ $this->_tagCache = $cache;
+ $this->_options['tag_cache'] = $cache;
+ }
+
+ /**
+ * Get the Inner Cache if set
+ *
+ * @return Zend_Cache_Core
+ */
+ public function getInnerCache()
+ {
+ if (is_null($this->_tagCache)) {
+ Zend_Cache::throwException('An Inner Cache has not been set; use setInnerCache()');
+ }
+ return $this->_tagCache;
+ }
+
+ /**
+ * Verify path exists and is non-empty
+ *
+ * @param string $path
+ * @return bool
+ */
+ protected function _verifyPath($path)
+ {
+ $path = realpath($path);
+ $base = realpath($this->_options['public_dir']);
+ return strncmp($path, $base, strlen($base)) !== 0;
+ }
+
+ /**
+ * Determine the page to save from the request
+ *
+ * @return string
+ */
+ protected function _detectId()
+ {
+ return $_SERVER['REQUEST_URI'];
+ }
+
+ /**
+ * Validate a cache id or a tag (security, reliable filenames, reserved prefixes...)
+ *
+ * Throw an exception if a problem is found
+ *
+ * @param string $string Cache id or tag
+ * @throws Zend_Cache_Exception
+ * @return void
+ * @deprecated Not usable until perhaps ZF 2.0
+ */
+ protected static function _validateIdOrTag($string)
+ {
+ if (!is_string($string)) {
+ Zend_Cache::throwException('Invalid id or tag : must be a string');
+ }
+
+ // Internal only checked in Frontend - not here!
+ if (substr($string, 0, 9) == 'internal-') {
+ return;
+ }
+
+ // Validation assumes no query string, fragments or scheme included - only the path
+ if (!preg_match(
+ '/^(?:\/(?:(?:%[[:xdigit:]]{2}|[A-Za-z0-9-_.!~*\'()\[\]:@&=+$,;])*)?)+$/',
+ $string
+ )
+ ) {
+ Zend_Cache::throwException("Invalid id or tag '$string' : must be a valid URL path");
+ }
+ }
+
+ /**
+ * Detect an octal string and return its octal value for file permission ops
+ * otherwise return the non-string (assumed octal or decimal int already)
+ *
+ * @param $val The potential octal in need of conversion
+ * @return int
+ */
+ protected function _octdec($val)
+ {
+ if (decoct(octdec($val)) == $val && is_string($val)) {
+ return octdec($val);
+ }
+ return $val;
+ }
+
+ /**
+ * Decode a request URI from the provided ID
+ */
+ protected function _decodeId($id)
+ {
+ return pack('H*', $id);;
+ }
+}
diff --git a/libs/Zend/Cache/Backend/Test.php b/libs/Zend/Cache/Backend/Test.php
index 713b48954a..f143ab4609 100644
--- a/libs/Zend/Cache/Backend/Test.php
+++ b/libs/Zend/Cache/Backend/Test.php
@@ -15,29 +15,29 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Test.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Test.php 21292 2010-03-02 10:25:22Z mabe $
*/
/**
* @see Zend_Cache_Backend_Interface
*/
-require_once 'Zend/Cache/Backend/Interface.php';
+// require_once 'Zend/Cache/Backend/ExtendedInterface.php';
/**
* @see Zend_Cache_Backend
*/
-require_once 'Zend/Cache/Backend.php';
+// require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Cache_Backend_Test extends Zend_Cache_Backend implements Zend_Cache_Backend_Interface
+class Zend_Cache_Backend_Test extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
{
/**
* Available options
@@ -103,7 +103,11 @@ class Zend_Cache_Backend_Test extends Zend_Cache_Backend implements Zend_Cache_B
public function load($id, $doNotTestCacheValidity = false)
{
$this->_addLog('get', array($id, $doNotTestCacheValidity));
- if ($id=='false') {
+ if ( $id == 'false'
+ || $id == 'd8523b3ee441006261eeffa5c3d3a0a7'
+ || $id == 'e83249ea22178277d5befc2c5e2e9ace'
+ || $id == '40f649b94977c0a6e76902e2a0b43587')
+ {
return false;
}
if ($id=='serialized') {
@@ -136,10 +140,7 @@ class Zend_Cache_Backend_Test extends Zend_Cache_Backend implements Zend_Cache_B
if ($id=='false') {
return false;
}
- if (($id=='d8523b3ee441006261eeffa5c3d3a0a7') or ($id=='3c439c922209e2cb0b54d6deffccd75a')) {
- return false;
- }
- if (($id=='40f649b94977c0a6e76902e2a0b43587') or ($id=='e83249ea22178277d5befc2c5e2e9ace')) {
+ if (($id=='3c439c922209e2cb0b54d6deffccd75a')) {
return false;
}
return 123456;
@@ -252,6 +253,145 @@ class Zend_Cache_Backend_Test extends Zend_Cache_Backend implements Zend_Cache_B
}
/**
+ * Return an array of stored cache ids
+ *
+ * @return array array of stored cache ids (string)
+ */
+ public function getIds()
+ {
+ return array(
+ 'prefix_id1', 'prefix_id2'
+ );
+ }
+
+ /**
+ * Return an array of stored tags
+ *
+ * @return array array of stored tags (string)
+ */
+ public function getTags()
+ {
+ return array(
+ 'tag1', 'tag2'
+ );
+ }
+
+ /**
+ * Return an array of stored cache ids which match given tags
+ *
+ * In case of multiple tags, a logical AND is made between tags
+ *
+ * @param array $tags array of tags
+ * @return array array of matching cache ids (string)
+ */
+ public function getIdsMatchingTags($tags = array())
+ {
+ if ($tags == array('tag1', 'tag2')) {
+ return array('prefix_id1', 'prefix_id2');
+ }
+
+ return array();
+ }
+
+ /**
+ * Return an array of stored cache ids which don't match given tags
+ *
+ * In case of multiple tags, a logical OR is made between tags
+ *
+ * @param array $tags array of tags
+ * @return array array of not matching cache ids (string)
+ */
+ public function getIdsNotMatchingTags($tags = array())
+ {
+ if ($tags == array('tag3', 'tag4')) {
+ return array('prefix_id3', 'prefix_id4');
+ }
+
+ return array();
+ }
+
+ /**
+ * Return an array of stored cache ids which match any given tags
+ *
+ * In case of multiple tags, a logical AND is made between tags
+ *
+ * @param array $tags array of tags
+ * @return array array of any matching cache ids (string)
+ */
+ public function getIdsMatchingAnyTags($tags = array())
+ {
+ if ($tags == array('tag5', 'tag6')) {
+ return array('prefix_id5', 'prefix_id6');
+ }
+
+ return array();
+ }
+
+ /**
+ * Return the filling percentage of the backend storage
+ *
+ * @return int integer between 0 and 100
+ */
+ public function getFillingPercentage()
+ {
+ return 50;
+ }
+
+ /**
+ * Return an array of metadatas for the given cache id
+ *
+ * The array must include these keys :
+ * - expire : the expire timestamp
+ * - tags : a string array of tags
+ * - mtime : timestamp of last modification time
+ *
+ * @param string $id cache id
+ * @return array array of metadatas (false if the cache id is not found)
+ */
+ public function getMetadatas($id)
+ {
+ return false;
+ }
+
+ /**
+ * Give (if possible) an extra lifetime to the given cache id
+ *
+ * @param string $id cache id
+ * @param int $extraLifetime
+ * @return boolean true if ok
+ */
+ public function touch($id, $extraLifetime)
+ {
+ return true;
+ }
+
+ /**
+ * Return an associative array of capabilities (booleans) of the backend
+ *
+ * The array must include these keys :
+ * - automatic_cleaning (is automating cleaning necessary)
+ * - tags (are tags supported)
+ * - expired_read (is it possible to read expired cache records
+ * (for doNotTestCacheValidity option for example))
+ * - priority does the backend deal with priority when saving
+ * - infinite_lifetime (is infinite lifetime can work with this backend)
+ * - get_list (is it possible to get the list of cache ids and the complete list of tags)
+ *
+ * @return array associative of with capabilities
+ */
+ public function getCapabilities()
+ {
+ return array(
+ 'automatic_cleaning' => true,
+ 'tags' => true,
+ 'expired_read' => false,
+ 'priority' => true,
+ 'infinite_lifetime' => true,
+ 'get_list' => true
+ );
+ }
+
+ /**
* Add an event to the log array
*
* @param string $methodName MethodName
diff --git a/libs/Zend/Cache/Backend/TwoLevels.php b/libs/Zend/Cache/Backend/TwoLevels.php
index b340645f6c..a537b739ca 100644
--- a/libs/Zend/Cache/Backend/TwoLevels.php
+++ b/libs/Zend/Cache/Backend/TwoLevels.php
@@ -15,27 +15,27 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: TwoLevels.php 17741 2009-08-22 02:58:33Z yoshida@zend.co.jp $
+ * @version $Id: TwoLevels.php 21954 2010-04-19 19:19:24Z mabe $
*/
/**
* @see Zend_Cache_Backend_ExtendedInterface
*/
-require_once 'Zend/Cache/Backend/ExtendedInterface.php';
+// require_once 'Zend/Cache/Backend/ExtendedInterface.php';
/**
* @see Zend_Cache_Backend
*/
-require_once 'Zend/Cache/Backend.php';
+// require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
@@ -95,21 +95,21 @@ class Zend_Cache_Backend_TwoLevels extends Zend_Cache_Backend implements Zend_Ca
*
* @var Zend_Cache_Backend
*/
- private $_slowBackend;
+ protected $_slowBackend;
/**
* Fast Backend
*
* @var Zend_Cache_Backend
*/
- private $_fastBackend;
+ protected $_fastBackend;
/**
* Cache for the fast backend filling percentage
*
* @var int
*/
- private $_fastBackendFillingPercentage = null;
+ protected $_fastBackendFillingPercentage = null;
/**
* Constructor
@@ -121,20 +121,39 @@ class Zend_Cache_Backend_TwoLevels extends Zend_Cache_Backend implements Zend_Ca
public function __construct(array $options = array())
{
parent::__construct($options);
+
if ($this->_options['slow_backend'] === null) {
Zend_Cache::throwException('slow_backend option has to set');
+ } elseif ($this->_options['slow_backend'] instanceof Zend_Cache_Backend_ExtendedInterface) {
+ $this->_slowBackend = $this->_options['slow_backend'];
+ } else {
+ $this->_slowBackend = Zend_Cache::_makeBackend(
+ $this->_options['slow_backend'],
+ $this->_options['slow_backend_options'],
+ $this->_options['slow_backend_custom_naming'],
+ $this->_options['slow_backend_autoload']
+ );
+ if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_slowBackend))) {
+ Zend_Cache::throwException('slow_backend must implement the Zend_Cache_Backend_ExtendedInterface interface');
+ }
}
+
if ($this->_options['fast_backend'] === null) {
Zend_Cache::throwException('fast_backend option has to set');
+ } elseif ($this->_options['fast_backend'] instanceof Zend_Cache_Backend_ExtendedInterface) {
+ $this->_fastBackend = $this->_options['fast_backend'];
+ } else {
+ $this->_fastBackend = Zend_Cache::_makeBackend(
+ $this->_options['fast_backend'],
+ $this->_options['fast_backend_options'],
+ $this->_options['fast_backend_custom_naming'],
+ $this->_options['fast_backend_autoload']
+ );
+ if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_fastBackend))) {
+ Zend_Cache::throwException('fast_backend must implement the Zend_Cache_Backend_ExtendedInterface interface');
+ }
}
- $this->_slowBackend = Zend_Cache::_makeBackend($this->_options['slow_backend'], $this->_options['slow_backend_options'], $this->_options['slow_backend_custom_naming'], $this->_options['slow_backend_autoload']);
- $this->_fastBackend = Zend_Cache::_makeBackend($this->_options['fast_backend'], $this->_options['fast_backend_options'], $this->_options['fast_backend_custom_naming'], $this->_options['fast_backend_autoload']);
- if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_slowBackend))) {
- Zend_Cache::throwException('slow_backend must implement the Zend_Cache_Backend_ExtendedInterface interface');
- }
- if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_fastBackend))) {
- Zend_Cache::throwException('fast_backend must implement the Zend_Cache_Backend_ExtendedInterface interface');
- }
+
$this->_slowBackend->setDirectives($this->_directives);
$this->_fastBackend->setDirectives($this->_directives);
}
@@ -177,8 +196,14 @@ class Zend_Cache_Backend_TwoLevels extends Zend_Cache_Backend implements Zend_Ca
if (($priority > 0) && (10 * $priority >= $usage)) {
$fastLifetime = $this->_getFastLifetime($lifetime, $priority);
$boolFast = $this->_fastBackend->save($preparedData, $id, array(), $fastLifetime);
+ $boolSlow = $this->_slowBackend->save($preparedData, $id, $tags, $lifetime);
+ } else {
+ $boolSlow = $this->_slowBackend->save($preparedData, $id, $tags, $lifetime);
+ if ($boolSlow === true) {
+ $boolFast = $this->_fastBackend->remove($id);
+ }
}
- $boolSlow = $this->_slowBackend->save($preparedData, $id, $tags, $lifetime);
+
return ($boolFast && $boolSlow);
}
diff --git a/libs/Zend/Cache/Backend/Xcache.php b/libs/Zend/Cache/Backend/Xcache.php
index 8f7af5963f..ccd9672ca6 100644
--- a/libs/Zend/Cache/Backend/Xcache.php
+++ b/libs/Zend/Cache/Backend/Xcache.php
@@ -15,27 +15,27 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Xcache.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Xcache.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Cache_Backend_Interface
*/
-require_once 'Zend/Cache/Backend/Interface.php';
+// require_once 'Zend/Cache/Backend/Interface.php';
/**
* @see Zend_Cache_Backend
*/
-require_once 'Zend/Cache/Backend.php';
+// require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_Xcache extends Zend_Cache_Backend implements Zend_Cache_Backend_Interface
@@ -46,7 +46,7 @@ class Zend_Cache_Backend_Xcache extends Zend_Cache_Backend implements Zend_Cache
*/
const TAGS_UNSUPPORTED_BY_CLEAN_OF_XCACHE_BACKEND = 'Zend_Cache_Backend_Xcache::clean() : tags are unsupported by the Xcache backend';
const TAGS_UNSUPPORTED_BY_SAVE_OF_XCACHE_BACKEND = 'Zend_Cache_Backend_Xcache::save() : tags are unsupported by the Xcache backend';
-
+
/**
* Available options
*
diff --git a/libs/Zend/Cache/Backend/ZendPlatform.php b/libs/Zend/Cache/Backend/ZendPlatform.php
index 71bbdab3e0..90b7c608c4 100644
--- a/libs/Zend/Cache/Backend/ZendPlatform.php
+++ b/libs/Zend/Cache/Backend/ZendPlatform.php
@@ -15,20 +15,20 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: ZendPlatform.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: ZendPlatform.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Cache_Backend_Interface
*/
-require_once 'Zend/Cache/Backend.php';
+// require_once 'Zend/Cache/Backend.php';
/**
* @see Zend_Cache_Backend_Interface
*/
-require_once 'Zend/Cache/Backend/Interface.php';
+// require_once 'Zend/Cache/Backend/Interface.php';
/**
@@ -36,7 +36,7 @@ require_once 'Zend/Cache/Backend/Interface.php';
*
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_ZendPlatform extends Zend_Cache_Backend implements Zend_Cache_Backend_Interface
diff --git a/libs/Zend/Cache/Backend/ZendServer.php b/libs/Zend/Cache/Backend/ZendServer.php
index 55840efa43..f7a62f6276 100644
--- a/libs/Zend/Cache/Backend/ZendServer.php
+++ b/libs/Zend/Cache/Backend/ZendServer.php
@@ -15,23 +15,23 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: ZendServer.php 17672 2009-08-19 13:05:18Z yoshida@zend.co.jp $
+ * @version $Id: ZendServer.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** @see Zend_Cache_Backend_Interface */
-require_once 'Zend/Cache/Backend/Interface.php';
+// require_once 'Zend/Cache/Backend/Interface.php';
/** @see Zend_Cache_Backend */
-require_once 'Zend/Cache/Backend.php';
+// require_once 'Zend/Cache/Backend.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Cache_Backend_ZendServer extends Zend_Cache_Backend implements Zend_Cache_Backend_Interface
diff --git a/libs/Zend/Cache/Backend/ZendServer/Disk.php b/libs/Zend/Cache/Backend/ZendServer/Disk.php
index ba0dd4b366..49c604d005 100644
--- a/libs/Zend/Cache/Backend/ZendServer/Disk.php
+++ b/libs/Zend/Cache/Backend/ZendServer/Disk.php
@@ -15,23 +15,23 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Disk.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Disk.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** @see Zend_Cache_Backend_Interface */
-require_once 'Zend/Cache/Backend/Interface.php';
+// require_once 'Zend/Cache/Backend/Interface.php';
/** @see Zend_Cache_Backend_ZendServer */
-require_once 'Zend/Cache/Backend/ZendServer.php';
+// require_once 'Zend/Cache/Backend/ZendServer.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_ZendServer_Disk extends Zend_Cache_Backend_ZendServer implements Zend_Cache_Backend_Interface
@@ -50,7 +50,7 @@ class Zend_Cache_Backend_ZendServer_Disk extends Zend_Cache_Backend_ZendServer i
parent::__construct($options);
}
- /**
+ /**
* Store data
*
* @param mixed $data Object to store
@@ -60,13 +60,13 @@ class Zend_Cache_Backend_ZendServer_Disk extends Zend_Cache_Backend_ZendServer i
*/
protected function _store($data, $id, $timeToLive)
{
- if (zend_disk_cache_store($this->_options['namespace'] . '::' . $id,
- $data,
- $timeToLive) === false) {
+ if (zend_disk_cache_store($this->_options['namespace'] . '::' . $id,
+ $data,
+ $timeToLive) === false) {
$this->_log('Store operation failed.');
return false;
- }
- return true;
+ }
+ return true;
}
/**
@@ -76,7 +76,7 @@ class Zend_Cache_Backend_ZendServer_Disk extends Zend_Cache_Backend_ZendServer i
*/
protected function _fetch($id)
{
- return zend_disk_cache_fetch($this->_options['namespace'] . '::' . $id);
+ return zend_disk_cache_fetch($this->_options['namespace'] . '::' . $id);
}
/**
@@ -87,7 +87,7 @@ class Zend_Cache_Backend_ZendServer_Disk extends Zend_Cache_Backend_ZendServer i
*/
protected function _unset($id)
{
- return zend_disk_cache_delete($this->_options['namespace'] . '::' . $id);
+ return zend_disk_cache_delete($this->_options['namespace'] . '::' . $id);
}
/**
@@ -95,6 +95,6 @@ class Zend_Cache_Backend_ZendServer_Disk extends Zend_Cache_Backend_ZendServer i
*/
protected function _clear()
{
- zend_disk_cache_clear($this->_options['namespace']);
+ zend_disk_cache_clear($this->_options['namespace']);
}
}
diff --git a/libs/Zend/Cache/Backend/ZendServer/ShMem.php b/libs/Zend/Cache/Backend/ZendServer/ShMem.php
index 8e42eb60f1..fd08df68bb 100644
--- a/libs/Zend/Cache/Backend/ZendServer/ShMem.php
+++ b/libs/Zend/Cache/Backend/ZendServer/ShMem.php
@@ -15,23 +15,23 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: ShMem.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: ShMem.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** @see Zend_Cache_Backend_Interface */
-require_once 'Zend/Cache/Backend/Interface.php';
+// require_once 'Zend/Cache/Backend/Interface.php';
/** @see Zend_Cache_Backend_ZendServer */
-require_once 'Zend/Cache/Backend/ZendServer.php';
+// require_once 'Zend/Cache/Backend/ZendServer.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Backend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Backend_ZendServer_ShMem extends Zend_Cache_Backend_ZendServer implements Zend_Cache_Backend_Interface
diff --git a/libs/Zend/Cache/Core.php b/libs/Zend/Cache/Core.php
index 361fc3e75c..680d4d8028 100644
--- a/libs/Zend/Cache/Core.php
+++ b/libs/Zend/Cache/Core.php
@@ -14,20 +14,26 @@
*
* @category Zend
* @package Zend_Cache
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Core.php 18255 2009-09-18 17:26:32Z padraic $
+ * @version $Id: Core.php 21293 2010-03-02 10:26:32Z mabe $
*/
/**
* @package Zend_Cache
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Core
{
/**
+ * Messages
+ */
+ const BACKEND_NOT_SUPPORTS_TAG = 'tags are not supported by the current backend';
+ const BACKEND_NOT_IMPLEMENTS_EXTENDED_IF = 'Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available';
+
+ /**
* Backend Object
*
* @var object $_backend
@@ -256,6 +262,9 @@ class Zend_Cache_Core
if (!is_string($name) || !array_key_exists($name, $this->_options)) {
Zend_Cache::throwException("Incorrect option name : $name");
}
+ if ($name == 'lifetime' && empty($value)) {
+ $value = null;
+ }
$this->_options[$name] = $value;
}
@@ -307,7 +316,7 @@ class Zend_Cache_Core
* Test if a cache is available for the given id
*
* @param string $id Cache id
- * @return boolean True is a cache is available, false else
+ * @return int|false Last modified time of cache entry if it is available, false otherwise
*/
public function test($id)
{
@@ -463,12 +472,26 @@ class Zend_Cache_Core
public function getIdsMatchingTags($tags = array())
{
if (!$this->_extendedBackend) {
- Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
}
if (!($this->_backendCapabilities['tags'])) {
- Zend_Cache::throwException('tags are not supported by the current backend');
+ Zend_Cache::throwException(self::BACKEND_NOT_SUPPORT_TAG);
}
- return $this->_backend->getIdsMatchingTags($tags);
+
+ $ids = $this->_backend->getIdsMatchingTags($tags);
+
+ // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
+ if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
+ $prefix = & $this->_options['cache_id_prefix'];
+ $prefixLen = strlen($prefix);
+ foreach ($ids as &$id) {
+ if (strpos($id, $prefix) === 0) {
+ $id = substr($id, $prefixLen);
+ }
+ }
+ }
+
+ return $ids;
}
/**
@@ -482,12 +505,59 @@ class Zend_Cache_Core
public function getIdsNotMatchingTags($tags = array())
{
if (!$this->_extendedBackend) {
- Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
+ }
+ if (!($this->_backendCapabilities['tags'])) {
+ Zend_Cache::throwException(self::BACKEND_NOT_SUPPORT_TAG);
+ }
+
+ $ids = $this->_backend->getIdsNotMatchingTags($tags);
+
+ // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
+ if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
+ $prefix = & $this->_options['cache_id_prefix'];
+ $prefixLen = strlen($prefix);
+ foreach ($ids as &$id) {
+ if (strpos($id, $prefix) === 0) {
+ $id = substr($id, $prefixLen);
+ }
+ }
+ }
+
+ return $ids;
+ }
+
+ /**
+ * Return an array of stored cache ids which match any given tags
+ *
+ * In case of multiple tags, a logical OR is made between tags
+ *
+ * @param array $tags array of tags
+ * @return array array of matching any cache ids (string)
+ */
+ public function getIdsMatchingAnyTags($tags = array())
+ {
+ if (!$this->_extendedBackend) {
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
}
if (!($this->_backendCapabilities['tags'])) {
- Zend_Cache::throwException('tags are not supported by the current backend');
+ Zend_Cache::throwException(self::BACKEND_NOT_SUPPORT_TAG);
+ }
+
+ $ids = $this->_backend->getIdsMatchingAnyTags($tags);
+
+ // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
+ if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
+ $prefix = & $this->_options['cache_id_prefix'];
+ $prefixLen = strlen($prefix);
+ foreach ($ids as &$id) {
+ if (strpos($id, $prefix) === 0) {
+ $id = substr($id, $prefixLen);
+ }
+ }
}
- return $this->_backend->getIdsNotMatchingTags($tags);
+
+ return $ids;
}
/**
@@ -498,20 +568,23 @@ class Zend_Cache_Core
public function getIds()
{
if (!$this->_extendedBackend) {
- Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
- }
- $array = $this->_backend->getIds();
- if ((!isset($this->_options['cache_id_prefix'])) || ($this->_options['cache_id_prefix'] == '')) return $array;
- // we need to remove cache_id_prefix from ids (see #ZF-6178)
- $res = array();
- while (list(,$id) = each($array)) {
- if (strpos($id, $this->_options['cache_id_prefix']) === 0) {
- $res[] = preg_replace("~^{$this->_options['cache_id_prefix']}~", '', $id);
- } else {
- $res[] = $id;
- }
- }
- return $res;
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
+ }
+
+ $ids = $this->_backend->getIds();
+
+ // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
+ if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
+ $prefix = & $this->_options['cache_id_prefix'];
+ $prefixLen = strlen($prefix);
+ foreach ($ids as &$id) {
+ if (strpos($id, $prefix) === 0) {
+ $id = substr($id, $prefixLen);
+ }
+ }
+ }
+
+ return $ids;
}
/**
@@ -522,10 +595,10 @@ class Zend_Cache_Core
public function getTags()
{
if (!$this->_extendedBackend) {
- Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
}
if (!($this->_backendCapabilities['tags'])) {
- Zend_Cache::throwException('tags are not supported by the current backend');
+ Zend_Cache::throwException(self::BACKEND_NOT_SUPPORT_TAG);
}
return $this->_backend->getTags();
}
@@ -538,11 +611,11 @@ class Zend_Cache_Core
public function getFillingPercentage()
{
if (!$this->_extendedBackend) {
- Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
}
return $this->_backend->getFillingPercentage();
}
-
+
/**
* Return an array of metadatas for the given cache id
*
@@ -556,8 +629,8 @@ class Zend_Cache_Core
*/
public function getMetadatas($id)
{
- if (!$this->_extendedBackend) {
- Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
+ if (!$this->_extendedBackend) {
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
}
$id = $this->_id($id); // cache id may need prefix
return $this->_backend->getMetadatas($id);
@@ -573,7 +646,7 @@ class Zend_Cache_Core
public function touch($id, $extraLifetime)
{
if (!$this->_extendedBackend) {
- Zend_Cache::throwException('Current backend doesn\'t implement the Zend_Cache_Backend_ExtendedInterface, so this method is not available');
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
}
$id = $this->_id($id); // cache id may need prefix
return $this->_backend->touch($id, $extraLifetime);
@@ -596,7 +669,7 @@ class Zend_Cache_Core
if (substr($string, 0, 9) == 'internal-') {
Zend_Cache::throwException('"internal-*" ids or tags are reserved');
}
- if (!preg_match('~^[\w]+$~D', $string)) {
+ if (!preg_match('~^[a-zA-Z0-9_]+$~D', $string)) {
Zend_Cache::throwException("Invalid id or tag '$string' : must use only [a-zA-Z0-9_]");
}
}
@@ -640,7 +713,7 @@ class Zend_Cache_Core
}
// Create a default logger to the standard output stream
- require_once 'Zend/Log/Writer/Stream.php';
+ // require_once 'Zend/Log/Writer/Stream.php';
$logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
$this->_options['logger'] = $logger;
}
diff --git a/libs/Zend/Cache/Exception.php b/libs/Zend/Cache/Exception.php
index 1e1e62c4d8..63a4a28838 100644
--- a/libs/Zend/Cache/Exception.php
+++ b/libs/Zend/Cache/Exception.php
@@ -14,19 +14,19 @@
*
* @category Zend
* @package Zend_Cache
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Exception
*/
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
* @package Zend_Cache
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Exception extends Zend_Exception {}
diff --git a/libs/Zend/Cache/Frontend/Capture.php b/libs/Zend/Cache/Frontend/Capture.php
new file mode 100644
index 0000000000..8536c5ffb5
--- /dev/null
+++ b/libs/Zend/Cache/Frontend/Capture.php
@@ -0,0 +1,87 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Cache
+ * @subpackage Zend_Cache_Frontend
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+
+/**
+ * @see Zend_Cache_Core
+ */
+// require_once 'Zend/Cache/Core.php';
+
+
+/**
+ * @package Zend_Cache
+ * @subpackage Zend_Cache_Frontend
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Cache_Frontend_Capture extends Zend_Cache_Core
+{
+ /**
+ * Page identifiers
+ * @var array
+ */
+ protected $_idStack = array();
+
+ /**
+ * Tags
+ * @var array
+ */
+ protected $_tags = array();
+
+ protected $_extension = null;
+
+ /**
+ * Start the cache
+ *
+ * @param string $id Cache id
+ * @return mixed True if the cache is hit (false else) with $echoData=true (default) ; string else (datas)
+ */
+ public function start($id, array $tags, $extension = null)
+ {
+ $this->_tags = $tags;
+ $this->_extension = $extension;
+ ob_start(array($this, '_flush'));
+ ob_implicit_flush(false);
+ $this->_idStack[] = $id;
+ return false;
+ }
+
+ /**
+ * callback for output buffering
+ * (shouldn't really be called manually)
+ *
+ * @param string $data Buffered output
+ * @return string Data to send to browser
+ */
+ public function _flush($data)
+ {
+ $id = array_pop($this->_idStack);
+ if (is_null($id)) {
+ Zend_Cache::throwException('use of _flush() without a start()');
+ }
+ if ($this->_extension) {
+ $this->save(serialize(array($data, $this->_extension)), $id, $this->_tags);
+ } else {
+ $this->save($data, $id, $this->_tags);
+ }
+ return $data;
+ }
+}
diff --git a/libs/Zend/Cache/Frontend/Class.php b/libs/Zend/Cache/Frontend/Class.php
index 6c4ef471b8..3dbdcf666b 100644
--- a/libs/Zend/Cache/Frontend/Class.php
+++ b/libs/Zend/Cache/Frontend/Class.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Class.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Class.php 20379 2010-01-18 14:40:57Z mabe $
*/
/**
* @see Zend_Cache_Core
*/
-require_once 'Zend/Cache/Core.php';
+// require_once 'Zend/Cache/Core.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Frontend_Class extends Zend_Cache_Core
@@ -208,14 +208,14 @@ class Zend_Cache_Frontend_Class extends Zend_Cache_Core
// We do not have not cache
return call_user_func_array(array($this->_cachedEntity, $name), $parameters);
}
+
$id = $this->_makeId($name, $parameters);
- if ($this->test($id)) {
+ if ( ($rs = $this->load($id)) && isset($rs[0], $rs[1]) ) {
// A cache is available
- $result = $this->load($id);
- $output = $result[0];
- $return = $result[1];
+ $output = $rs[0];
+ $return = $rs[1];
} else {
- // A cache is not available
+ // A cache is not available (or not valid for this frontend)
ob_start();
ob_implicit_flush(false);
$return = call_user_func_array(array($this->_cachedEntity, $name), $parameters);
@@ -224,6 +224,7 @@ class Zend_Cache_Frontend_Class extends Zend_Cache_Core
$data = array($output, $return);
$this->save($data, $id, $this->_tags, $this->_specificLifetime, $this->_priority);
}
+
echo $output;
return $return;
}
diff --git a/libs/Zend/Cache/Frontend/File.php b/libs/Zend/Cache/Frontend/File.php
index 5e28e015d5..2cbfe74d0c 100644
--- a/libs/Zend/Cache/Frontend/File.php
+++ b/libs/Zend/Cache/Frontend/File.php
@@ -15,66 +15,66 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: File.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: File.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Cache_Core
*/
-require_once 'Zend/Cache/Core.php';
+// require_once 'Zend/Cache/Core.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Frontend_File extends Zend_Cache_Core
{
-
- /**
- * Consts for master_files_mode
- */
- const MODE_AND = 'AND';
- const MODE_OR = 'OR';
-
+
+ /**
+ * Consts for master_files_mode
+ */
+ const MODE_AND = 'AND';
+ const MODE_OR = 'OR';
+
/**
* Available options
*
* ====> (string) master_file :
* - a complete path of the master file
* - deprecated (see master_files)
- *
+ *
* ====> (array) master_files :
* - an array of complete path of master files
* - this option has to be set !
- *
+ *
* ====> (string) master_files_mode :
* - Zend_Cache_Frontend_File::MODE_AND or Zend_Cache_Frontend_File::MODE_OR
* - if MODE_AND, then all master files have to be touched to get a cache invalidation
* - if MODE_OR (default), then a single touched master file is enough to get a cache invalidation
*
* ====> (boolean) ignore_missing_master_files
- * - if set to true, missing master files are ignored silently
+ * - if set to true, missing master files are ignored silently
* - if set to false (default), an exception is thrown if there is a missing master file
* @var array available options
*/
protected $_specificOptions = array(
- 'master_file' => null,
+ 'master_file' => null,
'master_files' => null,
- 'master_files_mode' => 'OR',
- 'ignore_missing_master_files' => false
+ 'master_files_mode' => 'OR',
+ 'ignore_missing_master_files' => false
);
/**
* Master file mtimes
*
* Array of int
- *
+ *
* @var array
*/
private $_masterFile_mtimes = null;
@@ -95,10 +95,10 @@ class Zend_Cache_Frontend_File extends Zend_Cache_Core
Zend_Cache::throwException('master_files option must be set');
}
}
-
+
/**
* Change the master_file option
- *
+ *
* @param string $masterFile the complete path and name of the master file
*/
public function setMasterFiles($masterFiles)
@@ -109,27 +109,27 @@ class Zend_Cache_Frontend_File extends Zend_Cache_Core
$this->_masterFile_mtimes = array();
$i = 0;
foreach ($masterFiles as $masterFile) {
- $this->_masterFile_mtimes[$i] = @filemtime($masterFile);
- if ((!($this->_specificOptions['ignore_missing_master_files'])) && (!($this->_masterFile_mtimes[$i]))) {
- Zend_Cache::throwException('Unable to read master_file : '.$masterFile);
- }
- $i++;
+ $this->_masterFile_mtimes[$i] = @filemtime($masterFile);
+ if ((!($this->_specificOptions['ignore_missing_master_files'])) && (!($this->_masterFile_mtimes[$i]))) {
+ Zend_Cache::throwException('Unable to read master_file : '.$masterFile);
+ }
+ $i++;
}
}
-
+
/**
* Change the master_file option
- *
- * To keep the compatibility
- *
+ *
+ * To keep the compatibility
+ *
* @deprecated
* @param string $masterFile the complete path and name of the master file
- */
+ */
public function setMasterFile($masterFile)
{
- $this->setMasterFiles(array(0 => $masterFile));
+ $this->setMasterFiles(array(0 => $masterFile));
}
-
+
/**
* Public frontend to set an option
*
@@ -145,7 +145,7 @@ class Zend_Cache_Frontend_File extends Zend_Cache_Core
if ($name == 'master_file') {
$this->setMasterFile($value);
} else if ($name == 'master_files') {
- $this->setMasterFiles($value);
+ $this->setMasterFiles($value);
} else {
parent::setOption($name, $value);
}
@@ -174,33 +174,33 @@ class Zend_Cache_Frontend_File extends Zend_Cache_Core
* Test if a cache is available for the given id
*
* @param string $id Cache id
- * @return boolean True is a cache is available, false else
+ * @return int|false Last modified time of cache entry if it is available, false otherwise
*/
public function test($id)
{
$lastModified = parent::test($id);
if ($lastModified) {
- if ($this->_specificOptions['master_files_mode'] == self::MODE_AND) {
- // MODE_AND
- foreach($this->_masterFile_mtimes as $masterFileMTime) {
- if ($masterFileMTime) {
- if ($lastModified > $masterFileMTime) {
- return $lastModified;
- }
- }
- }
- } else {
- // MODE_OR
- $res = true;
- foreach($this->_masterFile_mtimes as $masterFileMTime) {
- if ($masterFileMTime) {
- if ($lastModified <= $masterFileMTime) {
- return false;
- }
- }
- }
- return $lastModified;
- }
+ if ($this->_specificOptions['master_files_mode'] == self::MODE_AND) {
+ // MODE_AND
+ foreach($this->_masterFile_mtimes as $masterFileMTime) {
+ if ($masterFileMTime) {
+ if ($lastModified > $masterFileMTime) {
+ return $lastModified;
+ }
+ }
+ }
+ } else {
+ // MODE_OR
+ $res = true;
+ foreach($this->_masterFile_mtimes as $masterFileMTime) {
+ if ($masterFileMTime) {
+ if ($lastModified <= $masterFileMTime) {
+ return false;
+ }
+ }
+ }
+ return $lastModified;
+ }
}
return false;
}
diff --git a/libs/Zend/Cache/Frontend/Function.php b/libs/Zend/Cache/Frontend/Function.php
index 03e28931ce..7d7f827fee 100644
--- a/libs/Zend/Cache/Frontend/Function.php
+++ b/libs/Zend/Cache/Frontend/Function.php
@@ -15,22 +15,22 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Function.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Function.php 20379 2010-01-18 14:40:57Z mabe $
*/
/**
* @see Zend_Cache_Core
*/
-require_once 'Zend/Cache/Core.php';
+// require_once 'Zend/Cache/Core.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Frontend_Function extends Zend_Cache_Core
@@ -76,7 +76,7 @@ class Zend_Cache_Frontend_Function extends Zend_Cache_Core
* @param array $parameters Function parameters
* @param array $tags Cache tags
* @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
- * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
+ * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
* @return mixed Result
*/
public function call($name, $parameters = array(), $tags = array(), $specificLifetime = false, $priority = 8)
@@ -89,14 +89,14 @@ class Zend_Cache_Frontend_Function extends Zend_Cache_Core
// We do not have not cache
return call_user_func_array($name, $parameters);
}
+
$id = $this->_makeId($name, $parameters);
- if ($this->test($id)) {
+ if ( ($rs = $this->load($id)) && isset($rs[0], $rs[1])) {
// A cache is available
- $result = $this->load($id);
- $output = $result[0];
- $return = $result[1];
+ $output = $rs[0];
+ $return = $rs[1];
} else {
- // A cache is not available
+ // A cache is not available (or not valid for this frontend)
ob_start();
ob_implicit_flush(false);
$return = call_user_func_array($name, $parameters);
@@ -105,6 +105,7 @@ class Zend_Cache_Frontend_Function extends Zend_Cache_Core
$data = array($output, $return);
$this->save($data, $id, $tags, $specificLifetime, $priority);
}
+
echo $output;
return $return;
}
diff --git a/libs/Zend/Cache/Frontend/Output.php b/libs/Zend/Cache/Frontend/Output.php
index 00f200d722..1757381ce4 100644
--- a/libs/Zend/Cache/Frontend/Output.php
+++ b/libs/Zend/Cache/Frontend/Output.php
@@ -15,22 +15,22 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Output.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Output.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Cache_Core
*/
-require_once 'Zend/Cache/Core.php';
+// require_once 'Zend/Cache/Core.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Frontend_Output extends Zend_Cache_Core
diff --git a/libs/Zend/Cache/Frontend/Page.php b/libs/Zend/Cache/Frontend/Page.php
index 8a6a6f64f4..21ce6537a7 100644
--- a/libs/Zend/Cache/Frontend/Page.php
+++ b/libs/Zend/Cache/Frontend/Page.php
@@ -15,22 +15,22 @@
* @category Zend
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Page.php 16974 2009-07-22 19:23:08Z matthew $
+ * @version $Id: Page.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Cache_Core
*/
-require_once 'Zend/Cache/Core.php';
+// require_once 'Zend/Cache/Core.php';
/**
* @package Zend_Cache
* @subpackage Zend_Cache_Frontend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Cache_Frontend_Page extends Zend_Cache_Core
@@ -275,7 +275,7 @@ class Zend_Cache_Frontend_Page extends Zend_Cache_Core
header("$name: $value");
}
}
- if ($this->_specificOptions['debug_header']) {
+ if ($this->_specificOptions['debug_header']) {
echo 'DEBUG HEADER : This is a cached page !';
}
echo $data;
@@ -339,9 +339,9 @@ class Zend_Cache_Frontend_Page extends Zend_Cache_Core
{
$tmp = $_SERVER['REQUEST_URI'];
$array = explode('?', $tmp, 2);
- $tmp = $array[0];
+ $tmp = $array[0];
foreach (array('Get', 'Post', 'Session', 'Files', 'Cookie') as $arrayName) {
- $tmp2 = $this->_makePartialId($arrayName, $this->_activeOptions['cache_with_' . strtolower($arrayName) . '_variables'], $this->_activeOptions['make_id_with_' . strtolower($arrayName) . '_variables']);
+ $tmp2 = $this->_makePartialId($arrayName, $this->_activeOptions['cache_with_' . strtolower($arrayName) . '_variables'], $this->_activeOptions['make_id_with_' . strtolower($arrayName) . '_variables']);
if ($tmp2===false) {
return false;
}
@@ -360,7 +360,7 @@ class Zend_Cache_Frontend_Page extends Zend_Cache_Core
*/
protected function _makePartialId($arrayName, $bool1, $bool2)
{
- switch ($arrayName) {
+ switch ($arrayName) {
case 'Get':
$var = $_GET;
break;
diff --git a/libs/Zend/Cache/Manager.php b/libs/Zend/Cache/Manager.php
new file mode 100644
index 0000000000..d7f157038c
--- /dev/null
+++ b/libs/Zend/Cache/Manager.php
@@ -0,0 +1,286 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Cache
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+
+/** @see Zend_Cache_Exception */
+// require_once 'Zend/Cache/Exception.php';
+
+/** @see Zend_Cache */
+// require_once 'Zend/Cache.php';
+
+/**
+ * @category Zend
+ * @package Zend_Cache
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Cache_Manager
+{
+ /**
+ * Constant holding reserved name for default Page Cache
+ */
+ const PAGECACHE = 'page';
+
+ /**
+ * Constant holding reserved name for default Page Tag Cache
+ */
+ const PAGETAGCACHE = 'pagetag';
+
+ /**
+ * Array of caches stored by the Cache Manager instance
+ *
+ * @var array
+ */
+ protected $_caches = array();
+
+ /**
+ * Array of ready made configuration templates for lazy
+ * loading caches.
+ *
+ * @var array
+ */
+ protected $_optionTemplates = array(
+ // Null Cache (Enforce Null/Empty Values)
+ 'skeleton' => array(
+ 'frontend' => array(
+ 'name' => null,
+ 'options' => array(),
+ ),
+ 'backend' => array(
+ 'name' => null,
+ 'options' => array(),
+ ),
+ ),
+ // Simple Common Default
+ 'default' => array(
+ 'frontend' => array(
+ 'name' => 'Core',
+ 'options' => array(
+ 'automatic_serialization' => true,
+ ),
+ ),
+ 'backend' => array(
+ 'name' => 'File',
+ 'options' => array(
+ 'cache_dir' => '../cache',
+ ),
+ ),
+ ),
+ // Static Page HTML Cache
+ 'page' => array(
+ 'frontend' => array(
+ 'name' => 'Capture',
+ 'options' => array(
+ 'ignore_user_abort' => true,
+ ),
+ ),
+ 'backend' => array(
+ 'name' => 'Static',
+ 'options' => array(
+ 'public_dir' => '../public',
+ ),
+ ),
+ ),
+ // Tag Cache
+ 'pagetag' => array(
+ 'frontend' => array(
+ 'name' => 'Core',
+ 'options' => array(
+ 'automatic_serialization' => true,
+ 'lifetime' => null
+ ),
+ ),
+ 'backend' => array(
+ 'name' => 'File',
+ 'options' => array(
+ 'cache_dir' => '../cache',
+ 'cache_file_umask' => 0644
+ ),
+ ),
+ ),
+ );
+
+ /**
+ * Set a new cache for the Cache Manager to contain
+ *
+ * @param string $name
+ * @param Zend_Cache_Core $cache
+ * @return Zend_Cache_Manager
+ */
+ public function setCache($name, Zend_Cache_Core $cache)
+ {
+ $this->_caches[$name] = $cache;
+ return $this;
+ }
+
+ /**
+ * Check if the Cache Manager contains the named cache object, or a named
+ * configuration template to lazy load the cache object
+ *
+ * @param string $name
+ * @return bool
+ */
+ public function hasCache($name)
+ {
+ if (isset($this->_caches[$name])
+ || $this->hasCacheTemplate($name)
+ ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Fetch the named cache object, or instantiate and return a cache object
+ * using a named configuration template
+ *
+ * @param string $name
+ * @return Zend_Cache_Core
+ */
+ public function getCache($name)
+ {
+ if (isset($this->_caches[$name])) {
+ return $this->_caches[$name];
+ }
+ if (isset($this->_optionTemplates[$name])) {
+ if ($name == self::PAGECACHE
+ && (!isset($this->_optionTemplates[$name]['backend']['options']['tag_cache'])
+ || !$this->_optionTemplates[$name]['backend']['options']['tag_cache'] instanceof Zend_Cache_Core)
+ ) {
+ $this->_optionTemplates[$name]['backend']['options']['tag_cache']
+ = $this->getCache(self::PAGETAGCACHE);
+ }
+ $this->_caches[$name] = Zend_Cache::factory(
+ $this->_optionTemplates[$name]['frontend']['name'],
+ $this->_optionTemplates[$name]['backend']['name'],
+ isset($this->_optionTemplates[$name]['frontend']['options']) ? $this->_optionTemplates[$name]['frontend']['options'] : array(),
+ isset($this->_optionTemplates[$name]['backend']['options']) ? $this->_optionTemplates[$name]['backend']['options'] : array(),
+ isset($this->_optionTemplates[$name]['frontend']['customFrontendNaming']) ? $this->_optionTemplates[$name]['frontend']['customFrontendNaming'] : false,
+ isset($this->_optionTemplates[$name]['backend']['customBackendNaming']) ? $this->_optionTemplates[$name]['backend']['customBackendNaming'] : false,
+ isset($this->_optionTemplates[$name]['frontendBackendAutoload']) ? $this->_optionTemplates[$name]['frontendBackendAutoload'] : false
+ );
+ return $this->_caches[$name];
+ }
+ }
+
+ /**
+ * Set a named configuration template from which a cache object can later
+ * be lazy loaded
+ *
+ * @param string $name
+ * @param array $options
+ * @return Zend_Cache_Manager
+ */
+ public function setCacheTemplate($name, $options)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } elseif (!is_array($options)) {
+ // require_once 'Zend/Cache/Exception.php';
+ throw new Zend_Cache_Exception('Options passed must be in'
+ . ' an associative array or instance of Zend_Config');
+ }
+ $this->_optionTemplates[$name] = $options;
+ return $this;
+ }
+
+ /**
+ * Check if the named configuration template
+ *
+ * @param string $name
+ * @return bool
+ */
+ public function hasCacheTemplate($name)
+ {
+ if (isset($this->_optionTemplates[$name])) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the named configuration template
+ *
+ * @param string $name
+ * @return array
+ */
+ public function getCacheTemplate($name)
+ {
+ if (isset($this->_optionTemplates[$name])) {
+ return $this->_optionTemplates[$name];
+ }
+ }
+
+ /**
+ * Pass an array containing changes to be applied to a named
+ * configuration
+ * template
+ *
+ * @param string $name
+ * @param array $options
+ * @return Zend_Cache_Manager
+ * @throws Zend_Cache_Exception for invalid options format or if option templates do not have $name
+ */
+ public function setTemplateOptions($name, $options)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } elseif (!is_array($options)) {
+ // require_once 'Zend/Cache/Exception.php';
+ throw new Zend_Cache_Exception('Options passed must be in'
+ . ' an associative array or instance of Zend_Config');
+ }
+ if (!isset($this->_optionTemplates[$name])) {
+ throw new Zend_Cache_Exception('A cache configuration template'
+ . 'does not exist with the name "' . $name . '"');
+ }
+ $this->_optionTemplates[$name]
+ = $this->_mergeOptions($this->_optionTemplates[$name], $options);
+ return $this;
+ }
+
+ /**
+ * Simple method to merge two configuration arrays
+ *
+ * @param array $current
+ * @param array $options
+ * @return array
+ */
+ protected function _mergeOptions(array $current, array $options)
+ {
+ if (isset($options['frontend']['name'])) {
+ $current['frontend']['name'] = $options['frontend']['name'];
+ }
+ if (isset($options['backend']['name'])) {
+ $current['backend']['name'] = $options['backend']['name'];
+ }
+ if (isset($options['frontend']['options'])) {
+ foreach ($options['frontend']['options'] as $key=>$value) {
+ $current['frontend']['options'][$key] = $value;
+ }
+ }
+ if (isset($options['backend']['options'])) {
+ foreach ($options['backend']['options'] as $key=>$value) {
+ $current['backend']['options'][$key] = $value;
+ }
+ }
+ return $current;
+ }
+}
diff --git a/libs/Zend/Config.php b/libs/Zend/Config.php
index 0652e9901f..0ba76392f4 100644
--- a/libs/Zend/Config.php
+++ b/libs/Zend/Config.php
@@ -14,16 +14,16 @@
*
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Config.php 16201 2009-06-21 18:51:15Z thomas $
+ * @version $Id: Config.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Config implements Countable, Iterator
@@ -83,7 +83,7 @@ class Zend_Config implements Countable, Iterator
/**
* Load file error string.
- *
+ *
* Is null if there was no error while file loading
*
* @var string
@@ -165,15 +165,15 @@ class Zend_Config implements Countable, Iterator
$this->_count = count($this->_data);
} else {
/** @see Zend_Config_Exception */
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception('Zend_Config is read only');
}
}
-
+
/**
* Deep clone of this instance to ensure that nested Zend_Configs
* are also cloned.
- *
+ *
* @return void
*/
public function __clone()
@@ -234,7 +234,7 @@ class Zend_Config implements Countable, Iterator
$this->_skipNextIteration = true;
} else {
/** @see Zend_Config_Exception */
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception('Zend_Config is read only');
}
@@ -374,7 +374,7 @@ class Zend_Config implements Countable, Iterator
}
}
}
-
+
/**
* Returns if this Zend_Config object is read only or not.
*
@@ -384,7 +384,7 @@ class Zend_Config implements Countable, Iterator
{
return !$this->_allowModifications;
}
-
+
/**
* Get the current extends
*
@@ -394,7 +394,7 @@ class Zend_Config implements Countable, Iterator
{
return $this->_extends;
}
-
+
/**
* Set an extend for Zend_Config_Writer
*
@@ -410,7 +410,7 @@ class Zend_Config implements Countable, Iterator
$this->_extends[$extendingSection] = $extendedSection;
}
}
-
+
/**
* Throws an exception if $extendingSection may not extend $extendedSection,
* and tracks the section extension if it is valid.
@@ -427,7 +427,7 @@ class Zend_Config implements Countable, Iterator
while (array_key_exists($extendedSectionCurrent, $this->_extends)) {
if ($this->_extends[$extendedSectionCurrent] == $extendingSection) {
/** @see Zend_Config_Exception */
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception('Illegal circular inheritance detected');
}
$extendedSectionCurrent = $this->_extends[$extendedSectionCurrent];
@@ -445,7 +445,7 @@ class Zend_Config implements Countable, Iterator
* @param integer $errline
*/
protected function _loadFileErrorHandler($errno, $errstr, $errfile, $errline)
- {
+ {
if ($this->_loadFileErrorStr === null) {
$this->_loadFileErrorStr = $errstr;
} else {
@@ -453,4 +453,32 @@ class Zend_Config implements Countable, Iterator
}
}
-}
+ /**
+ * Merge two arrays recursively, overwriting keys of the same name
+ * in $firstArray with the value in $secondArray.
+ *
+ * @param mixed $firstArray First array
+ * @param mixed $secondArray Second array to merge into first array
+ * @return array
+ */
+ protected function _arrayMergeRecursive($firstArray, $secondArray)
+ {
+ if (is_array($firstArray) && is_array($secondArray)) {
+ foreach ($secondArray as $key => $value) {
+ if (isset($firstArray[$key])) {
+ $firstArray[$key] = $this->_arrayMergeRecursive($firstArray[$key], $value);
+ } else {
+ if($key === 0) {
+ $firstArray= array(0=>$this->_arrayMergeRecursive($firstArray, $value));
+ } else {
+ $firstArray[$key] = $value;
+ }
+ }
+ }
+ } else {
+ $firstArray = $secondArray;
+ }
+
+ return $firstArray;
+ }
+} \ No newline at end of file
diff --git a/libs/Zend/Config/Exception.php b/libs/Zend/Config/Exception.php
index 859d3bf71c..8ef700783c 100644
--- a/libs/Zend/Config/Exception.php
+++ b/libs/Zend/Config/Exception.php
@@ -14,20 +14,20 @@
*
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Exception
*/
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Config_Exception extends Zend_Exception {}
diff --git a/libs/Zend/Config/Ini.php b/libs/Zend/Config/Ini.php
index efb6862713..63cab0f9a4 100644
--- a/libs/Zend/Config/Ini.php
+++ b/libs/Zend/Config/Ini.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Ini.php 16201 2009-06-21 18:51:15Z thomas $
+ * @version $Id: Ini.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Config
*/
-require_once 'Zend/Config.php';
+// require_once 'Zend/Config.php';
/**
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Config_Ini extends Zend_Config
@@ -49,12 +49,12 @@ class Zend_Config_Ini extends Zend_Config
protected $_sectionSeparator = ':';
/**
- * Wether to skip extends or not
+ * Whether to skip extends or not
*
* @var boolean
*/
protected $_skipExtends = false;
-
+
/**
* Loads the section $section from the config file $filename for
* access facilitated by nested object properties.
@@ -103,7 +103,7 @@ class Zend_Config_Ini extends Zend_Config
/**
* @see Zend_Config_Exception
*/
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception('Filename is not set');
}
@@ -129,7 +129,7 @@ class Zend_Config_Ini extends Zend_Config
$dataArray = array();
foreach ($iniArray as $sectionName => $sectionData) {
if(!is_array($sectionData)) {
- $dataArray = array_merge_recursive($dataArray, $this->_processKey(array(), $sectionName, $sectionData));
+ $dataArray = $this->_arrayMergeRecursive($dataArray, $this->_processKey(array(), $sectionName, $sectionData));
} else {
$dataArray[$sectionName] = $this->_processSection($iniArray, $sectionName);
}
@@ -146,44 +146,59 @@ class Zend_Config_Ini extends Zend_Config
/**
* @see Zend_Config_Exception
*/
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("Section '$sectionName' cannot be found in $filename");
}
- $dataArray = array_merge($this->_processSection($iniArray, $sectionName), $dataArray);
+ $dataArray = $this->_arrayMergeRecursive($this->_processSection($iniArray, $sectionName), $dataArray);
}
parent::__construct($dataArray, $allowModifications);
- }
+ }
$this->_loadedSection = $section;
}
-
+
/**
- * Load the ini file and preprocess the section separator (':' in the
- * section name (that is used for section extension) so that the resultant
- * array has the correct section names and the extension information is
- * stored in a sub-key called ';extends'. We use ';extends' as this can
- * never be a valid key name in an INI file that has been loaded using
- * parse_ini_file().
- *
+ * Load the INI file from disk using parse_ini_file(). Use a private error
+ * handler to convert any loading errors into a Zend_Config_Exception
+ *
* @param string $filename
* @throws Zend_Config_Exception
* @return array
*/
- protected function _loadIniFile($filename)
+ protected function _parseIniFile($filename)
{
set_error_handler(array($this, '_loadFileErrorHandler'));
- $loaded = parse_ini_file($filename, true); // Warnings and errors are suppressed
+ $iniArray = parse_ini_file($filename, true); // Warnings and errors are suppressed
restore_error_handler();
+
// Check if there was a error while loading file
if ($this->_loadFileErrorStr !== null) {
/**
* @see Zend_Config_Exception
*/
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception($this->_loadFileErrorStr);
}
+
+ return $iniArray;
+ }
+ /**
+ * Load the ini file and preprocess the section separator (':' in the
+ * section name (that is used for section extension) so that the resultant
+ * array has the correct section names and the extension information is
+ * stored in a sub-key called ';extends'. We use ';extends' as this can
+ * never be a valid key name in an INI file that has been loaded using
+ * parse_ini_file().
+ *
+ * @param string $filename
+ * @throws Zend_Config_Exception
+ * @return array
+ */
+ protected function _loadIniFile($filename)
+ {
+ $loaded = $this->_parseIniFile($filename);
$iniArray = array();
foreach ($loaded as $key => $data)
{
@@ -203,14 +218,14 @@ class Zend_Config_Ini extends Zend_Config
/**
* @see Zend_Config_Exception
*/
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("Section '$thisSection' may not extend multiple sections in $filename");
}
}
return $iniArray;
}
-
+
/**
* Process each element in the section and handle the ";extends" inheritance
* key. Passes control to _processKey() to handle the nest separator
@@ -230,7 +245,7 @@ class Zend_Config_Ini extends Zend_Config
if (strtolower($key) == ';extends') {
if (isset($iniArray[$value])) {
$this->_assertValidExtend($section, $value);
-
+
if (!$this->_skipExtends) {
$config = $this->_processSection($iniArray, $value, $config);
}
@@ -238,7 +253,7 @@ class Zend_Config_Ini extends Zend_Config
/**
* @see Zend_Config_Exception
*/
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("Parent section '$section' cannot be found");
}
} else {
@@ -274,7 +289,7 @@ class Zend_Config_Ini extends Zend_Config
/**
* @see Zend_Config_Exception
*/
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("Cannot create sub-key for '{$pieces[0]}' as key already exists");
}
$config[$pieces[0]] = $this->_processKey($config[$pieces[0]], $pieces[1], $value);
@@ -282,7 +297,7 @@ class Zend_Config_Ini extends Zend_Config
/**
* @see Zend_Config_Exception
*/
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("Invalid key '$key'");
}
} else {
diff --git a/libs/Zend/Config/Writer.php b/libs/Zend/Config/Writer.php
index 56bb66bfd1..9bfedca748 100644
--- a/libs/Zend/Config/Writer.php
+++ b/libs/Zend/Config/Writer.php
@@ -14,28 +14,28 @@
*
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Writer.php 16201 2009-06-21 18:51:15Z thomas $
+ * @version $Id: Writer.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Config_Writer
{
/**
* Option keys to skip when calling setOptions()
- *
+ *
* @var array
*/
protected $_skipOptions = array(
'options'
);
-
+
/**
* Config object to write
*
@@ -45,8 +45,8 @@ abstract class Zend_Config_Writer
/**
* Create a new adapter
- *
- * $options can only be passed as array or be omitted
+ *
+ * $options can only be passed as array or be omitted
*
* @param null|array $options
*/
@@ -56,7 +56,7 @@ abstract class Zend_Config_Writer
$this->setOptions($options);
}
}
-
+
/**
* Set options via a Zend_Config instance
*
@@ -66,10 +66,10 @@ abstract class Zend_Config_Writer
public function setConfig(Zend_Config $config)
{
$this->_config = $config;
-
+
return $this;
}
-
+
/**
* Set options via an array
*
@@ -88,10 +88,10 @@ abstract class Zend_Config_Writer
$this->$method($value);
}
}
-
+
return $this;
}
-
+
/**
* Write a Zend_Config object to it's target
*
diff --git a/libs/Zend/Config/Writer/Array.php b/libs/Zend/Config/Writer/Array.php
index dd880b010b..6e9b158997 100644
--- a/libs/Zend/Config/Writer/Array.php
+++ b/libs/Zend/Config/Writer/Array.php
@@ -14,119 +14,42 @@
*
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Array.php 16201 2009-06-21 18:51:15Z thomas $
+ * @version $Id: Array.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Config_Writer
*/
-require_once 'Zend/Config/Writer.php';
+// require_once 'Zend/Config/Writer/FileAbstract.php';
/**
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Config_Writer_Array extends Zend_Config_Writer
+class Zend_Config_Writer_Array extends Zend_Config_Writer_FileAbstract
{
/**
- * Filename to write to
+ * Render a Zend_Config into a PHP Array config string.
*
- * @var string
+ * @since 1.10
+ * @return string
*/
- protected $_filename = null;
-
- /**
- * Wether to exclusively lock the file or not
- *
- * @var boolean
- */
- protected $_exclusiveLock = false;
-
- /**
- * Set the target filename
- *
- * @param string $filename
- * @return Zend_Config_Writer_Array
- */
- public function setFilename($filename)
- {
- $this->_filename = $filename;
-
- return $this;
- }
-
- /**
- * Set wether to exclusively lock the file or not
- *
- * @param boolean $exclusiveLock
- * @return Zend_Config_Writer_Array
- */
- public function setExclusiveLock($exclusiveLock)
- {
- $this->_exclusiveLock = $exclusiveLock;
-
- return $this;
- }
-
- /**
- * Defined by Zend_Config_Writer
- *
- * @param string $filename
- * @param Zend_Config $config
- * @param boolean $exclusiveLock
- * @throws Zend_Config_Exception When filename was not set
- * @throws Zend_Config_Exception When filename is not writable
- * @return void
- */
- public function write($filename = null, Zend_Config $config = null, $exclusiveLock = null)
+ public function render()
{
- if ($filename !== null) {
- $this->setFilename($filename);
- }
-
- if ($config !== null) {
- $this->setConfig($config);
- }
-
- if ($exclusiveLock !== null) {
- $this->setExclusiveLock($exclusiveLock);
- }
-
- if ($this->_filename === null) {
- require_once 'Zend/Config/Exception.php';
- throw new Zend_Config_Exception('No filename was set');
- }
-
- if ($this->_config === null) {
- require_once 'Zend/Config/Exception.php';
- throw new Zend_Config_Exception('No config was set');
- }
-
$data = $this->_config->toArray();
$sectionName = $this->_config->getSectionName();
-
+
if (is_string($sectionName)) {
$data = array($sectionName => $data);
}
-
+
$arrayString = "<?php\n"
. "return " . var_export($data, true) . ";\n";
-
- $flags = 0;
-
- if ($this->_exclusiveLock) {
- $flags |= LOCK_EX;
- }
-
- $result = @file_put_contents($this->_filename, $arrayString, $flags);
-
- if ($result === false) {
- require_once 'Zend/Config/Exception.php';
- throw new Zend_Config_Exception('Could not write to file "' . $this->_filename . '"');
- }
+
+ return $arrayString;
}
}
diff --git a/libs/Zend/Config/Writer/FileAbstract.php b/libs/Zend/Config/Writer/FileAbstract.php
new file mode 100644
index 0000000000..ee14b772fa
--- /dev/null
+++ b/libs/Zend/Config/Writer/FileAbstract.php
@@ -0,0 +1,134 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Config
+ * @package Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+// require_once "Zend/Config/Writer.php";
+
+/**
+ * Abstract File Writer
+ *
+ * @category Zend
+ * @package Zend_package
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: FileAbstract.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+class Zend_Config_Writer_FileAbstract extends Zend_Config_Writer
+{
+ /**
+ * Filename to write to
+ *
+ * @var string
+ */
+ protected $_filename = null;
+
+ /**
+ * Wether to exclusively lock the file or not
+ *
+ * @var boolean
+ */
+ protected $_exclusiveLock = false;
+
+ /**
+ * Set the target filename
+ *
+ * @param string $filename
+ * @return Zend_Config_Writer_Array
+ */
+ public function setFilename($filename)
+ {
+ $this->_filename = $filename;
+
+ return $this;
+ }
+
+ /**
+ * Set wether to exclusively lock the file or not
+ *
+ * @param boolean $exclusiveLock
+ * @return Zend_Config_Writer_Array
+ */
+ public function setExclusiveLock($exclusiveLock)
+ {
+ $this->_exclusiveLock = $exclusiveLock;
+
+ return $this;
+ }
+
+ /**
+ * Write configuration to file.
+ *
+ * @param string $filename
+ * @param Zend_Config $config
+ * @param bool $exclusiveLock
+ * @return void
+ */
+ public function write($filename = null, Zend_Config $config = null, $exclusiveLock = null)
+ {
+ if ($filename !== null) {
+ $this->setFilename($filename);
+ }
+
+ if ($config !== null) {
+ $this->setConfig($config);
+ }
+
+ if ($exclusiveLock !== null) {
+ $this->setExclusiveLock($exclusiveLock);
+ }
+
+ if ($this->_filename === null) {
+ // require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('No filename was set');
+ }
+
+ if ($this->_config === null) {
+ // require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('No config was set');
+ }
+
+ $configString = $this->render();
+
+ $flags = 0;
+
+ if ($this->_exclusiveLock) {
+ $flags |= LOCK_EX;
+ }
+
+ $result = @file_put_contents($this->_filename, $configString, $flags);
+
+ if ($result === false) {
+ // require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Could not write to file "' . $this->_filename . '"');
+ }
+ }
+
+ /**
+ * Render a Zend_Config into a config file string.
+ *
+ * @since 1.10
+ * @todo For 2.0 this should be redone into an abstract method.
+ * @return string
+ */
+ public function render()
+ {
+ return "";
+ }
+} \ No newline at end of file
diff --git a/libs/Zend/Config/Writer/Ini.php b/libs/Zend/Config/Writer/Ini.php
index ea65ca87c3..163c95e216 100644
--- a/libs/Zend/Config/Writer/Ini.php
+++ b/libs/Zend/Config/Writer/Ini.php
@@ -14,123 +14,81 @@
*
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Ini.php 16201 2009-06-21 18:51:15Z thomas $
+ * @version $Id: Ini.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Config_Writer
*/
-require_once 'Zend/Config/Writer.php';
+// require_once 'Zend/Config/Writer/FileAbstract.php';
/**
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Config_Writer_Ini extends Zend_Config_Writer
+class Zend_Config_Writer_Ini extends Zend_Config_Writer_FileAbstract
{
/**
- * Filename to write to
- *
- * @var string
- */
- protected $_filename = null;
-
- /**
- * Wether to exclusively lock the file or not
- *
- * @var boolean
- */
- protected $_exclusiveLock = false;
-
- /**
* String that separates nesting levels of configuration data identifiers
*
* @var string
*/
protected $_nestSeparator = '.';
-
+
/**
- * Set the target filename
+ * If true the ini string is rendered in the global namespace without sections.
*
- * @param string $filename
- * @return Zend_Config_Writer_Xml
+ * @var bool
*/
- public function setFilename($filename)
- {
- $this->_filename = $filename;
-
- return $this;
- }
-
+ protected $_renderWithoutSections = false;
+
/**
- * Set wether to exclusively lock the file or not
+ * Set the nest separator
*
- * @param boolean $exclusiveLock
- * @return Zend_Config_Writer_Array
+ * @param string $filename
+ * @return Zend_Config_Writer_Ini
*/
- public function setExclusiveLock($exclusiveLock)
+ public function setNestSeparator($separator)
{
- $this->_exclusiveLock = $exclusiveLock;
-
+ $this->_nestSeparator = $separator;
+
return $this;
}
-
+
/**
- * Set the nest separator
+ * Set if rendering should occour without sections or not.
*
- * @param string $filename
+ * If set to true, the INI file is rendered without sections completely
+ * into the global namespace of the INI file.
+ *
+ * @param bool $withoutSections
* @return Zend_Config_Writer_Ini
*/
- public function setNestSeparator($separator)
+ public function setRenderWithoutSections($withoutSections=true)
{
- $this->_nestSeparator = $separator;
-
+ $this->_renderWithoutSections = (bool)$withoutSections;
return $this;
}
-
+
/**
- * Defined by Zend_Config_Writer
+ * Render a Zend_Config into a INI config string.
*
- * @param string $filename
- * @param Zend_Config $config
- * @param boolean $exclusiveLock
- * @throws Zend_Config_Exception When filename was not set
- * @throws Zend_Config_Exception When filename is not writable
- * @return void
+ * @since 1.10
+ * @return string
*/
- public function write($filename = null, Zend_Config $config = null, $exclusiveLock = null)
+ public function render()
{
- if ($filename !== null) {
- $this->setFilename($filename);
- }
-
- if ($config !== null) {
- $this->setConfig($config);
- }
-
- if ($exclusiveLock !== null) {
- $this->setExclusiveLock($exclusiveLock);
- }
-
- if ($this->_filename === null) {
- require_once 'Zend/Config/Exception.php';
- throw new Zend_Config_Exception('No filename was set');
- }
-
- if ($this->_config === null) {
- require_once 'Zend/Config/Exception.php';
- throw new Zend_Config_Exception('No config was set');
- }
-
$iniString = '';
$extends = $this->_config->getExtends();
$sectionName = $this->_config->getSectionName();
-
- if (is_string($sectionName)) {
+
+ if($this->_renderWithoutSections == true) {
+ $iniString .= $this->_addBranch($this->_config);
+ } else if (is_string($sectionName)) {
$iniString .= '[' . $sectionName . ']' . "\n"
. $this->_addBranch($this->_config)
. "\n";
@@ -145,28 +103,17 @@ class Zend_Config_Writer_Ini extends Zend_Config_Writer
if (isset($extends[$sectionName])) {
$sectionName .= ' : ' . $extends[$sectionName];
}
-
+
$iniString .= '[' . $sectionName . ']' . "\n"
. $this->_addBranch($data)
. "\n";
}
}
}
-
- $flags = 0;
-
- if ($this->_exclusiveLock) {
- $flags |= LOCK_EX;
- }
-
- $result = @file_put_contents($this->_filename, $iniString, $flags);
- if ($result === false) {
- require_once 'Zend/Config/Exception.php';
- throw new Zend_Config_Exception('Could not write to file "' . $this->_filename . '"');
- }
+ return $iniString;
}
-
+
/**
* Add a branch to an INI string recursively
*
@@ -179,7 +126,7 @@ class Zend_Config_Writer_Ini extends Zend_Config_Writer
foreach ($config as $key => $value) {
$group = array_merge($parents, array($key));
-
+
if ($value instanceof Zend_Config) {
$iniString .= $this->_addBranch($value, $group);
} else {
@@ -189,10 +136,10 @@ class Zend_Config_Writer_Ini extends Zend_Config_Writer
. "\n";
}
}
-
+
return $iniString;
}
-
+
/**
* Prepare a value for INI
*
@@ -205,8 +152,12 @@ class Zend_Config_Writer_Ini extends Zend_Config_Writer
return $value;
} elseif (is_bool($value)) {
return ($value ? 'true' : 'false');
+ } elseif (strpos($value, '"') === false) {
+ return '"' . $value . '"';
} else {
- return '"' . addslashes($value) . '"';
+ /** @see Zend_Config_Exception */
+ // require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Value can not contain double quotes "');
}
}
}
diff --git a/libs/Zend/Config/Writer/Xml.php b/libs/Zend/Config/Writer/Xml.php
index 764b461ded..7b779d63af 100644
--- a/libs/Zend/Config/Writer/Xml.php
+++ b/libs/Zend/Config/Writer/Xml.php
@@ -14,107 +14,41 @@
*
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Xml.php 16924 2009-07-21 16:34:04Z dasprid $
+ * @version $Id: Xml.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Config_Writer
*/
-require_once 'Zend/Config/Writer.php';
+// require_once 'Zend/Config/Writer/FileAbstract.php';
/**
* @see Zend_Config_Xml
*/
-require_once 'Zend/Config/Xml.php';
+// require_once 'Zend/Config/Xml.php';
/**
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Config_Writer_Xml extends Zend_Config_Writer
+class Zend_Config_Writer_Xml extends Zend_Config_Writer_FileAbstract
{
/**
- * Filename to write to
+ * Render a Zend_Config into a XML config string.
*
- * @var string
+ * @since 1.10
+ * @return string
*/
- protected $_filename = null;
-
- /**
- * Wether to exclusively lock the file or not
- *
- * @var boolean
- */
- protected $_exclusiveLock = false;
-
- /**
- * Set the target filename
- *
- * @param string $filename
- * @return Zend_Config_Writer_Xml
- */
- public function setFilename($filename)
- {
- $this->_filename = $filename;
-
- return $this;
- }
-
- /**
- * Set wether to exclusively lock the file or not
- *
- * @param boolean $exclusiveLock
- * @return Zend_Config_Writer_Array
- */
- public function setExclusiveLock($exclusiveLock)
+ public function render()
{
- $this->_exclusiveLock = $exclusiveLock;
-
- return $this;
- }
-
- /**
- * Defined by Zend_Config_Writer
- *
- * @param string $filename
- * @param Zend_Config $config
- * @param boolean $exclusiveLock
- * @throws Zend_Config_Exception When filename was not set
- * @throws Zend_Config_Exception When filename is not writable
- * @return void
- */
- public function write($filename = null, Zend_Config $config = null, $exclusiveLock = null)
- {
- if ($filename !== null) {
- $this->setFilename($filename);
- }
-
- if ($config !== null) {
- $this->setConfig($config);
- }
-
- if ($exclusiveLock !== null) {
- $this->setExclusiveLock($exclusiveLock);
- }
-
- if ($this->_filename === null) {
- require_once 'Zend/Config/Exception.php';
- throw new Zend_Config_Exception('No filename was set');
- }
-
- if ($this->_config === null) {
- require_once 'Zend/Config/Exception.php';
- throw new Zend_Config_Exception('No config was set');
- }
-
$xml = new SimpleXMLElement('<zend-config xmlns:zf="' . Zend_Config_Xml::XML_NAMESPACE . '"/>');
$extends = $this->_config->getExtends();
$sectionName = $this->_config->getSectionName();
-
+
if (is_string($sectionName)) {
$child = $xml->addChild($sectionName);
@@ -125,35 +59,24 @@ class Zend_Config_Writer_Xml extends Zend_Config_Writer
$xml->addChild($sectionName, (string) $data);
} else {
$child = $xml->addChild($sectionName);
-
+
if (isset($extends[$sectionName])) {
$child->addAttribute('zf:extends', $extends[$sectionName], Zend_Config_Xml::XML_NAMESPACE);
}
-
+
$this->_addBranch($data, $child, $xml);
}
}
}
-
+
$dom = dom_import_simplexml($xml)->ownerDocument;
$dom->formatOutput = true;
-
+
$xmlString = $dom->saveXML();
-
- $flags = 0;
-
- if ($this->_exclusiveLock) {
- $flags |= LOCK_EX;
- }
-
- $result = @file_put_contents($this->_filename, $xmlString, $flags);
-
- if ($result === false) {
- require_once 'Zend/Config/Exception.php';
- throw new Zend_Config_Exception('Could not write to file "' . $this->_filename . '"');
- }
+
+ return $xmlString;
}
-
+
/**
* Add a branch to an XML object recursively
*
@@ -165,35 +88,35 @@ class Zend_Config_Writer_Xml extends Zend_Config_Writer
protected function _addBranch(Zend_Config $config, SimpleXMLElement $xml, SimpleXMLElement $parent)
{
$branchType = null;
-
+
foreach ($config as $key => $value) {
if ($branchType === null) {
if (is_numeric($key)) {
$branchType = 'numeric';
$branchName = $xml->getName();
$xml = $parent;
-
+
unset($parent->{$branchName});
} else {
$branchType = 'string';
}
} else if ($branchType !== (is_numeric($key) ? 'numeric' : 'string')) {
- require_once 'Zend/Config/Exception.php';
- throw new Zend_Config_Exception('Mixing of string and numeric keys is not allowed');
+ // require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Mixing of string and numeric keys is not allowed');
}
-
+
if ($branchType === 'numeric') {
if ($value instanceof Zend_Config) {
- $child = $parent->addChild($branchName, (string) $value);
-
+ $child = $parent->addChild($branchName);
+
$this->_addBranch($value, $child, $parent);
} else {
$parent->addChild($branchName, (string) $value);
}
- } else {
+ } else {
if ($value instanceof Zend_Config) {
$child = $xml->addChild($key);
-
+
$this->_addBranch($value, $child, $xml);
} else {
$xml->addChild($key, (string) $value);
diff --git a/libs/Zend/Config/Xml.php b/libs/Zend/Config/Xml.php
index e68bfd3b32..698247cec8 100644
--- a/libs/Zend/Config/Xml.php
+++ b/libs/Zend/Config/Xml.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Xml.php 17267 2009-07-29 02:13:18Z yoshida@zend.co.jp $
+ * @version $Id: Xml.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Config
*/
-require_once 'Zend/Config.php';
+// require_once 'Zend/Config.php';
/**
* XML Adapter for Zend_Config
*
* @category Zend
* @package Zend_Config
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Config_Xml extends Zend_Config
@@ -40,7 +40,7 @@ class Zend_Config_Xml extends Zend_Config
const XML_NAMESPACE = 'http://framework.zend.com/xml/zend-config-xml/1.0/';
/**
- * Wether to skip extends or not
+ * Whether to skip extends or not
*
* @var boolean
*/
@@ -61,14 +61,14 @@ class Zend_Config_Xml extends Zend_Config
*
* @param string $xml XML file or string to process
* @param mixed $section Section to process
- * @param boolean $options Whether modifiacations are allowed at runtime
+ * @param boolean $options Whether modifications are allowed at runtime
* @throws Zend_Config_Exception When xml is not set or cannot be loaded
* @throws Zend_Config_Exception When section $sectionName cannot be found in $xml
*/
public function __construct($xml, $section = null, $options = false)
{
if (empty($xml)) {
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception('Filename is not set');
}
@@ -94,7 +94,7 @@ class Zend_Config_Xml extends Zend_Config
restore_error_handler();
// Check if there was a error while loading file
if ($this->_loadFileErrorStr !== null) {
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception($this->_loadFileErrorStr);
}
@@ -109,7 +109,7 @@ class Zend_Config_Xml extends Zend_Config
$dataArray = array();
foreach ($section as $sectionName) {
if (!isset($config->$sectionName)) {
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("Section '$sectionName' cannot be found in $xml");
}
@@ -119,7 +119,7 @@ class Zend_Config_Xml extends Zend_Config
parent::__construct($dataArray, $allowModifications);
} else {
if (!isset($config->$section)) {
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("Section '$section' cannot be found in $xml");
}
@@ -148,7 +148,7 @@ class Zend_Config_Xml extends Zend_Config
protected function _processExtends(SimpleXMLElement $element, $section, array $config = array())
{
if (!isset($element->$section)) {
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("Section '$section' cannot be found");
}
@@ -205,7 +205,7 @@ class Zend_Config_Xml extends Zend_Config
// Search for local 'const' nodes and replace them
if (count($xmlObject->children(self::XML_NAMESPACE)) > 0) {
if (count($xmlObject->children()) > 0) {
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("A node with a 'const' childnode may not have any other children");
}
@@ -224,14 +224,14 @@ class Zend_Config_Xml extends Zend_Config
switch ($node->localName) {
case 'const':
if (!$node->hasAttributeNS(self::XML_NAMESPACE, 'name')) {
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("Misssing 'name' attribute in 'const' node");
}
$constantName = $node->getAttributeNS(self::XML_NAMESPACE, 'name');
if (!defined($constantName)) {
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("Constant with name '$constantName' was not defined");
}
@@ -241,7 +241,7 @@ class Zend_Config_Xml extends Zend_Config
break;
default:
- require_once 'Zend/Config/Exception.php';
+ // require_once 'Zend/Config/Exception.php';
throw new Zend_Config_Exception("Unknown node with name '$node->localName' found");
}
}
@@ -283,33 +283,4 @@ class Zend_Config_Xml extends Zend_Config
return $config;
}
-
- /**
- * Merge two arrays recursively, overwriting keys of the same name
- * in $firstArray with the value in $secondArray.
- *
- * @param mixed $firstArray First array
- * @param mixed $secondArray Second array to merge into first array
- * @return array
- */
- protected function _arrayMergeRecursive($firstArray, $secondArray)
- {
- if (is_array($firstArray) && is_array($secondArray)) {
- foreach ($secondArray as $key => $value) {
- if (isset($firstArray[$key])) {
- $firstArray[$key] = $this->_arrayMergeRecursive($firstArray[$key], $value);
- } else {
- if($key === 0) {
- $firstArray= array(0=>$this->_arrayMergeRecursive($firstArray, $value));
- } else {
- $firstArray[$key] = $value;
- }
- }
- }
- } else {
- $firstArray = $secondArray;
- }
-
- return $firstArray;
- }
}
diff --git a/libs/Zend/Db.php b/libs/Zend/Db.php
index b62bcdbbee..9bbf1e793f 100644
--- a/libs/Zend/Db.php
+++ b/libs/Zend/Db.php
@@ -15,9 +15,9 @@
*
* @category Zend
* @package Zend_Db
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Db.php 18373 2009-09-22 19:16:25Z ralph $
+ * @version $Id: Db.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -26,7 +26,7 @@
*
* @category Zend
* @package Zend_Db
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db
@@ -219,7 +219,7 @@ class Zend_Db
/**
* @see Zend_Db_Exception
*/
- require_once 'Zend/Db/Exception.php';
+ // require_once 'Zend/Db/Exception.php';
throw new Zend_Db_Exception('Adapter parameters must be in an array or a Zend_Config object');
}
@@ -230,7 +230,7 @@ class Zend_Db
/**
* @see Zend_Db_Exception
*/
- require_once 'Zend/Db/Exception.php';
+ // require_once 'Zend/Db/Exception.php';
throw new Zend_Db_Exception('Adapter name must be specified in a string');
}
@@ -253,10 +253,10 @@ class Zend_Db
* Load the adapter class. This throws an exception
* if the specified class cannot be loaded.
*/
- if (!class_exists($adapterName)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($adapterName);
- }
+ // if (!class_exists($adapterName)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($adapterName);
+ // }
/*
* Create an instance of the adapter class.
@@ -271,7 +271,7 @@ class Zend_Db
/**
* @see Zend_Db_Exception
*/
- require_once 'Zend/Db/Exception.php';
+ // require_once 'Zend/Db/Exception.php';
throw new Zend_Db_Exception("Adapter class '$adapterName' does not extend Zend_Db_Adapter_Abstract");
}
diff --git a/libs/Zend/Db/Adapter/Abstract.php b/libs/Zend/Db/Adapter/Abstract.php
index bd00da96f4..09ab9e692d 100644
--- a/libs/Zend/Db/Adapter/Abstract.php
+++ b/libs/Zend/Db/Adapter/Abstract.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 18633 2009-10-17 05:36:58Z ralph $
+ * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db
*/
-require_once 'Zend/Db.php';
+// require_once 'Zend/Db.php';
/**
* @see Zend_Db_Select
*/
-require_once 'Zend/Db/Select.php';
+// require_once 'Zend/Db/Select.php';
/**
* Class for connecting to SQL databases and performing common operations.
@@ -37,7 +37,7 @@ require_once 'Zend/Db/Select.php';
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Db_Adapter_Abstract
@@ -175,7 +175,7 @@ abstract class Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception('Adapter parameters must be in an array or a Zend_Config object');
}
}
@@ -230,7 +230,7 @@ abstract class Zend_Db_Adapter_Abstract
break;
default:
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception('Case must be one of the following constants: '
. 'Zend_Db::CASE_NATURAL, Zend_Db::CASE_LOWER, Zend_Db::CASE_UPPER');
}
@@ -272,7 +272,7 @@ abstract class Zend_Db_Adapter_Abstract
// we need at least a dbname
if (! array_key_exists('dbname', $config)) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'dbname' that names the database instance");
}
@@ -280,7 +280,7 @@ abstract class Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'password' for login credentials");
}
@@ -288,7 +288,7 @@ abstract class Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'username' for login credentials");
}
}
@@ -358,7 +358,7 @@ abstract class Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Profiler_Exception
*/
- require_once 'Zend/Db/Profiler/Exception.php';
+ // require_once 'Zend/Db/Profiler/Exception.php';
throw new Zend_Db_Profiler_Exception('Profiler argument must be an instance of either Zend_Db_Profiler'
. ' or Zend_Config when provided as an object');
}
@@ -379,16 +379,16 @@ abstract class Zend_Db_Adapter_Abstract
}
if ($profilerInstance === null) {
- if (!class_exists($profilerClass)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($profilerClass);
- }
+ // if (!class_exists($profilerClass)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($profilerClass);
+ // }
$profilerInstance = new $profilerClass();
}
if (!$profilerInstance instanceof Zend_Db_Profiler) {
/** @see Zend_Db_Profiler_Exception */
- require_once 'Zend/Db/Profiler/Exception.php';
+ // require_once 'Zend/Db/Profiler/Exception.php';
throw new Zend_Db_Profiler_Exception('Class ' . get_class($profilerInstance) . ' does not extend '
. 'Zend_Db_Profiler');
}
@@ -579,7 +579,7 @@ abstract class Zend_Db_Adapter_Abstract
$i++;
} else {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception(get_class($this) ." doesn't support positional or named binding");
}
}
@@ -902,7 +902,7 @@ abstract class Zend_Db_Adapter_Abstract
return str_replace('?', $this->quote($value, $type), $text);
} else {
while ($count > 0) {
- if (strpos($text, '?') != false) {
+ if (strpos($text, '?') !== false) {
$text = substr_replace($text, $this->quote($value, $type), strpos($text, '?'), 1);
}
--$count;
@@ -1097,7 +1097,7 @@ abstract class Zend_Db_Adapter_Abstract
{
if ($this->_allowSerialization == false) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception(get_class($this) ." is not allowed to be serialized");
}
$this->_connection = false;
diff --git a/libs/Zend/Db/Adapter/Db2.php b/libs/Zend/Db/Adapter/Db2.php
index 9d9e9849f3..bde2100793 100644
--- a/libs/Zend/Db/Adapter/Db2.php
+++ b/libs/Zend/Db/Adapter/Db2.php
@@ -15,31 +15,31 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Db2.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Db2.php 20096 2010-01-06 02:05:09Z bkarwin $
*
*/
/**
* @see Zend_Db
*/
-require_once 'Zend/Db.php';
+// require_once 'Zend/Db.php';
/**
* @see Zend_Db_Adapter_Abstract
*/
-require_once 'Zend/Db/Adapter/Abstract.php';
+// require_once 'Zend/Db/Adapter/Abstract.php';
/**
* @see Zend_Db_Statement_Db2
*/
-require_once 'Zend/Db/Statement/Db2.php';
+// require_once 'Zend/Db/Statement/Db2.php';
/**
* @package Zend_Db
- * @copyright Copyright (c) 2005-2009 Zend Technologies Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
@@ -127,7 +127,7 @@ class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Db2_Exception
*/
- require_once 'Zend/Db/Adapter/Db2/Exception.php';
+ // require_once 'Zend/Db/Adapter/Db2/Exception.php';
throw new Zend_Db_Adapter_Db2_Exception('The IBM DB2 extension is required for this adapter but the extension is not loaded');
}
@@ -184,7 +184,7 @@ class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Db2_Exception
*/
- require_once 'Zend/Db/Adapter/Db2/Exception.php';
+ // require_once 'Zend/Db/Adapter/Db2/Exception.php';
throw new Zend_Db_Adapter_Db2_Exception(db2_conn_errormsg(), db2_conn_error());
}
}
@@ -223,10 +223,10 @@ class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
{
$this->_connect();
$stmtClass = $this->_defaultStmtClass;
- if (!class_exists($stmtClass)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($stmtClass);
- }
+ // if (!class_exists($stmtClass)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($stmtClass);
+ // }
$stmt = new $stmtClass($this, $sql);
$stmt->setFetchMode($this->_fetchMode);
return $stmt;
@@ -258,7 +258,7 @@ class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Db2_Exception
*/
- require_once 'Zend/Db/Adapter/Db2/Exception.php';
+ // require_once 'Zend/Db/Adapter/Db2/Exception.php';
throw new Zend_Db_Adapter_Db2_Exception("execution mode not supported");
break;
}
@@ -373,7 +373,7 @@ class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
if ($schemaName === null && $this->_config['schema'] != null) {
$schemaName = $this->_config['schema'];
}
-
+
if (!$this->_isI5) {
$sql = "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno,
@@ -402,14 +402,14 @@ class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
$sql = "SELECT DISTINCT C.TABLE_SCHEMA, C.TABLE_NAME, C.COLUMN_NAME, C.ORDINAL_POSITION,
C.DATA_TYPE, C.COLUMN_DEFAULT, C.NULLS ,C.LENGTH, C.SCALE, LEFT(C.IDENTITY,1),
LEFT(tc.TYPE, 1) AS tabconsttype, k.COLSEQ
- FROM QSYS2.SYSCOLUMNS C
+ FROM QSYS2.SYSCOLUMNS C
LEFT JOIN (QSYS2.syskeycst k JOIN QSYS2.SYSCST tc
ON (k.TABLE_SCHEMA = tc.TABLE_SCHEMA
AND k.TABLE_NAME = tc.TABLE_NAME
- AND LEFT(tc.type,1) = 'P'))
+ AND LEFT(tc.type,1) = 'P'))
ON (C.TABLE_SCHEMA = k.TABLE_SCHEMA
AND C.TABLE_NAME = k.TABLE_NAME
- AND C.COLUMN_NAME = k.COLUMN_NAME)
+ AND C.COLUMN_NAME = k.COLUMN_NAME)
WHERE "
. $this->quoteInto('UPPER(C.TABLE_NAME) = UPPER(?)', $tableName);
@@ -583,7 +583,7 @@ class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Db2_Exception
*/
- require_once 'Zend/Db/Adapter/Db2/Exception.php';
+ // require_once 'Zend/Db/Adapter/Db2/Exception.php';
throw new Zend_Db_Adapter_Db2_Exception(
db2_conn_errormsg($this->_connection),
db2_conn_error($this->_connection));
@@ -603,7 +603,7 @@ class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Db2_Exception
*/
- require_once 'Zend/Db/Adapter/Db2/Exception.php';
+ // require_once 'Zend/Db/Adapter/Db2/Exception.php';
throw new Zend_Db_Adapter_Db2_Exception(
db2_conn_errormsg($this->_connection),
db2_conn_error($this->_connection));
@@ -631,14 +631,14 @@ class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Db2_Exception
*/
- require_once 'Zend/Db/Adapter/Db2/Exception.php';
+ // require_once 'Zend/Db/Adapter/Db2/Exception.php';
throw new Zend_Db_Adapter_Db2_Exception('FETCH_BOUND is not supported yet');
break;
default:
/**
* @see Zend_Db_Adapter_Db2_Exception
*/
- require_once 'Zend/Db/Adapter/Db2/Exception.php';
+ // require_once 'Zend/Db/Adapter/Db2/Exception.php';
throw new Zend_Db_Adapter_Db2_Exception("Invalid fetch mode '$mode' specified");
break;
}
@@ -659,7 +659,7 @@ class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Db2_Exception
*/
- require_once 'Zend/Db/Adapter/Db2/Exception.php';
+ // require_once 'Zend/Db/Adapter/Db2/Exception.php';
throw new Zend_Db_Adapter_Db2_Exception("LIMIT argument count=$count is not valid");
}
@@ -668,7 +668,7 @@ class Zend_Db_Adapter_Db2 extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Db2_Exception
*/
- require_once 'Zend/Db/Adapter/Db2/Exception.php';
+ // require_once 'Zend/Db/Adapter/Db2/Exception.php';
throw new Zend_Db_Adapter_Db2_Exception("LIMIT argument offset=$offset is not valid");
}
diff --git a/libs/Zend/Db/Adapter/Db2/Exception.php b/libs/Zend/Db/Adapter/Db2/Exception.php
index 621274745d..8104606d59 100644
--- a/libs/Zend/Db/Adapter/Db2/Exception.php
+++ b/libs/Zend/Db/Adapter/Db2/Exception.php
@@ -15,22 +15,22 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Db_Adapter_Exception
*/
-require_once 'Zend/Db/Adapter/Exception.php';
+// require_once 'Zend/Db/Adapter/Exception.php';
/**
* Zend_Db_Adapter_Db2_Exception
*
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Db2_Exception extends Zend_Db_Adapter_Exception
@@ -38,8 +38,8 @@ class Zend_Db_Adapter_Db2_Exception extends Zend_Db_Adapter_Exception
protected $code = '00000';
protected $message = 'unknown exception';
- function __construct($msg = 'unknown exception', $state = '00000') {
- $this->message = $msg;
- $this->code = $state;
+ function __construct($message = 'unknown exception', $code = '00000', Exception $e = null)
+ {
+ parent::__construct($message, $code, $e);
}
}
diff --git a/libs/Zend/Db/Adapter/Exception.php b/libs/Zend/Db/Adapter/Exception.php
index 51c06874a6..2510ef6526 100644
--- a/libs/Zend/Db/Adapter/Exception.php
+++ b/libs/Zend/Db/Adapter/Exception.php
@@ -15,44 +15,43 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 17860 2009-08-27 22:48:48Z beberlei $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Db_Exception
*/
-require_once 'Zend/Db/Exception.php';
+// require_once 'Zend/Db/Exception.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Exception extends Zend_Db_Exception
{
protected $_chainedException = null;
- public function __construct($message = null, Exception $e = null)
+ public function __construct($message = '', $code = 0, Exception $e = null)
{
- if ($e) {
- $this->_chainedException = $e;
- $this->code = $e->getCode();
+ if ($e && (0 === $code)) {
+ $code = $e->getCode();
}
- parent::__construct($message);
+ parent::__construct($message, $code, $e);
}
public function hasChainedException()
{
- return ($this->_chainedException!==null);
+ return ($this->_previous !== null);
}
public function getChainedException()
{
- return $this->_chainedException;
+ return $this->getPrevious();
}
}
diff --git a/libs/Zend/Db/Adapter/Mysqli.php b/libs/Zend/Db/Adapter/Mysqli.php
index 3b686948c8..eb9437d059 100644
--- a/libs/Zend/Db/Adapter/Mysqli.php
+++ b/libs/Zend/Db/Adapter/Mysqli.php
@@ -15,38 +15,38 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mysqli.php 16203 2009-06-21 18:56:17Z thomas $
+ * @version $Id: Mysqli.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Adapter_Abstract
*/
-require_once 'Zend/Db/Adapter/Abstract.php';
+// require_once 'Zend/Db/Adapter/Abstract.php';
/**
* @see Zend_Db_Profiler
*/
-require_once 'Zend/Db/Profiler.php';
+// require_once 'Zend/Db/Profiler.php';
/**
* @see Zend_Db_Select
*/
-require_once 'Zend/Db/Select.php';
+// require_once 'Zend/Db/Select.php';
/**
* @see Zend_Db_Statement_Mysqli
*/
-require_once 'Zend/Db/Statement/Mysqli.php';
+// require_once 'Zend/Db/Statement/Mysqli.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Mysqli extends Zend_Db_Adapter_Abstract
@@ -140,7 +140,7 @@ class Zend_Db_Adapter_Mysqli extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Mysqli_Exception
*/
- require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
throw new Zend_Db_Adapter_Mysqli_Exception($this->getConnection()->error);
}
return $result;
@@ -200,7 +200,7 @@ class Zend_Db_Adapter_Mysqli extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Mysqli_Exception
*/
- require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
throw new Zend_Db_Adapter_Mysqli_Exception($this->getConnection()->error);
}
@@ -287,7 +287,7 @@ class Zend_Db_Adapter_Mysqli extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Mysqli_Exception
*/
- require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
throw new Zend_Db_Adapter_Mysqli_Exception('The Mysqli extension is required for this adapter but the extension is not loaded');
}
@@ -329,7 +329,7 @@ class Zend_Db_Adapter_Mysqli extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Mysqli_Exception
*/
- require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
throw new Zend_Db_Adapter_Mysqli_Exception(mysqli_connect_error());
}
@@ -374,10 +374,10 @@ class Zend_Db_Adapter_Mysqli extends Zend_Db_Adapter_Abstract
$this->_stmt->close();
}
$stmtClass = $this->_defaultStmtClass;
- if (!class_exists($stmtClass)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($stmtClass);
- }
+ // if (!class_exists($stmtClass)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($stmtClass);
+ // }
$stmt = new $stmtClass($this, $sql);
if ($stmt === false) {
return false;
@@ -467,14 +467,14 @@ class Zend_Db_Adapter_Mysqli extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Mysqli_Exception
*/
- require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
throw new Zend_Db_Adapter_Mysqli_Exception('FETCH_BOUND is not supported yet');
break;
default:
/**
* @see Zend_Db_Adapter_Mysqli_Exception
*/
- require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
throw new Zend_Db_Adapter_Mysqli_Exception("Invalid fetch mode '$mode' specified");
}
}
@@ -494,7 +494,7 @@ class Zend_Db_Adapter_Mysqli extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Mysqli_Exception
*/
- require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
throw new Zend_Db_Adapter_Mysqli_Exception("LIMIT argument count=$count is not valid");
}
@@ -503,7 +503,7 @@ class Zend_Db_Adapter_Mysqli extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Mysqli_Exception
*/
- require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Adapter/Mysqli/Exception.php';
throw new Zend_Db_Adapter_Mysqli_Exception("LIMIT argument offset=$offset is not valid");
}
diff --git a/libs/Zend/Db/Adapter/Mysqli/Exception.php b/libs/Zend/Db/Adapter/Mysqli/Exception.php
index f2fbd8f958..f7f9f4a8fa 100644
--- a/libs/Zend/Db/Adapter/Mysqli/Exception.php
+++ b/libs/Zend/Db/Adapter/Mysqli/Exception.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*
*/
/**
* Zend
*/
-require_once 'Zend/Db/Adapter/Exception.php';
+// require_once 'Zend/Db/Adapter/Exception.php';
/**
* Zend_Db_Adapter_Mysqli_Exception
@@ -32,7 +32,7 @@ require_once 'Zend/Db/Adapter/Exception.php';
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Mysqli_Exception extends Zend_Db_Adapter_Exception
diff --git a/libs/Zend/Db/Adapter/Oracle.php b/libs/Zend/Db/Adapter/Oracle.php
index 233335825d..17fb8488f4 100644
--- a/libs/Zend/Db/Adapter/Oracle.php
+++ b/libs/Zend/Db/Adapter/Oracle.php
@@ -15,26 +15,26 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Oracle.php 18415 2009-09-25 17:46:24Z mikaelkael $
+ * @version $Id: Oracle.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Adapter_Abstract
*/
-require_once 'Zend/Db/Adapter/Abstract.php';
+// require_once 'Zend/Db/Adapter/Abstract.php';
/**
* @see Zend_Db_Statement_Oracle
*/
-require_once 'Zend/Db/Statement/Oracle.php';
+// require_once 'Zend/Db/Statement/Oracle.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
@@ -115,14 +115,14 @@ class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Adapter/Oracle/Exception.php';
+ // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
throw new Zend_Db_Adapter_Oracle_Exception('The OCI8 extension is required for this adapter but the extension is not loaded');
}
$this->_setExecuteMode(OCI_COMMIT_ON_SUCCESS);
$connectionFuncName = ($this->_config['persistent'] == true) ? 'oci_pconnect' : 'oci_connect';
-
+
$this->_connection = @$connectionFuncName(
$this->_config['username'],
$this->_config['password'],
@@ -134,7 +134,7 @@ class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Adapter/Oracle/Exception.php';
+ // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
throw new Zend_Db_Adapter_Oracle_Exception(oci_error());
}
}
@@ -204,10 +204,10 @@ class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
{
$this->_connect();
$stmtClass = $this->_defaultStmtClass;
- if (!class_exists($stmtClass)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($stmtClass);
- }
+ // if (!class_exists($stmtClass)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($stmtClass);
+ // }
$stmt = new $stmtClass($this, $sql);
if ($stmt instanceof Zend_Db_Statement_Oracle) {
$stmt->setLobAsString($this->getLobAsString());
@@ -360,7 +360,7 @@ class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
TC.DATA_SCALE, TC.DATA_PRECISION, C.CONSTRAINT_TYPE, CC.POSITION
FROM ALL_TAB_COLUMNS TC
LEFT JOIN (ALL_CONS_COLUMNS CC JOIN ALL_CONSTRAINTS C
- ON (CC.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND CC.TABLE_NAME = C.TABLE_NAME AND C.CONSTRAINT_TYPE = 'P'))
+ ON (CC.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND CC.TABLE_NAME = C.TABLE_NAME AND CC.OWNER = C.OWNER AND C.CONSTRAINT_TYPE = 'P'))
ON TC.TABLE_NAME = CC.TABLE_NAME AND TC.COLUMN_NAME = CC.COLUMN_NAME
WHERE UPPER(TC.TABLE_NAME) = UPPER(:TBNAME)";
$bind[':TBNAME'] = $tableName;
@@ -467,7 +467,7 @@ class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Adapter/Oracle/Exception.php';
+ // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
throw new Zend_Db_Adapter_Oracle_Exception(oci_error($this->_connection));
}
$this->_setExecuteMode(OCI_COMMIT_ON_SUCCESS);
@@ -485,7 +485,7 @@ class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Adapter/Oracle/Exception.php';
+ // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
throw new Zend_Db_Adapter_Oracle_Exception(oci_error($this->_connection));
}
$this->_setExecuteMode(OCI_COMMIT_ON_SUCCESS);
@@ -513,14 +513,14 @@ class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Adapter/Oracle/Exception.php';
+ // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
throw new Zend_Db_Adapter_Oracle_Exception('FETCH_BOUND is not supported yet');
break;
default:
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Adapter/Oracle/Exception.php';
+ // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
throw new Zend_Db_Adapter_Oracle_Exception("Invalid fetch mode '$mode' specified");
break;
}
@@ -542,7 +542,7 @@ class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Adapter/Oracle/Exception.php';
+ // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
throw new Zend_Db_Adapter_Oracle_Exception("LIMIT argument count=$count is not valid");
}
@@ -551,7 +551,7 @@ class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Adapter/Oracle/Exception.php';
+ // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
throw new Zend_Db_Adapter_Oracle_Exception("LIMIT argument offset=$offset is not valid");
}
@@ -588,7 +588,7 @@ class Zend_Db_Adapter_Oracle extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Adapter/Oracle/Exception.php';
+ // require_once 'Zend/Db/Adapter/Oracle/Exception.php';
throw new Zend_Db_Adapter_Oracle_Exception("Invalid execution mode '$mode' specified");
break;
}
diff --git a/libs/Zend/Db/Adapter/Oracle/Exception.php b/libs/Zend/Db/Adapter/Oracle/Exception.php
index 39809b10df..a2f43ae893 100644
--- a/libs/Zend/Db/Adapter/Oracle/Exception.php
+++ b/libs/Zend/Db/Adapter/Oracle/Exception.php
@@ -15,15 +15,15 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Db_Adapter_Exception
*/
-require_once 'Zend/Db/Adapter/Exception.php';
+// require_once 'Zend/Db/Adapter/Exception.php';
/**
* Zend_Db_Adapter_Oracle_Exception
@@ -31,7 +31,7 @@ require_once 'Zend/Db/Adapter/Exception.php';
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Oracle_Exception extends Zend_Db_Adapter_Exception
diff --git a/libs/Zend/Db/Adapter/Pdo/Abstract.php b/libs/Zend/Db/Adapter/Pdo/Abstract.php
index 9d05f417b4..0ffc1f428f 100644
--- a/libs/Zend/Db/Adapter/Pdo/Abstract.php
+++ b/libs/Zend/Db/Adapter/Pdo/Abstract.php
@@ -15,22 +15,22 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 17860 2009-08-27 22:48:48Z beberlei $
+ * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Adapter_Abstract
*/
-require_once 'Zend/Db/Adapter/Abstract.php';
+// require_once 'Zend/Db/Adapter/Abstract.php';
/**
* @see Zend_Db_Statement_Pdo
*/
-require_once 'Zend/Db/Statement/Pdo.php';
+// require_once 'Zend/Db/Statement/Pdo.php';
/**
@@ -39,7 +39,7 @@ require_once 'Zend/Db/Statement/Pdo.php';
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
@@ -99,7 +99,7 @@ abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception('The PDO extension is required for this adapter but the extension is not loaded');
}
@@ -108,7 +108,7 @@ abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception('The ' . $this->_pdoType . ' driver is not currently installed');
}
@@ -119,7 +119,7 @@ abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
if (isset($this->_config['persistent']) && ($this->_config['persistent'] == true)) {
$this->_config['driver_options'][PDO::ATTR_PERSISTENT] = true;
}
-
+
try {
$this->_connection = new PDO(
$dsn,
@@ -140,8 +140,8 @@ abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
- throw new Zend_Db_Adapter_Exception($e->getMessage(), $e);
+ // require_once 'Zend/Db/Adapter/Exception.php';
+ throw new Zend_Db_Adapter_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -177,10 +177,10 @@ abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
{
$this->_connect();
$stmtClass = $this->_defaultStmtClass;
- if (!class_exists($stmtClass)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($stmtClass);
- }
+ // if (!class_exists($stmtClass)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($stmtClass);
+ // }
$stmt = new $stmtClass($this, $sql);
$stmt->setFetchMode($this->_fetchMode);
return $stmt;
@@ -240,7 +240,7 @@ abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Statement_Exception
*/
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -258,26 +258,26 @@ abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
if ($sql instanceof Zend_Db_Select) {
$sql = $sql->assemble();
}
-
+
try {
$affected = $this->getConnection()->exec($sql);
-
+
if ($affected === false) {
$errorInfo = $this->getConnection()->errorInfo();
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception($errorInfo[2]);
}
-
+
return $affected;
} catch (PDOException $e) {
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
- throw new Zend_Db_Adapter_Exception($e->getMessage(), $e);
+ // require_once 'Zend/Db/Adapter/Exception.php';
+ throw new Zend_Db_Adapter_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -338,7 +338,7 @@ abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception('The PDO extension is required for this adapter but the extension is not loaded');
}
switch ($mode) {
@@ -354,7 +354,7 @@ abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("Invalid fetch mode '$mode' specified");
break;
}
diff --git a/libs/Zend/Db/Adapter/Pdo/Ibm.php b/libs/Zend/Db/Adapter/Pdo/Ibm.php
index 47d91da0dc..22738248a9 100644
--- a/libs/Zend/Db/Adapter/Pdo/Ibm.php
+++ b/libs/Zend/Db/Adapter/Pdo/Ibm.php
@@ -15,30 +15,30 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Ibm.php 16203 2009-06-21 18:56:17Z thomas $
+ * @version $Id: Ibm.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** @see Zend_Db_Adapter_Pdo_Abstract */
-require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
+// require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
/** @see Zend_Db_Abstract_Pdo_Ibm_Db2 */
-require_once 'Zend/Db/Adapter/Pdo/Ibm/Db2.php';
+// require_once 'Zend/Db/Adapter/Pdo/Ibm/Db2.php';
/** @see Zend_Db_Abstract_Pdo_Ibm_Ids */
-require_once 'Zend/Db/Adapter/Pdo/Ibm/Ids.php';
+// require_once 'Zend/Db/Adapter/Pdo/Ibm/Ids.php';
/** @see Zend_Db_Statement_Pdo_Ibm */
-require_once 'Zend/Db/Statement/Pdo/Ibm.php';
+// require_once 'Zend/Db/Statement/Pdo/Ibm.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Pdo_Ibm extends Zend_Db_Adapter_Pdo_Abstract
@@ -131,12 +131,12 @@ class Zend_Db_Adapter_Pdo_Ibm extends Zend_Db_Adapter_Pdo_Abstract
}
} catch (PDOException $e) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
$error = strpos($e->getMessage(), 'driver does not support that attribute');
if ($error) {
- throw new Zend_Db_Adapter_Exception("PDO_IBM driver extension is downlevel. Please use driver release version 1.2.1 or later");
+ throw new Zend_Db_Adapter_Exception("PDO_IBM driver extension is downlevel. Please use driver release version 1.2.1 or later", 0, $e);
} else {
- throw new Zend_Db_Adapter_Exception($e->getMessage());
+ throw new Zend_Db_Adapter_Exception($e->getMessage(), $e->getCode(), $e);
}
}
}
@@ -178,7 +178,7 @@ class Zend_Db_Adapter_Pdo_Ibm extends Zend_Db_Adapter_Pdo_Abstract
if (array_key_exists('host', $this->_config) &&
!array_key_exists('port', $config)) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("Configuration must have a key for 'port' when 'host' is specified");
}
}
diff --git a/libs/Zend/Db/Adapter/Pdo/Ibm/Db2.php b/libs/Zend/Db/Adapter/Pdo/Ibm/Db2.php
index 99182c0576..94899d4462 100644
--- a/libs/Zend/Db/Adapter/Pdo/Ibm/Db2.php
+++ b/libs/Zend/Db/Adapter/Pdo/Ibm/Db2.php
@@ -15,24 +15,24 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Db2.php 16203 2009-06-21 18:56:17Z thomas $
+ * @version $Id: Db2.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** @see Zend_Db_Adapter_Pdo_Ibm */
-require_once 'Zend/Db/Adapter/Pdo/Ibm.php';
+// require_once 'Zend/Db/Adapter/Pdo/Ibm.php';
/** @see Zend_Db_Statement_Pdo_Ibm */
-require_once 'Zend/Db/Statement/Pdo/Ibm.php';
+// require_once 'Zend/Db/Statement/Pdo/Ibm.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Pdo_Ibm_Db2
@@ -168,13 +168,13 @@ class Zend_Db_Adapter_Pdo_Ibm_Db2
$count = intval($count);
if ($count < 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument count=$count is not valid");
} else {
$offset = intval($offset);
if ($offset < 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument offset=$offset is not valid");
}
diff --git a/libs/Zend/Db/Adapter/Pdo/Ibm/Ids.php b/libs/Zend/Db/Adapter/Pdo/Ibm/Ids.php
index 766106332b..5777e5621c 100644
--- a/libs/Zend/Db/Adapter/Pdo/Ibm/Ids.php
+++ b/libs/Zend/Db/Adapter/Pdo/Ibm/Ids.php
@@ -15,24 +15,24 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Ids.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Ids.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** @see Zend_Db_Adapter_Pdo_Ibm */
-require_once 'Zend/Db/Adapter/Pdo/Ibm.php';
+// require_once 'Zend/Db/Adapter/Pdo/Ibm.php';
/** @see Zend_Db_Statement_Pdo_Ibm */
-require_once 'Zend/Db/Statement/Pdo/Ibm.php';
+// require_once 'Zend/Db/Statement/Pdo/Ibm.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Pdo_Ibm_Ids
@@ -250,7 +250,7 @@ class Zend_Db_Adapter_Pdo_Ibm_Ids
$count = intval($count);
if ($count < 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument count=$count is not valid");
} else if ($count == 0) {
$limit_sql = str_ireplace("SELECT", "SELECT * FROM (SELECT", $sql);
@@ -259,7 +259,7 @@ class Zend_Db_Adapter_Pdo_Ibm_Ids
$offset = intval($offset);
if ($offset < 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument offset=$offset is not valid");
}
if ($offset == 0) {
diff --git a/libs/Zend/Db/Adapter/Pdo/Mssql.php b/libs/Zend/Db/Adapter/Pdo/Mssql.php
index b61a4d61cc..0bd7a1bfbd 100644
--- a/libs/Zend/Db/Adapter/Pdo/Mssql.php
+++ b/libs/Zend/Db/Adapter/Pdo/Mssql.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mssql.php 17792 2009-08-24 16:18:02Z ralph $
+ * @version $Id: Mssql.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Adapter_Pdo_Abstract
*/
-require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
+// require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
/**
@@ -33,7 +33,7 @@ require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Pdo_Mssql extends Zend_Db_Adapter_Pdo_Abstract
@@ -254,7 +254,7 @@ class Zend_Db_Adapter_Pdo_Mssql extends Zend_Db_Adapter_Pdo_Abstract
if ($schemaName != null) {
$sql .= ", @table_owner = " . $this->quoteIdentifier($schemaName, true);
}
-
+
$stmt = $this->query($sql);
$primaryKeysResult = $stmt->fetchAll(Zend_Db::FETCH_NUM);
$primaryKeyColumn = array();
@@ -319,14 +319,14 @@ class Zend_Db_Adapter_Pdo_Mssql extends Zend_Db_Adapter_Pdo_Abstract
$count = intval($count);
if ($count <= 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument count=$count is not valid");
}
$offset = intval($offset);
if ($offset < 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument offset=$offset is not valid");
}
@@ -335,46 +335,46 @@ class Zend_Db_Adapter_Pdo_Mssql extends Zend_Db_Adapter_Pdo_Abstract
'SELECT $1TOP ' . ($count+$offset) . ' ',
$sql
);
-
+
if ($offset > 0) {
- $orderby = stristr($sql, 'ORDER BY');
-
- if ($orderby !== false) {
- $orderParts = explode(',', substr($orderby, 8));
- $pregReplaceCount = null;
- $orderbyInverseParts = array();
- foreach ($orderParts as $orderPart) {
- $orderPart = rtrim($orderPart);
- $inv = preg_replace('/\s+desc$/i', ' ASC', $orderPart, 1, $pregReplaceCount);
- if ($pregReplaceCount) {
- $orderbyInverseParts[] = $inv;
- continue;
- }
- $inv = preg_replace('/\s+asc$/i', ' DESC', $orderPart, 1, $pregReplaceCount);
- if ($pregReplaceCount) {
- $orderbyInverseParts[] = $inv;
- continue;
- } else {
- $orderbyInverseParts[] = $orderPart . ' DESC';
- }
- }
-
- $orderbyInverse = 'ORDER BY ' . implode(', ', $orderbyInverseParts);
- }
-
-
-
-
- $sql = 'SELECT * FROM (SELECT TOP ' . $count . ' * FROM (' . $sql . ') AS inner_tbl';
- if ($orderby !== false) {
- $sql .= ' ' . $orderbyInverse . ' ';
- }
- $sql .= ') AS outer_tbl';
- if ($orderby !== false) {
- $sql .= ' ' . $orderby;
- }
+ $orderby = stristr($sql, 'ORDER BY');
+
+ if ($orderby !== false) {
+ $orderParts = explode(',', substr($orderby, 8));
+ $pregReplaceCount = null;
+ $orderbyInverseParts = array();
+ foreach ($orderParts as $orderPart) {
+ $orderPart = rtrim($orderPart);
+ $inv = preg_replace('/\s+desc$/i', ' ASC', $orderPart, 1, $pregReplaceCount);
+ if ($pregReplaceCount) {
+ $orderbyInverseParts[] = $inv;
+ continue;
+ }
+ $inv = preg_replace('/\s+asc$/i', ' DESC', $orderPart, 1, $pregReplaceCount);
+ if ($pregReplaceCount) {
+ $orderbyInverseParts[] = $inv;
+ continue;
+ } else {
+ $orderbyInverseParts[] = $orderPart . ' DESC';
+ }
+ }
+
+ $orderbyInverse = 'ORDER BY ' . implode(', ', $orderbyInverseParts);
+ }
+
+
+
+
+ $sql = 'SELECT * FROM (SELECT TOP ' . $count . ' * FROM (' . $sql . ') AS inner_tbl';
+ if ($orderby !== false) {
+ $sql .= ' ' . $orderbyInverse . ' ';
+ }
+ $sql .= ') AS outer_tbl';
+ if ($orderby !== false) {
+ $sql .= ' ' . $orderby;
+ }
}
-
+
return $sql;
}
diff --git a/libs/Zend/Db/Adapter/Pdo/Mysql.php b/libs/Zend/Db/Adapter/Pdo/Mysql.php
index 98551812cc..0e4d794922 100644
--- a/libs/Zend/Db/Adapter/Pdo/Mysql.php
+++ b/libs/Zend/Db/Adapter/Pdo/Mysql.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mysql.php 16942 2009-07-22 04:03:09Z ralph $
+ * @version $Id: Mysql.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Adapter_Pdo_Abstract
*/
-require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
+// require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
/**
@@ -33,7 +33,7 @@ require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Abstract
@@ -235,14 +235,14 @@ class Zend_Db_Adapter_Pdo_Mysql extends Zend_Db_Adapter_Pdo_Abstract
$count = intval($count);
if ($count <= 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument count=$count is not valid");
}
$offset = intval($offset);
if ($offset < 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument offset=$offset is not valid");
}
diff --git a/libs/Zend/Db/Adapter/Pdo/Oci.php b/libs/Zend/Db/Adapter/Pdo/Oci.php
index 91ce3ac370..fb47ad1c0b 100644
--- a/libs/Zend/Db/Adapter/Pdo/Oci.php
+++ b/libs/Zend/Db/Adapter/Pdo/Oci.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Oci.php 16203 2009-06-21 18:56:17Z thomas $
+ * @version $Id: Oci.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Adapter_Pdo_Abstract
*/
-require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
+// require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
/**
@@ -33,7 +33,7 @@ require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Pdo_Oci extends Zend_Db_Adapter_Pdo_Abstract
@@ -186,7 +186,7 @@ class Zend_Db_Adapter_Pdo_Oci extends Zend_Db_Adapter_Pdo_Abstract
TC.DATA_SCALE, TC.DATA_PRECISION, C.CONSTRAINT_TYPE, CC.POSITION
FROM ALL_TAB_COLUMNS TC
LEFT JOIN (ALL_CONS_COLUMNS CC JOIN ALL_CONSTRAINTS C
- ON (CC.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND CC.TABLE_NAME = C.TABLE_NAME AND C.CONSTRAINT_TYPE = 'P'))
+ ON (CC.CONSTRAINT_NAME = C.CONSTRAINT_NAME AND CC.TABLE_NAME = C.TABLE_NAME AND CC.OWNER = C.OWNER AND C.CONSTRAINT_TYPE = 'P'))
ON TC.TABLE_NAME = CC.TABLE_NAME AND TC.COLUMN_NAME = CC.COLUMN_NAME
WHERE UPPER(TC.TABLE_NAME) = UPPER(:TBNAME)";
$bind[':TBNAME'] = $tableName;
@@ -347,14 +347,14 @@ class Zend_Db_Adapter_Pdo_Oci extends Zend_Db_Adapter_Pdo_Abstract
$count = intval($count);
if ($count <= 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument count=$count is not valid");
}
$offset = intval($offset);
if ($offset < 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument offset=$offset is not valid");
}
diff --git a/libs/Zend/Db/Adapter/Pdo/Pgsql.php b/libs/Zend/Db/Adapter/Pdo/Pgsql.php
index 0c1d0ca2e8..bec14b569b 100644
--- a/libs/Zend/Db/Adapter/Pdo/Pgsql.php
+++ b/libs/Zend/Db/Adapter/Pdo/Pgsql.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Pgsql.php 18646 2009-10-18 13:16:21Z mikaelkael $
+ * @version $Id: Pgsql.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Adapter_Pdo_Abstract
*/
-require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
+// require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
/**
@@ -33,7 +33,7 @@ require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Pdo_Pgsql extends Zend_Db_Adapter_Pdo_Abstract
@@ -195,15 +195,15 @@ class Zend_Db_Adapter_Pdo_Pgsql extends Zend_Db_Adapter_Pdo_Abstract
$desc = array();
foreach ($result as $key => $row) {
$defaultValue = $row[$default_value];
- if ($row[$type] == 'varchar') {
- if (preg_match('/character varying(?:\((\d+)\))?/', $row[$complete_type], $matches)) {
+ if ($row[$type] == 'varchar' || $row[$type] == 'bpchar' ) {
+ if (preg_match('/character(?: varying)?(?:\((\d+)\))?/', $row[$complete_type], $matches)) {
if (isset($matches[1])) {
$row[$length] = $matches[1];
} else {
$row[$length] = null; // unlimited
}
}
- if (preg_match("/^'(.*?)'::character varying$/", $defaultValue, $matches)) {
+ if (preg_match("/^'(.*?)'::(?:character varying|bpchar)$/", $defaultValue, $matches)) {
$defaultValue = $matches[1];
}
}
@@ -249,7 +249,7 @@ class Zend_Db_Adapter_Pdo_Pgsql extends Zend_Db_Adapter_Pdo_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument count=$count is not valid");
}
@@ -258,7 +258,7 @@ class Zend_Db_Adapter_Pdo_Pgsql extends Zend_Db_Adapter_Pdo_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument offset=$offset is not valid");
}
diff --git a/libs/Zend/Db/Adapter/Pdo/Sqlite.php b/libs/Zend/Db/Adapter/Pdo/Sqlite.php
index 82687d5a9d..f1e6562ef7 100644
--- a/libs/Zend/Db/Adapter/Pdo/Sqlite.php
+++ b/libs/Zend/Db/Adapter/Pdo/Sqlite.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Sqlite.php 18214 2009-09-18 05:30:19Z ralph $
+ * @version $Id: Sqlite.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Adapter_Pdo_Abstract
*/
-require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
+// require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
/**
@@ -33,7 +33,7 @@ require_once 'Zend/Db/Adapter/Pdo/Abstract.php';
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Pdo_Sqlite extends Zend_Db_Adapter_Pdo_Abstract
@@ -106,7 +106,7 @@ class Zend_Db_Adapter_Pdo_Sqlite extends Zend_Db_Adapter_Pdo_Abstract
// we need at least a dbname
if (! array_key_exists('dbname', $config)) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'dbname' that names the database instance");
}
}
@@ -140,7 +140,7 @@ class Zend_Db_Adapter_Pdo_Sqlite extends Zend_Db_Adapter_Pdo_Abstract
if ($retval === false) {
$error = $this->_connection->errorInfo();
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception($error[2]);
}
@@ -148,7 +148,7 @@ class Zend_Db_Adapter_Pdo_Sqlite extends Zend_Db_Adapter_Pdo_Abstract
if ($retval === false) {
$error = $this->_connection->errorInfo();
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception($error[2]);
}
}
@@ -198,11 +198,11 @@ class Zend_Db_Adapter_Pdo_Sqlite extends Zend_Db_Adapter_Pdo_Abstract
public function describeTable($tableName, $schemaName = null)
{
$sql = 'PRAGMA ';
-
+
if ($schemaName) {
$sql .= $this->quoteIdentifier($schemaName) . '.';
}
-
+
$sql .= 'table_info('.$this->quoteIdentifier($tableName).')';
$stmt = $this->query($sql);
@@ -275,14 +275,14 @@ class Zend_Db_Adapter_Pdo_Sqlite extends Zend_Db_Adapter_Pdo_Abstract
$count = intval($count);
if ($count <= 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument count=$count is not valid");
}
$offset = intval($offset);
if ($offset < 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument offset=$offset is not valid");
}
diff --git a/libs/Zend/Db/Adapter/Sqlsrv.php b/libs/Zend/Db/Adapter/Sqlsrv.php
index 3de2500ea1..533523759e 100644
--- a/libs/Zend/Db/Adapter/Sqlsrv.php
+++ b/libs/Zend/Db/Adapter/Sqlsrv.php
@@ -15,25 +15,26 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Sqlsrv.php 21197 2010-02-24 16:12:53Z rob $
*/
/**
* @see Zend_Db_Adapter_Abstract
*/
-require_once 'Zend/Db/Adapter/Abstract.php';
+// require_once 'Zend/Db/Adapter/Abstract.php';
/**
* @see Zend_Db_Statement_Sqlsrv
*/
-require_once 'Zend/Db/Statement/Sqlsrv.php';
+// require_once 'Zend/Db/Statement/Sqlsrv.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
@@ -120,7 +121,7 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Sqlsrv_Exception
*/
- require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
throw new Zend_Db_Adapter_Sqlsrv_Exception('The Sqlsrv extension is required for this adapter but the extension is not loaded');
}
@@ -147,11 +148,11 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
foreach ($this->_config['driver_options'] as $option => $value) {
// A value may be a constant.
if (is_string($value)) {
- $constantValue = @constant(strtoupper($value));
- if ($constantValue === null) {
- $connectionInfo[$option] = $value;
+ $constantName = strtoupper($value);
+ if (defined($constantName)) {
+ $connectionInfo[$option] = constant($constantName);
} else {
- $connectionInfo[$option] = $constantValue;
+ $connectionInfo[$option] = $value;
}
}
}
@@ -163,7 +164,7 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Sqlsrv_Exception
*/
- require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
throw new Zend_Db_Adapter_Sqlsrv_Exception(sqlsrv_errors());
}
}
@@ -180,7 +181,7 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
// we need at least a dbname
if (! array_key_exists('dbname', $config)) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'dbname' that names the database instance");
}
@@ -188,7 +189,7 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'password' for login credentials.
If Windows Authentication is desired, both keys 'username' and 'password' should be ommited from config.");
}
@@ -197,7 +198,7 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
/**
* @see Zend_Db_Adapter_Exception
*/
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'username' for login credentials.
If Windows Authentication is desired, both keys 'username' and 'password' should be ommited from config.");
}
@@ -238,12 +239,12 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
$sql = "SERIALIZABLE";
break;
default:
- require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
throw new Zend_Db_Adapter_Sqlsrv_Exception("Invalid transaction isolation level mode '$level' specified");
}
if (!sqlsrv_query($this->_connection, "SET TRANSACTION ISOLATION LEVEL $sql;")) {
- require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
throw new Zend_Db_Adapter_Sqlsrv_Exception("Transaction cannot be changed to '$level'");
}
@@ -286,13 +287,13 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
$this->_connect();
$stmtClass = $this->_defaultStmtClass;
- if (!class_exists($stmtClass)) {
+ // if (!class_exists($stmtClass)) {
/**
* @see Zend_Loader
*/
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($stmtClass);
- }
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($stmtClass);
+ // }
$stmt = new $stmtClass($this, $sql);
$stmt->setFetchMode($this->_fetchMode);
@@ -518,7 +519,7 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
protected function _beginTransaction()
{
if (!sqlsrv_begin_transaction($this->_connection)) {
- require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
throw new Zend_Db_Adapter_Sqlsrv_Exception(sqlsrv_errors());
}
}
@@ -532,7 +533,7 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
protected function _commit()
{
if (!sqlsrv_commit($this->_connection)) {
- require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
throw new Zend_Db_Adapter_Sqlsrv_Exception(sqlsrv_errors());
}
}
@@ -546,7 +547,7 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
protected function _rollBack()
{
if (!sqlsrv_rollback($this->_connection)) {
- require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
throw new Zend_Db_Adapter_Sqlsrv_Exception(sqlsrv_errors());
}
}
@@ -570,11 +571,11 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
$this->_fetchMode = $mode;
break;
case Zend_Db::FETCH_BOUND: // bound to PHP variable
- require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
throw new Zend_Db_Adapter_Sqlsrv_Exception('FETCH_BOUND is not supported yet');
break;
default:
- require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Adapter/Sqlsrv/Exception.php';
throw new Zend_Db_Adapter_Sqlsrv_Exception("Invalid fetch mode '$mode' specified");
break;
}
@@ -593,34 +594,40 @@ class Zend_Db_Adapter_Sqlsrv extends Zend_Db_Adapter_Abstract
{
$count = intval($count);
if ($count <= 0) {
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument count=$count is not valid");
}
$offset = intval($offset);
if ($offset < 0) {
/** @see Zend_Db_Adapter_Exception */
- require_once 'Zend/Db/Adapter/Exception.php';
+ // require_once 'Zend/Db/Adapter/Exception.php';
throw new Zend_Db_Adapter_Exception("LIMIT argument offset=$offset is not valid");
}
- $orderby = stristr($sql, 'ORDER BY');
- if ($orderby !== false) {
- $sort = (stripos($orderby, ' desc') !== false) ? 'desc' : 'asc';
- $order = str_ireplace('ORDER BY', '', $orderby);
- $order = trim(preg_replace('/\bASC\b|\bDESC\b/i', '', $order));
- }
-
- $sql = preg_replace('/^SELECT\s/i', 'SELECT TOP ' . ($count+$offset) . ' ', $sql);
-
- $sql = 'SELECT * FROM (SELECT TOP ' . $count . ' * FROM (' . $sql . ') AS inner_tbl';
- if ($orderby !== false) {
- $sql .= ' ORDER BY ' . $order . ' ';
- $sql .= (stripos($sort, 'asc') !== false) ? 'DESC' : 'ASC';
- }
- $sql .= ') AS outer_tbl';
- if ($orderby !== false) {
- $sql .= ' ORDER BY ' . $order . ' ' . $sort;
+ if ($offset == 0) {
+ $sql = preg_replace('/^SELECT\s/i', 'SELECT TOP ' . $count . ' ', $sql);
+ } else {
+ $orderby = stristr($sql, 'ORDER BY');
+ if ($orderby !== false) {
+ $sort = (stripos($orderby, ' desc') !== false) ? 'desc' : 'asc';
+ $order = str_ireplace('ORDER BY', '', $orderby);
+ $order = trim(preg_replace('/\bASC\b|\bDESC\b/i', '', $order));
+ }
+
+ $sql = preg_replace('/^SELECT\s/i', 'SELECT TOP ' . ($count+$offset) . ' ', $sql);
+
+ $sql = 'SELECT * FROM (SELECT TOP ' . $count . ' * FROM (' . $sql . ') AS inner_tbl';
+ if ($orderby !== false) {
+ $innerOrder = preg_replace('/\".*\".\"(.*)\"/i', '"inner_tbl"."$1"', $order);
+ $sql .= ' ORDER BY ' . $innerOrder . ' ';
+ $sql .= (stripos($sort, 'asc') !== false) ? 'DESC' : 'ASC';
+ }
+ $sql .= ') AS outer_tbl';
+ if ($orderby !== false) {
+ $outerOrder = preg_replace('/\".*\".\"(.*)\"/i', '"outer_tbl"."$1"', $order);
+ $sql .= ' ORDER BY ' . $outerOrder . ' ' . $sort;
+ }
}
return $sql;
diff --git a/libs/Zend/Db/Adapter/Sqlsrv/Exception.php b/libs/Zend/Db/Adapter/Sqlsrv/Exception.php
index a07b3eb9a3..1f68aa9c56 100644
--- a/libs/Zend/Db/Adapter/Sqlsrv/Exception.php
+++ b/libs/Zend/Db/Adapter/Sqlsrv/Exception.php
@@ -15,15 +15,15 @@
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- *
+ * @version $Id: Exception.php 20629 2010-01-25 21:17:23Z ralph $
*/
/**
* @see Zend_Db_Adapter_Exception
*/
-require_once 'Zend/Db/Adapter/Exception.php';
+// require_once 'Zend/Db/Adapter/Exception.php';
/**
* Zend_Db_Adapter_Sqlsrv_Exception
@@ -31,7 +31,7 @@ require_once 'Zend/Db/Adapter/Exception.php';
* @category Zend
* @package Zend_Db
* @subpackage Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Adapter_Sqlsrv_Exception extends Zend_Db_Adapter_Exception
@@ -58,6 +58,6 @@ class Zend_Db_Adapter_Sqlsrv_Exception extends Zend_Db_Adapter_Exception
$code = (int) $message['code'];
$message = (string) $message['message'];
}
- parent::__construct($message, new Exception($message, $code));
+ parent::__construct($message, $code, new Exception($message, $code));
}
}
diff --git a/libs/Zend/Db/Exception.php b/libs/Zend/Db/Exception.php
index 3d30302674..43e374b1b0 100644
--- a/libs/Zend/Db/Exception.php
+++ b/libs/Zend/Db/Exception.php
@@ -14,20 +14,20 @@
*
* @category Zend
* @package Zend_Db
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Exception
*/
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Db
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Exception extends Zend_Exception
diff --git a/libs/Zend/Db/Expr.php b/libs/Zend/Db/Expr.php
index 2f2b7d51db..df366b3b2a 100644
--- a/libs/Zend/Db/Expr.php
+++ b/libs/Zend/Db/Expr.php
@@ -15,9 +15,9 @@
* @category Zend
* @package Zend_Db
* @subpackage Expr
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Expr.php 16203 2009-06-21 18:56:17Z thomas $
+ * @version $Id: Expr.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -43,7 +43,7 @@
* @category Zend
* @package Zend_Db
* @subpackage Expr
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Expr
diff --git a/libs/Zend/Db/Profiler.php b/libs/Zend/Db/Profiler.php
index d0b2af5f1a..9d695b877d 100644
--- a/libs/Zend/Db/Profiler.php
+++ b/libs/Zend/Db/Profiler.php
@@ -15,9 +15,9 @@
* @category Zend
* @package Zend_Db
* @subpackage Profiler
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Profiler.php 16203 2009-06-21 18:56:17Z thomas $
+ * @version $Id: Profiler.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,7 +25,7 @@
* @category Zend
* @package Zend_Db
* @subpackage Profiler
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Profiler
@@ -68,6 +68,15 @@ class Zend_Db_Profiler
*/
const TRANSACTION = 64;
+ /**
+ * Inform that a query is stored (in case of filtering)
+ */
+ const STORED = 'stored';
+
+ /**
+ * Inform that a query is ignored (in case of filtering)
+ */
+ const IGNORED = 'ignored';
/**
* Array of Zend_Db_Profiler_Query objects.
@@ -269,7 +278,7 @@ class Zend_Db_Profiler
/**
* @see Zend_Db_Profiler_Query
*/
- require_once 'Zend/Db/Profiler/Query.php';
+ // require_once 'Zend/Db/Profiler/Query.php';
$this->_queryProfiles[] = new Zend_Db_Profiler_Query($queryText, $queryType);
end($this->_queryProfiles);
@@ -289,7 +298,7 @@ class Zend_Db_Profiler
{
// Don't do anything if the Zend_Db_Profiler is not enabled.
if (!$this->_enabled) {
- return;
+ return self::IGNORED;
}
// Check for a valid query handle.
@@ -297,7 +306,7 @@ class Zend_Db_Profiler
/**
* @see Zend_Db_Profiler_Exception
*/
- require_once 'Zend/Db/Profiler/Exception.php';
+ // require_once 'Zend/Db/Profiler/Exception.php';
throw new Zend_Db_Profiler_Exception("Profiler has no query with handle '$queryId'.");
}
@@ -308,7 +317,7 @@ class Zend_Db_Profiler
/**
* @see Zend_Db_Profiler_Exception
*/
- require_once 'Zend/Db/Profiler/Exception.php';
+ // require_once 'Zend/Db/Profiler/Exception.php';
throw new Zend_Db_Profiler_Exception("Query with profiler handle '$queryId' has already ended.");
}
@@ -321,7 +330,7 @@ class Zend_Db_Profiler
*/
if (null !== $this->_filterElapsedSecs && $qp->getElapsedSecs() < $this->_filterElapsedSecs) {
unset($this->_queryProfiles[$queryId]);
- return;
+ return self::IGNORED;
}
/**
@@ -330,8 +339,10 @@ class Zend_Db_Profiler
*/
if (null !== $this->_filterTypes && !($qp->getQueryType() & $this->_filterTypes)) {
unset($this->_queryProfiles[$queryId]);
- return;
+ return self::IGNORED;
}
+
+ return self::STORED;
}
/**
@@ -348,7 +359,7 @@ class Zend_Db_Profiler
/**
* @see Zend_Db_Profiler_Exception
*/
- require_once 'Zend/Db/Profiler/Exception.php';
+ // require_once 'Zend/Db/Profiler/Exception.php';
throw new Zend_Db_Profiler_Exception("Query handle '$queryId' not found in profiler log.");
}
diff --git a/libs/Zend/Db/Profiler/Exception.php b/libs/Zend/Db/Profiler/Exception.php
index 3494622c2d..6caab626f7 100644
--- a/libs/Zend/Db/Profiler/Exception.php
+++ b/libs/Zend/Db/Profiler/Exception.php
@@ -15,23 +15,23 @@
* @category Zend
* @package Zend_Db
* @subpackage Profiler
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16203 2009-06-21 18:56:17Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Exception
*/
-require_once 'Zend/Db/Exception.php';
+// require_once 'Zend/Db/Exception.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Profiler
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Profiler_Exception extends Zend_Db_Exception
diff --git a/libs/Zend/Db/Profiler/Firebug.php b/libs/Zend/Db/Profiler/Firebug.php
index 35a4ebd7b9..0ffaf142be 100644
--- a/libs/Zend/Db/Profiler/Firebug.php
+++ b/libs/Zend/Db/Profiler/Firebug.php
@@ -15,27 +15,27 @@
* @category Zend
* @package Zend_Db
* @subpackage Profiler
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Firebug.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Firebug.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Db_Profiler */
-require_once 'Zend/Db/Profiler.php';
+// require_once 'Zend/Db/Profiler.php';
/** Zend_Wildfire_Plugin_FirePhp */
-require_once 'Zend/Wildfire/Plugin/FirePhp.php';
+// require_once 'Zend/Wildfire/Plugin/FirePhp.php';
/** Zend_Wildfire_Plugin_FirePhp_TableMessage */
-require_once 'Zend/Wildfire/Plugin/FirePhp/TableMessage.php';
+// require_once 'Zend/Wildfire/Plugin/FirePhp/TableMessage.php';
/**
* Writes DB events as log messages to the Firebug Console via FirePHP.
- *
+ *
* @category Zend
* @package Zend_Db
* @subpackage Profiler
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Profiler_Firebug extends Zend_Db_Profiler
@@ -45,25 +45,25 @@ class Zend_Db_Profiler_Firebug extends Zend_Db_Profiler
* @var string
*/
protected $_label = null;
-
+
/**
* The label template for this profiler
* @var string
*/
protected $_label_template = '%label% (%totalCount% @ %totalDuration% sec)';
-
+
/**
* The message envelope holding the profiling summary
* @var Zend_Wildfire_Plugin_FirePhp_TableMessage
*/
protected $_message = null;
-
+
/**
* The total time taken for all profiled queries.
* @var float
*/
protected $_totalElapsedTime = 0;
-
+
/**
* Constructor
*
@@ -90,7 +90,7 @@ class Zend_Db_Profiler_Firebug extends Zend_Db_Profiler
parent::setEnabled($enable);
if ($this->getEnabled()) {
-
+
if (!$this->_message) {
$this->_message = new Zend_Wildfire_Plugin_FirePhp_TableMessage($this->_label);
$this->_message->setBuffered(true);
@@ -106,7 +106,7 @@ class Zend_Db_Profiler_Firebug extends Zend_Db_Profiler
$this->_message->setDestroy(true);
$this->_message = null;
}
-
+
}
return $this;
@@ -121,28 +121,28 @@ class Zend_Db_Profiler_Firebug extends Zend_Db_Profiler
*/
public function queryEnd($queryId)
{
- parent::queryEnd($queryId);
-
- if (!$this->getEnabled()) {
+ $state = parent::queryEnd($queryId);
+
+ if (!$this->getEnabled() || $state == self::IGNORED) {
return;
}
$this->_message->setDestroy(false);
$profile = $this->getQueryProfile($queryId);
-
+
$this->_totalElapsedTime += $profile->getElapsedSecs();
-
+
$this->_message->addRow(array((string)round($profile->getElapsedSecs(),5),
$profile->getQuery(),
($params=$profile->getQueryParams())?$params:null));
-
+
$this->updateMessageLabel();
}
-
+
/**
* Update the label of the message holding the profile info.
- *
+ *
* @return void
*/
protected function updateMessageLabel()
diff --git a/libs/Zend/Db/Profiler/Query.php b/libs/Zend/Db/Profiler/Query.php
index 74f3fe1aec..aacc16fbb9 100644
--- a/libs/Zend/Db/Profiler/Query.php
+++ b/libs/Zend/Db/Profiler/Query.php
@@ -15,9 +15,9 @@
* @category Zend
* @package Zend_Db
* @subpackage Profiler
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Query.php 16203 2009-06-21 18:56:17Z thomas $
+ * @version $Id: Query.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,7 +25,7 @@
* @category Zend
* @package Zend_Db
* @subpackage Profiler
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Profiler_Query
diff --git a/libs/Zend/Db/Select.php b/libs/Zend/Db/Select.php
index c8f1c77607..721f3ec859 100644
--- a/libs/Zend/Db/Select.php
+++ b/libs/Zend/Db/Select.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Db
* @subpackage Select
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Select.php 18511 2009-10-12 14:33:35Z ralph $
+ * @version $Id: Select.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Adapter_Abstract
*/
-require_once 'Zend/Db/Adapter/Abstract.php';
+// require_once 'Zend/Db/Adapter/Abstract.php';
/**
* @see Zend_Db_Expr
*/
-require_once 'Zend/Db/Expr.php';
+// require_once 'Zend/Db/Expr.php';
/**
@@ -38,7 +38,7 @@ require_once 'Zend/Db/Expr.php';
* @category Zend
* @package Zend_Db
* @subpackage Select
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Select
@@ -173,7 +173,7 @@ class Zend_Db_Select
*/
public function getBind()
{
- return $this->_bind;
+ return $this->_bind;
}
/**
@@ -184,9 +184,9 @@ class Zend_Db_Select
*/
public function bind($bind)
{
- $this->_bind = $bind;
+ $this->_bind = $bind;
- return $this;
+ return $this;
}
/**
@@ -243,14 +243,15 @@ class Zend_Db_Select
public function columns($cols = '*', $correlationName = null)
{
if ($correlationName === null && count($this->_parts[self::FROM])) {
- $correlationName = current(array_keys($this->_parts[self::FROM]));
+ $correlationNameKeys = array_keys($this->_parts[self::FROM]);
+ $correlationName = current($correlationNameKeys);
}
if (!array_key_exists($correlationName, $this->_parts[self::FROM])) {
/**
* @see Zend_Db_Select_Exception
*/
- require_once 'Zend/Db/Select/Exception.php';
+ // require_once 'Zend/Db/Select/Exception.php';
throw new Zend_Db_Select_Exception("No table has been specified for the FROM clause");
}
@@ -262,20 +263,31 @@ class Zend_Db_Select
/**
* Adds a UNION clause to the query.
*
- * The first parameter $select can be a string, an existing Zend_Db_Select
- * object or an array of either of these types.
+ * The first parameter has to be an array of Zend_Db_Select or
+ * sql query strings.
*
- * @param array|string|Zend_Db_Select $select One or more select clauses for the UNION.
+ * <code>
+ * $sql1 = $db->select();
+ * $sql2 = "SELECT ...";
+ * $select = $db->select()
+ * ->union(array($sql1, $sql2))
+ * ->order("id");
+ * </code>
+ *
+ * @param array $select Array of select clauses for the union.
* @return Zend_Db_Select This Zend_Db_Select object.
*/
public function union($select = array(), $type = self::SQL_UNION)
{
if (!is_array($select)) {
- $select = array();
+ // require_once 'Zend/Db/Select/Exception.php';
+ throw new Zend_Db_Select_Exception(
+ "union() only accepts an array of Zend_Db_Select instances of sql query strings."
+ );
}
if (!in_array($type, self::$_unionTypes)) {
- require_once 'Zend/Db/Select/Exception.php';
+ // require_once 'Zend/Db/Select/Exception.php';
throw new Zend_Db_Select_Exception("Invalid union type '{$type}'");
}
@@ -454,7 +466,7 @@ class Zend_Db_Select
* </code>
*
* @param string $cond The WHERE condition.
- * @param string $value OPTIONAL A single value to quote into the condition.
+ * @param mixed $value OPTIONAL The value to quote into the condition.
* @param constant $type OPTIONAL The type of the given value
* @return Zend_Db_Select This Zend_Db_Select object.
*/
@@ -471,7 +483,7 @@ class Zend_Db_Select
* Otherwise identical to where().
*
* @param string $cond The WHERE condition.
- * @param string $value OPTIONAL A single value to quote into the condition.
+ * @param mixed $value OPTIONAL The value to quote into the condition.
* @param constant $type OPTIONAL The type of the given value
* @return Zend_Db_Select This Zend_Db_Select object.
*
@@ -514,7 +526,7 @@ class Zend_Db_Select
* appears. See {@link where()} for an example
*
* @param string $cond The HAVING condition.
- * @param string|Zend_Db_Expr $val A single value to quote into the condition.
+ * @param string|Zend_Db_Expr $val The value to quote into the condition.
* @return Zend_Db_Select This Zend_Db_Select object.
*/
public function having($cond)
@@ -539,7 +551,7 @@ class Zend_Db_Select
* Otherwise identical to orHaving().
*
* @param string $cond The HAVING condition.
- * @param string $val A single value to quote into the condition.
+ * @param mixed $val The value to quote into the condition.
* @return Zend_Db_Select This Zend_Db_Select object.
*
* @see having()
@@ -652,7 +664,7 @@ class Zend_Db_Select
{
$part = strtolower($part);
if (!array_key_exists($part, $this->_parts)) {
- require_once 'Zend/Db/Select/Exception.php';
+ // require_once 'Zend/Db/Select/Exception.php';
throw new Zend_Db_Select_Exception("Invalid Select part '$part'");
}
return $this->_parts[$part];
@@ -745,12 +757,12 @@ class Zend_Db_Select
/**
* @see Zend_Db_Select_Exception
*/
- require_once 'Zend/Db/Select/Exception.php';
+ // require_once 'Zend/Db/Select/Exception.php';
throw new Zend_Db_Select_Exception("Invalid join type '$type'");
}
if (count($this->_parts[self::UNION])) {
- require_once 'Zend/Db/Select/Exception.php';
+ // require_once 'Zend/Db/Select/Exception.php';
throw new Zend_Db_Select_Exception("Invalid use of table with " . self::SQL_UNION);
}
@@ -786,16 +798,16 @@ class Zend_Db_Select
list($schema, $tableName) = explode('.', $tableName);
}
+ $lastFromCorrelationName = null;
if (!empty($correlationName)) {
if (array_key_exists($correlationName, $this->_parts[self::FROM])) {
/**
* @see Zend_Db_Select_Exception
*/
- require_once 'Zend/Db/Select/Exception.php';
+ // require_once 'Zend/Db/Select/Exception.php';
throw new Zend_Db_Select_Exception("You cannot define a correlation name '$correlationName' more than once");
}
-
- $lastFromCorrelationName = null;
+
if ($type == self::FROM) {
// append this from after the last from joinType
$tmpFromParts = $this->_parts[self::FROM];
@@ -827,7 +839,7 @@ class Zend_Db_Select
// add to the columns from this joined table
if ($type == self::FROM && $lastFromCorrelationName == null) {
$lastFromCorrelationName = true;
- }
+ }
$this->_tableCols($correlationName, $cols, $lastFromCorrelationName);
return $this;
@@ -861,7 +873,7 @@ class Zend_Db_Select
public function _joinUsing($type, $name, $cond, $cols = '*', $schema = null)
{
if (empty($this->_parts[self::FROM])) {
- require_once 'Zend/Db/Select/Exception.php';
+ // require_once 'Zend/Db/Select/Exception.php';
throw new Zend_Db_Select_Exception("You can only perform a joinUsing after specifying a FROM table");
}
@@ -945,7 +957,7 @@ class Zend_Db_Select
} else {
$tmpColumns = array();
}
-
+
// find the correlation name to insert after
if (is_string($afterCorrelationName)) {
while ($tmpColumns) {
@@ -960,7 +972,7 @@ class Zend_Db_Select
foreach ($columnValues as $columnValue) {
array_push($this->_parts[self::COLUMNS], $columnValue);
}
-
+
// finish ensuring that all previous values are applied (if they exist)
while ($tmpColumns) {
array_push($this->_parts[self::COLUMNS], array_shift($tmpColumns));
@@ -972,7 +984,7 @@ class Zend_Db_Select
* Internal function for creating the where clause
*
* @param string $condition
- * @param string $value optional
+ * @param mixed $value optional
* @param string $type optional
* @param boolean $bool true = AND, false = OR
* @return string clause
@@ -980,7 +992,7 @@ class Zend_Db_Select
protected function _where($condition, $value = null, $type = null, $bool = true)
{
if (count($this->_parts[self::UNION])) {
- require_once 'Zend/Db/Select/Exception.php';
+ // require_once 'Zend/Db/Select/Exception.php';
throw new Zend_Db_Select_Exception("Invalid use of where clause with " . self::SQL_UNION);
}
@@ -1104,7 +1116,7 @@ class Zend_Db_Select
$tmp = '';
$joinType = ($table['joinType'] == self::FROM) ? self::INNER_JOIN : $table['joinType'];
-
+
// Add join clause (if applicable)
if (! empty($from)) {
$tmp .= ' ' . strtoupper($joinType) . ' ';
@@ -1246,8 +1258,7 @@ class Zend_Db_Select
if (!empty($this->_parts[self::LIMIT_OFFSET])) {
$offset = (int) $this->_parts[self::LIMIT_OFFSET];
- // This should reduce to the max integer PHP can support
- $count = intval(9223372036854775807);
+ $count = PHP_INT_MAX;
}
if (!empty($this->_parts[self::LIMIT_COUNT])) {
@@ -1303,11 +1314,11 @@ class Zend_Db_Select
if ($type) {
$type .= ' join';
if (!in_array($type, self::$_joinTypes)) {
- require_once 'Zend/Db/Select/Exception.php';
+ // require_once 'Zend/Db/Select/Exception.php';
throw new Zend_Db_Select_Exception("Unrecognized method '$method()'");
}
if (in_array($type, array(self::CROSS_JOIN, self::NATURAL_JOIN))) {
- require_once 'Zend/Db/Select/Exception.php';
+ // require_once 'Zend/Db/Select/Exception.php';
throw new Zend_Db_Select_Exception("Cannot perform a joinUsing with method '$method()'");
}
} else {
@@ -1317,7 +1328,7 @@ class Zend_Db_Select
return call_user_func_array(array($this, '_joinUsing'), $args);
}
- require_once 'Zend/Db/Select/Exception.php';
+ // require_once 'Zend/Db/Select/Exception.php';
throw new Zend_Db_Select_Exception("Unrecognized method '$method()'");
}
diff --git a/libs/Zend/Db/Select/Exception.php b/libs/Zend/Db/Select/Exception.php
index 23fdf2dfec..dc02cb40ab 100644
--- a/libs/Zend/Db/Select/Exception.php
+++ b/libs/Zend/Db/Select/Exception.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Db
* @subpackage Select
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Db_Exception
*/
-require_once 'Zend/Db/Exception.php';
+// require_once 'Zend/Db/Exception.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Select
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
diff --git a/libs/Zend/Db/Statement.php b/libs/Zend/Db/Statement.php
index 7dada0964a..df99fa0133 100644
--- a/libs/Zend/Db/Statement.php
+++ b/libs/Zend/Db/Statement.php
@@ -15,20 +15,20 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Statement.php 17858 2009-08-27 22:04:38Z ralph $
+ * @version $Id: Statement.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db
*/
-require_once 'Zend/Db.php';
+// require_once 'Zend/Db.php';
/**
* @see Zend_Db_Statement_Interface
*/
-require_once 'Zend/Db/Statement/Interface.php';
+// require_once 'Zend/Db/Statement/Interface.php';
/**
* Abstract class to emulate a PDOStatement for native database adapters.
@@ -36,7 +36,7 @@ require_once 'Zend/Db/Statement/Interface.php';
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
@@ -46,7 +46,7 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
* @var resource|object The driver level statement object/resource
*/
protected $_stmt = null;
-
+
/**
* @var Zend_Db_Adapter_Abstract
*/
@@ -120,14 +120,14 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
/**
* Internal method called by abstract statment constructor to setup
* the driver level statement
- *
+ *
* @return void
*/
protected function _prepare($sql)
{
return;
}
-
+
/**
* @param string $sql
* @return void
@@ -148,7 +148,7 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
/**
* @see Zend_Db_Statement_Exception
*/
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception("Invalid bind-variable position '$val'");
}
} else if ($val[0] == ':') {
@@ -156,7 +156,7 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
/**
* @see Zend_Db_Statement_Exception
*/
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception("Invalid bind-variable name '$val'");
}
}
@@ -241,7 +241,7 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
/**
* @see Zend_Db_Statement_Exception
*/
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception('Invalid bind-variable position');
}
@@ -263,7 +263,7 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
/**
* @see Zend_Db_Statement_Exception
*/
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception("Invalid bind-variable position '$parameter'");
}
@@ -433,7 +433,7 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
/**
* @see Zend_Db_Statement_Exception
*/
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception('invalid fetch mode');
break;
}
@@ -472,9 +472,9 @@ abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
{
return $this->_adapter;
}
-
+
/**
- * Gets the resource or object setup by the
+ * Gets the resource or object setup by the
* _parse
* @return unknown_type
*/
diff --git a/libs/Zend/Db/Statement/Db2.php b/libs/Zend/Db/Statement/Db2.php
index c2dac3a646..729d65c61a 100644
--- a/libs/Zend/Db/Statement/Db2.php
+++ b/libs/Zend/Db/Statement/Db2.php
@@ -15,22 +15,22 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Db2.php 17857 2009-08-27 22:01:47Z ralph $
+ * @version $Id: Db2.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Statement
*/
-require_once 'Zend/Db/Statement.php';
+// require_once 'Zend/Db/Statement.php';
/**
* Extends for DB2 native adapter.
*
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Statement_Db2 extends Zend_Db_Statement
@@ -65,7 +65,7 @@ class Zend_Db_Statement_Db2 extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Db2_Exception
*/
- require_once 'Zend/Db/Statement/Db2/Exception.php';
+ // require_once 'Zend/Db/Statement/Db2/Exception.php';
throw new Zend_Db_Statement_Db2_Exception(
db2_stmt_errormsg(),
db2_stmt_error()
@@ -100,7 +100,7 @@ class Zend_Db_Statement_Db2 extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Db2_Exception
*/
- require_once 'Zend/Db/Statement/Db2/Exception.php';
+ // require_once 'Zend/Db/Statement/Db2/Exception.php';
throw new Zend_Db_Statement_Db2_Exception(
db2_stmt_errormsg(),
db2_stmt_error()
@@ -154,7 +154,7 @@ class Zend_Db_Statement_Db2 extends Zend_Db_Statement
$error = db2_stmt_error();
if ($error === '') {
- return false;
+ return false;
}
return $error;
@@ -168,10 +168,10 @@ class Zend_Db_Statement_Db2 extends Zend_Db_Statement
*/
public function errorInfo()
{
- $error = $this->errorCode();
- if ($error === false){
- return false;
- }
+ $error = $this->errorCode();
+ if ($error === false){
+ return false;
+ }
/*
* Return three-valued array like PDO. But DB2 does not distinguish
@@ -208,7 +208,7 @@ class Zend_Db_Statement_Db2 extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Db2_Exception
*/
- require_once 'Zend/Db/Statement/Db2/Exception.php';
+ // require_once 'Zend/Db/Statement/Db2/Exception.php';
throw new Zend_Db_Statement_Db2_Exception(
db2_stmt_errormsg(),
db2_stmt_error());
@@ -272,7 +272,7 @@ class Zend_Db_Statement_Db2 extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Db2_Exception
*/
- require_once 'Zend/Db/Statement/Db2/Exception.php';
+ // require_once 'Zend/Db/Statement/Db2/Exception.php';
throw new Zend_Db_Statement_Db2_Exception("Invalid fetch mode '$style' specified");
break;
}
@@ -306,7 +306,7 @@ class Zend_Db_Statement_Db2 extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Db2_Exception
*/
- require_once 'Zend/Db/Statement/Db2/Exception.php';
+ // require_once 'Zend/Db/Statement/Db2/Exception.php';
throw new Zend_Db_Statement_Db2_Exception(__FUNCTION__ . '() is not implemented');
}
diff --git a/libs/Zend/Db/Statement/Db2/Exception.php b/libs/Zend/Db/Statement/Db2/Exception.php
index 0b04bf4af2..d77b5d830c 100644
--- a/libs/Zend/Db/Statement/Db2/Exception.php
+++ b/libs/Zend/Db/Statement/Db2/Exception.php
@@ -15,20 +15,20 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Db_Statement_Exception
*/
-require_once 'Zend/Db/Statement/Exception.php';
+// require_once 'Zend/Db/Statement/Exception.php';
/**
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
diff --git a/libs/Zend/Db/Statement/Exception.php b/libs/Zend/Db/Statement/Exception.php
index 7c9d58992a..511888a5e3 100644
--- a/libs/Zend/Db/Statement/Exception.php
+++ b/libs/Zend/Db/Statement/Exception.php
@@ -15,15 +15,15 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 17860 2009-08-27 22:48:48Z beberlei $
+ * @version $Id: Exception.php 20514 2010-01-22 07:57:10Z ralph $
*/
/**
* @see Zend_Db_Exception
*/
-require_once 'Zend/Db/Exception.php';
+// require_once 'Zend/Db/Exception.php';
/**
* Zend_Db_Statement_Exception
@@ -31,36 +31,19 @@ require_once 'Zend/Db/Exception.php';
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Statement_Exception extends Zend_Db_Exception
{
/**
- * @var Exception
- */
- protected $_chainedException = null;
-
- /**
- * @param string $message
- * @param string|int $code
- * @param Exception $chainedException
- */
- public function __construct($message = null, $code = null, Exception $chainedException=null)
- {
- $this->message = $message;
- $this->code = $code;
- $this->_chainedException = $chainedException;
- }
-
- /**
* Check if this general exception has a specific database driver specific exception nested inside.
- *
+ *
* @return bool
*/
public function hasChainedException()
{
- return ($this->_chainedException!==null);
+ return ($this->getPrevious() !== null);
}
/**
@@ -68,6 +51,6 @@ class Zend_Db_Statement_Exception extends Zend_Db_Exception
*/
public function getChainedException()
{
- return $this->_chainedException;
+ return $this->getPrevious();
}
}
diff --git a/libs/Zend/Db/Statement/Interface.php b/libs/Zend/Db/Statement/Interface.php
index 2cf951b057..701c64010e 100644
--- a/libs/Zend/Db/Statement/Interface.php
+++ b/libs/Zend/Db/Statement/Interface.php
@@ -15,9 +15,9 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
@@ -26,7 +26,7 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Db_Statement_Interface
diff --git a/libs/Zend/Db/Statement/Mysqli.php b/libs/Zend/Db/Statement/Mysqli.php
index a1870f13fa..51dba7160f 100644
--- a/libs/Zend/Db/Statement/Mysqli.php
+++ b/libs/Zend/Db/Statement/Mysqli.php
@@ -15,25 +15,25 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mysqli.php 18195 2009-09-17 20:58:05Z bittarman $
+ * @version $Id: Mysqli.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Statement
*/
-require_once 'Zend/Db/Statement.php';
+// require_once 'Zend/Db/Statement.php';
+
-
/**
* Extends for Mysqli
*
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Statement_Mysqli extends Zend_Db_Statement
@@ -73,7 +73,7 @@ class Zend_Db_Statement_Mysqli extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Mysqli_Exception
*/
- require_once 'Zend/Db/Statement/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Statement/Mysqli/Exception.php';
throw new Zend_Db_Statement_Mysqli_Exception("Mysqli prepare error: " . $mysqli->error, $mysqli->errno);
}
}
@@ -210,7 +210,7 @@ class Zend_Db_Statement_Mysqli extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Mysqli_Exception
*/
- require_once 'Zend/Db/Statement/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Statement/Mysqli/Exception.php';
throw new Zend_Db_Statement_Mysqli_Exception("Mysqli statement execute error : " . $this->_stmt->error, $this->_stmt->errno);
}
@@ -222,7 +222,7 @@ class Zend_Db_Statement_Mysqli extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Mysqli_Exception
*/
- require_once 'Zend/Db/Statement/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Statement/Mysqli/Exception.php';
throw new Zend_Db_Statement_Mysqli_Exception("Mysqli statement metadata error: " . $this->_stmt->error, $this->_stmt->errno);
}
}
@@ -275,12 +275,12 @@ class Zend_Db_Statement_Mysqli extends Zend_Db_Statement
// fetch the next result
$retval = $this->_stmt->fetch();
switch ($retval) {
- case null: // end of data
- case false: // error occurred
- $this->_stmt->reset();
- return false;
- default:
- // fallthrough
+ case null: // end of data
+ case false: // error occurred
+ $this->_stmt->reset();
+ return false;
+ default:
+ // fallthrough
}
// make sure we have a fetch mode
@@ -319,7 +319,7 @@ class Zend_Db_Statement_Mysqli extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Mysqli_Exception
*/
- require_once 'Zend/Db/Statement/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Statement/Mysqli/Exception.php';
throw new Zend_Db_Statement_Mysqli_Exception("Invalid fetch mode '$style' specified");
break;
}
@@ -339,7 +339,7 @@ class Zend_Db_Statement_Mysqli extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Mysqli_Exception
*/
- require_once 'Zend/Db/Statement/Mysqli/Exception.php';
+ // require_once 'Zend/Db/Statement/Mysqli/Exception.php';
throw new Zend_Db_Statement_Mysqli_Exception(__FUNCTION__.'() is not implemented');
}
diff --git a/libs/Zend/Db/Statement/Mysqli/Exception.php b/libs/Zend/Db/Statement/Mysqli/Exception.php
index a90162db02..4847231476 100644
--- a/libs/Zend/Db/Statement/Mysqli/Exception.php
+++ b/libs/Zend/Db/Statement/Mysqli/Exception.php
@@ -15,20 +15,20 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Db_Statement_Exception
*/
-require_once 'Zend/Db/Statement/Exception.php';
+// require_once 'Zend/Db/Statement/Exception.php';
/**
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
diff --git a/libs/Zend/Db/Statement/Oracle.php b/libs/Zend/Db/Statement/Oracle.php
index 0c8c18a6bd..d84d2bab7f 100644
--- a/libs/Zend/Db/Statement/Oracle.php
+++ b/libs/Zend/Db/Statement/Oracle.php
@@ -15,15 +15,15 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Oracle.php 18636 2009-10-17 05:44:41Z ralph $
+ * @version $Id: Oracle.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Statement
*/
-require_once 'Zend/Db/Statement.php';
+// require_once 'Zend/Db/Statement.php';
/**
* Extends for Oracle.
@@ -31,7 +31,7 @@ require_once 'Zend/Db/Statement.php';
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Statement_Oracle extends Zend_Db_Statement
@@ -92,7 +92,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception(oci_error($connection));
}
}
@@ -125,7 +125,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception(oci_error($this->_stmt));
}
@@ -249,7 +249,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception(oci_error($this->_stmt));
}
}
@@ -259,7 +259,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception(oci_error($this->_stmt));
}
@@ -323,7 +323,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception(
array(
'code' => 'HYC00',
@@ -337,7 +337,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception($error);
}
@@ -374,7 +374,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception(
array(
'code' => 'HYC00',
@@ -402,7 +402,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception(
array(
'code' => 'HYC00',
@@ -419,7 +419,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception($error);
}
if (!$rows) {
@@ -442,7 +442,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception($error);
}
}
@@ -472,7 +472,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception($error);
}
@@ -481,7 +481,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception(oci_error($this->_stmt));
}
@@ -516,7 +516,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception($error);
}
@@ -538,7 +538,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Statement_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception(
array(
'code' => 'HYC00',
@@ -567,7 +567,7 @@ class Zend_Db_Statement_Oracle extends Zend_Db_Statement
/**
* @see Zend_Db_Adapter_Oracle_Exception
*/
- require_once 'Zend/Db/Statement/Oracle/Exception.php';
+ // require_once 'Zend/Db/Statement/Oracle/Exception.php';
throw new Zend_Db_Statement_Oracle_Exception(oci_error($this->_stmt));
}
diff --git a/libs/Zend/Db/Statement/Oracle/Exception.php b/libs/Zend/Db/Statement/Oracle/Exception.php
index 26f5412eef..d5e21bad3f 100644
--- a/libs/Zend/Db/Statement/Oracle/Exception.php
+++ b/libs/Zend/Db/Statement/Oracle/Exception.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Db_Statement_Exception
*/
-require_once 'Zend/Db/Statement/Exception.php';
+// require_once 'Zend/Db/Statement/Exception.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
diff --git a/libs/Zend/Db/Statement/Pdo.php b/libs/Zend/Db/Statement/Pdo.php
index c0f6bc5248..b9e9400d28 100644
--- a/libs/Zend/Db/Statement/Pdo.php
+++ b/libs/Zend/Db/Statement/Pdo.php
@@ -15,15 +15,15 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Pdo.php 18079 2009-09-11 17:46:45Z ralph $
+ * @version $Id: Pdo.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Statement
*/
-require_once 'Zend/Db/Statement.php';
+// require_once 'Zend/Db/Statement.php';
/**
* Proxy class to wrap a PDOStatement object.
@@ -34,7 +34,7 @@ require_once 'Zend/Db/Statement.php';
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggregate
@@ -57,7 +57,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
$this->_stmt = $this->_adapter->getConnection()->prepare($sql);
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -81,7 +81,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
return $this->_stmt->bindColumn($column, $param, $type);
}
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -113,7 +113,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
}
return $this->_stmt->bindParam($parameter, $variable, $type, $length, $options);
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -132,9 +132,9 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
if (is_string($parameter) && $parameter[0] != ':') {
$parameter = ":$parameter";
}
-
+
$this->_bindParam[$parameter] = $value;
-
+
try {
if ($type === null) {
return $this->_stmt->bindValue($parameter, $value);
@@ -142,7 +142,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
return $this->_stmt->bindValue($parameter, $value, $type);
}
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -158,7 +158,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->closeCursor();
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -175,7 +175,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->columnCount();
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -192,7 +192,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->errorCode();
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -209,7 +209,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->errorInfo();
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -230,8 +230,8 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
return $this->_stmt->execute();
}
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
- throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
+ // require_once 'Zend/Db/Statement/Exception.php';
+ throw new Zend_Db_Statement_Exception($e->getMessage(), (int) $e->getCode(), $e);
}
}
@@ -252,7 +252,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->fetch($style, $cursor, $offset);
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -290,7 +290,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
return $this->_stmt->fetchAll($style);
}
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -307,7 +307,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->fetchColumn($col);
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -325,7 +325,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->fetchObject($class, $config);
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -342,7 +342,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->getAttribute($key);
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -359,7 +359,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->getColumnMeta($column);
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -377,7 +377,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->nextRowset();
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -395,7 +395,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->rowCount();
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -413,7 +413,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->setAttribute($key, $val);
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
@@ -431,7 +431,7 @@ class Zend_Db_Statement_Pdo extends Zend_Db_Statement implements IteratorAggrega
try {
return $this->_stmt->setFetchMode($mode);
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
diff --git a/libs/Zend/Db/Statement/Pdo/Ibm.php b/libs/Zend/Db/Statement/Pdo/Ibm.php
index 29ae3db62e..20b6aea7a9 100644
--- a/libs/Zend/Db/Statement/Pdo/Ibm.php
+++ b/libs/Zend/Db/Statement/Pdo/Ibm.php
@@ -15,15 +15,15 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Ibm.php 17860 2009-08-27 22:48:48Z beberlei $
+ * @version $Id: Ibm.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Statement_Pdo
*/
-require_once 'Zend/Db/Statement/Pdo.php';
+// require_once 'Zend/Db/Statement/Pdo.php';
/**
* Proxy class to wrap a PDOStatement object for IBM Databases.
@@ -34,7 +34,7 @@ require_once 'Zend/Db/Statement/Pdo.php';
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Statement_Pdo_Ibm extends Zend_Db_Statement_Pdo
@@ -86,7 +86,7 @@ class Zend_Db_Statement_Pdo_Ibm extends Zend_Db_Statement_Pdo
return $this->_stmt->bindParam($parameter, $variable, $type, $length, $options);
}
} catch (PDOException $e) {
- require_once 'Zend/Db/Statement/Exception.php';
+ // require_once 'Zend/Db/Statement/Exception.php';
throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
}
}
diff --git a/libs/Zend/Db/Statement/Pdo/Oci.php b/libs/Zend/Db/Statement/Pdo/Oci.php
index e4b1edc638..2306228187 100644
--- a/libs/Zend/Db/Statement/Pdo/Oci.php
+++ b/libs/Zend/Db/Statement/Pdo/Oci.php
@@ -15,15 +15,15 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Oci.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Oci.php 21105 2010-02-19 21:27:09Z mikaelkael $
*/
/**
* @see Zend_Db_Statement_Pdo
*/
-require_once 'Zend/Db/Statement/Pdo.php';
+// require_once 'Zend/Db/Statement/Pdo.php';
/**
* Proxy class to wrap a PDOStatement object for IBM Databases.
@@ -34,7 +34,7 @@ require_once 'Zend/Db/Statement/Pdo.php';
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Statement_Pdo_Oci extends Zend_Db_Statement_Pdo
@@ -66,4 +66,26 @@ class Zend_Db_Statement_Pdo_Oci extends Zend_Db_Statement_Pdo
}
return $results;
}
+
+
+ /**
+ * Fetches a row from the result set.
+ *
+ * @param int $style OPTIONAL Fetch mode for this fetch operation.
+ * @param int $cursor OPTIONAL Absolute, relative, or other.
+ * @param int $offset OPTIONAL Number for absolute or relative cursors.
+ * @return mixed Array, object, or scalar depending on fetch mode.
+ * @throws Zend_Db_Statement_Exception
+ */
+ public function fetch($style = null, $cursor = null, $offset = null)
+ {
+ $row = parent::fetch($style, $cursor, $offset);
+
+ $remove = $this->_adapter->foldCase('zend_db_rownum');
+ if (is_array($row) && array_key_exists($remove, $row)) {
+ unset($row[$remove]);
+ }
+
+ return $row;
+ }
} \ No newline at end of file
diff --git a/libs/Zend/Db/Statement/Sqlsrv.php b/libs/Zend/Db/Statement/Sqlsrv.php
index 45c243edf1..9663c83ccf 100644
--- a/libs/Zend/Db/Statement/Sqlsrv.php
+++ b/libs/Zend/Db/Statement/Sqlsrv.php
@@ -15,14 +15,15 @@
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Sqlsrv.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Statement
*/
-require_once 'Zend/Db/Statement.php';
+// require_once 'Zend/Db/Statement.php';
/**
* Extends for Microsoft SQL Server Driver for PHP
@@ -30,7 +31,7 @@ require_once 'Zend/Db/Statement.php';
* @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Statement_Sqlsrv extends Zend_Db_Statement
@@ -65,7 +66,7 @@ class Zend_Db_Statement_Sqlsrv extends Zend_Db_Statement
$this->_stmt = sqlsrv_prepare($connection, $sql);
if (!$this->_stmt) {
- require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
throw new Zend_Db_Statement_Sqlsrv_Exception(sqlsrv_errors());
}
@@ -201,7 +202,7 @@ class Zend_Db_Statement_Sqlsrv extends Zend_Db_Statement
$this->_stmt = sqlsrv_query($connection, $this->_originalSQL, $params);
if (!$this->_stmt) {
- require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
throw new Zend_Db_Statement_Sqlsrv_Exception(sqlsrv_errors());
}
@@ -232,7 +233,7 @@ class Zend_Db_Statement_Sqlsrv extends Zend_Db_Statement
$values = sqlsrv_fetch_array($this->_stmt, SQLSRV_FETCH_ASSOC);
if (!$values && (null !== $error = sqlsrv_errors())) {
- require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
throw new Zend_Db_Statement_Sqlsrv_Exception($error);
}
@@ -269,7 +270,7 @@ class Zend_Db_Statement_Sqlsrv extends Zend_Db_Statement
$row = $this->_fetchBound($row);
break;
default:
- require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
throw new Zend_Db_Statement_Sqlsrv_Exception("Invalid fetch mode '$style' specified");
break;
}
@@ -292,7 +293,7 @@ class Zend_Db_Statement_Sqlsrv extends Zend_Db_Statement
if (!sqlsrv_fetch($this->_stmt)) {
if (null !== $error = sqlsrv_errors()) {
- require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
throw new Zend_Db_Statement_Sqlsrv_Exception($error);
}
@@ -302,7 +303,7 @@ class Zend_Db_Statement_Sqlsrv extends Zend_Db_Statement
$data = sqlsrv_get_field($this->_stmt, $col); //0-based
if ($data === false) {
- require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
throw new Zend_Db_Statement_Sqlsrv_Exception(sqlsrv_errors());
}
@@ -326,7 +327,7 @@ class Zend_Db_Statement_Sqlsrv extends Zend_Db_Statement
$obj = sqlsrv_fetch_object($this->_stmt);
if ($error = sqlsrv_errors()) {
- require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
throw new Zend_Db_Statement_Sqlsrv_Exception($error);
}
@@ -372,7 +373,7 @@ class Zend_Db_Statement_Sqlsrv extends Zend_Db_Statement
public function nextRowset()
{
if (sqlsrv_next_result($this->_stmt) === false) {
- require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
throw new Zend_Db_Statement_Sqlsrv_Exception(sqlsrv_errors());
}
@@ -401,7 +402,7 @@ class Zend_Db_Statement_Sqlsrv extends Zend_Db_Statement
// Strict check is necessary; 0 is a valid return value
if ($num_rows === false) {
- require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
+ // require_once 'Zend/Db/Statement/Sqlsrv/Exception.php';
throw new Zend_Db_Statement_Sqlsrv_Exception(sqlsrv_errors());
}
diff --git a/libs/Zend/Db/Statement/Sqlsrv/Exception.php b/libs/Zend/Db/Statement/Sqlsrv/Exception.php
index 02378627f9..cbd4cf4d45 100644
--- a/libs/Zend/Db/Statement/Sqlsrv/Exception.php
+++ b/libs/Zend/Db/Statement/Sqlsrv/Exception.php
@@ -12,21 +12,23 @@
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
*
+ * @category Zend
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Statement_Exception
*/
-require_once 'Zend/Db/Statement/Exception.php';
+// require_once 'Zend/Db/Statement/Exception.php';
/**
* @package Zend_Db
* @subpackage Statement
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Statement_Sqlsrv_Exception extends Zend_Db_Statement_Exception
diff --git a/libs/Zend/Db/Table.php b/libs/Zend/Db/Table.php
index 20319fd1ec..ba22f7f262 100644
--- a/libs/Zend/Db/Table.php
+++ b/libs/Zend/Db/Table.php
@@ -15,20 +15,20 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Table.php 16733 2009-07-15 13:16:50Z ralph $
+ * @version $Id: Table.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
- * Zend_Db_Table_Abstract
+ * @see Zend_Db_Table_Abstract
*/
-require_once 'Zend/Db/Table/Abstract.php';
+// require_once 'Zend/Db/Table/Abstract.php';
/**
* @see Zend_Db_Table_Definition
*/
-require_once 'Zend/Db/Table/Definition.php';
+// require_once 'Zend/Db/Table/Definition.php';
/**
* Class for SQL table interface.
@@ -36,25 +36,25 @@ require_once 'Zend/Db/Table/Definition.php';
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Table extends Zend_Db_Table_Abstract
{
-
+
/**
* __construct() - For concrete implementation of Zend_Db_Table
*
* @param string|array $config string can reference a Zend_Registry key for a db adapter
- * OR it can refernece the name of a table
- * @param unknown_type $definition
+ * OR it can reference the name of a table
+ * @param array|Zend_Db_Table_Definition $definition
*/
public function __construct($config = array(), $definition = null)
{
if ($definition !== null && is_array($definition)) {
$definition = new Zend_Db_Table_Definition($definition);
}
-
+
if (is_string($config)) {
if (Zend_Registry::isRegistered($config)) {
trigger_error(__CLASS__ . '::' . __METHOD__ . '(\'registryName\') is not valid usage of Zend_Db_Table, '
@@ -73,12 +73,7 @@ class Zend_Db_Table extends Zend_Db_Table_Abstract
}
}
}
-
+
parent::__construct($config);
}
-
-
-
-
-
}
diff --git a/libs/Zend/Db/Table/Abstract.php b/libs/Zend/Db/Table/Abstract.php
index f0a6ea18d7..e07ed22517 100644
--- a/libs/Zend/Db/Table/Abstract.php
+++ b/libs/Zend/Db/Table/Abstract.php
@@ -15,25 +15,25 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 17822 2009-08-26 00:03:56Z ralph $
+ * @version $Id: Abstract.php 21079 2010-02-18 18:15:49Z tech13 $
*/
/**
* @see Zend_Db_Adapter_Abstract
*/
-require_once 'Zend/Db/Adapter/Abstract.php';
+// require_once 'Zend/Db/Adapter/Abstract.php';
/**
* @see Zend_Db_Adapter_Abstract
*/
-require_once 'Zend/Db/Select.php';
+// require_once 'Zend/Db/Select.php';
/**
* @see Zend_Db
*/
-require_once 'Zend/Db.php';
+// require_once 'Zend/Db.php';
/**
* Class for SQL table interface.
@@ -41,7 +41,7 @@ require_once 'Zend/Db.php';
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Db_Table_Abstract
@@ -93,14 +93,14 @@ abstract class Zend_Db_Table_Abstract
* @var unknown_type
*/
protected $_definition = null;
-
+
/**
* Optional definition config name used in concrete implementation
*
* @var string
*/
protected $_definitionConfigName = null;
-
+
/**
* Default cache for information provided by the adapter's describeTable() method.
*
@@ -326,7 +326,7 @@ abstract class Zend_Db_Table_Abstract
return $this;
}
-
+
/**
* setDefinition()
*
@@ -338,7 +338,7 @@ abstract class Zend_Db_Table_Abstract
$this->_definition = $definition;
return $this;
}
-
+
/**
* getDefinition()
*
@@ -348,7 +348,7 @@ abstract class Zend_Db_Table_Abstract
{
return $this->_definition;
}
-
+
/**
* setDefinitionConfigName()
*
@@ -360,7 +360,7 @@ abstract class Zend_Db_Table_Abstract
$this->_definitionConfigName = $definitionConfigName;
return $this;
}
-
+
/**
* getDefinitionConfigName()
*
@@ -466,11 +466,11 @@ abstract class Zend_Db_Table_Abstract
$refMap = $this->_getReferenceMapNormalized();
if ($ruleKey !== null) {
if (!isset($refMap[$ruleKey])) {
- require_once "Zend/Db/Table/Exception.php";
+ // require_once "Zend/Db/Table/Exception.php";
throw new Zend_Db_Table_Exception("No reference rule \"$ruleKey\" from table $thisClass to table $tableClassname");
}
if ($refMap[$ruleKey][self::REF_TABLE_CLASS] != $tableClassname) {
- require_once "Zend/Db/Table/Exception.php";
+ // require_once "Zend/Db/Table/Exception.php";
throw new Zend_Db_Table_Exception("Reference rule \"$ruleKey\" does not reference table $tableClassname");
}
return $refMap[$ruleKey];
@@ -480,7 +480,7 @@ abstract class Zend_Db_Table_Abstract
return $reference;
}
}
- require_once "Zend/Db/Table/Exception.php";
+ // require_once "Zend/Db/Table/Exception.php";
throw new Zend_Db_Table_Exception("No reference from table $thisClass to table $tableClassname");
}
@@ -603,11 +603,11 @@ abstract class Zend_Db_Table_Abstract
return null;
}
if (is_string($db)) {
- require_once 'Zend/Registry.php';
+ // require_once 'Zend/Registry.php';
$db = Zend_Registry::get($db);
}
if (!$db instanceof Zend_Db_Adapter_Abstract) {
- require_once 'Zend/Db/Table/Exception.php';
+ // require_once 'Zend/Db/Table/Exception.php';
throw new Zend_Db_Table_Exception('Argument must be of type Zend_Db_Adapter_Abstract, or a Registry key where a Zend_Db_Adapter_Abstract object is stored');
}
return $db;
@@ -698,11 +698,11 @@ abstract class Zend_Db_Table_Abstract
return null;
}
if (is_string($metadataCache)) {
- require_once 'Zend/Registry.php';
+ // require_once 'Zend/Registry.php';
$metadataCache = Zend_Registry::get($metadataCache);
}
if (!$metadataCache instanceof Zend_Cache_Core) {
- require_once 'Zend/Db/Table/Exception.php';
+ // require_once 'Zend/Db/Table/Exception.php';
throw new Zend_Db_Table_Exception('Argument must be of type Zend_Cache_Core, or a Registry key where a Zend_Cache_Core object is stored');
}
return $metadataCache;
@@ -750,7 +750,7 @@ abstract class Zend_Db_Table_Abstract
if (! $this->_db) {
$this->_db = self::getDefaultAdapter();
if (!$this->_db instanceof Zend_Db_Adapter_Abstract) {
- require_once 'Zend/Db/Table/Exception.php';
+ // require_once 'Zend/Db/Table/Exception.php';
throw new Zend_Db_Table_Exception('No adapter found for ' . get_class($this));
}
}
@@ -803,10 +803,10 @@ abstract class Zend_Db_Table_Abstract
// If $this has a metadata cache
if (null !== $this->_metadataCache) {
// Define the cache identifier where the metadata are saved
-
+
//get db configuration
$dbConfig = $this->_db->getConfig();
-
+
// Define the cache identifier where the metadata are saved
$cacheId = md5( // port:host/dbname:schema.table (based on availabilty)
(isset($dbConfig['options']['port']) ? ':'.$dbConfig['options']['port'] : null)
@@ -823,11 +823,7 @@ abstract class Zend_Db_Table_Abstract
$metadata = $this->_db->describeTable($this->_name, $this->_schema);
// If $this has a metadata cache, then cache the metadata
if (null !== $this->_metadataCache && !$this->_metadataCache->save($metadata, $cacheId)) {
- /**
- * @see Zend_Db_Table_Exception
- */
- require_once 'Zend/Db/Table/Exception.php';
- throw new Zend_Db_Table_Exception('Failed saving metadata to metadataCache');
+ trigger_error('Failed saving metadata to metadataCache', E_USER_NOTICE);
}
}
@@ -876,7 +872,7 @@ abstract class Zend_Db_Table_Abstract
// if no primary key was specified and none was found in the metadata
// then throw an exception.
if (empty($this->_primary)) {
- require_once 'Zend/Db/Table/Exception.php';
+ // require_once 'Zend/Db/Table/Exception.php';
throw new Zend_Db_Table_Exception('A table must have a primary key, but none was found');
}
} else if (!is_array($this->_primary)) {
@@ -888,7 +884,7 @@ abstract class Zend_Db_Table_Abstract
$cols = $this->_getCols();
if (! array_intersect((array) $this->_primary, $cols) == (array) $this->_primary) {
- require_once 'Zend/Db/Table/Exception.php';
+ // require_once 'Zend/Db/Table/Exception.php';
throw new Zend_Db_Table_Exception("Primary key column(s) ("
. implode(',', (array) $this->_primary)
. ") are not columns in this table ("
@@ -990,7 +986,7 @@ abstract class Zend_Db_Table_Abstract
}
if (!array_key_exists($key, $info)) {
- require_once 'Zend/Db/Table/Exception.php';
+ // require_once 'Zend/Db/Table/Exception.php';
throw new Zend_Db_Table_Exception('There is no table information for the key "' . $key . '"');
}
@@ -1005,7 +1001,7 @@ abstract class Zend_Db_Table_Abstract
*/
public function select($withFromPart = self::SELECT_WITHOUT_FROM_PART)
{
- require_once 'Zend/Db/Table/Select.php';
+ // require_once 'Zend/Db/Table/Select.php';
$select = new Zend_Db_Table_Select($this);
if ($withFromPart == self::SELECT_WITH_FROM_PART) {
$select->from($this->info(self::NAME), Zend_Db_Table_Select::SQL_WILDCARD, $this->info(self::SCHEMA));
@@ -1092,7 +1088,7 @@ abstract class Zend_Db_Table_Abstract
/**
* @see Zend_Db_Table_Exception
*/
- require_once 'Zend/Db/Table/Exception.php';
+ // require_once 'Zend/Db/Table/Exception.php';
throw new Zend_Db_Table_Exception('Column "' . $column . '" not found in table.');
}
@@ -1225,12 +1221,12 @@ abstract class Zend_Db_Table_Abstract
$keyNames = array_values((array) $this->_primary);
if (count($args) < count($keyNames)) {
- require_once 'Zend/Db/Table/Exception.php';
+ // require_once 'Zend/Db/Table/Exception.php';
throw new Zend_Db_Table_Exception("Too few columns for the primary key");
}
if (count($args) > count($keyNames)) {
- require_once 'Zend/Db/Table/Exception.php';
+ // require_once 'Zend/Db/Table/Exception.php';
throw new Zend_Db_Table_Exception("Too many columns for the primary key");
}
@@ -1247,7 +1243,7 @@ abstract class Zend_Db_Table_Abstract
if ($numberTerms == 0) {
$numberTerms = $keyValuesCount;
} else if ($keyValuesCount != $numberTerms) {
- require_once 'Zend/Db/Table/Exception.php';
+ // require_once 'Zend/Db/Table/Exception.php';
throw new Zend_Db_Table_Exception("Missing value(s) for the primary key");
}
$keyValues = array_values($keyValues);
@@ -1280,13 +1276,13 @@ abstract class Zend_Db_Table_Abstract
// issue ZF-5775 (empty where clause should return empty rowset)
if ($whereClause == null) {
$rowsetClass = $this->getRowsetClass();
- if (!class_exists($rowsetClass)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($rowsetClass);
- }
+ // if (!class_exists($rowsetClass)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($rowsetClass);
+ // }
return new $rowsetClass(array('table' => $this, 'rowClass' => $this->getRowClass(), 'stored' => true));
}
-
+
return $this->fetchAll($whereClause);
}
@@ -1333,10 +1329,10 @@ abstract class Zend_Db_Table_Abstract
);
$rowsetClass = $this->getRowsetClass();
- if (!class_exists($rowsetClass)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($rowsetClass);
- }
+ // if (!class_exists($rowsetClass)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($rowsetClass);
+ // }
return new $rowsetClass($data);
}
@@ -1382,10 +1378,10 @@ abstract class Zend_Db_Table_Abstract
);
$rowClass = $this->getRowClass();
- if (!class_exists($rowClass)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($rowClass);
- }
+ // if (!class_exists($rowClass)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($rowClass);
+ // }
return new $rowClass($data);
}
@@ -1445,10 +1441,10 @@ abstract class Zend_Db_Table_Abstract
);
$rowClass = $this->getRowClass();
- if (!class_exists($rowClass)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($rowClass);
- }
+ // if (!class_exists($rowClass)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($rowClass);
+ // }
$row = new $rowClass($config);
$row->setFromArray($data);
return $row;
diff --git a/libs/Zend/Db/Table/Definition.php b/libs/Zend/Db/Table/Definition.php
index edea0ee640..30e601a5b1 100644
--- a/libs/Zend/Db/Table/Definition.php
+++ b/libs/Zend/Db/Table/Definition.php
@@ -15,9 +15,9 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Definition.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Definition.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
@@ -26,17 +26,17 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Table_Definition
{
-
+
/**
* @var array
*/
protected $_tableConfigs = array();
-
+
/**
* __construct()
*
@@ -50,7 +50,7 @@ class Zend_Db_Table_Definition
$this->setOptions($options);
}
}
-
+
/**
* setConfig()
*
@@ -62,7 +62,7 @@ class Zend_Db_Table_Definition
$this->setOptions($config->toArray());
return $this;
}
-
+
/**
* setOptions()
*
@@ -76,7 +76,7 @@ class Zend_Db_Table_Definition
}
return $this;
}
-
+
/**
* @param string $tableName
* @param array $tableConfig
@@ -87,15 +87,15 @@ class Zend_Db_Table_Definition
// @todo logic here
$tableConfig[Zend_Db_Table::DEFINITION_CONFIG_NAME] = $tableName;
$tableConfig[Zend_Db_Table::DEFINITION] = $this;
-
+
if (!isset($tableConfig[Zend_Db_Table::NAME])) {
$tableConfig[Zend_Db_Table::NAME] = $tableName;
}
-
+
$this->_tableConfigs[$tableName] = $tableConfig;
return $this;
}
-
+
/**
* getTableConfig()
*
@@ -106,7 +106,7 @@ class Zend_Db_Table_Definition
{
return $this->_tableConfigs[$tableName];
}
-
+
/**
* removeTableConfig()
*
@@ -116,7 +116,7 @@ class Zend_Db_Table_Definition
{
unset($this->_tableConfigs[$tableName]);
}
-
+
/**
* hasTableConfig()
*
diff --git a/libs/Zend/Db/Table/Exception.php b/libs/Zend/Db/Table/Exception.php
index 2d85136109..3757324052 100644
--- a/libs/Zend/Db/Table/Exception.php
+++ b/libs/Zend/Db/Table/Exception.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Db_Exception
*/
-require_once 'Zend/Db/Exception.php';
+// require_once 'Zend/Db/Exception.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Table_Exception extends Zend_Db_Exception
diff --git a/libs/Zend/Db/Table/Row.php b/libs/Zend/Db/Table/Row.php
index 970c493419..5e80a644c0 100644
--- a/libs/Zend/Db/Table/Row.php
+++ b/libs/Zend/Db/Table/Row.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Row.php 16203 2009-06-21 18:56:17Z thomas $
+ * @version $Id: Row.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Table_Row_Abstract
*/
-require_once 'Zend/Db/Table/Row/Abstract.php';
+// require_once 'Zend/Db/Table/Row/Abstract.php';
/**
@@ -34,7 +34,7 @@ require_once 'Zend/Db/Table/Row/Abstract.php';
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Table_Row extends Zend_Db_Table_Row_Abstract
diff --git a/libs/Zend/Db/Table/Row/Abstract.php b/libs/Zend/Db/Table/Row/Abstract.php
index 501bae171a..c7243eb003 100644
--- a/libs/Zend/Db/Table/Row/Abstract.php
+++ b/libs/Zend/Db/Table/Row/Abstract.php
@@ -15,24 +15,24 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Abstract.php 22230 2010-05-21 20:59:18Z ralph $
*/
/**
* @see Zend_Db
*/
-require_once 'Zend/Db.php';
+// require_once 'Zend/Db.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
+abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess, IteratorAggregate
{
/**
@@ -122,7 +122,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
if (isset($config['data'])) {
if (!is_array($config['data'])) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception('Data must be an array');
}
$this->_data = $config['data'];
@@ -157,7 +157,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
protected function _transformColumn($columnName)
{
if (!is_string($columnName)) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception('Specified column is not a string');
}
// Perform no transformation by default
@@ -175,7 +175,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
{
$columnName = $this->_transformColumn($columnName);
if (!array_key_exists($columnName, $this->_data)) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is not in the row");
}
return $this->_data[$columnName];
@@ -193,7 +193,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
{
$columnName = $this->_transformColumn($columnName);
if (!array_key_exists($columnName, $this->_data)) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is not in the row");
}
$this->_data[$columnName] = $value;
@@ -211,11 +211,11 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
{
$columnName = $this->_transformColumn($columnName);
if (!array_key_exists($columnName, $this->_data)) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is not in the row");
}
if ($this->isConnected() && in_array($columnName, $this->_table->info('primary'))) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is a primary key and should not be unset");
}
unset($this->_data[$columnName]);
@@ -293,13 +293,14 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
}
/**
- * Does nothing
+ * Proxy to __unset
* Required by the ArrayAccess implementation
*
* @param string $offset
*/
public function offsetUnset($offset)
{
+ return $this->__unset($offset);
}
/**
@@ -341,7 +342,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
$tableClass = get_class($table);
if (! $table instanceof $this->_tableClass) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("The specified Table is of class $tableClass, expecting class to be instance of $this->_tableClass");
}
@@ -351,13 +352,13 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
$info = $this->_table->info();
if ($info['cols'] != array_keys($this->_data)) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception('The specified Table does not have the same columns as the Row');
}
if (! array_intersect((array) $this->_primary, $info['primary']) == (array) $this->_primary) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("The specified Table '$tableClass' does not have the same primary key as the Row");
}
@@ -450,7 +451,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
* A read-only row cannot be saved.
*/
if ($this->_readOnly === true) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception('This row has been marked read-only');
}
@@ -472,9 +473,9 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
if (is_array($primaryKey)) {
$newPrimaryKey = $primaryKey;
} else {
- //ZF-6167 Use tempPrimaryKey temporary to avoid that zend encoding fails.
+ //ZF-6167 Use tempPrimaryKey temporary to avoid that zend encoding fails.
$tempPrimaryKey = (array) $this->_primary;
- $newPrimaryKey = array(current($tempPrimaryKey) => $primaryKey);
+ $newPrimaryKey = array(current($tempPrimaryKey) => $primaryKey);
}
/**
@@ -508,7 +509,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
* A read-only row cannot be saved.
*/
if ($this->_readOnly === true) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception('This row has been marked read-only');
}
@@ -597,7 +598,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
* A read-only row cannot be deleted.
*/
if ($this->_readOnly === true) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception('This row has been marked read-only');
}
@@ -641,6 +642,11 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
return $result;
}
+ public function getIterator()
+ {
+ return new ArrayIterator((array) $this->_data);
+ }
+
/**
* Returns the column/value data as an array.
*
@@ -686,7 +692,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
protected function _getTable()
{
if (!$this->_connected) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception('Cannot save a Row unless it is connected');
}
return $this->_table;
@@ -701,7 +707,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
protected function _getPrimaryKey($useDirty = true)
{
if (!is_array($this->_primary)) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("The primary key must be set as an array");
}
@@ -712,7 +718,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
$array = array_intersect_key($this->_cleanData, $primary);
}
if (count($primary) != count($array)) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("The specified Table '$this->_tableClass' does not have the same primary key as the Row");
}
return $array;
@@ -754,7 +760,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
$row = $this->_getTable()->fetchRow($where);
if (null === $row) {
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception('Cannot refresh row as parent is missing');
}
@@ -865,13 +871,13 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
if (is_string($dependentTable)) {
$dependentTable = $this->_getTableFromString($dependentTable);
}
-
+
if (!$dependentTable instanceof Zend_Db_Table_Abstract) {
$type = gettype($dependentTable);
if ($type == 'object') {
$type = get_class($dependentTable);
}
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Dependent table must be a Zend_Db_Table_Abstract, but it is $type");
}
@@ -921,13 +927,13 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
if (is_string($parentTable)) {
$parentTable = $this->_getTableFromString($parentTable);
}
-
+
if (!$parentTable instanceof Zend_Db_Table_Abstract) {
$type = gettype($parentTable);
if ($type == 'object') {
$type = get_class($parentTable);
}
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Parent table must be a Zend_Db_Table_Abstract, but it is $type");
}
@@ -937,7 +943,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
&& ($parentTable->getDefinition() == null)) {
$parentTable->setOptions(array(Zend_Db_Table_Abstract::DEFINITION => $tableDefinition));
}
-
+
if ($select === null) {
$select = $parentTable->select();
} else {
@@ -955,7 +961,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
$parentColumnName = $parentDb->foldCase($map[Zend_Db_Table_Abstract::REF_COLUMNS][$i]);
$parentColumn = $parentDb->quoteIdentifier($parentColumnName, true);
$parentInfo = $parentTable->info();
-
+
// determine where part
$type = $parentInfo[Zend_Db_Table_Abstract::METADATA][$parentColumnName]['DATA_TYPE'];
$nullable = $parentInfo[Zend_Db_Table_Abstract::METADATA][$parentColumnName]['NULLABLE'];
@@ -966,7 +972,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
} else {
$select->where("$parentColumn = ?", $value, $type);
}
-
+
}
return $parentTable->fetchRow($select);
@@ -989,13 +995,13 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
if (is_string($intersectionTable)) {
$intersectionTable = $this->_getTableFromString($intersectionTable);
}
-
+
if (!$intersectionTable instanceof Zend_Db_Table_Abstract) {
$type = gettype($intersectionTable);
if ($type == 'object') {
$type = get_class($intersectionTable);
}
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Intersection table must be a Zend_Db_Table_Abstract, but it is $type");
}
@@ -1005,17 +1011,17 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
&& ($intersectionTable->getDefinition() == null)) {
$intersectionTable->setOptions(array(Zend_Db_Table_Abstract::DEFINITION => $tableDefinition));
}
-
+
if (is_string($matchTable)) {
$matchTable = $this->_getTableFromString($matchTable);
}
-
+
if (! $matchTable instanceof Zend_Db_Table_Abstract) {
$type = gettype($matchTable);
if ($type == 'object') {
$type = get_class($matchTable);
}
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Match table must be a Zend_Db_Table_Abstract, but it is $type");
}
@@ -1025,7 +1031,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
&& ($matchTable->getDefinition() == null)) {
$matchTable->setOptions(array(Zend_Db_Table_Abstract::DEFINITION => $tableDefinition));
}
-
+
if ($select === null) {
$select = $matchTable->select();
} else {
@@ -1050,7 +1056,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
}
$joinCond = implode(' AND ', $joinCond);
- $select->from(array('i' => $interName), Zend_Db_Select::SQL_WILDCARD, $interSchema)
+ $select->from(array('i' => $interName), array(), $interSchema)
->joinInner(array('m' => $matchName), $joinCond, Zend_Db_Select::SQL_WILDCARD, $matchSchema)
->setIntegrityCheck(false);
@@ -1077,15 +1083,15 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
);
$rowsetClass = $matchTable->getRowsetClass();
- if (!class_exists($rowsetClass)) {
- try {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($rowsetClass);
- } catch (Zend_Exception $e) {
- require_once 'Zend/Db/Table/Row/Exception.php';
- throw new Zend_Db_Table_Row_Exception($e->getMessage());
- }
- }
+ // if (!class_exists($rowsetClass)) {
+ // try {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($rowsetClass);
+ // } catch (Zend_Exception $e) {
+ // require_once 'Zend/Db/Table/Row/Exception.php';
+ // throw new Zend_Db_Table_Row_Exception($e->getMessage(), $e->getCode(), $e);
+ // }
+ // }
$rowset = new $rowsetClass($config);
return $rowset;
}
@@ -1148,7 +1154,7 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
return $this->findDependentRowset($class, $ruleKey1, $select);
}
- require_once 'Zend/Db/Table/Row/Exception.php';
+ // require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Unrecognized method '$method()'");
}
@@ -1164,29 +1170,29 @@ abstract class Zend_Db_Table_Row_Abstract implements ArrayAccess
if ($this->_table instanceof Zend_Db_Table_Abstract) {
$tableDefinition = $this->_table->getDefinition();
-
+
if ($tableDefinition !== null && $tableDefinition->hasTableConfig($tableName)) {
return new Zend_Db_Table($tableName, $tableDefinition);
- }
- }
-
- // assume the tableName is the class name
- if (!class_exists($tableName)) {
- try {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($tableName);
- } catch (Zend_Exception $e) {
- require_once 'Zend/Db/Table/Row/Exception.php';
- throw new Zend_Db_Table_Row_Exception($e->getMessage());
}
}
+ // assume the tableName is the class name
+ // if (!class_exists($tableName)) {
+ // try {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($tableName);
+ // } catch (Zend_Exception $e) {
+ // require_once 'Zend/Db/Table/Row/Exception.php';
+ // throw new Zend_Db_Table_Row_Exception($e->getMessage(), $e->getCode(), $e);
+ // }
+ // }
+
$options = array();
-
+
if (($table = $this->_getTable())) {
$options['db'] = $table->getAdapter();
}
-
+
if (isset($tableDefinition) && $tableDefinition !== null) {
$options[Zend_Db_Table_Abstract::DEFINITION] = $tableDefinition;
}
diff --git a/libs/Zend/Db/Table/Row/Exception.php b/libs/Zend/Db/Table/Row/Exception.php
index 12d17febcd..236c4bec42 100644
--- a/libs/Zend/Db/Table/Row/Exception.php
+++ b/libs/Zend/Db/Table/Row/Exception.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Db_Table_Exception
*/
-require_once 'Zend/Db/Table/Exception.php';
+// require_once 'Zend/Db/Table/Exception.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Table_Row_Exception extends Zend_Db_Table_Exception
diff --git a/libs/Zend/Db/Table/Rowset.php b/libs/Zend/Db/Table/Rowset.php
index b7e495d6d0..186abe14fd 100644
--- a/libs/Zend/Db/Table/Rowset.php
+++ b/libs/Zend/Db/Table/Rowset.php
@@ -16,16 +16,16 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Rowset.php 16203 2009-06-21 18:56:17Z thomas $
+ * @version $Id: Rowset.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Table_Rowset_Abstract
*/
-require_once 'Zend/Db/Table/Rowset/Abstract.php';
+// require_once 'Zend/Db/Table/Rowset/Abstract.php';
/**
@@ -35,7 +35,7 @@ require_once 'Zend/Db/Table/Rowset/Abstract.php';
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Table_Rowset extends Zend_Db_Table_Rowset_Abstract
diff --git a/libs/Zend/Db/Table/Rowset/Abstract.php b/libs/Zend/Db/Table/Rowset/Abstract.php
index d9e324baf1..8cafadc91e 100644
--- a/libs/Zend/Db/Table/Rowset/Abstract.php
+++ b/libs/Zend/Db/Table/Rowset/Abstract.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Db_Table_Rowset_Abstract implements SeekableIterator, Countable, ArrayAccess
@@ -111,10 +111,10 @@ abstract class Zend_Db_Table_Rowset_Abstract implements SeekableIterator, Counta
if (isset($config['rowClass'])) {
$this->_rowClass = $config['rowClass'];
}
- if (!class_exists($this->_rowClass)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($this->_rowClass);
- }
+ // if (!class_exists($this->_rowClass)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($this->_rowClass);
+ // }
if (isset($config['data'])) {
$this->_data = $config['data'];
}
@@ -321,7 +321,7 @@ abstract class Zend_Db_Table_Rowset_Abstract implements SeekableIterator, Counta
{
$position = (int) $position;
if ($position < 0 || $position >= $this->_count) {
- require_once 'Zend/Db/Table/Rowset/Exception.php';
+ // require_once 'Zend/Db/Table/Rowset/Exception.php';
throw new Zend_Db_Table_Rowset_Exception("Illegal index $position");
}
$this->_pointer = $position;
@@ -390,8 +390,8 @@ abstract class Zend_Db_Table_Rowset_Abstract implements SeekableIterator, Counta
$this->seek($position);
$row = $this->current();
} catch (Zend_Db_Table_Rowset_Exception $e) {
- require_once 'Zend/Db/Table/Rowset/Exception.php';
- throw new Zend_Db_Table_Rowset_Exception('No row could be found at position ' . (int) $position);
+ // require_once 'Zend/Db/Table/Rowset/Exception.php';
+ throw new Zend_Db_Table_Rowset_Exception('No row could be found at position ' . (int) $position, 0, $e);
}
if ($seek == false) {
$this->seek($key);
diff --git a/libs/Zend/Db/Table/Rowset/Exception.php b/libs/Zend/Db/Table/Rowset/Exception.php
index 99b4dc54a4..8696c74e06 100644
--- a/libs/Zend/Db/Table/Rowset/Exception.php
+++ b/libs/Zend/Db/Table/Rowset/Exception.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Db_Table_Exception
*/
-require_once 'Zend/Db/Table/Exception.php';
+// require_once 'Zend/Db/Table/Exception.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Table_Rowset_Exception extends Zend_Db_Table_Exception
diff --git a/libs/Zend/Db/Table/Select.php b/libs/Zend/Db/Table/Select.php
index c99a5ad8de..699c071884 100644
--- a/libs/Zend/Db/Table/Select.php
+++ b/libs/Zend/Db/Table/Select.php
@@ -16,22 +16,22 @@
* @category Zend
* @package Zend_Db
* @subpackage Select
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Select.php 18200 2009-09-17 21:25:37Z beberlei $
+ * @version $Id: Select.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Db_Select
*/
-require_once 'Zend/Db/Select.php';
+// require_once 'Zend/Db/Select.php';
/**
* @see Zend_Db_Table_Abstract
*/
-require_once 'Zend/Db/Table/Abstract.php';
+// require_once 'Zend/Db/Table/Abstract.php';
/**
@@ -40,7 +40,7 @@ require_once 'Zend/Db/Table/Abstract.php';
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Db_Table_Select extends Zend_Db_Select
@@ -195,7 +195,7 @@ class Zend_Db_Table_Select extends Zend_Db_Select
if (count($this->_parts[self::UNION]) == 0) {
-
+
// If no fields are specified we assume all fields from primary table
if (!count($fields)) {
$this->from($primary, self::SQL_WILDCARD, $schema);
@@ -211,7 +211,7 @@ class Zend_Db_Table_Select extends Zend_Db_Select
// Check each column to ensure it only references the primary table
if ($column) {
if (!isset($from[$table]) || $from[$table]['tableName'] != $primary) {
- require_once 'Zend/Db/Table/Select/Exception.php';
+ // require_once 'Zend/Db/Table/Select/Exception.php';
throw new Zend_Db_Table_Select_Exception('Select query cannot join with another table');
}
}
diff --git a/libs/Zend/Db/Table/Select/Exception.php b/libs/Zend/Db/Table/Select/Exception.php
index 886f11876e..ac03702c2d 100644
--- a/libs/Zend/Db/Table/Select/Exception.php
+++ b/libs/Zend/Db/Table/Select/Exception.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Db
* @subpackage Select
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Db_Exception
*/
-require_once 'Zend/Db/Select/Exception.php';
+// require_once 'Zend/Db/Select/Exception.php';
/**
* @category Zend
* @package Zend_Db
* @subpackage Table
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
diff --git a/libs/Zend/Exception.php b/libs/Zend/Exception.php
index 3cb5704b3f..bbfb792e93 100644
--- a/libs/Zend/Exception.php
+++ b/libs/Zend/Exception.php
@@ -14,18 +14,82 @@
*
* @category Zend
* @package Zend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
*/
-
/**
- * @category Zend
- * @package Zend
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
+* @category Zend
+* @package Zend
+* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+* @license http://framework.zend.com/license/new-bsd New BSD License
+*/
class Zend_Exception extends Exception
-{}
+{
+ /**
+ * @var null|Exception
+ */
+ private $_previous = null;
+
+ /**
+ * Construct the exception
+ *
+ * @param string $msg
+ * @param int $code
+ * @param Exception $previous
+ * @return void
+ */
+ public function __construct($msg = '', $code = 0, Exception $previous = null)
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+ parent::__construct($msg, (int) $code);
+ $this->_previous = $previous;
+ } else {
+ parent::__construct($msg, (int) $code, $previous);
+ }
+ }
+
+ /**
+ * Overloading
+ *
+ * For PHP < 5.3.0, provides access to the getPrevious() method.
+ *
+ * @param string $method
+ * @param array $args
+ * @return mixed
+ */
+ public function __call($method, array $args)
+ {
+ if ('getprevious' == strtolower($method)) {
+ return $this->_getPrevious();
+ }
+ return null;
+ }
+
+ /**
+ * String representation of the exception
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+ if (null !== ($e = $this->getPrevious())) {
+ return $e->__toString()
+ . "\n\nNext "
+ . parent::__toString();
+ }
+ }
+ return parent::__toString();
+ }
+ /**
+ * Returns previous Exception
+ *
+ * @return Exception|null
+ */
+ protected function _getPrevious()
+ {
+ return $this->_previous;
+ }
+}
diff --git a/libs/Zend/Feed.php b/libs/Zend/Feed.php
index b8555c7ce8..5e4d7b0894 100644
--- a/libs/Zend/Feed.php
+++ b/libs/Zend/Feed.php
@@ -15,9 +15,9 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Feed.php 18291 2009-09-18 21:00:51Z padraic $
+ * @version $Id: Feed.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -29,7 +29,7 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed
@@ -84,7 +84,7 @@ class Zend_Feed
/**
* @see Zend_Http_Client
*/
- require_once 'Zend/Http/Client.php';
+ // require_once 'Zend/Http/Client.php';
self::$_httpClient = new Zend_Http_Client();
}
@@ -173,7 +173,7 @@ class Zend_Feed
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Feed failed to load, got response code ' . $response->getStatus());
}
$feed = $response->getBody();
@@ -194,7 +194,7 @@ class Zend_Feed
$libxml_errflag = libxml_use_internal_errors(true);
$doc = new DOMDocument;
if (trim($string) == '') {
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Document/string being imported'
. ' is an Empty string or comes from an empty HTTP response');
}
@@ -216,7 +216,7 @@ class Zend_Feed
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception($errormsg);
}
@@ -226,7 +226,7 @@ class Zend_Feed
/**
* @see Zend_Feed_Atom
*/
- require_once 'Zend/Feed/Atom.php';
+ // require_once 'Zend/Feed/Atom.php';
// return a newly created Zend_Feed_Atom object
return new Zend_Feed_Atom(null, $string);
}
@@ -236,7 +236,7 @@ class Zend_Feed
/**
* @see Zend_Feed_Rss
*/
- require_once 'Zend/Feed/Rss.php';
+ // require_once 'Zend/Feed/Rss.php';
// return a newly created Zend_Feed_Rss object
return new Zend_Feed_Rss(null, $string);
}
@@ -245,7 +245,7 @@ class Zend_Feed
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Invalid or unsupported feed format');
}
@@ -266,7 +266,7 @@ class Zend_Feed
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception("File could not be loaded: $php_errormsg");
}
return self::importString($feed);
@@ -293,7 +293,7 @@ class Zend_Feed
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception("Failed to access $uri, got response code " . $response->getStatus());
}
$contents = $response->getBody();
@@ -307,7 +307,7 @@ class Zend_Feed
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception("Internal error: $php_errormsg");
}
@@ -380,15 +380,15 @@ class Zend_Feed
public static function importArray(array $data, $format = 'atom')
{
$obj = 'Zend_Feed_' . ucfirst(strtolower($format));
- if (!class_exists($obj)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($obj);
- }
+ // if (!class_exists($obj)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($obj);
+ // }
/**
* @see Zend_Feed_Builder
*/
- require_once 'Zend/Feed/Builder.php';
+ // require_once 'Zend/Feed/Builder.php';
return new $obj(null, null, new Zend_Feed_Builder($data));
}
@@ -402,10 +402,10 @@ class Zend_Feed
public static function importBuilder(Zend_Feed_Builder_Interface $builder, $format = 'atom')
{
$obj = 'Zend_Feed_' . ucfirst(strtolower($format));
- if (!class_exists($obj)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($obj);
- }
+ // if (!class_exists($obj)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($obj);
+ // }
return new $obj(null, null, $builder);
}
}
diff --git a/libs/Zend/Feed/Abstract.php b/libs/Zend/Feed/Abstract.php
index ce59dc0793..8cd77dee7c 100644
--- a/libs/Zend/Feed/Abstract.php
+++ b/libs/Zend/Feed/Abstract.php
@@ -15,16 +15,16 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 18293 2009-09-18 22:16:07Z padraic $
+ * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Element
*/
-require_once 'Zend/Feed/Element.php';
+// require_once 'Zend/Feed/Element.php';
/**
@@ -37,7 +37,7 @@ require_once 'Zend/Feed/Element.php';
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Feed_Abstract extends Zend_Feed_Element implements Iterator, Countable
@@ -77,10 +77,10 @@ abstract class Zend_Feed_Abstract extends Zend_Feed_Element implements Iterator,
$client->setUri($uri);
$response = $client->request('GET');
if ($response->getStatus() !== 200) {
- /**
+ /**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Feed failed to load, got response code ' . $response->getStatus());
}
$this->_element = $response->getBody();
@@ -123,11 +123,11 @@ abstract class Zend_Feed_Abstract extends Zend_Feed_Element implements Iterator,
$php_errormsg = '(error message not available)';
}
}
-
- /**
+
+ /**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception("DOMDocument cannot parse XML: $php_errormsg");
}
diff --git a/libs/Zend/Feed/Atom.php b/libs/Zend/Feed/Atom.php
index db0055c5c2..8a723f862d 100644
--- a/libs/Zend/Feed/Atom.php
+++ b/libs/Zend/Feed/Atom.php
@@ -15,21 +15,21 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Atom.php 16205 2009-06-21 19:08:45Z thomas $
+ * @version $Id: Atom.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Abstract
*/
-require_once 'Zend/Feed/Abstract.php';
+// require_once 'Zend/Feed/Abstract.php';
/**
* @see Zend_Feed_Entry_Atom
*/
-require_once 'Zend/Feed/Entry/Atom.php';
+// require_once 'Zend/Feed/Entry/Atom.php';
/**
@@ -44,7 +44,7 @@ require_once 'Zend/Feed/Entry/Atom.php';
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Atom extends Zend_Feed_Abstract
@@ -89,10 +89,10 @@ class Zend_Feed_Atom extends Zend_Feed_Abstract
// Try to find a single <entry> instead.
$element = $this->_element->getElementsByTagName($this->_entryElementName)->item(0);
if (!$element) {
- /**
+ /**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('No root <feed> or <' . $this->_entryElementName
. '> element found, cannot parse feed.');
}
@@ -376,10 +376,10 @@ class Zend_Feed_Atom extends Zend_Feed_Abstract
public function send()
{
if (headers_sent()) {
- /**
+ /**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Cannot send ATOM because headers have already been sent.');
}
diff --git a/libs/Zend/Feed/Builder.php b/libs/Zend/Feed/Builder.php
index a0adbb1643..a9517ce5be 100644
--- a/libs/Zend/Feed/Builder.php
+++ b/libs/Zend/Feed/Builder.php
@@ -15,26 +15,26 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Builder.php 16205 2009-06-21 19:08:45Z thomas $
+ * @version $Id: Builder.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Builder_Interface
*/
-require_once 'Zend/Feed/Builder/Interface.php';
+// require_once 'Zend/Feed/Builder/Interface.php';
/**
* @see Zend_Feed_Builder_Header
*/
-require_once 'Zend/Feed/Builder/Header.php';
+// require_once 'Zend/Feed/Builder/Header.php';
/**
* @see Zend_Feed_Builder_Entry
*/
-require_once 'Zend/Feed/Builder/Entry.php';
+// require_once 'Zend/Feed/Builder/Entry.php';
/**
@@ -44,7 +44,7 @@ require_once 'Zend/Feed/Builder/Entry.php';
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Builder implements Zend_Feed_Builder_Interface
@@ -212,7 +212,7 @@ class Zend_Feed_Builder implements Zend_Feed_Builder_Interface
* @throws Zend_Feed_Builder_Exception
* @return void
*/
- private function _createHeader(array $data)
+ protected function _createHeader(array $data)
{
$mandatories = array('title', 'link', 'charset');
foreach ($mandatories as $mandatory) {
@@ -220,7 +220,7 @@ class Zend_Feed_Builder implements Zend_Feed_Builder_Interface
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("$mandatory key is missing");
}
}
@@ -268,7 +268,7 @@ class Zend_Feed_Builder implements Zend_Feed_Builder_Interface
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to define $mandatory property of your cloud");
}
}
@@ -282,7 +282,7 @@ class Zend_Feed_Builder implements Zend_Feed_Builder_Interface
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to define $mandatory property of your textInput");
}
}
@@ -340,7 +340,7 @@ class Zend_Feed_Builder implements Zend_Feed_Builder_Interface
* @throws Zend_Feed_Builder_Exception
* @return void
*/
- private function _createEntries(array $data)
+ protected function _createEntries(array $data)
{
foreach ($data as $row) {
$mandatories = array('title', 'link', 'description');
@@ -349,7 +349,7 @@ class Zend_Feed_Builder implements Zend_Feed_Builder_Interface
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("$mandatory key is missing");
}
}
@@ -379,7 +379,7 @@ class Zend_Feed_Builder implements Zend_Feed_Builder_Interface
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("$mandatory key of source property is missing");
}
}
@@ -395,4 +395,4 @@ class Zend_Feed_Builder implements Zend_Feed_Builder_Interface
$this->_entries[] = $entry;
}
}
-} \ No newline at end of file
+}
diff --git a/libs/Zend/Feed/Builder/Entry.php b/libs/Zend/Feed/Builder/Entry.php
index e428928717..6e7edc67b0 100644
--- a/libs/Zend/Feed/Builder/Entry.php
+++ b/libs/Zend/Feed/Builder/Entry.php
@@ -15,9 +15,9 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Entry.php 16205 2009-06-21 19:08:45Z thomas $
+ * @version $Id: Entry.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -29,7 +29,7 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Builder_Entry extends ArrayObject
@@ -224,7 +224,7 @@ class Zend_Feed_Builder_Entry extends ArrayObject
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to define the name of the category");
}
@@ -263,7 +263,7 @@ class Zend_Feed_Builder_Entry extends ArrayObject
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to supply an url for your enclosure");
}
$type = isset($enclosure['type']) ? $enclosure['type'] : '';
diff --git a/libs/Zend/Feed/Builder/Exception.php b/libs/Zend/Feed/Builder/Exception.php
index b213ceb42b..9037cc891a 100644
--- a/libs/Zend/Feed/Builder/Exception.php
+++ b/libs/Zend/Feed/Builder/Exception.php
@@ -15,16 +15,16 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16205 2009-06-21 19:08:45Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Exception
*/
-require_once 'Zend/Feed/Exception.php';
+// require_once 'Zend/Feed/Exception.php';
/**
@@ -32,7 +32,7 @@ require_once 'Zend/Feed/Exception.php';
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Builder_Exception extends Zend_Feed_Exception
diff --git a/libs/Zend/Feed/Builder/Header.php b/libs/Zend/Feed/Builder/Header.php
index a234377a15..51a57953f2 100644
--- a/libs/Zend/Feed/Builder/Header.php
+++ b/libs/Zend/Feed/Builder/Header.php
@@ -15,20 +15,20 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Header.php 16205 2009-06-21 19:08:45Z thomas $
+ * @version $Id: Header.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Builder_Header_Itunes
*/
-require_once 'Zend/Feed/Builder/Header/Itunes.php';
+// require_once 'Zend/Feed/Builder/Header/Itunes.php';
/**
* @see Zend_Uri
*/
-require_once 'Zend/Uri.php';
+// require_once 'Zend/Uri.php';
/**
@@ -39,7 +39,7 @@ require_once 'Zend/Uri.php';
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Builder_Header extends ArrayObject
@@ -172,13 +172,13 @@ class Zend_Feed_Builder_Header extends ArrayObject
/**
* @see Zend_Validate_EmailAddress
*/
- require_once 'Zend/Validate/EmailAddress.php';
+ // require_once 'Zend/Validate/EmailAddress.php';
$validate = new Zend_Validate_EmailAddress();
if (!$validate->isValid($email)) {
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to set a valid email address into the email property");
}
$this->offsetSet('email', $email);
@@ -246,13 +246,13 @@ class Zend_Feed_Builder_Header extends ArrayObject
/**
* @see Zend_Validate_EmailAddress
*/
- require_once 'Zend/Validate/EmailAddress.php';
+ // require_once 'Zend/Validate/EmailAddress.php';
$validate = new Zend_Validate_EmailAddress();
if (!$validate->isValid($webmaster)) {
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to set a valid email address into the webmaster property");
}
$this->offsetSet('webmaster', $webmaster);
@@ -272,13 +272,13 @@ class Zend_Feed_Builder_Header extends ArrayObject
/**
* @see Zend_Validate_Int
*/
- require_once 'Zend/Validate/Int.php';
+ // require_once 'Zend/Validate/Int.php';
$validate = new Zend_Validate_Int();
if (!$validate->isValid($ttl)) {
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to set an integer value to the ttl property");
}
$this->offsetSet('ttl', $ttl);
@@ -317,7 +317,7 @@ class Zend_Feed_Builder_Header extends ArrayObject
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception('Passed parameter is not a valid HTTP URI');
}
if (!$uri->getPort()) {
@@ -362,7 +362,7 @@ class Zend_Feed_Builder_Header extends ArrayObject
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you can not have more than 24 rows in the skipHours property");
}
foreach ($hours as $hour) {
@@ -370,7 +370,7 @@ class Zend_Feed_Builder_Header extends ArrayObject
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("$hour has te be between 0 and 23");
}
}
@@ -392,7 +392,7 @@ class Zend_Feed_Builder_Header extends ArrayObject
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you can not have more than 7 days in the skipDays property");
}
$valid = array('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday');
@@ -401,7 +401,7 @@ class Zend_Feed_Builder_Header extends ArrayObject
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("$day is not a valid day");
}
}
diff --git a/libs/Zend/Feed/Builder/Header/Itunes.php b/libs/Zend/Feed/Builder/Header/Itunes.php
index cbb443bbae..9445460c07 100644
--- a/libs/Zend/Feed/Builder/Header/Itunes.php
+++ b/libs/Zend/Feed/Builder/Header/Itunes.php
@@ -15,9 +15,9 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Itunes.php 16205 2009-06-21 19:08:45Z thomas $
+ * @version $Id: Itunes.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -28,7 +28,7 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Builder_Header_Itunes extends ArrayObject
@@ -66,14 +66,14 @@ class Zend_Feed_Builder_Header_Itunes extends ArrayObject
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to set at least one itunes category");
}
if ($nb > 3) {
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to set at most three itunes categories");
}
foreach ($categories as $i => $category) {
@@ -81,7 +81,7 @@ class Zend_Feed_Builder_Header_Itunes extends ArrayObject
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to set the main category (category #$i)");
}
}
@@ -112,16 +112,16 @@ class Zend_Feed_Builder_Header_Itunes extends ArrayObject
public function setOwner($name = '', $email = '')
{
if (!empty($email)) {
- /**
- * @see Zend_Validate_EmailAddress
- */
- require_once 'Zend/Validate/EmailAddress.php';
+ /**
+ * @see Zend_Validate_EmailAddress
+ */
+ // require_once 'Zend/Validate/EmailAddress.php';
$validate = new Zend_Validate_EmailAddress();
if (!$validate->isValid($email)) {
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to set a valid email address into the itunes owner's email property");
}
}
@@ -182,7 +182,7 @@ class Zend_Feed_Builder_Header_Itunes extends ArrayObject
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to set yes or no to the itunes block property");
}
$this->offsetSet('block', $block);
@@ -203,7 +203,7 @@ class Zend_Feed_Builder_Header_Itunes extends ArrayObject
/**
* @see Zend_Feed_Builder_Exception
*/
- require_once 'Zend/Feed/Builder/Exception.php';
+ // require_once 'Zend/Feed/Builder/Exception.php';
throw new Zend_Feed_Builder_Exception("you have to set yes, no or clean to the itunes explicit property");
}
$this->offsetSet('explicit', $explicit);
diff --git a/libs/Zend/Feed/Builder/Interface.php b/libs/Zend/Feed/Builder/Interface.php
index a3cce7e018..9dce55f815 100644
--- a/libs/Zend/Feed/Builder/Interface.php
+++ b/libs/Zend/Feed/Builder/Interface.php
@@ -15,9 +15,9 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16205 2009-06-21 19:08:45Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -29,7 +29,7 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Feed_Builder_Interface
diff --git a/libs/Zend/Feed/Element.php b/libs/Zend/Feed/Element.php
index 2f0337d54f..b7a8e632f2 100644
--- a/libs/Zend/Feed/Element.php
+++ b/libs/Zend/Feed/Element.php
@@ -15,9 +15,9 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Element.php 18568 2009-10-16 11:59:55Z sgehrig $
+ * @version $Id: Element.php 20104 2010-01-06 21:26:01Z matthew $
*/
@@ -26,7 +26,7 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Element implements ArrayAccess
@@ -38,6 +38,11 @@ class Zend_Feed_Element implements ArrayAccess
protected $_element;
/**
+ * @var string Character encoding to utilize
+ */
+ protected $_encoding = 'UTF-8';
+
+ /**
* @var Zend_Feed_Element
*/
protected $_parentElement;
@@ -148,6 +153,27 @@ class Zend_Feed_Element implements ArrayAccess
return $this->_element->ownerDocument->saveXML($this->_element);
}
+ /**
+ * Get encoding
+ *
+ * @return string
+ */
+ public function getEncoding()
+ {
+ return $this->_encoding;
+ }
+
+ /**
+ * Set encoding
+ *
+ * @param string $value Encoding to use
+ * @return Zend_Feed_Element
+ */
+ public function setEncoding($value)
+ {
+ $this->_encoding = (string) $value;
+ return $this;
+ }
/**
* Map variable access onto the underlying entry representation.
@@ -205,18 +231,18 @@ class Zend_Feed_Element implements ArrayAccess
if (strpos($var, ':') !== false) {
list($ns, $elt) = explode(':', $var, 2);
$node = $this->_element->ownerDocument->createElementNS(Zend_Feed::lookupNamespace($ns),
- $var, htmlspecialchars($val, ENT_NOQUOTES, 'UTF-8'));
+ $var, htmlspecialchars($val, ENT_NOQUOTES, $this->getEncoding()));
$this->_element->appendChild($node);
} else {
$node = $this->_element->ownerDocument->createElement($var,
- htmlspecialchars($val, ENT_NOQUOTES, 'UTF-8'));
+ htmlspecialchars($val, ENT_NOQUOTES, $this->getEncoding()));
$this->_element->appendChild($node);
}
} elseif (count($nodes) > 1) {
- /**
+ /**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Cannot set the value of multiple tags simultaneously.');
} else {
$nodes[0]->nodeValue = $val;
diff --git a/libs/Zend/Feed/Entry/Abstract.php b/libs/Zend/Feed/Entry/Abstract.php
index ba82f1fca1..60c10cc89a 100644
--- a/libs/Zend/Feed/Entry/Abstract.php
+++ b/libs/Zend/Feed/Entry/Abstract.php
@@ -15,21 +15,21 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 16205 2009-06-21 19:08:45Z thomas $
+ * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed
*/
-require_once 'Zend/Feed.php';
+// require_once 'Zend/Feed.php';
/**
* @see Zend_Feed_Element
*/
-require_once 'Zend/Feed/Element.php';
+// require_once 'Zend/Feed/Element.php';
/**
@@ -38,7 +38,7 @@ require_once 'Zend/Feed/Element.php';
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Feed_Entry_Abstract extends Zend_Feed_Element
@@ -93,19 +93,19 @@ abstract class Zend_Feed_Entry_Abstract extends Zend_Feed_Element
}
}
- /**
+ /**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception("DOMDocument cannot parse XML: $php_errormsg");
}
$element = $doc->getElementsByTagName($this->_rootElement)->item(0);
if (!$element) {
- /**
+ /**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('No root <' . $this->_rootElement . '> element found, cannot parse feed.');
}
} else {
diff --git a/libs/Zend/Feed/Entry/Atom.php b/libs/Zend/Feed/Entry/Atom.php
index 7cbfce2c0e..01a17232eb 100644
--- a/libs/Zend/Feed/Entry/Atom.php
+++ b/libs/Zend/Feed/Entry/Atom.php
@@ -15,16 +15,16 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Atom.php 18184 2009-09-17 18:26:40Z padraic $
+ * @version $Id: Atom.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Entry_Abstract
*/
-require_once 'Zend/Feed/Entry/Abstract.php';
+// require_once 'Zend/Feed/Entry/Abstract.php';
/**
@@ -32,15 +32,15 @@ require_once 'Zend/Feed/Entry/Abstract.php';
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Entry_Atom extends Zend_Feed_Entry_Abstract
{
- /**
- * Content-Type
- */
- const CONTENT_TYPE = 'application/atom+xml';
+ /**
+ * Content-Type
+ */
+ const CONTENT_TYPE = 'application/atom+xml';
/**
* Root XML element for Atom entries.
@@ -79,7 +79,7 @@ class Zend_Feed_Entry_Atom extends Zend_Feed_Entry_Abstract
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Cannot delete entry; no link rel="edit" is present.');
}
@@ -107,7 +107,7 @@ class Zend_Feed_Entry_Atom extends Zend_Feed_Entry_Abstract
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception("Expected response code 2xx, got $httpStatus");
}
} while (true);
@@ -144,7 +144,7 @@ class Zend_Feed_Entry_Atom extends Zend_Feed_Entry_Abstract
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Cannot edit entry; no link rel="edit" is present.');
}
@@ -164,7 +164,7 @@ class Zend_Feed_Entry_Atom extends Zend_Feed_Entry_Abstract
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Expected response code 200, got ' . $response->getStatus());
}
} else {
@@ -172,7 +172,7 @@ class Zend_Feed_Entry_Atom extends Zend_Feed_Entry_Abstract
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('PostURI must be specified to save new entries.');
}
$client = Zend_Feed::getHttpClient();
@@ -185,7 +185,7 @@ class Zend_Feed_Entry_Atom extends Zend_Feed_Entry_Abstract
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Expected response code 201, got '
. $response->getStatus());
}
@@ -210,7 +210,7 @@ class Zend_Feed_Entry_Atom extends Zend_Feed_Entry_Abstract
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('XML cannot be parsed: ' . $php_errormsg);
}
@@ -219,7 +219,7 @@ class Zend_Feed_Entry_Atom extends Zend_Feed_Entry_Abstract
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('No root <feed> element found in server response:'
. "\n\n" . $client->responseBody);
}
diff --git a/libs/Zend/Feed/Entry/Rss.php b/libs/Zend/Feed/Entry/Rss.php
index 464601b5e7..a03fe8052e 100644
--- a/libs/Zend/Feed/Entry/Rss.php
+++ b/libs/Zend/Feed/Entry/Rss.php
@@ -15,16 +15,16 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Rss.php 16205 2009-06-21 19:08:45Z thomas $
+ * @version $Id: Rss.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Entry_Abstract
*/
-require_once 'Zend/Feed/Entry/Abstract.php';
+// require_once 'Zend/Feed/Entry/Abstract.php';
/**
@@ -32,7 +32,7 @@ require_once 'Zend/Feed/Entry/Abstract.php';
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Entry_Rss extends Zend_Feed_Entry_Abstract
@@ -98,7 +98,7 @@ class Zend_Feed_Entry_Rss extends Zend_Feed_Entry_Abstract
return parent::__isset($var);
}
}
-
+
/**
* Overwrites parent::_call method to enable read access
* to content:encoded element.
diff --git a/libs/Zend/Feed/Exception.php b/libs/Zend/Feed/Exception.php
index c77bb35495..1142c88a00 100644
--- a/libs/Zend/Feed/Exception.php
+++ b/libs/Zend/Feed/Exception.php
@@ -15,16 +15,16 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16205 2009-06-21 19:08:45Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Exception
*/
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
@@ -34,7 +34,7 @@ require_once 'Zend/Exception.php';
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Exception extends Zend_Exception
diff --git a/libs/Zend/Feed/Pubsubhubbub.php b/libs/Zend/Feed/Pubsubhubbub.php
new file mode 100644
index 0000000000..eeffd74218
--- /dev/null
+++ b/libs/Zend/Feed/Pubsubhubbub.php
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @see Zend_Http_Client
+ */
+// require_once 'Zend/Http/Client.php';
+
+/**
+ * @see Zend_Uri
+ */
+// require_once 'Zend/Uri.php';
+
+/**
+ * @see Zend_Version
+ */
+// require_once 'Zend/Version.php';
+
+/**
+ * @see Zend_Feed_Reader
+ */
+// require_once 'Zend/Feed/Reader.php';
+
+/**
+ * @see Zend_Feed_Abstract
+ */
+// require_once 'Zend/Feed/Abstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Pubsubhubbub
+{
+ /**
+ * Verification Modes
+ */
+ const VERIFICATION_MODE_SYNC = 'sync';
+ const VERIFICATION_MODE_ASYNC = 'async';
+
+ /**
+ * Subscription States
+ */
+ const SUBSCRIPTION_VERIFIED = 'verified';
+ const SUBSCRIPTION_NOTVERIFIED = 'not_verified';
+ const SUBSCRIPTION_TODELETE = 'to_delete';
+
+ /**
+ * Singleton instance if required of the HTTP client
+ *
+ * @var Zend_Http_Client
+ */
+ protected static $httpClient = null;
+
+ /**
+ * Simple utility function which imports any feed URL and
+ * determines the existence of Hub Server endpoints. This works
+ * best if directly given an instance of Zend_Feed_Reader_Atom|Rss
+ * to leverage off.
+ *
+ * @param Zend_Feed_Reader_FeedAbstract|Zend_Feed_Abstract|string $source
+ * @return array
+ */
+ public static function detectHubs($source)
+ {
+ if (is_string($source)) {
+ $feed = Zend_Feed_Reader::import($source);
+ } elseif (is_object($source) && $source instanceof Zend_Feed_Reader_FeedAbstract) {
+ $feed = $source;
+ } elseif (is_object($source) && $source instanceof Zend_Feed_Abstract) {
+ $feed = Zend_Feed_Reader::importFeed($source);
+ } else {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('The source parameter was'
+ . ' invalid, i.e. not a URL string or an instance of type'
+ . ' Zend_Feed_Reader_FeedAbstract or Zend_Feed_Abstract');
+ }
+ return $feed->getHubs();
+ }
+
+ /**
+ * Allows the external environment to make Zend_Oauth use a specific
+ * Client instance.
+ *
+ * @param Zend_Http_Client $httpClient
+ * @return void
+ */
+ public static function setHttpClient(Zend_Http_Client $httpClient)
+ {
+ self::$httpClient = $httpClient;
+ }
+
+ /**
+ * Return the singleton instance of the HTTP Client. Note that
+ * the instance is reset and cleared of previous parameters GET/POST.
+ * Headers are NOT reset but handled by this component if applicable.
+ *
+ * @return Zend_Http_Client
+ */
+ public static function getHttpClient()
+ {
+ if (!isset(self::$httpClient)):
+ self::$httpClient = new Zend_Http_Client;
+ else:
+ self::$httpClient->resetParameters();
+ endif;
+ return self::$httpClient;
+ }
+
+ /**
+ * Simple mechanism to delete the entire singleton HTTP Client instance
+ * which forces an new instantiation for subsequent requests.
+ *
+ * @return void
+ */
+ public static function clearHttpClient()
+ {
+ self::$httpClient = null;
+ }
+
+ /**
+ * RFC 3986 safe url encoding method
+ *
+ * @param string $string
+ * @return string
+ */
+ public static function urlencode($string)
+ {
+ $rawencoded = rawurlencode($string);
+ $rfcencoded = str_replace('%7E', '~', $rawencoded);
+ return $rfcencoded;
+ }
+}
diff --git a/libs/Zend/Feed/Pubsubhubbub/CallbackAbstract.php b/libs/Zend/Feed/Pubsubhubbub/CallbackAbstract.php
new file mode 100644
index 0000000000..2fae31b831
--- /dev/null
+++ b/libs/Zend/Feed/Pubsubhubbub/CallbackAbstract.php
@@ -0,0 +1,307 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @subpackage Callback
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @see Zend_Feed_Pubsubhubbub_CallbackInterface
+ */
+// require_once 'Zend/Feed/Pubsubhubbub/CallbackInterface.php';
+
+/**
+ * @see Zend_Feed_Pubsubhubbub_HttpResponse
+ */
+// require_once 'Zend/Feed/Pubsubhubbub/HttpResponse.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @subpackage Callback
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+abstract class Zend_Feed_Pubsubhubbub_CallbackAbstract
+ implements Zend_Feed_Pubsubhubbub_CallbackInterface
+{
+ /**
+ * An instance of Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface used
+ * to background save any verification tokens associated with a subscription
+ * or other.
+ *
+ * @var Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface
+ */
+ protected $_storage = null;
+
+ /**
+ * An instance of a class handling Http Responses. This is implemented in
+ * Zend_Feed_Pubsubhubbub_HttpResponse which shares an unenforced interface with
+ * (i.e. not inherited from) Zend_Controller_Response_Http.
+ *
+ * @var Zend_Feed_Pubsubhubbub_HttpResponse|Zend_Controller_Response_Http
+ */
+ protected $_httpResponse = null;
+
+ /**
+ * The number of Subscribers for which any updates are on behalf of.
+ *
+ * @var int
+ */
+ protected $_subscriberCount = 1;
+
+ /**
+ * Constructor; accepts an array or Zend_Config instance to preset
+ * options for the Subscriber without calling all supported setter
+ * methods in turn.
+ *
+ * @param array|Zend_Config $options Options array or Zend_Config instance
+ */
+ public function __construct($config = null)
+ {
+ if (!is_null($config)) {
+ $this->setConfig($config);
+ }
+ }
+
+ /**
+ * Process any injected configuration options
+ *
+ * @param array|Zend_Config $options Options array or Zend_Config instance
+ * @return Zend_Feed_Pubsubhubbub_CallbackAbstract
+ */
+ public function setConfig($config)
+ {
+ if ($config instanceof Zend_Config) {
+ $config = $config->toArray();
+ } elseif (!is_array($config)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Array or Zend_Config object'
+ . 'expected, got ' . gettype($config));
+ }
+ if (array_key_exists('storage', $config)) {
+ $this->setStorage($config['storage']);
+ }
+ return $this;
+ }
+
+ /**
+ * Send the response, including all headers.
+ * If you wish to handle this via Zend_Controller, use the getter methods
+ * to retrieve any data needed to be set on your HTTP Response object, or
+ * simply give this object the HTTP Response instance to work with for you!
+ *
+ * @return void
+ */
+ public function sendResponse()
+ {
+ $this->getHttpResponse()->sendResponse();
+ }
+
+ /**
+ * Sets an instance of Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface used
+ * to background save any verification tokens associated with a subscription
+ * or other.
+ *
+ * @param Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface $storage
+ * @return Zend_Feed_Pubsubhubbub_CallbackAbstract
+ */
+ public function setStorage(Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface $storage)
+ {
+ $this->_storage = $storage;
+ return $this;
+ }
+
+ /**
+ * Gets an instance of Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface used
+ * to background save any verification tokens associated with a subscription
+ * or other.
+ *
+ * @return Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface
+ */
+ public function getStorage()
+ {
+ if ($this->_storage === null) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('No storage object has been'
+ . ' set that subclasses Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface');
+ }
+ return $this->_storage;
+ }
+
+ /**
+ * An instance of a class handling Http Responses. This is implemented in
+ * Zend_Feed_Pubsubhubbub_HttpResponse which shares an unenforced interface with
+ * (i.e. not inherited from) Zend_Controller_Response_Http.
+ *
+ * @param Zend_Feed_Pubsubhubbub_HttpResponse|Zend_Controller_Response_Http $httpResponse
+ * @return Zend_Feed_Pubsubhubbub_CallbackAbstract
+ */
+ public function setHttpResponse($httpResponse)
+ {
+ if (!is_object($httpResponse)
+ || (!$httpResponse instanceof Zend_Feed_Pubsubhubbub_HttpResponse
+ && !$httpResponse instanceof Zend_Controller_Response_Http)
+ ) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('HTTP Response object must'
+ . ' implement one of Zend_Feed_Pubsubhubbub_HttpResponse or'
+ . ' Zend_Controller_Response_Http');
+ }
+ $this->_httpResponse = $httpResponse;
+ return $this;
+ }
+
+ /**
+ * An instance of a class handling Http Responses. This is implemented in
+ * Zend_Feed_Pubsubhubbub_HttpResponse which shares an unenforced interface with
+ * (i.e. not inherited from) Zend_Controller_Response_Http.
+ *
+ * @return Zend_Feed_Pubsubhubbub_HttpResponse|Zend_Controller_Response_Http
+ */
+ public function getHttpResponse()
+ {
+ if ($this->_httpResponse === null) {
+ $this->_httpResponse = new Zend_Feed_Pubsubhubbub_HttpResponse;
+ }
+ return $this->_httpResponse;
+ }
+
+ /**
+ * Sets the number of Subscribers for which any updates are on behalf of.
+ * In other words, is this class serving one or more subscribers? How many?
+ * Defaults to 1 if left unchanged.
+ *
+ * @param string|int $count
+ * @return Zend_Feed_Pubsubhubbub_CallbackAbstract
+ */
+ public function setSubscriberCount($count)
+ {
+ $count = intval($count);
+ if ($count <= 0) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Subscriber count must be'
+ . ' greater than zero');
+ }
+ $this->_subscriberCount = $count;
+ return $this;
+ }
+
+ /**
+ * Gets the number of Subscribers for which any updates are on behalf of.
+ * In other words, is this class serving one or more subscribers? How many?
+ *
+ * @return int
+ */
+ public function getSubscriberCount()
+ {
+ return $this->_subscriberCount;
+ }
+
+ /**
+ * Attempt to detect the callback URL (specifically the path forward)
+ */
+ protected function _detectCallbackUrl()
+ {
+ $callbackUrl = '';
+ if (isset($_SERVER['HTTP_X_REWRITE_URL'])) {
+ $callbackUrl = $_SERVER['HTTP_X_REWRITE_URL'];
+ } elseif (isset($_SERVER['REQUEST_URI'])) {
+ $callbackUrl = $_SERVER['REQUEST_URI'];
+ $scheme = 'http';
+ if ($_SERVER['HTTPS'] == 'on') {
+ $scheme = 'https';
+ }
+ $schemeAndHttpHost = $scheme . '://' . $this->_getHttpHost();
+ if (strpos($callbackUrl, $schemeAndHttpHost) === 0) {
+ $callbackUrl = substr($callbackUrl, strlen($schemeAndHttpHost));
+ }
+ } elseif (isset($_SERVER['ORIG_PATH_INFO'])) {
+ $callbackUrl= $_SERVER['ORIG_PATH_INFO'];
+ if (!empty($_SERVER['QUERY_STRING'])) {
+ $callbackUrl .= '?' . $_SERVER['QUERY_STRING'];
+ }
+ }
+ return $callbackUrl;
+ }
+
+ /**
+ * Get the HTTP host
+ *
+ * @return string
+ */
+ protected function _getHttpHost()
+ {
+ if (!empty($_SERVER['HTTP_HOST'])) {
+ return $_SERVER['HTTP_HOST'];
+ }
+ $scheme = 'http';
+ if ($_SERVER['HTTPS'] == 'on') {
+ $scheme = 'https';
+ }
+ $name = $_SERVER['SERVER_NAME'];
+ $port = $_SERVER['SERVER_PORT'];
+ if (($scheme == 'http' && $port == 80)
+ || ($scheme == 'https' && $port == 443)
+ ) {
+ return $name;
+ } else {
+ return $name . ':' . $port;
+ }
+ }
+
+ /**
+ * Retrieve a Header value from either $_SERVER or Apache
+ *
+ * @param string $header
+ */
+ protected function _getHeader($header)
+ {
+ $temp = strtoupper(str_replace('-', '_', $header));
+ if (!empty($_SERVER[$temp])) {
+ return $_SERVER[$temp];
+ }
+ $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
+ if (!empty($_SERVER[$temp])) {
+ return $_SERVER[$temp];
+ }
+ if (function_exists('apache_request_headers')) {
+ $headers = apache_request_headers();
+ if (!empty($headers[$header])) {
+ return $headers[$header];
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return the raw body of the request
+ *
+ * @return string|false Raw body, or false if not present
+ */
+ protected function _getRawBody()
+ {
+ $body = file_get_contents('php://input');
+ if (strlen(trim($body)) == 0 && isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
+ $body = $GLOBALS['HTTP_RAW_POST_DATA'];
+ }
+ if (strlen(trim($body)) > 0) {
+ return $body;
+ }
+ return false;
+ }
+}
diff --git a/libs/Zend/Feed/Pubsubhubbub/CallbackInterface.php b/libs/Zend/Feed/Pubsubhubbub/CallbackInterface.php
new file mode 100644
index 0000000000..ce30a6bb23
--- /dev/null
+++ b/libs/Zend/Feed/Pubsubhubbub/CallbackInterface.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @subpackage Callback
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @subpackage Callback
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+interface Zend_Feed_Pubsubhubbub_CallbackInterface
+{
+ /**
+ * Handle any callback from a Hub Server responding to a subscription or
+ * unsubscription request. This should be the Hub Server confirming the
+ * the request prior to taking action on it.
+ *
+ * @param array $httpData GET/POST data if available and not in $_GET/POST
+ * @param bool $sendResponseNow Whether to send response now or when asked
+ */
+ public function handle(array $httpData = null, $sendResponseNow = false);
+
+ /**
+ * Send the response, including all headers.
+ * If you wish to handle this via Zend_Controller, use the getter methods
+ * to retrieve any data needed to be set on your HTTP Response object, or
+ * simply give this object the HTTP Response instance to work with for you!
+ *
+ * @return void
+ */
+ public function sendResponse();
+
+ /**
+ * An instance of a class handling Http Responses. This is implemented in
+ * Zend_Feed_Pubsubhubbub_HttpResponse which shares an unenforced interface with
+ * (i.e. not inherited from) Zend_Controller_Response_Http.
+ *
+ * @param Zend_Feed_Pubsubhubbub_HttpResponse|Zend_Controller_Response_Http $httpResponse
+ */
+ public function setHttpResponse($httpResponse);
+
+ /**
+ * An instance of a class handling Http Responses. This is implemented in
+ * Zend_Feed_Pubsubhubbub_HttpResponse which shares an unenforced interface with
+ * (i.e. not inherited from) Zend_Controller_Response_Http.
+ *
+ * @return Zend_Feed_Pubsubhubbub_HttpResponse|Zend_Controller_Response_Http
+ */
+ public function getHttpResponse();
+}
diff --git a/libs/Zend/Feed/Pubsubhubbub/Exception.php b/libs/Zend/Feed/Pubsubhubbub/Exception.php
new file mode 100644
index 0000000000..5bc562c94e
--- /dev/null
+++ b/libs/Zend/Feed/Pubsubhubbub/Exception.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @see Zend_Exception
+ */
+// require_once 'Zend/Exception.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Pubsubhubbub_Exception extends Zend_Exception
+{}
diff --git a/libs/Zend/Feed/Pubsubhubbub/HttpResponse.php b/libs/Zend/Feed/Pubsubhubbub/HttpResponse.php
new file mode 100644
index 0000000000..e44f0eb86a
--- /dev/null
+++ b/libs/Zend/Feed/Pubsubhubbub/HttpResponse.php
@@ -0,0 +1,233 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @see Zend_Feed_Pubsubhubbub
+ */
+// require_once 'Zend/Feed/Pubsubhubbub.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Pubsubhubbub_HttpResponse
+{
+ /**
+ * The body of any response to the current callback request
+ *
+ * @var string
+ */
+ protected $_body = '';
+
+ /**
+ * Array of headers. Each header is an array with keys 'name' and 'value'
+ *
+ * @var array
+ */
+ protected $_headers = array();
+
+ /**
+ * HTTP response code to use in headers
+ *
+ * @var int
+ */
+ protected $_httpResponseCode = 200;
+
+ /**
+ * Send the response, including all headers
+ *
+ * @return void
+ */
+ public function sendResponse()
+ {
+ $this->sendHeaders();
+ echo $this->getBody();
+ }
+
+ /**
+ * Send all headers
+ *
+ * Sends any headers specified. If an {@link setHttpResponseCode() HTTP response code}
+ * has been specified, it is sent with the first header.
+ *
+ * @return void
+ */
+ public function sendHeaders()
+ {
+ if (count($this->_headers) || (200 != $this->_httpResponseCode)) {
+ $this->canSendHeaders(true);
+ } elseif (200 == $this->_httpResponseCode) {
+ return;
+ }
+ $httpCodeSent = false;
+ foreach ($this->_headers as $header) {
+ if (!$httpCodeSent && $this->_httpResponseCode) {
+ header($header['name'] . ': ' . $header['value'], $header['replace'], $this->_httpResponseCode);
+ $httpCodeSent = true;
+ } else {
+ header($header['name'] . ': ' . $header['value'], $header['replace']);
+ }
+ }
+ if (!$httpCodeSent) {
+ header('HTTP/1.1 ' . $this->_httpResponseCode);
+ $httpCodeSent = true;
+ }
+ }
+
+ /**
+ * Set a header
+ *
+ * If $replace is true, replaces any headers already defined with that
+ * $name.
+ *
+ * @param string $name
+ * @param string $value
+ * @param boolean $replace
+ * @return Zend_Feed_Pubsubhubbub_HttpResponse
+ */
+ public function setHeader($name, $value, $replace = false)
+ {
+ $name = $this->_normalizeHeader($name);
+ $value = (string) $value;
+ if ($replace) {
+ foreach ($this->_headers as $key => $header) {
+ if ($name == $header['name']) {
+ unset($this->_headers[$key]);
+ }
+ }
+ }
+ $this->_headers[] = array(
+ 'name' => $name,
+ 'value' => $value,
+ 'replace' => $replace,
+ );
+
+ return $this;
+ }
+
+ /**
+ * Check if a specific Header is set and return its value
+ *
+ * @param string $name
+ * @return string|null
+ */
+ public function getHeader($name)
+ {
+ $name = $this->_normalizeHeader($name);
+ foreach ($this->_headers as $header) {
+ if ($header['name'] == $name) {
+ return $header['value'];
+ }
+ }
+ }
+
+ /**
+ * Return array of headers; see {@link $_headers} for format
+ *
+ * @return array
+ */
+ public function getHeaders()
+ {
+ return $this->_headers;
+ }
+
+ /**
+ * Can we send headers?
+ *
+ * @param boolean $throw Whether or not to throw an exception if headers have been sent; defaults to false
+ * @return boolean
+ * @throws Zend_Feed_Pubsubhubbub_Exception
+ */
+ public function canSendHeaders($throw = false)
+ {
+ $ok = headers_sent($file, $line);
+ if ($ok && $throw) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Cannot send headers; headers already sent in ' . $file . ', line ' . $line);
+ }
+ return !$ok;
+ }
+
+ /**
+ * Set HTTP response code to use with headers
+ *
+ * @param int $code
+ * @return Zend_Feed_Pubsubhubbub_HttpResponse
+ */
+ public function setHttpResponseCode($code)
+ {
+ if (!is_int($code) || (100 > $code) || (599 < $code)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid HTTP response'
+ . ' code:' . $code);
+ }
+ $this->_httpResponseCode = $code;
+ return $this;
+ }
+
+ /**
+ * Retrieve HTTP response code
+ *
+ * @return int
+ */
+ public function getHttpResponseCode()
+ {
+ return $this->_httpResponseCode;
+ }
+
+ /**
+ * Set body content
+ *
+ * @param string $content
+ * @return Zend_Feed_Pubsubhubbub_HttpResponse
+ */
+ public function setBody($content)
+ {
+ $this->_body = (string) $content;
+ $this->setHeader('content-length', strlen($content));
+ return $this;
+ }
+
+ /**
+ * Return the body content
+ *
+ * @return string
+ */
+ public function getBody()
+ {
+ return $this->_body;
+ }
+
+ /**
+ * Normalizes a header name to X-Capitalized-Names
+ *
+ * @param string $name
+ * @return string
+ */
+ protected function _normalizeHeader($name)
+ {
+ $filtered = str_replace(array('-', '_'), ' ', (string) $name);
+ $filtered = ucwords(strtolower($filtered));
+ $filtered = str_replace(' ', '-', $filtered);
+ return $filtered;
+ }
+}
diff --git a/libs/Zend/Feed/Pubsubhubbub/Model/ModelAbstract.php b/libs/Zend/Feed/Pubsubhubbub/Model/ModelAbstract.php
new file mode 100644
index 0000000000..eab4b56322
--- /dev/null
+++ b/libs/Zend/Feed/Pubsubhubbub/Model/ModelAbstract.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+
+/** @see Zend_Db_Table */
+// require_once 'Zend/Db/Table.php';
+
+/**
+ * @see Zend_Registry
+ * Seems to fix the file not being included by Zend_Db_Table...
+ */
+// require_once 'Zend/Registry.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Pubsubhubbub_Model_ModelAbstract
+{
+ /**
+ * Zend_Db_Table instance to host database methods
+ *
+ * @var Zend_Db_Table
+ */
+ protected $_db = null;
+
+ /**
+ * Constructor
+ *
+ * @param array $data
+ * @param Zend_Db_Table_Abstract $tableGateway
+ * @return void
+ */
+ public function __construct(Zend_Db_Table_Abstract $tableGateway = null)
+ {
+ if (is_null($tableGateway)) {
+ $parts = explode('_', get_class($this));
+ $table = strtolower(array_pop($parts));
+ $this->_db = new Zend_Db_Table($table);
+ } else {
+ $this->_db = $tableGateway;
+ }
+ }
+
+}
diff --git a/libs/Zend/Feed/Pubsubhubbub/Model/Subscription.php b/libs/Zend/Feed/Pubsubhubbub/Model/Subscription.php
new file mode 100644
index 0000000000..ea971b4f77
--- /dev/null
+++ b/libs/Zend/Feed/Pubsubhubbub/Model/Subscription.php
@@ -0,0 +1,131 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @subpackage Entity
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/** @see Zend_Feed_Pubsubhubbub_Model_ModelAbstract */
+// require_once 'Zend/Feed/Pubsubhubbub/Model/ModelAbstract.php';
+
+/** @see Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface */
+// require_once 'Zend/Feed/Pubsubhubbub/Model/SubscriptionInterface.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @subpackage Entity
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Pubsubhubbub_Model_Subscription
+ extends Zend_Feed_Pubsubhubbub_Model_ModelAbstract
+ implements Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface
+{
+
+ /**
+ * Save subscription to RDMBS
+ *
+ * @param array $data
+ * @return bool
+ */
+ public function setSubscription(array $data)
+ {
+ if (!isset($data['id'])) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception(
+ 'ID must be set before attempting a save'
+ );
+ }
+ $result = $this->_db->find($data['id']);
+ if ($result) {
+ $data['created_time'] = $result->current()->created_time;
+ $now = new Zend_Date;
+ if ($data['lease_seconds']) {
+ $data['expiration_time'] = $now->add($data['lease_seconds'], Zend_Date::SECOND)
+ ->get('yyyy-MM-dd HH:mm:ss');
+ }
+ $this->_db->update(
+ $data,
+ $this->_db->getAdapter()->quoteInto('id = ?', $data['id'])
+ );
+ return false;
+ }
+
+ $this->_db->insert($data);
+ return true;
+ }
+
+ /**
+ * Get subscription by ID/key
+ *
+ * @param string $key
+ * @return array
+ */
+ public function getSubscription($key)
+ {
+ if (empty($key) || !is_string($key)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "key"'
+ .' of "' . $key . '" must be a non-empty string');
+ }
+ $result = $this->_db->find($key);
+ if ($result) {
+ return (array) $result->current();
+ }
+ return false;
+ }
+
+ /**
+ * Determine if a subscription matching the key exists
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function hasSubscription($key)
+ {
+ if (empty($key) || !is_string($key)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "key"'
+ .' of "' . $key . '" must be a non-empty string');
+ }
+ $result = $this->_db->find($key);
+ if ($result) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Delete a subscription
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function deleteSubscription($key)
+ {
+ $result = $this->_db->find($key);
+ if ($result) {
+ $this->_db->delete(
+ $this->_db->getAdapter()->quoteInto('id = ?', $key)
+ );
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/libs/Zend/Feed/Pubsubhubbub/Model/SubscriptionInterface.php b/libs/Zend/Feed/Pubsubhubbub/Model/SubscriptionInterface.php
new file mode 100644
index 0000000000..f8a6e6a3e3
--- /dev/null
+++ b/libs/Zend/Feed/Pubsubhubbub/Model/SubscriptionInterface.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @subpackage Entity
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @subpackage Entity
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+interface Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface
+{
+
+ /**
+ * Save subscription to RDMBS
+ *
+ * @param array $data The key must be stored here as a $data['id'] entry
+ * @return bool
+ */
+ public function setSubscription(array $data);
+
+ /**
+ * Get subscription by ID/key
+ *
+ * @param string $key
+ * @return array
+ */
+ public function getSubscription($key);
+
+ /**
+ * Determine if a subscription matching the key exists
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function hasSubscription($key);
+
+ /**
+ * Delete a subscription
+ *
+ * @param string $key
+ * @return bool
+ */
+ public function deleteSubscription($key);
+
+}
diff --git a/libs/Zend/Feed/Pubsubhubbub/Publisher.php b/libs/Zend/Feed/Pubsubhubbub/Publisher.php
new file mode 100644
index 0000000000..dfc388beca
--- /dev/null
+++ b/libs/Zend/Feed/Pubsubhubbub/Publisher.php
@@ -0,0 +1,417 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @see Zend_Feed_Pubsubhubbub
+ */
+// require_once 'Zend/Feed/Pubsubhubbub.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Pubsubhubbub_Publisher
+{
+ /**
+ * An array of URLs for all Hub Servers used by the Publisher, and to
+ * which all topic update notifications will be sent.
+ *
+ * @var array
+ */
+ protected $_hubUrls = array();
+
+ /**
+ * An array of topic (Atom or RSS feed) URLs which have been updated and
+ * whose updated status will be notified to all Hub Servers.
+ *
+ * @var array
+ */
+ protected $_updatedTopicUrls = array();
+
+ /**
+ * An array of any errors including keys for 'response', 'hubUrl'.
+ * The response is the actual Zend_Http_Response object.
+ *
+ * @var array
+ */
+ protected $_errors = array();
+
+ /**
+ * An array of topic (Atom or RSS feed) URLs which have been updated and
+ * whose updated status will be notified to all Hub Servers.
+ *
+ * @var array
+ */
+ protected $_parameters = array();
+
+ /**
+ * Constructor; accepts an array or Zend_Config instance to preset
+ * options for the Publisher without calling all supported setter
+ * methods in turn.
+ *
+ * @param array|Zend_Config $options Options array or Zend_Config instance
+ * @return void
+ */
+ public function __construct($config = null)
+ {
+ if (!is_null($config)) {
+ $this->setConfig($config);
+ }
+ }
+
+ /**
+ * Process any injected configuration options
+ *
+ * @param array|Zend_Config $options Options array or Zend_Config instance
+ * @return Zend_Feed_Pubsubhubbub_Publisher
+ */
+ public function setConfig($config)
+ {
+ if ($config instanceof Zend_Config) {
+ $config = $config->toArray();
+ } elseif (!is_array($config)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Array or Zend_Config object'
+ . 'expected, got ' . gettype($config));
+ }
+ if (array_key_exists('hubUrls', $config)) {
+ $this->addHubUrls($config['hubUrls']);
+ }
+ if (array_key_exists('updatedTopicUrls', $config)) {
+ $this->addUpdatedTopicUrls($config['updatedTopicUrls']);
+ }
+ if (array_key_exists('parameters', $config)) {
+ $this->setParameters($config['parameters']);
+ }
+ return $this;
+ }
+
+ /**
+ * Add a Hub Server URL supported by Publisher
+ *
+ * @param string $url
+ * @return Zend_Feed_Pubsubhubbub_Publisher
+ */
+ public function addHubUrl($url)
+ {
+ if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "url"'
+ .' of "' . $url . '" must be a non-empty string and a valid'
+ .'URL');
+ }
+ $this->_hubUrls[] = $url;
+ return $this;
+ }
+
+ /**
+ * Add an array of Hub Server URLs supported by Publisher
+ *
+ * @param array $urls
+ * @return Zend_Feed_Pubsubhubbub_Publisher
+ */
+ public function addHubUrls(array $urls)
+ {
+ foreach ($urls as $url) {
+ $this->addHubUrl($url);
+ }
+ return $this;
+ }
+
+ /**
+ * Remove a Hub Server URL
+ *
+ * @param string $url
+ * @return Zend_Feed_Pubsubhubbub_Publisher
+ */
+ public function removeHubUrl($url)
+ {
+ if (!in_array($url, $this->getHubUrls())) {
+ return $this;
+ }
+ $key = array_search($url, $this->_hubUrls);
+ unset($this->_hubUrls[$key]);
+ return $this;
+ }
+
+ /**
+ * Return an array of unique Hub Server URLs currently available
+ *
+ * @return array
+ */
+ public function getHubUrls()
+ {
+ $this->_hubUrls = array_unique($this->_hubUrls);
+ return $this->_hubUrls;
+ }
+
+ /**
+ * Add a URL to a topic (Atom or RSS feed) which has been updated
+ *
+ * @param string $url
+ * @return Zend_Feed_Pubsubhubbub_Publisher
+ */
+ public function addUpdatedTopicUrl($url)
+ {
+ if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "url"'
+ .' of "' . $url . '" must be a non-empty string and a valid'
+ .'URL');
+ }
+ $this->_updatedTopicUrls[] = $url;
+ return $this;
+ }
+
+ /**
+ * Add an array of Topic URLs which have been updated
+ *
+ * @param array $urls
+ * @return Zend_Feed_Pubsubhubbub_Publisher
+ */
+ public function addUpdatedTopicUrls(array $urls)
+ {
+ foreach ($urls as $url) {
+ $this->addUpdatedTopicUrl($url);
+ }
+ return $this;
+ }
+
+ /**
+ * Remove an updated topic URL
+ *
+ * @param string $url
+ * @return Zend_Feed_Pubsubhubbub_Publisher
+ */
+ public function removeUpdatedTopicUrl($url)
+ {
+ if (!in_array($url, $this->getUpdatedTopicUrls())) {
+ return $this;
+ }
+ $key = array_search($url, $this->_updatedTopicUrls);
+ unset($this->_updatedTopicUrls[$key]);
+ return $this;
+ }
+
+ /**
+ * Return an array of unique updated topic URLs currently available
+ *
+ * @return array
+ */
+ public function getUpdatedTopicUrls()
+ {
+ $this->_updatedTopicUrls = array_unique($this->_updatedTopicUrls);
+ return $this->_updatedTopicUrls;
+ }
+
+ /**
+ * Notifies a single Hub Server URL of changes
+ *
+ * @param string $url The Hub Server's URL
+ * @return void
+ * @throws Zend_Feed_Pubsubhubbub_Exception Thrown on failure
+ */
+ public function notifyHub($url)
+ {
+ if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "url"'
+ .' of "' . $url . '" must be a non-empty string and a valid'
+ .'URL');
+ }
+ $client = $this->_getHttpClient();
+ $client->setUri($url);
+ $response = $client->request();
+ if ($response->getStatus() !== 204) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Notification to Hub Server '
+ . 'at "' . $url . '" appears to have failed with a status code of "'
+ . $response->getStatus() . '" and message "'
+ . $response->getMessage() . '"');
+ }
+ }
+
+ /**
+ * Notifies all Hub Server URLs of changes
+ *
+ * If a Hub notification fails, certain data will be retained in an
+ * an array retrieved using getErrors(), if a failure occurs for any Hubs
+ * the isSuccess() check will return FALSE. This method is designed not
+ * to needlessly fail with an Exception/Error unless from Zend_Http_Client.
+ *
+ * @return void
+ * @throws Zend_Feed_Pubsubhubbub_Exception Thrown if no hubs attached
+ */
+ public function notifyAll()
+ {
+ $client = $this->_getHttpClient();
+ $hubs = $this->getHubUrls();
+ if (empty($hubs)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('No Hub Server URLs'
+ . ' have been set so no notifcations can be sent');
+ }
+ $this->_errors = array();
+ foreach ($hubs as $url) {
+ $client->setUri($url);
+ $response = $client->request();
+ if ($response->getStatus() !== 204) {
+ $this->_errors[] = array(
+ 'response' => $response,
+ 'hubUrl' => $url
+ );
+ }
+ }
+ }
+
+ /**
+ * Add an optional parameter to the update notification requests
+ *
+ * @param string $name
+ * @param string|null $value
+ * @return Zend_Feed_Pubsubhubbub_Publisher
+ */
+ public function setParameter($name, $value = null)
+ {
+ if (is_array($name)) {
+ $this->setParameters($name);
+ return $this;
+ }
+ if (empty($name) || !is_string($name)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "name"'
+ .' of "' . $name . '" must be a non-empty string');
+ }
+ if ($value === null) {
+ $this->removeParameter($name);
+ return $this;
+ }
+ if (empty($value) || (!is_string($value) && !is_null($value))) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "value"'
+ .' of "' . $value . '" must be a non-empty string');
+ }
+ $this->_parameters[$name] = $value;
+ return $this;
+ }
+
+ /**
+ * Add an optional parameter to the update notification requests
+ *
+ * @param array $parameters
+ * @return Zend_Feed_Pubsubhubbub_Publisher
+ */
+ public function setParameters(array $parameters)
+ {
+ foreach ($parameters as $name => $value) {
+ $this->setParameter($name, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * Remove an optional parameter for the notification requests
+ *
+ * @param string $name
+ * @return Zend_Feed_Pubsubhubbub_Publisher
+ */
+ public function removeParameter($name)
+ {
+ if (empty($name) || !is_string($name)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "name"'
+ .' of "' . $name . '" must be a non-empty string');
+ }
+ if (array_key_exists($name, $this->_parameters)) {
+ unset($this->_parameters[$name]);
+ }
+ return $this;
+ }
+
+ /**
+ * Return an array of optional parameters for notification requests
+ *
+ * @return array
+ */
+ public function getParameters()
+ {
+ return $this->_parameters;
+ }
+
+ /**
+ * Returns a boolean indicator of whether the notifications to Hub
+ * Servers were ALL successful. If even one failed, FALSE is returned.
+ *
+ * @return bool
+ */
+ public function isSuccess()
+ {
+ if (count($this->_errors) > 0) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return an array of errors met from any failures, including keys:
+ * 'response' => the Zend_Http_Response object from the failure
+ * 'hubUrl' => the URL of the Hub Server whose notification failed
+ *
+ * @return array
+ */
+ public function getErrors()
+ {
+ return $this->_errors;
+ }
+
+ /**
+ * Get a basic prepared HTTP client for use
+ *
+ * @return Zend_Http_Client
+ */
+ protected function _getHttpClient()
+ {
+ $client = Zend_Feed_Pubsubhubbub::getHttpClient();
+ $client->setMethod(Zend_Http_Client::POST);
+ $client->setConfig(array(
+ 'useragent' => 'Zend_Feed_Pubsubhubbub_Publisher/' . Zend_Version::VERSION,
+ ));
+ $params = array();
+ $params[] = 'hub.mode=publish';
+ $topics = $this->getUpdatedTopicUrls();
+ if (empty($topics)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('No updated topic URLs'
+ . ' have been set');
+ }
+ foreach ($topics as $topicUrl) {
+ $params[] = 'hub.url=' . urlencode($topicUrl);
+ }
+ $optParams = $this->getParameters();
+ foreach ($optParams as $name => $value) {
+ $params[] = urlencode($name) . '=' . urlencode($value);
+ }
+ $paramString = implode('&', $params);
+ $client->setRawData($paramString);
+ return $client;
+ }
+}
diff --git a/libs/Zend/Feed/Pubsubhubbub/Subscriber.php b/libs/Zend/Feed/Pubsubhubbub/Subscriber.php
new file mode 100644
index 0000000000..9921bce594
--- /dev/null
+++ b/libs/Zend/Feed/Pubsubhubbub/Subscriber.php
@@ -0,0 +1,856 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @see Zend_Feed_Pubsubhubbub
+ */
+// require_once 'Zend/Feed/Pubsubhubbub.php';
+
+/**
+ * @see Zend_Date
+ */
+// require_once 'Zend/Date.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Pubsubhubbub_Subscriber
+{
+ /**
+ * An array of URLs for all Hub Servers to subscribe/unsubscribe.
+ *
+ * @var array
+ */
+ protected $_hubUrls = array();
+
+ /**
+ * An array of optional parameters to be included in any
+ * (un)subscribe requests.
+ *
+ * @var array
+ */
+ protected $_parameters = array();
+
+ /**
+ * The URL of the topic (Rss or Atom feed) which is the subject of
+ * our current intent to subscribe to/unsubscribe from updates from
+ * the currently configured Hub Servers.
+ *
+ * @var string
+ */
+ protected $_topicUrl = '';
+
+ /**
+ * The URL Hub Servers must use when communicating with this Subscriber
+ *
+ * @var string
+ */
+ protected $_callbackUrl = '';
+
+ /**
+ * The number of seconds for which the subscriber would like to have the
+ * subscription active. Defaults to null, i.e. not sent, to setup a
+ * permanent subscription if possible.
+ *
+ * @var int
+ */
+ protected $_leaseSeconds = null;
+
+ /**
+ * The preferred verification mode (sync or async). By default, this
+ * Subscriber prefers synchronous verification, but is considered
+ * desireable to support asynchronous verification if possible.
+ *
+ * Zend_Feed_Pubsubhubbub_Subscriber will always send both modes, whose
+ * order of occurance in the parameter list determines this preference.
+ *
+ * @var string
+ */
+ protected $_preferredVerificationMode
+ = Zend_Feed_Pubsubhubbub::VERIFICATION_MODE_SYNC;
+
+ /**
+ * An array of any errors including keys for 'response', 'hubUrl'.
+ * The response is the actual Zend_Http_Response object.
+ *
+ * @var array
+ */
+ protected $_errors = array();
+
+ /**
+ * An array of Hub Server URLs for Hubs operating at this time in
+ * asynchronous verification mode.
+ *
+ * @var array
+ */
+ protected $_asyncHubs = array();
+
+ /**
+ * An instance of Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface used to background
+ * save any verification tokens associated with a subscription or other.
+ *
+ * @var Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface
+ */
+ protected $_storage = null;
+
+ /**
+ * An array of authentication credentials for HTTP Basic Authentication
+ * if required by specific Hubs. The array is indexed by Hub Endpoint URI
+ * and the value is a simple array of the username and password to apply.
+ *
+ * @var array
+ */
+ protected $_authentications = array();
+
+ /**
+ * Tells the Subscriber to append any subscription identifier to the path
+ * of the base Callback URL. E.g. an identifier "subkey1" would be added
+ * to the callback URL "http://www.example.com/callback" to create a subscription
+ * specific Callback URL of "http://www.example.com/callback/subkey1".
+ *
+ * This is required for all Hubs using the Pubsubhubbub 0.1 Specification.
+ * It should be manually intercepted and passed to the Callback class using
+ * Zend_Feed_Pubsubhubbub_Subscriber_Callback::setSubscriptionKey(). Will
+ * require a route in the form "callback/:subkey" to allow the parameter be
+ * retrieved from an action using the Zend_Controller_Action::_getParam()
+ * method.
+ *
+ * @var string
+ */
+ protected $_usePathParameter = false;
+
+ /**
+ * Constructor; accepts an array or Zend_Config instance to preset
+ * options for the Subscriber without calling all supported setter
+ * methods in turn.
+ *
+ * @param array|Zend_Config $options Options array or Zend_Config instance
+ * @return void
+ */
+ public function __construct($config = null)
+ {
+ if (!is_null($config)) {
+ $this->setConfig($config);
+ }
+ }
+
+ /**
+ * Process any injected configuration options
+ *
+ * @param array|Zend_Config $options Options array or Zend_Config instance
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function setConfig($config)
+ {
+ if ($config instanceof Zend_Config) {
+ $config = $config->toArray();
+ } elseif (!is_array($config)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Array or Zend_Config object'
+ . ' expected, got ' . gettype($config));
+ }
+ if (array_key_exists('hubUrls', $config)) {
+ $this->addHubUrls($config['hubUrls']);
+ }
+ if (array_key_exists('callbackUrl', $config)) {
+ $this->setCallbackUrl($config['callbackUrl']);
+ }
+ if (array_key_exists('topicUrl', $config)) {
+ $this->setTopicUrl($config['topicUrl']);
+ }
+ if (array_key_exists('storage', $config)) {
+ $this->setStorage($config['storage']);
+ }
+ if (array_key_exists('leaseSeconds', $config)) {
+ $this->setLeaseSeconds($config['leaseSeconds']);
+ }
+ if (array_key_exists('parameters', $config)) {
+ $this->setParameters($config['parameters']);
+ }
+ if (array_key_exists('authentications', $config)) {
+ $this->addAuthentications($config['authentications']);
+ }
+ if (array_key_exists('usePathParameter', $config)) {
+ $this->usePathParameter($config['usePathParameter']);
+ }
+ if (array_key_exists('preferredVerificationMode', $config)) {
+ $this->setPreferredVerificationMode(
+ $config['preferredVerificationMode']
+ );
+ }
+ return $this;
+ }
+
+ /**
+ * Set the topic URL (RSS or Atom feed) to which the intended (un)subscribe
+ * event will relate
+ *
+ * @param string $url
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function setTopicUrl($url)
+ {
+ if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "url"'
+ .' of "' . $url . '" must be a non-empty string and a valid'
+ .' URL');
+ }
+ $this->_topicUrl = $url;
+ return $this;
+ }
+
+ /**
+ * Set the topic URL (RSS or Atom feed) to which the intended (un)subscribe
+ * event will relate
+ *
+ * @return string
+ */
+ public function getTopicUrl()
+ {
+ if (empty($this->_topicUrl)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('A valid Topic (RSS or Atom'
+ . ' feed) URL MUST be set before attempting any operation');
+ }
+ return $this->_topicUrl;
+ }
+
+ /**
+ * Set the number of seconds for which any subscription will remain valid
+ *
+ * @param int $seconds
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function setLeaseSeconds($seconds)
+ {
+ $seconds = intval($seconds);
+ if ($seconds <= 0) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Expected lease seconds'
+ . ' must be an integer greater than zero');
+ }
+ $this->_leaseSeconds = $seconds;
+ return $this;
+ }
+
+ /**
+ * Get the number of lease seconds on subscriptions
+ *
+ * @return int
+ */
+ public function getLeaseSeconds()
+ {
+ return $this->_leaseSeconds;
+ }
+
+ /**
+ * Set the callback URL to be used by Hub Servers when communicating with
+ * this Subscriber
+ *
+ * @param string $url
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function setCallbackUrl($url)
+ {
+ if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "url"'
+ . ' of "' . $url . '" must be a non-empty string and a valid'
+ . ' URL');
+ }
+ $this->_callbackUrl = $url;
+ return $this;
+ }
+
+ /**
+ * Get the callback URL to be used by Hub Servers when communicating with
+ * this Subscriber
+ *
+ * @return string
+ */
+ public function getCallbackUrl()
+ {
+ if (empty($this->_callbackUrl)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('A valid Callback URL MUST be'
+ . ' set before attempting any operation');
+ }
+ return $this->_callbackUrl;
+ }
+
+ /**
+ * Set preferred verification mode (sync or async). By default, this
+ * Subscriber prefers synchronous verification, but does support
+ * asynchronous if that's the Hub Server's utilised mode.
+ *
+ * Zend_Feed_Pubsubhubbub_Subscriber will always send both modes, whose
+ * order of occurance in the parameter list determines this preference.
+ *
+ * @param string $mode Should be 'sync' or 'async'
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function setPreferredVerificationMode($mode)
+ {
+ if ($mode !== Zend_Feed_Pubsubhubbub::VERIFICATION_MODE_SYNC
+ && $mode !== Zend_Feed_Pubsubhubbub::VERIFICATION_MODE_ASYNC) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid preferred'
+ . ' mode specified: "' . $mode . '" but should be one of'
+ . ' Zend_Feed_Pubsubhubbub::VERIFICATION_MODE_SYNC or'
+ . ' Zend_Feed_Pubsubhubbub::VERIFICATION_MODE_ASYNC');
+ }
+ $this->_preferredVerificationMode = $mode;
+ return $this;
+ }
+
+ /**
+ * Get preferred verification mode (sync or async).
+ *
+ * @return string
+ */
+ public function getPreferredVerificationMode()
+ {
+ return $this->_preferredVerificationMode;
+ }
+
+ /**
+ * Add a Hub Server URL supported by Publisher
+ *
+ * @param string $url
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function addHubUrl($url)
+ {
+ if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "url"'
+ . ' of "' . $url . '" must be a non-empty string and a valid'
+ . ' URL');
+ }
+ $this->_hubUrls[] = $url;
+ return $this;
+ }
+
+ /**
+ * Add an array of Hub Server URLs supported by Publisher
+ *
+ * @param array $urls
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function addHubUrls(array $urls)
+ {
+ foreach ($urls as $url) {
+ $this->addHubUrl($url);
+ }
+ return $this;
+ }
+
+ /**
+ * Remove a Hub Server URL
+ *
+ * @param string $url
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function removeHubUrl($url)
+ {
+ if (!in_array($url, $this->getHubUrls())) {
+ return $this;
+ }
+ $key = array_search($url, $this->_hubUrls);
+ unset($this->_hubUrls[$key]);
+ return $this;
+ }
+
+ /**
+ * Return an array of unique Hub Server URLs currently available
+ *
+ * @return array
+ */
+ public function getHubUrls()
+ {
+ $this->_hubUrls = array_unique($this->_hubUrls);
+ return $this->_hubUrls;
+ }
+
+ /**
+ * Add authentication credentials for a given URL
+ *
+ * @param string $url
+ * @param array $authentication
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function addAuthentication($url, array $authentication)
+ {
+ if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "url"'
+ . ' of "' . $url . '" must be a non-empty string and a valid'
+ . ' URL');
+ }
+ $this->_authentications[$url] = $authentication;
+ return $this;
+ }
+
+ /**
+ * Add authentication credentials for hub URLs
+ *
+ * @param array $authentications
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function addAuthentications(array $authentications)
+ {
+ foreach ($authentications as $url => $authentication) {
+ $this->addAuthentication($url, $authentication);
+ }
+ return $this;
+ }
+
+ /**
+ * Get all hub URL authentication credentials
+ *
+ * @return array
+ */
+ public function getAuthentications()
+ {
+ return $this->_authentications;
+ }
+
+ /**
+ * Set flag indicating whether or not to use a path parameter
+ *
+ * @param bool $bool
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function usePathParameter($bool = true)
+ {
+ $this->_usePathParameter = $bool;
+ return $this;
+ }
+
+ /**
+ * Add an optional parameter to the (un)subscribe requests
+ *
+ * @param string $name
+ * @param string|null $value
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function setParameter($name, $value = null)
+ {
+ if (is_array($name)) {
+ $this->setParameters($name);
+ return $this;
+ }
+ if (empty($name) || !is_string($name)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "name"'
+ . ' of "' . $name . '" must be a non-empty string');
+ }
+ if ($value === null) {
+ $this->removeParameter($name);
+ return $this;
+ }
+ if (empty($value) || (!is_string($value) && !is_null($value))) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "value"'
+ . ' of "' . $value . '" must be a non-empty string');
+ }
+ $this->_parameters[$name] = $value;
+ return $this;
+ }
+
+ /**
+ * Add an optional parameter to the (un)subscribe requests
+ *
+ * @param string $name
+ * @param string|null $value
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function setParameters(array $parameters)
+ {
+ foreach ($parameters as $name => $value) {
+ $this->setParameter($name, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * Remove an optional parameter for the (un)subscribe requests
+ *
+ * @param string $name
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function removeParameter($name)
+ {
+ if (empty($name) || !is_string($name)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid parameter "name"'
+ . ' of "' . $name . '" must be a non-empty string');
+ }
+ if (array_key_exists($name, $this->_parameters)) {
+ unset($this->_parameters[$name]);
+ }
+ return $this;
+ }
+
+ /**
+ * Return an array of optional parameters for (un)subscribe requests
+ *
+ * @return array
+ */
+ public function getParameters()
+ {
+ return $this->_parameters;
+ }
+
+ /**
+ * Sets an instance of Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface used to background
+ * save any verification tokens associated with a subscription or other.
+ *
+ * @param Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface $storage
+ * @return Zend_Feed_Pubsubhubbub_Subscriber
+ */
+ public function setStorage(Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface $storage)
+ {
+ $this->_storage = $storage;
+ return $this;
+ }
+
+ /**
+ * Gets an instance of Zend_Feed_Pubsubhubbub_Storage_StorageInterface used
+ * to background save any verification tokens associated with a subscription
+ * or other.
+ *
+ * @return Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface
+ */
+ public function getStorage()
+ {
+ if ($this->_storage === null) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('No storage vehicle '
+ . 'has been set.');
+ }
+ return $this->_storage;
+ }
+
+ /**
+ * Subscribe to one or more Hub Servers using the stored Hub URLs
+ * for the given Topic URL (RSS or Atom feed)
+ *
+ * @return void
+ */
+ public function subscribeAll()
+ {
+ return $this->_doRequest('subscribe');
+ }
+
+ /**
+ * Unsubscribe from one or more Hub Servers using the stored Hub URLs
+ * for the given Topic URL (RSS or Atom feed)
+ *
+ * @return void
+ */
+ public function unsubscribeAll()
+ {
+ return $this->_doRequest('unsubscribe');
+ }
+
+ /**
+ * Returns a boolean indicator of whether the notifications to Hub
+ * Servers were ALL successful. If even one failed, FALSE is returned.
+ *
+ * @return bool
+ */
+ public function isSuccess()
+ {
+ if (count($this->_errors) > 0) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return an array of errors met from any failures, including keys:
+ * 'response' => the Zend_Http_Response object from the failure
+ * 'hubUrl' => the URL of the Hub Server whose notification failed
+ *
+ * @return array
+ */
+ public function getErrors()
+ {
+ return $this->_errors;
+ }
+
+ /**
+ * Return an array of Hub Server URLs who returned a response indicating
+ * operation in Asynchronous Verification Mode, i.e. they will not confirm
+ * any (un)subscription immediately but at a later time (Hubs may be
+ * doing this as a batch process when load balancing)
+ *
+ * @return array
+ */
+ public function getAsyncHubs()
+ {
+ return $this->_asyncHubs;
+ }
+
+ /**
+ * Executes an (un)subscribe request
+ *
+ * @param string $mode
+ * @return void
+ */
+ protected function _doRequest($mode)
+ {
+ $client = $this->_getHttpClient();
+ $hubs = $this->getHubUrls();
+ if (empty($hubs)) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('No Hub Server URLs'
+ . ' have been set so no subscriptions can be attempted');
+ }
+ $this->_errors = array();
+ $this->_asyncHubs = array();
+ foreach ($hubs as $url) {
+ if (array_key_exists($url, $this->_authentications)) {
+ $auth = $this->_authentications[$url];
+ $client->setAuth($auth[0], $auth[1]);
+ }
+ $client->setUri($url);
+ $client->setRawData($this->_getRequestParameters($url, $mode));
+ $response = $client->request();
+ if ($response->getStatus() !== 204
+ && $response->getStatus() !== 202
+ ) {
+ $this->_errors[] = array(
+ 'response' => $response,
+ 'hubUrl' => $url,
+ );
+ /**
+ * At first I thought it was needed, but the backend storage will
+ * allow tracking async without any user interference. It's left
+ * here in case the user is interested in knowing what Hubs
+ * are using async verification modes so they may update Models and
+ * move these to asynchronous processes.
+ */
+ } elseif ($response->getStatus() == 202) {
+ $this->_asyncHubs[] = array(
+ 'response' => $response,
+ 'hubUrl' => $url,
+ );
+ }
+ }
+ }
+
+ /**
+ * Get a basic prepared HTTP client for use
+ *
+ * @param string $mode Must be "subscribe" or "unsubscribe"
+ * @return Zend_Http_Client
+ */
+ protected function _getHttpClient()
+ {
+ $client = Zend_Feed_Pubsubhubbub::getHttpClient();
+ $client->setMethod(Zend_Http_Client::POST);
+ $client->setConfig(array('useragent' => 'Zend_Feed_Pubsubhubbub_Subscriber/'
+ . Zend_Version::VERSION));
+ return $client;
+ }
+
+ /**
+ * Return a list of standard protocol/optional parameters for addition to
+ * client's POST body that are specific to the current Hub Server URL
+ *
+ * @param string $hubUrl
+ * @param mode $hubUrl
+ * @return string
+ */
+ protected function _getRequestParameters($hubUrl, $mode)
+ {
+ if (!in_array($mode, array('subscribe', 'unsubscribe'))) {
+ // require_once 'Zend/Feed/Pubsubhubbub/Exception.php';
+ throw new Zend_Feed_Pubsubhubbub_Exception('Invalid mode specified: "'
+ . $mode . '" which should have been "subscribe" or "unsubscribe"');
+ }
+
+ $params = array(
+ 'hub.mode' => $mode,
+ 'hub.topic' => $this->getTopicUrl(),
+ );
+
+ if ($this->getPreferredVerificationMode()
+ == Zend_Feed_Pubsubhubbub::VERIFICATION_MODE_SYNC
+ ) {
+ $vmodes = array(
+ Zend_Feed_Pubsubhubbub::VERIFICATION_MODE_SYNC,
+ Zend_Feed_Pubsubhubbub::VERIFICATION_MODE_ASYNC,
+ );
+ } else {
+ $vmodes = array(
+ Zend_Feed_Pubsubhubbub::VERIFICATION_MODE_ASYNC,
+ Zend_Feed_Pubsubhubbub::VERIFICATION_MODE_SYNC,
+ );
+ }
+ $params['hub.verify'] = array();
+ foreach($vmodes as $vmode) {
+ $params['hub.verify'][] = $vmode;
+ }
+
+ /**
+ * Establish a persistent verify_token and attach key to callback
+ * URL's path/querystring
+ */
+ $key = $this->_generateSubscriptionKey($params, $hubUrl);
+ $token = $this->_generateVerifyToken();
+ $params['hub.verify_token'] = $token;
+
+ // Note: query string only usable with PuSH 0.2 Hubs
+ if (!$this->_usePathParameter) {
+ $params['hub.callback'] = $this->getCallbackUrl()
+ . '?xhub.subscription=' . Zend_Feed_Pubsubhubbub::urlencode($key);
+ } else {
+ $params['hub.callback'] = rtrim($this->getCallbackUrl(), '/')
+ . '/' . Zend_Feed_Pubsubhubbub::urlencode($key);
+ }
+ if ($mode == 'subscribe' && !is_null($this->getLeaseSeconds())) {
+ $params['hub.lease_seconds'] = $this->getLeaseSeconds();
+ }
+
+ // hub.secret not currently supported
+ $optParams = $this->getParameters();
+ foreach ($optParams as $name => $value) {
+ $params[$name] = $value;
+ }
+
+ // store subscription to storage
+ $now = new Zend_Date;
+ $expires = null;
+ if (isset($params['hub.lease_seconds'])) {
+ $expires = $now->add($params['hub.lease_seconds'], Zend_Date::SECOND)
+ ->get('yyyy-MM-dd HH:mm:ss');
+ }
+ $data = array(
+ 'id' => $key,
+ 'topic_url' => $params['hub.topic'],
+ 'hub_url' => $hubUrl,
+ 'created_time' => $now->get('yyyy-MM-dd HH:mm:ss'),
+ 'lease_seconds' => $expires,
+ 'verify_token' => hash('sha256', $params['hub.verify_token']),
+ 'secret' => null,
+ 'expiration_time' => $expires,
+ 'subscription_state' => Zend_Feed_Pubsubhubbub::SUBSCRIPTION_NOTVERIFIED,
+ );
+ $this->getStorage()->setSubscription($data);
+
+ return $this->_toByteValueOrderedString(
+ $this->_urlEncode($params)
+ );
+ }
+
+ /**
+ * Simple helper to generate a verification token used in (un)subscribe
+ * requests to a Hub Server. Follows no particular method, which means
+ * it might be improved/changed in future.
+ *
+ * @param string $hubUrl The Hub Server URL for which this token will apply
+ * @return string
+ */
+ protected function _generateVerifyToken()
+ {
+ if (!empty($this->_testStaticToken)) {
+ return $this->_testStaticToken;
+ }
+ return uniqid(rand(), true) . time();
+ }
+
+ /**
+ * Simple helper to generate a verification token used in (un)subscribe
+ * requests to a Hub Server.
+ *
+ * @param string $hubUrl The Hub Server URL for which this token will apply
+ * @return string
+ */
+ protected function _generateSubscriptionKey(array $params, $hubUrl)
+ {
+ $keyBase = $params['hub.topic'] . $hubUrl;
+ $key = md5($keyBase);
+ return $key;
+ }
+
+ /**
+ * URL Encode an array of parameters
+ *
+ * @param array $params
+ * @return array
+ */
+ protected function _urlEncode(array $params)
+ {
+ $encoded = array();
+ foreach ($params as $key => $value) {
+ if (is_array($value)) {
+ $ekey = Zend_Feed_Pubsubhubbub::urlencode($key);
+ $encoded[$ekey] = array();
+ foreach ($value as $duplicateKey) {
+ $encoded[$ekey][]
+ = Zend_Feed_Pubsubhubbub::urlencode($duplicateKey);
+ }
+ } else {
+ $encoded[Zend_Feed_Pubsubhubbub::urlencode($key)]
+ = Zend_Feed_Pubsubhubbub::urlencode($value);
+ }
+ }
+ return $encoded;
+ }
+
+ /**
+ * Order outgoing parameters
+ *
+ * @param array $params
+ * @return array
+ */
+ protected function _toByteValueOrderedString(array $params)
+ {
+ $return = array();
+ uksort($params, 'strnatcmp');
+ foreach ($params as $key => $value) {
+ if (is_array($value)) {
+ foreach ($value as $keyduplicate) {
+ $return[] = $key . '=' . $keyduplicate;
+ }
+ } else {
+ $return[] = $key . '=' . $value;
+ }
+ }
+ return implode('&', $return);
+ }
+
+ /**
+ * This is STRICTLY for testing purposes only...
+ */
+ protected $_testStaticToken = null;
+
+ final public function setTestStaticToken($token)
+ {
+ $this->_testStaticToken = (string) $token;
+ }
+}
diff --git a/libs/Zend/Feed/Pubsubhubbub/Subscriber/Callback.php b/libs/Zend/Feed/Pubsubhubbub/Subscriber/Callback.php
new file mode 100644
index 0000000000..1f42375839
--- /dev/null
+++ b/libs/Zend/Feed/Pubsubhubbub/Subscriber/Callback.php
@@ -0,0 +1,328 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @see Zend_Feed_Pubsubhubbub
+ */
+// require_once 'Zend/Feed/Pubsubhubbub.php';
+
+/**
+ * @see Zend_Feed_Pubsubhubbub
+ */
+// require_once 'Zend/Feed/Pubsubhubbub/CallbackAbstract.php';
+
+/**
+ * @see Zend_Feed_Reader
+ */
+// require_once 'Zend/Feed/Reader.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Pubsubhubbub
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Pubsubhubbub_Subscriber_Callback
+ extends Zend_Feed_Pubsubhubbub_CallbackAbstract
+{
+ /**
+ * Contains the content of any feeds sent as updates to the Callback URL
+ *
+ * @var string
+ */
+ protected $_feedUpdate = null;
+
+ /**
+ * Holds a manually set subscription key (i.e. identifies a unique
+ * subscription) which is typical when it is not passed in the query string
+ * but is part of the Callback URL path, requiring manual retrieval e.g.
+ * using a route and the Zend_Controller_Action::_getParam() method.
+ *
+ * @var string
+ */
+ protected $_subscriptionKey = null;
+
+ /**
+ * After verification, this is set to the verified subscription's data.
+ *
+ * @var array
+ */
+ protected $_currentSubscriptionData = null;
+
+ /**
+ * Set a subscription key to use for the current callback request manually.
+ * Required if usePathParameter is enabled for the Subscriber.
+ *
+ * @param string $key
+ * @return Zend_Feed_Pubsubhubbub_Subscriber_Callback
+ */
+ public function setSubscriptionKey($key)
+ {
+ $this->_subscriptionKey = $key;
+ return $this;
+ }
+
+ /**
+ * Handle any callback from a Hub Server responding to a subscription or
+ * unsubscription request. This should be the Hub Server confirming the
+ * the request prior to taking action on it.
+ *
+ * @param array $httpGetData GET data if available and not in $_GET
+ * @param bool $sendResponseNow Whether to send response now or when asked
+ * @return void
+ */
+ public function handle(array $httpGetData = null, $sendResponseNow = false)
+ {
+ if ($httpGetData === null) {
+ $httpGetData = $_GET;
+ }
+
+ /**
+ * Handle any feed updates (sorry for the mess :P)
+ *
+ * This DOES NOT attempt to process a feed update. Feed updates
+ * SHOULD be validated/processed by an asynchronous process so as
+ * to avoid holding up responses to the Hub.
+ */
+ if (strtolower($_SERVER['REQUEST_METHOD']) == 'post'
+ && $this->_hasValidVerifyToken(null, false)
+ && ($this->_getHeader('Content-Type') == 'application/atom+xml'
+ || $this->_getHeader('Content-Type') == 'application/rss+xml'
+ || $this->_getHeader('Content-Type') == 'application/xml'
+ || $this->_getHeader('Content-Type') == 'text/xml'
+ || $this->_getHeader('Content-Type') == 'application/rdf+xml')
+ ) {
+ $this->setFeedUpdate($this->_getRawBody());
+ $this->getHttpResponse()
+ ->setHeader('X-Hub-On-Behalf-Of', $this->getSubscriberCount());
+ /**
+ * Handle any (un)subscribe confirmation requests
+ */
+ } elseif ($this->isValidHubVerification($httpGetData)) {
+ $data = $this->_currentSubscriptionData;
+ $this->getHttpResponse()->setBody($httpGetData['hub_challenge']);
+ $data['subscription_state'] = Zend_Feed_Pubsubhubbub::SUBSCRIPTION_VERIFIED;
+ if (isset($httpGetData['hub_lease_seconds'])) {
+ $data['lease_seconds'] = $httpGetData['hub_lease_seconds'];
+ }
+ $this->getStorage()->setSubscription($data);
+ /**
+ * Hey, C'mon! We tried everything else!
+ */
+ } else {
+ $this->getHttpResponse()->setHttpResponseCode(404);
+ }
+ if ($sendResponseNow) {
+ $this->sendResponse();
+ }
+ }
+
+ /**
+ * Checks validity of the request simply by making a quick pass and
+ * confirming the presence of all REQUIRED parameters.
+ *
+ * @param array $httpGetData
+ * @return bool
+ */
+ public function isValidHubVerification(array $httpGetData)
+ {
+ /**
+ * As per the specification, the hub.verify_token is OPTIONAL. This
+ * implementation of Pubsubhubbub considers it REQUIRED and will
+ * always send a hub.verify_token parameter to be echoed back
+ * by the Hub Server. Therefore, its absence is considered invalid.
+ */
+ if (strtolower($_SERVER['REQUEST_METHOD']) !== 'get') {
+ return false;
+ }
+ $required = array(
+ 'hub_mode',
+ 'hub_topic',
+ 'hub_challenge',
+ 'hub_verify_token',
+ );
+ foreach ($required as $key) {
+ if (!array_key_exists($key, $httpGetData)) {
+ return false;
+ }
+ }
+ if ($httpGetData['hub_mode'] !== 'subscribe'
+ && $httpGetData['hub_mode'] !== 'unsubscribe'
+ ) {
+ return false;
+ }
+ if ($httpGetData['hub_mode'] == 'subscribe'
+ && !array_key_exists('hub_lease_seconds', $httpGetData)
+ ) {
+ return false;
+ }
+ if (!Zend_Uri::check($httpGetData['hub_topic'])) {
+ return false;
+ }
+
+ /**
+ * Attempt to retrieve any Verification Token Key attached to Callback
+ * URL's path by our Subscriber implementation
+ */
+ if (!$this->_hasValidVerifyToken($httpGetData)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Sets a newly received feed (Atom/RSS) sent by a Hub as an update to a
+ * Topic we've subscribed to.
+ *
+ * @param string $feed
+ * @return Zend_Feed_Pubsubhubbub_Subscriber_Callback
+ */
+ public function setFeedUpdate($feed)
+ {
+ $this->_feedUpdate = $feed;
+ return $this;
+ }
+
+ /**
+ * Check if any newly received feed (Atom/RSS) update was received
+ *
+ * @return bool
+ */
+ public function hasFeedUpdate()
+ {
+ if (is_null($this->_feedUpdate)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Gets a newly received feed (Atom/RSS) sent by a Hub as an update to a
+ * Topic we've subscribed to.
+ *
+ * @return string
+ */
+ public function getFeedUpdate()
+ {
+ return $this->_feedUpdate;
+ }
+
+ /**
+ * Check for a valid verify_token. By default attempts to compare values
+ * with that sent from Hub, otherwise merely ascertains its existence.
+ *
+ * @param array $httpGetData
+ * @param bool $checkValue
+ * @return bool
+ */
+ protected function _hasValidVerifyToken(array $httpGetData = null, $checkValue = true)
+ {
+ $verifyTokenKey = $this->_detectVerifyTokenKey($httpGetData);
+ if (empty($verifyTokenKey)) {
+ return false;
+ }
+ $verifyTokenExists = $this->getStorage()->hasSubscription($verifyTokenKey);
+ if (!$verifyTokenExists) {
+ return false;
+ }
+ if ($checkValue) {
+ $data = $this->getStorage()->getSubscription($verifyTokenKey);
+ $verifyToken = $data['verify_token'];
+ if ($verifyToken !== hash('sha256', $httpGetData['hub_verify_token'])) {
+ return false;
+ }
+ $this->_currentSubscriptionData = $data;
+ return true;
+ }
+ return true;
+ }
+
+ /**
+ * Attempt to detect the verification token key. This would be passed in
+ * the Callback URL (which we are handling with this class!) as a URI
+ * path part (the last part by convention).
+ *
+ * @param null|array $httpGetData
+ * @return false|string
+ */
+ protected function _detectVerifyTokenKey(array $httpGetData = null)
+ {
+ /**
+ * Available when sub keys encoding in Callback URL path
+ */
+ if (isset($this->_subscriptionKey)) {
+ return $this->_subscriptionKey;
+ }
+
+ /**
+ * Available only if allowed by PuSH 0.2 Hubs
+ */
+ if (is_array($httpGetData)
+ && isset($httpGetData['xhub_subscription'])
+ ) {
+ return $httpGetData['xhub_subscription'];
+ }
+
+ /**
+ * Available (possibly) if corrupted in transit and not part of $_GET
+ */
+ $params = $this->_parseQueryString();
+ if (isset($params['xhub.subscription'])) {
+ return rawurldecode($params['xhub.subscription']);
+ }
+
+ return false;
+ }
+
+ /**
+ * Build an array of Query String parameters.
+ * This bypasses $_GET which munges parameter names and cannot accept
+ * multiple parameters with the same key.
+ *
+ * @return array|void
+ */
+ protected function _parseQueryString()
+ {
+ $params = array();
+ $queryString = '';
+ if (isset($_SERVER['QUERY_STRING'])) {
+ $queryString = $_SERVER['QUERY_STRING'];
+ }
+ if (empty($queryString)) {
+ return array();
+ }
+ $parts = explode('&', $queryString);
+ foreach ($parts as $kvpair) {
+ $pair = explode('=', $kvpair);
+ $key = rawurldecode($pair[0]);
+ $value = rawurldecode($pair[1]);
+ if (isset($params[$key])) {
+ if (is_array($params[$key])) {
+ $params[$key][] = $value;
+ } else {
+ $params[$key] = array($params[$key], $value);
+ }
+ } else {
+ $params[$key] = $value;
+ }
+ }
+ return $params;
+ }
+}
diff --git a/libs/Zend/Feed/Reader.php b/libs/Zend/Feed/Reader.php
index ced12cf7c7..26bf661cdf 100644
--- a/libs/Zend/Feed/Reader.php
+++ b/libs/Zend/Feed/Reader.php
@@ -14,49 +14,55 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Reader.php 17391 2009-08-05 11:27:52Z padraic $
+ * @version $Id: Reader.php 22093 2010-05-04 12:55:06Z padraic $
*/
/**
* @see Zend_Feed
*/
-require_once 'Zend/Feed.php';
+// require_once 'Zend/Feed.php';
/**
* @see Zend_Feed_Reader_Feed_Rss
*/
-require_once 'Zend/Feed/Reader/Feed/Rss.php';
+// require_once 'Zend/Feed/Reader/Feed/Rss.php';
/**
* @see Zend_Feed_Reader_Feed_Atom
*/
-require_once 'Zend/Feed/Reader/Feed/Atom.php';
+// require_once 'Zend/Feed/Reader/Feed/Atom.php';
+
+/**
+ * @see Zend_Feed_Reader_FeedSet
+ */
+// require_once 'Zend/Feed/Reader/FeedSet.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Reader
{
- /**
- * Namespace constants
- */
- const NAMESPACE_ATOM_03 = 'http://purl.org/atom/ns#';
+ /**
+ * Namespace constants
+ */
+ const NAMESPACE_ATOM_03 = 'http://purl.org/atom/ns#';
const NAMESPACE_ATOM_10 = 'http://www.w3.org/2005/Atom';
const NAMESPACE_RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
const NAMESPACE_RSS_090 = 'http://my.netscape.com/rdf/simple/0.9/';
const NAMESPACE_RSS_10 = 'http://purl.org/rss/1.0/';
/**
- * Feed type constants
- */
- const TYPE_ANY = 'any';
- const TYPE_ATOM_03 = 'atom-03';
+ * Feed type constants
+ */
+ const TYPE_ANY = 'any';
+ const TYPE_ATOM_03 = 'atom-03';
const TYPE_ATOM_10 = 'atom-10';
+ const TYPE_ATOM_10_ENTRY = 'atom-10-entry';
const TYPE_ATOM_ANY = 'atom';
const TYPE_RSS_090 = 'rss-090';
const TYPE_RSS_091 = 'rss-091';
@@ -161,7 +167,7 @@ class Zend_Feed_Reader
/**
* @see Zend_Http_Client
*/
- require_once 'Zend/Http/Client.php';
+ // require_once 'Zend/Http/Client.php';
self::$_httpClient = new Zend_Http_Client();
}
@@ -208,13 +214,13 @@ class Zend_Feed_Reader
}
/**
- * Import a feed by providing a URL
- *
- * @param string $url The URL to the feed
+ * Import a feed by providing a URL
+ *
+ * @param string $url The URL to the feed
* @param string $etag OPTIONAL Last received ETag for this resource
* @param string $lastModified OPTIONAL Last-Modified value for this resource
- * @return Zend_Feed_Reader_Feed_Interface
- */
+ * @return Zend_Feed_Reader_FeedInterface
+ */
public static function import($uri, $etag = null, $lastModified = null)
{
$cache = self::getCache();
@@ -245,7 +251,7 @@ class Zend_Feed_Reader
}
$response = $client->request('GET');
if ($response->getStatus() !== 200 && $response->getStatus() !== 304) {
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Feed failed to load, got response code ' . $response->getStatus());
}
if ($response->getStatus() == 304) {
@@ -268,7 +274,7 @@ class Zend_Feed_Reader
}
$response = $client->request('GET');
if ($response->getStatus() !== 200) {
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Feed failed to load, got response code ' . $response->getStatus());
}
$responseXml = $response->getBody();
@@ -277,10 +283,12 @@ class Zend_Feed_Reader
} else {
$response = $client->request('GET');
if ($response->getStatus() !== 200) {
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Feed failed to load, got response code ' . $response->getStatus());
}
- return self::importString($response->getBody());
+ $reader = self::importString($response->getBody());
+ $reader->setOriginalSourceUri($uri);
+ return $reader;
}
}
@@ -288,8 +296,8 @@ class Zend_Feed_Reader
* Import a feed by providing a Zend_Feed_Abstract object
*
* @param Zend_Feed_Abstract $feed A fully instantiated Zend_Feed object
- * @return Zend_Feed_Reader_Feed_Interface
- */
+ * @return Zend_Feed_Reader_FeedInterface
+ */
public static function importFeed(Zend_Feed_Abstract $feed)
{
$dom = $feed->getDOM()->ownerDocument;
@@ -298,7 +306,7 @@ class Zend_Feed_Reader
if (substr($type, 0, 3) == 'rss') {
$reader = new Zend_Feed_Reader_Feed_Rss($dom, $type);
} else {
- $reader = new Zend_Feed_Reader_Feed_Atom($dom, $type);
+ $reader = new Zend_Feed_Reader_Feed_Atom($dom, $type);
}
return $reader;
@@ -308,7 +316,7 @@ class Zend_Feed_Reader
* Import a feed froma string
*
* @param string $string
- * @return Zend_Feed_Reader_Feed_Interface
+ * @return Zend_Feed_Reader_FeedInterface
*/
public static function importString($string)
{
@@ -321,12 +329,12 @@ class Zend_Feed_Reader
// Build error message
$error = libxml_get_last_error();
if ($error && $error->message) {
- $errormsg = "DOMDocument cannot parse XML: {$error->message}";
+ $errormsg = "DOMDocument cannot parse XML: {$error->message}";
} else {
- $errormsg = "DOMDocument cannot parse XML: Please check the XML document's validity";
+ $errormsg = "DOMDocument cannot parse XML: Please check the XML document's validity";
}
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception($errormsg);
}
@@ -336,8 +344,14 @@ class Zend_Feed_Reader
if (substr($type, 0, 3) == 'rss') {
$reader = new Zend_Feed_Reader_Feed_Rss($dom, $type);
+ } elseif (substr($type, 8, 5) == 'entry') {
+ $reader = new Zend_Feed_Reader_Entry_Atom($dom->documentElement, 0, Zend_Feed_Reader::TYPE_ATOM_10);
+ } elseif (substr($type, 0, 4) == 'atom') {
+ $reader = new Zend_Feed_Reader_Feed_Atom($dom, $type);
} else {
- $reader = new Zend_Feed_Reader_Feed_Atom($dom, $type);
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('The URI used does not point to a '
+ . 'valid Atom, RSS or RDF feed that Zend_Feed_Reader can parse.');
}
return $reader;
}
@@ -358,7 +372,7 @@ class Zend_Feed_Reader
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception("File could not be loaded: $php_errormsg");
}
return self::importString($feed);
@@ -374,62 +388,48 @@ class Zend_Feed_Reader
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception("Failed to access $uri, got response code " . $response->getStatus());
}
$responseHtml = $response->getBody();
- @ini_set('track_errors', 1);
+ $libxml_errflag = libxml_use_internal_errors(true);
$dom = new DOMDocument;
- $status = @$dom->loadHTML($responseHtml);
- @ini_restore('track_errors');
+ $status = $dom->loadHTML($responseHtml);
+ libxml_use_internal_errors($libxml_errflag);
if (!$status) {
- if (!isset($php_errormsg)) {
- if (function_exists('xdebug_is_enabled')) {
- $php_errormsg = '(error message not available, when XDebug is running)';
- } else {
- $php_errormsg = '(error message not available)';
- }
+ // Build error message
+ $error = libxml_get_last_error();
+ if ($error && $error->message) {
+ $errormsg = "DOMDocument cannot parse HTML: {$error->message}";
+ } else {
+ $errormsg = "DOMDocument cannot parse HTML: Please check the XML document's validity";
}
- require_once 'Zend/Feed/Exception.php';
- throw new Zend_Feed_Exception("DOMDocument cannot parse XML: $php_errormsg");
+
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception($errormsg);
}
- $feedLinks = new stdClass;
+ $feedSet = new Zend_Feed_Reader_FeedSet;
$links = $dom->getElementsByTagName('link');
- foreach ($links as $link) {
- if (strtolower($link->getAttribute('rel')) !== 'alternate'
- || !$link->getAttribute('type') || !$link->getAttribute('href')) {
- continue;
- }
- if (!isset($feedLinks->rss) && $link->getAttribute('type') == 'application/rss+xml') {
- $feedLinks->rss = $link->getAttribute('href');
- } elseif(!isset($feedLinks->atom) && $link->getAttribute('type') == 'application/atom+xml') {
- $feedLinks->atom = $link->getAttribute('href');
- } elseif(!isset($feedLinks->rdf) && $link->getAttribute('type') == 'application/rdf+xml') {
- $feedLinks->rdf = $link->getAttribute('href');
- }
- if (isset($feedLinks->rss) && isset($feedLinks->atom) && isset($feedLinks->rdf)) {
- break;
- }
- }
- return $feedLinks;
+ $feedSet->addLinks($links, $uri);
+ return $feedSet;
}
/**
* Detect the feed type of the provided feed
*
- * @param Zend_Feed_Abstract $feed A fully instantiated Zend_Feed object
+ * @param Zend_Feed_Abstract|DOMDocument|string $feed
* @return string
*/
- public static function detectType($feed)
+ public static function detectType($feed, $specOnly = false)
{
if ($feed instanceof Zend_Feed_Reader_FeedInterface) {
$dom = $feed->getDomDocument();
- } elseif($feed instanceof DomDocument) {
+ } elseif($feed instanceof DOMDocument) {
$dom = $feed;
} elseif(is_string($feed) && !empty($feed)) {
@ini_set('track_errors', 1);
$dom = new DOMDocument;
- $status = @$doc->loadXML($string);
+ $status = @$dom->loadXML($feed);
@ini_restore('track_errors');
if (!$status) {
if (!isset($php_errormsg)) {
@@ -439,12 +439,13 @@ class Zend_Feed_Reader
$php_errormsg = '(error message not available)';
}
}
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception("DOMDocument cannot parse XML: $php_errormsg");
}
} else {
- require_once 'Zend/Feed/Exception.php';
- throw new Zend_Feed_Exception('Invalid object/scalar provided: must be of type Zend_Feed_Reader_FeedInterface, DomDocument or string');
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid object/scalar provided: must'
+ . ' be of type Zend_Feed_Reader_FeedInterface, DomDocument or string');
}
$xpath = new DOMXPath($dom);
@@ -509,6 +510,14 @@ class Zend_Feed_Reader
if ($xpath->query('//atom:feed')->length) {
return self::TYPE_ATOM_10;
}
+
+ if ($xpath->query('//atom:entry')->length) {
+ if ($specOnly == true) {
+ return self::TYPE_ATOM_10;
+ } else {
+ return self::TYPE_ATOM_10_ENTRY;
+ }
+ }
$xpath->registerNamespace('atom', self::NAMESPACE_ATOM_03);
@@ -537,7 +546,7 @@ class Zend_Feed_Reader
public static function getPluginLoader()
{
if (!isset(self::$_pluginLoader)) {
- require_once 'Zend/Loader/PluginLoader.php';
+ // require_once 'Zend/Loader/PluginLoader.php';
self::$_pluginLoader = new Zend_Loader_PluginLoader(array(
'Zend_Feed_Reader_Extension_' => 'Zend/Feed/Reader/Extension/',
));
@@ -607,7 +616,7 @@ class Zend_Feed_Reader
if (!self::getPluginLoader()->isLoaded($feedName)
&& !self::getPluginLoader()->isLoaded($entryName)
) {
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Could not load extension: ' . $name
. 'using Plugin Loader. Check prefix paths are configured and extension exists.');
}
@@ -689,4 +698,24 @@ class Zend_Feed_Reader
self::registerExtension('Thread');
self::registerExtension('Podcast');
}
+
+ /**
+ * Utility method to apply array_unique operation to a multidimensional
+ * array.
+ *
+ * @param array
+ * @return array
+ */
+ public static function arrayUnique(array $array)
+ {
+ foreach ($array as &$value) {
+ $value = serialize($value);
+ }
+ $array = array_unique($array);
+ foreach ($array as &$value) {
+ $value = unserialize($value);
+ }
+ return $array;
+ }
+
}
diff --git a/libs/Zend/Feed/Reader/Collection.php b/libs/Zend/Feed/Reader/Collection.php
new file mode 100644
index 0000000000..fba2b52b52
--- /dev/null
+++ b/libs/Zend/Feed/Reader/Collection.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Reader_Collection extends ArrayObject
+{
+
+
+
+}
diff --git a/libs/Zend/Feed/Reader/Collection/Author.php b/libs/Zend/Feed/Reader/Collection/Author.php
new file mode 100644
index 0000000000..6a039974b6
--- /dev/null
+++ b/libs/Zend/Feed/Reader/Collection/Author.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Author.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @see Zend_Feed_Reader_Collection_CollectionAbstract
+ */
+// require_once 'Zend/Feed/Reader/Collection/CollectionAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Reader_Collection_Author
+extends Zend_Feed_Reader_Collection_CollectionAbstract
+{
+
+ /**
+ * Return a simple array of the most relevant slice of
+ * the author values, i.e. all author names.
+ *
+ * @return array
+ */
+ public function getValues() {
+ $authors = array();
+ foreach ($this->getIterator() as $element) {
+ $authors[] = $element['name'];
+ }
+ return array_unique($authors);
+ }
+
+}
diff --git a/libs/Zend/Feed/Reader/Collection/Category.php b/libs/Zend/Feed/Reader/Collection/Category.php
new file mode 100644
index 0000000000..2587c13268
--- /dev/null
+++ b/libs/Zend/Feed/Reader/Collection/Category.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Category.php 20954 2010-02-06 17:56:27Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Reader_Collection_CollectionAbstract
+ */
+// require_once 'Zend/Feed/Reader/Collection/CollectionAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Reader_Collection_Category
+extends Zend_Feed_Reader_Collection_CollectionAbstract
+{
+
+ /**
+ * Return a simple array of the most relevant slice of
+ * the collection values. For example, feed categories contain
+ * the category name, domain/URI, and other data. This method would
+ * merely return the most useful data - i.e. the category names.
+ *
+ * @return array
+ */
+ public function getValues() {
+ $categories = array();
+ foreach ($this->getIterator() as $element) {
+ if (isset($element['label']) && !empty($element['label'])) {
+ $categories[] = $element['label'];
+ } else {
+ $categories[] = $element['term'];
+ }
+ }
+ return array_unique($categories);
+ }
+
+}
diff --git a/libs/Zend/Feed/Reader/Collection/CollectionAbstract.php b/libs/Zend/Feed/Reader/Collection/CollectionAbstract.php
new file mode 100644
index 0000000000..7b6dbd0317
--- /dev/null
+++ b/libs/Zend/Feed/Reader/Collection/CollectionAbstract.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: CollectionAbstract.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+abstract class Zend_Feed_Reader_Collection_CollectionAbstract extends ArrayObject
+{
+
+ /**
+ * Return a simple array of the most relevant slice of
+ * the collection values. For example, feed categories contain
+ * the category name, domain/URI, and other data. This method would
+ * merely return the most useful data - i.e. the category names.
+ *
+ * @return array
+ */
+ public abstract function getValues();
+
+}
diff --git a/libs/Zend/Feed/Reader/Entry/Atom.php b/libs/Zend/Feed/Reader/Entry/Atom.php
index b788cd2533..77289b411b 100644
--- a/libs/Zend/Feed/Reader/Entry/Atom.php
+++ b/libs/Zend/Feed/Reader/Entry/Atom.php
@@ -14,35 +14,35 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Atom.php 16966 2009-07-22 15:22:18Z padraic $
+ * @version $Id: Atom.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader
*/
-require_once 'Zend/Feed/Reader.php';
+// require_once 'Zend/Feed/Reader.php';
/**
* @see Zend_Feed_Reader_EntryInterface
*/
-require_once 'Zend/Feed/Reader/EntryInterface.php';
+// require_once 'Zend/Feed/Reader/EntryInterface.php';
/**
* @see Zend_Feed_Reader_EntryAbstract
*/
-require_once 'Zend/Feed/Reader/EntryAbstract.php';
+// require_once 'Zend/Feed/Reader/EntryAbstract.php';
/**
* @see Zend_Feed_Reader_Extension_Atom_Entry
*/
-require_once 'Zend/Feed/Reader/Extension/Atom/Entry.php';
+// require_once 'Zend/Feed/Reader/Extension/Atom/Entry.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Reader_Entry_Atom extends Zend_Feed_Reader_EntryAbstract implements Zend_Feed_Reader_EntryInterface
@@ -74,9 +74,12 @@ class Zend_Feed_Reader_Entry_Atom extends Zend_Feed_Reader_EntryAbstract impleme
$threadClass = Zend_Feed_Reader::getPluginLoader()->getClassName('Thread_Entry');
$this->_extensions['Thread_Entry'] = new $threadClass($entry, $entryKey, $type);
+
+ $threadClass = Zend_Feed_Reader::getPluginLoader()->getClassName('DublinCore_Entry');
+ $this->_extensions['DublinCore_Entry'] = new $threadClass($entry, $entryKey, $type);
}
- /**
+ /**
* Get the specified author
*
* @param int $index
@@ -295,7 +298,7 @@ class Zend_Feed_Reader_Entry_Atom extends Zend_Feed_Reader_EntryAbstract impleme
return $this->_data['commentcount'];
}
- $commentcount = $this->getExtension('Thread')>getCommentCount();
+ $commentcount = $this->getExtension('Thread')->getCommentCount();
if (!$commentcount) {
$commentcount = $this->getExtension('Atom')->getCommentCount();
@@ -341,6 +344,46 @@ class Zend_Feed_Reader_Entry_Atom extends Zend_Feed_Reader_EntryAbstract impleme
return $this->_data['commentfeedlink'];
}
+
+ /**
+ * Get category data as a Zend_Feed_Reader_Collection_Category object
+ *
+ * @return Zend_Feed_Reader_Collection_Category
+ */
+ public function getCategories()
+ {
+ if (array_key_exists('categories', $this->_data)) {
+ return $this->_data['categories'];
+ }
+
+ $categoryCollection = $this->getExtension('Atom')->getCategories();
+
+ if (count($categoryCollection) == 0) {
+ $categoryCollection = $this->getExtension('DublinCore')->getCategories();
+ }
+
+ $this->_data['categories'] = $categoryCollection;
+
+ return $this->_data['categories'];
+ }
+
+ /**
+ * Get source feed metadata from the entry
+ *
+ * @return Zend_Feed_Reader_Feed_Atom_Source|null
+ */
+ public function getSource()
+ {
+ if (array_key_exists('source', $this->_data)) {
+ return $this->_data['source'];
+ }
+
+ $source = $this->getExtension('Atom')->getSource();
+
+ $this->_data['source'] = $source;
+
+ return $this->_data['source'];
+ }
/**
* Set the XPath query (incl. on all Extensions)
diff --git a/libs/Zend/Feed/Reader/Entry/Rss.php b/libs/Zend/Feed/Reader/Entry/Rss.php
index b91990a665..21a30a98fc 100644
--- a/libs/Zend/Feed/Reader/Entry/Rss.php
+++ b/libs/Zend/Feed/Reader/Entry/Rss.php
@@ -14,65 +14,70 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Rss.php 18367 2009-09-22 14:55:59Z padraic $
+ * @version $Id: Rss.php 22301 2010-05-26 10:15:13Z padraic $
*/
/**
* @see Zend_Feed_Reader
*/
-require_once 'Zend/Feed/Reader.php';
+// require_once 'Zend/Feed/Reader.php';
/**
* @see Zend_Feed_Reader_EntryInterface
*/
-require_once 'Zend/Feed/Reader/EntryInterface.php';
+// require_once 'Zend/Feed/Reader/EntryInterface.php';
/**
* @see Zend_Feed_Reader_EntryAbstract
*/
-require_once 'Zend/Feed/Reader/EntryAbstract.php';
+// require_once 'Zend/Feed/Reader/EntryAbstract.php';
/**
* @see Zend_Feed_Reader_Extension_DublinCore_Entry
*/
-require_once 'Zend/Feed/Reader/Extension/DublinCore/Entry.php';
+// require_once 'Zend/Feed/Reader/Extension/DublinCore/Entry.php';
/**
* @see Zend_Feed_Reader_Extension_Content_Entry
*/
-require_once 'Zend/Feed/Reader/Extension/Content/Entry.php';
+// require_once 'Zend/Feed/Reader/Extension/Content/Entry.php';
/**
* @see Zend_Feed_Reader_Extension_Atom_Entry
*/
-require_once 'Zend/Feed/Reader/Extension/Atom/Entry.php';
+// require_once 'Zend/Feed/Reader/Extension/Atom/Entry.php';
/**
* @see Zend_Feed_Reader_Extension_WellformedWeb_Entry
*/
-require_once 'Zend/Feed/Reader/Extension/WellFormedWeb/Entry.php';
+// require_once 'Zend/Feed/Reader/Extension/WellFormedWeb/Entry.php';
/**
* @see Zend_Feed_Reader_Extension_Slash_Entry
*/
-require_once 'Zend/Feed/Reader/Extension/Slash/Entry.php';
+// require_once 'Zend/Feed/Reader/Extension/Slash/Entry.php';
/**
* @see Zend_Feed_Reader_Extension_Thread_Entry
*/
-require_once 'Zend/Feed/Reader/Extension/Thread/Entry.php';
+// require_once 'Zend/Feed/Reader/Extension/Thread/Entry.php';
/**
* @see Zend_Date
*/
-require_once 'Zend/Date.php';
+// require_once 'Zend/Date.php';
+
+/**
+ * @see Zend_Feed_Reader_Collection_Category
+ */
+// require_once 'Zend/Feed/Reader/Collection/Category.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_EntryAbstract implements Zend_Feed_Reader_EntryInterface
@@ -154,45 +159,50 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_EntryAbstract implemen
if (array_key_exists('authors', $this->_data)) {
return $this->_data['authors'];
}
-
+
$authors = array();
- // @todo: create a list from all potential sources rather than from alternatives
- if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 &&
- $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
- $list = $this->_xpath->evaluate($this->_xpathQueryRss.'//author');
- } else {
- $list = $this->_xpath->evaluate($this->_xpathQueryRdf.'//rss:author');
- }
- if (!$list->length) {
- if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
- $list = $this->_xpath->query('//author');
- } else {
- $list = $this->_xpath->query('//rss:author');
+ $authors_dc = $this->getExtension('DublinCore')->getAuthors();
+ if (!empty($authors_dc)) {
+ foreach ($authors_dc as $author) {
+ $authors[] = array(
+ 'name' => $author['name']
+ );
}
}
-
+
+ if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
+ && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
+ $list = $this->_xpath->query($this->_xpathQueryRss . '//author');
+ } else {
+ $list = $this->_xpath->query($this->_xpathQueryRdf . '//rss:author');
+ }
if ($list->length) {
foreach ($list as $author) {
- if ($this->getType() == Zend_Feed_Reader::TYPE_RSS_20
- && preg_match("/\(([^\)]+)\)/", $author->nodeValue, $matches, PREG_OFFSET_CAPTURE)
- ) {
- // source name from RSS 2.0 <author>
- // format "joe@example.com (Joe Bloggs)"
- $authors[] = $matches[1][0];
- } else {
- $authors[] = $author->nodeValue;
- }
+ $string = trim($author->nodeValue);
+ $email = null;
+ $name = null;
+ $data = array();
+ // Pretty rough parsing - but it's a catchall
+ if (preg_match("/^.*@[^ ]*/", $string, $matches)) {
+ $data['email'] = trim($matches[0]);
+ if (preg_match("/\((.*)\)$/", $string, $matches)) {
+ $data['name'] = $matches[1];
+ }
+ $authors[] = $data;
+ }
}
-
- $authors = array_unique($authors);
}
- if (empty($authors)) {
- $authors = $this->getExtension('DublinCore')->getAuthors();
+ if (count($authors) == 0) {
+ $authors = $this->getExtension('Atom')->getAuthors();
+ } else {
+ $authors = new Zend_Feed_Reader_Collection_Author(
+ Zend_Feed_Reader::arrayUnique($authors)
+ );
}
- if (empty($authors)) {
- $authors = $this->getExtension('Atom')->getAuthors();
+ if (count($authors) == 0) {
+ $authors = null;
}
$this->_data['authors'] = $authors;
@@ -255,21 +265,27 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_EntryAbstract implemen
) {
$dateModified = $this->_xpath->evaluate('string('.$this->_xpathQueryRss.'/pubDate)');
if ($dateModified) {
- $dateStandards = array(Zend_Date::RSS, Zend_Date::RFC_822,
- Zend_Date::RFC_2822, Zend_Date::DATES);
- $date = new Zend_Date;
- foreach ($dateStandards as $standard) {
- try {
- $date->set($dateModified, $standard);
- break;
- } catch (Zend_Date_Exception $e) {
- if ($standard == Zend_Date::DATES) {
- require_once 'Zend/Feed/Exception.php';
- throw new Zend_Feed_Exception(
- 'Could not load date due to unrecognised'
- .' format (should follow RFC 822 or 2822):'
- . $e->getMessage()
- );
+ $dateModifiedParsed = strtotime($dateModified);
+ if ($dateModifiedParsed) {
+ $date = new Zend_Date($dateModifiedParsed);
+ } else {
+ $dateStandards = array(Zend_Date::RSS, Zend_Date::RFC_822,
+ Zend_Date::RFC_2822, Zend_Date::DATES);
+ $date = new Zend_Date;
+ foreach ($dateStandards as $standard) {
+ try {
+ $date->set($dateModified, $standard);
+ break;
+ } catch (Zend_Date_Exception $e) {
+ if ($standard == Zend_Date::DATES) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception(
+ 'Could not load date due to unrecognised'
+ .' format (should follow RFC 822 or 2822):'
+ . $e->getMessage(),
+ 0, $e
+ );
+ }
}
}
}
@@ -324,8 +340,6 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_EntryAbstract implemen
if (!$description) {
$description = null;
- } else {
- $description = html_entity_decode($description, ENT_QUOTES, $this->getEncoding());
}
$this->_data['description'] = $description;
@@ -458,6 +472,46 @@ class Zend_Feed_Reader_Entry_Rss extends Zend_Feed_Reader_EntryAbstract implemen
return $this->_data['links'];
}
+
+ /**
+ * Get all categories
+ *
+ * @return Zend_Feed_Reader_Collection_Category
+ */
+ public function getCategories()
+ {
+ if (array_key_exists('categories', $this->_data)) {
+ return $this->_data['categories'];
+ }
+
+ if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 &&
+ $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
+ $list = $this->_xpath->query($this->_xpathQueryRss.'//category');
+ } else {
+ $list = $this->_xpath->query($this->_xpathQueryRdf.'//rss:category');
+ }
+
+ if ($list->length) {
+ $categoryCollection = new Zend_Feed_Reader_Collection_Category;
+ foreach ($list as $category) {
+ $categoryCollection[] = array(
+ 'term' => $category->nodeValue,
+ 'scheme' => $category->getAttribute('domain'),
+ 'label' => $category->nodeValue,
+ );
+ }
+ } else {
+ $categoryCollection = $this->getExtension('DublinCore')->getCategories();
+ }
+
+ if (count($categoryCollection) == 0) {
+ $categoryCollection = $this->getExtension('Atom')->getCategories();
+ }
+
+ $this->_data['categories'] = $categoryCollection;
+
+ return $this->_data['categories'];
+ }
/**
* Get a permalink to the entry
diff --git a/libs/Zend/Feed/Reader/EntryAbstract.php b/libs/Zend/Feed/Reader/EntryAbstract.php
index 153149ebcc..f73e1d1e8e 100644
--- a/libs/Zend/Feed/Reader/EntryAbstract.php
+++ b/libs/Zend/Feed/Reader/EntryAbstract.php
@@ -14,15 +14,15 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: EntryAbstract.php 16966 2009-07-22 15:22:18Z padraic $
+ * @version $Id: EntryAbstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Feed_Reader_EntryAbstract
@@ -118,6 +118,9 @@ abstract class Zend_Feed_Reader_EntryAbstract
public function getEncoding()
{
$assumed = $this->getDomDocument()->encoding;
+ if (empty($assumed)) {
+ $assumed = 'UTF-8';
+ }
return $assumed;
}
@@ -134,7 +137,7 @@ abstract class Zend_Feed_Reader_EntryAbstract
return $dom->saveXml();
}
- /**
+ /**
* Get the entry type
*
* @return string
@@ -151,10 +154,13 @@ abstract class Zend_Feed_Reader_EntryAbstract
*/
public function getXpath()
{
+ if (!$this->_xpath) {
+ $this->setXpath(new DOMXPath($this->getDomDocument()));
+ }
return $this->_xpath;
}
- /**
+ /**
* Set the XPath query
*
* @param DOMXPath $xpath
@@ -167,16 +173,6 @@ abstract class Zend_Feed_Reader_EntryAbstract
}
/**
- * Serialize the entry to an array
- *
- * @return array
- */
- public function toArray()
- {
- return $this->_data;
- }
-
- /**
* Get registered extensions
*
* @return array
@@ -215,7 +211,7 @@ abstract class Zend_Feed_Reader_EntryAbstract
return call_user_func_array(array($extension, $method), $args);
}
}
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Method: ' . $method
. 'does not exist and could not be located on a registered Extension');
}
diff --git a/libs/Zend/Feed/Reader/EntryInterface.php b/libs/Zend/Feed/Reader/EntryInterface.php
index dafbe293dd..392a533a30 100644
--- a/libs/Zend/Feed/Reader/EntryInterface.php
+++ b/libs/Zend/Feed/Reader/EntryInterface.php
@@ -14,15 +14,15 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: EntryInterface.php 16953 2009-07-22 11:57:25Z padraic $
+ * @version $Id: EntryInterface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Feed_Reader_EntryInterface
@@ -133,4 +133,11 @@ interface Zend_Feed_Reader_EntryInterface
* @return string
*/
public function getCommentFeedLink();
+
+ /**
+ * Get all categories
+ *
+ * @return Zend_Feed_Reader_Collection_Category
+ */
+ public function getCategories();
}
diff --git a/libs/Zend/Feed/Reader/Extension/Atom/Entry.php b/libs/Zend/Feed/Reader/Extension/Atom/Entry.php
index f442115801..1efa197787 100644
--- a/libs/Zend/Feed/Reader/Extension/Atom/Entry.php
+++ b/libs/Zend/Feed/Reader/Extension/Atom/Entry.php
@@ -14,41 +14,51 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Entry.php 18655 2009-10-20 14:17:39Z padraic $
+ * @version $Id: Entry.php 22301 2010-05-26 10:15:13Z padraic $
*/
/**
* @see Zend_Feed_Reader
*/
-require_once 'Zend/Feed/Reader.php';
+// require_once 'Zend/Feed/Reader.php';
/**
* @see Zend_Feed_Reader_Extension_EntryAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
/**
* @see Zend_Date
*/
-require_once 'Zend/Date.php';
+// require_once 'Zend/Date.php';
/**
* @see Zend_Uri
*/
-require_once 'Zend/Uri.php';
+// require_once 'Zend/Uri.php';
+
+/**
+ * @see Zend_Feed_Reader_Collection_Category
+ */
+// require_once 'Zend/Feed/Reader/Collection/Category.php';
+
+/**
+ * @see Zend_Feed_Reader_Feed_Atom_Source
+ */
+// require_once 'Zend/Feed/Reader/Feed/Atom/Source.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Reader_Extension_Atom_Entry
extends Zend_Feed_Reader_Extension_EntryAbstract
{
- /**
+ /**
* Get the specified author
*
* @param int $index
@@ -76,33 +86,34 @@ class Zend_Feed_Reader_Extension_Atom_Entry
return $this->_data['authors'];
}
- $authors = $this->_xpath->query(
- $this->getXpathPrefix() . '//atom:author' . '|'
- . $this->getXpathPrefix(). '//atom:contributor'
- );
+ $authors = array();
+ $list = $this->getXpath()->query($this->getXpathPrefix() . '//atom:author');
- if (!$authors->length) {
- $authors = $this->_xpath->query(
- '//atom:author' . '|' . '//atom:contributor'
- );
+ if (!$list->length) {
+ /**
+ * TODO: Limit query to feed level els only!
+ */
+ $list = $this->getXpath()->query('//atom:author');
}
- $people = array();
-
- if ($authors->length) {
- foreach ($authors as $author) {
+ if ($list->length) {
+ foreach ($list as $author) {
$author = $this->_getAuthor($author);
-
if (!empty($author)) {
- $people[] = $author;
+ $authors[] = $author;
}
}
}
- $people = array_unique($people);
-
- $this->_data['authors'] = $people;
+ if (count($authors) == 0) {
+ $authors = null;
+ } else {
+ $authors = new Zend_Feed_Reader_Collection_Author(
+ Zend_Feed_Reader::arrayUnique($authors)
+ );
+ }
+ $this->_data['authors'] = $authors;
return $this->_data['authors'];
}
@@ -116,21 +127,65 @@ class Zend_Feed_Reader_Extension_Atom_Entry
if (array_key_exists('content', $this->_data)) {
return $this->_data['content'];
}
-
- $content = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:content)');
-
- if ($content) {
- $content = html_entity_decode($content, ENT_QUOTES, $this->getEncoding());
+
+ $content = null;
+
+ $el = $this->getXpath()->query($this->getXpathPrefix() . '/atom:content');
+ if($el->length > 0) {
+ $el = $el->item(0);
+ $type = $el->getAttribute('type');
+ switch ($type) {
+ case '':
+ case 'text':
+ case 'text/plain':
+ case 'html':
+ case 'text/html':
+ $content = $el->nodeValue;
+ break;
+ case 'xhtml':
+ $this->getXpath()->registerNamespace('xhtml', 'http://www.w3.org/1999/xhtml');
+ $xhtml = $this->getXpath()->query(
+ $this->getXpathPrefix() . '/atom:content/xhtml:div'
+ )->item(0);
+ //$xhtml->setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
+ $d = new DOMDocument('1.0', $this->getEncoding());
+ $xhtmls = $d->importNode($xhtml, true);
+ $d->appendChild($xhtmls);
+ $content = $this->_collectXhtml(
+ $d->saveXML(),
+ $d->lookupPrefix('http://www.w3.org/1999/xhtml')
+ );
+ break;
+ }
}
+
+ //var_dump($content); exit;
if (!$content) {
$content = $this->getDescription();
}
- $this->_data['content'] = $content;
+ $this->_data['content'] = trim($content);
return $this->_data['content'];
}
+
+ /**
+ * Parse out XHTML to remove the namespacing
+ */
+ protected function _collectXhtml($xhtml, $prefix)
+ {
+ if (!empty($prefix)) $prefix = $prefix . ':';
+ $matches = array(
+ "/<\?xml[^<]*>[^<]*<" . $prefix . "div[^<]*/",
+ "/<\/" . $prefix . "div>\s*$/"
+ );
+ $xhtml = preg_replace($matches, '', $xhtml);
+ if (!empty($prefix)) {
+ $xhtml = preg_replace("/(<[\/]?)" . $prefix . "([a-zA-Z]+)/", '$1$2', $xhtml);
+ }
+ return $xhtml;
+ }
/**
* Get the entry creation date
@@ -145,10 +200,10 @@ class Zend_Feed_Reader_Extension_Atom_Entry
$date = null;
- if ($this->getType() === Zend_Feed_Reader::TYPE_ATOM_03) {
- $dateCreated = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:created)');
+ if ($this->_getAtomType() === Zend_Feed_Reader::TYPE_ATOM_03) {
+ $dateCreated = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:created)');
} else {
- $dateCreated = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:published)');
+ $dateCreated = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:published)');
}
if ($dateCreated) {
@@ -174,10 +229,10 @@ class Zend_Feed_Reader_Extension_Atom_Entry
$date = null;
- if ($this->getType() === Zend_Feed_Reader::TYPE_ATOM_03) {
- $dateModified = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:modified)');
+ if ($this->_getAtomType() === Zend_Feed_Reader::TYPE_ATOM_03) {
+ $dateModified = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:modified)');
} else {
- $dateModified = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:updated)');
+ $dateModified = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:updated)');
}
if ($dateModified) {
@@ -201,12 +256,10 @@ class Zend_Feed_Reader_Extension_Atom_Entry
return $this->_data['description'];
}
- $description = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:summary)');
+ $description = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:summary)');
if (!$description) {
$description = null;
- } else {
- $description = html_entity_decode($description, ENT_QUOTES, $this->getEncoding());
}
$this->_data['description'] = $description;
@@ -227,7 +280,7 @@ class Zend_Feed_Reader_Extension_Atom_Entry
$enclosure = null;
- $nodeList = $this->_xpath->query($this->getXpathPrefix() . '/atom:link[@rel="enclosure"]');
+ $nodeList = $this->getXpath()->query($this->getXpathPrefix() . '/atom:link[@rel="enclosure"]');
if ($nodeList->length > 0) {
$enclosure = new stdClass();
@@ -252,7 +305,7 @@ class Zend_Feed_Reader_Extension_Atom_Entry
return $this->_data['id'];
}
- $id = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:id)');
+ $id = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:id)');
if (!$id) {
if ($this->getPermalink()) {
@@ -268,7 +321,7 @@ class Zend_Feed_Reader_Extension_Atom_Entry
return $this->_data['id'];
}
-
+
/**
* Get the base URI of the feed (if set).
*
@@ -279,19 +332,19 @@ class Zend_Feed_Reader_Extension_Atom_Entry
if (array_key_exists('baseUrl', $this->_data)) {
return $this->_data['baseUrl'];
}
-
- $baseUrl = $this->_xpath->evaluate('string('
+
+ $baseUrl = $this->getXpath()->evaluate('string('
. $this->getXpathPrefix() . '/@xml:base[1]'
. ')');
-
+
if (!$baseUrl) {
- $baseUrl = $this->_xpath->evaluate('string(//@xml:base[1])');
+ $baseUrl = $this->getXpath()->evaluate('string(//@xml:base[1])');
}
if (!$baseUrl) {
$baseUrl = null;
}
-
+
$this->_data['baseUrl'] = $baseUrl;
return $this->_data['baseUrl'];
@@ -329,7 +382,7 @@ class Zend_Feed_Reader_Extension_Atom_Entry
$links = array();
- $list = $this->_xpath->query(
+ $list = $this->getXpath()->query(
$this->getXpathPrefix() . '//atom:link[@rel="alternate"]/@href' . '|' .
$this->getXpathPrefix() . '//atom:link[not(@rel)]/@href'
);
@@ -366,12 +419,10 @@ class Zend_Feed_Reader_Extension_Atom_Entry
return $this->_data['title'];
}
- $title = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:title)');
+ $title = $this->getXpath()->evaluate('string(' . $this->getXpathPrefix() . '/atom:title)');
if (!$title) {
$title = null;
- } else {
- $title = html_entity_decode($title, ENT_QUOTES, $this->getEncoding());
}
$this->_data['title'] = $title;
@@ -392,8 +443,8 @@ class Zend_Feed_Reader_Extension_Atom_Entry
$count = null;
- $this->_xpath->registerNamespace('thread10', 'http://purl.org/syndication/thread/1.0');
- $list = $this->_xpath->query(
+ $this->getXpath()->registerNamespace('thread10', 'http://purl.org/syndication/thread/1.0');
+ $list = $this->getXpath()->query(
$this->getXpathPrefix() . '//atom:link[@rel="replies"]/@thread10:count'
);
@@ -419,7 +470,7 @@ class Zend_Feed_Reader_Extension_Atom_Entry
$link = null;
- $list = $this->_xpath->query(
+ $list = $this->getXpath()->query(
$this->getXpathPrefix() . '//atom:link[@rel="replies" and @type="text/html"]/@href'
);
@@ -446,7 +497,7 @@ class Zend_Feed_Reader_Extension_Atom_Entry
$link = null;
- $list = $this->_xpath->query(
+ $list = $this->getXpath()->query(
$this->getXpathPrefix() . '//atom:link[@rel="replies" and @type="application/'.$type.'+xml"]/@href'
);
@@ -461,6 +512,72 @@ class Zend_Feed_Reader_Extension_Atom_Entry
}
/**
+ * Get all categories
+ *
+ * @return Zend_Feed_Reader_Collection_Category
+ */
+ public function getCategories()
+ {
+ if (array_key_exists('categories', $this->_data)) {
+ return $this->_data['categories'];
+ }
+
+ if ($this->_getAtomType() == Zend_Feed_Reader::TYPE_ATOM_10) {
+ $list = $this->getXpath()->query($this->getXpathPrefix() . '//atom:category');
+ } else {
+ /**
+ * Since Atom 0.3 did not support categories, it would have used the
+ * Dublin Core extension. However there is a small possibility Atom 0.3
+ * may have been retrofittied to use Atom 1.0 instead.
+ */
+ $this->getXpath()->registerNamespace('atom10', Zend_Feed_Reader::NAMESPACE_ATOM_10);
+ $list = $this->getXpath()->query($this->getXpathPrefix() . '//atom10:category');
+ }
+
+ if ($list->length) {
+ $categoryCollection = new Zend_Feed_Reader_Collection_Category;
+ foreach ($list as $category) {
+ $categoryCollection[] = array(
+ 'term' => $category->getAttribute('term'),
+ 'scheme' => $category->getAttribute('scheme'),
+ 'label' => $category->getAttribute('label')
+ );
+ }
+ } else {
+ return new Zend_Feed_Reader_Collection_Category;
+ }
+
+ $this->_data['categories'] = $categoryCollection;
+
+ return $this->_data['categories'];
+ }
+
+ /**
+ * Get source feed metadata from the entry
+ *
+ * @return Zend_Feed_Reader_Feed_Atom_Source|null
+ */
+ public function getSource()
+ {
+ if (array_key_exists('source', $this->_data)) {
+ return $this->_data['source'];
+ }
+
+ $source = null;
+ // TODO: Investigate why _getAtomType() fails here. Is it even needed?
+ if ($this->getType() == Zend_Feed_Reader::TYPE_ATOM_10) {
+ $list = $this->getXpath()->query($this->getXpathPrefix() . '/atom:source[1]');
+ if ($list->length) {
+ $element = $list->item(0);
+ $source = new Zend_Feed_Reader_Feed_Atom_Source($element, $this->getXpathPrefix());
+ }
+ }
+
+ $this->_data['source'] = $source;
+ return $this->_data['source'];
+ }
+
+ /**
* Attempt to absolutise the URI, i.e. if a relative URI apply the
* xml:base value as a prefix to turn into an absolute URI.
*/
@@ -485,35 +602,28 @@ class Zend_Feed_Reader_Extension_Atom_Entry
*/
protected function _getAuthor(DOMElement $element)
{
- $email = null;
- $name = null;
- $uri = null;
+ $author = array();
$emailNode = $element->getElementsByTagName('email');
$nameNode = $element->getElementsByTagName('name');
$uriNode = $element->getElementsByTagName('uri');
-
- if ($emailNode->length) {
- $email = $emailNode->item(0)->nodeValue;
+
+ if ($emailNode->length && strlen($emailNode->item(0)->nodeValue) > 0) {
+ $author['email'] = $emailNode->item(0)->nodeValue;
}
- if ($nameNode->length) {
- $name = $nameNode->item(0)->nodeValue;
+ if ($nameNode->length && strlen($nameNode->item(0)->nodeValue) > 0) {
+ $author['name'] = $nameNode->item(0)->nodeValue;
}
- if ($uriNode->length) {
- $uri = $uriNode->item(0)->nodeValue;
+ if ($uriNode->length && strlen($uriNode->item(0)->nodeValue) > 0) {
+ $author['uri'] = $uriNode->item(0)->nodeValue;
}
- if (!empty($email)) {
- return $email . (empty($name) ? '' : ' (' . $name . ')');
- } else if (!empty($name)) {
- return $name;
- } else if (!empty($uri)) {
- return $uri;
+ if (empty($author)) {
+ return null;
}
-
- return null;
+ return $author;
}
/**
@@ -521,18 +631,12 @@ class Zend_Feed_Reader_Extension_Atom_Entry
*/
protected function _registerNamespaces()
{
- if ($this->getType() == Zend_Feed_Reader::TYPE_ATOM_10
- || $this->getType() == Zend_Feed_Reader::TYPE_ATOM_03
- ) {
- return; // pre-registered at Feed level
- }
- $atomDetected = $this->_getAtomType();
- switch ($atomDetected) {
+ switch ($this->_getAtomType()) {
case Zend_Feed_Reader::TYPE_ATOM_03:
- $this->_xpath->registerNamespace('atom', Zend_Feed_Reader::NAMESPACE_ATOM_03);
+ $this->getXpath()->registerNamespace('atom', Zend_Feed_Reader::NAMESPACE_ATOM_03);
break;
default:
- $this->_xpath->registerNamespace('atom', Zend_Feed_Reader::NAMESPACE_ATOM_10);
+ $this->getXpath()->registerNamespace('atom', Zend_Feed_Reader::NAMESPACE_ATOM_10);
break;
}
}
@@ -542,17 +646,16 @@ class Zend_Feed_Reader_Extension_Atom_Entry
*/
protected function _getAtomType()
{
- $nslist = $this->getDomDocument()->documentElement->attributes;
- if (!$nslist->length) {
- return null;
- }
- foreach ($nslist as $ns) {
- if ($ns->value == Zend_Feed_Reader::NAMESPACE_ATOM_10) {
- return Zend_Feed_Reader::TYPE_ATOM_10;
- }
- if ($ns->value == Zend_Feed_Reader::NAMESPACE_ATOM_03) {
- return Zend_Feed_Reader::TYPE_ATOM_03;
- }
+ $dom = $this->getDomDocument();
+ $prefixAtom03 = $dom->lookupPrefix(Zend_Feed_Reader::NAMESPACE_ATOM_03);
+ $prefixAtom10 = $dom->lookupPrefix(Zend_Feed_Reader::NAMESPACE_ATOM_10);
+ if ($dom->isDefaultNamespace(Zend_Feed_Reader::NAMESPACE_ATOM_03)
+ || !empty($prefixAtom03)) {
+ return Zend_Feed_Reader::TYPE_ATOM_03;
+ }
+ if ($dom->isDefaultNamespace(Zend_Feed_Reader::NAMESPACE_ATOM_10)
+ || !empty($prefixAtom10)) {
+ return Zend_Feed_Reader::TYPE_ATOM_10;
}
}
}
diff --git a/libs/Zend/Feed/Reader/Extension/Atom/Feed.php b/libs/Zend/Feed/Reader/Extension/Atom/Feed.php
index 4b1de87ed8..3e0e2079c5 100644
--- a/libs/Zend/Feed/Reader/Extension/Atom/Feed.php
+++ b/libs/Zend/Feed/Reader/Extension/Atom/Feed.php
@@ -14,33 +14,38 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Feed.php 18655 2009-10-20 14:17:39Z padraic $
+ * @version $Id: Feed.php 22301 2010-05-26 10:15:13Z padraic $
*/
/**
* @see Zend_Feed_Reader_Extension_FeedAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/FeedAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/FeedAbstract.php';
/**
* @see Zend_Date
*/
-require_once 'Zend/Date.php';
+// require_once 'Zend/Date.php';
/**
* @see Zend_Uri
*/
-require_once 'Zend/Uri.php';
+// require_once 'Zend/Uri.php';
+
+/**
+ * @see Zend_Feed_Reader_Collection_Author
+ */
+// require_once 'Zend/Feed/Reader/Collection/Author.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Feed_Reader_Extension_Atom_Feed
+class Zend_Feed_Reader_Extension_Atom_Feed
extends Zend_Feed_Reader_Extension_FeedAbstract
{
/**
@@ -71,38 +76,28 @@ class Zend_Feed_Reader_Extension_Atom_Feed
return $this->_data['authors'];
}
- $authors = $this->_xpath->query('//atom:author');
- $contributors = $this->_xpath->query('//atom:contributor');
+ $list = $this->_xpath->query('//atom:author');
- $people = array();
+ $authors = array();
- if ($authors->length) {
- foreach ($authors as $author) {
+ if ($list->length) {
+ foreach ($list as $author) {
$author = $this->_getAuthor($author);
-
if (!empty($author)) {
- $people[] = $author;
- }
- }
- }
-
- if ($contributors->length) {
- foreach ($contributors as $contributor) {
- $contributor = $this->_getAuthor($contributor);
-
- if (!empty($contributor)) {
- $people[] = $contributor;
+ $authors[] = $author;
}
}
}
- if (empty($people)) {
- $people = null;
+ if (count($authors) == 0) {
+ $authors = null;
} else {
- $people = array_unique($people);
+ $authors = new Zend_Feed_Reader_Collection_Author(
+ Zend_Feed_Reader::arrayUnique($authors)
+ );
}
- $this->_data['authors'] = $people;
+ $this->_data['authors'] = $authors;
return $this->_data['authors'];
}
@@ -236,8 +231,6 @@ class Zend_Feed_Reader_Extension_Atom_Feed
if (!$generator) {
$generator = null;
- } else {
- $generator = html_entity_decode($generator, ENT_QUOTES, $this->getEncoding());
}
$this->_data['generator'] = $generator;
@@ -245,7 +238,7 @@ class Zend_Feed_Reader_Extension_Atom_Feed
return $this->_data['generator'];
}
- /**
+ /**
* Get the feed ID
*
* @return string|null
@@ -298,7 +291,31 @@ class Zend_Feed_Reader_Extension_Atom_Feed
return $this->_data['language'];
}
-
+
+ /**
+ * Get the feed image
+ *
+ * @return array|null
+ */
+ public function getImage()
+ {
+ if (array_key_exists('image', $this->_data)) {
+ return $this->_data['image'];
+ }
+
+ $imageUrl = $this->_xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:logo)');
+
+ if (!$imageUrl) {
+ $image = null;
+ } else {
+ $image = array('uri'=>$imageUrl);
+ }
+
+ $this->_data['image'] = $image;
+
+ return $this->_data['image'];
+ }
+
/**
* Get the base URI of the feed (if set).
*
@@ -332,12 +349,12 @@ class Zend_Feed_Reader_Extension_Atom_Feed
}
$link = null;
-
+
$list = $this->_xpath->query(
$this->getXpathPrefix() . '/atom:link[@rel="alternate"]/@href' . '|' .
$this->getXpathPrefix() . '/atom:link[not(@rel)]/@href'
);
-
+
if ($list->length) {
$link = $list->item(0)->nodeValue;
$link = $this->_absolutiseUri($link);
@@ -369,6 +386,34 @@ class Zend_Feed_Reader_Extension_Atom_Feed
}
/**
+ * Get an array of any supported Pusubhubbub endpoints
+ *
+ * @return array|null
+ */
+ public function getHubs()
+ {
+ if (array_key_exists('hubs', $this->_data)) {
+ return $this->_data['hubs'];
+ }
+ $hubs = array();
+
+ $list = $this->_xpath->query($this->getXpathPrefix()
+ . '//atom:link[@rel="hub"]/@href');
+
+ if ($list->length) {
+ foreach ($list as $uri) {
+ $hubs[] = $this->_absolutiseUri($uri->nodeValue);
+ }
+ } else {
+ $hubs = null;
+ }
+
+ $this->_data['hubs'] = $hubs;
+
+ return $this->_data['hubs'];
+ }
+
+ /**
* Get the feed title
*
* @return string|null
@@ -389,8 +434,49 @@ class Zend_Feed_Reader_Extension_Atom_Feed
return $this->_data['title'];
}
+
+ /**
+ * Get all categories
+ *
+ * @return Zend_Feed_Reader_Collection_Category
+ */
+ public function getCategories()
+ {
+ if (array_key_exists('categories', $this->_data)) {
+ return $this->_data['categories'];
+ }
- /**
+ if ($this->getType() == Zend_Feed_Reader::TYPE_ATOM_10) {
+ $list = $this->_xpath->query($this->getXpathPrefix() . '/atom:category');
+ } else {
+ /**
+ * Since Atom 0.3 did not support categories, it would have used the
+ * Dublin Core extension. However there is a small possibility Atom 0.3
+ * may have been retrofittied to use Atom 1.0 instead.
+ */
+ $this->_xpath->registerNamespace('atom10', Zend_Feed_Reader::NAMESPACE_ATOM_10);
+ $list = $this->_xpath->query($this->getXpathPrefix() . '/atom10:category');
+ }
+
+ if ($list->length) {
+ $categoryCollection = new Zend_Feed_Reader_Collection_Category;
+ foreach ($list as $category) {
+ $categoryCollection[] = array(
+ 'term' => $category->getAttribute('term'),
+ 'scheme' => $category->getAttribute('scheme'),
+ 'label' => $category->getAttribute('label')
+ );
+ }
+ } else {
+ return new Zend_Feed_Reader_Collection_Category;
+ }
+
+ $this->_data['categories'] = $categoryCollection;
+
+ return $this->_data['categories'];
+ }
+
+ /**
* Get an author entry in RSS format
*
* @param DOMElement $element
@@ -398,37 +484,30 @@ class Zend_Feed_Reader_Extension_Atom_Feed
*/
protected function _getAuthor(DOMElement $element)
{
- $email = null;
- $name = null;
- $uri = null;
+ $author = array();
$emailNode = $element->getElementsByTagName('email');
$nameNode = $element->getElementsByTagName('name');
$uriNode = $element->getElementsByTagName('uri');
-
- if ($emailNode->length) {
- $email = $emailNode->item(0)->nodeValue;
+
+ if ($emailNode->length && strlen($emailNode->item(0)->nodeValue) > 0) {
+ $author['email'] = $emailNode->item(0)->nodeValue;
}
- if ($nameNode->length) {
- $name = $nameNode->item(0)->nodeValue;
+ if ($nameNode->length && strlen($nameNode->item(0)->nodeValue) > 0) {
+ $author['name'] = $nameNode->item(0)->nodeValue;
}
- if ($uriNode->length) {
- $uri = $uriNode->item(0)->nodeValue;
+ if ($uriNode->length && strlen($uriNode->item(0)->nodeValue) > 0) {
+ $author['uri'] = $uriNode->item(0)->nodeValue;
}
- if (!empty($email)) {
- return $email . (empty($name) ? '' : ' (' . $name . ')');
- } else if (!empty($name)) {
- return $name;
- } else if (!empty($uri)) {
- return $uri;
+ if (empty($author)) {
+ return null;
}
-
- return null;
+ return $author;
}
-
+
/**
* Attempt to absolutise the URI, i.e. if a relative URI apply the
* xml:base value as a prefix to turn into an absolute URI.
@@ -451,7 +530,7 @@ class Zend_Feed_Reader_Extension_Atom_Feed
*/
protected function _registerNamespaces()
{
- if ($this->getType() == Zend_Feed_Reader::TYPE_ATOM_10
+ if ($this->getType() == Zend_Feed_Reader::TYPE_ATOM_10
|| $this->getType() == Zend_Feed_Reader::TYPE_ATOM_03
) {
return; // pre-registered at Feed level
@@ -472,17 +551,16 @@ class Zend_Feed_Reader_Extension_Atom_Feed
*/
protected function _getAtomType()
{
- $nslist = $this->getDomDocument()->documentElement->attributes;
- if (!$nslist->length) {
- return null;
- }
- foreach ($nslist as $ns) {
- if ($ns->value == Zend_Feed_Reader::NAMESPACE_ATOM_10) {
- return Zend_Feed_Reader::TYPE_ATOM_10;
- }
- if ($ns->value == Zend_Feed_Reader::NAMESPACE_ATOM_03) {
- return Zend_Feed_Reader::TYPE_ATOM_03;
- }
+ $dom = $this->getDomDocument();
+ $prefixAtom03 = $dom->lookupPrefix(Zend_Feed_Reader::NAMESPACE_ATOM_03);
+ $prefixAtom10 = $dom->lookupPrefix(Zend_Feed_Reader::NAMESPACE_ATOM_10);
+ if ($dom->isDefaultNamespace(Zend_Feed_Reader::NAMESPACE_ATOM_10)
+ || !empty($prefixAtom10)) {
+ return Zend_Feed_Reader::TYPE_ATOM_10;
+ }
+ if ($dom->isDefaultNamespace(Zend_Feed_Reader::NAMESPACE_ATOM_03)
+ || !empty($prefixAtom03)) {
+ return Zend_Feed_Reader::TYPE_ATOM_03;
}
}
}
diff --git a/libs/Zend/Feed/Reader/Extension/Content/Entry.php b/libs/Zend/Feed/Reader/Extension/Content/Entry.php
index 7145281ecb..ca10f24a3b 100644
--- a/libs/Zend/Feed/Reader/Extension/Content/Entry.php
+++ b/libs/Zend/Feed/Reader/Extension/Content/Entry.php
@@ -14,43 +14,40 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Entry.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Entry.php 22301 2010-05-26 10:15:13Z padraic $
*/
/**
* @see Zend_Feed_Reader
*/
-require_once 'Zend/Feed/Reader.php';
+// require_once 'Zend/Feed/Reader.php';
/**
* @see Zend_Feed_Reader_Entry_EntryAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Feed_Reader_Extension_Content_Entry
+class Zend_Feed_Reader_Extension_Content_Entry
extends Zend_Feed_Reader_Extension_EntryAbstract
{
public function getContent()
{
- if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
+ if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
&& $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090
) {
$content = $this->_xpath->evaluate('string('.$this->getXpathPrefix().'/content:encoded)');
} else {
$content = $this->_xpath->evaluate('string('.$this->getXpathPrefix().'/content:encoded)');
}
- if ($content) {
- $content = html_entity_decode($content, ENT_QUOTES, $this->getEncoding());
- }
return $content;
}
diff --git a/libs/Zend/Feed/Reader/Extension/CreativeCommons/Entry.php b/libs/Zend/Feed/Reader/Extension/CreativeCommons/Entry.php
index b9830089d3..5e78db10ab 100644
--- a/libs/Zend/Feed/Reader/Extension/CreativeCommons/Entry.php
+++ b/libs/Zend/Feed/Reader/Extension/CreativeCommons/Entry.php
@@ -14,25 +14,25 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Entry.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Entry.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader_Extension_EntryAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
/**
* @see Zend_Feed_Reader_Extension_CreativeCommons_Feed
*/
-require_once 'Zend/Feed/Reader/Extension/CreativeCommons/Feed.php';
+// require_once 'Zend/Feed/Reader/Extension/CreativeCommons/Feed.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Reader_Extension_CreativeCommons_Entry extends Zend_Feed_Reader_Extension_EntryAbstract
diff --git a/libs/Zend/Feed/Reader/Extension/CreativeCommons/Feed.php b/libs/Zend/Feed/Reader/Extension/CreativeCommons/Feed.php
index c3d0cd2d42..3d29c6911f 100644
--- a/libs/Zend/Feed/Reader/Extension/CreativeCommons/Feed.php
+++ b/libs/Zend/Feed/Reader/Extension/CreativeCommons/Feed.php
@@ -14,23 +14,23 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Feed.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Feed.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader_Extension_FeedAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/FeedAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/FeedAbstract.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Feed_Reader_Extension_CreativeCommons_Feed
+class Zend_Feed_Reader_Extension_CreativeCommons_Feed
extends Zend_Feed_Reader_Extension_FeedAbstract
{
/**
diff --git a/libs/Zend/Feed/Reader/Extension/DublinCore/Entry.php b/libs/Zend/Feed/Reader/Extension/DublinCore/Entry.php
index 522e2c1498..4ad104b6ff 100644
--- a/libs/Zend/Feed/Reader/Extension/DublinCore/Entry.php
+++ b/libs/Zend/Feed/Reader/Extension/DublinCore/Entry.php
@@ -14,33 +14,33 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Entry.php 16711 2009-07-14 16:10:54Z matthew $
+ * @version $Id: Entry.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader
*/
-require_once 'Zend/Feed/Reader.php';
+// require_once 'Zend/Feed/Reader.php';
/**
* @see Zend_Feed_Reader_Extension_EntryAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
/**
* @see Zend_Date
*/
-require_once 'Zend/Date.php';
+// require_once 'Zend/Date.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Feed_Reader_Extension_DublinCore_Entry
+class Zend_Feed_Reader_Extension_DublinCore_Entry
extends Zend_Feed_Reader_Extension_EntryAbstract
{
/**
@@ -87,22 +87,56 @@ class Zend_Feed_Reader_Extension_DublinCore_Entry
if ($list->length) {
foreach ($list as $author) {
- if ($this->getType() == Zend_Feed_Reader::TYPE_RSS_20
- && preg_match("/\(([^\)]+)\)/", $author->nodeValue, $matches, PREG_OFFSET_CAPTURE)
- ) {
- $authors[] = $matches[1][0];
- } else {
- $authors[] = $author->nodeValue;
- }
+ $authors[] = array(
+ 'name' => $author->nodeValue
+ );
}
-
- $authors = array_unique($authors);
+ $authors = new Zend_Feed_Reader_Collection_Author(
+ Zend_Feed_Reader::arrayUnique($authors)
+ );
+ } else {
+ $authors = null;
}
$this->_data['authors'] = $authors;
return $this->_data['authors'];
}
+
+ /**
+ * Get categories (subjects under DC)
+ *
+ * @return Zend_Feed_Reader_Collection_Category
+ */
+ public function getCategories()
+ {
+ if (array_key_exists('categories', $this->_data)) {
+ return $this->_data['categories'];
+ }
+
+ $list = $this->_xpath->evaluate($this->getXpathPrefix() . '//dc11:subject');
+
+ if (!$list->length) {
+ $list = $this->_xpath->evaluate($this->getXpathPrefix() . '//dc10:subject');
+ }
+
+ if ($list->length) {
+ $categoryCollection = new Zend_Feed_Reader_Collection_Category;
+ foreach ($list as $category) {
+ $categoryCollection[] = array(
+ 'term' => $category->nodeValue,
+ 'scheme' => null,
+ 'label' => $category->nodeValue,
+ );
+ }
+ } else {
+ $categoryCollection = new Zend_Feed_Reader_Collection_Category;
+ }
+
+ $this->_data['categories'] = $categoryCollection;
+ return $this->_data['categories'];
+ }
+
/**
* Get the entry content
diff --git a/libs/Zend/Feed/Reader/Extension/DublinCore/Feed.php b/libs/Zend/Feed/Reader/Extension/DublinCore/Feed.php
index 68078578b2..4e4bcf4888 100644
--- a/libs/Zend/Feed/Reader/Extension/DublinCore/Feed.php
+++ b/libs/Zend/Feed/Reader/Extension/DublinCore/Feed.php
@@ -14,31 +14,36 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Feed.php 16711 2009-07-14 16:10:54Z matthew $
+ * @version $Id: Feed.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader_Extension_FeedAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/FeedAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/FeedAbstract.php';
/**
* @see Zend_Date
*/
-require_once 'Zend/Date.php';
+// require_once 'Zend/Date.php';
+
+/**
+ * @see Zend_Feed_Reader_Collection_Author
+ */
+// require_once 'Zend/Feed/Reader/Collection/Author.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Feed_Reader_Extension_DublinCore_Feed
+class Zend_Feed_Reader_Extension_DublinCore_Feed
extends Zend_Feed_Reader_Extension_FeedAbstract
{
- /**
+ /**
* Get a single author
*
* @param int $index
@@ -79,13 +84,18 @@ class Zend_Feed_Reader_Extension_DublinCore_Feed
$list = $this->_xpath->query('//dc10:publisher');
}
}
-
- foreach ($list as $authorObj) {
- $authors[] = $authorObj->nodeValue;
- }
-
- if (!empty($authors)) {
- $authors = array_unique($authors);
+
+ if ($list->length) {
+ foreach ($list as $author) {
+ $authors[] = array(
+ 'name' => $author->nodeValue
+ );
+ }
+ $authors = new Zend_Feed_Reader_Collection_Author(
+ Zend_Feed_Reader::arrayUnique($authors)
+ );
+ } else {
+ $authors = null;
}
$this->_data['authors'] = $authors;
@@ -251,6 +261,40 @@ class Zend_Feed_Reader_Extension_DublinCore_Feed
return $this->_data['date'];
}
+
+ /**
+ * Get categories (subjects under DC)
+ *
+ * @return Zend_Feed_Reader_Collection_Category
+ */
+ public function getCategories()
+ {
+ if (array_key_exists('categories', $this->_data)) {
+ return $this->_data['categories'];
+ }
+
+ $list = $this->_xpath->evaluate($this->getXpathPrefix() . '//dc11:subject');
+
+ if (!$list->length) {
+ $list = $this->_xpath->evaluate($this->getXpathPrefix() . '//dc10:subject');
+ }
+
+ if ($list->length) {
+ $categoryCollection = new Zend_Feed_Reader_Collection_Category;
+ foreach ($list as $category) {
+ $categoryCollection[] = array(
+ 'term' => $category->nodeValue,
+ 'scheme' => null,
+ 'label' => $category->nodeValue,
+ );
+ }
+ } else {
+ $categoryCollection = new Zend_Feed_Reader_Collection_Category;
+ }
+
+ $this->_data['categories'] = $categoryCollection;
+ return $this->_data['categories'];
+ }
/**
* Register the default namespaces for the current feed format
diff --git a/libs/Zend/Feed/Reader/Extension/EntryAbstract.php b/libs/Zend/Feed/Reader/Extension/EntryAbstract.php
index 68ae193cf7..299c1bfbaf 100644
--- a/libs/Zend/Feed/Reader/Extension/EntryAbstract.php
+++ b/libs/Zend/Feed/Reader/Extension/EntryAbstract.php
@@ -14,15 +14,15 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: EntryAbstract.php 16711 2009-07-14 16:10:54Z matthew $
+ * @version $Id: EntryAbstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Feed_Reader_Extension_EntryAbstract
@@ -86,14 +86,14 @@ abstract class Zend_Feed_Reader_Extension_EntryAbstract
if (!is_null($type)) {
$this->_data['type'] = $type;
} else {
- $this->_data['type'] = Zend_Feed_Reader::detectType($feed);
+ $this->_data['type'] = Zend_Feed_Reader::detectType($entry->ownerDocument, true);
}
// set the XPath query prefix for the entry being queried
- if ($this->getType() == Zend_Feed_Reader::TYPE_RSS_10
+ if ($this->getType() == Zend_Feed_Reader::TYPE_RSS_10
|| $this->getType() == Zend_Feed_Reader::TYPE_RSS_090
) {
$this->setXpathPrefix('//rss:item[' . ($this->_entryKey+1) . ']');
- } elseif ($this->getType() == Zend_Feed_Reader::TYPE_ATOM_10
+ } elseif ($this->getType() == Zend_Feed_Reader::TYPE_ATOM_10
|| $this->getType() == Zend_Feed_Reader::TYPE_ATOM_03
) {
$this->setXpathPrefix('//atom:entry[' . ($this->_entryKey+1) . ']');
@@ -123,7 +123,7 @@ abstract class Zend_Feed_Reader_Extension_EntryAbstract
return $assumed;
}
- /**
+ /**
* Get the entry type
*
* @return string
@@ -153,6 +153,9 @@ abstract class Zend_Feed_Reader_Extension_EntryAbstract
*/
public function getXpath()
{
+ if (!$this->_xpath) {
+ $this->setXpath(new DOMXPath($this->getDomDocument()));
+ }
return $this->_xpath;
}
@@ -178,8 +181,8 @@ abstract class Zend_Feed_Reader_Extension_EntryAbstract
/**
* Set the XPath prefix
- *
- * @param string $prefix
+ *
+ * @param string $prefix
* @return Zend_Feed_Reader_Extension_EntryAbstract
*/
public function setXpathPrefix($prefix)
@@ -190,7 +193,7 @@ abstract class Zend_Feed_Reader_Extension_EntryAbstract
/**
* Register XML namespaces
- *
+ *
* @return void
*/
protected abstract function _registerNamespaces();
diff --git a/libs/Zend/Feed/Reader/Extension/FeedAbstract.php b/libs/Zend/Feed/Reader/Extension/FeedAbstract.php
index 973dd81197..23d97d3f7a 100644
--- a/libs/Zend/Feed/Reader/Extension/FeedAbstract.php
+++ b/libs/Zend/Feed/Reader/Extension/FeedAbstract.php
@@ -14,36 +14,36 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: FeedAbstract.php 16711 2009-07-14 16:10:54Z matthew $
+ * @version $Id: FeedAbstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader
*/
-require_once 'Zend/Feed/Reader.php';
+// require_once 'Zend/Feed/Reader.php';
/**
* @see Zend_Feed_Reader_Entry_Atom
*/
-require_once 'Zend/Feed/Reader/Entry/Atom.php';
+// require_once 'Zend/Feed/Reader/Entry/Atom.php';
/**
* @see Zend_Feed_Reader_Entry_Rss
*/
-require_once 'Zend/Feed/Reader/Entry/Rss.php';
+// require_once 'Zend/Feed/Reader/Entry/Rss.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Feed_Reader_Extension_FeedAbstract
{
- /**
+ /**
* Parsed feed data
*
* @var array
@@ -139,10 +139,33 @@ abstract class Zend_Feed_Reader_Extension_FeedAbstract
return $this->_data;
}
- /**
+ /**
+ * Set the XPath query
+ *
+ * @param DOMXPath $xpath
+ * @return Zend_Feed_Reader_Extension_EntryAbstract
+ */
+ public function setXpath(DOMXPath $xpath)
+ {
+ $this->_xpath = $xpath;
+ $this->_registerNamespaces();
+ return $this;
+ }
+
+ /**
+ * Get the DOMXPath object
+ *
+ * @return string
+ */
+ public function getXpath()
+ {
+ return $this->_xpath;
+ }
+
+ /**
* Get the XPath prefix
- *
- * @return string
+ *
+ * @return string
*/
public function getXpathPrefix()
{
diff --git a/libs/Zend/Feed/Reader/Extension/Podcast/Entry.php b/libs/Zend/Feed/Reader/Extension/Podcast/Entry.php
index 7af2285421..bbe340ce63 100644
--- a/libs/Zend/Feed/Reader/Extension/Podcast/Entry.php
+++ b/libs/Zend/Feed/Reader/Extension/Podcast/Entry.php
@@ -14,25 +14,25 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Entry.php 16792 2009-07-17 02:52:37Z norm2782 $
+ * @version $Id: Entry.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader
*/
-require_once 'Zend/Feed/Reader.php';
+// require_once 'Zend/Feed/Reader.php';
/**
* @see Zend_Feed_Reader_Extension_EntryAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Reader_Extension_Podcast_Entry extends Zend_Feed_Reader_Extension_EntryAbstract
diff --git a/libs/Zend/Feed/Reader/Extension/Podcast/Feed.php b/libs/Zend/Feed/Reader/Extension/Podcast/Feed.php
index b213d34590..c4ea180f7c 100644
--- a/libs/Zend/Feed/Reader/Extension/Podcast/Feed.php
+++ b/libs/Zend/Feed/Reader/Extension/Podcast/Feed.php
@@ -14,20 +14,20 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Feed.php 16792 2009-07-17 02:52:37Z norm2782 $
+ * @version $Id: Feed.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader_Extension_FeedAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/FeedAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/FeedAbstract.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Reader_Extension_Podcast_Feed extends Zend_Feed_Reader_Extension_FeedAbstract
diff --git a/libs/Zend/Feed/Reader/Extension/Slash/Entry.php b/libs/Zend/Feed/Reader/Extension/Slash/Entry.php
index b2aa12457b..222c0e1062 100644
--- a/libs/Zend/Feed/Reader/Extension/Slash/Entry.php
+++ b/libs/Zend/Feed/Reader/Extension/Slash/Entry.php
@@ -14,28 +14,28 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Entry.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Entry.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader
*/
-require_once 'Zend/Feed/Reader.php';
+// require_once 'Zend/Feed/Reader.php';
/**
* @see Zend_Feed_Reader_Extension_EntryAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Feed_Reader_Extension_Slash_Entry
+class Zend_Feed_Reader_Extension_Slash_Entry
extends Zend_Feed_Reader_Extension_EntryAbstract
{
/**
diff --git a/libs/Zend/Feed/Reader/Extension/Syndication/Feed.php b/libs/Zend/Feed/Reader/Extension/Syndication/Feed.php
index bd205bcf61..5b383cfedb 100644
--- a/libs/Zend/Feed/Reader/Extension/Syndication/Feed.php
+++ b/libs/Zend/Feed/Reader/Extension/Syndication/Feed.php
@@ -14,25 +14,25 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Feed.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Feed.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader_Extension_FeedAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/FeedAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/FeedAbstract.php';
-require_once 'Zend/Date.php';
+// require_once 'Zend/Date.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Feed_Reader_Extension_Syndication_Feed
+class Zend_Feed_Reader_Extension_Syndication_Feed
extends Zend_Feed_Reader_Extension_FeedAbstract
{
/**
@@ -57,7 +57,7 @@ class Zend_Feed_Reader_Extension_Syndication_Feed
case 'yearly':
return $period;
default:
- throw new Zend_Feed_Exception("Feed specified invalid update period: '$period'."
+ throw new Zend_Feed_Exception("Feed specified invalid update period: '$period'."
. " Must be one of hourly, daily, weekly or yearly"
);
}
@@ -100,13 +100,13 @@ class Zend_Feed_Reader_Extension_Syndication_Feed
switch ($period)
{
//intentional fall through
- case 'yearly':
+ case 'yearly':
$ticks *= 52; //TODO: fix generalisation, how?
- case 'weekly':
+ case 'weekly':
$ticks *= 7;
- case 'daily':
+ case 'daily':
$ticks *= 24;
- case 'hourly':
+ case 'hourly':
$ticks *= 3600;
break;
default: //Never arrive here, exception thrown in getPeriod()
diff --git a/libs/Zend/Feed/Reader/Extension/Thread/Entry.php b/libs/Zend/Feed/Reader/Extension/Thread/Entry.php
index c8b632726c..e8a4bde92f 100644
--- a/libs/Zend/Feed/Reader/Extension/Thread/Entry.php
+++ b/libs/Zend/Feed/Reader/Extension/Thread/Entry.php
@@ -14,28 +14,28 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Entry.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Entry.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader_Extension_EntryAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Feed_Reader_Extension_Thread_Entry
+class Zend_Feed_Reader_Extension_Thread_Entry
extends Zend_Feed_Reader_Extension_EntryAbstract
{
/**
* Get the "in-reply-to" value
- *
+ *
* @return string
*/
public function getInReplyTo()
diff --git a/libs/Zend/Feed/Reader/Extension/WellFormedWeb/Entry.php b/libs/Zend/Feed/Reader/Extension/WellFormedWeb/Entry.php
index 8c96f6e316..fe47448338 100644
--- a/libs/Zend/Feed/Reader/Extension/WellFormedWeb/Entry.php
+++ b/libs/Zend/Feed/Reader/Extension/WellFormedWeb/Entry.php
@@ -14,28 +14,28 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Entry.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Entry.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Reader
*/
-require_once 'Zend/Feed/Reader.php';
+// require_once 'Zend/Feed/Reader.php';
/**
* @see Zend_Feed_Reader_Extension_EntryAbstract
*/
-require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
+// require_once 'Zend/Feed/Reader/Extension/EntryAbstract.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Feed_Reader_Extension_WellFormedWeb_Entry
+class Zend_Feed_Reader_Extension_WellFormedWeb_Entry
extends Zend_Feed_Reader_Extension_EntryAbstract
{
/**
diff --git a/libs/Zend/Feed/Reader/Feed/Atom.php b/libs/Zend/Feed/Reader/Feed/Atom.php
index 0256e36122..8199355995 100644
--- a/libs/Zend/Feed/Reader/Feed/Atom.php
+++ b/libs/Zend/Feed/Reader/Feed/Atom.php
@@ -14,25 +14,25 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Atom.php 18655 2009-10-20 14:17:39Z padraic $
+ * @version $Id: Atom.php 22108 2010-05-05 13:44:11Z padraic $
*/
/**
* @see Zend_Feed_Reader_FeedAbstract
*/
-require_once 'Zend/Feed/Reader/FeedAbstract.php';
+// require_once 'Zend/Feed/Reader/FeedAbstract.php';
/**
* @see Zend_Feed_Reader_Extension_Atom_Feed
*/
-require_once 'Zend/Feed/Reader/Extension/Atom/Feed.php';
+// require_once 'Zend/Feed/Reader/Extension/Atom/Feed.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Reader_Feed_Atom extends Zend_Feed_Reader_FeedAbstract
@@ -41,15 +41,16 @@ class Zend_Feed_Reader_Feed_Atom extends Zend_Feed_Reader_FeedAbstract
/**
* Constructor
*
- * @param Zend_Feed_Abstract $feed
+ * @param DOMDocument $dom
* @param string $type
- * @param string $xpath
*/
- public function __construct(DomDocument $dom, $type = null)
+ public function __construct(DOMDocument $dom, $type = null)
{
parent::__construct($dom, $type);
$atomClass = Zend_Feed_Reader::getPluginLoader()->getClassName('Atom_Feed');
$this->_extensions['Atom_Feed'] = new $atomClass($dom, $this->_data['type'], $this->_xpath);
+ $atomClass = Zend_Feed_Reader::getPluginLoader()->getClassName('DublinCore_Feed');
+ $this->_extensions['DublinCore_Feed'] = new $atomClass($dom, $this->_data['type'], $this->_xpath);
foreach ($this->_extensions as $extension) {
$extension->setXpathPrefix('/atom:feed');
}
@@ -83,9 +84,9 @@ class Zend_Feed_Reader_Feed_Atom extends Zend_Feed_Reader_FeedAbstract
return $this->_data['authors'];
}
- $people = $this->getExtension('Atom')->getAuthors();
+ $authors = $this->getExtension('Atom')->getAuthors();
- $this->_data['authors'] = $people;
+ $this->_data['authors'] = $authors;
return $this->_data['authors'];
}
@@ -157,6 +158,16 @@ class Zend_Feed_Reader_Feed_Atom extends Zend_Feed_Reader_FeedAbstract
}
/**
+ * Get the feed lastBuild date. This is not implemented in Atom.
+ *
+ * @return string|null
+ */
+ public function getLastBuildDate()
+ {
+ return null;
+ }
+
+ /**
* Get the feed description
*
* @return string|null
@@ -196,7 +207,7 @@ class Zend_Feed_Reader_Feed_Atom extends Zend_Feed_Reader_FeedAbstract
return $this->_data['generator'];
}
- /**
+ /**
* Get the feed ID
*
* @return string|null
@@ -239,7 +250,7 @@ class Zend_Feed_Reader_Feed_Atom extends Zend_Feed_Reader_FeedAbstract
return $this->_data['language'];
}
-
+
/**
* Get a link to the source website
*
@@ -277,6 +288,24 @@ class Zend_Feed_Reader_Feed_Atom extends Zend_Feed_Reader_FeedAbstract
}
/**
+ * Get feed image data
+ *
+ * @return array|null
+ */
+ public function getImage()
+ {
+ if (array_key_exists('image', $this->_data)) {
+ return $this->_data['image'];
+ }
+
+ $link = $this->getExtension('Atom')->getImage();
+
+ $this->_data['image'] = $link;
+
+ return $this->_data['image'];
+ }
+
+ /**
* Get a link to the feed's XML Url
*
* @return string|null
@@ -289,6 +318,10 @@ class Zend_Feed_Reader_Feed_Atom extends Zend_Feed_Reader_FeedAbstract
$link = $this->getExtension('Atom')->getFeedLink();
+ if (is_null($link) || empty($link)) {
+ $link = $this->getOriginalSourceUri();
+ }
+
$this->_data['feedlink'] = $link;
return $this->_data['feedlink'];
@@ -312,9 +345,50 @@ class Zend_Feed_Reader_Feed_Atom extends Zend_Feed_Reader_FeedAbstract
return $this->_data['title'];
}
- /**
+ /**
+ * Get an array of any supported Pusubhubbub endpoints
+ *
+ * @return array|null
+ */
+ public function getHubs()
+ {
+ if (array_key_exists('hubs', $this->_data)) {
+ return $this->_data['hubs'];
+ }
+
+ $hubs = $this->getExtension('Atom')->getHubs();
+
+ $this->_data['hubs'] = $hubs;
+
+ return $this->_data['hubs'];
+ }
+
+ /**
+ * Get all categories
+ *
+ * @return Zend_Feed_Reader_Collection_Category
+ */
+ public function getCategories()
+ {
+ if (array_key_exists('categories', $this->_data)) {
+ return $this->_data['categories'];
+ }
+
+ $categoryCollection = $this->getExtension('Atom')->getCategories();
+
+ if (count($categoryCollection) == 0) {
+ $categoryCollection = $this->getExtension('DublinCore')->getCategories();
+ }
+
+ $this->_data['categories'] = $categoryCollection;
+
+ return $this->_data['categories'];
+ }
+
+ /**
* Read all entries to the internal entries array
*
+ * @return void
*/
protected function _indexEntries()
{
diff --git a/libs/Zend/Feed/Reader/Feed/Atom/Source.php b/libs/Zend/Feed/Reader/Feed/Atom/Source.php
new file mode 100644
index 0000000000..bdd972f93e
--- /dev/null
+++ b/libs/Zend/Feed/Reader/Feed/Atom/Source.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Atom.php 19165 2009-11-21 16:46:40Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Reader_Feed_Atom
+ */
+// require_once 'Zend/Feed/Reader/Feed/Atom.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Reader_Feed_Atom_Source extends Zend_Feed_Reader_Feed_Atom
+{
+
+ /**
+ * Constructor: Create a Source object which is largely just a normal
+ * Zend_Feed_Reader_FeedAbstract object only designed to retrieve feed level
+ * metadata from an Atom entry's source element.
+ *
+ * @param DOMElement $source
+ * @param string $xpathPrefix Passed from parent Entry object
+ * @param string $type Nearly always Atom 1.0
+ */
+ public function __construct(DOMElement $source, $xpathPrefix, $type = Zend_Feed_Reader::TYPE_ATOM_10)
+ {
+ $this->_domDocument = $source->ownerDocument;
+ $this->_xpath = new DOMXPath($this->_domDocument);
+ $this->_data['type'] = $type;
+ $this->_registerNamespaces();
+ $this->_loadExtensions();
+
+ $atomClass = Zend_Feed_Reader::getPluginLoader()->getClassName('Atom_Feed');
+ $this->_extensions['Atom_Feed'] = new $atomClass($this->_domDocument, $this->_data['type'], $this->_xpath);
+ $atomClass = Zend_Feed_Reader::getPluginLoader()->getClassName('DublinCore_Feed');
+ $this->_extensions['DublinCore_Feed'] = new $atomClass($this->_domDocument, $this->_data['type'], $this->_xpath);
+ foreach ($this->_extensions as $extension) {
+ $extension->setXpathPrefix(rtrim($xpathPrefix, '/') . '/atom:source');
+ }
+ }
+
+ /**
+ * Since this is not an Entry carrier but a vehicle for Feed metadata, any
+ * applicable Entry methods are stubbed out and do nothing.
+ */
+
+ /**
+ * @return void
+ */
+ public function count() {}
+
+ /**
+ * @return void
+ */
+ public function current() {}
+
+ /**
+ * @return void
+ */
+ public function key() {}
+
+ /**
+ * @return void
+ */
+ public function next() {}
+
+ /**
+ * @return void
+ */
+ public function rewind() {}
+
+ /**
+ * @return void
+ */
+ public function valid() {}
+
+ /**
+ * @return void
+ */
+ protected function _indexEntries() {}
+
+}
diff --git a/libs/Zend/Feed/Reader/Feed/Rss.php b/libs/Zend/Feed/Reader/Feed/Rss.php
index 2dc2ec86f4..bff78c3455 100644
--- a/libs/Zend/Feed/Reader/Feed/Rss.php
+++ b/libs/Zend/Feed/Reader/Feed/Rss.php
@@ -14,35 +14,40 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Rss.php 18367 2009-09-22 14:55:59Z padraic $
+ * @version $Id: Rss.php 22301 2010-05-26 10:15:13Z padraic $
*/
/**
* @see Zend_Feed_Reader_FeedAbstract
*/
-require_once 'Zend/Feed/Reader/FeedAbstract.php';
+// require_once 'Zend/Feed/Reader/FeedAbstract.php';
/**
* @see Zend_feed_Reader_Extension_Atom_Feed
*/
-require_once 'Zend/Feed/Reader/Extension/Atom/Feed.php';
+// require_once 'Zend/Feed/Reader/Extension/Atom/Feed.php';
/**
* @see Zend_Feed_Reader_Extension_DublinCore_Feed
*/
-require_once 'Zend/Feed/Reader/Extension/DublinCore/Feed.php';
+// require_once 'Zend/Feed/Reader/Extension/DublinCore/Feed.php';
/**
* @see Zend_Date
*/
-require_once 'Zend/Date.php';
+// require_once 'Zend/Date.php';
+
+/**
+ * @see Zend_Feed_Reader_Collection_Author
+ */
+// require_once 'Zend/Feed/Reader/Collection/Author.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Reader_Feed_Rss extends Zend_Feed_Reader_FeedAbstract
@@ -51,9 +56,8 @@ class Zend_Feed_Reader_Feed_Rss extends Zend_Feed_Reader_FeedAbstract
/**
* Constructor
*
- * @param Zend_Feed_Abstract $feed
+ * @param DOMDocument $dom
* @param string $type
- * @param string $xpath
*/
public function __construct(DomDocument $dom, $type = null)
{
@@ -74,7 +78,7 @@ class Zend_Feed_Reader_Feed_Rss extends Zend_Feed_Reader_FeedAbstract
}
}
- /**
+ /**
* Get a single author
*
* @param int $index
@@ -101,33 +105,54 @@ class Zend_Feed_Reader_Feed_Rss extends Zend_Feed_Reader_FeedAbstract
if (array_key_exists('authors', $this->_data)) {
return $this->_data['authors'];
}
-
+
$authors = array();
-
- if (empty($authors)) {
- $authors = $this->getExtension('DublinCore')->getAuthors();
- }
-
- if (empty($authors)) {
- if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
- $list = $this->_xpath->query('//author');
- } else {
- $list = $this->_xpath->query('//rss:author');
+ $authors_dc = $this->getExtension('DublinCore')->getAuthors();
+ if (!empty($authors_dc)) {
+ foreach ($authors_dc as $author) {
+ $authors[] = array(
+ 'name' => $author['name']
+ );
}
+ }
- foreach ($list as $authorObj) {
- $authors[] = $authorObj->nodeValue;
+ /**
+ * Technically RSS doesn't specific author element use at the feed level
+ * but it's supported on a "just in case" basis.
+ */
+ if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10
+ && $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
+ $list = $this->_xpath->query('//author');
+ } else {
+ $list = $this->_xpath->query('//rss:author');
+ }
+ if ($list->length) {
+ foreach ($list as $author) {
+ $string = trim($author->nodeValue);
+ $email = null;
+ $name = null;
+ $data = array();
+ // Pretty rough parsing - but it's a catchall
+ if (preg_match("/^.*@[^ ]*/", $string, $matches)) {
+ $data['email'] = trim($matches[0]);
+ if (preg_match("/\((.*)\)$/", $string, $matches)) {
+ $data['name'] = $matches[1];
+ }
+ $authors[] = $data;
+ }
}
}
- if (empty($authors)) {
+ if (count($authors) == 0) {
$authors = $this->getExtension('Atom')->getAuthors();
+ } else {
+ $authors = new Zend_Feed_Reader_Collection_Author(
+ Zend_Feed_Reader::arrayUnique($authors)
+ );
}
- if (empty($authors)) {
+ if (count($authors) == 0) {
$authors = null;
- } else {
- $authors = array_unique($authors);
}
$this->_data['authors'] = $authors;
@@ -170,7 +195,7 @@ class Zend_Feed_Reader_Feed_Rss extends Zend_Feed_Reader_FeedAbstract
return $this->_data['copyright'];
}
- /**
+ /**
* Get the feed creation date
*
* @return string|null
@@ -201,21 +226,27 @@ class Zend_Feed_Reader_Feed_Rss extends Zend_Feed_Reader_FeedAbstract
$dateModified = $this->_xpath->evaluate('string(/rss/channel/lastBuildDate)');
}
if ($dateModified) {
- $dateStandards = array(Zend_Date::RSS, Zend_Date::RFC_822,
- Zend_Date::RFC_2822, Zend_Date::DATES);
- $date = new Zend_Date;
- foreach ($dateStandards as $standard) {
- try {
- $date->set($dateModified, $standard);
- break;
- } catch (Zend_Date_Exception $e) {
- if ($standard == Zend_Date::DATES) {
- require_once 'Zend/Feed/Exception.php';
- throw new Zend_Feed_Exception(
- 'Could not load date due to unrecognised'
- .' format (should follow RFC 822 or 2822):'
- . $e->getMessage()
- );
+ $dateModifiedParsed = strtotime($dateModified);
+ if ($dateModifiedParsed) {
+ $date = new Zend_Date($dateModifiedParsed);
+ } else {
+ $dateStandards = array(Zend_Date::RSS, Zend_Date::RFC_822,
+ Zend_Date::RFC_2822, Zend_Date::DATES);
+ $date = new Zend_Date;
+ foreach ($dateStandards as $standard) {
+ try {
+ $date->set($dateModified, $standard);
+ break;
+ } catch (Zend_Date_Exception $e) {
+ if ($standard == Zend_Date::DATES) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception(
+ 'Could not load date due to unrecognised'
+ .' format (should follow RFC 822 or 2822):'
+ . $e->getMessage(),
+ 0, $e
+ );
+ }
}
}
}
@@ -240,6 +271,60 @@ class Zend_Feed_Reader_Feed_Rss extends Zend_Feed_Reader_FeedAbstract
}
/**
+ * Get the feed lastBuild date
+ *
+ * @return Zend_Date
+ */
+ public function getLastBuildDate()
+ {
+ if (array_key_exists('lastBuildDate', $this->_data)) {
+ return $this->_data['lastBuildDate'];
+ }
+
+ $lastBuildDate = null;
+ $date = null;
+
+ if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 &&
+ $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
+ $lastBuildDate = $this->_xpath->evaluate('string(/rss/channel/lastBuildDate)');
+ if ($lastBuildDate) {
+ $lastBuildDateParsed = strtotime($lastBuildDate);
+ if ($lastBuildDateParsed) {
+ $date = new Zend_Date($lastBuildDateParsed);
+ } else {
+ $dateStandards = array(Zend_Date::RSS, Zend_Date::RFC_822,
+ Zend_Date::RFC_2822, Zend_Date::DATES);
+ $date = new Zend_Date;
+ foreach ($dateStandards as $standard) {
+ try {
+ $date->set($lastBuildDate, $standard);
+ break;
+ } catch (Zend_Date_Exception $e) {
+ if ($standard == Zend_Date::DATES) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception(
+ 'Could not load date due to unrecognised'
+ .' format (should follow RFC 822 or 2822):'
+ . $e->getMessage(),
+ 0, $e
+ );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!$date) {
+ $date = null;
+ }
+
+ $this->_data['lastBuildDate'] = $date;
+
+ return $this->_data['lastBuildDate'];
+ }
+
+ /**
* Get the feed description
*
* @return string|null
@@ -318,6 +403,60 @@ class Zend_Feed_Reader_Feed_Rss extends Zend_Feed_Reader_FeedAbstract
}
/**
+ * Get the feed image data
+ *
+ * @return array|null
+ */
+ public function getImage()
+ {
+ if (array_key_exists('image', $this->_data)) {
+ return $this->_data['image'];
+ }
+
+ if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 &&
+ $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
+ $list = $this->_xpath->query('/rss/channel/image');
+ $prefix = '/rss/channel/image[1]';
+ } else {
+ $list = $this->_xpath->query('/rdf:RDF/rss:channel/rss:image');
+ $prefix = '/rdf:RDF/rss:channel/rss:image[1]';
+ }
+ if ($list->length > 0) {
+ $image = array();
+ $value = $this->_xpath->evaluate('string(' . $prefix . '/url)');
+ if ($value) {
+ $image['uri'] = $value;
+ }
+ $value = $this->_xpath->evaluate('string(' . $prefix . '/link)');
+ if ($value) {
+ $image['link'] = $value;
+ }
+ $value = $this->_xpath->evaluate('string(' . $prefix . '/title)');
+ if ($value) {
+ $image['title'] = $value;
+ }
+ $value = $this->_xpath->evaluate('string(' . $prefix . '/height)');
+ if ($value) {
+ $image['height'] = $value;
+ }
+ $value = $this->_xpath->evaluate('string(' . $prefix . '/width)');
+ if ($value) {
+ $image['width'] = $value;
+ }
+ $value = $this->_xpath->evaluate('string(' . $prefix . '/description)');
+ if ($value) {
+ $image['description'] = $value;
+ }
+ } else {
+ $image = null;
+ }
+
+ $this->_data['image'] = $image;
+
+ return $this->_data['image'];
+ }
+
+ /**
* Get the feed language
*
* @return string|null
@@ -404,8 +543,8 @@ class Zend_Feed_Reader_Feed_Rss extends Zend_Feed_Reader_FeedAbstract
$link = $this->getExtension('Atom')->getFeedLink();
- if (!$link) {
- $link = null;
+ if (is_null($link) || empty($link)) {
+ $link = $this->getOriginalSourceUri();
}
$this->_data['feedlink'] = $link;
@@ -438,9 +577,6 @@ class Zend_Feed_Reader_Feed_Rss extends Zend_Feed_Reader_FeedAbstract
} else {
$generator = $this->_xpath->evaluate('string(/rdf:RDF/rss:channel/atom:generator)');
}
- if ($generator) {
- $generator = html_entity_decode($generator, ENT_QUOTES, $this->getEncoding());
- }
}
if (empty($generator)) {
@@ -493,7 +629,71 @@ class Zend_Feed_Reader_Feed_Rss extends Zend_Feed_Reader_FeedAbstract
return $this->_data['title'];
}
- /**
+ /**
+ * Get an array of any supported Pusubhubbub endpoints
+ *
+ * @return array|null
+ */
+ public function getHubs()
+ {
+ if (array_key_exists('hubs', $this->_data)) {
+ return $this->_data['hubs'];
+ }
+
+ $hubs = $this->getExtension('Atom')->getHubs();
+
+ if (empty($hubs)) {
+ $hubs = null;
+ } else {
+ $hubs = array_unique($hubs);
+ }
+
+ $this->_data['hubs'] = $hubs;
+
+ return $this->_data['hubs'];
+ }
+
+ /**
+ * Get all categories
+ *
+ * @return Zend_Feed_Reader_Collection_Category
+ */
+ public function getCategories()
+ {
+ if (array_key_exists('categories', $this->_data)) {
+ return $this->_data['categories'];
+ }
+
+ if ($this->getType() !== Zend_Feed_Reader::TYPE_RSS_10 &&
+ $this->getType() !== Zend_Feed_Reader::TYPE_RSS_090) {
+ $list = $this->_xpath->query('/rss/channel//category');
+ } else {
+ $list = $this->_xpath->query('/rdf:RDF/rss:channel//rss:category');
+ }
+
+ if ($list->length) {
+ $categoryCollection = new Zend_Feed_Reader_Collection_Category;
+ foreach ($list as $category) {
+ $categoryCollection[] = array(
+ 'term' => $category->nodeValue,
+ 'scheme' => $category->getAttribute('domain'),
+ 'label' => $category->nodeValue,
+ );
+ }
+ } else {
+ $categoryCollection = $this->getExtension('DublinCore')->getCategories();
+ }
+
+ if (count($categoryCollection) == 0) {
+ $categoryCollection = $this->getExtension('Atom')->getCategories();
+ }
+
+ $this->_data['categories'] = $categoryCollection;
+
+ return $this->_data['categories'];
+ }
+
+ /**
* Read all entries to the internal entries array
*
*/
diff --git a/libs/Zend/Feed/Reader/FeedAbstract.php b/libs/Zend/Feed/Reader/FeedAbstract.php
index 1e8da71726..bda9f23b46 100644
--- a/libs/Zend/Feed/Reader/FeedAbstract.php
+++ b/libs/Zend/Feed/Reader/FeedAbstract.php
@@ -14,41 +14,30 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: FeedAbstract.php 16966 2009-07-22 15:22:18Z padraic $
+ * @version $Id: FeedAbstract.php 22093 2010-05-04 12:55:06Z padraic $
*/
/**
* @see Zend_Feed_Reader
*/
-require_once 'Zend/Feed/Reader.php';
-
-/**
- * @see Zend_Feed_Reader_Entry_Atom
- */
-require_once 'Zend/Feed/Reader/Entry/Atom.php';
-
-
-/**
- * @see Zend_Feed_Reader_Entry_Rss
- */
-require_once 'Zend/Feed/Reader/Entry/Rss.php';
+// require_once 'Zend/Feed/Reader.php';
/**
* @see Zend_feed_Reader_FeedInterface
*/
-require_once 'Zend/Feed/Reader/FeedInterface.php';
+// require_once 'Zend/Feed/Reader/FeedInterface.php';
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Feed_Reader_FeedAbstract implements Zend_Feed_Reader_FeedInterface
{
- /**
+ /**
* Parsed feed data
*
* @var array
@@ -83,9 +72,21 @@ abstract class Zend_Feed_Reader_FeedAbstract implements Zend_Feed_Reader_FeedInt
*/
protected $_xpath = null;
+ /**
+ * Array of loaded extensions
+ *
+ * @var array
+ */
protected $_extensions = array();
/**
+ * Original Source URI (set if imported from a URI)
+ *
+ * @var string
+ */
+ protected $_originalSourceUri = null;
+
+ /**
* Constructor
*
* @param DomDocument The DOM object for the feed's XML
@@ -106,7 +107,30 @@ abstract class Zend_Feed_Reader_FeedAbstract implements Zend_Feed_Reader_FeedInt
$this->_loadExtensions();
}
- /**
+ /**
+ * Set an original source URI for the feed being parsed. This value
+ * is returned from getFeedLink() method if the feed does not carry
+ * a self-referencing URI.
+ *
+ * @param string $uri
+ */
+ public function setOriginalSourceUri($uri)
+ {
+ $this->_originalSourceUri = $uri;
+ }
+
+ /**
+ * Get an original source URI for the feed being parsed. Returns null if
+ * unset or the feed was not imported from a URI.
+ *
+ * @return string|null
+ */
+ public function getOriginalSourceUri()
+ {
+ return $this->_originalSourceUri;
+ }
+
+ /**
* Get the number of feed entries.
* Required by the Iterator interface.
*
@@ -117,10 +141,10 @@ abstract class Zend_Feed_Reader_FeedAbstract implements Zend_Feed_Reader_FeedInt
return count($this->_entries);
}
- /**
+ /**
* Return the current entry
*
- * @return Zend_Feed_Reader_Entry_Interface
+ * @return Zend_Feed_Reader_EntryInterface
*/
public function current()
{
@@ -153,6 +177,9 @@ abstract class Zend_Feed_Reader_FeedAbstract implements Zend_Feed_Reader_FeedInt
public function getEncoding()
{
$assumed = $this->getDomDocument()->encoding;
+ if (empty($assumed)) {
+ $assumed = 'UTF-8';
+ }
return $assumed;
}
@@ -196,7 +223,7 @@ abstract class Zend_Feed_Reader_FeedAbstract implements Zend_Feed_Reader_FeedInt
return $this->_data['type'];
}
- /**
+ /**
* Return the current feed key
*
* @return unknown
@@ -206,7 +233,7 @@ abstract class Zend_Feed_Reader_FeedAbstract implements Zend_Feed_Reader_FeedInt
return $this->_entriesKey;
}
- /**
+ /**
* Move the feed pointer forward
*
*/
@@ -225,16 +252,6 @@ abstract class Zend_Feed_Reader_FeedAbstract implements Zend_Feed_Reader_FeedInt
}
/**
- * Return the feed as an array
- *
- * @return array
- */
- public function toArray() // untested
- {
- return $this->_data;
- }
-
- /**
* Check to see if the iterator is still valid
*
* @return boolean
@@ -256,7 +273,7 @@ abstract class Zend_Feed_Reader_FeedAbstract implements Zend_Feed_Reader_FeedInt
return call_user_func_array(array($extension, $method), $args);
}
}
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Method: ' . $method
. 'does not exist and could not be located on a registered Extension');
}
diff --git a/libs/Zend/Feed/Reader/FeedInterface.php b/libs/Zend/Feed/Reader/FeedInterface.php
index 3278f3ea75..35060bafce 100644
--- a/libs/Zend/Feed/Reader/FeedInterface.php
+++ b/libs/Zend/Feed/Reader/FeedInterface.php
@@ -14,15 +14,15 @@
*
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: FeedInterface.php 16953 2009-07-22 11:57:25Z padraic $
+ * @version $Id: FeedInterface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Feed_Reader
- * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Feed_Reader_FeedInterface extends Iterator, Countable
@@ -111,5 +111,12 @@ interface Zend_Feed_Reader_FeedInterface extends Iterator, Countable
* @return string|null
*/
public function getTitle();
+
+ /**
+ * Get all categories
+ *
+ * @return Zend_Feed_Reader_Collection_Category
+ */
+ public function getCategories();
}
diff --git a/libs/Zend/Feed/Reader/FeedSet.php b/libs/Zend/Feed/Reader/FeedSet.php
new file mode 100644
index 0000000000..57ccbf6056
--- /dev/null
+++ b/libs/Zend/Feed/Reader/FeedSet.php
@@ -0,0 +1,148 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: FeedSet.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @see Zend_Feed_Reader
+ */
+// require_once 'Zend/Feed/Reader.php';
+
+/**
+ * @see Zend_Uri
+ */
+// require_once 'Zend/Uri.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Reader
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Reader_FeedSet extends ArrayObject
+{
+
+ public $rss = null;
+
+ public $rdf = null;
+
+ public $atom = null;
+
+ /**
+ * Import a DOMNodeList from any document containing a set of links
+ * for alternate versions of a document, which will normally refer to
+ * RSS/RDF/Atom feeds for the current document.
+ *
+ * All such links are stored internally, however the first instance of
+ * each RSS, RDF or Atom type has its URI stored as a public property
+ * as a shortcut where the use case is simply to get a quick feed ref.
+ *
+ * Note that feeds are not loaded at this point, but will be lazy
+ * loaded automatically when each links 'feed' array key is accessed.
+ *
+ * @param DOMNodeList $links
+ * @param string $uri
+ * @return void
+ */
+ public function addLinks(DOMNodeList $links, $uri)
+ {
+ foreach ($links as $link) {
+ if (strtolower($link->getAttribute('rel')) !== 'alternate'
+ || !$link->getAttribute('type') || !$link->getAttribute('href')) {
+ continue;
+ }
+ if (!isset($this->rss) && $link->getAttribute('type') == 'application/rss+xml') {
+ $this->rss = $this->_absolutiseUri(trim($link->getAttribute('href')), $uri);
+ } elseif(!isset($this->atom) && $link->getAttribute('type') == 'application/atom+xml') {
+ $this->atom = $this->_absolutiseUri(trim($link->getAttribute('href')), $uri);
+ } elseif(!isset($this->rdf) && $link->getAttribute('type') == 'application/rdf+xml') {
+ $this->rdf = $this->_absolutiseUri(trim($link->getAttribute('href')), $uri);
+ }
+ $this[] = new self(array(
+ 'rel' => 'alternate',
+ 'type' => $link->getAttribute('type'),
+ 'href' => $this->_absolutiseUri(trim($link->getAttribute('href')), $uri),
+ ));
+ }
+ }
+
+ /**
+ * Attempt to turn a relative URI into an absolute URI
+ */
+ protected function _absolutiseUri($link, $uri = null)
+ {
+ if (!Zend_Uri::check($link)) {
+ if (!is_null($uri)) {
+ $uri = Zend_Uri::factory($uri);
+
+ if ($link[0] !== '/') {
+ $link = $uri->getPath() . '/' . $link;
+ }
+
+ $link = $uri->getScheme() . '://' . $uri->getHost() . '/' . $this->_canonicalizePath($link);
+ if (!Zend_Uri::check($link)) {
+ $link = null;
+ }
+ }
+ }
+ return $link;
+ }
+
+ /**
+ * Canonicalize relative path
+ */
+ protected function _canonicalizePath($path)
+ {
+ $parts = array_filter(explode('/', $path));
+ $absolutes = array();
+ foreach ($parts as $part) {
+ if ('.' == $part) {
+ continue;
+ }
+ if ('..' == $part) {
+ array_pop($absolutes);
+ } else {
+ $absolutes[] = $part;
+ }
+ }
+ return implode('/', $absolutes);
+ }
+
+ /**
+ * Supports lazy loading of feeds using Zend_Feed_Reader::import() but
+ * delegates any other operations to the parent class.
+ *
+ * @param string $offset
+ * @return mixed
+ * @uses Zend_Feed_Reader
+ */
+ public function offsetGet($offset)
+ {
+ if ($offset == 'feed' && !$this->offsetExists('feed')) {
+ if (!$this->offsetExists('href')) {
+ return null;
+ }
+ $feed = Zend_Feed_Reader::import($this->offsetGet('href'));
+ $this->offsetSet('feed', $feed);
+ return $feed;
+ }
+ return parent::offsetGet($offset);
+ }
+
+}
diff --git a/libs/Zend/Feed/Rss.php b/libs/Zend/Feed/Rss.php
index 351dcdf2e5..19eaa8ec19 100644
--- a/libs/Zend/Feed/Rss.php
+++ b/libs/Zend/Feed/Rss.php
@@ -15,21 +15,21 @@
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Rss.php 18266 2009-09-18 18:32:30Z padraic $
+ * @version $Id: Rss.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Feed_Abstract
*/
-require_once 'Zend/Feed/Abstract.php';
+// require_once 'Zend/Feed/Abstract.php';
/**
* @see Zend_Feed_Entry_Rss
*/
-require_once 'Zend/Feed/Entry/Rss.php';
+// require_once 'Zend/Feed/Entry/Rss.php';
/**
@@ -43,7 +43,7 @@ require_once 'Zend/Feed/Entry/Rss.php';
*
* @category Zend
* @package Zend_Feed
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Feed_Rss extends Zend_Feed_Abstract
@@ -82,7 +82,7 @@ class Zend_Feed_Rss extends Zend_Feed_Abstract
// Find the base channel element and create an alias to it.
$rdfTags = $this->_element->getElementsByTagNameNS('http://www.w3.org/1999/02/22-rdf-syntax-ns#', 'RDF');
if ($rdfTags->length != 0) {
- $this->_element = $rdfTags->item(0);
+ $this->_element = $rdfTags->item(0);
} else {
$this->_element = $this->_element->getElementsByTagName('channel')->item(0);
}
@@ -90,7 +90,7 @@ class Zend_Feed_Rss extends Zend_Feed_Abstract
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('No root <channel> element found, cannot parse channel.');
}
@@ -282,11 +282,12 @@ class Zend_Feed_Rss extends Zend_Feed_Abstract
$author = '';
$email = '';
if (isset($array->itunes->owner)) {
- if (isset($array->itunes->owner['name'])) {
- $author = $array->itunes->owner['name'];
+ $itunesOwner = $array->itunes->owner;
+ if (isset($itunesOwner['name'])) {
+ $author = $itunesOwner['name'];
}
- if (isset($array->itunes->owner['email'])) {
- $email = $array->itunes->owner['email'];
+ if (isset($itunesOwner['email'])) {
+ $email = $itunesOwner['email'];
}
}
if (empty($author) && isset($array->author)) {
@@ -411,6 +412,9 @@ class Zend_Feed_Rss extends Zend_Feed_Abstract
if (isset($dataentry->guid)) {
$guid = $this->_element->createElement('guid', $dataentry->guid);
+ if (!Zend_Uri::check($dataentry->guid)) {
+ $guid->setAttribute('isPermaLink', 'false');
+ }
$item->appendChild($guid);
}
@@ -514,7 +518,7 @@ class Zend_Feed_Rss extends Zend_Feed_Abstract
/**
* @see Zend_Feed_Exception
*/
- require_once 'Zend/Feed/Exception.php';
+ // require_once 'Zend/Feed/Exception.php';
throw new Zend_Feed_Exception('Cannot send RSS because headers have already been sent.');
}
diff --git a/libs/Zend/Feed/Writer.php b/libs/Zend/Feed/Writer.php
new file mode 100644
index 0000000000..1a40f63cd9
--- /dev/null
+++ b/libs/Zend/Feed/Writer.php
@@ -0,0 +1,267 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Writer.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer
+{
+ /**
+ * Namespace constants
+ */
+ const NAMESPACE_ATOM_03 = 'http://purl.org/atom/ns#';
+ const NAMESPACE_ATOM_10 = 'http://www.w3.org/2005/Atom';
+ const NAMESPACE_RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
+ const NAMESPACE_RSS_090 = 'http://my.netscape.com/rdf/simple/0.9/';
+ const NAMESPACE_RSS_10 = 'http://purl.org/rss/1.0/';
+
+ /**
+ * Feed type constants
+ */
+ const TYPE_ANY = 'any';
+ const TYPE_ATOM_03 = 'atom-03';
+ const TYPE_ATOM_10 = 'atom-10';
+ const TYPE_ATOM_ANY = 'atom';
+ const TYPE_RSS_090 = 'rss-090';
+ const TYPE_RSS_091 = 'rss-091';
+ const TYPE_RSS_091_NETSCAPE = 'rss-091n';
+ const TYPE_RSS_091_USERLAND = 'rss-091u';
+ const TYPE_RSS_092 = 'rss-092';
+ const TYPE_RSS_093 = 'rss-093';
+ const TYPE_RSS_094 = 'rss-094';
+ const TYPE_RSS_10 = 'rss-10';
+ const TYPE_RSS_20 = 'rss-20';
+ const TYPE_RSS_ANY = 'rss';
+
+ /**
+ * PluginLoader instance used by component
+ *
+ * @var Zend_Loader_PluginLoader_Interface
+ */
+ protected static $_pluginLoader = null;
+
+ /**
+ * Path on which to search for Extension classes
+ *
+ * @var array
+ */
+ protected static $_prefixPaths = array();
+
+ /**
+ * Array of registered extensions by class postfix (after the base class
+ * name) across four categories - data containers and renderers for entry
+ * and feed levels.
+ *
+ * @var array
+ */
+ protected static $_extensions = array(
+ 'entry' => array(),
+ 'feed' => array(),
+ 'entryRenderer' => array(),
+ 'feedRenderer' => array(),
+ );
+
+ /**
+ * Set plugin loader for use with Extensions
+ *
+ * @param Zend_Loader_PluginLoader_Interface
+ */
+ public static function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader)
+ {
+ self::$_pluginLoader = $loader;
+ }
+
+ /**
+ * Get plugin loader for use with Extensions
+ *
+ * @return Zend_Loader_PluginLoader_Interface
+ */
+ public static function getPluginLoader()
+ {
+ if (!isset(self::$_pluginLoader)) {
+ // require_once 'Zend/Loader/PluginLoader.php';
+ self::$_pluginLoader = new Zend_Loader_PluginLoader(array(
+ 'Zend_Feed_Writer_Extension_' => 'Zend/Feed/Writer/Extension/',
+ ));
+ }
+ return self::$_pluginLoader;
+ }
+
+ /**
+ * Add prefix path for loading Extensions
+ *
+ * @param string $prefix
+ * @param string $path
+ * @return void
+ */
+ public static function addPrefixPath($prefix, $path)
+ {
+ $prefix = rtrim($prefix, '_');
+ $path = rtrim($path, DIRECTORY_SEPARATOR);
+ self::getPluginLoader()->addPrefixPath($prefix, $path);
+ }
+
+ /**
+ * Add multiple Extension prefix paths at once
+ *
+ * @param array $spec
+ * @return void
+ */
+ public static function addPrefixPaths(array $spec)
+ {
+ if (isset($spec['prefix']) && isset($spec['path'])) {
+ self::addPrefixPath($spec['prefix'], $spec['path']);
+ }
+ foreach ($spec as $prefixPath) {
+ if (isset($prefixPath['prefix']) && isset($prefixPath['path'])) {
+ self::addPrefixPath($prefixPath['prefix'], $prefixPath['path']);
+ }
+ }
+ }
+
+ /**
+ * Register an Extension by name
+ *
+ * @param string $name
+ * @return void
+ * @throws Zend_Feed_Exception if unable to resolve Extension class
+ */
+ public static function registerExtension($name)
+ {
+ $feedName = $name . '_Feed';
+ $entryName = $name . '_Entry';
+ $feedRendererName = $name . '_Renderer_Feed';
+ $entryRendererName = $name . '_Renderer_Entry';
+ if (self::isRegistered($name)) {
+ if (self::getPluginLoader()->isLoaded($feedName)
+ || self::getPluginLoader()->isLoaded($entryName)
+ || self::getPluginLoader()->isLoaded($feedRendererName)
+ || self::getPluginLoader()->isLoaded($entryRendererName)
+ ) {
+ return;
+ }
+ }
+ try {
+ self::getPluginLoader()->load($feedName);
+ self::$_extensions['feed'][] = $feedName;
+ } catch (Zend_Loader_PluginLoader_Exception $e) {
+ }
+ try {
+ self::getPluginLoader()->load($entryName);
+ self::$_extensions['entry'][] = $entryName;
+ } catch (Zend_Loader_PluginLoader_Exception $e) {
+ }
+ try {
+ self::getPluginLoader()->load($feedRendererName);
+ self::$_extensions['feedRenderer'][] = $feedRendererName;
+ } catch (Zend_Loader_PluginLoader_Exception $e) {
+ }
+ try {
+ self::getPluginLoader()->load($entryRendererName);
+ self::$_extensions['entryRenderer'][] = $entryRendererName;
+ } catch (Zend_Loader_PluginLoader_Exception $e) {
+ }
+ if (!self::getPluginLoader()->isLoaded($feedName)
+ && !self::getPluginLoader()->isLoaded($entryName)
+ && !self::getPluginLoader()->isLoaded($feedRendererName)
+ && !self::getPluginLoader()->isLoaded($entryRendererName)
+ ) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Could not load extension: ' . $name
+ . 'using Plugin Loader. Check prefix paths are configured and extension exists.');
+ }
+ }
+
+ /**
+ * Is a given named Extension registered?
+ *
+ * @param string $extensionName
+ * @return boolean
+ */
+ public static function isRegistered($extensionName)
+ {
+ $feedName = $extensionName . '_Feed';
+ $entryName = $extensionName . '_Entry';
+ $feedRendererName = $extensionName . '_Renderer_Feed';
+ $entryRendererName = $extensionName . '_Renderer_Entry';
+ if (in_array($feedName, self::$_extensions['feed'])
+ || in_array($entryName, self::$_extensions['entry'])
+ || in_array($feedRendererName, self::$_extensions['feedRenderer'])
+ || in_array($entryRendererName, self::$_extensions['entryRenderer'])
+ ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get a list of extensions
+ *
+ * @return array
+ */
+ public static function getExtensions()
+ {
+ return self::$_extensions;
+ }
+
+ /**
+ * Reset class state to defaults
+ *
+ * @return void
+ */
+ public static function reset()
+ {
+ self::$_pluginLoader = null;
+ self::$_prefixPaths = array();
+ self::$_extensions = array(
+ 'entry' => array(),
+ 'feed' => array(),
+ 'entryRenderer' => array(),
+ 'feedRenderer' => array(),
+ );
+ }
+
+ /**
+ * Register core (default) extensions
+ *
+ * @return void
+ */
+ public static function registerCoreExtensions()
+ {
+ self::registerExtension('DublinCore');
+ self::registerExtension('Content');
+ self::registerExtension('Atom');
+ self::registerExtension('Slash');
+ self::registerExtension('WellFormedWeb');
+ self::registerExtension('Threading');
+ self::registerExtension('ITunes');
+ }
+
+ public static function lcfirst($str)
+ {
+ $str[0] = strtolower($str[0]);
+ return $str;
+ }
+
+}
diff --git a/libs/Zend/Feed/Writer/Deleted.php b/libs/Zend/Feed/Writer/Deleted.php
new file mode 100644
index 0000000000..19bb56b49e
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Deleted.php
@@ -0,0 +1,202 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Feed.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+// require_once 'Zend/Feed/Writer/Feed/FeedAbstract.php';
+
+ /**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Deleted
+{
+
+ /**
+ * Internal array containing all data associated with this entry or item.
+ *
+ * @var array
+ */
+ protected $_data = array();
+
+ /**
+ * Holds the value "atom" or "rss" depending on the feed type set when
+ * when last exported.
+ *
+ * @var string
+ */
+ protected $_type = null;
+
+ /**
+ * Set the feed character encoding
+ *
+ * @return string|null
+ */
+ public function setEncoding($encoding)
+ {
+ if (empty($encoding) || !is_string($encoding)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['encoding'] = $encoding;
+ }
+
+ /**
+ * Get the feed character encoding
+ *
+ * @return string|null
+ */
+ public function getEncoding()
+ {
+ if (!array_key_exists('encoding', $this->_data)) {
+ return 'UTF-8';
+ }
+ return $this->_data['encoding'];
+ }
+
+ /**
+ * Unset a specific data point
+ *
+ * @param string $name
+ */
+ public function remove($name)
+ {
+ if (isset($this->_data[$name])) {
+ unset($this->_data[$name]);
+ }
+ }
+
+ /**
+ * Set the current feed type being exported to "rss" or "atom". This allows
+ * other objects to gracefully choose whether to execute or not, depending
+ * on their appropriateness for the current type, e.g. renderers.
+ *
+ * @param string $type
+ */
+ public function setType($type)
+ {
+ $this->_type = $type;
+ }
+
+ /**
+ * Retrieve the current or last feed type exported.
+ *
+ * @return string Value will be "rss" or "atom"
+ */
+ public function getType()
+ {
+ return $this->_type;
+ }
+
+ public function setReference($reference)
+ {
+ if (empty($reference) || !is_string($reference)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: reference must be a non-empty string');
+ }
+ $this->_data['reference'] = $reference;
+ }
+
+ public function getReference()
+ {
+ if (!array_key_exists('reference', $this->_data)) {
+ return null;
+ }
+ return $this->_data['reference'];
+ }
+
+ public function setWhen($date = null)
+ {
+ $zdate = null;
+ if (is_null($date)) {
+ $zdate = new Zend_Date;
+ } elseif (ctype_digit($date) && strlen($date) == 10) {
+ $zdate = new Zend_Date($date, Zend_Date::TIMESTAMP);
+ } elseif ($date instanceof Zend_Date) {
+ $zdate = $date;
+ } else {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid Zend_Date object or UNIX Timestamp passed as parameter');
+ }
+ $this->_data['when'] = $zdate;
+ }
+
+ public function getWhen()
+ {
+ if (!array_key_exists('when', $this->_data)) {
+ return null;
+ }
+ return $this->_data['when'];
+ }
+
+ public function setBy(array $by)
+ {
+ $author = array();
+ if (!array_key_exists('name', $by)
+ || empty($by['name'])
+ || !is_string($by['name'])
+ ) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: author array must include a "name" key with a non-empty string value');
+ }
+ $author['name'] = $by['name'];
+ if (isset($by['email'])) {
+ if (empty($by['email']) || !is_string($by['email'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "email" array value must be a non-empty string');
+ }
+ $author['email'] = $by['email'];
+ }
+ if (isset($by['uri'])) {
+ if (empty($by['uri'])
+ || !is_string($by['uri'])
+ || !Zend_Uri::check($by['uri'])
+ ) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "uri" array value must be a non-empty string and valid URI/IRI');
+ }
+ $author['uri'] = $by['uri'];
+ }
+ $this->_data['by'] = $author;
+ }
+
+ public function getBy()
+ {
+ if (!array_key_exists('by', $this->_data)) {
+ return null;
+ }
+ return $this->_data['by'];
+ }
+
+ public function setComment($comment)
+ {
+ $this->_data['comment'] = $comment;
+ }
+
+ public function getComment()
+ {
+ if (!array_key_exists('comment', $this->_data)) {
+ return null;
+ }
+ return $this->_data['comment'];
+ }
+
+}
diff --git a/libs/Zend/Feed/Writer/Entry.php b/libs/Zend/Feed/Writer/Entry.php
new file mode 100644
index 0000000000..01d290e6fb
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Entry.php
@@ -0,0 +1,761 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Entry.php 22065 2010-04-30 14:04:57Z padraic $
+ */
+
+/**
+ * @see Zend_Date
+ */
+// require_once 'Zend/Date.php';
+
+/**
+ * @see Zend_Date
+ */
+// require_once 'Zend/Uri.php';
+
+// require_once 'Zend/Feed/Writer/Source.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Entry
+{
+
+ /**
+ * Internal array containing all data associated with this entry or item.
+ *
+ * @var array
+ */
+ protected $_data = array();
+
+ /**
+ * Registered extensions
+ *
+ * @var array
+ */
+ protected $_extensions = array();
+
+ /**
+ * Holds the value "atom" or "rss" depending on the feed type set when
+ * when last exported.
+ *
+ * @var string
+ */
+ protected $_type = null;
+
+ /**
+ * Constructor: Primarily triggers the registration of core extensions and
+ * loads those appropriate to this data container.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ Zend_Feed_Writer::registerCoreExtensions();
+ $this->_loadExtensions();
+ }
+
+ /**
+ * Set a single author
+ *
+ * @param int $index
+ * @return string|null
+ */
+ public function addAuthor($name, $email = null, $uri = null)
+ {
+ $author = array();
+ if (is_array($name)) {
+ if (!array_key_exists('name', $name)
+ || empty($name['name'])
+ || !is_string($name['name'])
+ ) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: author array must include a "name" key with a non-empty string value');
+ }
+ $author['name'] = $name['name'];
+ if (isset($name['email'])) {
+ if (empty($name['email']) || !is_string($name['email'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "email" array value must be a non-empty string');
+ }
+ $author['email'] = $name['email'];
+ }
+ if (isset($name['uri'])) {
+ if (empty($name['uri'])
+ || !is_string($name['uri'])
+ || !Zend_Uri::check($name['uri'])
+ ) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "uri" array value must be a non-empty string and valid URI/IRI');
+ }
+ $author['uri'] = $name['uri'];
+ }
+ /**
+ * @deprecated
+ * Array notation (above) is preferred and will be the sole supported input from ZF 2.0
+ */
+ } else {
+ if (empty($name['name']) || !is_string($name['name'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "name" must be a non-empty string value');
+ }
+ $author['name'] = $name;
+ if (isset($email)) {
+ if (empty($email) || !is_string($email)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "email" value must be a non-empty string');
+ }
+ $author['email'] = $email;
+ }
+ if (isset($uri)) {
+ if (empty($uri) || !is_string($uri) || !Zend_Uri::check($uri)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "uri" value must be a non-empty string and valid URI/IRI');
+ }
+ $author['uri'] = $uri;
+ }
+ }
+ $this->_data['authors'][] = $author;
+ }
+
+ /**
+ * Set an array with feed authors
+ *
+ * @return array
+ */
+ public function addAuthors(array $authors)
+ {
+ foreach($authors as $author) {
+ $this->addAuthor($author);
+ }
+ }
+
+ /**
+ * Set the feed character encoding
+ *
+ * @return string|null
+ */
+ public function setEncoding($encoding)
+ {
+ if (empty($encoding) || !is_string($encoding)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['encoding'] = $encoding;
+ }
+
+ /**
+ * Get the feed character encoding
+ *
+ * @return string|null
+ */
+ public function getEncoding()
+ {
+ if (!array_key_exists('encoding', $this->_data)) {
+ return 'UTF-8';
+ }
+ return $this->_data['encoding'];
+ }
+
+ /**
+ * Set the copyright entry
+ *
+ * @return string|null
+ */
+ public function setCopyright($copyright)
+ {
+ if (empty($copyright) || !is_string($copyright)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['copyright'] = $copyright;
+ }
+
+ /**
+ * Set the entry's content
+ *
+ * @return string|null
+ */
+ public function setContent($content)
+ {
+ if (empty($content) || !is_string($content)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['content'] = $content;
+ }
+
+ /**
+ * Set the feed creation date
+ *
+ * @return string|null
+ */
+ public function setDateCreated($date = null)
+ {
+ $zdate = null;
+ if (is_null($date)) {
+ $zdate = new Zend_Date;
+ } elseif (ctype_digit($date) && strlen($date) == 10) {
+ $zdate = new Zend_Date($date, Zend_Date::TIMESTAMP);
+ } elseif ($date instanceof Zend_Date) {
+ $zdate = $date;
+ } else {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid Zend_Date object or UNIX Timestamp passed as parameter');
+ }
+ $this->_data['dateCreated'] = $zdate;
+ }
+
+ /**
+ * Set the feed modification date
+ *
+ * @return string|null
+ */
+ public function setDateModified($date = null)
+ {
+ $zdate = null;
+ if (is_null($date)) {
+ $zdate = new Zend_Date;
+ } elseif (ctype_digit($date) && strlen($date) == 10) {
+ $zdate = new Zend_Date($date, Zend_Date::TIMESTAMP);
+ } elseif ($date instanceof Zend_Date) {
+ $zdate = $date;
+ } else {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid Zend_Date object or UNIX Timestamp passed as parameter');
+ }
+ $this->_data['dateModified'] = $zdate;
+ }
+
+ /**
+ * Set the feed description
+ *
+ * @return string|null
+ */
+ public function setDescription($description)
+ {
+ if (empty($description) || !is_string($description)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['description'] = $description;
+ }
+
+ /**
+ * Set the feed ID
+ *
+ * @return string|null
+ */
+ public function setId($id)
+ {
+ if (empty($id) || !is_string($id)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['id'] = $id;
+ }
+
+ /**
+ * Set a link to the HTML source of this entry
+ *
+ * @return string|null
+ */
+ public function setLink($link)
+ {
+ if (empty($link) || !is_string($link) || !Zend_Uri::check($link)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string and valid URI/IRI');
+ }
+ $this->_data['link'] = $link;
+ }
+
+ /**
+ * Set the number of comments associated with this entry
+ *
+ * @return string|null
+ */
+ public function setCommentCount($count)
+ {
+ if (empty($count) || !is_numeric($count) || (int) $count < 0) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "count" must be a non-empty integer number');
+ }
+ $this->_data['commentCount'] = (int) $count;
+ }
+
+ /**
+ * Set a link to a HTML page containing comments associated with this entry
+ *
+ * @return string|null
+ */
+ public function setCommentLink($link)
+ {
+ if (empty($link) || !is_string($link) || !Zend_Uri::check($link)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "link" must be a non-empty string and valid URI/IRI');
+ }
+ $this->_data['commentLink'] = $link;
+ }
+
+ /**
+ * Set a link to an XML feed for any comments associated with this entry
+ *
+ * @return string|null
+ */
+ public function setCommentFeedLink(array $link)
+ {
+ if (!isset($link['uri']) || !is_string($link['uri']) || !Zend_Uri::check($link['uri'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "link" must be a non-empty string and valid URI/IRI');
+ }
+ if (!isset($link['type']) || !in_array($link['type'], array('atom', 'rss', 'rdf'))) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "type" must be one'
+ . ' of "atom", "rss" or "rdf"');
+ }
+ if (!isset($this->_data['commentFeedLinks'])) {
+ $this->_data['commentFeedLinks'] = array();
+ }
+ $this->_data['commentFeedLinks'][] = $link;
+ }
+
+ /**
+ * Set a links to an XML feed for any comments associated with this entry.
+ * Each link is an array with keys "uri" and "type", where type is one of:
+ * "atom", "rss" or "rdf".
+ *
+ * @return string|null
+ */
+ public function setCommentFeedLinks(array $links)
+ {
+ foreach ($links as $link) {
+ $this->setCommentFeedLink($link);
+ }
+ }
+
+ /**
+ * Set the feed title
+ *
+ * @return string|null
+ */
+ public function setTitle($title)
+ {
+ if (empty($title) || !is_string($title)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['title'] = $title;
+ }
+
+ /**
+ * Get an array with feed authors
+ *
+ * @return array
+ */
+ public function getAuthors()
+ {
+ if (!array_key_exists('authors', $this->_data)) {
+ return null;
+ }
+ return $this->_data['authors'];
+ }
+
+ /**
+ * Get the entry content
+ *
+ * @return string
+ */
+ public function getContent()
+ {
+ if (!array_key_exists('content', $this->_data)) {
+ return null;
+ }
+ return $this->_data['content'];
+ }
+
+ /**
+ * Get the entry copyright information
+ *
+ * @return string
+ */
+ public function getCopyright()
+ {
+ if (!array_key_exists('copyright', $this->_data)) {
+ return null;
+ }
+ return $this->_data['copyright'];
+ }
+
+ /**
+ * Get the entry creation date
+ *
+ * @return string
+ */
+ public function getDateCreated()
+ {
+ if (!array_key_exists('dateCreated', $this->_data)) {
+ return null;
+ }
+ return $this->_data['dateCreated'];
+ }
+
+ /**
+ * Get the entry modification date
+ *
+ * @return string
+ */
+ public function getDateModified()
+ {
+ if (!array_key_exists('dateModified', $this->_data)) {
+ return null;
+ }
+ return $this->_data['dateModified'];
+ }
+
+ /**
+ * Get the entry description
+ *
+ * @return string
+ */
+ public function getDescription()
+ {
+ if (!array_key_exists('description', $this->_data)) {
+ return null;
+ }
+ return $this->_data['description'];
+ }
+
+ /**
+ * Get the entry ID
+ *
+ * @return string
+ */
+ public function getId()
+ {
+ if (!array_key_exists('id', $this->_data)) {
+ return null;
+ }
+ return $this->_data['id'];
+ }
+
+ /**
+ * Get a link to the HTML source
+ *
+ * @return string|null
+ */
+ public function getLink()
+ {
+ if (!array_key_exists('link', $this->_data)) {
+ return null;
+ }
+ return $this->_data['link'];
+ }
+
+
+ /**
+ * Get all links
+ *
+ * @return array
+ */
+ public function getLinks()
+ {
+ if (!array_key_exists('links', $this->_data)) {
+ return null;
+ }
+ return $this->_data['links'];
+ }
+
+ /**
+ * Get the entry title
+ *
+ * @return string
+ */
+ public function getTitle()
+ {
+ if (!array_key_exists('title', $this->_data)) {
+ return null;
+ }
+ return $this->_data['title'];
+ }
+
+ /**
+ * Get the number of comments/replies for current entry
+ *
+ * @return integer
+ */
+ public function getCommentCount()
+ {
+ if (!array_key_exists('commentCount', $this->_data)) {
+ return null;
+ }
+ return $this->_data['commentCount'];
+ }
+
+ /**
+ * Returns a URI pointing to the HTML page where comments can be made on this entry
+ *
+ * @return string
+ */
+ public function getCommentLink()
+ {
+ if (!array_key_exists('commentLink', $this->_data)) {
+ return null;
+ }
+ return $this->_data['commentLink'];
+ }
+
+ /**
+ * Returns an array of URIs pointing to a feed of all comments for this entry
+ * where the array keys indicate the feed type (atom, rss or rdf).
+ *
+ * @return string
+ */
+ public function getCommentFeedLinks()
+ {
+ if (!array_key_exists('commentFeedLinks', $this->_data)) {
+ return null;
+ }
+ return $this->_data['commentFeedLinks'];
+ }
+
+ /**
+ * Add a entry category
+ *
+ * @param string $category
+ */
+ public function addCategory(array $category)
+ {
+ if (!isset($category['term'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Each category must be an array and '
+ . 'contain at least a "term" element containing the machine '
+ . ' readable category name');
+ }
+ if (isset($category['scheme'])) {
+ if (empty($category['scheme'])
+ || !is_string($category['scheme'])
+ || !Zend_Uri::check($category['scheme'])
+ ) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('The Atom scheme or RSS domain of'
+ . ' a category must be a valid URI');
+ }
+ }
+ if (!isset($this->_data['categories'])) {
+ $this->_data['categories'] = array();
+ }
+ $this->_data['categories'][] = $category;
+ }
+
+ /**
+ * Set an array of entry categories
+ *
+ * @param array $categories
+ */
+ public function addCategories(array $categories)
+ {
+ foreach ($categories as $category) {
+ $this->addCategory($category);
+ }
+ }
+
+ /**
+ * Get the entry categories
+ *
+ * @return string|null
+ */
+ public function getCategories()
+ {
+ if (!array_key_exists('categories', $this->_data)) {
+ return null;
+ }
+ return $this->_data['categories'];
+ }
+
+ /**
+ * Adds an enclosure to the entry. The array parameter may contain the
+ * keys 'uri', 'type' and 'length'. Only 'uri' is required for Atom, though the
+ * others must also be provided or RSS rendering (where they are required)
+ * will throw an Exception.
+ *
+ * @param array $enclosures
+ */
+ public function setEnclosure(array $enclosure)
+ {
+ if (!isset($enclosure['uri'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Enclosure "uri" is not set');
+ }
+ if (!Zend_Uri::check($enclosure['uri'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Enclosure "uri" is not a valid URI/IRI');
+ }
+ $this->_data['enclosure'] = $enclosure;
+ }
+
+ /**
+ * Retrieve an array of all enclosures to be added to entry.
+ *
+ * @return array
+ */
+ public function getEnclosure()
+ {
+ if (!array_key_exists('enclosure', $this->_data)) {
+ return null;
+ }
+ return $this->_data['enclosure'];
+ }
+
+ /**
+ * Unset a specific data point
+ *
+ * @param string $name
+ */
+ public function remove($name)
+ {
+ if (isset($this->_data[$name])) {
+ unset($this->_data[$name]);
+ }
+ }
+
+ /**
+ * Get registered extensions
+ *
+ * @return array
+ */
+ public function getExtensions()
+ {
+ return $this->_extensions;
+ }
+
+ /**
+ * Return an Extension object with the matching name (postfixed with _Entry)
+ *
+ * @param string $name
+ * @return object
+ */
+ public function getExtension($name)
+ {
+ if (array_key_exists($name . '_Entry', $this->_extensions)) {
+ return $this->_extensions[$name . '_Entry'];
+ }
+ return null;
+ }
+
+ /**
+ * Set the current feed type being exported to "rss" or "atom". This allows
+ * other objects to gracefully choose whether to execute or not, depending
+ * on their appropriateness for the current type, e.g. renderers.
+ *
+ * @param string $type
+ */
+ public function setType($type)
+ {
+ $this->_type = $type;
+ }
+
+ /**
+ * Retrieve the current or last feed type exported.
+ *
+ * @return string Value will be "rss" or "atom"
+ */
+ public function getType()
+ {
+ return $this->_type;
+ }
+
+ /**
+ * Method overloading: call given method on first extension implementing it
+ *
+ * @param string $method
+ * @param array $args
+ * @return mixed
+ * @throws Zend_Feed_Exception if no extensions implements the method
+ */
+ public function __call($method, $args)
+ {
+ foreach ($this->_extensions as $extension) {
+ try {
+ return call_user_func_array(array($extension, $method), $args);
+ } catch (Zend_Feed_Writer_Exception_InvalidMethodException $e) {
+ }
+ }
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Method: ' . $method
+ . ' does not exist and could not be located on a registered Extension');
+ }
+
+ /**
+ * Creates a new Zend_Feed_Writer_Source data container for use. This is NOT
+ * added to the current feed automatically, but is necessary to create a
+ * container with some initial values preset based on the current feed data.
+ *
+ * @return Zend_Feed_Writer_Source
+ */
+ public function createSource()
+ {
+ $source = new Zend_Feed_Writer_Source;
+ if ($this->getEncoding()) {
+ $source->setEncoding($this->getEncoding());
+ }
+ $source->setType($this->getType());
+ return $source;
+ }
+
+ /**
+ * Appends a Zend_Feed_Writer_Entry object representing a new entry/item
+ * the feed data container's internal group of entries.
+ *
+ * @param Zend_Feed_Writer_Source $source
+ */
+ public function setSource(Zend_Feed_Writer_Source $source)
+ {
+ $this->_data['source'] = $source;
+ }
+
+ /**
+ * @return Zend_Feed_Writer_Source
+ */
+ public function getSource()
+ {
+ if (isset($this->_data['source'])) {
+ return $this->_data['source'];
+ }
+ return null;
+ }
+
+ /**
+ * Load extensions from Zend_Feed_Writer
+ *
+ * @return void
+ */
+ protected function _loadExtensions()
+ {
+ $all = Zend_Feed_Writer::getExtensions();
+ $exts = $all['entry'];
+ foreach ($exts as $ext) {
+ $className = Zend_Feed_Writer::getPluginLoader()->getClassName($ext);
+ $this->_extensions[$ext] = new $className();
+ $this->_extensions[$ext]->setEncoding($this->getEncoding());
+ }
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Exception/InvalidMethodException.php b/libs/Zend/Feed/Writer/Exception/InvalidMethodException.php
new file mode 100644
index 0000000000..4510f12b68
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Exception/InvalidMethodException.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: InvalidMethodException.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+
+/**
+ * @see Zend_Feed_Exception
+ */
+// require_once 'Zend/Feed/Exception.php';
+
+
+/**
+ * Feed exceptions
+ *
+ * Class to represent exceptions that occur during Feed operations.
+ *
+ * @category Zend
+ * @package Zend_Feed
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Exception_InvalidMethodException extends Zend_Exception
+{}
diff --git a/libs/Zend/Feed/Writer/Extension/Atom/Renderer/Feed.php b/libs/Zend/Feed/Writer/Extension/Atom/Renderer/Feed.php
new file mode 100644
index 0000000000..588a57af66
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/Atom/Renderer/Feed.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Feed.php 20326 2010-01-16 00:20:43Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Extension_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Extension/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Extension_Atom_Renderer_Feed
+ extends Zend_Feed_Writer_Extension_RendererAbstract
+{
+
+ /**
+ * Set to TRUE if a rendering method actually renders something. This
+ * is used to prevent premature appending of a XML namespace declaration
+ * until an element which requires it is actually appended.
+ *
+ * @var bool
+ */
+ protected $_called = false;
+
+ /**
+ * Render feed
+ *
+ * @return void
+ */
+ public function render()
+ {
+ /**
+ * RSS 2.0 only. Used mainly to include Atom links and
+ * Pubsubhubbub Hub endpoint URIs under the Atom namespace
+ */
+ if (strtolower($this->getType()) == 'atom') {
+ return;
+ }
+ $this->_setFeedLinks($this->_dom, $this->_base);
+ $this->_setHubs($this->_dom, $this->_base);
+ if ($this->_called) {
+ $this->_appendNamespaces();
+ }
+ }
+
+ /**
+ * Append namespaces to root element of feed
+ *
+ * @return void
+ */
+ protected function _appendNamespaces()
+ {
+ $this->getRootElement()->setAttribute('xmlns:atom',
+ 'http://www.w3.org/2005/Atom');
+ }
+
+ /**
+ * Set feed link elements
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setFeedLinks(DOMDocument $dom, DOMElement $root)
+ {
+ $flinks = $this->getDataContainer()->getFeedLinks();
+ if(!$flinks || empty($flinks)) {
+ return;
+ }
+ foreach ($flinks as $type => $href) {
+ $mime = 'application/' . strtolower($type) . '+xml';
+ $flink = $dom->createElement('atom:link');
+ $root->appendChild($flink);
+ $flink->setAttribute('rel', 'self');
+ $flink->setAttribute('type', $mime);
+ $flink->setAttribute('href', $href);
+ }
+ $this->_called = true;
+ }
+
+ /**
+ * Set PuSH hubs
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setHubs(DOMDocument $dom, DOMElement $root)
+ {
+ $hubs = $this->getDataContainer()->getHubs();
+ if (!$hubs || empty($hubs)) {
+ return;
+ }
+ foreach ($hubs as $hubUrl) {
+ $hub = $dom->createElement('atom:link');
+ $hub->setAttribute('rel', 'hub');
+ $hub->setAttribute('href', $hubUrl);
+ $root->appendChild($hub);
+ }
+ $this->_called = true;
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Extension/Content/Renderer/Entry.php b/libs/Zend/Feed/Writer/Extension/Content/Renderer/Entry.php
new file mode 100644
index 0000000000..0036c6325e
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/Content/Renderer/Entry.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Entry.php 20326 2010-01-16 00:20:43Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Extension_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Extension/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Extension_Content_Renderer_Entry
+ extends Zend_Feed_Writer_Extension_RendererAbstract
+{
+
+ /**
+ * Set to TRUE if a rendering method actually renders something. This
+ * is used to prevent premature appending of a XML namespace declaration
+ * until an element which requires it is actually appended.
+ *
+ * @var bool
+ */
+ protected $_called = false;
+
+ /**
+ * Render entry
+ *
+ * @return void
+ */
+ public function render()
+ {
+ if (strtolower($this->getType()) == 'atom') {
+ return;
+ }
+ $this->_setContent($this->_dom, $this->_base);
+ if ($this->_called) {
+ $this->_appendNamespaces();
+ }
+ }
+
+ /**
+ * Append namespaces to root element
+ *
+ * @return void
+ */
+ protected function _appendNamespaces()
+ {
+ $this->getRootElement()->setAttribute('xmlns:content',
+ 'http://purl.org/rss/1.0/modules/content/');
+ }
+
+ /**
+ * Set entry content
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setContent(DOMDocument $dom, DOMElement $root)
+ {
+ $content = $this->getDataContainer()->getContent();
+ if (!$content) {
+ return;
+ }
+ $element = $dom->createElement('content:encoded');
+ $root->appendChild($element);
+ $cdata = $dom->createCDATASection($content);
+ $element->appendChild($cdata);
+ $this->_called = true;
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Extension/DublinCore/Renderer/Entry.php b/libs/Zend/Feed/Writer/Extension/DublinCore/Renderer/Entry.php
new file mode 100644
index 0000000000..c433ea3a6c
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/DublinCore/Renderer/Entry.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Entry.php 20326 2010-01-16 00:20:43Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Extension_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Extension/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Extension_DublinCore_Renderer_Entry
+ extends Zend_Feed_Writer_Extension_RendererAbstract
+{
+
+ /**
+ * Set to TRUE if a rendering method actually renders something. This
+ * is used to prevent premature appending of a XML namespace declaration
+ * until an element which requires it is actually appended.
+ *
+ * @var bool
+ */
+ protected $_called = false;
+
+ /**
+ * Render entry
+ *
+ * @return void
+ */
+ public function render()
+ {
+ if (strtolower($this->getType()) == 'atom') {
+ return;
+ }
+ $this->_setAuthors($this->_dom, $this->_base);
+ if ($this->_called) {
+ $this->_appendNamespaces();
+ }
+ }
+
+ /**
+ * Append namespaces to entry
+ *
+ * @return void
+ */
+ protected function _appendNamespaces()
+ {
+ $this->getRootElement()->setAttribute('xmlns:dc',
+ 'http://purl.org/dc/elements/1.1/');
+ }
+
+ /**
+ * Set entry author elements
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setAuthors(DOMDocument $dom, DOMElement $root)
+ {
+ $authors = $this->getDataContainer()->getAuthors();
+ if (!$authors || empty($authors)) {
+ return;
+ }
+ foreach ($authors as $data) {
+ $author = $this->_dom->createElement('dc:creator');
+ if (array_key_exists('name', $data)) {
+ $text = $dom->createTextNode($data['name']);
+ $author->appendChild($text);
+ $root->appendChild($author);
+ }
+ }
+ $this->_called = true;
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Extension/DublinCore/Renderer/Feed.php b/libs/Zend/Feed/Writer/Extension/DublinCore/Renderer/Feed.php
new file mode 100644
index 0000000000..e1a0105019
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/DublinCore/Renderer/Feed.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Feed.php 20326 2010-01-16 00:20:43Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Extension_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Extension/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Extension_DublinCore_Renderer_Feed
+ extends Zend_Feed_Writer_Extension_RendererAbstract
+{
+
+ /**
+ * Set to TRUE if a rendering method actually renders something. This
+ * is used to prevent premature appending of a XML namespace declaration
+ * until an element which requires it is actually appended.
+ *
+ * @var bool
+ */
+ protected $_called = false;
+
+ /**
+ * Render feed
+ *
+ * @return void
+ */
+ public function render()
+ {
+ if (strtolower($this->getType()) == 'atom') {
+ return;
+ }
+ $this->_setAuthors($this->_dom, $this->_base);
+ if ($this->_called) {
+ $this->_appendNamespaces();
+ }
+ }
+
+ /**
+ * Append namespaces to feed element
+ *
+ * @return void
+ */
+ protected function _appendNamespaces()
+ {
+ $this->getRootElement()->setAttribute('xmlns:dc',
+ 'http://purl.org/dc/elements/1.1/');
+ }
+
+ /**
+ * Set feed authors
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setAuthors(DOMDocument $dom, DOMElement $root)
+ {
+ $authors = $this->getDataContainer()->getAuthors();
+ if (!$authors || empty($authors)) {
+ return;
+ }
+ foreach ($authors as $data) {
+ $author = $this->_dom->createElement('dc:creator');
+ if (array_key_exists('name', $data)) {
+ $text = $dom->createTextNode($data['name']);
+ $author->appendChild($text);
+ $root->appendChild($author);
+ }
+ }
+ $this->_called = true;
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Extension/ITunes/Entry.php b/libs/Zend/Feed/Writer/Extension/ITunes/Entry.php
new file mode 100644
index 0000000000..1d7fbc5070
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/ITunes/Entry.php
@@ -0,0 +1,242 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Entry.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Extension_ITunes_Entry
+{
+ /**
+ * Array of Feed data for rendering by Extension's renderers
+ *
+ * @var array
+ */
+ protected $_data = array();
+
+ /**
+ * Encoding of all text values
+ *
+ * @var string
+ */
+ protected $_encoding = 'UTF-8';
+
+ /**
+ * Set feed encoding
+ *
+ * @param string $enc
+ * @return Zend_Feed_Writer_Extension_ITunes_Entry
+ */
+ public function setEncoding($enc)
+ {
+ $this->_encoding = $enc;
+ return $this;
+ }
+
+ /**
+ * Get feed encoding
+ *
+ * @return string
+ */
+ public function getEncoding()
+ {
+ return $this->_encoding;
+ }
+
+ /**
+ * Set a block value of "yes" or "no". You may also set an empty string.
+ *
+ * @param string
+ * @return Zend_Feed_Writer_Extension_ITunes_Entry
+ */
+ public function setItunesBlock($value)
+ {
+ if (!ctype_alpha($value) && strlen($value) > 0) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "block" may only'
+ . ' contain alphabetic characters');
+ }
+ if (iconv_strlen($value, $this->getEncoding()) > 255) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "block" may only'
+ . ' contain a maximum of 255 characters');
+ }
+ $this->_data['block'] = $value;
+ }
+
+ /**
+ * Add authors to itunes entry
+ *
+ * @param array $values
+ * @return Zend_Feed_Writer_Extension_ITunes_Entry
+ */
+ public function addItunesAuthors(array $values)
+ {
+ foreach ($values as $value) {
+ $this->addItunesAuthor($value);
+ }
+ return $this;
+ }
+
+ /**
+ * Add author to itunes entry
+ *
+ * @param string $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Entry
+ */
+ public function addItunesAuthor($value)
+ {
+ if (iconv_strlen($value, $this->getEncoding()) > 255) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: any "author" may only'
+ . ' contain a maximum of 255 characters each');
+ }
+ if (!isset($this->_data['authors'])) {
+ $this->_data['authors'] = array();
+ }
+ $this->_data['authors'][] = $value;
+ return $this;
+ }
+
+ /**
+ * Set duration
+ *
+ * @param int $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Entry
+ */
+ public function setItunesDuration($value)
+ {
+ $value = (string) $value;
+ if (!ctype_digit($value)
+ && !preg_match("/^\d+:[0-5]{1}[0-9]{1}$/", $value)
+ && !preg_match("/^\d+:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}$/", $value)
+ ) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "duration" may only'
+ . ' be of a specified [[HH:]MM:]SS format');
+ }
+ $this->_data['duration'] = $value;
+ return $this;
+ }
+
+ /**
+ * Set "explicit" flag
+ *
+ * @param bool $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Entry
+ */
+ public function setItunesExplicit($value)
+ {
+ if (!in_array($value, array('yes','no','clean'))) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "explicit" may only'
+ . ' be one of "yes", "no" or "clean"');
+ }
+ $this->_data['explicit'] = $value;
+ return $this;
+ }
+
+ /**
+ * Set keywords
+ *
+ * @param array $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Entry
+ */
+ public function setItunesKeywords(array $value)
+ {
+ if (count($value) > 12) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "keywords" may only'
+ . ' contain a maximum of 12 terms');
+ }
+ $concat = implode(',', $value);
+ if (iconv_strlen($concat, $this->getEncoding()) > 255) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "keywords" may only'
+ . ' have a concatenated length of 255 chars where terms are delimited'
+ . ' by a comma');
+ }
+ $this->_data['keywords'] = $value;
+ return $this;
+ }
+
+ /**
+ * Set subtitle
+ *
+ * @param string $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Entry
+ */
+ public function setItunesSubtitle($value)
+ {
+ if (iconv_strlen($value, $this->getEncoding()) > 255) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "subtitle" may only'
+ . ' contain a maximum of 255 characters');
+ }
+ $this->_data['subtitle'] = $value;
+ return $this;
+ }
+
+ /**
+ * Set summary
+ *
+ * @param string $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Entry
+ */
+ public function setItunesSummary($value)
+ {
+ if (iconv_strlen($value, $this->getEncoding()) > 4000) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "summary" may only'
+ . ' contain a maximum of 4000 characters');
+ }
+ $this->_data['summary'] = $value;
+ return $this;
+ }
+
+ /**
+ * Overloading to itunes specific setters
+ *
+ * @param string $method
+ * @param array $params
+ * @return mixed
+ */
+ public function __call($method, array $params)
+ {
+ $point = Zend_Feed_Writer::lcfirst(substr($method, 9));
+ if (!method_exists($this, 'setItunes' . ucfirst($point))
+ && !method_exists($this, 'addItunes' . ucfirst($point))
+ ) {
+ // require_once 'Zend/Feed/Writer/Exception/InvalidMethodException.php';
+ throw new Zend_Feed_Writer_Exception_InvalidMethodException(
+ 'invalid method: ' . $method
+ );
+ }
+ if (!array_key_exists($point, $this->_data)
+ || empty($this->_data[$point])
+ ) {
+ return null;
+ }
+ return $this->_data[$point];
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Extension/ITunes/Feed.php b/libs/Zend/Feed/Writer/Extension/ITunes/Feed.php
new file mode 100644
index 0000000000..caf0440a03
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/ITunes/Feed.php
@@ -0,0 +1,361 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Feed.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Extension_ITunes_Feed
+{
+ /**
+ * Array of Feed data for rendering by Extension's renderers
+ *
+ * @var array
+ */
+ protected $_data = array();
+
+ /**
+ * Encoding of all text values
+ *
+ * @var string
+ */
+ protected $_encoding = 'UTF-8';
+
+ /**
+ * Set feed encoding
+ *
+ * @param string $enc
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function setEncoding($enc)
+ {
+ $this->_encoding = $enc;
+ return $this;
+ }
+
+ /**
+ * Get feed encoding
+ *
+ * @return string
+ */
+ public function getEncoding()
+ {
+ return $this->_encoding;
+ }
+
+ /**
+ * Set a block value of "yes" or "no". You may also set an empty string.
+ *
+ * @param string
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function setItunesBlock($value)
+ {
+ if (!ctype_alpha($value) && strlen($value) > 0) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "block" may only'
+ . ' contain alphabetic characters');
+ }
+ if (iconv_strlen($value, $this->getEncoding()) > 255) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "block" may only'
+ . ' contain a maximum of 255 characters');
+ }
+ $this->_data['block'] = $value;
+ return $this;
+ }
+
+ /**
+ * Add feed authors
+ *
+ * @param array $values
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function addItunesAuthors(array $values)
+ {
+ foreach ($values as $value) {
+ $this->addItunesAuthor($value);
+ }
+ return $this;
+ }
+
+ /**
+ * Add feed author
+ *
+ * @param string $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function addItunesAuthor($value)
+ {
+ if (iconv_strlen($value, $this->getEncoding()) > 255) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: any "author" may only'
+ . ' contain a maximum of 255 characters each');
+ }
+ if (!isset($this->_data['authors'])) {
+ $this->_data['authors'] = array();
+ }
+ $this->_data['authors'][] = $value;
+ return $this;
+ }
+
+ /**
+ * Set feed categories
+ *
+ * @param array $values
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function setItunesCategories(array $values)
+ {
+ if (!isset($this->_data['categories'])) {
+ $this->_data['categories'] = array();
+ }
+ foreach ($values as $key=>$value) {
+ if (!is_array($value)) {
+ if (iconv_strlen($value, $this->getEncoding()) > 255) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: any "category" may only'
+ . ' contain a maximum of 255 characters each');
+ }
+ $this->_data['categories'][] = $value;
+ } else {
+ if (iconv_strlen($key, $this->getEncoding()) > 255) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: any "category" may only'
+ . ' contain a maximum of 255 characters each');
+ }
+ $this->_data['categories'][$key] = array();
+ foreach ($value as $val) {
+ if (iconv_strlen($val, $this->getEncoding()) > 255) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: any "category" may only'
+ . ' contain a maximum of 255 characters each');
+ }
+ $this->_data['categories'][$key][] = $val;
+ }
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Set feed image (icon)
+ *
+ * @param string $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function setItunesImage($value)
+ {
+ if (!Zend_Uri::check($value)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "image" may only'
+ . ' be a valid URI/IRI');
+ }
+ if (!in_array(substr($value, -3), array('jpg','png'))) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "image" may only'
+ . ' use file extension "jpg" or "png" which must be the last three'
+ . ' characters of the URI (i.e. no query string or fragment)');
+ }
+ $this->_data['image'] = $value;
+ return $this;
+ }
+
+ /**
+ * Set feed cumulative duration
+ *
+ * @param string $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function setItunesDuration($value)
+ {
+ $value = (string) $value;
+ if (!ctype_digit($value)
+ && !preg_match("/^\d+:[0-5]{1}[0-9]{1}$/", $value)
+ && !preg_match("/^\d+:[0-5]{1}[0-9]{1}:[0-5]{1}[0-9]{1}$/", $value)
+ ) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "duration" may only'
+ . ' be of a specified [[HH:]MM:]SS format');
+ }
+ $this->_data['duration'] = $value;
+ return $this;
+ }
+
+ /**
+ * Set "explicit" flag
+ *
+ * @param bool $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function setItunesExplicit($value)
+ {
+ if (!in_array($value, array('yes','no','clean'))) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "explicit" may only'
+ . ' be one of "yes", "no" or "clean"');
+ }
+ $this->_data['explicit'] = $value;
+ return $this;
+ }
+
+ /**
+ * Set feed keywords
+ *
+ * @param array $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function setItunesKeywords(array $value)
+ {
+ if (count($value) > 12) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "keywords" may only'
+ . ' contain a maximum of 12 terms');
+ }
+ $concat = implode(',', $value);
+ if (iconv_strlen($concat, $this->getEncoding()) > 255) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "keywords" may only'
+ . ' have a concatenated length of 255 chars where terms are delimited'
+ . ' by a comma');
+ }
+ $this->_data['keywords'] = $value;
+ return $this;
+ }
+
+ /**
+ * Set new feed URL
+ *
+ * @param string $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function setItunesNewFeedUrl($value)
+ {
+ if (!Zend_Uri::check($value)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "newFeedUrl" may only'
+ . ' be a valid URI/IRI');
+ }
+ $this->_data['newFeedUrl'] = $value;
+ return $this;
+ }
+
+ /**
+ * Add feed owners
+ *
+ * @param array $values
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function addItunesOwners(array $values)
+ {
+ foreach ($values as $value) {
+ $this->addItunesOwner($value);
+ }
+ return $this;
+ }
+
+ /**
+ * Add feed owner
+ *
+ * @param string $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function addItunesOwner(array $value)
+ {
+ if (!isset($value['name']) || !isset($value['email'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: any "owner" must'
+ . ' be an array containing keys "name" and "email"');
+ }
+ if (iconv_strlen($value['name'], $this->getEncoding()) > 255
+ || iconv_strlen($value['email'], $this->getEncoding()) > 255
+ ) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: any "owner" may only'
+ . ' contain a maximum of 255 characters each for "name" and "email"');
+ }
+ if (!isset($this->_data['owners'])) {
+ $this->_data['owners'] = array();
+ }
+ $this->_data['owners'][] = $value;
+ return $this;
+ }
+
+ /**
+ * Set feed subtitle
+ *
+ * @param string $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function setItunesSubtitle($value)
+ {
+ if (iconv_strlen($value, $this->getEncoding()) > 255) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "subtitle" may only'
+ . ' contain a maximum of 255 characters');
+ }
+ $this->_data['subtitle'] = $value;
+ return $this;
+ }
+
+ /**
+ * Set feed summary
+ *
+ * @param string $value
+ * @return Zend_Feed_Writer_Extension_ITunes_Feed
+ */
+ public function setItunesSummary($value)
+ {
+ if (iconv_strlen($value, $this->getEncoding()) > 4000) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('invalid parameter: "summary" may only'
+ . ' contain a maximum of 4000 characters');
+ }
+ $this->_data['summary'] = $value;
+ return $this;
+ }
+
+ /**
+ * Overloading: proxy to internal setters
+ *
+ * @param string $method
+ * @param array $params
+ * @return mixed
+ */
+ public function __call($method, array $params)
+ {
+ $point = Zend_Feed_Writer::lcfirst(substr($method, 9));
+ if (!method_exists($this, 'setItunes' . ucfirst($point))
+ && !method_exists($this, 'addItunes' . ucfirst($point))
+ ) {
+ // require_once 'Zend/Feed/Writer/Exception/InvalidMethodException.php';
+ throw new Zend_Feed_Writer_Exception_InvalidMethodException(
+ 'invalid method: ' . $method
+ );
+ }
+ if (!array_key_exists($point, $this->_data) || empty($this->_data[$point])) {
+ return null;
+ }
+ return $this->_data[$point];
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Extension/ITunes/Renderer/Entry.php b/libs/Zend/Feed/Writer/Extension/ITunes/Renderer/Entry.php
new file mode 100644
index 0000000000..046cb546fb
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/ITunes/Renderer/Entry.php
@@ -0,0 +1,216 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Entry.php 20326 2010-01-16 00:20:43Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Extension_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Extension/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Extension_ITunes_Renderer_Entry
+ extends Zend_Feed_Writer_Extension_RendererAbstract
+{
+ /**
+ * Set to TRUE if a rendering method actually renders something. This
+ * is used to prevent premature appending of a XML namespace declaration
+ * until an element which requires it is actually appended.
+ *
+ * @var bool
+ */
+ protected $_called = false;
+
+ /**
+ * Render entry
+ *
+ * @return void
+ */
+ public function render()
+ {
+ $this->_setAuthors($this->_dom, $this->_base);
+ $this->_setBlock($this->_dom, $this->_base);
+ $this->_setDuration($this->_dom, $this->_base);
+ $this->_setExplicit($this->_dom, $this->_base);
+ $this->_setKeywords($this->_dom, $this->_base);
+ $this->_setSubtitle($this->_dom, $this->_base);
+ $this->_setSummary($this->_dom, $this->_base);
+ if ($this->_called) {
+ $this->_appendNamespaces();
+ }
+ }
+
+ /**
+ * Append namespaces to entry root
+ *
+ * @return void
+ */
+ protected function _appendNamespaces()
+ {
+ $this->getRootElement()->setAttribute('xmlns:itunes',
+ 'http://www.itunes.com/dtds/podcast-1.0.dtd');
+ }
+
+ /**
+ * Set entry authors
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setAuthors(DOMDocument $dom, DOMElement $root)
+ {
+ $authors = $this->getDataContainer()->getItunesAuthors();
+ if (!$authors || empty($authors)) {
+ return;
+ }
+ foreach ($authors as $author) {
+ $el = $dom->createElement('itunes:author');
+ $text = $dom->createTextNode($author);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+ }
+
+ /**
+ * Set itunes block
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setBlock(DOMDocument $dom, DOMElement $root)
+ {
+ $block = $this->getDataContainer()->getItunesBlock();
+ if (is_null($block)) {
+ return;
+ }
+ $el = $dom->createElement('itunes:block');
+ $text = $dom->createTextNode($block);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set entry duration
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDuration(DOMDocument $dom, DOMElement $root)
+ {
+ $duration = $this->getDataContainer()->getItunesDuration();
+ if (!$duration) {
+ return;
+ }
+ $el = $dom->createElement('itunes:duration');
+ $text = $dom->createTextNode($duration);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set explicit flag
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setExplicit(DOMDocument $dom, DOMElement $root)
+ {
+ $explicit = $this->getDataContainer()->getItunesExplicit();
+ if (is_null($explicit)) {
+ return;
+ }
+ $el = $dom->createElement('itunes:explicit');
+ $text = $dom->createTextNode($explicit);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set entry keywords
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setKeywords(DOMDocument $dom, DOMElement $root)
+ {
+ $keywords = $this->getDataContainer()->getItunesKeywords();
+ if (!$keywords || empty($keywords)) {
+ return;
+ }
+ $el = $dom->createElement('itunes:keywords');
+ $text = $dom->createTextNode(implode(',', $keywords));
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set entry subtitle
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setSubtitle(DOMDocument $dom, DOMElement $root)
+ {
+ $subtitle = $this->getDataContainer()->getItunesSubtitle();
+ if (!$subtitle) {
+ return;
+ }
+ $el = $dom->createElement('itunes:subtitle');
+ $text = $dom->createTextNode($subtitle);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set entry summary
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setSummary(DOMDocument $dom, DOMElement $root)
+ {
+ $summary = $this->getDataContainer()->getItunesSummary();
+ if (!$summary) {
+ return;
+ }
+ $el = $dom->createElement('itunes:summary');
+ $text = $dom->createTextNode($summary);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Extension/ITunes/Renderer/Feed.php b/libs/Zend/Feed/Writer/Extension/ITunes/Renderer/Feed.php
new file mode 100644
index 0000000000..192d19ec42
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/ITunes/Renderer/Feed.php
@@ -0,0 +1,320 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Feed.php 20326 2010-01-16 00:20:43Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Extension_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Extension/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Extension_ITunes_Renderer_Feed
+ extends Zend_Feed_Writer_Extension_RendererAbstract
+{
+
+ /**
+ * Set to TRUE if a rendering method actually renders something. This
+ * is used to prevent premature appending of a XML namespace declaration
+ * until an element which requires it is actually appended.
+ *
+ * @var bool
+ */
+ protected $_called = false;
+
+ /**
+ * Render feed
+ *
+ * @return void
+ */
+ public function render()
+ {
+ $this->_setAuthors($this->_dom, $this->_base);
+ $this->_setBlock($this->_dom, $this->_base);
+ $this->_setCategories($this->_dom, $this->_base);
+ $this->_setImage($this->_dom, $this->_base);
+ $this->_setDuration($this->_dom, $this->_base);
+ $this->_setExplicit($this->_dom, $this->_base);
+ $this->_setKeywords($this->_dom, $this->_base);
+ $this->_setNewFeedUrl($this->_dom, $this->_base);
+ $this->_setOwners($this->_dom, $this->_base);
+ $this->_setSubtitle($this->_dom, $this->_base);
+ $this->_setSummary($this->_dom, $this->_base);
+ if ($this->_called) {
+ $this->_appendNamespaces();
+ }
+ }
+
+ /**
+ * Append feed namespaces
+ *
+ * @return void
+ */
+ protected function _appendNamespaces()
+ {
+ $this->getRootElement()->setAttribute('xmlns:itunes',
+ 'http://www.itunes.com/dtds/podcast-1.0.dtd');
+ }
+
+ /**
+ * Set feed authors
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setAuthors(DOMDocument $dom, DOMElement $root)
+ {
+ $authors = $this->getDataContainer()->getItunesAuthors();
+ if (!$authors || empty($authors)) {
+ return;
+ }
+ foreach ($authors as $author) {
+ $el = $dom->createElement('itunes:author');
+ $text = $dom->createTextNode($author);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ }
+ $this->_called = true;
+ }
+
+ /**
+ * Set feed itunes block
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setBlock(DOMDocument $dom, DOMElement $root)
+ {
+ $block = $this->getDataContainer()->getItunesBlock();
+ if (is_null($block)) {
+ return;
+ }
+ $el = $dom->createElement('itunes:block');
+ $text = $dom->createTextNode($block);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set feed categories
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCategories(DOMDocument $dom, DOMElement $root)
+ {
+ $cats = $this->getDataContainer()->getItunesCategories();
+ if (!$cats || empty($cats)) {
+ return;
+ }
+ foreach ($cats as $key=>$cat) {
+ if (!is_array($cat)) {
+ $el = $dom->createElement('itunes:category');
+ $el->setAttribute('text', $cat);
+ $root->appendChild($el);
+ } else {
+ $el = $dom->createElement('itunes:category');
+ $el->setAttribute('text', $key);
+ $root->appendChild($el);
+ foreach ($cat as $subcat) {
+ $el2 = $dom->createElement('itunes:category');
+ $el2->setAttribute('text', $subcat);
+ $el->appendChild($el2);
+ }
+ }
+ }
+ $this->_called = true;
+ }
+
+ /**
+ * Set feed image (icon)
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setImage(DOMDocument $dom, DOMElement $root)
+ {
+ $image = $this->getDataContainer()->getItunesImage();
+ if (!$image) {
+ return;
+ }
+ $el = $dom->createElement('itunes:image');
+ $el->setAttribute('href', $image);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set feed cumulative duration
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDuration(DOMDocument $dom, DOMElement $root)
+ {
+ $duration = $this->getDataContainer()->getItunesDuration();
+ if (!$duration) {
+ return;
+ }
+ $el = $dom->createElement('itunes:duration');
+ $text = $dom->createTextNode($duration);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set explicit flag
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setExplicit(DOMDocument $dom, DOMElement $root)
+ {
+ $explicit = $this->getDataContainer()->getItunesExplicit();
+ if (is_null($explicit)) {
+ return;
+ }
+ $el = $dom->createElement('itunes:explicit');
+ $text = $dom->createTextNode($explicit);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set feed keywords
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setKeywords(DOMDocument $dom, DOMElement $root)
+ {
+ $keywords = $this->getDataContainer()->getItunesKeywords();
+ if (!$keywords || empty($keywords)) {
+ return;
+ }
+ $el = $dom->createElement('itunes:keywords');
+ $text = $dom->createTextNode(implode(',', $keywords));
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set feed's new URL
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setNewFeedUrl(DOMDocument $dom, DOMElement $root)
+ {
+ $url = $this->getDataContainer()->getItunesNewFeedUrl();
+ if (!$url) {
+ return;
+ }
+ $el = $dom->createElement('itunes:new-feed-url');
+ $text = $dom->createTextNode($url);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set feed owners
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setOwners(DOMDocument $dom, DOMElement $root)
+ {
+ $owners = $this->getDataContainer()->getItunesOwners();
+ if (!$owners || empty($owners)) {
+ return;
+ }
+ foreach ($owners as $owner) {
+ $el = $dom->createElement('itunes:owner');
+ $name = $dom->createElement('itunes:name');
+ $text = $dom->createTextNode($owner['name']);
+ $name->appendChild($text);
+ $email = $dom->createElement('itunes:email');
+ $text = $dom->createTextNode($owner['email']);
+ $email->appendChild($text);
+ $root->appendChild($el);
+ $el->appendChild($name);
+ $el->appendChild($email);
+ }
+ $this->_called = true;
+ }
+
+ /**
+ * Set feed subtitle
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setSubtitle(DOMDocument $dom, DOMElement $root)
+ {
+ $subtitle = $this->getDataContainer()->getItunesSubtitle();
+ if (!$subtitle) {
+ return;
+ }
+ $el = $dom->createElement('itunes:subtitle');
+ $text = $dom->createTextNode($subtitle);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+
+ /**
+ * Set feed summary
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setSummary(DOMDocument $dom, DOMElement $root)
+ {
+ $summary = $this->getDataContainer()->getItunesSummary();
+ if (!$summary) {
+ return;
+ }
+ $el = $dom->createElement('itunes:summary');
+ $text = $dom->createTextNode($summary);
+ $el->appendChild($text);
+ $root->appendChild($el);
+ $this->_called = true;
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Extension/RendererAbstract.php b/libs/Zend/Feed/Writer/Extension/RendererAbstract.php
new file mode 100644
index 0000000000..b381be3657
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/RendererAbstract.php
@@ -0,0 +1,179 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to padraic dot brady at yahoo dot com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer_Entry_Rss
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @see Zend_Feed_Writer_Extension_RendererInterface
+ */
+// require_once 'Zend/Feed/Writer/Extension/RendererInterface.php';
+
+ /**
+ * @category Zend
+ * @package Zend_Feed_Writer_Entry_Rss
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+abstract class Zend_Feed_Writer_Extension_RendererAbstract
+ implements Zend_Feed_Writer_Extension_RendererInterface
+{
+ /**
+ * @var DOMDocument
+ */
+ protected $_dom = null;
+
+ /**
+ * @var mixed
+ */
+ protected $_entry = null;
+
+ /**
+ * @var DOMElement
+ */
+ protected $_base = null;
+
+ /**
+ * @var mixed
+ */
+ protected $_container = null;
+
+ /**
+ * @var string
+ */
+ protected $_type = null;
+
+ /**
+ * @var DOMElement
+ */
+ protected $_rootElement = null;
+
+ /**
+ * Encoding of all text values
+ *
+ * @var string
+ */
+ protected $_encoding = 'UTF-8';
+
+ /**
+ * Constructor
+ *
+ * @param mixed $container
+ * @return void
+ */
+ public function __construct($container)
+ {
+ $this->_container = $container;
+ }
+
+ /**
+ * Set feed encoding
+ *
+ * @param string $enc
+ * @return Zend_Feed_Writer_Extension_RendererAbstract
+ */
+ public function setEncoding($enc)
+ {
+ $this->_encoding = $enc;
+ return $this;
+ }
+
+ /**
+ * Get feed encoding
+ *
+ * @return void
+ */
+ public function getEncoding()
+ {
+ return $this->_encoding;
+ }
+
+ /**
+ * Set DOMDocument and DOMElement on which to operate
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $base
+ * @return Zend_Feed_Writer_Extension_RendererAbstract
+ */
+ public function setDomDocument(DOMDocument $dom, DOMElement $base)
+ {
+ $this->_dom = $dom;
+ $this->_base = $base;
+ return $this;
+ }
+
+ /**
+ * Get data container being rendered
+ *
+ * @return mixed
+ */
+ public function getDataContainer()
+ {
+ return $this->_container;
+ }
+
+ /**
+ * Set feed type
+ *
+ * @param string $type
+ * @return Zend_Feed_Writer_Extension_RendererAbstract
+ */
+ public function setType($type)
+ {
+ $this->_type = $type;
+ return $this;
+ }
+
+ /**
+ * Get feedtype
+ *
+ * @return string
+ */
+ public function getType()
+ {
+ return $this->_type;
+ }
+
+ /**
+ * Set root element of document
+ *
+ * @param DOMElement $root
+ * @return Zend_Feed_Writer_Extension_RendererAbstract
+ */
+ public function setRootElement(DOMElement $root)
+ {
+ $this->_rootElement = $root;
+ return $this;
+ }
+
+ /**
+ * Get root element
+ *
+ * @return DOMElement
+ */
+ public function getRootElement()
+ {
+ return $this->_rootElement;
+ }
+
+ /**
+ * Append namespaces to feed
+ *
+ * @return void
+ */
+ abstract protected function _appendNamespaces();
+}
diff --git a/libs/Zend/Feed/Writer/Extension/RendererInterface.php b/libs/Zend/Feed/Writer/Extension/RendererInterface.php
new file mode 100644
index 0000000000..e9c9014176
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/RendererInterface.php
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to padraic dot brady at yahoo dot com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+interface Zend_Feed_Writer_Extension_RendererInterface
+{
+ /**
+ * Constructor
+ *
+ * @param mixed $container
+ * @return void
+ */
+ public function __construct($container);
+
+ /**
+ * Set DOMDocument and DOMElement on which to operate
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $base
+ * @return void
+ */
+ public function setDomDocument(DOMDocument $dom, DOMElement $base);
+
+ /**
+ * Render
+ *
+ * @return void
+ */
+ public function render();
+
+ /**
+ * Retrieve container
+ *
+ * @return mixed
+ */
+ public function getDataContainer();
+}
diff --git a/libs/Zend/Feed/Writer/Extension/Slash/Renderer/Entry.php b/libs/Zend/Feed/Writer/Extension/Slash/Renderer/Entry.php
new file mode 100644
index 0000000000..2814775551
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/Slash/Renderer/Entry.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Entry.php 20326 2010-01-16 00:20:43Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Extension_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Extension/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Extension_Slash_Renderer_Entry
+ extends Zend_Feed_Writer_Extension_RendererAbstract
+{
+
+ /**
+ * Set to TRUE if a rendering method actually renders something. This
+ * is used to prevent premature appending of a XML namespace declaration
+ * until an element which requires it is actually appended.
+ *
+ * @var bool
+ */
+ protected $_called = false;
+
+ /**
+ * Render entry
+ *
+ * @return void
+ */
+ public function render()
+ {
+ if (strtolower($this->getType()) == 'atom') {
+ return; // RSS 2.0 only
+ }
+ $this->_setCommentCount($this->_dom, $this->_base);
+ if ($this->_called) {
+ $this->_appendNamespaces();
+ }
+ }
+
+ /**
+ * Append entry namespaces
+ *
+ * @return void
+ */
+ protected function _appendNamespaces()
+ {
+ $this->getRootElement()->setAttribute('xmlns:slash',
+ 'http://purl.org/rss/1.0/modules/slash/');
+ }
+
+ /**
+ * Set entry comment count
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCommentCount(DOMDocument $dom, DOMElement $root)
+ {
+ $count = $this->getDataContainer()->getCommentCount();
+ if (!$count) {
+ $count = 0;
+ }
+ $tcount = $this->_dom->createElement('slash:comments');
+ $tcount->nodeValue = $count;
+ $root->appendChild($tcount);
+ $this->_called = true;
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Extension/Threading/Renderer/Entry.php b/libs/Zend/Feed/Writer/Extension/Threading/Renderer/Entry.php
new file mode 100644
index 0000000000..69e731d4ba
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/Threading/Renderer/Entry.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Entry.php 20326 2010-01-16 00:20:43Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Extension_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Extension/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Extension_Threading_Renderer_Entry
+ extends Zend_Feed_Writer_Extension_RendererAbstract
+{
+
+ /**
+ * Set to TRUE if a rendering method actually renders something. This
+ * is used to prevent premature appending of a XML namespace declaration
+ * until an element which requires it is actually appended.
+ *
+ * @var bool
+ */
+ protected $_called = false;
+
+ /**
+ * Render entry
+ *
+ * @return void
+ */
+ public function render()
+ {
+ if (strtolower($this->getType()) == 'rss') {
+ return; // Atom 1.0 only
+ }
+ $this->_setCommentLink($this->_dom, $this->_base);
+ $this->_setCommentFeedLinks($this->_dom, $this->_base);
+ $this->_setCommentCount($this->_dom, $this->_base);
+ if ($this->_called) {
+ $this->_appendNamespaces();
+ }
+ }
+
+ /**
+ * Append entry namespaces
+ *
+ * @return void
+ */
+ protected function _appendNamespaces()
+ {
+ $this->getRootElement()->setAttribute('xmlns:thr',
+ 'http://purl.org/syndication/thread/1.0');
+ }
+
+ /**
+ * Set comment link
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCommentLink(DOMDocument $dom, DOMElement $root)
+ {
+ $link = $this->getDataContainer()->getCommentLink();
+ if (!$link) {
+ return;
+ }
+ $clink = $this->_dom->createElement('link');
+ $clink->setAttribute('rel', 'replies');
+ $clink->setAttribute('type', 'text/html');
+ $clink->setAttribute('href', $link);
+ $count = $this->getDataContainer()->getCommentCount();
+ if (!is_null($count)) {
+ $clink->setAttribute('thr:count', $count);
+ }
+ $root->appendChild($clink);
+ $this->_called = true;
+ }
+
+ /**
+ * Set comment feed links
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCommentFeedLinks(DOMDocument $dom, DOMElement $root)
+ {
+ $links = $this->getDataContainer()->getCommentFeedLinks();
+ if (!$links || empty($links)) {
+ return;
+ }
+ foreach ($links as $link) {
+ $flink = $this->_dom->createElement('link');
+ $flink->setAttribute('rel', 'replies');
+ $flink->setAttribute('type', 'application/'. $link['type'] .'+xml');
+ $flink->setAttribute('href', $link['uri']);
+ $count = $this->getDataContainer()->getCommentCount();
+ if (!is_null($count)) {
+ $flink->setAttribute('thr:count', $count);
+ }
+ $root->appendChild($flink);
+ $this->_called = true;
+ }
+ }
+
+ /**
+ * Set entry comment count
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCommentCount(DOMDocument $dom, DOMElement $root)
+ {
+ $count = $this->getDataContainer()->getCommentCount();
+ if (is_null($count)) {
+ return;
+ }
+ $tcount = $this->_dom->createElement('thr:total');
+ $tcount->nodeValue = $count;
+ $root->appendChild($tcount);
+ $this->_called = true;
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Extension/WellFormedWeb/Renderer/Entry.php b/libs/Zend/Feed/Writer/Extension/WellFormedWeb/Renderer/Entry.php
new file mode 100644
index 0000000000..c57244ae4b
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Extension/WellFormedWeb/Renderer/Entry.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Entry.php 20326 2010-01-16 00:20:43Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Extension_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Extension/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Extension_WellFormedWeb_Renderer_Entry
+ extends Zend_Feed_Writer_Extension_RendererAbstract
+{
+
+ /**
+ * Set to TRUE if a rendering method actually renders something. This
+ * is used to prevent premature appending of a XML namespace declaration
+ * until an element which requires it is actually appended.
+ *
+ * @var bool
+ */
+ protected $_called = false;
+
+ /**
+ * Render entry
+ *
+ * @return void
+ */
+ public function render()
+ {
+ if (strtolower($this->getType()) == 'atom') {
+ return; // RSS 2.0 only
+ }
+ $this->_setCommentFeedLinks($this->_dom, $this->_base);
+ if ($this->_called) {
+ $this->_appendNamespaces();
+ }
+ }
+
+ /**
+ * Append entry namespaces
+ *
+ * @return void
+ */
+ protected function _appendNamespaces()
+ {
+ $this->getRootElement()->setAttribute('xmlns:wfw',
+ 'http://wellformedweb.org/CommentAPI/');
+ }
+
+ /**
+ * Set entry comment feed links
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCommentFeedLinks(DOMDocument $dom, DOMElement $root)
+ {
+ $links = $this->getDataContainer()->getCommentFeedLinks();
+ if (!$links || empty($links)) {
+ return;
+ }
+ foreach ($links as $link) {
+ if ($link['type'] == 'rss') {
+ $flink = $this->_dom->createElement('wfw:commentRss');
+ $text = $dom->createTextNode($link['uri']);
+ $flink->appendChild($text);
+ $root->appendChild($flink);
+ }
+ }
+ $this->_called = true;
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Feed.php b/libs/Zend/Feed/Writer/Feed.php
new file mode 100644
index 0000000000..724caed1a2
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Feed.php
@@ -0,0 +1,281 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Feed.php 20519 2010-01-22 14:06:24Z padraic $
+ */
+
+/**
+ * @see Zend_Date
+ */
+// require_once 'Zend/Date.php';
+
+/**
+ * @see Zend_Date
+ */
+// require_once 'Zend/Uri.php';
+
+/**
+ * @see Zend_Feed_Writer
+ */
+// require_once 'Zend/Feed/Writer.php';
+
+/**
+ * @see Zend_Feed_Writer_Entry
+ */
+// require_once 'Zend/Feed/Writer/Entry.php';
+
+/**
+ * @see Zend_Feed_Writer_Deleted
+ */
+// require_once 'Zend/Feed/Writer/Deleted.php';
+
+/**
+ * @see Zend_Feed_Writer_Renderer_Feed_Atom
+ */
+// require_once 'Zend/Feed/Writer/Renderer/Feed/Atom.php';
+
+/**
+ * @see Zend_Feed_Writer_Renderer_Feed_Rss
+ */
+// require_once 'Zend/Feed/Writer/Renderer/Feed/Rss.php';
+
+// require_once 'Zend/Feed/Writer/Feed/FeedAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Feed extends Zend_Feed_Writer_Feed_FeedAbstract
+implements Iterator, Countable
+{
+
+ /**
+ * Contains all entry objects
+ *
+ * @var array
+ */
+ protected $_entries = array();
+
+ /**
+ * A pointer for the iterator to keep track of the entries array
+ *
+ * @var int
+ */
+ protected $_entriesKey = 0;
+
+ /**
+ * Creates a new Zend_Feed_Writer_Entry data container for use. This is NOT
+ * added to the current feed automatically, but is necessary to create a
+ * container with some initial values preset based on the current feed data.
+ *
+ * @return Zend_Feed_Writer_Entry
+ */
+ public function createEntry()
+ {
+ $entry = new Zend_Feed_Writer_Entry;
+ if ($this->getEncoding()) {
+ $entry->setEncoding($this->getEncoding());
+ }
+ $entry->setType($this->getType());
+ return $entry;
+ }
+
+ /**
+ * Appends a Zend_Feed_Writer_Deleted object representing a new entry tombstone
+ * to the feed data container's internal group of entries.
+ *
+ * @param Zend_Feed_Writer_Deleted $entry
+ */
+ public function addTombstone(Zend_Feed_Writer_Deleted $deleted)
+ {
+ $this->_entries[] = $deleted;
+ }
+
+ /**
+ * Creates a new Zend_Feed_Writer_Deleted data container for use. This is NOT
+ * added to the current feed automatically, but is necessary to create a
+ * container with some initial values preset based on the current feed data.
+ *
+ * @return Zend_Feed_Writer_Deleted
+ */
+ public function createTombstone()
+ {
+ $deleted = new Zend_Feed_Writer_Deleted;
+ if ($this->getEncoding()) {
+ $deleted->setEncoding($this->getEncoding());
+ }
+ $deleted->setType($this->getType());
+ return $deleted;
+ }
+
+ /**
+ * Appends a Zend_Feed_Writer_Entry object representing a new entry/item
+ * the feed data container's internal group of entries.
+ *
+ * @param Zend_Feed_Writer_Entry $entry
+ */
+ public function addEntry(Zend_Feed_Writer_Entry $entry)
+ {
+ $this->_entries[] = $entry;
+ }
+
+ /**
+ * Removes a specific indexed entry from the internal queue. Entries must be
+ * added to a feed container in order to be indexed.
+ *
+ * @param int $index
+ */
+ public function removeEntry($index)
+ {
+ if (isset($this->_entries[$index])) {
+ unset($this->_entries[$index]);
+ }
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Undefined index: ' . $index . '. Entry does not exist.');
+ }
+
+ /**
+ * Retrieve a specific indexed entry from the internal queue. Entries must be
+ * added to a feed container in order to be indexed.
+ *
+ * @param int $index
+ */
+ public function getEntry($index = 0)
+ {
+ if (isset($this->_entries[$index])) {
+ return $this->_entries[$index];
+ }
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Undefined index: ' . $index . '. Entry does not exist.');
+ }
+
+ /**
+ * Orders all indexed entries by date, thus offering date ordered readable
+ * content where a parser (or Homo Sapien) ignores the generic rule that
+ * XML element order is irrelevant and has no intrinsic meaning.
+ *
+ * Using this method will alter the original indexation.
+ *
+ * @return void
+ */
+ public function orderByDate()
+ {
+ /**
+ * Could do with some improvement for performance perhaps
+ */
+ $timestamp = time();
+ $entries = array();
+ foreach ($this->_entries as $entry) {
+ if ($entry->getDateModified()) {
+ $timestamp = (int) $entry->getDateModified()->get(Zend_Date::TIMESTAMP);
+ } elseif ($entry->getDateCreated()) {
+ $timestamp = (int) $entry->getDateCreated()->get(Zend_Date::TIMESTAMP);
+ }
+ $entries[$timestamp] = $entry;
+ }
+ krsort($entries, SORT_NUMERIC);
+ $this->_entries = array_values($entries);
+ }
+
+ /**
+ * Get the number of feed entries.
+ * Required by the Iterator interface.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->_entries);
+ }
+
+ /**
+ * Return the current entry
+ *
+ * @return Zend_Feed_Reader_Entry_Interface
+ */
+ public function current()
+ {
+ return $this->_entries[$this->key()];
+ }
+
+ /**
+ * Return the current feed key
+ *
+ * @return unknown
+ */
+ public function key()
+ {
+ return $this->_entriesKey;
+ }
+
+ /**
+ * Move the feed pointer forward
+ *
+ * @return void
+ */
+ public function next()
+ {
+ ++$this->_entriesKey;
+ }
+
+ /**
+ * Reset the pointer in the feed object
+ *
+ * @return void
+ */
+ public function rewind()
+ {
+ $this->_entriesKey = 0;
+ }
+
+ /**
+ * Check to see if the iterator is still valid
+ *
+ * @return boolean
+ */
+ public function valid()
+ {
+ return 0 <= $this->_entriesKey && $this->_entriesKey < $this->count();
+ }
+
+ /**
+ * Attempt to build and return the feed resulting from the data set
+ *
+ * @param $type The feed type "rss" or "atom" to export as
+ * @return string
+ */
+ public function export($type, $ignoreExceptions = false)
+ {
+ $this->setType(strtolower($type));
+ $type = ucfirst($this->getType());
+ if ($type !== 'Rss' && $type !== 'Atom') {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid feed type specified: ' . $type . '.'
+ . ' Should be one of "rss" or "atom".');
+ }
+ $renderClass = 'Zend_Feed_Writer_Renderer_Feed_' . $type;
+ $renderer = new $renderClass($this);
+ if ($ignoreExceptions) {
+ $renderer->ignoreExceptions();
+ }
+ return $renderer->render()->saveXml();
+ }
+
+}
diff --git a/libs/Zend/Feed/Writer/Feed/FeedAbstract.php b/libs/Zend/Feed/Writer/Feed/FeedAbstract.php
new file mode 100644
index 0000000000..bc2a0fa06f
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Feed/FeedAbstract.php
@@ -0,0 +1,805 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Feed.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @see Zend_Date
+ */
+// require_once 'Zend/Date.php';
+
+/**
+ * @see Zend_Date
+ */
+// require_once 'Zend/Uri.php';
+
+/**
+ * @see Zend_Feed_Writer
+ */
+// require_once 'Zend/Feed/Writer.php';
+
+/**
+ * @see Zend_Feed_Writer_Entry
+ */
+// require_once 'Zend/Feed/Writer/Entry.php';
+
+/**
+ * @see Zend_Feed_Writer_Renderer_Feed_Atom
+ */
+// require_once 'Zend/Feed/Writer/Renderer/Feed/Atom.php';
+
+/**
+ * @see Zend_Feed_Writer_Renderer_Feed_Rss
+ */
+// require_once 'Zend/Feed/Writer/Renderer/Feed/Rss.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Feed_FeedAbstract
+{
+ /**
+ * Contains all Feed level date to append in feed output
+ *
+ * @var array
+ */
+ protected $_data = array();
+
+ /**
+ * Holds the value "atom" or "rss" depending on the feed type set when
+ * when last exported.
+ *
+ * @var string
+ */
+ protected $_type = null;
+
+ /**
+ * Constructor: Primarily triggers the registration of core extensions and
+ * loads those appropriate to this data container.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ Zend_Feed_Writer::registerCoreExtensions();
+ $this->_loadExtensions();
+ }
+
+ /**
+ * Set a single author
+ *
+ * @param int $index
+ * @return string|null
+ */
+ public function addAuthor($name, $email = null, $uri = null)
+ {
+ $author = array();
+ if (is_array($name)) {
+ if (!array_key_exists('name', $name) || empty($name['name']) || !is_string($name['name'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: author array must include a "name" key with a non-empty string value');
+ }
+ $author['name'] = $name['name'];
+ if (isset($name['email'])) {
+ if (empty($name['email']) || !is_string($name['email'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "email" array value must be a non-empty string');
+ }
+ $author['email'] = $name['email'];
+ }
+ if (isset($name['uri'])) {
+ if (empty($name['uri']) || !is_string($name['uri']) || !Zend_Uri::check($name['uri'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "uri" array value must be a non-empty string and valid URI/IRI');
+ }
+ $author['uri'] = $name['uri'];
+ }
+ } else {
+ if (empty($name['name']) || !is_string($name['name'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "name" must be a non-empty string value');
+ }
+ $author['name'] = $name;
+ if (isset($email)) {
+ if (empty($email) || !is_string($email)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "email" value must be a non-empty string');
+ }
+ $author['email'] = $email;
+ }
+ if (isset($uri)) {
+ if (empty($uri) || !is_string($uri) || !Zend_Uri::check($uri)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "uri" value must be a non-empty string and valid URI/IRI');
+ }
+ $author['uri'] = $uri;
+ }
+ }
+ $this->_data['authors'][] = $author;
+ }
+
+ /**
+ * Set an array with feed authors
+ *
+ * @return array
+ */
+ public function addAuthors(array $authors)
+ {
+ foreach($authors as $author) {
+ $this->addAuthor($author);
+ }
+ }
+
+ /**
+ * Set the copyright entry
+ *
+ * @return string|null
+ */
+ public function setCopyright($copyright)
+ {
+ if (empty($copyright) || !is_string($copyright)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['copyright'] = $copyright;
+ }
+
+ /**
+ * Set the feed creation date
+ *
+ * @param null|integer|Zend_Date
+ */
+ public function setDateCreated($date = null)
+ {
+ $zdate = null;
+ if (is_null($date)) {
+ $zdate = new Zend_Date;
+ } elseif (ctype_digit($date) && strlen($date) == 10) {
+ $zdate = new Zend_Date($date, Zend_Date::TIMESTAMP);
+ } elseif ($date instanceof Zend_Date) {
+ $zdate = $date;
+ } else {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid Zend_Date object or UNIX Timestamp passed as parameter');
+ }
+ $this->_data['dateCreated'] = $zdate;
+ }
+
+ /**
+ * Set the feed modification date
+ *
+ * @param null|integer|Zend_Date
+ */
+ public function setDateModified($date = null)
+ {
+ $zdate = null;
+ if (is_null($date)) {
+ $zdate = new Zend_Date;
+ } elseif (ctype_digit($date) && strlen($date) == 10) {
+ $zdate = new Zend_Date($date, Zend_Date::TIMESTAMP);
+ } elseif ($date instanceof Zend_Date) {
+ $zdate = $date;
+ } else {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid Zend_Date object or UNIX Timestamp passed as parameter');
+ }
+ $this->_data['dateModified'] = $zdate;
+ }
+
+ /**
+ * Set the feed last-build date. Ignored for Atom 1.0.
+ *
+ * @param null|integer|Zend_Date
+ */
+ public function setLastBuildDate($date = null)
+ {
+ $zdate = null;
+ if (is_null($date)) {
+ $zdate = new Zend_Date;
+ } elseif (ctype_digit($date) && strlen($date) == 10) {
+ $zdate = new Zend_Date($date, Zend_Date::TIMESTAMP);
+ } elseif ($date instanceof Zend_Date) {
+ $zdate = $date;
+ } else {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid Zend_Date object or UNIX Timestamp passed as parameter');
+ }
+ $this->_data['lastBuildDate'] = $zdate;
+ }
+
+ /**
+ * Set the feed description
+ *
+ * @return string|null
+ */
+ public function setDescription($description)
+ {
+ if (empty($description) || !is_string($description)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['description'] = $description;
+ }
+
+ /**
+ * Set the feed generator entry
+ *
+ * @return string|null
+ */
+ public function setGenerator($name, $version = null, $uri = null)
+ {
+ if (is_array($name)) {
+ $data = $name;
+ if (empty($data['name']) || !is_string($data['name'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "name" must be a non-empty string');
+ }
+ $generator = array('name' => $data['name']);
+ if (isset($data['version'])) {
+ if (empty($data['version']) || !is_string($data['version'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "version" must be a non-empty string');
+ }
+ $generator['version'] = $data['version'];
+ }
+ if (isset($data['uri'])) {
+ if (empty($data['uri']) || !is_string($data['uri']) || !Zend_Uri::check($data['uri'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "uri" must be a non-empty string and a valid URI/IRI');
+ }
+ $generator['uri'] = $data['uri'];
+ }
+ } else {
+ if (empty($name) || !is_string($name)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "name" must be a non-empty string');
+ }
+ $generator = array('name' => $name);
+ if (isset($version)) {
+ if (empty($version) || !is_string($version)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "version" must be a non-empty string');
+ }
+ $generator['version'] = $version;
+ }
+ if (isset($uri)) {
+ if (empty($uri) || !is_string($uri) || !Zend_Uri::check($uri)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "uri" must be a non-empty string and a valid URI/IRI');
+ }
+ $generator['uri'] = $uri;
+ }
+ }
+ $this->_data['generator'] = $generator;
+ }
+
+ /**
+ * Set the feed ID - URI or URN (via PCRE pattern) supported
+ *
+ * @param string $id
+ */
+ public function setId($id)
+ {
+ if ((empty($id) || !is_string($id) || !Zend_Uri::check($id)) &&
+ !preg_match("#^urn:[a-zA-Z0-9][a-zA-Z0-9\-]{1,31}:([a-zA-Z0-9\(\)\+\,\.\:\=\@\;\$\_\!\*\-]|%[0-9a-fA-F]{2})*#", $id)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string and valid URI/IRI');
+ }
+ $this->_data['id'] = $id;
+ }
+
+ /**
+ * Set a feed image (URI at minimum). Parameter is a single array with the
+ * required key 'uri'. When rendering as RSS, the required keys are 'uri',
+ * 'title' and 'link'. RSS also specifies three optional parameters 'width',
+ * 'height' and 'description'. Only 'uri' is required and used for Atom rendering.
+ *
+ * @param array $data
+ */
+ public function setImage(array $data)
+ {
+ if (empty($data['uri']) || !is_string($data['uri'])
+ || !Zend_Uri::check($data['uri'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter \'uri\''
+ . ' must be a non-empty string and valid URI/IRI');
+ }
+ $this->_data['image'] = $data;
+ }
+
+ /**
+ * Set the feed language
+ *
+ * @return string|null
+ */
+ public function setLanguage($language)
+ {
+ if (empty($language) || !is_string($language)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['language'] = $language;
+ }
+
+ /**
+ * Set a link to the HTML source
+ *
+ * @param string $link
+ */
+ public function setLink($link)
+ {
+ if (empty($link) || !is_string($link) || !Zend_Uri::check($link)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string and valid URI/IRI');
+ }
+ $this->_data['link'] = $link;
+ }
+
+ /**
+ * Set a link to an XML feed for any feed type/version
+ *
+ * @return string|null
+ */
+ public function setFeedLink($link, $type)
+ {
+ if (empty($link) || !is_string($link) || !Zend_Uri::check($link)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "link"" must be a non-empty string and valid URI/IRI');
+ }
+ if (!in_array(strtolower($type), array('rss', 'rdf', 'atom'))) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "type"; You must declare the type of feed the link points to, i.e. RSS, RDF or Atom');
+ }
+ $this->_data['feedLinks'][strtolower($type)] = $link;
+ }
+
+ /**
+ * Set the feed title
+ *
+ * @return string|null
+ */
+ public function setTitle($title)
+ {
+ if (empty($title) || !is_string($title)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['title'] = $title;
+ }
+
+ /**
+ * Set the feed character encoding
+ *
+ * @param string $encoding
+ */
+ public function setEncoding($encoding)
+ {
+ if (empty($encoding) || !is_string($encoding)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: parameter must be a non-empty string');
+ }
+ $this->_data['encoding'] = $encoding;
+ }
+
+ /**
+ * Set the feed's base URL
+ *
+ * @param string $url
+ */
+ public function setBaseUrl($url)
+ {
+ if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "url" array value'
+ . ' must be a non-empty string and valid URI/IRI');
+ }
+ $this->_data['baseUrl'] = $url;
+ }
+
+ /**
+ * Add a Pubsubhubbub hub endpoint URL
+ *
+ * @param string $url
+ */
+ public function addHub($url)
+ {
+ if (empty($url) || !is_string($url) || !Zend_Uri::check($url)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: "url" array value'
+ . ' must be a non-empty string and valid URI/IRI');
+ }
+ if (!isset($this->_data['hubs'])) {
+ $this->_data['hubs'] = array();
+ }
+ $this->_data['hubs'][] = $url;
+ }
+
+ /**
+ * Add Pubsubhubbub hub endpoint URLs
+ *
+ * @param array $urls
+ */
+ public function addHubs(array $urls)
+ {
+ foreach ($urls as $url) {
+ $this->addHub($url);
+ }
+ }
+
+ /**
+ * Add a feed category
+ *
+ * @param string $category
+ */
+ public function addCategory(array $category)
+ {
+ if (!isset($category['term'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Each category must be an array and '
+ . 'contain at least a "term" element containing the machine '
+ . ' readable category name');
+ }
+ if (isset($category['scheme'])) {
+ if (empty($category['scheme'])
+ || !is_string($category['scheme'])
+ || !Zend_Uri::check($category['scheme'])
+ ) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('The Atom scheme or RSS domain of'
+ . ' a category must be a valid URI');
+ }
+ }
+ if (!isset($this->_data['categories'])) {
+ $this->_data['categories'] = array();
+ }
+ $this->_data['categories'][] = $category;
+ }
+
+ /**
+ * Set an array of feed categories
+ *
+ * @param array $categories
+ */
+ public function addCategories(array $categories)
+ {
+ foreach ($categories as $category) {
+ $this->addCategory($category);
+ }
+ }
+
+ /**
+ * Get a single author
+ *
+ * @param int $index
+ * @return string|null
+ */
+ public function getAuthor($index = 0)
+ {
+ if (isset($this->_data['authors'][$index])) {
+ return $this->_data['authors'][$index];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get an array with feed authors
+ *
+ * @return array
+ */
+ public function getAuthors()
+ {
+ if (!array_key_exists('authors', $this->_data)) {
+ return null;
+ }
+ return $this->_data['authors'];
+ }
+
+ /**
+ * Get the copyright entry
+ *
+ * @return string|null
+ */
+ public function getCopyright()
+ {
+ if (!array_key_exists('copyright', $this->_data)) {
+ return null;
+ }
+ return $this->_data['copyright'];
+ }
+
+ /**
+ * Get the feed creation date
+ *
+ * @return string|null
+ */
+ public function getDateCreated()
+ {
+ if (!array_key_exists('dateCreated', $this->_data)) {
+ return null;
+ }
+ return $this->_data['dateCreated'];
+ }
+
+ /**
+ * Get the feed modification date
+ *
+ * @return string|null
+ */
+ public function getDateModified()
+ {
+ if (!array_key_exists('dateModified', $this->_data)) {
+ return null;
+ }
+ return $this->_data['dateModified'];
+ }
+
+ /**
+ * Get the feed last-build date
+ *
+ * @return string|null
+ */
+ public function getLastBuildDate()
+ {
+ if (!array_key_exists('lastBuildDate', $this->_data)) {
+ return null;
+ }
+ return $this->_data['lastBuildDate'];
+ }
+
+ /**
+ * Get the feed description
+ *
+ * @return string|null
+ */
+ public function getDescription()
+ {
+ if (!array_key_exists('description', $this->_data)) {
+ return null;
+ }
+ return $this->_data['description'];
+ }
+
+ /**
+ * Get the feed generator entry
+ *
+ * @return string|null
+ */
+ public function getGenerator()
+ {
+ if (!array_key_exists('generator', $this->_data)) {
+ return null;
+ }
+ return $this->_data['generator'];
+ }
+
+ /**
+ * Get the feed ID
+ *
+ * @return string|null
+ */
+ public function getId()
+ {
+ if (!array_key_exists('id', $this->_data)) {
+ return null;
+ }
+ return $this->_data['id'];
+ }
+
+ /**
+ * Get the feed image URI
+ *
+ * @return array
+ */
+ public function getImage()
+ {
+ if (!array_key_exists('image', $this->_data)) {
+ return null;
+ }
+ return $this->_data['image'];
+ }
+
+ /**
+ * Get the feed language
+ *
+ * @return string|null
+ */
+ public function getLanguage()
+ {
+ if (!array_key_exists('language', $this->_data)) {
+ return null;
+ }
+ return $this->_data['language'];
+ }
+
+ /**
+ * Get a link to the HTML source
+ *
+ * @return string|null
+ */
+ public function getLink()
+ {
+ if (!array_key_exists('link', $this->_data)) {
+ return null;
+ }
+ return $this->_data['link'];
+ }
+
+ /**
+ * Get a link to the XML feed
+ *
+ * @return string|null
+ */
+ public function getFeedLinks()
+ {
+ if (!array_key_exists('feedLinks', $this->_data)) {
+ return null;
+ }
+ return $this->_data['feedLinks'];
+ }
+
+ /**
+ * Get the feed title
+ *
+ * @return string|null
+ */
+ public function getTitle()
+ {
+ if (!array_key_exists('title', $this->_data)) {
+ return null;
+ }
+ return $this->_data['title'];
+ }
+
+ /**
+ * Get the feed character encoding
+ *
+ * @return string|null
+ */
+ public function getEncoding()
+ {
+ if (!array_key_exists('encoding', $this->_data)) {
+ return 'UTF-8';
+ }
+ return $this->_data['encoding'];
+ }
+
+ /**
+ * Get the feed's base url
+ *
+ * @return string|null
+ */
+ public function getBaseUrl()
+ {
+ if (!array_key_exists('baseUrl', $this->_data)) {
+ return null;
+ }
+ return $this->_data['baseUrl'];
+ }
+
+ /**
+ * Get the URLs used as Pubsubhubbub hubs endpoints
+ *
+ * @return string|null
+ */
+ public function getHubs()
+ {
+ if (!array_key_exists('hubs', $this->_data)) {
+ return null;
+ }
+ return $this->_data['hubs'];
+ }
+
+ /**
+ * Get the feed categories
+ *
+ * @return string|null
+ */
+ public function getCategories()
+ {
+ if (!array_key_exists('categories', $this->_data)) {
+ return null;
+ }
+ return $this->_data['categories'];
+ }
+
+ /**
+ * Resets the instance and deletes all data
+ *
+ * @return void
+ */
+ public function reset()
+ {
+ $this->_data = array();
+ }
+
+ /**
+ * Set the current feed type being exported to "rss" or "atom". This allows
+ * other objects to gracefully choose whether to execute or not, depending
+ * on their appropriateness for the current type, e.g. renderers.
+ *
+ * @param string $type
+ */
+ public function setType($type)
+ {
+ $this->_type = $type;
+ }
+
+ /**
+ * Retrieve the current or last feed type exported.
+ *
+ * @return string Value will be "rss" or "atom"
+ */
+ public function getType()
+ {
+ return $this->_type;
+ }
+
+ /**
+ * Unset a specific data point
+ *
+ * @param string $name
+ */
+ public function remove($name)
+ {
+ if (isset($this->_data[$name])) {
+ unset($this->_data[$name]);
+ }
+ }
+
+ /**
+ * Method overloading: call given method on first extension implementing it
+ *
+ * @param string $method
+ * @param array $args
+ * @return mixed
+ * @throws Zend_Feed_Exception if no extensions implements the method
+ */
+ public function __call($method, $args)
+ {
+ foreach ($this->_extensions as $extension) {
+ try {
+ return call_user_func_array(array($extension, $method), $args);
+ } catch (Zend_Feed_Writer_Exception_InvalidMethodException $e) {
+ }
+ }
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Method: ' . $method
+ . ' does not exist and could not be located on a registered Extension');
+ }
+
+ /**
+ * Load extensions from Zend_Feed_Writer
+ *
+ * @return void
+ */
+ protected function _loadExtensions()
+ {
+ $all = Zend_Feed_Writer::getExtensions();
+ $exts = $all['feed'];
+ foreach ($exts as $ext) {
+ $className = Zend_Feed_Writer::getPluginLoader()->getClassName($ext);
+ $this->_extensions[$ext] = new $className();
+ $this->_extensions[$ext]->setEncoding($this->getEncoding());
+ }
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Renderer/Entry/Atom.php b/libs/Zend/Feed/Writer/Renderer/Entry/Atom.php
new file mode 100644
index 0000000000..76095e89f0
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Renderer/Entry/Atom.php
@@ -0,0 +1,410 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Atom.php 22065 2010-04-30 14:04:57Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Renderer_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Renderer/RendererAbstract.php';
+
+// require_once 'Zend/Feed/Writer/Renderer/Feed/Atom/Source.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Renderer_Entry_Atom
+ extends Zend_Feed_Writer_Renderer_RendererAbstract
+ implements Zend_Feed_Writer_Renderer_RendererInterface
+{
+ /**
+ * Constructor
+ *
+ * @param Zend_Feed_Writer_Entry $container
+ * @return void
+ */
+ public function __construct (Zend_Feed_Writer_Entry $container)
+ {
+ parent::__construct($container);
+ }
+
+ /**
+ * Render atom entry
+ *
+ * @return Zend_Feed_Writer_Renderer_Entry_Atom
+ */
+ public function render()
+ {
+ $this->_dom = new DOMDocument('1.0', $this->_container->getEncoding());
+ $this->_dom->formatOutput = true;
+ $entry = $this->_dom->createElementNS(Zend_Feed_Writer::NAMESPACE_ATOM_10, 'entry');
+ $this->_dom->appendChild($entry);
+
+ $this->_setSource($this->_dom, $entry);
+ $this->_setTitle($this->_dom, $entry);
+ $this->_setDescription($this->_dom, $entry);
+ $this->_setDateCreated($this->_dom, $entry);
+ $this->_setDateModified($this->_dom, $entry);
+ $this->_setLink($this->_dom, $entry);
+ $this->_setId($this->_dom, $entry);
+ $this->_setAuthors($this->_dom, $entry);
+ $this->_setEnclosure($this->_dom, $entry);
+ $this->_setContent($this->_dom, $entry);
+ $this->_setCategories($this->_dom, $entry);
+
+ foreach ($this->_extensions as $ext) {
+ $ext->setType($this->getType());
+ $ext->setRootElement($this->getRootElement());
+ $ext->setDomDocument($this->getDomDocument(), $entry);
+ $ext->render();
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set entry title
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setTitle(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getTitle()) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Atom 1.0 entry elements MUST contain exactly one'
+ . ' atom:title element but a title has not been set';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ $title = $dom->createElement('title');
+ $root->appendChild($title);
+ $title->setAttribute('type', 'html');
+ $cdata = $dom->createCDATASection($this->getDataContainer()->getTitle());
+ $title->appendChild($cdata);
+ }
+
+ /**
+ * Set entry description
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDescription(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getDescription()) {
+ return; // unless src content or base64
+ }
+ $subtitle = $dom->createElement('summary');
+ $root->appendChild($subtitle);
+ $subtitle->setAttribute('type', 'html');
+ $cdata = $dom->createCDATASection(
+ $this->getDataContainer()->getDescription()
+ );
+ $subtitle->appendChild($cdata);
+ }
+
+ /**
+ * Set date entry was modified
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDateModified(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getDateModified()) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Atom 1.0 entry elements MUST contain exactly one'
+ . ' atom:updated element but a modification date has not been set';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+
+ $updated = $dom->createElement('updated');
+ $root->appendChild($updated);
+ $text = $dom->createTextNode(
+ $this->getDataContainer()->getDateModified()->get(Zend_Date::ISO_8601)
+ );
+ $updated->appendChild($text);
+ }
+
+ /**
+ * Set date entry was created
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDateCreated(DOMDocument $dom, DOMElement $root)
+ {
+ if (!$this->getDataContainer()->getDateCreated()) {
+ return;
+ }
+ $el = $dom->createElement('published');
+ $root->appendChild($el);
+ $text = $dom->createTextNode(
+ $this->getDataContainer()->getDateCreated()->get(Zend_Date::ISO_8601)
+ );
+ $el->appendChild($text);
+ }
+
+ /**
+ * Set entry authors
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setAuthors(DOMDocument $dom, DOMElement $root)
+ {
+ $authors = $this->_container->getAuthors();
+ if ((!$authors || empty($authors))) {
+ /**
+ * This will actually trigger an Exception at the feed level if
+ * a feed level author is not set.
+ */
+ return;
+ }
+ foreach ($authors as $data) {
+ $author = $this->_dom->createElement('author');
+ $name = $this->_dom->createElement('name');
+ $author->appendChild($name);
+ $root->appendChild($author);
+ $text = $dom->createTextNode($data['name']);
+ $name->appendChild($text);
+ if (array_key_exists('email', $data)) {
+ $email = $this->_dom->createElement('email');
+ $author->appendChild($email);
+ $text = $dom->createTextNode($data['email']);
+ $email->appendChild($text);
+ }
+ if (array_key_exists('uri', $data)) {
+ $uri = $this->_dom->createElement('uri');
+ $author->appendChild($uri);
+ $text = $dom->createTextNode($data['uri']);
+ $uri->appendChild($text);
+ }
+ }
+ }
+
+ /**
+ * Set entry enclosure
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setEnclosure(DOMDocument $dom, DOMElement $root)
+ {
+ $data = $this->_container->getEnclosure();
+ if ((!$data || empty($data))) {
+ return;
+ }
+ $enclosure = $this->_dom->createElement('link');
+ $enclosure->setAttribute('rel', 'enclosure');
+ if (isset($data['type'])) {
+ $enclosure->setAttribute('type', $data['type']);
+ }
+ if (isset($data['length'])) {
+ $enclosure->setAttribute('length', $data['length']);
+ }
+ $enclosure->setAttribute('href', $data['uri']);
+ $root->appendChild($enclosure);
+ }
+
+ protected function _setLink(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getLink()) {
+ return;
+ }
+ $link = $dom->createElement('link');
+ $root->appendChild($link);
+ $link->setAttribute('rel', 'alternate');
+ $link->setAttribute('type', 'text/html');
+ $link->setAttribute('href', $this->getDataContainer()->getLink());
+ }
+
+ /**
+ * Set entry identifier
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setId(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getId()
+ && !$this->getDataContainer()->getLink()) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Atom 1.0 entry elements MUST contain exactly one '
+ . 'atom:id element, or as an alternative, we can use the same '
+ . 'value as atom:link however neither a suitable link nor an '
+ . 'id have been set';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+
+ if (!$this->getDataContainer()->getId()) {
+ $this->getDataContainer()->setId(
+ $this->getDataContainer()->getLink());
+ }
+ if (!Zend_Uri::check($this->getDataContainer()->getId()) &&
+ !preg_match("#^urn:[a-zA-Z0-9][a-zA-Z0-9\-]{1,31}:([a-zA-Z0-9\(\)\+\,\.\:\=\@\;\$\_\!\*\-]|%[0-9a-fA-F]{2})*#", $this->getDataContainer()->getId())) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Atom 1.0 IDs must be a valid URI/IRI');
+ }
+ $id = $dom->createElement('id');
+ $root->appendChild($id);
+ $text = $dom->createTextNode($this->getDataContainer()->getId());
+ $id->appendChild($text);
+ }
+
+ /**
+ * Set entry content
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setContent(DOMDocument $dom, DOMElement $root)
+ {
+ $content = $this->getDataContainer()->getContent();
+ if (!$content && !$this->getDataContainer()->getLink()) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Atom 1.0 entry elements MUST contain exactly one '
+ . 'atom:content element, or as an alternative, at least one link '
+ . 'with a rel attribute of "alternate" to indicate an alternate '
+ . 'method to consume the content.';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ if (!$content) {
+ return;
+ }
+ $element = $dom->createElement('content');
+ $element->setAttribute('type', 'xhtml');
+ $xhtmlElement = $this->_loadXhtml($content);
+ $xhtml = $dom->importNode($xhtmlElement, true);
+ $element->appendChild($xhtml);
+ $root->appendChild($element);
+ }
+
+ /**
+ * Load a HTML string and attempt to normalise to XML
+ */
+ protected function _loadXhtml($content)
+ {
+ $xhtml = '';
+ if (class_exists('tidy', false)) {
+ $tidy = new tidy;
+ $config = array(
+ 'output-xhtml' => true,
+ 'show-body-only' => true,
+ 'quote-nbsp' => false
+ );
+ $encoding = str_replace('-', '', $this->getEncoding());
+ $tidy->parseString($content, $config, $encoding);
+ $tidy->cleanRepair();
+ $xhtml = (string) $tidy;
+ } else {
+ $xhtml = $content;
+ }
+ $xhtml = preg_replace(array(
+ "/(<[\/]?)([a-zA-Z]+)/"
+ ), '$1xhtml:$2', $xhtml);
+ $dom = new DOMDocument('1.0', $this->getEncoding());
+ $dom->loadXML('<xhtml:div xmlns:xhtml="http://www.w3.org/1999/xhtml">'
+ . $xhtml . '</xhtml:div>');
+ return $dom->documentElement;
+ }
+
+ /**
+ * Set entry cateories
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCategories(DOMDocument $dom, DOMElement $root)
+ {
+ $categories = $this->getDataContainer()->getCategories();
+ if (!$categories) {
+ return;
+ }
+ foreach ($categories as $cat) {
+ $category = $dom->createElement('category');
+ $category->setAttribute('term', $cat['term']);
+ if (isset($cat['label'])) {
+ $category->setAttribute('label', $cat['label']);
+ } else {
+ $category->setAttribute('label', $cat['term']);
+ }
+ if (isset($cat['scheme'])) {
+ $category->setAttribute('scheme', $cat['scheme']);
+ }
+ $root->appendChild($category);
+ }
+ }
+
+ /**
+ * Append Source element (Atom 1.0 Feed Metadata)
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setSource(DOMDocument $dom, DOMElement $root)
+ {
+ $source = $this->getDataContainer()->getSource();
+ if (!$source) {
+ return;
+ }
+ $renderer = new Zend_Feed_Writer_Renderer_Feed_Atom_Source($source);
+ $renderer->setType($this->getType());
+ $element = $renderer->render()->getElement();
+ $imported = $dom->importNode($element, true);
+ $root->appendChild($imported);
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Renderer/Entry/Atom/Deleted.php b/libs/Zend/Feed/Writer/Renderer/Entry/Atom/Deleted.php
new file mode 100644
index 0000000000..fb75262935
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Renderer/Entry/Atom/Deleted.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Atom.php 20506 2010-01-21 22:19:05Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Renderer_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Renderer/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Renderer_Entry_Atom_Deleted
+ extends Zend_Feed_Writer_Renderer_RendererAbstract
+ implements Zend_Feed_Writer_Renderer_RendererInterface
+{
+ /**
+ * Constructor
+ *
+ * @param Zend_Feed_Writer_Deleted $container
+ * @return void
+ */
+ public function __construct (Zend_Feed_Writer_Deleted $container)
+ {
+ parent::__construct($container);
+ }
+
+ /**
+ * Render atom entry
+ *
+ * @return Zend_Feed_Writer_Renderer_Entry_Atom
+ */
+ public function render()
+ {
+ $this->_dom = new DOMDocument('1.0', $this->_container->getEncoding());
+ $this->_dom->formatOutput = true;
+ $entry = $this->_dom->createElement('at:deleted-entry');
+ $this->_dom->appendChild($entry);
+
+ $entry->setAttribute('ref', $this->_container->getReference());
+ $entry->setAttribute('when', $this->_container->getWhen()->get(Zend_Date::ISO_8601));
+
+ $this->_setBy($this->_dom, $entry);
+ $this->_setComment($this->_dom, $entry);
+
+ return $this;
+ }
+
+ /**
+ * Set tombstone comment
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setComment(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getComment()) {
+ return;
+ }
+ $c = $dom->createElement('at:comment');
+ $root->appendChild($c);
+ $c->setAttribute('type', 'html');
+ $cdata = $dom->createCDATASection($this->getDataContainer()->getComment());
+ $c->appendChild($cdata);
+ }
+
+ /**
+ * Set entry authors
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setBy(DOMDocument $dom, DOMElement $root)
+ {
+ $data = $this->_container->getBy();
+ if ((!$data || empty($data))) {
+ return;
+ }
+ $author = $this->_dom->createElement('at:by');
+ $name = $this->_dom->createElement('name');
+ $author->appendChild($name);
+ $root->appendChild($author);
+ $text = $dom->createTextNode($data['name']);
+ $name->appendChild($text);
+ if (array_key_exists('email', $data)) {
+ $email = $this->_dom->createElement('email');
+ $author->appendChild($email);
+ $text = $dom->createTextNode($data['email']);
+ $email->appendChild($text);
+ }
+ if (array_key_exists('uri', $data)) {
+ $uri = $this->_dom->createElement('uri');
+ $author->appendChild($uri);
+ $text = $dom->createTextNode($data['uri']);
+ $uri->appendChild($text);
+ }
+ }
+
+}
diff --git a/libs/Zend/Feed/Writer/Renderer/Entry/Rss.php b/libs/Zend/Feed/Writer/Renderer/Entry/Rss.php
new file mode 100644
index 0000000000..74e80f5707
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Renderer/Entry/Rss.php
@@ -0,0 +1,346 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Rss.php 22065 2010-04-30 14:04:57Z padraic $
+ */
+
+/**
+ * @see Zend_Feed_Writer_Renderer_RendererAbstract
+ */
+// require_once 'Zend/Feed/Writer/Renderer/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Renderer_Entry_Rss
+ extends Zend_Feed_Writer_Renderer_RendererAbstract
+ implements Zend_Feed_Writer_Renderer_RendererInterface
+{
+ /**
+ * Constructor
+ *
+ * @param Zend_Feed_Writer_Entry $container
+ * @return void
+ */
+ public function __construct (Zend_Feed_Writer_Entry $container)
+ {
+ parent::__construct($container);
+ }
+
+ /**
+ * Render RSS entry
+ *
+ * @return Zend_Feed_Writer_Renderer_Entry_Rss
+ */
+ public function render()
+ {
+ $this->_dom = new DOMDocument('1.0', $this->_container->getEncoding());
+ $this->_dom->formatOutput = true;
+ $this->_dom->substituteEntities = false;
+ $entry = $this->_dom->createElement('item');
+ $this->_dom->appendChild($entry);
+
+ $this->_setTitle($this->_dom, $entry);
+ $this->_setDescription($this->_dom, $entry);
+ $this->_setDateCreated($this->_dom, $entry);
+ $this->_setDateModified($this->_dom, $entry);
+ $this->_setLink($this->_dom, $entry);
+ $this->_setId($this->_dom, $entry);
+ $this->_setAuthors($this->_dom, $entry);
+ $this->_setEnclosure($this->_dom, $entry);
+ $this->_setCommentLink($this->_dom, $entry);
+ $this->_setCategories($this->_dom, $entry);
+ foreach ($this->_extensions as $ext) {
+ $ext->setType($this->getType());
+ $ext->setRootElement($this->getRootElement());
+ $ext->setDomDocument($this->getDomDocument(), $entry);
+ $ext->render();
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set entry title
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setTitle(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getDescription()
+ && !$this->getDataContainer()->getTitle()) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'RSS 2.0 entry elements SHOULD contain exactly one'
+ . ' title element but a title has not been set. In addition, there'
+ . ' is no description as required in the absence of a title.';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ $title = $dom->createElement('title');
+ $root->appendChild($title);
+ $text = $dom->createTextNode($this->getDataContainer()->getTitle());
+ $title->appendChild($text);
+ }
+
+ /**
+ * Set entry description
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDescription(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getDescription()
+ && !$this->getDataContainer()->getTitle()) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'RSS 2.0 entry elements SHOULD contain exactly one'
+ . ' description element but a description has not been set. In'
+ . ' addition, there is no title element as required in the absence'
+ . ' of a description.';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ if (!$this->getDataContainer()->getDescription()) {
+ return;
+ }
+ $subtitle = $dom->createElement('description');
+ $root->appendChild($subtitle);
+ $text = $dom->createCDATASection($this->getDataContainer()->getDescription());
+ $subtitle->appendChild($text);
+ }
+
+ /**
+ * Set date entry was last modified
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDateModified(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getDateModified()) {
+ return;
+ }
+
+ $updated = $dom->createElement('pubDate');
+ $root->appendChild($updated);
+ $text = $dom->createTextNode(
+ $this->getDataContainer()->getDateModified()->get(Zend_Date::RSS)
+ );
+ $updated->appendChild($text);
+ }
+
+ /**
+ * Set date entry was created
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDateCreated(DOMDocument $dom, DOMElement $root)
+ {
+ if (!$this->getDataContainer()->getDateCreated()) {
+ return;
+ }
+ if (!$this->getDataContainer()->getDateModified()) {
+ $this->getDataContainer()->setDateModified(
+ $this->getDataContainer()->getDateCreated()
+ );
+ }
+ }
+
+ /**
+ * Set entry authors
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setAuthors(DOMDocument $dom, DOMElement $root)
+ {
+ $authors = $this->_container->getAuthors();
+ if ((!$authors || empty($authors))) {
+ return;
+ }
+ foreach ($authors as $data) {
+ $author = $this->_dom->createElement('author');
+ $name = $data['name'];
+ if (array_key_exists('email', $data)) {
+ $name = $data['email'] . ' (' . $data['name'] . ')';
+ }
+ $text = $dom->createTextNode($name);
+ $author->appendChild($text);
+ $root->appendChild($author);
+ }
+ }
+
+ /**
+ * Set entry enclosure
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setEnclosure(DOMDocument $dom, DOMElement $root)
+ {
+ $data = $this->_container->getEnclosure();
+ if ((!$data || empty($data))) {
+ return;
+ }
+ if (!isset($data['type'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ $exception = new Zend_Feed_Exception('Enclosure "type" is not set');
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ if (!isset($data['length'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ $exception = new Zend_Feed_Exception('Enclosure "length" is not set');
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ if (isset($data['length']) && (int) $data['length'] <= 0) {
+ // require_once 'Zend/Feed/Exception.php';
+ $exception = new Zend_Feed_Exception('Enclosure "length" must be an integer'
+ . ' indicating the content\'s length in bytes');
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ $enclosure = $this->_dom->createElement('enclosure');
+ $enclosure->setAttribute('type', $data['type']);
+ $enclosure->setAttribute('length', $data['length']);
+ $enclosure->setAttribute('url', $data['uri']);
+ $root->appendChild($enclosure);
+ }
+
+ /**
+ * Set link to entry
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setLink(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getLink()) {
+ return;
+ }
+ $link = $dom->createElement('link');
+ $root->appendChild($link);
+ $text = $dom->createTextNode($this->getDataContainer()->getLink());
+ $link->appendChild($text);
+ }
+
+ /**
+ * Set entry identifier
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setId(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getId()
+ && !$this->getDataContainer()->getLink()) {
+ return;
+ }
+
+ $id = $dom->createElement('guid');
+ $root->appendChild($id);
+ if (!$this->getDataContainer()->getId()) {
+ $this->getDataContainer()->setId(
+ $this->getDataContainer()->getLink());
+ }
+ $text = $dom->createTextNode($this->getDataContainer()->getId());
+ $id->appendChild($text);
+ if (!Zend_Uri::check($this->getDataContainer()->getId())) {
+ $id->setAttribute('isPermaLink', 'false');
+ }
+ }
+
+ /**
+ * Set link to entry comments
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCommentLink(DOMDocument $dom, DOMElement $root)
+ {
+ $link = $this->getDataContainer()->getCommentLink();
+ if (!$link) {
+ return;
+ }
+ $clink = $this->_dom->createElement('comments');
+ $text = $dom->createTextNode($link);
+ $clink->appendChild($text);
+ $root->appendChild($clink);
+ }
+
+ /**
+ * Set entry categories
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCategories(DOMDocument $dom, DOMElement $root)
+ {
+ $categories = $this->getDataContainer()->getCategories();
+ if (!$categories) {
+ return;
+ }
+ foreach ($categories as $cat) {
+ $category = $dom->createElement('category');
+ if (isset($cat['scheme'])) {
+ $category->setAttribute('domain', $cat['scheme']);
+ }
+ $text = $dom->createCDATASection($cat['term']);
+ $category->appendChild($text);
+ $root->appendChild($category);
+ }
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Renderer/Feed/Atom.php b/libs/Zend/Feed/Writer/Renderer/Feed/Atom.php
new file mode 100644
index 0000000000..2c88dd4298
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Renderer/Feed/Atom.php
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Atom.php 22098 2010-05-04 18:03:29Z padraic $
+ */
+
+/** @see Zend_Feed_Writer_Feed */
+// require_once 'Zend/Feed/Writer/Feed.php';
+
+/** @see Zend_Version */
+// require_once 'Zend/Version.php';
+
+/** @see Zend_Feed_Writer_Renderer_RendererInterface */
+// require_once 'Zend/Feed/Writer/Renderer/RendererInterface.php';
+
+/** @see Zend_Feed_Writer_Renderer_Entry_Atom */
+// require_once 'Zend/Feed/Writer/Renderer/Entry/Atom.php';
+
+/** @see Zend_Feed_Writer_Renderer_Entry_Atom_Deleted */
+// require_once 'Zend/Feed/Writer/Renderer/Entry/Atom/Deleted.php';
+
+/** @see Zend_Feed_Writer_Renderer_RendererAbstract */
+// require_once 'Zend/Feed/Writer/Renderer/RendererAbstract.php';
+
+// require_once 'Zend/Feed/Writer/Renderer/Feed/Atom/AtomAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Renderer_Feed_Atom
+ extends Zend_Feed_Writer_Renderer_Feed_Atom_AtomAbstract
+ implements Zend_Feed_Writer_Renderer_RendererInterface
+{
+ /**
+ * Constructor
+ *
+ * @param Zend_Feed_Writer_Feed $container
+ * @return void
+ */
+ public function __construct (Zend_Feed_Writer_Feed $container)
+ {
+ parent::__construct($container);
+ }
+
+ /**
+ * Render Atom feed
+ *
+ * @return Zend_Feed_Writer_Renderer_Feed_Atom
+ */
+ public function render()
+ {
+ if (!$this->_container->getEncoding()) {
+ $this->_container->setEncoding('UTF-8');
+ }
+ $this->_dom = new DOMDocument('1.0', $this->_container->getEncoding());
+ $this->_dom->formatOutput = true;
+ $root = $this->_dom->createElementNS(
+ Zend_Feed_Writer::NAMESPACE_ATOM_10, 'feed'
+ );
+ $this->setRootElement($root);
+ $this->_dom->appendChild($root);
+ $this->_setLanguage($this->_dom, $root);
+ $this->_setBaseUrl($this->_dom, $root);
+ $this->_setTitle($this->_dom, $root);
+ $this->_setDescription($this->_dom, $root);
+ $this->_setImage($this->_dom, $root);
+ $this->_setDateCreated($this->_dom, $root);
+ $this->_setDateModified($this->_dom, $root);
+ $this->_setGenerator($this->_dom, $root);
+ $this->_setLink($this->_dom, $root);
+ $this->_setFeedLinks($this->_dom, $root);
+ $this->_setId($this->_dom, $root);
+ $this->_setAuthors($this->_dom, $root);
+ $this->_setCopyright($this->_dom, $root);
+ $this->_setCategories($this->_dom, $root);
+ $this->_setHubs($this->_dom, $root);
+
+ foreach ($this->_extensions as $ext) {
+ $ext->setType($this->getType());
+ $ext->setRootElement($this->getRootElement());
+ $ext->setDomDocument($this->getDomDocument(), $root);
+ $ext->render();
+ }
+
+ foreach ($this->_container as $entry) {
+ if ($this->getDataContainer()->getEncoding()) {
+ $entry->setEncoding($this->getDataContainer()->getEncoding());
+ }
+ if ($entry instanceof Zend_Feed_Writer_Entry) {
+ $renderer = new Zend_Feed_Writer_Renderer_Entry_Atom($entry);
+ } else {
+ if (!$this->_dom->documentElement->hasAttribute('xmlns:at')) {
+ $this->_dom->documentElement->setAttribute(
+ 'xmlns:at', 'http://purl.org/atompub/tombstones/1.0'
+ );
+ }
+ $renderer = new Zend_Feed_Writer_Renderer_Entry_Atom_Deleted($entry);
+ }
+ if ($this->_ignoreExceptions === true) {
+ $renderer->ignoreExceptions();
+ }
+ $renderer->setType($this->getType());
+ $renderer->setRootElement($this->_dom->documentElement);
+ $renderer->render();
+ $element = $renderer->getElement();
+ $imported = $this->_dom->importNode($element, true);
+ $root->appendChild($imported);
+ }
+ return $this;
+ }
+
+}
diff --git a/libs/Zend/Feed/Writer/Renderer/Feed/Atom/AtomAbstract.php b/libs/Zend/Feed/Writer/Renderer/Feed/Atom/AtomAbstract.php
new file mode 100644
index 0000000000..254516e5b5
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Renderer/Feed/Atom/AtomAbstract.php
@@ -0,0 +1,427 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Atom.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/** @see Zend_Feed_Writer_Feed */
+// require_once 'Zend/Feed/Writer/Feed.php';
+
+/** @see Zend_Version */
+// require_once 'Zend/Version.php';
+
+/** @see Zend_Feed_Writer_Renderer_RendererInterface */
+// require_once 'Zend/Feed/Writer/Renderer/RendererInterface.php';
+
+/** @see Zend_Feed_Writer_Renderer_Entry_Atom */
+// require_once 'Zend/Feed/Writer/Renderer/Entry/Atom.php';
+
+/** @see Zend_Feed_Writer_Renderer_RendererAbstract */
+// require_once 'Zend/Feed/Writer/Renderer/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Renderer_Feed_Atom_AtomAbstract
+ extends Zend_Feed_Writer_Renderer_RendererAbstract
+{
+ /**
+ * Constructor
+ *
+ * @param Zend_Feed_Writer_Feed $container
+ * @return void
+ */
+ public function __construct ($container)
+ {
+ parent::__construct($container);
+ }
+
+ /**
+ * Set feed language
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setLanguage(DOMDocument $dom, DOMElement $root)
+ {
+ if ($this->getDataContainer()->getLanguage()) {
+ $root->setAttribute('xml:lang', $this->getDataContainer()
+ ->getLanguage());
+ }
+ }
+
+ /**
+ * Set feed title
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setTitle(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getTitle()) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Atom 1.0 feed elements MUST contain exactly one'
+ . ' atom:title element but a title has not been set';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+
+ $title = $dom->createElement('title');
+ $root->appendChild($title);
+ $title->setAttribute('type', 'text');
+ $text = $dom->createTextNode($this->getDataContainer()->getTitle());
+ $title->appendChild($text);
+ }
+
+ /**
+ * Set feed description
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDescription(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getDescription()) {
+ return;
+ }
+ $subtitle = $dom->createElement('subtitle');
+ $root->appendChild($subtitle);
+ $subtitle->setAttribute('type', 'text');
+ $text = $dom->createTextNode($this->getDataContainer()->getDescription());
+ $subtitle->appendChild($text);
+ }
+
+ /**
+ * Set date feed was last modified
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDateModified(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getDateModified()) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Atom 1.0 feed elements MUST contain exactly one'
+ . ' atom:updated element but a modification date has not been set';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+
+ $updated = $dom->createElement('updated');
+ $root->appendChild($updated);
+ $text = $dom->createTextNode(
+ $this->getDataContainer()->getDateModified()->get(Zend_Date::ISO_8601)
+ );
+ $updated->appendChild($text);
+ }
+
+ /**
+ * Set feed generator string
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setGenerator(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getGenerator()) {
+ $this->getDataContainer()->setGenerator('Zend_Feed_Writer',
+ Zend_Version::VERSION, 'http://framework.zend.com');
+ }
+
+ $gdata = $this->getDataContainer()->getGenerator();
+ $generator = $dom->createElement('generator');
+ $root->appendChild($generator);
+ $text = $dom->createTextNode($gdata['name']);
+ $generator->appendChild($text);
+ if (array_key_exists('uri', $gdata)) {
+ $generator->setAttribute('uri', $gdata['uri']);
+ }
+ if (array_key_exists('version', $gdata)) {
+ $generator->setAttribute('version', $gdata['version']);
+ }
+ }
+
+ /**
+ * Set link to feed
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setLink(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getLink()) {
+ return;
+ }
+ $link = $dom->createElement('link');
+ $root->appendChild($link);
+ $link->setAttribute('rel', 'alternate');
+ $link->setAttribute('type', 'text/html');
+ $link->setAttribute('href', $this->getDataContainer()->getLink());
+ }
+
+ /**
+ * Set feed links
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setFeedLinks(DOMDocument $dom, DOMElement $root)
+ {
+ $flinks = $this->getDataContainer()->getFeedLinks();
+ if(!$flinks || !array_key_exists('atom', $flinks)) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Atom 1.0 feed elements SHOULD contain one atom:link '
+ . 'element with a rel attribute value of "self". This is the '
+ . 'preferred URI for retrieving Atom Feed Documents representing '
+ . 'this Atom feed but a feed link has not been set';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+
+ foreach ($flinks as $type => $href) {
+ $mime = 'application/' . strtolower($type) . '+xml';
+ $flink = $dom->createElement('link');
+ $root->appendChild($flink);
+ $flink->setAttribute('rel', 'self');
+ $flink->setAttribute('type', $mime);
+ $flink->setAttribute('href', $href);
+ }
+ }
+
+ /**
+ * Set feed authors
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setAuthors(DOMDocument $dom, DOMElement $root)
+ {
+ $authors = $this->_container->getAuthors();
+ if (!$authors || empty($authors)) {
+ /**
+ * Technically we should defer an exception until we can check
+ * that all entries contain an author. If any entry is missing
+ * an author, then a missing feed author element is invalid
+ */
+ return;
+ }
+ foreach ($authors as $data) {
+ $author = $this->_dom->createElement('author');
+ $name = $this->_dom->createElement('name');
+ $author->appendChild($name);
+ $root->appendChild($author);
+ $text = $dom->createTextNode($data['name']);
+ $name->appendChild($text);
+ if (array_key_exists('email', $data)) {
+ $email = $this->_dom->createElement('email');
+ $author->appendChild($email);
+ $text = $dom->createTextNode($data['email']);
+ $email->appendChild($text);
+ }
+ if (array_key_exists('uri', $data)) {
+ $uri = $this->_dom->createElement('uri');
+ $author->appendChild($uri);
+ $text = $dom->createTextNode($data['uri']);
+ $uri->appendChild($text);
+ }
+ }
+ }
+
+ /**
+ * Set feed identifier
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setId(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getId()
+ && !$this->getDataContainer()->getLink()) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Atom 1.0 feed elements MUST contain exactly one '
+ . 'atom:id element, or as an alternative, we can use the same '
+ . 'value as atom:link however neither a suitable link nor an '
+ . 'id have been set';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+
+ if (!$this->getDataContainer()->getId()) {
+ $this->getDataContainer()->setId(
+ $this->getDataContainer()->getLink());
+ }
+ $id = $dom->createElement('id');
+ $root->appendChild($id);
+ $text = $dom->createTextNode($this->getDataContainer()->getId());
+ $id->appendChild($text);
+ }
+
+ /**
+ * Set feed copyright
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCopyright(DOMDocument $dom, DOMElement $root)
+ {
+ $copyright = $this->getDataContainer()->getCopyright();
+ if (!$copyright) {
+ return;
+ }
+ $copy = $dom->createElement('rights');
+ $root->appendChild($copy);
+ $text = $dom->createTextNode($copyright);
+ $copy->appendChild($text);
+ }
+
+ /**
+ * Set feed level logo (image)
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setImage(DOMDocument $dom, DOMElement $root)
+ {
+ $image = $this->getDataContainer()->getImage();
+ if (!$image) {
+ return;
+ }
+ $img = $dom->createElement('logo');
+ $root->appendChild($img);
+ $text = $dom->createTextNode($image['uri']);
+ $img->appendChild($text);
+ }
+
+ /**
+ * Set date feed was created
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDateCreated(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getDateCreated()) {
+ return;
+ }
+ if(!$this->getDataContainer()->getDateModified()) {
+ $this->getDataContainer()->setDateModified(
+ $this->getDataContainer()->getDateCreated()
+ );
+ }
+ }
+
+ /**
+ * Set base URL to feed links
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setBaseUrl(DOMDocument $dom, DOMElement $root)
+ {
+ $baseUrl = $this->getDataContainer()->getBaseUrl();
+ if (!$baseUrl) {
+ return;
+ }
+ $root->setAttribute('xml:base', $baseUrl);
+ }
+
+ /**
+ * Set hubs to which this feed pushes
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setHubs(DOMDocument $dom, DOMElement $root)
+ {
+ $hubs = $this->getDataContainer()->getHubs();
+ if (!$hubs) {
+ return;
+ }
+ foreach ($hubs as $hubUrl) {
+ $hub = $dom->createElement('link');
+ $hub->setAttribute('rel', 'hub');
+ $hub->setAttribute('href', $hubUrl);
+ $root->appendChild($hub);
+ }
+ }
+
+ /**
+ * Set feed cateories
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCategories(DOMDocument $dom, DOMElement $root)
+ {
+ $categories = $this->getDataContainer()->getCategories();
+ if (!$categories) {
+ return;
+ }
+ foreach ($categories as $cat) {
+ $category = $dom->createElement('category');
+ $category->setAttribute('term', $cat['term']);
+ if (isset($cat['label'])) {
+ $category->setAttribute('label', $cat['label']);
+ } else {
+ $category->setAttribute('label', $cat['term']);
+ }
+ if (isset($cat['scheme'])) {
+ $category->setAttribute('scheme', $cat['scheme']);
+ }
+ $root->appendChild($category);
+ }
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Renderer/Feed/Atom/Source.php b/libs/Zend/Feed/Writer/Renderer/Feed/Atom/Source.php
new file mode 100644
index 0000000000..125fed1eaf
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Renderer/Feed/Atom/Source.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Atom.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+// require_once 'Zend/Feed/Writer/Renderer/Feed/Atom/AtomAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Renderer_Feed_Atom_Source
+ extends Zend_Feed_Writer_Renderer_Feed_Atom_AtomAbstract
+ implements Zend_Feed_Writer_Renderer_RendererInterface
+{
+
+ /**
+ * Constructor
+ *
+ * @param Zend_Feed_Writer_Feed_Source $container
+ * @return void
+ */
+ public function __construct (Zend_Feed_Writer_Source $container)
+ {
+ parent::__construct($container);
+ }
+
+ /**
+ * Render Atom Feed Metadata (Source element)
+ *
+ * @return Zend_Feed_Writer_Renderer_Feed_Atom
+ */
+ public function render()
+ {
+ if (!$this->_container->getEncoding()) {
+ $this->_container->setEncoding('UTF-8');
+ }
+ $this->_dom = new DOMDocument('1.0', $this->_container->getEncoding());
+ $this->_dom->formatOutput = true;
+ $root = $this->_dom->createElement('source');
+ $this->setRootElement($root);
+ $this->_dom->appendChild($root);
+ $this->_setLanguage($this->_dom, $root);
+ $this->_setBaseUrl($this->_dom, $root);
+ $this->_setTitle($this->_dom, $root);
+ $this->_setDescription($this->_dom, $root);
+ $this->_setDateCreated($this->_dom, $root);
+ $this->_setDateModified($this->_dom, $root);
+ $this->_setGenerator($this->_dom, $root);
+ $this->_setLink($this->_dom, $root);
+ $this->_setFeedLinks($this->_dom, $root);
+ $this->_setId($this->_dom, $root);
+ $this->_setAuthors($this->_dom, $root);
+ $this->_setCopyright($this->_dom, $root);
+ $this->_setCategories($this->_dom, $root);
+
+ foreach ($this->_extensions as $ext) {
+ $ext->setType($this->getType());
+ $ext->setRootElement($this->getRootElement());
+ $ext->setDomDocument($this->getDomDocument(), $root);
+ $ext->render();
+ }
+ return $this;
+ }
+
+ /**
+ * Set feed generator string
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setGenerator(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getGenerator()) {
+ return;
+ }
+
+ $gdata = $this->getDataContainer()->getGenerator();
+ $generator = $dom->createElement('generator');
+ $root->appendChild($generator);
+ $text = $dom->createTextNode($gdata['name']);
+ $generator->appendChild($text);
+ if (array_key_exists('uri', $gdata)) {
+ $generator->setAttribute('uri', $gdata['uri']);
+ }
+ if (array_key_exists('version', $gdata)) {
+ $generator->setAttribute('version', $gdata['version']);
+ }
+ }
+
+}
diff --git a/libs/Zend/Feed/Writer/Renderer/Feed/Rss.php b/libs/Zend/Feed/Writer/Renderer/Feed/Rss.php
new file mode 100644
index 0000000000..07b94e7b86
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Renderer/Feed/Rss.php
@@ -0,0 +1,505 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Rss.php 22108 2010-05-05 13:44:11Z padraic $
+ */
+
+/** @see Zend_Feed_Writer_Feed */
+// require_once 'Zend/Feed/Writer/Feed.php';
+
+/** @see Zend_Version */
+// require_once 'Zend/Version.php';
+
+/** @see Zend_Feed_Writer_Renderer_RendererInterface */
+// require_once 'Zend/Feed/Writer/Renderer/RendererInterface.php';
+
+/** @see Zend_Feed_Writer_Renderer_Entry_Rss */
+// require_once 'Zend/Feed/Writer/Renderer/Entry/Rss.php';
+
+/** @see Zend_Feed_Writer_Renderer_RendererAbstract */
+// require_once 'Zend/Feed/Writer/Renderer/RendererAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Renderer_Feed_Rss
+ extends Zend_Feed_Writer_Renderer_RendererAbstract
+ implements Zend_Feed_Writer_Renderer_RendererInterface
+{
+ /**
+ * Constructor
+ *
+ * @param Zend_Feed_Writer_Feed $container
+ * @return void
+ */
+ public function __construct (Zend_Feed_Writer_Feed $container)
+ {
+ parent::__construct($container);
+ }
+
+ /**
+ * Render RSS feed
+ *
+ * @return Zend_Feed_Writer_Renderer_Feed_Rss
+ */
+ public function render()
+ {
+ if (!$this->_container->getEncoding()) {
+ $this->_container->setEncoding('UTF-8');
+ }
+ $this->_dom = new DOMDocument('1.0', $this->_container->getEncoding());
+ $this->_dom->formatOutput = true;
+ $this->_dom->substituteEntities = false;
+ $rss = $this->_dom->createElement('rss');
+ $this->setRootElement($rss);
+ $rss->setAttribute('version', '2.0');
+
+ $channel = $this->_dom->createElement('channel');
+ $rss->appendChild($channel);
+ $this->_dom->appendChild($rss);
+ $this->_setLanguage($this->_dom, $channel);
+ $this->_setBaseUrl($this->_dom, $channel);
+ $this->_setTitle($this->_dom, $channel);
+ $this->_setDescription($this->_dom, $channel);
+ $this->_setImage($this->_dom, $channel);
+ $this->_setDateCreated($this->_dom, $channel);
+ $this->_setDateModified($this->_dom, $channel);
+ $this->_setLastBuildDate($this->_dom, $channel);
+ $this->_setGenerator($this->_dom, $channel);
+ $this->_setLink($this->_dom, $channel);
+ $this->_setAuthors($this->_dom, $channel);
+ $this->_setCopyright($this->_dom, $channel);
+ $this->_setCategories($this->_dom, $channel);
+
+ foreach ($this->_extensions as $ext) {
+ $ext->setType($this->getType());
+ $ext->setRootElement($this->getRootElement());
+ $ext->setDomDocument($this->getDomDocument(), $channel);
+ $ext->render();
+ }
+
+ foreach ($this->_container as $entry) {
+ if ($this->getDataContainer()->getEncoding()) {
+ $entry->setEncoding($this->getDataContainer()->getEncoding());
+ }
+ if ($entry instanceof Zend_Feed_Writer_Entry) {
+ $renderer = new Zend_Feed_Writer_Renderer_Entry_Rss($entry);
+ } else {
+ continue;
+ }
+ if ($this->_ignoreExceptions === true) {
+ $renderer->ignoreExceptions();
+ }
+ $renderer->setType($this->getType());
+ $renderer->setRootElement($this->_dom->documentElement);
+ $renderer->render();
+ $element = $renderer->getElement();
+ $imported = $this->_dom->importNode($element, true);
+ $channel->appendChild($imported);
+ }
+ return $this;
+ }
+
+ /**
+ * Set feed language
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setLanguage(DOMDocument $dom, DOMElement $root)
+ {
+ $lang = $this->getDataContainer()->getLanguage();
+ if (!$lang) {
+ return;
+ }
+ $language = $dom->createElement('language');
+ $root->appendChild($language);
+ $language->nodeValue = $lang;
+ }
+
+ /**
+ * Set feed title
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setTitle(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getTitle()) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'RSS 2.0 feed elements MUST contain exactly one'
+ . ' title element but a title has not been set';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+
+ $title = $dom->createElement('title');
+ $root->appendChild($title);
+ $text = $dom->createTextNode($this->getDataContainer()->getTitle());
+ $title->appendChild($text);
+ }
+
+ /**
+ * Set feed description
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDescription(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getDescription()) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'RSS 2.0 feed elements MUST contain exactly one'
+ . ' description element but one has not been set';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ $subtitle = $dom->createElement('description');
+ $root->appendChild($subtitle);
+ $text = $dom->createTextNode($this->getDataContainer()->getDescription());
+ $subtitle->appendChild($text);
+ }
+
+ /**
+ * Set date feed was last modified
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDateModified(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getDateModified()) {
+ return;
+ }
+
+ $updated = $dom->createElement('pubDate');
+ $root->appendChild($updated);
+ $text = $dom->createTextNode(
+ $this->getDataContainer()->getDateModified()->get(Zend_Date::RSS)
+ );
+ $updated->appendChild($text);
+ }
+
+ /**
+ * Set feed generator string
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setGenerator(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getGenerator()) {
+ $this->getDataContainer()->setGenerator('Zend_Feed_Writer',
+ Zend_Version::VERSION, 'http://framework.zend.com');
+ }
+
+ $gdata = $this->getDataContainer()->getGenerator();
+ $generator = $dom->createElement('generator');
+ $root->appendChild($generator);
+ $name = $gdata['name'];
+ if (array_key_exists('version', $gdata)) {
+ $name .= ' ' . $gdata['version'];
+ }
+ if (array_key_exists('uri', $gdata)) {
+ $name .= ' (' . $gdata['uri'] . ')';
+ }
+ $text = $dom->createTextNode($name);
+ $generator->appendChild($text);
+ }
+
+ /**
+ * Set link to feed
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setLink(DOMDocument $dom, DOMElement $root)
+ {
+ $value = $this->getDataContainer()->getLink();
+ if(!$value) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'RSS 2.0 feed elements MUST contain exactly one'
+ . ' link element but one has not been set';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ $link = $dom->createElement('link');
+ $root->appendChild($link);
+ $text = $dom->createTextNode($value);
+ $link->appendChild($text);
+ if (!Zend_Uri::check($value)) {
+ $link->setAttribute('isPermaLink', 'false');
+ }
+ }
+
+ /**
+ * Set feed authors
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setAuthors(DOMDocument $dom, DOMElement $root)
+ {
+ $authors = $this->getDataContainer()->getAuthors();
+ if (!$authors || empty($authors)) {
+ return;
+ }
+ foreach ($authors as $data) {
+ $author = $this->_dom->createElement('author');
+ $name = $data['name'];
+ if (array_key_exists('email', $data)) {
+ $name = $data['email'] . ' (' . $data['name'] . ')';
+ }
+ $text = $dom->createTextNode($name);
+ $author->appendChild($text);
+ $root->appendChild($author);
+ }
+ }
+
+ /**
+ * Set feed copyright
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCopyright(DOMDocument $dom, DOMElement $root)
+ {
+ $copyright = $this->getDataContainer()->getCopyright();
+ if (!$copyright) {
+ return;
+ }
+ $copy = $dom->createElement('copyright');
+ $root->appendChild($copy);
+ $text = $dom->createTextNode($copyright);
+ $copy->appendChild($text);
+ }
+
+ /**
+ * Set feed channel image
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setImage(DOMDocument $dom, DOMElement $root)
+ {
+ $image = $this->getDataContainer()->getImage();
+ if (!$image) {
+ return;
+ }
+ if (!isset($image['title']) || empty($image['title'])
+ || !is_string($image['title'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'RSS 2.0 feed images must include a title';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ if (empty($image['link']) || !is_string($image['link'])
+ || !Zend_Uri::check($image['link'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Invalid parameter: parameter \'link\''
+ . ' must be a non-empty string and valid URI/IRI';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ $img = $dom->createElement('image');
+ $root->appendChild($img);
+ $url = $dom->createElement('url');
+ $text = $dom->createTextNode($image['uri']);
+ $url->appendChild($text);
+ $title = $dom->createElement('title');
+ $text = $dom->createTextNode($image['title']);
+ $title->appendChild($text);
+ $link = $dom->createElement('link');
+ $text = $dom->createTextNode($image['link']);
+ $link->appendChild($text);
+ $img->appendChild($url);
+ $img->appendChild($title);
+ $img->appendChild($link);
+ if (isset($image['height'])) {
+ if (!ctype_digit((string) $image['height']) || $image['height'] > 400) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Invalid parameter: parameter \'height\''
+ . ' must be an integer not exceeding 400';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ $height = $dom->createElement('height');
+ $text = $dom->createTextNode($image['height']);
+ $height->appendChild($text);
+ $img->appendChild($height);
+ }
+ if (isset($image['width'])) {
+ if (!ctype_digit((string) $image['width']) || $image['width'] > 144) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Invalid parameter: parameter \'width\''
+ . ' must be an integer not exceeding 144';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ $width = $dom->createElement('width');
+ $text = $dom->createTextNode($image['width']);
+ $width->appendChild($text);
+ $img->appendChild($width);
+ }
+ if (isset($image['description'])) {
+ if (empty($image['description']) || !is_string($image['description'])) {
+ // require_once 'Zend/Feed/Exception.php';
+ $message = 'Invalid parameter: parameter \'description\''
+ . ' must be a non-empty string';
+ $exception = new Zend_Feed_Exception($message);
+ if (!$this->_ignoreExceptions) {
+ throw $exception;
+ } else {
+ $this->_exceptions[] = $exception;
+ return;
+ }
+ }
+ $desc = $dom->createElement('description');
+ $text = $dom->createTextNode($image['description']);
+ $desc->appendChild($text);
+ $img->appendChild($desc);
+ }
+ }
+
+ /**
+ * Set date feed was created
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setDateCreated(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getDateCreated()) {
+ return;
+ }
+ if(!$this->getDataContainer()->getDateModified()) {
+ $this->getDataContainer()->setDateModified(
+ $this->getDataContainer()->getDateCreated()
+ );
+ }
+ }
+
+ /**
+ * Set date feed last build date
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setLastBuildDate(DOMDocument $dom, DOMElement $root)
+ {
+ if(!$this->getDataContainer()->getLastBuildDate()) {
+ return;
+ }
+
+ $lastBuildDate = $dom->createElement('lastBuildDate');
+ $root->appendChild($lastBuildDate);
+ $text = $dom->createTextNode(
+ $this->getDataContainer()->getLastBuildDate()->get(Zend_Date::RSS)
+ );
+ $lastBuildDate->appendChild($text);
+ }
+
+ /**
+ * Set base URL to feed links
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setBaseUrl(DOMDocument $dom, DOMElement $root)
+ {
+ $baseUrl = $this->getDataContainer()->getBaseUrl();
+ if (!$baseUrl) {
+ return;
+ }
+ $root->setAttribute('xml:base', $baseUrl);
+ }
+
+ /**
+ * Set feed categories
+ *
+ * @param DOMDocument $dom
+ * @param DOMElement $root
+ * @return void
+ */
+ protected function _setCategories(DOMDocument $dom, DOMElement $root)
+ {
+ $categories = $this->getDataContainer()->getCategories();
+ if (!$categories) {
+ return;
+ }
+ foreach ($categories as $cat) {
+ $category = $dom->createElement('category');
+ if (isset($cat['scheme'])) {
+ $category->setAttribute('domain', $cat['scheme']);
+ }
+ $text = $dom->createTextNode($cat['term']);
+ $category->appendChild($text);
+ $root->appendChild($category);
+ }
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Renderer/RendererAbstract.php b/libs/Zend/Feed/Writer/Renderer/RendererAbstract.php
new file mode 100644
index 0000000000..b3457ed643
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Renderer/RendererAbstract.php
@@ -0,0 +1,250 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: RendererAbstract.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/** @see Zend_Feed_Writer */
+// require_once 'Zend/Feed/Writer.php';
+
+/** @see Zend_Version */
+// require_once 'Zend/Version.php';
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Renderer_RendererAbstract
+{
+ /**
+ * Extensions
+ * @var array
+ */
+ protected $_extensions = array();
+
+ /**
+ * @var mixed
+ */
+ protected $_container = null;
+
+ /**
+ * @var DOMDocument
+ */
+ protected $_dom = null;
+
+ /**
+ * @var bool
+ */
+ protected $_ignoreExceptions = false;
+
+ /**
+ * @var array
+ */
+ protected $_exceptions = array();
+
+ /**
+ * Encoding of all text values
+ *
+ * @var string
+ */
+ protected $_encoding = 'UTF-8';
+
+ /**
+ * Holds the value "atom" or "rss" depending on the feed type set when
+ * when last exported.
+ *
+ * @var string
+ */
+ protected $_type = null;
+
+ /**
+ * @var DOMElement
+ */
+ protected $_rootElement = null;
+
+ /**
+ * Constructor
+ *
+ * @param mixed $container
+ * @return void
+ */
+ public function __construct($container)
+ {
+ $this->_container = $container;
+ $this->setType($container->getType());
+ $this->_loadExtensions();
+ }
+
+ /**
+ * Save XML to string
+ *
+ * @return string
+ */
+ public function saveXml()
+ {
+ return $this->getDomDocument()->saveXml();
+ }
+
+ /**
+ * Get DOM document
+ *
+ * @return DOMDocument
+ */
+ public function getDomDocument()
+ {
+ return $this->_dom;
+ }
+
+ /**
+ * Get document element from DOM
+ *
+ * @return DOMElement
+ */
+ public function getElement()
+ {
+ return $this->getDomDocument()->documentElement;
+ }
+
+ /**
+ * Get data container of items being rendered
+ *
+ * @return mixed
+ */
+ public function getDataContainer()
+ {
+ return $this->_container;
+ }
+
+ /**
+ * Set feed encoding
+ *
+ * @param string $enc
+ * @return Zend_Feed_Writer_Renderer_RendererAbstract
+ */
+ public function setEncoding($enc)
+ {
+ $this->_encoding = $enc;
+ return $this;
+ }
+
+ /**
+ * Get feed encoding
+ *
+ * @return string
+ */
+ public function getEncoding()
+ {
+ return $this->_encoding;
+ }
+
+ /**
+ * Indicate whether or not to ignore exceptions
+ *
+ * @param bool $bool
+ * @return Zend_Feed_Writer_Renderer_RendererAbstract
+ */
+ public function ignoreExceptions($bool = true)
+ {
+ if (!is_bool($bool)) {
+ // require_once 'Zend/Feed/Exception.php';
+ throw new Zend_Feed_Exception('Invalid parameter: $bool. Should be TRUE or FALSE (defaults to TRUE if null)');
+ }
+ $this->_ignoreExceptions = $bool;
+ return $this;
+ }
+
+ /**
+ * Get exception list
+ *
+ * @return array
+ */
+ public function getExceptions()
+ {
+ return $this->_exceptions;
+ }
+
+ /**
+ * Set the current feed type being exported to "rss" or "atom". This allows
+ * other objects to gracefully choose whether to execute or not, depending
+ * on their appropriateness for the current type, e.g. renderers.
+ *
+ * @param string $type
+ */
+ public function setType($type)
+ {
+ $this->_type = $type;
+ }
+
+ /**
+ * Retrieve the current or last feed type exported.
+ *
+ * @return string Value will be "rss" or "atom"
+ */
+ public function getType()
+ {
+ return $this->_type;
+ }
+
+ /**
+ * Sets the absolute root element for the XML feed being generated. This
+ * helps simplify the appending of namespace declarations, but also ensures
+ * namespaces are added to the root element - not scattered across the entire
+ * XML file - may assist namespace unsafe parsers and looks pretty ;).
+ *
+ * @param DOMElement $root
+ */
+ public function setRootElement(DOMElement $root)
+ {
+ $this->_rootElement = $root;
+ }
+
+ /**
+ * Retrieve the absolute root element for the XML feed being generated.
+ *
+ * @return DOMElement
+ */
+ public function getRootElement()
+ {
+ return $this->_rootElement;
+ }
+
+ /**
+ * Load extensions from Zend_Feed_Writer
+ *
+ * @return void
+ */
+ protected function _loadExtensions()
+ {
+ Zend_Feed_Writer::registerCoreExtensions();
+ $all = Zend_Feed_Writer::getExtensions();
+ if (stripos(get_class($this), 'entry')) {
+ $exts = $all['entryRenderer'];
+ } else {
+ $exts = $all['feedRenderer'];
+ }
+ foreach ($exts as $extension) {
+ $className = Zend_Feed_Writer::getPluginLoader()->getClassName($extension);
+ $this->_extensions[$extension] = new $className(
+ $this->getDataContainer()
+ );
+ $this->_extensions[$extension]->setEncoding($this->getEncoding());
+ }
+ }
+}
diff --git a/libs/Zend/Feed/Writer/Renderer/RendererInterface.php b/libs/Zend/Feed/Writer/Renderer/RendererInterface.php
new file mode 100644
index 0000000000..89b4294416
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Renderer/RendererInterface.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: RendererInterface.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+interface Zend_Feed_Writer_Renderer_RendererInterface
+{
+ /**
+ * Render feed/entry
+ *
+ * @return void
+ */
+ public function render();
+
+ /**
+ * Save feed and/or entry to XML and return string
+ *
+ * @return string
+ */
+ public function saveXml();
+
+ /**
+ * Get DOM document
+ *
+ * @return DOMDocument
+ */
+ public function getDomDocument();
+
+ /**
+ * Get document element from DOM
+ *
+ * @return DOMElement
+ */
+ public function getElement();
+
+ /**
+ * Get data container containing feed items
+ *
+ * @return mixed
+ */
+ public function getDataContainer();
+
+ /**
+ * Should exceptions be ignored?
+ *
+ * @return mixed
+ */
+ public function ignoreExceptions();
+
+ /**
+ * Get list of thrown exceptions
+ *
+ * @return array
+ */
+ public function getExceptions();
+
+ /**
+ * Set the current feed type being exported to "rss" or "atom". This allows
+ * other objects to gracefully choose whether to execute or not, depending
+ * on their appropriateness for the current type, e.g. renderers.
+ *
+ * @param string $type
+ */
+ public function setType($type);
+
+ /**
+ * Retrieve the current or last feed type exported.
+ *
+ * @return string Value will be "rss" or "atom"
+ */
+ public function getType();
+
+ /**
+ * Sets the absolute root element for the XML feed being generated. This
+ * helps simplify the appending of namespace declarations, but also ensures
+ * namespaces are added to the root element - not scattered across the entire
+ * XML file - may assist namespace unsafe parsers and looks pretty ;).
+ *
+ * @param DOMElement $root
+ */
+ public function setRootElement(DOMElement $root);
+
+ /**
+ * Retrieve the absolute root element for the XML feed being generated.
+ *
+ * @return DOMElement
+ */
+ public function getRootElement();
+}
diff --git a/libs/Zend/Feed/Writer/Source.php b/libs/Zend/Feed/Writer/Source.php
new file mode 100644
index 0000000000..3861fc77fc
--- /dev/null
+++ b/libs/Zend/Feed/Writer/Source.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Feed.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+// require_once 'Zend/Feed/Writer/Feed/FeedAbstract.php';
+
+ /**
+ * @category Zend
+ * @package Zend_Feed_Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Feed_Writer_Source extends Zend_Feed_Writer_Feed_FeedAbstract
+{
+
+}
diff --git a/libs/Zend/Http/Client.php b/libs/Zend/Http/Client.php
index 5596a190ce..1cd17e8da4 100644
--- a/libs/Zend/Http/Client.php
+++ b/libs/Zend/Http/Client.php
@@ -16,33 +16,38 @@
* @category Zend
* @package Zend_Http
* @subpackage Client
- * @version $Id: Client.php 17843 2009-08-27 14:40:35Z cogo $
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Client.php 21952 2010-04-19 18:44:26Z shahar $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* @see Zend_Loader
*/
-require_once 'Zend/Loader.php';
+// require_once 'Zend/Loader.php';
/**
* @see Zend_Uri
*/
-require_once 'Zend/Uri.php';
+// require_once 'Zend/Uri.php';
/**
* @see Zend_Http_Client_Adapter_Interface
*/
-require_once 'Zend/Http/Client/Adapter/Interface.php';
+// require_once 'Zend/Http/Client/Adapter/Interface.php';
/**
* @see Zend_Http_Response
*/
-require_once 'Zend/Http/Response.php';
+// require_once 'Zend/Http/Response.php';
+
+/**
+ * @see Zend_Http_Response_Stream
+ */
+// require_once 'Zend/Http/Response/Stream.php';
/**
* Zend_Http_Client is an implemetation of an HTTP client in PHP. The client
@@ -55,7 +60,7 @@ require_once 'Zend/Http/Response.php';
* @package Zend_Http
* @subpackage Client
* @throws Zend_Http_Client_Exception
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Http_Client
@@ -71,6 +76,7 @@ class Zend_Http_Client
const TRACE = 'TRACE';
const OPTIONS = 'OPTIONS';
const CONNECT = 'CONNECT';
+ const MERGE = 'MERGE';
/**
* Supported HTTP Authentication methods
@@ -110,7 +116,9 @@ class Zend_Http_Client
'httpversion' => self::HTTP_1,
'keepalive' => false,
'storeresponse' => true,
- 'strict' => true
+ 'strict' => true,
+ 'output_stream' => false,
+ 'encodecookies' => true,
);
/**
@@ -125,7 +133,7 @@ class Zend_Http_Client
*
* @var Zend_Uri_Http
*/
- protected $uri;
+ protected $uri = null;
/**
* Associative array of request headers
@@ -263,10 +271,15 @@ class Zend_Http_Client
if (!$uri instanceof Zend_Uri_Http) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception('Passed parameter is not a valid HTTP URI.');
}
+ // Set auth if username and password has been specified in the uri
+ if ($uri->getUsername() && $uri->getPassword()) {
+ $this->setAuth($uri->getUsername(), $uri->getPassword());
+ }
+
// We have no ports, set the defaults
if (! $uri->getPort()) {
$uri->setPort(($uri->getScheme() == 'https' ? 443 : 80));
@@ -306,7 +319,7 @@ class Zend_Http_Client
} elseif (! is_array($config)) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception('Array or Zend_Config object expected, got ' . gettype($config));
}
@@ -337,7 +350,7 @@ class Zend_Http_Client
{
if (! preg_match('/^[^\x00-\x1f\x7f-\xff\(\)<>@,;:\\\\"\/\[\]\?={}\s]+$/', $method)) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception("'{$method}' is not a valid HTTP request method.");
}
@@ -389,7 +402,7 @@ class Zend_Http_Client
// Make sure the name is valid if we are in strict mode
if ($this->config['strict'] && (! preg_match('/^[a-zA-Z0-9-]+$/', $name))) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception("{$name} is not a valid HTTP header name");
}
@@ -536,12 +549,17 @@ class Zend_Http_Client
if ($user === false || $user === null) {
$this->auth = null;
+ // Clear the auth information in the uri instance as well
+ if ($this->uri instanceof Zend_Uri_Http) {
+ $this->getUri()->setUsername('');
+ $this->getUri()->setPassword('');
+ }
// Else, set up authentication
} else {
// Check we got a proper authentication type
if (! defined('self::AUTH_' . strtoupper($type))) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception("Invalid or not supported authentication type: '$type'");
}
@@ -568,7 +586,7 @@ class Zend_Http_Client
public function setCookieJar($cookiejar = true)
{
if (! class_exists('Zend_Http_CookieJar')) {
- require_once 'Zend/Http/CookieJar.php';
+ // require_once 'Zend/Http/CookieJar.php';
}
if ($cookiejar instanceof Zend_Http_CookieJar) {
@@ -579,7 +597,7 @@ class Zend_Http_Client
$this->cookiejar = null;
} else {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception('Invalid parameter type passed as CookieJar');
}
@@ -608,7 +626,7 @@ class Zend_Http_Client
public function setCookie($cookie, $value = null)
{
if (! class_exists('Zend_Http_Cookie')) {
- require_once 'Zend/Http/Cookie.php';
+ // require_once 'Zend/Http/Cookie.php';
}
if (is_array($cookie)) {
@@ -623,7 +641,7 @@ class Zend_Http_Client
return $this;
}
- if ($value !== null) {
+ if ($value !== null && $this->config['encodecookies']) {
$value = urlencode($value);
}
@@ -631,7 +649,9 @@ class Zend_Http_Client
if ($cookie instanceof Zend_Http_Cookie) {
$this->cookiejar->addCookie($cookie);
} elseif (is_string($cookie) && $value !== null) {
- $cookie = Zend_Http_Cookie::fromString("{$cookie}={$value}", $this->uri);
+ $cookie = Zend_Http_Cookie::fromString("{$cookie}={$value}",
+ $this->uri,
+ $this->config['encodecookies']);
$this->cookiejar->addCookie($cookie);
}
} else {
@@ -643,7 +663,7 @@ class Zend_Http_Client
if (preg_match("/[=,; \t\r\n\013\014]/", $cookie)) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception("Cookie name cannot contain these characters: =,; \t\r\n\013\014 ({$cookie})");
}
@@ -683,7 +703,7 @@ class Zend_Http_Client
if ($data === null) {
if (($data = @file_get_contents($filename)) === false) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception("Unable to read file '{$filename}' for upload");
}
@@ -726,7 +746,9 @@ class Zend_Http_Client
* 2. For backwards compatibilty: If someone uses the old post($data) method.
* this method will be used to set the encoded data.
*
- * @param string $data
+ * $data can also be stream (such as file) from which the data will be read.
+ *
+ * @param string|resource $data
* @param string $enctype
* @return Zend_Http_Client
*/
@@ -734,7 +756,13 @@ class Zend_Http_Client
{
$this->raw_post_data = $data;
$this->setEncType($enctype);
-
+ if (is_resource($data)) {
+ // We've got stream data
+ $stat = @fstat($data);
+ if($stat) {
+ $this->setHeaders(self::CONTENT_LENGTH, $stat['size']);
+ }
+ }
return $this;
}
@@ -744,9 +772,13 @@ class Zend_Http_Client
* Should be used to reset the request parameters if the client is
* used for several concurrent requests.
*
+ * clearAll parameter controls if we clean just parameters or also
+ * headers and last_*
+ *
+ * @param bool $clearAll Should all data be cleared?
* @return Zend_Http_Client
*/
- public function resetParameters()
+ public function resetParameters($clearAll = false)
{
// Reset parameter data
$this->paramsGet = array();
@@ -754,12 +786,18 @@ class Zend_Http_Client
$this->files = array();
$this->raw_post_data = null;
- // Clear outdated headers
- if (isset($this->headers[strtolower(self::CONTENT_TYPE)])) {
- unset($this->headers[strtolower(self::CONTENT_TYPE)]);
- }
- if (isset($this->headers[strtolower(self::CONTENT_LENGTH)])) {
- unset($this->headers[strtolower(self::CONTENT_LENGTH)]);
+ if($clearAll) {
+ $this->headers = array();
+ $this->last_request = null;
+ $this->last_response = null;
+ } else {
+ // Clear outdated headers
+ if (isset($this->headers[strtolower(self::CONTENT_TYPE)])) {
+ unset($this->headers[strtolower(self::CONTENT_TYPE)]);
+ }
+ if (isset($this->headers[strtolower(self::CONTENT_LENGTH)])) {
+ unset($this->headers[strtolower(self::CONTENT_LENGTH)]);
+ }
}
return $this;
@@ -803,12 +841,12 @@ class Zend_Http_Client
if (is_string($adapter)) {
if (!class_exists($adapter)) {
try {
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
Zend_Loader::loadClass($adapter);
} catch (Zend_Exception $e) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
- throw new Zend_Http_Client_Exception("Unable to load adapter '$adapter': {$e->getMessage()}");
+ // require_once 'Zend/Http/Client/Exception.php';
+ throw new Zend_Http_Client_Exception("Unable to load adapter '$adapter': {$e->getMessage()}", 0, $e);
}
}
@@ -817,7 +855,7 @@ class Zend_Http_Client
if (! $adapter instanceof Zend_Http_Client_Adapter_Interface) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception('Passed adapter is not a HTTP connection adapter');
}
@@ -828,6 +866,62 @@ class Zend_Http_Client
}
/**
+ * Load the connection adapter
+ *
+ * @return Zend_Http_Client_Adapter_Interface $adapter
+ */
+ public function getAdapter()
+ {
+ return $this->adapter;
+ }
+
+ /**
+ * Set streaming for received data
+ *
+ * @param string|boolean $streamfile Stream file, true for temp file, false/null for no streaming
+ * @return Zend_Http_Client
+ */
+ public function setStream($streamfile = true)
+ {
+ $this->setConfig(array("output_stream" => $streamfile));
+ return $this;
+ }
+
+ /**
+ * Get status of streaming for received data
+ * @return boolean|string
+ */
+ public function getStream()
+ {
+ return $this->config["output_stream"];
+ }
+
+ /**
+ * Create temporary stream
+ *
+ * @return resource
+ */
+ protected function _openTempStream()
+ {
+ $this->_stream_name = $this->config['output_stream'];
+ if(!is_string($this->_stream_name)) {
+ // If name is not given, create temp name
+ $this->_stream_name = tempnam(isset($this->config['stream_tmp_dir'])?$this->config['stream_tmp_dir']:sys_get_temp_dir(),
+ 'Zend_Http_Client');
+ }
+
+ if (false === ($fp = @fopen($this->_stream_name, "w+b"))) {
+ if ($this->adapter instanceof Zend_Http_Client_Adapter_Interface) {
+ $this->adapter->close();
+ }
+ // require_once 'Zend/Http/Client/Exception.php';
+ throw new Zend_Http_Client_Exception("Could not open temp file {$this->_stream_name}");
+ }
+
+ return $fp;
+ }
+
+ /**
* Send the HTTP request and return an HTTP response object
*
* @param string $method
@@ -838,7 +932,7 @@ class Zend_Http_Client
{
if (! $this->uri instanceof Zend_Uri_Http) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception('No valid URI has been passed to the client');
}
@@ -870,21 +964,52 @@ class Zend_Http_Client
$body = $this->_prepareBody();
$headers = $this->_prepareHeaders();
+ // check that adapter supports streaming before using it
+ if(is_resource($body) && !($this->adapter instanceof Zend_Http_Client_Adapter_Stream)) {
+ /** @see Zend_Http_Client_Exception */
+ // require_once 'Zend/Http/Client/Exception.php';
+ throw new Zend_Http_Client_Exception('Adapter does not support streaming');
+ }
+
// Open the connection, send the request and read the response
$this->adapter->connect($uri->getHost(), $uri->getPort(),
($uri->getScheme() == 'https' ? true : false));
+ if($this->config['output_stream']) {
+ if($this->adapter instanceof Zend_Http_Client_Adapter_Stream) {
+ $stream = $this->_openTempStream();
+ $this->adapter->setOutputStream($stream);
+ } else {
+ /** @see Zend_Http_Client_Exception */
+ // require_once 'Zend/Http/Client/Exception.php';
+ throw new Zend_Http_Client_Exception('Adapter does not support streaming');
+ }
+ }
+
$this->last_request = $this->adapter->write($this->method,
$uri, $this->config['httpversion'], $headers, $body);
$response = $this->adapter->read();
if (! $response) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception('Unable to read response, or response is empty');
}
- $response = Zend_Http_Response::fromString($response);
+ if($this->config['output_stream']) {
+ rewind($stream);
+ // cleanup the adapter
+ $this->adapter->setOutputStream(null);
+ $response = Zend_Http_Response_Stream::fromStream($response, $stream);
+ $response->setStreamName($this->_stream_name);
+ if(!is_string($this->config['output_stream'])) {
+ // we used temp name, will need to clean up
+ $response->setCleanup(true);
+ }
+ } else {
+ $response = Zend_Http_Response::fromString($response);
+ }
+
if ($this->config['storeresponse']) {
$this->last_response = $response;
}
@@ -1039,6 +1164,9 @@ class Zend_Http_Client
return '';
}
+ if (isset($this->raw_post_data) && is_resource($this->raw_post_data)) {
+ return $this->raw_post_data;
+ }
// If mbstring overloads substr and strlen functions, we have to
// override it's internal encoding
if (function_exists('mb_internal_encoding') &&
@@ -1100,7 +1228,7 @@ class Zend_Http_Client
}
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception("Cannot handle content type '{$this->enctype}' automatically." .
" Please use Zend_Http_Client::setRawData to send this kind of content.");
break;
@@ -1261,7 +1389,7 @@ class Zend_Http_Client
// In basic authentication, the user name cannot contain ":"
if (strpos($user, ':') !== false) {
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception("The user name cannot contain ':' in 'Basic' HTTP authentication");
}
@@ -1276,7 +1404,7 @@ class Zend_Http_Client
default:
/** @see Zend_Http_Client_Exception */
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception("Not a supported HTTP authentication type: '$type'");
}
diff --git a/libs/Zend/Http/Client/Adapter/Curl.php b/libs/Zend/Http/Client/Adapter/Curl.php
index 3335745c1f..4747bd898c 100644
--- a/libs/Zend/Http/Client/Adapter/Curl.php
+++ b/libs/Zend/Http/Client/Adapter/Curl.php
@@ -16,16 +16,24 @@
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter
- * @version $Id: Curl.php 17118 2009-07-26 09:41:41Z shahar $
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Curl.php 22221 2010-05-21 07:00:58Z dragonbe $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-/** Zend_Uri_Http */
-require_once 'Zend/Uri/Http.php';
+/**
+ * @see Zend_Uri_Http
+ */
+// require_once 'Zend/Uri/Http.php';
-/** Zend_Http_Client_Adapter_Interface */
-require_once 'Zend/Http/Client/Adapter/Interface.php';
+/**
+ * @see Zend_Http_Client_Adapter_Interface
+ */
+// require_once 'Zend/Http/Client/Adapter/Interface.php';
+/**
+ * @see Zend_Http_Client_Adapter_Stream
+ */
+// require_once 'Zend/Http/Client/Adapter/Stream.php';
/**
* An adapter class for Zend_Http_Client based on the curl extension.
@@ -34,10 +42,10 @@ require_once 'Zend/Http/Client/Adapter/Interface.php';
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interface
+class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interface, Zend_Http_Client_Adapter_Stream
{
/**
* Parameters array
@@ -65,23 +73,7 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
*
* @var array
*/
- protected $_invalidOverwritableCurlOptions = array(
- CURLOPT_HTTPGET,
- CURLOPT_POST,
- CURLOPT_PUT,
- CURLOPT_CUSTOMREQUEST,
- CURLOPT_HEADER,
- CURLOPT_RETURNTRANSFER,
- CURLOPT_HTTPHEADER,
- CURLOPT_POSTFIELDS,
- CURLOPT_INFILE,
- CURLOPT_INFILESIZE,
- CURLOPT_PORT,
- CURLOPT_MAXREDIRS,
- CURLOPT_TIMEOUT,
- CURL_HTTP_VERSION_1_1,
- CURL_HTTP_VERSION_1_0,
- );
+ protected $_invalidOverwritableCurlOptions;
/**
* Response gotten from server
@@ -91,6 +83,13 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
protected $_response = null;
/**
+ * Stream for storing output
+ *
+ * @var resource
+ */
+ protected $out_stream;
+
+ /**
* Adapter constructor
*
* Config is set using setConfig()
@@ -101,9 +100,26 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
public function __construct()
{
if (!extension_loaded('curl')) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception('cURL extension has to be loaded to use this Zend_Http_Client adapter.');
}
+ $this->_invalidOverwritableCurlOptions = array(
+ CURLOPT_HTTPGET,
+ CURLOPT_POST,
+ CURLOPT_PUT,
+ CURLOPT_CUSTOMREQUEST,
+ CURLOPT_HEADER,
+ CURLOPT_RETURNTRANSFER,
+ CURLOPT_HTTPHEADER,
+ CURLOPT_POSTFIELDS,
+ CURLOPT_INFILE,
+ CURLOPT_INFILESIZE,
+ CURLOPT_PORT,
+ CURLOPT_MAXREDIRS,
+ CURLOPT_CONNECTTIMEOUT,
+ CURL_HTTP_VERSION_1_1,
+ CURL_HTTP_VERSION_1_0,
+ );
}
/**
@@ -119,7 +135,7 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
$config = $config->toArray();
} elseif (! is_array($config)) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception(
'Array or Zend_Config object expected, got ' . gettype($config)
);
@@ -149,6 +165,16 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
}
/**
+ * Retrieve the array of all configuration options
+ *
+ * @return array
+ */
+ public function getConfig()
+ {
+ return $this->_config;
+ }
+
+ /**
* Direct setter for cURL adapter related options.
*
* @param string|int $option
@@ -196,7 +222,7 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
}
// Set timeout
- curl_setopt($this->_curl, CURLOPT_TIMEOUT, $this->_config['timeout']);
+ curl_setopt($this->_curl, CURLOPT_CONNECTTIMEOUT, $this->_config['timeout']);
// Set Max redirects
curl_setopt($this->_curl, CURLOPT_MAXREDIRS, $this->_config['maxredirects']);
@@ -204,7 +230,7 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
if (!$this->_curl) {
$this->close();
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception('Unable to Connect to ' . $host . ':' . $port);
}
@@ -233,16 +259,16 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
* @return string $request
* @throws Zend_Http_Client_Adapter_Exception If connection fails, connected to wrong host, no PUT file defined, unsupported method, or unsupported cURL option
*/
- public function write($method, $uri, $http_ver = '1.1', $headers = array(), $body = '')
+ public function write($method, $uri, $httpVersion = 1.1, $headers = array(), $body = '')
{
// Make sure we're properly connected
if (!$this->_curl) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are not connected");
}
if ($this->_connected_to[0] != $uri->getHost() || $this->_connected_to[1] != $uri->getPort()) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong host");
}
@@ -263,20 +289,30 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
case Zend_Http_Client::PUT:
// There are two different types of PUT request, either a Raw Data string has been set
// or CURLOPT_INFILE and CURLOPT_INFILESIZE are used.
+ if(is_resource($body)) {
+ $this->_config['curloptions'][CURLOPT_INFILE] = $body;
+ }
if (isset($this->_config['curloptions'][CURLOPT_INFILE])) {
- if (!isset($this->_config['curloptions'][CURLOPT_INFILESIZE])) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
- throw new Zend_Http_Client_Adapter_Exception("Cannot set a file-handle for cURL option CURLOPT_INFILE without also setting its size in CURLOPT_INFILESIZE.");
- }
-
// Now we will probably already have Content-Length set, so that we have to delete it
// from $headers at this point:
foreach ($headers AS $k => $header) {
- if (stristr($header, "Content-Length:") !== false) {
+ if (preg_match('/Content-Length:\s*(\d+)/i', $header, $m)) {
+ if(is_resource($body)) {
+ $this->_config['curloptions'][CURLOPT_INFILESIZE] = (int)$m[1];
+ }
unset($headers[$k]);
}
}
+ if (!isset($this->_config['curloptions'][CURLOPT_INFILESIZE])) {
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
+ throw new Zend_Http_Client_Adapter_Exception("Cannot set a file-handle for cURL option CURLOPT_INFILE without also setting its size in CURLOPT_INFILESIZE.");
+ }
+
+ if(is_resource($body)) {
+ $body = '';
+ }
+
$curlMethod = CURLOPT_PUT;
} else {
$curlMethod = CURLOPT_CUSTOMREQUEST;
@@ -298,25 +334,43 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
$curlMethod = CURLOPT_CUSTOMREQUEST;
$curlValue = "TRACE";
break;
+
+ case Zend_Http_Client::HEAD:
+ $curlMethod = CURLOPT_CUSTOMREQUEST;
+ $curlValue = "HEAD";
+ break;
default:
// For now, through an exception for unsupported request methods
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception("Method currently not supported");
}
+ if(is_resource($body) && $curlMethod != CURLOPT_PUT) {
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
+ throw new Zend_Http_Client_Adapter_Exception("Streaming requests are allowed only with PUT");
+ }
+
// get http version to use
- $curlHttp = ($http_ver = 1.1) ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0;
+ $curlHttp = ($httpVersion == 1.1) ? CURL_HTTP_VERSION_1_1 : CURL_HTTP_VERSION_1_0;
// mark as HTTP request and set HTTP method
curl_setopt($this->_curl, $curlHttp, true);
curl_setopt($this->_curl, $curlMethod, $curlValue);
- // ensure headers are also returned
- curl_setopt($this->_curl, CURLOPT_HEADER, true);
-
- // ensure actual response is returned
- curl_setopt($this->_curl, CURLOPT_RETURNTRANSFER, true);
+ if($this->out_stream) {
+ // headers will be read into the response
+ curl_setopt($this->_curl, CURLOPT_HEADER, false);
+ curl_setopt($this->_curl, CURLOPT_HEADERFUNCTION, array($this, "readHeader"));
+ // and data will be written into the file
+ curl_setopt($this->_curl, CURLOPT_FILE, $this->out_stream);
+ } else {
+ // ensure headers are also returned
+ curl_setopt($this->_curl, CURLOPT_HEADER, true);
+
+ // ensure actual response is returned
+ curl_setopt($this->_curl, CURLOPT_RETURNTRANSFER, true);
+ }
// set additional headers
$headers['Accept'] = '';
@@ -346,7 +400,7 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
foreach ((array)$this->_config['curloptions'] as $k => $v) {
if (!in_array($k, $this->_invalidOverwritableCurlOptions)) {
if (curl_setopt($this->_curl, $k, $v) == false) {
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception(sprintf("Unknown or erroreous cURL option '%s' set", $k));
}
}
@@ -354,13 +408,18 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
}
// send the request
- $this->_response = curl_exec($this->_curl);
+ $response = curl_exec($this->_curl);
+
+ // if we used streaming, headers are already there
+ if(!is_resource($this->out_stream)) {
+ $this->_response = $response;
+ }
$request = curl_getinfo($this->_curl, CURLINFO_HEADER_OUT);
$request .= $body;
if (empty($this->_response)) {
- require_once 'Zend/Http/Client/Exception.php';
+ // require_once 'Zend/Http/Client/Exception.php';
throw new Zend_Http_Client_Exception("Error in cURL request: " . curl_error($this->_curl));
}
@@ -420,4 +479,29 @@ class Zend_Http_Client_Adapter_Curl implements Zend_Http_Client_Adapter_Interfac
{
return $this->_curl;
}
+
+ /**
+ * Set output stream for the response
+ *
+ * @param resource $stream
+ * @return Zend_Http_Client_Adapter_Socket
+ */
+ public function setOutputStream($stream)
+ {
+ $this->out_stream = $stream;
+ return $this;
+ }
+
+ /**
+ * Header reader function for CURL
+ *
+ * @param resource $curl
+ * @param string $header
+ * @return int
+ */
+ public function readHeader($curl, $header)
+ {
+ $this->_response .= $header;
+ return strlen($header);
+ }
}
diff --git a/libs/Zend/Http/Client/Adapter/Exception.php b/libs/Zend/Http/Client/Adapter/Exception.php
index b157e0facf..082c8af302 100644
--- a/libs/Zend/Http/Client/Adapter/Exception.php
+++ b/libs/Zend/Http/Client/Adapter/Exception.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter_Exception
- * @version $Id: Exception.php 17118 2009-07-26 09:41:41Z shahar $
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* @see Zend_Http_Client_Exception
*/
-require_once 'Zend/Http/Client/Exception.php';
+// require_once 'Zend/Http/Client/Exception.php';
/**
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Http_Client_Adapter_Exception extends Zend_Http_Client_Exception
diff --git a/libs/Zend/Http/Client/Adapter/Interface.php b/libs/Zend/Http/Client/Adapter/Interface.php
index 46b84accbf..be9d187947 100644
--- a/libs/Zend/Http/Client/Adapter/Interface.php
+++ b/libs/Zend/Http/Client/Adapter/Interface.php
@@ -16,8 +16,8 @@
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter
- * @version $Id: Interface.php 16214 2009-06-21 19:34:03Z thomas $
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
@@ -30,7 +30,7 @@
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Http_Client_Adapter_Interface
diff --git a/libs/Zend/Http/Client/Adapter/Proxy.php b/libs/Zend/Http/Client/Adapter/Proxy.php
index 932b1b66b6..cda6d62dbb 100644
--- a/libs/Zend/Http/Client/Adapter/Proxy.php
+++ b/libs/Zend/Http/Client/Adapter/Proxy.php
@@ -16,23 +16,23 @@
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter
- * @version $Id: Proxy.php 17118 2009-07-26 09:41:41Z shahar $
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Proxy.php 20947 2010-02-06 17:09:07Z padraic $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* @see Zend_Uri_Http
*/
-require_once 'Zend/Uri/Http.php';
+// require_once 'Zend/Uri/Http.php';
/**
* @see Zend_Http_Client
*/
-require_once 'Zend/Http/Client.php';
+// require_once 'Zend/Http/Client.php';
/**
* @see Zend_Http_Client_Adapter_Socket
*/
-require_once 'Zend/Http/Client/Adapter/Socket.php';
+// require_once 'Zend/Http/Client/Adapter/Socket.php';
/**
* HTTP Proxy-supporting Zend_Http_Client adapter class, based on the default
@@ -46,7 +46,7 @@ require_once 'Zend/Http/Client/Adapter/Socket.php';
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Http_Client_Adapter_Proxy extends Zend_Http_Client_Adapter_Socket
@@ -91,6 +91,11 @@ class Zend_Http_Client_Adapter_Proxy extends Zend_Http_Client_Adapter_Socket
if (! $this->config['proxy_host']) {
return parent::connect($host, $port, $secure);
}
+
+ /* Url might require stream context even if proxy connection doesn't */
+ if ($secure) {
+ $this->config['sslusecontext'] = true;
+ }
// Connect (a non-secure connection) to the proxy server
return parent::connect(
@@ -117,7 +122,7 @@ class Zend_Http_Client_Adapter_Proxy extends Zend_Http_Client_Adapter_Socket
// Make sure we're properly connected
if (! $this->socket) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are not connected");
}
@@ -125,7 +130,7 @@ class Zend_Http_Client_Adapter_Proxy extends Zend_Http_Client_Adapter_Socket
$port = $this->config['proxy_port'];
if ($this->connected_to[0] != "tcp://$host" || $this->connected_to[1] != $port) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception("Trying to write but we are connected to the wrong proxy server");
}
@@ -167,7 +172,7 @@ class Zend_Http_Client_Adapter_Proxy extends Zend_Http_Client_Adapter_Socket
// Send the request
if (! @fwrite($this->socket, $request)) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception("Error writing request to proxy server");
}
@@ -203,7 +208,7 @@ class Zend_Http_Client_Adapter_Proxy extends Zend_Http_Client_Adapter_Socket
// Send the request
if (! @fwrite($this->socket, $request)) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception("Error writing request to proxy server");
}
@@ -220,7 +225,7 @@ class Zend_Http_Client_Adapter_Proxy extends Zend_Http_Client_Adapter_Socket
// Check that the response from the proxy is 200
if (Zend_Http_Response::extractCode($response) != 200) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception("Unable to connect to HTTPS proxy. Server response: " . $response);
}
@@ -240,7 +245,7 @@ class Zend_Http_Client_Adapter_Proxy extends Zend_Http_Client_Adapter_Socket
}
if (! $success) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception("Unable to connect to" .
" HTTPS server through proxy: could not negotiate secure connection.");
}
diff --git a/libs/Zend/Http/Client/Adapter/Socket.php b/libs/Zend/Http/Client/Adapter/Socket.php
index 13427c749f..4f3d41722d 100644
--- a/libs/Zend/Http/Client/Adapter/Socket.php
+++ b/libs/Zend/Http/Client/Adapter/Socket.php
@@ -16,19 +16,23 @@
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter
- * @version $Id: Socket.php 17124 2009-07-26 09:46:42Z shahar $
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Socket.php 21778 2010-04-06 11:19:35Z shahar $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* @see Zend_Uri_Http
*/
-require_once 'Zend/Uri/Http.php';
+// require_once 'Zend/Uri/Http.php';
/**
* @see Zend_Http_Client_Adapter_Interface
*/
-require_once 'Zend/Http/Client/Adapter/Interface.php';
+// require_once 'Zend/Http/Client/Adapter/Interface.php';
+/**
+ * @see Zend_Http_Client_Adapter_Stream
+ */
+// require_once 'Zend/Http/Client/Adapter/Stream.php';
/**
* A sockets based (stream_socket_client) adapter class for Zend_Http_Client. Can be used
@@ -37,10 +41,10 @@ require_once 'Zend/Http/Client/Adapter/Interface.php';
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interface
+class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interface, Zend_Http_Client_Adapter_Stream
{
/**
* The socket for server connection
@@ -57,6 +61,13 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
protected $connected_to = array(null, null);
/**
+ * Stream for storing output
+ *
+ * @var resource
+ */
+ protected $out_stream = null;
+
+ /**
* Parameters array
*
* @var array
@@ -65,7 +76,8 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
'persistent' => false,
'ssltransport' => 'ssl',
'sslcert' => null,
- 'sslpassphrase' => null
+ 'sslpassphrase' => null,
+ 'sslusecontext' => false
);
/**
@@ -101,7 +113,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
$config = $config->toArray();
} elseif (! is_array($config)) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception(
'Array or Zend_Config object expected, got ' . gettype($config)
);
@@ -112,7 +124,17 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
}
}
- /**
+ /**
+ * Retrieve the array of all configuration options
+ *
+ * @return array
+ */
+ public function getConfig()
+ {
+ return $this->config;
+ }
+
+ /**
* Set the stream context for the TCP connection to the server
*
* Can accept either a pre-existing stream context resource, or an array
@@ -135,7 +157,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
} else {
// Invalid parameter
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception(
"Expecting either a stream context resource or array, got " . gettype($context)
);
@@ -180,18 +202,18 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
// Now, if we are not connected, connect
if (! is_resource($this->socket) || ! $this->config['keepalive']) {
$context = $this->getStreamContext();
- if ($secure) {
+ if ($secure || $this->config['sslusecontext']) {
if ($this->config['sslcert'] !== null) {
if (! stream_context_set_option($context, 'ssl', 'local_cert',
$this->config['sslcert'])) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception('Unable to set sslcert option');
}
}
if ($this->config['sslpassphrase'] !== null) {
if (! stream_context_set_option($context, 'ssl', 'passphrase',
$this->config['sslpassphrase'])) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception('Unable to set sslpassphrase option');
}
}
@@ -209,14 +231,14 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
if (! $this->socket) {
$this->close();
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception(
'Unable to Connect to ' . $host . ':' . $port . '. Error #' . $errno . ': ' . $errstr);
}
// Set the stream timeout
if (! stream_set_timeout($this->socket, (int) $this->config['timeout'])) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception('Unable to set the connection timeout');
}
@@ -239,14 +261,14 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
{
// Make sure we're properly connected
if (! $this->socket) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception('Trying to write but we are not connected');
}
$host = $uri->getHost();
$host = (strtolower($uri->getScheme()) == 'https' ? $this->config['ssltransport'] : 'tcp') . '://' . $host;
if ($this->connected_to[0] != $host || $this->connected_to[1] != $uri->getPort()) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception('Trying to write but we are connected to the wrong host');
}
@@ -262,14 +284,25 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
$request .= "$v\r\n";
}
- // Add the request body
- $request .= "\r\n" . $body;
-
+ if(is_resource($body)) {
+ $request .= "\r\n";
+ } else {
+ // Add the request body
+ $request .= "\r\n" . $body;
+ }
+
// Send the request
if (! @fwrite($this->socket, $request)) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception('Error writing request to server');
}
+
+ if(is_resource($body)) {
+ if(stream_copy_to_stream($body, $this->socket) == 0) {
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
+ throw new Zend_Http_Client_Adapter_Exception('Error writing request to server');
+ }
+ }
return $request;
}
@@ -284,6 +317,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
// First, read headers only
$response = '';
$gotStatus = false;
+ $stream = !empty($this->config['stream']);
while (($line = @fgets($this->socket)) !== false) {
$gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
@@ -292,7 +326,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
if (rtrim($line) === '') break;
}
}
-
+
$this->_checkSocketReadTimeout();
$statusCode = Zend_Http_Response::extractCode($response);
@@ -319,7 +353,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
// If we got a 'transfer-encoding: chunked' header
if (isset($headers['transfer-encoding'])) {
-
+
if (strtolower($headers['transfer-encoding']) == 'chunked') {
do {
@@ -332,7 +366,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
$chunksize = trim($line);
if (! ctype_xdigit($chunksize)) {
$this->close();
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception('Invalid chunk size "' .
$chunksize . '" unable to read chunked body');
}
@@ -347,45 +381,71 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
$current_pos = ftell($this->socket);
if ($current_pos >= $read_to) break;
- $line = @fread($this->socket, $read_to - $current_pos);
- if ($line === false || strlen($line) === 0) {
- $this->_checkSocketReadTimeout();
- break;
+ if($this->out_stream) {
+ if(stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) {
+ $this->_checkSocketReadTimeout();
+ break;
+ }
} else {
- $chunk .= $line;
+ $line = @fread($this->socket, $read_to - $current_pos);
+ if ($line === false || strlen($line) === 0) {
+ $this->_checkSocketReadTimeout();
+ break;
+ }
+ $chunk .= $line;
}
-
} while (! feof($this->socket));
$chunk .= @fgets($this->socket);
$this->_checkSocketReadTimeout();
- $response .= $chunk;
+ if(!$this->out_stream) {
+ $response .= $chunk;
+ }
} while ($chunksize > 0);
-
} else {
$this->close();
throw new Zend_Http_Client_Adapter_Exception('Cannot handle "' .
$headers['transfer-encoding'] . '" transfer encoding');
}
-
+
+ // We automatically decode chunked-messages when writing to a stream
+ // this means we have to disallow the Zend_Http_Response to do it again
+ if ($this->out_stream) {
+ $response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $response);
+ }
// Else, if we got the content-length header, read this number of bytes
} elseif (isset($headers['content-length'])) {
+ // If we got more than one Content-Length header (see ZF-9404) use
+ // the last value sent
+ if (is_array($headers['content-length'])) {
+ $contentLength = $headers['content-length'][count($headers['content-length']) - 1];
+ } else {
+ $contentLength = $headers['content-length'];
+ }
+
$current_pos = ftell($this->socket);
$chunk = '';
- for ($read_to = $current_pos + $headers['content-length'];
+ for ($read_to = $current_pos + $contentLength;
$read_to > $current_pos;
$current_pos = ftell($this->socket)) {
- $chunk = @fread($this->socket, $read_to - $current_pos);
- if ($chunk === false || strlen($chunk) === 0) {
- $this->_checkSocketReadTimeout();
- break;
- }
+ if($this->out_stream) {
+ if(@stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0) {
+ $this->_checkSocketReadTimeout();
+ break;
+ }
+ } else {
+ $chunk = @fread($this->socket, $read_to - $current_pos);
+ if ($chunk === false || strlen($chunk) === 0) {
+ $this->_checkSocketReadTimeout();
+ break;
+ }
- $response .= $chunk;
+ $response .= $chunk;
+ }
// Break if the connection ended prematurely
if (feof($this->socket)) break;
@@ -395,12 +455,19 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
} else {
do {
- $buff = @fread($this->socket, 8192);
- if ($buff === false || strlen($buff) === 0) {
- $this->_checkSocketReadTimeout();
- break;
- } else {
- $response .= $buff;
+ if($this->out_stream) {
+ if(@stream_copy_to_stream($this->socket, $this->out_stream) == 0) {
+ $this->_checkSocketReadTimeout();
+ break;
+ }
+ } else {
+ $buff = @fread($this->socket, 8192);
+ if ($buff === false || strlen($buff) === 0) {
+ $this->_checkSocketReadTimeout();
+ break;
+ } else {
+ $response .= $buff;
+ }
}
} while (feof($this->socket) === false);
@@ -440,7 +507,7 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
$timedout = $info['timed_out'];
if ($timedout) {
$this->close();
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception(
"Read timed out after {$this->config['timeout']} seconds",
Zend_Http_Client_Adapter_Exception::READ_TIMEOUT
@@ -448,7 +515,19 @@ class Zend_Http_Client_Adapter_Socket implements Zend_Http_Client_Adapter_Interf
}
}
}
-
+
+ /**
+ * Set output stream for the response
+ *
+ * @param resource $stream
+ * @return Zend_Http_Client_Adapter_Socket
+ */
+ public function setOutputStream($stream)
+ {
+ $this->out_stream = $stream;
+ return $this;
+ }
+
/**
* Destructor: make sure the socket is disconnected
*
diff --git a/libs/Zend/Http/Client/Adapter/Stream.php b/libs/Zend/Http/Client/Adapter/Stream.php
new file mode 100644
index 0000000000..58dd921f20
--- /dev/null
+++ b/libs/Zend/Http/Client/Adapter/Stream.php
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Http
+ * @subpackage Client_Adapter
+ * @version $Id: Interface.php 16214 2009-06-21 19:34:03Z thomas $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * An interface description for Zend_Http_Client_Adapter_Stream classes.
+ *
+ * This interface decribes Zend_Http_Client_Adapter which supports streaming.
+ *
+ * @category Zend
+ * @package Zend_Http
+ * @subpackage Client_Adapter
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+interface Zend_Http_Client_Adapter_Stream
+{
+ /**
+ * Set output stream
+ *
+ * This function sets output stream where the result will be stored.
+ *
+ * @param resource $stream Stream to write the output to
+ *
+ */
+ function setOutputStream($stream);
+}
diff --git a/libs/Zend/Http/Client/Adapter/Test.php b/libs/Zend/Http/Client/Adapter/Test.php
index e36f43ee84..f974400868 100644
--- a/libs/Zend/Http/Client/Adapter/Test.php
+++ b/libs/Zend/Http/Client/Adapter/Test.php
@@ -15,23 +15,23 @@
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter
- * @version $Id: Test.php 17869 2009-08-28 10:37:13Z cogo $
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Test.php 20096 2010-01-06 02:05:09Z bkarwin $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* @see Zend_Uri_Http
*/
-require_once 'Zend/Uri/Http.php';
+// require_once 'Zend/Uri/Http.php';
/**
* @see Zend_Http_Response
*/
-require_once 'Zend/Http/Response.php';
+// require_once 'Zend/Http/Response.php';
/**
* @see Zend_Http_Client_Adapter_Interface
*/
-require_once 'Zend/Http/Client/Adapter/Interface.php';
+// require_once 'Zend/Http/Client/Adapter/Interface.php';
/**
* A testing-purposes adapter.
@@ -44,7 +44,7 @@ require_once 'Zend/Http/Client/Adapter/Interface.php';
* @category Zend
* @package Zend_Http
* @subpackage Client_Adapter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Http_Client_Adapter_Test implements Zend_Http_Client_Adapter_Interface
@@ -72,6 +72,13 @@ class Zend_Http_Client_Adapter_Test implements Zend_Http_Client_Adapter_Interfac
protected $responseIndex = 0;
/**
+ * Wether or not the next request will fail with an exception
+ *
+ * @var boolean
+ */
+ protected $_nextRequestWillFail = false;
+
+ /**
* Adapter constructor, currently empty. Config is set using setConfig()
*
*/
@@ -79,6 +86,19 @@ class Zend_Http_Client_Adapter_Test implements Zend_Http_Client_Adapter_Interfac
{ }
/**
+ * Set the nextRequestWillFail flag
+ *
+ * @param boolean $flag
+ * @return Zend_Http_Client_Adapter_Test
+ */
+ public function setNextRequestWillFail($flag)
+ {
+ $this->_nextRequestWillFail = (bool) $flag;
+
+ return $this;
+ }
+
+ /**
* Set the configuration array for the adapter
*
* @param Zend_Config | array $config
@@ -89,7 +109,7 @@ class Zend_Http_Client_Adapter_Test implements Zend_Http_Client_Adapter_Interfac
$config = $config->toArray();
} elseif (! is_array($config)) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception(
'Array or Zend_Config object expected, got ' . gettype($config)
);
@@ -108,9 +128,16 @@ class Zend_Http_Client_Adapter_Test implements Zend_Http_Client_Adapter_Interfac
* @param int $port
* @param boolean $secure
* @param int $timeout
+ * @throws Zend_Http_Client_Adapter_Exception
*/
public function connect($host, $port = 80, $secure = false)
- { }
+ {
+ if ($this->_nextRequestWillFail) {
+ $this->_nextRequestWillFail = false;
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
+ throw new Zend_Http_Client_Adapter_Exception('Request failed');
+ }
+ }
/**
* Send request to the remote server
@@ -202,7 +229,7 @@ class Zend_Http_Client_Adapter_Test implements Zend_Http_Client_Adapter_Interfac
public function setResponseIndex($index)
{
if ($index < 0 || $index >= count($this->responses)) {
- require_once 'Zend/Http/Client/Adapter/Exception.php';
+ // require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception(
'Index out of range of response buffer size');
}
diff --git a/libs/Zend/Http/Client/Exception.php b/libs/Zend/Http/Client/Exception.php
index 6d5efdf27e..dc35e3a0e2 100644
--- a/libs/Zend/Http/Client/Exception.php
+++ b/libs/Zend/Http/Client/Exception.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Http
* @subpackage Client_Exception
- * @version $Id: Exception.php 16872 2009-07-20 11:47:08Z mikaelkael $
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* @see Zend_Http_Exception
*/
-require_once 'Zend/Http/Exception.php';
+// require_once 'Zend/Http/Exception.php';
/**
* @category Zend
* @package Zend_Http
* @subpackage Client
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Http_Client_Exception extends Zend_Http_Exception
diff --git a/libs/Zend/Http/Cookie.php b/libs/Zend/Http/Cookie.php
index d8e278898a..49d2ff6ad8 100644
--- a/libs/Zend/Http/Cookie.php
+++ b/libs/Zend/Http/Cookie.php
@@ -16,15 +16,15 @@
* @category Zend
* @package Zend_Http
* @subpackage Cookie
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
- * @version $Id: Cookie.php 17124 2009-07-26 09:46:42Z shahar $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Cookie.php 21020 2010-02-11 17:27:23Z shahar $
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* @see Zend_Uri_Http
*/
-require_once 'Zend/Uri/Http.php';
+// require_once 'Zend/Uri/Http.php';
/**
@@ -41,7 +41,7 @@ require_once 'Zend/Uri/Http.php';
*
* @category Zend
* @package Zend_Http
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Http_Cookie
@@ -89,6 +89,13 @@ class Zend_Http_Cookie
protected $secure;
/**
+ * Whether the cookie value has been encoded/decoded
+ *
+ * @var boolean
+ */
+ protected $encodeValue;
+
+ /**
* Cookie object constructor
*
* @todo Add validation of each one of the parameters (legal domain, etc.)
@@ -103,17 +110,17 @@ class Zend_Http_Cookie
public function __construct($name, $value, $domain, $expires = null, $path = null, $secure = false)
{
if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception("Cookie name cannot contain these characters: =,; \\t\\r\\n\\013\\014 ({$name})");
}
if (! $this->name = (string) $name) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception('Cookies must have a name');
}
if (! $this->domain = (string) $domain) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception('Cookies must have a domain');
}
@@ -227,7 +234,7 @@ class Zend_Http_Cookie
// Make sure we have a valid Zend_Uri_Http object
if (! ($uri->valid() && ($uri->getScheme() == 'http' || $uri->getScheme() =='https'))) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception('Passed URI is not a valid HTTP or HTTPS URI');
}
@@ -258,7 +265,10 @@ class Zend_Http_Cookie
*/
public function __toString()
{
- return $this->name . '=' . urlencode($this->value) . ';';
+ if ($this->encodeValue) {
+ return $this->name . '=' . urlencode($this->value) . ';';
+ }
+ return $this->name . '=' . $this->value . ';';
}
/**
@@ -266,14 +276,16 @@ class Zend_Http_Cookie
* (for example the value of the Set-Cookie HTTP header)
*
* @param string $cookieStr
- * @param Zend_Uri_Http|string $ref_uri Reference URI for default values (domain, path)
+ * @param Zend_Uri_Http|string $refUri Reference URI for default values (domain, path)
+ * @param boolean $encodeValue Weither or not the cookie's value should be
+ * passed through urlencode/urldecode
* @return Zend_Http_Cookie A new Zend_Http_Cookie object or false on failure.
*/
- public static function fromString($cookieStr, $ref_uri = null)
+ public static function fromString($cookieStr, $refUri = null, $encodeValue = true)
{
// Set default values
- if (is_string($ref_uri)) {
- $ref_uri = Zend_Uri_Http::factory($ref_uri);
+ if (is_string($refUri)) {
+ $refUri = Zend_Uri_Http::factory($refUri);
}
$name = '';
@@ -290,12 +302,14 @@ class Zend_Http_Cookie
// Get the name and value of the cookie
list($name, $value) = explode('=', trim(array_shift($parts)), 2);
$name = trim($name);
- $value = urldecode(trim($value));
+ if ($encodeValue) {
+ $value = urldecode(trim($value));
+ }
// Set default domain and path
- if ($ref_uri instanceof Zend_Uri_Http) {
- $domain = $ref_uri->getHost();
- $path = $ref_uri->getPath();
+ if ($refUri instanceof Zend_Uri_Http) {
+ $domain = $refUri->getHost();
+ $path = $refUri->getPath();
$path = substr($path, 0, strrpos($path, '/'));
}
@@ -320,7 +334,7 @@ class Zend_Http_Cookie
*
* @see Zend_Date
*/
- require_once 'Zend/Date.php';
+ // require_once 'Zend/Date.php';
$expireDate = new Zend_Date($v);
$expires = $expireDate->getTimestamp();
@@ -342,7 +356,9 @@ class Zend_Http_Cookie
}
if ($name !== '') {
- return new self($name, $value, $domain, $expires, $path, $secure);
+ $ret = new self($name, $value, $domain, $expires, $path, $secure);
+ $ret->encodeValue = ($encodeValue) ? true : false;
+ return $ret;
} else {
return false;
}
@@ -361,12 +377,12 @@ class Zend_Http_Cookie
public static function matchCookieDomain($cookieDomain, $host)
{
if (! $cookieDomain) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception("\$cookieDomain is expected to be a cookie domain");
}
if (! $host) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception("\$host is expected to be a host name");
}
@@ -394,12 +410,12 @@ class Zend_Http_Cookie
public static function matchCookiePath($cookiePath, $path)
{
if (! $cookiePath) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception("\$cookiePath is expected to be a cookie path");
}
if (! $path) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception("\$path is expected to be a host name");
}
diff --git a/libs/Zend/Http/CookieJar.php b/libs/Zend/Http/CookieJar.php
index 59afdfbd52..3d00a8e0af 100644
--- a/libs/Zend/Http/CookieJar.php
+++ b/libs/Zend/Http/CookieJar.php
@@ -15,23 +15,23 @@
* @category Zend
* @package Zend_Http
* @subpackage CookieJar
- * @version $Id: CookieJar.php 17124 2009-07-26 09:46:42Z shahar $
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: CookieJar.php 20096 2010-01-06 02:05:09Z bkarwin $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* @see Zend_Uri
*/
-require_once "Zend/Uri.php";
+// require_once "Zend/Uri.php";
/**
* @see Zend_Http_Cookie
*/
-require_once "Zend/Http/Cookie.php";
+// require_once "Zend/Http/Cookie.php";
/**
* @see Zend_Http_Response
*/
-require_once "Zend/Http/Response.php";
+// require_once "Zend/Http/Response.php";
/**
* A Zend_Http_CookieJar object is designed to contain and maintain HTTP cookies, and should
@@ -54,7 +54,7 @@ require_once "Zend/Http/Response.php";
* @category Zend
* @package Zend_Http
* @subpackage CookieJar
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Http_CookieJar implements Countable, IteratorAggregate
@@ -131,7 +131,7 @@ class Zend_Http_CookieJar implements Countable, IteratorAggregate
$this->cookies[$domain][$path][$cookie->getName()] = $cookie;
$this->_rawCookies[] = $cookie;
} else {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception('Supplient argument is not a valid cookie string or object');
}
}
@@ -146,7 +146,7 @@ class Zend_Http_CookieJar implements Countable, IteratorAggregate
public function addCookiesFromResponse($response, $ref_uri)
{
if (! $response instanceof Zend_Http_Response) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception('$response is expected to be a Response object, ' .
gettype($response) . ' was passed');
}
@@ -190,7 +190,7 @@ class Zend_Http_CookieJar implements Countable, IteratorAggregate
{
if (is_string($uri)) $uri = Zend_Uri::factory($uri);
if (! $uri instanceof Zend_Uri_Http) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception("Invalid URI string or object passed");
}
@@ -226,7 +226,7 @@ class Zend_Http_CookieJar implements Countable, IteratorAggregate
}
if (! $uri instanceof Zend_Uri_Http) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception('Invalid URI specified');
}
@@ -249,7 +249,7 @@ class Zend_Http_CookieJar implements Countable, IteratorAggregate
break;
default:
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception("Invalid value passed for \$ret_as: {$ret_as}");
break;
}
diff --git a/libs/Zend/Http/Exception.php b/libs/Zend/Http/Exception.php
index 93a3869153..230c9c0a77 100644
--- a/libs/Zend/Http/Exception.php
+++ b/libs/Zend/Http/Exception.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Http
* @subpackage Exception
- * @version $Id: Exception.php 16872 2009-07-20 11:47:08Z mikaelkael $
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* @see Zend_Exception
*/
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Http
* @subpackage Client
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Http_Exception extends Zend_Exception
diff --git a/libs/Zend/Http/Response.php b/libs/Zend/Http/Response.php
index 9db70f4e25..decb5f357e 100644
--- a/libs/Zend/Http/Response.php
+++ b/libs/Zend/Http/Response.php
@@ -16,8 +16,8 @@
* @category Zend
* @package Zend_Http
* @subpackage Response
- * @version $Id: Response.php 17124 2009-07-26 09:46:42Z shahar $
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Response.php 20096 2010-01-06 02:05:09Z bkarwin $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
@@ -28,7 +28,7 @@
*
* @package Zend_Http
* @subpackage Response
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Http_Response
@@ -152,7 +152,7 @@ class Zend_Http_Response
{
// Make sure the response code is valid and set it
if (self::responseCodeAsText($code) === null) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception("{$code} is not a valid HTTP response code");
}
@@ -160,7 +160,7 @@ class Zend_Http_Response
// Make sure we got valid headers and set them
if (! is_array($headers)) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception('No valid headers were passed');
}
@@ -176,7 +176,7 @@ class Zend_Http_Response
// Set the HTTP version
if (! preg_match('|^\d\.\d$|', $version)) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception("Invalid HTTP response version: $version");
}
@@ -572,7 +572,7 @@ class Zend_Http_Response
while (trim($body)) {
if (! preg_match("/^([\da-fA-F]+)[^\r\n]*\r\n/sm", $body, $m)) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception("Error parsing body - doesn't seem to be a chunked message");
}
@@ -600,7 +600,7 @@ class Zend_Http_Response
public static function decodeGzip($body)
{
if (! function_exists('gzinflate')) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception(
'zlib extension is required in order to decode "gzip" encoding'
);
@@ -620,7 +620,7 @@ class Zend_Http_Response
public static function decodeDeflate($body)
{
if (! function_exists('gzuncompress')) {
- require_once 'Zend/Http/Exception.php';
+ // require_once 'Zend/Http/Exception.php';
throw new Zend_Http_Exception(
'zlib extension is required in order to decode "deflate" encoding'
);
diff --git a/libs/Zend/Http/Response/Stream.php b/libs/Zend/Http/Response/Stream.php
new file mode 100644
index 0000000000..667ca321ab
--- /dev/null
+++ b/libs/Zend/Http/Response/Stream.php
@@ -0,0 +1,235 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Http
+ * @subpackage Response
+ * @version $Id: Response.php 17131 2009-07-26 10:03:39Z shahar $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+
+/**
+ * Zend_Http_Response represents an HTTP 1.0 / 1.1 response message. It
+ * includes easy access to all the response's different elemts, as well as some
+ * convenience methods for parsing and validating HTTP responses.
+ *
+ * @package Zend_Http
+ * @subpackage Response
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Http_Response_Stream extends Zend_Http_Response
+{
+ /**
+ * Response as stream
+ *
+ * @var resource
+ */
+ protected $stream;
+
+ /**
+ * The name of the file containing the stream
+ *
+ * Will be empty if stream is not file-based.
+ *
+ * @var string
+ */
+ protected $stream_name;
+
+ /**
+ * Should we clean up the stream file when this response is closed?
+ *
+ * @var boolean
+ */
+ protected $_cleanup;
+
+ /**
+ * Get the response as stream
+ *
+ * @return resourse
+ */
+ public function getStream()
+ {
+ return $this->stream;
+ }
+
+ /**
+ * Set the response stream
+ *
+ * @param resourse $stream
+ * @return Zend_Http_Response_Stream
+ */
+ public function setStream($stream)
+ {
+ $this->stream = $stream;
+ return $this;
+ }
+
+ /**
+ * Get the cleanup trigger
+ *
+ * @return boolean
+ */
+ public function getCleanup() {
+ return $this->_cleanup;
+ }
+
+ /**
+ * Set the cleanup trigger
+ *
+ * @param $cleanup Set cleanup trigger
+ */
+ public function setCleanup($cleanup = true) {
+ $this->_cleanup = $cleanup;
+ }
+
+ /**
+ * Get file name associated with the stream
+ *
+ * @return string
+ */
+ public function getStreamName() {
+ return $this->stream_name;
+ }
+
+ /**
+ * Set file name associated with the stream
+ *
+ * @param string $stream_name Name to set
+ * @return Zend_Http_Response_Stream
+ */
+ public function setStreamName($stream_name) {
+ $this->stream_name = $stream_name;
+ return $this;
+ }
+
+
+ /**
+ * HTTP response constructor
+ *
+ * In most cases, you would use Zend_Http_Response::fromString to parse an HTTP
+ * response string and create a new Zend_Http_Response object.
+ *
+ * NOTE: The constructor no longer accepts nulls or empty values for the code and
+ * headers and will throw an exception if the passed values do not form a valid HTTP
+ * responses.
+ *
+ * If no message is passed, the message will be guessed according to the response code.
+ *
+ * @param int $code Response code (200, 404, ...)
+ * @param array $headers Headers array
+ * @param string $body Response body
+ * @param string $version HTTP version
+ * @param string $message Response code as text
+ * @throws Zend_Http_Exception
+ */
+ public function __construct($code, $headers, $body = null, $version = '1.1', $message = null)
+ {
+
+ if(is_resource($body)) {
+ $this->setStream($body);
+ $body = '';
+ }
+ parent::__construct($code, $headers, $body, $version, $message);
+ }
+
+ /**
+ * Create a new Zend_Http_Response_Stream object from a string
+ *
+ * @param string $response_str
+ * @param resource $stream
+ * @return Zend_Http_Response_Stream
+ */
+ public static function fromStream($response_str, $stream)
+ {
+ $code = self::extractCode($response_str);
+ $headers = self::extractHeaders($response_str);
+ $version = self::extractVersion($response_str);
+ $message = self::extractMessage($response_str);
+
+ return new self($code, $headers, $stream, $version, $message);
+ }
+
+ /**
+ * Get the response body as string
+ *
+ * This method returns the body of the HTTP response (the content), as it
+ * should be in it's readable version - that is, after decoding it (if it
+ * was decoded), deflating it (if it was gzip compressed), etc.
+ *
+ * If you want to get the raw body (as transfered on wire) use
+ * $this->getRawBody() instead.
+ *
+ * @return string
+ */
+ public function getBody()
+ {
+ if($this->stream != null) {
+ $this->readStream();
+ }
+ return parent::getBody();
+ }
+
+ /**
+ * Get the raw response body (as transfered "on wire") as string
+ *
+ * If the body is encoded (with Transfer-Encoding, not content-encoding -
+ * IE "chunked" body), gzip compressed, etc. it will not be decoded.
+ *
+ * @return string
+ */
+ public function getRawBody()
+ {
+ if($this->stream) {
+ $this->readStream();
+ }
+ return $this->body;
+ }
+
+ /**
+ * Read stream content and return it as string
+ *
+ * Function reads the remainder of the body from the stream and closes the stream.
+ *
+ * @return string
+ */
+ protected function readStream()
+ {
+ if(!is_resource($this->stream)) {
+ return '';
+ }
+
+ if(isset($headers['content-length'])) {
+ $this->body = stream_get_contents($this->stream, $headers['content-length']);
+ } else {
+ $this->body = stream_get_contents($this->stream);
+ }
+ fclose($this->stream);
+ $this->stream = null;
+ }
+
+ public function __destruct()
+ {
+ if(is_resource($this->stream)) {
+ fclose($this->stream);
+ $this->stream = null;
+ }
+ if($this->_cleanup) {
+ @unlink($this->stream_name);
+ }
+ }
+
+}
diff --git a/libs/Zend/Loader.php b/libs/Zend/Loader.php
index bfa962a62d..b5ae731ef0 100644
--- a/libs/Zend/Loader.php
+++ b/libs/Zend/Loader.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Loader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Loader.php 16206 2009-06-21 19:15:37Z thomas $
+ * @version $Id: Loader.php 22020 2010-04-27 16:35:56Z matthew $
*/
/**
@@ -24,7 +24,7 @@
*
* @category Zend
* @package Zend_Loader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Loader
@@ -56,12 +56,24 @@ class Zend_Loader
}
if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) {
- require_once 'Zend/Exception.php';
+ // require_once 'Zend/Exception.php';
throw new Zend_Exception('Directory argument must be a string or an array');
}
- // autodiscover the path from the class name
- $file = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
+ // Autodiscover the path from the class name
+ // Implementation is PHP namespace-aware, and based on
+ // Framework Interop Group reference implementation:
+ // http://groups.google.com/group/php-standards/web/psr-0-final-proposal
+ $className = ltrim($class, '\\');
+ $file = '';
+ $namespace = '';
+ if ($lastNsPos = strripos($className, '\\')) {
+ $namespace = substr($className, 0, $lastNsPos);
+ $className = substr($className, $lastNsPos + 1);
+ $file = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
+ }
+ $file .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
+
if (!empty($dirs)) {
// use the autodiscovered path
$dirPath = dirname($file);
@@ -79,12 +91,11 @@ class Zend_Loader
$file = basename($file);
self::loadFile($file, $dirs, true);
} else {
- self::_securityCheck($file);
- include $file;
+ self::loadFile($file, null, true);
}
if (!class_exists($class, false) && !interface_exists($class, false)) {
- require_once 'Zend/Exception.php';
+ // require_once 'Zend/Exception.php';
throw new Zend_Exception("File \"$file\" does not exist or class \"$class\" was not found in the file");
}
}
@@ -162,11 +173,59 @@ class Zend_Loader
*/
public static function isReadable($filename)
{
- if (!$fh = @fopen($filename, 'r', true)) {
+ if (is_readable($filename)) {
+ // Return early if the filename is readable without needing the
+ // include_path
+ return true;
+ }
+
+ if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'
+ && preg_match('/^[a-z]:/i', $filename)
+ ) {
+ // If on windows, and path provided is clearly an absolute path,
+ // return false immediately
return false;
}
- @fclose($fh);
- return true;
+
+ foreach (self::explodeIncludePath() as $path) {
+ if ($path == '.') {
+ if (is_readable($filename)) {
+ return true;
+ }
+ continue;
+ }
+ $file = $path . '/' . $filename;
+ if (is_readable($file)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Explode an include path into an array
+ *
+ * If no path provided, uses current include_path. Works around issues that
+ * occur when the path includes stream schemas.
+ *
+ * @param string|null $path
+ * @return array
+ */
+ public static function explodeIncludePath($path = null)
+ {
+ if (null === $path) {
+ $path = get_include_path();
+ }
+
+ if (PATH_SEPARATOR == ':') {
+ // On *nix systems, include_paths which include paths with a stream
+ // schema cannot be safely explode'd, so we have to be a bit more
+ // intelligent in the approach.
+ $paths = preg_split('#:(?!//)#', $path);
+ } else {
+ $paths = explode(PATH_SEPARATOR, $path);
+ }
+ return $paths;
}
/**
@@ -205,7 +264,7 @@ class Zend_Loader
public static function registerAutoload($class = 'Zend_Loader', $enabled = true)
{
trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0; use Zend_Loader_Autoloader instead', E_USER_NOTICE);
- require_once 'Zend/Loader/Autoloader.php';
+ // require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->setFallbackAutoloader(true);
@@ -213,7 +272,7 @@ class Zend_Loader
self::loadClass($class);
$methods = get_class_methods($class);
if (!in_array('autoload', (array) $methods)) {
- require_once 'Zend/Exception.php';
+ // require_once 'Zend/Exception.php';
throw new Zend_Exception("The class \"$class\" does not have an autoload() method");
}
@@ -240,7 +299,7 @@ class Zend_Loader
* Security check
*/
if (preg_match('/[^a-z0-9\\/\\\\_.:-]/i', $filename)) {
- require_once 'Zend/Exception.php';
+ // require_once 'Zend/Exception.php';
throw new Zend_Exception('Security check: Illegal character in filename');
}
}
diff --git a/libs/Zend/Loader/Autoloader.php b/libs/Zend/Loader/Autoloader.php
index d218331444..11ddf6eca4 100644
--- a/libs/Zend/Loader/Autoloader.php
+++ b/libs/Zend/Loader/Autoloader.php
@@ -15,8 +15,8 @@
* @category Zend
* @package Zend_Loader
* @subpackage Autoloader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
- * @version $Id: Autoloader.php 18339 2009-09-21 15:05:25Z matthew $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Autoloader.php 20096 2010-01-06 02:05:09Z bkarwin $
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
@@ -25,11 +25,11 @@ require_once 'Zend/Loader.php';
/**
* Autoloader stack and namespace autoloader
- *
+ *
* @uses Zend_Loader_Autoloader
* @package Zend_Loader
* @subpackage Autoloader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Loader_Autoloader
@@ -84,7 +84,7 @@ class Zend_Loader_Autoloader
/**
* Retrieve singleton instance
- *
+ *
* @return Zend_Loader_Autoloader
*/
public static function getInstance()
@@ -97,7 +97,7 @@ class Zend_Loader_Autoloader
/**
* Reset the singleton instance
- *
+ *
* @return void
*/
public static function resetInstance()
@@ -107,8 +107,8 @@ class Zend_Loader_Autoloader
/**
* Autoload a class
- *
- * @param string $class
+ *
+ * @param string $class
* @return bool
*/
public static function autoload($class)
@@ -138,7 +138,7 @@ class Zend_Loader_Autoloader
/**
* Set the default autoloader implementation
- *
+ *
* @param string|array $callback PHP callback
* @return void
*/
@@ -154,7 +154,7 @@ class Zend_Loader_Autoloader
/**
* Retrieve the default autoloader callback
- *
+ *
* @return string|array PHP Callback
*/
public function getDefaultAutoloader()
@@ -164,7 +164,7 @@ class Zend_Loader_Autoloader
/**
* Set several autoloader callbacks at once
- *
+ *
* @param array $autoloaders Array of PHP callbacks (or Zend_Loader_Autoloader_Interface implementations) to act as autoloaders
* @return Zend_Loader_Autoloader
*/
@@ -176,7 +176,7 @@ class Zend_Loader_Autoloader
/**
* Get attached autoloader implementations
- *
+ *
* @return array
*/
public function getAutoloaders()
@@ -186,7 +186,7 @@ class Zend_Loader_Autoloader
/**
* Return all autoloaders for a given namespace
- *
+ *
* @param string $namespace
* @return array
*/
@@ -201,8 +201,8 @@ class Zend_Loader_Autoloader
/**
* Register a namespace to autoload
- *
- * @param string|array $namespace
+ *
+ * @param string|array $namespace
* @return Zend_Loader_Autoloader
*/
public function registerNamespace($namespace)
@@ -223,8 +223,8 @@ class Zend_Loader_Autoloader
/**
* Unload a registered autoload namespace
- *
- * @param string|array $namespace
+ *
+ * @param string|array $namespace
* @return Zend_Loader_Autoloader
*/
public function unregisterNamespace($namespace)
@@ -245,7 +245,7 @@ class Zend_Loader_Autoloader
/**
* Get a list of registered autoload namespaces
- *
+ *
* @return array
*/
public function getRegisteredNamespaces()
@@ -281,8 +281,8 @@ class Zend_Loader_Autoloader
/**
* Get or set the value of the "suppress not found warnings" flag
- *
- * @param null|bool $flag
+ *
+ * @param null|bool $flag
* @return bool|Zend_Loader_Autoloader Returns boolean if no argument is passed, object instance otherwise
*/
public function suppressNotFoundWarnings($flag = null)
@@ -296,8 +296,8 @@ class Zend_Loader_Autoloader
/**
* Indicate whether or not this autoloader should be a fallback autoloader
- *
- * @param bool $flag
+ *
+ * @param bool $flag
* @return Zend_Loader_Autoloader
*/
public function setFallbackAutoloader($flag)
@@ -308,7 +308,7 @@ class Zend_Loader_Autoloader
/**
* Is this instance acting as a fallback autoloader?
- *
+ *
* @return bool
*/
public function isFallbackAutoloader()
@@ -319,11 +319,11 @@ class Zend_Loader_Autoloader
/**
* Get autoloaders to use when matching class
*
- * Determines if the class matches a registered namespace, and, if so,
- * returns only the autoloaders for that namespace. Otherwise, it returns
+ * Determines if the class matches a registered namespace, and, if so,
+ * returns only the autoloaders for that namespace. Otherwise, it returns
* all non-namespaced autoloaders.
*
- * @param string $class
+ * @param string $class
* @return array Array of autoloaders to use
*/
public function getClassAutoloaders($class)
@@ -365,7 +365,7 @@ class Zend_Loader_Autoloader
/**
* Add an autoloader to the beginning of the stack
- *
+ *
* @param object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation
* @param string|array $namespace Specific namespace(s) under which to register callback
* @return Zend_Loader_Autoloader
@@ -388,7 +388,7 @@ class Zend_Loader_Autoloader
/**
* Append an autoloader to the autoloader stack
- *
+ *
* @param object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation
* @param string|array $namespace Specific namespace(s) under which to register callback
* @return Zend_Loader_Autoloader
@@ -411,7 +411,7 @@ class Zend_Loader_Autoloader
/**
* Remove an autoloader from the autoloader stack
- *
+ *
* @param object|array|string $callback PHP callback or Zend_Loader_Autoloader_Interface implementation
* @param null|string|array $namespace Specific namespace(s) from which to remove autoloader
* @return Zend_Loader_Autoloader
@@ -449,7 +449,7 @@ class Zend_Loader_Autoloader
* Constructor
*
* Registers instance with spl_autoload stack
- *
+ *
* @return void
*/
protected function __construct()
@@ -460,8 +460,8 @@ class Zend_Loader_Autoloader
/**
* Internal autoloader implementation
- *
- * @param string $class
+ *
+ * @param string $class
* @return bool
*/
protected function _autoload($class)
@@ -481,9 +481,9 @@ class Zend_Loader_Autoloader
/**
* Set autoloaders for a specific namespace
- *
- * @param array $autoloaders
- * @param string $namespace
+ *
+ * @param array $autoloaders
+ * @param string $namespace
* @return Zend_Loader_Autoloader
*/
protected function _setNamespaceAutoloaders(array $autoloaders, $namespace = '')
@@ -495,15 +495,15 @@ class Zend_Loader_Autoloader
/**
* Retrieve the filesystem path for the requested ZF version
- *
- * @param string $path
- * @param string $version
+ *
+ * @param string $path
+ * @param string $version
* @return void
*/
protected function _getVersionPath($path, $version)
{
$type = $this->_getVersionType($version);
-
+
if ($type == 'latest') {
$version = 'latest';
}
@@ -519,8 +519,8 @@ class Zend_Loader_Autoloader
/**
* Retrieve the ZF version type
- *
- * @param string $version
+ *
+ * @param string $version
* @return string "latest", "major", "minor", or "specific"
* @throws Zend_Loader_Exception if version string contains too many dots
*/
@@ -546,9 +546,9 @@ class Zend_Loader_Autoloader
/**
* Get available versions for the version type requested
- *
- * @param string $path
- * @param string $version
+ *
+ * @param string $path
+ * @param string $version
* @return array
*/
protected function _getAvailableVersions($path, $version)
diff --git a/libs/Zend/Loader/Autoloader/Interface.php b/libs/Zend/Loader/Autoloader/Interface.php
index 09983ae188..8bcaf14fb2 100644
--- a/libs/Zend/Loader/Autoloader/Interface.php
+++ b/libs/Zend/Loader/Autoloader/Interface.php
@@ -15,17 +15,17 @@
* @category Zend
* @package Zend_Loader
* @subpackage Autoloader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
- * @version $Id: Interface.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/**
* Autoloader interface
- *
+ *
* @package Zend_Loader
* @subpackage Autoloader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Loader_Autoloader_Interface
diff --git a/libs/Zend/Loader/Autoloader/Resource.php b/libs/Zend/Loader/Autoloader/Resource.php
index 15ae74c9a0..cd0a7fe7fc 100644
--- a/libs/Zend/Loader/Autoloader/Resource.php
+++ b/libs/Zend/Loader/Autoloader/Resource.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Loader
* @subpackage Autoloader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
- * @version $Id: Resource.php 18173 2009-09-17 15:35:05Z padraic $
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @version $Id: Resource.php 20096 2010-01-06 02:05:09Z bkarwin $
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
/** Zend_Loader_Autoloader_Interface */
-require_once 'Zend/Loader/Autoloader/Interface.php';
+// require_once 'Zend/Loader/Autoloader/Interface.php';
/**
* Resource loader
- *
+ *
* @uses Zend_Loader_Autoloader_Interface
* @package Zend_Loader
* @subpackage Autoloader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interface
@@ -61,7 +61,7 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Constructor
- *
+ *
* @param array|Zend_Config $options Configuration options for resource autoloader
* @return void
*/
@@ -71,7 +71,7 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
$options = $options->toArray();
}
if (!is_array($options)) {
- require_once 'Zend/Loader/Exception.php';
+ // require_once 'Zend/Loader/Exception.php';
throw new Zend_Loader_Exception('Options must be passed to resource loader constructor');
}
@@ -81,7 +81,7 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
if ((null === $namespace)
|| (null === $this->getBasePath())
) {
- require_once 'Zend/Loader/Exception.php';
+ // require_once 'Zend/Loader/Exception.php';
throw new Zend_Loader_Exception('Resource loader requires both a namespace and a base path for initialization');
}
@@ -94,7 +94,7 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Overloading: methods
*
- * Allow retrieving concrete resource object instances using 'get<Resourcename>()'
+ * Allow retrieving concrete resource object instances using 'get<Resourcename>()'
* syntax. Example:
* <code>
* $loader = new Zend_Loader_Autoloader_Resource(array(
@@ -105,9 +105,9 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
*
* $foo = $loader->getModel('Foo'); // get instance of Stuff_Model_Foo class
* </code>
- *
- * @param string $method
- * @param array $args
+ *
+ * @param string $method
+ * @param array $args
* @return mixed
* @throws Zend_Loader_Exception if method not beginning with 'get' or not matching a valid resource type is called
*/
@@ -116,28 +116,28 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
if ('get' == substr($method, 0, 3)) {
$type = strtolower(substr($method, 3));
if (!$this->hasResourceType($type)) {
- require_once 'Zend/Loader/Exception.php';
+ // require_once 'Zend/Loader/Exception.php';
throw new Zend_Loader_Exception("Invalid resource type $type; cannot load resource");
}
if (empty($args)) {
- require_once 'Zend/Loader/Exception.php';
+ // require_once 'Zend/Loader/Exception.php';
throw new Zend_Loader_Exception("Cannot load resources; no resource specified");
}
$resource = array_shift($args);
return $this->load($resource, $type);
}
- require_once 'Zend/Loader/Exception.php';
+ // require_once 'Zend/Loader/Exception.php';
throw new Zend_Loader_Exception("Method '$method' is not supported");
}
/**
- * Attempt to autoload a class
- *
- * @param string $class
- * @return mixed False if not matched, otherwise result if include operation
+ * Helper method to calculate the correct class path
+ *
+ * @param string $class
+ * @return False if not matched other wise the correct path
*/
- public function autoload($class)
+ public function getClassPath($class)
{
$segments = explode('_', $class);
$namespaceTopLevel = $this->getNamespace();
@@ -171,15 +171,36 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
return false;
}
- $final = substr($class, strlen($lastMatch));
+ $final = substr($class, strlen($lastMatch) + 1);
$path = $this->_components[$lastMatch];
- return include $path . '/' . str_replace('_', '/', $final) . '.php';
+ $classPath = $path . '/' . str_replace('_', '/', $final) . '.php';
+
+ if (Zend_Loader::isReadable($classPath)) {
+ return $classPath;
+ }
+
+ return false;
+ }
+
+ /**
+ * Attempt to autoload a class
+ *
+ * @param string $class
+ * @return mixed False if not matched, otherwise result if include operation
+ */
+ public function autoload($class)
+ {
+ $classPath = $this->getClassPath($class);
+ if (false !== $classPath) {
+ return include $classPath;
+ }
+ return false;
}
/**
* Set class state from options
- *
- * @param array $options
+ *
+ * @param array $options
* @return Zend_Loader_Autoloader_Resource
*/
public function setOptions(array $options)
@@ -196,8 +217,8 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Set namespace that this autoloader handles
- *
- * @param string $namespace
+ *
+ * @param string $namespace
* @return Zend_Loader_Autoloader_Resource
*/
public function setNamespace($namespace)
@@ -208,7 +229,7 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Get namespace this autoloader handles
- *
+ *
* @return string
*/
public function getNamespace()
@@ -218,8 +239,8 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Set base path for this set of resources
- *
- * @param string $path
+ *
+ * @param string $path
* @return Zend_Loader_Autoloader_Resource
*/
public function setBasePath($path)
@@ -227,10 +248,10 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
$this->_basePath = (string) $path;
return $this;
}
-
+
/**
* Get base path to this set of resources
- *
+ *
* @return string
*/
public function getBasePath()
@@ -240,7 +261,7 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Add resource type
- *
+ *
* @param string $type identifier for the resource type being loaded
* @param string $path path relative to resource base path containing the resource types
* @param null|string $namespace sub-component namespace to append to base namespace that qualifies this resource type
@@ -251,7 +272,7 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
$type = strtolower($type);
if (!isset($this->_resourceTypes[$type])) {
if (null === $namespace) {
- require_once 'Zend/Loader/Exception.php';
+ // require_once 'Zend/Loader/Exception.php';
throw new Zend_Loader_Exception('Initial definition of a resource type must include a namespace');
}
$namespaceTopLevel = $this->getNamespace();
@@ -261,7 +282,7 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
);
}
if (!is_string($path)) {
- require_once 'Zend/Loader/Exception.php';
+ // require_once 'Zend/Loader/Exception.php';
throw new Zend_Loader_Exception('Invalid path specification provided; must be string');
}
$this->_resourceTypes[$type]['path'] = $this->getBasePath() . '/' . rtrim($path, '\/');
@@ -274,10 +295,10 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Add multiple resources at once
*
- * $types should be an associative array of resource type => specification
- * pairs. Each specification should be an associative array containing
- * minimally the 'path' key (specifying the path relative to the resource
- * base path) and optionally the 'namespace' key (indicating the subcomponent
+ * $types should be an associative array of resource type => specification
+ * pairs. Each specification should be an associative array containing
+ * minimally the 'path' key (specifying the path relative to the resource
+ * base path) and optionally the 'namespace' key (indicating the subcomponent
* namespace to append to the resource namespace).
*
* As an example:
@@ -293,19 +314,19 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
* ),
* ));
* </code>
- *
- * @param array $types
+ *
+ * @param array $types
* @return Zend_Loader_Autoloader_Resource
*/
public function addResourceTypes(array $types)
{
foreach ($types as $type => $spec) {
if (!is_array($spec)) {
- require_once 'Zend/Loader/Exception.php';
+ // require_once 'Zend/Loader/Exception.php';
throw new Zend_Loader_Exception('addResourceTypes() expects an array of arrays');
}
if (!isset($spec['path'])) {
- require_once 'Zend/Loader/Exception.php';
+ // require_once 'Zend/Loader/Exception.php';
throw new Zend_Loader_Exception('addResourceTypes() expects each array to include a paths element');
}
$paths = $spec['path'];
@@ -320,9 +341,9 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Overwrite existing and set multiple resource types at once
- *
+ *
* @see Zend_Loader_Autoloader_Resource::addResourceTypes()
- * @param array $types
+ * @param array $types
* @return Zend_Loader_Autoloader_Resource
*/
public function setResourceTypes(array $types)
@@ -333,7 +354,7 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Retrieve resource type mappings
- *
+ *
* @return array
*/
public function getResourceTypes()
@@ -343,8 +364,8 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Is the requested resource type defined?
- *
- * @param string $type
+ *
+ * @param string $type
* @return bool
*/
public function hasResourceType($type)
@@ -354,8 +375,8 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Remove the requested resource type
- *
- * @param string $type
+ *
+ * @param string $type
* @return Zend_Loader_Autoloader_Resource
*/
public function removeResourceType($type)
@@ -370,7 +391,7 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Clear all resource types
- *
+ *
* @return Zend_Loader_Autoloader_Resource
*/
public function clearResourceTypes()
@@ -382,8 +403,8 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Set default resource type to use when calling load()
- *
- * @param string $type
+ *
+ * @param string $type
* @return Zend_Loader_Autoloader_Resource
*/
public function setDefaultResourceType($type)
@@ -396,7 +417,7 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Get default resource type to use when calling load()
- *
+ *
* @return string|null
*/
public function getDefaultResourceType()
@@ -407,12 +428,12 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
/**
* Object registry and factory
*
- * Loads the requested resource of type $type (or uses the default resource
- * type if none provided). If the resource has been loaded previously,
+ * Loads the requested resource of type $type (or uses the default resource
+ * type if none provided). If the resource has been loaded previously,
* returns the previous instance; otherwise, instantiates it.
- *
- * @param string $resource
- * @param string $type
+ *
+ * @param string $resource
+ * @param string $type
* @return object
* @throws Zend_Loader_Exception if resource type not specified or invalid
*/
@@ -421,12 +442,12 @@ class Zend_Loader_Autoloader_Resource implements Zend_Loader_Autoloader_Interfac
if (null === $type) {
$type = $this->getDefaultResourceType();
if (empty($type)) {
- require_once 'Zend/Loader/Exception.php';
+ // require_once 'Zend/Loader/Exception.php';
throw new Zend_Loader_Exception('No resource type specified');
}
}
if (!$this->hasResourceType($type)) {
- require_once 'Zend/Loader/Exception.php';
+ // require_once 'Zend/Loader/Exception.php';
throw new Zend_Loader_Exception('Invalid resource type specified');
}
$namespace = $this->_resourceTypes[$type]['namespace'];
diff --git a/libs/Zend/Loader/Exception.php b/libs/Zend/Loader/Exception.php
index 99ad35db7b..84d40420ef 100644
--- a/libs/Zend/Loader/Exception.php
+++ b/libs/Zend/Loader/Exception.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Loader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Exception
*/
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Loader
* @uses Zend_Exception
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Loader_Exception extends Zend_Exception
-{}
+class Zend_Loader_Exception extends Zend_Exception
+{} \ No newline at end of file
diff --git a/libs/Zend/Loader/PluginLoader.php b/libs/Zend/Loader/PluginLoader.php
index 39ff94cfe5..f3f6170c67 100644
--- a/libs/Zend/Loader/PluginLoader.php
+++ b/libs/Zend/Loader/PluginLoader.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Loader
* @subpackage PluginLoader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: PluginLoader.php 18207 2009-09-17 22:29:50Z beberlei $
+ * @version $Id: PluginLoader.php 21170 2010-02-23 19:50:16Z matthew $
*/
/** Zend_Loader_PluginLoader_Interface */
-require_once 'Zend/Loader/PluginLoader/Interface.php';
+// require_once 'Zend/Loader/PluginLoader/Interface.php';
/** Zend_Loader */
-require_once 'Zend/Loader.php';
+// require_once 'Zend/Loader.php';
/**
* Generic plugin class loader
@@ -32,7 +32,7 @@ require_once 'Zend/Loader.php';
* @category Zend
* @package Zend_Loader
* @subpackage PluginLoader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
@@ -123,9 +123,15 @@ class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
*/
protected function _formatPrefix($prefix)
{
- if($prefix == "") {
- return $prefix;
- }
+ if($prefix == "") {
+ return $prefix;
+ }
+
+ $last = strlen($prefix) - 1;
+ if ($prefix{$last} == '\\') {
+ return $prefix;
+ }
+
return rtrim($prefix, '_') . '_';
}
@@ -139,7 +145,7 @@ class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
public function addPrefixPath($prefix, $path)
{
if (!is_string($prefix) || !is_string($path)) {
- require_once 'Zend/Loader/PluginLoader/Exception.php';
+ // require_once 'Zend/Loader/PluginLoader/Exception.php';
throw new Zend_Loader_PluginLoader_Exception('Zend_Loader_PluginLoader::addPrefixPath() method only takes strings for prefix and path.');
}
@@ -244,14 +250,14 @@ class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
}
if (!isset($registry[$prefix])) {
- require_once 'Zend/Loader/PluginLoader/Exception.php';
+ // require_once 'Zend/Loader/PluginLoader/Exception.php';
throw new Zend_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' was not found in the PluginLoader.');
}
if ($path != null) {
$pos = array_search($path, $registry[$prefix]);
if ($pos === null) {
- require_once 'Zend/Loader/PluginLoader/Exception.php';
+ // require_once 'Zend/Loader/PluginLoader/Exception.php';
throw new Zend_Loader_PluginLoader_Exception('Prefix ' . $prefix . ' / Path ' . $path . ' was not found in the PluginLoader.');
}
unset($registry[$prefix][$pos]);
@@ -298,7 +304,7 @@ class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
public function getClassName($name)
{
$name = $this->_formatName($name);
- if ($this->_useStaticRegistry
+ if ($this->_useStaticRegistry
&& isset(self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name])
) {
return self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name];
@@ -311,14 +317,14 @@ class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
/**
* Get path to plugin class
- *
- * @param mixed $name
+ *
+ * @param mixed $name
* @return string|false False if not found
*/
public function getClassPath($name)
{
$name = $this->_formatName($name);
- if ($this->_useStaticRegistry
+ if ($this->_useStaticRegistry
&& !empty(self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name])
) {
return self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name];
@@ -345,9 +351,9 @@ class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
* Load a plugin via the name provided
*
* @param string $name
- * @param bool $throwExceptions Whether or not to throw exceptions if the
+ * @param bool $throwExceptions Whether or not to throw exceptions if the
* class is not resolved
- * @return string|false Class name of loaded class; false if $throwExceptions
+ * @return string|false Class name of loaded class; false if $throwExceptions
* if false and no class found
* @throws Zend_Loader_Exception if class not found
*/
@@ -402,16 +408,14 @@ class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
foreach ($registry as $prefix => $paths) {
$message .= "\n$prefix: " . implode(PATH_SEPARATOR, $paths);
}
- require_once 'Zend/Loader/PluginLoader/Exception.php';
+ // require_once 'Zend/Loader/PluginLoader/Exception.php';
throw new Zend_Loader_PluginLoader_Exception($message);
}
if ($this->_useStaticRegistry) {
self::$_staticLoadedPlugins[$this->_useStaticRegistry][$name] = $className;
- self::$_staticLoadedPluginPaths[$this->_useStaticRegistry][$name] = (isset($loadFile) ? $loadFile : '');
} else {
$this->_loadedPlugins[$name] = $className;
- $this->_loadedPluginPaths[$name] = (isset($loadFile) ? $loadFile : '');
}
return $className;
}
@@ -419,10 +423,10 @@ class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
/**
* Set path to class file cache
*
- * Specify a path to a file that will add include_once statements for each
+ * Specify a path to a file that will add include_once statements for each
* plugin class loaded. This is an opt-in feature for performance purposes.
- *
- * @param string $file
+ *
+ * @param string $file
* @return void
* @throws Zend_Loader_PluginLoader_Exception if file is not writeable or path does not exist
*/
@@ -434,15 +438,15 @@ class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
}
if (!file_exists($file) && !file_exists(dirname($file))) {
- require_once 'Zend/Loader/PluginLoader/Exception.php';
+ // require_once 'Zend/Loader/PluginLoader/Exception.php';
throw new Zend_Loader_PluginLoader_Exception('Specified file does not exist and/or directory does not exist (' . $file . ')');
}
if (file_exists($file) && !is_writable($file)) {
- require_once 'Zend/Loader/PluginLoader/Exception.php';
+ // require_once 'Zend/Loader/PluginLoader/Exception.php';
throw new Zend_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')');
}
if (!file_exists($file) && file_exists(dirname($file)) && !is_writable(dirname($file))) {
- require_once 'Zend/Loader/PluginLoader/Exception.php';
+ // require_once 'Zend/Loader/PluginLoader/Exception.php';
throw new Zend_Loader_PluginLoader_Exception('Specified file is not writeable (' . $file . ')');
}
@@ -451,7 +455,7 @@ class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
/**
* Retrieve class file cache path
- *
+ *
* @return string|null
*/
public static function getIncludeFileCache()
@@ -461,8 +465,8 @@ class Zend_Loader_PluginLoader implements Zend_Loader_PluginLoader_Interface
/**
* Append an include_once statement to the class file cache
- *
- * @param string $incFile
+ *
+ * @param string $incFile
* @return void
*/
protected static function _appendIncFile($incFile)
diff --git a/libs/Zend/Loader/PluginLoader/Exception.php b/libs/Zend/Loader/PluginLoader/Exception.php
index 9e0a744e5f..7db26ae6be 100644
--- a/libs/Zend/Loader/PluginLoader/Exception.php
+++ b/libs/Zend/Loader/PluginLoader/Exception.php
@@ -15,15 +15,15 @@
* @category Zend
* @package Zend_Loader
* @subpackage PluginLoader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Loader_Exception
*/
-require_once 'Zend/Loader/Exception.php';
+// require_once 'Zend/Loader/Exception.php';
/**
* Plugin class loader exceptions
@@ -31,7 +31,7 @@ require_once 'Zend/Loader/Exception.php';
* @category Zend
* @package Zend_Loader
* @subpackage PluginLoader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Loader_PluginLoader_Exception extends Zend_Loader_Exception
diff --git a/libs/Zend/Loader/PluginLoader/Interface.php b/libs/Zend/Loader/PluginLoader/Interface.php
index 67da668506..bfbbe50e3c 100644
--- a/libs/Zend/Loader/PluginLoader/Interface.php
+++ b/libs/Zend/Loader/PluginLoader/Interface.php
@@ -15,9 +15,9 @@
* @category Zend
* @package Zend_Loader
* @subpackage PluginLoader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
@@ -26,7 +26,7 @@
* @category Zend
* @package Zend_Loader
* @subpackage PluginLoader
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Loader_PluginLoader_Interface
@@ -39,7 +39,7 @@ interface Zend_Loader_PluginLoader_Interface
* @return Zend_Loader_PluginLoader
*/
public function addPrefixPath($prefix, $path);
-
+
/**
* Remove a prefix (or prefixed-path) from the registry
*
@@ -48,7 +48,7 @@ interface Zend_Loader_PluginLoader_Interface
* @return Zend_Loader_PluginLoader
*/
public function removePrefixPath($prefix, $path = null);
-
+
/**
* Whether or not a Helper by a specific name
*
@@ -64,7 +64,7 @@ interface Zend_Loader_PluginLoader_Interface
* @return string
*/
public function getClassName($name);
-
+
/**
* Load a helper via the name provided
*
diff --git a/libs/Zend/Log.php b/libs/Zend/Log.php
index 04b7ebb85a..471c0e3cf4 100644
--- a/libs/Zend/Log.php
+++ b/libs/Zend/Log.php
@@ -14,17 +14,17 @@
*
* @category Zend
* @package Zend_Log
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Log.php 16207 2009-06-21 19:17:51Z thomas $
+ * @version $Id: Log.php 20893 2010-02-03 22:59:25Z yoshida@zend.co.jp $
*/
/**
* @category Zend
* @package Zend_Log
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Log.php 16207 2009-06-21 19:17:51Z thomas $
+ * @version $Id: Log.php 20893 2010-02-03 22:59:25Z yoshida@zend.co.jp $
*/
class Zend_Log
{
@@ -59,6 +59,19 @@ class Zend_Log
protected $_extras = array();
/**
+ *
+ * @var string
+ */
+ protected $_defaultWriterNamespace = 'Zend_Log_Writer';
+
+ /**
+ *
+ * @var string
+ */
+ protected $_defaultFilterNamespace = 'Zend_Log_Filter';
+
+
+ /**
* Class constructor. Create a new logger
*
* @param Zend_Log_Writer_Abstract|null $writer default writer
@@ -74,6 +87,146 @@ class Zend_Log
}
/**
+ * Factory to construct the logger and one or more writers
+ * based on the configuration array
+ *
+ * @param array|Zend_Config Array or instance of Zend_Config
+ * @return Zend_Log
+ */
+ static public function factory($config = array())
+ {
+ if ($config instanceof Zend_Config) {
+ $config = $config->toArray();
+ }
+
+ if (!is_array($config) || empty($config)) {
+ /** @see Zend_Log_Exception */
+ // require_once 'Zend/Log/Exception.php';
+ throw new Zend_Log_Exception('Configuration must be an array or instance of Zend_Config');
+ }
+
+ $log = new Zend_Log;
+
+ if (!is_array(current($config))) {
+ $log->addWriter(current($config));
+ } else {
+ foreach($config as $writer) {
+ $log->addWriter($writer);
+ }
+ }
+
+ return $log;
+ }
+
+
+ /**
+ * Construct a writer object based on a configuration array
+ *
+ * @param array $spec config array with writer spec
+ * @return Zend_Log_Writer_Abstract
+ */
+ protected function _constructWriterFromConfig($config)
+ {
+ $writer = $this->_constructFromConfig('writer', $config, $this->_defaultWriterNamespace);
+
+ if (!$writer instanceof Zend_Log_Writer_Abstract) {
+ /** @see Zend_Log_Exception */
+ // require_once 'Zend/Log/Exception.php';
+ throw new Zend_Log_Exception("{$writerName} does not extend Zend_Log_Writer_Abstract!");
+ }
+
+ if (isset($config['filterName'])) {
+ $filter = $this->_constructFilterFromConfig($config);
+ $writer->addFilter($filter);
+ }
+
+ return $writer;
+ }
+
+ /**
+ * Construct filter object from configuration array or Zend_Config object
+ *
+ * @param array|Zend_Config $config Zend_Config or Array
+ * @return Zend_Log_Filter_Interface
+ */
+ protected function _constructFilterFromConfig($config)
+ {
+ $filter = $this->_constructFromConfig('filter', $config, $this->_defaultFilterNamespace);
+
+ if (!$filter instanceof Zend_Log_Filter_Interface) {
+ /** @see Zend_Log_Exception */
+ // require_once 'Zend/Log/Exception.php';
+ throw new Zend_Log_Exception("{$filterName} does not implement Zend_Log_Filter_Interface");
+ }
+
+ return $filter;
+ }
+
+ /**
+ * Construct a filter or writer from config
+ *
+ * @param string $type 'writer' of 'filter'
+ * @param mixed $config Zend_Config or Array
+ * @param string $namespace
+ * @return object
+ */
+ protected function _constructFromConfig($type, $config, $namespace)
+ {
+ if ($config instanceof Zend_Config) {
+ $config = $config->toArray();
+ }
+
+ if (!is_array($config) || empty($config)) {
+ // require_once 'Zend/Log/Exception.php';
+ throw new Zend_Log_Exception(
+ 'Configuration must be an array or instance of Zend_Config'
+ );
+ }
+
+ $params = isset($config[ $type .'Params' ]) ? $config[ $type .'Params' ] : array();
+ $className = $this->getClassName($config, $type, $namespace);
+ // if (!class_exists($className)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($className);
+ // }
+
+ $reflection = new ReflectionClass($className);
+ if (!$reflection->implementsInterface('Zend_Log_FactoryInterface')) {
+ // require_once 'Zend/Log/Exception.php';
+ throw new Zend_Log_Exception(
+ 'Driver does not implement Zend_Log_FactoryInterface and can not be constructed from config.'
+ );
+ }
+
+ return call_user_func(array($className, 'factory'), $params);
+ }
+
+ /**
+ * Get the writer or filter full classname
+ *
+ * @param array $config
+ * @param string $type filter|writer
+ * @param string $defaultNamespace
+ * @return string full classname
+ */
+ protected function getClassName($config, $type, $defaultNamespace)
+ {
+ if (!isset($config[ $type . 'Name' ])) {
+ // require_once 'Zend/Log/Exception.php';
+ throw new Zend_Log_Exception("Specify {$type}Name in the configuration array");
+ }
+ $className = $config[ $type . 'Name' ];
+
+ $namespace = $defaultNamespace;
+ if (isset($config[ $type . 'Namespace' ])) {
+ $namespace = $config[ $type . 'Namespace' ];
+ }
+
+ $fullClassName = $namespace . '_' . $className;
+ return $fullClassName;
+ }
+
+ /**
* Class destructor. Shutdown log writers
*
* @return void
@@ -100,10 +253,24 @@ class Zend_Log
{
$priority = strtoupper($method);
if (($priority = array_search($priority, $this->_priorities)) !== false) {
- $this->log(array_shift($params), $priority);
+ switch (count($params)) {
+ case 0:
+ /** @see Zend_Log_Exception */
+ // require_once 'Zend/Log/Exception.php';
+ throw new Zend_Log_Exception('Missing log message');
+ case 1:
+ $message = array_shift($params);
+ $extras = null;
+ break;
+ default:
+ $message = array_shift($params);
+ $extras = array_shift($params);
+ break;
+ }
+ $this->log($message, $priority, $extras);
} else {
/** @see Zend_Log_Exception */
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Bad log priority');
}
}
@@ -113,21 +280,22 @@ class Zend_Log
*
* @param string $message Message to log
* @param integer $priority Priority of message
+ * @param mixed $extras Extra information to log in event
* @return void
* @throws Zend_Log_Exception
*/
- public function log($message, $priority)
+ public function log($message, $priority, $extras = null)
{
// sanity checks
if (empty($this->_writers)) {
/** @see Zend_Log_Exception */
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('No writers were added');
}
if (! isset($this->_priorities[$priority])) {
/** @see Zend_Log_Exception */
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Bad log priority');
}
@@ -138,6 +306,25 @@ class Zend_Log
'priorityName' => $this->_priorities[$priority]),
$this->_extras);
+ // Check to see if any extra information was passed
+ if (!empty($extras)) {
+ $info = array();
+ if (is_array($extras)) {
+ foreach ($extras as $key => $value) {
+ if (is_string($key)) {
+ $event[$key] = $value;
+ } else {
+ $info[] = $value;
+ }
+ }
+ } else {
+ $info = $extras;
+ }
+ if (!empty($info)) {
+ $event['info'] = $info;
+ }
+ }
+
// abort if rejected by the global filters
foreach ($this->_filters as $filter) {
if (! $filter->accept($event)) {
@@ -166,7 +353,7 @@ class Zend_Log
if (isset($this->_priorities[$priority])
|| array_search($name, $this->_priorities)) {
/** @see Zend_Log_Exception */
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Existing priorities cannot be overwritten');
}
@@ -184,12 +371,16 @@ class Zend_Log
public function addFilter($filter)
{
if (is_integer($filter)) {
- /** @see Zend_Log_Filter_Priority */
- require_once 'Zend/Log/Filter/Priority.php';
+ /** @see Zend_Log_Filter_Priority */
+ // require_once 'Zend/Log/Filter/Priority.php';
$filter = new Zend_Log_Filter_Priority($filter);
- } elseif(!is_object($filter) || ! $filter instanceof Zend_Log_Filter_Interface) {
+
+ } elseif ($filter instanceof Zend_Config || is_array($filter)) {
+ $filter = $this->_constructFilterFromConfig($filter);
+
+ } elseif(! $filter instanceof Zend_Log_Filter_Interface) {
/** @see Zend_Log_Exception */
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Invalid filter provided');
}
@@ -200,11 +391,24 @@ class Zend_Log
* Add a writer. A writer is responsible for taking a log
* message and writing it out to storage.
*
- * @param Zend_Log_Writer_Abstract $writer
+ * @param mixed $writer Zend_Log_Writer_Abstract or Config array
* @return void
*/
- public function addWriter(Zend_Log_Writer_Abstract $writer)
+ public function addWriter($writer)
{
+ if (is_array($writer) || $writer instanceof Zend_Config) {
+ $writer = $this->_constructWriterFromConfig($writer);
+ }
+
+ if (!$writer instanceof Zend_Log_Writer_Abstract) {
+ /** @see Zend_Log_Exception */
+ // require_once 'Zend/Log/Exception.php';
+ throw new Zend_Log_Exception(
+ 'Writer must be an instance of Zend_Log_Writer_Abstract'
+ . ' or you should pass a configuration array'
+ );
+ }
+
$this->_writers[] = $writer;
}
@@ -218,5 +422,4 @@ class Zend_Log
public function setEventItem($name, $value) {
$this->_extras = array_merge($this->_extras, array($name => $value));
}
-
}
diff --git a/libs/Zend/Log/Exception.php b/libs/Zend/Log/Exception.php
index 4290898cdd..b4bd50b5bb 100644
--- a/libs/Zend/Log/Exception.php
+++ b/libs/Zend/Log/Exception.php
@@ -14,20 +14,20 @@
*
* @category Zend
* @package Zend_Log
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Exception */
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Log
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
class Zend_Log_Exception extends Zend_Exception
{}
diff --git a/libs/Zend/Log/FactoryInterface.php b/libs/Zend/Log/FactoryInterface.php
new file mode 100644
index 0000000000..20a270747f
--- /dev/null
+++ b/libs/Zend/Log/FactoryInterface.php
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Log
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+
+/**
+ * @category Zend
+ * @package Zend_Log
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+interface Zend_Log_FactoryInterface
+{
+ /**
+ * Construct a Zend_Log driver
+ *
+ * @param array|Zen_Config $config
+ * @return Zend_Log_FactoryInterface
+ */
+ static public function factory($config);
+}
diff --git a/libs/Zend/Log/Filter/Abstract.php b/libs/Zend/Log/Filter/Abstract.php
new file mode 100644
index 0000000000..e0e97b89f2
--- /dev/null
+++ b/libs/Zend/Log/Filter/Abstract.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Log
+ * @subpackage Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+
+/** @see Zend_Log_Filter_Interface */
+// require_once 'Zend/Log/Filter/Interface.php';
+
+/** @see Zend_Log_FactoryInterface */
+// require_once 'Zend/Log/FactoryInterface.php';
+
+/**
+ * @category Zend
+ * @package Zend_Log
+ * @subpackage Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+abstract class Zend_Log_Filter_Abstract
+ implements Zend_Log_Filter_Interface, Zend_Log_FactoryInterface
+{
+ /**
+ * Validate and optionally convert the config to array
+ *
+ * @param array|Zend_Config $config Zend_Config or Array
+ * @return array
+ * @throws Zend_Log_Exception
+ */
+ static protected function _parseConfig($config)
+ {
+ if ($config instanceof Zend_Config) {
+ $config = $config->toArray();
+ }
+
+ if (!is_array($config)) {
+ // require_once 'Zend/Log/Exception.php';
+ throw new Zend_Log_Exception('Configuration must be an array or instance of Zend_Config');
+ }
+
+ return $config;
+ }
+}
diff --git a/libs/Zend/Log/Filter/Interface.php b/libs/Zend/Log/Filter/Interface.php
index 104b578f91..c2165d2ba6 100644
--- a/libs/Zend/Log/Filter/Interface.php
+++ b/libs/Zend/Log/Filter/Interface.php
@@ -15,18 +15,18 @@
* @category Zend
* @package Zend_Log
* @subpackage Filter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Log
* @subpackage Filter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
interface Zend_Log_Filter_Interface
{
@@ -37,5 +37,4 @@ interface Zend_Log_Filter_Interface
* @return boolean accepted?
*/
public function accept($event);
-
}
diff --git a/libs/Zend/Log/Filter/Message.php b/libs/Zend/Log/Filter/Message.php
index 9a05deaedf..4510888610 100644
--- a/libs/Zend/Log/Filter/Message.php
+++ b/libs/Zend/Log/Filter/Message.php
@@ -15,23 +15,23 @@
* @category Zend
* @package Zend_Log
* @subpackage Filter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Message.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Message.php 20982 2010-02-08 15:51:36Z matthew $
*/
-/** Zend_Log_Filter_Interface */
-require_once 'Zend/Log/Filter/Interface.php';
+/** Zend_Log_Filter_Abstract */
+// require_once 'Zend/Log/Filter/Abstract.php';
/**
* @category Zend
* @package Zend_Log
* @subpackage Filter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Message.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Message.php 20982 2010-02-08 15:51:36Z matthew $
*/
-class Zend_Log_Filter_Message implements Zend_Log_Filter_Interface
+class Zend_Log_Filter_Message extends Zend_Log_Filter_Abstract
{
/**
* @var string
@@ -47,13 +47,32 @@ class Zend_Log_Filter_Message implements Zend_Log_Filter_Interface
public function __construct($regexp)
{
if (@preg_match($regexp, '') === false) {
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception("Invalid regular expression '$regexp'");
}
$this->_regexp = $regexp;
}
/**
+ * Create a new instance of Zend_Log_Filter_Message
+ *
+ * @param array|Zend_Config $config
+ * @return Zend_Log_Filter_Message
+ * @throws Zend_Log_Exception
+ */
+ static public function factory($config)
+ {
+ $config = self::_parseConfig($config);
+ $config = array_merge(array(
+ 'regexp' => null
+ ), $config);
+
+ return new self(
+ $config['regexp']
+ );
+ }
+
+ /**
* Returns TRUE to accept the message, FALSE to block it.
*
* @param array $event event data
@@ -63,5 +82,4 @@ class Zend_Log_Filter_Message implements Zend_Log_Filter_Interface
{
return preg_match($this->_regexp, $event['message']) > 0;
}
-
}
diff --git a/libs/Zend/Log/Filter/Priority.php b/libs/Zend/Log/Filter/Priority.php
index d19c3f9ec6..45ba7c953b 100644
--- a/libs/Zend/Log/Filter/Priority.php
+++ b/libs/Zend/Log/Filter/Priority.php
@@ -15,23 +15,23 @@
* @category Zend
* @package Zend_Log
* @subpackage Filter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Priority.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Priority.php 20260 2010-01-13 18:29:22Z ralph $
*/
-/** Zend_Log_Filter_Interface */
-require_once 'Zend/Log/Filter/Interface.php';
+/** Zend_Log_Filter_Abstract */
+// require_once 'Zend/Log/Filter/Abstract.php';
/**
* @category Zend
* @package Zend_Log
* @subpackage Filter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Priority.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Priority.php 20260 2010-01-13 18:29:22Z ralph $
*/
-class Zend_Log_Filter_Priority implements Zend_Log_Filter_Interface
+class Zend_Log_Filter_Priority extends Zend_Log_Filter_Abstract
{
/**
* @var integer
@@ -51,15 +51,41 @@ class Zend_Log_Filter_Priority implements Zend_Log_Filter_Interface
* @param string $operator Comparison operator
* @throws Zend_Log_Exception
*/
- public function __construct($priority, $operator = '<=')
+ public function __construct($priority, $operator = NULL)
{
if (! is_integer($priority)) {
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Priority must be an integer');
}
$this->_priority = $priority;
- $this->_operator = $operator;
+ $this->_operator = is_null($operator) ? '<=' : $operator;
+ }
+
+ /**
+ * Create a new instance of Zend_Log_Filter_Priority
+ *
+ * @param array|Zend_Config $config
+ * @return Zend_Log_Filter_Priority
+ * @throws Zend_Log_Exception
+ */
+ static public function factory($config)
+ {
+ $config = self::_parseConfig($config);
+ $config = array_merge(array(
+ 'priority' => null,
+ 'operator' => null,
+ ), $config);
+
+ // Add support for constants
+ if (!is_numeric($config['priority']) && isset($config['priority']) && defined($config['priority'])) {
+ $config['priority'] = constant($config['priority']);
+ }
+
+ return new self(
+ (int) $config['priority'],
+ $config['operator']
+ );
}
/**
@@ -72,5 +98,4 @@ class Zend_Log_Filter_Priority implements Zend_Log_Filter_Interface
{
return version_compare($event['priority'], $this->_priority, $this->_operator);
}
-
}
diff --git a/libs/Zend/Log/Filter/Suppress.php b/libs/Zend/Log/Filter/Suppress.php
index 026db36727..d87d2720a2 100644
--- a/libs/Zend/Log/Filter/Suppress.php
+++ b/libs/Zend/Log/Filter/Suppress.php
@@ -15,23 +15,23 @@
* @category Zend
* @package Zend_Log
* @subpackage Filter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Suppress.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Suppress.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Log_Filter_Interface */
-require_once 'Zend/Log/Filter/Interface.php';
+// require_once 'Zend/Log/Filter/Interface.php';
/**
* @category Zend
* @package Zend_Log
* @subpackage Filter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Suppress.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Suppress.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
-class Zend_Log_Filter_Suppress implements Zend_Log_Filter_Interface
+class Zend_Log_Filter_Suppress extends Zend_Log_Filter_Abstract
{
/**
* @var boolean
@@ -63,4 +63,15 @@ class Zend_Log_Filter_Suppress implements Zend_Log_Filter_Interface
return $this->_accept;
}
+ /**
+ * Create a new instance of Zend_Log_Filter_Suppress
+ *
+ * @param array|Zend_Config $config
+ * @return Zend_Log_Filter_Suppress
+ * @throws Zend_Log_Exception
+ */
+ static public function factory($config)
+ {
+ return new self();
+ }
}
diff --git a/libs/Zend/Log/Formatter/Firebug.php b/libs/Zend/Log/Formatter/Firebug.php
index 2d348d0c78..a0238935ec 100644
--- a/libs/Zend/Log/Formatter/Firebug.php
+++ b/libs/Zend/Log/Formatter/Firebug.php
@@ -15,27 +15,27 @@
* @category Zend
* @package Zend_Log
* @subpackage Formatter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Firebug.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Firebug.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Log_Formatter_Interface */
-require_once 'Zend/Log/Formatter/Interface.php';
+// require_once 'Zend/Log/Formatter/Interface.php';
/**
* @category Zend
* @package Zend_Log
* @subpackage Formatter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Log_Formatter_Firebug implements Zend_Log_Formatter_Interface
{
/**
* This method formats the event for the firebug writer.
- *
- * The default is to just send the message parameter, but through
+ *
+ * The default is to just send the message parameter, but through
* extension of this class and calling the
* {@see Zend_Log_Writer_Firebug::setFormatter()} method you can
* pass as much of the event data as you are interested in.
diff --git a/libs/Zend/Log/Formatter/Interface.php b/libs/Zend/Log/Formatter/Interface.php
index 000734f393..2d05145a3f 100644
--- a/libs/Zend/Log/Formatter/Interface.php
+++ b/libs/Zend/Log/Formatter/Interface.php
@@ -15,18 +15,18 @@
* @category Zend
* @package Zend_Log
* @subpackage Formatter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Log
* @subpackage Formatter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
interface Zend_Log_Formatter_Interface
{
diff --git a/libs/Zend/Log/Formatter/Simple.php b/libs/Zend/Log/Formatter/Simple.php
index 0761404742..22f5a116fc 100644
--- a/libs/Zend/Log/Formatter/Simple.php
+++ b/libs/Zend/Log/Formatter/Simple.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Log
* @subpackage Formatter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Simple.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Simple.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Log_Formatter_Interface */
-require_once 'Zend/Log/Formatter/Interface.php';
+// require_once 'Zend/Log/Formatter/Interface.php';
/**
* @category Zend
* @package Zend_Log
* @subpackage Formatter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Simple.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Simple.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
class Zend_Log_Formatter_Simple implements Zend_Log_Formatter_Interface
{
@@ -53,7 +53,7 @@ class Zend_Log_Formatter_Simple implements Zend_Log_Formatter_Interface
}
if (! is_string($format)) {
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Format must be a string');
}
diff --git a/libs/Zend/Log/Formatter/Xml.php b/libs/Zend/Log/Formatter/Xml.php
index ce0edb1301..ebf3c29e97 100644
--- a/libs/Zend/Log/Formatter/Xml.php
+++ b/libs/Zend/Log/Formatter/Xml.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Log
* @subpackage Formatter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Xml.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Xml.php 20104 2010-01-06 21:26:01Z matthew $
*/
/** Zend_Log_Formatter_Interface */
-require_once 'Zend/Log/Formatter/Interface.php';
+// require_once 'Zend/Log/Formatter/Interface.php';
/**
* @category Zend
* @package Zend_Log
* @subpackage Formatter
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Xml.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Xml.php 20104 2010-01-06 21:26:01Z matthew $
*/
class Zend_Log_Formatter_Xml implements Zend_Log_Formatter_Interface
{
@@ -44,14 +44,44 @@ class Zend_Log_Formatter_Xml implements Zend_Log_Formatter_Interface
protected $_elementMap;
/**
+ * @var string Encoding to use in XML
+ */
+ protected $_encoding;
+
+ /**
* Class constructor
*
+ * @param string $rootElement Name of root element
* @param array $elementMap
+ * @param string $encoding Encoding to use (defaults to UTF-8)
*/
- public function __construct($rootElement = 'logEntry', $elementMap = null)
+ public function __construct($rootElement = 'logEntry', $elementMap = null, $encoding = 'UTF-8')
{
$this->_rootElement = $rootElement;
$this->_elementMap = $elementMap;
+ $this->setEncoding($encoding);
+ }
+
+ /**
+ * Get encoding
+ *
+ * @return string
+ */
+ public function getEncoding()
+ {
+ return $this->_encoding;
+ }
+
+ /**
+ * Set encoding
+ *
+ * @param string $value
+ * @return Zend_Log_Formatter_Xml
+ */
+ public function setEncoding($value)
+ {
+ $this->_encoding = (string) $value;
+ return $this;
}
/**
@@ -71,12 +101,13 @@ class Zend_Log_Formatter_Xml implements Zend_Log_Formatter_Interface
}
}
- $dom = new DOMDocument();
+ $enc = $this->getEncoding();
+ $dom = new DOMDocument('1.0', $enc);
$elt = $dom->appendChild(new DOMElement($this->_rootElement));
foreach ($dataToInsert as $key => $value) {
if($key == "message") {
- $value = htmlspecialchars($value);
+ $value = htmlspecialchars($value, ENT_COMPAT, $enc);
}
$elt->appendChild(new DOMElement($key, $value));
}
diff --git a/libs/Zend/Log/Writer/Abstract.php b/libs/Zend/Log/Writer/Abstract.php
index 3e3be2d6cd..80b939db18 100644
--- a/libs/Zend/Log/Writer/Abstract.php
+++ b/libs/Zend/Log/Writer/Abstract.php
@@ -15,23 +15,23 @@
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Log_Filter_Priority */
-require_once 'Zend/Log/Filter/Priority.php';
+// require_once 'Zend/Log/Filter/Priority.php';
/**
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
-abstract class Zend_Log_Writer_Abstract
+abstract class Zend_Log_Writer_Abstract implements Zend_Log_FactoryInterface
{
/**
* @var array of Zend_Log_Filter_Interface
@@ -104,4 +104,26 @@ abstract class Zend_Log_Writer_Abstract
*/
abstract protected function _write($event);
-} \ No newline at end of file
+ /**
+ * Validate and optionally convert the config to array
+ *
+ * @param array|Zend_Config $config Zend_Config or Array
+ * @return array
+ * @throws Zend_Log_Exception
+ */
+ static protected function _parseConfig($config)
+ {
+ if ($config instanceof Zend_Config) {
+ $config = $config->toArray();
+ }
+
+ if (!is_array($config)) {
+ // require_once 'Zend/Log/Exception.php';
+ throw new Zend_Log_Exception(
+ 'Configuration must be an array or instance of Zend_Config'
+ );
+ }
+
+ return $config;
+ }
+}
diff --git a/libs/Zend/Log/Writer/Db.php b/libs/Zend/Log/Writer/Db.php
index 2130efe28e..6f77a12cb7 100644
--- a/libs/Zend/Log/Writer/Db.php
+++ b/libs/Zend/Log/Writer/Db.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Db.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Db.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Log_Writer_Abstract */
-require_once 'Zend/Log/Writer/Abstract.php';
+// require_once 'Zend/Log/Writer/Abstract.php';
/**
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Db.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Db.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
class Zend_Log_Writer_Db extends Zend_Log_Writer_Abstract
{
@@ -67,11 +67,38 @@ class Zend_Log_Writer_Db extends Zend_Log_Writer_Abstract
}
/**
+ * Create a new instance of Zend_Log_Writer_Db
+ *
+ * @param array|Zend_Config $config
+ * @return Zend_Log_Writer_Db
+ * @throws Zend_Log_Exception
+ */
+ static public function factory($config)
+ {
+ $config = self::_parseConfig($config);
+ $config = array_merge(array(
+ 'db' => null,
+ 'table' => null,
+ 'columnMap' => null,
+ ), $config);
+
+ if (isset($config['columnmap'])) {
+ $config['columnMap'] = $config['columnmap'];
+ }
+
+ return new self(
+ $config['db'],
+ $config['table'],
+ $config['columnMap']
+ );
+ }
+
+ /**
* Formatting is not possible on this writer
*/
public function setFormatter($formatter)
{
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception(get_class() . ' does not support formatting');
}
@@ -94,7 +121,7 @@ class Zend_Log_Writer_Db extends Zend_Log_Writer_Abstract
protected function _write($event)
{
if ($this->_db === null) {
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Database adapter is null');
}
@@ -109,5 +136,4 @@ class Zend_Log_Writer_Db extends Zend_Log_Writer_Abstract
$this->_db->insert($this->_table, $dataToInsert);
}
-
}
diff --git a/libs/Zend/Log/Writer/Firebug.php b/libs/Zend/Log/Writer/Firebug.php
index 49eeae9a2d..585f6a3dc1 100644
--- a/libs/Zend/Log/Writer/Firebug.php
+++ b/libs/Zend/Log/Writer/Firebug.php
@@ -15,30 +15,30 @@
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Firebug.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Firebug.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Log */
-require_once 'Zend/Log.php';
+// require_once 'Zend/Log.php';
/** Zend_Log_Writer_Abstract */
-require_once 'Zend/Log/Writer/Abstract.php';
+// require_once 'Zend/Log/Writer/Abstract.php';
/** Zend_Log_Formatter_Firebug */
-require_once 'Zend/Log/Formatter/Firebug.php';
+// require_once 'Zend/Log/Formatter/Firebug.php';
/** Zend_Wildfire_Plugin_FirePhp */
-require_once 'Zend/Wildfire/Plugin/FirePhp.php';
+// require_once 'Zend/Wildfire/Plugin/FirePhp.php';
/**
* Writes log messages to the Firebug Console via FirePHP.
- *
+ *
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Log_Writer_Firebug extends Zend_Log_Writer_Abstract
@@ -56,35 +56,47 @@ class Zend_Log_Writer_Firebug extends Zend_Log_Writer_Abstract
Zend_Log::NOTICE => Zend_Wildfire_Plugin_FirePhp::INFO,
Zend_Log::INFO => Zend_Wildfire_Plugin_FirePhp::INFO,
Zend_Log::DEBUG => Zend_Wildfire_Plugin_FirePhp::LOG);
-
+
/**
* The default logging style for un-mapped priorities
* @var string
- */
+ */
protected $_defaultPriorityStyle = Zend_Wildfire_Plugin_FirePhp::LOG;
-
+
/**
* Flag indicating whether the log writer is enabled
* @var boolean
*/
protected $_enabled = true;
-
+
/**
* Class constructor
*/
public function __construct()
{
- if (php_sapi_name()=='cli') {
+ if (php_sapi_name() == 'cli') {
$this->setEnabled(false);
}
-
+
$this->_formatter = new Zend_Log_Formatter_Firebug();
}
-
+
/**
- * Enable or disable the log writer.
+ * Create a new instance of Zend_Log_Writer_Firebug
*
- * @param boolean $enabled Set to TRUE to enable the log writer
+ * @param array|Zend_Config $config
+ * @return Zend_Log_Writer_Firebug
+ * @throws Zend_Log_Exception
+ */
+ static public function factory($config)
+ {
+ return new self();
+ }
+
+ /**
+ * Enable or disable the log writer.
+ *
+ * @param boolean $enabled Set to TRUE to enable the log writer
* @return boolean The previous value.
*/
public function setEnabled($enabled)
@@ -93,43 +105,43 @@ class Zend_Log_Writer_Firebug extends Zend_Log_Writer_Abstract
$this->_enabled = $enabled;
return $previous;
}
-
+
/**
* Determine if the log writer is enabled.
- *
+ *
* @return boolean Returns TRUE if the log writer is enabled.
*/
public function getEnabled()
{
return $this->_enabled;
}
-
+
/**
* Set the default display style for user-defined priorities
- *
+ *
* @param string $style The default log display style
* @return string Returns previous default log display style
- */
+ */
public function setDefaultPriorityStyle($style)
{
$previous = $this->_defaultPriorityStyle;
$this->_defaultPriorityStyle = $style;
return $previous;
}
-
+
/**
* Get the default display style for user-defined priorities
- *
+ *
* @return string Returns the default log display style
- */
+ */
public function getDefaultPriorityStyle()
{
return $this->_defaultPriorityStyle;
}
-
+
/**
* Set a display style for a logging priority
- *
+ *
* @param int $priority The logging priority
* @param string $style The logging display style
* @return string|boolean The previous logging display style if defined or TRUE otherwise
@@ -146,7 +158,7 @@ class Zend_Log_Writer_Firebug extends Zend_Log_Writer_Abstract
/**
* Get a display style for a logging priority
- *
+ *
* @param int $priority The logging priority
* @return string|boolean The logging display style if defined or FALSE otherwise
*/
@@ -169,15 +181,15 @@ class Zend_Log_Writer_Firebug extends Zend_Log_Writer_Abstract
if (!$this->getEnabled()) {
return;
}
-
+
if (array_key_exists($event['priority'],$this->_priorityStyles)) {
$type = $this->_priorityStyles[$event['priority']];
} else {
$type = $this->_defaultPriorityStyle;
}
-
+
$message = $this->_formatter->format($event);
-
+
$label = isset($event['firebugLabel'])?$event['firebugLabel']:null;
Zend_Wildfire_Plugin_FirePhp::getInstance()->send($message,
diff --git a/libs/Zend/Log/Writer/Mail.php b/libs/Zend/Log/Writer/Mail.php
index 068bd33dc1..70f57b8616 100644
--- a/libs/Zend/Log/Writer/Mail.php
+++ b/libs/Zend/Log/Writer/Mail.php
@@ -15,19 +15,19 @@
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mail.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Mail.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Log_Writer_Abstract */
-require_once 'Zend/Log/Writer/Abstract.php';
+// require_once 'Zend/Log/Writer/Abstract.php';
/** Zend_Log_Exception */
-require_once 'Zend/Log/Exception.php';
+// require_once 'Zend/Log/Exception.php';
/** Zend_Log_Formatter_Simple*/
-require_once 'Zend/Log/Formatter/Simple.php';
+// require_once 'Zend/Log/Formatter/Simple.php';
/**
* Class used for writing log messages to email via Zend_Mail.
@@ -39,9 +39,9 @@ require_once 'Zend/Log/Formatter/Simple.php';
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mail.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Mail.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
class Zend_Log_Writer_Mail extends Zend_Log_Writer_Abstract
{
@@ -117,6 +117,18 @@ class Zend_Log_Writer_Mail extends Zend_Log_Writer_Abstract
$this->_layout = $layout;
$this->_formatter = new Zend_Log_Formatter_Simple();
}
+
+ /**
+ * Create a new instance of Zend_Log_Writer_Mail
+ *
+ * @param array|Zend_Config $config
+ * @return Zend_Log_Writer_Mail
+ * @throws Zend_Log_Exception
+ */
+ static public function factory($config)
+ {
+ throw new Zend_Exception('Zend_Log_Writer_Mail does not currently implement a factory');
+ }
/**
* Places event line into array of lines to be used as message body.
diff --git a/libs/Zend/Log/Writer/Mock.php b/libs/Zend/Log/Writer/Mock.php
index 2a593c0d9e..1e14a2f00e 100644
--- a/libs/Zend/Log/Writer/Mock.php
+++ b/libs/Zend/Log/Writer/Mock.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mock.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Mock.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Log_Writer_Abstract */
-require_once 'Zend/Log/Writer/Abstract.php';
+// require_once 'Zend/Log/Writer/Abstract.php';
/**
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mock.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Mock.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
class Zend_Log_Writer_Mock extends Zend_Log_Writer_Abstract
{
@@ -63,4 +63,16 @@ class Zend_Log_Writer_Mock extends Zend_Log_Writer_Abstract
{
$this->shutdown = true;
}
-} \ No newline at end of file
+
+ /**
+ * Create a new instance of Zend_Log_Writer_Mock
+ *
+ * @param array|Zend_Config $config
+ * @return Zend_Log_Writer_Mock
+ * @throws Zend_Log_Exception
+ */
+ static public function factory($config)
+ {
+ return new self();
+ }
+}
diff --git a/libs/Zend/Log/Writer/Null.php b/libs/Zend/Log/Writer/Null.php
index de791d3a99..f281883fbb 100644
--- a/libs/Zend/Log/Writer/Null.php
+++ b/libs/Zend/Log/Writer/Null.php
@@ -15,21 +15,21 @@
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Null.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Null.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Log_Writer_Abstract */
-require_once 'Zend/Log/Writer/Abstract.php';
+// require_once 'Zend/Log/Writer/Abstract.php';
/**
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Null.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Null.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
class Zend_Log_Writer_Null extends Zend_Log_Writer_Abstract
{
@@ -42,5 +42,16 @@ class Zend_Log_Writer_Null extends Zend_Log_Writer_Abstract
protected function _write($event)
{
}
-
-} \ No newline at end of file
+
+ /**
+ * Create a new instance of Zend_Log_Writer_Null
+ *
+ * @param array|Zend_Config $config
+ * @return Zend_Log_Writer_Null
+ * @throws Zend_Log_Exception
+ */
+ static public function factory($config)
+ {
+ return new self();
+ }
+}
diff --git a/libs/Zend/Log/Writer/Stream.php b/libs/Zend/Log/Writer/Stream.php
index 99b050ad6b..b722dbb4bd 100644
--- a/libs/Zend/Log/Writer/Stream.php
+++ b/libs/Zend/Log/Writer/Stream.php
@@ -15,24 +15,24 @@
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Stream.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Stream.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Log_Writer_Abstract */
-require_once 'Zend/Log/Writer/Abstract.php';
+// require_once 'Zend/Log/Writer/Abstract.php';
/** Zend_Log_Formatter_Simple */
-require_once 'Zend/Log/Formatter/Simple.php';
+// require_once 'Zend/Log/Formatter/Simple.php';
/**
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Stream.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Stream.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
class Zend_Log_Writer_Stream extends Zend_Log_Writer_Abstract
{
@@ -48,23 +48,32 @@ class Zend_Log_Writer_Stream extends Zend_Log_Writer_Abstract
* @param streamOrUrl Stream or URL to open as a stream
* @param mode Mode, only applicable if a URL is given
*/
- public function __construct($streamOrUrl, $mode = 'a')
+ public function __construct($streamOrUrl, $mode = NULL)
{
+ // Setting the default
+ if ($mode === NULL) {
+ $mode = 'a';
+ }
+
if (is_resource($streamOrUrl)) {
if (get_resource_type($streamOrUrl) != 'stream') {
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Resource is not a stream');
}
if ($mode != 'a') {
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception('Mode cannot be changed on existing streams');
}
$this->_stream = $streamOrUrl;
} else {
+ if (is_array($streamOrUrl) && isset($streamOrUrl['stream'])) {
+ $streamOrUrl = $streamOrUrl['stream'];
+ }
+
if (! $this->_stream = @fopen($streamOrUrl, $mode, false)) {
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
$msg = "\"$streamOrUrl\" cannot be opened with mode \"$mode\"";
throw new Zend_Log_Exception($msg);
}
@@ -72,7 +81,30 @@ class Zend_Log_Writer_Stream extends Zend_Log_Writer_Abstract
$this->_formatter = new Zend_Log_Formatter_Simple();
}
+
+ /**
+ * Create a new instance of Zend_Log_Writer_Mock
+ *
+ * @param array|Zend_Config $config
+ * @return Zend_Log_Writer_Mock
+ * @throws Zend_Log_Exception
+ */
+ static public function factory($config)
+ {
+ $config = self::_parseConfig($config);
+ $config = array_merge(array(
+ 'stream' => null,
+ 'mode' => null,
+ ), $config);
+ $streamOrUrl = isset($config['url']) ? $config['url'] : $config['stream'];
+
+ return new self(
+ $streamOrUrl,
+ $config['mode']
+ );
+ }
+
/**
* Close the stream resource.
*
@@ -96,9 +128,8 @@ class Zend_Log_Writer_Stream extends Zend_Log_Writer_Abstract
$line = $this->_formatter->format($event);
if (false === @fwrite($this->_stream, $line)) {
- require_once 'Zend/Log/Exception.php';
+ // require_once 'Zend/Log/Exception.php';
throw new Zend_Log_Exception("Unable to write to stream");
}
}
-
}
diff --git a/libs/Zend/Log/Writer/Syslog.php b/libs/Zend/Log/Writer/Syslog.php
index 3409ae56dc..310bcf54ec 100644
--- a/libs/Zend/Log/Writer/Syslog.php
+++ b/libs/Zend/Log/Writer/Syslog.php
@@ -15,13 +15,13 @@
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Syslog.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Syslog.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/** Zend_Log_Writer_Abstract */
-require_once 'Zend/Log/Writer/Abstract.php';
+// require_once 'Zend/Log/Writer/Abstract.php';
/**
* Writes log messages to syslog
@@ -29,7 +29,7 @@ require_once 'Zend/Log/Writer/Abstract.php';
* @category Zend
* @package Zend_Log
* @subpackage Writer
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Log_Writer_Syslog extends Zend_Log_Writer_Abstract
@@ -95,6 +95,18 @@ class Zend_Log_Writer_Syslog extends Zend_Log_Writer_Abstract
}
$this->_initializeSyslog();
}
+
+ /**
+ * Create a new instance of Zend_Log_Writer_Syslog
+ *
+ * @param array|Zend_Config $config
+ * @return Zend_Log_Writer_Syslog
+ * @throws Zend_Log_Exception
+ */
+ static public function factory($config)
+ {
+ return new self(self::_parseConfig($config));
+ }
/**
* Initialize syslog / set application name and facility
diff --git a/libs/Zend/Log/Writer/ZendMonitor.php b/libs/Zend/Log/Writer/ZendMonitor.php
new file mode 100644
index 0000000000..59a648fa8b
--- /dev/null
+++ b/libs/Zend/Log/Writer/ZendMonitor.php
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Log
+ * @subpackage Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+
+/** Zend_Log_Writer_Abstract */
+// require_once 'Zend/Log/Writer/Abstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Log
+ * @subpackage Writer
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id$
+ */
+class Zend_Log_Writer_ZendMonitor extends Zend_Log_Writer_Abstract
+{
+ /**
+ * Is Zend Monitor enabled?
+ * @var bool
+ */
+ protected $_isEnabled = true;
+
+ /**
+ * @throws Zend_Log_Exception if Zend Monitor extension not present
+ */
+ public function __construct()
+ {
+ if (!function_exists('monitor_custom_event')) {
+ $this->_isEnabled = false;
+ }
+ }
+
+ /**
+ * Create a new instance of Zend_Log_Writer_ZendMonitor
+ *
+ * @param array|Zend_Config $config
+ * @return Zend_Log_Writer_Syslog
+ * @throws Zend_Log_Exception
+ */
+ static public function factory($config)
+ {
+ return new self();
+ }
+
+ /**
+ * Is logging to this writer enabled?
+ *
+ * If the Zend Monitor extension is not enabled, this log writer will
+ * fail silently. You can query this method to determine if the log
+ * writer is enabled.
+ *
+ * @return bool
+ */
+ public function isEnabled()
+ {
+ return $this->_isEnabled;
+ }
+
+ /**
+ * Log a message to this writer.
+ *
+ * @param array $event log data event
+ * @return void
+ */
+ public function write($event)
+ {
+ if (!$this->isEnabled()) {
+ return;
+ }
+
+ parent::write($event);
+ }
+
+ /**
+ * Write a message to the log.
+ *
+ * @param array $event log data event
+ * @return void
+ */
+ protected function _write($event)
+ {
+ $priority = $event['priority'];
+ $message = $event['message'];
+ unset($event['priority'], $event['message']);
+
+ if (!empty($event)) {
+ monitor_custom_event($priority, $message, $event);
+ } else {
+ monitor_custom_event($priority, $message);
+ }
+ }
+}
diff --git a/libs/Zend/Mail.php b/libs/Zend/Mail.php
index ca3641ea81..81d1b5051d 100644
--- a/libs/Zend/Mail.php
+++ b/libs/Zend/Mail.php
@@ -14,31 +14,31 @@
*
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mail.php 16207 2009-06-21 19:17:51Z thomas $
+ * @version $Id: Mail.php 20783 2010-01-31 08:06:30Z yoshida@zend.co.jp $
*/
/**
* @see Zend_Mail_Transport_Abstract
*/
-require_once 'Zend/Mail/Transport/Abstract.php';
+// require_once 'Zend/Mail/Transport/Abstract.php';
/**
* @see Zend_Mime
*/
-require_once 'Zend/Mime.php';
+// require_once 'Zend/Mime.php';
/**
* @see Zend_Mime_Message
*/
-require_once 'Zend/Mime/Message.php';
+// require_once 'Zend/Mime/Message.php';
/**
* @see Zend_Mime_Part
*/
-require_once 'Zend/Mime/Part.php';
+// require_once 'Zend/Mime/Part.php';
/**
@@ -46,7 +46,7 @@ require_once 'Zend/Mime/Part.php';
*
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail extends Zend_Mime_Message
@@ -62,6 +62,18 @@ class Zend_Mail extends Zend_Mime_Message
protected static $_defaultTransport = null;
/**
+ * @var array
+ * @static
+ */
+ protected static $_defaultFrom;
+
+ /**
+ * @var array
+ * @static
+ */
+ protected static $_defaultReplyTo;
+
+ /**
* Mail character set
* @var string
*/
@@ -98,6 +110,12 @@ class Zend_Mail extends Zend_Mime_Message
protected $_recipients = array();
/**
+ * Reply-To header
+ * @var string
+ */
+ protected $_replyTo = null;
+
+ /**
* Return-Path header
* @var string
*/
@@ -168,6 +186,26 @@ class Zend_Mail extends Zend_Mime_Message
}
/**
+ * Gets the default mail transport for all following uses of
+ * unittests
+ *
+ * @todo Allow passing a string to indicate the transport to load
+ * @todo Allow passing in optional options for the transport to load
+ */
+ public static function getDefaultTransport()
+ {
+ return self::$_defaultTransport;
+ }
+
+ /**
+ * Clear the default transport property
+ */
+ public static function clearDefaultTransport()
+ {
+ self::$_defaultTransport = null;
+ }
+
+ /**
* Public constructor
*
* @param string $charset
@@ -207,7 +245,7 @@ class Zend_Mail extends Zend_Mime_Message
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('Invalid content type "' . $type . '"');
}
@@ -301,7 +339,7 @@ class Zend_Mail extends Zend_Mime_Message
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('Invalid encoding "' . $encoding . '"');
}
$this->_headerEncoding = $encoding;
@@ -458,7 +496,7 @@ class Zend_Mail extends Zend_Mime_Message
*/
protected function _encodeHeader($value)
{
- if (Zend_Mime::isPrintable($value) === false) {
+ if (Zend_Mime::isPrintable($value) === false) {
if ($this->getHeaderEncoding() === Zend_Mime::ENCODING_QUOTEDPRINTABLE) {
$value = Zend_Mime::encodeQuotedPrintableHeader($value, $this->getCharset(), Zend_Mime::LINELENGTH, Zend_Mime::LINEEND);
} else {
@@ -522,41 +560,62 @@ class Zend_Mail extends Zend_Mime_Message
}
/**
- * Adds To-header and recipient
+ * Adds To-header and recipient, $email can be an array, or a single string address
*
- * @param string $email
+ * @param string|array $email
* @param string $name
* @return Zend_Mail Provides fluent interface
*/
public function addTo($email, $name='')
{
- $this->_addRecipientAndHeader('To', $email, $name);
- $this->_to[] = $email;
+ if (!is_array($email)) {
+ $email = array($name => $email);
+ }
+
+ foreach ($email as $n => $recipient) {
+ $this->_addRecipientAndHeader('To', $recipient, is_int($n) ? '' : $n);
+ $this->_to[] = $recipient;
+ }
+
return $this;
}
/**
- * Adds Cc-header and recipient
+ * Adds Cc-header and recipient, $email can be an array, or a single string address
*
- * @param string $email
+ * @param string|array $email
* @param string $name
* @return Zend_Mail Provides fluent interface
*/
public function addCc($email, $name='')
{
- $this->_addRecipientAndHeader('Cc', $email, $name);
+ if (!is_array($email)) {
+ $email = array($name => $email);
+ }
+
+ foreach ($email as $n => $recipient) {
+ $this->_addRecipientAndHeader('Cc', $recipient, is_int($n) ? '' : $n);
+ }
+
return $this;
}
/**
- * Adds Bcc recipient
+ * Adds Bcc recipient, $email can be an array, or a single string address
*
- * @param string $email
+ * @param string|array $email
* @return Zend_Mail Provides fluent interface
*/
public function addBcc($email)
{
- $this->_addRecipientAndHeader('Bcc', $email, '');
+ if (!is_array($email)) {
+ $email = array($email);
+ }
+
+ foreach ($email as $recipient) {
+ $this->_addRecipientAndHeader('Bcc', $recipient, '');
+ }
+
return $this;
}
@@ -597,18 +656,19 @@ class Zend_Mail extends Zend_Mime_Message
*/
public function setFrom($email, $name = null)
{
- if ($this->_from === null) {
- $email = $this->_filterEmail($email);
- $name = $this->_filterName($name);
- $this->_from = $email;
- $this->_storeHeader('From', $this->_formatAddress($email, $name), true);
- } else {
+ if (null !== $this->_from) {
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('From Header set twice');
}
+
+ $email = $this->_filterEmail($email);
+ $name = $this->_filterName($name);
+ $this->_from = $email;
+ $this->_storeHeader('From', $this->_formatAddress($email, $name), true);
+
return $this;
}
@@ -618,10 +678,23 @@ class Zend_Mail extends Zend_Mime_Message
* @param string $email
* @param string $name
* @return Zend_Mail
+ * @throws Zend_Mail_Exception if called more than one time
*/
- public function setReplyTo($email, $name=null)
+ public function setReplyTo($email, $name = null)
{
- $this->_addRecipientAndHeader('Reply-To', $email, $name);
+ if (null !== $this->_replyTo) {
+ /**
+ * @see Zend_Mail_Exception
+ */
+ // require_once 'Zend/Mail/Exception.php';
+ throw new Zend_Mail_Exception('Reply-To Header set twice');
+ }
+
+ $email = $this->_filterEmail($email);
+ $name = $this->_filterName($name);
+ $this->_replyTo = $email;
+ $this->_storeHeader('Reply-To', $this->_formatAddress($email, $name), true);
+
return $this;
}
@@ -636,6 +709,16 @@ class Zend_Mail extends Zend_Mime_Message
}
/**
+ * Returns the current Reply-To address of the message
+ *
+ * @return string|null Reply-To address, null when not set
+ */
+ public function getReplyTo()
+ {
+ return $this->_replyTo;
+ }
+
+ /**
* Clears the sender from the mail
*
* @return Zend_Mail Provides fluent interface
@@ -648,6 +731,119 @@ class Zend_Mail extends Zend_Mime_Message
return $this;
}
+ /**
+ * Clears the current Reply-To address from the message
+ *
+ * @return Zend_Mail Provides fluent interface
+ */
+ public function clearReplyTo()
+ {
+ $this->_replyTo = null;
+ $this->_clearHeader('Reply-To');
+
+ return $this;
+ }
+
+ /**
+ * Sets Default From-email and name of the message
+ *
+ * @param string $email
+ * @param string Optional $name
+ * @return void
+ */
+ public static function setDefaultFrom($email, $name = null)
+ {
+ self::$_defaultFrom = array('email' => $email, 'name' => $name);
+ }
+
+ /**
+ * Returns the default sender of the mail
+ *
+ * @return null|array Null if none was set.
+ */
+ public static function getDefaultFrom()
+ {
+ return self::$_defaultFrom;
+ }
+
+ /**
+ * Clears the default sender from the mail
+ *
+ * @return void
+ */
+ public static function clearDefaultFrom()
+ {
+ self::$_defaultFrom = null;
+ }
+
+ /**
+ * Sets From-name and -email based on the defaults
+ *
+ * @return Zend_Mail Provides fluent interface
+ */
+ public function setFromToDefaultFrom() {
+ $from = self::getDefaultFrom();
+ if($from === null) {
+ // require_once 'Zend/Mail/Exception.php';
+ throw new Zend_Mail_Exception(
+ 'No default From Address set to use');
+ }
+
+ $this->setFrom($from['email'], $from['name']);
+
+ return $this;
+ }
+
+ /**
+ * Sets Default ReplyTo-address and -name of the message
+ *
+ * @param string $email
+ * @param string Optional $name
+ * @return void
+ */
+ public static function setDefaultReplyTo($email, $name = null)
+ {
+ self::$_defaultReplyTo = array('email' => $email, 'name' => $name);
+ }
+
+ /**
+ * Returns the default Reply-To Address and Name of the mail
+ *
+ * @return null|array Null if none was set.
+ */
+ public static function getDefaultReplyTo()
+ {
+ return self::$_defaultReplyTo;
+ }
+
+ /**
+ * Clears the default ReplyTo-address and -name from the mail
+ *
+ * @return void
+ */
+ public static function clearDefaultReplyTo()
+ {
+ self::$_defaultReplyTo = null;
+ }
+
+ /**
+ * Sets ReplyTo-name and -email based on the defaults
+ *
+ * @return Zend_Mail Provides fluent interface
+ */
+ public function setReplyToFromDefault() {
+ $replyTo = self::getDefaultReplyTo();
+ if($replyTo === null) {
+ // require_once 'Zend/Mail/Exception.php';
+ throw new Zend_Mail_Exception(
+ 'No default Reply-To Address set to use');
+ }
+
+ $this->setReplyTo($replyTo['email'], $replyTo['name']);
+
+ return $this;
+ }
+
/**
* Sets the Return-Path header of the message
*
@@ -665,7 +861,7 @@ class Zend_Mail extends Zend_Mime_Message
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('Return-Path Header set twice');
}
return $this;
@@ -717,7 +913,7 @@ class Zend_Mail extends Zend_Mime_Message
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('Subject set twice');
}
return $this;
@@ -749,9 +945,9 @@ class Zend_Mail extends Zend_Mime_Message
/**
* Sets Date-header
*
- * @param string $date
+ * @param timestamp|string|Zend_Date $date
* @return Zend_Mail Provides fluent interface
- * @throws Zend_Mail_Exception if called subsequent times
+ * @throws Zend_Mail_Exception if called subsequent times or wrong date format.
*/
public function setDate($date = null)
{
@@ -763,22 +959,22 @@ class Zend_Mail extends Zend_Mime_Message
} else if (is_string($date)) {
$date = strtotime($date);
if ($date === false || $date < 0) {
- /**
- * @see Zend_Mail_Exception
- */
- require_once 'Zend/Mail/Exception.php';
- throw new Zend_Mail_Exception('String representations of Date Header must be ' .
+ /**
+ * @see Zend_Mail_Exception
+ */
+ // require_once 'Zend/Mail/Exception.php';
+ throw new Zend_Mail_Exception('String representations of Date Header must be ' .
'strtotime()-compatible');
}
$date = date('r', $date);
} else if ($date instanceof Zend_Date) {
$date = $date->get(Zend_Date::RFC_2822);
} else {
- /**
- * @see Zend_Mail_Exception
- */
- require_once 'Zend/Mail/Exception.php';
- throw new Zend_Mail_Exception(__METHOD__ . ' only accepts UNIX timestamps, Zend_Date objects, ' .
+ /**
+ * @see Zend_Mail_Exception
+ */
+ // require_once 'Zend/Mail/Exception.php';
+ throw new Zend_Mail_Exception(__METHOD__ . ' only accepts UNIX timestamps, Zend_Date objects, ' .
' and strtotime()-compatible strings');
}
$this->_date = $date;
@@ -787,8 +983,8 @@ class Zend_Mail extends Zend_Mime_Message
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
- throw new Zend_Mail_Exception('Date Header set twice');
+ // require_once 'Zend/Mail/Exception.php';
+ throw new Zend_Mail_Exception('Date Header set twice');
}
return $this;
}
@@ -823,27 +1019,27 @@ class Zend_Mail extends Zend_Mime_Message
* true :Auto
* false :No set
* null :No set
- * string:Sets string
+ * string:Sets given string (Angle brackets is not necessary)
* @return Zend_Mail Provides fluent interface
* @throws Zend_Mail_Exception
*/
public function setMessageId($id = true)
{
- if ($id === null || $id === false) {
- return $this;
- } elseif ($id === true) {
+ if ($id === null || $id === false) {
+ return $this;
+ } elseif ($id === true) {
$id = $this->createMessageId();
- }
+ }
if ($this->_messageId === null) {
- $id = $this->_filterOther($id);
+ $id = $this->_filterOther($id);
$this->_messageId = $id;
- $this->_storeHeader('Message-Id', $this->_messageId);
+ $this->_storeHeader('Message-Id', '<' . $this->_messageId . '>');
} else {
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('Message-ID set twice');
}
@@ -884,25 +1080,25 @@ class Zend_Mail extends Zend_Mime_Message
$time = time();
if ($this->_from !== null) {
- $user = $this->_from;
+ $user = $this->_from;
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
- $user = $_SERVER['REMOTE_ADDR'];
+ $user = $_SERVER['REMOTE_ADDR'];
} else {
- $user = getmypid();
+ $user = getmypid();
}
- $rand = mt_rand();
+ $rand = mt_rand();
- if ($this->_recipients !== array()) {
+ if ($this->_recipients !== array()) {
$recipient = array_rand($this->_recipients);
- } else {
- $recipient = 'unknown';
- }
+ } else {
+ $recipient = 'unknown';
+ }
- if (isset($_SERVER["SERVER_NAME"])) {
+ if (isset($_SERVER["SERVER_NAME"])) {
$hostName = $_SERVER["SERVER_NAME"];
} else {
- $hostName = php_uname('n');
+ $hostName = php_uname('n');
}
return sha1($time . $user . $rand . $recipient) . '@' . $hostName;
@@ -920,13 +1116,14 @@ class Zend_Mail extends Zend_Mime_Message
public function addHeader($name, $value, $append = false)
{
$prohibit = array('to', 'cc', 'bcc', 'from', 'subject',
- 'return-path', 'date', 'message-id',
+ 'reply-to', 'return-path',
+ 'date', 'message-id',
);
if (in_array(strtolower($name), $prohibit)) {
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('Cannot set standard header from addHeader()');
}
@@ -959,7 +1156,7 @@ class Zend_Mail extends Zend_Mime_Message
{
if ($transport === null) {
if (! self::$_defaultTransport instanceof Zend_Mail_Transport_Abstract) {
- require_once 'Zend/Mail/Transport/Sendmail.php';
+ // require_once 'Zend/Mail/Transport/Sendmail.php';
$transport = new Zend_Mail_Transport_Sendmail();
} else {
$transport = self::$_defaultTransport;
@@ -970,6 +1167,14 @@ class Zend_Mail extends Zend_Mime_Message
$this->setDate();
}
+ if(null === $this->_from && null !== self::getDefaultFrom()) {
+ $this->setFromToDefaultFrom();
+ }
+
+ if(null === $this->_replyTo && null !== self::getDefaultReplyTo()) {
+ $this->setReplyToFromDefault();
+ }
+
$transport->send($this);
return $this;
@@ -983,14 +1188,14 @@ class Zend_Mail extends Zend_Mime_Message
*/
protected function _filterEmail($email)
{
- $rule = array("\r" => '',
- "\n" => '',
- "\t" => '',
+ $rule = array("\r" => '',
+ "\n" => '',
+ "\t" => '',
'"' => '',
- ',' => '',
+ ',' => '',
'<' => '',
'>' => '',
- );
+ );
return strtr($email, $rule);
}
@@ -1003,13 +1208,13 @@ class Zend_Mail extends Zend_Mime_Message
*/
protected function _filterName($name)
{
- $rule = array("\r" => '',
+ $rule = array("\r" => '',
"\n" => '',
"\t" => '',
'"' => "'",
'<' => '[',
- '>' => ']',
- );
+ '>' => ']',
+ );
return trim(strtr($name, $rule));
}
@@ -1043,7 +1248,8 @@ class Zend_Mail extends Zend_Mime_Message
return $email;
} else {
$encodedName = $this->_encodeHeader($name);
- if ($encodedName === $name && strpos($name, ',') !== false) {
+ if ($encodedName === $name &&
+ ((strpos($name, '@') !== false) || (strpos($name, ',') !== false))) {
$format = '"%s" <%s>';
} else {
$format = '%s <%s>';
diff --git a/libs/Zend/Mail/Exception.php b/libs/Zend/Mail/Exception.php
index 864d1ca932..c912769ee4 100644
--- a/libs/Zend/Mail/Exception.php
+++ b/libs/Zend/Mail/Exception.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Exception
*/
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Exception extends Zend_Exception
diff --git a/libs/Zend/Mail/Message.php b/libs/Zend/Mail/Message.php
index 5b35ab2f67..bff51340d2 100644
--- a/libs/Zend/Mail/Message.php
+++ b/libs/Zend/Mail/Message.php
@@ -14,26 +14,26 @@
*
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Message.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Message.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Mail_Part
*/
-require_once 'Zend/Mail/Part.php';
+// require_once 'Zend/Mail/Part.php';
/**
* Zend_Mail_Message_Interface
*/
-require_once 'Zend/Mail/Message/Interface.php';
+// require_once 'Zend/Mail/Message/Interface.php';
/**
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Message extends Zend_Mail_Part implements Zend_Mail_Message_Interface
@@ -63,7 +63,7 @@ class Zend_Mail_Message extends Zend_Mail_Part implements Zend_Mail_Message_Inte
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('could not open file');
}
} else {
diff --git a/libs/Zend/Mail/Message/File.php b/libs/Zend/Mail/Message/File.php
index 6d621ae39c..7857c743d6 100644
--- a/libs/Zend/Mail/Message/File.php
+++ b/libs/Zend/Mail/Message/File.php
@@ -14,26 +14,26 @@
*
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: File.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: File.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Mail_Part
*/
-require_once 'Zend/Mail/Part/File.php';
+// require_once 'Zend/Mail/Part/File.php';
/**
* Zend_Mail_Message_Interface
*/
-require_once 'Zend/Mail/Message/Interface.php';
+// require_once 'Zend/Mail/Message/Interface.php';
/**
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Message_File extends Zend_Mail_Part_File implements Zend_Mail_Message_Interface
@@ -59,7 +59,7 @@ class Zend_Mail_Message_File extends Zend_Mail_Part_File implements Zend_Mail_Me
// set key and value to the same value for easy lookup
$this->_flags = array_combine($params['flags'], $params['flags']);
}
-
+
parent::__construct($params);
}
diff --git a/libs/Zend/Mail/Message/Interface.php b/libs/Zend/Mail/Message/Interface.php
index a9752a3230..833be6b44a 100644
--- a/libs/Zend/Mail/Message/Interface.php
+++ b/libs/Zend/Mail/Message/Interface.php
@@ -11,13 +11,13 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,7 +25,7 @@
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
diff --git a/libs/Zend/Mail/Part.php b/libs/Zend/Mail/Part.php
index 4541a5acc1..bb7b38e447 100644
--- a/libs/Zend/Mail/Part.php
+++ b/libs/Zend/Mail/Part.php
@@ -14,27 +14,27 @@
*
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Part.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Part.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mime_Decode
*/
-require_once 'Zend/Mime/Decode.php';
+// require_once 'Zend/Mime/Decode.php';
/**
* @see Zend_Mail_Part_Interface
*/
-require_once 'Zend/Mail/Part/Interface.php';
+// require_once 'Zend/Mail/Part/Interface.php';
/**
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Part implements RecursiveIterator, Zend_Mail_Part_Interface
@@ -108,14 +108,14 @@ class Zend_Mail_Part implements RecursiveIterator, Zend_Mail_Part_Interface
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('handler is not a valid mail handler');
}
if (!isset($params['id'])) {
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('need a message id with a handler');
}
@@ -176,7 +176,7 @@ class Zend_Mail_Part implements RecursiveIterator, Zend_Mail_Part_Interface
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('no content');
}
}
@@ -216,7 +216,7 @@ class Zend_Mail_Part implements RecursiveIterator, Zend_Mail_Part_Interface
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('no boundary found in content type to split message');
}
$parts = Zend_Mime_Decode::splitMessageStruct($this->_content, $boundary);
@@ -246,7 +246,7 @@ class Zend_Mail_Part implements RecursiveIterator, Zend_Mail_Part_Interface
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('part not found');
}
@@ -261,7 +261,7 @@ class Zend_Mail_Part implements RecursiveIterator, Zend_Mail_Part_Interface
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('part not found');
}
@@ -343,7 +343,7 @@ class Zend_Mail_Part implements RecursiveIterator, Zend_Mail_Part_Interface
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception("no Header with Name $name or $lowerName found");
}
}
@@ -381,7 +381,7 @@ class Zend_Mail_Part implements RecursiveIterator, Zend_Mail_Part_Interface
return false;
}
}
-
+
/**
* Get a specific field from a header like content type or all fields as array
*
diff --git a/libs/Zend/Mail/Part/File.php b/libs/Zend/Mail/Part/File.php
index efa0538b4d..581195bcc0 100644
--- a/libs/Zend/Mail/Part/File.php
+++ b/libs/Zend/Mail/Part/File.php
@@ -14,27 +14,27 @@
*
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: File.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: File.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mime_Decode
*/
-require_once 'Zend/Mime/Decode.php';
+// require_once 'Zend/Mime/Decode.php';
/**
* @see Zend_Mail_Part
*/
-require_once 'Zend/Mail/Part.php';
+// require_once 'Zend/Mail/Part.php';
/**
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Part_File extends Zend_Mail_Part
@@ -60,10 +60,10 @@ class Zend_Mail_Part_File extends Zend_Mail_Part
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('no file given in params');
}
-
+
if (!is_resource($params['file'])) {
$this->_fh = fopen($params['file'], 'r');
} else {
@@ -73,7 +73,7 @@ class Zend_Mail_Part_File extends Zend_Mail_Part
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('could not open file');
}
if (isset($params['startPos'])) {
@@ -86,7 +86,7 @@ class Zend_Mail_Part_File extends Zend_Mail_Part
}
Zend_Mime_Decode::splitMessage($header, $this->_headers, $null);
-
+
$this->_contentPos[0] = ftell($this->_fh);
if ($endPos !== null) {
$this->_contentPos[1] = $endPos;
@@ -97,16 +97,16 @@ class Zend_Mail_Part_File extends Zend_Mail_Part
if (!$this->isMultipart()) {
return;
}
-
+
$boundary = $this->getHeaderField('content-type', 'boundary');
if (!$boundary) {
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('no boundary found in content type to split message');
}
-
+
$part = array();
$pos = $this->_contentPos[0];
fseek($this->_fh, $pos);
@@ -119,7 +119,7 @@ class Zend_Mail_Part_File extends Zend_Mail_Part
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('error reading file');
}
@@ -141,7 +141,7 @@ class Zend_Mail_Part_File extends Zend_Mail_Part
}
}
$this->_countParts = count($this->_partPos);
-
+
}
@@ -157,7 +157,7 @@ class Zend_Mail_Part_File extends Zend_Mail_Part
{
fseek($this->_fh, $this->_contentPos[0]);
if ($stream !== null) {
- return stream_copy_to_stream($this->_fh, $stream, $this->_contentPos[1] - $this->_contentPos[0]);
+ return stream_copy_to_stream($this->_fh, $stream, $this->_contentPos[1] - $this->_contentPos[0]);
}
$length = $this->_contentPos[1] - $this->_contentPos[0];
return $length < 1 ? '' : fread($this->_fh, $length);
@@ -188,11 +188,11 @@ class Zend_Mail_Part_File extends Zend_Mail_Part
/**
* @see Zend_Mail_Exception
*/
- require_once 'Zend/Mail/Exception.php';
+ // require_once 'Zend/Mail/Exception.php';
throw new Zend_Mail_Exception('part not found');
}
- return new self(array('file' => $this->_fh, 'startPos' => $this->_partPos[$num][0],
+ return new self(array('file' => $this->_fh, 'startPos' => $this->_partPos[$num][0],
'endPos' => $this->_partPos[$num][1]));
}
}
diff --git a/libs/Zend/Mail/Part/Interface.php b/libs/Zend/Mail/Part/Interface.php
index 46cc4b0843..2d8f6f8943 100644
--- a/libs/Zend/Mail/Part/Interface.php
+++ b/libs/Zend/Mail/Part/Interface.php
@@ -11,13 +11,13 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,7 +25,7 @@
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
@@ -95,7 +95,7 @@ interface Zend_Mail_Part_Interface extends RecursiveIterator
* @throws Zend_Mail_Exception
*/
public function getHeader($name, $format = null);
-
+
/**
* Get a specific field from a header like content type or all fields as array
*
diff --git a/libs/Zend/Mail/Protocol/Abstract.php b/libs/Zend/Mail/Protocol/Abstract.php
index 4ef5792b11..cbfeaa8946 100644
--- a/libs/Zend/Mail/Protocol/Abstract.php
+++ b/libs/Zend/Mail/Protocol/Abstract.php
@@ -12,39 +12,39 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Abstract.php 21635 2010-03-24 15:25:13Z yoshida@zend.co.jp $
*/
/**
* @see Zend_Validate
*/
-require_once 'Zend/Validate.php';
+// require_once 'Zend/Validate.php';
/**
* @see Zend_Validate_Hostname
*/
-require_once 'Zend/Validate/Hostname.php';
+// require_once 'Zend/Validate/Hostname.php';
/**
* Zend_Mail_Protocol_Abstract
*
* Provides low-level methods for concrete adapters to communicate with a remote mail server and track requests and responses.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Abstract.php 21635 2010-03-24 15:25:13Z yoshida@zend.co.jp $
* @todo Implement proxy settings
*/
abstract class Zend_Mail_Protocol_Abstract
@@ -60,6 +60,11 @@ abstract class Zend_Mail_Protocol_Abstract
*/
const TIMEOUT_CONNECTION = 30;
+ /**
+ * Maximum of the transaction log
+ */
+ const MAXIMUM_LOG = 64;
+
/**
* Hostname or IP address of remote server
@@ -106,15 +111,16 @@ abstract class Zend_Mail_Protocol_Abstract
/**
* String template for parsing server responses using sscanf (default: 3 digit code and response string)
* @var resource
+ * @deprecated Since 1.10.3
*/
protected $_template = '%d%s';
/**
* Log of mail requests and server responses for a session
- * @var string
+ * @var array
*/
- private $_log;
+ private $_log = array();
/**
@@ -134,7 +140,7 @@ abstract class Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessages()));
}
@@ -191,7 +197,7 @@ abstract class Zend_Mail_Protocol_Abstract
*/
public function getLog()
{
- return $this->_log;
+ return implode('', $this->_log);
}
@@ -202,9 +208,23 @@ abstract class Zend_Mail_Protocol_Abstract
*/
public function resetLog()
{
- $this->_log = '';
+ $this->_log = array();
}
+ /**
+ * Add the transaction log
+ *
+ * @param string new transaction
+ * @return void
+ */
+ protected function _addLog($value)
+ {
+ if (count($this->_log) >= self::MAXIMUM_LOG) {
+ array_shift($this->_log);
+ }
+
+ $this->_log[] = $value;
+ }
/**
* Connect to the server using the supplied transport and target
@@ -230,7 +250,7 @@ abstract class Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception($errorStr);
}
@@ -238,7 +258,7 @@ abstract class Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Could not set stream timeout');
}
@@ -272,7 +292,7 @@ abstract class Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host);
}
@@ -281,13 +301,13 @@ abstract class Zend_Mail_Protocol_Abstract
$result = fwrite($this->_socket, $request . self::EOL);
// Save request to internal log
- $this->_log .= $request . self::EOL;
+ $this->_addLog($request . self::EOL);
if ($result === false) {
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Could not send request to ' . $this->_host);
}
@@ -308,7 +328,7 @@ abstract class Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host);
}
@@ -321,7 +341,7 @@ abstract class Zend_Mail_Protocol_Abstract
$reponse = fgets($this->_socket, 1024);
// Save request to internal log
- $this->_log .= $reponse;
+ $this->_addLog($reponse);
// Check meta data to ensure connection is still valid
$info = stream_get_meta_data($this->_socket);
@@ -330,7 +350,7 @@ abstract class Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception($this->_host . ' has timed out');
}
@@ -338,7 +358,7 @@ abstract class Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Could not read from ' . $this->_host);
}
@@ -359,8 +379,10 @@ abstract class Zend_Mail_Protocol_Abstract
protected function _expect($code, $timeout = null)
{
$this->_response = array();
- $cmd = '';
- $msg = '';
+ $cmd = '';
+ $more = '';
+ $msg = '';
+ $errMsg = '';
if (!is_array($code)) {
$code = array($code);
@@ -368,17 +390,23 @@ abstract class Zend_Mail_Protocol_Abstract
do {
$this->_response[] = $result = $this->_receive($timeout);
- sscanf($result, $this->_template, $cmd, $msg);
-
- if ($cmd === null || !in_array($cmd, $code)) {
- /**
- * @see Zend_Mail_Protocol_Exception
- */
- require_once 'Zend/Mail/Protocol/Exception.php';
- throw new Zend_Mail_Protocol_Exception($result);
+ list($cmd, $more, $msg) = preg_split('/([\s-]+)/', $result, 2, PREG_SPLIT_DELIM_CAPTURE);
+
+ if ($errMsg !== '') {
+ $errMsg .= ' ' . $msg;
+ } elseif ($cmd === null || !in_array($cmd, $code)) {
+ $errMsg = $msg;
}
- } while (strpos($msg, '-') === 0); // The '-' message prefix indicates an information string instead of a response string.
+ } while (strpos($more, '-') === 0); // The '-' message prefix indicates an information string instead of a response string.
+
+ if ($errMsg !== '') {
+ /**
+ * @see Zend_Mail_Protocol_Exception
+ */
+ // require_once 'Zend/Mail/Protocol/Exception.php';
+ throw new Zend_Mail_Protocol_Exception($errMsg);
+ }
return $msg;
}
diff --git a/libs/Zend/Mail/Protocol/Exception.php b/libs/Zend/Mail/Protocol/Exception.php
index 117cafb56e..30999c2d14 100644
--- a/libs/Zend/Mail/Protocol/Exception.php
+++ b/libs/Zend/Mail/Protocol/Exception.php
@@ -11,27 +11,27 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Exception
*/
-require_once 'Zend/Mail/Exception.php';
+// require_once 'Zend/Mail/Exception.php';
/**
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Protocol_Exception extends Zend_Mail_Exception
diff --git a/libs/Zend/Mail/Protocol/Imap.php b/libs/Zend/Mail/Protocol/Imap.php
index 2adc9efb14..286642fb48 100644
--- a/libs/Zend/Mail/Protocol/Imap.php
+++ b/libs/Zend/Mail/Protocol/Imap.php
@@ -15,9 +15,9 @@
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Imap.php 18499 2009-10-08 22:24:02Z yoshida@zend.co.jp $
+ * @version $Id: Imap.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,7 +25,7 @@
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Protocol_Imap
@@ -50,7 +50,7 @@ class Zend_Mail_Protocol_Imap
/**
* Public constructor
*
- * @param string $host hostname of IP address of IMAP server, if given connect() is called
+ * @param string $host hostname or IP address of IMAP server, if given connect() is called
* @param int|null $port port of IMAP server, null for default (143 or 993 for ssl)
* @param bool $ssl use ssl? 'SSL', 'TLS' or false
* @throws Zend_Mail_Protocol_Exception
@@ -71,9 +71,9 @@ class Zend_Mail_Protocol_Imap
}
/**
- * Open connection to POP3 server
+ * Open connection to IMAP server
*
- * @param string $host hostname of IP address of POP3 server
+ * @param string $host hostname or IP address of IMAP server
* @param int|null $port of IMAP server, default is 143 (993 for ssl)
* @param string|bool $ssl use 'SSL', 'TLS' or false
* @return string welcome message
@@ -96,15 +96,16 @@ class Zend_Mail_Protocol_Imap
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
- throw new Zend_Mail_Protocol_Exception('cannot connect to host : ' . $errno . ' : ' . $errstr);
+ // require_once 'Zend/Mail/Protocol/Exception.php';
+ throw new Zend_Mail_Protocol_Exception('cannot connect to host; error = ' . $errstr .
+ ' (errno = ' . $errno . ' )');
}
if (!$this->_assumedNextLine('* OK')) {
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('host doesn\'t allow connection');
}
@@ -115,7 +116,7 @@ class Zend_Mail_Protocol_Imap
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('cannot enable TLS');
}
}
@@ -134,7 +135,7 @@ class Zend_Mail_Protocol_Imap
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('cannot read - connection closed?');
}
@@ -208,7 +209,7 @@ class Zend_Mail_Protocol_Imap
$token = substr($token, 1);
}
if ($token[0] == '"') {
- if (preg_match('%^"((.|\\\\|\\")*?)" *%', $line, $matches)) {
+ if (preg_match('%^\(*"((.|\\\\|\\")*?)" *%', $line, $matches)) {
$tokens[] = $matches[1];
$line = substr($line, strlen($matches[0]));
continue;
@@ -347,14 +348,14 @@ class Zend_Mail_Protocol_Imap
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('cannot write - connection closed?');
}
if (!$this->_assumedNextLine('+ ')) {
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('cannot send literal string');
}
$line = $token[1];
@@ -367,7 +368,7 @@ class Zend_Mail_Protocol_Imap
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('cannot write - connection closed?');
}
}
@@ -628,7 +629,7 @@ class Zend_Mail_Protocol_Imap
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('the single id was not found in response');
}
diff --git a/libs/Zend/Mail/Protocol/Pop3.php b/libs/Zend/Mail/Protocol/Pop3.php
index cc7d5b2f09..78f01fe376 100644
--- a/libs/Zend/Mail/Protocol/Pop3.php
+++ b/libs/Zend/Mail/Protocol/Pop3.php
@@ -11,13 +11,13 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Pop3.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Pop3.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,7 +25,7 @@
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Protocol_Pop3
@@ -34,7 +34,7 @@ class Zend_Mail_Protocol_Pop3
* Default timeout in seconds for initiating session
*/
const TIMEOUT_CONNECTION = 30;
-
+
/**
* saves if server supports top
* @var null|bool
@@ -57,7 +57,7 @@ class Zend_Mail_Protocol_Pop3
/**
* Public constructor
*
- * @param string $host hostname of IP address of POP3 server, if given connect() is called
+ * @param string $host hostname or IP address of POP3 server, if given connect() is called
* @param int|null $port port of POP3 server, null for default (110 or 995 for ssl)
* @param bool|string $ssl use ssl? 'SSL', 'TLS' or false
* @throws Zend_Mail_Protocol_Exception
@@ -82,7 +82,7 @@ class Zend_Mail_Protocol_Pop3
/**
* Open connection to POP3 server
*
- * @param string $host hostname of IP address of POP3 server
+ * @param string $host hostname or IP address of POP3 server
* @param int|null $port of POP3 server, default is 110 (995 for ssl)
* @param string|bool $ssl use 'SSL', 'TLS' or false
* @return string welcome message
@@ -105,8 +105,9 @@ class Zend_Mail_Protocol_Pop3
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
- throw new Zend_Mail_Protocol_Exception('cannot connect to host : ' . $errno . ' : ' . $errstr);
+ // require_once 'Zend/Mail/Protocol/Exception.php';
+ throw new Zend_Mail_Protocol_Exception('cannot connect to host; error = ' . $errstr .
+ ' (errno = ' . $errno . ' )');
}
$welcome = $this->readResponse();
@@ -126,7 +127,7 @@ class Zend_Mail_Protocol_Pop3
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('cannot enable TLS');
}
}
@@ -149,7 +150,7 @@ class Zend_Mail_Protocol_Pop3
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('send failed - connection closed?');
}
}
@@ -169,7 +170,7 @@ class Zend_Mail_Protocol_Pop3
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('read failed - connection closed?');
}
@@ -185,7 +186,7 @@ class Zend_Mail_Protocol_Pop3
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('last request failed');
}
@@ -384,7 +385,7 @@ class Zend_Mail_Protocol_Pop3
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('top not supported and no fallback wanted');
}
}
diff --git a/libs/Zend/Mail/Protocol/Smtp.php b/libs/Zend/Mail/Protocol/Smtp.php
index 819b89551c..a7d8153fa2 100644
--- a/libs/Zend/Mail/Protocol/Smtp.php
+++ b/libs/Zend/Mail/Protocol/Smtp.php
@@ -12,37 +12,37 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Smtp.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Smtp.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mime
*/
-require_once 'Zend/Mime.php';
+// require_once 'Zend/Mime.php';
/**
* @see Zend_Mail_Protocol_Abstract
*/
-require_once 'Zend/Mail/Protocol/Abstract.php';
+// require_once 'Zend/Mail/Protocol/Abstract.php';
/**
* Smtp implementation of Zend_Mail_Protocol_Abstract
*
* Minimum implementation according to RFC2821: EHLO, MAIL FROM, RCPT TO, DATA, RSET, NOOP, QUIT
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract
@@ -140,7 +140,7 @@ class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception($config['ssl'] . ' is unsupported SSL type');
break;
}
@@ -182,7 +182,7 @@ class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Cannot issue HELO to existing session');
}
@@ -191,7 +191,7 @@ class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessages()));
}
@@ -207,7 +207,7 @@ class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Unable to connect via TLS');
}
$this->_ehlo($host);
@@ -253,7 +253,7 @@ class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('A valid session has not been started');
}
@@ -280,7 +280,7 @@ class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('No sender reverse path has been supplied');
}
@@ -305,7 +305,7 @@ class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('No recipient forward path has been supplied');
}
@@ -403,7 +403,7 @@ class Zend_Mail_Protocol_Smtp extends Zend_Mail_Protocol_Abstract
/**
* @see Zend_Mail_Protocol_Exception
*/
- require_once 'Zend/Mail/Protocol/Exception.php';
+ // require_once 'Zend/Mail/Protocol/Exception.php';
throw new Zend_Mail_Protocol_Exception('Already authenticated for this session');
}
}
diff --git a/libs/Zend/Mail/Protocol/Smtp/Auth/Crammd5.php b/libs/Zend/Mail/Protocol/Smtp/Auth/Crammd5.php
index ec5594e067..523d383e23 100644
--- a/libs/Zend/Mail/Protocol/Smtp/Auth/Crammd5.php
+++ b/libs/Zend/Mail/Protocol/Smtp/Auth/Crammd5.php
@@ -11,20 +11,20 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Crammd5.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Crammd5.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mail_Protocol_Smtp
*/
-require_once 'Zend/Mail/Protocol/Smtp.php';
+// require_once 'Zend/Mail/Protocol/Smtp.php';
/**
@@ -33,7 +33,7 @@ require_once 'Zend/Mail/Protocol/Smtp.php';
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Protocol_Smtp_Auth_Crammd5 extends Zend_Mail_Protocol_Smtp
diff --git a/libs/Zend/Mail/Protocol/Smtp/Auth/Login.php b/libs/Zend/Mail/Protocol/Smtp/Auth/Login.php
index a624792f4d..892f6724ec 100644
--- a/libs/Zend/Mail/Protocol/Smtp/Auth/Login.php
+++ b/libs/Zend/Mail/Protocol/Smtp/Auth/Login.php
@@ -11,20 +11,20 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Login.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Login.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mail_Protocol_Smtp
*/
-require_once 'Zend/Mail/Protocol/Smtp.php';
+// require_once 'Zend/Mail/Protocol/Smtp.php';
/**
@@ -33,7 +33,7 @@ require_once 'Zend/Mail/Protocol/Smtp.php';
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Protocol_Smtp_Auth_Login extends Zend_Mail_Protocol_Smtp
diff --git a/libs/Zend/Mail/Protocol/Smtp/Auth/Plain.php b/libs/Zend/Mail/Protocol/Smtp/Auth/Plain.php
index 26e65d3009..02784cb9d3 100644
--- a/libs/Zend/Mail/Protocol/Smtp/Auth/Plain.php
+++ b/libs/Zend/Mail/Protocol/Smtp/Auth/Plain.php
@@ -11,20 +11,20 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Plain.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Plain.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mail_Protocol_Smtp
*/
-require_once 'Zend/Mail/Protocol/Smtp.php';
+// require_once 'Zend/Mail/Protocol/Smtp.php';
/**
@@ -33,7 +33,7 @@ require_once 'Zend/Mail/Protocol/Smtp.php';
* @category Zend
* @package Zend_Mail
* @subpackage Protocol
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Protocol_Smtp_Auth_Plain extends Zend_Mail_Protocol_Smtp
diff --git a/libs/Zend/Mail/Storage.php b/libs/Zend/Mail/Storage.php
index 4c1a321962..771f7ae23b 100644
--- a/libs/Zend/Mail/Storage.php
+++ b/libs/Zend/Mail/Storage.php
@@ -14,15 +14,15 @@
*
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Storage.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Storage.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @category Zend
* @package Zend_Mail
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Storage
diff --git a/libs/Zend/Mail/Storage/Abstract.php b/libs/Zend/Mail/Storage/Abstract.php
index 052654b706..0d5f1ed1e7 100644
--- a/libs/Zend/Mail/Storage/Abstract.php
+++ b/libs/Zend/Mail/Storage/Abstract.php
@@ -11,13 +11,13 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,7 +25,7 @@
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Mail_Storage_Abstract implements Countable, ArrayAccess, SeekableIterator
@@ -78,11 +78,11 @@ abstract class Zend_Mail_Storage_Abstract implements Countable, ArrayAccess, See
$var = strtolower(substr($var, 3));
return isset($this->_has[$var]) ? $this->_has[$var] : null;
}
-
+
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception($var . ' not found');
}
@@ -264,7 +264,7 @@ abstract class Zend_Mail_Storage_Abstract implements Countable, ArrayAccess, See
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot write mail messages via array access');
}
diff --git a/libs/Zend/Mail/Storage/Exception.php b/libs/Zend/Mail/Storage/Exception.php
index 497ab2c7ce..29cbc26981 100644
--- a/libs/Zend/Mail/Storage/Exception.php
+++ b/libs/Zend/Mail/Storage/Exception.php
@@ -11,27 +11,27 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mail_Exception
*/
-require_once 'Zend/Mail/Exception.php';
+// require_once 'Zend/Mail/Exception.php';
/**
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Storage_Exception extends Zend_Mail_Exception
diff --git a/libs/Zend/Mail/Storage/Folder.php b/libs/Zend/Mail/Storage/Folder.php
index 1fc9641fdf..51d8a61a5d 100644
--- a/libs/Zend/Mail/Storage/Folder.php
+++ b/libs/Zend/Mail/Storage/Folder.php
@@ -11,13 +11,13 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Folder.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Folder.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,7 +25,7 @@
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Storage_Folder implements RecursiveIterator
@@ -154,7 +154,7 @@ class Zend_Mail_Storage_Folder implements RecursiveIterator
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception("no subfolder named $name");
}
diff --git a/libs/Zend/Mail/Storage/Folder/Interface.php b/libs/Zend/Mail/Storage/Folder/Interface.php
index 683dc22e43..b5c89ac917 100644
--- a/libs/Zend/Mail/Storage/Folder/Interface.php
+++ b/libs/Zend/Mail/Storage/Folder/Interface.php
@@ -11,13 +11,13 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,7 +25,7 @@
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Mail_Storage_Folder_Interface
diff --git a/libs/Zend/Mail/Storage/Folder/Maildir.php b/libs/Zend/Mail/Storage/Folder/Maildir.php
index c2bf340c7d..228465a9e3 100644
--- a/libs/Zend/Mail/Storage/Folder/Maildir.php
+++ b/libs/Zend/Mail/Storage/Folder/Maildir.php
@@ -11,37 +11,37 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Maildir.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Maildir.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mail_Storage_Folder
*/
-require_once 'Zend/Mail/Storage/Folder.php';
+// require_once 'Zend/Mail/Storage/Folder.php';
/**
* @see Zend_Mail_Storage_Folder_Interface
*/
-require_once 'Zend/Mail/Storage/Folder/Interface.php';
+// require_once 'Zend/Mail/Storage/Folder/Interface.php';
/**
* @see Zend_Mail_Storage_Maildir
*/
-require_once 'Zend/Mail/Storage/Maildir.php';
+// require_once 'Zend/Mail/Storage/Maildir.php';
/**
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Storage_Folder_Maildir extends Zend_Mail_Storage_Maildir implements Zend_Mail_Storage_Folder_Interface
@@ -90,7 +90,7 @@ class Zend_Mail_Storage_Folder_Maildir extends Zend_Mail_Storage_Maildir impleme
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('no valid dirname given in params');
}
@@ -123,7 +123,7 @@ class Zend_Mail_Storage_Folder_Maildir extends Zend_Mail_Storage_Maildir impleme
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception("can't read folders in maildir");
}
$dirs = array();
@@ -152,7 +152,7 @@ class Zend_Mail_Storage_Folder_Maildir extends Zend_Mail_Storage_Maildir impleme
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('error while reading maildir');
}
array_push($stack, $parent);
@@ -171,7 +171,7 @@ class Zend_Mail_Storage_Folder_Maildir extends Zend_Mail_Storage_Maildir impleme
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('error while reading maildir');
}
}
@@ -208,7 +208,7 @@ class Zend_Mail_Storage_Folder_Maildir extends Zend_Mail_Storage_Maildir impleme
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception("folder $rootFolder not found");
}
return $currentFolder;
@@ -238,17 +238,17 @@ class Zend_Mail_Storage_Folder_Maildir extends Zend_Mail_Storage_Maildir impleme
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
- throw new Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable");
+ // require_once 'Zend/Mail/Storage/Exception.php';
+ throw new Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable", 0, $e);
}
// seems like file has vanished; rebuilding folder tree - but it's still an exception
$this->_buildFolderTree($this->_rootdir);
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('seems like the maildir has vanished, I\'ve rebuild the ' .
- 'folder tree, search for an other folder and try again');
+ 'folder tree, search for an other folder and try again', 0, $e);
}
}
diff --git a/libs/Zend/Mail/Storage/Folder/Mbox.php b/libs/Zend/Mail/Storage/Folder/Mbox.php
index e942322980..fc1d50b2a0 100644
--- a/libs/Zend/Mail/Storage/Folder/Mbox.php
+++ b/libs/Zend/Mail/Storage/Folder/Mbox.php
@@ -11,37 +11,37 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mbox.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Mbox.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mail_Storage_Folder
*/
-require_once 'Zend/Mail/Storage/Folder.php';
+// require_once 'Zend/Mail/Storage/Folder.php';
/**
* @see Zend_Mail_Storage_Folder_Interface
*/
-require_once 'Zend/Mail/Storage/Folder/Interface.php';
+// require_once 'Zend/Mail/Storage/Folder/Interface.php';
/**
* @see Zend_Mail_Storage_Mbox
*/
-require_once 'Zend/Mail/Storage/Mbox.php';
+// require_once 'Zend/Mail/Storage/Mbox.php';
/**
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Storage_Folder_Mbox extends Zend_Mail_Storage_Mbox implements Zend_Mail_Storage_Folder_Interface
@@ -86,7 +86,7 @@ class Zend_Mail_Storage_Folder_Mbox extends Zend_Mail_Storage_Mbox implements Ze
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('use Zend_Mail_Storage_Mbox for a single file');
}
@@ -94,7 +94,7 @@ class Zend_Mail_Storage_Folder_Mbox extends Zend_Mail_Storage_Mbox implements Ze
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('no valid dirname given in params');
}
@@ -130,7 +130,7 @@ class Zend_Mail_Storage_Folder_Mbox extends Zend_Mail_Storage_Mbox implements Ze
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception("can't read dir $currentDir");
}
while (($entry = readdir($dh)) !== false) {
@@ -182,7 +182,7 @@ class Zend_Mail_Storage_Folder_Mbox extends Zend_Mail_Storage_Mbox implements Ze
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception("folder $rootFolder not found");
}
return $currentFolder;
@@ -212,17 +212,17 @@ class Zend_Mail_Storage_Folder_Mbox extends Zend_Mail_Storage_Mbox implements Ze
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
- throw new Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable");
+ // require_once 'Zend/Mail/Storage/Exception.php';
+ throw new Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable", 0, $e);
}
// seems like file has vanished; rebuilding folder tree - but it's still an exception
$this->_buildFolderTree($this->_rootdir);
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('seems like the mbox file has vanished, I\'ve rebuild the ' .
- 'folder tree, search for an other folder and try again');
+ 'folder tree, search for an other folder and try again', 0, $e);
}
}
diff --git a/libs/Zend/Mail/Storage/Imap.php b/libs/Zend/Mail/Storage/Imap.php
index 2495e90782..2efc5b856b 100644
--- a/libs/Zend/Mail/Storage/Imap.php
+++ b/libs/Zend/Mail/Storage/Imap.php
@@ -11,56 +11,56 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Imap.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Imap.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mail_Storage_Abstract
*/
-require_once 'Zend/Mail/Storage/Abstract.php';
+// require_once 'Zend/Mail/Storage/Abstract.php';
/**
* @see Zend_Mail_Protocol_Imap
*/
-require_once 'Zend/Mail/Protocol/Imap.php';
+// require_once 'Zend/Mail/Protocol/Imap.php';
/**
* @see Zend_Mail_Storage_Writable_Interface
*/
-require_once 'Zend/Mail/Storage/Writable/Interface.php';
+// require_once 'Zend/Mail/Storage/Writable/Interface.php';
/**
* @see Zend_Mail_Storage_Folder_Interface
*/
-require_once 'Zend/Mail/Storage/Folder/Interface.php';
+// require_once 'Zend/Mail/Storage/Folder/Interface.php';
/**
* @see Zend_Mail_Storage_Folder
*/
-require_once 'Zend/Mail/Storage/Folder.php';
+// require_once 'Zend/Mail/Storage/Folder.php';
/**
* @see Zend_Mail_Message
*/
-require_once 'Zend/Mail/Message.php';
+// require_once 'Zend/Mail/Message.php';
/**
* @see Zend_Mail_Storage
*/
-require_once 'Zend/Mail/Storage.php';
+// require_once 'Zend/Mail/Storage.php';
/**
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
@@ -116,14 +116,14 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('No selected folder to count');
}
if ($flags === null) {
return count($this->_protocol->search(array('ALL')));
}
-
+
$params = array();
foreach ((array)$flags as $flag) {
if (isset(self::$_searchFlags[$flag])) {
@@ -189,7 +189,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('not implemented');
}
@@ -213,7 +213,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('not implemented');
}
@@ -250,8 +250,8 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
- throw new Zend_Mail_Storage_Exception('cannot select INBOX, is this a valid transport?');
+ // require_once 'Zend/Mail/Storage/Exception.php';
+ throw new Zend_Mail_Storage_Exception('cannot select INBOX, is this a valid transport?', 0, $e);
}
return;
}
@@ -260,7 +260,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('need at least user in params');
}
@@ -275,7 +275,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot login, user or password wrong');
}
$this->selectFolder(isset($params->folder) ? $params->folder : 'INBOX');
@@ -305,7 +305,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('could not do nothing');
}
}
@@ -325,7 +325,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot set deleted flag');
}
// TODO: expunge here or at close? we can handle an error here better and are more fail safe
@@ -333,7 +333,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('message marked as deleted, but could not expunge');
}
}
@@ -379,7 +379,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('unique id not found');
}
@@ -399,7 +399,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('folder not found');
}
@@ -437,7 +437,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('error while constructing folder tree');
}
}
@@ -463,7 +463,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot change folder, maybe it does not exist');
}
}
@@ -506,7 +506,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot create folder');
}
}
@@ -528,7 +528,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot delete folder');
}
}
@@ -553,7 +553,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot rename folder');
}
}
@@ -582,7 +582,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot create message, please check if the folder exists and your flags');
}
}
@@ -601,7 +601,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot copy message, does the folder exist?');
}
}
@@ -636,7 +636,7 @@ class Zend_Mail_Storage_Imap extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot set flags, have you tried to set the recent flag or special chars?');
}
}
diff --git a/libs/Zend/Mail/Storage/Maildir.php b/libs/Zend/Mail/Storage/Maildir.php
index 3954db4a1c..736b70cc66 100644
--- a/libs/Zend/Mail/Storage/Maildir.php
+++ b/libs/Zend/Mail/Storage/Maildir.php
@@ -11,37 +11,37 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Maildir.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Maildir.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mail_Storage_Abstract
*/
-require_once 'Zend/Mail/Storage/Abstract.php';
+// require_once 'Zend/Mail/Storage/Abstract.php';
/**
* @see Zend_Mail_Message_File
*/
-require_once 'Zend/Mail/Message/File.php';
+// require_once 'Zend/Mail/Message/File.php';
/**
* @see Zend_Mail_Storage
*/
-require_once 'Zend/Mail/Storage.php';
+// require_once 'Zend/Mail/Storage.php';
/**
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
@@ -71,7 +71,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
'R' => Zend_Mail_Storage::FLAG_ANSWERED,
'S' => Zend_Mail_Storage::FLAG_SEEN,
'T' => Zend_Mail_Storage::FLAG_DELETED);
-
+
// TODO: getFlags($id) for fast access if headers are not needed (i.e. just setting flags)?
/**
@@ -86,7 +86,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
return count($this->_files);
}
- $count = 0;
+ $count = 0;
if (!is_array($flags)) {
foreach ($this->_files as $file) {
if (isset($file['flaglookup'][$flags])) {
@@ -95,7 +95,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
}
return $count;
}
-
+
$flags = array_flip($flags);
foreach ($this->_files as $file) {
foreach ($flags as $flag => $v) {
@@ -122,7 +122,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('id does not exist');
}
@@ -134,7 +134,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('field does not exist');
}
@@ -179,7 +179,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
return new $this->_messageClass(array('file' => $this->_getFileData($id, 'filename'),
'flags' => $this->_getFileData($id, 'flags')));
}
-
+
return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $this->getRawHeader($id),
'flags' => $this->_getFileData($id, 'flags')));
}
@@ -200,7 +200,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('not implemented');
}
@@ -234,7 +234,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('not implemented');
}
@@ -270,7 +270,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('no valid dirname given in params');
}
@@ -278,7 +278,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('invalid maildir given');
}
@@ -322,7 +322,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot open maildir');
}
$this->_getMaildirFiles($dh, $dirname . '/cur/');
@@ -336,7 +336,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot read recent mails in maildir');
}
}
@@ -422,7 +422,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('maildir is (currently) read-only');
}
@@ -469,7 +469,7 @@ class Zend_Mail_Storage_Maildir extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('unique id not found');
}
}
diff --git a/libs/Zend/Mail/Storage/Mbox.php b/libs/Zend/Mail/Storage/Mbox.php
index 8fad784c5d..97bc56e394 100644
--- a/libs/Zend/Mail/Storage/Mbox.php
+++ b/libs/Zend/Mail/Storage/Mbox.php
@@ -11,13 +11,13 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mbox.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Mbox.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,24 +25,24 @@
* @see Zend_Loader
* May be used in constructor, but commented out for now
*/
-// require_once 'Zend/Loader.php';
+// // require_once 'Zend/Loader.php';
/**
* @see Zend_Mail_Storage_Abstract
*/
-require_once 'Zend/Mail/Storage/Abstract.php';
+// require_once 'Zend/Mail/Storage/Abstract.php';
/**
* @see Zend_Mail_Message_File
*/
-require_once 'Zend/Mail/Message/File.php';
+// require_once 'Zend/Mail/Message/File.php';
/**
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract
@@ -124,7 +124,7 @@ class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('id does not exist');
}
@@ -180,7 +180,7 @@ class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('not implemented');
}
$messagePos = $this->_getPos($id);
@@ -204,7 +204,7 @@ class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('not implemented');
}
$messagePos = $this->_getPos($id);
@@ -224,12 +224,12 @@ class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract
if (is_array($params)) {
$params = (object)$params;
}
-
+
if (!isset($params->filename) /* || Zend_Loader::isReadable($params['filename']) */) {
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('no valid filename given in params');
}
@@ -290,7 +290,7 @@ class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot open mbox file');
}
$this->_filename = $filename;
@@ -301,7 +301,7 @@ class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('file is not a valid mbox format');
}
@@ -362,7 +362,7 @@ class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('mbox is read-only');
}
@@ -438,7 +438,7 @@ class Zend_Mail_Storage_Mbox extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot open mbox file');
}
}
diff --git a/libs/Zend/Mail/Storage/Pop3.php b/libs/Zend/Mail/Storage/Pop3.php
index b3ea092032..0841c3c352 100644
--- a/libs/Zend/Mail/Storage/Pop3.php
+++ b/libs/Zend/Mail/Storage/Pop3.php
@@ -11,37 +11,37 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Pop3.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Pop3.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mail_Storage_Abstract
*/
-require_once 'Zend/Mail/Storage/Abstract.php';
+// require_once 'Zend/Mail/Storage/Abstract.php';
/**
* @see Zend_Mail_Protocol_Pop3
*/
-require_once 'Zend/Mail/Protocol/Pop3.php';
+// require_once 'Zend/Mail/Protocol/Pop3.php';
/**
* @see Zend_Mail_Message
*/
-require_once 'Zend/Mail/Message.php';
+// require_once 'Zend/Mail/Message.php';
/**
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Storage_Pop3 extends Zend_Mail_Storage_Abstract
@@ -112,7 +112,7 @@ class Zend_Mail_Storage_Pop3 extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('not implemented');
}
@@ -135,7 +135,7 @@ class Zend_Mail_Storage_Pop3 extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('not implemented');
}
@@ -177,7 +177,7 @@ class Zend_Mail_Storage_Pop3 extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('need at least user in params');
}
@@ -244,7 +244,7 @@ class Zend_Mail_Storage_Pop3 extends Zend_Mail_Storage_Abstract
}
$count = $this->countMessages();
if ($count < 1) {
- return array();
+ return array();
}
$range = range(1, $count);
return array_combine($range, $range);
@@ -279,7 +279,7 @@ class Zend_Mail_Storage_Pop3 extends Zend_Mail_Storage_Abstract
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('unique id not found');
}
diff --git a/libs/Zend/Mail/Storage/Writable/Interface.php b/libs/Zend/Mail/Storage/Writable/Interface.php
index fd73380df7..982b44eeb9 100644
--- a/libs/Zend/Mail/Storage/Writable/Interface.php
+++ b/libs/Zend/Mail/Storage/Writable/Interface.php
@@ -11,13 +11,13 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,7 +25,7 @@
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
diff --git a/libs/Zend/Mail/Storage/Writable/Maildir.php b/libs/Zend/Mail/Storage/Writable/Maildir.php
index 303b86066d..3519a4b411 100644
--- a/libs/Zend/Mail/Storage/Writable/Maildir.php
+++ b/libs/Zend/Mail/Storage/Writable/Maildir.php
@@ -11,32 +11,32 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Maildir.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Maildir.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mail_Storage_Folder_Maildir
*/
-require_once 'Zend/Mail/Storage/Folder/Maildir.php';
+// require_once 'Zend/Mail/Storage/Folder/Maildir.php';
/**
* @see Zend_Mail_Storage_Writable_Interface
*/
-require_once 'Zend/Mail/Storage/Writable/Interface.php';
+// require_once 'Zend/Mail/Storage/Writable/Interface.php';
/**
* @category Zend
* @package Zend_Mail
* @subpackage Storage
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Maildir
@@ -49,7 +49,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
* @var bool|int
*/
protected $_quota;
-
+
/**
* create a new maildir
*
@@ -66,7 +66,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('maildir must be a directory if already exists');
}
} else {
@@ -74,7 +74,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
$dir = dirname($dir);
if (!file_exists($dir)) {
throw new Zend_Mail_Storage_Exception("parent $dir not found");
@@ -85,7 +85,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
}
}
}
-
+
foreach (array('cur', 'tmp', 'new') as $subdir) {
if (!@mkdir($dir . DIRECTORY_SEPARATOR . $subdir)) {
// ignore if dir exists (i.e. was already valid maildir or two processes try to create one)
@@ -93,13 +93,13 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('could not create subdir ' . $subdir);
}
}
}
}
-
+
/**
* Create instance with parameters
* Additional parameters are (see parent for more):
@@ -112,11 +112,11 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
if (is_array($params)) {
$params = (object)$params;
}
-
+
if (!empty($params->create) && isset($params->dirname) && !file_exists($params->dirname . DIRECTORY_SEPARATOR . 'cur')) {
self::initMaildir($params->dirname);
}
-
+
parent::__construct($params);
}
@@ -154,7 +154,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('folder already exists');
}
@@ -162,7 +162,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('invalid name - folder parts may not be empty');
}
@@ -178,7 +178,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('invalid name - no directory seprator allowed in folder name');
}
@@ -199,7 +199,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('error while creating new folder, may be created incompletly');
}
@@ -241,7 +241,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('delete children first');
}
@@ -249,7 +249,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('wont delete INBOX');
}
@@ -257,7 +257,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('wont delete selected folder');
}
@@ -271,7 +271,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception("error opening $subdir");
}
while (($entry = readdir($dh)) !== false) {
@@ -282,7 +282,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception("error cleaning $subdir");
}
}
@@ -292,7 +292,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception("error removing $subdir");
}
}
@@ -304,7 +304,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception("error removing maindir");
}
@@ -345,7 +345,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('new folder cannot be a child of old folder');
}
@@ -356,7 +356,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('wont rename INBOX');
}
@@ -364,7 +364,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('wont rename selected folder');
}
@@ -387,7 +387,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('error while moving ' . $subdir);
}
}
@@ -442,7 +442,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('problems creating tmp dir');
}
}
@@ -464,7 +464,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('could not open temp file');
}
break;
@@ -476,7 +476,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception("tried $max_tries unique ids for a temp file, but all were taken"
. ' - giving up');
}
@@ -500,7 +500,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('recent flag may not be set');
}
@@ -520,7 +520,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('unknown flag(s): ' . $wanted_flags);
}
@@ -545,8 +545,8 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
- throw new Zend_Mail_Storage_Exception('storage is over quota!');
+ // require_once 'Zend/Mail/Storage/Exception.php';
+ throw new Zend_Mail_Storage_Exception('storage is over quota!');
}
if ($folder === null) {
@@ -587,7 +587,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
$exception = new Zend_Mail_Storage_Exception('cannot link message file to final dir');
}
@unlink($temp_file['filename']);
@@ -618,10 +618,10 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
- throw new Zend_Mail_Storage_Exception('storage is over quota!');
+ // require_once 'Zend/Mail/Storage/Exception.php';
+ throw new Zend_Mail_Storage_Exception('storage is over quota!');
}
-
+
if (!($folder instanceof Zend_Mail_Storage_Folder)) {
$folder = $this->getFolders($folder);
}
@@ -656,13 +656,13 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
$exception = new Zend_Mail_Storage_Exception('cannot copy message file');
} else if (!link($temp_file['filename'], $new_file)) {
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
$exception = new Zend_Mail_Storage_Exception('cannot link message file to final dir');
}
@unlink($temp_file['filename']);
@@ -677,7 +677,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
'flags' => $flags,
'filename' => $new_file);
}
-
+
if ($this->_quota) {
$this->_addQuotaEntry((int)$size, 1);
}
@@ -695,16 +695,16 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
if (!($folder instanceof Zend_Mail_Storage_Folder)) {
$folder = $this->getFolders($folder);
}
-
+
if ($folder->getGlobalName() == $this->_currentFolder
|| ($this->_currentFolder == 'INBOX' && $folder->getGlobalName() == '/')) {
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('target is current folder');
}
-
+
$filedata = $this->_getFileData($id);
$old_file = $filedata['filename'];
$flags = $filedata['flags'];
@@ -734,7 +734,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
$exception = new Zend_Mail_Storage_Exception('cannot move message file');
}
@unlink($temp_file['filename']);
@@ -770,7 +770,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot rename file');
}
@@ -790,16 +790,16 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
public function removeMessage($id)
{
$filename = $this->_getFileData($id, 'filename');
-
+
if ($this->_quota) {
$size = filesize($filename);
}
-
+
if (!@unlink($filename)) {
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot remove message');
}
unset($this->_files[$id - 1]);
@@ -809,7 +809,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
$this->_addQuotaEntry(0 - (int)$size, -1);
}
}
-
+
/**
* enable/disable quota and set a quota value if wanted or needed
*
@@ -824,7 +824,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
public function setQuota($value) {
$this->_quota = $value;
}
-
+
/**
* get currently set quota
*
@@ -839,7 +839,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
/**
* @see Zend_Mail_Storage_Exception
*/
- require_once 'Zend/Mail/Storage/Exception.php';
+ // require_once 'Zend/Mail/Storage/Exception.php';
throw new Zend_Mail_Storage_Exception('cannot open maildirsize');
}
$definition = fgets($fh);
@@ -855,10 +855,10 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
}
return $quota;
}
-
+
return $this->_quota;
}
-
+
/**
* @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating maildirsize"
*/
@@ -873,10 +873,10 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
try {
$quota = $this->getQuota(true);
} catch (Zend_Mail_Storage_Exception $e) {
- throw new Zend_Mail_Storage_Exception('no quota defintion found');
+ throw new Zend_Mail_Storage_Exception('no quota definition found', 0, $e);
}
}
-
+
$folders = new RecursiveIteratorIterator($this->getFolders(), RecursiveIteratorIterator::SELF_FIRST);
foreach ($folders as $folder) {
$subdir = $folder->getGlobalName();
@@ -888,29 +888,29 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
if ($subdir == 'Trash') {
continue;
}
-
+
foreach (array('cur', 'new') as $subsubdir) {
$dirname = $this->_rootdir . $subdir . DIRECTORY_SEPARATOR . $subsubdir . DIRECTORY_SEPARATOR;
if (!file_exists($dirname)) {
continue;
}
// NOTE: we are using mtime instead of "the latest timestamp". The latest would be atime
- // and as we are accessing the directory it would make the whole calculation useless.
+ // and as we are accessing the directory it would make the whole calculation useless.
$timestamps[$dirname] = filemtime($dirname);
$dh = opendir($dirname);
- // NOTE: Should have been checked in constructor. Not throwing an exception here, quotas will
+ // NOTE: Should have been checked in constructor. Not throwing an exception here, quotas will
// therefore not be fully enforeced, but next request will fail anyway, if problem persists.
if (!$dh) {
continue;
}
-
-
+
+
while (($entry = readdir()) !== false) {
if ($entry[0] == '.' || !is_file($dirname . $entry)) {
continue;
}
-
+
if (strpos($entry, ',S=')) {
strtok($entry, '=');
$filesize = strtok(':');
@@ -930,7 +930,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
}
}
}
-
+
$tmp = $this->_createTmpFile();
$fh = $tmp['handle'];
$definition = array();
@@ -951,10 +951,10 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
break;
}
}
-
+
return array('size' => $total_size, 'count' => $messages, 'quota' => $quota);
}
-
+
/**
* @see http://www.inter7.com/courierimap/README.maildirquota.html "Calculating the quota for a Maildir++"
*/
@@ -1001,9 +1001,9 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
$messages += $count;
}
}
-
+
$over_quota = false;
- $over_quota = $over_quota || (isset($quota['size']) && $total_size > $quota['size']);
+ $over_quota = $over_quota || (isset($quota['size']) && $total_size > $quota['size']);
$over_quota = $over_quota || (isset($quota['count']) && $messages > $quota['count']);
// NOTE: $maildirsize equals false if it wasn't set (AKA we recalculated) or it's only
// one line, because $maildirsize[0] gets unsetted.
@@ -1015,18 +1015,18 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
$messages = $result['count'];
$quota = $result['quota'];
$over_quota = false;
- $over_quota = $over_quota || (isset($quota['size']) && $total_size > $quota['size']);
+ $over_quota = $over_quota || (isset($quota['size']) && $total_size > $quota['size']);
$over_quota = $over_quota || (isset($quota['count']) && $messages > $quota['count']);
}
-
+
if ($fh) {
// TODO is there a safe way to keep the handle open for writing?
fclose($fh);
}
-
+
return array('size' => $total_size, 'count' => $messages, 'quota' => $quota, 'over_quota' => $over_quota);
}
-
+
protected function _addQuotaEntry($size, $count = 1) {
if (!file_exists($this->_rootdir . 'maildirsize')) {
// TODO: should get file handler from _calculateQuota
@@ -1035,7 +1035,7 @@ class Zend_Mail_Storage_Writable_Maildir extends Zend_Mail_Storage_Folder_Mai
$count = (int)$count;
file_put_contents($this->_rootdir . 'maildirsize', "$size $count\n", FILE_APPEND);
}
-
+
/**
* check if storage is currently over quota
*
diff --git a/libs/Zend/Mail/Transport/Abstract.php b/libs/Zend/Mail/Transport/Abstract.php
index 5ef4b7019c..74d6ab005f 100644
--- a/libs/Zend/Mail/Transport/Abstract.php
+++ b/libs/Zend/Mail/Transport/Abstract.php
@@ -15,16 +15,16 @@
* @category Zend
* @package Zend_Mail
* @subpackage Transport
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 17334 2009-08-01 01:25:22Z yoshida@zend.co.jp $
+ * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mime
*/
-require_once 'Zend/Mime.php';
+// require_once 'Zend/Mime.php';
/**
@@ -34,7 +34,7 @@ require_once 'Zend/Mime.php';
* @category Zend
* @package Zend_Mail
* @subpackage Transport
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Mail_Transport_Abstract
@@ -140,7 +140,7 @@ abstract class Zend_Mail_Transport_Abstract
}
$this->_headers['Content-Type'] = array(
- $type . '; charset=' . $this->_mail->getCharset() . ';'
+ $type . ';'
. $this->EOL
. " " . 'boundary="' . $boundary . '"'
);
@@ -184,7 +184,7 @@ abstract class Zend_Mail_Transport_Abstract
/**
* @see Zend_Mail_Transport_Exception
*/
- require_once 'Zend/Mail/Transport/Exception.php';
+ // require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('Missing Zend_Mail object in _mail property');
}
@@ -213,7 +213,7 @@ abstract class Zend_Mail_Transport_Abstract
/**
* @see Zend_Mail_Transport_Exception
*/
- require_once 'Zend/Mail/Transport/Exception.php';
+ // require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Exception('At least one mail header line is too long');
}
}
@@ -280,7 +280,7 @@ abstract class Zend_Mail_Transport_Abstract
/**
* @see Zend_Mail_Transport_Exception
*/
- require_once 'Zend/Mail/Transport/Exception.php';
+ // require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('No body specified');
}
@@ -319,7 +319,7 @@ abstract class Zend_Mail_Transport_Abstract
/**
* @see Zend_Mail_Transport_Exception
*/
- require_once 'Zend/Mail/Transport/Exception.php';
+ // require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('Empty mail cannot be sent');
}
diff --git a/libs/Zend/Mail/Transport/Exception.php b/libs/Zend/Mail/Transport/Exception.php
index 9947f45a79..cf4165a886 100644
--- a/libs/Zend/Mail/Transport/Exception.php
+++ b/libs/Zend/Mail/Transport/Exception.php
@@ -11,27 +11,27 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Transport
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mail_Exception
*/
-require_once 'Zend/Mail/Exception.php';
+// require_once 'Zend/Mail/Exception.php';
/**
* @category Zend
* @package Zend_Mail
* @subpackage Transport
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Transport_Exception extends Zend_Mail_Exception
diff --git a/libs/Zend/Mail/Transport/Sendmail.php b/libs/Zend/Mail/Transport/Sendmail.php
index cef1e2091f..c12eb46a23 100644
--- a/libs/Zend/Mail/Transport/Sendmail.php
+++ b/libs/Zend/Mail/Transport/Sendmail.php
@@ -11,20 +11,20 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Transport
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Sendmail.php 18264 2009-09-18 18:25:38Z beberlei $
+ * @version $Id: Sendmail.php 21605 2010-03-22 15:09:03Z yoshida@zend.co.jp $
*/
/**
* @see Zend_Mail_Transport_Abstract
*/
-require_once 'Zend/Mail/Transport/Abstract.php';
+// require_once 'Zend/Mail/Transport/Abstract.php';
/**
@@ -33,7 +33,7 @@ require_once 'Zend/Mail/Transport/Abstract.php';
* @category Zend
* @package Zend_Mail
* @subpackage Transport
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Transport_Sendmail extends Zend_Mail_Transport_Abstract
@@ -53,7 +53,6 @@ class Zend_Mail_Transport_Sendmail extends Zend_Mail_Transport_Abstract
*/
public $parameters;
-
/**
* EOL character string
* @var string
@@ -61,15 +60,28 @@ class Zend_Mail_Transport_Sendmail extends Zend_Mail_Transport_Abstract
*/
public $EOL = PHP_EOL;
+ /**
+ * error information
+ * @var string
+ */
+ protected $_errstr;
/**
* Constructor.
*
- * @param string $parameters OPTIONAL (Default: null)
+ * @param string|array|Zend_Config $parameters OPTIONAL (Default: null)
* @return void
*/
public function __construct($parameters = null)
{
+ if ($parameters instanceof Zend_Config) {
+ $parameters = $parameters->toArray();
+ }
+
+ if (is_array($parameters)) {
+ $parameters = implode(' ', $parameters);
+ }
+
$this->parameters = $parameters;
}
@@ -79,30 +91,50 @@ class Zend_Mail_Transport_Sendmail extends Zend_Mail_Transport_Abstract
*
* @access public
* @return void
+ * @throws Zend_Mail_Transport_Exception if parameters is set
+ * but not a string
* @throws Zend_Mail_Transport_Exception on mail() failure
*/
public function _sendMail()
{
if ($this->parameters === null) {
+ set_error_handler(array($this, '_handleMailErrors'));
$result = mail(
$this->recipients,
$this->_mail->getSubject(),
$this->body,
$this->header);
+ restore_error_handler();
} else {
+ if(!is_string($this->parameters)) {
+ /**
+ * @see Zend_Mail_Transport_Exception
+ *
+ * Exception is thrown here because
+ * $parameters is a public property
+ */
+ // require_once 'Zend/Mail/Transport/Exception.php';
+ throw new Zend_Mail_Transport_Exception(
+ 'Parameters were set but are not a string'
+ );
+ }
+
+ set_error_handler(array($this, '_handleMailErrors'));
$result = mail(
$this->recipients,
$this->_mail->getSubject(),
$this->body,
$this->header,
$this->parameters);
+ restore_error_handler();
}
- if (!$result) {
+
+ if ($this->_errstr !== null || !$result) {
/**
* @see Zend_Mail_Transport_Exception
*/
- require_once 'Zend/Mail/Transport/Exception.php';
- throw new Zend_Mail_Transport_Exception('Unable to send mail');
+ // require_once 'Zend/Mail/Transport/Exception.php';
+ throw new Zend_Mail_Transport_Exception('Unable to send mail. ' . $this->_errstr);
}
}
@@ -125,7 +157,7 @@ class Zend_Mail_Transport_Sendmail extends Zend_Mail_Transport_Abstract
/**
* @see Zend_Mail_Transport_Exception
*/
- require_once 'Zend/Mail/Transport/Exception.php';
+ // require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('_prepareHeaders requires a registered Zend_Mail object');
}
@@ -137,7 +169,7 @@ class Zend_Mail_Transport_Sendmail extends Zend_Mail_Transport_Abstract
/**
* @see Zend_Mail_Transport_Exception
*/
- require_once 'Zend/Mail/Transport/Exception.php';
+ // require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('Missing To addresses');
}
} else {
@@ -146,7 +178,7 @@ class Zend_Mail_Transport_Sendmail extends Zend_Mail_Transport_Abstract
/**
* @see Zend_Mail_Transport_Exception
*/
- require_once 'Zend/Mail/Transport/Exception.php';
+ // require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('Missing To header');
}
@@ -169,5 +201,20 @@ class Zend_Mail_Transport_Sendmail extends Zend_Mail_Transport_Abstract
$this->header = rtrim($this->header);
}
-}
+ /**
+ * Temporary error handler for PHP native mail().
+ *
+ * @param int $errno
+ * @param string $errstr
+ * @param string $errfile
+ * @param string $errline
+ * @param array $errcontext
+ * @return true
+ */
+ public function _handleMailErrors($errno, $errstr, $errfile = null, $errline = null, array $errcontext = null)
+ {
+ $this->_errstr = $errstr;
+ return true;
+ }
+}
diff --git a/libs/Zend/Mail/Transport/Smtp.php b/libs/Zend/Mail/Transport/Smtp.php
index 0c1f7cb0b9..288cb4644f 100644
--- a/libs/Zend/Mail/Transport/Smtp.php
+++ b/libs/Zend/Mail/Transport/Smtp.php
@@ -11,30 +11,30 @@
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@zend.com so we can send you a copy immediately.
- *
+ *
* @category Zend
* @package Zend_Mail
* @subpackage Transport
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Smtp.php 16219 2009-06-21 19:45:39Z thomas $
+ * @version $Id: Smtp.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mime
*/
-require_once 'Zend/Mime.php';
+// require_once 'Zend/Mime.php';
/**
* @see Zend_Mail_Protocol_Smtp
*/
-require_once 'Zend/Mail/Protocol/Smtp.php';
+// require_once 'Zend/Mail/Protocol/Smtp.php';
/**
* @see Zend_Mail_Transport_Abstract
*/
-require_once 'Zend/Mail/Transport/Abstract.php';
+// require_once 'Zend/Mail/Transport/Abstract.php';
/**
@@ -45,7 +45,7 @@ require_once 'Zend/Mail/Transport/Abstract.php';
* @category Zend
* @package Zend_Mail
* @subpackage Transport
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mail_Transport_Smtp extends Zend_Mail_Transport_Abstract
@@ -111,6 +111,9 @@ class Zend_Mail_Transport_Smtp extends Zend_Mail_Transport_Abstract
* @param string $host OPTIONAL (Default: 127.0.0.1)
* @param array|null $config OPTIONAL (Default: null)
* @return void
+ *
+ * @todo Someone please make this compatible
+ * with the SendMail transport class.
*/
public function __construct($host = '127.0.0.1', Array $config = array())
{
@@ -177,6 +180,7 @@ class Zend_Mail_Transport_Smtp extends Zend_Mail_Transport_Abstract
* developer to add a custom adapter if required before mail is sent.
*
* @return void
+ * @todo Rename this to sendMail, it's a public method...
*/
public function _sendMail()
{
@@ -187,10 +191,10 @@ class Zend_Mail_Transport_Smtp extends Zend_Mail_Transport_Abstract
if ($this->_auth) {
$connectionClass .= '_Auth_' . ucwords($this->_auth);
}
- if (!class_exists($connectionClass)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($connectionClass);
- }
+ // if (!class_exists($connectionClass)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($connectionClass);
+ // }
$this->setConnection(new $connectionClass($this->_host, $this->_port, $this->_config));
$this->_connection->connect();
$this->_connection->helo($this->_name);
@@ -199,8 +203,8 @@ class Zend_Mail_Transport_Smtp extends Zend_Mail_Transport_Abstract
$this->_connection->rset();
}
- // Set mail return path from sender email address
- $this->_connection->mail($this->_mail->getReturnPath());
+ // Set sender email address
+ $this->_connection->mail($this->_mail->getFrom());
// Set recipient forward paths
foreach ($this->_mail->getRecipients() as $recipient) {
@@ -227,7 +231,7 @@ class Zend_Mail_Transport_Smtp extends Zend_Mail_Transport_Abstract
/**
* @see Zend_Mail_Transport_Exception
*/
- require_once 'Zend/Mail/Transport/Exception.php';
+ // require_once 'Zend/Mail/Transport/Exception.php';
throw new Zend_Mail_Transport_Exception('_prepareHeaders requires a registered Zend_Mail object');
}
diff --git a/libs/Zend/Mime.php b/libs/Zend/Mime.php
index 921cc1f16f..aa3582efe9 100644
--- a/libs/Zend/Mime.php
+++ b/libs/Zend/Mime.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Mime
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Mime.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Mime.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
@@ -25,7 +25,7 @@
*
* @category Zend
* @package Zend_Mime
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mime
diff --git a/libs/Zend/Mime/Decode.php b/libs/Zend/Mime/Decode.php
index c50b495cfd..b996a4a028 100644
--- a/libs/Zend/Mime/Decode.php
+++ b/libs/Zend/Mime/Decode.php
@@ -14,20 +14,20 @@
*
* @category Zend
* @package Zend_Mime
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Decode.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Decode.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Mime
*/
-require_once 'Zend/Mime.php';
+// require_once 'Zend/Mime.php';
/**
* @category Zend
* @package Zend_Mime
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mime_Decode
diff --git a/libs/Zend/Mime/Exception.php b/libs/Zend/Mime/Exception.php
index 4d2811f048..cb76e79c50 100644
--- a/libs/Zend/Mime/Exception.php
+++ b/libs/Zend/Mime/Exception.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Mime
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Exception
*/
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Mime
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mime_Exception extends Zend_Exception
diff --git a/libs/Zend/Mime/Message.php b/libs/Zend/Mime/Message.php
index 537107d2c7..781ac99246 100644
--- a/libs/Zend/Mime/Message.php
+++ b/libs/Zend/Mime/Message.php
@@ -14,27 +14,27 @@
*
* @category Zend
* @package Zend_Mime
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Message.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Message.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Mime
*/
-require_once 'Zend/Mime.php';
+// require_once 'Zend/Mime.php';
/**
* Zend_Mime_Part
*/
-require_once 'Zend/Mime/Part.php';
+// require_once 'Zend/Mime/Part.php';
/**
* @category Zend
* @package Zend_Mime
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mime_Message
@@ -242,7 +242,7 @@ class Zend_Mime_Message
*/
public static function createFromMessage($message, $boundary, $EOL = Zend_Mime::LINEEND)
{
- require_once 'Zend/Mime/Decode.php';
+ // require_once 'Zend/Mime/Decode.php';
$parts = Zend_Mime_Decode::splitMessageStruct($message, $boundary, $EOL);
$res = new self();
diff --git a/libs/Zend/Mime/Part.php b/libs/Zend/Mime/Part.php
index 6609b51a76..96e20d09a3 100644
--- a/libs/Zend/Mime/Part.php
+++ b/libs/Zend/Mime/Part.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Mime
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Part.php 16541 2009-07-07 06:59:03Z bkarwin $
+ * @version $Id: Part.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* Zend_Mime
*/
-require_once 'Zend/Mime.php';
+// require_once 'Zend/Mime.php';
/**
* Class representing a MIME part.
*
* @category Zend
* @package Zend_Mime
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Mime_Part {
@@ -92,7 +92,7 @@ class Zend_Mime_Part {
public function getEncodedStream()
{
if (!$this->_isStream) {
- require_once 'Zend/Mime/Exception.php';
+ // require_once 'Zend/Mime/Exception.php';
throw new Zend_Mime_Exception('Attempt to get a stream from a string part');
}
@@ -109,7 +109,7 @@ class Zend_Mime_Part {
)
);
if (!is_resource($filter)) {
- require_once 'Zend/Mime/Exception.php';
+ // require_once 'Zend/Mime/Exception.php';
throw new Zend_Mime_Exception('Failed to append quoted-printable filter');
}
break;
@@ -124,7 +124,7 @@ class Zend_Mime_Part {
)
);
if (!is_resource($filter)) {
- require_once 'Zend/Mime/Exception.php';
+ // require_once 'Zend/Mime/Exception.php';
throw new Zend_Mime_Exception('Failed to append base64 filter');
}
break;
diff --git a/libs/Zend/Registry.php b/libs/Zend/Registry.php
index d801d1220b..845ef66bba 100644
--- a/libs/Zend/Registry.php
+++ b/libs/Zend/Registry.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Registry
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Registry.php 16207 2009-06-21 19:17:51Z thomas $
+ * @version $Id: Registry.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
@@ -24,7 +24,7 @@
*
* @category Zend
* @package Zend_Registry
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Registry extends ArrayObject
@@ -66,7 +66,7 @@ class Zend_Registry extends ArrayObject
public static function setInstance(Zend_Registry $registry)
{
if (self::$_registry !== null) {
- require_once 'Zend/Exception.php';
+ // require_once 'Zend/Exception.php';
throw new Zend_Exception('Registry is already initialized');
}
@@ -97,22 +97,22 @@ class Zend_Registry extends ArrayObject
public static function setClassName($registryClassName = 'Zend_Registry')
{
if (self::$_registry !== null) {
- require_once 'Zend/Exception.php';
+ // require_once 'Zend/Exception.php';
throw new Zend_Exception('Registry is already initialized');
}
if (!is_string($registryClassName)) {
- require_once 'Zend/Exception.php';
+ // require_once 'Zend/Exception.php';
throw new Zend_Exception("Argument is not a class name");
}
/**
* @see Zend_Loader
*/
- if (!class_exists($registryClassName)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($registryClassName);
- }
+ // if (!class_exists($registryClassName)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($registryClassName);
+ // }
self::$_registryClassName = $registryClassName;
}
@@ -143,7 +143,7 @@ class Zend_Registry extends ArrayObject
$instance = self::getInstance();
if (!$instance->offsetExists($index)) {
- require_once 'Zend/Exception.php';
+ // require_once 'Zend/Exception.php';
throw new Zend_Exception("No entry is registered for key '$index'");
}
diff --git a/libs/Zend/Session.php b/libs/Zend/Session.php
index 31ab5a50a1..e361d15db2 100644
--- a/libs/Zend/Session.php
+++ b/libs/Zend/Session.php
@@ -15,9 +15,9 @@
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Session.php 18342 2009-09-21 16:31:18Z alexander $
+ * @version $Id: Session.php 20096 2010-01-06 02:05:09Z bkarwin $
* @since Preview Release 0.2
*/
@@ -25,17 +25,17 @@
/**
* @see Zend_Session_Abstract
*/
-require_once 'Zend/Session/Abstract.php';
+// require_once 'Zend/Session/Abstract.php';
/**
* @see Zend_Session_Namespace
*/
-require_once 'Zend/Session/Namespace.php';
+// require_once 'Zend/Session/Namespace.php';
/**
* @see Zend_Session_SaveHandler_Interface
*/
-require_once 'Zend/Session/SaveHandler/Interface.php';
+// require_once 'Zend/Session/SaveHandler/Interface.php';
/**
@@ -43,7 +43,7 @@ require_once 'Zend/Session/SaveHandler/Interface.php';
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Session extends Zend_Session_Abstract
@@ -62,7 +62,7 @@ class Zend_Session extends Zend_Session_Abstract
* @var bool|bitset This could also be a combiniation of error codes to catch
*/
protected static $_throwStartupExceptions = true;
-
+
/**
* Check whether or not the session was started
*
@@ -223,7 +223,7 @@ class Zend_Session extends Zend_Session_Abstract
}
else {
/** @see Zend_Session_Exception */
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception("Unknown option: $userOptionName = $userOptionValue");
}
}
@@ -244,14 +244,14 @@ class Zend_Session extends Zend_Session_Abstract
foreach (self::$_localOptions as $localOptionName => $localOptionMemberName) {
$options[$localOptionName] = self::${$localOptionMemberName};
}
-
+
if ($optionName) {
if (array_key_exists($optionName, $options)) {
return $options[$optionName];
}
return null;
}
-
+
return $options;
}
@@ -303,7 +303,7 @@ class Zend_Session extends Zend_Session_Abstract
{
if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
/** @see Zend_Session_Exception */
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception("You must call " . __CLASS__ . '::' . __FUNCTION__ .
"() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
}
@@ -427,7 +427,7 @@ class Zend_Session extends Zend_Session_Abstract
public static function start($options = false)
{
if (self::$_sessionStarted && self::$_destroyed) {
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('The session was explicitly destroyed during this request, attempting to re-start is not allowed.');
}
@@ -443,14 +443,14 @@ class Zend_Session extends Zend_Session_Abstract
// In strict mode, do not allow auto-starting Zend_Session, such as via "new Zend_Session_Namespace()"
if (self::$_strict && $options === true) {
/** @see Zend_Session_Exception */
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('You must explicitly start the session with Zend_Session::start() when session options are set to strict.');
}
$filename = $linenum = null;
if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
/** @see Zend_Session_Exception */
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception("Session must be started before any output has been sent to the browser;"
. " output started in {$filename}/{$linenum}");
}
@@ -458,7 +458,7 @@ class Zend_Session extends Zend_Session_Abstract
// See http://www.php.net/manual/en/ref.session.php for explanation
if (!self::$_unitTestEnabled && defined('SID')) {
/** @see Zend_Session_Exception */
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('session has already been started by session.auto-start or session_start()');
}
@@ -466,23 +466,23 @@ class Zend_Session extends Zend_Session_Abstract
* Hack to throw exceptions on start instead of php errors
* @see http://framework.zend.com/issues/browse/ZF-1325
*/
-
+
$errorLevel = (is_int(self::$_throwStartupExceptions)) ? self::$_throwStartupExceptions : E_ALL;
-
+
/** @see Zend_Session_Exception */
if (!self::$_unitTestEnabled) {
-
+
if (self::$_throwStartupExceptions) {
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
set_error_handler(array('Zend_Session_Exception', 'handleSessionStartError'), $errorLevel);
}
-
+
$startedCleanly = session_start();
-
+
if (self::$_throwStartupExceptions) {
restore_error_handler();
}
-
+
if (!$startedCleanly || Zend_Session_Exception::$sessionStartError != null) {
if (self::$_throwStartupExceptions) {
set_error_handler(array('Zend_Session_Exception', 'handleSilentWriteClose'), $errorLevel);
@@ -528,7 +528,7 @@ class Zend_Session extends Zend_Session_Abstract
// Expire Namespace by Time (ENT)
if (isset($namespace_metadata['ENT']) && ($namespace_metadata['ENT'] > 0) && (time() > $namespace_metadata['ENT']) ) {
unset($_SESSION[$namespace]);
- unset($_SESSION['__ZF'][$namespace]['ENT']);
+ unset($_SESSION['__ZF'][$namespace]);
}
// Expire Namespace by Global Hop (ENGH)
@@ -540,7 +540,7 @@ class Zend_Session extends Zend_Session_Abstract
parent::$_expiringData[$namespace] = $_SESSION[$namespace];
unset($_SESSION[$namespace]);
}
- unset($_SESSION['__ZF'][$namespace]['ENGH']);
+ unset($_SESSION['__ZF'][$namespace]);
}
}
@@ -550,12 +550,11 @@ class Zend_Session extends Zend_Session_Abstract
if (time() > $time) {
unset($_SESSION[$namespace][$variable]);
unset($_SESSION['__ZF'][$namespace]['ENVT'][$variable]);
-
- if (empty($_SESSION['__ZF'][$namespace]['ENVT'])) {
- unset($_SESSION['__ZF'][$namespace]['ENVT']);
- }
}
}
+ if (empty($_SESSION['__ZF'][$namespace]['ENVT'])) {
+ unset($_SESSION['__ZF'][$namespace]['ENVT']);
+ }
}
// Expire Namespace Variables by Global Hop (ENVGH)
@@ -571,6 +570,9 @@ class Zend_Session extends Zend_Session_Abstract
unset($_SESSION['__ZF'][$namespace]['ENVGH'][$variable]);
}
}
+ if(empty($_SESSION['__ZF'][$namespace]['ENVGH'])) {
+ unset($_SESSION['__ZF'][$namespace]['ENVGH']);
+ }
}
}
@@ -630,20 +632,20 @@ class Zend_Session extends Zend_Session_Abstract
{
if (!self::$_unitTestEnabled && defined('SID')) {
/** @see Zend_Session_Exception */
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('The session has already been started. The session id must be set first.');
}
if (!self::$_unitTestEnabled && headers_sent($filename, $linenum)) {
/** @see Zend_Session_Exception */
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception("You must call ".__CLASS__.'::'.__FUNCTION__.
"() before any output has been sent to the browser; output started in {$filename}/{$linenum}");
}
if (!is_string($id) || $id === '') {
/** @see Zend_Session_Exception */
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('You must provide a non-empty string as a session identifier.');
}
@@ -772,14 +774,14 @@ class Zend_Session extends Zend_Session_Abstract
private static function _processValidators()
{
foreach ($_SESSION['__ZF']['VALID'] as $validator_name => $valid_data) {
- if (!class_exists($validator_name)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($validator_name);
- }
+ // if (!class_exists($validator_name)) {
+ // require_once 'Zend/Loader.php';
+ // Zend_Loader::loadClass($validator_name);
+ // }
$validator = new $validator_name;
if ($validator->validate() === false) {
/** @see Zend_Session_Exception */
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception("This session is not valid according to {$validator_name}.");
}
}
@@ -836,7 +838,7 @@ class Zend_Session extends Zend_Session_Abstract
{
if (parent::$_readable === false) {
/** @see Zend_Session_Exception */
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception(parent::_THROW_NOT_READABLE_MSG);
}
diff --git a/libs/Zend/Session/Abstract.php b/libs/Zend/Session/Abstract.php
index 448afbf5c5..2c5b613e95 100644
--- a/libs/Zend/Session/Abstract.php
+++ b/libs/Zend/Session/Abstract.php
@@ -15,9 +15,9 @@
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 16210 2009-06-21 19:22:17Z thomas $
+ * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
* @since Preview Release 0.2
*/
@@ -27,7 +27,7 @@
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Session_Abstract
@@ -82,7 +82,7 @@ abstract class Zend_Session_Abstract
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception(self::_THROW_NOT_READABLE_MSG);
}
@@ -108,7 +108,7 @@ abstract class Zend_Session_Abstract
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception(self::_THROW_NOT_WRITABLE_MSG);
}
@@ -143,7 +143,7 @@ abstract class Zend_Session_Abstract
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception(self::_THROW_NOT_READABLE_MSG);
}
diff --git a/libs/Zend/Session/Exception.php b/libs/Zend/Session/Exception.php
index 29ca6aa954..dc8aa638ff 100644
--- a/libs/Zend/Session/Exception.php
+++ b/libs/Zend/Session/Exception.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16210 2009-06-21 19:22:17Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
* @since Preview Release 0.2
*/
@@ -24,7 +24,7 @@
/**
* @see Zend_Exception
*/
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
@@ -32,7 +32,7 @@ require_once 'Zend/Exception.php';
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Session_Exception extends Zend_Exception
diff --git a/libs/Zend/Session/Namespace.php b/libs/Zend/Session/Namespace.php
index a18a66c99a..ef811a066b 100644
--- a/libs/Zend/Session/Namespace.php
+++ b/libs/Zend/Session/Namespace.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Namespace.php 16210 2009-06-21 19:22:17Z thomas $
+ * @version $Id: Namespace.php 20096 2010-01-06 02:05:09Z bkarwin $
* @since Preview Release 0.2
*/
@@ -24,13 +24,13 @@
/**
* @see Zend_Session
*/
-require_once 'Zend/Session.php';
+// require_once 'Zend/Session.php';
/**
* @see Zend_Session_Abstract
*/
-require_once 'Zend/Session/Abstract.php';
+// require_once 'Zend/Session/Abstract.php';
/**
@@ -38,7 +38,7 @@ require_once 'Zend/Session/Abstract.php';
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAggregate
@@ -84,11 +84,11 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
}
return;
}
-
+
self::$_singleInstances = array();
return;
}
-
+
/**
* __construct() - Returns an instance object bound to a particular, isolated section
* of the session, identified by $namespace name (defaulting to 'Default').
@@ -105,7 +105,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('Session namespace must be a non-empty string.');
}
@@ -113,7 +113,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('Session namespace must not start with an underscore.');
}
@@ -121,7 +121,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('Session namespace must not start with a number.');
}
@@ -129,7 +129,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception("A session namespace object already exists for this namespace ('$namespace'), and no additional accessors (session namespace objects) for this namespace are permitted.");
}
@@ -146,7 +146,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception(self::_THROW_NOT_READABLE_MSG);
}
@@ -167,7 +167,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
self::$_expiringData[$namespace] = $_SESSION[$namespace];
unset($_SESSION[$namespace]);
}
- unset($_SESSION['__ZF'][$namespace]['ENNH']);
+ unset($_SESSION['__ZF'][$namespace]);
}
}
@@ -184,6 +184,9 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
unset($_SESSION['__ZF'][$namespace]['ENVNH'][$variable]);
}
}
+ if(empty($_SESSION['__ZF'][$namespace]['ENVNH'])) {
+ unset($_SESSION['__ZF'][$namespace]['ENVNH']);
+ }
}
}
@@ -277,7 +280,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception("The '$name' key must be a non-empty string");
}
@@ -299,7 +302,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('This session/namespace has been marked as read-only.');
}
@@ -307,7 +310,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception("The '$name' key must be a non-empty string");
}
@@ -315,7 +318,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception(parent::_THROW_NOT_WRITABLE_MSG);
}
@@ -364,7 +367,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('Result must be an array. Got: ' . gettype($result));
}
$_SESSION[$this->_namespace] = $result;
@@ -384,7 +387,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception("The '$name' key must be a non-empty string");
}
@@ -404,7 +407,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception("The '$name' key must be a non-empty string");
}
@@ -427,7 +430,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception(parent::_THROW_NOT_WRITABLE_MSG);
}
@@ -435,7 +438,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('Seconds must be positive.');
}
@@ -475,7 +478,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception(parent::_THROW_NOT_WRITABLE_MSG);
}
@@ -483,7 +486,7 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
/**
* @see Zend_Session_Exception
*/
- require_once 'Zend/Session/Exception.php';
+ // require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('Hops must be positive number.');
}
@@ -514,4 +517,13 @@ class Zend_Session_Namespace extends Zend_Session_Abstract implements IteratorAg
}
}
+ /**
+ * Returns the namespace name
+ *
+ * @return string
+ */
+ public function getNamespace()
+ {
+ return $this->_namespace;
+ }
}
diff --git a/libs/Zend/Session/SaveHandler/DbTable.php b/libs/Zend/Session/SaveHandler/DbTable.php
index 84a7f73180..b59526d3a9 100644
--- a/libs/Zend/Session/SaveHandler/DbTable.php
+++ b/libs/Zend/Session/SaveHandler/DbTable.php
@@ -15,30 +15,30 @@
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: DbTable.php 16933 2009-07-21 20:24:35Z matthew $
+ * @version $Id: DbTable.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Session
*/
-require_once 'Zend/Session.php';
+// require_once 'Zend/Session.php';
/**
* @see Zend_Db_Table_Abstract
*/
-require_once 'Zend/Db/Table/Abstract.php';
+// require_once 'Zend/Db/Table/Abstract.php';
/**
* @see Zend_Db_Table_Row_Abstract
*/
-require_once 'Zend/Db/Table/Row/Abstract.php';
+// require_once 'Zend/Db/Table/Row/Abstract.php';
/**
* @see Zend_Config
*/
-require_once 'Zend/Config.php';
+// require_once 'Zend/Config.php';
/**
* Zend_Session_SaveHandler_DbTable
@@ -46,11 +46,11 @@ require_once 'Zend/Config.php';
* @category Zend
* @package Zend_Session
* @subpackage SaveHandler
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Session_SaveHandler_DbTable
- extends Zend_Db_Table_Abstract
+class Zend_Session_SaveHandler_DbTable
+ extends Zend_Db_Table_Abstract
implements Zend_Session_SaveHandler_Interface
{
const PRIMARY_ASSIGNMENT = 'primaryAssignment';
@@ -168,7 +168,7 @@ class Zend_Session_SaveHandler_DbTable
/**
* @see Zend_Session_SaveHandler_Exception
*/
- require_once 'Zend/Session/SaveHandler/Exception.php';
+ // require_once 'Zend/Session/SaveHandler/Exception.php';
throw new Zend_Session_SaveHandler_Exception(
'$config must be an instance of Zend_Config or array of key/value pairs containing '
@@ -232,7 +232,7 @@ class Zend_Session_SaveHandler_DbTable
/**
* @see Zend_Session_SaveHandler_Exception
*/
- require_once 'Zend/Session/SaveHandler/Exception.php';
+ // require_once 'Zend/Session/SaveHandler/Exception.php';
throw new Zend_Session_SaveHandler_Exception();
} else if (empty($lifetime)) {
$this->_lifetime = (int) ini_get('session.gc_maxlifetime');
@@ -420,7 +420,7 @@ class Zend_Session_SaveHandler_DbTable
/**
* @see Zend_Session_SaveHandler_Exception
*/
- require_once 'Zend/Session/SaveHandler/Exception.php';
+ // require_once 'Zend/Session/SaveHandler/Exception.php';
throw new Zend_Session_SaveHandler_Exception('session.save_path is a path and not a table name.');
}
@@ -452,7 +452,7 @@ class Zend_Session_SaveHandler_DbTable
/**
* @see Zend_Session_SaveHandler_Exception
*/
- require_once 'Zend/Session/SaveHandler/Exception.php';
+ // require_once 'Zend/Session/SaveHandler/Exception.php';
throw new Zend_Session_SaveHandler_Exception(
"Value for configuration option '" . self::PRIMARY_ASSIGNMENT . "' must have an assignment "
@@ -461,7 +461,7 @@ class Zend_Session_SaveHandler_DbTable
/**
* @see Zend_Session_SaveHandler_Exception
*/
- require_once 'Zend/Session/SaveHandler/Exception.php';
+ // require_once 'Zend/Session/SaveHandler/Exception.php';
throw new Zend_Session_SaveHandler_Exception(
"Value for configuration option '" . self::PRIMARY_ASSIGNMENT . "' must have an assignment "
@@ -481,7 +481,7 @@ class Zend_Session_SaveHandler_DbTable
/**
* @see Zend_Session_SaveHandler_Exception
*/
- require_once 'Zend/Session/SaveHandler/Exception.php';
+ // require_once 'Zend/Session/SaveHandler/Exception.php';
throw new Zend_Session_SaveHandler_Exception(
"Configuration must define '" . self::MODIFIED_COLUMN . "' which names the "
@@ -490,7 +490,7 @@ class Zend_Session_SaveHandler_DbTable
/**
* @see Zend_Session_SaveHandler_Exception
*/
- require_once 'Zend/Session/SaveHandler/Exception.php';
+ // require_once 'Zend/Session/SaveHandler/Exception.php';
throw new Zend_Session_SaveHandler_Exception(
"Configuration must define '" . self::LIFETIME_COLUMN . "' which names the "
@@ -499,7 +499,7 @@ class Zend_Session_SaveHandler_DbTable
/**
* @see Zend_Session_SaveHandler_Exception
*/
- require_once 'Zend/Session/SaveHandler/Exception.php';
+ // require_once 'Zend/Session/SaveHandler/Exception.php';
throw new Zend_Session_SaveHandler_Exception(
"Configuration must define '" . self::DATA_COLUMN . "' which names the "
@@ -516,7 +516,7 @@ class Zend_Session_SaveHandler_DbTable
*/
protected function _getPrimary($id, $type = null)
{
- $this->_setupPrimaryKey();
+ $this->_setupPrimaryKey();
if ($type === null) {
$type = self::PRIMARY_TYPE_NUM;
diff --git a/libs/Zend/Session/SaveHandler/Exception.php b/libs/Zend/Session/SaveHandler/Exception.php
index bb2124702d..249dcfa930 100644
--- a/libs/Zend/Session/SaveHandler/Exception.php
+++ b/libs/Zend/Session/SaveHandler/Exception.php
@@ -15,22 +15,22 @@
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16210 2009-06-21 19:22:17Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Session_Exception
*/
-require_once 'Zend/Session/Exception.php';
+// require_once 'Zend/Session/Exception.php';
/**
* Zend_Session_SaveHandler_Exception
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Session_SaveHandler_Exception extends Zend_Session_Exception
diff --git a/libs/Zend/Session/SaveHandler/Interface.php b/libs/Zend/Session/SaveHandler/Interface.php
index 2e4945a5d7..6e426974a7 100644
--- a/libs/Zend/Session/SaveHandler/Interface.php
+++ b/libs/Zend/Session/SaveHandler/Interface.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16210 2009-06-21 19:22:17Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
* @since Preview Release 0.2
*/
@@ -26,7 +26,7 @@
* @category Zend
* @package Zend_Session
* @subpackage SaveHandler
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @see http://php.net/session_set_save_handler
*/
diff --git a/libs/Zend/Session/Validator/Abstract.php b/libs/Zend/Session/Validator/Abstract.php
index e1a53f971a..6c4caaeb94 100644
--- a/libs/Zend/Session/Validator/Abstract.php
+++ b/libs/Zend/Session/Validator/Abstract.php
@@ -14,16 +14,16 @@
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 16210 2009-06-21 19:22:17Z thomas $
+ * @version $Id: Abstract.php 20096 2010-01-06 02:05:09Z bkarwin $
* @since Preview Release 0.2
*/
/**
* @see Zend_Session_Validator_Interface
*/
-require_once 'Zend/Session/Validator/Interface.php';
+// require_once 'Zend/Session/Validator/Interface.php';
/**
* Zend_Session_Validator_Abstract
@@ -31,7 +31,7 @@ require_once 'Zend/Session/Validator/Interface.php';
* @category Zend
* @package Zend_Session
* @subpackage Validator
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Session_Validator_Abstract implements Zend_Session_Validator_Interface
diff --git a/libs/Zend/Session/Validator/HttpUserAgent.php b/libs/Zend/Session/Validator/HttpUserAgent.php
index 3dccf9e32f..fef7d33329 100644
--- a/libs/Zend/Session/Validator/HttpUserAgent.php
+++ b/libs/Zend/Session/Validator/HttpUserAgent.php
@@ -14,16 +14,16 @@
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: HttpUserAgent.php 16210 2009-06-21 19:22:17Z thomas $
+ * @version $Id: HttpUserAgent.php 20096 2010-01-06 02:05:09Z bkarwin $
* @since Preview Release 0.2
*/
/**
* @see Zend_Session_Validator_Abstract
*/
-require_once 'Zend/Session/Validator/Abstract.php';
+// require_once 'Zend/Session/Validator/Abstract.php';
/**
* Zend_Session_Validator_HttpUserAgent
@@ -31,7 +31,7 @@ require_once 'Zend/Session/Validator/Abstract.php';
* @category Zend
* @package Zend_Session
* @subpackage Validator
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Session_Validator_HttpUserAgent extends Zend_Session_Validator_Abstract
diff --git a/libs/Zend/Session/Validator/Interface.php b/libs/Zend/Session/Validator/Interface.php
index b0d9825e90..eab9d186cd 100644
--- a/libs/Zend/Session/Validator/Interface.php
+++ b/libs/Zend/Session/Validator/Interface.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Session
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16210 2009-06-21 19:22:17Z thomas $
+ * @version $Id: Interface.php 20096 2010-01-06 02:05:09Z bkarwin $
* @since Preview Release 0.2
*/
@@ -26,7 +26,7 @@
* @category Zend
* @package Zend_Session
* @subpackage Validator
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Session_Validator_Interface
diff --git a/libs/Zend/Uri.php b/libs/Zend/Uri.php
index abbe5a248c..ad4c43ee99 100644
--- a/libs/Zend/Uri.php
+++ b/libs/Zend/Uri.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Uri
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Uri.php 16207 2009-06-21 19:17:51Z thomas $
+ * @version $Id: Uri.php 22083 2010-05-03 18:49:28Z shahar $
*/
/**
@@ -24,7 +24,7 @@
*
* @category Zend
* @package Zend_Uri
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Uri
@@ -44,7 +44,7 @@ abstract class Zend_Uri
static protected $_config = array(
'allow_unwise' => false
);
-
+
/**
* Return a string representation of this URI.
*
@@ -79,14 +79,16 @@ abstract class Zend_Uri
* Create a new Zend_Uri object for a URI. If building a new URI, then $uri should contain
* only the scheme (http, ftp, etc). Otherwise, supply $uri with the complete URI.
*
- * @param string $uri The URI form which a Zend_Uri instance is created
+ * @param string $uri The URI form which a Zend_Uri instance is created
+ * @param string $className The name of the class to use in order to manipulate URI
* @throws Zend_Uri_Exception When an empty string was supplied for the scheme
* @throws Zend_Uri_Exception When an illegal scheme is supplied
* @throws Zend_Uri_Exception When the scheme is not supported
+ * @throws Zend_Uri_Exception When $className doesn't exist or doesn't implements Zend_Uri
* @return Zend_Uri
* @link http://www.faqs.org/rfcs/rfc2396.html
*/
- public static function factory($uri = 'http')
+ public static function factory($uri = 'http', $className = null)
{
// Separate the scheme from the scheme-specific parts
$uri = explode(':', $uri, 2);
@@ -94,41 +96,54 @@ abstract class Zend_Uri
$schemeSpecific = isset($uri[1]) === true ? $uri[1] : '';
if (strlen($scheme) === 0) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('An empty string was supplied for the scheme');
}
// Security check: $scheme is used to load a class file, so only alphanumerics are allowed.
if (ctype_alnum($scheme) === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('Illegal scheme supplied, only alphanumeric characters are permitted');
}
- /**
- * Create a new Zend_Uri object for the $uri. If a subclass of Zend_Uri exists for the
- * scheme, return an instance of that class. Otherwise, a Zend_Uri_Exception is thrown.
- */
- switch ($scheme) {
- case 'http':
- // Break intentionally omitted
- case 'https':
- $className = 'Zend_Uri_Http';
- break;
-
- case 'mailto':
- // TODO
- default:
- require_once 'Zend/Uri/Exception.php';
- throw new Zend_Uri_Exception("Scheme \"$scheme\" is not supported");
- break;
- }
+ if ($className === null) {
+ /**
+ * Create a new Zend_Uri object for the $uri. If a subclass of Zend_Uri exists for the
+ * scheme, return an instance of that class. Otherwise, a Zend_Uri_Exception is thrown.
+ */
+ switch ($scheme) {
+ case 'http':
+ // Break intentionally omitted
+ case 'https':
+ $className = 'Zend_Uri_Http';
+ break;
- if (!class_exists($className)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($className);
+ case 'mailto':
+ // TODO
+ default:
+ // require_once 'Zend/Uri/Exception.php';
+ throw new Zend_Uri_Exception("Scheme \"$scheme\" is not supported");
+ break;
+ }
}
+
+ // if (!class_exists($className)) {
+ // require_once 'Zend/Loader.php';
+ // try {
+ // Zend_Loader::loadClass($className);
+ // } catch (Exception $e) {
+ // require_once 'Zend/Uri/Exception.php';
+ // throw new Zend_Uri_Exception("\"$className\" not found");
+ // }
+ // }
+
$schemeHandler = new $className($scheme, $schemeSpecific);
+ if (! $schemeHandler instanceof Zend_Uri) {
+ // require_once 'Zend/Uri/Exception.php';
+ throw new Zend_Uri_Exception("\"$className\" is not an instance of Zend_Uri");
+ }
+
return $schemeHandler;
}
@@ -149,15 +164,21 @@ abstract class Zend_Uri
/**
* Set global configuration options
*
- * @param array $config
+ * @param Zend_Config|array $config
*/
- static public function setConfig(array $config)
+ static public function setConfig($config)
{
+ if ($config instanceof Zend_Config) {
+ $config = $config->toArray();
+ } elseif (!is_array($config)) {
+ throw new Zend_Uri_Exception("Config must be an array or an instance of Zend_Config.");
+ }
+
foreach ($config as $k => $v) {
self::$_config[$k] = $v;
}
}
-
+
/**
* Zend_Uri and its subclasses cannot be instantiated directly.
* Use Zend_Uri::factory() to return a new Zend_Uri object.
diff --git a/libs/Zend/Uri/Exception.php b/libs/Zend/Uri/Exception.php
index 5f68ac9f67..ba2f1a8342 100644
--- a/libs/Zend/Uri/Exception.php
+++ b/libs/Zend/Uri/Exception.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Uri
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16208 2009-06-21 19:19:26Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Exception
*/
-require_once 'Zend/Exception.php';
+// require_once 'Zend/Exception.php';
/**
* Exceptions for Zend_Uri
*
* @category Zend
* @package Zend_Uri
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Uri_Exception extends Zend_Exception
diff --git a/libs/Zend/Uri/Http.php b/libs/Zend/Uri/Http.php
index c8ef6ac360..48911dad64 100644
--- a/libs/Zend/Uri/Http.php
+++ b/libs/Zend/Uri/Http.php
@@ -14,20 +14,20 @@
*
* @category Zend
* @package Zend_Uri
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Http.php 16208 2009-06-21 19:19:26Z thomas $
+ * @version $Id: Http.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Uri
*/
-require_once 'Zend/Uri.php';
+// require_once 'Zend/Uri.php';
/**
* @see Zend_Validate_Hostname
*/
-require_once 'Zend/Validate/Hostname.php';
+// require_once 'Zend/Validate/Hostname.php';
/**
* HTTP(S) URI handler
@@ -35,7 +35,7 @@ require_once 'Zend/Validate/Hostname.php';
* @category Zend
* @package Zend_Uri
* @uses Zend_Uri
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Uri_Http extends Zend_Uri
@@ -152,7 +152,7 @@ class Zend_Uri_Http extends Zend_Uri
// Validate the URI
if ($this->valid() === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('Invalid URI supplied');
}
}
@@ -170,7 +170,7 @@ class Zend_Uri_Http extends Zend_Uri
public static function fromString($uri)
{
if (is_string($uri) === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('$uri is not a string');
}
@@ -179,7 +179,7 @@ class Zend_Uri_Http extends Zend_Uri
$schemeSpecific = isset($uri[1]) === true ? $uri[1] : '';
if (in_array($scheme, array('http', 'https')) === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception("Invalid scheme: '$scheme'");
}
@@ -201,7 +201,7 @@ class Zend_Uri_Http extends Zend_Uri
$pattern = '~^((//)([^/?#]*))([^?#]*)(\?([^#]*))?(#(.*))?$~';
$status = @preg_match($pattern, $schemeSpecific, $matches);
if ($status === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('Internal error: scheme-specific decomposition failed');
}
@@ -220,7 +220,7 @@ class Zend_Uri_Http extends Zend_Uri
$pattern = '~^(([^:@]*)(:([^@]*))?@)?([^:]+)(:(.*))?$~';
$status = @preg_match($pattern, $combo, $matches);
if ($status === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('Internal error: authority decomposition failed');
}
@@ -247,7 +247,7 @@ class Zend_Uri_Http extends Zend_Uri
public function getUri()
{
if ($this->valid() === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('One or more parts of the URI are invalid');
}
@@ -320,7 +320,7 @@ class Zend_Uri_Http extends Zend_Uri
self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $username);
if ($status === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('Internal error: username validation failed');
}
@@ -337,7 +337,7 @@ class Zend_Uri_Http extends Zend_Uri
public function setUsername($username)
{
if ($this->validateUsername($username) === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception("Username \"$username\" is not a valid HTTP username");
}
@@ -387,7 +387,7 @@ class Zend_Uri_Http extends Zend_Uri
self::CHAR_ALNUM . self::CHAR_MARK . ';:&=+$,' . '])+$/', $password);
if ($status === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('Internal error: password validation failed.');
}
@@ -404,7 +404,7 @@ class Zend_Uri_Http extends Zend_Uri
public function setPassword($password)
{
if ($this->validatePassword($password) === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception("Password \"$password\" is not a valid HTTP password.");
}
@@ -459,7 +459,7 @@ class Zend_Uri_Http extends Zend_Uri
public function setHost($host)
{
if ($this->validateHost($host) === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception("Host \"$host\" is not a valid HTTP host");
}
@@ -511,7 +511,7 @@ class Zend_Uri_Http extends Zend_Uri
public function setPort($port)
{
if ($this->validatePort($port) === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception("Port \"$port\" is not a valid HTTP port.");
}
@@ -554,7 +554,7 @@ class Zend_Uri_Http extends Zend_Uri
$pattern = '/^' . $this->_regex['path'] . '$/';
$status = @preg_match($pattern, $path);
if ($status === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('Internal error: path validation failed');
}
@@ -571,7 +571,7 @@ class Zend_Uri_Http extends Zend_Uri
public function setPath($path)
{
if ($this->validatePath($path) === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception("Path \"$path\" is not a valid HTTP path");
}
@@ -592,6 +592,23 @@ class Zend_Uri_Http extends Zend_Uri
}
/**
+ * Returns the query portion of the URL (after ?) as a
+ * key-value-array. If the query is empty an empty array
+ * is returned
+ *
+ * @return array
+ */
+ public function getQueryAsArray()
+ {
+ $query = $this->getQuery();
+ $querryArray = array();
+ if ($query !== false) {
+ parse_str($query, $querryArray);
+ }
+ return $querryArray;
+ }
+
+ /**
* Returns true if and only if the query string passes validation. If no query is passed,
* then the query string contained in the instance variable is used.
*
@@ -615,7 +632,7 @@ class Zend_Uri_Http extends Zend_Uri
$pattern = '/^' . $this->_regex['uric'] . '*$/';
$status = @preg_match($pattern, $query);
if ($status === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('Internal error: query validation failed');
}
@@ -623,6 +640,32 @@ class Zend_Uri_Http extends Zend_Uri
}
/**
+ * Add or replace params in the query string for the current URI, and
+ * return the old query.
+ *
+ * @param array $queryParams
+ * @return string Old query string
+ */
+ public function addReplaceQueryParameters(array $queryParams)
+ {
+ $queryParams = array_merge($this->getQueryAsArray(), $queryParams);
+ return $this->setQuery($queryParams);
+ }
+
+ /**
+ * Remove params in the query string for the current URI, and
+ * return the old query.
+ *
+ * @param array $queryParamKeys
+ * @return string Old query string
+ */
+ public function removeQueryParameters(array $queryParamKeys)
+ {
+ $queryParams = array_diff_key($this->getQueryAsArray(), array_fill_keys($queryParamKeys, 0));
+ return $this->setQuery($queryParams);
+ }
+
+ /**
* Set the query string for the current URI, and return the old query
* string This method accepts both strings and arrays.
*
@@ -654,7 +697,7 @@ class Zend_Uri_Http extends Zend_Uri
// Make sure the query is valid, and set it
if ($this->validateQuery($query) === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception("'$query' is not a valid query string");
}
@@ -697,7 +740,7 @@ class Zend_Uri_Http extends Zend_Uri
$pattern = '/^' . $this->_regex['uric'] . '*$/';
$status = @preg_match($pattern, $fragment);
if ($status === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception('Internal error: fragment validation failed');
}
@@ -714,7 +757,7 @@ class Zend_Uri_Http extends Zend_Uri
public function setFragment($fragment)
{
if ($this->validateFragment($fragment) === false) {
- require_once 'Zend/Uri/Exception.php';
+ // require_once 'Zend/Uri/Exception.php';
throw new Zend_Uri_Exception("Fragment \"$fragment\" is not a valid HTTP fragment");
}
diff --git a/libs/Zend/Validate.php b/libs/Zend/Validate.php
index cb87ba5120..f14eb671e7 100644
--- a/libs/Zend/Validate.php
+++ b/libs/Zend/Validate.php
@@ -14,20 +14,20 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Validate.php 16286 2009-06-25 15:11:37Z thomas $
+ * @version $Id: Validate.php 21340 2010-03-05 15:33:49Z thomas $
*/
/**
* @see Zend_Validate_Interface
*/
-require_once 'Zend/Validate/Interface.php';
+// require_once 'Zend/Validate/Interface.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate implements Zend_Validate_Interface
@@ -195,30 +195,52 @@ class Zend_Validate implements Zend_Validate_Interface
public static function is($value, $classBaseName, array $args = array(), $namespaces = array())
{
$namespaces = array_merge((array) $namespaces, self::$_defaultNamespaces, array('Zend_Validate'));
- foreach ($namespaces as $namespace) {
- $className = $namespace . '_' . ucfirst($classBaseName);
- try {
- if (!class_exists($className)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($className);
+ $className = ucfirst($classBaseName);
+ try {
+ if (!class_exists($className, false)) {
+ // require_once 'Zend/Loader.php';
+ foreach($namespaces as $namespace) {
+ $class = $namespace . '_' . $className;
+ $file = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
+ if (Zend_Loader::isReadable($file)) {
+ Zend_Loader::loadClass($class);
+ $className = $class;
+ break;
+ }
}
- $class = new ReflectionClass($className);
- if ($class->implementsInterface('Zend_Validate_Interface')) {
- if ($class->hasMethod('__construct')) {
+ }
+
+ $class = new ReflectionClass($className);
+ if ($class->implementsInterface('Zend_Validate_Interface')) {
+ if ($class->hasMethod('__construct')) {
+ $keys = array_keys($args);
+ $numeric = false;
+ foreach($keys as $key) {
+ if (is_numeric($key)) {
+ $numeric = true;
+ break;
+ }
+ }
+
+ if ($numeric) {
$object = $class->newInstanceArgs($args);
} else {
- $object = $class->newInstance();
+ $object = $class->newInstance($args);
}
- return $object->isValid($value);
+ } else {
+ $object = $class->newInstance();
}
- } catch (Zend_Validate_Exception $ze) {
- // if there is an exception while validating throw it
- throw $ze;
- } catch (Zend_Exception $ze) {
- // fallthrough and continue for missing validation classes
+
+ return $object->isValid($value);
}
+ } catch (Zend_Validate_Exception $ze) {
+ // if there is an exception while validating throw it
+ throw $ze;
+ } catch (Exception $e) {
+ // fallthrough and continue for missing validation classes
}
- require_once 'Zend/Validate/Exception.php';
+
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("Validate class not found from basename '$classBaseName'");
}
@@ -229,7 +251,7 @@ class Zend_Validate implements Zend_Validate_Interface
*/
public static function getMessageLength()
{
- require_once 'Zend/Validate/Abstract.php';
+ // require_once 'Zend/Validate/Abstract.php';
return Zend_Validate_Abstract::getMessageLength();
}
@@ -240,7 +262,29 @@ class Zend_Validate implements Zend_Validate_Interface
*/
public static function setMessageLength($length = -1)
{
- require_once 'Zend/Validate/Abstract.php';
+ // require_once 'Zend/Validate/Abstract.php';
Zend_Validate_Abstract::setMessageLength($length);
}
+
+ /**
+ * Returns the default translation object
+ *
+ * @return Zend_Translate_Adapter|null
+ */
+ public static function getDefaultTranslator($translator = null)
+ {
+ // require_once 'Zend/Validate/Abstract.php';
+ return Zend_Validate_Abstract::getDefaultTranslator();
+ }
+
+ /**
+ * Sets a default translation object for all validation objects
+ *
+ * @param Zend_Translate|Zend_Translate_Adapter|null $translator
+ */
+ public static function setDefaultTranslator($translator = null)
+ {
+ // require_once 'Zend/Validate/Abstract.php';
+ Zend_Validate_Abstract::setDefaultTranslator($translator);
+ }
}
diff --git a/libs/Zend/Validate/Abstract.php b/libs/Zend/Validate/Abstract.php
index 3107360619..cbecc5eebf 100644
--- a/libs/Zend/Validate/Abstract.php
+++ b/libs/Zend/Validate/Abstract.php
@@ -14,20 +14,20 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 18688 2009-10-25 16:08:24Z thomas $
+ * @version $Id: Abstract.php 21726 2010-03-31 19:57:27Z rob $
*/
/**
* @see Zend_Validate_Interface
*/
-require_once 'Zend/Validate/Interface.php';
+// require_once 'Zend/Validate/Interface.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Validate_Abstract implements Zend_Validate_Interface
@@ -149,7 +149,7 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface
}
if (!isset($this->_messageTemplates[$messageKey])) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("No message template exists for key '$messageKey'");
}
@@ -191,7 +191,7 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface
/**
* @see Zend_Validate_Exception
*/
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("No property exists by the name '$property'");
}
@@ -251,11 +251,11 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface
}
/**
- * @param string $messageKey OPTIONAL
+ * @param string $messageKey
* @param string $value OPTIONAL
* @return void
*/
- protected function _error($messageKey = null, $value = null)
+ protected function _error($messageKey, $value = null)
{
if ($messageKey === null) {
$keys = array_keys($this->_messageTemplates);
@@ -328,7 +328,7 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface
} elseif ($translator instanceof Zend_Translate) {
$this->_translator = $translator->getAdapter();
} else {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception('Invalid translator specified');
}
return $this;
@@ -353,6 +353,16 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface
}
/**
+ * Does this validator have its own specific translator?
+ *
+ * @return bool
+ */
+ public function hasTranslator()
+ {
+ return (bool)$this->_translator;
+ }
+
+ /**
* Set default translation object for all validate objects
*
* @param Zend_Translate|Zend_Translate_Adapter|null $translator
@@ -365,7 +375,7 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface
} elseif ($translator instanceof Zend_Translate) {
self::$_defaultTranslator = $translator->getAdapter();
} else {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception('Invalid translator specified');
}
}
@@ -378,7 +388,7 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface
public static function getDefaultTranslator()
{
if (null === self::$_defaultTranslator) {
- require_once 'Zend/Registry.php';
+ // require_once 'Zend/Registry.php';
if (Zend_Registry::isRegistered('Zend_Translate')) {
$translator = Zend_Registry::get('Zend_Translate');
if ($translator instanceof Zend_Translate_Adapter) {
@@ -393,6 +403,16 @@ abstract class Zend_Validate_Abstract implements Zend_Validate_Interface
}
/**
+ * Is there a default translation object set?
+ *
+ * @return boolean
+ */
+ public static function hasDefaultTranslator()
+ {
+ return (bool)self::$_defaultTranslator;
+ }
+
+ /**
* Indicate whether or not translation should be disabled
*
* @param bool $flag
diff --git a/libs/Zend/Validate/Alnum.php b/libs/Zend/Validate/Alnum.php
index c2f2f46642..9db12a3062 100644
--- a/libs/Zend/Validate/Alnum.php
+++ b/libs/Zend/Validate/Alnum.php
@@ -14,33 +14,33 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Alnum.php 17467 2009-08-08 18:06:55Z thomas $
+ * @version $Id: Alnum.php 20442 2010-01-20 15:15:40Z matthew $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Alnum extends Zend_Validate_Abstract
{
const INVALID = 'alnumInvalid';
const NOT_ALNUM = 'notAlnum';
- const STRING_EMPTY = 'stringEmpty';
+ const STRING_EMPTY = 'alnumStringEmpty';
/**
* Whether to allow white space characters; off by default
*
* @var boolean
- * @depreciated
+ * @deprecated
*/
public $allowWhiteSpace;
@@ -58,18 +58,30 @@ class Zend_Validate_Alnum extends Zend_Validate_Abstract
*/
protected $_messageTemplates = array(
self::INVALID => "Invalid type given, value should be float, string, or integer",
- self::NOT_ALNUM => "'%value%' has not only alphabetic and digit characters",
- self::STRING_EMPTY => "'%value%' is an empty string"
+ self::NOT_ALNUM => "'%value%' contains characters which are non alphabetic and no digits",
+ self::STRING_EMPTY => "'%value%' is an empty string",
);
/**
* Sets default option values for this instance
*
- * @param boolean $allowWhiteSpace
+ * @param boolean|Zend_Config $allowWhiteSpace
* @return void
*/
public function __construct($allowWhiteSpace = false)
{
+ if ($allowWhiteSpace instanceof Zend_Config) {
+ $allowWhiteSpace = $allowWhiteSpace->toArray();
+ }
+
+ if (is_array($allowWhiteSpace)) {
+ if (array_key_exists('allowWhiteSpace', $allowWhiteSpace)) {
+ $allowWhiteSpace = $allowWhiteSpace['allowWhiteSpace'];
+ } else {
+ $allowWhiteSpace = false;
+ }
+ }
+
$this->allowWhiteSpace = (boolean) $allowWhiteSpace;
}
@@ -121,7 +133,7 @@ class Zend_Validate_Alnum extends Zend_Validate_Abstract
/**
* @see Zend_Filter_Alnum
*/
- require_once 'Zend/Filter/Alnum.php';
+ // require_once 'Zend/Filter/Alnum.php';
self::$_filter = new Zend_Filter_Alnum();
}
diff --git a/libs/Zend/Validate/Alpha.php b/libs/Zend/Validate/Alpha.php
index ce1f01872f..42864fa561 100644
--- a/libs/Zend/Validate/Alpha.php
+++ b/libs/Zend/Validate/Alpha.php
@@ -14,33 +14,33 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Alpha.php 16223 2009-06-21 20:04:53Z thomas $
+ * @version $Id: Alpha.php 20442 2010-01-20 15:15:40Z matthew $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Alpha extends Zend_Validate_Abstract
{
const INVALID = 'alphaInvalid';
const NOT_ALPHA = 'notAlpha';
- const STRING_EMPTY = 'stringEmpty';
+ const STRING_EMPTY = 'alphaStringEmpty';
/**
* Whether to allow white space characters; off by default
*
* @var boolean
- * @depreciated
+ * @deprecated
*/
public $allowWhiteSpace;
@@ -58,18 +58,30 @@ class Zend_Validate_Alpha extends Zend_Validate_Abstract
*/
protected $_messageTemplates = array(
self::INVALID => "Invalid type given, value should be a string",
- self::NOT_ALPHA => "'%value%' has not only alphabetic characters",
+ self::NOT_ALPHA => "'%value%' contains non alphabetic characters",
self::STRING_EMPTY => "'%value%' is an empty string"
);
/**
* Sets default option values for this instance
*
- * @param boolean $allowWhiteSpace
+ * @param boolean|Zend_Config $allowWhiteSpace
* @return void
*/
public function __construct($allowWhiteSpace = false)
{
+ if ($allowWhiteSpace instanceof Zend_Config) {
+ $allowWhiteSpace = $allowWhiteSpace->toArray();
+ }
+
+ if (is_array($allowWhiteSpace)) {
+ if (array_key_exists('allowWhiteSpace', $allowWhiteSpace)) {
+ $allowWhiteSpace = $allowWhiteSpace['allowWhiteSpace'];
+ } else {
+ $allowWhiteSpace = false;
+ }
+ }
+
$this->allowWhiteSpace = (boolean) $allowWhiteSpace;
}
@@ -121,7 +133,7 @@ class Zend_Validate_Alpha extends Zend_Validate_Abstract
/**
* @see Zend_Filter_Alpha
*/
- require_once 'Zend/Filter/Alpha.php';
+ // require_once 'Zend/Filter/Alpha.php';
self::$_filter = new Zend_Filter_Alpha();
}
diff --git a/libs/Zend/Validate/Barcode.php b/libs/Zend/Validate/Barcode.php
index 374a9e5449..111010880e 100644
--- a/libs/Zend/Validate/Barcode.php
+++ b/libs/Zend/Validate/Barcode.php
@@ -14,70 +14,164 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Barcode.php 16223 2009-06-21 20:04:53Z thomas $
+ * @version $Id: Barcode.php 21748 2010-04-03 10:29:56Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
+
+/**
+ * @see Zend_Loader
+ */
+// require_once 'Zend/Loader.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Barcode extends Zend_Validate_Abstract
{
+ const INVALID = 'barcodeInvalid';
+ const FAILED = 'barcodeFailed';
+ const INVALID_CHARS = 'barcodeInvalidChars';
+ const INVALID_LENGTH = 'barcodeInvalidLength';
+
+ protected $_messageTemplates = array(
+ self::FAILED => "'%value%' failed checksum validation",
+ self::INVALID_CHARS => "'%value%' contains invalid characters",
+ self::INVALID_LENGTH => "'%value%' should have a length of %length% characters",
+ self::INVALID => "Invalid type given, value should be string",
+ );
+
+ /**
+ * Additional variables available for validation failure messages
+ *
+ * @var array
+ */
+ protected $_messageVariables = array(
+ 'length' => '_length'
+ );
+
+ /**
+ * Length for the set subtype
+ *
+ * @var integer
+ */
+ protected $_length;
+
/**
- * Barcode validator
+ * Barcode adapter
*
- * @var Zend_Validate_Abstract
+ * @var Zend_Validate_Barcode_BarcodeAdapter
*/
- protected $_barcodeValidator;
+ protected $_adapter;
/**
* Generates the standard validator object
*
- * @param string $barcodeType - Barcode validator to use
+ * @param string|Zend_Config|
+ * Zend_Validate_Barcode_BarcodeAdapter $adapter Barcode adapter to use
* @return void
* @throws Zend_Validate_Exception
*/
- public function __construct($barcodeType)
+ public function __construct($adapter)
+ {
+ if ($adapter instanceof Zend_Config) {
+ $adapter = $adapter->toArray();
+ }
+
+ $options = null;
+ $checksum = null;
+ if (is_array($adapter)) {
+ if (array_key_exists('options', $adapter)) {
+ $options = $adapter['options'];
+ }
+
+ if (array_key_exists('checksum', $adapter)) {
+ $checksum = $adapter['checksum'];
+ }
+
+ if (array_key_exists('adapter', $adapter)) {
+ $adapter = $adapter['adapter'];
+ } else {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception("Missing option 'adapter'");
+ }
+ }
+
+ $this->setAdapter($adapter, $options);
+ if ($checksum !== null) {
+ $this->setChecksum($checksum);
+ }
+ }
+
+ /**
+ * Returns the set adapter
+ *
+ * @return Zend_Validate_Barcode_BarcodeAdapter
+ */
+ public function getAdapter()
{
- $this->setType($barcodeType);
+ return $this->_adapter;
}
/**
- * Sets a new barcode validator
+ * Sets a new barcode adapter
*
- * @param string $barcodeType - Barcode validator to use
+ * @param string|Zend_Validate_Barcode $adapter Barcode adapter to use
+ * @param array $options Options for this adapter
* @return void
* @throws Zend_Validate_Exception
*/
- public function setType($barcodeType)
+ public function setAdapter($adapter, $options = null)
{
- switch (strtolower($barcodeType)) {
- case 'upc':
- case 'upc-a':
- require_once 'Zend/Validate/Barcode/UpcA.php';
- $class = 'Zend_Validate_Barcode_UpcA';
- break;
- case 'ean13':
- case 'ean-13':
- require_once 'Zend/Validate/Barcode/Ean13.php';
- $class = 'Zend_Validate_Barcode_Ean13';
- break;
- default:
- require_once 'Zend/Validate/Exception.php';
- throw new Zend_Validate_Exception("Barcode type '$barcodeType' is not supported'");
- break;
+ $adapter = ucfirst(strtolower($adapter));
+ // require_once 'Zend/Loader.php';
+ if (Zend_Loader::isReadable('Zend/Validate/Barcode/' . $adapter. '.php')) {
+ $adapter = 'Zend_Validate_Barcode_' . $adapter;
+ }
+
+ // if (!class_exists($adapter)) {
+ // Zend_Loader::loadClass($adapter);
+ // }
+
+ $this->_adapter = new $adapter($options);
+ if (!$this->_adapter instanceof Zend_Validate_Barcode_AdapterInterface) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception(
+ "Adapter " . $adapter . " does not implement Zend_Validate_Barcode_AdapterInterface"
+ );
}
- $this->_barcodeValidator = new $class;
+ return $this;
+ }
+
+ /**
+ * Returns the checksum option
+ *
+ * @return boolean
+ */
+ public function getChecksum()
+ {
+ return $this->getAdapter()->getCheck();
+ }
+
+ /**
+ * Sets the checksum option
+ *
+ * @param boolean $checksum
+ * @return Zend_Validate_Barcode
+ */
+ public function setChecksum($checksum)
+ {
+ $this->getAdapter()->setCheck($checksum);
+ return $this;
}
/**
@@ -90,6 +184,34 @@ class Zend_Validate_Barcode extends Zend_Validate_Abstract
*/
public function isValid($value)
{
- return call_user_func(array($this->_barcodeValidator, 'isValid'), $value);
+ if (!is_string($value)) {
+ $this->_error(self::INVALID);
+ return false;
+ }
+
+ $this->_setValue($value);
+ $adapter = $this->getAdapter();
+ $this->_length = $adapter->getLength();
+ $result = $adapter->checkLength($value);
+ if (!$result) {
+ $this->_error(self::INVALID_LENGTH);
+ return false;
+ }
+
+ $result = $adapter->checkChars($value);
+ if (!$result) {
+ $this->_error(self::INVALID_CHARS);
+ return false;
+ }
+
+ if ($this->getChecksum()) {
+ $result = $adapter->checksum($value);
+ if (!$result) {
+ $this->_error(self::FAILED);
+ return false;
+ }
+ }
+
+ return true;
}
}
diff --git a/libs/Zend/Validate/Barcode/AdapterAbstract.php b/libs/Zend/Validate/Barcode/AdapterAbstract.php
new file mode 100644
index 0000000000..7cbb4644f8
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/AdapterAbstract.php
@@ -0,0 +1,315 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Ean13.php 18028 2009-09-08 20:52:23Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterInterface
+ */
+// require_once 'Zend/Validate/Barcode/AdapterInterface.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+abstract class Zend_Validate_Barcode_AdapterAbstract
+ implements Zend_Validate_Barcode_AdapterInterface
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer|array|string
+ */
+ protected $_length;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters;
+
+ /**
+ * Callback to checksum function
+ * @var string|array
+ */
+ protected $_checksum;
+
+ /**
+ * Is a checksum value included?
+ * @var boolean
+ */
+ protected $_hasChecksum = true;
+
+ /**
+ * Checks the length of a barcode
+ *
+ * @param string $value The barcode to check for proper length
+ * @return boolean
+ */
+ public function checkLength($value)
+ {
+ if (!is_string($value)) {
+ return false;
+ }
+
+ $fixum = strlen($value);
+ $found = false;
+ $length = $this->getLength();
+ if (is_array($length)) {
+ foreach ($length as $value) {
+ if ($fixum == $value) {
+ $found = true;
+ }
+
+ if ($value == -1) {
+ $found = true;
+ }
+ }
+ } elseif ($fixum == $length) {
+ $found = true;
+ } elseif ($length == -1) {
+ $found = true;
+ } elseif ($length == 'even') {
+ $count = $fixum % 2;
+ $found = ($count == 0) ? true : false;
+ } elseif ($length == 'odd') {
+ $count = $fixum % 2;
+ $found = ($count == 1) ? true : false;
+ }
+
+ return $found;
+ }
+
+ /**
+ * Checks for allowed characters within the barcode
+ *
+ * @param string $value The barcode to check for allowed characters
+ * @return boolean
+ */
+ public function checkChars($value)
+ {
+ if (!is_string($value)) {
+ return false;
+ }
+
+ $characters = $this->getCharacters();
+ if ($characters == 128) {
+ for ($x = 0; $x < 128; ++$x) {
+ $value = str_replace(chr($x), '', $value);
+ }
+ } else {
+ $chars = str_split($characters);
+ foreach ($chars as $char) {
+ $value = str_replace($char, '', $value);
+ }
+ }
+
+ if (strlen($value) > 0) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Validates the checksum
+ *
+ * @param string $value The barcode to check the checksum for
+ * @return boolean
+ */
+ public function checksum($value)
+ {
+ $checksum = $this->getChecksum();
+ if (!empty($checksum)) {
+ if (method_exists($this, $checksum)) {
+ return call_user_func(array($this, $checksum), $value);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns the allowed barcode length
+ *
+ * @return string
+ */
+ public function getLength()
+ {
+ return $this->_length;
+ }
+
+ /**
+ * Returns the allowed characters
+ *
+ * @return integer|string
+ */
+ public function getCharacters()
+ {
+ return $this->_characters;
+ }
+
+ /**
+ * Returns the checksum function name
+ *
+ */
+ public function getChecksum()
+ {
+ return $this->_checksum;
+ }
+
+ /**
+ * Returns if barcode uses checksum
+ *
+ * @return boolean
+ */
+ public function getCheck()
+ {
+ return $this->_hasChecksum;
+ }
+
+ /**
+ * Sets the checksum validation
+ *
+ * @param boolean $check
+ * @return Zend_Validate_Barcode_AdapterAbstract
+ */
+ public function setCheck($check)
+ {
+ $this->_hasChecksum = (boolean) $check;
+ return $this;
+ }
+
+ /**
+ * Validates the checksum (Modulo 10)
+ * GTIN implementation factor 3
+ *
+ * @param string $value The barcode to validate
+ * @return boolean
+ */
+ protected function _gtin($value)
+ {
+ $barcode = substr($value, 0, -1);
+ $sum = 0;
+ $length = strlen($barcode) - 1;
+
+ for ($i = 0; $i <= $length; $i++) {
+ if (($i % 2) === 0) {
+ $sum += $barcode[$length - $i] * 3;
+ } else {
+ $sum += $barcode[$length - $i];
+ }
+ }
+
+ $calc = $sum % 10;
+ $checksum = ($calc === 0) ? 0 : (10 - $calc);
+ if ($value[$length + 1] != $checksum) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Validates the checksum (Modulo 10)
+ * IDENTCODE implementation factors 9 and 4
+ *
+ * @param string $value The barcode to validate
+ * @return boolean
+ */
+ protected function _identcode($value)
+ {
+ $barcode = substr($value, 0, -1);
+ $sum = 0;
+ $length = strlen($value) - 2;
+
+ for ($i = 0; $i <= $length; $i++) {
+ if (($i % 2) === 0) {
+ $sum += $barcode[$length - $i] * 4;
+ } else {
+ $sum += $barcode[$length - $i] * 9;
+ }
+ }
+
+ $calc = $sum % 10;
+ $checksum = ($calc === 0) ? 0 : (10 - $calc);
+ if ($value[$length + 1] != $checksum) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Validates the checksum (Modulo 10)
+ * CODE25 implementation factor 3
+ *
+ * @param string $value The barcode to validate
+ * @return boolean
+ */
+ protected function _code25($value)
+ {
+ $barcode = substr($value, 0, -1);
+ $sum = 0;
+ $length = strlen($barcode) - 1;
+
+ for ($i = 0; $i <= $length; $i++) {
+ if (($i % 2) === 0) {
+ $sum += $barcode[$i] * 3;
+ } else {
+ $sum += $barcode[$i];
+ }
+ }
+
+ $calc = $sum % 10;
+ $checksum = ($calc === 0) ? 0 : (10 - $calc);
+ if ($value[$length + 1] != $checksum) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Validates the checksum ()
+ * POSTNET implementation
+ *
+ * @param string $value The barcode to validate
+ * @return boolean
+ */
+ protected function _postnet($value)
+ {
+ $checksum = substr($value, -1, 1);
+ $values = str_split(substr($value, 0, -1));
+
+ $check = 0;
+ foreach($values as $row) {
+ $check += $row;
+ }
+
+ $check %= 10;
+ $check = 10 - $check;
+ if ($check == $checksum) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/AdapterInterface.php b/libs/Zend/Validate/Barcode/AdapterInterface.php
new file mode 100644
index 0000000000..325c6048f3
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/AdapterInterface.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Ean13.php 18028 2009-09-08 20:52:23Z thomas $
+ */
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+interface Zend_Validate_Barcode_AdapterInterface
+{
+ /**
+ * Checks the length of a barcode
+ *
+ * @param string $value The barcode to check for proper length
+ * @return boolean
+ */
+ public function checkLength($value);
+
+ /**
+ * Checks for allowed characters within the barcode
+ *
+ * @param string $value The barcode to check for allowed characters
+ * @return boolean
+ */
+ public function checkChars($value);
+
+ /**
+ * Validates the checksum
+ *
+ * @param string $value The barcode to check the checksum for
+ * @return boolean
+ */
+ public function checksum($value);
+
+ /**
+ * Returns if barcode uses a checksum
+ *
+ * @return boolean
+ */
+ public function getCheck();
+
+ /**
+ * Sets the checksum validation
+ *
+ * @param boolean $check
+ * @return Zend_Validate_Barcode_Adapter Provides fluid interface
+ */
+ public function setCheck($check);
+}
diff --git a/libs/Zend/Validate/Barcode/Code25.php b/libs/Zend/Validate/Barcode/Code25.php
new file mode 100644
index 0000000000..6d1525da4c
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Code25.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Code25 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = -1;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_code25';
+
+ /**
+ * Constructor
+ *
+ * Sets check flag to false.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->setCheck(false);
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Code25interleaved.php b/libs/Zend/Validate/Barcode/Code25interleaved.php
new file mode 100644
index 0000000000..54fd90bd28
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Code25interleaved.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Code25interleaved extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 'even';
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_code25';
+
+ /**
+ * Constructor
+ *
+ * Sets check flag to false.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->setCheck(false);
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Code39.php b/libs/Zend/Validate/Barcode/Code39.php
new file mode 100644
index 0000000000..8208cffb9e
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Code39.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Code39 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = -1;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -.$/+%';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_code39';
+
+ /**
+ * @var array
+ */
+ protected $_check = array(
+ '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6,
+ '7' => 7, '8' => 8, '9' => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13,
+ 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20,
+ 'L' => 21, 'M' => 22, 'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27,
+ 'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34,
+ 'Z' => 35, '-' => 36, '.' => 37, ' ' => 38, '$' => 39, '/' => 40, '+' => 41,
+ '%' => 42,
+ );
+
+ /**
+ * Constructor
+ *
+ * Sets check flag to false.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->setCheck(false);
+ }
+
+ /**
+ * Validates the checksum (Modulo 43)
+ *
+ * @param string $value The barcode to validate
+ * @return boolean
+ */
+ protected function _code39($value)
+ {
+ $checksum = substr($value, -1, 1);
+ $value = str_split(substr($value, 0, -1));
+ $count = 0;
+ foreach($value as $char) {
+ $count += $this->_check[$char];
+ }
+
+ $mod = $count % 43;
+ if ($mod == $this->_check[$checksum]) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Code39ext.php b/libs/Zend/Validate/Barcode/Code39ext.php
new file mode 100644
index 0000000000..5b90254c50
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Code39ext.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Code39ext extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = -1;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = 128;
+
+ /**
+ * Constructor
+ *
+ * Sets check flag to false.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->setCheck(false);
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Code93.php b/libs/Zend/Validate/Barcode/Code93.php
new file mode 100644
index 0000000000..36a6567f36
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Code93.php
@@ -0,0 +1,120 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Code93 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = -1;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -.$/+%';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_code93';
+
+ /**
+ * Note that the characters !"§& are only synonyms
+ * @var array
+ */
+ protected $_check = array(
+ '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6,
+ '7' => 7, '8' => 8, '9' => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13,
+ 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20,
+ 'L' => 21, 'M' => 22, 'N' => 23, 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27,
+ 'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31, 'W' => 32, 'X' => 33, 'Y' => 34,
+ 'Z' => 35, '-' => 36, '.' => 37, ' ' => 38, '$' => 39, '/' => 40, '+' => 41,
+ '%' => 42, '!' => 43, '"' => 44, '§' => 45, '&' => 46,
+ );
+
+ /**
+ * Constructor
+ *
+ * Sets check flag to false.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->setCheck(false);
+ }
+
+ /**
+ * Validates the checksum (Modulo CK)
+ *
+ * @param string $value The barcode to validate
+ * @return boolean
+ */
+ protected function _code93($value)
+ {
+ $checksum = substr($value, -2, 2);
+ $value = str_split(substr($value, 0, -2));
+ $count = 0;
+ $length = count($value) % 20;
+ foreach($value as $char) {
+ if ($length == 0) {
+ $length = 20;
+ }
+
+ $count += $this->_check[$char] * $length;
+ --$length;
+ }
+
+ $check = array_search(($count % 47), $this->_check);
+ $value[] = $check;
+ $count = 0;
+ $length = count($value) % 15;
+ foreach($value as $char) {
+ if ($length == 0) {
+ $length = 15;
+ }
+
+ $count += $this->_check[$char] * $length;
+ --$length;
+ }
+ $check .= array_search(($count % 47), $this->_check);
+
+ if ($check == $checksum) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Code93ext.php b/libs/Zend/Validate/Barcode/Code93ext.php
new file mode 100644
index 0000000000..2aaf343162
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Code93ext.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Code93ext extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = -1;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = 128;
+
+ /**
+ * Constructor
+ *
+ * Sets check flag to false.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->setCheck(false);
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Ean12.php b/libs/Zend/Validate/Barcode/Ean12.php
new file mode 100644
index 0000000000..26dee47fb5
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Ean12.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Ean13.php 18028 2009-09-08 20:52:23Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Ean12 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 12;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+}
diff --git a/libs/Zend/Validate/Barcode/Ean13.php b/libs/Zend/Validate/Barcode/Ean13.php
index 068809248c..d5387e52f9 100644
--- a/libs/Zend/Validate/Barcode/Ean13.php
+++ b/libs/Zend/Validate/Barcode/Ean13.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,96 +14,39 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Ean13.php 16223 2009-06-21 20:04:53Z thomas $
+ * @version $Id: Ean13.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
-
/**
- * @see Zend_Validate_Abstract
+ * @see Zend_Validate_Barcode_AdapterAbstract
*/
-require_once 'Zend/Validate/Abstract.php';
-
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Validate_Barcode_Ean13 extends Zend_Validate_Abstract
+class Zend_Validate_Barcode_Ean13 extends Zend_Validate_Barcode_AdapterAbstract
{
/**
- * Validation failure message key for when the value is
- * an invalid barcode
- */
- const INVALID = 'invalid';
-
- /**
- * Validation failure message key for when the value is
- * not 13 characters long
+ * Allowed barcode lengths
+ * @var integer
*/
- const INVALID_LENGTH = 'invalidLength';
+ protected $_length = 13;
/**
- * Validation failure message key for when the value
- * does not only contain numeric characters
+ * Allowed barcode characters
+ * @var string
*/
- const NOT_NUMERIC = 'ean13NotNumeric';
+ protected $_characters = '0123456789';
/**
- * Validation failure message template definitions
- *
- * @var array
+ * Checksum function
+ * @var string
*/
- protected $_messageTemplates = array(
- self::INVALID => "'%value%' is an invalid EAN-13 barcode",
- self::INVALID_LENGTH => "'%value%' should be 13 characters",
- self::NOT_NUMERIC => "'%value%' should contain only numeric characters",
- );
-
- /**
- * Defined by Zend_Validate_Interface
- *
- * Returns true if and only if $value contains a valid barcode
- *
- * @param string $value
- * @return boolean
- */
- public function isValid($value)
- {
- if (!is_string($value) || !ctype_digit($value)) {
- $this->_error(self::NOT_NUMERIC);
- return false;
- }
-
- $this->_setValue($value);
- if (strlen($value) !== 13) {
- $this->_error(self::INVALID_LENGTH);
- return false;
- }
-
- $barcode = strrev(substr($value, 0, -1));
- $oddSum = 0;
- $evenSum = 0;
-
- for ($i = 0; $i < 12; $i++) {
- if ($i % 2 === 0) {
- $oddSum += $barcode[$i] * 3;
- } elseif ($i % 2 === 1) {
- $evenSum += $barcode[$i];
- }
- }
-
- $calculation = ($oddSum + $evenSum) % 10;
- $checksum = ($calculation === 0) ? 0 : 10 - $calculation;
-
- if ($value[12] != $checksum) {
- $this->_error(self::INVALID);
- return false;
- }
-
- return true;
- }
+ protected $_checksum = '_gtin';
}
diff --git a/libs/Zend/Validate/Barcode/Ean14.php b/libs/Zend/Validate/Barcode/Ean14.php
new file mode 100644
index 0000000000..19756c8ee7
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Ean14.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Ean13.php 18028 2009-09-08 20:52:23Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Ean14 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 14;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+}
diff --git a/libs/Zend/Validate/Barcode/Ean18.php b/libs/Zend/Validate/Barcode/Ean18.php
new file mode 100644
index 0000000000..7c6519959f
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Ean18.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Ean13.php 18028 2009-09-08 20:52:23Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Ean18 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 18;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+}
diff --git a/libs/Zend/Validate/Barcode/Ean2.php b/libs/Zend/Validate/Barcode/Ean2.php
new file mode 100644
index 0000000000..009bfe5e57
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Ean2.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Ean2 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 2;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Constructor
+ *
+ * Sets check flag to false.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->setCheck(false);
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Ean5.php b/libs/Zend/Validate/Barcode/Ean5.php
new file mode 100644
index 0000000000..7574e897e4
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Ean5.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Ean5 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 5;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Constructor
+ *
+ * Sets check flag to false.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->setCheck(false);
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Ean8.php b/libs/Zend/Validate/Barcode/Ean8.php
new file mode 100644
index 0000000000..ca68fe45d9
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Ean8.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Ean8 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = array(7, 8);
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+
+ /**
+ * Overrides parent checkLength
+ *
+ * @param string $value Value
+ * @return boolean
+ */
+ public function checkLength($value)
+ {
+ if (strlen($value) == 7) {
+ $this->setCheck(false);
+ } else {
+ $this->setCheck(true);
+ }
+
+ return parent::checkLength($value);
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Gtin12.php b/libs/Zend/Validate/Barcode/Gtin12.php
new file mode 100644
index 0000000000..7453e05f64
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Gtin12.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Ean13.php 18028 2009-09-08 20:52:23Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Gtin12 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 12;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+}
diff --git a/libs/Zend/Validate/Barcode/Gtin13.php b/libs/Zend/Validate/Barcode/Gtin13.php
new file mode 100644
index 0000000000..c466f5896a
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Gtin13.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Ean13.php 18028 2009-09-08 20:52:23Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Gtin13 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 13;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+}
diff --git a/libs/Zend/Validate/Barcode/Gtin14.php b/libs/Zend/Validate/Barcode/Gtin14.php
new file mode 100644
index 0000000000..7c5c1cdb5b
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Gtin14.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Ean13.php 18028 2009-09-08 20:52:23Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Gtin14 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 14;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+}
diff --git a/libs/Zend/Validate/Barcode/Identcode.php b/libs/Zend/Validate/Barcode/Identcode.php
new file mode 100644
index 0000000000..6899c17910
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Identcode.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Identcode extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 12;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_identcode';
+}
diff --git a/libs/Zend/Validate/Barcode/Intelligentmail.php b/libs/Zend/Validate/Barcode/Intelligentmail.php
new file mode 100644
index 0000000000..a0e81cfca6
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Intelligentmail.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_IntelligentMail extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = array(20, 25, 29, 31);
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Constructor
+ *
+ * Sets check flag to false.
+ *
+ * @return void
+ */
+ public function __construct()
+ {
+ $this->setCheck(false);
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Issn.php b/libs/Zend/Validate/Barcode/Issn.php
new file mode 100644
index 0000000000..e9507c9a5f
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Issn.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Issn extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = array(8, 13);
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789X';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+
+ /**
+ * Allows X on length of 8 chars
+ *
+ * @param string $value The barcode to check for allowed characters
+ * @return boolean
+ */
+ public function checkChars($value)
+ {
+ if (strlen($value) != 8) {
+ if (strpos($value, 'X') !== false) {
+ return false;
+ }
+ }
+
+ return parent::checkChars($value);
+ }
+
+ /**
+ * Validates the checksum
+ *
+ * @param string $value The barcode to check the checksum for
+ * @return boolean
+ */
+ public function checksum($value)
+ {
+ if (strlen($value) == 8) {
+ $this->_checksum = '_issn';
+ } else {
+ $this->_checksum = '_gtin';
+ }
+
+ return parent::checksum($value);
+ }
+
+ /**
+ * Validates the checksum ()
+ * ISSN implementation (reversed mod11)
+ *
+ * @param string $value The barcode to validate
+ * @return boolean
+ */
+ protected function _issn($value)
+ {
+ $checksum = substr($value, -1, 1);
+ $values = str_split(substr($value, 0, -1));
+ $check = 0;
+ $multi = 8;
+ foreach($values as $token) {
+ if ($token == 'X') {
+ $token = 10;
+ }
+
+ $check += ($token * $multi);
+ --$multi;
+ }
+
+ $check %= 11;
+ $check = 11 - $check;
+ if ($check == $checksum) {
+ return true;
+ } else if (($check == 10) && ($checksum == 'X')) {
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Itf14.php b/libs/Zend/Validate/Barcode/Itf14.php
new file mode 100644
index 0000000000..10cfeb761c
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Itf14.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Ean13.php 18028 2009-09-08 20:52:23Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Itf14 extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 14;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+}
diff --git a/libs/Zend/Validate/Barcode/Leitcode.php b/libs/Zend/Validate/Barcode/Leitcode.php
new file mode 100644
index 0000000000..52f1fc0428
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Leitcode.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Leitcode extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 14;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_identcode';
+}
diff --git a/libs/Zend/Validate/Barcode/Planet.php b/libs/Zend/Validate/Barcode/Planet.php
new file mode 100644
index 0000000000..b4eaf66cb9
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Planet.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Planet extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = array(12, 14);
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_postnet';
+}
diff --git a/libs/Zend/Validate/Barcode/Postnet.php b/libs/Zend/Validate/Barcode/Postnet.php
new file mode 100644
index 0000000000..9d2ff879b8
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Postnet.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Postnet extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = array(6, 7, 10, 12);
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_postnet';
+}
diff --git a/libs/Zend/Validate/Barcode/Royalmail.php b/libs/Zend/Validate/Barcode/Royalmail.php
new file mode 100644
index 0000000000..0bcdf1e16c
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Royalmail.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id:$
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Royalmail extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = -1;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+ protected $_rows = array(
+ '0' => 1, '1' => 1, '2' => 1, '3' => 1, '4' => 1, '5' => 1,
+ '6' => 2, '7' => 2, '8' => 2, '9' => 2, 'A' => 2, 'B' => 2,
+ 'C' => 3, 'D' => 3, 'E' => 3, 'F' => 3, 'G' => 3, 'H' => 3,
+ 'I' => 4, 'J' => 4, 'K' => 4, 'L' => 4, 'M' => 4, 'N' => 4,
+ 'O' => 5, 'P' => 5, 'Q' => 5, 'R' => 5, 'S' => 5, 'T' => 5,
+ 'U' => 0, 'V' => 0, 'W' => 0, 'X' => 0, 'Y' => 0, 'Z' => 0,
+ );
+
+ protected $_columns = array(
+ '0' => 1, '1' => 2, '2' => 3, '3' => 4, '4' => 5, '5' => 0,
+ '6' => 1, '7' => 2, '8' => 3, '9' => 4, 'A' => 5, 'B' => 0,
+ 'C' => 1, 'D' => 2, 'E' => 3, 'F' => 4, 'G' => 5, 'H' => 0,
+ 'I' => 1, 'J' => 2, 'K' => 3, 'L' => 4, 'M' => 5, 'N' => 0,
+ 'O' => 1, 'P' => 2, 'Q' => 3, 'R' => 4, 'S' => 5, 'T' => 0,
+ 'U' => 1, 'V' => 2, 'W' => 3, 'X' => 4, 'Y' => 5, 'Z' => 0,
+ );
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_royalmail';
+
+ /**
+ * Validates the checksum ()
+ *
+ * @param string $value The barcode to validate
+ * @return boolean
+ */
+ protected function _royalmail($value)
+ {
+ $checksum = substr($value, -1, 1);
+ $values = str_split(substr($value, 0, -1));
+ $rowvalue = 0;
+ $colvalue = 0;
+ foreach($values as $row) {
+ $rowvalue += $this->_rows[$row];
+ $colvalue += $this->_columns[$row];
+ }
+
+ $rowvalue %= 6;
+ $colvalue %= 6;
+
+ $rowchkvalue = array_keys($this->_rows, $rowvalue);
+ $colchkvalue = array_keys($this->_columns, $colvalue);
+ $chkvalue = current(array_intersect($rowchkvalue, $colchkvalue));
+ if ($chkvalue == $checksum) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Allows start and stop tag within checked chars
+ *
+ * @param string $value The barcode to check for allowed characters
+ * @return boolean
+ */
+ public function checkChars($value)
+ {
+ if ($value[0] == '(') {
+ $value = substr($value, 1);
+
+ if ($value[strlen($value) - 1] == ')') {
+ $value = substr($value, 0, -1);
+ } else {
+ return false;
+ }
+ }
+
+ return parent::checkChars($value);
+ }
+}
diff --git a/libs/Zend/Validate/Barcode/Sscc.php b/libs/Zend/Validate/Barcode/Sscc.php
new file mode 100644
index 0000000000..b44b19a561
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Sscc.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Ean13.php 18028 2009-09-08 20:52:23Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Sscc extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 18;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+}
diff --git a/libs/Zend/Validate/Barcode/UpcA.php b/libs/Zend/Validate/Barcode/UpcA.php
deleted file mode 100644
index cf33f31fab..0000000000
--- a/libs/Zend/Validate/Barcode/UpcA.php
+++ /dev/null
@@ -1,103 +0,0 @@
-<?php
-
-/**
- * Zend Framework
- *
- * LICENSE
- *
- * This source file is subject to the new BSD license that is bundled
- * with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://framework.zend.com/license/new-bsd
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@zend.com so we can send you a copy immediately.
- *
- * @category Zend
- * @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: UpcA.php 16223 2009-06-21 20:04:53Z thomas $
- */
-
-
-/**
- * @see Zend_Validate_Abstract
- */
-require_once 'Zend/Validate/Abstract.php';
-
-
-/**
- * @category Zend
- * @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
-class Zend_Validate_Barcode_UpcA extends Zend_Validate_Abstract
-{
- /**
- * Validation failure message key for when the value is
- * an invalid barcode
- */
- const INVALID = 'invalid';
-
- /**
- * Validation failure message key for when the value is
- * not 12 characters long
- */
- const INVALID_LENGTH = 'invalidLength';
-
- /**
- * Validation failure message template definitions
- *
- * @var array
- */
- protected $_messageTemplates = array(
- self::INVALID => "'%value%' is an invalid UPC-A barcode",
- self::INVALID_LENGTH => "'%value%' should be 12 characters",
- );
-
- /**
- * Defined by Zend_Validate_Interface
- *
- * Returns true if and only if $value contains a valid barcode
- *
- * @param string $value
- * @return boolean
- */
- public function isValid($value)
- {
- if (!is_string($value)) {
- $this->_error(self::INVALID);
- return false;
- }
-
- $this->_setValue($value);
- if (strlen($value) !== 12) {
- $this->_error(self::INVALID_LENGTH);
- return false;
- }
-
- $barcode = substr($value, 0, -1);
- $oddSum = 0;
- $evenSum = 0;
-
- for ($i = 0; $i < 11; $i++) {
- if ($i % 2 === 0) {
- $oddSum += $barcode[$i] * 3;
- } elseif ($i % 2 === 1) {
- $evenSum += $barcode[$i];
- }
- }
-
- $calculation = ($oddSum + $evenSum) % 10;
- $checksum = ($calculation === 0) ? 0 : 10 - $calculation;
-
- if ($value[11] != $checksum) {
- $this->_error(self::INVALID);
- return false;
- }
-
- return true;
- }
-}
diff --git a/libs/Zend/Validate/Barcode/Upca.php b/libs/Zend/Validate/Barcode/Upca.php
new file mode 100644
index 0000000000..2f0411ef95
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Upca.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Upca.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Upca extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = 12;
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+}
diff --git a/libs/Zend/Validate/Barcode/Upce.php b/libs/Zend/Validate/Barcode/Upce.php
new file mode 100644
index 0000000000..3199f19b90
--- /dev/null
+++ b/libs/Zend/Validate/Barcode/Upce.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: UpcA.php 18028 2009-09-08 20:52:23Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Barcode_AdapterAbstract
+ */
+// require_once 'Zend/Validate/Barcode/AdapterAbstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Barcode_Upce extends Zend_Validate_Barcode_AdapterAbstract
+{
+ /**
+ * Allowed barcode lengths
+ * @var integer
+ */
+ protected $_length = array(6, 7, 8);
+
+ /**
+ * Allowed barcode characters
+ * @var string
+ */
+ protected $_characters = '0123456789';
+
+ /**
+ * Checksum function
+ * @var string
+ */
+ protected $_checksum = '_gtin';
+
+ /**
+ * Overrides parent checkLength
+ *
+ * @param string $value Value
+ * @return boolean
+ */
+ public function checkLength($value)
+ {
+ if (strlen($value) != 8) {
+ $this->setCheck(false);
+ } else {
+ $this->setCheck(true);
+ }
+
+ return parent::checkLength($value);
+ }
+}
diff --git a/libs/Zend/Validate/Between.php b/libs/Zend/Validate/Between.php
index b9fd7c2dc6..7245295dbb 100644
--- a/libs/Zend/Validate/Between.php
+++ b/libs/Zend/Validate/Between.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,22 +14,20 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Between.php 16223 2009-06-21 20:04:53Z thomas $
+ * @version $Id: Between.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
-
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
-
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Between extends Zend_Validate_Abstract
@@ -91,17 +88,44 @@ class Zend_Validate_Between extends Zend_Validate_Abstract
/**
* Sets validator options
+ * Accepts the following option keys:
+ * 'min' => scalar, minimum border
+ * 'max' => scalar, maximum border
+ * 'inclusive' => boolean, inclusive border values
*
- * @param mixed $min
- * @param mixed $max
- * @param boolean $inclusive
+ * @param array|Zend_Config $options
* @return void
*/
- public function __construct($min, $max, $inclusive = true)
+ public function __construct($options)
{
- $this->setMin($min)
- ->setMax($max)
- ->setInclusive($inclusive);
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp['min'] = array_shift($options);
+ if (!empty($options)) {
+ $temp['max'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['inclusive'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ if (!array_key_exists('min', $options) || !array_key_exists('max', $options)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception("Missing option. 'min' and 'max' has to be given");
+ }
+
+ if (!array_key_exists('inclusive', $options)) {
+ $options['inclusive'] = true;
+ }
+
+ $this->setMin($options['min'])
+ ->setMax($options['max'])
+ ->setInclusive($options['inclusive']);
}
/**
diff --git a/libs/Zend/Validate/Callback.php b/libs/Zend/Validate/Callback.php
new file mode 100644
index 0000000000..398e27324c
--- /dev/null
+++ b/libs/Zend/Validate/Callback.php
@@ -0,0 +1,174 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Callback.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @see Zend_Validate_Abstract
+ */
+// require_once 'Zend/Validate/Abstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Callback extends Zend_Validate_Abstract
+{
+ /**
+ * Invalid callback
+ */
+ const INVALID_CALLBACK = 'callbackInvalid';
+
+ /**
+ * Invalid value
+ */
+ const INVALID_VALUE = 'callbackValue';
+
+ /**
+ * Validation failure message template definitions
+ *
+ * @var array
+ */
+ protected $_messageTemplates = array(
+ self::INVALID_VALUE => "'%value%' is not valid",
+ self::INVALID_CALLBACK => "Failure within the callback, exception returned",
+ );
+
+ /**
+ * Callback in a call_user_func format
+ *
+ * @var string|array
+ */
+ protected $_callback = null;
+
+ /**
+ * Default options to set for the filter
+ *
+ * @var mixed
+ */
+ protected $_options = array();
+
+ /**
+ * Sets validator options
+ *
+ * @param string|array $callback
+ * @param mixed $max
+ * @param boolean $inclusive
+ * @return void
+ */
+ public function __construct($callback = null)
+ {
+ if (is_callable($callback)) {
+ $this->setCallback($callback);
+ } elseif (is_array($callback)) {
+ if (isset($callback['callback'])) {
+ $this->setCallback($callback['callback']);
+ }
+ if (isset($callback['options'])) {
+ $this->setOptions($callback['options']);
+ }
+ }
+
+ if (null === ($initializedCallack = $this->getCallback())) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('No callback registered');
+ }
+ }
+
+ /**
+ * Returns the set callback
+ *
+ * @return mixed
+ */
+ public function getCallback()
+ {
+ return $this->_callback;
+ }
+
+ /**
+ * Sets the callback
+ *
+ * @param string|array $callback
+ * @return Zend_Validate_Callback Provides a fluent interface
+ */
+ public function setCallback($callback)
+ {
+ if (!is_callable($callback)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Invalid callback given');
+ }
+ $this->_callback = $callback;
+ return $this;
+ }
+
+ /**
+ * Returns the set options for the callback
+ *
+ * @return mixed
+ */
+ public function getOptions()
+ {
+ return $this->_options;
+ }
+
+ /**
+ * Sets options for the callback
+ *
+ * @param mixed $max
+ * @return Zend_Validate_Callback Provides a fluent interface
+ */
+ public function setOptions($options)
+ {
+ $this->_options = (array) $options;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Validate_Interface
+ *
+ * Returns true if and only if the set callback returns
+ * for the provided $value
+ *
+ * @param mixed $value
+ * @return boolean
+ */
+ public function isValid($value)
+ {
+ $this->_setValue($value);
+
+ $options = $this->getOptions();
+ $callback = $this->getCallback();
+ $args = func_get_args();
+ $options = array_merge($args, $options);
+
+ try {
+ if (!call_user_func_array($callback, $options)) {
+ $this->_error(self::INVALID_VALUE);
+ return false;
+ }
+ } catch (Exception $e) {
+ $this->_error(self::INVALID_CALLBACK);
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/libs/Zend/Validate/Ccnum.php b/libs/Zend/Validate/Ccnum.php
index 489573c48d..8c2a8beb14 100644
--- a/libs/Zend/Validate/Ccnum.php
+++ b/libs/Zend/Validate/Ccnum.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,22 +14,20 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Ccnum.php 16223 2009-06-21 20:04:53Z thomas $
+ * @version $Id: Ccnum.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
-
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
-
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Ccnum extends Zend_Validate_Abstract
@@ -62,6 +59,11 @@ class Zend_Validate_Ccnum extends Zend_Validate_Abstract
self::CHECKSUM => "Luhn algorithm (mod-10 checksum) failed on '%value%'"
);
+ public function __construct()
+ {
+ trigger_error('Using the Ccnum validator is deprecated in favor of the CreditCard validator');
+ }
+
/**
* Defined by Zend_Validate_Interface
*
@@ -78,7 +80,7 @@ class Zend_Validate_Ccnum extends Zend_Validate_Abstract
/**
* @see Zend_Filter_Digits
*/
- require_once 'Zend/Filter/Digits.php';
+ // require_once 'Zend/Filter/Digits.php';
self::$_filter = new Zend_Filter_Digits();
}
@@ -107,5 +109,4 @@ class Zend_Validate_Ccnum extends Zend_Validate_Abstract
return true;
}
-
}
diff --git a/libs/Zend/Validate/CreditCard.php b/libs/Zend/Validate/CreditCard.php
new file mode 100644
index 0000000000..9c8c039718
--- /dev/null
+++ b/libs/Zend/Validate/CreditCard.php
@@ -0,0 +1,317 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: CreditCard.php 21570 2010-03-19 19:00:50Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Abstract
+ */
+// require_once 'Zend/Validate/Abstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_CreditCard extends Zend_Validate_Abstract
+{
+ /**
+ * Detected CCI list
+ *
+ * @var string
+ */
+ const ALL = 'All';
+ const AMERICAN_EXPRESS = 'American_Express';
+ const UNIONPAY = 'Unionpay';
+ const DINERS_CLUB = 'Diners_Club';
+ const DINERS_CLUB_US = 'Diners_Club_US';
+ const DISCOVER = 'Discover';
+ const JCB = 'JCB';
+ const LASER = 'Laser';
+ const MAESTRO = 'Maestro';
+ const MASTERCARD = 'Mastercard';
+ const SOLO = 'Solo';
+ const VISA = 'Visa';
+
+ const CHECKSUM = 'creditcardChecksum';
+ const CONTENT = 'creditcardContent';
+ const INVALID = 'creditcardInvalid';
+ const LENGTH = 'creditcardLength';
+ const PREFIX = 'creditcardPrefix';
+ const SERVICE = 'creditcardService';
+ const SERVICEFAILURE = 'creditcardServiceFailure';
+
+ /**
+ * Validation failure message template definitions
+ *
+ * @var array
+ */
+ protected $_messageTemplates = array(
+ self::CHECKSUM => "Luhn algorithm (mod-10 checksum) failed on '%value%'",
+ self::CONTENT => "'%value%' must contain only digits",
+ self::INVALID => "Invalid type given, value should be a string",
+ self::LENGTH => "'%value%' contains an invalid amount of digits",
+ self::PREFIX => "'%value%' is not from an allowed institute",
+ self::SERVICE => "Validation of '%value%' has been failed by the service",
+ self::SERVICEFAILURE => "The service returned a failure while validating '%value%'",
+ );
+
+ /**
+ * List of allowed CCV lengths
+ *
+ * @var array
+ */
+ protected $_cardLength = array(
+ self::AMERICAN_EXPRESS => array(15),
+ self::DINERS_CLUB => array(14),
+ self::DINERS_CLUB_US => array(16),
+ self::DISCOVER => array(16),
+ self::JCB => array(16),
+ self::LASER => array(16, 17, 18, 19),
+ self::MAESTRO => array(12, 13, 14, 15, 16, 17, 18, 19),
+ self::MASTERCARD => array(16),
+ self::SOLO => array(16, 18, 19),
+ self::UNIONPAY => array(16, 17, 18, 19),
+ self::VISA => array(16),
+ );
+
+ /**
+ * List of accepted CCV provider tags
+ *
+ * @var array
+ */
+ protected $_cardType = array(
+ self::AMERICAN_EXPRESS => array('34', '37'),
+ self::DINERS_CLUB => array('300', '301', '302', '303', '304', '305', '36'),
+ self::DINERS_CLUB_US => array('54', '55'),
+ self::DISCOVER => array('6011', '622126', '622127', '622128', '622129', '62213',
+ '62214', '62215', '62216', '62217', '62218', '62219',
+ '6222', '6223', '6224', '6225', '6226', '6227', '6228',
+ '62290', '62291', '622920', '622921', '622922', '622923',
+ '622924', '622925', '644', '645', '646', '647', '648',
+ '649', '65'),
+ self::JCB => array('3528', '3529', '353', '354', '355', '356', '357', '358'),
+ self::LASER => array('6304', '6706', '6771', '6709'),
+ self::MAESTRO => array('5018', '5020', '5038', '6304', '6759', '6761', '6763'),
+ self::MASTERCARD => array('51', '52', '53', '54', '55'),
+ self::SOLO => array('6334', '6767'),
+ self::UNIONPAY => array('622126', '622127', '622128', '622129', '62213', '62214',
+ '62215', '62216', '62217', '62218', '62219', '6222', '6223',
+ '6224', '6225', '6226', '6227', '6228', '62290', '62291',
+ '622920', '622921', '622922', '622923', '622924', '622925'),
+ self::VISA => array('4'),
+ );
+
+ /**
+ * CCIs which are accepted by validation
+ *
+ * @var array
+ */
+ protected $_type = array();
+
+ /**
+ * Service callback for additional validation
+ *
+ * @var callback
+ */
+ protected $_service;
+
+ /**
+ * Constructor
+ *
+ * @param string|array $type OPTIONAL Type of CCI to allow
+ */
+ public function __construct($options = array())
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp['type'] = array_shift($options);
+ if (!empty($options)) {
+ $temp['service'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ if (!array_key_exists('type', $options)) {
+ $options['type'] = self::ALL;
+ }
+
+ $this->setType($options['type']);
+ if (array_key_exists('service', $options)) {
+ $this->setService($options['service']);
+ }
+ }
+
+ /**
+ * Returns a list of accepted CCIs
+ *
+ * @return array
+ */
+ public function getType()
+ {
+ return $this->_type;
+ }
+
+ /**
+ * Sets CCIs which are accepted by validation
+ *
+ * @param string|array $type Type to allow for validation
+ * @return Zend_Validate_CreditCard Provides a fluid interface
+ */
+ public function setType($type)
+ {
+ $this->_type = array();
+ return $this->addType($type);
+ }
+
+ /**
+ * Adds a CCI to be accepted by validation
+ *
+ * @param string|array $type Type to allow for validation
+ * @return Zend_Validate_CreditCard Provides a fluid interface
+ */
+ public function addType($type)
+ {
+ if (is_string($type)) {
+ $type = array($type);
+ }
+
+ foreach($type as $typ) {
+ if (defined('self::' . strtoupper($typ)) && !in_array($typ, $this->_type)) {
+ $this->_type[] = $typ;
+ }
+
+ if (($typ == self::ALL)) {
+ $this->_type = array_keys($this->_cardLength);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns the actual set service
+ *
+ * @return callback
+ */
+ public function getService()
+ {
+ return $this->_service;
+ }
+
+ /**
+ * Sets a new callback for service validation
+ *
+ * @param unknown_type $service
+ */
+ public function setService($service)
+ {
+ if (!is_callable($service)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Invalid callback given');
+ }
+
+ $this->_service = $service;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Validate_Interface
+ *
+ * Returns true if and only if $value follows the Luhn algorithm (mod-10 checksum)
+ *
+ * @param string $value
+ * @return boolean
+ */
+ public function isValid($value)
+ {
+ $this->_setValue($value);
+
+ if (!is_string($value)) {
+ $this->_error(self::INVALID, $value);
+ return false;
+ }
+
+ if (!ctype_digit($value)) {
+ $this->_error(self::CONTENT, $value);
+ return false;
+ }
+
+ $length = strlen($value);
+ $types = $this->getType();
+ $foundp = false;
+ $foundl = false;
+ foreach ($types as $type) {
+ foreach ($this->_cardType[$type] as $prefix) {
+ if (substr($value, 0, strlen($prefix)) == $prefix) {
+ $foundp = true;
+ if (in_array($length, $this->_cardLength[$type])) {
+ $foundl = true;
+ break 2;
+ }
+ }
+ }
+ }
+
+ if ($foundp == false){
+ $this->_error(self::PREFIX, $value);
+ return false;
+ }
+
+ if ($foundl == false) {
+ $this->_error(self::LENGTH, $value);
+ return false;
+ }
+
+ $sum = 0;
+ $weight = 2;
+
+ for ($i = $length - 2; $i >= 0; $i--) {
+ $digit = $weight * $value[$i];
+ $sum += floor($digit / 10) + $digit % 10;
+ $weight = $weight % 2 + 1;
+ }
+
+ if ((10 - $sum % 10) % 10 != $value[$length - 1]) {
+ $this->_error(self::CHECKSUM, $value);
+ return false;
+ }
+
+ if (!empty($this->_service)) {
+ try {
+ // require_once 'Zend/Validate/Callback.php';
+ $callback = new Zend_Validate_Callback($this->_service);
+ $callback->setOptions($this->_type);
+ if (!$callback->isValid($value)) {
+ $this->_error(self::SERVICE, $value);
+ return false;
+ }
+ } catch (Zend_Exception $e) {
+ $this->_error(self::SERVICEFAILURE, $value);
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/libs/Zend/Validate/Date.php b/libs/Zend/Validate/Date.php
index 5dbcc6d702..22e49b7aee 100644
--- a/libs/Zend/Validate/Date.php
+++ b/libs/Zend/Validate/Date.php
@@ -14,27 +14,26 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Date.php 17696 2009-08-20 20:12:33Z thomas $
+ * @version $Id: Date.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Date extends Zend_Validate_Abstract
{
const INVALID = 'dateInvalid';
- const NOT_YYYY_MM_DD = 'dateNotYYYY-MM-DD';
- const INVALID_DATE = 'dateInvalidDate';
+ const INVALID_DATE = 'dateInvalidDate';
const FALSEFORMAT = 'dateFalseFormat';
/**
@@ -44,9 +43,15 @@ class Zend_Validate_Date extends Zend_Validate_Abstract
*/
protected $_messageTemplates = array(
self::INVALID => "Invalid type given, value should be string, integer, array or Zend_Date",
- self::NOT_YYYY_MM_DD => "'%value%' is not of the format YYYY-MM-DD",
self::INVALID_DATE => "'%value%' does not appear to be a valid date",
- self::FALSEFORMAT => "'%value%' does not fit given date format"
+ self::FALSEFORMAT => "'%value%' does not fit the date format '%format%'",
+ );
+
+ /**
+ * @var array
+ */
+ protected $_messageVariables = array(
+ 'format' => '_format'
);
/**
@@ -66,22 +71,36 @@ class Zend_Validate_Date extends Zend_Validate_Abstract
/**
* Sets validator options
*
- * @param string $format OPTIONAL
- * @param string|Zend_Locale $locale OPTIONAL
+ * @param string|Zend_Config $options OPTIONAL
* @return void
*/
- public function __construct($format = null, $locale = null)
+ public function __construct($options = array())
{
- $this->setFormat($format);
- if ($locale === null) {
- require_once 'Zend/Registry.php';
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp['format'] = array_shift($options);
+ if (!empty($options)) {
+ $temp['locale'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ if (array_key_exists('format', $options)) {
+ $this->setFormat($options['format']);
+ }
+
+ if (!array_key_exists('locale', $options)) {
+ // require_once 'Zend/Registry.php';
if (Zend_Registry::isRegistered('Zend_Locale')) {
- $locale = Zend_Registry::get('Zend_Locale');
+ $options['locale'] = Zend_Registry::get('Zend_Locale');
}
}
- if ($locale !== null) {
- $this->setLocale($locale);
+ if (array_key_exists('locale', $options)) {
+ $this->setLocale($options['locale']);
}
}
@@ -103,7 +122,7 @@ class Zend_Validate_Date extends Zend_Validate_Abstract
*/
public function setLocale($locale = null)
{
- require_once 'Zend/Locale.php';
+ // require_once 'Zend/Locale.php';
$this->_locale = Zend_Locale::findLocale($locale);
return $this;
}
@@ -152,7 +171,7 @@ class Zend_Validate_Date extends Zend_Validate_Abstract
if (($this->_format !== null) || ($this->_locale !== null) || is_array($value) ||
$value instanceof Zend_Date) {
- require_once 'Zend/Date.php';
+ // require_once 'Zend/Date.php';
if (!Zend_Date::isDate($value, $this->_format, $this->_locale)) {
if ($this->_checkFormat($value) === false) {
$this->_error(self::FALSEFORMAT);
@@ -163,7 +182,9 @@ class Zend_Validate_Date extends Zend_Validate_Abstract
}
} else {
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
- $this->_error(self::NOT_YYYY_MM_DD);
+ $this->_format = 'yyyy-MM-dd';
+ $this->_error(self::FALSEFORMAT);
+ $this->_format = null;
return false;
}
@@ -187,7 +208,7 @@ class Zend_Validate_Date extends Zend_Validate_Abstract
private function _checkFormat($value)
{
try {
- require_once 'Zend/Locale/Format.php';
+ // require_once 'Zend/Locale/Format.php';
$parsed = Zend_Locale_Format::getDate($value, array(
'date_format' => $this->_format, 'format_type' => 'iso',
'fix_date' => false));
diff --git a/libs/Zend/Validate/Db/Abstract.php b/libs/Zend/Validate/Db/Abstract.php
index e5103ff4ed..5811c495a9 100644
--- a/libs/Zend/Validate/Db/Abstract.php
+++ b/libs/Zend/Validate/Db/Abstract.php
@@ -1,5 +1,4 @@
-<?php
-
+<?php
/**
* Zend Framework
*
@@ -15,134 +14,285 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Abstract.php 17160 2009-07-26 19:46:24Z bittarman $
- */
-
+ * @version $Id: Abstract.php 22225 2010-05-21 09:12:52Z bittarman $
+ */
+
/**
* @see Zend_Validate_Abstract
- */
-require_once 'Zend/Validate/Abstract.php';
-
+ */
+// require_once 'Zend/Validate/Abstract.php';
+
/**
* Class for Database record validation
- *
+ *
* @category Zend
* @package Zend_Validate
* @uses Zend_Validate_Abstract
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- */
-abstract class Zend_Validate_Db_Abstract extends Zend_Validate_Abstract
-{
+ */
+abstract class Zend_Validate_Db_Abstract extends Zend_Validate_Abstract
+{
/**
* Error constants
- */
- const ERROR_NO_RECORD_FOUND = 'noRecordFound';
- const ERROR_RECORD_FOUND = 'recordFound';
-
+ */
+ const ERROR_NO_RECORD_FOUND = 'noRecordFound';
+ const ERROR_RECORD_FOUND = 'recordFound';
+
/**
* @var array Message templates
- */
- protected $_messageTemplates = array(self::ERROR_NO_RECORD_FOUND => 'No record matching %value% was found',
- self::ERROR_RECORD_FOUND => 'A record matching %value% was found');
+ */
+ protected $_messageTemplates = array(
+ self::ERROR_NO_RECORD_FOUND => 'No record matching %value% was found',
+ self::ERROR_RECORD_FOUND => 'A record matching %value% was found',
+ );
/**
* @var string
- */
+ */
protected $_schema = null;
-
+
/**
* @var string
- */
- protected $_table = '';
-
+ */
+ protected $_table = '';
+
/**
* @var string
- */
- protected $_field = '';
-
+ */
+ protected $_field = '';
+
/**
* @var mixed
- */
- protected $_exclude = null;
-
+ */
+ protected $_exclude = null;
+
/**
* Database adapter to use. If null isValid() will use Zend_Db::getInstance instead
*
* @var unknown_type
- */
- protected $_adapter = null;
-
+ */
+ protected $_adapter = null;
+
/**
- * Provides basic configuration for use with Zend_Validate_Db Validators
+ * Provides basic configuration for use with Zend_Validate_Db Validators
* Setting $exclude allows a single record to be excluded from matching.
* Exclude can either be a String containing a where clause, or an array with `field` and `value` keys
- * to define the where clause added to the sql.
- * A database adapter may optionally be supplied to avoid using the registered default adapter.
- *
- * @param string||array $table The database table to validate against, or array with table and schema keys
- * @param string $field The field to check for a match
- * @param string||array $exclude An optional where clause or field/value pair to exclude from the query
- * @param Zend_Db_Adapter_Abstract $adapter An optional database adapter to use.
- */
- public function __construct($table, $field, $exclude = null, Zend_Db_Adapter_Abstract $adapter = null)
- {
- if ($adapter !== null) {
- $this->_adapter = $adapter;
- }
- $this->_exclude = $exclude;
- $this->_field = (string) $field;
-
- if (is_array($table)) {
- $this->_table = (isset($table['table'])) ? $table['table'] : '';
- $this->_schema = (isset($table['schema'])) ? $table['schema'] : null;
- } else {
- $this->_table = (string) $table;
+ * to define the where clause added to the sql.
+ * A database adapter may optionally be supplied to avoid using the registered default adapter.
+ *
+ * The following option keys are supported:
+ * 'table' => The database table to validate against
+ * 'schema' => The schema keys
+ * 'field' => The field to check for a match
+ * 'exclude' => An optional where clause or field/value pair to exclude from the query
+ * 'adapter' => An optional database adapter to use
+ *
+ * @param array|Zend_Config $options Options to use for this validator
+ */
+ public function __construct($options)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (func_num_args() > 1) {
+ $options = func_get_args();
+ $temp['table'] = array_shift($options);
+ $temp['field'] = array_shift($options);
+ if (!empty($options)) {
+ $temp['exclude'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['adapter'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ if (!array_key_exists('table', $options) && !array_key_exists('schema', $options)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Table or Schema option missing!');
+ }
+
+ if (!array_key_exists('field', $options)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Field option missing!');
+ }
+
+ if (array_key_exists('adapter', $options)) {
+ $this->setAdapter($options['adapter']);
+ }
+
+ if (array_key_exists('exclude', $options)) {
+ $this->setExclude($options['exclude']);
+ }
+
+ $this->setField($options['field']);
+ if (array_key_exists('table', $options)) {
+ $this->setTable($options['table']);
+ }
+
+ if (array_key_exists('schema', $options)) {
+ $this->setSchema($options['schema']);
}
+ }
+
+ /**
+ * Returns the set adapter
+ *
+ * @return Zend_Db_Adapter
+ */
+ public function getAdapter()
+ {
+ return $this->_adapter;
+ }
+
+ /**
+ * Sets a new database adapter
+ *
+ * @param Zend_Db_Adapter_Abstract $adapter
+ * @return Zend_Validate_Db_Abstract
+ */
+ public function setAdapter($adapter)
+ {
+ if (!($adapter instanceof Zend_Db_Adapter_Abstract)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Adapter option must be a database adapter!');
+ }
+
+ $this->_adapter = $adapter;
+ return $this;
+ }
+
+ /**
+ * Returns the set exclude clause
+ *
+ * @return string|array
+ */
+ public function getExclude()
+ {
+ return $this->_exclude;
+ }
+
+ /**
+ * Sets a new exclude clause
+ *
+ * @param string|array $exclude
+ * @return Zend_Validate_Db_Abstract
+ */
+ public function setExclude($exclude)
+ {
+ $this->_exclude = $exclude;
+ return $this;
+ }
+
+ /**
+ * Returns the set field
+ *
+ * @return string|array
+ */
+ public function getField()
+ {
+ return $this->_field;
+ }
+
+ /**
+ * Sets a new field
+ *
+ * @param string $field
+ * @return Zend_Validate_Db_Abstract
+ */
+ public function setField($field)
+ {
+ $this->_field = (string) $field;
+ return $this;
+ }
+
+ /**
+ * Returns the set table
+ *
+ * @return string
+ */
+ public function getTable()
+ {
+ return $this->_table;
+ }
+
+ /**
+ * Sets a new table
+ *
+ * @param string $table
+ * @return Zend_Validate_Db_Abstract
+ */
+ public function setTable($table)
+ {
+ $this->_table = (string) $table;
+ return $this;
+ }
+
+ /**
+ * Returns the set schema
+ *
+ * @return string
+ */
+ public function getSchema()
+ {
+ return $this->_schema;
+ }
+
+ /**
+ * Sets a new schema
+ *
+ * @param string $schema
+ * @return Zend_Validate_Db_Abstract
+ */
+ public function setSchema($schema)
+ {
+ $this->_schema = $schema;
+ return $this;
+ }
- }
-
/**
* Run query and returns matches, or null if no matches are found.
*
* @param String $value
* @return Array when matches are found.
- */
- protected function _query($value)
- {
+ */
+ protected function _query($value)
+ {
/**
* Check for an adapter being defined. if not, fetch the default adapter.
- */
+ */
if ($this->_adapter === null) {
$this->_adapter = Zend_Db_Table_Abstract::getDefaultAdapter();
if (null === $this->_adapter) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception('No database adapter present');
}
}
/**
* Build select object
- */
+ */
$select = new Zend_Db_Select($this->_adapter);
$select->from($this->_table, array($this->_field), $this->_schema)
- ->where($this->_adapter->quoteIdentifier($this->_field).' = ?', $value);
- if ($this->_exclude !== null) {
- if (is_array($this->_exclude)) {
- $select->where($this->_adapter->quoteIdentifier($this->_exclude['field']).' != ?', $this->_exclude['value']);
- } else {
- $select->where($this->_exclude);
- }
- }
- $select->limit(1);
-
+ ->where($this->_adapter->quoteIdentifier($this->_field, true).' = ?', $value);
+ if ($this->_exclude !== null) {
+ if (is_array($this->_exclude)) {
+ $select->where($this->_adapter->quoteIdentifier($this->_exclude['field'], true).' != ?', $this->_exclude['value']);
+ } else {
+ $select->where($this->_exclude);
+ }
+ }
+ $select->limit(1);
+
/**
* Run query
- */
- $result = $this->_adapter->fetchRow($select, array(), Zend_Db::FETCH_ASSOC);
-
- return $result;
- }
+ */
+ $result = $this->_adapter->fetchRow($select, array(), Zend_Db::FETCH_ASSOC);
+
+ return $result;
+ }
}
diff --git a/libs/Zend/Validate/Db/NoRecordExists.php b/libs/Zend/Validate/Db/NoRecordExists.php
index e9c0db49a8..700102e436 100644
--- a/libs/Zend/Validate/Db/NoRecordExists.php
+++ b/libs/Zend/Validate/Db/NoRecordExists.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,15 +14,15 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: NoRecordExists.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: NoRecordExists.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
* @see Zend_Validate_Db_Abstract
*/
-require_once 'Zend/Validate/Db/Abstract.php';
+// require_once 'Zend/Validate/Db/Abstract.php';
/**
* Confirms a record does not exist in a table.
@@ -31,7 +30,7 @@ require_once 'Zend/Validate/Db/Abstract.php';
* @category Zend
* @package Zend_Validate
* @uses Zend_Validate_Db_Abstract
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Db_NoRecordExists extends Zend_Validate_Db_Abstract
diff --git a/libs/Zend/Validate/Db/RecordExists.php b/libs/Zend/Validate/Db/RecordExists.php
index 2d753e4b0a..bf96b96f5c 100644
--- a/libs/Zend/Validate/Db/RecordExists.php
+++ b/libs/Zend/Validate/Db/RecordExists.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,39 +14,38 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: RecordExists.php 16971 2009-07-22 18:05:45Z mikaelkael $
- */
-
-
+ * @version $Id: RecordExists.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
/**
* @see Zend_Validate_Db_Abstract
- */
-require_once 'Zend/Validate/Db/Abstract.php';
-
+ */
+// require_once 'Zend/Validate/Db/Abstract.php';
+
/**
* Confirms a record exists in a table.
- *
+ *
* @category Zend
* @package Zend_Validate
* @uses Zend_Validate_Db_Abstract
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- */
-class Zend_Validate_Db_RecordExists extends Zend_Validate_Db_Abstract
-{
- public function isValid($value)
- {
- $valid = true;
- $this->_setValue($value);
-
- $result = $this->_query($value);
- if (!$result) {
- $valid = false;
- $this->_error(self::ERROR_NO_RECORD_FOUND);
- }
-
- return $valid;
- }
+ */
+class Zend_Validate_Db_RecordExists extends Zend_Validate_Db_Abstract
+{
+ public function isValid($value)
+ {
+ $valid = true;
+ $this->_setValue($value);
+
+ $result = $this->_query($value);
+ if (!$result) {
+ $valid = false;
+ $this->_error(self::ERROR_NO_RECORD_FOUND);
+ }
+
+ return $valid;
+ }
}
diff --git a/libs/Zend/Validate/Digits.php b/libs/Zend/Validate/Digits.php
index 12e6c4e454..9194568e27 100644
--- a/libs/Zend/Validate/Digits.php
+++ b/libs/Zend/Validate/Digits.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,28 +14,26 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Digits.php 16933 2009-07-21 20:24:35Z matthew $
+ * @version $Id: Digits.php 21136 2010-02-22 22:30:50Z thomas $
*/
-
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
-
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Digits extends Zend_Validate_Abstract
{
const NOT_DIGITS = 'notDigits';
- const STRING_EMPTY = 'stringEmpty';
+ const STRING_EMPTY = 'digitsStringEmpty';
const INVALID = 'digitsInvalid';
/**
@@ -52,7 +49,7 @@ class Zend_Validate_Digits extends Zend_Validate_Abstract
* @var array
*/
protected $_messageTemplates = array(
- self::NOT_DIGITS => "'%value%' contains not only digit characters",
+ self::NOT_DIGITS => "'%value%' contains characters which are not digits; but only digits are allowed",
self::STRING_EMPTY => "'%value%' is an empty string",
self::INVALID => "Invalid type given, value should be string, integer or float",
);
@@ -80,7 +77,7 @@ class Zend_Validate_Digits extends Zend_Validate_Abstract
}
if (null === self::$_filter) {
- require_once 'Zend/Filter/Digits.php';
+ // require_once 'Zend/Filter/Digits.php';
self::$_filter = new Zend_Filter_Digits();
}
@@ -91,5 +88,4 @@ class Zend_Validate_Digits extends Zend_Validate_Abstract
return true;
}
-
}
diff --git a/libs/Zend/Validate/EmailAddress.php b/libs/Zend/Validate/EmailAddress.php
index 4948bb83f3..c008dcfe9f 100644
--- a/libs/Zend/Validate/EmailAddress.php
+++ b/libs/Zend/Validate/EmailAddress.php
@@ -14,25 +14,25 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: EmailAddress.php 16223 2009-06-21 20:04:53Z thomas $
+ * @version $Id: EmailAddress.php 21461 2010-03-10 22:34:03Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @see Zend_Validate_Hostname
*/
-require_once 'Zend/Validate/Hostname.php';
+// require_once 'Zend/Validate/Hostname.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
@@ -41,6 +41,7 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
const INVALID_FORMAT = 'emailAddressInvalidFormat';
const INVALID_HOSTNAME = 'emailAddressInvalidHostname';
const INVALID_MX_RECORD = 'emailAddressInvalidMxRecord';
+ const INVALID_SEGMENT = 'emailAddressInvalidSegment';
const DOT_ATOM = 'emailAddressDotAtom';
const QUOTED_STRING = 'emailAddressQuotedString';
const INVALID_LOCAL_PART = 'emailAddressInvalidLocalPart';
@@ -51,37 +52,47 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
*/
protected $_messageTemplates = array(
self::INVALID => "Invalid type given, value should be a string",
- self::INVALID_FORMAT => "'%value%' is not a valid email address in the basic format local-part@hostname",
- self::INVALID_HOSTNAME => "'%hostname%' is not a valid hostname for email address '%value%'",
+ self::INVALID_FORMAT => "'%value%' is no valid email address in the basic format local-part@hostname",
+ self::INVALID_HOSTNAME => "'%hostname%' is no valid hostname for email address '%value%'",
self::INVALID_MX_RECORD => "'%hostname%' does not appear to have a valid MX record for the email address '%value%'",
- self::DOT_ATOM => "'%localPart%' not matched against dot-atom format",
- self::QUOTED_STRING => "'%localPart%' not matched against quoted-string format",
- self::INVALID_LOCAL_PART => "'%localPart%' is not a valid local part for email address '%value%'",
- self::LENGTH_EXCEEDED => "'%value%' exceeds the allowed length"
+ self::INVALID_SEGMENT => "'%hostname%' is not in a routable network segment. The email address '%value%' should not be resolved from public network.",
+ self::DOT_ATOM => "'%localPart%' can not be matched against dot-atom format",
+ self::QUOTED_STRING => "'%localPart%' can not be matched against quoted-string format",
+ self::INVALID_LOCAL_PART => "'%localPart%' is no valid local part for email address '%value%'",
+ self::LENGTH_EXCEEDED => "'%value%' exceeds the allowed length",
);
/**
+ * @see http://en.wikipedia.org/wiki/IPv4
* @var array
*/
- protected $_messageVariables = array(
- 'hostname' => '_hostname',
- 'localPart' => '_localPart'
+ protected $_invalidIp = array(
+ '0' => '0.0.0.0/8',
+ '10' => '10.0.0.0/8',
+ '127' => '127.0.0.0/8',
+ '128' => '128.0.0.0/16',
+ '169' => '169.254.0.0/16',
+ '172' => '172.16.0.0/12',
+ '191' => '191.255.0.0/16',
+ '192' => array(
+ '192.0.0.0/24',
+ '192.0.2.0/24',
+ '192.88.99.0/24',
+ '192.168.0.0/16'
+ ),
+ '198' => '198.18.0.0/15',
+ '223' => '223.255.255.0/24',
+ '224' => '224.0.0.0/4',
+ '240' => '240.0.0.0/4'
);
/**
- * Local object for validating the hostname part of an email address
- *
- * @var Zend_Validate_Hostname
- * @depreciated
- */
- public $hostnameValidator;
-
- /**
- * Whether we check for a valid MX record via DNS
- *
- * @var boolean
+ * @var array
*/
- protected $_validateMx = false;
+ protected $_messageVariables = array(
+ 'hostname' => '_hostname',
+ 'localPart' => '_localPart'
+ );
/**
* @var string
@@ -94,21 +105,118 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
protected $_localPart;
/**
+ * Internal options array
+ */
+ protected $_options = array(
+ 'mx' => false,
+ 'deep' => false,
+ 'domain' => true,
+ 'allow' => Zend_Validate_Hostname::ALLOW_DNS,
+ 'hostname' => null
+ );
+
+ /**
* Instantiates hostname validator for local use
*
- * You can pass a bitfield to determine what types of hostnames are allowed.
- * These bitfields are defined by the ALLOW_* constants in Zend_Validate_Hostname
- * The default is to allow DNS hostnames only
+ * The following option keys are supported:
+ * 'hostname' => A hostname validator, see Zend_Validate_Hostname
+ * 'allow' => Options for the hostname validator, see Zend_Validate_Hostname::ALLOW_*
+ * 'mx' => If MX check should be enabled, boolean
+ * 'deep' => If a deep MX check should be done, boolean
*
- * @param integer $allow OPTIONAL
- * @param bool $validateMx OPTIONAL
- * @param Zend_Validate_Hostname $hostnameValidator OPTIONAL
+ * @param array|Zend_Config $options OPTIONAL
* @return void
*/
- public function __construct($allow = Zend_Validate_Hostname::ALLOW_DNS, $validateMx = false, Zend_Validate_Hostname $hostnameValidator = null)
+ public function __construct($options = array())
{
- $this->setValidateMx($validateMx);
- $this->setHostnameValidator($hostnameValidator, $allow);
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp['allow'] = array_shift($options);
+ if (!empty($options)) {
+ $temp['mx'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['hostname'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ $options += $this->_options;
+ $this->setOptions($options);
+ }
+
+ /**
+ * Returns all set Options
+ *
+ * @return array
+ */
+ public function getOptions()
+ {
+ return $this->_options;
+ }
+
+ /**
+ * Set options for the email validator
+ *
+ * @param array $options
+ * @return Zend_Validate_EmailAddress fluid interface
+ */
+ public function setOptions(array $options = array())
+ {
+ if (array_key_exists('messages', $options)) {
+ $this->setMessages($options['messages']);
+ }
+
+ if (array_key_exists('hostname', $options)) {
+ if (array_key_exists('allow', $options)) {
+ $this->setHostnameValidator($options['hostname'], $options['allow']);
+ } else {
+ $this->setHostnameValidator($options['hostname']);
+ }
+ }
+
+ if (array_key_exists('mx', $options)) {
+ $this->setValidateMx($options['mx']);
+ }
+
+ if (array_key_exists('deep', $options)) {
+ $this->setDeepMxCheck($options['deep']);
+ }
+
+ if (array_key_exists('domain', $options)) {
+ $this->setDomainCheck($options['domain']);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Sets the validation failure message template for a particular key
+ * Adds the ability to set messages to the attached hostname validator
+ *
+ * @param string $messageString
+ * @param string $messageKey OPTIONAL
+ * @return Zend_Validate_Abstract Provides a fluent interface
+ * @throws Zend_Validate_Exception
+ */
+ public function setMessage($messageString, $messageKey = null)
+ {
+ $messageKeys = $messageKey;
+ if ($messageKey === null) {
+ $keys = array_keys($this->_messageTemplates);
+ $messageKeys = current($keys);
+ }
+
+ if (!isset($this->_messageTemplates[$messageKeys])) {
+ $this->_options['hostname']->setMessage($messageString, $messageKey);
+ }
+
+ $this->_messageTemplates[$messageKeys] = $messageString;
+ return $this;
}
/**
@@ -118,7 +226,7 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
*/
public function getHostnameValidator()
{
- return $this->hostnameValidator;
+ return $this->_options['hostname'];
}
/**
@@ -128,14 +236,17 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
*/
public function setHostnameValidator(Zend_Validate_Hostname $hostnameValidator = null, $allow = Zend_Validate_Hostname::ALLOW_DNS)
{
- if ($hostnameValidator === null) {
+ if (!$hostnameValidator) {
$hostnameValidator = new Zend_Validate_Hostname($allow);
}
- $this->hostnameValidator = $hostnameValidator;
+
+ $this->_options['hostname'] = $hostnameValidator;
+ $this->_options['allow'] = $allow;
+ return $this;
}
/**
- * Whether MX checking via dns_get_mx is supported or not
+ * Whether MX checking via getmxrr is supported or not
*
* This currently only works on UNIX systems
*
@@ -143,7 +254,17 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
*/
public function validateMxSupported()
{
- return function_exists('dns_get_mx');
+ return function_exists('getmxrr');
+ }
+
+ /**
+ * Returns the set validateMx option
+ *
+ * @return boolean
+ */
+ public function getValidateMx()
+ {
+ return $this->_options['mx'];
}
/**
@@ -151,11 +272,236 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
*
* This only applies when DNS hostnames are validated
*
- * @param boolean $allowed Set allowed to true to validate for MX records, and false to not validate them
+ * @param boolean $mx Set allowed to true to validate for MX records, and false to not validate them
+ * @return Zend_Validate_EmailAddress Fluid Interface
+ */
+ public function setValidateMx($mx)
+ {
+ if ((bool) $mx && !$this->validateMxSupported()) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('MX checking not available on this system');
+ }
+
+ $this->_options['mx'] = (bool) $mx;
+ return $this;
+ }
+
+ /**
+ * Returns the set deepMxCheck option
+ *
+ * @return boolean
+ */
+ public function getDeepMxCheck()
+ {
+ return $this->_options['deep'];
+ }
+
+ /**
+ * Set whether we check MX record should be a deep validation
+ *
+ * @param boolean $deep Set deep to true to perform a deep validation process for MX records
+ * @return Zend_Validate_EmailAddress Fluid Interface
*/
- public function setValidateMx($allowed)
+ public function setDeepMxCheck($deep)
{
- $this->_validateMx = (bool) $allowed;
+ $this->_options['deep'] = (bool) $deep;
+ return $this;
+ }
+
+ /**
+ * Returns the set domainCheck option
+ *
+ * @return unknown
+ */
+ public function getDomainCheck()
+ {
+ return $this->_options['domain'];
+ }
+
+ /**
+ * Sets if the domain should also be checked
+ * or only the local part of the email address
+ *
+ * @param boolean $domain
+ * @return Zend_Validate_EmailAddress Fluid Interface
+ */
+ public function setDomainCheck($domain = true)
+ {
+ $this->_options['domain'] = (boolean) $domain;
+ return $this;
+ }
+
+ /**
+ * Returns if the given host is reserved
+ *
+ * @param string $host
+ * @return boolean
+ */
+ private function _isReserved($host){
+ if (!preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $host)) {
+ $host = gethostbyname($host);
+ }
+
+ $octet = explode('.',$host);
+ if ((int)$octet[0] >= 224) {
+ return true;
+ } else if (array_key_exists($octet[0], $this->_invalidIp)) {
+ foreach ((array)$this->_invalidIp[$octet[0]] as $subnetData) {
+ // we skip the first loop as we already know that octet matches
+ for ($i = 1; $i < 4; $i++) {
+ if (strpos($subnetData, $octet[$i]) !== $i * 4) {
+ break;
+ }
+ }
+
+ $host = explode("/", $subnetData);
+ $binaryHost = "";
+ $tmp = explode(".", $host[0]);
+ for ($i = 0; $i < 4 ; $i++) {
+ $binaryHost .= str_pad(decbin($tmp[$i]), 8, "0", STR_PAD_LEFT);
+ }
+
+ $segmentData = array(
+ 'network' => (int)$this->_toIp(str_pad(substr($binaryHost, 0, $host[1]), 32, 0)),
+ 'broadcast' => (int)$this->_toIp(str_pad(substr($binaryHost, 0, $host[1]), 32, 1))
+ );
+
+ for ($j = $i; $j < 4; $j++) {
+ if ((int)$octet[$j] < $segmentData['network'][$j] ||
+ (int)$octet[$j] > $segmentData['broadcast'][$j]) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Converts a binary string to an IP address
+ *
+ * @param string $binary
+ * @return mixed
+ */
+ private function _toIp($binary)
+ {
+ $ip = array();
+ $tmp = explode(".", chunk_split($binary, 8, "."));
+ for ($i = 0; $i < 4 ; $i++) {
+ $ip[$i] = bindec($tmp[$i]);
+ }
+
+ return $ip;
+ }
+
+ /**
+ * Internal method to validate the local part of the email address
+ *
+ * @return boolean
+ */
+ private function _validateLocalPart()
+ {
+ // First try to match the local part on the common dot-atom format
+ $result = false;
+
+ // Dot-atom characters are: 1*atext *("." 1*atext)
+ // atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*",
+ // "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~"
+ $atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e';
+ if (preg_match('/^[' . $atext . ']+(\x2e+[' . $atext . ']+)*$/', $this->_localPart)) {
+ $result = true;
+ } else {
+ // Try quoted string format
+
+ // Quoted-string characters are: DQUOTE *([FWS] qtext/quoted-pair) [FWS] DQUOTE
+ // qtext: Non white space controls, and the rest of the US-ASCII characters not
+ // including "\" or the quote character
+ $noWsCtl = '\x01-\x08\x0b\x0c\x0e-\x1f\x7f';
+ $qtext = $noWsCtl . '\x21\x23-\x5b\x5d-\x7e';
+ $ws = '\x20\x09';
+ if (preg_match('/^\x22([' . $ws . $qtext . '])*[$ws]?\x22$/', $this->_localPart)) {
+ $result = true;
+ } else {
+ $this->_error(self::DOT_ATOM);
+ $this->_error(self::QUOTED_STRING);
+ $this->_error(self::INVALID_LOCAL_PART);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Internal method to validate the servers MX records
+ *
+ * @return boolean
+ */
+ private function _validateMXRecords()
+ {
+ $mxHosts = array();
+ $result = getmxrr($this->_hostname, $mxHosts);
+ if (!$result) {
+ $this->_error(self::INVALID_MX_RECORD);
+ } else if ($this->_options['deep'] && function_exists('checkdnsrr')) {
+ $validAddress = false;
+ $reserved = true;
+ foreach ($mxHosts as $hostname) {
+ $res = $this->_isReserved($hostname);
+ if (!$res) {
+ $reserved = false;
+ }
+
+ if (!$res
+ && (checkdnsrr($hostname, "A")
+ || checkdnsrr($hostname, "AAAA")
+ || checkdnsrr($hostname, "A6"))) {
+ $validAddress = true;
+ break;
+ }
+ }
+
+ if (!$validAddress) {
+ $result = false;
+ if ($reserved) {
+ $this->_error(self::INVALID_SEGMENT);
+ } else {
+ $this->_error(self::INVALID_MX_RECORD);
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Internal method to validate the hostname part of the email address
+ *
+ * @return boolean
+ */
+ private function _validateHostnamePart()
+ {
+ $hostname = $this->_options['hostname']->setTranslator($this->getTranslator())
+ ->isValid($this->_hostname);
+ if (!$hostname) {
+ $this->_error(self::INVALID_HOSTNAME);
+
+ // Get messages and errors from hostnameValidator
+ foreach ($this->_options['hostname']->getMessages() as $code => $message) {
+ $this->_messages[$code] = $message;
+ }
+
+ foreach ($this->_options['hostname']->getErrors() as $error) {
+ $this->_errors[] = $error;
+ }
+ } else if ($this->_options['mx']) {
+ // MX check on hostname
+ $hostname = $this->_validateMXRecords();
+ }
+
+ return $hostname;
}
/**
@@ -176,9 +522,8 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
return false;
}
- $matches = array();
- $length = true;
-
+ $matches = array();
+ $length = true;
$this->_setValue($value);
// Split email address up and disallow '..'
@@ -197,68 +542,19 @@ class Zend_Validate_EmailAddress extends Zend_Validate_Abstract
}
// Match hostname part
- $hostnameResult = $this->hostnameValidator->setTranslator($this->getTranslator())
- ->isValid($this->_hostname);
- if (!$hostnameResult) {
- $this->_error(self::INVALID_HOSTNAME);
-
- // Get messages and errors from hostnameValidator
- foreach ($this->hostnameValidator->getMessages() as $code => $message) {
- $this->_messages[$code] = $message;
- }
- foreach ($this->hostnameValidator->getErrors() as $error) {
- $this->_errors[] = $error;
- }
- } else if ($this->_validateMx) {
- // MX check on hostname via dns_get_record()
- if ($this->validateMxSupported()) {
- $result = dns_get_mx($this->_hostname, $mxHosts);
- if (count($mxHosts) < 1) {
- $hostnameResult = false;
- $this->_error(self::INVALID_MX_RECORD);
- }
- } else {
- /**
- * MX checks are not supported by this system
- * @see Zend_Validate_Exception
- */
- require_once 'Zend/Validate/Exception.php';
- throw new Zend_Validate_Exception('Internal error: MX checking not available on this system');
- }
+ if ($this->_options['domain']) {
+ $hostname = $this->_validateHostnamePart();
}
- // First try to match the local part on the common dot-atom format
- $localResult = false;
-
- // Dot-atom characters are: 1*atext *("." 1*atext)
- // atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*",
- // "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~"
- $atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e';
- if (preg_match('/^[' . $atext . ']+(\x2e+[' . $atext . ']+)*$/', $this->_localPart)) {
- $localResult = true;
- } else {
- // Try quoted string format
+ $local = $this->_validateLocalPart();
- // Quoted-string characters are: DQUOTE *([FWS] qtext/quoted-pair) [FWS] DQUOTE
- // qtext: Non white space controls, and the rest of the US-ASCII characters not
- // including "\" or the quote character
- $noWsCtl = '\x01-\x08\x0b\x0c\x0e-\x1f\x7f';
- $qtext = $noWsCtl . '\x21\x23-\x5b\x5d-\x7e';
- $ws = '\x20\x09';
- if (preg_match('/^\x22([' . $ws . $qtext . '])*[$ws]?\x22$/', $this->_localPart)) {
- $localResult = true;
- } else {
- $this->_error(self::DOT_ATOM);
- $this->_error(self::QUOTED_STRING);
- $this->_error(self::INVALID_LOCAL_PART);
+ // If both parts valid, return true
+ if ($local && $length) {
+ if (($this->_options['domain'] && $hostname) || !$this->_options['domain']) {
+ return true;
}
}
- // If both parts valid, return true
- if ($localResult && $hostnameResult && $length) {
- return true;
- } else {
- return false;
- }
+ return false;
}
}
diff --git a/libs/Zend/Validate/Exception.php b/libs/Zend/Validate/Exception.php
index d6b646f1cd..fd34efe0c1 100644
--- a/libs/Zend/Validate/Exception.php
+++ b/libs/Zend/Validate/Exception.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,22 +14,20 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exception.php 16223 2009-06-21 20:04:53Z thomas $
+ * @version $Id: Exception.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
-
/**
* @see Zend_Exception
*/
-require_once 'Zend/Exception.php';
-
+// require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Exception extends Zend_Exception
diff --git a/libs/Zend/Validate/File/Count.php b/libs/Zend/Validate/File/Count.php
index f2dfac7413..a4bff7ee8c 100644
--- a/libs/Zend/Validate/File/Count.php
+++ b/libs/Zend/Validate/File/Count.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Count.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: Count.php 21326 2010-03-04 20:32:39Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validator for counting all given files
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_Count extends Zend_Validate_Abstract
@@ -37,16 +37,16 @@ class Zend_Validate_File_Count extends Zend_Validate_Abstract
/**#@+
* @const string Error constants
*/
- const TOO_MUCH = 'fileCountTooMuch';
- const TOO_LESS = 'fileCountTooLess';
+ const TOO_MANY = 'fileCountTooMany';
+ const TOO_FEW = 'fileCountTooFew';
/**#@-*/
/**
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::TOO_MUCH => "Too much files, maximum '%max%' are allowed but '%count%' are given",
- self::TOO_LESS => "Too less files, minimum '%min%' are expected but '%count%' are given"
+ self::TOO_MANY => "Too many files, maximum '%max%' are allowed but '%count%' are given",
+ self::TOO_FEW => "Too few files, minimum '%min%' are expected but '%count%' are given",
);
/**
@@ -110,13 +110,11 @@ class Zend_Validate_File_Count extends Zend_Validate_Abstract
} elseif (is_string($options) || is_numeric($options)) {
$options = array('max' => $options);
} elseif (!is_array($options)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception ('Invalid options to validator provided');
}
if (1 < func_num_args()) {
-// @todo: Preperation for 2.0... needs to be cleared with the dev-team
-// trigger_error('Multiple arguments are deprecated in favor of an array of named arguments', E_USER_NOTICE);
$options['min'] = func_get_arg(0);
$options['max'] = func_get_arg(1);
}
@@ -154,13 +152,13 @@ class Zend_Validate_File_Count extends Zend_Validate_Abstract
}
if (!is_string($min) and !is_numeric($min)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception ('Invalid options to validator provided');
}
$min = (integer) $min;
if (($this->_max !== null) && ($min > $this->_max)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("The minimum must be less than or equal to the maximum file count, but $min >"
. " {$this->_max}");
}
@@ -193,13 +191,13 @@ class Zend_Validate_File_Count extends Zend_Validate_Abstract
}
if (!is_string($max) and !is_numeric($max)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception ('Invalid options to validator provided');
}
$max = (integer) $max;
if (($this->_min !== null) && ($max < $this->_min)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("The maximum must be greater than or equal to the minimum file count, but "
. "$max < {$this->_min}");
}
@@ -243,14 +241,25 @@ class Zend_Validate_File_Count extends Zend_Validate_Abstract
*/
public function isValid($value, $file = null)
{
- $this->addFile($value);
+ if (($file !== null) && !array_key_exists('destination', $file)) {
+ $file['destination'] = dirname($value);
+ }
+
+ if (($file !== null) && array_key_exists('tmp_name', $file)) {
+ $value = $file['destination'] . DIRECTORY_SEPARATOR . $file['name'];
+ }
+
+ if (($file === null) || !empty($file['tmp_name'])) {
+ $this->addFile($value);
+ }
+
$this->_count = count($this->_files);
if (($this->_max !== null) && ($this->_count > $this->_max)) {
- return $this->_throw($file, self::TOO_MUCH);
+ return $this->_throw($file, self::TOO_MANY);
}
if (($this->_min !== null) && ($this->_count < $this->_min)) {
- return $this->_throw($file, self::TOO_LESS);
+ return $this->_throw($file, self::TOO_FEW);
}
return true;
diff --git a/libs/Zend/Validate/File/Crc32.php b/libs/Zend/Validate/File/Crc32.php
index fd46d81b6b..31b420585e 100644
--- a/libs/Zend/Validate/File/Crc32.php
+++ b/libs/Zend/Validate/File/Crc32.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Crc32.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: Crc32.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_File_Hash
*/
-require_once 'Zend/Validate/File/Hash.php';
+// require_once 'Zend/Validate/File/Hash.php';
/**
* Validator for the crc32 hash of given files
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_Crc32 extends Zend_Validate_File_Hash
@@ -45,9 +45,9 @@ class Zend_Validate_File_Crc32 extends Zend_Validate_File_Hash
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::DOES_NOT_MATCH => "The file '%value%' does not match the given crc32 hashes",
- self::NOT_DETECTED => "There was no crc32 hash detected for the given file",
- self::NOT_FOUND => "The file '%value%' could not be found"
+ self::DOES_NOT_MATCH => "File '%value%' does not match the given crc32 hashes",
+ self::NOT_DETECTED => "A crc32 hash could not be evaluated for the given file",
+ self::NOT_FOUND => "File '%value%' could not be found",
);
/**
@@ -70,7 +70,7 @@ class Zend_Validate_File_Crc32 extends Zend_Validate_File_Hash
} elseif (is_scalar($options)) {
$options = array('hash1' => $options);
} elseif (!is_array($options)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception('Invalid options to validator provided');
}
@@ -157,7 +157,7 @@ class Zend_Validate_File_Crc32 extends Zend_Validate_File_Hash
public function isValid($value, $file = null)
{
// Is file readable ?
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (!Zend_Loader::isReadable($value)) {
return $this->_throw($file, self::NOT_FOUND);
}
diff --git a/libs/Zend/Validate/File/ExcludeExtension.php b/libs/Zend/Validate/File/ExcludeExtension.php
index 74264de98c..94fb27bb6d 100644
--- a/libs/Zend/Validate/File/ExcludeExtension.php
+++ b/libs/Zend/Validate/File/ExcludeExtension.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: ExcludeExtension.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: ExcludeExtension.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/File/Extension.php';
+// require_once 'Zend/Validate/File/Extension.php';
/**
* Validator for the excluding file extensions
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_ExcludeExtension extends Zend_Validate_File_Extension
@@ -44,8 +44,8 @@ class Zend_Validate_File_ExcludeExtension extends Zend_Validate_File_Extension
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::FALSE_EXTENSION => "The file '%value%' has a false extension",
- self::NOT_FOUND => "The file '%value%' was not found"
+ self::FALSE_EXTENSION => "File '%value%' has a false extension",
+ self::NOT_FOUND => "File '%value%' could not be found",
);
/**
@@ -61,7 +61,7 @@ class Zend_Validate_File_ExcludeExtension extends Zend_Validate_File_Extension
public function isValid($value, $file = null)
{
// Is file readable ?
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (!Zend_Loader::isReadable($value)) {
return $this->_throw($file, self::NOT_FOUND);
}
diff --git a/libs/Zend/Validate/File/ExcludeMimeType.php b/libs/Zend/Validate/File/ExcludeMimeType.php
index 4984b79cfb..436caa1f02 100644
--- a/libs/Zend/Validate/File/ExcludeMimeType.php
+++ b/libs/Zend/Validate/File/ExcludeMimeType.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: ExcludeMimeType.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: ExcludeMimeType.php 21936 2010-04-18 16:23:34Z thomas $
*/
/**
* @see Zend_Validate_File_MimeType
*/
-require_once 'Zend/Validate/File/MimeType.php';
+// require_once 'Zend/Validate/File/MimeType.php';
/**
* Validator for the mime type of a file
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_ExcludeMimeType extends Zend_Validate_File_MimeType
@@ -59,7 +59,7 @@ class Zend_Validate_File_ExcludeMimeType extends Zend_Validate_File_MimeType
}
// Is file readable ?
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (!Zend_Loader::isReadable($value)) {
return $this->_throw($file, self::NOT_READABLE);
}
@@ -73,7 +73,7 @@ class Zend_Validate_File_ExcludeMimeType extends Zend_Validate_File_MimeType
$mime = new finfo($const);
}
- if ($mime !== false) {
+ if (!empty($mime)) {
$this->_type = $mime->file($value);
}
unset($mime);
diff --git a/libs/Zend/Validate/File/Exists.php b/libs/Zend/Validate/File/Exists.php
index 835b4c2c70..6ecd11f1f0 100644
--- a/libs/Zend/Validate/File/Exists.php
+++ b/libs/Zend/Validate/File/Exists.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Exists.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: Exists.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validator which checks if the file already exists in the directory
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_Exists extends Zend_Validate_Abstract
@@ -43,7 +43,7 @@ class Zend_Validate_File_Exists extends Zend_Validate_Abstract
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::DOES_NOT_EXIST => "The file '%value%' does not exist"
+ self::DOES_NOT_EXIST => "File '%value%' does not exist",
);
/**
@@ -72,7 +72,7 @@ class Zend_Validate_File_Exists extends Zend_Validate_Abstract
} else if (is_string($directory)) {
$directory = explode(',', $directory);
} else if (!is_array($directory)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception ('Invalid options to validator provided');
}
@@ -122,7 +122,7 @@ class Zend_Validate_File_Exists extends Zend_Validate_Abstract
if (is_string($directory)) {
$directory = explode(',', $directory);
} else if (!is_array($directory)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception ('Invalid options to validator provided');
}
diff --git a/libs/Zend/Validate/File/Extension.php b/libs/Zend/Validate/File/Extension.php
index 58ab0b21af..8d903e4093 100644
--- a/libs/Zend/Validate/File/Extension.php
+++ b/libs/Zend/Validate/File/Extension.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Extension.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: Extension.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validator for the file extension of a file
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_Extension extends Zend_Validate_Abstract
@@ -44,8 +44,8 @@ class Zend_Validate_File_Extension extends Zend_Validate_Abstract
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::FALSE_EXTENSION => "The file '%value%' has a false extension",
- self::NOT_FOUND => "The file '%value%' was not found"
+ self::FALSE_EXTENSION => "File '%value%' has a false extension",
+ self::NOT_FOUND => "File '%value%' could not be found",
);
/**
@@ -81,8 +81,6 @@ class Zend_Validate_File_Extension extends Zend_Validate_Abstract
}
if (1 < func_num_args()) {
-// @todo: Preperation for 2.0... needs to be cleared with the dev-team
-// trigger_error('Multiple arguments to constructor are deprecated in favor of options array', E_USER_NOTICE);
$case = func_get_arg(1);
$this->setCase($case);
}
@@ -189,7 +187,7 @@ class Zend_Validate_File_Extension extends Zend_Validate_Abstract
public function isValid($value, $file = null)
{
// Is file readable ?
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (!Zend_Loader::isReadable($value)) {
return $this->_throw($file, self::NOT_FOUND);
}
diff --git a/libs/Zend/Validate/File/FilesSize.php b/libs/Zend/Validate/File/FilesSize.php
index 167304b771..ca20ad50af 100644
--- a/libs/Zend/Validate/File/FilesSize.php
+++ b/libs/Zend/Validate/File/FilesSize.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: FilesSize.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: FilesSize.php 20455 2010-01-20 22:54:18Z thomas $
*/
/**
* @see Zend_Validate_File_Size
*/
-require_once 'Zend/Validate/File/Size.php';
+// require_once 'Zend/Validate/File/Size.php';
/**
* Validator for the size of all files which will be validated in sum
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_FilesSize extends Zend_Validate_File_Size
@@ -47,7 +47,7 @@ class Zend_Validate_File_FilesSize extends Zend_Validate_File_Size
protected $_messageTemplates = array(
self::TOO_BIG => "All files in sum should have a maximum size of '%max%' but '%size%' were detected",
self::TOO_SMALL => "All files in sum should have a minimum size of '%min%' but '%size%' were detected",
- self::NOT_READABLE => "One or more files can not be read"
+ self::NOT_READABLE => "One or more files can not be read",
);
/**
@@ -76,14 +76,11 @@ class Zend_Validate_File_FilesSize extends Zend_Validate_File_Size
} elseif (is_scalar($options)) {
$options = array('max' => $options);
} elseif (!is_array($options)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception('Invalid options to validator provided');
}
if (1 < func_num_args()) {
-// @todo: Preperation for 2.0... needs to be cleared with the dev-team
-// trigger_error('Multiple constructor options are deprecated in favor of a single options array', E_USER_NOTICE);
-
$argv = func_get_args();
array_shift($argv);
$options['max'] = array_shift($argv);
@@ -107,7 +104,7 @@ class Zend_Validate_File_FilesSize extends Zend_Validate_File_Size
*/
public function isValid($value, $file = null)
{
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (is_string($value)) {
$value = array($value);
}
@@ -131,12 +128,14 @@ class Zend_Validate_File_FilesSize extends Zend_Validate_File_Size
// limited to 2GB files
$size += @filesize($files);
- $this->_setSize($size);
+ $this->_size = $size;
if (($max !== null) && ($max < $size)) {
if ($this->useByteString()) {
- $this->setMax($this->_toByteString($max));
+ $this->_max = $this->_toByteString($max);
+ $this->_size = $this->_toByteString($size);
$this->_throw($file, self::TOO_BIG);
- $this->setMax($max);
+ $this->_max = $max;
+ $this->_size = $size;
} else {
$this->_throw($file, self::TOO_BIG);
}
@@ -146,9 +145,11 @@ class Zend_Validate_File_FilesSize extends Zend_Validate_File_Size
// Check that aggregate files are >= minimum size
if (($min !== null) && ($size < $min)) {
if ($this->useByteString()) {
- $this->setMin($this->_toByteString($min));
+ $this->_min = $this->_toByteString($min);
+ $this->_size = $this->_toByteString($size);
$this->_throw($file, self::TOO_SMALL);
- $this->setMin($min);
+ $this->_min = $min;
+ $this->_size = $size;
} else {
$this->_throw($file, self::TOO_SMALL);
}
diff --git a/libs/Zend/Validate/File/Hash.php b/libs/Zend/Validate/File/Hash.php
index d2e8c2c645..6ade30cf41 100644
--- a/libs/Zend/Validate/File/Hash.php
+++ b/libs/Zend/Validate/File/Hash.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Hash.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: Hash.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validator for the hash of given files
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_Hash extends Zend_Validate_Abstract
@@ -45,9 +45,9 @@ class Zend_Validate_File_Hash extends Zend_Validate_Abstract
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::DOES_NOT_MATCH => "The file '%value%' does not match the given hashes",
- self::NOT_DETECTED => "There was no hash detected for the given file",
- self::NOT_FOUND => "The file '%value%' could not be found"
+ self::DOES_NOT_MATCH => "File '%value%' does not match the given hashes",
+ self::NOT_DETECTED => "A hash could not be evaluated for the given file",
+ self::NOT_FOUND => "File '%value%' could not be found"
);
/**
@@ -70,13 +70,11 @@ class Zend_Validate_File_Hash extends Zend_Validate_Abstract
} elseif (is_scalar($options)) {
$options = array('hash1' => $options);
} elseif (!is_array($options)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception('Invalid options to validator provided');
}
if (1 < func_num_args()) {
-// @todo: Preperation for 2.0... needs to be cleared with the dev-team
-// trigger_error('Multiple constructor options are deprecated in favor of a single options array', E_USER_NOTICE);
$options['algorithm'] = func_get_arg(1);
}
@@ -118,7 +116,7 @@ class Zend_Validate_File_Hash extends Zend_Validate_Abstract
if (is_string($options)) {
$options = array($options);
} else if (!is_array($options)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("False parameter given");
}
@@ -131,7 +129,7 @@ class Zend_Validate_File_Hash extends Zend_Validate_Abstract
}
if (!in_array($algorithm, $known)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("Unknown algorithm '{$algorithm}'");
}
@@ -154,7 +152,7 @@ class Zend_Validate_File_Hash extends Zend_Validate_Abstract
public function isValid($value, $file = null)
{
// Is file readable ?
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (!Zend_Loader::isReadable($value)) {
return $this->_throw($file, self::NOT_FOUND);
}
diff --git a/libs/Zend/Validate/File/ImageSize.php b/libs/Zend/Validate/File/ImageSize.php
index c01ec97341..54c1457500 100644
--- a/libs/Zend/Validate/File/ImageSize.php
+++ b/libs/Zend/Validate/File/ImageSize.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: ImageSize.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: ImageSize.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validator for the image size of a image file
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract
@@ -53,7 +53,7 @@ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract
self::HEIGHT_TOO_BIG => "Maximum allowed height for image '%value%' should be '%maxheight%' but '%height%' detected",
self::HEIGHT_TOO_SMALL => "Minimum expected height for image '%value%' should be '%minheight%' but '%height%' detected",
self::NOT_DETECTED => "The size of image '%value%' could not be detected",
- self::NOT_READABLE => "The image '%value%' can not be read"
+ self::NOT_READABLE => "File '%value%' can not be read",
);
/**
@@ -127,8 +127,6 @@ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract
if ($options instanceof Zend_Config) {
$options = $options->toArray();
} elseif (1 < func_num_args()) {
-// @todo: Preperation for 2.0... needs to be cleared with the dev-team
-// trigger_error('Multiple constructor options are deprecated in favor of a single options array', E_USER_NOTICE);
if (!is_array($options)) {
$options = array('minwidth' => $options);
}
@@ -142,7 +140,7 @@ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract
}
}
} else if (!is_array($options)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception ('Invalid options to validator provided');
}
@@ -207,7 +205,7 @@ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract
{
if (isset($options['minwidth'])) {
if (($this->_maxwidth !== null) and ($options['minwidth'] > $this->_maxwidth)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("The minimum image width must be less than or equal to the "
. " maximum image width, but {$options['minwidth']} > {$this->_maxwidth}");
}
@@ -215,7 +213,7 @@ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract
if (isset($options['maxheight'])) {
if (($this->_maxheight !== null) and ($options['minheight'] > $this->_maxheight)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("The minimum image height must be less than or equal to the "
. " maximum image height, but {$options['minheight']} > {$this->_maxheight}");
}
@@ -244,7 +242,7 @@ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract
{
if (isset($options['maxwidth'])) {
if (($this->_minwidth !== null) and ($options['maxwidth'] < $this->_minwidth)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("The maximum image width must be greater than or equal to the "
. "minimum image width, but {$options['maxwidth']} < {$this->_minwidth}");
}
@@ -252,7 +250,7 @@ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract
if (isset($options['maxheight'])) {
if (($this->_minheight !== null) and ($options['maxheight'] < $this->_minheight)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("The maximum image height must be greater than or equal to the "
. "minimum image height, but {$options['maxheight']} < {$this->_minwidth}");
}
@@ -310,7 +308,7 @@ class Zend_Validate_File_ImageSize extends Zend_Validate_Abstract
public function isValid($value, $file = null)
{
// Is file readable ?
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (!Zend_Loader::isReadable($value)) {
return $this->_throw($file, self::NOT_READABLE);
}
diff --git a/libs/Zend/Validate/File/IsCompressed.php b/libs/Zend/Validate/File/IsCompressed.php
index 3254d57341..dc0d99abb5 100644
--- a/libs/Zend/Validate/File/IsCompressed.php
+++ b/libs/Zend/Validate/File/IsCompressed.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: IsCompressed.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: IsCompressed.php 21138 2010-02-22 22:37:11Z thomas $
*/
/**
* @see Zend_Validate_File_MimeType
*/
-require_once 'Zend/Validate/File/MimeType.php';
+// require_once 'Zend/Validate/File/MimeType.php';
/**
* Validator which checks if the file already exists in the directory
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_IsCompressed extends Zend_Validate_File_MimeType
@@ -45,9 +45,9 @@ class Zend_Validate_File_IsCompressed extends Zend_Validate_File_MimeType
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::FALSE_TYPE => "The file '%value%' is not compressed, '%type%' detected",
- self::NOT_DETECTED => "The mimetype of file '%value%' has not been detected",
- self::NOT_READABLE => "The file '%value%' can not be read"
+ self::FALSE_TYPE => "File '%value%' is not compressed, '%type%' detected",
+ self::NOT_DETECTED => "The mimetype of file '%value%' could not been detected",
+ self::NOT_READABLE => "File '%value%' can not be read",
);
/**
@@ -60,27 +60,90 @@ class Zend_Validate_File_IsCompressed extends Zend_Validate_File_MimeType
{
if ($mimetype instanceof Zend_Config) {
$mimetype = $mimetype->toArray();
- } else if (empty($mimetype)) {
- $mimetype = array(
- 'application/x-tar',
- 'application/x-cpio',
- 'application/x-debian-package',
- 'application/x-archive',
- 'application/x-arc',
- 'application/x-arj',
- 'application/x-lharc',
- 'application/x-lha',
- 'application/x-rar',
- 'application/zip',
- 'application/zoo',
- 'application/x-eet',
- 'application/x-java-pack200',
- 'application/x-compress',
- 'application/x-gzip',
- 'application/x-bzip2'
- );
}
- $this->setMimeType($mimetype);
+ $temp = array();
+ // http://de.wikipedia.org/wiki/Liste_von_Dateiendungen
+ $default = array(
+ 'application/arj',
+ 'application/gnutar',
+ 'application/lha',
+ 'application/lzx',
+ 'application/vnd.ms-cab-compressed',
+ 'application/x-ace-compressed',
+ 'application/x-arc',
+ 'application/x-archive',
+ 'application/x-arj',
+ 'application/x-bzip',
+ 'application/x-bzip2',
+ 'application/x-cab-compressed',
+ 'application/x-compress',
+ 'application/x-compressed',
+ 'application/x-cpio',
+ 'application/x-debian-package',
+ 'application/x-eet',
+ 'application/x-gzip',
+ 'application/x-java-pack200',
+ 'application/x-lha',
+ 'application/x-lharc',
+ 'application/x-lzh',
+ 'application/x-lzma',
+ 'application/x-lzx',
+ 'application/x-rar',
+ 'application/x-sit',
+ 'application/x-stuffit',
+ 'application/x-tar',
+ 'application/zip',
+ 'application/zoo',
+ 'multipart/x-gzip',
+ );
+
+ if (is_array($mimetype)) {
+ $temp = $mimetype;
+ if (array_key_exists('magicfile', $temp)) {
+ unset($temp['magicfile']);
+ }
+
+ if (array_key_exists('headerCheck', $temp)) {
+ unset($temp['headerCheck']);
+ }
+
+ if (empty($temp)) {
+ $mimetype += $default;
+ }
+ }
+
+ if (empty($mimetype)) {
+ $mimetype = $default;
+ }
+
+ parent::__construct($mimetype);
+ }
+
+ /**
+ * Throws an error of the given type
+ * Duplicates parent method due to OOP Problem with late static binding in PHP 5.2
+ *
+ * @param string $file
+ * @param string $errorType
+ * @return false
+ */
+ protected function _throw($file, $errorType)
+ {
+ $this->_value = $file['name'];
+ switch($errorType) {
+ case Zend_Validate_File_MimeType::FALSE_TYPE :
+ $errorType = self::FALSE_TYPE;
+ break;
+ case Zend_Validate_File_MimeType::NOT_DETECTED :
+ $errorType = self::NOT_DETECTED;
+ break;
+ case Zend_Validate_File_MimeType::NOT_READABLE :
+ $errorType = self::NOT_READABLE;
+ break;
+ }
+
+ $this->_error($errorType);
+ return false;
}
}
diff --git a/libs/Zend/Validate/File/IsImage.php b/libs/Zend/Validate/File/IsImage.php
index 3904af1f90..d602ebe763 100644
--- a/libs/Zend/Validate/File/IsImage.php
+++ b/libs/Zend/Validate/File/IsImage.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: IsImage.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: IsImage.php 21138 2010-02-22 22:37:11Z thomas $
*/
/**
* @see Zend_Validate_File_MimeType
*/
-require_once 'Zend/Validate/File/MimeType.php';
+// require_once 'Zend/Validate/File/MimeType.php';
/**
* Validator which checks if the file already exists in the directory
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_IsImage extends Zend_Validate_File_MimeType
@@ -45,9 +45,9 @@ class Zend_Validate_File_IsImage extends Zend_Validate_File_MimeType
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::FALSE_TYPE => "The file '%value%' is no image, '%type%' detected",
- self::NOT_DETECTED => "The mimetype of file '%value%' has not been detected",
- self::NOT_READABLE => "The file '%value%' can not be read"
+ self::FALSE_TYPE => "File '%value%' is no image, '%type%' detected",
+ self::NOT_DETECTED => "The mimetype of file '%value%' could not be detected",
+ self::NOT_READABLE => "File '%value%' can not be read",
);
/**
@@ -60,31 +60,114 @@ class Zend_Validate_File_IsImage extends Zend_Validate_File_MimeType
{
if ($mimetype instanceof Zend_Config) {
$mimetype = $mimetype->toArray();
- } else if (empty($mimetype)) {
- $mimetype = array(
- 'image/x-quicktime',
- 'image/jp2',
- 'image/x-xpmi',
- 'image/x-portable-bitmap',
- 'image/x-portable-greymap',
- 'image/x-portable-pixmap',
- 'image/x-niff',
- 'image/tiff',
- 'image/png',
- 'image/x-unknown',
- 'image/gif',
- 'image/x-ms-bmp',
- 'application/dicom',
- 'image/vnd.adobe.photoshop',
- 'image/vnd.djvu',
- 'image/x-cpi',
- 'image/jpeg',
- 'image/x-ico',
- 'image/x-coreldraw',
- 'image/svg+xml'
- );
}
- $this->setMimeType($mimetype);
+ $temp = array();
+ // http://de.wikipedia.org/wiki/Liste_von_Dateiendungen
+ // http://www.iana.org/assignments/media-types/image/
+ $default = array(
+ 'application/cdf',
+ 'application/dicom',
+ 'application/fractals',
+ 'application/postscript',
+ 'application/vnd.hp-hpgl',
+ 'application/vnd.oasis.opendocument.graphics',
+ 'application/x-cdf',
+ 'application/x-cmu-raster',
+ 'application/x-ima',
+ 'application/x-inventor',
+ 'application/x-koan',
+ 'application/x-portable-anymap',
+ 'application/x-world-x-3dmf',
+ 'image/bmp',
+ 'image/c',
+ 'image/cgm',
+ 'image/fif',
+ 'image/gif',
+ 'image/jpeg',
+ 'image/jpm',
+ 'image/jpx',
+ 'image/jp2',
+ 'image/naplps',
+ 'image/pjpeg',
+ 'image/png',
+ 'image/svg',
+ 'image/svg+xml',
+ 'image/tiff',
+ 'image/vnd.adobe.photoshop',
+ 'image/vnd.djvu',
+ 'image/vnd.fpx',
+ 'image/vnd.net-fpx',
+ 'image/x-cmu-raster',
+ 'image/x-cmx',
+ 'image/x-coreldraw',
+ 'image/x-cpi',
+ 'image/x-emf',
+ 'image/x-ico',
+ 'image/x-icon',
+ 'image/x-jg',
+ 'image/x-ms-bmp',
+ 'image/x-niff',
+ 'image/x-pict',
+ 'image/x-pcx',
+ 'image/x-portable-anymap',
+ 'image/x-portable-bitmap',
+ 'image/x-portable-greymap',
+ 'image/x-portable-pixmap',
+ 'image/x-quicktime',
+ 'image/x-rgb',
+ 'image/x-tiff',
+ 'image/x-unknown',
+ 'image/x-windows-bmp',
+ 'image/x-xpmi',
+ );
+
+ if (is_array($mimetype)) {
+ $temp = $mimetype;
+ if (array_key_exists('magicfile', $temp)) {
+ unset($temp['magicfile']);
+ }
+
+ if (array_key_exists('headerCheck', $temp)) {
+ unset($temp['headerCheck']);
+ }
+
+ if (empty($temp)) {
+ $mimetype += $default;
+ }
+ }
+
+ if (empty($mimetype)) {
+ $mimetype = $default;
+ }
+
+ parent::__construct($mimetype);
+ }
+
+ /**
+ * Throws an error of the given type
+ * Duplicates parent method due to OOP Problem with late static binding in PHP 5.2
+ *
+ * @param string $file
+ * @param string $errorType
+ * @return false
+ */
+ protected function _throw($file, $errorType)
+ {
+ $this->_value = $file['name'];
+ switch($errorType) {
+ case Zend_Validate_File_MimeType::FALSE_TYPE :
+ $errorType = self::FALSE_TYPE;
+ break;
+ case Zend_Validate_File_MimeType::NOT_DETECTED :
+ $errorType = self::NOT_DETECTED;
+ break;
+ case Zend_Validate_File_MimeType::NOT_READABLE :
+ $errorType = self::NOT_READABLE;
+ break;
+ }
+
+ $this->_error($errorType);
+ return false;
}
}
diff --git a/libs/Zend/Validate/File/Md5.php b/libs/Zend/Validate/File/Md5.php
index cfbd83fb53..e76df71917 100644
--- a/libs/Zend/Validate/File/Md5.php
+++ b/libs/Zend/Validate/File/Md5.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Md5.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Md5.php 20442 2010-01-20 15:15:40Z matthew $
*/
/**
* @see Zend_Validate_File_Hash
*/
-require_once 'Zend/Validate/File/Hash.php';
+// require_once 'Zend/Validate/File/Hash.php';
/**
* Validator for the md5 hash of given files
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_Md5 extends Zend_Validate_File_Hash
@@ -45,9 +45,9 @@ class Zend_Validate_File_Md5 extends Zend_Validate_File_Hash
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::DOES_NOT_MATCH => "The file '%value%' does not match the given md5 hashes",
- self::NOT_DETECTED => "There was no md5 hash detected for the given file",
- self::NOT_FOUND => "The file '%value%' could not be found"
+ self::DOES_NOT_MATCH => "File '%value%' does not match the given md5 hashes",
+ self::NOT_DETECTED => "A md5 hash could not be evaluated for the given file",
+ self::NOT_FOUND => "File '%value%' could not be found",
);
/**
@@ -72,7 +72,7 @@ class Zend_Validate_File_Md5 extends Zend_Validate_File_Hash
} elseif (is_scalar($options)) {
$options = array('hash1' => $options);
} elseif (!is_array($options)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception('Invalid options to validator provided');
}
@@ -123,7 +123,7 @@ class Zend_Validate_File_Md5 extends Zend_Validate_File_Hash
* Adds the md5 hash for one or multiple files
*
* @param string|array $options
- * @param string $algorithm (Depreciated) Algorithm to use, fixed to md5
+ * @param string $algorithm (Deprecated) Algorithm to use, fixed to md5
* @return Zend_Validate_File_Hash Provides a fluent interface
*/
public function addHash($options)
@@ -161,7 +161,7 @@ class Zend_Validate_File_Md5 extends Zend_Validate_File_Hash
public function isValid($value, $file = null)
{
// Is file readable ?
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (!Zend_Loader::isReadable($value)) {
return $this->_throw($file, self::NOT_FOUND);
}
diff --git a/libs/Zend/Validate/File/MimeType.php b/libs/Zend/Validate/File/MimeType.php
index 2bf372c4fc..a31a7d35a3 100644
--- a/libs/Zend/Validate/File/MimeType.php
+++ b/libs/Zend/Validate/File/MimeType.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: MimeType.php 18513 2009-10-12 16:17:35Z matthew $
+ * @version $Id: MimeType.php 21936 2010-04-18 16:23:34Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validator for the mime type of a file
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_MimeType extends Zend_Validate_Abstract
@@ -46,9 +46,9 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::FALSE_TYPE => "The file '%value%' has a false mimetype of '%type%'",
- self::NOT_DETECTED => "The mimetype of file '%value%' could not been detected",
- self::NOT_READABLE => "The file '%value%' can not be read"
+ self::FALSE_TYPE => "File '%value%' has a false mimetype of '%type%'",
+ self::NOT_DETECTED => "The mimetype of file '%value%' could not be detected",
+ self::NOT_READABLE => "File '%value%' can not be read",
);
/**
@@ -80,6 +80,13 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract
protected $_magicfile;
/**
+ * Finfo object to use
+ *
+ * @var resource
+ */
+ protected $_finfo;
+
+ /**
* If no $_ENV['MAGIC'] is set, try and autodiscover it based on common locations
* @var array
*/
@@ -117,16 +124,18 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract
} elseif (is_string($mimetype)) {
$mimetype = explode(',', $mimetype);
} elseif (!is_array($mimetype)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("Invalid options to validator provided");
}
if (isset($mimetype['magicfile'])) {
$this->setMagicFile($mimetype['magicfile']);
+ unset($mimetype['magicfile']);
}
if (isset($mimetype['headerCheck'])) {
- $this->enableHeaderCheck(true);
+ $this->enableHeaderCheck($mimetype['headerCheck']);
+ unset($mimetype['headerCheck']);
}
$this->setMimeType($mimetype);
@@ -139,33 +148,62 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract
*/
public function getMagicFile()
{
- if (null === $this->_magicfile && empty($_ENV['MAGIC'])) {
- foreach ($this->_magicFiles as $file) {
- if (file_exists($file)) {
- $this->setMagicFile($file);
- break;
+ if (null === $this->_magicfile) {
+ if (!empty($_ENV['MAGIC'])) {
+ $this->setMagicFile($_ENV['MAGIC']);
+ } elseif (!(@ini_get("safe_mode") == 'On' || @ini_get("safe_mode") === 1)) {
+ // require_once 'Zend/Validate/Exception.php';
+ foreach ($this->_magicFiles as $file) {
+ // supressing errors which are thrown due to openbase_dir restrictions
+ try {
+ $this->setMagicFile($file);
+ if ($this->_magicfile !== null) {
+ break;
+ }
+ } catch (Zend_Validate_Exception $e) {
+ // Intentionally, catch and fall through
+ }
}
}
+
+ if ($this->_magicfile === null) {
+ $this->_magicfile = false;
+ }
}
+
return $this->_magicfile;
}
/**
* Sets the magicfile to use
* if null, the MAGIC constant from php is used
+ * if the MAGIC file is errorous, no file will be set
*
* @param string $file
+ * @throws Zend_Validate_Exception When finfo can not read the magicfile
* @return Zend_Validate_File_MimeType Provides fluid interface
*/
public function setMagicFile($file)
{
if (empty($file)) {
$this->_magicfile = null;
+ } else if (!(class_exists('finfo', false))) {
+ $this->_magicfile = null;
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Magicfile can not be set. There is no finfo extension installed');
} else if (!is_readable($file)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception('The given magicfile can not be read');
} else {
- $this->_magicfile = (string) $file;
+ $const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME;
+ $this->_finfo = @finfo_open($const, $file);
+ if (empty($this->_finfo)) {
+ $this->_finfo = null;
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('The given magicfile is not accepted by finfo');
+ } else {
+ $this->_magicfile = $file;
+ }
}
return $this;
@@ -237,7 +275,7 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract
if (is_string($mimetype)) {
$mimetype = explode(',', $mimetype);
} elseif (!is_array($mimetype)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("Invalid options to validator provided");
}
@@ -286,7 +324,7 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract
}
// Is file readable ?
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (!Zend_Loader::isReadable($value)) {
return $this->_throw($file, self::NOT_READABLE);
}
@@ -294,24 +332,27 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract
$mimefile = $this->getMagicFile();
if (class_exists('finfo', false)) {
$const = defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME;
- if (!empty($mimefile)) {
- $mime = new finfo($const, $mimefile);
- } else {
- $mime = new finfo($const);
+ if (!empty($mimefile) && empty($this->_finfo)) {
+ $this->_finfo = @finfo_open($const, $mimefile);
+ }
+
+ if (empty($this->_finfo)) {
+ $this->_finfo = @finfo_open($const);
}
- if ($mime !== false) {
- $this->_type = $mime->file($value);
+ $this->_type = null;
+ if (!empty($this->_finfo)) {
+ $this->_type = finfo_file($this->_finfo, $value);
}
- unset($mime);
}
- if (empty($this->_type)) {
- if (function_exists('mime_content_type') && ini_get('mime_magic.magicfile')) {
+ if (empty($this->_type) &&
+ (function_exists('mime_content_type') && ini_get('mime_magic.magicfile'))) {
$this->_type = mime_content_type($value);
- } elseif ($this->_headerCheck) {
- $this->_type = $file['type'];
- }
+ }
+
+ if (empty($this->_type) && $this->_headerCheck) {
+ $this->_type = $file['type'];
}
if (empty($this->_type)) {
@@ -325,6 +366,7 @@ class Zend_Validate_File_MimeType extends Zend_Validate_Abstract
$types = explode('/', $this->_type);
$types = array_merge($types, explode('-', $this->_type));
+ $types = array_merge($types, explode(';', $this->_type));
foreach($mimetype as $mime) {
if (in_array($mime, $types)) {
return true;
diff --git a/libs/Zend/Validate/File/NotExists.php b/libs/Zend/Validate/File/NotExists.php
index 0cc3c87ac9..a5afe94686 100644
--- a/libs/Zend/Validate/File/NotExists.php
+++ b/libs/Zend/Validate/File/NotExists.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: NotExists.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: NotExists.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_File_Exists
*/
-require_once 'Zend/Validate/File/Exists.php';
+// require_once 'Zend/Validate/File/Exists.php';
/**
* Validator which checks if the destination file does not exist
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_NotExists extends Zend_Validate_File_Exists
@@ -43,7 +43,7 @@ class Zend_Validate_File_NotExists extends Zend_Validate_File_Exists
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::DOES_EXIST => "The file '%value%' does exist"
+ self::DOES_EXIST => "File '%value%' exists",
);
/**
diff --git a/libs/Zend/Validate/File/Sha1.php b/libs/Zend/Validate/File/Sha1.php
index 9dd4418d71..1b5f8ee622 100644
--- a/libs/Zend/Validate/File/Sha1.php
+++ b/libs/Zend/Validate/File/Sha1.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Sha1.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Sha1.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_File_Hash
*/
-require_once 'Zend/Validate/File/Hash.php';
+// require_once 'Zend/Validate/File/Hash.php';
/**
* Validator for the sha1 hash of given files
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_Sha1 extends Zend_Validate_File_Hash
@@ -45,9 +45,9 @@ class Zend_Validate_File_Sha1 extends Zend_Validate_File_Hash
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::DOES_NOT_MATCH => "The file '%value%' does not match the given sha1 hashes",
- self::NOT_DETECTED => "There was no sha1 hash detected for the given file",
- self::NOT_FOUND => "The file '%value%' could not be found"
+ self::DOES_NOT_MATCH => "File '%value%' does not match the given sha1 hashes",
+ self::NOT_DETECTED => "A sha1 hash could not be evaluated for the given file",
+ self::NOT_FOUND => "File '%value%' could not be found",
);
/**
@@ -72,7 +72,7 @@ class Zend_Validate_File_Sha1 extends Zend_Validate_File_Hash
} elseif (is_scalar($options)) {
$options = array('hash1' => $options);
} elseif (!is_array($options)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception('Invalid options to validator provided');
}
@@ -159,7 +159,7 @@ class Zend_Validate_File_Sha1 extends Zend_Validate_File_Hash
public function isValid($value, $file = null)
{
// Is file readable ?
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (!Zend_Loader::isReadable($value)) {
return $this->_throw($file, self::NOT_FOUND);
}
diff --git a/libs/Zend/Validate/File/Size.php b/libs/Zend/Validate/File/Size.php
index 4c41178966..a3431cfae1 100644
--- a/libs/Zend/Validate/File/Size.php
+++ b/libs/Zend/Validate/File/Size.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Size.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: Size.php 20455 2010-01-20 22:54:18Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validator for the maximum size of a file up to a max of 2GB
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_Size extends Zend_Validate_Abstract
@@ -48,7 +48,7 @@ class Zend_Validate_File_Size extends Zend_Validate_Abstract
protected $_messageTemplates = array(
self::TOO_BIG => "Maximum allowed size for file '%value%' is '%max%' but '%size%' detected",
self::TOO_SMALL => "Minimum expected size for file '%value%' is '%min%' but '%size%' detected",
- self::NOT_FOUND => "The file '%value%' could not be found"
+ self::NOT_FOUND => "File '%value%' could not be found",
);
/**
@@ -107,13 +107,11 @@ class Zend_Validate_File_Size extends Zend_Validate_Abstract
} elseif (is_string($options) || is_numeric($options)) {
$options = array('max' => $options);
} elseif (!is_array($options)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception ('Invalid options to validator provided');
}
if (1 < func_num_args()) {
-// @todo: Preperation for 2.0... needs to be cleared with the dev-team
-// trigger_error('Multiple constructor options are deprecated in favor of a single options array', E_USER_NOTICE);
$argv = func_get_args();
array_shift($argv);
$options['max'] = array_shift($argv);
@@ -183,14 +181,14 @@ class Zend_Validate_File_Size extends Zend_Validate_Abstract
public function setMin($min)
{
if (!is_string($min) and !is_numeric($min)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception ('Invalid options to validator provided');
}
$min = (integer) $this->_fromByteString($min);
$max = $this->getMax(true);
if (($max !== null) && ($min > $max)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("The minimum must be less than or equal to the maximum filesize, but $min >"
. " $max");
}
@@ -225,14 +223,14 @@ class Zend_Validate_File_Size extends Zend_Validate_Abstract
public function setMax($max)
{
if (!is_string($max) && !is_numeric($max)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception ('Invalid options to validator provided');
}
$max = (integer) $this->_fromByteString($max);
$min = $this->getMin(true);
if (($min !== null) && ($max < $min)) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("The maximum must be greater than or equal to the minimum filesize, but "
. "$max < $min");
}
@@ -276,13 +274,14 @@ class Zend_Validate_File_Size extends Zend_Validate_Abstract
public function isValid($value, $file = null)
{
// Is file readable ?
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (!Zend_Loader::isReadable($value)) {
return $this->_throw($file, self::NOT_FOUND);
}
// limited to 4GB files
- $size = sprintf("%u", @filesize($value));
+ $size = sprintf("%u", @filesize($value));
+ $this->_size = $size;
// Check to see if it's smaller than min size
$min = $this->getMin(true);
diff --git a/libs/Zend/Validate/File/Upload.php b/libs/Zend/Validate/File/Upload.php
index fd1bdfe754..9a12f301d1 100644
--- a/libs/Zend/Validate/File/Upload.php
+++ b/libs/Zend/Validate/File/Upload.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Upload.php 18148 2009-09-16 19:27:43Z thomas $
+ * @version $Id: Upload.php 20431 2010-01-19 21:36:05Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validator for the maximum size of a file up to a max of 2GB
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_Upload extends Zend_Validate_Abstract
@@ -53,16 +53,16 @@ class Zend_Validate_File_Upload extends Zend_Validate_Abstract
* @var array Error message templates
*/
protected $_messageTemplates = array(
- self::INI_SIZE => "The file '%value%' exceeds the defined ini size",
- self::FORM_SIZE => "The file '%value%' exceeds the defined form size",
- self::PARTIAL => "The file '%value%' was only partially uploaded",
- self::NO_FILE => "The file '%value%' was not uploaded",
- self::NO_TMP_DIR => "No temporary directory was found for the file '%value%'",
- self::CANT_WRITE => "The file '%value%' can't be written",
- self::EXTENSION => "The extension returned an error while uploading the file '%value%'",
- self::ATTACK => "The file '%value%' was illegal uploaded, possible attack",
- self::FILE_NOT_FOUND => "The file '%value%' was not found",
- self::UNKNOWN => "Unknown error while uploading the file '%value%'"
+ self::INI_SIZE => "File '%value%' exceeds the defined ini size",
+ self::FORM_SIZE => "File '%value%' exceeds the defined form size",
+ self::PARTIAL => "File '%value%' was only partially uploaded",
+ self::NO_FILE => "File '%value%' was not uploaded",
+ self::NO_TMP_DIR => "No temporary directory was found for file '%value%'",
+ self::CANT_WRITE => "File '%value%' can't be written",
+ self::EXTENSION => "A PHP extension returned an error while uploading the file '%value%'",
+ self::ATTACK => "File '%value%' was illegally uploaded. This could be a possible attack",
+ self::FILE_NOT_FOUND => "File '%value%' was not found",
+ self::UNKNOWN => "Unknown error while uploading file '%value%'"
);
/**
@@ -112,7 +112,7 @@ class Zend_Validate_File_Upload extends Zend_Validate_Abstract
}
if (count($return) === 0) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("The file '$file' was not found");
}
diff --git a/libs/Zend/Validate/File/WordCount.php b/libs/Zend/Validate/File/WordCount.php
index b5249532d3..e69bf1db79 100644
--- a/libs/Zend/Validate/File/WordCount.php
+++ b/libs/Zend/Validate/File/WordCount.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: WordCount.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: WordCount.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_File_Count
*/
-require_once 'Zend/Validate/File/Count.php';
+// require_once 'Zend/Validate/File/Count.php';
/**
* Validator for counting all words in a file
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_File_WordCount extends Zend_Validate_File_Count
@@ -48,7 +48,7 @@ class Zend_Validate_File_WordCount extends Zend_Validate_File_Count
protected $_messageTemplates = array(
self::TOO_MUCH => "Too much words, maximum '%max%' are allowed but '%count%' were counted",
self::TOO_LESS => "Too less words, minimum '%min%' are expected but '%count%' were counted",
- self::NOT_FOUND => "The file '%value%' could not be found"
+ self::NOT_FOUND => "File '%value%' could not be found",
);
/**
@@ -64,7 +64,7 @@ class Zend_Validate_File_WordCount extends Zend_Validate_File_Count
public function isValid($value, $file = null)
{
// Is file readable ?
- require_once 'Zend/Loader.php';
+ // require_once 'Zend/Loader.php';
if (!Zend_Loader::isReadable($value)) {
return $this->_throw($file, self::NOT_FOUND);
}
diff --git a/libs/Zend/Validate/Float.php b/libs/Zend/Validate/Float.php
index bfa5e62c14..37755a8ab7 100644
--- a/libs/Zend/Validate/Float.php
+++ b/libs/Zend/Validate/Float.php
@@ -14,25 +14,25 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Float.php 17470 2009-08-08 22:27:09Z thomas $
+ * @version $Id: Float.php 21664 2010-03-27 21:39:38Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @see Zend_Locale_Format
*/
-require_once 'Zend/Locale/Format.php';
+// require_once 'Zend/Locale/Format.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Float extends Zend_Validate_Abstract
@@ -45,7 +45,7 @@ class Zend_Validate_Float extends Zend_Validate_Abstract
*/
protected $_messageTemplates = array(
self::INVALID => "Invalid type given, value should be float, string, or integer",
- self::NOT_FLOAT => "'%value%' does not appear to be a float"
+ self::NOT_FLOAT => "'%value%' does not appear to be a float",
);
protected $_locale;
@@ -53,13 +53,30 @@ class Zend_Validate_Float extends Zend_Validate_Abstract
/**
* Constructor for the float validator
*
- * @param string|Zend_Locale $locale
+ * @param string|Zend_Config|Zend_Locale $locale
*/
public function __construct($locale = null)
{
- if ($locale !== null) {
- $this->setLocale($locale);
+ if ($locale instanceof Zend_Config) {
+ $locale = $locale->toArray();
+ }
+
+ if (is_array($locale)) {
+ if (array_key_exists('locale', $locale)) {
+ $locale = $locale['locale'];
+ } else {
+ $locale = null;
+ }
}
+
+ if (empty($locale)) {
+ // require_once 'Zend/Registry.php';
+ if (Zend_Registry::isRegistered('Zend_Locale')) {
+ $locale = Zend_Registry::get('Zend_Locale');
+ }
+ }
+
+ $this->setLocale($locale);
}
/**
@@ -77,7 +94,7 @@ class Zend_Validate_Float extends Zend_Validate_Abstract
*/
public function setLocale($locale = null)
{
- require_once 'Zend/Locale.php';
+ // require_once 'Zend/Locale.php';
$this->_locale = Zend_Locale::findLocale($locale);
return $this;
}
@@ -97,28 +114,19 @@ class Zend_Validate_Float extends Zend_Validate_Abstract
return false;
}
- $this->_setValue($value);
- if ($this->_locale === null) {
- $locale = localeconv();
- $valueFiltered = str_replace($locale['thousands_sep'], '', (string) $value);
- $valueFiltered = str_replace($locale['decimal_point'], '.', $valueFiltered);
-
- if (strval(floatval($valueFiltered)) != $valueFiltered) {
- $this->_error(self::NOT_FLOAT);
- return false;
- }
+ if (is_float($value)) {
+ return true;
+ }
- } else {
- try {
- if (!Zend_Locale_Format::isFloat($value, array('locale' => 'en')) &&
- !Zend_Locale_Format::isFloat($value, array('locale' => $this->_locale))) {
- $this->_error(self::NOT_FLOAT);
- return false;
- }
- } catch (Zend_Locale_Exception $e) {
+ $this->_setValue($value);
+ try {
+ if (!Zend_Locale_Format::isFloat($value, array('locale' => $this->_locale))) {
$this->_error(self::NOT_FLOAT);
return false;
}
+ } catch (Zend_Locale_Exception $e) {
+ $this->_error(self::NOT_FLOAT);
+ return false;
}
return true;
diff --git a/libs/Zend/Validate/GreaterThan.php b/libs/Zend/Validate/GreaterThan.php
index 3c7b7931c9..a9b7a21879 100644
--- a/libs/Zend/Validate/GreaterThan.php
+++ b/libs/Zend/Validate/GreaterThan.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,22 +14,20 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: GreaterThan.php 17470 2009-08-08 22:27:09Z thomas $
+ * @version $Id: GreaterThan.php 20358 2010-01-17 19:03:49Z thomas $
*/
-
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
-
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_GreaterThan extends Zend_Validate_Abstract
@@ -42,7 +39,7 @@ class Zend_Validate_GreaterThan extends Zend_Validate_Abstract
* @var array
*/
protected $_messageTemplates = array(
- self::NOT_GREATER => "'%value%' is not greater than '%min%'"
+ self::NOT_GREATER => "'%value%' is not greater than '%min%'",
);
/**
@@ -62,11 +59,24 @@ class Zend_Validate_GreaterThan extends Zend_Validate_Abstract
/**
* Sets validator options
*
- * @param mixed $min
+ * @param mixed|Zend_Config $min
* @return void
*/
public function __construct($min)
{
+ if ($min instanceof Zend_Config) {
+ $min = $min->toArray();
+ }
+
+ if (is_array($min)) {
+ if (array_key_exists('min', $min)) {
+ $min = $min['min'];
+ } else {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception("Missing option 'min'");
+ }
+ }
+
$this->setMin($min);
}
diff --git a/libs/Zend/Validate/Hex.php b/libs/Zend/Validate/Hex.php
index 85d3e3a7a2..b2080d3aaa 100644
--- a/libs/Zend/Validate/Hex.php
+++ b/libs/Zend/Validate/Hex.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,22 +14,20 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Hex.php 17470 2009-08-08 22:27:09Z thomas $
+ * @version $Id: Hex.php 20358 2010-01-17 19:03:49Z thomas $
*/
-
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
-
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Hex extends Zend_Validate_Abstract
@@ -45,7 +42,7 @@ class Zend_Validate_Hex extends Zend_Validate_Abstract
*/
protected $_messageTemplates = array(
self::INVALID => "Invalid type given, value should be a string",
- self::NOT_HEX => "'%value%' has not only hexadecimal digit characters"
+ self::NOT_HEX => "'%value%' has not only hexadecimal digit characters",
);
/**
diff --git a/libs/Zend/Validate/Hostname.php b/libs/Zend/Validate/Hostname.php
index dd254d5596..1732e69c77 100644
--- a/libs/Zend/Validate/Hostname.php
+++ b/libs/Zend/Validate/Hostname.php
@@ -14,20 +14,20 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Hostname.php 17141 2009-07-26 12:49:17Z thomas $
+ * @version $Id: Hostname.php 21063 2010-02-15 23:00:17Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @see Zend_Validate_Ip
*/
-require_once 'Zend/Validate/Ip.php';
+// require_once 'Zend/Validate/Ip.php';
/**
* Please note there are two standalone test scripts for testing IDN characters due to problems
@@ -41,7 +41,7 @@ require_once 'Zend/Validate/Ip.php';
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Hostname extends Zend_Validate_Abstract
@@ -64,13 +64,13 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
self::INVALID => "Invalid type given, value should be a string",
self::IP_ADDRESS_NOT_ALLOWED => "'%value%' appears to be an IP address, but IP addresses are not allowed",
self::UNKNOWN_TLD => "'%value%' appears to be a DNS hostname but cannot match TLD against known list",
- self::INVALID_DASH => "'%value%' appears to be a DNS hostname but contains a dash (-) in an invalid position",
+ self::INVALID_DASH => "'%value%' appears to be a DNS hostname but contains a dash in an invalid position",
self::INVALID_HOSTNAME_SCHEMA => "'%value%' appears to be a DNS hostname but cannot match against hostname schema for TLD '%tld%'",
self::UNDECIPHERABLE_TLD => "'%value%' appears to be a DNS hostname but cannot extract TLD part",
self::INVALID_HOSTNAME => "'%value%' does not match the expected structure for a DNS hostname",
self::INVALID_LOCAL_NAME => "'%value%' does not appear to be a valid local network name",
self::LOCAL_NAME_NOT_ALLOWED => "'%value%' appears to be a local network name but local network names are not allowed",
- self::CANNOT_DECODE_PUNYCODE => "'%value%' appears to be a DNS hostname but the given punycode notation cannot be decoded"
+ self::CANNOT_DECODE_PUNYCODE => "'%value%' appears to be a DNS hostname but the given punycode notation cannot be decoded",
);
/**
@@ -101,27 +101,6 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
const ALLOW_ALL = 7;
/**
- * Whether IDN domains are validated
- *
- * @var boolean
- */
- private $_validateIdn = true;
-
- /**
- * Whether TLDs are validated against a known list
- *
- * @var boolean
- */
- private $_validateTld = true;
-
- /**
- * Bit field of ALLOW constants; determines which types of hostnames are allowed
- *
- * @var integer
- */
- protected $_allow;
-
- /**
* Array of valid top-level-domains
*
* @see ftp://data.iana.org/TLD/tlds-alpha-by-domain.txt List of all TLDs by domain
@@ -221,6 +200,12 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
'DE' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿăąāćĉčċďđĕěėęēğĝġģĥħĭĩįīıĵķĺľļłńňņŋŏőōœĸŕřŗśŝšşťţŧŭůűũųūŵŷźžż]{1,63}$/iu'),
'DK' => array(1 => '/^[\x{002d}0-9a-zäéöü]{1,63}$/iu'),
'ES' => array(1 => '/^[\x{002d}0-9a-zàáçèéíïñòóúü·]{1,63}$/iu'),
+ 'EU' => array(1 => '/^[\x{002d}0-9a-zà-öø-ÿ]{1,63}$/iu',
+ 2 => '/^[\x{002d}0-9a-zāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĺļľŀłńņňʼnŋōŏőœŕŗřśŝšťŧũūŭůűųŵŷźżž]{1,63}$/iu',
+ 3 => '/^[\x{002d}0-9a-zșț]{1,63}$/iu',
+ 4 => '/^[\x{002d}0-9a-zΐάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ]{1,63}$/iu',
+ 5 => '/^[\x{002d}0-9a-zабвгдежзийклмнопрстуфхцчшщъыьэюя]{1,63}$/iu',
+ 6 => '/^[\x{002d}0-9a-zἀ-ἇἐ-ἕἠ-ἧἰ-ἷὀ-ὅὐ-ὗὠ-ὧὰ-ώᾀ-ᾇᾐ-ᾗᾠ-ᾧᾰ-ᾴᾶᾷῂῃῄῆῇῐ-ΐῖῗῠ-ῧῲῳῴῶῷ]{1,63}$/iu'),
'FI' => array(1 => '/^[\x{002d}0-9a-zäåö]{1,63}$/iu'),
'GR' => array(1 => '/^[\x{002d}0-9a-zΆΈΉΊΌΎ-ΡΣ-ώἀ-ἕἘ-Ἕἠ-ὅὈ-Ὅὐ-ὗὙὛὝὟ-ώᾀ-ᾴᾶ-ᾼῂῃῄῆ-ῌῐ-ΐῖ-Ίῠ-Ῥῲῳῴῶ-ῼ]{1,63}$/iu'),
'HK' => 'Zend/Validate/Hostname/Cn.php',
@@ -320,6 +305,13 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
'网络' => array(1 => 20),
);
+ protected $_options = array(
+ 'allow' => self::ALLOW_DNS,
+ 'idn' => true,
+ 'tld' => true,
+ 'ip' => null
+ );
+
/**
* Sets validator options
*
@@ -330,16 +322,77 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
* @return void
* @see http://www.iana.org/cctld/specifications-policies-cctlds-01apr02.htm Technical Specifications for ccTLDs
*/
- public function __construct($allow = self::ALLOW_DNS, $validateIdn = true, $validateTld = true, Zend_Validate_Ip $ipValidator = null)
+ public function __construct($options = array())
{
- // Set allow options
- $this->setAllow($allow);
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp['allow'] = array_shift($options);
+ if (!empty($options)) {
+ $temp['idn'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['tld'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['ip'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ $options += $this->_options;
+ $this->setOptions($options);
+ }
+
+ /**
+ * Returns all set options
+ *
+ * @return array
+ */
+ public function getOptions()
+ {
+ return $this->_options;
+ }
+
+ /**
+ * Sets the options for this validator
+ *
+ * @param array $options
+ * @return Zend_Validate_Hostname
+ */
+ public function setOptions($options)
+ {
+ if (array_key_exists('allow', $options)) {
+ $this->setAllow($options['allow']);
+ }
- // Set validation options
- $this->_validateIdn = $validateIdn;
- $this->_validateTld = $validateTld;
+ if (array_key_exists('idn', $options)) {
+ $this->setValidateIdn($options['idn']);
+ }
+
+ if (array_key_exists('tld', $options)) {
+ $this->setValidateTld($options['tld']);
+ }
+
+ if (array_key_exists('ip', $options)) {
+ $this->setIpValidator($options['ip']);
+ }
- $this->setIpValidator($ipValidator);
+ return $this;
+ }
+
+ /**
+ * Returns the set ip validator
+ *
+ * @return Zend_Validate_Ip
+ */
+ public function getIpValidator()
+ {
+ return $this->_options['ip'];
}
/**
@@ -351,7 +404,9 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
if ($ipValidator === null) {
$ipValidator = new Zend_Validate_Ip();
}
- $this->_ipValidator = $ipValidator;
+
+ $this->_options['ip'] = $ipValidator;
+ return $this;
}
/**
@@ -361,7 +416,7 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
*/
public function getAllow()
{
- return $this->_allow;
+ return $this->_options['allow'];
}
/**
@@ -372,11 +427,21 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
*/
public function setAllow($allow)
{
- $this->_allow = $allow;
+ $this->_options['allow'] = $allow;
return $this;
}
/**
+ * Returns the set idn option
+ *
+ * @return boolean
+ */
+ public function getValidateIdn()
+ {
+ return $this->_options['idn'];
+ }
+
+ /**
* Set whether IDN domains are validated
*
* This only applies when DNS hostnames are validated
@@ -385,7 +450,18 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
*/
public function setValidateIdn ($allowed)
{
- $this->_validateIdn = (bool) $allowed;
+ $this->_options['idn'] = (bool) $allowed;
+ return $this;
+ }
+
+ /**
+ * Returns the set tld option
+ *
+ * @return boolean
+ */
+ public function getValidateTld()
+ {
+ return $this->_options['tld'];
}
/**
@@ -397,7 +473,8 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
*/
public function setValidateTld ($allowed)
{
- $this->_validateTld = (bool) $allowed;
+ $this->_options['tld'] = (bool) $allowed;
+ return $this;
}
/**
@@ -417,11 +494,10 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
}
$this->_setValue($value);
-
// Check input against IP address schema
if (preg_match('/^[0-9.a-e:.]*$/i', $value) &&
- $this->_ipValidator->setTranslator($this->getTranslator())->isValid($value)) {
- if (!($this->_allow & self::ALLOW_IP)) {
+ $this->_options['ip']->setTranslator($this->getTranslator())->isValid($value)) {
+ if (!($this->_options['allow'] & self::ALLOW_IP)) {
$this->_error(self::IP_ADDRESS_NOT_ALLOWED);
return false;
} else {
@@ -452,7 +528,7 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
// Match TLD against known list
$this->_tld = strtolower($matches[1]);
- if ($this->_validateTld) {
+ if ($this->_options['tld']) {
if (!in_array($this->_tld, $this->_validTlds)) {
$this->_error(self::UNKNOWN_TLD);
$status = false;
@@ -466,18 +542,17 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
* @see Zend_Validate_Hostname_Interface
*/
$regexChars = array(0 => '/^[a-z0-9\x2d]{1,63}$/i');
- if ($this->_validateIdn && isset($this->_validIdns[strtoupper($this->_tld)])) {
+ if ($this->_options['idn'] && isset($this->_validIdns[strtoupper($this->_tld)])) {
if (is_string($this->_validIdns[strtoupper($this->_tld)])) {
- $regexChars += include($this->_validIdns[strtoupper($this->_tld)]);
+ $regexChars += include(dirname(__FILE__) . '/../../' . $this->_validIdns[strtoupper($this->_tld)]);
} else {
$regexChars += $this->_validIdns[strtoupper($this->_tld)];
}
}
// Check each hostname part
- $valid = true;
+ $check = 0;
foreach ($domainParts as $domainPart) {
-
// Decode Punycode domainnames to IDN
if (strpos($domainPart, 'xn--') === 0) {
$domainPart = $this->decodePunycode(substr($domainPart, 4));
@@ -490,20 +565,16 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
if ((strpos($domainPart, '-') === 0)
|| ((strlen($domainPart) > 2) && (strpos($domainPart, '-', 2) == 2) && (strpos($domainPart, '-', 3) == 3))
|| (strpos($domainPart, '-') === (strlen($domainPart) - 1))) {
- $this->_error(self::INVALID_DASH);
+ $this->_error(self::INVALID_DASH);
$status = false;
break 2;
}
// Check each domain part
- $check = false;
+ $checked = false;
foreach($regexChars as $regexKey => $regexChar) {
$status = @preg_match($regexChar, $domainPart);
- if ($status === false) {
- iconv_set_encoding('internal_encoding', $origenc);
- require_once 'Zend/Validate/Exception.php';
- throw new Zend_Validate_Exception('Internal error: DNS validation failed');
- } elseif ($status !== 0) {
+ if ($status > 0) {
$length = 63;
if (array_key_exists(strtoupper($this->_tld), $this->_idnLength)
&& (array_key_exists($regexKey, $this->_idnLength[strtoupper($this->_tld)]))) {
@@ -513,23 +584,22 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
if (iconv_strlen($domainPart, 'UTF-8') > $length) {
$this->_error(self::INVALID_HOSTNAME);
} else {
- $check = true;
- break 2;
+ $checked = true;
+ break;
}
}
}
- if (!$check) {
- $valid = false;
+ if ($checked) {
+ ++$check;
}
}
- // If all labels didn't match, the hostname is invalid
- if (!$valid) {
+ // If one of the labels doesn't match, the hostname is invalid
+ if ($check !== count($domainParts)) {
$this->_error(self::INVALID_HOSTNAME_SCHEMA);
$status = false;
}
-
} else {
// Hostname not long enough
$this->_error(self::UNDECIPHERABLE_TLD);
@@ -540,28 +610,20 @@ class Zend_Validate_Hostname extends Zend_Validate_Abstract
iconv_set_encoding('internal_encoding', $origenc);
// If the input passes as an Internet domain name, and domain names are allowed, then the hostname
// passes validation
- if ($status && ($this->_allow & self::ALLOW_DNS)) {
+ if ($status && ($this->_options['allow'] & self::ALLOW_DNS)) {
return true;
}
- } else {
+ } else if ($this->_options['allow'] & self::ALLOW_DNS) {
$this->_error(self::INVALID_HOSTNAME);
}
// Check input against local network name schema; last chance to pass validation
$regexLocal = '/^(([a-zA-Z0-9\x2d]{1,63}\x2e)*[a-zA-Z0-9\x2d]{1,63}){1,254}$/';
$status = @preg_match($regexLocal, $value);
- if (false === $status) {
- /**
- * Regex error
- * @see Zend_Validate_Exception
- */
- require_once 'Zend/Validate/Exception.php';
- throw new Zend_Validate_Exception('Internal error: local network name validation failed');
- }
// If the input passes as a local network name, and local network names are allowed, then the
// hostname passes validation
- $allowLocal = $this->_allow & self::ALLOW_LOCAL;
+ $allowLocal = $this->_options['allow'] & self::ALLOW_LOCAL;
if ($status && $allowLocal) {
return true;
}
diff --git a/libs/Zend/Validate/Hostname/Biz.php b/libs/Zend/Validate/Hostname/Biz.php
index f2e3e7a009..38762217d8 100644
--- a/libs/Zend/Validate/Hostname/Biz.php
+++ b/libs/Zend/Validate/Hostname/Biz.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Biz.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Biz.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
@@ -24,7 +24,7 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
return array(
diff --git a/libs/Zend/Validate/Hostname/Cn.php b/libs/Zend/Validate/Hostname/Cn.php
index 1bcd91eb95..feee54ade2 100644
--- a/libs/Zend/Validate/Hostname/Cn.php
+++ b/libs/Zend/Validate/Hostname/Cn.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Cn.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Cn.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
@@ -24,7 +24,7 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
return array(
diff --git a/libs/Zend/Validate/Hostname/Com.php b/libs/Zend/Validate/Hostname/Com.php
index 19290b300f..413971fec5 100644
--- a/libs/Zend/Validate/Hostname/Com.php
+++ b/libs/Zend/Validate/Hostname/Com.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Com.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Com.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
@@ -24,7 +24,7 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
return array(
diff --git a/libs/Zend/Validate/Hostname/Jp.php b/libs/Zend/Validate/Hostname/Jp.php
index 0888472e61..02f278e2bd 100644
--- a/libs/Zend/Validate/Hostname/Jp.php
+++ b/libs/Zend/Validate/Hostname/Jp.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Jp.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Jp.php 20096 2010-01-06 02:05:09Z bkarwin $
*/
/**
@@ -24,7 +24,7 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
return array(
diff --git a/libs/Zend/Validate/Iban.php b/libs/Zend/Validate/Iban.php
index 071651fd96..097cd32cbd 100644
--- a/libs/Zend/Validate/Iban.php
+++ b/libs/Zend/Validate/Iban.php
@@ -14,22 +14,22 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Iban.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Iban.php 21563 2010-03-19 10:10:45Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validates IBAN Numbers (International Bank Account Numbers)
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Iban extends Zend_Validate_Abstract
@@ -44,9 +44,9 @@ class Zend_Validate_Iban extends Zend_Validate_Abstract
* @var array
*/
protected $_messageTemplates = array(
- self::NOTSUPPORTED => "'%value%' does not have IBAN",
- self::FALSEFORMAT => "'%value%' has a false format",
- self::CHECKFAILED => "'%value%' has failed the IBAN check"
+ self::NOTSUPPORTED => "Unknown country within the IBAN '%value%'",
+ self::FALSEFORMAT => "'%value%' has a false IBAN format",
+ self::CHECKFAILED => "'%value%' has failed the IBAN check",
);
/**
@@ -106,12 +106,31 @@ class Zend_Validate_Iban extends Zend_Validate_Abstract
/**
* Sets validator options
*
- * @param string|Zend_Locale $locale OPTIONAL
+ * @param string|Zend_Config|Zend_Locale $locale OPTIONAL
* @return void
*/
public function __construct($locale = null)
{
- if ($locale !== null) {
+ if ($locale instanceof Zend_Config) {
+ $locale = $locale->toArray();
+ }
+
+ if (is_array($locale)) {
+ if (array_key_exists('locale', $locale)) {
+ $locale = $locale['locale'];
+ } else {
+ $locale = null;
+ }
+ }
+
+ if ($locale !== false) {
+ // require_once 'Zend/Registry.php';
+ if (Zend_Registry::isRegistered('Zend_Locale')) {
+ $locale = Zend_Registry::get('Zend_Locale');
+ }
+ }
+
+ if (!empty($locale)) {
$this->setLocale($locale);
}
}
@@ -134,11 +153,13 @@ class Zend_Validate_Iban extends Zend_Validate_Abstract
*/
public function setLocale($locale = null)
{
- require_once 'Zend/Locale.php';
- $locale = Zend_Locale::findLocale($locale);
- if (strlen($locale) < 4) {
- require_once 'Zend/Validate/Exception.php';
- throw new Zend_Validate_Exception('Region must be given for IBAN validation');
+ if ($locale !== false) {
+ // require_once 'Zend/Locale.php';
+ $locale = Zend_Locale::findLocale($locale);
+ if (strlen($locale) < 4) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Region must be given for IBAN validation');
+ }
}
$this->_locale = $locale;
diff --git a/libs/Zend/Validate/Identical.php b/libs/Zend/Validate/Identical.php
index d1a046ea9f..7b37574050 100644
--- a/libs/Zend/Validate/Identical.php
+++ b/libs/Zend/Validate/Identical.php
@@ -14,18 +14,18 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Identical.php 17684 2009-08-20 09:20:36Z yoshida@zend.co.jp $
+ * @version $Id: Identical.php 22077 2010-05-02 13:44:46Z thomas $
*/
/** @see Zend_Validate_Abstract */
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Identical extends Zend_Validate_Abstract
@@ -42,7 +42,7 @@ class Zend_Validate_Identical extends Zend_Validate_Abstract
* @var array
*/
protected $_messageTemplates = array(
- self::NOT_SAME => "The token '%token%' does not match the given token '%value%'",
+ self::NOT_SAME => "The two given tokens do not match",
self::MISSING_TOKEN => 'No token was provided to match against',
);
@@ -59,6 +59,7 @@ class Zend_Validate_Identical extends Zend_Validate_Abstract
*/
protected $_tokenString;
protected $_token;
+ protected $_strict = true;
/**
* Sets validator options
@@ -68,12 +69,32 @@ class Zend_Validate_Identical extends Zend_Validate_Abstract
*/
public function __construct($token = null)
{
- if (null !== $token) {
+ if ($token instanceof Zend_Config) {
+ $token = $token->toArray();
+ }
+
+ if (is_array($token) && array_key_exists('token', $token)) {
+ if (array_key_exists('strict', $token)) {
+ $this->setStrict($token['strict']);
+ }
+
+ $this->setToken($token['token']);
+ } else if (null !== $token) {
$this->setToken($token);
}
}
/**
+ * Retrieve token
+ *
+ * @return string
+ */
+ public function getToken()
+ {
+ return $this->_token;
+ }
+
+ /**
* Set token against which to compare
*
* @param mixed $token
@@ -87,13 +108,24 @@ class Zend_Validate_Identical extends Zend_Validate_Abstract
}
/**
- * Retrieve token
+ * Returns the strict parameter
*
- * @return string
+ * @return boolean
*/
- public function getToken()
+ public function getStrict()
{
- return $this->_token;
+ return $this->_strict;
+ }
+
+ /**
+ * Sets the strict parameter
+ *
+ * @param Zend_Validate_Identical
+ */
+ public function setStrict($strict)
+ {
+ $this->_strict = (boolean) $strict;
+ return $this;
}
/**
@@ -103,19 +135,26 @@ class Zend_Validate_Identical extends Zend_Validate_Abstract
* matches that token.
*
* @param mixed $value
+ * @param array $context
* @return boolean
*/
- public function isValid($value)
+ public function isValid($value, $context = null)
{
$this->_setValue((string) $value);
- $token = $this->getToken();
+
+ if (($context !== null) && isset($context) && array_key_exists($this->getToken(), $context)) {
+ $token = $context[$this->getToken()];
+ } else {
+ $token = $this->getToken();
+ }
if ($token === null) {
$this->_error(self::MISSING_TOKEN);
return false;
}
- if ($value !== $token) {
+ $strict = $this->getStrict();
+ if (($strict && ($value !== $token)) || (!$strict && ($value != $token))) {
$this->_error(self::NOT_SAME);
return false;
}
diff --git a/libs/Zend/Validate/InArray.php b/libs/Zend/Validate/InArray.php
index 56940eb1aa..3b1870543c 100644
--- a/libs/Zend/Validate/InArray.php
+++ b/libs/Zend/Validate/InArray.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,34 +14,31 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: InArray.php 17470 2009-08-08 22:27:09Z thomas $
+ * @version $Id: InArray.php 20358 2010-01-17 19:03:49Z thomas $
*/
-
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
-
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_InArray extends Zend_Validate_Abstract
{
-
const NOT_IN_ARRAY = 'notInArray';
/**
* @var array
*/
protected $_messageTemplates = array(
- self::NOT_IN_ARRAY => "'%value%' was not found in the haystack"
+ self::NOT_IN_ARRAY => "'%value%' was not found in the haystack",
);
/**
@@ -57,19 +53,54 @@ class Zend_Validate_InArray extends Zend_Validate_Abstract
*
* @var boolean
*/
- protected $_strict;
+ protected $_strict = false;
+
+ /**
+ * Whether a recursive search should be done
+ *
+ * @var boolean
+ */
+ protected $_recursive = false;
/**
* Sets validator options
*
- * @param array $haystack
- * @param boolean $strict
+ * @param array|Zend_Config $haystack
* @return void
*/
- public function __construct(array $haystack, $strict = false)
+ public function __construct($options)
{
- $this->setHaystack($haystack)
- ->setStrict($strict);
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (!is_array($options)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Array expected as parameter');
+ } else {
+ $count = func_num_args();
+ $temp = array();
+ if ($count > 1) {
+ $temp['haystack'] = func_get_arg(0);
+ $temp['strict'] = func_get_arg(1);
+ $options = $temp;
+ } else {
+ $temp = func_get_arg(0);
+ if (!array_key_exists('haystack', $options)) {
+ $options = array();
+ $options['haystack'] = $temp;
+ } else {
+ $options = $temp;
+ }
+ }
+ }
+
+ $this->setHaystack($options['haystack']);
+ if (array_key_exists('strict', $options)) {
+ $this->setStrict($options['strict']);
+ }
+
+ if (array_key_exists('recursive', $options)) {
+ $this->setRecursive($options['recursive']);
+ }
}
/**
@@ -112,7 +143,29 @@ class Zend_Validate_InArray extends Zend_Validate_Abstract
*/
public function setStrict($strict)
{
- $this->_strict = $strict;
+ $this->_strict = (boolean) $strict;
+ return $this;
+ }
+
+ /**
+ * Returns the recursive option
+ *
+ * @return boolean
+ */
+ public function getRecursive()
+ {
+ return $this->_recursive;
+ }
+
+ /**
+ * Sets the recursive option
+ *
+ * @param boolean $recursive
+ * @return Zend_Validate_InArray Provides a fluent interface
+ */
+ public function setRecursive($recursive)
+ {
+ $this->_recursive = (boolean) $recursive;
return $this;
}
@@ -128,11 +181,24 @@ class Zend_Validate_InArray extends Zend_Validate_Abstract
public function isValid($value)
{
$this->_setValue($value);
- if (!in_array($value, $this->_haystack, $this->_strict)) {
- $this->_error(self::NOT_IN_ARRAY);
- return false;
+ if ($this->getRecursive()) {
+ $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($this->_haystack));
+ foreach($iterator as $element) {
+ if ($this->_strict) {
+ if ($element === $value) {
+ return true;
+ }
+ } else if ($element == $value) {
+ return true;
+ }
+ }
+ } else {
+ if (in_array($value, $this->_haystack, $this->_strict)) {
+ return true;
+ }
}
- return true;
- }
+ $this->_error(self::NOT_IN_ARRAY);
+ return false;
+ }
}
diff --git a/libs/Zend/Validate/Int.php b/libs/Zend/Validate/Int.php
index 1e34ee3427..89fa168627 100644
--- a/libs/Zend/Validate/Int.php
+++ b/libs/Zend/Validate/Int.php
@@ -14,25 +14,25 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Int.php 17470 2009-08-08 22:27:09Z thomas $
+ * @version $Id: Int.php 20532 2010-01-22 20:18:23Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @see Zend_Locale_Format
*/
-require_once 'Zend/Locale/Format.php';
+// require_once 'Zend/Locale/Format.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Int extends Zend_Validate_Abstract
@@ -44,8 +44,8 @@ class Zend_Validate_Int extends Zend_Validate_Abstract
* @var array
*/
protected $_messageTemplates = array(
- self::INVALID => "Invalid type given, value should be a string or a integer",
- self::NOT_INT => "'%value%' does not appear to be an integer"
+ self::INVALID => "Invalid type given, value should be string or integer",
+ self::NOT_INT => "'%value%' does not appear to be an integer",
);
protected $_locale;
@@ -53,10 +53,29 @@ class Zend_Validate_Int extends Zend_Validate_Abstract
/**
* Constructor for the integer validator
*
- * @param string|Zend_Locale $locale
+ * @param string|Zend_Config|Zend_Locale $locale
*/
public function __construct($locale = null)
{
+ if ($locale instanceof Zend_Config) {
+ $locale = $locale->toArray();
+ }
+
+ if (is_array($locale)) {
+ if (array_key_exists('locale', $locale)) {
+ $locale = $locale['locale'];
+ } else {
+ $locale = null;
+ }
+ }
+
+ if (empty($locale)) {
+ // require_once 'Zend/Registry.php';
+ if (Zend_Registry::isRegistered('Zend_Locale')) {
+ $locale = Zend_Registry::get('Zend_Locale');
+ }
+ }
+
if ($locale !== null) {
$this->setLocale($locale);
}
@@ -77,7 +96,7 @@ class Zend_Validate_Int extends Zend_Validate_Abstract
*/
public function setLocale($locale = null)
{
- require_once 'Zend/Locale.php';
+ // require_once 'Zend/Locale.php';
$this->_locale = Zend_Locale::findLocale($locale);
return $this;
}
@@ -97,6 +116,10 @@ class Zend_Validate_Int extends Zend_Validate_Abstract
return false;
}
+ if (is_int($value)) {
+ return true;
+ }
+
$this->_setValue($value);
if ($this->_locale === null) {
$locale = localeconv();
@@ -110,8 +133,7 @@ class Zend_Validate_Int extends Zend_Validate_Abstract
} else {
try {
- if (!Zend_Locale_Format::isInteger($value, array('locale' => 'en')) &&
- !Zend_Locale_Format::isInteger($value, array('locale' => $this->_locale))) {
+ if (!Zend_Locale_Format::isInteger($value, array('locale' => $this->_locale))) {
$this->_error(self::NOT_INT);
return false;
}
diff --git a/libs/Zend/Validate/Interface.php b/libs/Zend/Validate/Interface.php
index 842a57a8d1..9dfca94219 100644
--- a/libs/Zend/Validate/Interface.php
+++ b/libs/Zend/Validate/Interface.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,16 +14,15 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Interface.php 16223 2009-06-21 20:04:53Z thomas $
+ * @version $Id: Interface.php 20358 2010-01-17 19:03:49Z thomas $
*/
-
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
interface Zend_Validate_Interface
@@ -53,19 +51,4 @@ interface Zend_Validate_Interface
* @return array
*/
public function getMessages();
-
- /**
- * Returns an array of message codes that explain why a previous isValid() call
- * returned false.
- *
- * If isValid() was never called or if the most recent isValid() call
- * returned true, then this method returns an empty array.
- *
- * This is now the same as calling array_keys() on the return value from getMessages().
- *
- * @return array
- * @deprecated Since 1.5.0
- */
- public function getErrors();
-
}
diff --git a/libs/Zend/Validate/Ip.php b/libs/Zend/Validate/Ip.php
index a89bb36fe7..992e60a787 100644
--- a/libs/Zend/Validate/Ip.php
+++ b/libs/Zend/Validate/Ip.php
@@ -14,20 +14,20 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Ip.php 17470 2009-08-08 22:27:09Z thomas $
+ * @version $Id: Ip.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Ip extends Zend_Validate_Abstract
@@ -40,10 +40,78 @@ class Zend_Validate_Ip extends Zend_Validate_Abstract
*/
protected $_messageTemplates = array(
self::INVALID => "Invalid type given, value should be a string",
- self::NOT_IP_ADDRESS => "'%value%' does not appear to be a valid IP address"
+ self::NOT_IP_ADDRESS => "'%value%' does not appear to be a valid IP address",
);
/**
+ * internal options
+ *
+ * @var array
+ */
+ protected $_options = array(
+ 'allowipv6' => true,
+ 'allowipv4' => true
+ );
+
+ /**
+ * Sets validator options
+ *
+ * @param array $options OPTIONAL Options to set, see the manual for all available options
+ * @return void
+ */
+ public function __construct($options = array())
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp['allowipv6'] = array_shift($options);
+ if (!empty($options)) {
+ $temp['allowipv4'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ $options += $this->_options;
+ $this->setOptions($options);
+ }
+
+ /**
+ * Returns all set options
+ *
+ * @return array
+ */
+ public function getOptions()
+ {
+ return $this->_options;
+ }
+
+ /**
+ * Sets the options for this validator
+ *
+ * @param array $options
+ * @return Zend_Validate_Ip
+ */
+ public function setOptions($options)
+ {
+ if (array_key_exists('allowipv6', $options)) {
+ $this->_options['allowipv6'] = (boolean) $options['allowipv6'];
+ }
+
+ if (array_key_exists('allowipv4', $options)) {
+ $this->_options['allowipv4'] = (boolean) $options['allowipv4'];
+ }
+
+ if (!$this->_options['allowipv4'] && !$this->_options['allowipv6']) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Nothing to validate. Check your options');
+ }
+
+ return $this;
+ }
+
+ /**
* Defined by Zend_Validate_Interface
*
* Returns true if and only if $value is a valid IP address
@@ -59,18 +127,65 @@ class Zend_Validate_Ip extends Zend_Validate_Abstract
}
$this->_setValue($value);
+ if (($this->_options['allowipv4'] && !$this->_options['allowipv6'] && !$this->_validateIPv4($value)) ||
+ (!$this->_options['allowipv4'] && $this->_options['allowipv6'] && !$this->_validateIPv6($value)) ||
+ ($this->_options['allowipv4'] && $this->_options['allowipv6'] && !$this->_validateIPv4($value) && !$this->_validateIPv6($value))) {
+ $this->_error(self::NOT_IP_ADDRESS);
+ return false;
+ }
- if ((ip2long($value) === false) || (long2ip(ip2long($value)) !== $value)) {
- if (!function_exists('inet_pton')) {
- $this->_error(self::NOT_IP_ADDRESS);
- return false;
- } else if ((@inet_pton($value) === false) ||(inet_ntop(@inet_pton($value)) !== $value)) {
- $this->_error(self::NOT_IP_ADDRESS);
+ return true;
+ }
+
+ /**
+ * Validates an IPv4 address
+ *
+ * @param string $value
+ */
+ protected function _validateIPv4($value) {
+ $ip2long = ip2long($value);
+ if($ip2long === false) {
+ return false;
+ }
+
+ return $value == long2ip($ip2long);
+ }
+
+ /**
+ * Validates an IPv6 address
+ *
+ * @param string $value Value to check against
+ * @return boolean True when $value is a valid ipv6 address
+ * False otherwise
+ */
+ protected function _validateIPv6($value) {
+ if (strlen($value) < 3) {
+ return $value == '::';
+ }
+
+ if (strpos($value, '.')) {
+ $lastcolon = strrpos($value, ':');
+ if (!($lastcolon && $this->_validateIPv4(substr($value, $lastcolon + 1)))) {
return false;
}
+
+ $value = substr($value, 0, $lastcolon) . ':0:0';
}
- return true;
- }
+ if (strpos($value, '::') === false) {
+ return preg_match('/\A(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}\z/i', $value);
+ }
+
+ $colonCount = substr_count($value, ':');
+ if ($colonCount < 8) {
+ return preg_match('/\A(?::|(?:[a-f0-9]{1,4}:)+):(?:(?:[a-f0-9]{1,4}:)*[a-f0-9]{1,4})?\z/i', $value);
+ }
+ // special case with ending or starting double colon
+ if ($colonCount == 8) {
+ return preg_match('/\A(?:::)?(?:[a-f0-9]{1,4}:){6}[a-f0-9]{1,4}(?:::)?\z/i', $value);
+ }
+
+ return false;
+ }
}
diff --git a/libs/Zend/Validate/Isbn.php b/libs/Zend/Validate/Isbn.php
new file mode 100644
index 0000000000..e977871b20
--- /dev/null
+++ b/libs/Zend/Validate/Isbn.php
@@ -0,0 +1,279 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: Isbn.php 21761 2010-04-04 21:37:18Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Abstract
+ */
+// require_once 'Zend/Validate/Abstract.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_Isbn extends Zend_Validate_Abstract
+{
+ const AUTO = 'auto';
+ const ISBN10 = '10';
+ const ISBN13 = '13';
+ const INVALID = 'isbnInvalid';
+ const NO_ISBN = 'isbnNoIsbn';
+
+ /**
+ * Validation failure message template definitions.
+ *
+ * @var array
+ */
+ protected $_messageTemplates = array(
+ self::INVALID => "Invalid type given, value should be string or integer",
+ self::NO_ISBN => "'%value%' is no valid ISBN number",
+ );
+
+ /**
+ * Allowed type.
+ *
+ * @var string
+ */
+ protected $_type = self::AUTO;
+
+ /**
+ * Separator character.
+ *
+ * @var string
+ */
+ protected $_separator = '';
+
+ /**
+ * Set up options.
+ *
+ * @param Zend_Config|array $options
+ * @throws Zend_Validate_Exception When $options is not valid
+ * @return void
+ */
+ public function __construct($options = array())
+ {
+ // prepare options
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ }
+ if (!is_array($options)) {
+ /**
+ * @see Zend_Validate_Exception
+ */
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Invalid options provided.');
+ }
+
+ // set type
+ if (array_key_exists('type', $options)) {
+ $this->setType($options['type']);
+ }
+
+ // set separator
+ if (array_key_exists('separator', $options)) {
+ $this->setSeparator($options['separator']);
+ }
+ }
+
+ /**
+ * Detect input format.
+ *
+ * @return string
+ */
+ protected function _detectFormat()
+ {
+ // prepare separator and pattern list
+ $sep = quotemeta($this->_separator);
+ $patterns = array();
+ $lengths = array();
+
+ // check for ISBN-10
+ if ($this->_type == self::ISBN10 || $this->_type == self::AUTO) {
+ if (empty($sep)) {
+ $pattern = '/^[0-9]{9}[0-9X]{1}$/';
+ $length = 10;
+ } else {
+ $pattern = "/^[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9]{1,7}[{$sep}]{1}[0-9X]{1}$/";
+ $length = 13;
+ }
+
+ $patterns[$pattern] = self::ISBN10;
+ $lengths[$pattern] = $length;
+ }
+
+ // check for ISBN-13
+ if ($this->_type == self::ISBN13 || $this->_type == self::AUTO) {
+ if (empty($sep)) {
+ $pattern = '/^[0-9]{13}$/';
+ $length = 13;
+ } else {
+ $pattern = "/^[0-9]{1,9}[{$sep}]{1}[0-9]{1,5}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1,9}[{$sep}]{1}[0-9]{1}$/";
+ $length = 17;
+ }
+
+ $patterns[$pattern] = self::ISBN13;
+ $lengths[$pattern] = $length;
+ }
+
+ // check pattern list
+ foreach ($patterns as $pattern => $type) {
+ if ((strlen($this->_value) == $lengths[$pattern]) && preg_match($pattern, $this->_value)) {
+ return $type;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Defined by Zend_Validate_Interface.
+ *
+ * Returns true if and only if $value is a valid ISBN.
+ *
+ * @param string $value
+ * @return boolean
+ */
+ public function isValid($value)
+ {
+ if (!is_string($value) && !is_int($value)) {
+ $this->_error(self::INVALID);
+ return false;
+ }
+
+ $value = (string) $value;
+ $this->_setValue($value);
+
+ switch ($this->_detectFormat()) {
+ case self::ISBN10:
+ // sum
+ $isbn10 = str_replace($this->_separator, '', $value);
+ $sum = 0;
+ for ($i = 0; $i < 9; $i++) {
+ $sum += (10 - $i) * $isbn10{$i};
+ }
+
+ // checksum
+ $checksum = 11 - ($sum % 11);
+ if ($checksum == 11) {
+ $checksum = '0';
+ } elseif ($checksum == 10) {
+ $checksum = 'X';
+ }
+ break;
+
+ case self::ISBN13:
+ // sum
+ $isbn13 = str_replace($this->_separator, '', $value);
+ $sum = 0;
+ for ($i = 0; $i < 12; $i++) {
+ if ($i % 2 == 0) {
+ $sum += $isbn13{$i};
+ } else {
+ $sum += 3 * $isbn13{$i};
+ }
+ }
+ // checksum
+ $checksum = 10 - ($sum % 10);
+ if ($checksum == 10) {
+ $checksum = '0';
+ }
+ break;
+
+ default:
+ $this->_error(self::NO_ISBN);
+ return false;
+ }
+
+ // validate
+ if (substr($this->_value, -1) != $checksum) {
+ $this->_error(self::NO_ISBN);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Set separator characters.
+ *
+ * It is allowed only empty string, hyphen and space.
+ *
+ * @param string $separator
+ * @throws Zend_Validate_Exception When $separator is not valid
+ * @return Zend_Validate_Isbn Provides a fluent interface
+ */
+ public function setSeparator($separator)
+ {
+ // check separator
+ if (!in_array($separator, array('-', ' ', ''))) {
+ /**
+ * @see Zend_Validate_Exception
+ */
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Invalid ISBN separator.');
+ }
+
+ $this->_separator = $separator;
+ return $this;
+ }
+
+ /**
+ * Get separator characters.
+ *
+ * @return string
+ */
+ public function getSeparator()
+ {
+ return $this->_separator;
+ }
+
+ /**
+ * Set allowed ISBN type.
+ *
+ * @param string $type
+ * @throws Zend_Validate_Exception When $type is not valid
+ * @return Zend_Validate_Isbn Provides a fluent interface
+ */
+ public function setType($type)
+ {
+ // check type
+ if (!in_array($type, array(self::AUTO, self::ISBN10, self::ISBN13))) {
+ /**
+ * @see Zend_Validate_Exception
+ */
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Invalid ISBN type');
+ }
+
+ $this->_type = $type;
+ return $this;
+ }
+
+ /**
+ * Get allowed ISBN type.
+ *
+ * @return string
+ */
+ public function getType()
+ {
+ return $this->_type;
+ }
+}
diff --git a/libs/Zend/Validate/LessThan.php b/libs/Zend/Validate/LessThan.php
index 5d4e155559..213c766f88 100644
--- a/libs/Zend/Validate/LessThan.php
+++ b/libs/Zend/Validate/LessThan.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,27 +14,24 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: LessThan.php 17470 2009-08-08 22:27:09Z thomas $
+ * @version $Id: LessThan.php 20182 2010-01-10 21:12:01Z thomas $
*/
-
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
-
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_LessThan extends Zend_Validate_Abstract
{
-
const NOT_LESS = 'notLessThan';
/**
@@ -62,11 +58,24 @@ class Zend_Validate_LessThan extends Zend_Validate_Abstract
/**
* Sets validator options
*
- * @param mixed $max
+ * @param mixed|Zend_Config $max
* @return void
*/
public function __construct($max)
{
+ if ($max instanceof Zend_Config) {
+ $max = $max->toArray();
+ }
+
+ if (is_array($max)) {
+ if (array_key_exists('max', $max)) {
+ $max = $max['max'];
+ } else {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception("Missing option 'max'");
+ }
+ }
+
$this->setMax($max);
}
diff --git a/libs/Zend/Validate/NotEmpty.php b/libs/Zend/Validate/NotEmpty.php
index 304cf4fe70..e370459cf9 100644
--- a/libs/Zend/Validate/NotEmpty.php
+++ b/libs/Zend/Validate/NotEmpty.php
@@ -14,27 +14,51 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: NotEmpty.php 18186 2009-09-17 18:57:00Z matthew $
+ * @version $Id: NotEmpty.php 20193 2010-01-11 10:40:43Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_NotEmpty extends Zend_Validate_Abstract
{
+ const BOOLEAN = 1;
+ const INTEGER = 2;
+ const FLOAT = 4;
+ const STRING = 8;
+ const ZERO = 16;
+ const EMPTY_ARRAY = 32;
+ const NULL = 64;
+ const PHP = 127;
+ const SPACE = 128;
+ const ALL = 255;
+
const INVALID = 'notEmptyInvalid';
const IS_EMPTY = 'isEmpty';
+ protected $_constants = array(
+ self::BOOLEAN => 'boolean',
+ self::INTEGER => 'integer',
+ self::FLOAT => 'float',
+ self::STRING => 'string',
+ self::ZERO => 'zero',
+ self::EMPTY_ARRAY => 'array',
+ self::NULL => 'null',
+ self::PHP => 'php',
+ self::SPACE => 'space',
+ self::ALL => 'all'
+ );
+
/**
* @var array
*/
@@ -44,6 +68,80 @@ class Zend_Validate_NotEmpty extends Zend_Validate_Abstract
);
/**
+ * Internal type to detect
+ *
+ * @var integer
+ */
+ protected $_type = 237;
+
+ /**
+ * Constructor
+ *
+ * @param string|array|Zend_Config $options OPTIONAL
+ */
+ public function __construct($options = null)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp = array();
+ if (!empty($options)) {
+ $temp['type'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ if (is_array($options) && array_key_exists('type', $options)) {
+ $this->setType($options['type']);
+ }
+ }
+
+ /**
+ * Returns the set types
+ *
+ * @return array
+ */
+ public function getType()
+ {
+ return $this->_type;
+ }
+
+ /**
+ * Set the types
+ *
+ * @param integer|array $type
+ * @throws Zend_Validate_Exception
+ * @return Zend_Validate_NotEmpty
+ */
+ public function setType($type = null)
+ {
+ if (is_array($type)) {
+ $detected = 0;
+ foreach($type as $value) {
+ if (is_int($value)) {
+ $detected += $value;
+ } else if (in_array($value, $this->_constants)) {
+ $detected += array_search($value, $this->_constants);
+ }
+ }
+
+ $type = $detected;
+ } else if (is_string($type) && in_array($type, $this->_constants)) {
+ $type = array_search($type, $this->_constants);
+ }
+
+ if (!is_int($type) || ($type < 0) || ($type > self::ALL)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Unknown type');
+ }
+
+ $this->_type = $type;
+ return $this;
+ }
+
+ /**
* Defined by Zend_Validate_Interface
*
* Returns true if and only if $value is not an empty value.
@@ -59,21 +157,81 @@ class Zend_Validate_NotEmpty extends Zend_Validate_Abstract
return false;
}
+ $type = $this->getType();
$this->_setValue($value);
- if (is_string($value)
- && (('' === $value)
- || preg_match('/^\s+$/s', $value))
- ) {
- $this->_error(self::IS_EMPTY);
- return false;
- } elseif (is_int($value) && (0 === $value)) {
- return true;
- } elseif (!is_string($value) && empty($value)) {
- $this->_error(self::IS_EMPTY);
- return false;
+
+ // SPACE (' ')
+ if ($type >= self::SPACE) {
+ $type -= self::SPACE;
+ if (is_string($value) && (preg_match('/^\s+$/s', $value))) {
+ $this->_error(self::IS_EMPTY);
+ return false;
+ }
+ }
+
+ // NULL (null)
+ if ($type >= self::NULL) {
+ $type -= self::NULL;
+ if (is_null($value)) {
+ $this->_error(self::IS_EMPTY);
+ return false;
+ }
+ }
+
+ // EMPTY_ARRAY (array())
+ if ($type >= self::EMPTY_ARRAY) {
+ $type -= self::EMPTY_ARRAY;
+ if (is_array($value) && ($value == array())) {
+ $this->_error(self::IS_EMPTY);
+ return false;
+ }
+ }
+
+ // ZERO ('0')
+ if ($type >= self::ZERO) {
+ $type -= self::ZERO;
+ if (is_string($value) && ($value == '0')) {
+ $this->_error(self::IS_EMPTY);
+ return false;
+ }
+ }
+
+ // STRING ('')
+ if ($type >= self::STRING) {
+ $type -= self::STRING;
+ if (is_string($value) && ($value == '')) {
+ $this->_error(self::IS_EMPTY);
+ return false;
+ }
+ }
+
+ // FLOAT (0.0)
+ if ($type >= self::FLOAT) {
+ $type -= self::FLOAT;
+ if (is_float($value) && ($value == 0.0)) {
+ $this->_error(self::IS_EMPTY);
+ return false;
+ }
+ }
+
+ // INTEGER (0)
+ if ($type >= self::INTEGER) {
+ $type -= self::INTEGER;
+ if (is_int($value) && ($value == 0)) {
+ $this->_error(self::IS_EMPTY);
+ return false;
+ }
+ }
+
+ // BOOLEAN (false)
+ if ($type >= self::BOOLEAN) {
+ $type -= self::BOOLEAN;
+ if (is_bool($value) && ($value == false)) {
+ $this->_error(self::IS_EMPTY);
+ return false;
+ }
}
return true;
}
-
}
diff --git a/libs/Zend/Validate/PostCode.php b/libs/Zend/Validate/PostCode.php
new file mode 100644
index 0000000000..1ba58a996b
--- /dev/null
+++ b/libs/Zend/Validate/PostCode.php
@@ -0,0 +1,210 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ * @version $Id: PostCode.php 21487 2010-03-14 10:17:35Z thomas $
+ */
+
+/**
+ * @see Zend_Validate_Abstract
+ */
+// require_once 'Zend/Validate/Abstract.php';
+
+/**
+ * @see Zend_Locale_Format
+ */
+// require_once 'Zend/Locale/Format.php';
+
+/**
+ * @category Zend
+ * @package Zend_Validate
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Validate_PostCode extends Zend_Validate_Abstract
+{
+ const INVALID = 'postcodeInvalid';
+ const NO_MATCH = 'postcodeNoMatch';
+
+ /**
+ * @var array
+ */
+ protected $_messageTemplates = array(
+ self::INVALID => "Invalid type given. The value should be a string or a integer",
+ self::NO_MATCH => "'%value%' does not appear to be a postal code",
+ );
+
+ /**
+ * Locale to use
+ *
+ * @var string
+ */
+ protected $_locale;
+
+ /**
+ * Manual postal code format
+ *
+ * @var unknown_type
+ */
+ protected $_format;
+
+ /**
+ * Constructor for the integer validator
+ *
+ * Accepts either a string locale, a Zend_Locale object, or an array or
+ * Zend_Config object containing the keys "locale" and/or "format".
+ *
+ * @param string|Zend_Locale|array|Zend_Config $options
+ * @throws Zend_Validate_Exception On empty format
+ */
+ public function __construct($options = null)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ }
+
+ if (empty($options)) {
+ // require_once 'Zend/Registry.php';
+ if (Zend_Registry::isRegistered('Zend_Locale')) {
+ $this->setLocale(Zend_Registry::get('Zend_Locale'));
+ }
+ } elseif (is_array($options)) {
+ // Received
+ if (array_key_exists('locale', $options)) {
+ $this->setLocale($options['locale']);
+ }
+
+ if (array_key_exists('format', $options)) {
+ $this->setFormat($options['format']);
+ }
+ } elseif ($options instanceof Zend_Locale || is_string($options)) {
+ // Received Locale object or string locale
+ $this->setLocale($options);
+ }
+
+ $format = $this->getFormat();
+ if (empty($format)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception("A postcode-format string has to be given for validation");
+ }
+ }
+
+ /**
+ * Returns the set locale
+ *
+ * @return string|Zend_Locale The set locale
+ */
+ public function getLocale()
+ {
+ return $this->_locale;
+ }
+
+ /**
+ * Sets the locale to use
+ *
+ * @param string|Zend_Locale $locale
+ * @throws Zend_Validate_Exception On unrecognised region
+ * @throws Zend_Validate_Exception On not detected format
+ * @return Zend_Validate_PostCode Provides fluid interface
+ */
+ public function setLocale($locale = null)
+ {
+ // require_once 'Zend/Locale.php';
+ $this->_locale = Zend_Locale::findLocale($locale);
+ $locale = new Zend_Locale($this->_locale);
+ $region = $locale->getRegion();
+ if (empty($region)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception("Unable to detect a region for the locale '$locale'");
+ }
+
+ $format = Zend_Locale::getTranslation(
+ $locale->getRegion(),
+ 'postaltoterritory',
+ $this->_locale
+ );
+
+ if (empty($format)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception("Unable to detect a postcode format for the region '{$locale->getRegion()}'");
+ }
+
+ $this->setFormat($format);
+ return $this;
+ }
+
+ /**
+ * Returns the set postal code format
+ *
+ * @return string
+ */
+ public function getFormat()
+ {
+ return $this->_format;
+ }
+
+ /**
+ * Sets a self defined postal format as regex
+ *
+ * @param string $format
+ * @throws Zend_Validate_Exception On empty format
+ * @return Zend_Validate_PostCode Provides fluid interface
+ */
+ public function setFormat($format)
+ {
+ if (empty($format) || !is_string($format)) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception("A postcode-format string has to be given for validation");
+ }
+
+ if ($format[0] !== '/') {
+ $format = '/^' . $format;
+ }
+
+ if ($format[strlen($format) - 1] !== '/') {
+ $format .= '$/';
+ }
+
+ $this->_format = $format;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Validate_Interface
+ *
+ * Returns true if and only if $value is a valid postalcode
+ *
+ * @param string $value
+ * @return boolean
+ */
+ public function isValid($value)
+ {
+ $this->_setValue($value);
+ if (!is_string($value) && !is_int($value)) {
+ $this->_error(self::INVALID);
+ return false;
+ }
+
+ $format = $this->getFormat();
+ if (!preg_match($format, $value)) {
+ $this->_error(self::NO_MATCH);
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/libs/Zend/Validate/Regex.php b/libs/Zend/Validate/Regex.php
index e4707f5f60..e46143287f 100644
--- a/libs/Zend/Validate/Regex.php
+++ b/libs/Zend/Validate/Regex.php
@@ -1,5 +1,4 @@
<?php
-
/**
* Zend Framework
*
@@ -15,35 +14,35 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Regex.php 17470 2009-08-08 22:27:09Z thomas $
+ * @version $Id: Regex.php 21574 2010-03-19 20:00:37Z thomas $
*/
-
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
-
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Regex extends Zend_Validate_Abstract
{
const INVALID = 'regexInvalid';
const NOT_MATCH = 'regexNotMatch';
+ const ERROROUS = 'regexErrorous';
/**
* @var array
*/
protected $_messageTemplates = array(
self::INVALID => "Invalid type given, value should be string, integer or float",
- self::NOT_MATCH => "'%value%' does not match against pattern '%pattern%'"
+ self::NOT_MATCH => "'%value%' does not match against pattern '%pattern%'",
+ self::ERROROUS => "There was an internal error while using the pattern '%pattern%'",
);
/**
@@ -63,11 +62,25 @@ class Zend_Validate_Regex extends Zend_Validate_Abstract
/**
* Sets validator options
*
- * @param string $pattern
+ * @param string|Zend_Config $pattern
+ * @throws Zend_Validate_Exception On missing 'pattern' parameter
* @return void
*/
public function __construct($pattern)
{
+ if ($pattern instanceof Zend_Config) {
+ $pattern = $pattern->toArray();
+ }
+
+ if (is_array($pattern)) {
+ if (array_key_exists('pattern', $pattern)) {
+ $pattern = $pattern['pattern'];
+ } else {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception("Missing option 'pattern'");
+ }
+ }
+
$this->setPattern($pattern);
}
@@ -85,11 +98,19 @@ class Zend_Validate_Regex extends Zend_Validate_Abstract
* Sets the pattern option
*
* @param string $pattern
+ * @throws Zend_Validate_Exception if there is a fatal error in pattern matching
* @return Zend_Validate_Regex Provides a fluent interface
*/
public function setPattern($pattern)
{
$this->_pattern = (string) $pattern;
+ $status = @preg_match($this->_pattern, "Test");
+
+ if (false === $status) {
+ // require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception("Internal error while using the pattern '$this->_pattern'");
+ }
+
return $this;
}
@@ -99,7 +120,6 @@ class Zend_Validate_Regex extends Zend_Validate_Abstract
* Returns true if and only if $value matches against the pattern option
*
* @param string $value
- * @throws Zend_Validate_Exception if there is a fatal error in pattern matching
* @return boolean
*/
public function isValid($value)
@@ -113,14 +133,15 @@ class Zend_Validate_Regex extends Zend_Validate_Abstract
$status = @preg_match($this->_pattern, $value);
if (false === $status) {
- require_once 'Zend/Validate/Exception.php';
- throw new Zend_Validate_Exception("Internal error matching pattern '$this->_pattern' against value '$value'");
+ $this->_error(self::ERROROUS);
+ return false;
}
+
if (!$status) {
$this->_error(self::NOT_MATCH);
return false;
}
+
return true;
}
-
}
diff --git a/libs/Zend/Validate/Sitemap/Changefreq.php b/libs/Zend/Validate/Sitemap/Changefreq.php
index 9ff2715d20..6f023856dc 100644
--- a/libs/Zend/Validate/Sitemap/Changefreq.php
+++ b/libs/Zend/Validate/Sitemap/Changefreq.php
@@ -15,15 +15,15 @@
* @category Zend
* @package Zend_Validate
* @subpackage Sitemap
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Changefreq.php 17470 2009-08-08 22:27:09Z thomas $
+ * @version $Id: Changefreq.php 21365 2010-03-07 09:38:41Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validates whether a given value is valid as a sitemap <changefreq> value
@@ -33,7 +33,7 @@ require_once 'Zend/Validate/Abstract.php';
* @category Zend
* @package Zend_Validate
* @subpackage Sitemap
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Sitemap_Changefreq extends Zend_Validate_Abstract
@@ -42,7 +42,8 @@ class Zend_Validate_Sitemap_Changefreq extends Zend_Validate_Abstract
* Validation key for not valid
*
*/
- const NOT_VALID = 'invalidSitemapChangefreq';
+ const NOT_VALID = 'sitemapChangefreqNotValid';
+ const INVALID = 'sitemapChangefreqInvalid';
/**
* Validation failure message template definitions
@@ -50,7 +51,8 @@ class Zend_Validate_Sitemap_Changefreq extends Zend_Validate_Abstract
* @var array
*/
protected $_messageTemplates = array(
- self::NOT_VALID => "'%value%' is not a valid sitemap changefreq",
+ self::NOT_VALID => "'%value%' is no valid sitemap changefreq",
+ self::INVALID => "Invalid type given, the value should be a string",
);
/**
@@ -73,8 +75,12 @@ class Zend_Validate_Sitemap_Changefreq extends Zend_Validate_Abstract
*/
public function isValid($value)
{
- $this->_setValue($value);
+ if (!is_string($value)) {
+ $this->_error(self::INVALID);
+ return false;
+ }
+ $this->_setValue($value);
if (!is_string($value)) {
return false;
}
diff --git a/libs/Zend/Validate/Sitemap/Lastmod.php b/libs/Zend/Validate/Sitemap/Lastmod.php
index 4f01d1a781..aa2266ecd9 100644
--- a/libs/Zend/Validate/Sitemap/Lastmod.php
+++ b/libs/Zend/Validate/Sitemap/Lastmod.php
@@ -15,15 +15,15 @@
* @category Zend
* @package Zend_Validate
* @subpackage Sitemap
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Lastmod.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Lastmod.php 21365 2010-03-07 09:38:41Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validates whether a given value is valid as a sitemap <lastmod> value
@@ -33,7 +33,7 @@ require_once 'Zend/Validate/Abstract.php';
* @category Zend
* @package Zend_Validate
* @subpackage Sitemap
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Sitemap_Lastmod extends Zend_Validate_Abstract
@@ -42,13 +42,14 @@ class Zend_Validate_Sitemap_Lastmod extends Zend_Validate_Abstract
* Regular expression to use when validating
*
*/
- const LASTMOD_REGEX = '/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])(T([0-1][0-9]|2[0-3])(:[0-5][0-9]){2}(\\+|-)([0-1][0-9]|2[0-3]):[0-5][0-9])?$/m';
+ const LASTMOD_REGEX = '/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])(T([0-1][0-9]|2[0-3])(:[0-5][0-9])(:[0-5][0-9])?(\\+|-)([0-1][0-9]|2[0-3]):[0-5][0-9])?$/';
/**
* Validation key for not valid
*
*/
- const NOT_VALID = 'invalidSitemapLastmod';
+ const NOT_VALID = 'sitemapLastmodNotValid';
+ const INVALID = 'sitemapLastmodInvalid';
/**
* Validation failure message template definitions
@@ -56,7 +57,8 @@ class Zend_Validate_Sitemap_Lastmod extends Zend_Validate_Abstract
* @var array
*/
protected $_messageTemplates = array(
- self::NOT_VALID => "'%value%' is not a valid sitemap lastmod",
+ self::NOT_VALID => "'%value%' is no valid sitemap lastmod",
+ self::INVALID => "Invalid type given, the value should be a string",
);
/**
@@ -69,13 +71,18 @@ class Zend_Validate_Sitemap_Lastmod extends Zend_Validate_Abstract
*/
public function isValid($value)
{
- $this->_setValue($value);
-
if (!is_string($value)) {
+ $this->_error(self::INVALID);
return false;
}
- return @preg_match(self::LASTMOD_REGEX, $value) == 1;
- }
+ $this->_setValue($value);
+ $result = @preg_match(self::LASTMOD_REGEX, $value);
+ if ($result != 1) {
+ $this->_error(self::NOT_VALID);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/libs/Zend/Validate/Sitemap/Loc.php b/libs/Zend/Validate/Sitemap/Loc.php
index 92d5272030..180f669a01 100644
--- a/libs/Zend/Validate/Sitemap/Loc.php
+++ b/libs/Zend/Validate/Sitemap/Loc.php
@@ -15,20 +15,20 @@
* @category Zend
* @package Zend_Validate
* @subpackage Sitemap
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Loc.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Loc.php 21365 2010-03-07 09:38:41Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @see Zend_Uri
*/
-require_once 'Zend/Uri.php';
+// require_once 'Zend/Uri.php';
/**
* Validates whether a given value is valid as a sitemap <loc> value
@@ -38,7 +38,7 @@ require_once 'Zend/Uri.php';
* @category Zend
* @package Zend_Validate
* @subpackage Sitemap
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Sitemap_Loc extends Zend_Validate_Abstract
@@ -47,7 +47,8 @@ class Zend_Validate_Sitemap_Loc extends Zend_Validate_Abstract
* Validation key for not valid
*
*/
- const NOT_VALID = 'invalidSitemapLoc';
+ const NOT_VALID = 'sitemapLocNotValid';
+ const INVALID = 'sitemapLocInvalid';
/**
* Validation failure message template definitions
@@ -55,7 +56,8 @@ class Zend_Validate_Sitemap_Loc extends Zend_Validate_Abstract
* @var array
*/
protected $_messageTemplates = array(
- self::NOT_VALID => "'%value%' is not a valid sitemap location",
+ self::NOT_VALID => "'%value%' is no valid sitemap location",
+ self::INVALID => "Invalid type given, the value should be a string",
);
/**
@@ -68,12 +70,18 @@ class Zend_Validate_Sitemap_Loc extends Zend_Validate_Abstract
*/
public function isValid($value)
{
- $this->_setValue($value);
-
if (!is_string($value)) {
+ $this->_error(self::INVALID);
+ return false;
+ }
+
+ $this->_setValue($value);
+ $result = Zend_Uri::check($value);
+ if ($result !== true) {
+ $this->_error(self::NOT_VALID);
return false;
}
- return Zend_Uri::check($value);
+ return true;
}
}
diff --git a/libs/Zend/Validate/Sitemap/Priority.php b/libs/Zend/Validate/Sitemap/Priority.php
index 3568a9fc0f..58772d5b2d 100644
--- a/libs/Zend/Validate/Sitemap/Priority.php
+++ b/libs/Zend/Validate/Sitemap/Priority.php
@@ -15,15 +15,15 @@
* @category Zend
* @package Zend_Validate
* @subpackage Sitemap
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Priority.php 16971 2009-07-22 18:05:45Z mikaelkael $
+ * @version $Id: Priority.php 21365 2010-03-07 09:38:41Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* Validates whether a given value is valid as a sitemap <priority> value
@@ -33,7 +33,7 @@ require_once 'Zend/Validate/Abstract.php';
* @category Zend
* @package Zend_Validate
* @subpackage Sitemap
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_Sitemap_Priority extends Zend_Validate_Abstract
@@ -42,7 +42,8 @@ class Zend_Validate_Sitemap_Priority extends Zend_Validate_Abstract
* Validation key for not valid
*
*/
- const NOT_VALID = 'invalidSitemapPriority';
+ const NOT_VALID = 'sitemapPriorityNotValid';
+ const INVALID = 'sitemapPriorityInvalid';
/**
* Validation failure message template definitions
@@ -50,7 +51,8 @@ class Zend_Validate_Sitemap_Priority extends Zend_Validate_Abstract
* @var array
*/
protected $_messageTemplates = array(
- self::NOT_VALID => "'%value%' is not a valid sitemap priority",
+ self::NOT_VALID => "'%value%' is no valid sitemap priority",
+ self::INVALID => "Invalid type given, the value should be a integer, a float or a numeric string",
);
/**
@@ -63,13 +65,18 @@ class Zend_Validate_Sitemap_Priority extends Zend_Validate_Abstract
*/
public function isValid($value)
{
- $this->_setValue($value);
-
if (!is_numeric($value)) {
+ $this->_error(self::INVALID);
+ return false;
+ }
+
+ $this->_setValue($value);
+ $value = (float) $value;
+ if ($value < 0 || $value > 1) {
+ $this->_error(self::NOT_VALID);
return false;
}
- $value = (float)$value;
- return $value >= 0 && $value <= 1;
+ return true;
}
}
diff --git a/libs/Zend/Validate/StringLength.php b/libs/Zend/Validate/StringLength.php
index 7ec9125f92..c9362ace22 100644
--- a/libs/Zend/Validate/StringLength.php
+++ b/libs/Zend/Validate/StringLength.php
@@ -14,20 +14,20 @@
*
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: StringLength.php 16223 2009-06-21 20:04:53Z thomas $
+ * @version $Id: StringLength.php 20358 2010-01-17 19:03:49Z thomas $
*/
/**
* @see Zend_Validate_Abstract
*/
-require_once 'Zend/Validate/Abstract.php';
+// require_once 'Zend/Validate/Abstract.php';
/**
* @category Zend
* @package Zend_Validate
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Validate_StringLength extends Zend_Validate_Abstract
@@ -42,7 +42,7 @@ class Zend_Validate_StringLength extends Zend_Validate_Abstract
protected $_messageTemplates = array(
self::INVALID => "Invalid type given, value should be a string",
self::TOO_SHORT => "'%value%' is less than %min% characters long",
- self::TOO_LONG => "'%value%' is greater than %max% characters long"
+ self::TOO_LONG => "'%value%' is more than %max% characters long",
);
/**
@@ -79,15 +79,39 @@ class Zend_Validate_StringLength extends Zend_Validate_Abstract
/**
* Sets validator options
*
- * @param integer $min
- * @param integer $max
+ * @param integer|array|Zend_Config $options
* @return void
*/
- public function __construct($min = 0, $max = null, $encoding = null)
+ public function __construct($options = array())
{
- $this->setMin($min);
- $this->setMax($max);
- $this->setEncoding($encoding);
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp['min'] = array_shift($options);
+ if (!empty($options)) {
+ $temp['max'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['encoding'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ if (!array_key_exists('min', $options)) {
+ $options['min'] = 0;
+ }
+
+ $this->setMin($options['min']);
+ if (array_key_exists('max', $options)) {
+ $this->setMax($options['max']);
+ }
+
+ if (array_key_exists('encoding', $options)) {
+ $this->setEncoding($options['encoding']);
+ }
}
/**
@@ -113,7 +137,7 @@ class Zend_Validate_StringLength extends Zend_Validate_Abstract
/**
* @see Zend_Validate_Exception
*/
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("The minimum must be less than or equal to the maximum length, but $min >"
. " $this->_max");
}
@@ -146,7 +170,7 @@ class Zend_Validate_StringLength extends Zend_Validate_Abstract
/**
* @see Zend_Validate_Exception
*/
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception("The maximum must be greater than or equal to the minimum length, but "
. "$max < $this->_min");
} else {
@@ -178,7 +202,7 @@ class Zend_Validate_StringLength extends Zend_Validate_Abstract
$orig = iconv_get_encoding('internal_encoding');
$result = iconv_set_encoding('internal_encoding', $encoding);
if (!$result) {
- require_once 'Zend/Validate/Exception.php';
+ // require_once 'Zend/Validate/Exception.php';
throw new Zend_Validate_Exception('Given encoding not supported on this OS!');
}
diff --git a/libs/Zend/Version.php b/libs/Zend/Version.php
index ded3d4cdd1..392ae3c7df 100644
--- a/libs/Zend/Version.php
+++ b/libs/Zend/Version.php
@@ -14,9 +14,9 @@
*
* @category Zend
* @package Zend_Version
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id: Version.php 18706 2009-10-26 13:15:20Z matthew $
+ * @version $Id: Version.php 22304 2010-05-26 14:25:33Z matthew $
*/
/**
@@ -24,7 +24,7 @@
*
* @category Zend
* @package Zend_Version
- * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
final class Zend_Version
@@ -32,7 +32,7 @@ final class Zend_Version
/**
* Zend Framework version identification - see compareVersion()
*/
- const VERSION = '1.9.5';
+ const VERSION = '1.10.5';
/**
* Compare the specified Zend Framework version string $version
diff --git a/libs/javascript/json2.js b/libs/javascript/json2.js
index d7c3fb5d13..273eca0fc2 100644
--- a/libs/javascript/json2.js
+++ b/libs/javascript/json2.js
@@ -1,29 +1 @@
-// see http://www.json.org/js.html
-if(!this.JSON){JSON={};}
-(function(){function f(n){return n<10?'0'+n:n;}
-if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+'-'+
-f(this.getUTCMonth()+1)+'-'+
-f(this.getUTCDate())+'T'+
-f(this.getUTCHours())+':'+
-f(this.getUTCMinutes())+':'+
-f(this.getUTCSeconds())+'Z';};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
-var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
-function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
-if(typeof rep==='function'){value=rep.call(holder,key,value);}
-switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
-gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||'null';}
-v=partial.length===0?'[]':gap?'[\n'+gap+
-partial.join(',\n'+gap)+'\n'+
-mind+']':'['+partial.join(',')+']';gap=mind;return v;}
-if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==='string'){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?': ':':')+v);}}}}
-v=partial.length===0?'{}':gap?'{\n'+gap+partial.join(',\n'+gap)+'\n'+
-mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
-if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i<space;i+=1){indent+=' ';}}else if(typeof space==='string'){indent=space;}
-rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
-return str('',{'':value});};}
-if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
-return reviver.call(holder,key,value);}
-cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\\u'+
-('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
-if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
-throw new SyntaxError('JSON.parse');};}}()); \ No newline at end of file
+if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}()); \ No newline at end of file
diff --git a/libs/jquery/fdd2div-modified.js b/libs/jquery/fdd2div-modified.js
index a1e4629a0e..2f04934b00 100644
--- a/libs/jquery/fdd2div-modified.js
+++ b/libs/jquery/fdd2div-modified.js
@@ -95,7 +95,11 @@
$('body').append("<div style=\"position:absolute\">"+newForm+"</div>");
child_options+="<li><a href='"+FormAction+"' onclick=\"document.form"+unique_id+"_"+n+".submit();return false;\">"+i.firstChild.nodeValue+"</a></li>\n";
} else {
- child_options+="<li><a href='"+FormAction+SelectName+"="+OptionValue+"'>"+i.firstChild.nodeValue+"</a></li>\n";
+ if($(i).attr('href')) {
+ child_options+="<li><b><a target='_blank' href='"+$(i).attr('href')+"'>"+i.firstChild.nodeValue+"</a></b></li>\n";
+ } else {
+ child_options+="<li><a href='"+FormAction+SelectName+"="+OptionValue+"'>"+i.firstChild.nodeValue+"</a></li>\n";
+ }
}
}
});
diff --git a/libs/jquery/jquery-calendar.css b/libs/jquery/jquery-calendar.css
deleted file mode 100644
index fc40fd1d3e..0000000000
--- a/libs/jquery/jquery-calendar.css
+++ /dev/null
@@ -1,190 +0,0 @@
-/* Main Style Sheet for jQuery Calendar */
-#calendar_div,.calendar_inline {
- font-size: 14px;
- padding: 0;
- margin: 0;
-}
-
-#calendar_div {
- display: none;
- border: 1px solid #777;
- z-index: 10; /*must have*/
-}
-
-#calendar_div,.calendar_control,.calendar_links,.calendar_header,.calendar
- {
- width: 185px;
-}
-
-.calendar_inline {
- float: left;
- display: block;
- border: 0;
-}
-
-.calendar_dialog {
- padding: 5px !important;
- border: 4px ridge #ddd !important;
-}
-
-button.calendar_trigger {
- width: 25px;
-}
-
-img.calendar_trigger {
- margin: 2px;
- vertical-align: middle;
-}
-
-.calendar_prompt {
- float: left;
- width: 181px;
- padding: 2px;
- background: #ddd;
- color: #000;
-}
-
-* html .calendar_prompt {
- width: 185px;
-}
-
-.calendar_control,.calendar_links,.calendar_header,.calendar {
- clear: both;
- float: left;
- color: #fff;
-}
-
-.calendar_control {
- background: #400;
-}
-
-.calendar_links {
- background: #000;
-}
-
-.calendar_control,.calendar_links {
- font-weight: bold;
- font-size: 80%;
- letter-spacing: 1px;
-}
-
-.calendar_links label { /* disabled links */
- padding: 2px 5px;
- color: #888;
-}
-
-.calendar_clear,.calendar_prev {
- float: left;
-}
-
-.calendar_current {
- float: left;
- width: 35%;
- text-align: center;
-}
-
-.calendar_close,.calendar_next {
- float: right;
-}
-
-.calendar_header {
- background: #333;
- text-align: center;
- font-weight: bold;
-}
-
-.calendar_header select {
- background: #333;
- color: #fff;
- border: 0px;
- font-weight: bold;
-}
-
-.calendar {
- background: #ccc;
- text-align: center;
- font-size: 100%;
-}
-
-.calendar a {
- display: block;
- width: 100%;
-}
-
-.calendar .calendar_titleRow {
- background: #777;
-}
-
-.calendar .calendar_daysRow {
- background: #eee;
- color: #666;
-}
-
-.calendar .calendar_daysCell {
- color: #000;
- border: 1px solid #ddd;
-}
-
-#calendar .calendar_daysCell a {
- display: block;
-}
-
-.calendar .calendar_weekEndCell {
- background: #ddd;
-}
-
-.calendar .calendar_daysCellOver {
- background: #fff;
- border: 1px solid #777;
-}
-
-.calendar .calendar_unselectable {
- color: #888;
-}
-
-/* ________ CALENDAR LINKS _______
-
-** Reset link properties and then override them with !important */
-#calendar_div a,.calendar_inline a {
- cursor: pointer;
- margin: 0;
- padding: 0;
- background: none;
- color: #000;
-}
-
-.calendar_inline .calendar_links a {
- padding: 0 5px !important;
-}
-
-.calendar_control a,.calendar_links a {
- padding: 2px 5px !important;
- color: #eee !important;
-}
-
-.calendar_titleRow a {
- color: #eee !important;
-}
-
-.calendar_control a:hover {
- background: #fdd !important;
- color: #333 !important;
-}
-
-.calendar_links a:hover,.calendar_titleRow a:hover {
- background: #ddd !important;
- color: #333 !important;
-}
-
-/* ___________ IE6 IFRAME FIX ________ */
-.calendar_cover {
- display: none; /*sorry for IE5*/
- display /**/: block; /*sorry for IE5*/
- position: absolute; /*must have*/
- z-index: -1; /*must have*/
- filter: mask(); /*must have*/
- top: -4px; /*must have*/
- left: -4px; /*must have*/
- width: 193px; /*must have to match width and borders*/
- height: 200px; /*must have to match maximum height*/
-}
diff --git a/libs/jquery/jquery-calendar.js b/libs/jquery/jquery-calendar.js
deleted file mode 100644
index 6b80456d29..0000000000
--- a/libs/jquery/jquery-calendar.js
+++ /dev/null
@@ -1,72 +0,0 @@
-
-function PopUpCal(){this._nextId=0;this._inst=[];this._curInst=null;this._disabledInputs=[];this._popUpShowing=false;this._inDialog=false;this.regional=[];this.regional['']={clearText:'Clear',closeText:'Close',prevText:'&lt;Prev',nextText:'Next&gt;',currentText:'Today',dayNames:['Su','Mo','Tu','We','Th','Fr','Sa'],monthNames:['January','February','March','April','May','June','July','August','September','October','November','December'],dateFormat:'DMY/'};this._defaults={autoPopUp:'focus',appendText:'',buttonText:'...',buttonImage:'',buttonImageOnly:false,closeAtTop:true,hideIfNoPrevNext:false,changeMonth:true,changeYear:true,yearRange:'-10:+10',firstDay:0,changeFirstDay:true,showOtherMonths:false,minDate:null,maxDate:null,speed:'medium',customDate:null,fieldSettings:null,onSelect:null};$.extend(this._defaults,this.regional['']);this._calendarDiv=$('<div id="calendar_div"></div>');$(document.body).append(this._calendarDiv);$(document.body).mousedown(this._checkExternalClick);}
-$.extend(PopUpCal.prototype,{_register:function(inst){var id=this._nextId++;this._inst[id]=inst;return id;},_getInst:function(id){return this._inst[id]||id;},setDefaults:function(settings){$.extend(this._defaults,settings||{});},_doKeyDown:function(e){var inst=popUpCal._getInst(this._calId);if(popUpCal._popUpShowing){switch(e.keyCode){case 9:popUpCal.hideCalendar(inst,'');break;case 13:popUpCal._selectDate(inst);break;case 27:popUpCal.hideCalendar(inst,inst._get('speed'));break;case 33:popUpCal._adjustDate(inst,-1,(e.ctrlKey?'Y':'M'));break;case 34:popUpCal._adjustDate(inst,+1,(e.ctrlKey?'Y':'M'));break;case 35:if(e.ctrlKey)popUpCal._clearDate(inst);break;case 36:if(e.ctrlKey)popUpCal._gotoToday(inst);break;case 37:if(e.ctrlKey)popUpCal._adjustDate(inst,-1,'D');break;case 38:if(e.ctrlKey)popUpCal._adjustDate(inst,-7,'D');break;case 39:if(e.ctrlKey)popUpCal._adjustDate(inst,+1,'D');break;case 40:if(e.ctrlKey)popUpCal._adjustDate(inst,+7,'D');break;}}
-else if(e.keyCode==36&&e.ctrlKey){popUpCal.showFor(this);}},_doKeyPress:function(e){var inst=popUpCal._getInst(this._calId);var chr=String.fromCharCode(e.charCode==undefined?e.keyCode:e.charCode);return(chr<' '||chr==inst._get('dateFormat').charAt(3)||(chr>='0'&&chr<='9'));},_connectCalendar:function(target,inst){var $input=$(target);var appendText=inst._get('appendText');if(appendText){$input.after('<span class="calendar_append">'+appendText+'</span>');}
-var autoPopUp=inst._get('autoPopUp');if(autoPopUp=='focus'||autoPopUp=='both'){$input.focus(this.showFor);}
-if(autoPopUp=='button'||autoPopUp=='both'){var buttonText=inst._get('buttonText');var buttonImage=inst._get('buttonImage');var buttonImageOnly=inst._get('buttonImageOnly');var trigger=$(buttonImageOnly?'<img class="calendar_trigger" src="'+
-buttonImage+'" alt="'+buttonText+'" title="'+buttonText+'"/>':'<button type="button" class="calendar_trigger">'+(buttonImage!=''?'<img src="'+buttonImage+'" alt="'+buttonText+'" title="'+buttonText+'"/>':buttonText)+'</button>');$input.wrap('<span class="calendar_wrap"></span>').after(trigger);trigger.click(this.showFor);}
-$input.keydown(this._doKeyDown).keypress(this._doKeyPress);$input[0]._calId=inst._id;},_inlineCalendar:function(target,inst,defaultDate){$(target).append(inst._calendarDiv);target._calId=inst._id;var date=defaultDate;inst._selectedDay=date.getDate();inst._selectedMonth=date.getMonth();inst._selectedYear=date.getFullYear();popUpCal._adjustDate(inst);},dialogCalendar:function(dateText,onSelect,settings,pos){var inst=this._dialogInst;if(!inst){inst=this._dialogInst=new PopUpCalInstance({},false);this._dialogInput=$('<input type="text" size="1" style="position: absolute; top: -100px;"/>');this._dialogInput.keydown(this._doKeyDown);$('body').append(this._dialogInput);this._dialogInput[0]._calId=inst._id;}
-$.extend(inst._settings,settings||{});this._dialogInput.val(dateText);if(self.innerHeight){windowWidth=self.innerWidth;windowHeight=self.innerHeight;}else if(document.documentElement&&document.documentElement.clientHeight){windowWidth=document.documentElement.clientWidth;windowHeight=document.documentElement.clientHeight;}else if(document.body){windowWidth=document.body.clientWidth;windowHeight=document.body.clientHeight;}
-this._pos=pos||[(windowWidth/2)-100,(windowHeight/2)-100];this._dialogInput.css('left',this._pos[0]+'px').css('top',this._pos[1]+'px');inst._settings.onSelect=onSelect;this._inDialog=true;this._calendarDiv.addClass('calendar_dialog');this.showFor(this._dialogInput[0]);if($.blockUI){$.blockUI(this._calendarDiv);}},enableFor:function(inputs){inputs=(inputs.jquery?inputs:$(inputs));inputs.each(function(){this.disabled=false;$('../button.calendar_trigger',this).each(function(){this.disabled=false;});$('../img.calendar_trigger',this).css({opacity:'1.0',cursor:''});var $this=this;popUpCal._disabledInputs=$.map(popUpCal._disabledInputs,function(value){return(value==$this?null:value);});});},disableFor:function(inputs){inputs=(inputs.jquery?inputs:$(inputs));inputs.each(function(){this.disabled=true;$('../button.calendar_trigger',this).each(function(){this.disabled=true;});$('../img.calendar_trigger',this).css({opacity:'0.5',cursor:'default'});var $this=this;popUpCal._disabledInputs=$.map(popUpCal._disabledInputs,function(value){return(value==$this?null:value);});popUpCal._disabledInputs[popUpCal._disabledInputs.length]=this;});},reconfigureFor:function(control,settings){var inst=this._getInst(control._calId);if(inst){$.extend(inst._settings,settings||{});this._updateCalendar(inst);}},setDateFor:function(control,date){var inst=this._getInst(control._calId);if(inst){inst._setDate(date);}},getDateFor:function(control){var inst=this._getInst(control._calId);return(inst?inst._getDate():null);},showFor:function(target){var input=(target.nodeName&&target.nodeName.toLowerCase()=='input'?target:this);if(input.nodeName.toLowerCase()!='input'){input=$('input',input.parentNode)[0];}
-if(popUpCal._lastInput==input){return;}
-for(var i=0;i<popUpCal._disabledInputs.length;i++){if(popUpCal._disabledInputs[i]==input){return;}}
-var inst=popUpCal._getInst(input._calId);popUpCal.hideCalendar(inst,'');popUpCal._lastInput=input;inst._setDateFromField(input);if(popUpCal._inDialog){input.value='';}
-if(!popUpCal._pos){popUpCal._pos=popUpCal._findPos(input);popUpCal._pos[1]+=input.offsetHeight;}
-inst._calendarDiv.css('position',(popUpCal._inDialog&&$.blockUI?'static':'absolute')).css('left',popUpCal._pos[0]+'px').css('top',popUpCal._pos[1]+'px');popUpCal._pos=null;var fieldSettings=inst._get('fieldSettings');$.extend(inst._settings,(fieldSettings?fieldSettings(input):{}));popUpCal._showCalendar(inst);},_showCalendar:function(id){var inst=this._getInst(id);popUpCal._updateCalendar(inst);if(!inst._inline){var speed=inst._get('speed');inst._calendarDiv.show(speed,function(){popUpCal._popUpShowing=true;popUpCal._afterShow(inst);});if(speed==''){popUpCal._popUpShowing=true;popUpCal._afterShow(inst);}
-if(inst._input[0].type!='hidden'){inst._input[0].focus();}
-this._curInst=inst;}},_updateCalendar:function(inst){inst._calendarDiv.empty().append(inst._generateCalendar());if(inst._input&&inst._input!='hidden'){inst._input[0].focus();}},_afterShow:function(inst){if($.browser.msie){$('#calendar_cover').css({width:inst._calendarDiv[0].offsetWidth+4,height:inst._calendarDiv[0].offsetHeight+4});}},hideCalendar:function(id,speed){var inst=this._getInst(id);if(popUpCal._popUpShowing){speed=(speed!=null?speed:inst._get('speed'));inst._calendarDiv.hide(speed,function(){popUpCal._tidyDialog(inst);});if(speed==''){popUpCal._tidyDialog(inst);}
-popUpCal._popUpShowing=false;popUpCal._lastInput=null;inst._settings.prompt=null;if(popUpCal._inDialog){popUpCal._dialogInput.css('position','absolute').css('left','0px').css('top','-100px');if($.blockUI){$.unblockUI();$('body').append(this._calendarDiv);}}
-popUpCal._inDialog=false;}
-popUpCal._curInst=null;},_tidyDialog:function(inst){inst._calendarDiv.removeClass('calendar_dialog');$('.calendar_prompt',inst._calendarDiv).remove();},_checkExternalClick:function(event){if(!popUpCal._curInst){return;}
-var target=$(event.target);if((target.parents("#calendar_div").length==0)&&(target.attr('class')!='calendar_trigger')&&popUpCal._popUpShowing&&!(popUpCal._inDialog&&$.blockUI))
-{popUpCal.hideCalendar(popUpCal._curInst,'');}},_adjustDate:function(id,offset,period){var inst=this._getInst(id);inst._adjustDate(offset,period);this._updateCalendar(inst);},_gotoToday:function(id){var date=new Date();var inst=this._getInst(id);inst._selectedDay=date.getDate();inst._selectedMonth=date.getMonth();inst._selectedYear=date.getFullYear();this._adjustDate(inst);},_selectMonthYear:function(id,select,period){var inst=this._getInst(id);inst._selectingMonthYear=false;inst[period=='M'?'_selectedMonth':'_selectedYear']=select.options[select.selectedIndex].value-0;this._adjustDate(inst);},_clickMonthYear:function(id){var inst=this._getInst(id);if(inst._input&&inst._selectingMonthYear&&!$.browser.msie){inst._input[0].focus();}
-inst._selectingMonthYear=!inst._selectingMonthYear;},_changeFirstDay:function(id,a){var inst=this._getInst(id);var dayNames=inst._get('dayNames');var value=a.firstChild.nodeValue;for(var i=0;i<7;i++){if(dayNames[i]==value){inst._settings.firstDay=i;break;}}
-this._updateCalendar(inst);},_selectDay:function(id,td){var inst=this._getInst(id);inst._selectedDay=$("a",td).html();this._selectDate(id);},_clearDate:function(id){this._selectDate(id,'');},_selectDate:function(id,dateStr){var inst=this._getInst(id);dateStr=(dateStr!=null?dateStr:inst._formatDate());if(inst._input){inst._input.val(dateStr);}
-var onSelect=inst._get('onSelect');if(onSelect){onSelect(dateStr);}
-else{inst._input.trigger('change');}
-if(inst._inline){this._updateCalendar(inst);}
-else{this.hideCalendar(inst,inst._get('speed'));}},noWeekends:function(date){var day=date.getDay();return[(day>0&&day<6),''];},_findPos:function(obj){if(obj.type=='hidden'){obj=obj.nextSibling;}
-var curleft=curtop=0;if(obj.offsetParent){curleft=obj.offsetLeft;curtop=obj.offsetTop;while(obj=obj.offsetParent){var origcurleft=curleft;curleft+=obj.offsetLeft;if(curleft<0){curleft=origcurleft;}
-curtop+=obj.offsetTop;}}
-return[curleft,curtop];}});function PopUpCalInstance(settings,inline,defaultDate){this._id=popUpCal._register(this);this._selectedDay=0;this._selectedMonth=0;this._selectedYear=0;this._input=null;this._inline=inline;this._calendarDiv=(!inline?popUpCal._calendarDiv:$('<div id="calendar_div_'+this._id+'" class="calendar_inline"></div>'));if(inline){var date=defaultDate;this._currentDate=defaultDate;this._currentDay=date.getDate();this._currentMonth=date.getMonth();this._currentYear=date.getFullYear();}
-this._settings=$.extend({},settings||{});}
-$.extend(PopUpCalInstance.prototype,{_get:function(name){return(this._settings[name]!=null?this._settings[name]:popUpCal._defaults[name]);},_setDateFromField:function(input){this._input=$(input);var dateFormat=this._get('dateFormat');var currentDate=this._input.val().split(dateFormat.charAt(3));if(currentDate.length==3){this._currentDay=parseInt(currentDate[dateFormat.indexOf('D')],10);this._currentMonth=parseInt(currentDate[dateFormat.indexOf('M')],10)-1;this._currentYear=parseInt(currentDate[dateFormat.indexOf('Y')],10);}
-else{var date=new Date();this._currentDay=date.getDate();this._currentMonth=date.getMonth();this._currentYear=date.getFullYear();}
-this._selectedDay=this._currentDay;this._selectedMonth=this._currentMonth;this._selectedYear=this._currentYear;this._adjustDate();},_setDate:function(date){this._selectedDay=this._currentDay=date.getDate();this._selectedMonth=this._currentMonth=date.getMonth();this._selectedYear=this._currentYear=date.getFullYear();this._adjustDate();},_getDate:function(){return new Date(this._currentYear,this._currentMonth,this._currentDay);},_generateCalendar:function(){var today=this._currentDate;today=new Date(today.getFullYear(),today.getMonth(),today.getDate());var controls='<div class="calendar_control">'+'<a class="calendar_clear" onclick="popUpCal._clearDate('+this._id+');">'+
-this._get('clearText')+'</a>'+'<a class="calendar_close" onclick="popUpCal.hideCalendar('+this._id+');">'+
-this._get('closeText')+'</a></div>';var prompt=this._get('prompt');var closeAtTop=this._get('closeAtTop');var hideIfNoPrevNext=this._get('hideIfNoPrevNext');var html=(prompt?'<div class="calendar_prompt">'+prompt+'</div>':'')+
-(closeAtTop&&!this._inline?controls:'')+'<div class="calendar_links">'+
-(this._canAdjustMonth(-1)?'<a class="calendar_prev" '+'onclick="popUpCal._adjustDate('+this._id+', -1, \'M\');">'+this._get('prevText')+'</a>':(hideIfNoPrevNext?'':'<label class="calendar_prev">'+this._get('prevText')+'</label>'))+
-(this._isInRange(today)?'<a class="calendar_current" '+'onclick="popUpCal._gotoToday('+this._id+');">'+this._get('currentText')+'</a>':'')+
-(this._canAdjustMonth(+1)?'<a class="calendar_next" '+'onclick="popUpCal._adjustDate('+this._id+', +1, \'M\');">'+this._get('nextText')+'</a>':(hideIfNoPrevNext?'':'<label class="calendar_next">'+this._get('nextText')+'</label>'))+'</div><div class="calendar_header">';var minDate=this._get('minDate');var maxDate=this._get('maxDate');var monthNames=this._get('monthNames');if(!this._get('changeMonth')){html+=monthNames[this._selectedMonth]+'&nbsp;';}
-else{var inMinYear=(minDate&&minDate.getFullYear()==this._selectedYear);var inMaxYear=(maxDate&&maxDate.getFullYear()==this._selectedYear);html+='<select class="calendar_newMonth" '+'onchange="popUpCal._selectMonthYear('+this._id+', this, \'M\');" '+'onclick="popUpCal._clickMonthYear('+this._id+');">';for(var month=0;month<12;month++){if((!inMinYear||month>=minDate.getMonth())&&(!inMaxYear||month<=maxDate.getMonth())){html+='<option value="'+month+'"'+
-(month==this._selectedMonth?' selected="selected"':'')+'>'+monthNames[month]+'</option>';}}
-html+='</select>';}
-if(!this._get('changeYear')){html+=this._selectedYear;}
-else{var years=this._get('yearRange').split(':');var year=0;var endYear=0;if(years.length!=2){year=this._selectedYear-10;endYear=this._selectedYear+10;}
-else if(years[0].charAt(0)=='+'||years[0].charAt(0)=='-'){year=this._selectedYear+parseInt(years[0],10);endYear=this._selectedYear+parseInt(years[1],10);}
-else{year=parseInt(years[0],10);endYear=parseInt(years[1],10);}
-year=(minDate?Math.max(year,minDate.getFullYear()):year);endYear=(maxDate?Math.min(endYear,maxDate.getFullYear()):endYear);html+='<select class="calendar_newYear" onchange="popUpCal._selectMonthYear('+
-this._id+', this, \'Y\');" '+'onclick="popUpCal._clickMonthYear('+
-this._id+');">';for(;year<=endYear;year++){html+='<option value="'+year+'"'+
-(year==this._selectedYear?' selected="selected"':'')+'>'+year+'</option>';}
-html+='</select>';}
-html+='</div><table class="calendar" cellpadding="0" cellspacing="0"><thead>'+'<tr class="calendar_titleRow">';var firstDay=this._get('firstDay');var changeFirstDay=this._get('changeFirstDay');var dayNames=this._get('dayNames');for(var dow=0;dow<7;dow++){html+='<td>'+(!changeFirstDay?'':'<a onclick="popUpCal._changeFirstDay('+
-this._id+', this);">')+dayNames[(dow+firstDay)%7]+
-(changeFirstDay?'</a>':'')+'</td>';}
-html+='</tr></thead><tbody>';var daysInMonth=this._getDaysInMonth(this._selectedYear,this._selectedMonth);this._selectedDay=Math.min(this._selectedDay,daysInMonth);var leadDays=(this._getFirstDayOfMonth(this._selectedYear,this._selectedMonth)-firstDay+7)%7;var currentDate=new Date(this._currentYear,this._currentMonth,this._currentDay);var selectedDate=new Date(this._selectedYear,this._selectedMonth,this._selectedDay);var printDate=new Date(this._selectedYear,this._selectedMonth,1-leadDays);var numRows=Math.ceil((leadDays+daysInMonth)/7);var customDate=this._get('customDate');var showOtherMonths=this._get('showOtherMonths');for(var row=0;row<numRows;row++){html+='<tr class="calendar_daysRow">';for(var dow=0;dow<7;dow++){var customSettings=(customDate?customDate(printDate):[true,'']);var otherMonth=(printDate.getMonth()!=this._selectedMonth);var unselectable=otherMonth||!customSettings[0]||(minDate&&printDate<minDate)||(maxDate&&printDate>maxDate);html+='<td class="calendar_daysCell'+
-((dow+firstDay+6)%7>=5?' calendar_weekEndCell':'')+
-(otherMonth?' calendar_otherMonth':'')+
-(unselectable?' calendar_unselectable':'')+
-(!otherMonth||showOtherMonths?' '+customSettings[1]:'')+
-(printDate.getTime()==currentDate.getTime()?' calendar_currentDay':(printDate.getTime()==today.getTime()?' calendar_today':''))+'"'+
-(unselectable?'':' onmouseover="$(this).addClass(\'calendar_daysCellOver\');"'+' onmouseout="$(this).removeClass(\'calendar_daysCellOver\');"'+' onclick="popUpCal._selectDay('+this._id+', this);"')+'>'+
-(otherMonth?(showOtherMonths?printDate.getDate():'&nbsp;'):(unselectable?printDate.getDate():'<a>'+printDate.getDate()+'</a>'))+'</td>';printDate.setDate(printDate.getDate()+1);}
-html+='</tr>';}
-html+='</tbody></table>'+(!closeAtTop&&!this._inline?controls:'')+'<div style="clear: both;"></div>'+(!$.browser.msie?'':'<!--[if lte IE 6.5]><iframe src="javascript:false;" class="calendar_cover"></iframe><![endif]-->');return html;},_adjustDate:function(offset,period){var date=new Date(this._selectedYear+(period=='Y'?offset:0),this._selectedMonth+(period=='M'?offset:0),this._selectedDay+(period=='D'?offset:0));var minDate=this._get('minDate');var maxDate=this._get('maxDate');date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);this._selectedDay=date.getDate();this._selectedMonth=date.getMonth();this._selectedYear=date.getFullYear();},_getDaysInMonth:function(year,month){return 32-new Date(year,month,32).getDate();},_getFirstDayOfMonth:function(year,month){return new Date(year,month,1).getDay();},_canAdjustMonth:function(offset){var date=new Date(this._selectedYear,this._selectedMonth+offset,1);if(offset<0){date.setDate(this._getDaysInMonth(date.getFullYear(),date.getMonth()));}
-return this._isInRange(date);},_isInRange:function(date){var minDate=this._get('minDate');var maxDate=this._get('maxDate');return((!minDate||date>=minDate)&&(!maxDate||date<=maxDate));},_formatDate:function(){var day=this._currentDay=this._selectedDay;var month=this._currentMonth=this._selectedMonth;var year=this._currentYear=this._selectedYear;month++;var dateFormat=this._get('dateFormat');var dateString='';for(var i=0;i<3;i++){dateString+=dateFormat.charAt(3)+
-(dateFormat.charAt(i)=='D'?(day<10?'0':'')+day:(dateFormat.charAt(i)=='M'?(month<10?'0':'')+month:(dateFormat.charAt(i)=='Y'?year:'?')));}
-return dateString.substring(dateFormat.charAt(3)?1:0);}});$.fn.calendar=function(settings,defaultDate){return this.each(function(){var inlineSettings=null;for(attrName in popUpCal._defaults){var attrValue=this.getAttribute('cal:'+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue);}
-catch(err){inlineSettings[attrName]=attrValue;}}}
-var nodeName=this.nodeName.toLowerCase();if(nodeName=='input'){var instSettings=(inlineSettings?$.extend($.extend({},settings||{}),inlineSettings||{}):settings);var inst=(inst&&!inlineSettings?inst:new PopUpCalInstance(instSettings,false,defaultDate));popUpCal._connectCalendar(this,inst);}
-else if(nodeName=='div'||nodeName=='span'){var instSettings=$.extend($.extend({},settings||{}),inlineSettings||{});var inst=new PopUpCalInstance(instSettings,true,defaultDate);popUpCal._inlineCalendar(this,inst,defaultDate);}});};$(document).ready(function(){popUpCal=new PopUpCal();});
diff --git a/libs/jquery/jquery-ui.js b/libs/jquery/jquery-ui.js
index 013c0364a9..4b7a52cddb 100644
--- a/libs/jquery/jquery-ui.js
+++ b/libs/jquery/jquery-ui.js
@@ -1,10 +1,393 @@
-/*
- * jQuery UI 1.7.2
+/*!
+ * jQuery UI 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI
*/
-jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla&&(parseFloat(c.browser.version)<1.9);c.ui={version:"1.7.2",plugin:{add:function(k,l,n){var m=c.ui[k].prototype;for(var j in n){m.plugins[j]=m.plugins[j]||[];m.plugins[j].push([l,n[j]])}},call:function(j,l,k){var n=j.plugins[l];if(!n||!j.element[0].parentNode){return}for(var m=0;m<n.length;m++){if(j.options[n[m][0]]){n[m][1].apply(j.element,k)}}}},contains:function(k,j){return document.compareDocumentPosition?k.compareDocumentPosition(j)&16:k!==j&&k.contains(j)},hasScroll:function(m,k){if(c(m).css("overflow")=="hidden"){return false}var j=(k&&k=="left")?"scrollLeft":"scrollTop",l=false;if(m[j]>0){return true}m[j]=1;l=(m[j]>0);m[j]=0;return l},isOverAxis:function(k,j,l){return(k>j)&&(k<(j+l))},isOver:function(o,k,n,m,j,l){return c.ui.isOverAxis(o,n,j)&&c.ui.isOverAxis(k,m,l)},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(d){var f=c.attr,e=c.fn.removeAttr,h="http://www.w3.org/2005/07/aaa",a=/^aria-/,b=/^wairole:/;c.attr=function(k,j,l){var m=l!==undefined;return(j=="role"?(m?f.call(this,k,j,"wairole:"+l):(f.apply(this,arguments)||"").replace(b,"")):(a.test(j)?(m?k.setAttributeNS(h,j.replace(a,"aaa:"),l):f.call(this,k,j.replace(a,"aaa:"))):f.apply(this,arguments)))};c.fn.removeAttr=function(j){return(a.test(j)?this.each(function(){this.removeAttributeNS(h,j.replace(a,""))}):e.call(this,j))}}c.fn.extend({remove:function(){c("*",this).add(this).each(function(){c(this).triggerHandler("remove")});return i.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","").unbind("selectstart.ui")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})},scrollParent:function(){var j;if((c.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){j=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(c.curCSS(this,"position",1))&&(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}else{j=this.parents().filter(function(){return(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!j.length?c(document):j}});c.extend(c.expr[":"],{data:function(l,k,j){return !!c.data(l,j[3])},focusable:function(k){var l=k.nodeName.toLowerCase(),j=c.attr(k,"tabindex");return(/input|select|textarea|button|object/.test(l)?!k.disabled:"a"==l||"area"==l?k.href||!isNaN(j):!isNaN(j))&&!c(k)["area"==l?"parents":"closest"](":hidden").length},tabbable:function(k){var j=c.attr(k,"tabindex");return(isNaN(j)||j>=0)&&c(k).is(":focusable")}});function g(m,n,o,l){function k(q){var p=c[m][n][q]||[];return(typeof p=="string"?p.split(/,?\s+/):p)}var j=k("getter");if(l.length==1&&typeof l[0]=="string"){j=j.concat(k("getterSetter"))}return(c.inArray(o,j)!=-1)}c.widget=function(k,j){var l=k.split(".")[0];k=k.split(".")[1];c.fn[k]=function(p){var n=(typeof p=="string"),o=Array.prototype.slice.call(arguments,1);if(n&&p.substring(0,1)=="_"){return this}if(n&&g(l,k,p,o)){var m=c.data(this[0],k);return(m?m[p].apply(m,o):undefined)}return this.each(function(){var q=c.data(this,k);(!q&&!n&&c.data(this,k,new c[l][k](this,p))._init());(q&&n&&c.isFunction(q[p])&&q[p].apply(q,o))})};c[l]=c[l]||{};c[l][k]=function(o,n){var m=this;this.namespace=l;this.widgetName=k;this.widgetEventPrefix=c[l][k].eventPrefix||k;this.widgetBaseClass=l+"-"+k;this.options=c.extend({},c.widget.defaults,c[l][k].defaults,c.metadata&&c.metadata.get(o)[k],n);this.element=c(o).bind("setData."+k,function(q,p,r){if(q.target==o){return m._setData(p,r)}}).bind("getData."+k,function(q,p){if(q.target==o){return m._getData(p)}}).bind("remove",function(){return m.destroy()})};c[l][k].prototype=c.extend({},c.widget.prototype,j);c[l][k].getterSetter="option"};c.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled")},option:function(l,m){var k=l,j=this;if(typeof l=="string"){if(m===undefined){return this._getData(l)}k={};k[l]=m}c.each(k,function(n,o){j._setData(n,o)})},_getData:function(j){return this.options[j]},_setData:function(j,k){this.options[j]=k;if(j=="disabled"){this.element[k?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",k)}},enable:function(){this._setData("disabled",false)},disable:function(){this._setData("disabled",true)},_trigger:function(l,m,n){var p=this.options[l],j=(l==this.widgetEventPrefix?l:this.widgetEventPrefix+l);m=c.Event(m);m.type=j;if(m.originalEvent){for(var k=c.event.props.length,o;k;){o=c.event.props[--k];m[o]=m.originalEvent[o]}}this.element.trigger(m,n);return !(c.isFunction(p)&&p.call(this.element[0],m,n)===false||m.isDefaultPrevented())}};c.widget.defaults={disabled:false};c.ui.mouse={_mouseInit:function(){var j=this;this.element.bind("mousedown."+this.widgetName,function(k){return j._mouseDown(k)}).bind("click."+this.widgetName,function(k){if(j._preventClickEvent){j._preventClickEvent=false;k.stopImmediatePropagation();return false}});if(c.browser.msie){this._mouseUnselectable=this.element.attr("unselectable");this.element.attr("unselectable","on")}this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);(c.browser.msie&&this.element.attr("unselectable",this._mouseUnselectable))},_mouseDown:function(l){l.originalEvent=l.originalEvent||{};if(l.originalEvent.mouseHandled){return}(this._mouseStarted&&this._mouseUp(l));this._mouseDownEvent=l;var k=this,m=(l.which==1),j=(typeof this.options.cancel=="string"?c(l.target).parents().add(l.target).filter(this.options.cancel).length:false);if(!m||j||!this._mouseCapture(l)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){k.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(l)&&this._mouseDelayMet(l)){this._mouseStarted=(this._mouseStart(l)!==false);if(!this._mouseStarted){l.preventDefault();return true}}this._mouseMoveDelegate=function(n){return k._mouseMove(n)};this._mouseUpDelegate=function(n){return k._mouseUp(n)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);(c.browser.safari||l.preventDefault());l.originalEvent.mouseHandled=true;return true},_mouseMove:function(j){if(c.browser.msie&&!j.button){return this._mouseUp(j)}if(this._mouseStarted){this._mouseDrag(j);return j.preventDefault()}if(this._mouseDistanceMet(j)&&this._mouseDelayMet(j)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,j)!==false);(this._mouseStarted?this._mouseDrag(j):this._mouseUp(j))}return !this._mouseStarted},_mouseUp:function(j){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(j.target==this._mouseDownEvent.target);this._mouseStop(j)}return false},_mouseDistanceMet:function(j){return(Math.max(Math.abs(this._mouseDownEvent.pageX-j.pageX),Math.abs(this._mouseDownEvent.pageY-j.pageY))>=this.options.distance)},_mouseDelayMet:function(j){return this.mouseDelayMet},_mouseStart:function(j){},_mouseDrag:function(j){},_mouseStop:function(j){},_mouseCapture:function(j){return true}};c.ui.mouse.defaults={cancel:null,distance:1,delay:0}})(jQuery);(function(a){a.widget("ui.draggable",a.extend({},a.ui.mouse,{_init:function(){if(this.options.helper=="original"&&!(/^(?:r|a|f)/).test(this.element.css("position"))){this.element[0].style.position="relative"}(this.options.addClasses&&this.element.addClass("ui-draggable"));(this.options.disabled&&this.element.addClass("ui-draggable-disabled"));this._mouseInit()},destroy:function(){if(!this.element.data("draggable")){return}this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy()},_mouseCapture:function(b){var c=this.options;if(this.helper||c.disabled||a(b.target).is(".ui-resizable-handle")){return false}this.handle=this._getHandle(b);if(!this.handle){return false}return true},_mouseStart:function(b){var c=this.options;this.helper=this._createHelper(b);this._cacheHelperProportions();if(a.ui.ddmanager){a.ui.ddmanager.current=this}this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(b);this.originalPageX=b.pageX;this.originalPageY=b.pageY;if(c.cursorAt){this._adjustOffsetFromHelper(c.cursorAt)}if(c.containment){this._setContainment()}this._trigger("start",b);this._cacheHelperProportions();if(a.ui.ddmanager&&!c.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,b)}this.helper.addClass("ui-draggable-dragging");this._mouseDrag(b,true);return true},_mouseDrag:function(b,d){this.position=this._generatePosition(b);this.positionAbs=this._convertPositionTo("absolute");if(!d){var c=this._uiHash();this._trigger("drag",b,c);this.position=c.position}if(!this.options.axis||this.options.axis!="y"){this.helper[0].style.left=this.position.left+"px"}if(!this.options.axis||this.options.axis!="x"){this.helper[0].style.top=this.position.top+"px"}if(a.ui.ddmanager){a.ui.ddmanager.drag(this,b)}return false},_mouseStop:function(c){var d=false;if(a.ui.ddmanager&&!this.options.dropBehaviour){d=a.ui.ddmanager.drop(this,c)}if(this.dropped){d=this.dropped;this.dropped=false}if((this.options.revert=="invalid"&&!d)||(this.options.revert=="valid"&&d)||this.options.revert===true||(a.isFunction(this.options.revert)&&this.options.revert.call(this.element,d))){var b=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){b._trigger("stop",c);b._clear()})}else{this._trigger("stop",c);this._clear()}return false},_getHandle:function(b){var c=!this.options.handle||!a(this.options.handle,this.element).length?true:false;a(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==b.target){c=true}});return c},_createHelper:function(c){var d=this.options;var b=a.isFunction(d.helper)?a(d.helper.apply(this.element[0],[c])):(d.helper=="clone"?this.element.clone():this.element);if(!b.parents("body").length){b.appendTo((d.appendTo=="parent"?this.element[0].parentNode:d.appendTo))}if(b[0]!=this.element[0]&&!(/(fixed|absolute)/).test(b.css("position"))){b.css("position","absolute")}return b},_adjustOffsetFromHelper:function(b){if(b.left!=undefined){this.offset.click.left=b.left+this.margins.left}if(b.right!=undefined){this.offset.click.left=this.helperProportions.width-b.right+this.margins.left}if(b.top!=undefined){this.offset.click.top=b.top+this.margins.top}if(b.bottom!=undefined){this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top}},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){b.left+=this.scrollParent.scrollLeft();b.top+=this.scrollParent.scrollTop()}if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)){b={top:0,left:0}}return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var b=this.element.position();return{top:b.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:b.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else{return{top:0,left:0}}},_cacheMargins:function(){this.margins={left:(parseInt(this.element.css("marginLeft"),10)||0),top:(parseInt(this.element.css("marginTop"),10)||0)}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e=this.options;if(e.containment=="parent"){e.containment=this.helper[0].parentNode}if(e.containment=="document"||e.containment=="window"){this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(e.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(e.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]}if(!(/^(document|window|parent)$/).test(e.containment)&&e.containment.constructor!=Array){var c=a(e.containment)[0];if(!c){return}var d=a(e.containment).offset();var b=(a(c).css("overflow")!="hidden");this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(b?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(b?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}else{if(e.containment.constructor==Array){this.containment=e.containment}}},_convertPositionTo:function(f,h){if(!h){h=this.position}var c=f=="absolute"?1:-1;var e=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=(/(html|body)/i).test(b[0].tagName);return{top:(h.top+this.offset.relative.top*c+this.offset.parent.top*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(g?0:b.scrollTop()))*c)),left:(h.left+this.offset.relative.left*c+this.offset.parent.left*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:b.scrollLeft())*c))}},_generatePosition:function(e){var h=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,i=(/(html|body)/i).test(b[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset()}var d=e.pageX;var c=e.pageY;if(this.originalPosition){if(this.containment){if(e.pageX-this.offset.click.left<this.containment[0]){d=this.containment[0]+this.offset.click.left}if(e.pageY-this.offset.click.top<this.containment[1]){c=this.containment[1]+this.offset.click.top}if(e.pageX-this.offset.click.left>this.containment[2]){d=this.containment[2]+this.offset.click.left}if(e.pageY-this.offset.click.top>this.containment[3]){c=this.containment[3]+this.offset.click.top}}if(h.grid){var g=this.originalPageY+Math.round((c-this.originalPageY)/h.grid[1])*h.grid[1];c=this.containment?(!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:(!(g-this.offset.click.top<this.containment[1])?g-h.grid[1]:g+h.grid[1])):g;var f=this.originalPageX+Math.round((d-this.originalPageX)/h.grid[0])*h.grid[0];d=this.containment?(!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:(!(f-this.offset.click.left<this.containment[0])?f-h.grid[0]:f+h.grid[0])):f}}return{top:(c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(i?0:b.scrollTop())))),left:(d-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:b.scrollLeft())))}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");if(this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval){this.helper.remove()}this.helper=null;this.cancelHelperRemoval=false},_trigger:function(b,c,d){d=d||this._uiHash();a.ui.plugin.call(this,b,[c,d]);if(b=="drag"){this.positionAbs=this._convertPositionTo("absolute")}return a.widget.prototype._trigger.call(this,b,c,d)},plugins:{},_uiHash:function(b){return{helper:this.helper,position:this.position,absolutePosition:this.positionAbs,offset:this.positionAbs}}}));a.extend(a.ui.draggable,{version:"1.7.2",eventPrefix:"drag",defaults:{addClasses:true,appendTo:"parent",axis:false,cancel:":input,option",connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false}});a.ui.plugin.add("draggable","connectToSortable",{start:function(c,e){var d=a(this).data("draggable"),f=d.options,b=a.extend({},e,{item:d.element});d.sortables=[];a(f.connectToSortable).each(function(){var g=a.data(this,"sortable");if(g&&!g.options.disabled){d.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",c,b)}})},stop:function(c,e){var d=a(this).data("draggable"),b=a.extend({},e,{item:d.element});a.each(d.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;d.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert){this.instance.options.revert=true}this.instance._mouseStop(c);this.instance.options.helper=this.instance.options._helper;if(d.options.helper=="original"){this.instance.currentItem.css({top:"auto",left:"auto"})}}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",c,b)}})},drag:function(c,f){var e=a(this).data("draggable"),b=this;var d=function(i){var n=this.offset.click.top,m=this.offset.click.left;var g=this.positionAbs.top,k=this.positionAbs.left;var j=i.height,l=i.width;var p=i.top,h=i.left;return a.ui.isOver(g+n,k+m,p,h,j,l)};a.each(e.sortables,function(g){this.instance.positionAbs=e.positionAbs;this.instance.helperProportions=e.helperProportions;this.instance.offset.click=e.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=a(b).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return f.helper[0]};c.target=this.instance.currentItem[0];this.instance._mouseCapture(c,true);this.instance._mouseStart(c,true,true);this.instance.offset.click.top=e.offset.click.top;this.instance.offset.click.left=e.offset.click.left;this.instance.offset.parent.left-=e.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=e.offset.parent.top-this.instance.offset.parent.top;e._trigger("toSortable",c);e.dropped=this.instance.element;e.currentItem=e.element;this.instance.fromOutside=e}if(this.instance.currentItem){this.instance._mouseDrag(c)}}else{if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",c,this.instance._uiHash(this.instance));this.instance._mouseStop(c,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();if(this.instance.placeholder){this.instance.placeholder.remove()}e._trigger("fromSortable",c);e.dropped=false}}})}});a.ui.plugin.add("draggable","cursor",{start:function(c,d){var b=a("body"),e=a(this).data("draggable").options;if(b.css("cursor")){e._cursor=b.css("cursor")}b.css("cursor",e.cursor)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._cursor){a("body").css("cursor",d._cursor)}}});a.ui.plugin.add("draggable","iframeFix",{start:function(b,c){var d=a(this).data("draggable").options;a(d.iframeFix===true?"iframe":d.iframeFix).each(function(){a('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1000}).css(a(this).offset()).appendTo("body")})},stop:function(b,c){a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});a.ui.plugin.add("draggable","opacity",{start:function(c,d){var b=a(d.helper),e=a(this).data("draggable").options;if(b.css("opacity")){e._opacity=b.css("opacity")}b.css("opacity",e.opacity)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._opacity){a(c.helper).css("opacity",d._opacity)}}});a.ui.plugin.add("draggable","scroll",{start:function(c,d){var b=a(this).data("draggable");if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!="HTML"){b.overflowOffset=b.scrollParent.offset()}},drag:function(d,e){var c=a(this).data("draggable"),f=c.options,b=false;if(c.scrollParent[0]!=document&&c.scrollParent[0].tagName!="HTML"){if(!f.axis||f.axis!="x"){if((c.overflowOffset.top+c.scrollParent[0].offsetHeight)-d.pageY<f.scrollSensitivity){c.scrollParent[0].scrollTop=b=c.scrollParent[0].scrollTop+f.scrollSpeed}else{if(d.pageY-c.overflowOffset.top<f.scrollSensitivity){c.scrollParent[0].scrollTop=b=c.scrollParent[0].scrollTop-f.scrollSpeed}}}if(!f.axis||f.axis!="y"){if((c.overflowOffset.left+c.scrollParent[0].offsetWidth)-d.pageX<f.scrollSensitivity){c.scrollParent[0].scrollLeft=b=c.scrollParent[0].scrollLeft+f.scrollSpeed}else{if(d.pageX-c.overflowOffset.left<f.scrollSensitivity){c.scrollParent[0].scrollLeft=b=c.scrollParent[0].scrollLeft-f.scrollSpeed}}}}else{if(!f.axis||f.axis!="x"){if(d.pageY-a(document).scrollTop()<f.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()-f.scrollSpeed)}else{if(a(window).height()-(d.pageY-a(document).scrollTop())<f.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()+f.scrollSpeed)}}}if(!f.axis||f.axis!="y"){if(d.pageX-a(document).scrollLeft()<f.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()-f.scrollSpeed)}else{if(a(window).width()-(d.pageX-a(document).scrollLeft())<f.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()+f.scrollSpeed)}}}}if(b!==false&&a.ui.ddmanager&&!f.dropBehaviour){a.ui.ddmanager.prepareOffsets(c,d)}}});a.ui.plugin.add("draggable","snap",{start:function(c,d){var b=a(this).data("draggable"),e=b.options;b.snapElements=[];a(e.snap.constructor!=String?(e.snap.items||":data(draggable)"):e.snap).each(function(){var g=a(this);var f=g.offset();if(this!=b.element[0]){b.snapElements.push({item:this,width:g.outerWidth(),height:g.outerHeight(),top:f.top,left:f.left})}})},drag:function(u,p){var g=a(this).data("draggable"),q=g.options;var y=q.snapTolerance;var x=p.offset.left,w=x+g.helperProportions.width,f=p.offset.top,e=f+g.helperProportions.height;for(var v=g.snapElements.length-1;v>=0;v--){var s=g.snapElements[v].left,n=s+g.snapElements[v].width,m=g.snapElements[v].top,A=m+g.snapElements[v].height;if(!((s-y<x&&x<n+y&&m-y<f&&f<A+y)||(s-y<x&&x<n+y&&m-y<e&&e<A+y)||(s-y<w&&w<n+y&&m-y<f&&f<A+y)||(s-y<w&&w<n+y&&m-y<e&&e<A+y))){if(g.snapElements[v].snapping){(g.options.snap.release&&g.options.snap.release.call(g.element,u,a.extend(g._uiHash(),{snapItem:g.snapElements[v].item})))}g.snapElements[v].snapping=false;continue}if(q.snapMode!="inner"){var c=Math.abs(m-e)<=y;var z=Math.abs(A-f)<=y;var j=Math.abs(s-w)<=y;var k=Math.abs(n-x)<=y;if(c){p.position.top=g._convertPositionTo("relative",{top:m-g.helperProportions.height,left:0}).top-g.margins.top}if(z){p.position.top=g._convertPositionTo("relative",{top:A,left:0}).top-g.margins.top}if(j){p.position.left=g._convertPositionTo("relative",{top:0,left:s-g.helperProportions.width}).left-g.margins.left}if(k){p.position.left=g._convertPositionTo("relative",{top:0,left:n}).left-g.margins.left}}var h=(c||z||j||k);if(q.snapMode!="outer"){var c=Math.abs(m-f)<=y;var z=Math.abs(A-e)<=y;var j=Math.abs(s-x)<=y;var k=Math.abs(n-w)<=y;if(c){p.position.top=g._convertPositionTo("relative",{top:m,left:0}).top-g.margins.top}if(z){p.position.top=g._convertPositionTo("relative",{top:A-g.helperProportions.height,left:0}).top-g.margins.top}if(j){p.position.left=g._convertPositionTo("relative",{top:0,left:s}).left-g.margins.left}if(k){p.position.left=g._convertPositionTo("relative",{top:0,left:n-g.helperProportions.width}).left-g.margins.left}}if(!g.snapElements[v].snapping&&(c||z||j||k||h)){(g.options.snap.snap&&g.options.snap.snap.call(g.element,u,a.extend(g._uiHash(),{snapItem:g.snapElements[v].item})))}g.snapElements[v].snapping=(c||z||j||k||h)}}});a.ui.plugin.add("draggable","stack",{start:function(b,c){var e=a(this).data("draggable").options;var d=a.makeArray(a(e.stack.group)).sort(function(g,f){return(parseInt(a(g).css("zIndex"),10)||e.stack.min)-(parseInt(a(f).css("zIndex"),10)||e.stack.min)});a(d).each(function(f){this.style.zIndex=e.stack.min+f});this[0].style.zIndex=e.stack.min+d.length}});a.ui.plugin.add("draggable","zIndex",{start:function(c,d){var b=a(d.helper),e=a(this).data("draggable").options;if(b.css("zIndex")){e._zIndex=b.css("zIndex")}b.css("zIndex",e.zIndex)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._zIndex){a(c.helper).css("zIndex",d._zIndex)}}})})(jQuery);(function(a){a.widget("ui.droppable",{_init:function(){var c=this.options,b=c.accept;this.isover=0;this.isout=1;this.options.accept=this.options.accept&&a.isFunction(this.options.accept)?this.options.accept:function(e){return e.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};a.ui.ddmanager.droppables[this.options.scope]=a.ui.ddmanager.droppables[this.options.scope]||[];a.ui.ddmanager.droppables[this.options.scope].push(this);(this.options.addClasses&&this.element.addClass("ui-droppable"))},destroy:function(){var b=a.ui.ddmanager.droppables[this.options.scope];for(var c=0;c<b.length;c++){if(b[c]==this){b.splice(c,1)}}this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable")},_setData:function(b,c){if(b=="accept"){this.options.accept=c&&a.isFunction(c)?c:function(e){return e.is(c)}}else{a.widget.prototype._setData.apply(this,arguments)}},_activate:function(c){var b=a.ui.ddmanager.current;if(this.options.activeClass){this.element.addClass(this.options.activeClass)}(b&&this._trigger("activate",c,this.ui(b)))},_deactivate:function(c){var b=a.ui.ddmanager.current;if(this.options.activeClass){this.element.removeClass(this.options.activeClass)}(b&&this._trigger("deactivate",c,this.ui(b)))},_over:function(c){var b=a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.hoverClass){this.element.addClass(this.options.hoverClass)}this._trigger("over",c,this.ui(b))}},_out:function(c){var b=a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.hoverClass){this.element.removeClass(this.options.hoverClass)}this._trigger("out",c,this.ui(b))}},_drop:function(c,d){var b=d||a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return false}var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var f=a.data(this,"droppable");if(f.options.greedy&&a.ui.intersect(b,a.extend(f,{offset:f.element.offset()}),f.options.tolerance)){e=true;return false}});if(e){return false}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.activeClass){this.element.removeClass(this.options.activeClass)}if(this.options.hoverClass){this.element.removeClass(this.options.hoverClass)}this._trigger("drop",c,this.ui(b));return this.element}return false},ui:function(b){return{draggable:(b.currentItem||b.element),helper:b.helper,position:b.position,absolutePosition:b.positionAbs,offset:b.positionAbs}}});a.extend(a.ui.droppable,{version:"1.7.2",eventPrefix:"drop",defaults:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"}});a.ui.intersect=function(q,j,o){if(!j.offset){return false}var e=(q.positionAbs||q.position.absolute).left,d=e+q.helperProportions.width,n=(q.positionAbs||q.position.absolute).top,m=n+q.helperProportions.height;var g=j.offset.left,c=g+j.proportions.width,p=j.offset.top,k=p+j.proportions.height;switch(o){case"fit":return(g<e&&d<c&&p<n&&m<k);break;case"intersect":return(g<e+(q.helperProportions.width/2)&&d-(q.helperProportions.width/2)<c&&p<n+(q.helperProportions.height/2)&&m-(q.helperProportions.height/2)<k);break;case"pointer":var h=((q.positionAbs||q.position.absolute).left+(q.clickOffset||q.offset.click).left),i=((q.positionAbs||q.position.absolute).top+(q.clickOffset||q.offset.click).top),f=a.ui.isOver(i,h,p,g,j.proportions.height,j.proportions.width);return f;break;case"touch":return((n>=p&&n<=k)||(m>=p&&m<=k)||(n<p&&m>k))&&((e>=g&&e<=c)||(d>=g&&d<=c)||(e<g&&d>c));break;default:return false;break}};a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,g){var b=a.ui.ddmanager.droppables[e.options.scope];var f=g?g.type:null;var h=(e.currentItem||e.element).find(":data(droppable)").andSelf();droppablesLoop:for(var d=0;d<b.length;d++){if(b[d].options.disabled||(e&&!b[d].options.accept.call(b[d].element[0],(e.currentItem||e.element)))){continue}for(var c=0;c<h.length;c++){if(h[c]==b[d].element[0]){b[d].proportions.height=0;continue droppablesLoop}}b[d].visible=b[d].element.css("display")!="none";if(!b[d].visible){continue}b[d].offset=b[d].element.offset();b[d].proportions={width:b[d].element[0].offsetWidth,height:b[d].element[0].offsetHeight};if(f=="mousedown"){b[d]._activate.call(b[d],g)}}},drop:function(b,c){var d=false;a.each(a.ui.ddmanager.droppables[b.options.scope],function(){if(!this.options){return}if(!this.options.disabled&&this.visible&&a.ui.intersect(b,this,this.options.tolerance)){d=this._drop.call(this,c)}if(!this.options.disabled&&this.visible&&this.options.accept.call(this.element[0],(b.currentItem||b.element))){this.isout=1;this.isover=0;this._deactivate.call(this,c)}});return d},drag:function(b,c){if(b.options.refreshPositions){a.ui.ddmanager.prepareOffsets(b,c)}a.each(a.ui.ddmanager.droppables[b.options.scope],function(){if(this.options.disabled||this.greedyChild||!this.visible){return}var e=a.ui.intersect(b,this,this.options.tolerance);var g=!e&&this.isover==1?"isout":(e&&this.isover==0?"isover":null);if(!g){return}var f;if(this.options.greedy){var d=this.element.parents(":data(droppable):eq(0)");if(d.length){f=a.data(d[0],"droppable");f.greedyChild=(g=="isover"?1:0)}}if(f&&g=="isover"){f.isover=0;f.isout=1;f._out.call(f,c)}this[g]=1;this[g=="isout"?"isover":"isout"]=0;this[g=="isover"?"_over":"_out"].call(this,c);if(f&&g=="isout"){f.isout=0;f.isover=1;f._over.call(f,c)}})}}})(jQuery);(function(c){c.widget("ui.resizable",c.extend({},c.ui.mouse,{_init:function(){var e=this,j=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(j.aspectRatio),aspectRatio:j.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:j.helper||j.ghost||j.animate?j.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){if(/relative/.test(this.element.css("position"))&&c.browser.opera){this.element.css({position:"relative",top:"auto",left:"auto"})}this.element.wrap(c('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=j.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var k=this.handles.split(",");this.handles={};for(var f=0;f<k.length;f++){var h=c.trim(k[f]),d="ui-resizable-"+h;var g=c('<div class="ui-resizable-handle '+d+'"></div>');if(/sw|se|ne|nw/.test(h)){g.css({zIndex:++j.zIndex})}if("se"==h){g.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[h]=".ui-resizable-"+h;this.element.append(g)}}this._renderAxis=function(p){p=p||this.element;for(var m in this.handles){if(this.handles[m].constructor==String){this.handles[m]=c(this.handles[m],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var n=c(this.handles[m],this.element),o=0;o=/sw|ne|nw|se|n|s/.test(m)?n.outerHeight():n.outerWidth();var l=["padding",/ne|nw|n/.test(m)?"Top":/se|sw|s/.test(m)?"Bottom":/^e$/.test(m)?"Right":"Left"].join("");p.css(l,o);this._proportionallyResize()}if(!c(this.handles[m]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!e.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}e.axis=i&&i[1]?i[1]:"se"}});if(j.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){c(this).removeClass("ui-resizable-autohide");e._handles.show()},function(){if(!e.resizing){c(this).addClass("ui-resizable-autohide");e._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var d=function(f){c(f).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){d(this.element);var e=this.element;e.parent().append(this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")})).end().remove()}this.originalElement.css("resize",this.originalResizeStyle);d(this.originalElement)},_mouseCapture:function(e){var f=false;for(var d in this.handles){if(c(this.handles[d])[0]==e.target){f=true}}return this.options.disabled||!!f},_mouseStart:function(f){var i=this.options,e=this.element.position(),d=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(d.is(".ui-draggable")||(/absolute/).test(d.css("position"))){d.css({position:"absolute",top:e.top,left:e.left})}if(c.browser.opera&&(/relative/).test(d.css("position"))){d.css({position:"relative",top:"auto",left:"auto"})}this._renderProxy();var j=b(this.helper.css("left")),g=b(this.helper.css("top"));if(i.containment){j+=c(i.containment).scrollLeft()||0;g+=c(i.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:j,top:g};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:j,top:g};this.sizeDiff={width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:f.pageX,top:f.pageY};this.aspectRatio=(typeof i.aspectRatio=="number")?i.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var h=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",h=="auto"?this.axis+"-resize":h);d.addClass("ui-resizable-resizing");this._propagate("start",f);return true},_mouseDrag:function(d){var g=this.helper,f=this.options,l={},p=this,i=this.originalMousePosition,m=this.axis;var q=(d.pageX-i.left)||0,n=(d.pageY-i.top)||0;var h=this._change[m];if(!h){return false}var k=h.apply(this,[d,q,n]),j=c.browser.msie&&c.browser.version<7,e=this.sizeDiff;if(this._aspectRatio||d.shiftKey){k=this._updateRatio(k,d)}k=this._respectSize(k,d);this._propagate("resize",d);g.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(k);this._trigger("resize",d,this.ui());return false},_mouseStop:function(g){this.resizing=false;var h=this.options,l=this;if(this._helper){var f=this._proportionallyResizeElements,d=f.length&&(/textarea/i).test(f[0].nodeName),e=d&&c.ui.hasScroll(f[0],"left")?0:l.sizeDiff.height,j=d?0:l.sizeDiff.width;var m={width:(l.size.width-j),height:(l.size.height-e)},i=(parseInt(l.element.css("left"),10)+(l.position.left-l.originalPosition.left))||null,k=(parseInt(l.element.css("top"),10)+(l.position.top-l.originalPosition.top))||null;if(!h.animate){this.element.css(c.extend(m,{top:k,left:i}))}l.helper.height(l.size.height);l.helper.width(l.size.width);if(this._helper&&!h.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",g);if(this._helper){this.helper.remove()}return false},_updateCache:function(d){var e=this.options;this.offset=this.helper.offset();if(a(d.left)){this.position.left=d.left}if(a(d.top)){this.position.top=d.top}if(a(d.height)){this.size.height=d.height}if(a(d.width)){this.size.width=d.width}},_updateRatio:function(g,f){var h=this.options,i=this.position,e=this.size,d=this.axis;if(g.height){g.width=(e.height*this.aspectRatio)}else{if(g.width){g.height=(e.width/this.aspectRatio)}}if(d=="sw"){g.left=i.left+(e.width-g.width);g.top=null}if(d=="nw"){g.top=i.top+(e.height-g.height);g.left=i.left+(e.width-g.width)}return g},_respectSize:function(k,f){var i=this.helper,h=this.options,q=this._aspectRatio||f.shiftKey,p=this.axis,s=a(k.width)&&h.maxWidth&&(h.maxWidth<k.width),l=a(k.height)&&h.maxHeight&&(h.maxHeight<k.height),g=a(k.width)&&h.minWidth&&(h.minWidth>k.width),r=a(k.height)&&h.minHeight&&(h.minHeight>k.height);if(g){k.width=h.minWidth}if(r){k.height=h.minHeight}if(s){k.width=h.maxWidth}if(l){k.height=h.maxHeight}var e=this.originalPosition.left+this.originalSize.width,n=this.position.top+this.size.height;var j=/sw|nw|w/.test(p),d=/nw|ne|n/.test(p);if(g&&j){k.left=e-h.minWidth}if(s&&j){k.left=e-h.maxWidth}if(r&&d){k.top=n-h.minHeight}if(l&&d){k.top=n-h.maxHeight}var m=!k.width&&!k.height;if(m&&!k.left&&k.top){k.top=null}else{if(m&&!k.top&&k.left){k.left=null}}return k},_proportionallyResize:function(){var j=this.options;if(!this._proportionallyResizeElements.length){return}var f=this.helper||this.element;for(var e=0;e<this._proportionallyResizeElements.length;e++){var g=this._proportionallyResizeElements[e];if(!this.borderDif){var d=[g.css("borderTopWidth"),g.css("borderRightWidth"),g.css("borderBottomWidth"),g.css("borderLeftWidth")],h=[g.css("paddingTop"),g.css("paddingRight"),g.css("paddingBottom"),g.css("paddingLeft")];this.borderDif=c.map(d,function(k,m){var l=parseInt(k,10)||0,n=parseInt(h[m],10)||0;return l+n})}if(c.browser.msie&&!(!(c(f).is(":hidden")||c(f).parents(":hidden").length))){continue}g.css({height:(f.height()-this.borderDif[0]-this.borderDif[2])||0,width:(f.width()-this.borderDif[1]-this.borderDif[3])||0})}},_renderProxy:function(){var e=this.element,h=this.options;this.elementOffset=e.offset();if(this._helper){this.helper=this.helper||c('<div style="overflow:hidden;"></div>');var d=c.browser.msie&&c.browser.version<7,f=(d?1:0),g=(d?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+g,height:this.element.outerHeight()+g,position:"absolute",left:this.elementOffset.left-f+"px",top:this.elementOffset.top-f+"px",zIndex:++h.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(f,e,d){return{width:this.originalSize.width+e}},w:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{left:h.left+e,width:f.width-e}},n:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{top:h.top+d,height:f.height-d}},s:function(f,e,d){return{height:this.originalSize.height+d}},se:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},sw:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[f,e,d]))},ne:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},nw:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[f,e,d]))}},_propagate:function(e,d){c.ui.plugin.call(this,e,[d,this.ui()]);(e!="resize"&&this._trigger(e,d,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}));c.extend(c.ui.resizable,{version:"1.7.2",eventPrefix:"resize",defaults:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,cancel:":input,option",containment:false,delay:0,distance:1,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000}});c.ui.plugin.add("resizable","alsoResize",{start:function(e,f){var d=c(this).data("resizable"),g=d.options;_store=function(h){c(h).each(function(){c(this).data("resizable-alsoresize",{width:parseInt(c(this).width(),10),height:parseInt(c(this).height(),10),left:parseInt(c(this).css("left"),10),top:parseInt(c(this).css("top"),10)})})};if(typeof(g.alsoResize)=="object"&&!g.alsoResize.parentNode){if(g.alsoResize.length){g.alsoResize=g.alsoResize[0];_store(g.alsoResize)}else{c.each(g.alsoResize,function(h,i){_store(h)})}}else{_store(g.alsoResize)}},resize:function(f,h){var e=c(this).data("resizable"),i=e.options,g=e.originalSize,k=e.originalPosition;var j={height:(e.size.height-g.height)||0,width:(e.size.width-g.width)||0,top:(e.position.top-k.top)||0,left:(e.position.left-k.left)||0},d=function(l,m){c(l).each(function(){var p=c(this),q=c(this).data("resizable-alsoresize"),o={},n=m&&m.length?m:["width","height","top","left"];c.each(n||["width","height","top","left"],function(r,u){var s=(q[u]||0)+(j[u]||0);if(s&&s>=0){o[u]=s||null}});if(/relative/.test(p.css("position"))&&c.browser.opera){e._revertToRelativePosition=true;p.css({position:"absolute",top:"auto",left:"auto"})}p.css(o)})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.nodeType){c.each(i.alsoResize,function(l,m){d(l,m)})}else{d(i.alsoResize)}},stop:function(e,f){var d=c(this).data("resizable");if(d._revertToRelativePosition&&c.browser.opera){d._revertToRelativePosition=false;el.css({position:"relative"})}c(this).removeData("resizable-alsoresize-start")}});c.ui.plugin.add("resizable","animate",{stop:function(h,m){var n=c(this).data("resizable"),i=n.options;var g=n._proportionallyResizeElements,d=g.length&&(/textarea/i).test(g[0].nodeName),e=d&&c.ui.hasScroll(g[0],"left")?0:n.sizeDiff.height,k=d?0:n.sizeDiff.width;var f={width:(n.size.width-k),height:(n.size.height-e)},j=(parseInt(n.element.css("left"),10)+(n.position.left-n.originalPosition.left))||null,l=(parseInt(n.element.css("top"),10)+(n.position.top-n.originalPosition.top))||null;n.element.animate(c.extend(f,l&&j?{top:l,left:j}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var o={width:parseInt(n.element.css("width"),10),height:parseInt(n.element.css("height"),10),top:parseInt(n.element.css("top"),10),left:parseInt(n.element.css("left"),10)};if(g&&g.length){c(g[0]).css({width:o.width,height:o.height})}n._updateCache(o);n._propagate("resize",h)}})}});c.ui.plugin.add("resizable","containment",{start:function(e,q){var s=c(this).data("resizable"),i=s.options,k=s.element;var f=i.containment,j=(f instanceof c)?f.get(0):(/parent/.test(f))?k.parent().get(0):f;if(!j){return}s.containerElement=c(j);if(/document/.test(f)||f==document){s.containerOffset={left:0,top:0};s.containerPosition={left:0,top:0};s.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var m=c(j),h=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){h[p]=b(m.css("padding"+o))});s.containerOffset=m.offset();s.containerPosition=m.position();s.containerSize={height:(m.innerHeight()-h[3]),width:(m.innerWidth()-h[1])};var n=s.containerOffset,d=s.containerSize.height,l=s.containerSize.width,g=(c.ui.hasScroll(j,"left")?j.scrollWidth:l),r=(c.ui.hasScroll(j)?j.scrollHeight:d);s.parentData={element:j,left:n.left,top:n.top,width:g,height:r}}},resize:function(f,p){var s=c(this).data("resizable"),h=s.options,e=s.containerSize,n=s.containerOffset,l=s.size,m=s.position,q=s._aspectRatio||f.shiftKey,d={top:0,left:0},g=s.containerElement;if(g[0]!=document&&(/static/).test(g.css("position"))){d=n}if(m.left<(s._helper?n.left:0)){s.size.width=s.size.width+(s._helper?(s.position.left-n.left):(s.position.left-d.left));if(q){s.size.height=s.size.width/h.aspectRatio}s.position.left=h.helper?n.left:0}if(m.top<(s._helper?n.top:0)){s.size.height=s.size.height+(s._helper?(s.position.top-n.top):s.position.top);if(q){s.size.width=s.size.height*h.aspectRatio}s.position.top=s._helper?n.top:0}s.offset.left=s.parentData.left+s.position.left;s.offset.top=s.parentData.top+s.position.top;var k=Math.abs((s._helper?s.offset.left-d.left:(s.offset.left-d.left))+s.sizeDiff.width),r=Math.abs((s._helper?s.offset.top-d.top:(s.offset.top-n.top))+s.sizeDiff.height);var j=s.containerElement.get(0)==s.element.parent().get(0),i=/relative|absolute/.test(s.containerElement.css("position"));if(j&&i){k-=s.parentData.left}if(k+s.size.width>=s.parentData.width){s.size.width=s.parentData.width-k;if(q){s.size.height=s.size.width/s.aspectRatio}}if(r+s.size.height>=s.parentData.height){s.size.height=s.parentData.height-r;if(q){s.size.width=s.size.height*s.aspectRatio}}},stop:function(e,m){var p=c(this).data("resizable"),f=p.options,k=p.position,l=p.containerOffset,d=p.containerPosition,g=p.containerElement;var i=c(p.helper),q=i.offset(),n=i.outerWidth()-p.sizeDiff.width,j=i.outerHeight()-p.sizeDiff.height;if(p._helper&&!f.animate&&(/relative/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}if(p._helper&&!f.animate&&(/static/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}}});c.ui.plugin.add("resizable","ghost",{start:function(f,g){var d=c(this).data("resizable"),h=d.options,e=d.size;d.ghost=d.originalElement.clone();d.ghost.css({opacity:0.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof h.ghost=="string"?h.ghost:"");d.ghost.appendTo(d.helper)},resize:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost){d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})}},stop:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost&&d.helper){d.helper.get(0).removeChild(d.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(d,l){var n=c(this).data("resizable"),g=n.options,j=n.size,h=n.originalSize,i=n.originalPosition,m=n.axis,k=g._aspectRatio||d.shiftKey;g.grid=typeof g.grid=="number"?[g.grid,g.grid]:g.grid;var f=Math.round((j.width-h.width)/(g.grid[0]||1))*(g.grid[0]||1),e=Math.round((j.height-h.height)/(g.grid[1]||1))*(g.grid[1]||1);if(/^(se|s|e)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e}else{if(/^(ne)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e}else{if(/^(sw)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.left=i.left-f}else{n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e;n.position.left=i.left-f}}}}});var b=function(d){return parseInt(d,10)||0};var a=function(d){return !isNaN(parseInt(d,10))}})(jQuery);(function(a){a.widget("ui.selectable",a.extend({},a.ui.mouse,{_init:function(){var b=this;this.element.addClass("ui-selectable");this.dragged=false;var c;this.refresh=function(){c=a(b.options.filter,b.element[0]);c.each(function(){var d=a(this);var e=d.offset();a.data(this,"selectable-item",{element:this,$element:d,left:e.left,top:e.top,right:e.left+d.outerWidth(),bottom:e.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"),selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=c.addClass("ui-selectee");this._mouseInit();this.helper=a(document.createElement("div")).css({border:"1px dotted black"}).addClass("ui-selectable-helper")},destroy:function(){this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy()},_mouseStart:function(d){var b=this;this.opos=[d.pageX,d.pageY];if(this.options.disabled){return}var c=this.options;this.selectees=a(c.filter,this.element[0]);this._trigger("start",d);a(c.appendTo).append(this.helper);this.helper.css({"z-index":100,position:"absolute",left:d.clientX,top:d.clientY,width:0,height:0});if(c.autoRefresh){this.refresh()}this.selectees.filter(".ui-selected").each(function(){var e=a.data(this,"selectable-item");e.startselected=true;if(!d.metaKey){e.$element.removeClass("ui-selected");e.selected=false;e.$element.addClass("ui-unselecting");e.unselecting=true;b._trigger("unselecting",d,{unselecting:e.element})}});a(d.target).parents().andSelf().each(function(){var e=a.data(this,"selectable-item");if(e){e.$element.removeClass("ui-unselecting").addClass("ui-selecting");e.unselecting=false;e.selecting=true;e.selected=true;b._trigger("selecting",d,{selecting:e.element});return false}})},_mouseDrag:function(i){var c=this;this.dragged=true;if(this.options.disabled){return}var e=this.options;var d=this.opos[0],h=this.opos[1],b=i.pageX,g=i.pageY;if(d>b){var f=b;b=d;d=f}if(h>g){var f=g;g=h;h=f}this.helper.css({left:d,top:h,width:b-d,height:g-h});this.selectees.each(function(){var j=a.data(this,"selectable-item");if(!j||j.element==c.element[0]){return}var k=false;if(e.tolerance=="touch"){k=(!(j.left>b||j.right<d||j.top>g||j.bottom<h))}else{if(e.tolerance=="fit"){k=(j.left>d&&j.right<b&&j.top>h&&j.bottom<g)}}if(k){if(j.selected){j.$element.removeClass("ui-selected");j.selected=false}if(j.unselecting){j.$element.removeClass("ui-unselecting");j.unselecting=false}if(!j.selecting){j.$element.addClass("ui-selecting");j.selecting=true;c._trigger("selecting",i,{selecting:j.element})}}else{if(j.selecting){if(i.metaKey&&j.startselected){j.$element.removeClass("ui-selecting");j.selecting=false;j.$element.addClass("ui-selected");j.selected=true}else{j.$element.removeClass("ui-selecting");j.selecting=false;if(j.startselected){j.$element.addClass("ui-unselecting");j.unselecting=true}c._trigger("unselecting",i,{unselecting:j.element})}}if(j.selected){if(!i.metaKey&&!j.startselected){j.$element.removeClass("ui-selected");j.selected=false;j.$element.addClass("ui-unselecting");j.unselecting=true;c._trigger("unselecting",i,{unselecting:j.element})}}}});return false},_mouseStop:function(d){var b=this;this.dragged=false;var c=this.options;a(".ui-unselecting",this.element[0]).each(function(){var e=a.data(this,"selectable-item");e.$element.removeClass("ui-unselecting");e.unselecting=false;e.startselected=false;b._trigger("unselected",d,{unselected:e.element})});a(".ui-selecting",this.element[0]).each(function(){var e=a.data(this,"selectable-item");e.$element.removeClass("ui-selecting").addClass("ui-selected");e.selecting=false;e.selected=true;e.startselected=true;b._trigger("selected",d,{selected:e.element})});this._trigger("stop",d);this.helper.remove();return false}}));a.extend(a.ui.selectable,{version:"1.7.2",defaults:{appendTo:"body",autoRefresh:true,cancel:":input,option",delay:0,distance:0,filter:"*",tolerance:"touch"}})})(jQuery);(function(a){a.widget("ui.sortable",a.extend({},a.ui.mouse,{_init:function(){var b=this.options;this.containerCache={};this.element.addClass("ui-sortable");this.refresh();this.floating=this.items.length?(/left|right/).test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--){this.items[b].item.removeData("sortable-item")}},_mouseCapture:function(e,f){if(this.reverting){return false}if(this.options.disabled||this.options.type=="static"){return false}this._refreshItems(e);var d=null,c=this,b=a(e.target).parents().each(function(){if(a.data(this,"sortable-item")==c){d=a(this);return false}});if(a.data(e.target,"sortable-item")==c){d=a(e.target)}if(!d){return false}if(this.options.handle&&!f){var g=false;a(this.options.handle,d).find("*").andSelf().each(function(){if(this==e.target){g=true}});if(!g){return false}}this.currentItem=d;this._removeCurrentsFromItems();return true},_mouseStart:function(e,f,b){var g=this.options,c=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(e);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");a.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(e);this.originalPageX=e.pageX;this.originalPageY=e.pageY;if(g.cursorAt){this._adjustOffsetFromHelper(g.cursorAt)}this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};if(this.helper[0]!=this.currentItem[0]){this.currentItem.hide()}this._createPlaceholder();if(g.containment){this._setContainment()}if(g.cursor){if(a("body").css("cursor")){this._storedCursor=a("body").css("cursor")}a("body").css("cursor",g.cursor)}if(g.opacity){if(this.helper.css("opacity")){this._storedOpacity=this.helper.css("opacity")}this.helper.css("opacity",g.opacity)}if(g.zIndex){if(this.helper.css("zIndex")){this._storedZIndex=this.helper.css("zIndex")}this.helper.css("zIndex",g.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){this.overflowOffset=this.scrollParent.offset()}this._trigger("start",e,this._uiHash());if(!this._preserveHelperProportions){this._cacheHelperProportions()}if(!b){for(var d=this.containers.length-1;d>=0;d--){this.containers[d]._trigger("activate",e,c._uiHash(this))}}if(a.ui.ddmanager){a.ui.ddmanager.current=this}if(a.ui.ddmanager&&!g.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,e)}this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(e);return true},_mouseDrag:function(f){this.position=this._generatePosition(f);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs){this.lastPositionAbs=this.positionAbs}if(this.options.scroll){var g=this.options,b=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if((this.overflowOffset.top+this.scrollParent[0].offsetHeight)-f.pageY<g.scrollSensitivity){this.scrollParent[0].scrollTop=b=this.scrollParent[0].scrollTop+g.scrollSpeed}else{if(f.pageY-this.overflowOffset.top<g.scrollSensitivity){this.scrollParent[0].scrollTop=b=this.scrollParent[0].scrollTop-g.scrollSpeed}}if((this.overflowOffset.left+this.scrollParent[0].offsetWidth)-f.pageX<g.scrollSensitivity){this.scrollParent[0].scrollLeft=b=this.scrollParent[0].scrollLeft+g.scrollSpeed}else{if(f.pageX-this.overflowOffset.left<g.scrollSensitivity){this.scrollParent[0].scrollLeft=b=this.scrollParent[0].scrollLeft-g.scrollSpeed}}}else{if(f.pageY-a(document).scrollTop()<g.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()-g.scrollSpeed)}else{if(a(window).height()-(f.pageY-a(document).scrollTop())<g.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()+g.scrollSpeed)}}if(f.pageX-a(document).scrollLeft()<g.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()-g.scrollSpeed)}else{if(a(window).width()-(f.pageX-a(document).scrollLeft())<g.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()+g.scrollSpeed)}}}if(b!==false&&a.ui.ddmanager&&!g.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,f)}}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y"){this.helper[0].style.left=this.position.left+"px"}if(!this.options.axis||this.options.axis!="x"){this.helper[0].style.top=this.position.top+"px"}for(var d=this.items.length-1;d>=0;d--){var e=this.items[d],c=e.item[0],h=this._intersectsWithPointer(e);if(!h){continue}if(c!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=c&&!a.ui.contains(this.placeholder[0],c)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],c):true)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(e)){this._rearrange(f,e)}else{break}this._trigger("change",f,this._uiHash());break}}this._contactContainers(f);if(a.ui.ddmanager){a.ui.ddmanager.drag(this,f)}this._trigger("sort",f,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(c,d){if(!c){return}if(a.ui.ddmanager&&!this.options.dropBehaviour){a.ui.ddmanager.drop(this,c)}if(this.options.revert){var b=this;var e=b.placeholder.offset();b.reverting=true;a(this.helper).animate({left:e.left-this.offset.parent.left-b.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-b.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){b._clear(c)})}else{this._clear(c,d)}return false},cancel:function(){var b=this;if(this.dragging){this._mouseUp();if(this.options.helper=="original"){this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else{this.currentItem.show()}for(var c=this.containers.length-1;c>=0;c--){this.containers[c]._trigger("deactivate",null,b._uiHash(this));if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",null,b._uiHash(this));this.containers[c].containerCache.over=0}}}if(this.placeholder[0].parentNode){this.placeholder[0].parentNode.removeChild(this.placeholder[0])}if(this.options.helper!="original"&&this.helper&&this.helper[0].parentNode){this.helper.remove()}a.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});if(this.domPosition.prev){a(this.domPosition.prev).after(this.currentItem)}else{a(this.domPosition.parent).prepend(this.currentItem)}return true},serialize:function(d){var b=this._getItemsAsjQuery(d&&d.connected);var c=[];d=d||{};a(b).each(function(){var e=(a(d.item||this).attr(d.attribute||"id")||"").match(d.expression||(/(.+)[-=_](.+)/));if(e){c.push((d.key||e[1]+"[]")+"="+(d.key&&d.expression?e[1]:e[2]))}});return c.join("&")},toArray:function(d){var b=this._getItemsAsjQuery(d&&d.connected);var c=[];d=d||{};b.each(function(){c.push(a(d.item||this).attr(d.attribute||"id")||"")});return c},_intersectsWith:function(m){var e=this.positionAbs.left,d=e+this.helperProportions.width,k=this.positionAbs.top,j=k+this.helperProportions.height;var f=m.left,c=f+m.width,n=m.top,i=n+m.height;var o=this.offset.click.top,h=this.offset.click.left;var g=(k+o)>n&&(k+o)<i&&(e+h)>f&&(e+h)<c;if(this.options.tolerance=="pointer"||this.options.forcePointerForContainers||(this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>m[this.floating?"width":"height"])){return g}else{return(f<e+(this.helperProportions.width/2)&&d-(this.helperProportions.width/2)<c&&n<k+(this.helperProportions.height/2)&&j-(this.helperProportions.height/2)<i)}},_intersectsWithPointer:function(d){var e=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,d.top,d.height),c=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,d.left,d.width),g=e&&c,b=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();if(!g){return false}return this.floating?(((f&&f=="right")||b=="down")?2:1):(b&&(b=="down"?2:1))},_intersectsWithSides:function(e){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,e.top+(e.height/2),e.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,e.left+(e.width/2),e.width),b=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();if(this.floating&&f){return((f=="right"&&d)||(f=="left"&&!d))}else{return b&&((b=="down"&&c)||(b=="up"&&!c))}},_getDragVerticalDirection:function(){var b=this.positionAbs.top-this.lastPositionAbs.top;return b!=0&&(b>0?"down":"up")},_getDragHorizontalDirection:function(){var b=this.positionAbs.left-this.lastPositionAbs.left;return b!=0&&(b>0?"right":"left")},refresh:function(b){this._refreshItems(b);this.refreshPositions()},_connectWith:function(){var b=this.options;return b.connectWith.constructor==String?[b.connectWith]:b.connectWith},_getItemsAsjQuery:function(b){var l=this;var g=[];var e=[];var h=this._connectWith();if(h&&b){for(var d=h.length-1;d>=0;d--){var k=a(h[d]);for(var c=k.length-1;c>=0;c--){var f=a.data(k[c],"sortable");if(f&&f!=this&&!f.options.disabled){e.push([a.isFunction(f.options.items)?f.options.items.call(f.element):a(f.options.items,f.element).not(".ui-sortable-helper"),f])}}}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper"),this]);for(var d=e.length-1;d>=0;d--){e[d][0].each(function(){g.push(this)})}return a(g)},_removeCurrentsFromItems:function(){var d=this.currentItem.find(":data(sortable-item)");for(var c=0;c<this.items.length;c++){for(var b=0;b<d.length;b++){if(d[b]==this.items[c].item[0]){this.items.splice(c,1)}}}},_refreshItems:function(b){this.items=[];this.containers=[this];var h=this.items;var p=this;var f=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],b,{item:this.currentItem}):a(this.options.items,this.element),this]];var l=this._connectWith();if(l){for(var e=l.length-1;e>=0;e--){var m=a(l[e]);for(var d=m.length-1;d>=0;d--){var g=a.data(m[d],"sortable");if(g&&g!=this&&!g.options.disabled){f.push([a.isFunction(g.options.items)?g.options.items.call(g.element[0],b,{item:this.currentItem}):a(g.options.items,g.element),g]);this.containers.push(g)}}}}for(var e=f.length-1;e>=0;e--){var k=f[e][1];var c=f[e][0];for(var d=0,n=c.length;d<n;d++){var o=a(c[d]);o.data("sortable-item",k);h.push({item:o,instance:k,width:0,height:0,left:0,top:0})}}},refreshPositions:function(b){if(this.offsetParent&&this.helper){this.offset.parent=this._getParentOffset()}for(var d=this.items.length-1;d>=0;d--){var e=this.items[d];if(e.instance!=this.currentContainer&&this.currentContainer&&e.item[0]!=this.currentItem[0]){continue}var c=this.options.toleranceElement?a(this.options.toleranceElement,e.item):e.item;if(!b){e.width=c.outerWidth();e.height=c.outerHeight()}var f=c.offset();e.left=f.left;e.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers){this.options.custom.refreshContainers.call(this)}else{for(var d=this.containers.length-1;d>=0;d--){var f=this.containers[d].element.offset();this.containers[d].containerCache.left=f.left;this.containers[d].containerCache.top=f.top;this.containers[d].containerCache.width=this.containers[d].element.outerWidth();this.containers[d].containerCache.height=this.containers[d].element.outerHeight()}}},_createPlaceholder:function(d){var b=d||this,e=b.options;if(!e.placeholder||e.placeholder.constructor==String){var c=e.placeholder;e.placeholder={element:function(){var f=a(document.createElement(b.currentItem[0].nodeName)).addClass(c||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!c){f.style.visibility="hidden"}return f},update:function(f,g){if(c&&!e.forcePlaceholderSize){return}if(!g.height()){g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10))}if(!g.width()){g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=a(e.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);e.placeholder.update(b,b.placeholder)},_contactContainers:function(d){for(var c=this.containers.length-1;c>=0;c--){if(this._intersectsWith(this.containers[c].containerCache)){if(!this.containers[c].containerCache.over){if(this.currentContainer!=this.containers[c]){var h=10000;var g=null;var e=this.positionAbs[this.containers[c].floating?"left":"top"];for(var b=this.items.length-1;b>=0;b--){if(!a.ui.contains(this.containers[c].element[0],this.items[b].item[0])){continue}var f=this.items[b][this.containers[c].floating?"left":"top"];if(Math.abs(f-e)<h){h=Math.abs(f-e);g=this.items[b]}}if(!g&&!this.options.dropOnEmpty){continue}this.currentContainer=this.containers[c];g?this._rearrange(d,g,null,true):this._rearrange(d,null,this.containers[c].element,true);this._trigger("change",d,this._uiHash());this.containers[c]._trigger("change",d,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder)}this.containers[c]._trigger("over",d,this._uiHash(this));this.containers[c].containerCache.over=1}}else{if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",d,this._uiHash(this));this.containers[c].containerCache.over=0}}}},_createHelper:function(c){var d=this.options;var b=a.isFunction(d.helper)?a(d.helper.apply(this.element[0],[c,this.currentItem])):(d.helper=="clone"?this.currentItem.clone():this.currentItem);if(!b.parents("body").length){a(d.appendTo!="parent"?d.appendTo:this.currentItem[0].parentNode)[0].appendChild(b[0])}if(b[0]==this.currentItem[0]){this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}}if(b[0].style.width==""||d.forceHelperSize){b.width(this.currentItem.width())}if(b[0].style.height==""||d.forceHelperSize){b.height(this.currentItem.height())}return b},_adjustOffsetFromHelper:function(b){if(b.left!=undefined){this.offset.click.left=b.left+this.margins.left}if(b.right!=undefined){this.offset.click.left=this.helperProportions.width-b.right+this.margins.left}if(b.top!=undefined){this.offset.click.top=b.top+this.margins.top}if(b.bottom!=undefined){this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top}},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){b.left+=this.scrollParent.scrollLeft();b.top+=this.scrollParent.scrollTop()}if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)){b={top:0,left:0}}return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var b=this.currentItem.position();return{top:b.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:b.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else{return{top:0,left:0}}},_cacheMargins:function(){this.margins={left:(parseInt(this.currentItem.css("marginLeft"),10)||0),top:(parseInt(this.currentItem.css("marginTop"),10)||0)}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e=this.options;if(e.containment=="parent"){e.containment=this.helper[0].parentNode}if(e.containment=="document"||e.containment=="window"){this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(e.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(e.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]}if(!(/^(document|window|parent)$/).test(e.containment)){var c=a(e.containment)[0];var d=a(e.containment).offset();var b=(a(c).css("overflow")!="hidden");this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(b?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(b?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(f,h){if(!h){h=this.position}var c=f=="absolute"?1:-1;var e=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=(/(html|body)/i).test(b[0].tagName);return{top:(h.top+this.offset.relative.top*c+this.offset.parent.top*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(g?0:b.scrollTop()))*c)),left:(h.left+this.offset.relative.left*c+this.offset.parent.left*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:b.scrollLeft())*c))}},_generatePosition:function(e){var h=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,i=(/(html|body)/i).test(b[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset()}var d=e.pageX;var c=e.pageY;if(this.originalPosition){if(this.containment){if(e.pageX-this.offset.click.left<this.containment[0]){d=this.containment[0]+this.offset.click.left}if(e.pageY-this.offset.click.top<this.containment[1]){c=this.containment[1]+this.offset.click.top}if(e.pageX-this.offset.click.left>this.containment[2]){d=this.containment[2]+this.offset.click.left}if(e.pageY-this.offset.click.top>this.containment[3]){c=this.containment[3]+this.offset.click.top}}if(h.grid){var g=this.originalPageY+Math.round((c-this.originalPageY)/h.grid[1])*h.grid[1];c=this.containment?(!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:(!(g-this.offset.click.top<this.containment[1])?g-h.grid[1]:g+h.grid[1])):g;var f=this.originalPageX+Math.round((d-this.originalPageX)/h.grid[0])*h.grid[0];d=this.containment?(!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:(!(f-this.offset.click.left<this.containment[0])?f-h.grid[0]:f+h.grid[0])):f}}return{top:(c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(i?0:b.scrollTop())))),left:(d-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:b.scrollLeft())))}},_rearrange:function(g,f,c,e){c?c[0].appendChild(this.placeholder[0]):f.item[0].parentNode.insertBefore(this.placeholder[0],(this.direction=="down"?f.item[0]:f.item[0].nextSibling));this.counter=this.counter?++this.counter:1;var d=this,b=this.counter;window.setTimeout(function(){if(b==d.counter){d.refreshPositions(!e)}},0)},_clear:function(d,e){this.reverting=false;var f=[],b=this;if(!this._noFinalSort&&this.currentItem[0].parentNode){this.placeholder.before(this.currentItem)}this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var c in this._storedCSS){if(this._storedCSS[c]=="auto"||this._storedCSS[c]=="static"){this._storedCSS[c]=""}}this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else{this.currentItem.show()}if(this.fromOutside&&!e){f.push(function(g){this._trigger("receive",g,this._uiHash(this.fromOutside))})}if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!e){f.push(function(g){this._trigger("update",g,this._uiHash())})}if(!a.ui.contains(this.element[0],this.currentItem[0])){if(!e){f.push(function(g){this._trigger("remove",g,this._uiHash())})}for(var c=this.containers.length-1;c>=0;c--){if(a.ui.contains(this.containers[c].element[0],this.currentItem[0])&&!e){f.push((function(g){return function(h){g._trigger("receive",h,this._uiHash(this))}}).call(this,this.containers[c]));f.push((function(g){return function(h){g._trigger("update",h,this._uiHash(this))}}).call(this,this.containers[c]))}}}for(var c=this.containers.length-1;c>=0;c--){if(!e){f.push((function(g){return function(h){g._trigger("deactivate",h,this._uiHash(this))}}).call(this,this.containers[c]))}if(this.containers[c].containerCache.over){f.push((function(g){return function(h){g._trigger("out",h,this._uiHash(this))}}).call(this,this.containers[c]));this.containers[c].containerCache.over=0}}if(this._storedCursor){a("body").css("cursor",this._storedCursor)}if(this._storedOpacity){this.helper.css("opacity",this._storedOpacity)}if(this._storedZIndex){this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex)}this.dragging=false;if(this.cancelHelperRemoval){if(!e){this._trigger("beforeStop",d,this._uiHash());for(var c=0;c<f.length;c++){f[c].call(this,d)}this._trigger("stop",d,this._uiHash())}return false}if(!e){this._trigger("beforeStop",d,this._uiHash())}this.placeholder[0].parentNode.removeChild(this.placeholder[0]);if(this.helper[0]!=this.currentItem[0]){this.helper.remove()}this.helper=null;if(!e){for(var c=0;c<f.length;c++){f[c].call(this,d)}this._trigger("stop",d,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){if(a.widget.prototype._trigger.apply(this,arguments)===false){this.cancel()}},_uiHash:function(c){var b=c||this;return{helper:b.helper,placeholder:b.placeholder||a([]),position:b.position,absolutePosition:b.positionAbs,offset:b.positionAbs,item:b.currentItem,sender:c?c.element:null}}}));a.extend(a.ui.sortable,{getter:"serialize toArray",version:"1.7.2",eventPrefix:"sort",defaults:{appendTo:"parent",axis:false,cancel:":input,option",connectWith:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1000}})})(jQuery);jQuery.effects||(function(d){d.effects={version:"1.7.2",save:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.data("ec.storage."+h[f],g[0].style[h[f]])}}},restore:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.css(h[f],g.data("ec.storage."+h[f]))}}},setMode:function(f,g){if(g=="toggle"){g=f.is(":hidden")?"show":"hide"}return g},getBaseline:function(g,h){var i,f;switch(g[0]){case"top":i=0;break;case"middle":i=0.5;break;case"bottom":i=1;break;default:i=g[0]/h.height}switch(g[1]){case"left":f=0;break;case"center":f=0.5;break;case"right":f=1;break;default:f=g[1]/h.width}return{x:f,y:i}},createWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent()}var g={width:f.outerWidth(true),height:f.outerHeight(true),"float":f.css("float")};f.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');var j=f.parent();if(f.css("position")=="static"){j.css({position:"relative"});f.css({position:"relative"})}else{var i=f.css("top");if(isNaN(parseInt(i,10))){i="auto"}var h=f.css("left");if(isNaN(parseInt(h,10))){h="auto"}j.css({position:f.css("position"),top:i,left:h,zIndex:f.css("z-index")}).show();f.css({position:"relative",top:0,left:0})}j.css(g);return j},removeWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent().replaceWith(f)}return f},setTransition:function(g,i,f,h){h=h||{};d.each(i,function(k,j){unit=g.cssUnit(j);if(unit[0]>0){h[j]=unit[0]*f+unit[1]}});return h},animateClass:function(h,i,k,j){var f=(typeof k=="function"?k:(j?j:null));var g=(typeof k=="string"?k:null);return this.each(function(){var q={};var o=d(this);var p=o.attr("style")||"";if(typeof p=="object"){p=p.cssText}if(h.toggle){o.hasClass(h.toggle)?h.remove=h.toggle:h.add=h.toggle}var l=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.addClass(h.add)}if(h.remove){o.removeClass(h.remove)}var m=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.removeClass(h.add)}if(h.remove){o.addClass(h.remove)}for(var r in m){if(typeof m[r]!="function"&&m[r]&&r.indexOf("Moz")==-1&&r.indexOf("length")==-1&&m[r]!=l[r]&&(r.match(/color/i)||(!r.match(/color/i)&&!isNaN(parseInt(m[r],10))))&&(l.position!="static"||(l.position=="static"&&!r.match(/left|top|bottom|right/)))){q[r]=m[r]}}o.animate(q,i,g,function(){if(typeof d(this).attr("style")=="object"){d(this).attr("style")["cssText"]="";d(this).attr("style")["cssText"]=p}else{d(this).attr("style",p)}if(h.add){d(this).addClass(h.add)}if(h.remove){d(this).removeClass(h.remove)}if(f){f.apply(this,arguments)}})})}};function c(g,f){var i=g[1]&&g[1].constructor==Object?g[1]:{};if(f){i.mode=f}var h=g[1]&&g[1].constructor!=Object?g[1]:(i.duration?i.duration:g[2]);h=d.fx.off?0:typeof h==="number"?h:d.fx.speeds[h]||d.fx.speeds._default;var j=i.callback||(d.isFunction(g[1])&&g[1])||(d.isFunction(g[2])&&g[2])||(d.isFunction(g[3])&&g[3]);return[g[0],i,h,j]}d.fn.extend({_show:d.fn.show,_hide:d.fn.hide,__toggle:d.fn.toggle,_addClass:d.fn.addClass,_removeClass:d.fn.removeClass,_toggleClass:d.fn.toggleClass,effect:function(g,f,h,i){return d.effects[g]?d.effects[g].call(this,{method:g,options:f||{},duration:h,callback:i}):null},show:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._show.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"show"))}},hide:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._hide.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"hide"))}},toggle:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))||(d.isFunction(arguments[0])||typeof arguments[0]=="boolean")){return this.__toggle.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"toggle"))}},addClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{add:g},f,i,h]):this._addClass(g)},removeClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{remove:g},f,i,h]):this._removeClass(g)},toggleClass:function(g,f,i,h){return((typeof f!=="boolean")&&f)?d.effects.animateClass.apply(this,[{toggle:g},f,i,h]):this._toggleClass(g,f)},morph:function(f,h,g,j,i){return d.effects.animateClass.apply(this,[{add:h,remove:f},g,j,i])},switchClass:function(){return this.morph.apply(this,arguments)},cssUnit:function(f){var g=this.css(f),h=[];d.each(["em","px","%","pt"],function(j,k){if(g.indexOf(k)>0){h=[parseFloat(g),k]}});return h}});d.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(g,f){d.fx.step[f]=function(h){if(h.state==0){h.start=e(h.elem,f);h.end=b(h.end)}h.elem.style[f]="rgb("+[Math.max(Math.min(parseInt((h.pos*(h.end[0]-h.start[0]))+h.start[0],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[1]-h.start[1]))+h.start[1],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[2]-h.start[2]))+h.start[2],10),255),0)].join(",")+")"}});function b(g){var f;if(g&&g.constructor==Array&&g.length==3){return g}if(f=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(g)){return[parseInt(f[1],10),parseInt(f[2],10),parseInt(f[3],10)]}if(f=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(g)){return[parseFloat(f[1])*2.55,parseFloat(f[2])*2.55,parseFloat(f[3])*2.55]}if(f=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(g)){return[parseInt(f[1],16),parseInt(f[2],16),parseInt(f[3],16)]}if(f=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(g)){return[parseInt(f[1]+f[1],16),parseInt(f[2]+f[2],16),parseInt(f[3]+f[3],16)]}if(f=/rgba\(0, 0, 0, 0\)/.exec(g)){return a.transparent}return a[d.trim(g).toLowerCase()]}function e(h,f){var g;do{g=d.curCSS(h,f);if(g!=""&&g!="transparent"||d.nodeName(h,"body")){break}f="backgroundColor"}while(h=h.parentNode);return b(g)}var a={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]};d.easing.jswing=d.easing.swing;d.extend(d.easing,{def:"easeOutQuad",swing:function(g,h,f,j,i){return d.easing[d.easing.def](g,h,f,j,i)},easeInQuad:function(g,h,f,j,i){return j*(h/=i)*h+f},easeOutQuad:function(g,h,f,j,i){return -j*(h/=i)*(h-2)+f},easeInOutQuad:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h+f}return -j/2*((--h)*(h-2)-1)+f},easeInCubic:function(g,h,f,j,i){return j*(h/=i)*h*h+f},easeOutCubic:function(g,h,f,j,i){return j*((h=h/i-1)*h*h+1)+f},easeInOutCubic:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h+f}return j/2*((h-=2)*h*h+2)+f},easeInQuart:function(g,h,f,j,i){return j*(h/=i)*h*h*h+f},easeOutQuart:function(g,h,f,j,i){return -j*((h=h/i-1)*h*h*h-1)+f},easeInOutQuart:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h+f}return -j/2*((h-=2)*h*h*h-2)+f},easeInQuint:function(g,h,f,j,i){return j*(h/=i)*h*h*h*h+f},easeOutQuint:function(g,h,f,j,i){return j*((h=h/i-1)*h*h*h*h+1)+f},easeInOutQuint:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h*h+f}return j/2*((h-=2)*h*h*h*h+2)+f},easeInSine:function(g,h,f,j,i){return -j*Math.cos(h/i*(Math.PI/2))+j+f},easeOutSine:function(g,h,f,j,i){return j*Math.sin(h/i*(Math.PI/2))+f},easeInOutSine:function(g,h,f,j,i){return -j/2*(Math.cos(Math.PI*h/i)-1)+f},easeInExpo:function(g,h,f,j,i){return(h==0)?f:j*Math.pow(2,10*(h/i-1))+f},easeOutExpo:function(g,h,f,j,i){return(h==i)?f+j:j*(-Math.pow(2,-10*h/i)+1)+f},easeInOutExpo:function(g,h,f,j,i){if(h==0){return f}if(h==i){return f+j}if((h/=i/2)<1){return j/2*Math.pow(2,10*(h-1))+f}return j/2*(-Math.pow(2,-10*--h)+2)+f},easeInCirc:function(g,h,f,j,i){return -j*(Math.sqrt(1-(h/=i)*h)-1)+f},easeOutCirc:function(g,h,f,j,i){return j*Math.sqrt(1-(h=h/i-1)*h)+f},easeInOutCirc:function(g,h,f,j,i){if((h/=i/2)<1){return -j/2*(Math.sqrt(1-h*h)-1)+f}return j/2*(Math.sqrt(1-(h-=2)*h)+1)+f},easeInElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return -(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f},easeOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return h*Math.pow(2,-10*i)*Math.sin((i*l-j)*(2*Math.PI)/k)+m+f},easeInOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l/2)==2){return f+m}if(!k){k=l*(0.3*1.5)}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}if(i<1){return -0.5*(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f}return h*Math.pow(2,-10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k)*0.5+m+f},easeInBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*(h/=j)*h*((i+1)*h-i)+f},easeOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*((h=h/j-1)*h*((i+1)*h+i)+1)+f},easeInOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}if((h/=j/2)<1){return k/2*(h*h*(((i*=(1.525))+1)*h-i))+f}return k/2*((h-=2)*h*(((i*=(1.525))+1)*h+i)+2)+f},easeInBounce:function(g,h,f,j,i){return j-d.easing.easeOutBounce(g,i-h,0,j,i)+f},easeOutBounce:function(g,h,f,j,i){if((h/=i)<(1/2.75)){return j*(7.5625*h*h)+f}else{if(h<(2/2.75)){return j*(7.5625*(h-=(1.5/2.75))*h+0.75)+f}else{if(h<(2.5/2.75)){return j*(7.5625*(h-=(2.25/2.75))*h+0.9375)+f}else{return j*(7.5625*(h-=(2.625/2.75))*h+0.984375)+f}}}},easeInOutBounce:function(g,h,f,j,i){if(h<i/2){return d.easing.easeInBounce(g,h*2,0,j,i)*0.5+f}return d.easing.easeOutBounce(g,h*2-i,0,j,i)*0.5+j*0.5+f}})})(jQuery);(function(a){a.effects.blind=function(b){return this.queue(function(){var d=a(this),c=["position","top","left"];var h=a.effects.setMode(d,b.options.mode||"hide");var g=b.options.direction||"vertical";a.effects.save(d,c);d.show();var j=a.effects.createWrapper(d).css({overflow:"hidden"});var e=(g=="vertical")?"height":"width";var i=(g=="vertical")?j.height():j.width();if(h=="show"){j.css(e,0)}var f={};f[e]=h=="show"?i:0;j.animate(f,b.duration,b.options.easing,function(){if(h=="hide"){d.hide()}a.effects.restore(d,c);a.effects.removeWrapper(d);if(b.callback){b.callback.apply(d[0],arguments)}d.dequeue()})})}})(jQuery);(function(a){a.effects.bounce=function(b){return this.queue(function(){var e=a(this),l=["position","top","left"];var k=a.effects.setMode(e,b.options.mode||"effect");var n=b.options.direction||"up";var c=b.options.distance||20;var d=b.options.times||5;var g=b.duration||250;if(/show|hide/.test(k)){l.push("opacity")}a.effects.save(e,l);e.show();a.effects.createWrapper(e);var f=(n=="up"||n=="down")?"top":"left";var p=(n=="up"||n=="left")?"pos":"neg";var c=b.options.distance||(f=="top"?e.outerHeight({margin:true})/3:e.outerWidth({margin:true})/3);if(k=="show"){e.css("opacity",0).css(f,p=="pos"?-c:c)}if(k=="hide"){c=c/(d*2)}if(k!="hide"){d--}if(k=="show"){var h={opacity:1};h[f]=(p=="pos"?"+=":"-=")+c;e.animate(h,g/2,b.options.easing);c=c/2;d--}for(var j=0;j<d;j++){var o={},m={};o[f]=(p=="pos"?"-=":"+=")+c;m[f]=(p=="pos"?"+=":"-=")+c;e.animate(o,g/2,b.options.easing).animate(m,g/2,b.options.easing);c=(k=="hide")?c*2:c/2}if(k=="hide"){var h={opacity:0};h[f]=(p=="pos"?"-=":"+=")+c;e.animate(h,g/2,b.options.easing,function(){e.hide();a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}})}else{var o={},m={};o[f]=(p=="pos"?"-=":"+=")+c;m[f]=(p=="pos"?"+=":"-=")+c;e.animate(o,g/2,b.options.easing).animate(m,g/2,b.options.easing,function(){a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}})}e.queue("fx",function(){e.dequeue()});e.dequeue()})}})(jQuery);(function(a){a.effects.clip=function(b){return this.queue(function(){var f=a(this),j=["position","top","left","height","width"];var i=a.effects.setMode(f,b.options.mode||"hide");var k=b.options.direction||"vertical";a.effects.save(f,j);f.show();var c=a.effects.createWrapper(f).css({overflow:"hidden"});var e=f[0].tagName=="IMG"?c:f;var g={size:(k=="vertical")?"height":"width",position:(k=="vertical")?"top":"left"};var d=(k=="vertical")?e.height():e.width();if(i=="show"){e.css(g.size,0);e.css(g.position,d/2)}var h={};h[g.size]=i=="show"?d:0;h[g.position]=i=="show"?0:d/2;e.animate(h,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){f.hide()}a.effects.restore(f,j);a.effects.removeWrapper(f);if(b.callback){b.callback.apply(f[0],arguments)}f.dequeue()}})})}})(jQuery);(function(a){a.effects.drop=function(b){return this.queue(function(){var e=a(this),d=["position","top","left","opacity"];var i=a.effects.setMode(e,b.options.mode||"hide");var h=b.options.direction||"left";a.effects.save(e,d);e.show();a.effects.createWrapper(e);var f=(h=="up"||h=="down")?"top":"left";var c=(h=="up"||h=="left")?"pos":"neg";var j=b.options.distance||(f=="top"?e.outerHeight({margin:true})/2:e.outerWidth({margin:true})/2);if(i=="show"){e.css("opacity",0).css(f,c=="pos"?-j:j)}var g={opacity:i=="show"?1:0};g[f]=(i=="show"?(c=="pos"?"+=":"-="):(c=="pos"?"-=":"+="))+j;e.animate(g,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){e.hide()}a.effects.restore(e,d);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);(function(a){a.effects.explode=function(b){return this.queue(function(){var k=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;var e=b.options.pieces?Math.round(Math.sqrt(b.options.pieces)):3;b.options.mode=b.options.mode=="toggle"?(a(this).is(":visible")?"hide":"show"):b.options.mode;var h=a(this).show().css("visibility","hidden");var l=h.offset();l.top-=parseInt(h.css("marginTop"),10)||0;l.left-=parseInt(h.css("marginLeft"),10)||0;var g=h.outerWidth(true);var c=h.outerHeight(true);for(var f=0;f<k;f++){for(var d=0;d<e;d++){h.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-d*(g/e),top:-f*(c/k)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:g/e,height:c/k,left:l.left+d*(g/e)+(b.options.mode=="show"?(d-Math.floor(e/2))*(g/e):0),top:l.top+f*(c/k)+(b.options.mode=="show"?(f-Math.floor(k/2))*(c/k):0),opacity:b.options.mode=="show"?0:1}).animate({left:l.left+d*(g/e)+(b.options.mode=="show"?0:(d-Math.floor(e/2))*(g/e)),top:l.top+f*(c/k)+(b.options.mode=="show"?0:(f-Math.floor(k/2))*(c/k)),opacity:b.options.mode=="show"?1:0},b.duration||500)}}setTimeout(function(){b.options.mode=="show"?h.css({visibility:"visible"}):h.css({visibility:"visible"}).hide();if(b.callback){b.callback.apply(h[0])}h.dequeue();a("div.ui-effects-explode").remove()},b.duration||500)})}})(jQuery);(function(a){a.effects.fold=function(b){return this.queue(function(){var e=a(this),k=["position","top","left"];var h=a.effects.setMode(e,b.options.mode||"hide");var o=b.options.size||15;var n=!(!b.options.horizFirst);var g=b.duration?b.duration/2:a.fx.speeds._default/2;a.effects.save(e,k);e.show();var d=a.effects.createWrapper(e).css({overflow:"hidden"});var i=((h=="show")!=n);var f=i?["width","height"]:["height","width"];var c=i?[d.width(),d.height()]:[d.height(),d.width()];var j=/([0-9]+)%/.exec(o);if(j){o=parseInt(j[1],10)/100*c[h=="hide"?0:1]}if(h=="show"){d.css(n?{height:0,width:o}:{height:o,width:0})}var m={},l={};m[f[0]]=h=="show"?c[0]:o;l[f[1]]=h=="show"?c[1]:0;d.animate(m,g,b.options.easing).animate(l,g,b.options.easing,function(){if(h=="hide"){e.hide()}a.effects.restore(e,k);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(e[0],arguments)}e.dequeue()})})}})(jQuery);(function(a){a.effects.highlight=function(b){return this.queue(function(){var e=a(this),d=["backgroundImage","backgroundColor","opacity"];var h=a.effects.setMode(e,b.options.mode||"show");var c=b.options.color||"#ffff99";var g=e.css("backgroundColor");a.effects.save(e,d);e.show();e.css({backgroundImage:"none",backgroundColor:c});var f={backgroundColor:g};if(h=="hide"){f.opacity=0}e.animate(f,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(h=="hide"){e.hide()}a.effects.restore(e,d);if(h=="show"&&a.browser.msie){this.style.removeAttribute("filter")}if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);(function(a){a.effects.pulsate=function(b){return this.queue(function(){var d=a(this);var g=a.effects.setMode(d,b.options.mode||"show");var f=b.options.times||5;var e=b.duration?b.duration/2:a.fx.speeds._default/2;if(g=="hide"){f--}if(d.is(":hidden")){d.css("opacity",0);d.show();d.animate({opacity:1},e,b.options.easing);f=f-2}for(var c=0;c<f;c++){d.animate({opacity:0},e,b.options.easing).animate({opacity:1},e,b.options.easing)}if(g=="hide"){d.animate({opacity:0},e,b.options.easing,function(){d.hide();if(b.callback){b.callback.apply(this,arguments)}})}else{d.animate({opacity:0},e,b.options.easing).animate({opacity:1},e,b.options.easing,function(){if(b.callback){b.callback.apply(this,arguments)}})}d.queue("fx",function(){d.dequeue()});d.dequeue()})}})(jQuery);(function(a){a.effects.puff=function(b){return this.queue(function(){var f=a(this);var c=a.extend(true,{},b.options);var h=a.effects.setMode(f,b.options.mode||"hide");var g=parseInt(b.options.percent,10)||150;c.fade=true;var e={height:f.height(),width:f.width()};var d=g/100;f.from=(h=="hide")?e:{height:e.height*d,width:e.width*d};c.from=f.from;c.percent=(h=="hide")?g:100;c.mode=h;f.effect("scale",c,b.duration,b.callback);f.dequeue()})};a.effects.scale=function(b){return this.queue(function(){var g=a(this);var d=a.extend(true,{},b.options);var j=a.effects.setMode(g,b.options.mode||"effect");var h=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:(j=="hide"?0:100));var i=b.options.direction||"both";var c=b.options.origin;if(j!="effect"){d.origin=c||["middle","center"];d.restore=true}var f={height:g.height(),width:g.width()};g.from=b.options.from||(j=="show"?{height:0,width:0}:f);var e={y:i!="horizontal"?(h/100):1,x:i!="vertical"?(h/100):1};g.to={height:f.height*e.y,width:f.width*e.x};if(b.options.fade){if(j=="show"){g.from.opacity=0;g.to.opacity=1}if(j=="hide"){g.from.opacity=1;g.to.opacity=0}}d.from=g.from;d.to=g.to;d.mode=j;g.effect("size",d,b.duration,b.callback);g.dequeue()})};a.effects.size=function(b){return this.queue(function(){var c=a(this),n=["position","top","left","width","height","overflow","opacity"];var m=["position","top","left","overflow","opacity"];var j=["width","height","overflow"];var p=["fontSize"];var k=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"];var f=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"];var g=a.effects.setMode(c,b.options.mode||"effect");var i=b.options.restore||false;var e=b.options.scale||"both";var o=b.options.origin;var d={height:c.height(),width:c.width()};c.from=b.options.from||d;c.to=b.options.to||d;if(o){var h=a.effects.getBaseline(o,d);c.from.top=(d.height-c.from.height)*h.y;c.from.left=(d.width-c.from.width)*h.x;c.to.top=(d.height-c.to.height)*h.y;c.to.left=(d.width-c.to.width)*h.x}var l={from:{y:c.from.height/d.height,x:c.from.width/d.width},to:{y:c.to.height/d.height,x:c.to.width/d.width}};if(e=="box"||e=="both"){if(l.from.y!=l.to.y){n=n.concat(k);c.from=a.effects.setTransition(c,k,l.from.y,c.from);c.to=a.effects.setTransition(c,k,l.to.y,c.to)}if(l.from.x!=l.to.x){n=n.concat(f);c.from=a.effects.setTransition(c,f,l.from.x,c.from);c.to=a.effects.setTransition(c,f,l.to.x,c.to)}}if(e=="content"||e=="both"){if(l.from.y!=l.to.y){n=n.concat(p);c.from=a.effects.setTransition(c,p,l.from.y,c.from);c.to=a.effects.setTransition(c,p,l.to.y,c.to)}}a.effects.save(c,i?n:m);c.show();a.effects.createWrapper(c);c.css("overflow","hidden").css(c.from);if(e=="content"||e=="both"){k=k.concat(["marginTop","marginBottom"]).concat(p);f=f.concat(["marginLeft","marginRight"]);j=n.concat(k).concat(f);c.find("*[width]").each(function(){child=a(this);if(i){a.effects.save(child,j)}var q={height:child.height(),width:child.width()};child.from={height:q.height*l.from.y,width:q.width*l.from.x};child.to={height:q.height*l.to.y,width:q.width*l.to.x};if(l.from.y!=l.to.y){child.from=a.effects.setTransition(child,k,l.from.y,child.from);child.to=a.effects.setTransition(child,k,l.to.y,child.to)}if(l.from.x!=l.to.x){child.from=a.effects.setTransition(child,f,l.from.x,child.from);child.to=a.effects.setTransition(child,f,l.to.x,child.to)}child.css(child.from);child.animate(child.to,b.duration,b.options.easing,function(){if(i){a.effects.restore(child,j)}})})}c.animate(c.to,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(g=="hide"){c.hide()}a.effects.restore(c,i?n:m);a.effects.removeWrapper(c);if(b.callback){b.callback.apply(this,arguments)}c.dequeue()}})})}})(jQuery);(function(a){a.effects.shake=function(b){return this.queue(function(){var e=a(this),l=["position","top","left"];var k=a.effects.setMode(e,b.options.mode||"effect");var n=b.options.direction||"left";var c=b.options.distance||20;var d=b.options.times||3;var g=b.duration||b.options.duration||140;a.effects.save(e,l);e.show();a.effects.createWrapper(e);var f=(n=="up"||n=="down")?"top":"left";var p=(n=="up"||n=="left")?"pos":"neg";var h={},o={},m={};h[f]=(p=="pos"?"-=":"+=")+c;o[f]=(p=="pos"?"+=":"-=")+c*2;m[f]=(p=="pos"?"-=":"+=")+c*2;e.animate(h,g,b.options.easing);for(var j=1;j<d;j++){e.animate(o,g,b.options.easing).animate(m,g,b.options.easing)}e.animate(o,g,b.options.easing).animate(h,g/2,b.options.easing,function(){a.effects.restore(e,l);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}});e.queue("fx",function(){e.dequeue()});e.dequeue()})}})(jQuery);(function(a){a.effects.slide=function(b){return this.queue(function(){var e=a(this),d=["position","top","left"];var i=a.effects.setMode(e,b.options.mode||"show");var h=b.options.direction||"left";a.effects.save(e,d);e.show();a.effects.createWrapper(e).css({overflow:"hidden"});var f=(h=="up"||h=="down")?"top":"left";var c=(h=="up"||h=="left")?"pos":"neg";var j=b.options.distance||(f=="top"?e.outerHeight({margin:true}):e.outerWidth({margin:true}));if(i=="show"){e.css(f,c=="pos"?-j:j)}var g={};g[f]=(i=="show"?(c=="pos"?"+=":"-="):(c=="pos"?"-=":"+="))+j;e.animate(g,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){e.hide()}a.effects.restore(e,d);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);(function(a){a.effects.transfer=function(b){return this.queue(function(){var f=a(this),h=a(b.options.to),e=h.offset(),g={top:e.top,left:e.left,height:h.innerHeight(),width:h.innerWidth()},d=f.offset(),c=a('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(b.options.className).css({top:d.top,left:d.left,height:f.innerHeight(),width:f.innerWidth(),position:"absolute"}).animate(g,b.duration,b.options.easing,function(){c.remove();(b.callback&&b.callback.apply(f[0],arguments));f.dequeue()})})}})(jQuery);(function(a){a.widget("ui.accordion",{_init:function(){var d=this.options,b=this;this.running=0;if(d.collapsible==a.ui.accordion.defaults.collapsible&&d.alwaysOpen!=a.ui.accordion.defaults.alwaysOpen){d.collapsible=!d.alwaysOpen}if(d.navigation){var c=this.element.find("a").filter(d.navigationFilter);if(c.length){if(c.filter(d.header).length){this.active=c}else{this.active=c.parent().parent().prev();c.addClass("ui-accordion-content-active")}}}this.element.addClass("ui-accordion ui-widget ui-helper-reset");if(this.element[0].nodeName=="UL"){this.element.children("li").addClass("ui-accordion-li-fix")}this.headers=this.element.find(d.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){a(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){a(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){a(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){a(this).removeClass("ui-state-focus")});this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");this.active=this._findActive(this.active||d.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass("ui-accordion-content-active");a("<span/>").addClass("ui-icon "+d.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(d.icons.header).toggleClass(d.icons.headerSelected);if(a.browser.msie){this.element.find("a").css("zoom","1")}this.resize();this.element.attr("role","tablist");this.headers.attr("role","tab").bind("keydown",function(e){return b._keydown(e)}).next().attr("role","tabpanel");this.headers.not(this.active||"").attr("aria-expanded","false").attr("tabIndex","-1").next().hide();if(!this.active.length){this.headers.eq(0).attr("tabIndex","0")}else{this.active.attr("aria-expanded","true").attr("tabIndex","0")}if(!a.browser.safari){this.headers.find("a").attr("tabIndex","-1")}if(d.event){this.headers.bind((d.event)+".accordion",function(e){return b._clickHandler.call(b,e,this)})}},destroy:function(){var c=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind(".accordion").removeData("accordion");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");this.headers.find("a").removeAttr("tabindex");this.headers.children(".ui-icon").remove();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(c.autoHeight||c.fillHeight){b.css("height","")}},_setData:function(b,c){if(b=="alwaysOpen"){b="collapsible";c=!c}a.widget.prototype._setData.apply(this,arguments)},_keydown:function(e){var g=this.options,f=a.ui.keyCode;if(g.disabled||e.altKey||e.ctrlKey){return}var d=this.headers.length;var b=this.headers.index(e.target);var c=false;switch(e.keyCode){case f.RIGHT:case f.DOWN:c=this.headers[(b+1)%d];break;case f.LEFT:case f.UP:c=this.headers[(b-1+d)%d];break;case f.SPACE:case f.ENTER:return this._clickHandler({target:e.target},e.target)}if(c){a(e.target).attr("tabIndex","-1");a(c).attr("tabIndex","0");c.focus();return false}return true},resize:function(){var e=this.options,d;if(e.fillSpace){if(a.browser.msie){var b=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}d=this.element.parent().height();if(a.browser.msie){this.element.parent().css("overflow",b)}this.headers.each(function(){d-=a(this).outerHeight()});var c=0;this.headers.next().each(function(){c=Math.max(c,a(this).innerHeight()-a(this).height())}).height(Math.max(0,d-c)).css("overflow","auto")}else{if(e.autoHeight){d=0;this.headers.next().each(function(){d=Math.max(d,a(this).outerHeight())}).height(d)}}},activate:function(b){var c=this._findActive(b)[0];this._clickHandler({target:c},c)},_findActive:function(b){return b?typeof b=="number"?this.headers.filter(":eq("+b+")"):this.headers.not(this.headers.not(b)):b===false?a([]):this.headers.filter(":eq(0)")},_clickHandler:function(b,f){var d=this.options;if(d.disabled){return false}if(!b.target&&d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");var h=this.active.next(),e={options:d,newHeader:a([]),oldHeader:d.active,newContent:a([]),oldContent:h},c=(this.active=a([]));this._toggle(c,h,e);return false}var g=a(b.currentTarget||f);var i=g[0]==this.active[0];if(this.running||(!d.collapsible&&i)){return false}this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");if(!i){g.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);g.next().addClass("ui-accordion-content-active")}var c=g.next(),h=this.active.next(),e={options:d,newHeader:i&&d.collapsible?a([]):g,oldHeader:this.active,newContent:i&&d.collapsible?a([]):c.find("> *"),oldContent:h.find("> *")},j=this.headers.index(this.active[0])>this.headers.index(g[0]);this.active=i?a([]):g;this._toggle(c,h,e,i,j);return false},_toggle:function(b,i,g,j,k){var d=this.options,m=this;this.toShow=b;this.toHide=i;this.data=g;var c=function(){if(!m){return}return m._completed.apply(m,arguments)};this._trigger("changestart",null,this.data);this.running=i.size()===0?b.size():i.size();if(d.animated){var f={};if(d.collapsible&&j){f={toShow:a([]),toHide:i,complete:c,down:k,autoHeight:d.autoHeight||d.fillSpace}}else{f={toShow:b,toHide:i,complete:c,down:k,autoHeight:d.autoHeight||d.fillSpace}}if(!d.proxied){d.proxied=d.animated}if(!d.proxiedDuration){d.proxiedDuration=d.duration}d.animated=a.isFunction(d.proxied)?d.proxied(f):d.proxied;d.duration=a.isFunction(d.proxiedDuration)?d.proxiedDuration(f):d.proxiedDuration;var l=a.ui.accordion.animations,e=d.duration,h=d.animated;if(!l[h]){l[h]=function(n){this.slide(n,{easing:h,duration:e||700})}}l[h](f)}else{if(d.collapsible&&j){b.toggle()}else{i.hide();b.show()}c(true)}i.prev().attr("aria-expanded","false").attr("tabIndex","-1").blur();b.prev().attr("aria-expanded","true").attr("tabIndex","0").focus()},_completed:function(b){var c=this.options;this.running=b?0:--this.running;if(this.running){return}if(c.clearStyle){this.toShow.add(this.toHide).css({height:"",overflow:""})}this._trigger("change",null,this.data)}});a.extend(a.ui.accordion,{version:"1.7.2",defaults:{active:null,alwaysOpen:true,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase()}},animations:{slide:function(j,h){j=a.extend({easing:"swing",duration:300},j,h);if(!j.toHide.size()){j.toShow.animate({height:"show"},j);return}if(!j.toShow.size()){j.toHide.animate({height:"hide"},j);return}var c=j.toShow.css("overflow"),g,d={},f={},e=["height","paddingTop","paddingBottom"],b;var i=j.toShow;b=i[0].style.width;i.width(parseInt(i.parent().width(),10)-parseInt(i.css("paddingLeft"),10)-parseInt(i.css("paddingRight"),10)-(parseInt(i.css("borderLeftWidth"),10)||0)-(parseInt(i.css("borderRightWidth"),10)||0));a.each(e,function(k,m){f[m]="hide";var l=(""+a.css(j.toShow[0],m)).match(/^([\d+-.]+)(.*)$/);d[m]={value:l[1],unit:l[2]||"px"}});j.toShow.css({height:0,overflow:"hidden"}).show();j.toHide.filter(":hidden").each(j.complete).end().filter(":visible").animate(f,{step:function(k,l){if(l.prop=="height"){g=(l.now-l.start)/(l.end-l.start)}j.toShow[0].style[l.prop]=(g*d[l.prop].value)+d[l.prop].unit},duration:j.duration,easing:j.easing,complete:function(){if(!j.autoHeight){j.toShow.css("height","")}j.toShow.css("width",b);j.toShow.css({overflow:c});j.complete()}})},bounceslide:function(b){this.slide(b,{easing:b.down?"easeOutBounce":"swing",duration:b.down?1000:200})},easeslide:function(b){this.slide(b,{easing:"easeinout",duration:700})}}})})(jQuery);(function($){$.extend($.ui,{datepicker:{version:"1.7.2"}});var PROP_NAME="datepicker";function Datepicker(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._datepickerShowing=false;this._inDialog=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass="ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],dateFormat:"mm/dd/yy",firstDay:0,isRTL:false};this._defaults={showOn:"focus",showAnim:"show",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,showMonthAfterYear:false,yearRange:"-10:+10",showOtherMonths:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"normal",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false};$.extend(this._defaults,this.regional[""]);this.dpDiv=$('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",log:function(){if(this.debug){console.log.apply("",arguments)}},setDefaults:function(settings){extendRemove(this._defaults,settings||{});return this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase();var inline=(nodeName=="div"||nodeName=="span");if(!target.id){target.id="dp"+(++this.uuid)}var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{});if(nodeName=="input"){this._connectDatepicker(target,inst)}else{if(inline){this._inlineDatepicker(target,inst)}}},_newInst:function(target,inline){var id=target[0].id.replace(/([:\[\]\.])/g,"\\\\$1");return{id:id,input:target,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:inline,dpDiv:(!inline?this.dpDiv:$('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}},_connectDatepicker:function(target,inst){var input=$(target);inst.append=$([]);inst.trigger=$([]);if(input.hasClass(this.markerClassName)){return}var appendText=this._get(inst,"appendText");var isRTL=this._get(inst,"isRTL");if(appendText){inst.append=$('<span class="'+this._appendClass+'">'+appendText+"</span>");input[isRTL?"before":"after"](inst.append)}var showOn=this._get(inst,"showOn");if(showOn=="focus"||showOn=="both"){input.focus(this._showDatepicker)}if(showOn=="button"||showOn=="both"){var buttonText=this._get(inst,"buttonText");var buttonImage=this._get(inst,"buttonImage");inst.trigger=$(this._get(inst,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:buttonImage,alt:buttonText,title:buttonText}):$('<button type="button"></button>').addClass(this._triggerClass).html(buttonImage==""?buttonText:$("<img/>").attr({src:buttonImage,alt:buttonText,title:buttonText})));input[isRTL?"before":"after"](inst.trigger);inst.trigger.click(function(){if($.datepicker._datepickerShowing&&$.datepicker._lastInput==target){$.datepicker._hideDatepicker()}else{$.datepicker._showDatepicker(target)}return false})}input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst)},_inlineDatepicker:function(target,inst){var divSpan=$(target);if(divSpan.hasClass(this.markerClassName)){return}divSpan.addClass(this.markerClassName).append(inst.dpDiv).bind("setData.datepicker",function(event,key,value){inst.settings[key]=value}).bind("getData.datepicker",function(event,key){return this._get(inst,key)});$.data(target,PROP_NAME,inst);this._setDate(inst,this._getDefaultDate(inst));this._updateDatepicker(inst);this._updateAlternate(inst)},_dialogDatepicker:function(input,dateText,onSelect,settings,pos){var inst=this._dialogInst;if(!inst){var id="dp"+(++this.uuid);this._dialogInput=$('<input type="text" id="'+id+'" size="1" style="position: absolute; top: -100px;"/>');this._dialogInput.keydown(this._doKeyDown);$("body").append(this._dialogInput);inst=this._dialogInst=this._newInst(this._dialogInput,false);inst.settings={};$.data(this._dialogInput[0],PROP_NAME,inst)}extendRemove(inst.settings,settings||{});this._dialogInput.val(dateText);this._pos=(pos?(pos.length?pos:[pos.pageX,pos.pageY]):null);if(!this._pos){var browserWidth=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;var browserHeight=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;var scrollX=document.documentElement.scrollLeft||document.body.scrollLeft;var scrollY=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[(browserWidth/2)-100+scrollX,(browserHeight/2)-150+scrollY]}this._dialogInput.css("left",this._pos[0]+"px").css("top",this._pos[1]+"px");inst.settings.onSelect=onSelect;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);if($.blockUI){$.blockUI(this.dpDiv)}$.data(this._dialogInput[0],PROP_NAME,inst);return this},_destroyDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();$.removeData(target,PROP_NAME);if(nodeName=="input"){inst.append.remove();inst.trigger.remove();$target.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress)}else{if(nodeName=="div"||nodeName=="span"){$target.removeClass(this.markerClassName).empty()}}},_enableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=false;inst.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().removeClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)})},_disableDatepicker:function(target){var $target=$(target);var inst=$.data(target,PROP_NAME);if(!$target.hasClass(this.markerClassName)){return}var nodeName=target.nodeName.toLowerCase();if(nodeName=="input"){target.disabled=true;inst.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else{if(nodeName=="div"||nodeName=="span"){var inline=$target.children("."+this._inlineClass);inline.children().addClass("ui-state-disabled")}}this._disabledInputs=$.map(this._disabledInputs,function(value){return(value==target?null:value)});this._disabledInputs[this._disabledInputs.length]=target},_isDisabledDatepicker:function(target){if(!target){return false}for(var i=0;i<this._disabledInputs.length;i++){if(this._disabledInputs[i]==target){return true}}return false},_getInst:function(target){try{return $.data(target,PROP_NAME)}catch(err){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(target,name,value){var inst=this._getInst(target);if(arguments.length==2&&typeof name=="string"){return(name=="defaults"?$.extend({},$.datepicker._defaults):(inst?(name=="all"?$.extend({},inst.settings):this._get(inst,name)):null))}var settings=name||{};if(typeof name=="string"){settings={};settings[name]=value}if(inst){if(this._curInst==inst){this._hideDatepicker(null)}var date=this._getDateDatepicker(target);extendRemove(inst.settings,settings);this._setDateDatepicker(target,date);this._updateDatepicker(inst)}},_changeDatepicker:function(target,name,value){this._optionDatepicker(target,name,value)},_refreshDatepicker:function(target){var inst=this._getInst(target);if(inst){this._updateDatepicker(inst)}},_setDateDatepicker:function(target,date,endDate){var inst=this._getInst(target);if(inst){this._setDate(inst,date,endDate);this._updateDatepicker(inst);this._updateAlternate(inst)}},_getDateDatepicker:function(target){var inst=this._getInst(target);if(inst&&!inst.inline){this._setDateFromField(inst)}return(inst?this._getDate(inst):null)},_doKeyDown:function(event){var inst=$.datepicker._getInst(event.target);var handled=true;var isRTL=inst.dpDiv.is(".ui-datepicker-rtl");inst._keyEvent=true;if($.datepicker._datepickerShowing){switch(event.keyCode){case 9:$.datepicker._hideDatepicker(null,"");break;case 13:var sel=$("td."+$.datepicker._dayOverClass+", td."+$.datepicker._currentClass,inst.dpDiv);if(sel[0]){$.datepicker._selectDay(event.target,inst.selectedMonth,inst.selectedYear,sel[0])}else{$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"))}return false;break;case 27:$.datepicker._hideDatepicker(null,$.datepicker._get(inst,"duration"));break;case 33:$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M");break;case 34:$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M");break;case 35:if(event.ctrlKey||event.metaKey){$.datepicker._clearDate(event.target)}handled=event.ctrlKey||event.metaKey;break;case 36:if(event.ctrlKey||event.metaKey){$.datepicker._gotoToday(event.target)}handled=event.ctrlKey||event.metaKey;break;case 37:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?+1:-1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?-$.datepicker._get(inst,"stepBigMonths"):-$.datepicker._get(inst,"stepMonths")),"M")}break;case 38:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,-7,"D")}handled=event.ctrlKey||event.metaKey;break;case 39:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,(isRTL?-1:+1),"D")}handled=event.ctrlKey||event.metaKey;if(event.originalEvent.altKey){$.datepicker._adjustDate(event.target,(event.ctrlKey?+$.datepicker._get(inst,"stepBigMonths"):+$.datepicker._get(inst,"stepMonths")),"M")}break;case 40:if(event.ctrlKey||event.metaKey){$.datepicker._adjustDate(event.target,+7,"D")}handled=event.ctrlKey||event.metaKey;break;default:handled=false}}else{if(event.keyCode==36&&event.ctrlKey){$.datepicker._showDatepicker(this)}else{handled=false}}if(handled){event.preventDefault();event.stopPropagation()}},_doKeyPress:function(event){var inst=$.datepicker._getInst(event.target);if($.datepicker._get(inst,"constrainInput")){var chars=$.datepicker._possibleChars($.datepicker._get(inst,"dateFormat"));var chr=String.fromCharCode(event.charCode==undefined?event.keyCode:event.charCode);return event.ctrlKey||(chr<" "||!chars||chars.indexOf(chr)>-1)}},_showDatepicker:function(input){input=input.target||input;if(input.nodeName.toLowerCase()!="input"){input=$("input",input.parentNode)[0]}if($.datepicker._isDisabledDatepicker(input)||$.datepicker._lastInput==input){return}var inst=$.datepicker._getInst(input);var beforeShow=$.datepicker._get(inst,"beforeShow");extendRemove(inst.settings,(beforeShow?beforeShow.apply(input,[input,inst]):{}));$.datepicker._hideDatepicker(null,"");$.datepicker._lastInput=input;$.datepicker._setDateFromField(inst);if($.datepicker._inDialog){input.value=""}if(!$.datepicker._pos){$.datepicker._pos=$.datepicker._findPos(input);$.datepicker._pos[1]+=input.offsetHeight}var isFixed=false;$(input).parents().each(function(){isFixed|=$(this).css("position")=="fixed";return !isFixed});if(isFixed&&$.browser.opera){$.datepicker._pos[0]-=document.documentElement.scrollLeft;$.datepicker._pos[1]-=document.documentElement.scrollTop}var offset={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null;inst.rangeStart=null;inst.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});$.datepicker._updateDatepicker(inst);offset=$.datepicker._checkOffset(inst,offset,isFixed);inst.dpDiv.css({position:($.datepicker._inDialog&&$.blockUI?"static":(isFixed?"fixed":"absolute")),display:"none",left:offset.left+"px",top:offset.top+"px"});if(!inst.inline){var showAnim=$.datepicker._get(inst,"showAnim")||"show";var duration=$.datepicker._get(inst,"duration");var postProcess=function(){$.datepicker._datepickerShowing=true;if($.browser.msie&&parseInt($.browser.version,10)<7){$("iframe.ui-datepicker-cover").css({width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4})}};if($.effects&&$.effects[showAnim]){inst.dpDiv.show(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[showAnim](duration,postProcess)}if(duration==""){postProcess()}if(inst.input[0].type!="hidden"){inst.input[0].focus()}$.datepicker._curInst=inst}},_updateDatepicker:function(inst){var dims={width:inst.dpDiv.width()+4,height:inst.dpDiv.height()+4};var self=this;inst.dpDiv.empty().append(this._generateHTML(inst)).find("iframe.ui-datepicker-cover").css({width:dims.width,height:dims.height}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){$(this).removeClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).removeClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).removeClass("ui-datepicker-next-hover")}}).bind("mouseover",function(){if(!self._isDisabledDatepicker(inst.inline?inst.dpDiv.parent()[0]:inst.input[0])){$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");$(this).addClass("ui-state-hover");if(this.className.indexOf("ui-datepicker-prev")!=-1){$(this).addClass("ui-datepicker-prev-hover")}if(this.className.indexOf("ui-datepicker-next")!=-1){$(this).addClass("ui-datepicker-next-hover")}}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();var numMonths=this._getNumberOfMonths(inst);var cols=numMonths[1];var width=17;if(cols>1){inst.dpDiv.addClass("ui-datepicker-multi-"+cols).css("width",(width*cols)+"em")}else{inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("")}inst.dpDiv[(numMonths[0]!=1||numMonths[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");inst.dpDiv[(this._get(inst,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");if(inst.input&&inst.input[0].type!="hidden"&&inst==$.datepicker._curInst){$(inst.input[0]).focus()}},_checkOffset:function(inst,offset,isFixed){var dpWidth=inst.dpDiv.outerWidth();var dpHeight=inst.dpDiv.outerHeight();var inputWidth=inst.input?inst.input.outerWidth():0;var inputHeight=inst.input?inst.input.outerHeight():0;var viewWidth=(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)+$(document).scrollLeft();var viewHeight=(window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight)+$(document).scrollTop();offset.left-=(this._get(inst,"isRTL")?(dpWidth-inputWidth):0);offset.left-=(isFixed&&offset.left==inst.input.offset().left)?$(document).scrollLeft():0;offset.top-=(isFixed&&offset.top==(inst.input.offset().top+inputHeight))?$(document).scrollTop():0;offset.left-=(offset.left+dpWidth>viewWidth&&viewWidth>dpWidth)?Math.abs(offset.left+dpWidth-viewWidth):0;offset.top-=(offset.top+dpHeight>viewHeight&&viewHeight>dpHeight)?Math.abs(offset.top+dpHeight+inputHeight*2-viewHeight):0;return offset},_findPos:function(obj){while(obj&&(obj.type=="hidden"||obj.nodeType!=1)){obj=obj.nextSibling}var position=$(obj).offset();return[position.left,position.top]},_hideDatepicker:function(input,duration){var inst=this._curInst;if(!inst||(input&&inst!=$.data(input,PROP_NAME))){return}if(inst.stayOpen){this._selectDate("#"+inst.id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear))}inst.stayOpen=false;if(this._datepickerShowing){duration=(duration!=null?duration:this._get(inst,"duration"));var showAnim=this._get(inst,"showAnim");var postProcess=function(){$.datepicker._tidyDialog(inst)};if(duration!=""&&$.effects&&$.effects[showAnim]){inst.dpDiv.hide(showAnim,$.datepicker._get(inst,"showOptions"),duration,postProcess)}else{inst.dpDiv[(duration==""?"hide":(showAnim=="slideDown"?"slideUp":(showAnim=="fadeIn"?"fadeOut":"hide")))](duration,postProcess)}if(duration==""){this._tidyDialog(inst)}var onClose=this._get(inst,"onClose");if(onClose){onClose.apply((inst.input?inst.input[0]:null),[(inst.input?inst.input.val():""),inst])}this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if($.blockUI){$.unblockUI();$("body").append(this.dpDiv)}}this._inDialog=false}this._curInst=null},_tidyDialog:function(inst){inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(event){if(!$.datepicker._curInst){return}var $target=$(event.target);if(($target.parents("#"+$.datepicker._mainDivId).length==0)&&!$target.hasClass($.datepicker.markerClassName)&&!$target.hasClass($.datepicker._triggerClass)&&$.datepicker._datepickerShowing&&!($.datepicker._inDialog&&$.blockUI)){$.datepicker._hideDatepicker(null,"")}},_adjustDate:function(id,offset,period){var target=$(id);var inst=this._getInst(target[0]);if(this._isDisabledDatepicker(target[0])){return}this._adjustInstDate(inst,offset+(period=="M"?this._get(inst,"showCurrentAtPos"):0),period);this._updateDatepicker(inst)},_gotoToday:function(id){var target=$(id);var inst=this._getInst(target[0]);if(this._get(inst,"gotoCurrent")&&inst.currentDay){inst.selectedDay=inst.currentDay;inst.drawMonth=inst.selectedMonth=inst.currentMonth;inst.drawYear=inst.selectedYear=inst.currentYear}else{var date=new Date();inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear()}this._notifyChange(inst);this._adjustDate(target)},_selectMonthYear:function(id,select,period){var target=$(id);var inst=this._getInst(target[0]);inst._selectingMonthYear=false;inst["selected"+(period=="M"?"Month":"Year")]=inst["draw"+(period=="M"?"Month":"Year")]=parseInt(select.options[select.selectedIndex].value,10);this._notifyChange(inst);this._adjustDate(target)},_clickMonthYear:function(id){var target=$(id);var inst=this._getInst(target[0]);if(inst.input&&inst._selectingMonthYear&&!$.browser.msie){inst.input[0].focus()}inst._selectingMonthYear=!inst._selectingMonthYear},_selectDay:function(id,month,year,td){var target=$(id);if($(td).hasClass(this._unselectableClass)||this._isDisabledDatepicker(target[0])){return}var inst=this._getInst(target[0]);inst.selectedDay=inst.currentDay=$("a",td).html();inst.selectedMonth=inst.currentMonth=month;inst.selectedYear=inst.currentYear=year;if(inst.stayOpen){inst.endDay=inst.endMonth=inst.endYear=null}this._selectDate(id,this._formatDate(inst,inst.currentDay,inst.currentMonth,inst.currentYear));if(inst.stayOpen){inst.rangeStart=this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay));this._updateDatepicker(inst)}},_clearDate:function(id){var target=$(id);var inst=this._getInst(target[0]);inst.stayOpen=false;inst.endDay=inst.endMonth=inst.endYear=inst.rangeStart=null;this._selectDate(target,"")},_selectDate:function(id,dateStr){var target=$(id);var inst=this._getInst(target[0]);dateStr=(dateStr!=null?dateStr:this._formatDate(inst));if(inst.input){inst.input.val(dateStr)}this._updateAlternate(inst);var onSelect=this._get(inst,"onSelect");if(onSelect){onSelect.apply((inst.input?inst.input[0]:null),[dateStr,inst])}else{if(inst.input){inst.input.trigger("change")}}if(inst.inline){this._updateDatepicker(inst)}else{if(!inst.stayOpen){this._hideDatepicker(null,this._get(inst,"duration"));this._lastInput=inst.input[0];if(typeof(inst.input[0])!="object"){inst.input[0].focus()}this._lastInput=null}}},_updateAlternate:function(inst){var altField=this._get(inst,"altField");if(altField){var altFormat=this._get(inst,"altFormat")||this._get(inst,"dateFormat");var date=this._getDate(inst);dateStr=this.formatDate(altFormat,date,this._getFormatConfig(inst));$(altField).each(function(){$(this).val(dateStr)})}},noWeekends:function(date){var day=date.getDay();return[(day>0&&day<6),""]},iso8601Week:function(date){var checkDate=new Date(date.getFullYear(),date.getMonth(),date.getDate());var firstMon=new Date(checkDate.getFullYear(),1-1,4);var firstDay=firstMon.getDay()||7;firstMon.setDate(firstMon.getDate()+1-firstDay);if(firstDay<4&&checkDate<firstMon){checkDate.setDate(checkDate.getDate()-3);return $.datepicker.iso8601Week(checkDate)}else{if(checkDate>new Date(checkDate.getFullYear(),12-1,28)){firstDay=new Date(checkDate.getFullYear()+1,1-1,4).getDay()||7;if(firstDay>4&&(checkDate.getDay()||7)<firstDay-3){return 1}}}return Math.floor(((checkDate-firstMon)/86400000)/7)+1},parseDate:function(format,value,settings){if(format==null||value==null){throw"Invalid arguments"}value=(typeof value=="object"?value.toString():value+"");if(value==""){return null}var shortYearCutoff=(settings?settings.shortYearCutoff:null)||this._defaults.shortYearCutoff;var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var year=-1;var month=-1;var day=-1;var doy=-1;var literal=false;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var getNumber=function(match){lookAhead(match);var origSize=(match=="@"?14:(match=="y"?4:(match=="o"?3:2)));var size=origSize;var num=0;while(size>0&&iValue<value.length&&value.charAt(iValue)>="0"&&value.charAt(iValue)<="9"){num=num*10+parseInt(value.charAt(iValue++),10);size--}if(size==origSize){throw"Missing number at position "+iValue}return num};var getName=function(match,shortNames,longNames){var names=(lookAhead(match)?longNames:shortNames);var size=0;for(var j=0;j<names.length;j++){size=Math.max(size,names[j].length)}var name="";var iInit=iValue;while(size>0&&iValue<value.length){name+=value.charAt(iValue++);for(var i=0;i<names.length;i++){if(name==names[i]){return i+1}}size--}throw"Unknown name at position "+iInit};var checkLiteral=function(){if(value.charAt(iValue)!=format.charAt(iFormat)){throw"Unexpected literal at position "+iValue}iValue++};var iValue=0;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{checkLiteral()}}else{switch(format.charAt(iFormat)){case"d":day=getNumber("d");break;case"D":getName("D",dayNamesShort,dayNames);break;case"o":doy=getNumber("o");break;case"m":month=getNumber("m");break;case"M":month=getName("M",monthNamesShort,monthNames);break;case"y":year=getNumber("y");break;case"@":var date=new Date(getNumber("@"));year=date.getFullYear();month=date.getMonth()+1;day=date.getDate();break;case"'":if(lookAhead("'")){checkLiteral()}else{literal=true}break;default:checkLiteral()}}}if(year==-1){year=new Date().getFullYear()}else{if(year<100){year+=new Date().getFullYear()-new Date().getFullYear()%100+(year<=shortYearCutoff?0:-100)}}if(doy>-1){month=1;day=doy;do{var dim=this._getDaysInMonth(year,month-1);if(day<=dim){break}month++;day-=dim}while(true)}var date=this._daylightSavingAdjust(new Date(year,month-1,day));if(date.getFullYear()!=year||date.getMonth()+1!=month||date.getDate()!=day){throw"Invalid date"}return date},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TIMESTAMP:"@",W3C:"yy-mm-dd",formatDate:function(format,date,settings){if(!date){return""}var dayNamesShort=(settings?settings.dayNamesShort:null)||this._defaults.dayNamesShort;var dayNames=(settings?settings.dayNames:null)||this._defaults.dayNames;var monthNamesShort=(settings?settings.monthNamesShort:null)||this._defaults.monthNamesShort;var monthNames=(settings?settings.monthNames:null)||this._defaults.monthNames;var lookAhead=function(match){var matches=(iFormat+1<format.length&&format.charAt(iFormat+1)==match);if(matches){iFormat++}return matches};var formatNumber=function(match,value,len){var num=""+value;if(lookAhead(match)){while(num.length<len){num="0"+num}}return num};var formatName=function(match,value,shortNames,longNames){return(lookAhead(match)?longNames[value]:shortNames[value])};var output="";var literal=false;if(date){for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{output+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":output+=formatNumber("d",date.getDate(),2);break;case"D":output+=formatName("D",date.getDay(),dayNamesShort,dayNames);break;case"o":var doy=date.getDate();for(var m=date.getMonth()-1;m>=0;m--){doy+=this._getDaysInMonth(date.getFullYear(),m)}output+=formatNumber("o",doy,3);break;case"m":output+=formatNumber("m",date.getMonth()+1,2);break;case"M":output+=formatName("M",date.getMonth(),monthNamesShort,monthNames);break;case"y":output+=(lookAhead("y")?date.getFullYear():(date.getYear()%100<10?"0":"")+date.getYear()%100);break;case"@":output+=date.getTime();break;case"'":if(lookAhead("'")){output+="'"}else{literal=true}break;default:output+=format.charAt(iFormat)}}}}return output},_possibleChars:function(format){var chars="";var literal=false;for(var iFormat=0;iFormat<format.length;iFormat++){if(literal){if(format.charAt(iFormat)=="'"&&!lookAhead("'")){literal=false}else{chars+=format.charAt(iFormat)}}else{switch(format.charAt(iFormat)){case"d":case"m":case"y":case"@":chars+="0123456789";break;case"D":case"M":return null;case"'":if(lookAhead("'")){chars+="'"}else{literal=true}break;default:chars+=format.charAt(iFormat)}}}return chars},_get:function(inst,name){return inst.settings[name]!==undefined?inst.settings[name]:this._defaults[name]},_setDateFromField:function(inst){var dateFormat=this._get(inst,"dateFormat");var dates=inst.input?inst.input.val():null;inst.endDay=inst.endMonth=inst.endYear=null;var date=defaultDate=this._getDefaultDate(inst);var settings=this._getFormatConfig(inst);try{date=this.parseDate(dateFormat,dates,settings)||defaultDate}catch(event){this.log(event);date=defaultDate}inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();inst.currentDay=(dates?date.getDate():0);inst.currentMonth=(dates?date.getMonth():0);inst.currentYear=(dates?date.getFullYear():0);this._adjustInstDate(inst)},_getDefaultDate:function(inst){var date=this._determineDate(this._get(inst,"defaultDate"),new Date());var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);return date},_determineDate:function(date,defaultDate){var offsetNumeric=function(offset){var date=new Date();date.setDate(date.getDate()+offset);return date};var offsetString=function(offset,getDaysInMonth){var date=new Date();var year=date.getFullYear();var month=date.getMonth();var day=date.getDate();var pattern=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;var matches=pattern.exec(offset);while(matches){switch(matches[2]||"d"){case"d":case"D":day+=parseInt(matches[1],10);break;case"w":case"W":day+=parseInt(matches[1],10)*7;break;case"m":case"M":month+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break;case"y":case"Y":year+=parseInt(matches[1],10);day=Math.min(day,getDaysInMonth(year,month));break}matches=pattern.exec(offset)}return new Date(year,month,day)};date=(date==null?defaultDate:(typeof date=="string"?offsetString(date,this._getDaysInMonth):(typeof date=="number"?(isNaN(date)?defaultDate:offsetNumeric(date)):date)));date=(date&&date.toString()=="Invalid Date"?defaultDate:date);if(date){date.setHours(0);date.setMinutes(0);date.setSeconds(0);date.setMilliseconds(0)}return this._daylightSavingAdjust(date)},_daylightSavingAdjust:function(date){if(!date){return null}date.setHours(date.getHours()>12?date.getHours()+2:0);return date},_setDate:function(inst,date,endDate){var clear=!(date);var origMonth=inst.selectedMonth;var origYear=inst.selectedYear;date=this._determineDate(date,new Date());inst.selectedDay=inst.currentDay=date.getDate();inst.drawMonth=inst.selectedMonth=inst.currentMonth=date.getMonth();inst.drawYear=inst.selectedYear=inst.currentYear=date.getFullYear();if(origMonth!=inst.selectedMonth||origYear!=inst.selectedYear){this._notifyChange(inst)}this._adjustInstDate(inst);if(inst.input){inst.input.val(clear?"":this._formatDate(inst))}},_getDate:function(inst){var startDate=(!inst.currentYear||(inst.input&&inst.input.val()=="")?null:this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return startDate},_generateHTML:function(inst){var today=new Date();today=this._daylightSavingAdjust(new Date(today.getFullYear(),today.getMonth(),today.getDate()));var isRTL=this._get(inst,"isRTL");var showButtonPanel=this._get(inst,"showButtonPanel");var hideIfNoPrevNext=this._get(inst,"hideIfNoPrevNext");var navigationAsDateFormat=this._get(inst,"navigationAsDateFormat");var numMonths=this._getNumberOfMonths(inst);var showCurrentAtPos=this._get(inst,"showCurrentAtPos");var stepMonths=this._get(inst,"stepMonths");var stepBigMonths=this._get(inst,"stepBigMonths");var isMultiMonth=(numMonths[0]!=1||numMonths[1]!=1);var currentDate=this._daylightSavingAdjust((!inst.currentDay?new Date(9999,9,9):new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");var drawMonth=inst.drawMonth-showCurrentAtPos;var drawYear=inst.drawYear;if(drawMonth<0){drawMonth+=12;drawYear--}if(maxDate){var maxDraw=this._daylightSavingAdjust(new Date(maxDate.getFullYear(),maxDate.getMonth()-numMonths[1]+1,maxDate.getDate()));maxDraw=(minDate&&maxDraw<minDate?minDate:maxDraw);while(this._daylightSavingAdjust(new Date(drawYear,drawMonth,1))>maxDraw){drawMonth--;if(drawMonth<0){drawMonth=11;drawYear--}}}inst.drawMonth=drawMonth;inst.drawYear=drawYear;var prevText=this._get(inst,"prevText");prevText=(!navigationAsDateFormat?prevText:this.formatDate(prevText,this._daylightSavingAdjust(new Date(drawYear,drawMonth-stepMonths,1)),this._getFormatConfig(inst)));var prev=(this._canAdjustMonth(inst,-1,drawYear,drawMonth)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', -"+stepMonths+", 'M');\" title=\""+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+prevText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"e":"w")+'">'+prevText+"</span></a>"));var nextText=this._get(inst,"nextText");nextText=(!navigationAsDateFormat?nextText:this.formatDate(nextText,this._daylightSavingAdjust(new Date(drawYear,drawMonth+stepMonths,1)),this._getFormatConfig(inst)));var next=(this._canAdjustMonth(inst,+1,drawYear,drawMonth)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#'+inst.id+"', +"+stepMonths+", 'M');\" title=\""+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>":(hideIfNoPrevNext?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+nextText+'"><span class="ui-icon ui-icon-circle-triangle-'+(isRTL?"w":"e")+'">'+nextText+"</span></a>"));var currentText=this._get(inst,"currentText");var gotoDate=(this._get(inst,"gotoCurrent")&&inst.currentDay?currentDate:today);currentText=(!navigationAsDateFormat?currentText:this.formatDate(currentText,gotoDate,this._getFormatConfig(inst)));var controls=(!inst.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">'+this._get(inst,"closeText")+"</button>":"");var buttonPanel=(showButtonPanel)?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(isRTL?controls:"")+(this._isInRange(inst,gotoDate)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#'+inst.id+"');\">"+currentText+"</button>":"")+(isRTL?"":controls)+"</div>":"";var firstDay=parseInt(this._get(inst,"firstDay"),10);firstDay=(isNaN(firstDay)?0:firstDay);var dayNames=this._get(inst,"dayNames");var dayNamesShort=this._get(inst,"dayNamesShort");var dayNamesMin=this._get(inst,"dayNamesMin");var monthNames=this._get(inst,"monthNames");var monthNamesShort=this._get(inst,"monthNamesShort");var beforeShowDay=this._get(inst,"beforeShowDay");var showOtherMonths=this._get(inst,"showOtherMonths");var calculateWeek=this._get(inst,"calculateWeek")||this.iso8601Week;var endDate=inst.endDay?this._daylightSavingAdjust(new Date(inst.endYear,inst.endMonth,inst.endDay)):currentDate;var defaultDate=this._getDefaultDate(inst);var html="";for(var row=0;row<numMonths[0];row++){var group="";for(var col=0;col<numMonths[1];col++){var selectedDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,inst.selectedDay));var cornerClass=" ui-corner-all";var calender="";if(isMultiMonth){calender+='<div class="ui-datepicker-group ui-datepicker-group-';switch(col){case 0:calender+="first";cornerClass=" ui-corner-"+(isRTL?"right":"left");break;case numMonths[1]-1:calender+="last";cornerClass=" ui-corner-"+(isRTL?"left":"right");break;default:calender+="middle";cornerClass="";break}calender+='">'}calender+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+cornerClass+'">'+(/all|left/.test(cornerClass)&&row==0?(isRTL?next:prev):"")+(/all|right/.test(cornerClass)&&row==0?(isRTL?prev:next):"")+this._generateMonthYearHeader(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,row>0||col>0,monthNames,monthNamesShort)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var thead="";for(var dow=0;dow<7;dow++){var day=(dow+firstDay)%7;thead+="<th"+((dow+firstDay+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+dayNames[day]+'">'+dayNamesMin[day]+"</span></th>"}calender+=thead+"</tr></thead><tbody>";var daysInMonth=this._getDaysInMonth(drawYear,drawMonth);if(drawYear==inst.selectedYear&&drawMonth==inst.selectedMonth){inst.selectedDay=Math.min(inst.selectedDay,daysInMonth)}var leadDays=(this._getFirstDayOfMonth(drawYear,drawMonth)-firstDay+7)%7;var numRows=(isMultiMonth?6:Math.ceil((leadDays+daysInMonth)/7));var printDate=this._daylightSavingAdjust(new Date(drawYear,drawMonth,1-leadDays));for(var dRow=0;dRow<numRows;dRow++){calender+="<tr>";var tbody="";for(var dow=0;dow<7;dow++){var daySettings=(beforeShowDay?beforeShowDay.apply((inst.input?inst.input[0]:null),[printDate]):[true,""]);var otherMonth=(printDate.getMonth()!=drawMonth);var unselectable=otherMonth||!daySettings[0]||(minDate&&printDate<minDate)||(maxDate&&printDate>maxDate);tbody+='<td class="'+((dow+firstDay+6)%7>=5?" ui-datepicker-week-end":"")+(otherMonth?" ui-datepicker-other-month":"")+((printDate.getTime()==selectedDate.getTime()&&drawMonth==inst.selectedMonth&&inst._keyEvent)||(defaultDate.getTime()==printDate.getTime()&&defaultDate.getTime()==selectedDate.getTime())?" "+this._dayOverClass:"")+(unselectable?" "+this._unselectableClass+" ui-state-disabled":"")+(otherMonth&&!showOtherMonths?"":" "+daySettings[1]+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" "+this._currentClass:"")+(printDate.getTime()==today.getTime()?" ui-datepicker-today":""))+'"'+((!otherMonth||showOtherMonths)&&daySettings[2]?' title="'+daySettings[2]+'"':"")+(unselectable?"":" onclick=\"DP_jQuery.datepicker._selectDay('#"+inst.id+"',"+drawMonth+","+drawYear+', this);return false;"')+">"+(otherMonth?(showOtherMonths?printDate.getDate():"&#xa0;"):(unselectable?'<span class="ui-state-default">'+printDate.getDate()+"</span>":'<a class="ui-state-default'+(printDate.getTime()==today.getTime()?" ui-state-highlight":"")+(printDate.getTime()>=currentDate.getTime()&&printDate.getTime()<=endDate.getTime()?" ui-state-active":"")+'" href="#">'+printDate.getDate()+"</a>"))+"</td>";printDate.setDate(printDate.getDate()+1);printDate=this._daylightSavingAdjust(printDate)}calender+=tbody+"</tr>"}drawMonth++;if(drawMonth>11){drawMonth=0;drawYear++}calender+="</tbody></table>"+(isMultiMonth?"</div>"+((numMonths[0]>0&&col==numMonths[1]-1)?'<div class="ui-datepicker-row-break"></div>':""):"");group+=calender}html+=group}html+=buttonPanel+($.browser.msie&&parseInt($.browser.version,10)<7&&!inst.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':"");inst._keyEvent=false;return html},_generateMonthYearHeader:function(inst,drawMonth,drawYear,minDate,maxDate,selectedDate,secondary,monthNames,monthNamesShort){minDate=(inst.rangeStart&&minDate&&selectedDate<minDate?selectedDate:minDate);var changeMonth=this._get(inst,"changeMonth");var changeYear=this._get(inst,"changeYear");var showMonthAfterYear=this._get(inst,"showMonthAfterYear");var html='<div class="ui-datepicker-title">';var monthHtml="";if(secondary||!changeMonth){monthHtml+='<span class="ui-datepicker-month">'+monthNames[drawMonth]+"</span> "}else{var inMinYear=(minDate&&minDate.getFullYear()==drawYear);var inMaxYear=(maxDate&&maxDate.getFullYear()==drawYear);monthHtml+='<select class="ui-datepicker-month" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'M');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(var month=0;month<12;month++){if((!inMinYear||month>=minDate.getMonth())&&(!inMaxYear||month<=maxDate.getMonth())){monthHtml+='<option value="'+month+'"'+(month==drawMonth?' selected="selected"':"")+">"+monthNamesShort[month]+"</option>"}}monthHtml+="</select>"}if(!showMonthAfterYear){html+=monthHtml+((secondary||changeMonth||changeYear)&&(!(changeMonth&&changeYear))?"&#xa0;":"")}if(secondary||!changeYear){html+='<span class="ui-datepicker-year">'+drawYear+"</span>"}else{var years=this._get(inst,"yearRange").split(":");var year=0;var endYear=0;if(years.length!=2){year=drawYear-10;endYear=drawYear+10}else{if(years[0].charAt(0)=="+"||years[0].charAt(0)=="-"){year=drawYear+parseInt(years[0],10);endYear=drawYear+parseInt(years[1],10)}else{year=parseInt(years[0],10);endYear=parseInt(years[1],10)}}year=(minDate?Math.max(year,minDate.getFullYear()):year);endYear=(maxDate?Math.min(endYear,maxDate.getFullYear()):endYear);html+='<select class="ui-datepicker-year" onchange="DP_jQuery.datepicker._selectMonthYear(\'#'+inst.id+"', this, 'Y');\" onclick=\"DP_jQuery.datepicker._clickMonthYear('#"+inst.id+"');\">";for(;year<=endYear;year++){html+='<option value="'+year+'"'+(year==drawYear?' selected="selected"':"")+">"+year+"</option>"}html+="</select>"}if(showMonthAfterYear){html+=(secondary||changeMonth||changeYear?"&#xa0;":"")+monthHtml}html+="</div>";return html},_adjustInstDate:function(inst,offset,period){var year=inst.drawYear+(period=="Y"?offset:0);var month=inst.drawMonth+(period=="M"?offset:0);var day=Math.min(inst.selectedDay,this._getDaysInMonth(year,month))+(period=="D"?offset:0);var date=this._daylightSavingAdjust(new Date(year,month,day));var minDate=this._getMinMaxDate(inst,"min",true);var maxDate=this._getMinMaxDate(inst,"max");date=(minDate&&date<minDate?minDate:date);date=(maxDate&&date>maxDate?maxDate:date);inst.selectedDay=date.getDate();inst.drawMonth=inst.selectedMonth=date.getMonth();inst.drawYear=inst.selectedYear=date.getFullYear();if(period=="M"||period=="Y"){this._notifyChange(inst)}},_notifyChange:function(inst){var onChange=this._get(inst,"onChangeMonthYear");if(onChange){onChange.apply((inst.input?inst.input[0]:null),[inst.selectedYear,inst.selectedMonth+1,inst])}},_getNumberOfMonths:function(inst){var numMonths=this._get(inst,"numberOfMonths");return(numMonths==null?[1,1]:(typeof numMonths=="number"?[1,numMonths]:numMonths))},_getMinMaxDate:function(inst,minMax,checkRange){var date=this._determineDate(this._get(inst,minMax+"Date"),null);return(!checkRange||!inst.rangeStart?date:(!date||inst.rangeStart>date?inst.rangeStart:date))},_getDaysInMonth:function(year,month){return 32-new Date(year,month,32).getDate()},_getFirstDayOfMonth:function(year,month){return new Date(year,month,1).getDay()},_canAdjustMonth:function(inst,offset,curYear,curMonth){var numMonths=this._getNumberOfMonths(inst);var date=this._daylightSavingAdjust(new Date(curYear,curMonth+(offset<0?offset:numMonths[1]),1));if(offset<0){date.setDate(this._getDaysInMonth(date.getFullYear(),date.getMonth()))}return this._isInRange(inst,date)},_isInRange:function(inst,date){var newMinDate=(!inst.rangeStart?null:this._daylightSavingAdjust(new Date(inst.selectedYear,inst.selectedMonth,inst.selectedDay)));newMinDate=(newMinDate&&inst.rangeStart<newMinDate?inst.rangeStart:newMinDate);var minDate=newMinDate||this._getMinMaxDate(inst,"min");var maxDate=this._getMinMaxDate(inst,"max");return((!minDate||date>=minDate)&&(!maxDate||date<=maxDate))},_getFormatConfig:function(inst){var shortYearCutoff=this._get(inst,"shortYearCutoff");shortYearCutoff=(typeof shortYearCutoff!="string"?shortYearCutoff:new Date().getFullYear()%100+parseInt(shortYearCutoff,10));return{shortYearCutoff:shortYearCutoff,dayNamesShort:this._get(inst,"dayNamesShort"),dayNames:this._get(inst,"dayNames"),monthNamesShort:this._get(inst,"monthNamesShort"),monthNames:this._get(inst,"monthNames")}},_formatDate:function(inst,day,month,year){if(!day){inst.currentDay=inst.selectedDay;inst.currentMonth=inst.selectedMonth;inst.currentYear=inst.selectedYear}var date=(day?(typeof day=="object"?day:this._daylightSavingAdjust(new Date(year,month,day))):this._daylightSavingAdjust(new Date(inst.currentYear,inst.currentMonth,inst.currentDay)));return this.formatDate(this._get(inst,"dateFormat"),date,this._getFormatConfig(inst))}});function extendRemove(target,props){$.extend(target,props);for(var name in props){if(props[name]==null||props[name]==undefined){target[name]=props[name]}}return target}function isArray(a){return(a&&(($.browser.safari&&typeof a=="object"&&a.length)||(a.constructor&&a.constructor.toString().match(/\Array\(\)/))))}$.fn.datepicker=function(options){if(!$.datepicker.initialized){$(document).mousedown($.datepicker._checkExternalClick).find("body").append($.datepicker.dpDiv);$.datepicker.initialized=true}var otherArgs=Array.prototype.slice.call(arguments,1);if(typeof options=="string"&&(options=="isDisabled"||options=="getDate")){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}if(options=="option"&&arguments.length==2&&typeof arguments[1]=="string"){return $.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this[0]].concat(otherArgs))}return this.each(function(){typeof options=="string"?$.datepicker["_"+options+"Datepicker"].apply($.datepicker,[this].concat(otherArgs)):$.datepicker._attachDatepicker(this,options)})};$.datepicker=new Datepicker();$.datepicker.initialized=false;$.datepicker.uuid=new Date().getTime();$.datepicker.version="1.7.2";window.DP_jQuery=$})(jQuery);(function(c){var b={dragStart:"start.draggable",drag:"drag.draggable",dragStop:"stop.draggable",maxHeight:"maxHeight.resizable",minHeight:"minHeight.resizable",maxWidth:"maxWidth.resizable",minWidth:"minWidth.resizable",resizeStart:"start.resizable",resize:"drag.resizable",resizeStop:"stop.resizable"},a="ui-dialog ui-widget ui-widget-content ui-corner-all ";c.widget("ui.dialog",{_init:function(){this.originalTitle=this.element.attr("title");var l=this,m=this.options,j=m.title||this.originalTitle||"&nbsp;",e=c.ui.dialog.getTitleId(this.element),k=(this.uiDialog=c("<div/>")).appendTo(document.body).hide().addClass(a+m.dialogClass).css({position:"absolute",overflow:"hidden",zIndex:m.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(n){(m.closeOnEscape&&n.keyCode&&n.keyCode==c.ui.keyCode.ESCAPE&&l.close(n))}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(n){l.moveToTop(false,n)}),g=this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(k),f=(this.uiDialogTitlebar=c("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(k),i=c('<a href="#"/>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){i.addClass("ui-state-hover")},function(){i.removeClass("ui-state-hover")}).focus(function(){i.addClass("ui-state-focus")}).blur(function(){i.removeClass("ui-state-focus")}).mousedown(function(n){n.stopPropagation()}).click(function(n){l.close(n);return false}).appendTo(f),h=(this.uiDialogTitlebarCloseText=c("<span/>")).addClass("ui-icon ui-icon-closethick").text(m.closeText).appendTo(i),d=c("<span/>").addClass("ui-dialog-title").attr("id",e).html(j).prependTo(f);f.find("*").add(f).disableSelection();(m.draggable&&c.fn.draggable&&this._makeDraggable());(m.resizable&&c.fn.resizable&&this._makeResizable());this._createButtons(m.buttons);this._isOpen=false;(m.bgiframe&&c.fn.bgiframe&&k.bgiframe());(m.autoOpen&&this.open())},destroy:function(){(this.overlay&&this.overlay.destroy());this.uiDialog.hide();this.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");this.uiDialog.remove();(this.originalTitle&&this.element.attr("title",this.originalTitle))},close:function(f){var d=this;if(false===d._trigger("beforeclose",f)){return}(d.overlay&&d.overlay.destroy());d.uiDialog.unbind("keypress.ui-dialog");(d.options.hide?d.uiDialog.hide(d.options.hide,function(){d._trigger("close",f)}):d.uiDialog.hide()&&d._trigger("close",f));c.ui.dialog.overlay.resize();d._isOpen=false;if(d.options.modal){var e=0;c(".ui-dialog").each(function(){if(this!=d.uiDialog[0]){e=Math.max(e,c(this).css("z-index"))}});c.ui.dialog.maxZ=e}},isOpen:function(){return this._isOpen},moveToTop:function(f,e){if((this.options.modal&&!f)||(!this.options.stack&&!this.options.modal)){return this._trigger("focus",e)}if(this.options.zIndex>c.ui.dialog.maxZ){c.ui.dialog.maxZ=this.options.zIndex}(this.overlay&&this.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=++c.ui.dialog.maxZ));var d={scrollTop:this.element.attr("scrollTop"),scrollLeft:this.element.attr("scrollLeft")};this.uiDialog.css("z-index",++c.ui.dialog.maxZ);this.element.attr(d);this._trigger("focus",e)},open:function(){if(this._isOpen){return}var e=this.options,d=this.uiDialog;this.overlay=e.modal?new c.ui.dialog.overlay(this):null;(d.next().length&&d.appendTo("body"));this._size();this._position(e.position);d.show(e.show);this.moveToTop(true);(e.modal&&d.bind("keypress.ui-dialog",function(h){if(h.keyCode!=c.ui.keyCode.TAB){return}var g=c(":tabbable",this),i=g.filter(":first")[0],f=g.filter(":last")[0];if(h.target==f&&!h.shiftKey){setTimeout(function(){i.focus()},1)}else{if(h.target==i&&h.shiftKey){setTimeout(function(){f.focus()},1)}}}));c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();this._trigger("open");this._isOpen=true},_createButtons:function(g){var f=this,d=false,e=c("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");this.uiDialog.find(".ui-dialog-buttonpane").remove();(typeof g=="object"&&g!==null&&c.each(g,function(){return !(d=true)}));if(d){c.each(g,function(h,i){c('<button type="button"></button>').addClass("ui-state-default ui-corner-all").text(h).click(function(){i.apply(f.element[0],arguments)}).hover(function(){c(this).addClass("ui-state-hover")},function(){c(this).removeClass("ui-state-hover")}).focus(function(){c(this).addClass("ui-state-focus")}).blur(function(){c(this).removeClass("ui-state-focus")}).appendTo(e)});e.appendTo(this.uiDialog)}},_makeDraggable:function(){var d=this,f=this.options,e;this.uiDialog.draggable({cancel:".ui-dialog-content",handle:".ui-dialog-titlebar",containment:"document",start:function(){e=f.height;c(this).height(c(this).height()).addClass("ui-dialog-dragging");(f.dragStart&&f.dragStart.apply(d.element[0],arguments))},drag:function(){(f.drag&&f.drag.apply(d.element[0],arguments))},stop:function(){c(this).removeClass("ui-dialog-dragging").height(e);(f.dragStop&&f.dragStop.apply(d.element[0],arguments));c.ui.dialog.overlay.resize()}})},_makeResizable:function(g){g=(g===undefined?this.options.resizable:g);var d=this,f=this.options,e=typeof g=="string"?g:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",alsoResize:this.element,maxWidth:f.maxWidth,maxHeight:f.maxHeight,minWidth:f.minWidth,minHeight:f.minHeight,start:function(){c(this).addClass("ui-dialog-resizing");(f.resizeStart&&f.resizeStart.apply(d.element[0],arguments))},resize:function(){(f.resize&&f.resize.apply(d.element[0],arguments))},handles:e,stop:function(){c(this).removeClass("ui-dialog-resizing");f.height=c(this).height();f.width=c(this).width();(f.resizeStop&&f.resizeStop.apply(d.element[0],arguments));c.ui.dialog.overlay.resize()}}).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_position:function(i){var e=c(window),f=c(document),g=f.scrollTop(),d=f.scrollLeft(),h=g;if(c.inArray(i,["center","top","right","bottom","left"])>=0){i=[i=="right"||i=="left"?i:"center",i=="top"||i=="bottom"?i:"middle"]}if(i.constructor!=Array){i=["center","middle"]}if(i[0].constructor==Number){d+=i[0]}else{switch(i[0]){case"left":d+=0;break;case"right":d+=e.width()-this.uiDialog.outerWidth();break;default:case"center":d+=(e.width()-this.uiDialog.outerWidth())/2}}if(i[1].constructor==Number){g+=i[1]}else{switch(i[1]){case"top":g+=0;break;case"bottom":g+=e.height()-this.uiDialog.outerHeight();break;default:case"middle":g+=(e.height()-this.uiDialog.outerHeight())/2}}g=Math.max(g,h);this.uiDialog.css({top:g,left:d})},_setData:function(e,f){(b[e]&&this.uiDialog.data(b[e],f));switch(e){case"buttons":this._createButtons(f);break;case"closeText":this.uiDialogTitlebarCloseText.text(f);break;case"dialogClass":this.uiDialog.removeClass(this.options.dialogClass).addClass(a+f);break;case"draggable":(f?this._makeDraggable():this.uiDialog.draggable("destroy"));break;case"height":this.uiDialog.height(f);break;case"position":this._position(f);break;case"resizable":var d=this.uiDialog,g=this.uiDialog.is(":data(resizable)");(g&&!f&&d.resizable("destroy"));(g&&typeof f=="string"&&d.resizable("option","handles",f));(g||this._makeResizable(f));break;case"title":c(".ui-dialog-title",this.uiDialogTitlebar).html(f||"&nbsp;");break;case"width":this.uiDialog.width(f);break}c.widget.prototype._setData.apply(this,arguments)},_size:function(){var e=this.options;this.element.css({height:0,minHeight:0,width:"auto"});var d=this.uiDialog.css({height:"auto",width:e.width}).height();this.element.css({minHeight:Math.max(e.minHeight-d,0),height:e.height=="auto"?"auto":Math.max(e.height-d,0)})}});c.extend(c.ui.dialog,{version:"1.7.2",defaults:{autoOpen:true,bgiframe:false,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:"center",resizable:true,show:null,stack:true,title:"",width:300,zIndex:1000},getter:"isOpen",uuid:0,maxZ:0,getTitleId:function(d){return"ui-dialog-title-"+(d.attr("id")||++this.uuid)},overlay:function(d){this.$el=c.ui.dialog.overlay.create(d)}});c.extend(c.ui.dialog.overlay,{instances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(d){return d+".dialog-overlay"}).join(" "),create:function(e){if(this.instances.length===0){setTimeout(function(){if(c.ui.dialog.overlay.instances.length){c(document).bind(c.ui.dialog.overlay.events,function(f){var g=c(f.target).parents(".ui-dialog").css("zIndex")||0;return(g>c.ui.dialog.overlay.maxZ)})}},1);c(document).bind("keydown.dialog-overlay",function(f){(e.options.closeOnEscape&&f.keyCode&&f.keyCode==c.ui.keyCode.ESCAPE&&e.close(f))});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var d=c("<div></div>").appendTo(document.body).addClass("ui-widget-overlay").css({width:this.width(),height:this.height()});(e.options.bgiframe&&c.fn.bgiframe&&d.bgiframe());this.instances.push(d);return d},destroy:function(d){this.instances.splice(c.inArray(this.instances,d),1);if(this.instances.length===0){c([document,window]).unbind(".dialog-overlay")}d.remove();var e=0;c.each(this.instances,function(){e=Math.max(e,this.css("z-index"))});this.maxZ=e},height:function(){if(c.browser.msie&&c.browser.version<7){var e=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);var d=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);if(e<d){return c(window).height()+"px"}else{return e+"px"}}else{return c(document).height()+"px"}},width:function(){if(c.browser.msie&&c.browser.version<7){var d=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);var e=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);if(d<e){return c(window).width()+"px"}else{return d+"px"}}else{return c(document).width()+"px"}},resize:function(){var d=c([]);c.each(c.ui.dialog.overlay.instances,function(){d=d.add(this)});d.css({width:0,height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);(function(a){a.widget("ui.progressbar",{_init:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=a('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow").removeData("progressbar").unbind(".progressbar");this.valueDiv.remove();a.widget.prototype.destroy.apply(this,arguments)},value:function(b){if(b===undefined){return this._value()}this._setData("value",b);return this},_setData:function(b,c){switch(b){case"value":this.options.value=c;this._refreshValue();this._trigger("change",null,{});break}a.widget.prototype._setData.apply(this,arguments)},_value:function(){var b=this.options.value;if(b<this._valueMin()){b=this._valueMin()}if(b>this._valueMax()){b=this._valueMax()}return b},_valueMin:function(){var b=0;return b},_valueMax:function(){var b=100;return b},_refreshValue:function(){var b=this.value();this.valueDiv[b==this._valueMax()?"addClass":"removeClass"]("ui-corner-right");this.valueDiv.width(b+"%");this.element.attr("aria-valuenow",b)}});a.extend(a.ui.progressbar,{version:"1.7.2",defaults:{value:0}})})(jQuery);(function(a){a.widget("ui.slider",a.extend({},a.ui.mouse,{_init:function(){var b=this,c=this.options;this._keySliding=false;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");this.range=a([]);if(c.range){if(c.range===true){this.range=a("<div></div>");if(!c.values){c.values=[this._valueMin(),this._valueMin()]}if(c.values.length&&c.values.length!=2){c.values=[c.values[0],c.values[0]]}}else{this.range=a("<div></div>")}this.range.appendTo(this.element).addClass("ui-slider-range");if(c.range=="min"||c.range=="max"){this.range.addClass("ui-slider-range-"+c.range)}this.range.addClass("ui-widget-header")}if(a(".ui-slider-handle",this.element).length==0){a('<a href="#"></a>').appendTo(this.element).addClass("ui-slider-handle")}if(c.values&&c.values.length){while(a(".ui-slider-handle",this.element).length<c.values.length){a('<a href="#"></a>').appendTo(this.element).addClass("ui-slider-handle")}}this.handles=a(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(d){d.preventDefault()}).hover(function(){if(!c.disabled){a(this).addClass("ui-state-hover")}},function(){a(this).removeClass("ui-state-hover")}).focus(function(){if(!c.disabled){a(".ui-slider .ui-state-focus").removeClass("ui-state-focus");a(this).addClass("ui-state-focus")}else{a(this).blur()}}).blur(function(){a(this).removeClass("ui-state-focus")});this.handles.each(function(d){a(this).data("index.ui-slider-handle",d)});this.handles.keydown(function(i){var f=true;var e=a(this).data("index.ui-slider-handle");if(b.options.disabled){return}switch(i.keyCode){case a.ui.keyCode.HOME:case a.ui.keyCode.END:case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:f=false;if(!b._keySliding){b._keySliding=true;a(this).addClass("ui-state-active");b._start(i,e)}break}var g,d,h=b._step();if(b.options.values&&b.options.values.length){g=d=b.values(e)}else{g=d=b.value()}switch(i.keyCode){case a.ui.keyCode.HOME:d=b._valueMin();break;case a.ui.keyCode.END:d=b._valueMax();break;case a.ui.keyCode.UP:case a.ui.keyCode.RIGHT:if(g==b._valueMax()){return}d=g+h;break;case a.ui.keyCode.DOWN:case a.ui.keyCode.LEFT:if(g==b._valueMin()){return}d=g-h;break}b._slide(i,e,d);return f}).keyup(function(e){var d=a(this).data("index.ui-slider-handle");if(b._keySliding){b._stop(e,d);b._change(e,d);b._keySliding=false;a(this).removeClass("ui-state-active")}});this._refreshValue()},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");this._mouseDestroy()},_mouseCapture:function(d){var e=this.options;if(e.disabled){return false}this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();var h={x:d.pageX,y:d.pageY};var j=this._normValueFromMouse(h);var c=this._valueMax()-this._valueMin()+1,f;var k=this,i;this.handles.each(function(l){var m=Math.abs(j-k.values(l));if(c>m){c=m;f=a(this);i=l}});if(e.range==true&&this.values(1)==e.min){f=a(this.handles[++i])}this._start(d,i);k._handleIndex=i;f.addClass("ui-state-active").focus();var g=f.offset();var b=!a(d.target).parents().andSelf().is(".ui-slider-handle");this._clickOffset=b?{left:0,top:0}:{left:d.pageX-g.left-(f.width()/2),top:d.pageY-g.top-(f.height()/2)-(parseInt(f.css("borderTopWidth"),10)||0)-(parseInt(f.css("borderBottomWidth"),10)||0)+(parseInt(f.css("marginTop"),10)||0)};j=this._normValueFromMouse(h);this._slide(d,i,j);return true},_mouseStart:function(b){return true},_mouseDrag:function(d){var b={x:d.pageX,y:d.pageY};var c=this._normValueFromMouse(b);this._slide(d,this._handleIndex,c);return false},_mouseStop:function(b){this.handles.removeClass("ui-state-active");this._stop(b,this._handleIndex);this._change(b,this._handleIndex);this._handleIndex=null;this._clickOffset=null;return false},_detectOrientation:function(){this.orientation=this.options.orientation=="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(d){var c,h;if("horizontal"==this.orientation){c=this.elementSize.width;h=d.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{c=this.elementSize.height;h=d.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}var f=(h/c);if(f>1){f=1}if(f<0){f=0}if("vertical"==this.orientation){f=1-f}var e=this._valueMax()-this._valueMin(),i=f*e,b=i%this.options.step,g=this._valueMin()+i-b;if(b>(this.options.step/2)){g+=this.options.step}return parseFloat(g.toFixed(5))},_start:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("start",d,b)},_slide:function(f,e,d){var g=this.handles[e];if(this.options.values&&this.options.values.length){var b=this.values(e?0:1);if((this.options.values.length==2&&this.options.range===true)&&((e==0&&d>b)||(e==1&&d<b))){d=b}if(d!=this.values(e)){var c=this.values();c[e]=d;var h=this._trigger("slide",f,{handle:this.handles[e],value:d,values:c});var b=this.values(e?0:1);if(h!==false){this.values(e,d,(f.type=="mousedown"&&this.options.animate),true)}}}else{if(d!=this.value()){var h=this._trigger("slide",f,{handle:this.handles[e],value:d});if(h!==false){this._setData("value",d,(f.type=="mousedown"&&this.options.animate))}}}},_stop:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("stop",d,b)},_change:function(d,c){var b={handle:this.handles[c],value:this.value()};if(this.options.values&&this.options.values.length){b.value=this.values(c);b.values=this.values()}this._trigger("change",d,b)},value:function(b){if(arguments.length){this._setData("value",b);this._change(null,0)}return this._value()},values:function(b,e,c,d){if(arguments.length>1){this.options.values[b]=e;this._refreshValue(c);if(!d){this._change(null,b)}}if(arguments.length){if(this.options.values&&this.options.values.length){return this._values(b)}else{return this.value()}}else{return this._values()}},_setData:function(b,d,c){a.widget.prototype._setData.apply(this,arguments);switch(b){case"disabled":if(d){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled")}else{this.handles.removeAttr("disabled")}case"orientation":this._detectOrientation();this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue(c);break;case"value":this._refreshValue(c);break}},_step:function(){var b=this.options.step;return b},_value:function(){var b=this.options.value;if(b<this._valueMin()){b=this._valueMin()}if(b>this._valueMax()){b=this._valueMax()}return b},_values:function(b){if(arguments.length){var c=this.options.values[b];if(c<this._valueMin()){c=this._valueMin()}if(c>this._valueMax()){c=this._valueMax()}return c}else{return this.options.values}},_valueMin:function(){var b=this.options.min;return b},_valueMax:function(){var b=this.options.max;return b},_refreshValue:function(c){var f=this.options.range,d=this.options,l=this;if(this.options.values&&this.options.values.length){var i,h;this.handles.each(function(p,n){var o=(l.values(p)-l._valueMin())/(l._valueMax()-l._valueMin())*100;var m={};m[l.orientation=="horizontal"?"left":"bottom"]=o+"%";a(this).stop(1,1)[c?"animate":"css"](m,d.animate);if(l.options.range===true){if(l.orientation=="horizontal"){(p==0)&&l.range.stop(1,1)[c?"animate":"css"]({left:o+"%"},d.animate);(p==1)&&l.range[c?"animate":"css"]({width:(o-lastValPercent)+"%"},{queue:false,duration:d.animate})}else{(p==0)&&l.range.stop(1,1)[c?"animate":"css"]({bottom:(o)+"%"},d.animate);(p==1)&&l.range[c?"animate":"css"]({height:(o-lastValPercent)+"%"},{queue:false,duration:d.animate})}}lastValPercent=o})}else{var j=this.value(),g=this._valueMin(),k=this._valueMax(),e=k!=g?(j-g)/(k-g)*100:0;var b={};b[l.orientation=="horizontal"?"left":"bottom"]=e+"%";this.handle.stop(1,1)[c?"animate":"css"](b,d.animate);(f=="min")&&(this.orientation=="horizontal")&&this.range.stop(1,1)[c?"animate":"css"]({width:e+"%"},d.animate);(f=="max")&&(this.orientation=="horizontal")&&this.range[c?"animate":"css"]({width:(100-e)+"%"},{queue:false,duration:d.animate});(f=="min")&&(this.orientation=="vertical")&&this.range.stop(1,1)[c?"animate":"css"]({height:e+"%"},d.animate);(f=="max")&&(this.orientation=="vertical")&&this.range[c?"animate":"css"]({height:(100-e)+"%"},{queue:false,duration:d.animate})}}}));a.extend(a.ui.slider,{getter:"value values",version:"1.7.2",eventPrefix:"slide",defaults:{animate:false,delay:0,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null}})})(jQuery);(function(a){a.widget("ui.tabs",{_init:function(){if(this.options.deselectable!==undefined){this.options.collapsible=this.options.deselectable}this._tabify(true)},_setData:function(b,c){if(b=="selected"){if(this.options.collapsible&&c==this.options.selected){return}this.select(c)}else{this.options[b]=c;if(b=="deselectable"){this.options.collapsible=c}this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+a.data(b)},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+a.data(this.list[0]));return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(c,b){return{tab:c,panel:b,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(n){this.list=this.element.children("ul:first");this.lis=a("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return a("a",this)[0]});this.panels=a([]);var p=this,d=this.options;var c=/^#.+/;this.anchors.each(function(r,o){var q=a(o).attr("href");var s=q.split("#")[0],u;if(s&&(s===location.toString().split("#")[0]||(u=a("base")[0])&&s===u.href)){q=o.hash;o.href=q}if(c.test(q)){p.panels=p.panels.add(p._sanitizeSelector(q))}else{if(q!="#"){a.data(o,"href.tabs",q);a.data(o,"load.tabs",q.replace(/#.*$/,""));var w=p._tabId(o);o.href="#"+w;var v=a("#"+w);if(!v.length){v=a(d.panelTemplate).attr("id",w).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(p.panels[r-1]||p.list);v.data("destroy.tabs",true)}p.panels=p.panels.add(v)}else{d.disabled.push(r)}}});if(n){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all");this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(d.selected===undefined){if(location.hash){this.anchors.each(function(q,o){if(o.hash==location.hash){d.selected=q;return false}})}if(typeof d.selected!="number"&&d.cookie){d.selected=parseInt(p._cookie(),10)}if(typeof d.selected!="number"&&this.lis.filter(".ui-tabs-selected").length){d.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))}d.selected=d.selected||0}else{if(d.selected===null){d.selected=-1}}d.selected=((d.selected>=0&&this.anchors[d.selected])||d.selected<0)?d.selected:0;d.disabled=a.unique(d.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(q,o){return p.lis.index(q)}))).sort();if(a.inArray(d.selected,d.disabled)!=-1){d.disabled.splice(a.inArray(d.selected,d.disabled),1)}this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active");if(d.selected>=0&&this.anchors.length){this.panels.eq(d.selected).removeClass("ui-tabs-hide");this.lis.eq(d.selected).addClass("ui-tabs-selected ui-state-active");p.element.queue("tabs",function(){p._trigger("show",null,p._ui(p.anchors[d.selected],p.panels[d.selected]))});this.load(d.selected)}a(window).bind("unload",function(){p.lis.add(p.anchors).unbind(".tabs");p.lis=p.anchors=p.panels=null})}else{d.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))}this.element[d.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");if(d.cookie){this._cookie(d.selected,d.cookie)}for(var g=0,m;(m=this.lis[g]);g++){a(m)[a.inArray(g,d.disabled)!=-1&&!a(m).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled")}if(d.cache===false){this.anchors.removeData("cache.tabs")}this.lis.add(this.anchors).unbind(".tabs");if(d.event!="mouseover"){var f=function(o,i){if(i.is(":not(.ui-state-disabled)")){i.addClass("ui-state-"+o)}};var j=function(o,i){i.removeClass("ui-state-"+o)};this.lis.bind("mouseover.tabs",function(){f("hover",a(this))});this.lis.bind("mouseout.tabs",function(){j("hover",a(this))});this.anchors.bind("focus.tabs",function(){f("focus",a(this).closest("li"))});this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var b,h;if(d.fx){if(a.isArray(d.fx)){b=d.fx[0];h=d.fx[1]}else{b=h=d.fx}}function e(i,o){i.css({display:""});if(a.browser.msie&&o.opacity){i[0].style.removeAttribute("filter")}}var k=h?function(i,o){a(i).closest("li").removeClass("ui-state-default").addClass("ui-tabs-selected ui-state-active");o.hide().removeClass("ui-tabs-hide").animate(h,h.duration||"normal",function(){e(o,h);p._trigger("show",null,p._ui(i,o[0]))})}:function(i,o){a(i).closest("li").removeClass("ui-state-default").addClass("ui-tabs-selected ui-state-active");o.removeClass("ui-tabs-hide");p._trigger("show",null,p._ui(i,o[0]))};var l=b?function(o,i){i.animate(b,b.duration||"normal",function(){p.lis.removeClass("ui-tabs-selected ui-state-active").addClass("ui-state-default");i.addClass("ui-tabs-hide");e(i,b);p.element.dequeue("tabs")})}:function(o,i,q){p.lis.removeClass("ui-tabs-selected ui-state-active").addClass("ui-state-default");i.addClass("ui-tabs-hide");p.element.dequeue("tabs")};this.anchors.bind(d.event+".tabs",function(){var o=this,r=a(this).closest("li"),i=p.panels.filter(":not(.ui-tabs-hide)"),q=a(p._sanitizeSelector(this.hash));if((r.hasClass("ui-tabs-selected")&&!d.collapsible)||r.hasClass("ui-state-disabled")||r.hasClass("ui-state-processing")||p._trigger("select",null,p._ui(this,q[0]))===false){this.blur();return false}d.selected=p.anchors.index(this);p.abort();if(d.collapsible){if(r.hasClass("ui-tabs-selected")){d.selected=-1;if(d.cookie){p._cookie(d.selected,d.cookie)}p.element.queue("tabs",function(){l(o,i)}).dequeue("tabs");this.blur();return false}else{if(!i.length){if(d.cookie){p._cookie(d.selected,d.cookie)}p.element.queue("tabs",function(){k(o,q)});p.load(p.anchors.index(this));this.blur();return false}}}if(d.cookie){p._cookie(d.selected,d.cookie)}if(q.length){if(i.length){p.element.queue("tabs",function(){l(o,i)})}p.element.queue("tabs",function(){k(o,q)});p.load(p.anchors.index(this))}else{throw"jQuery UI Tabs: Mismatching fragment identifier."}if(a.browser.msie){this.blur()}});this.anchors.bind("click.tabs",function(){return false})},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var c=a.data(this,"href.tabs");if(c){this.href=c}var d=a(this).unbind(".tabs");a.each(["href","load","cache"],function(e,f){d.removeData(f+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){if(a.data(this,"destroy.tabs")){a(this).remove()}else{a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}});if(b.cookie){this._cookie(null,b.cookie)}},add:function(e,d,c){if(c===undefined){c=this.anchors.length}var b=this,g=this.options,i=a(g.tabTemplate.replace(/#\{href\}/g,e).replace(/#\{label\}/g,d)),h=!e.indexOf("#")?e.replace("#",""):this._tabId(a("a",i)[0]);i.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var f=a("#"+h);if(!f.length){f=a(g.panelTemplate).attr("id",h).data("destroy.tabs",true)}f.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(c>=this.lis.length){i.appendTo(this.list);f.appendTo(this.list[0].parentNode)}else{i.insertBefore(this.lis[c]);f.insertBefore(this.panels[c])}g.disabled=a.map(g.disabled,function(k,j){return k>=c?++k:k});this._tabify();if(this.anchors.length==1){i.addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[0],b.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[c],this.panels[c]))},remove:function(b){var d=this.options,e=this.lis.eq(b).remove(),c=this.panels.eq(b).remove();if(e.hasClass("ui-tabs-selected")&&this.anchors.length>1){this.select(b+(b+1<this.anchors.length?1:-1))}d.disabled=a.map(a.grep(d.disabled,function(g,f){return g!=b}),function(g,f){return g>=b?--g:g});this._tabify();this._trigger("remove",null,this._ui(e.find("a")[0],c[0]))},enable:function(b){var c=this.options;if(a.inArray(b,c.disabled)==-1){return}this.lis.eq(b).removeClass("ui-state-disabled");c.disabled=a.grep(c.disabled,function(e,d){return e!=b});this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b]))},disable:function(c){var b=this,d=this.options;if(c!=d.selected){this.lis.eq(c).addClass("ui-state-disabled");d.disabled.push(c);d.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}},select:function(b){if(typeof b=="string"){b=this.anchors.index(this.anchors.filter("[href$="+b+"]"))}else{if(b===null){b=-1}}if(b==-1&&this.options.collapsible){b=this.options.selected}this.anchors.eq(b).trigger(this.options.event+".tabs")},load:function(e){var c=this,g=this.options,b=this.anchors.eq(e)[0],d=a.data(b,"load.tabs");this.abort();if(!d||this.element.queue("tabs").length!==0&&a.data(b,"cache.tabs")){this.element.dequeue("tabs");return}this.lis.eq(e).addClass("ui-state-processing");if(g.spinner){var f=a("span",b);f.data("label.tabs",f.html()).html(g.spinner)}this.xhr=a.ajax(a.extend({},g.ajaxOptions,{url:d,success:function(i,h){a(c._sanitizeSelector(b.hash)).html(i);c._cleanup();if(g.cache){a.data(b,"cache.tabs",true)}c._trigger("load",null,c._ui(c.anchors[e],c.panels[e]));try{g.ajaxOptions.success(i,h)}catch(j){}c.element.dequeue("tabs")}}))},abort:function(){this.element.queue([]);this.panels.stop(false,true);if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup()},url:function(c,b){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",b)},length:function(){return this.anchors.length}});a.extend(a.ui.tabs,{version:"1.7.2",getter:"length",defaults:{ajaxOptions:null,cache:false,cookie:null,collapsible:false,disabled:[],event:"click",fx:null,idPrefix:"ui-tabs-",panelTemplate:"<div></div>",spinner:"<em>Loading&#8230;</em>",tabTemplate:'<li><a href="#{href}"><span>#{label}</span></a></li>'}});a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(d,f){var b=this,g=this.options;var c=b._rotate||(b._rotate=function(h){clearTimeout(b.rotation);b.rotation=setTimeout(function(){var i=g.selected;b.select(++i<b.anchors.length?i:0)},d);if(h){h.stopPropagation()}});var e=b._unrotate||(b._unrotate=!f?function(h){if(h.clientX){b.rotate(null)}}:function(h){t=g.selected;c()});if(d){this.element.bind("tabsshow",c);this.anchors.bind(g.event+".tabs",e);c()}else{clearTimeout(b.rotation);this.element.unbind("tabsshow",c);this.anchors.unbind(g.event+".tabs",e);delete this._rotate;delete this._unrotate}}})})(jQuery);
+(function(c){c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.2",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==
+"hidden")return false;b=b&&b=="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,f,g){return c.ui.isOverAxis(a,d,f)&&c.ui.isOverAxis(b,e,g)},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,
+NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect",
+"none")},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",
+1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==undefined)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b=="absolute"||b=="relative"||b=="fixed"){b=parseInt(a.css("zIndex"));if(!isNaN(b)&&b!=0)return b}a=a.parent()}}return 0}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");return(/input|select|textarea|button|object/.test(b)?
+!a.disabled:"a"==b||"area"==b?a.href||!isNaN(d):!isNaN(d))&&!c(a)["area"==b?"parents":"closest"](":hidden").length},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}})}})(jQuery);
+(function(b){var j=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add(this).each(function(){b(this).triggerHandler("remove")});return j.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend({},c.options);b[e][a].prototype=
+b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==undefined){h=i;return false}}):this.each(function(){var g=
+b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){this.element=b(c).data(this.widgetName,this);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();
+this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===undefined)return this.options[a];d={};d[a]=c}b.each(d,function(f,
+h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=
+b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
+(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&
+this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();
+return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.browser.safari||a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&
+this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-
+a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
+(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper==
+"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b=
+this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;return true},_mouseStart:function(a){var b=this.options;this.helper=this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-
+this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();
+d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);return true},_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||
+this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b=false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if(!this.element[0]||!this.element[0].parentNode)return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,
+b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle||!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==
+a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone():this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&&a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
+0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
+this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-
+(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment==
+"parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&
+a.containment.constructor!=Array){var b=d(a.containment)[0];if(b){a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),
+10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
+this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():
+f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])e=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+
+this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])e=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;e=this.originalPageX+
+Math.round((e-this.originalPageX)/b.grid[0])*b.grid[0];e=this.containment?!(e-this.offset.click.left<this.containment[0]||e-this.offset.click.left>this.containment[2])?e:!(e-this.offset.click.left<this.containment[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-
+this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=
+this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b,c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.2"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var g=d.data(this,"sortable");
+if(g&&!g.options.disabled){c.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;
+c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=
+1;this.instance.currentItem=d(f).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;
+this.instance.offset.parent.top-=c.offset.parent.top-this.instance.offset.parent.top;c._trigger("toSortable",a);c.dropped=this.instance.element;c.currentItem=c.element;this.instance.fromOutside=c}this.instance.currentItem&&this.instance._mouseDrag(a)}else if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",a,this.instance._uiHash(this.instance));this.instance._mouseStop(a,true);this.instance.options.helper=
+this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&&this.instance.placeholder.remove();c._trigger("fromSortable",a);c.dropped=false}})}});d.ui.plugin.add("draggable","cursor",{start:function(){var a=d("body"),b=d(this).data("draggable").options;if(a.css("cursor"))b._cursor=a.css("cursor");a.css("cursor",b.cursor)},stop:function(){var a=d(this).data("draggable").options;a._cursor&&d("body").css("cursor",a._cursor)}});d.ui.plugin.add("draggable","iframeFix",{start:function(){var a=
+d(this).data("draggable").options;d(a.iframeFix===true?"iframe":a.iframeFix).each(function(){d('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")})},stop:function(){d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;
+if(a.css("opacity"))b._opacity=a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!=
+"HTML"){if(!c.axis||c.axis!="x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop+c.scrollSpeed;else if(a.pageY-b.overflowOffset.top<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop-c.scrollSpeed;if(!c.axis||c.axis!="y")if(b.overflowOffset.left+b.scrollParent[0].offsetWidth-a.pageX<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft+c.scrollSpeed;else if(a.pageX-
+b.overflowOffset.left<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft-c.scrollSpeed}else{if(!c.axis||c.axis!="x")if(a.pageY-d(document).scrollTop()<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()-c.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()+c.scrollSpeed);if(!c.axis||c.axis!="y")if(a.pageX-d(document).scrollLeft()<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()-
+c.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()+c.scrollSpeed)}f!==false&&d.ui.ddmanager&&!c.dropBehaviour&&d.ui.ddmanager.prepareOffsets(b,a)}});d.ui.plugin.add("draggable","snap",{start:function(){var a=d(this).data("draggable"),b=a.options;a.snapElements=[];d(b.snap.constructor!=String?b.snap.items||":data(draggable)":b.snap).each(function(){var c=d(this),f=c.offset();this!=a.element[0]&&a.snapElements.push({item:this,
+width:c.outerWidth(),height:c.outerHeight(),top:f.top,left:f.left})})},drag:function(a,b){for(var c=d(this).data("draggable"),f=c.options,e=f.snapTolerance,g=b.offset.left,n=g+c.helperProportions.width,m=b.offset.top,o=m+c.helperProportions.height,h=c.snapElements.length-1;h>=0;h--){var i=c.snapElements[h].left,k=i+c.snapElements[h].width,j=c.snapElements[h].top,l=j+c.snapElements[h].height;if(i-e<g&&g<k+e&&j-e<m&&m<l+e||i-e<g&&g<k+e&&j-e<o&&o<l+e||i-e<n&&n<k+e&&j-e<m&&m<l+e||i-e<n&&n<k+e&&j-e<o&&
+o<l+e){if(f.snapMode!="inner"){var p=Math.abs(j-o)<=e,q=Math.abs(l-m)<=e,r=Math.abs(i-n)<=e,s=Math.abs(k-g)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j-c.helperProportions.height,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i-c.helperProportions.width}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k}).left-c.margins.left}var t=
+p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(j-m)<=e;q=Math.abs(l-o)<=e;r=Math.abs(i-g)<=e;s=Math.abs(k-n)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:j,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:l-c.helperProportions.height,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:i}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:k-c.helperProportions.width}).left-c.margins.left}if(!c.snapElements[h].snapping&&
+(p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=p||q||r||s||t}else{c.snapElements[h].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[h].item}));c.snapElements[h].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"),
+10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery);
+(function(d){d.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"},_create:function(){var a=this.options,b=a.accept;this.isover=0;this.isout=1;this.accept=d.isFunction(b)?b:function(c){return c.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};d.ui.ddmanager.droppables[a.scope]=d.ui.ddmanager.droppables[a.scope]||[];d.ui.ddmanager.droppables[a.scope].push(this);
+a.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var a=d.ui.ddmanager.droppables[this.options.scope],b=0;b<a.length;b++)a[b]==this&&a.splice(b,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(a,b){if(a=="accept")this.accept=d.isFunction(b)?b:function(c){return c.is(b)};d.Widget.prototype._setOption.apply(this,arguments)},_activate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&
+this.element.addClass(this.options.activeClass);b&&this._trigger("activate",a,this.ui(b))},_deactivate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass);b&&this._trigger("deactivate",a,this.ui(b))},_over:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.addClass(this.options.hoverClass);
+this._trigger("over",a,this.ui(b))}},_out:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("out",a,this.ui(b))}},_drop:function(a,b){var c=b||d.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return false;var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var g=
+d.data(this,"droppable");if(g.options.greedy&&!g.options.disabled&&g.options.scope==c.options.scope&&g.accept.call(g.element[0],c.currentItem||c.element)&&d.ui.intersect(c,d.extend(g,{offset:g.element.offset()}),g.options.tolerance)){e=true;return false}});if(e)return false;if(this.accept.call(this.element[0],c.currentItem||c.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass);this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("drop",
+a,this.ui(c));return this.element}return false},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}});d.extend(d.ui.droppable,{version:"1.8.2"});d.ui.intersect=function(a,b,c){if(!b.offset)return false;var e=(a.positionAbs||a.position.absolute).left,g=e+a.helperProportions.width,f=(a.positionAbs||a.position.absolute).top,h=f+a.helperProportions.height,i=b.offset.left,k=i+b.proportions.width,j=b.offset.top,l=j+b.proportions.height;
+switch(c){case "fit":return i<e&&g<k&&j<f&&h<l;case "intersect":return i<e+a.helperProportions.width/2&&g-a.helperProportions.width/2<k&&j<f+a.helperProportions.height/2&&h-a.helperProportions.height/2<l;case "pointer":return d.ui.isOver((a.positionAbs||a.position.absolute).top+(a.clickOffset||a.offset.click).top,(a.positionAbs||a.position.absolute).left+(a.clickOffset||a.offset.click).left,j,i,b.proportions.height,b.proportions.width);case "touch":return(f>=j&&f<=l||h>=j&&h<=l||f<j&&h>l)&&(e>=i&&
+e<=k||g>=i&&g<=k||e<i&&g>k);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f<c.length;f++)if(!(c[f].options.disabled||a&&!c[f].accept.call(c[f].element[0],a.currentItem||a.element))){for(var h=0;h<g.length;h++)if(g[h]==c[f].element[0]){c[f].proportions.height=0;continue a}c[f].visible=c[f].element.css("display")!=
+"none";if(c[f].visible){c[f].offset=c[f].element.offset();c[f].proportions={width:c[f].element[0].offsetWidth,height:c[f].element[0].offsetHeight};e=="mousedown"&&c[f]._activate.call(c[f],b)}}},drop:function(a,b){var c=false;d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&d.ui.intersect(a,this,this.options.tolerance))c=c||this._drop.call(this,b);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],a.currentItem||
+a.element)){this.isout=1;this.isover=0;this._deactivate.call(this,b)}}});return c},drag:function(a,b){a.options.refreshPositions&&d.ui.ddmanager.prepareOffsets(a,b);d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var c=d.ui.intersect(a,this,this.options.tolerance);if(c=!c&&this.isover==1?"isout":c&&this.isover==0?"isover":null){var e;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");if(g.length){e=
+d.data(g[0],"droppable");e.greedyChild=c=="isover"?1:0}}if(e&&c=="isover"){e.isover=0;e.isout=1;e._out.call(e,b)}this[c]=1;this[c=="isout"?"isover":"isout"]=0;this[c=="isover"?"_over":"_out"].call(this,b);if(e&&c=="isout"){e.isout=0;e.isover=1;e._over.call(e,b)}}}})}}})(jQuery);
+(function(d){d.widget("ui.resizable",d.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1E3},_create:function(){var b=this,a=this.options;this.element.addClass("ui-resizable");d.extend(this,{_aspectRatio:!!a.aspectRatio,aspectRatio:a.aspectRatio,originalElement:this.element,
+_proportionallyResizeElements:[],_helper:a.helper||a.ghost||a.animate?a.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){/relative/.test(this.element.css("position"))&&d.browser.opera&&this.element.css({position:"relative",top:"auto",left:"auto"});this.element.wrap(d('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),
+top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=
+this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!d(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",
+nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var e=0;e<c.length;e++){var g=d.trim(c[e]),f=d('<div class="ui-resizable-handle '+("ui-resizable-"+g)+'"></div>');/sw|se|ne|nw/.test(g)&&f.css({zIndex:++a.zIndex});"se"==g&&f.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[g]=".ui-resizable-"+g;this.element.append(f)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor==
+String)this.handles[i]=d(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=d(this.handles[i],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,l);this._proportionallyResize()}d(this.handles[i])}};this._renderAxis(this.element);this._handles=d(".ui-resizable-handle",this.element).disableSelection();
+this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();d(this.element).addClass("ui-resizable-autohide").hover(function(){d(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){d(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){d(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};
+if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(d(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(),
+e=this.element;this.resizing=true;this.documentScroll={top:d(document).scrollTop(),left:d(document).scrollLeft()};if(e.is(".ui-draggable")||/absolute/.test(e.css("position")))e.css({position:"absolute",top:c.top,left:c.left});d.browser.opera&&/relative/.test(e.css("position"))&&e.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var g=m(this.helper.css("top"));if(a.containment){c+=d(a.containment).scrollLeft()||0;g+=d(a.containment).scrollTop()||0}this.offset=
+this.helper.offset();this.position={left:c,top:g};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:c,top:g};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio:
+this.originalSize.width/this.originalSize.height||1;a=d(".ui-resizable-"+this.axis).css("cursor");d("body").css("cursor",a=="auto"?this.axis+"-resize":a);e.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,e=this._change[this.axis];if(!e)return false;c=e.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize",
+b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var e=this._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName);e=g&&d.ui.hasScroll(e[0],"left")?0:c.sizeDiff.height;
+g={width:c.size.width-(g?0:c.sizeDiff.width),height:c.size.height-e};e=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var f=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(d.extend(g,{top:f,left:e}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}d("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",
+b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(k(b.left))this.position.left=b.left;if(k(b.top))this.position.top=b.top;if(k(b.height))this.size.height=b.height;if(k(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,e=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(e=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(e=="nw"){b.top=
+a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,e=k(b.width)&&a.maxWidth&&a.maxWidth<b.width,g=k(b.height)&&a.maxHeight&&a.maxHeight<b.height,f=k(b.width)&&a.minWidth&&a.minWidth>b.width,h=k(b.height)&&a.minHeight&&a.minHeight>b.height;if(f)b.width=a.minWidth;if(h)b.height=a.minHeight;if(e)b.width=a.maxWidth;if(g)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height,
+l=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(f&&l)b.left=i-a.minWidth;if(e&&l)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(g&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a<this._proportionallyResizeElements.length;a++){var c=this._proportionallyResizeElements[a];if(!this.borderDif){var e=[c.css("borderTopWidth"),
+c.css("borderRightWidth"),c.css("borderBottomWidth"),c.css("borderLeftWidth")],g=[c.css("paddingTop"),c.css("paddingRight"),c.css("paddingBottom"),c.css("paddingLeft")];this.borderDif=d.map(e,function(f,h){f=parseInt(f,10)||0;h=parseInt(g[h],10)||0;return f+h})}d.browser.msie&&(d(b).is(":hidden")||d(b).parents(":hidden").length)||c.css({height:b.height()-this.borderDif[0]-this.borderDif[2]||0,width:b.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var b=this.options;this.elementOffset=
+this.element.offset();if(this._helper){this.helper=this.helper||d('<div style="overflow:hidden;"></div>');var a=d.browser.msie&&d.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+
+a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return d.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return d.extend(this._change.n.apply(this,
+arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return d.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){d.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});d.extend(d.ui.resizable,
+{version:"1.8.2"});d.ui.plugin.add("resizable","alsoResize",{start:function(){var b=d(this).data("resizable").options,a=function(c){d(c).each(function(){d(this).data("resizable-alsoresize",{width:parseInt(d(this).width(),10),height:parseInt(d(this).height(),10),left:parseInt(d(this).css("left"),10),top:parseInt(d(this).css("top"),10)})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else d.each(b.alsoResize,function(c){a(c)});
+else a(b.alsoResize)},resize:function(){var b=d(this).data("resizable"),a=b.options,c=b.originalSize,e=b.originalPosition,g={height:b.size.height-c.height||0,width:b.size.width-c.width||0,top:b.position.top-e.top||0,left:b.position.left-e.left||0},f=function(h,i){d(h).each(function(){var j=d(this),l=d(this).data("resizable-alsoresize"),p={};d.each((i&&i.length?i:["width","height","top","left"])||["width","height","top","left"],function(n,o){if((n=(l[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(/relative/.test(j.css("position"))&&
+d.browser.opera){b._revertToRelativePosition=true;j.css({position:"absolute",top:"auto",left:"auto"})}j.css(p)})};typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?d.each(a.alsoResize,function(h,i){f(h,i)}):f(a.alsoResize)},stop:function(){var b=d(this).data("resizable");if(b._revertToRelativePosition&&d.browser.opera){b._revertToRelativePosition=false;el.css({position:"relative"})}d(this).removeData("resizable-alsoresize-start")}});d.ui.plugin.add("resizable","animate",{stop:function(b){var a=
+d(this).data("resizable"),c=a.options,e=a._proportionallyResizeElements,g=e.length&&/textarea/i.test(e[0].nodeName),f=g&&d.ui.hasScroll(e[0],"left")?0:a.sizeDiff.height;g={width:a.size.width-(g?0:a.sizeDiff.width),height:a.size.height-f};f=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(d.extend(g,h&&f?{top:h,left:f}:{}),{duration:c.animateDuration,easing:c.animateEasing,
+step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};e&&e.length&&d(e[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",b)}})}});d.ui.plugin.add("resizable","containment",{start:function(){var b=d(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof d?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement=
+d(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:d(document),left:0,top:0,width:d(document).width(),height:d(document).height()||document.body.parentNode.scrollHeight}}else{var e=d(a),g=[];d(["Top","Right","Left","Bottom"]).each(function(i,j){g[i]=m(e.css("padding"+j))});b.containerOffset=e.offset();b.containerPosition=e.position();b.containerSize={height:e.innerHeight()-g[3],width:e.innerWidth()-g[1]};c=b.containerOffset;
+var f=b.containerSize.height,h=b.containerSize.width;h=d.ui.hasScroll(a,"left")?a.scrollWidth:h;f=d.ui.hasScroll(a)?a.scrollHeight:f;b.parentData={element:a,left:c.left,top:c.top,width:h,height:f}}}},resize:function(b){var a=d(this).data("resizable"),c=a.options,e=a.containerOffset,g=a.position;b=a._aspectRatio||b.shiftKey;var f={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))f=e;if(g.left<(a._helper?e.left:0)){a.size.width+=a._helper?a.position.left-e.left:
+a.position.left-f.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?e.left:0}if(g.top<(a._helper?e.top:0)){a.size.height+=a._helper?a.position.top-e.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?e.top:0}a.offset.left=a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-f.left:a.offset.left-f.left)+a.sizeDiff.width);e=Math.abs((a._helper?a.offset.top-f.top:a.offset.top-
+e.top)+a.sizeDiff.height);g=a.containerElement.get(0)==a.element.parent().get(0);f=/relative|absolute/.test(a.containerElement.css("position"));if(g&&f)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(e+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-e;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=d(this).data("resizable"),a=b.options,c=b.containerOffset,e=b.containerPosition,
+g=b.containerElement,f=d(b.helper),h=f.offset(),i=f.outerWidth()-b.sizeDiff.width;f=f.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f});b._helper&&!a.animate&&/static/.test(g.css("position"))&&d(this).css({left:h.left-e.left-c.left,width:i,height:f})}});d.ui.plugin.add("resizable","ghost",{start:function(){var b=d(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25,
+display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=d(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=d(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});d.ui.plugin.add("resizable","grid",{resize:function(){var b=
+d(this).data("resizable"),a=b.options,c=b.size,e=b.originalSize,g=b.originalPosition,f=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-e.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-e.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a}else if(/^(ne)$/.test(f)){b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}else{if(/^(sw)$/.test(f)){b.size.width=e.width+h;b.size.height=
+e.height+a}else{b.size.width=e.width+h;b.size.height=e.height+a;b.position.top=g.top-a}b.position.left=g.left-h}}});var m=function(b){return parseInt(b,10)||0},k=function(b){return!isNaN(parseInt(b,10))}})(jQuery);
+(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"),
+selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("<div class='ui-selectable-helper'></div>")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX,
+c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({"z-index":100,position:"absolute",left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting");
+b.unselecting=true;f._trigger("unselecting",c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f=
+this;this.dragged=true;if(!this.options.disabled){var d=this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.right<b||a.top>i||a.bottom<g);else if(d.tolerance=="fit")k=a.left>b&&a.right<h&&a.top>g&&a.bottom<i;if(k){if(a.selected){a.$element.removeClass("ui-selected");
+a.selected=false}if(a.unselecting){a.$element.removeClass("ui-unselecting");a.unselecting=false}if(!a.selecting){a.$element.addClass("ui-selecting");a.selecting=true;f._trigger("selecting",c,{selecting:a.element})}}else{if(a.selecting)if(c.metaKey&&a.startselected){a.$element.removeClass("ui-selecting");a.selecting=false;a.$element.addClass("ui-selected");a.selected=true}else{a.$element.removeClass("ui-selecting");a.selecting=false;if(a.startselected){a.$element.addClass("ui-unselecting");a.unselecting=
+true}f._trigger("unselecting",c,{unselecting:a.element})}if(a.selected)if(!c.metaKey&&!a.startselected){a.$element.removeClass("ui-selected");a.selected=false;a.$element.addClass("ui-unselecting");a.unselecting=true;f._trigger("unselecting",c,{unselecting:a.element})}}}});return false}},_mouseStop:function(c){var f=this;this.dragged=false;e(".ui-unselecting",this.element[0]).each(function(){var d=e.data(this,"selectable-item");d.$element.removeClass("ui-unselecting");d.unselecting=false;d.startselected=
+false;f._trigger("unselected",c,{unselected:d.element})});e(".ui-selecting",this.element[0]).each(function(){var d=e.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected");d.selecting=false;d.selected=true;d.startselected=true;f._trigger("selected",c,{selected:d.element})});this._trigger("stop",c);this.helper.remove();return false}});e.extend(e.ui.selectable,{version:"1.8.2"})})(jQuery);
+(function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable");
+this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,
+arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=
+c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,
+{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();
+if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",
+a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");
+if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+
+this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+
+b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+
+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,
+c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==
+document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",
+null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):
+d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},
+_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?j:g<b+this.helperProportions.width/
+2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?c&&c=="right"||a=="down"?2:1:a&&(a=="down"?2:1)},_intersectsWithSides:function(a){var b=
+d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=
+this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?
+h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),
+b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?
+i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&this.helper)this.offset.parent=this._getParentOffset();for(var b=this.items.length-1;b>=0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,
+c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=
+this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-
+parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],
+this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=
+1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=this.containers[c];e?this._rearrange(a,e,null,true):this._rearrange(a,null,this.containers[c].element,true);this._trigger("change",a,this._uiHash());this.containers[c]._trigger("change",
+a,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}}},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a,this.currentItem])):b.helper=="clone"?this.currentItem.clone():this.currentItem;a.parents("body").length||d(b.appendTo!="parent"?b.appendTo:this.currentItem[0].parentNode)[0].appendChild(a[0]);if(a[0]==
+this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(a[0].style.width==""||b.forceHelperSize)a.width(this.currentItem.width());if(a[0].style.height==""||b.forceHelperSize)a.height(this.currentItem.height());return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
+0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
+this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-
+(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;
+if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)){var b=
+d(a.containment)[0];a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-
+this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);return{top:b.top+
+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
+this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset();var f=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])f=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;
+if(a.pageX-this.offset.click.left>this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;f=this.originalPageX+Math.round((f-
+this.originalPageX)/b.grid[0])*b.grid[0];f=this.containment?!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:!(f-this.offset.click.left<this.containment[0])?f-b.grid[0]:f+b.grid[0]:f}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+
+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())}},_rearrange:function(a,b,c,e){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling);this.counter=this.counter?++this.counter:1;var f=this,g=this.counter;window.setTimeout(function(){g==f.counter&&f.refreshPositions(!e)},0)},_clear:function(a,b){this.reverting=false;var c=[];!this._noFinalSort&&
+this.currentItem[0].parentNode&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var e in this._storedCSS)if(this._storedCSS[e]=="auto"||this._storedCSS[e]=="static")this._storedCSS[e]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",f,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||
+this.domPosition.parent!=this.currentItem.parent()[0])&&!b)c.push(function(f){this._trigger("update",f,this._uiHash())});if(!d.ui.contains(this.element[0],this.currentItem[0])){b||c.push(function(f){this._trigger("remove",f,this._uiHash())});for(e=this.containers.length-1;e>=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",
+g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",
+this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=
+0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});d.extend(d.ui.sortable,{version:"1.8.2"})})(jQuery);
+jQuery.effects||function(f){function k(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1],
+16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return l.transparent;return l[f.trim(c).toLowerCase()]}function q(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return k(b)}function m(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,
+a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function n(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in r||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function s(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function j(c,a,b,d){if(typeof c=="object"){d=
+a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(f.isFunction(b)){d=b;b=null}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:f.fx.speeds[b]||f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=q(b.elem,a);b.end=k(b.end);b.colorInit=
+true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var l={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,
+183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,
+165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},o=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,d){if(f.isFunction(b)){d=b;b=null}return this.each(function(){var e=f(this),g=e.attr("style")||" ",h=n(m.call(this)),p,t=e.attr("className");f.each(o,function(u,
+i){c[i]&&e[i+"Class"](c[i])});p=n(m.call(this));e.attr("className",t);e.animate(s(h,p),a,b,function(){f.each(o,function(u,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)})})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?
+f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===undefined?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.2",save:function(c,a){for(var b=0;b<a.length;b++)a[b]!==
+null&&c.data("ec.storage."+a[b],c[0].style[a[b]])},restore:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.css(a[b],c.data("ec.storage."+a[b]))},setMode:function(c,a){if(a=="toggle")a=c.is(":hidden")?"show":"hide";return a},getBaseline:function(c,a){var b;switch(c[0]){case "top":b=0;break;case "middle":b=0.5;break;case "bottom":b=1;break;default:b=c[0]/a.height}switch(c[1]){case "left":c=0;break;case "center":c=0.5;break;case "right":c=1;break;default:c=c[1]/a.width}return{x:c,y:b}},createWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent();
+var a={width:c.outerWidth(true),height:c.outerHeight(true),"float":c.css("float")},b=f("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"});
+c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=j.apply(this,arguments);a={options:a[1],duration:a[2],callback:a[3]};var b=f.effects[c];return b&&!f.fx.off?b.call(this,a):this},_show:f.fn.show,show:function(c){if(!c||
+typeof c=="number"||f.fx.speeds[c])return this._show.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(!c||typeof c=="number"||f.fx.speeds[c])return this._hide.apply(this,arguments);else{var a=j.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||typeof c=="boolean"||f.isFunction(c))return this.__toggle.apply(this,
+arguments);else{var a=j.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,
+a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+
+b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,
+10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*
+a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return-(h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g))+b},easeOutElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return h*Math.pow(2,-10*a)*Math.sin((a*e-c)*2*Math.PI/g)+d+b},easeInOutElastic:function(c,
+a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e/2)==2)return b+d;g||(g=e*0.3*1.5);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);if(a<1)return-0.5*h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)+b;return h*Math.pow(2,-10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)*0.5+d+b},easeInBack:function(c,a,b,d,e,g){if(g==undefined)g=1.70158;return d*(a/=e)*a*((g+1)*a-g)+b},easeOutBack:function(c,a,b,d,e,g){if(g==undefined)g=1.70158;return d*((a=a/e-1)*a*((g+1)*a+g)+1)+b},easeInOutBack:function(c,
+a,b,d,e,g){if(g==undefined)g=1.70158;if((a/=e/2)<1)return d/2*a*a*(((g*=1.525)+1)*a-g)+b;return d/2*((a-=2)*a*(((g*=1.525)+1)*a+g)+2)+b},easeInBounce:function(c,a,b,d,e){return d-f.easing.easeOutBounce(c,e-a,0,d,e)+b},easeOutBounce:function(c,a,b,d,e){return(a/=e)<1/2.75?d*7.5625*a*a+b:a<2/2.75?d*(7.5625*(a-=1.5/2.75)*a+0.75)+b:a<2.5/2.75?d*(7.5625*(a-=2.25/2.75)*a+0.9375)+b:d*(7.5625*(a-=2.625/2.75)*a+0.984375)+b},easeInOutBounce:function(c,a,b,d,e){if(a<e/2)return f.easing.easeInBounce(c,a*2,0,
+d,e)*0.5+b;return f.easing.easeOutBounce(c,a*2-e,0,d,e)*0.5+d*0.5+b}})}(jQuery);
+(function(b){b.effects.blind=function(c){return this.queue(function(){var a=b(this),g=["position","top","left"],f=b.effects.setMode(a,c.options.mode||"hide"),d=c.options.direction||"vertical";b.effects.save(a,g);a.show();var e=b.effects.createWrapper(a).css({overflow:"hidden"}),h=d=="vertical"?"height":"width";d=d=="vertical"?e.height():e.width();f=="show"&&e.css(h,0);var i={};i[h]=f=="show"?d:0;e.animate(i,c.duration,c.options.easing,function(){f=="hide"&&a.hide();b.effects.restore(a,g);b.effects.removeWrapper(a);
+c.callback&&c.callback.apply(a[0],arguments);a.dequeue()})})}})(jQuery);
+(function(e){e.effects.bounce=function(b){return this.queue(function(){var a=e(this),l=["position","top","left"],h=e.effects.setMode(a,b.options.mode||"effect"),d=b.options.direction||"up",c=b.options.distance||20,m=b.options.times||5,i=b.duration||250;/show|hide/.test(h)&&l.push("opacity");e.effects.save(a,l);a.show();e.effects.createWrapper(a);var f=d=="up"||d=="down"?"top":"left";d=d=="up"||d=="left"?"pos":"neg";c=b.options.distance||(f=="top"?a.outerHeight({margin:true})/3:a.outerWidth({margin:true})/
+3);if(h=="show")a.css("opacity",0).css(f,d=="pos"?-c:c);if(h=="hide")c/=m*2;h!="hide"&&m--;if(h=="show"){var g={opacity:1};g[f]=(d=="pos"?"+=":"-=")+c;a.animate(g,i/2,b.options.easing);c/=2;m--}for(g=0;g<m;g++){var j={},k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing);c=h=="hide"?c*2:c/2}if(h=="hide"){g={opacity:0};g[f]=(d=="pos"?"-=":"+=")+c;a.animate(g,i/2,b.options.easing,function(){a.hide();e.effects.restore(a,l);e.effects.removeWrapper(a);
+b.callback&&b.callback.apply(this,arguments)})}else{j={};k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing,function(){e.effects.restore(a,l);e.effects.removeWrapper(a);b.callback&&b.callback.apply(this,arguments)})}a.queue("fx",function(){a.dequeue()});a.dequeue()})}})(jQuery);
+(function(b){b.effects.clip=function(e){return this.queue(function(){var a=b(this),i=["position","top","left","height","width"],f=b.effects.setMode(a,e.options.mode||"hide"),c=e.options.direction||"vertical";b.effects.save(a,i);a.show();var d=b.effects.createWrapper(a).css({overflow:"hidden"});d=a[0].tagName=="IMG"?d:a;var g={size:c=="vertical"?"height":"width",position:c=="vertical"?"top":"left"};c=c=="vertical"?d.height():d.width();if(f=="show"){d.css(g.size,0);d.css(g.position,c/2)}var h={};h[g.size]=
+f=="show"?c:0;h[g.position]=f=="show"?0:c/2;d.animate(h,{queue:false,duration:e.duration,easing:e.options.easing,complete:function(){f=="hide"&&a.hide();b.effects.restore(a,i);b.effects.removeWrapper(a);e.callback&&e.callback.apply(a[0],arguments);a.dequeue()}})})}})(jQuery);
+(function(c){c.effects.drop=function(d){return this.queue(function(){var a=c(this),h=["position","top","left","opacity"],e=c.effects.setMode(a,d.options.mode||"hide"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a);var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true})/2:a.outerWidth({margin:true})/2);if(e=="show")a.css("opacity",0).css(f,b=="pos"?-g:g);var i={opacity:e=="show"?1:
+0};i[f]=(e=="show"?b=="pos"?"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+(function(j){j.effects.explode=function(a){return this.queue(function(){var c=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3,d=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3;a.options.mode=a.options.mode=="toggle"?j(this).is(":visible")?"hide":"show":a.options.mode;var b=j(this).show().css("visibility","hidden"),g=b.offset();g.top-=parseInt(b.css("marginTop"),10)||0;g.left-=parseInt(b.css("marginLeft"),10)||0;for(var h=b.outerWidth(true),i=b.outerHeight(true),e=0;e<c;e++)for(var f=
+0;f<d;f++)b.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+
+e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery);
+(function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery);
+(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100*
+f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery);
+(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&&
+this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c<times;c++){b.animate({opacity:animateTo},duration,a.options.easing);animateTo=(animateTo+1)%2}b.animate({opacity:animateTo},duration,
+a.options.easing,function(){animateTo==0&&b.hide();a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()}).dequeue()})}})(jQuery);
+(function(c){c.effects.puff=function(b){return this.queue(function(){var a=c(this),e=c.effects.setMode(a,b.options.mode||"hide"),g=parseInt(b.options.percent,10)||150,h=g/100,i={height:a.height(),width:a.width()};c.extend(b.options,{fade:true,mode:e,percent:e=="hide"?g:100,from:e=="hide"?i:{height:i.height*h,width:i.width*h}});a.effect("scale",b.options,b.duration,b.callback);a.dequeue()})};c.effects.scale=function(b){return this.queue(function(){var a=c(this),e=c.extend(true,{},b.options),g=c.effects.setMode(a,
+b.options.mode||"effect"),h=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:g=="hide"?0:100),i=b.options.direction||"both",f=b.options.origin;if(g!="effect"){e.origin=f||["middle","center"];e.restore=true}f={height:a.height(),width:a.width()};a.from=b.options.from||(g=="show"?{height:0,width:0}:f);h={y:i!="horizontal"?h/100:1,x:i!="vertical"?h/100:1};a.to={height:f.height*h.y,width:f.width*h.x};if(b.options.fade){if(g=="show"){a.from.opacity=0;a.to.opacity=1}if(g=="hide"){a.from.opacity=
+1;a.to.opacity=0}}e.from=a.from;e.to=a.to;e.mode=g;a.effect("size",e,b.duration,b.callback);a.dequeue()})};c.effects.size=function(b){return this.queue(function(){var a=c(this),e=["position","top","left","width","height","overflow","opacity"],g=["position","top","left","overflow","opacity"],h=["width","height","overflow"],i=["fontSize"],f=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],k=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=c.effects.setMode(a,
+b.options.mode||"effect"),n=b.options.restore||false,m=b.options.scale||"both",l=b.options.origin,j={height:a.height(),width:a.width()};a.from=b.options.from||j;a.to=b.options.to||j;if(l){l=c.effects.getBaseline(l,j);a.from.top=(j.height-a.from.height)*l.y;a.from.left=(j.width-a.from.width)*l.x;a.to.top=(j.height-a.to.height)*l.y;a.to.left=(j.width-a.to.width)*l.x}var d={from:{y:a.from.height/j.height,x:a.from.width/j.width},to:{y:a.to.height/j.height,x:a.to.width/j.width}};if(m=="box"||m=="both"){if(d.from.y!=
+d.to.y){e=e.concat(f);a.from=c.effects.setTransition(a,f,d.from.y,a.from);a.to=c.effects.setTransition(a,f,d.to.y,a.to)}if(d.from.x!=d.to.x){e=e.concat(k);a.from=c.effects.setTransition(a,k,d.from.x,a.from);a.to=c.effects.setTransition(a,k,d.to.x,a.to)}}if(m=="content"||m=="both")if(d.from.y!=d.to.y){e=e.concat(i);a.from=c.effects.setTransition(a,i,d.from.y,a.from);a.to=c.effects.setTransition(a,i,d.to.y,a.to)}c.effects.save(a,n?e:g);a.show();c.effects.createWrapper(a);a.css("overflow","hidden").css(a.from);
+if(m=="content"||m=="both"){f=f.concat(["marginTop","marginBottom"]).concat(i);k=k.concat(["marginLeft","marginRight"]);h=e.concat(f).concat(k);a.find("*[width]").each(function(){child=c(this);n&&c.effects.save(child,h);var o={height:child.height(),width:child.width()};child.from={height:o.height*d.from.y,width:o.width*d.from.x};child.to={height:o.height*d.to.y,width:o.width*d.to.x};if(d.from.y!=d.to.y){child.from=c.effects.setTransition(child,f,d.from.y,child.from);child.to=c.effects.setTransition(child,
+f,d.to.y,child.to)}if(d.from.x!=d.to.x){child.from=c.effects.setTransition(child,k,d.from.x,child.from);child.to=c.effects.setTransition(child,k,d.to.x,child.to)}child.css(child.from);child.animate(child.to,b.duration,b.options.easing,function(){n&&c.effects.restore(child,h)})})}a.animate(a.to,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){a.to.opacity===0&&a.css("opacity",a.from.opacity);p=="hide"&&a.hide();c.effects.restore(a,n?e:g);c.effects.removeWrapper(a);b.callback&&
+b.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+(function(d){d.effects.shake=function(a){return this.queue(function(){var b=d(this),j=["position","top","left"];d.effects.setMode(b,a.options.mode||"effect");var c=a.options.direction||"left",e=a.options.distance||20,l=a.options.times||3,f=a.duration||a.options.duration||140;d.effects.save(b,j);b.show();d.effects.createWrapper(b);var g=c=="up"||c=="down"?"top":"left",h=c=="up"||c=="left"?"pos":"neg";c={};var i={},k={};c[g]=(h=="pos"?"-=":"+=")+e;i[g]=(h=="pos"?"+=":"-=")+e*2;k[g]=(h=="pos"?"-=":"+=")+
+e*2;b.animate(c,f,a.options.easing);for(e=1;e<l;e++)b.animate(i,f,a.options.easing).animate(k,f,a.options.easing);b.animate(i,f,a.options.easing).animate(c,f/2,a.options.easing,function(){d.effects.restore(b,j);d.effects.removeWrapper(b);a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()});b.dequeue()})}})(jQuery);
+(function(c){c.effects.slide=function(d){return this.queue(function(){var a=c(this),h=["position","top","left"],e=c.effects.setMode(a,d.options.mode||"show"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a).css({overflow:"hidden"});var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true}):a.outerWidth({margin:true}));if(e=="show")a.css(f,b=="pos"?-g:g);var i={};i[f]=(e=="show"?b=="pos"?
+"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery);
+(function(e){e.effects.transfer=function(a){return this.queue(function(){var b=e(this),c=e(a.options.to),d=c.offset();c={top:d.top,left:d.left,height:c.innerHeight(),width:c.innerWidth()};d=b.offset();var f=e('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments);
+b.dequeue()})})}})(jQuery);
+(function(c){c.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()==location.href.toLowerCase()}},_create:function(){var a=this.options,b=this;this.running=0;this.element.addClass("ui-accordion ui-widget ui-helper-reset");
+this.element.children("li").addClass("ui-accordion-li-fix");this.headers=this.element.find(a.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){c(this).removeClass("ui-state-focus")});this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
+if(a.navigation){var d=this.element.find("a").filter(a.navigationFilter);if(d.length){var f=d.closest(".ui-accordion-header");this.active=f.length?f:d.closest(".ui-accordion-content").prev()}}this.active=this._findActive(this.active||a.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");this.active.next().addClass("ui-accordion-content-active");this._createIcons();this.resize();this.element.attr("role","tablist");this.headers.attr("role",
+"tab").bind("keydown",function(g){return b._keydown(g)}).next().attr("role","tabpanel");this.headers.not(this.active||"").attr("aria-expanded","false").attr("tabIndex","-1").next().hide();this.active.length?this.active.attr("aria-expanded","true").attr("tabIndex","0"):this.headers.eq(0).attr("tabIndex","0");c.browser.safari||this.headers.find("a").attr("tabIndex","-1");a.event&&this.headers.bind(a.event+".accordion",function(g){b._clickHandler.call(b,g,this);g.preventDefault()})},_createIcons:function(){var a=
+this.options;if(a.icons){c("<span/>").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.find(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role").unbind(".accordion").removeData("accordion");
+this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("tabIndex");this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");if(a.autoHeight||a.fillHeight)b.css("height",
+"");return this},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons();b&&this._createIcons()}},_keydown:function(a){var b=c.ui.keyCode;if(!(this.options.disabled||a.altKey||a.ctrlKey)){var d=this.headers.length,f=this.headers.index(a.target),g=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:g=this.headers[(f+1)%d];break;case b.LEFT:case b.UP:g=this.headers[(f-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},
+a.target);a.preventDefault()}if(g){c(a.target).attr("tabIndex","-1");c(g).attr("tabIndex","0");g.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,
+b-c(this).innerHeight()+c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a=="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d=
+this.options;if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]==this.active[0];d.active=d.collapsible&&b?false:c(".ui-accordion-header",this.element).index(a);if(!(this.running||!d.collapsible&&b)){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").find(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);
+a.next().addClass("ui-accordion-content-active")}e=a.next();f=this.active.next();g={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):e,oldContent:f};d=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(e,f,g,b,d)}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").find(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);
+this.active.next().addClass("ui-accordion-content-active");var f=this.active.next(),g={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:f},e=this.active=c([]);this._toggle(e,f,g)}},_toggle:function(a,b,d,f,g){var e=this.options,k=this;this.toShow=a;this.toHide=b;this.data=d;var i=function(){if(k)return k._completed.apply(k,arguments)};this._trigger("changestart",null,this.data);this.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&f?{toShow:c([]),
+toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:i,down:g,autoHeight:e.autoHeight||e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;f=c.ui.accordion.animations;var h=e.duration,j=e.animated;if(j&&!f[j]&&!c.easing[j])j="slide";f[j]||(f[j]=function(l){this.slide(l,{easing:j,
+duration:h||700})});f[j](d)}else{if(e.collapsible&&f)a.toggle();else{b.hide();a.show()}i(true)}b.prev().attr("aria-expanded","false").attr("tabIndex","-1").blur();a.prev().attr("aria-expanded","true").attr("tabIndex","0").focus()},_completed:function(a){var b=this.options;this.running=a?0:--this.running;if(!this.running){b.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,
+{version:"1.8.2",animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),f=0,g={},e={},k;b=a.toShow;k=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(i,h){e[h]="hide";i=(""+c.css(a.toShow[0],
+h)).match(/^([\d+-.]+)(.*)$/);g[h]={value:i[1],unit:i[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(e,{step:function(i,h){if(h.prop=="height")f=h.end-h.start===0?0:(h.now-h.start)/(h.end-h.start);a.toShow[0].style[h.prop]=f*g[h.prop].value+g[h.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css("width",k);a.toShow.css({overflow:d});a.complete()}})}else a.toHide.animate({height:"hide"},
+a);else a.toShow.animate({height:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery);
+(function(e){e.widget("ui.autocomplete",{options:{minLength:1,delay:300},_create:function(){var a=this,c=this.element[0].ownerDocument;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(d){var b=e.ui.keyCode;switch(d.keyCode){case b.PAGE_UP:a._move("previousPage",d);break;case b.PAGE_DOWN:a._move("nextPage",d);break;case b.UP:a._move("previous",d);d.preventDefault();
+break;case b.DOWN:a._move("next",d);d.preventDefault();break;case b.ENTER:case b.NUMPAD_ENTER:a.menu.active&&d.preventDefault();case b.TAB:if(!a.menu.active)return;a.menu.select(d);break;case b.ESCAPE:a.element.val(a.term);a.close(d);break;case b.LEFT:case b.RIGHT:case b.SHIFT:case b.CONTROL:case b.ALT:case b.COMMAND:case b.COMMAND_RIGHT:case b.INSERT:case b.CAPS_LOCK:case b.END:case b.HOME:break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){a.search(null,d)},a.options.delay);
+break}}).bind("focus.autocomplete",function(){a.selectedItem=null;a.previous=a.element.val()}).bind("blur.autocomplete",function(d){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(d);a._change(d)},150)});this._initSource();this.response=function(){return a._response.apply(a,arguments)};this.menu=e("<ul></ul>").addClass("ui-autocomplete").appendTo("body",c).mousedown(function(){setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(d,b){b=b.item.data("item.autocomplete");
+false!==a._trigger("focus",null,{item:b})&&/^key/.test(d.originalEvent.type)&&a.element.val(b.value)},selected:function(d,b){b=b.item.data("item.autocomplete");false!==a._trigger("select",d,{item:b})&&a.element.val(b.value);a.close(d);d=a.previous;if(a.element[0]!==c.activeElement){a.element.focus();a.previous=d}a.selectedItem=b},blur:function(){a.menu.element.is(":visible")&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu");e.fn.bgiframe&&this.menu.element.bgiframe()},
+destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();e.Widget.prototype.destroy.call(this)},_setOption:function(a){e.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource()},_initSource:function(){var a,c;if(e.isArray(this.options.source)){a=this.options.source;this.source=function(d,b){b(e.ui.autocomplete.filter(a,d.term))}}else if(typeof this.options.source===
+"string"){c=this.options.source;this.source=function(d,b){e.getJSON(c,d,b)}}else this.source=this.options.source},search:function(a,c){a=a!=null?a:this.element.val();if(a.length<this.options.minLength)return this.close(c);clearTimeout(this.closing);if(this._trigger("search")!==false)return this._search(a)},_search:function(a){this.term=this.element.addClass("ui-autocomplete-loading").val();this.source({term:a},this.response)},_response:function(a){if(a.length){a=this._normalize(a);this._suggest(a);
+this._trigger("open")}else this.close();this.element.removeClass("ui-autocomplete-loading")},close:function(a){clearTimeout(this.closing);if(this.menu.element.is(":visible")){this._trigger("close",a);this.menu.element.hide();this.menu.deactivate()}},_change:function(a){this.previous!==this.element.val()&&this._trigger("change",a,{item:this.selectedItem})},_normalize:function(a){if(a.length&&a[0].label&&a[0].value)return a;return e.map(a,function(c){if(typeof c==="string")return{label:c,value:c};return e.extend({label:c.label||
+c.value,value:c.value||c.label},c)})},_suggest:function(a){var c=this.menu.element.empty().zIndex(this.element.zIndex()+1),d;this._renderMenu(c,a);this.menu.deactivate();this.menu.refresh();this.menu.element.show().position({my:"left top",at:"left bottom",of:this.element,collision:"none"});a=c.width("").width();d=this.element.width();c.width(Math.max(a,d))},_renderMenu:function(a,c){var d=this;e.each(c,function(b,f){d._renderItem(a,f)})},_renderItem:function(a,c){return e("<li></li>").data("item.autocomplete",
+c).append("<a>"+c.label+"</a>").appendTo(a)},_move:function(a,c){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](c);else this.search(null,c)},widget:function(){return this.menu.element}});e.extend(e.ui.autocomplete,{escapeRegex:function(a){return a.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")},filter:function(a,c){var d=new RegExp(e.ui.autocomplete.escapeRegex(c),
+"i");return e.grep(a,function(b){return d.test(b.label||b.value||b)})}})})(jQuery);
+(function(e){e.widget("ui.menu",{_create:function(){var a=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(c){if(e(c.target).closest(".ui-menu-item a").length){c.preventDefault();a.select(c)}});this.refresh()},refresh:function(){var a=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex",
+-1).mouseenter(function(c){a.activate(c,e(this).parent())}).mouseleave(function(){a.deactivate()})},activate:function(a,c){this.deactivate();if(this.hasScroll()){var d=c.offset().top-this.element.offset().top,b=this.element.attr("scrollTop"),f=this.element.height();if(d<0)this.element.attr("scrollTop",b+d);else d>f&&this.element.attr("scrollTop",b+d-f+c.height())}this.active=c.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",a,{item:c})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id");
+this._trigger("blur");this.active=null}},next:function(a){this.move("next",".ui-menu-item:first",a)},previous:function(a){this.move("prev",".ui-menu-item:last",a)},first:function(){return this.active&&!this.active.prev().length},last:function(){return this.active&&!this.active.next().length},move:function(a,c,d){if(this.active){a=this.active[a+"All"](".ui-menu-item").eq(0);a.length?this.activate(d,a):this.activate(d,this.element.children(c))}else this.activate(d,this.element.children(c))},nextPage:function(a){if(this.hasScroll())if(!this.active||
+this.last())this.activate(a,this.element.children(":first"));else{var c=this.active.offset().top,d=this.element.height(),b=this.element.children("li").filter(function(){var f=e(this).offset().top-c-d+e(this).height();return f<10&&f>-10});b.length||(b=this.element.children(":last"));this.activate(a,b)}else this.activate(a,this.element.children(!this.active||this.last()?":first":":last"))},previousPage:function(a){if(this.hasScroll())if(!this.active||this.first())this.activate(a,this.element.children(":last"));
+else{var c=this.active.offset().top,d=this.element.height();result=this.element.children("li").filter(function(){var b=e(this).offset().top-c+d-e(this).height();return b<10&&b>-10});result.length||(result=this.element.children(":first"));this.activate(a,result)}else this.activate(a,this.element.children(!this.active||this.first()?":last":":first"))},hasScroll:function(){return this.element.height()<this.element.attr("scrollHeight")},select:function(a){this._trigger("selected",a,{item:this.active})}})})(jQuery);
+(function(a){var g,i=function(b){a(":ui-button",b.target.form).each(function(){var c=a(this).data("button");setTimeout(function(){c.refresh()},1)})},h=function(b){var c=b.name,d=b.form,e=a([]);if(c)e=d?a(d).find("[name='"+c+"']"):a("[name='"+c+"']",b.ownerDocument).filter(function(){return!this.form});return e};a.widget("ui.button",{options:{text:true,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",i);this._determineButtonType();
+this.hasTitle=!!this.buttonElement.attr("title");var b=this,c=this.options,d=this.type==="checkbox"||this.type==="radio",e="ui-state-hover"+(!d?" ui-state-active":"");if(c.label===null)c.label=this.buttonElement.html();if(this.element.is(":disabled"))c.disabled=true;this.buttonElement.addClass("ui-button ui-widget ui-state-default ui-corner-all").attr("role","button").bind("mouseenter.button",function(){if(!c.disabled){a(this).addClass("ui-state-hover");this===g&&a(this).addClass("ui-state-active")}}).bind("mouseleave.button",
+function(){c.disabled||a(this).removeClass(e)}).bind("focus.button",function(){a(this).addClass("ui-state-focus")}).bind("blur.button",function(){a(this).removeClass("ui-state-focus")});d&&this.element.bind("change.button",function(){b.refresh()});if(this.type==="checkbox")this.buttonElement.bind("click.button",function(){if(c.disabled)return false;a(this).toggleClass("ui-state-active");b.buttonElement.attr("aria-pressed",b.element[0].checked)});else if(this.type==="radio")this.buttonElement.bind("click.button",
+function(){if(c.disabled)return false;a(this).addClass("ui-state-active");b.buttonElement.attr("aria-pressed",true);var f=b.element[0];h(f).not(f).map(function(){return a(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed",false)});else{this.buttonElement.bind("mousedown.button",function(){if(c.disabled)return false;a(this).addClass("ui-state-active");g=this;a(document).one("mouseup",function(){g=null})}).bind("mouseup.button",function(){if(c.disabled)return false;a(this).removeClass("ui-state-active")}).bind("keydown.button",
+function(f){if(c.disabled)return false;if(f.keyCode==a.ui.keyCode.SPACE||f.keyCode==a.ui.keyCode.ENTER)a(this).addClass("ui-state-active")}).bind("keyup.button",function(){a(this).removeClass("ui-state-active")});this.buttonElement.is("a")&&this.buttonElement.keyup(function(f){f.keyCode===a.ui.keyCode.SPACE&&a(this).click()})}this._setOption("disabled",c.disabled)},_determineButtonType:function(){this.type=this.element.is(":checkbox")?"checkbox":this.element.is(":radio")?"radio":this.element.is("input")?
+"input":"button";if(this.type==="checkbox"||this.type==="radio"){this.buttonElement=this.element.parents().last().find("[for="+this.element.attr("id")+"]");this.element.addClass("ui-helper-hidden-accessible");var b=this.element.is(":checked");b&&this.buttonElement.addClass("ui-state-active");this.buttonElement.attr("aria-pressed",b)}else this.buttonElement=this.element},widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible");this.buttonElement.removeClass("ui-button ui-widget ui-state-default ui-corner-all ui-state-hover ui-state-active ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon ui-button-text-only").removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html());
+this.hasTitle||this.buttonElement.removeAttr("title");a.Widget.prototype.destroy.call(this)},_setOption:function(b,c){a.Widget.prototype._setOption.apply(this,arguments);if(b==="disabled")c?this.element.attr("disabled",true):this.element.removeAttr("disabled");this._resetButton()},refresh:function(){var b=this.element.is(":disabled");b!==this.options.disabled&&this._setOption("disabled",b);if(this.type==="radio")h(this.element[0]).each(function(){a(this).is(":checked")?a(this).button("widget").addClass("ui-state-active").attr("aria-pressed",
+true):a(this).button("widget").removeClass("ui-state-active").attr("aria-pressed",false)});else if(this.type==="checkbox")this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed",true):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed",false)},_resetButton:function(){if(this.type==="input")this.options.label&&this.element.val(this.options.label);else{var b=this.buttonElement.removeClass("ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon ui-button-text-only"),
+c=a("<span></span>").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(),d=this.options.icons,e=d.primary&&d.secondary;if(d.primary||d.secondary){b.addClass("ui-button-text-icon"+(e?"s":""));d.primary&&b.prepend("<span class='ui-button-icon-primary ui-icon "+d.primary+"'></span>");d.secondary&&b.append("<span class='ui-button-icon-secondary ui-icon "+d.secondary+"'></span>");if(!this.options.text){b.addClass(e?"ui-button-icons-only":"ui-button-icon-only").removeClass("ui-button-text-icons ui-button-text-icon");
+this.hasTitle||b.attr("title",c)}}else b.addClass("ui-button-text-only")}}});a.widget("ui.buttonset",{_create:function(){this.element.addClass("ui-buttonset");this._init()},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(":button, :submit, :reset, :checkbox, :radio, a, :data(button)").filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end()},
+destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");a.Widget.prototype.destroy.call(this)}})})(jQuery);
+(function(d){function J(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass=
+"ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su",
+"Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:false,showMonthAfterYear:false,yearSuffix:""};this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,yearRange:"c-10:c+10",showOtherMonths:false,selectOtherMonths:false,showWeek:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",
+minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false,autoSize:false};d.extend(this._defaults,this.regional[""]);this.dpDiv=d('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>')}function E(a,b){d.extend(a,
+b);for(var c in b)if(b[c]==null||b[c]==undefined)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.2"}});var y=(new Date).getTime();d.extend(J.prototype,{markerClassName:"hasDatepicker",log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(a){E(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=
+f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_])/g,"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:d('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')}},
+_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&
+b.append.remove();if(c){b.append=d('<span class="'+this._appendClass+'">'+c+"</span>");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c=="focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("<img/>").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('<button type="button"></button>').addClass(this._triggerClass).html(f==
+""?c:d("<img/>").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker():d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;g<f.length;g++)if(f[g].length>h){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,
+c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a,b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),
+true);this._updateDatepicker(b);this._updateAlternate(b)}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+=1;this._dialogInput=d('<input type="text" id="'+("dp"+this.uuid)+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}E(a.settings,e||{});b=b&&b.constructor==
+Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);
+d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},
+_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().removeClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=
+d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span")b.children("."+this._inlineClass).children().addClass("ui-state-disabled");this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;
+for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return true;return false},_getInst:function(a){try{return d.data(a,"datepicker")}catch(b){throw"Missing instance data for this datepicker";}},_optionDatepicker:function(a,b,c){var e=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?d.extend({},d.datepicker._defaults):e?b=="all"?d.extend({},e.settings):this._get(e,b):null;var f=b||{};if(typeof b=="string"){f={};f[b]=c}if(e){this._curInst==e&&
+this._hideDatepicker();var h=this._getDateDatepicker(a,true);E(e.settings,f);this._attachments(d(a),e);this._autoSize(e);this._setDateDatepicker(a,h);this._updateDatepicker(e)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){(a=this._getInst(a))&&this._updateDatepicker(a)},_setDateDatepicker:function(a,b){if(a=this._getInst(a)){this._setDate(a,b);this._updateDatepicker(a);this._updateAlternate(a)}},_getDateDatepicker:function(a,b){(a=this._getInst(a))&&
+!a.inline&&this._setDateFromField(a,b);return a?this._getDate(a):null},_doKeyDown:function(a){var b=d.datepicker._getInst(a.target),c=true,e=b.dpDiv.is(".ui-datepicker-rtl");b._keyEvent=true;if(d.datepicker._datepickerShowing)switch(a.keyCode){case 9:d.datepicker._hideDatepicker();c=false;break;case 13:c=d("td."+d.datepicker._dayOverClass,b.dpDiv).add(d("td."+d.datepicker._currentClass,b.dpDiv));c[0]?d.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,c[0]):d.datepicker._hideDatepicker();
+return false;case 27:d.datepicker._hideDatepicker();break;case 33:d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 34:d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 35:if(a.ctrlKey||a.metaKey)d.datepicker._clearDate(a.target);c=a.ctrlKey||a.metaKey;break;case 36:if(a.ctrlKey||a.metaKey)d.datepicker._gotoToday(a.target);c=a.ctrlKey||
+a.metaKey;break;case 37:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?+1:-1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 38:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,-7,"D");c=a.ctrlKey||a.metaKey;break;case 39:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?-1:+1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,
+a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 40:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,+7,"D");c=a.ctrlKey||a.metaKey;break;default:c=false}else if(a.keyCode==36&&a.ctrlKey)d.datepicker._showDatepicker(this);else c=false;if(c){a.preventDefault();a.stopPropagation()}},_doKeyPress:function(a){var b=d.datepicker._getInst(a.target);if(d.datepicker._get(b,"constrainInput")){b=d.datepicker._possibleChars(d.datepicker._get(b,"dateFormat"));
+var c=String.fromCharCode(a.charCode==undefined?a.keyCode:a.charCode);return a.ctrlKey||c<" "||!b||b.indexOf(c)>-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||
+a;if(a.nodeName.toLowerCase()!="input")a=d("input",a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);d.datepicker._curInst&&d.datepicker._curInst!=b&&d.datepicker._curInst.dpDiv.stop(true,true);var c=d.datepicker._get(b,"beforeShow");E(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos=d.datepicker._findPos(a);
+d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b,c,e);b.dpDiv.css({position:d.datepicker._inDialog&&
+d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){d.datepicker._datepickerShowing=true;var i=d.datepicker._getBorders(b.dpDiv);b.dpDiv.find("iframe.ui-datepicker-cover").css({left:-i[0],top:-i[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})};b.dpDiv.zIndex(d(a).zIndex()+1);d.effects&&d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,
+h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){var b=this,c=d.datepicker._getBorders(a.dpDiv);a.dpDiv.empty().append(this._generateHTML(a)).find("iframe.ui-datepicker-cover").css({left:-c[0],top:-c[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()}).end().find("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a").bind("mouseout",function(){d(this).removeClass("ui-state-hover");
+this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).removeClass("ui-datepicker-prev-hover");this.className.indexOf("ui-datepicker-next")!=-1&&d(this).removeClass("ui-datepicker-next-hover")}).bind("mouseover",function(){if(!b._isDisabledDatepicker(a.inline?a.dpDiv.parent()[0]:a.input[0])){d(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");d(this).addClass("ui-state-hover");this.className.indexOf("ui-datepicker-prev")!=-1&&d(this).addClass("ui-datepicker-prev-hover");
+this.className.indexOf("ui-datepicker-next")!=-1&&d(this).addClass("ui-datepicker-next-hover")}}).end().find("."+this._dayOverClass+" a").trigger("mouseover").end();c=this._getNumberOfMonths(a);var e=c[1];e>1?a.dpDiv.addClass("ui-datepicker-multi-"+e).css("width",17*e+"em"):a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");a.dpDiv[(c[0]!=1||c[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");
+a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&&a.input.focus()},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth():0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),
+k=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>k&&k>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a),"isRTL");a&&(a.type=="hidden"||a.nodeType!=1);)a=a[b?"previousSibling":"nextSibling"];
+a=d(a).offset();return[a.left,a.top]},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst=null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();if(a=this._get(b,"onClose"))a.apply(b.input?b.input[0]:null,[b.input?b.input.val():
+"",b]);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&
+!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"):0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;
+b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e._selectingMonthYear=false;e["selected"+(c=="M"?"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_clickMonthYear:function(a){a=this._getInst(d(a)[0]);
+a.input&&a._selectingMonthYear&&!d.browser.msie&&a.input.focus();a._selectingMonthYear=!a._selectingMonthYear},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a);this._getInst(a[0]);this._selectDate(a,
+"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];typeof a.input[0]!="object"&&a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a,"altFormat")||
+this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b=="")return null;
+for(var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff,f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,k=c=-1,l=-1,u=-1,j=false,o=function(p){(p=z+1<a.length&&a.charAt(z+1)==p)&&z++;return p},m=function(p){o(p);p=new RegExp("^\\d{1,"+(p=="@"?14:p=="!"?20:p=="y"?4:p=="o"?3:2)+"}");p=b.substring(s).match(p);if(!p)throw"Missing number at position "+
+s;s+=p[0].length;return parseInt(p[0],10)},n=function(p,w,G){p=o(p)?G:w;for(w=0;w<p.length;w++)if(b.substr(s,p[w].length)==p[w]){s+=p[w].length;return w+1}throw"Unknown name at position "+s;},r=function(){if(b.charAt(s)!=a.charAt(z))throw"Unexpected literal at position "+s;s++},s=0,z=0;z<a.length;z++)if(j)if(a.charAt(z)=="'"&&!o("'"))j=false;else r();else switch(a.charAt(z)){case "d":l=m("d");break;case "D":n("D",f,h);break;case "o":u=m("o");break;case "m":k=m("m");break;case "M":k=n("M",i,g);break;
+case "y":c=m("y");break;case "@":var v=new Date(m("@"));c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "!":v=new Date((m("!")-this._ticksTo1970)/1E4);c=v.getFullYear();k=v.getMonth()+1;l=v.getDate();break;case "'":if(o("'"))r();else j=true;break;default:r()}if(c==-1)c=(new Date).getFullYear();else if(c<100)c+=(new Date).getFullYear()-(new Date).getFullYear()%100+(c<=e?0:-100);if(u>-1){k=1;l=u;do{e=this._getDaysInMonth(c,k-1);if(l<=e)break;k++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,
+k-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=k||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?
+c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=j+1<a.length&&a.charAt(j+1)==o)&&j++;return o},g=function(o,m,n){m=""+m;if(i(o))for(;m.length<n;)m="0"+m;return m},k=function(o,m,n,r){return i(o)?r[m]:n[m]},l="",u=false;if(b)for(var j=0;j<a.length;j++)if(u)if(a.charAt(j)=="'"&&!i("'"))u=false;else l+=a.charAt(j);else switch(a.charAt(j)){case "d":l+=g("d",b.getDate(),2);break;
+case "D":l+=k("D",b.getDay(),e,f);break;case "o":l+=g("o",(b.getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864E5,3);break;case "m":l+=g("m",b.getMonth()+1,2);break;case "M":l+=k("M",b.getMonth(),h,c);break;case "y":l+=i("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case "@":l+=b.getTime();break;case "!":l+=b.getTime()*1E4+this._ticksTo1970;break;case "'":if(i("'"))l+="'";else u=true;break;default:l+=a.charAt(j)}return l},_possibleChars:function(a){for(var b="",c=false,
+e=function(h){(h=f+1<a.length&&a.charAt(f+1)==h)&&f++;return h},f=0;f<a.length;f++)if(c)if(a.charAt(f)=="'"&&!e("'"))c=false;else b+=a.charAt(f);else switch(a.charAt(f)){case "d":case "m":case "y":case "@":b+="0123456789";break;case "D":case "M":return null;case "'":if(e("'"))b+="'";else c=true;break;default:b+=a.charAt(f)}return b},_get:function(a,b){return a.settings[b]!==undefined?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()!=a.lastVal){var c=this._get(a,"dateFormat"),
+e=a.lastVal=a.input?a.input.val():null,f,h;f=h=this._getDefaultDate(a);var i=this._getFormatConfig(a);try{f=this.parseDate(c,e,i)||h}catch(g){this.log(g);e=b?"":e}a.selectedDay=f.getDate();a.drawMonth=a.selectedMonth=f.getMonth();a.drawYear=a.selectedYear=f.getFullYear();a.currentDay=e?f.getDate():0;a.currentMonth=e?f.getMonth():0;a.currentYear=e?f.getFullYear():0;this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,this._get(a,"defaultDate"),new Date))},
+_determineDate:function(a,b,c){var e=function(h){var i=new Date;i.setDate(i.getDate()+h);return i},f=function(h){try{return d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),h,d.datepicker._getFormatConfig(a))}catch(i){}var g=(h.toLowerCase().match(/^c/)?d.datepicker._getDate(a):null)||new Date,k=g.getFullYear(),l=g.getMonth();g=g.getDate();for(var u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,j=u.exec(h);j;){switch(j[2]||"d"){case "d":case "D":g+=parseInt(j[1],10);break;case "w":case "W":g+=parseInt(j[1],
+10)*7;break;case "m":case "M":l+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break;case "y":case "Y":k+=parseInt(j[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(k,l));break}j=u.exec(h)}return new Date(k,l,g)};if(b=(b=b==null?c:typeof b=="string"?f(b):typeof b=="number"?isNaN(b)?c:e(b):b)&&b.toString()=="Invalid Date"?c:b){b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0)}return this._daylightSavingAdjust(b)},_daylightSavingAdjust:function(a){if(!a)return null;
+a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear;b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a))},_getDate:function(a){return!a.currentYear||
+a.input&&a.input.val()==""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),k=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay?
+new Date(9999,9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),j=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=j&&n<j?j:n;this._daylightSavingAdjust(new Date(m,g,1))>n;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-k,1)),this._getFormatConfig(a));
+n=this._canAdjustMonth(a,-1,m,g)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', -"+k+", 'M');\" title=\""+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>":f?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>";var r=this._get(a,"nextText");r=!h?r:this.formatDate(r,this._daylightSavingAdjust(new Date(m,
+g+k,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+y+".datepicker._adjustDate('#"+a.id+"', +"+k+", 'M');\" title=\""+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>":f?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+r+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+r+"</span></a>";k=this._get(a,"currentText");r=this._get(a,"gotoCurrent")&&
+a.currentDay?u:b;k=!h?k:this.formatDate(k,r,this._getFormatConfig(a));h=!a.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+y+'.datepicker._hideDatepicker();">'+this._get(a,"closeText")+"</button>":"";e=e?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?h:"")+(this._isInRange(a,r)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+
+y+".datepicker._gotoToday('#"+a.id+"');\">"+k+"</button>":"")+(c?"":h)+"</div>":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;k=this._get(a,"showWeek");r=this._get(a,"dayNames");this._get(a,"dayNamesShort");var s=this._get(a,"dayNamesMin"),z=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),w=this._get(a,"showOtherMonths"),G=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var K=this._getDefaultDate(a),H="",C=0;C<i[0];C++){for(var L=
+"",D=0;D<i[1];D++){var M=this._daylightSavingAdjust(new Date(m,g,a.selectedDay)),t=" ui-corner-all",x="";if(l){x+='<div class="ui-datepicker-group';if(i[1]>1)switch(D){case 0:x+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:x+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:x+=" ui-datepicker-group-middle";t="";break}x+='">'}x+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+t+'">'+(/all|left/.test(t)&&C==0?c?
+f:n:"")+(/all|right/.test(t)&&C==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,j,o,C>0||D>0,z,v)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var A=k?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(t=0;t<7;t++){var q=(t+h)%7;A+="<th"+((t+h+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+r[q]+'">'+s[q]+"</span></th>"}x+=A+"</tr></thead><tbody>";A=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay,
+A);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;A=l?6:Math.ceil((t+A)/7);q=this._daylightSavingAdjust(new Date(m,g,1-t));for(var N=0;N<A;N++){x+="<tr>";var O=!k?"":'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(q)+"</td>";for(t=0;t<7;t++){var F=p?p.apply(a.input?a.input[0]:null,[q]):[true,""],B=q.getMonth()!=g,I=B&&!G||!F[0]||j&&q<j||o&&q>o;O+='<td class="'+((t+h+6)%7>=5?" ui-datepicker-week-end":"")+(B?" ui-datepicker-other-month":"")+(q.getTime()==M.getTime()&&g==a.selectedMonth&&
+a._keyEvent||K.getTime()==q.getTime()&&K.getTime()==M.getTime()?" "+this._dayOverClass:"")+(I?" "+this._unselectableClass+" ui-state-disabled":"")+(B&&!w?"":" "+F[1]+(q.getTime()==u.getTime()?" "+this._currentClass:"")+(q.getTime()==b.getTime()?" ui-datepicker-today":""))+'"'+((!B||w)&&F[2]?' title="'+F[2]+'"':"")+(I?"":' onclick="DP_jQuery_'+y+".datepicker._selectDay('#"+a.id+"',"+q.getMonth()+","+q.getFullYear()+', this);return false;"')+">"+(B&&!w?"&#xa0;":I?'<span class="ui-state-default">'+q.getDate()+
+"</span>":'<a class="ui-state-default'+(q.getTime()==b.getTime()?" ui-state-highlight":"")+(q.getTime()==u.getTime()?" ui-state-active":"")+(B?" ui-priority-secondary":"")+'" href="#">'+q.getDate()+"</a>")+"</td>";q.setDate(q.getDate()+1);q=this._daylightSavingAdjust(q)}x+=O+"</tr>"}g++;if(g>11){g=0;m++}x+="</tbody></table>"+(l?"</div>"+(i[0]>0&&D==i[1]-1?'<div class="ui-datepicker-row-break"></div>':""):"");L+=x}H+=L}H+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':
+"");a._keyEvent=false;return H},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var k=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),j='<div class="ui-datepicker-title">',o="";if(h||!k)o+='<span class="ui-datepicker-month">'+i[b]+"</span>";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+
+a.id+"');\">";for(var n=0;n<12;n++)if((!i||n>=e.getMonth())&&(!m||n<=f.getMonth()))o+='<option value="'+n+'"'+(n==b?' selected="selected"':"")+">"+g[n]+"</option>";o+="</select>"}u||(j+=o+(h||!(k&&l)?"&#xa0;":""));if(h||!l)j+='<span class="ui-datepicker-year">'+c+"</span>";else{g=this._get(a,"yearRange").split(":");var r=(new Date).getFullYear();i=function(s){s=s.match(/c[+-].*/)?c+parseInt(s.substring(1),10):s.match(/[+-].*/)?r+parseInt(s,10):parseInt(s,10);return isNaN(s)?r:s};b=i(g[0]);g=Math.max(b,
+i(g[1]||""));b=e?Math.max(b,e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(j+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+y+".datepicker._selectMonthYear('#"+a.id+"', this, 'Y');\" onclick=\"DP_jQuery_"+y+".datepicker._clickMonthYear('#"+a.id+"');\">";b<=g;b++)j+='<option value="'+b+'"'+(b==c?' selected="selected"':"")+">"+b+"</option>";j+="</select>"}j+=this._get(a,"yearSuffix");if(u)j+=(h||!(k&&l)?"&#xa0;":"")+o;j+="</div>";return j},_adjustInstDate:function(a,b,c){var e=
+a.drawYear+(c=="Y"?b:0),f=a.drawMonth+(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&b<c?c:b;return b=a&&b>a?a:b},_notifyChange:function(a){var b=this._get(a,
+"onChangeMonthYear");if(b)b.apply(a.input?a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a);
+c=this._daylightSavingAdjust(new Date(c,e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,
+"dayNamesShort"),dayNames:this._get(a,"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=
+function(a){if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));
+return this.each(function(){typeof a=="string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new J;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.2";window["DP_jQuery_"+y]=d})(jQuery);
+(function(c){c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:"center",resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");var a=this,b=a.options,d=b.title||a.originalTitle||"&#160;",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("<div></div>")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+
+b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),
+h=c('<a href="#"></a>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("<span></span>")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("<span></span>").addClass("ui-dialog-title").attr("id",
+e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");
+a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!==
+b.uiDialog[0])d=Math.max(d,c(this).css("z-index"))});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.attr("scrollTop"),scrollLeft:d.element.attr("scrollLeft")};c.ui.dialog.maxZ+=1;d.uiDialog.css("z-index",
+c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;d.next().length&&d.appendTo("body");a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target===
+f[0]&&e.shiftKey){g.focus(1);return false}}});c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();a._trigger("open");a._isOpen=true;return a}},_createButtons:function(a){var b=this,d=false,e=c("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a,function(){return!(d=true)});if(d){c.each(a,
+function(g,f){g=c('<button type="button"></button>').text(g).click(function(){f.apply(b.element[0],arguments)}).appendTo(e);c.fn.button&&g.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");
+b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition,originalSize:f.originalSize,position:f.position,size:f.size}}a=a===undefined?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");
+a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize",f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",
+f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0];a=a||c.ui.dialog.prototype.options.position;if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "):[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(e,g){if(+b[e]===b[e]){d[e]=b[e];b[e]=
+g}})}else if(typeof a==="object"){if("left"in a){b[0]="left";d[0]=a.left}else if("right"in a){b[0]="right";d[0]=-a.right}if("top"in a){b[1]="top";d[1]=a.top}else if("bottom"in a){b[1]="bottom";d[1]=-a.bottom}}(a=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position({my:b.join(" "),at:b.join(" "),offset:d.join(" "),of:window,collision:"fit",using:function(e){var g=c(this).css(e).offset().top;g<0&&c(this).css("top",e.top-g)}});a||this.uiDialog.hide()},_setOption:function(a,
+b){var d=this,e=d.uiDialog,g=e.is(":data(resizable)"),f=false;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"):e.removeClass("ui-dialog-disabled");break;case "draggable":b?d._makeDraggable():e.draggable("destroy");break;
+case "height":f=true;break;case "maxHeight":g&&e.resizable("option","maxHeight",b);f=true;break;case "maxWidth":g&&e.resizable("option","maxWidth",b);f=true;break;case "minHeight":g&&e.resizable("option","minHeight",b);f=true;break;case "minWidth":g&&e.resizable("option","minWidth",b);f=true;break;case "position":d._position(b);break;case "resizable":g&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",
+d.uiDialogTitlebar).html(""+(b||"&#160;"));break;case "width":f=true;break}c.Widget.prototype._setOption.apply(d,arguments);f&&d._size()},_size:function(){var a=this.options,b;this.element.css({width:"auto",minHeight:0,height:0});b=this.uiDialog.css({height:"auto",width:a.width}).height();this.element.css(a.height==="auto"?{minHeight:Math.max(a.minHeight-b,0),height:"auto"}:{minHeight:0,height:Math.max(a.height-b,0)}).show();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",
+this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.2",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&
+c(document).bind(c.ui.dialog.overlay.events,function(d){return c(d.target).zIndex()>=c.ui.dialog.overlay.maxZ})},1);c(document).bind("keydown.dialog-overlay",function(d){if(a.options.closeOnEscape&&d.keyCode&&d.keyCode===c.ui.keyCode.ESCAPE){a.close(d);d.preventDefault()}});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var b=(this.oldInstances.pop()||c("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&&
+b.bgiframe();this.instances.push(b);return b},destroy:function(a){this.oldInstances.push(this.instances.splice(c.inArray(a,this.instances),1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var b=0;c.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight,
+document.body.offsetHeight);return a<b?c(window).height()+"px":a+"px"}else return c(document).height()+"px"},width:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);b=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);return a<b?c(window).width()+"px":a+"px"}else return c(document).width()+"px"},resize:function(){var a=c([]);c.each(c.ui.dialog.overlay.instances,function(){a=a.add(this)});a.css({width:0,
+height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);
+(function(c){c.ui=c.ui||{};var m=/left|center|right/,n=/top|center|bottom/,p=c.fn.position,q=c.fn.offset;c.fn.position=function(a){if(!a||!a.of)return p.apply(this,arguments);a=c.extend({},a);var b=c(a.of),d=(a.collision||"flip").split(" "),e=a.offset?a.offset.split(" "):[0,0],g,h,i;if(a.of.nodeType===9){g=b.width();h=b.height();i={top:0,left:0}}else if(a.of.scrollTo&&a.of.document){g=b.width();h=b.height();i={top:b.scrollTop(),left:b.scrollLeft()}}else if(a.of.preventDefault){a.at="left top";g=h=
+0;i={top:a.of.pageY,left:a.of.pageX}}else{g=b.outerWidth();h=b.outerHeight();i=b.offset()}c.each(["my","at"],function(){var f=(a[this]||"").split(" ");if(f.length===1)f=m.test(f[0])?f.concat(["center"]):n.test(f[0])?["center"].concat(f):["center","center"];f[0]=m.test(f[0])?f[0]:"center";f[1]=n.test(f[1])?f[1]:"center";a[this]=f});if(d.length===1)d[1]=d[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(a.at[0]==="right")i.left+=g;else if(a.at[0]==="center")i.left+=
+g/2;if(a.at[1]==="bottom")i.top+=h;else if(a.at[1]==="center")i.top+=h/2;i.left+=e[0];i.top+=e[1];return this.each(function(){var f=c(this),k=f.outerWidth(),l=f.outerHeight(),j=c.extend({},i);if(a.my[0]==="right")j.left-=k;else if(a.my[0]==="center")j.left-=k/2;if(a.my[1]==="bottom")j.top-=l;else if(a.my[1]==="center")j.top-=l/2;j.left=parseInt(j.left);j.top=parseInt(j.top);c.each(["left","top"],function(o,r){c.ui.position[d[o]]&&c.ui.position[d[o]][r](j,{targetWidth:g,targetHeight:h,elemWidth:k,
+elemHeight:l,offset:e,my:a.my,at:a.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(j,{using:a.using}))})};c.ui.position={fit:{left:function(a,b){var d=c(window);b=a.left+b.elemWidth-d.width()-d.scrollLeft();a.left=b>0?a.left-b:Math.max(0,a.left)},top:function(a,b){var d=c(window);b=a.top+b.elemHeight-d.height()-d.scrollTop();a.top=b>0?a.top-b:Math.max(0,a.top)}},flip:{left:function(a,b){if(b.at[0]!=="center"){var d=c(window);d=a.left+b.elemWidth-d.width()-d.scrollLeft();var e=b.my[0]==="left"?
+-b.elemWidth:b.my[0]==="right"?b.elemWidth:0,g=-2*b.offset[0];a.left+=a.left<0?e+b.targetWidth+g:d>0?e-b.targetWidth+g:0}},top:function(a,b){if(b.at[1]!=="center"){var d=c(window);d=a.top+b.elemHeight-d.height()-d.scrollTop();var e=b.my[1]==="top"?-b.elemHeight:b.my[1]==="bottom"?b.elemHeight:0,g=b.at[1]==="top"?b.targetHeight:-b.targetHeight,h=-2*b.offset[1];a.top+=a.top<0?e+b.targetHeight+h:d>0?e+g+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(a,b){if(/static/.test(c.curCSS(a,"position")))a.style.position=
+"relative";var d=c(a),e=d.offset(),g=parseInt(c.curCSS(a,"top",true),10)||0,h=parseInt(c.curCSS(a,"left",true),10)||0;e={top:b.top-e.top+g,left:b.left-e.left+h};"using"in b?b.using.call(a,e):d.css(e)};c.fn.offset=function(a){var b=this[0];if(!b||!b.ownerDocument)return null;if(a)return this.each(function(){c.offset.setOffset(this,a)});return q.call(this)}}})(jQuery);
+(function(b){b.widget("ui.progressbar",{options:{value:0},_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this._valueMin(),"aria-valuemax":this._valueMax(),"aria-valuenow":this._value()});this.valueDiv=b("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element);this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow");
+this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===undefined)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){switch(a){case "value":this.options.value=c;this._refreshValue();this._trigger("change");break}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;if(a<this._valueMin())a=this._valueMin();if(a>this._valueMax())a=this._valueMax();return a},
+_valueMin:function(){return 0},_valueMax:function(){return 100},_refreshValue:function(){var a=this.value();this.valueDiv[a===this._valueMax()?"addClass":"removeClass"]("ui-corner-right").width(a+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.2"})})(jQuery);
+(function(d){d.widget("ui.slider",d.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null},_create:function(){var a=this,b=this.options;this._mouseSliding=this._keySliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget ui-widget-content ui-corner-all");b.disabled&&this.element.addClass("ui-slider-disabled ui-disabled");
+this.range=d([]);if(b.range){if(b.range===true){this.range=d("<div></div>");if(!b.values)b.values=[this._valueMin(),this._valueMin()];if(b.values.length&&b.values.length!==2)b.values=[b.values[0],b.values[0]]}else this.range=d("<div></div>");this.range.appendTo(this.element).addClass("ui-slider-range");if(b.range==="min"||b.range==="max")this.range.addClass("ui-slider-range-"+b.range);this.range.addClass("ui-widget-header")}d(".ui-slider-handle",this.element).length===0&&d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");
+if(b.values&&b.values.length)for(;d(".ui-slider-handle",this.element).length<b.values.length;)d("<a href='#'></a>").appendTo(this.element).addClass("ui-slider-handle");this.handles=d(".ui-slider-handle",this.element).addClass("ui-state-default ui-corner-all");this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(c){c.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur();
+else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(c){d(this).data("index.ui-slider-handle",c)});this.handles.keydown(function(c){var e=true,f=d(this).data("index.ui-slider-handle"),g,h,i;if(!a.options.disabled){switch(c.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:e=
+false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");g=a._start(c,f);if(g===false)return}break}i=a.options.step;g=a.options.values&&a.options.values.length?(h=a.values(f)):(h=a.value());switch(c.keyCode){case d.ui.keyCode.HOME:h=a._valueMin();break;case d.ui.keyCode.END:h=a._valueMax();break;case d.ui.keyCode.PAGE_UP:h=a._trimAlignValue(g+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:h=a._trimAlignValue(g-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(g===
+a._valueMax())return;h=a._trimAlignValue(g+i);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(g===a._valueMin())return;h=a._trimAlignValue(g-i);break}a._slide(c,f,h);return e}}).keyup(function(c){var e=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(c,e);a._change(c,e);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");
+this._mouseDestroy();return this},_mouseCapture:function(a){var b=this.options,c,e,f,g,h,i;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c={x:a.pageX,y:a.pageY};e=this._normValueFromMouse(c);f=this._valueMax()-this._valueMin()+1;h=this;this.handles.each(function(j){var k=Math.abs(e-h.values(j));if(f>k){f=k;g=d(this);i=j}});if(b.range===true&&this.values(1)===b.min){i+=1;g=d(this.handles[i])}if(this._start(a,
+i)===false)return false;this._mouseSliding=true;h._handleIndex=i;g.addClass("ui-state-active").focus();b=g.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-g.width()/2,top:a.pageY-b.top-g.height()/2-(parseInt(g.css("borderTopWidth"),10)||0)-(parseInt(g.css("borderBottomWidth"),10)||0)+(parseInt(g.css("marginTop"),10)||0)};e=this._normValueFromMouse(c);this._slide(a,i,e);return this._animateOff=true},_mouseStart:function(){return true},
+_mouseDrag:function(a){var b=this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b;
+if(this.orientation==="horizontal"){b=this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=
+this.values(b);c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var e;if(this.options.values&&this.options.values.length){e=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>e||b===1&&c<e))c=e;if(c!==this.values(b)){e=this.values();e[b]=c;a=this._trigger("slide",a,{handle:this.handles[b],value:c,values:e});this.values(b?0:1);a!==false&&this.values(b,c,true)}}else if(c!==this.value()){a=this._trigger("slide",a,{handle:this.handles[b],
+value:c});a!==false&&this.value(c)}},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("change",a,c)}},value:function(a){if(arguments.length){this.options.value=
+this._trimAlignValue(a);this._refreshValue();this._change(null,0)}return this._value()},values:function(a,b){var c,e,f;if(arguments.length>1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;e=arguments[0];for(f=0;f<c.length;f+=1){c[f]=this._trimAlignValue(e[f]);this._change(null,f)}this._refreshValue()}else return this.options.values&&this.options.values.length?this._values(a):this.value();
+else return this._values()},_setOption:function(a,b){var c,e=0;if(d.isArray(this.options.values))e=this.options.values.length;d.Widget.prototype._setOption.apply(this,arguments);switch(a){case "disabled":if(b){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.attr("disabled","disabled");this.element.addClass("ui-disabled")}else{this.handles.removeAttr("disabled");this.element.removeClass("ui-disabled")}break;case "orientation":this._detectOrientation();
+this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue();break;case "value":this._animateOff=true;this._refreshValue();this._change(null,0);this._animateOff=false;break;case "values":this._animateOff=true;this._refreshValue();for(c=0;c<e;c+=1)this._change(null,c);this._animateOff=false;break}},_value:function(){var a=this.options.value;return a=this._trimAlignValue(a)},_values:function(a){var b,c;if(arguments.length){b=this.options.values[a];
+return b=this._trimAlignValue(b)}else{b=this.options.values.slice();for(c=0;c<b.length;c+=1)b[c]=this._trimAlignValue(b[c]);return b}},_trimAlignValue:function(a){if(a<this._valueMin())return this._valueMin();if(a>this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=a%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a=
+this.options.range,b=this.options,c=this,e=!this._animateOff?b.animate:false,f,g={},h,i,j,k;if(this.options.values&&this.options.values.length)this.handles.each(function(l){f=(c.values(l)-c._valueMin())/(c._valueMax()-c._valueMin())*100;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";d(this).stop(1,1)[e?"animate":"css"](g,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(l===0)c.range.stop(1,1)[e?"animate":"css"]({left:f+"%"},b.animate);if(l===1)c.range[e?"animate":"css"]({width:f-
+h+"%"},{queue:false,duration:b.animate})}else{if(l===0)c.range.stop(1,1)[e?"animate":"css"]({bottom:f+"%"},b.animate);if(l===1)c.range[e?"animate":"css"]({height:f-h+"%"},{queue:false,duration:b.animate})}h=f});else{i=this.value();j=this._valueMin();k=this._valueMax();f=k!==j?(i-j)/(k-j)*100:0;g[c.orientation==="horizontal"?"left":"bottom"]=f+"%";this.handle.stop(1,1)[e?"animate":"css"](g,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[e?"animate":"css"]({width:f+"%"},
+b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[e?"animate":"css"]({width:100-f+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[e?"animate":"css"]({height:f+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[e?"animate":"css"]({height:100-f+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.2"})})(jQuery);
+(function(d){function s(){return++u}function v(){return++w}var u=0,w=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"<div></div>",remove:null,select:null,show:null,spinner:"<em>Loading&#8230;</em>",tabTemplate:'<li><a href="#{href}"><span>#{label}</span></a></li>'},_create:function(){this._tabify(true)},_setOption:function(c,e){if(c=="selected")this.options.collapsible&&
+e==this.options.selected||this.select(e);else{this.options[c]=e;this._tabify()}},_tabId:function(c){return c.title&&c.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+s()},_sanitizeSelector:function(c){return c.replace(/:/g,"\\:")},_cookie:function(){var c=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+v());return d.cookie.apply(null,[c].concat(d.makeArray(arguments)))},_ui:function(c,e){return{tab:c,panel:e,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var c=
+d(this);c.html(c.data("label.tabs")).removeData("label.tabs")})},_tabify:function(c){function e(g,f){g.css({display:""});!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}this.list=this.element.find("ol,ul").eq(0);this.lis=d("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);var a=this,b=this.options,h=/^#.+/;this.anchors.each(function(g,f){var j=d(f).attr("href"),l=j.split("#")[0],p;if(l&&(l===location.toString().split("#")[0]||
+(p=d("base")[0])&&l===p.href)){j=f.hash;f.href=j}if(h.test(j))a.panels=a.panels.add(a._sanitizeSelector(j));else if(j!="#"){d.data(f,"href.tabs",j);d.data(f,"load.tabs",j.replace(/#.*$/,""));j=a._tabId(f);f.href="#"+j;f=d("#"+j);if(!f.length){f=d(b.panelTemplate).attr("id",j).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else b.disabled.push(g)});if(c){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all");
+this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(b.selected===undefined){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){b.selected=g;return false}});if(typeof b.selected!="number"&&b.cookie)b.selected=parseInt(a._cookie(),10);if(typeof b.selected!="number"&&this.lis.filter(".ui-tabs-selected").length)b.selected=
+this.lis.index(this.lis.filter(".ui-tabs-selected"));b.selected=b.selected||(this.lis.length?0:-1)}else if(b.selected===null)b.selected=-1;b.selected=b.selected>=0&&this.anchors[b.selected]||b.selected<0?b.selected:0;b.disabled=d.unique(b.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(b.selected,b.disabled)!=-1&&b.disabled.splice(d.inArray(b.selected,b.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active");
+if(b.selected>=0&&this.anchors.length){this.panels.eq(b.selected).removeClass("ui-tabs-hide");this.lis.eq(b.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[b.selected],a.panels[b.selected]))});this.load(b.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else b.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"));this.element[b.collapsible?"addClass":
+"removeClass"]("ui-tabs-collapsible");b.cookie&&this._cookie(b.selected,b.cookie);c=0;for(var i;i=this.lis[c];c++)d(i)[d.inArray(c,b.disabled)!=-1&&!d(i).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");b.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(b.event!="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+g)};this.lis.bind("mouseover.tabs",
+function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(b.fx)if(d.isArray(b.fx)){m=b.fx[0];o=b.fx[1]}else m=o=b.fx;var q=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal",function(){e(f,o);a._trigger("show",
+null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},r=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")};this.anchors.bind(b.event+".tabs",
+function(){var g=this,f=d(this).closest("li"),j=a.panels.filter(":not(.ui-tabs-hide)"),l=d(a._sanitizeSelector(this.hash));if(f.hasClass("ui-tabs-selected")&&!b.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}b.selected=a.anchors.index(this);a.abort();if(b.collapsible)if(f.hasClass("ui-tabs-selected")){b.selected=-1;b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){r(g,
+j)}).dequeue("tabs");this.blur();return false}else if(!j.length){b.cookie&&a._cookie(b.selected,b.cookie);a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this));this.blur();return false}b.cookie&&a._cookie(b.selected,b.cookie);if(l.length){j.length&&a.element.queue("tabs",function(){r(g,j)});a.element.queue("tabs",function(){q(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier.";d.browser.msie&&this.blur()});this.anchors.bind("click.tabs",
+function(){return false})},destroy:function(){var c=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e=d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(b,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this,
+"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});c.cookie&&this._cookie(null,c.cookie);return this},add:function(c,e,a){if(a===undefined)a=this.anchors.length;var b=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,c).replace(/#\{label\}/g,e));c=!c.indexOf("#")?c.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs",
+true);var i=d("#"+c);i.length||(i=d(h.panelTemplate).attr("id",c).data("destroy.tabs",true));i.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);i.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]);i.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");i.removeClass("ui-tabs-hide");
+this.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[0],b.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(c){var e=this.options,a=this.lis.eq(c).remove(),b=this.panels.eq(c).remove();if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(c+(c+1<this.anchors.length?1:-1));e.disabled=d.map(d.grep(e.disabled,function(h){return h!=c}),function(h){return h>=c?--h:h});this._tabify();this._trigger("remove",
+null,this._ui(a.find("a")[0],b[0]));return this},enable:function(c){var e=this.options;if(d.inArray(c,e.disabled)!=-1){this.lis.eq(c).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=c});this._trigger("enable",null,this._ui(this.anchors[c],this.panels[c]));return this}},disable:function(c){var e=this.options;if(c!=e.selected){this.lis.eq(c).addClass("ui-state-disabled");e.disabled.push(c);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}return this},
+select:function(c){if(typeof c=="string")c=this.anchors.index(this.anchors.filter("[href$="+c+"]"));else if(c===null)c=-1;if(c==-1&&this.options.collapsible)c=this.options.selected;this.anchors.eq(c).trigger(this.options.event+".tabs");return this},load:function(c){var e=this,a=this.options,b=this.anchors.eq(c)[0],h=d.data(b,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(b,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(c).addClass("ui-state-processing");
+if(a.spinner){var i=d("span",b);i.data("label.tabs",i.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){d(e._sanitizeSelector(b.hash)).html(k);e._cleanup();a.cache&&d.data(b,"cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[c],e.panels[c]));try{a.ajaxOptions.error(k,n,c,b)}catch(m){}}}));e.element.dequeue("tabs");return this}},
+abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this},url:function(c,e){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.2"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(c,e){var a=this,b=this.options,h=a._rotate||(a._rotate=
+function(i){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=b.selected;a.select(++k<a.anchors.length?k:0)},c);i&&i.stopPropagation()});e=a._unrotate||(a._unrotate=!e?function(i){i.clientX&&a.rotate(null)}:function(){t=b.selected;h()});if(c){this.element.bind("tabsshow",h);this.anchors.bind(b.event+".tabs",e);h()}else{clearTimeout(a.rotation);this.element.unbind("tabsshow",h);this.anchors.unbind(b.event+".tabs",e);delete this._rotate;delete this._unrotate}return this}})})(jQuery);
diff --git a/libs/jquery/jquery.bgiframe.js b/libs/jquery/jquery.bgiframe.js
new file mode 100644
index 0000000000..ef8679d906
--- /dev/null
+++ b/libs/jquery/jquery.bgiframe.js
@@ -0,0 +1,10 @@
+/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
+ *
+ * $LastChangedDate: 2007-07-21 18:45:56 -0500 (Sat, 21 Jul 2007) $
+ * $Rev: 2447 $
+ *
+ * Version 2.1.1
+ */
+(function($){$.fn.bgIframe=$.fn.bgiframe=function(s){if($.browser.msie&&/6.0/.test(navigator.userAgent)){s=$.extend({top:'auto',left:'auto',width:'auto',height:'auto',opacity:true,src:'javascript:false;'},s||{});var prop=function(n){return n&&n.constructor==Number?n+'px':n;},html='<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+'style="display:block;position:absolute;z-index:-1;'+(s.opacity!==false?'filter:Alpha(Opacity=\'0\');':'')+'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+'"/>';return this.each(function(){if($('> iframe.bgiframe',this).length==0)this.insertBefore(document.createElement(html),this.firstChild);});}return this;};})(jQuery); \ No newline at end of file
diff --git a/libs/jquery/jquery.blockUI.js b/libs/jquery/jquery.blockUI.js
index 35925db955..e5a30ccd2a 100644
--- a/libs/jquery/jquery.blockUI.js
+++ b/libs/jquery/jquery.blockUI.js
@@ -1 +1,14 @@
-(function(f){if(/1\.(0|1|2)\.(0|1|2)/.test(f.fn.jquery)||/^1.1/.test(f.fn.jquery)){alert("blockUI requires jQuery v1.2.3 or later! You are using v"+f.fn.jquery);return}f.blockUI=function(m){c(window,m)};f.unblockUI=function(m){g(window,m)};f.growlUI=function(p,n,o){var m=f('<div class="growlUI"></div>');if(p){m.append("<h1>"+p+"</h1>")}if(n){m.append("<h2>"+n+"</h2>")}if(o==undefined){o=3000}f.blockUI({message:m,fadeIn:700,fadeOut:1000,centerY:false,timeout:o,showOverlay:false,css:f.blockUI.defaults.growlCSS})};f.fn.block=function(m){return this.each(function(){if(f.css(this,"position")=="static"){this.style.position="relative"}if(f.browser.msie){this.style.zoom=1}c(this,m)})};f.fn.unblock=function(m){return this.each(function(){g(this,m)})};f.blockUI.version=2.14;f.blockUI.defaults={message:"<h1>Please wait...</h1>",css:{padding:0,margin:0,width:"30%",top:"40%",left:"35%",textAlign:"center",color:"#000",border:"3px solid #aaa",backgroundColor:"#fff",cursor:"wait"},overlayCSS:{backgroundColor:"#000",opacity:"0.6"},growlCSS:{width:"350px",top:"10px",left:"",right:"10px",border:"none",padding:"5px",opacity:"0.6",cursor:null,color:"#fff",backgroundColor:"#000","-webkit-border-radius":"10px","-moz-border-radius":"10px"},baseZ:1000,centerX:true,centerY:true,allowBodyStretch:true,constrainTabKey:true,fadeIn:200,fadeOut:400,timeout:0,showOverlay:true,focusInput:true,applyPlatformOpacityRules:true,onUnblock:null,quirksmodeOffsetHack:4};var d=f.browser.msie&&/MSIE 6.0/.test(navigator.userAgent);var b=null;var e=[];function c(o,m){var y=(o==window);var p=m&&m.message!==undefined?m.message:undefined;m=f.extend({},f.blockUI.defaults,m||{});m.overlayCSS=f.extend({},f.blockUI.defaults.overlayCSS,m.overlayCSS||{});var x=f.extend({},f.blockUI.defaults.css,m.css||{});p=p===undefined?m.message:p;if(y&&b){g(window,{fadeOut:0})}if(p&&typeof p!="string"&&(p.parentNode||p.jquery)){var r=p.jquery?p[0]:p;var w={};f(o).data("blockUI.history",w);w.el=r;w.parent=r.parentNode;w.display=r.style.display;w.position=r.style.position;if(w.parent){w.parent.removeChild(r)}}var A=m.baseZ;var v=(f.browser.msie)?f('<iframe class="blockUI" style="z-index:'+A+++';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="javascript:false;"></iframe>'):f('<div class="blockUI" style="display:none"></div>');var u=f('<div class="blockUI blockOverlay" style="z-index:'+A+++';display:none;cursor:wait;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');var q=y?f('<div class="blockUI blockMsg blockPage" style="z-index:'+A+';display:none;position:fixed"></div>'):f('<div class="blockUI blockMsg blockElement" style="z-index:'+A+';display:none;position:absolute"></div>');if(p){q.css(x)}if(!m.applyPlatformOpacityRules||!(f.browser.mozilla&&/Linux/.test(navigator.platform))){u.css(m.overlayCSS)}u.css("position",y?"fixed":"absolute");if(f.browser.msie){v.css("opacity","0.0")}f([v[0],u[0],q[0]]).appendTo(y?"body":o);var C=f.browser.msie&&(!f.boxModel||f("object,embed",y?null:o).length>0);if(d||C){if(y&&m.allowBodyStretch&&f.boxModel){f("html,body").css("height","100%")}if((d||!f.boxModel)&&!y){var D=j(o,"borderTopWidth"),s=j(o,"borderLeftWidth");var B=D?"(0 - "+D+")":0;var n=s?"(0 - "+s+")":0}f.each([v,u,q],function(t,G){var z=G[0].style;z.position="absolute";if(t<2){y?z.setExpression("height","Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:"+m.quirksmodeOffsetHack+') + "px"'):z.setExpression("height",'this.parentNode.offsetHeight + "px"');y?z.setExpression("width",'jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"'):z.setExpression("width",'this.parentNode.offsetWidth + "px"');if(n){z.setExpression("left",n)}if(B){z.setExpression("top",B)}}else{if(m.centerY){if(y){z.setExpression("top",'(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"')}z.marginTop=0}else{if(!m.centerY&&y){var E=(m.css&&m.css.top)?parseInt(m.css.top):0;var F="((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "+E+') + "px"';z.setExpression("top",F)}}}})}q.append(p);if(p&&(p.jquery||p.nodeType)){f(p).show()}if(m.fadeIn){if(f.browser.msie&&m.showOverlay){v.fadeIn(m.fadeIn)}if(m.showOverlay){u.fadeIn(m.fadeIn)}q.fadeIn(m.fadeIn)}else{if(f.browser.msie&&m.showOverlay){v.show()}if(m.showOverlay){u.show()}q.show()}i(1,o,m);if(y){b=q[0];e=f(":input:enabled:visible",b);if(m.focusInput){setTimeout(l,20)}}else{a(q[0],m.centerX,m.centerY)}if(m.timeout){setTimeout(function(){y?f.unblockUI(m):f(o).unblock(m)},m.timeout)}}function g(o,p){var n=o==window;var q=f(o).data("blockUI.history");p=f.extend({},f.blockUI.defaults,p||{});i(0,o,p);var m=n?f("body").children().filter(".blockUI"):f(".blockUI",o);if(n){b=e=null}if(p.fadeOut){m.fadeOut(p.fadeOut);setTimeout(function(){h(m,q,p,o)},p.fadeOut)}else{h(m,q,p,o)}}function h(m,p,o,n){m.each(function(q,r){if(this.parentNode){this.parentNode.removeChild(this)}});if(p&&p.el){p.el.style.display=p.display;p.el.style.position=p.position;if(p.parent){p.parent.appendChild(p.el)}f(p.el).removeData("blockUI.history")}if(typeof o.onUnblock=="function"){o.onUnblock(n,o)}}function i(m,q,r){var p=q==window,o=f(q);if(!m&&(p&&!b||!p&&!o.data("blockUI.isBlocked"))){return}if(!p){o.data("blockUI.isBlocked",m)}if(m&&!r.showOverlay){return}var n="mousedown mouseup keydown keypress";m?f(document).bind(n,r,k):f(document).unbind(n,k)}function k(p){if(p.keyCode&&p.keyCode==9){if(b&&p.data.constrainTabKey){var o=e;var n=!p.shiftKey&&p.target==o[o.length-1];var m=p.shiftKey&&p.target==o[0];if(n||m){setTimeout(function(){l(m)},10);return false}}}if(f(p.target).parents("div.blockMsg").length>0){return true}return f(p.target).parents().children().filter("div.blockUI").length==0}function l(m){if(!e){return}var n=e[m===true?e.length-1:0];if(n){n.focus()}}function a(r,m,v){var u=r.parentNode,q=r.style;var n=((u.offsetWidth-r.offsetWidth)/2)-j(u,"borderLeftWidth");var o=((u.offsetHeight-r.offsetHeight)/2)-j(u,"borderTopWidth");if(m){q.left=n>0?(n+"px"):"0"}if(v){q.top=o>0?(o+"px"):"0"}}function j(m,n){return parseInt(f.css(m,n))||0}})(jQuery); \ No newline at end of file
+/*
+ * jQuery blockUI plugin
+ * Version 2.31 (06-JAN-2010)
+ * @requires jQuery v1.2.3 or later
+ *
+ * Examples at: http://malsup.com/jquery/block/
+ * Copyright (c) 2007-2008 M. Alsup
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Thanks to Amir-Hossein Sobhi for some excellent contributions!
+ */
+(function(i){if(/1\.(0|1|2)\.(0|1|2)/.test(i.fn.jquery)||/^1.1/.test(i.fn.jquery)){alert("blockUI requires jQuery v1.2.3 or later! You are using v"+i.fn.jquery);return}i.fn._fadeIn=i.fn.fadeIn;var c=function(){};var j=document.documentMode||0;var e=i.browser.msie&&((i.browser.version<8&&!j)||j<8);var f=i.browser.msie&&/MSIE 6.0/.test(navigator.userAgent)&&!j;i.blockUI=function(p){d(window,p)};i.unblockUI=function(p){h(window,p)};i.growlUI=function(t,r,s,p){var q=i('<div class="growlUI"></div>');if(t){q.append("<h1>"+t+"</h1>")}if(r){q.append("<h2>"+r+"</h2>")}if(s==undefined){s=3000}i.blockUI({message:q,fadeIn:700,fadeOut:1000,centerY:false,timeout:s,showOverlay:false,onUnblock:p,css:i.blockUI.defaults.growlCSS})};i.fn.block=function(p){return this.unblock({fadeOut:0}).each(function(){if(i.css(this,"position")=="static"){this.style.position="relative"}if(i.browser.msie){this.style.zoom=1}d(this,p)})};i.fn.unblock=function(p){return this.each(function(){h(this,p)})};i.blockUI.version=2.31;i.blockUI.defaults={message:"<h1>Please wait...</h1>",title:null,draggable:true,theme:false,css:{padding:0,margin:0,width:"30%",top:"40%",left:"35%",textAlign:"center",color:"#000",border:"3px solid #aaa",backgroundColor:"#fff",cursor:"wait"},themedCSS:{width:"30%",top:"40%",left:"35%"},overlayCSS:{backgroundColor:"#000",opacity:0.6,cursor:"wait"},growlCSS:{width:"350px",top:"10px",left:"",right:"10px",border:"none",padding:"5px",opacity:0.6,cursor:"default",color:"#fff",backgroundColor:"#000","-webkit-border-radius":"10px","-moz-border-radius":"10px"},iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank",forceIframe:false,baseZ:1000,centerX:true,centerY:true,allowBodyStretch:true,bindEvents:true,constrainTabKey:true,fadeIn:200,fadeOut:400,timeout:0,showOverlay:true,focusInput:true,applyPlatformOpacityRules:true,onBlock:null,onUnblock:null,quirksmodeOffsetHack:4};var b=null;var g=[];function d(r,F){var A=(r==window);var w=F&&F.message!==undefined?F.message:undefined;F=i.extend({},i.blockUI.defaults,F||{});F.overlayCSS=i.extend({},i.blockUI.defaults.overlayCSS,F.overlayCSS||{});var C=i.extend({},i.blockUI.defaults.css,F.css||{});var N=i.extend({},i.blockUI.defaults.themedCSS,F.themedCSS||{});w=w===undefined?F.message:w;if(A&&b){h(window,{fadeOut:0})}if(w&&typeof w!="string"&&(w.parentNode||w.jquery)){var I=w.jquery?w[0]:w;var P={};i(r).data("blockUI.history",P);P.el=I;P.parent=I.parentNode;P.display=I.style.display;P.position=I.style.position;if(P.parent){P.parent.removeChild(I)}}var B=F.baseZ;var M=(i.browser.msie||F.forceIframe)?i('<iframe class="blockUI" style="z-index:'+(B++)+';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+F.iframeSrc+'"></iframe>'):i('<div class="blockUI" style="display:none"></div>');var L=i('<div class="blockUI blockOverlay" style="z-index:'+(B++)+';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');var K;if(F.theme&&A){var G='<div class="blockUI blockMsg blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+B+';display:none;position:fixed"><div class="ui-widget-header ui-dialog-titlebar blockTitle">'+(F.title||"&nbsp;")+'</div><div class="ui-widget-content ui-dialog-content"></div></div>';K=i(G)}else{K=A?i('<div class="blockUI blockMsg blockPage" style="z-index:'+B+';display:none;position:fixed"></div>'):i('<div class="blockUI blockMsg blockElement" style="z-index:'+B+';display:none;position:absolute"></div>')}if(w){if(F.theme){K.css(N);K.addClass("ui-widget-content")}else{K.css(C)}}if(!F.applyPlatformOpacityRules||!(i.browser.mozilla&&/Linux/.test(navigator.platform))){L.css(F.overlayCSS)}L.css("position",A?"fixed":"absolute");if(i.browser.msie||F.forceIframe){M.css("opacity",0)}var y=[M,L,K],O=A?i("body"):i(r);i.each(y,function(){this.appendTo(O)});if(F.theme&&F.draggable&&i.fn.draggable){K.draggable({handle:".ui-dialog-titlebar",cancel:"li"})}var v=e&&(!i.boxModel||i("object,embed",A?null:r).length>0);if(f||v){if(A&&F.allowBodyStretch&&i.boxModel){i("html,body").css("height","100%")}if((f||!i.boxModel)&&!A){var E=m(r,"borderTopWidth"),J=m(r,"borderLeftWidth");var x=E?"(0 - "+E+")":0;var D=J?"(0 - "+J+")":0}i.each([M,L,K],function(t,S){var z=S[0].style;z.position="absolute";if(t<2){A?z.setExpression("height","Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:"+F.quirksmodeOffsetHack+') + "px"'):z.setExpression("height",'this.parentNode.offsetHeight + "px"');A?z.setExpression("width",'jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"'):z.setExpression("width",'this.parentNode.offsetWidth + "px"');if(D){z.setExpression("left",D)}if(x){z.setExpression("top",x)}}else{if(F.centerY){if(A){z.setExpression("top",'(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"')}z.marginTop=0}else{if(!F.centerY&&A){var Q=(F.css&&F.css.top)?parseInt(F.css.top):0;var R="((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "+Q+') + "px"';z.setExpression("top",R)}}}})}if(w){if(F.theme){K.find(".ui-widget-content").append(w)}else{K.append(w)}if(w.jquery||w.nodeType){i(w).show()}}if((i.browser.msie||F.forceIframe)&&F.showOverlay){M.show()}if(F.fadeIn){var H=F.onBlock?F.onBlock:c;var q=(F.showOverlay&&!w)?H:c;var p=w?H:c;if(F.showOverlay){L._fadeIn(F.fadeIn,q)}if(w){K._fadeIn(F.fadeIn,p)}}else{if(F.showOverlay){L.show()}if(w){K.show()}if(F.onBlock){F.onBlock()}}l(1,r,F);if(A){b=K[0];g=i(":input:enabled:visible",b);if(F.focusInput){setTimeout(o,20)}}else{a(K[0],F.centerX,F.centerY)}if(F.timeout){var u=setTimeout(function(){A?i.unblockUI(F):i(r).unblock(F)},F.timeout);i(r).data("blockUI.timeout",u)}}function h(s,t){var r=(s==window);var q=i(s);var u=q.data("blockUI.history");var v=q.data("blockUI.timeout");if(v){clearTimeout(v);q.removeData("blockUI.timeout")}t=i.extend({},i.blockUI.defaults,t||{});l(0,s,t);var p;if(r){p=i("body").children().filter(".blockUI").add("body > .blockUI")}else{p=i(".blockUI",s)}if(r){b=g=null}if(t.fadeOut){p.fadeOut(t.fadeOut);setTimeout(function(){k(p,u,t,s)},t.fadeOut)}else{k(p,u,t,s)}}function k(p,s,r,q){p.each(function(t,u){if(this.parentNode){this.parentNode.removeChild(this)}});if(s&&s.el){s.el.style.display=s.display;s.el.style.position=s.position;if(s.parent){s.parent.appendChild(s.el)}i(q).removeData("blockUI.history")}if(typeof r.onUnblock=="function"){r.onUnblock(q,r)}}function l(p,t,u){var s=t==window,r=i(t);if(!p&&(s&&!b||!s&&!r.data("blockUI.isBlocked"))){return}if(!s){r.data("blockUI.isBlocked",p)}if(!u.bindEvents||(p&&!u.showOverlay)){return}var q="mousedown mouseup keydown keypress";p?i(document).bind(q,u,n):i(document).unbind(q,n)}function n(s){if(s.keyCode&&s.keyCode==9){if(b&&s.data.constrainTabKey){var r=g;var q=!s.shiftKey&&s.target==r[r.length-1];var p=s.shiftKey&&s.target==r[0];if(q||p){setTimeout(function(){o(p)},10);return false}}}if(i(s.target).parents("div.blockMsg").length>0){return true}return i(s.target).parents().children().filter("div.blockUI").length==0}function o(p){if(!g){return}var q=g[p===true?g.length-1:0];if(q){q.focus()}}function a(w,q,A){var z=w.parentNode,v=w.style;var r=((z.offsetWidth-w.offsetWidth)/2)-m(z,"borderLeftWidth");var u=((z.offsetHeight-w.offsetHeight)/2)-m(z,"borderTopWidth");if(q){v.left=r>0?(r+"px"):"0"}if(A){v.top=u>0?(u+"px"):"0"}}function m(q,r){return parseInt(i.css(q,r))||0}})(jQuery); \ No newline at end of file
diff --git a/libs/jquery/jquery.js b/libs/jquery/jquery.js
index b1ae21d8b2..7c24308023 100644
--- a/libs/jquery/jquery.js
+++ b/libs/jquery/jquery.js
@@ -1,19 +1,154 @@
-/*
- * jQuery JavaScript Library v1.3.2
+/*!
+ * jQuery JavaScript Library v1.4.2
* http://jquery.com/
*
- * Copyright (c) 2009 John Resig
- * Dual licensed under the MIT and GPL licenses.
- * http://docs.jquery.com/License
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
*
- * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
- * Revision: 6246
- */
-(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
-/*
- * Sizzle CSS Selector Engine - v0.9.3
- * Copyright 2009, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- * More information: http://sizzlejs.com/
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Sat Feb 13 22:33:48 2010 -0500
*/
-(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML=' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file
+(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
+e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
+j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
+"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
+true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
+Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
+(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
+a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
+"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
+function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
+c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
+L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
+"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
+d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
+a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
+!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
+true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
+parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
+s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
+applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
+else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
+a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
+w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
+cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
+i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
+" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
+this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
+e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
+c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
+a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
+function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
+k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
+C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
+null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
+e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
+f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
+if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
+"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
+a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
+isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
+{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
+if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
+e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
+"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
+d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
+!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
+toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
+u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
+function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
+if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
+t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
+g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
+for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
+1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
+CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
+relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
+l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
+h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
+CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
+g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
+text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
+setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
+h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
+m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
+"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
+h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
+!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
+h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
+q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
+if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
+(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
+function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
+gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
+c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
+{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
+"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
+d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
+a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
+1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
+a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
+""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
+this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
+u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
+1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
+return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
+""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
+c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
+c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
+function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
+Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
+"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
+a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
+a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
+"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
+serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
+function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
+global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
+e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
+"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
+false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
+false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
+c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
+d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
+g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
+1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
+"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
+if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
+this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
+"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
+animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
+j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
+this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
+"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
+c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
+this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
+this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
+e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
+c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
+function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
+this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
+k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
+f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
+a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
+c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
+d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
+f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
+"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
+e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
diff --git a/libs/jquery/jquery.scrollTo-min.js b/libs/jquery/jquery.scrollTo-min.js
deleted file mode 100644
index eacfe567c3..0000000000
--- a/libs/jquery/jquery.scrollTo-min.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * jQuery.ScrollTo - Easy element scrolling using jQuery.
- * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
- * Dual licensed under MIT and GPL.
- * Date: 9/11/2008
- * @author Ariel Flesler
- * @version 1.4
- *
- * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
- */
-;(function(h){var m=h.scrollTo=function(b,c,g){h(window).scrollTo(b,c,g)};m.defaults={axis:'y',duration:1};m.window=function(b){return h(window).scrollable()};h.fn.scrollable=function(){return this.map(function(){var b=this.parentWindow||this.defaultView,c=this.nodeName=='#document'?b.frameElement||b:this,g=c.contentDocument||(c.contentWindow||c).document,i=c.setInterval;return c.nodeName=='IFRAME'||i&&h.browser.safari?g.body:i?g.documentElement:this})};h.fn.scrollTo=function(r,j,a){if(typeof j=='object'){a=j;j=0}if(typeof a=='function')a={onAfter:a};a=h.extend({},m.defaults,a);j=j||a.speed||a.duration;a.queue=a.queue&&a.axis.length>1;if(a.queue)j/=2;a.offset=n(a.offset);a.over=n(a.over);return this.scrollable().each(function(){var k=this,o=h(k),d=r,l,e={},p=o.is('html,body');switch(typeof d){case'number':case'string':if(/^([+-]=)?\d+(px)?$/.test(d)){d=n(d);break}d=h(d,this);case'object':if(d.is||d.style)l=(d=h(d)).offset()}h.each(a.axis.split(''),function(b,c){var g=c=='x'?'Left':'Top',i=g.toLowerCase(),f='scroll'+g,s=k[f],t=c=='x'?'Width':'Height',v=t.toLowerCase();if(l){e[f]=l[i]+(p?0:s-o.offset()[i]);if(a.margin){e[f]-=parseInt(d.css('margin'+g))||0;e[f]-=parseInt(d.css('border'+g+'Width'))||0}e[f]+=a.offset[i]||0;if(a.over[i])e[f]+=d[v]()*a.over[i]}else e[f]=d[i];if(/^\d+$/.test(e[f]))e[f]=e[f]<=0?0:Math.min(e[f],u(t));if(!b&&a.queue){if(s!=e[f])q(a.onAfterFirst);delete e[f]}});q(a.onAfter);function q(b){o.animate(e,j,a.easing,b&&function(){b.call(this,r,a)})};function u(b){var c='scroll'+b,g=k.ownerDocument;return p?Math.max(g.documentElement[c],g.body[c]):k[c]}}).end()};function n(b){return typeof b=='object'?b:{top:b,left:b}}})(jQuery); \ No newline at end of file
diff --git a/libs/jquery/macFFBgHack.png b/libs/jquery/macFFBgHack.png
deleted file mode 100644
index c6473b324e..0000000000
--- a/libs/jquery/macFFBgHack.png
+++ /dev/null
Binary files differ
diff --git a/libs/jquery/original lib/jquery-calendar.js b/libs/jquery/original lib/jquery-calendar.js
deleted file mode 100644
index e7100e2d93..0000000000
--- a/libs/jquery/original lib/jquery-calendar.js
+++ /dev/null
@@ -1,814 +0,0 @@
-/* jQuery Calendar v2.7
- Written by Marc Grabanski (m@marcgrabanski.com) and enhanced by Keith Wood (kbwood@iprimus.com.au).
-
- Copyright (c) 2007 Marc Grabanski (http://marcgrabanski.com/code/jquery-calendar)
- Dual licensed under the GPL (http://www.gnu.org/licenses/gpl-3.0.txt) and
- CC (http://creativecommons.org/licenses/by/3.0/) licenses. "Share or Remix it but please Attribute the authors."
- Date: 09-03-2007 */
-
-/* PopUp Calendar manager.
- Use the singleton instance of this class, popUpCal, to interact with the calendar.
- Settings for (groups of) calendars are maintained in an instance object
- (PopUpCalInstance), allowing multiple different settings on the same page. */
-function PopUpCal() {
- this._nextId = 0; // Next ID for a calendar instance
- this._inst = []; // List of instances indexed by ID
- this._curInst = null; // The current instance in use
- this._disabledInputs = []; // List of calendar inputs that have been disabled
- this._popUpShowing = false; // True if the popup calendar is showing , false if not
- this._inDialog = false; // True if showing within a "dialog", false if not
- this.regional = []; // Available regional settings, indexed by language code
- this.regional[''] = { // Default regional settings
- clearText: 'Clear', // Display text for clear link
- closeText: 'Close', // Display text for close link
- prevText: '&lt;Prev', // Display text for previous month link
- nextText: 'Next&gt;', // Display text for next month link
- currentText: 'Today', // Display text for current month link
- dayNames: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Names of days starting at Sunday
- monthNames: ['January','February','March','April','May','June',
- 'July','August','September','October','November','December'], // Names of months
- dateFormat: 'DMY/' // First three are day, month, year in the required order,
- // fourth (optional) is the separator, e.g. US would be 'MDY/', ISO would be 'YMD-'
- };
- this._defaults = { // Global defaults for all the calendar instances
- autoPopUp: 'focus', // 'focus' for popup on focus,
- // 'button' for trigger button, or 'both' for either
- appendText: '', // Display text following the input box, e.g. showing the format
- buttonText: '...', // Text for trigger button
- buttonImage: '', // URL for trigger button image
- buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
- closeAtTop: true, // True to have the clear/close at the top,
- // false to have them at the bottom
- hideIfNoPrevNext: false, // True to hide next/previous month links
- // if not applicable, false to just disable them
- changeMonth: true, // True if month can be selected directly, false if only prev/next
- changeYear: true, // True if year can be selected directly, false if only prev/next
- yearRange: '-10:+10', // Range of years to display in drop-down,
- // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
- firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
- changeFirstDay: true, // True to click on day name to change, false to remain as set
- showOtherMonths: false, // True to show dates in other months, false to leave blank
- minDate: null, // The earliest selectable date, or null for no limit
- maxDate: null, // The latest selectable date, or null for no limit
- speed: 'medium', // Speed of display/closure
- customDate: null, // Function that takes a date and returns an array with
- // [0] = true if selectable, false if not,
- // [1] = custom CSS class name(s) or '', e.g. popUpCal.noWeekends
- fieldSettings: null, // Function that takes an input field and
- // returns a set of custom settings for the calendar
- onSelect: null // Define a callback function when a date is selected
- };
- $.extend(this._defaults, this.regional['']);
- this._calendarDiv = $('<div id="calendar_div"></div>');
- $(document.body).append(this._calendarDiv);
- $(document.body).mousedown(this._checkExternalClick);
-}
-
-$.extend(PopUpCal.prototype, {
- /* Register a new calendar instance - with custom settings. */
- _register: function(inst) {
- var id = this._nextId++;
- this._inst[id] = inst;
- return id;
- },
-
- /* Retrieve a particular calendar instance based on its ID. */
- _getInst: function(id) {
- return this._inst[id] || id;
- },
-
- /* Override the default settings for all instances of the calendar.
- @param settings object - the new settings to use as defaults (anonymous object)
- @return void */
- setDefaults: function(settings) {
- $.extend(this._defaults, settings || {});
- },
-
- /* Handle keystrokes. */
- _doKeyDown: function(e) {
- var inst = popUpCal._getInst(this._calId);
- if (popUpCal._popUpShowing) {
- switch (e.keyCode) {
- case 9: popUpCal.hideCalendar(inst, '');
- break; // hide on tab out
- case 13: popUpCal._selectDate(inst);
- break; // select the value on enter
- case 27: popUpCal.hideCalendar(inst, inst._get('speed'));
- break; // hide on escape
- case 33: popUpCal._adjustDate(inst, -1, (e.ctrlKey ? 'Y' : 'M'));
- break; // previous month/year on page up/+ ctrl
- case 34: popUpCal._adjustDate(inst, +1, (e.ctrlKey ? 'Y' : 'M'));
- break; // next month/year on page down/+ ctrl
- case 35: if (e.ctrlKey) popUpCal._clearDate(inst);
- break; // clear on ctrl+end
- case 36: if (e.ctrlKey) popUpCal._gotoToday(inst);
- break; // current on ctrl+home
- case 37: if (e.ctrlKey) popUpCal._adjustDate(inst, -1, 'D');
- break; // -1 day on ctrl+left
- case 38: if (e.ctrlKey) popUpCal._adjustDate(inst, -7, 'D');
- break; // -1 week on ctrl+up
- case 39: if (e.ctrlKey) popUpCal._adjustDate(inst, +1, 'D');
- break; // +1 day on ctrl+right
- case 40: if (e.ctrlKey) popUpCal._adjustDate(inst, +7, 'D');
- break; // +1 week on ctrl+down
- }
- }
- else if (e.keyCode == 36 && e.ctrlKey) { // display the calendar on ctrl+home
- popUpCal.showFor(this);
- }
- },
-
- /* Filter entered characters. */
- _doKeyPress: function(e) {
- var inst = popUpCal._getInst(this._calId);
- var chr = String.fromCharCode(e.charCode == undefined ? e.keyCode : e.charCode);
- return (chr < ' ' || chr == inst._get('dateFormat').charAt(3) ||
- (chr >= '0' && chr <= '9')); // only allow numbers and separator
- },
-
- /* Attach the calendar to an input field. */
- _connectCalendar: function(target, inst) {
- var $input = $(target);
- var appendText = inst._get('appendText');
- if (appendText) {
- $input.after('<span class="calendar_append">' + appendText + '</span>');
- }
- var autoPopUp = inst._get('autoPopUp');
- if (autoPopUp == 'focus' || autoPopUp == 'both') { // pop-up calendar when in the marked field
- $input.focus(this.showFor);
- }
- if (autoPopUp == 'button' || autoPopUp == 'both') { // pop-up calendar when button clicked
- var buttonText = inst._get('buttonText');
- var buttonImage = inst._get('buttonImage');
- var buttonImageOnly = inst._get('buttonImageOnly');
- var trigger = $(buttonImageOnly ? '<img class="calendar_trigger" src="' +
- buttonImage + '" alt="' + buttonText + '" title="' + buttonText + '"/>' :
- '<button type="button" class="calendar_trigger">' + (buttonImage != '' ?
- '<img src="' + buttonImage + '" alt="' + buttonText + '" title="' + buttonText + '"/>' :
- buttonText) + '</button>');
- $input.wrap('<span class="calendar_wrap"></span>').after(trigger);
- trigger.click(this.showFor);
- }
- $input.keydown(this._doKeyDown).keypress(this._doKeyPress);
- $input[0]._calId = inst._id;
- },
-
- /* Attach an inline calendar to a div. */
- _inlineCalendar: function(target, inst, defaultDate) {
- $(target).append(inst._calendarDiv);
- target._calId = inst._id;
- var date = defaultDate;
- inst._selectedDay = date.getDate();
- inst._selectedMonth = date.getMonth();
- inst._selectedYear = date.getFullYear();
- popUpCal._adjustDate(inst);
- },
-
- /* Pop-up the calendar in a "dialog" box.
- @param dateText string - the initial date to display (in the current format)
- @param onSelect function - the function(dateText) to call when a date is selected
- @param settings object - update the dialog calendar instance's settings (anonymous object)
- @param pos int[2] - coordinates for the dialog's position within the screen
- leave empty for default (screen centre)
- @return void */
- dialogCalendar: function(dateText, onSelect, settings, pos) {
- var inst = this._dialogInst; // internal instance
- if (!inst) {
- inst = this._dialogInst = new PopUpCalInstance({}, false);
- this._dialogInput = $('<input type="text" size="1" style="position: absolute; top: -100px;"/>');
- this._dialogInput.keydown(this._doKeyDown);
- $('body').append(this._dialogInput);
- this._dialogInput[0]._calId = inst._id;
- }
- $.extend(inst._settings, settings || {});
- this._dialogInput.val(dateText);
-
- /* Cross Browser Positioning */
- if (self.innerHeight) { // all except Explorer
- windowWidth = self.innerWidth;
- windowHeight = self.innerHeight;
- } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
- windowWidth = document.documentElement.clientWidth;
- windowHeight = document.documentElement.clientHeight;
- } else if (document.body) { // other Explorers
- windowWidth = document.body.clientWidth;
- windowHeight = document.body.clientHeight;
- }
- this._pos = pos || // should use actual width/height below
- [(windowWidth / 2) - 100, (windowHeight / 2) - 100];
-
- // move input on screen for focus, but hidden behind dialog
- this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
- inst._settings.onSelect = onSelect;
- this._inDialog = true;
- this._calendarDiv.addClass('calendar_dialog');
- this.showFor(this._dialogInput[0]);
- if ($.blockUI) {
- $.blockUI(this._calendarDiv);
- }
- },
-
- /* Enable the input field(s) for entry.
- @param inputs element/object - single input field or jQuery collection of input fields
- @return void */
- enableFor: function(inputs) {
- inputs = (inputs.jquery ? inputs : $(inputs));
- inputs.each(function() {
- this.disabled = false;
- $('../button.calendar_trigger', this).each(function() { this.disabled = false; });
- $('../img.calendar_trigger',
-this).css({opacity:'1.0',cursor:''});
- var $this = this;
- popUpCal._disabledInputs = $.map(popUpCal._disabledInputs,
- function(value) { return (value == $this ? null : value); }); // delete entry
- });
- },
-
- /* Disable the input field(s) from entry.
- @param inputs element/object - single input field or jQuery collection of input fields
- @return void */
- disableFor: function(inputs) {
- inputs = (inputs.jquery ? inputs : $(inputs));
- inputs.each(function() {
- this.disabled = true;
- $('../button.calendar_trigger', this).each(function() { this.disabled = true; });
- $('../img.calendar_trigger', this).css({opacity:'0.5',cursor:'default'});
- var $this = this;
- popUpCal._disabledInputs = $.map(popUpCal._disabledInputs,
- function(value) { return (value == $this ? null : value); }); // delete entry
- popUpCal._disabledInputs[popUpCal._disabledInputs.length] = this;
- });
- },
-
- /* Update the settings for a calendar attached to an input field or division.
- @param control element - the input field or div/span attached to the calendar
- @param settings object - the new settings to update
- @return void */
- reconfigureFor: function(control, settings) {
- var inst = this._getInst(control._calId);
- if (inst) {
- $.extend(inst._settings, settings || {});
- this._updateCalendar(inst);
- }
- },
-
- /* Set the date for a calendar attached to an input field or division.
- @param control element - the input field or div/span attached to the calendar
- @param date Date - the new date
- @return void */
- setDateFor: function(control, date) {
- var inst = this._getInst(control._calId);
- if (inst) {
- inst._setDate(date);
- }
- },
-
- /* Retrieve the date for a calendar attached to an input field or division.
- @param control element - the input field or div/span attached to the calendar
- @return Date - the current date */
- getDateFor: function(control) {
- var inst = this._getInst(control._calId);
- return (inst ? inst._getDate() : null);
- },
-
- /* Pop-up the calendar for a given input field.
- @param target element - the input field attached to the calendar
- @return void */
- showFor: function(target) {
- var input = (target.nodeName && target.nodeName.toLowerCase() == 'input' ? target : this);
- if (input.nodeName.toLowerCase() != 'input') { // find from button/image trigger
- input = $('input', input.parentNode)[0];
- }
- if (popUpCal._lastInput == input) { // already here
- return;
- }
- for (var i = 0; i < popUpCal._disabledInputs.length; i++) { // check not disabled
- if (popUpCal._disabledInputs[i] == input) {
- return;
- }
- }
- var inst = popUpCal._getInst(input._calId);
- popUpCal.hideCalendar(inst, '');
- popUpCal._lastInput = input;
- inst._setDateFromField(input);
- if (popUpCal._inDialog) { // hide cursor
- input.value = '';
- }
- if (!popUpCal._pos) { // position below input
- popUpCal._pos = popUpCal._findPos(input);
- popUpCal._pos[1] += input.offsetHeight;
- }
- inst._calendarDiv.css('position', (popUpCal._inDialog && $.blockUI ? 'static' : 'absolute')).
- css('left', popUpCal._pos[0] + 'px').css('top', popUpCal._pos[1] + 'px');
- popUpCal._pos = null;
- var fieldSettings = inst._get('fieldSettings');
- $.extend(inst._settings, (fieldSettings ? fieldSettings(input) : {}));
- popUpCal._showCalendar(inst);
- },
-
- /* Construct and display the calendar. */
- _showCalendar: function(id) {
- var inst = this._getInst(id);
- popUpCal._updateCalendar(inst);
- if (!inst._inline) {
- var speed = inst._get('speed');
- inst._calendarDiv.show(speed, function() {
- popUpCal._popUpShowing = true;
- popUpCal._afterShow(inst);
- });
- if (speed == '') {
- popUpCal._popUpShowing = true;
- popUpCal._afterShow(inst);
- }
- if (inst._input[0].type != 'hidden') {
- inst._input[0].focus();
- }
- this._curInst = inst;
- }
- },
-
- /* Generate the calendar content. */
- _updateCalendar: function(inst) {
- inst._calendarDiv.empty().append(inst._generateCalendar());
- if (inst._input && inst._input != 'hidden') {
- inst._input[0].focus();
- }
- },
-
- /* Tidy up after displaying the calendar. */
- _afterShow: function(inst) {
- if ($.browser.msie) { // fix IE < 7 select problems
- $('#calendar_cover').css({width: inst._calendarDiv[0].offsetWidth + 4,
- height: inst._calendarDiv[0].offsetHeight + 4});
- }
- /*// re-position on screen if necessary
- var calDiv = inst._calendarDiv[0];
- var pos = popUpCal._findPos(inst._input[0]);
- if ((calDiv.offsetLeft + calDiv.offsetWidth) >
- (document.body.clientWidth + document.body.scrollLeft)) {
- inst._calendarDiv.css('left', (pos[0] + inst._input[0].offsetWidth - calDiv.offsetWidth) + 'px');
- }
- if ((calDiv.offsetTop + calDiv.offsetHeight) >
- (document.body.clientHeight + document.body.scrollTop)) {
- inst._calendarDiv.css('top', (pos[1] - calDiv.offsetHeight) + 'px');
- }*/
- },
-
- /* Hide the calendar from view.
- @param id string/object - the ID of the current calendar instance,
- or the instance itself
- @param speed string - the speed at which to close the calendar
- @return void */
- hideCalendar: function(id, speed) {
- var inst = this._getInst(id);
- if (popUpCal._popUpShowing) {
- speed = (speed != null ? speed : inst._get('speed'));
- inst._calendarDiv.hide(speed, function() {
- popUpCal._tidyDialog(inst);
- });
- if (speed == '') {
- popUpCal._tidyDialog(inst);
- }
- popUpCal._popUpShowing = false;
- popUpCal._lastInput = null;
- inst._settings.prompt = null;
- if (popUpCal._inDialog) {
- popUpCal._dialogInput.css('position', 'absolute').
- css('left', '0px').css('top', '-100px');
- if ($.blockUI) {
- $.unblockUI();
- $('body').append(this._calendarDiv);
- }
- }
- popUpCal._inDialog = false;
- }
- popUpCal._curInst = null;
- },
-
- /* Tidy up after a dialog display. */
- _tidyDialog: function(inst) {
- inst._calendarDiv.removeClass('calendar_dialog');
- $('.calendar_prompt', inst._calendarDiv).remove();
- },
-
- /* Close calendar if clicked elsewhere. */
- _checkExternalClick: function(event) {
- if (!popUpCal._curInst) {
- return;
- }
- var target = $(event.target);
- if( (target.parents("#calendar_div").length == 0)
- && (target.attr('class') != 'calendar_trigger')
- && popUpCal._popUpShowing
- && !(popUpCal._inDialog && $.blockUI) )
- {
- popUpCal.hideCalendar(popUpCal._curInst, '');
- }
- },
-
- /* Adjust one of the date sub-fields. */
- _adjustDate: function(id, offset, period) {
- var inst = this._getInst(id);
- inst._adjustDate(offset, period);
- this._updateCalendar(inst);
- },
-
- /* Action for current link. */
- _gotoToday: function(id) {
- var date = new Date();
- var inst = this._getInst(id);
- inst._selectedDay = date.getDate();
- inst._selectedMonth = date.getMonth();
- inst._selectedYear = date.getFullYear();
- this._adjustDate(inst);
- },
-
- /* Action for selecting a new month/year. */
- _selectMonthYear: function(id, select, period) {
- var inst = this._getInst(id);
- inst._selectingMonthYear = false;
- inst[period == 'M' ? '_selectedMonth' : '_selectedYear'] =
- select.options[select.selectedIndex].value - 0;
- this._adjustDate(inst);
- },
-
- /* Restore input focus after not changing month/year. */
- _clickMonthYear: function(id) {
- var inst = this._getInst(id);
- if (inst._input && inst._selectingMonthYear && !$.browser.msie) {
- inst._input[0].focus();
- }
- inst._selectingMonthYear = !inst._selectingMonthYear;
- },
-
- /* Action for changing the first week day. */
- _changeFirstDay: function(id, a) {
- var inst = this._getInst(id);
- var dayNames = inst._get('dayNames');
- var value = a.firstChild.nodeValue;
- for (var i = 0; i < 7; i++) {
- if (dayNames[i] == value) {
- inst._settings.firstDay = i;
- break;
- }
- }
- this._updateCalendar(inst);
- },
-
- /* Action for selecting a day. */
- _selectDay: function(id, td) {
- var inst = this._getInst(id);
- inst._selectedDay = $("a", td).html();
- this._selectDate(id);
- },
-
- /* Erase the input field and hide the calendar. */
- _clearDate: function(id) {
- this._selectDate(id, '');
- },
-
- /* Update the input field with the selected date. */
- _selectDate: function(id, dateStr) {
- var inst = this._getInst(id);
- dateStr = (dateStr != null ? dateStr : inst._formatDate());
- if (inst._input) {
- inst._input.val(dateStr);
- }
- var onSelect = inst._get('onSelect');
- if (onSelect) {
- onSelect(dateStr); // trigger custom callback
- }
- else {
- inst._input.trigger('change'); // fire the change event
- }
- if (inst._inline) {
- this._updateCalendar(inst);
- }
- else {
- this.hideCalendar(inst, inst._get('speed'));
- }
- },
-
- /* Set as customDate function to prevent selection of weekends.
- @param date Date - the date to customise
- @return [boolean, string] - is this date selectable?, what is its CSS class? */
- noWeekends: function(date) {
- var day = date.getDay();
- return [(day > 0 && day < 6), ''];
- },
-
- /* Find an object's position on the screen. */
- _findPos: function(obj) {
- if (obj.type == 'hidden') {
- obj = obj.nextSibling;
- }
- var curleft = curtop = 0;
- if (obj.offsetParent) {
- curleft = obj.offsetLeft;
- curtop = obj.offsetTop;
- while (obj = obj.offsetParent) {
- var origcurleft = curleft;
- curleft += obj.offsetLeft;
- if (curleft < 0) {
- curleft = origcurleft;
- }
- curtop += obj.offsetTop;
- }
- }
- return [curleft,curtop];
- }
-});
-
-/* Individualised settings for calendars applied to one or more related inputs.
- Instances are managed and manipulated through the PopUpCal manager. */
-function PopUpCalInstance(settings, inline, defaultDate) {
- this._id = popUpCal._register(this);
- this._selectedDay = 0;
- this._selectedMonth = 0; // 0-11
- this._selectedYear = 0; // 4-digit year
- this._input = null; // The attached input field
- this._inline = inline; // True if showing inline, false if used in a popup
- this._calendarDiv = (!inline ? popUpCal._calendarDiv :
- $('<div id="calendar_div_' + this._id + '" class="calendar_inline"></div>'));
- if (inline) {
- var date = defaultDate;
- this._currentDate = defaultDate;
- this._currentDay = date.getDate();
- this._currentMonth = date.getMonth();
- this._currentYear = date.getFullYear();
- }
- // customise the calendar object - uses manager defaults if not overridden
- this._settings = $.extend({}, settings || {}); // clone
-}
-
-$.extend(PopUpCalInstance.prototype, {
- /* Get a setting value, defaulting if necessary. */
- _get: function(name) {
- return (this._settings[name] != null ? this._settings[name] : popUpCal._defaults[name]);
- },
-
- /* Parse existing date and initialise calendar. */
- _setDateFromField: function(input) {
- this._input = $(input);
- var dateFormat = this._get('dateFormat');
- var currentDate = this._input.val().split(dateFormat.charAt(3));
- if (currentDate.length == 3) {
- this._currentDay = parseInt(currentDate[dateFormat.indexOf('D')], 10);
- this._currentMonth = parseInt(currentDate[dateFormat.indexOf('M')], 10) - 1;
- this._currentYear = parseInt(currentDate[dateFormat.indexOf('Y')], 10);
- }
- else {
- var date = new Date();
- this._currentDay = date.getDate();
- this._currentMonth = date.getMonth();
- this._currentYear = date.getFullYear();
- }
- this._selectedDay = this._currentDay;
- this._selectedMonth = this._currentMonth;
- this._selectedYear = this._currentYear;
- this._adjustDate();
- },
-
- /* Set the date directly. */
- _setDate: function(date) {
- this._selectedDay = this._currentDay = date.getDate();
- this._selectedMonth = this._currentMonth = date.getMonth();
- this._selectedYear = this._currentYear = date.getFullYear();
- this._adjustDate();
- },
-
- /* Retrieve the date directly. */
- _getDate: function() {
- return new Date(this._currentYear, this._currentMonth, this._currentDay);
- },
-
- /* Generate the HTML for the current state of the calendar. */
- _generateCalendar: function() {
- var today = this._currentDate;
- today = new Date(today.getFullYear(), today.getMonth(), today.getDate()); // clear time
- // build the calendar HTML
- var controls = '<div class="calendar_control">' +
- '<a class="calendar_clear" onclick="popUpCal._clearDate(' + this._id + ');">' +
- this._get('clearText') + '</a>' +
- '<a class="calendar_close" onclick="popUpCal.hideCalendar(' + this._id + ');">' +
- this._get('closeText') + '</a></div>';
- var prompt = this._get('prompt');
- var closeAtTop = this._get('closeAtTop');
- var hideIfNoPrevNext = this._get('hideIfNoPrevNext');
- // controls and links
- var html = (prompt ? '<div class="calendar_prompt">' + prompt + '</div>' : '') +
- (closeAtTop && !this._inline ? controls : '') + '<div class="calendar_links">' +
- (this._canAdjustMonth(-1) ? '<a class="calendar_prev" ' +
- 'onclick="popUpCal._adjustDate(' + this._id + ', -1, \'M\');">' + this._get('prevText') + '</a>' :
- (hideIfNoPrevNext ? '' : '<label class="calendar_prev">' + this._get('prevText') + '</label>')) +
- (this._isInRange(today) ? '<a class="calendar_current" ' +
- 'onclick="popUpCal._gotoToday(' + this._id + ');">' + this._get('currentText') + '</a>' : '') +
- (this._canAdjustMonth(+1) ? '<a class="calendar_next" ' +
- 'onclick="popUpCal._adjustDate(' + this._id + ', +1, \'M\');">' + this._get('nextText') + '</a>' :
- (hideIfNoPrevNext ? '' : '<label class="calendar_next">' + this._get('nextText') + '</label>')) +
- '</div><div class="calendar_header">';
- var minDate = this._get('minDate');
- var maxDate = this._get('maxDate');
- // month selection
- var monthNames = this._get('monthNames');
- if (!this._get('changeMonth')) {
- html += monthNames[this._selectedMonth] + '&nbsp;';
- }
- else {
- var inMinYear = (minDate && minDate.getFullYear() == this._selectedYear);
- var inMaxYear = (maxDate && maxDate.getFullYear() == this._selectedYear);
- html += '<select class="calendar_newMonth" ' +
- 'onchange="popUpCal._selectMonthYear(' + this._id + ', this, \'M\');" ' +
- 'onclick="popUpCal._clickMonthYear(' + this._id + ');">';
- for (var month = 0; month < 12; month++) {
- if ((!inMinYear || month >= minDate.getMonth()) &&
- (!inMaxYear || month <= maxDate.getMonth())) {
- html += '<option value="' + month + '"' +
- (month == this._selectedMonth ? ' selected="selected"' : '') +
- '>' + monthNames[month] + '</option>';
- }
- }
- html += '</select>';
- }
- // year selection
- if (!this._get('changeYear')) {
- html += this._selectedYear;
- }
- else {
- // determine range of years to display
- var years = this._get('yearRange').split(':');
- var year = 0;
- var endYear = 0;
- if (years.length != 2) {
- year = this._selectedYear - 10;
- endYear = this._selectedYear + 10;
- }
- else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
- year = this._selectedYear + parseInt(years[0], 10);
- endYear = this._selectedYear + parseInt(years[1], 10);
- }
- else {
- year = parseInt(years[0], 10);
- endYear = parseInt(years[1], 10);
- }
- year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
- endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
- html += '<select class="calendar_newYear" onchange="popUpCal._selectMonthYear(' +
- this._id + ', this, \'Y\');" ' + 'onclick="popUpCal._clickMonthYear(' +
- this._id + ');">';
- for (; year <= endYear; year++) {
- html += '<option value="' + year + '"' +
- (year == this._selectedYear ? ' selected="selected"' : '') +
- '>' + year + '</option>';
- }
- html += '</select>';
- }
- html += '</div><table class="calendar" cellpadding="0" cellspacing="0"><thead>' +
- '<tr class="calendar_titleRow">';
- var firstDay = this._get('firstDay');
- var changeFirstDay = this._get('changeFirstDay');
- var dayNames = this._get('dayNames');
- for (var dow = 0; dow < 7; dow++) { // days of the week
- html += '<td>' + (!changeFirstDay ? '' : '<a onclick="popUpCal._changeFirstDay(' +
- this._id + ', this);">') + dayNames[(dow + firstDay) % 7] +
- (changeFirstDay ? '</a>' : '') + '</td>';
- }
- html += '</tr></thead><tbody>';
- var daysInMonth = this._getDaysInMonth(this._selectedYear, this._selectedMonth);
- this._selectedDay = Math.min(this._selectedDay, daysInMonth);
- var leadDays = (this._getFirstDayOfMonth(this._selectedYear, this._selectedMonth) - firstDay + 7) % 7;
- var currentDate = new Date(this._currentYear, this._currentMonth, this._currentDay);
- var selectedDate = new Date(this._selectedYear, this._selectedMonth, this._selectedDay);
- var printDate = new Date(this._selectedYear, this._selectedMonth, 1 - leadDays);
- var numRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
- var customDate = this._get('customDate');
- var showOtherMonths = this._get('showOtherMonths');
- for (var row = 0; row < numRows; row++) { // create calendar rows
- html += '<tr class="calendar_daysRow">';
- for (var dow = 0; dow < 7; dow++) { // create calendar days
- var customSettings = (customDate ? customDate(printDate) : [true, '']);
- var otherMonth = (printDate.getMonth() != this._selectedMonth);
- var unselectable = otherMonth || !customSettings[0] ||
- (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
- html += '<td class="calendar_daysCell' +
- ((dow + firstDay + 6) % 7 >= 5 ? ' calendar_weekEndCell' : '') + // highlight weekends
- (otherMonth ? ' calendar_otherMonth' : '') + // highlight days from other months
- //(printDate.getTime() == selectedDate.getTime() ? ' calendar_daysCellOver' : '') + // highlight selected day
- (unselectable ? ' calendar_unselectable' : '') + // highlight unselectable days
- (!otherMonth || showOtherMonths ? ' ' + customSettings[1] : '') + // highlight custom dates
- (printDate.getTime() == currentDate.getTime() ? ' calendar_currentDay' : // highlight current day
- (printDate.getTime() == today.getTime() ? ' calendar_today' : '')) + '"' + // highlight today (if different)
- (unselectable ? '' : ' onmouseover="$(this).addClass(\'calendar_daysCellOver\');"' +
- ' onmouseout="$(this).removeClass(\'calendar_daysCellOver\');"' +
- ' onclick="popUpCal._selectDay(' + this._id + ', this);"') + '>' + // actions
- (otherMonth ? (showOtherMonths ? printDate.getDate() : '&nbsp;') : // display for other months
- (unselectable ? printDate.getDate() : '<a>' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
- printDate.setDate(printDate.getDate() + 1);
- }
- html += '</tr>';
- }
- html += '</tbody></table>' + (!closeAtTop && !this._inline ? controls : '') +
- '<div style="clear: both;"></div>' + (!$.browser.msie ? '' :
- '<!--[if lte IE 6.5]><iframe src="javascript:false;" class="calendar_cover"></iframe><![endif]-->');
- return html;
- },
-
- /* Adjust one of the date sub-fields. */
- _adjustDate: function(offset, period) {
- var date = new Date(this._selectedYear + (period == 'Y' ? offset : 0),
- this._selectedMonth + (period == 'M' ? offset : 0),
- this._selectedDay + (period == 'D' ? offset : 0));
- // ensure it is within the bounds set
- var minDate = this._get('minDate');
- var maxDate = this._get('maxDate');
- date = (minDate && date < minDate ? minDate : date);
- date = (maxDate && date > maxDate ? maxDate : date);
- this._selectedDay = date.getDate();
- this._selectedMonth = date.getMonth();
- this._selectedYear = date.getFullYear();
- },
-
- /* Find the number of days in a given month. */
- _getDaysInMonth: function(year, month) {
- return 32 - new Date(year, month, 32).getDate();
- },
-
- /* Find the day of the week of the first of a month. */
- _getFirstDayOfMonth: function(year, month) {
- return new Date(year, month, 1).getDay();
- },
-
- /* Determines if we should allow a "next/prev" month display change. */
- _canAdjustMonth: function(offset) {
- var date = new Date(this._selectedYear, this._selectedMonth + offset, 1);
- if (offset < 0) {
- date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
- }
- return this._isInRange(date);
- },
-
- /* Is the given date in the accepted range? */
- _isInRange: function(date) {
- var minDate = this._get('minDate');
- var maxDate = this._get('maxDate');
- return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
- },
-
- /* Format the given date for display. */
- _formatDate: function() {
- var day = this._currentDay = this._selectedDay;
- var month = this._currentMonth = this._selectedMonth;
- var year = this._currentYear = this._selectedYear;
- month++; // adjust javascript month
- var dateFormat = this._get('dateFormat');
- var dateString = '';
- for (var i = 0; i < 3; i++) {
- dateString += dateFormat.charAt(3) +
- (dateFormat.charAt(i) == 'D' ? (day < 10 ? '0' : '') + day :
- (dateFormat.charAt(i) == 'M' ? (month < 10 ? '0' : '') + month :
- (dateFormat.charAt(i) == 'Y' ? year : '?')));
- }
- return dateString.substring(dateFormat.charAt(3) ? 1 : 0);
- }
-});
-
-/* Attach the calendar to a jQuery selection.
- @param settings object - the new settings to use for this calendar instance (anonymous)
- @return jQuery object - for chaining further calls */
-$.fn.calendar = function(settings, defaultDate) {
- return this.each(function() {
- // check for settings on the control itself - in namespace 'cal:'
- var inlineSettings = null;
- for (attrName in popUpCal._defaults) {
- var attrValue = this.getAttribute('cal:' + attrName);
- if (attrValue) {
- inlineSettings = inlineSettings || {};
- try {
- inlineSettings[attrName] = eval(attrValue);
- }
- catch (err) {
- inlineSettings[attrName] = attrValue;
- }
- }
- }
- var nodeName = this.nodeName.toLowerCase();
- if (nodeName == 'input') {
- var instSettings = (inlineSettings ? $.extend($.extend({}, settings || {}),
- inlineSettings || {}) : settings); // clone and customise
- var inst = (inst && !inlineSettings ? inst :
- new PopUpCalInstance(instSettings, false, defaultDate));
- popUpCal._connectCalendar(this, inst);
- }
- else if (nodeName == 'div' || nodeName == 'span') {
- var instSettings = $.extend($.extend({}, settings || {}),
- inlineSettings || {}); // clone and customise
- var inst = new PopUpCalInstance(instSettings, true, defaultDate);
- popUpCal._inlineCalendar(this, inst, defaultDate);
- }
- });
-};
-
-/* Initialise the calendar. */
-$(document).ready(function() {
- popUpCal = new PopUpCal(); // singleton instance
-});
diff --git a/libs/jquery/original lib/jquery-ui.js b/libs/jquery/original lib/jquery-ui.js
index fc3a87fabe..5b1595b3f2 100644
--- a/libs/jquery/original lib/jquery-ui.js
+++ b/libs/jquery/original lib/jquery-ui.js
@@ -1,20 +1,26 @@
-/*
- * jQuery UI 1.7.2
+/*!
+ * jQuery UI 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI
*/
-;jQuery.ui || (function($) {
-var _remove = $.fn.remove,
- isFF2 = $.browser.mozilla && (parseFloat($.browser.version) < 1.9);
+(function($) {
+
+// prevent duplicate loading
+// this is only a problem because we proxy existing functions
+// and we don't want to double proxy them
+$.ui = $.ui || {};
+if ($.ui.version) {
+ return;
+}
//Helper functions and ui object
-$.ui = {
- version: "1.7.2",
+$.extend($.ui, {
+ version: "1.8.2",
// $.ui.plugin is deprecated. Use the proxy pattern instead.
plugin: {
@@ -73,9 +79,13 @@ $.ui = {
},
keyCode: {
+ ALT: 18,
BACKSPACE: 8,
CAPS_LOCK: 20,
COMMA: 188,
+ COMMAND: 91,
+ COMMAND_LEFT: 91, // COMMAND
+ COMMAND_RIGHT: 93,
CONTROL: 17,
DELETE: 46,
DOWN: 40,
@@ -85,6 +95,7 @@ $.ui = {
HOME: 36,
INSERT: 45,
LEFT: 37,
+ MENU: 93, // COMMAND_RIGHT
NUMPAD_ADD: 107,
NUMPAD_DECIMAL: 110,
NUMPAD_DIVIDE: 111,
@@ -98,64 +109,36 @@ $.ui = {
SHIFT: 16,
SPACE: 32,
TAB: 9,
- UP: 38
+ UP: 38,
+ WINDOWS: 91 // COMMAND
}
-};
-
-// WAI-ARIA normalization
-if (isFF2) {
- var attr = $.attr,
- removeAttr = $.fn.removeAttr,
- ariaNS = "http://www.w3.org/2005/07/aaa",
- ariaState = /^aria-/,
- ariaRole = /^wairole:/;
-
- $.attr = function(elem, name, value) {
- var set = value !== undefined;
-
- return (name == 'role'
- ? (set
- ? attr.call(this, elem, name, "wairole:" + value)
- : (attr.apply(this, arguments) || "").replace(ariaRole, ""))
- : (ariaState.test(name)
- ? (set
- ? elem.setAttributeNS(ariaNS,
- name.replace(ariaState, "aaa:"), value)
- : attr.call(this, elem, name.replace(ariaState, "aaa:")))
- : attr.apply(this, arguments)));
- };
-
- $.fn.removeAttr = function(name) {
- return (ariaState.test(name)
- ? this.each(function() {
- this.removeAttributeNS(ariaNS, name.replace(ariaState, ""));
- }) : removeAttr.call(this, name));
- };
-}
+});
//jQuery plugins
$.fn.extend({
- remove: function() {
- // Safari has a native remove event which actually removes DOM elements,
- // so we have to use triggerHandler instead of trigger (#3037).
- $("*", this).add(this).each(function() {
- $(this).triggerHandler("remove");
- });
- return _remove.apply(this, arguments );
+ _focus: $.fn.focus,
+ focus: function(delay, fn) {
+ return typeof delay === 'number'
+ ? this.each(function() {
+ var elem = this;
+ setTimeout(function() {
+ $(elem).focus();
+ (fn && fn.call(elem));
+ }, delay);
+ })
+ : this._focus.apply(this, arguments);
},
-
+
enableSelection: function() {
return this
.attr('unselectable', 'off')
- .css('MozUserSelect', '')
- .unbind('selectstart.ui');
+ .css('MozUserSelect', '');
},
disableSelection: function() {
return this
.attr('unselectable', 'on')
- .css('MozUserSelect', 'none')
- .bind('selectstart.ui', function() { return false; });
+ .css('MozUserSelect', 'none');
},
scrollParent: function() {
@@ -171,6 +154,36 @@ $.fn.extend({
}
return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
+ },
+
+ zIndex: function(zIndex) {
+ if (zIndex !== undefined) {
+ return this.css('zIndex', zIndex);
+ }
+
+ if (this.length) {
+ var elem = $(this[0]), position, value;
+ while (elem.length && elem[0] !== document) {
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
+ // This makes behavior of this function consistent across browsers
+ // WebKit always returns auto if the element is positioned
+ position = elem.css('position');
+ if (position == 'absolute' || position == 'relative' || position == 'fixed')
+ {
+ // IE returns 0 when zIndex is not specified
+ // other browsers return a string
+ // we ignore the case of nested elements with an explicit value of 0
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
+ value = parseInt(elem.css('zIndex'));
+ if (!isNaN(value) && value != 0) {
+ return value;
+ }
+ }
+ elem = elem.parent();
+ }
+ }
+
+ return 0;
}
});
@@ -200,176 +213,263 @@ $.extend($.expr[':'], {
}
});
+})(jQuery);
+/*!
+ * jQuery UI Widget 1.8.2
+ *
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Widget
+ */
+(function( $ ) {
-// $.widget is a factory to create jQuery plugins
-// taking some boilerplate code out of the plugin code
-function getter(namespace, plugin, method, args) {
- function getMethods(type) {
- var methods = $[namespace][plugin][type] || [];
- return (typeof methods == 'string' ? methods.split(/,?\s+/) : methods);
- }
+var _remove = $.fn.remove;
- var methods = getMethods('getter');
- if (args.length == 1 && typeof args[0] == 'string') {
- methods = methods.concat(getMethods('getterSetter'));
- }
- return ($.inArray(method, methods) != -1);
-}
+$.fn.remove = function( selector, keepData ) {
+ return this.each(function() {
+ if ( !keepData ) {
+ if ( !selector || $.filter( selector, [ this ] ).length ) {
+ $( "*", this ).add( this ).each(function() {
+ $( this ).triggerHandler( "remove" );
+ });
+ }
+ }
+ return _remove.call( $(this), selector, keepData );
+ });
+};
-$.widget = function(name, prototype) {
- var namespace = name.split(".")[0];
- name = name.split(".")[1];
+$.widget = function( name, base, prototype ) {
+ var namespace = name.split( "." )[ 0 ],
+ fullName;
+ name = name.split( "." )[ 1 ];
+ fullName = namespace + "-" + name;
- // create plugin method
- $.fn[name] = function(options) {
- var isMethodCall = (typeof options == 'string'),
- args = Array.prototype.slice.call(arguments, 1);
+ if ( !prototype ) {
+ prototype = base;
+ base = $.Widget;
+ }
- // prevent calls to internal methods
- if (isMethodCall && options.substring(0, 1) == '_') {
- return this;
- }
+ // create selector for plugin
+ $.expr[ ":" ][ fullName ] = function( elem ) {
+ return !!$.data( elem, name );
+ };
- // handle getter methods
- if (isMethodCall && getter(namespace, name, options, args)) {
- var instance = $.data(this[0], name);
- return (instance ? instance[options].apply(instance, args)
- : undefined);
+ $[ namespace ] = $[ namespace ] || {};
+ $[ namespace ][ name ] = function( options, element ) {
+ // allow instantiation without initializing for simple inheritance
+ if ( arguments.length ) {
+ this._createWidget( options, element );
}
+ };
- // handle initialization and non-getter methods
- return this.each(function() {
- var instance = $.data(this, name);
+ var basePrototype = new base();
+ // we need to make the options hash a property directly on the new instance
+ // otherwise we'll modify the options hash on the prototype that we're
+ // inheriting from
+// $.each( basePrototype, function( key, val ) {
+// if ( $.isPlainObject(val) ) {
+// basePrototype[ key ] = $.extend( {}, val );
+// }
+// });
+ basePrototype.options = $.extend( {}, basePrototype.options );
+ $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
+ namespace: namespace,
+ widgetName: name,
+ widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
+ widgetBaseClass: fullName
+ }, prototype );
+
+ $.widget.bridge( name, $[ namespace ][ name ] );
+};
- // constructor
- (!instance && !isMethodCall &&
- $.data(this, name, new $[namespace][name](this, options))._init());
+$.widget.bridge = function( name, object ) {
+ $.fn[ name ] = function( options ) {
+ var isMethodCall = typeof options === "string",
+ args = Array.prototype.slice.call( arguments, 1 ),
+ returnValue = this;
- // method call
- (instance && isMethodCall && $.isFunction(instance[options]) &&
- instance[options].apply(instance, args));
- });
- };
-
- // create widget constructor
- $[namespace] = $[namespace] || {};
- $[namespace][name] = function(element, options) {
- var self = this;
+ // allow multiple hashes to be passed on init
+ options = !isMethodCall && args.length ?
+ $.extend.apply( null, [ true, options ].concat(args) ) :
+ options;
- this.namespace = namespace;
- this.widgetName = name;
- this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
- this.widgetBaseClass = namespace + '-' + name;
-
- this.options = $.extend({},
- $.widget.defaults,
- $[namespace][name].defaults,
- $.metadata && $.metadata.get(element)[name],
- options);
-
- this.element = $(element)
- .bind('setData.' + name, function(event, key, value) {
- if (event.target == element) {
- return self._setData(key, value);
+ // prevent calls to internal methods
+ if ( isMethodCall && options.substring( 0, 1 ) === "_" ) {
+ return returnValue;
+ }
+
+ if ( isMethodCall ) {
+ this.each(function() {
+ var instance = $.data( this, name ),
+ methodValue = instance && $.isFunction( instance[options] ) ?
+ instance[ options ].apply( instance, args ) :
+ instance;
+ if ( methodValue !== instance && methodValue !== undefined ) {
+ returnValue = methodValue;
+ return false;
}
- })
- .bind('getData.' + name, function(event, key) {
- if (event.target == element) {
- return self._getData(key);
+ });
+ } else {
+ this.each(function() {
+ var instance = $.data( this, name );
+ if ( instance ) {
+ if ( options ) {
+ instance.option( options );
+ }
+ instance._init();
+ } else {
+ $.data( this, name, new object( options, this ) );
}
- })
- .bind('remove', function() {
- return self.destroy();
});
- };
+ }
- // add widget prototype
- $[namespace][name].prototype = $.extend({}, $.widget.prototype, prototype);
+ return returnValue;
+ };
+};
- // TODO: merge getter and getterSetter properties from widget prototype
- // and plugin prototype
- $[namespace][name].getterSetter = 'option';
+$.Widget = function( options, element ) {
+ // allow instantiation without initializing for simple inheritance
+ if ( arguments.length ) {
+ this._createWidget( options, element );
+ }
};
-$.widget.prototype = {
+$.Widget.prototype = {
+ widgetName: "widget",
+ widgetEventPrefix: "",
+ options: {
+ disabled: false
+ },
+ _createWidget: function( options, element ) {
+ // $.widget.bridge stores the plugin instance, but we do it anyway
+ // so that it's stored even before the _create function runs
+ this.element = $( element ).data( this.widgetName, this );
+ this.options = $.extend( true, {},
+ this.options,
+ $.metadata && $.metadata.get( element )[ this.widgetName ],
+ options );
+
+ var self = this;
+ this.element.bind( "remove." + this.widgetName, function() {
+ self.destroy();
+ });
+
+ this._create();
+ this._init();
+ },
+ _create: function() {},
_init: function() {},
+
destroy: function() {
- this.element.removeData(this.widgetName)
- .removeClass(this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled')
- .removeAttr('aria-disabled');
+ this.element
+ .unbind( "." + this.widgetName )
+ .removeData( this.widgetName );
+ this.widget()
+ .unbind( "." + this.widgetName )
+ .removeAttr( "aria-disabled" )
+ .removeClass(
+ this.widgetBaseClass + "-disabled " +
+ "ui-state-disabled" );
+ },
+
+ widget: function() {
+ return this.element;
},
- option: function(key, value) {
+ option: function( key, value ) {
var options = key,
self = this;
- if (typeof key == "string") {
- if (value === undefined) {
- return this._getData(key);
+ if ( arguments.length === 0 ) {
+ // don't return a reference to the internal hash
+ return $.extend( {}, self.options );
+ }
+
+ if (typeof key === "string" ) {
+ if ( value === undefined ) {
+ return this.options[ key ];
}
options = {};
- options[key] = value;
+ options[ key ] = value;
}
- $.each(options, function(key, value) {
- self._setData(key, value);
+ $.each( options, function( key, value ) {
+ self._setOption( key, value );
});
+
+ return self;
},
- _getData: function(key) {
- return this.options[key];
- },
- _setData: function(key, value) {
- this.options[key] = value;
+ _setOption: function( key, value ) {
+ this.options[ key ] = value;
- if (key == 'disabled') {
- this.element
- [value ? 'addClass' : 'removeClass'](
- this.widgetBaseClass + '-disabled' + ' ' +
- this.namespace + '-state-disabled')
- .attr("aria-disabled", value);
+ if ( key === "disabled" ) {
+ this.widget()
+ [ value ? "addClass" : "removeClass"](
+ this.widgetBaseClass + "-disabled" + " " +
+ "ui-state-disabled" )
+ .attr( "aria-disabled", value );
}
+
+ return this;
},
enable: function() {
- this._setData('disabled', false);
+ return this._setOption( "disabled", false );
},
disable: function() {
- this._setData('disabled', true);
+ return this._setOption( "disabled", true );
},
- _trigger: function(type, event, data) {
- var callback = this.options[type],
- eventName = (type == this.widgetEventPrefix
- ? type : this.widgetEventPrefix + type);
+ _trigger: function( type, event, data ) {
+ var callback = this.options[ type ];
- event = $.Event(event);
- event.type = eventName;
+ event = $.Event( event );
+ event.type = ( type === this.widgetEventPrefix ?
+ type :
+ this.widgetEventPrefix + type ).toLowerCase();
+ data = data || {};
// copy original event properties over to the new event
// this would happen if we could call $.event.fix instead of $.Event
// but we don't have a way to force an event to be fixed multiple times
- if (event.originalEvent) {
- for (var i = $.event.props.length, prop; i;) {
- prop = $.event.props[--i];
- event[prop] = event.originalEvent[prop];
+ if ( event.originalEvent ) {
+ for ( var i = $.event.props.length, prop; i; ) {
+ prop = $.event.props[ --i ];
+ event[ prop ] = event.originalEvent[ prop ];
}
}
- this.element.trigger(event, data);
+ this.element.trigger( event, data );
- return !($.isFunction(callback) && callback.call(this.element[0], event, data) === false
- || event.isDefaultPrevented());
+ return !( $.isFunction(callback) &&
+ callback.call( this.element[0], event, data ) === false ||
+ event.isDefaultPrevented() );
}
};
-$.widget.defaults = {
- disabled: false
-};
-
-
-/** Mouse Interaction Plugin **/
+})( jQuery );
+/*!
+ * jQuery UI Mouse 1.8.2
+ *
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Mouse
+ *
+ * Depends:
+ * jquery.ui.widget.js
+ */
+(function($) {
-$.ui.mouse = {
+$.widget("ui.mouse", {
+ options: {
+ cancel: ':input,option',
+ distance: 1,
+ delay: 0
+ },
_mouseInit: function() {
var self = this;
@@ -385,12 +485,6 @@ $.ui.mouse = {
}
});
- // Prevent text selection in IE
- if ($.browser.msie) {
- this._mouseUnselectable = this.element.attr('unselectable');
- this.element.attr('unselectable', 'on');
- }
-
this.started = false;
},
@@ -398,10 +492,6 @@ $.ui.mouse = {
// other instances of mouse
_mouseDestroy: function() {
this.element.unbind('.'+this.widgetName);
-
- // Restore text selection in IE
- ($.browser.msie
- && this.element.attr('unselectable', this._mouseUnselectable));
},
_mouseDown: function(event) {
@@ -508,32 +598,54 @@ $.ui.mouse = {
_mouseDrag: function(event) {},
_mouseStop: function(event) {},
_mouseCapture: function(event) { return true; }
-};
-
-$.ui.mouse.defaults = {
- cancel: null,
- distance: 1,
- delay: 0
-};
+});
})(jQuery);
/*
- * jQuery UI Draggable 1.7.2
+ * jQuery UI Draggable 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Draggables
*
* Depends:
- * ui.core.js
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
*/
(function($) {
-$.widget("ui.draggable", $.extend({}, $.ui.mouse, {
-
- _init: function() {
+$.widget("ui.draggable", $.ui.mouse, {
+ widgetEventPrefix: "drag",
+ options: {
+ addClasses: true,
+ appendTo: "parent",
+ axis: false,
+ connectToSortable: false,
+ containment: false,
+ cursor: "auto",
+ cursorAt: false,
+ grid: false,
+ handle: false,
+ helper: "original",
+ iframeFix: false,
+ opacity: false,
+ refreshPositions: false,
+ revert: false,
+ revertDuration: 500,
+ scope: "default",
+ scroll: true,
+ scrollSensitivity: 20,
+ scrollSpeed: 20,
+ snap: false,
+ snapMode: "both",
+ snapTolerance: 20,
+ stack: false,
+ zIndex: false
+ },
+ _create: function() {
if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
this.element[0].style.position = 'relative';
@@ -554,12 +666,15 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
+ " ui-draggable-dragging"
+ " ui-draggable-disabled");
this._mouseDestroy();
+
+ return this;
},
_mouseCapture: function(event) {
var o = this.options;
+ // among others, prevent a drag on a resizable-handle
if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
return false;
@@ -599,7 +714,7 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
this.scrollParent = this.helper.scrollParent();
//The element's absolute position on the page minus margins
- this.offset = this.element.offset();
+ this.offset = this.positionAbs = this.element.offset();
this.offset = {
top: this.offset.top - this.margins.top,
left: this.offset.left - this.margins.left
@@ -615,20 +730,22 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
});
//Generate the original position
- this.originalPosition = this._generatePosition(event);
+ this.originalPosition = this.position = this._generatePosition(event);
this.originalPageX = event.pageX;
this.originalPageY = event.pageY;
//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
- if(o.cursorAt)
- this._adjustOffsetFromHelper(o.cursorAt);
+ (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
//Set a containment if given in the options
if(o.containment)
this._setContainment();
- //Call plugins and callbacks
- this._trigger("start", event);
+ //Trigger event + callbacks
+ if(this._trigger("start", event) === false) {
+ this._clear();
+ return false;
+ }
//Recache the helper size
this._cacheHelperProportions();
@@ -651,7 +768,10 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
//Call plugins and callbacks and use the resulting position if something is returned
if (!noPropagation) {
var ui = this._uiHash();
- this._trigger('drag', event, ui);
+ if(this._trigger('drag', event, ui) === false) {
+ this._mouseUp({});
+ return false;
+ }
this.position = ui.position;
}
@@ -674,20 +794,38 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
dropped = this.dropped;
this.dropped = false;
}
+
+ //if the original element is removed, don't bother to continue
+ if(!this.element[0] || !this.element[0].parentNode)
+ return false;
if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
var self = this;
$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
- self._trigger("stop", event);
- self._clear();
+ if(self._trigger("stop", event) !== false) {
+ self._clear();
+ }
});
} else {
- this._trigger("stop", event);
- this._clear();
+ if(this._trigger("stop", event) !== false) {
+ this._clear();
+ }
}
return false;
},
+
+ cancel: function() {
+
+ if(this.helper.is(".ui-draggable-dragging")) {
+ this._mouseUp({});
+ } else {
+ this._clear();
+ }
+
+ return this;
+
+ },
_getHandle: function(event) {
@@ -719,10 +857,24 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
},
_adjustOffsetFromHelper: function(obj) {
- if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
- if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
- if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
- if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+ if (typeof obj == 'string') {
+ obj = obj.split(' ');
+ }
+ if ($.isArray(obj)) {
+ obj = {left: +obj[0], top: +obj[1] || 0};
+ }
+ if ('left' in obj) {
+ this.offset.click.left = obj.left + this.margins.left;
+ }
+ if ('right' in obj) {
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+ }
+ if ('top' in obj) {
+ this.offset.click.top = obj.top + this.margins.top;
+ }
+ if ('bottom' in obj) {
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+ }
},
_getParentOffset: function() {
@@ -818,13 +970,13 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
pos.top // The absolute mouse position
+ this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
- - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
+ - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
),
left: (
pos.left // The absolute mouse position
+ this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
- - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
+ - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
)
};
@@ -833,15 +985,6 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
_generatePosition: function(event) {
var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
-
- // This is another very weird special case that only happens for relative elements:
- // 1. If the css position is relative
- // 2. and the scroll parent is the document or similar to the offset parent
- // we have to refresh the relative offset during the scroll so there are no jumps
- if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
- this.offset.relative = this._getRelativeOffset();
- }
-
var pageX = event.pageX;
var pageY = event.pageY;
@@ -875,14 +1018,14 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
- this.offset.click.top // Click offset (relative to the element)
- this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
- this.offset.parent.top // The offsetParent's offset without borders (offset + border)
- + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
+ + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
),
left: (
pageX // The absolute mouse position
- this.offset.click.left // Click offset (relative to the element)
- this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
- this.offset.parent.left // The offsetParent's offset without borders (offset + border)
- + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
+ + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
)
};
@@ -902,7 +1045,7 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
ui = ui || this._uiHash();
$.ui.plugin.call(this, type, [event, ui]);
if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
- return $.widget.prototype._trigger.call(this, type, event, ui);
+ return $.Widget.prototype._trigger.call(this, type, event, ui);
},
plugins: {},
@@ -911,45 +1054,15 @@ $.widget("ui.draggable", $.extend({}, $.ui.mouse, {
return {
helper: this.helper,
position: this.position,
- absolutePosition: this.positionAbs, //deprecated
+ originalPosition: this.originalPosition,
offset: this.positionAbs
};
}
-}));
+});
$.extend($.ui.draggable, {
- version: "1.7.2",
- eventPrefix: "drag",
- defaults: {
- addClasses: true,
- appendTo: "parent",
- axis: false,
- cancel: ":input,option",
- connectToSortable: false,
- containment: false,
- cursor: "auto",
- cursorAt: false,
- delay: 0,
- distance: 1,
- grid: false,
- handle: false,
- helper: "original",
- iframeFix: false,
- opacity: false,
- refreshPositions: false,
- revert: false,
- revertDuration: 500,
- scope: "default",
- scroll: true,
- scrollSensitivity: 20,
- scrollSpeed: 20,
- snap: false,
- snapMode: "both",
- snapTolerance: 20,
- stack: false,
- zIndex: false
- }
+ version: "1.8.2"
});
$.ui.plugin.add("draggable", "connectToSortable", {
@@ -1019,12 +1132,12 @@ $.ui.plugin.add("draggable", "connectToSortable", {
};
$.each(inst.sortables, function(i) {
-
+
//Copy over some variables to allow calling the sortable's native _intersectsWith
this.instance.positionAbs = inst.positionAbs;
this.instance.helperProportions = inst.helperProportions;
this.instance.offset.click = inst.offset.click;
-
+
if(this.instance._intersectsWith(this.instance.containerCache)) {
//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
@@ -1067,13 +1180,13 @@ $.ui.plugin.add("draggable", "connectToSortable", {
this.instance.isOver = 0;
this.instance.cancelHelperRemoval = true;
-
+
//Prevent reverting on this forced stop
this.instance.options.revert = false;
-
+
// The out event needs to be triggered independently
this.instance._trigger('out', event, this.instance._uiHash(this.instance));
-
+
this.instance._mouseStop(event, true);
this.instance.options.helper = this.instance.options._helper;
@@ -1257,15 +1370,17 @@ $.ui.plugin.add("draggable", "stack", {
var o = $(this).data("draggable").options;
- var group = $.makeArray($(o.stack.group)).sort(function(a,b) {
- return (parseInt($(a).css("zIndex"),10) || o.stack.min) - (parseInt($(b).css("zIndex"),10) || o.stack.min);
+ var group = $.makeArray($(o.stack)).sort(function(a,b) {
+ return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
});
-
+ if (!group.length) { return; }
+
+ var min = parseInt(group[0].style.zIndex) || 0;
$(group).each(function(i) {
- this.style.zIndex = o.stack.min + i;
+ this.style.zIndex = min + i;
});
- this[0].style.zIndex = o.stack.min + group.length;
+ this[0].style.zIndex = min + group.length;
}
});
@@ -1284,28 +1399,39 @@ $.ui.plugin.add("draggable", "zIndex", {
})(jQuery);
/*
- * jQuery UI Droppable 1.7.2
+ * jQuery UI Droppable 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Droppables
*
* Depends:
- * ui.core.js
- * ui.draggable.js
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.mouse.js
+ * jquery.ui.draggable.js
*/
(function($) {
$.widget("ui.droppable", {
-
- _init: function() {
+ widgetEventPrefix: "drop",
+ options: {
+ accept: '*',
+ activeClass: false,
+ addClasses: true,
+ greedy: false,
+ hoverClass: false,
+ scope: 'default',
+ tolerance: 'intersect'
+ },
+ _create: function() {
var o = this.options, accept = o.accept;
this.isover = 0; this.isout = 1;
- this.options.accept = this.options.accept && $.isFunction(this.options.accept) ? this.options.accept : function(d) {
+ this.accept = $.isFunction(accept) ? accept : function(d) {
return d.is(accept);
};
@@ -1313,10 +1439,10 @@ $.widget("ui.droppable", {
this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
// Add the reference and positions to the manager
- $.ui.ddmanager.droppables[this.options.scope] = $.ui.ddmanager.droppables[this.options.scope] || [];
- $.ui.ddmanager.droppables[this.options.scope].push(this);
+ $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
+ $.ui.ddmanager.droppables[o.scope].push(this);
- (this.options.addClasses && this.element.addClass("ui-droppable"));
+ (o.addClasses && this.element.addClass("ui-droppable"));
},
@@ -1330,18 +1456,18 @@ $.widget("ui.droppable", {
.removeClass("ui-droppable ui-droppable-disabled")
.removeData("droppable")
.unbind(".droppable");
+
+ return this;
},
- _setData: function(key, value) {
+ _setOption: function(key, value) {
if(key == 'accept') {
- this.options.accept = value && $.isFunction(value) ? value : function(d) {
+ this.accept = $.isFunction(value) ? value : function(d) {
return d.is(value);
};
- } else {
- $.widget.prototype._setData.apply(this, arguments);
}
-
+ $.Widget.prototype._setOption.apply(this, arguments);
},
_activate: function(event) {
@@ -1361,7 +1487,7 @@ $.widget("ui.droppable", {
var draggable = $.ui.ddmanager.current;
if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
- if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
this._trigger('over', event, this.ui(draggable));
}
@@ -1373,7 +1499,7 @@ $.widget("ui.droppable", {
var draggable = $.ui.ddmanager.current;
if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
- if (this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
this._trigger('out', event, this.ui(draggable));
}
@@ -1388,13 +1514,17 @@ $.widget("ui.droppable", {
var childrenIntersection = false;
this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
var inst = $.data(this, 'droppable');
- if(inst.options.greedy && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)) {
- childrenIntersection = true; return false;
- }
+ if(
+ inst.options.greedy
+ && !inst.options.disabled
+ && inst.options.scope == draggable.options.scope
+ && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
+ && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
+ ) { childrenIntersection = true; return false; }
});
if(childrenIntersection) return false;
- if(this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
this._trigger('drop', event, this.ui(draggable));
@@ -1410,7 +1540,6 @@ $.widget("ui.droppable", {
draggable: (c.currentItem || c.element),
helper: c.helper,
position: c.position,
- absolutePosition: c.positionAbs, //deprecated
offset: c.positionAbs
};
}
@@ -1418,17 +1547,7 @@ $.widget("ui.droppable", {
});
$.extend($.ui.droppable, {
- version: "1.7.2",
- eventPrefix: 'drop',
- defaults: {
- accept: '*',
- activeClass: false,
- addClasses: true,
- greedy: false,
- hoverClass: false,
- scope: 'default',
- tolerance: 'intersect'
- }
+ version: "1.8.2"
});
$.ui.intersect = function(draggable, droppable, toleranceMode) {
@@ -1483,13 +1602,13 @@ $.ui.ddmanager = {
droppables: { 'default': [] },
prepareOffsets: function(t, event) {
- var m = $.ui.ddmanager.droppables[t.options.scope];
+ var m = $.ui.ddmanager.droppables[t.options.scope] || [];
var type = event ? event.type : null; // workaround for #2317
var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
droppablesLoop: for (var i = 0; i < m.length; i++) {
- if(m[i].options.disabled || (t && !m[i].options.accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
+ if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
@@ -1504,13 +1623,13 @@ $.ui.ddmanager = {
drop: function(draggable, event) {
var dropped = false;
- $.each($.ui.ddmanager.droppables[draggable.options.scope], function() {
+ $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
if(!this.options) return;
if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
- dropped = this._drop.call(this, event);
+ dropped = dropped || this._drop.call(this, event);
- if (!this.options.disabled && this.visible && this.options.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
this.isout = 1; this.isover = 0;
this._deactivate.call(this, event);
}
@@ -1525,8 +1644,7 @@ $.ui.ddmanager = {
if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
//Run through all droppables and check their positions based on specific tolerance options
-
- $.each($.ui.ddmanager.droppables[draggable.options.scope], function() {
+ $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
if(this.options.disabled || this.greedyChild || !this.visible) return;
var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
@@ -1566,22 +1684,42 @@ $.ui.ddmanager = {
})(jQuery);
/*
- * jQuery UI Resizable 1.7.2
+ * jQuery UI Resizable 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Resizables
*
* Depends:
- * ui.core.js
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
*/
(function($) {
-$.widget("ui.resizable", $.extend({}, $.ui.mouse, {
-
- _init: function() {
+$.widget("ui.resizable", $.ui.mouse, {
+ widgetEventPrefix: "resize",
+ options: {
+ alsoResize: false,
+ animate: false,
+ animateDuration: "slow",
+ animateEasing: "swing",
+ aspectRatio: false,
+ autoHide: false,
+ containment: false,
+ ghost: false,
+ grid: false,
+ handles: "e,s,se",
+ helper: false,
+ maxHeight: null,
+ maxWidth: null,
+ minHeight: 10,
+ minWidth: 10,
+ zIndex: 1000
+ },
+ _create: function() {
var self = this, o = this.options;
this.element.addClass("ui-resizable");
@@ -1752,7 +1890,7 @@ $.widget("ui.resizable", $.extend({}, $.ui.mouse, {
if (this.elementIsWrapper) {
_destroy(this.element);
var wrapper = this.element;
- wrapper.parent().append(
+ wrapper.after(
this.originalElement.css({
position: wrapper.css('position'),
width: wrapper.outerWidth(),
@@ -1760,23 +1898,24 @@ $.widget("ui.resizable", $.extend({}, $.ui.mouse, {
top: wrapper.css('top'),
left: wrapper.css('left')
})
- ).end().remove();
+ ).remove();
}
this.originalElement.css('resize', this.originalResizeStyle);
_destroy(this.originalElement);
+ return this;
},
_mouseCapture: function(event) {
-
var handle = false;
- for(var i in this.handles) {
- if($(this.handles[i])[0] == event.target) handle = true;
+ for (var i in this.handles) {
+ if ($(this.handles[i])[0] == event.target) {
+ handle = true;
+ }
}
- return this.options.disabled || !!handle;
-
+ return !this.options.disabled && handle;
},
_mouseStart: function(event) {
@@ -2062,32 +2201,10 @@ $.widget("ui.resizable", $.extend({}, $.ui.mouse, {
};
}
-}));
+});
$.extend($.ui.resizable, {
- version: "1.7.2",
- eventPrefix: "resize",
- defaults: {
- alsoResize: false,
- animate: false,
- animateDuration: "slow",
- animateEasing: "swing",
- aspectRatio: false,
- autoHide: false,
- cancel: ":input,option",
- containment: false,
- delay: 0,
- distance: 1,
- ghost: false,
- grid: false,
- handles: "e,s,se",
- helper: false,
- maxHeight: null,
- maxWidth: null,
- minHeight: 10,
- minWidth: 10,
- zIndex: 1000
- }
+ version: "1.8.2"
});
/*
@@ -2100,7 +2217,7 @@ $.ui.plugin.add("resizable", "alsoResize", {
var self = $(this).data("resizable"), o = self.options;
- _store = function(exp) {
+ var _store = function(exp) {
$(exp).each(function() {
$(this).data("resizable-alsoresize", {
width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
@@ -2365,23 +2482,32 @@ var isNumber = function(value) {
};
})(jQuery);
+
/*
- * jQuery UI Selectable 1.7.2
+ * jQuery UI Selectable 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Selectables
*
* Depends:
- * ui.core.js
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
*/
(function($) {
-$.widget("ui.selectable", $.extend({}, $.ui.mouse, {
-
- _init: function() {
+$.widget("ui.selectable", $.ui.mouse, {
+ options: {
+ appendTo: 'body',
+ autoRefresh: true,
+ distance: 0,
+ filter: '*',
+ tolerance: 'touch'
+ },
+ _create: function() {
var self = this;
this.element.addClass("ui-selectable");
@@ -2415,17 +2541,20 @@ $.widget("ui.selectable", $.extend({}, $.ui.mouse, {
this._mouseInit();
- this.helper = $(document.createElement('div'))
- .css({border:'1px dotted black'})
- .addClass("ui-selectable-helper");
+ this.helper = $("<div class='ui-selectable-helper'></div>");
},
destroy: function() {
+ this.selectees
+ .removeClass("ui-selectee")
+ .removeData("selectable-item");
this.element
.removeClass("ui-selectable ui-selectable-disabled")
.removeData("selectable")
.unbind(".selectable");
this._mouseDestroy();
+
+ return this;
},
_mouseStart: function(event) {
@@ -2475,14 +2604,23 @@ $.widget("ui.selectable", $.extend({}, $.ui.mouse, {
$(event.target).parents().andSelf().each(function() {
var selectee = $.data(this, "selectable-item");
if (selectee) {
- selectee.$element.removeClass("ui-unselecting").addClass('ui-selecting');
- selectee.unselecting = false;
- selectee.selecting = true;
- selectee.selected = true;
- // selectable SELECTING callback
- self._trigger("selecting", event, {
- selecting: selectee.element
- });
+ var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
+ selectee.$element
+ .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
+ .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
+ selectee.unselecting = !doSelect;
+ selectee.selecting = doSelect;
+ selectee.selected = doSelect;
+ // selectable (UN)SELECTING callback
+ if (doSelect) {
+ self._trigger("selecting", event, {
+ selecting: selectee.element
+ });
+ } else {
+ self._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
return false;
}
});
@@ -2606,38 +2744,56 @@ $.widget("ui.selectable", $.extend({}, $.ui.mouse, {
return false;
}
-}));
+});
$.extend($.ui.selectable, {
- version: "1.7.2",
- defaults: {
- appendTo: 'body',
- autoRefresh: true,
- cancel: ":input,option",
- delay: 0,
- distance: 0,
- filter: '*',
- tolerance: 'touch'
- }
+ version: "1.8.2"
});
})(jQuery);
/*
- * jQuery UI Sortable 1.7.2
+ * jQuery UI Sortable 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Sortables
*
* Depends:
- * ui.core.js
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
*/
(function($) {
-$.widget("ui.sortable", $.extend({}, $.ui.mouse, {
- _init: function() {
+$.widget("ui.sortable", $.ui.mouse, {
+ widgetEventPrefix: "sort",
+ options: {
+ appendTo: "parent",
+ axis: false,
+ connectWith: false,
+ containment: false,
+ cursor: 'auto',
+ cursorAt: false,
+ dropOnEmpty: true,
+ forcePlaceholderSize: false,
+ forceHelperSize: false,
+ grid: false,
+ handle: false,
+ helper: "original",
+ items: '> *',
+ opacity: false,
+ placeholder: false,
+ revert: false,
+ scroll: true,
+ scrollSensitivity: 20,
+ scrollSpeed: 20,
+ scope: "default",
+ tolerance: "intersect",
+ zIndex: 1000
+ },
+ _create: function() {
var o = this.options;
this.containerCache = {};
@@ -2666,6 +2822,20 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
for ( var i = this.items.length - 1; i >= 0; i-- )
this.items[i].item.removeData("sortable-item");
+
+ return this;
+ },
+
+ _setOption: function(key, value){
+ if ( key === "disabled" ) {
+ this.options[ key ] = value;
+
+ this.widget()
+ [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
+ } else {
+ // Don't call widget base _setOption for disable as it adds ui-state-disabled class
+ $.Widget.prototype._setOption.apply(this, arguments);
+ }
},
_mouseCapture: function(event, overrideHandle) {
@@ -2754,8 +2924,7 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
this.originalPageY = event.pageY;
//Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
- if(o.cursorAt)
- this._adjustOffsetFromHelper(o.cursorAt);
+ (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
//Cache the former DOM position
this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
@@ -2880,6 +3049,7 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
&& this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
&& !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
&& (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
+ //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
) {
this.direction = intersection == 1 ? "down" : "up";
@@ -2978,7 +3148,7 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
$(this.domPosition.parent).prepend(this.currentItem);
}
- return true;
+ return this;
},
@@ -3084,6 +3254,7 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
refresh: function(event) {
this._refreshItems(event);
this.refreshPositions();
+ return this;
},
_connectWith: function() {
@@ -3092,7 +3263,7 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
? [options.connectWith]
: options.connectWith;
},
-
+
_getItemsAsjQuery: function(connected) {
var self = this;
@@ -3106,13 +3277,13 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
for (var j = cur.length - 1; j >= 0; j--){
var inst = $.data(cur[j], 'sortable');
if(inst && inst != this && !inst.options.disabled) {
- queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper"), inst]);
+ queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
}
};
};
}
- queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper"), this]);
+ queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
for (var i = queries.length - 1; i >= 0; i--){
queries[i][0].each(function() {
@@ -3191,10 +3362,6 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
for (var i = this.items.length - 1; i >= 0; i--){
var item = this.items[i];
- //We ignore calculating positions of all connected containers when we're not over them
- if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
- continue;
-
var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
if (!fast) {
@@ -3219,6 +3386,7 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
};
}
+ return this;
},
_createPlaceholder: function(that) {
@@ -3264,47 +3432,71 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
},
_contactContainers: function(event) {
+
+ // get innermost container that intersects with item
+ var innermostContainer = null, innermostIndex = null;
+
+
for (var i = this.containers.length - 1; i >= 0; i--){
- if(this._intersectsWith(this.containers[i].containerCache)) {
- if(!this.containers[i].containerCache.over) {
-
- if(this.currentContainer != this.containers[i]) {
-
- //When entering a new container, we will find the item with the least distance and append our item near it
- var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[i].floating ? 'left' : 'top'];
- for (var j = this.items.length - 1; j >= 0; j--) {
- if(!$.ui.contains(this.containers[i].element[0], this.items[j].item[0])) continue;
- var cur = this.items[j][this.containers[i].floating ? 'left' : 'top'];
- if(Math.abs(cur - base) < dist) {
- dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
- }
- }
-
- if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
- continue;
-
- this.currentContainer = this.containers[i];
- itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[i].element, true);
- this._trigger("change", event, this._uiHash());
- this.containers[i]._trigger("change", event, this._uiHash(this));
+ // never consider a container that's located within the item itself
+ if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
+ continue;
- //Update the placeholder
- this.options.placeholder.update(this.currentContainer, this.placeholder);
+ if(this._intersectsWith(this.containers[i].containerCache)) {
- }
+ // if we've already found a container and it's more "inner" than this, then continue
+ if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
+ continue;
- this.containers[i]._trigger("over", event, this._uiHash(this));
- this.containers[i].containerCache.over = 1;
- }
+ innermostContainer = this.containers[i];
+ innermostIndex = i;
+
} else {
+ // container doesn't intersect. trigger "out" event if necessary
if(this.containers[i].containerCache.over) {
this.containers[i]._trigger("out", event, this._uiHash(this));
this.containers[i].containerCache.over = 0;
}
}
- };
+ }
+
+ // if no intersecting containers found, return
+ if(!innermostContainer) return;
+
+ // move the item into the container if it's not there already
+ if(this.containers.length === 1) {
+ this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
+ this.containers[innermostIndex].containerCache.over = 1;
+ } else if(this.currentContainer != this.containers[innermostIndex]) {
+
+ //When entering a new container, we will find the item with the least distance and append our item near it
+ var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top'];
+ for (var j = this.items.length - 1; j >= 0; j--) {
+ if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
+ var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top'];
+ if(Math.abs(cur - base) < dist) {
+ dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
+ }
+ }
+
+ if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
+ return;
+
+ this.currentContainer = this.containers[innermostIndex];
+ itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
+ this._trigger("change", event, this._uiHash());
+ this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
+
+ //Update the placeholder
+ this.options.placeholder.update(this.currentContainer, this.placeholder);
+
+ this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
+ this.containers[innermostIndex].containerCache.over = 1;
+ }
+
+
},
_createHelper: function(event) {
@@ -3326,10 +3518,24 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
},
_adjustOffsetFromHelper: function(obj) {
- if(obj.left != undefined) this.offset.click.left = obj.left + this.margins.left;
- if(obj.right != undefined) this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
- if(obj.top != undefined) this.offset.click.top = obj.top + this.margins.top;
- if(obj.bottom != undefined) this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+ if (typeof obj == 'string') {
+ obj = obj.split(' ');
+ }
+ if ($.isArray(obj)) {
+ obj = {left: +obj[0], top: +obj[1] || 0};
+ }
+ if ('left' in obj) {
+ this.offset.click.left = obj.left + this.margins.left;
+ }
+ if ('right' in obj) {
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+ }
+ if ('top' in obj) {
+ this.offset.click.top = obj.top + this.margins.top;
+ }
+ if ('bottom' in obj) {
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+ }
},
_getParentOffset: function() {
@@ -3556,7 +3762,7 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
//Do what was originally in plugins
if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
- if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset cursor
+ if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
this.dragging = false;
@@ -3587,7 +3793,7 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
},
_trigger: function() {
- if ($.widget.prototype._trigger.apply(this, arguments) === false) {
+ if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
this.cancel();
}
},
@@ -3598,53 +3804,24 @@ $.widget("ui.sortable", $.extend({}, $.ui.mouse, {
helper: self.helper,
placeholder: self.placeholder || $([]),
position: self.position,
- absolutePosition: self.positionAbs, //deprecated
+ originalPosition: self.originalPosition,
offset: self.positionAbs,
item: self.currentItem,
sender: inst ? inst.element : null
};
}
-}));
+});
$.extend($.ui.sortable, {
- getter: "serialize toArray",
- version: "1.7.2",
- eventPrefix: "sort",
- defaults: {
- appendTo: "parent",
- axis: false,
- cancel: ":input,option",
- connectWith: false,
- containment: false,
- cursor: 'auto',
- cursorAt: false,
- delay: 0,
- distance: 1,
- dropOnEmpty: true,
- forcePlaceholderSize: false,
- forceHelperSize: false,
- grid: false,
- handle: false,
- helper: "original",
- items: '> *',
- opacity: false,
- placeholder: false,
- revert: false,
- scroll: true,
- scrollSensitivity: 20,
- scrollSpeed: 20,
- scope: "default",
- tolerance: "intersect",
- zIndex: 1000
- }
+ version: "1.8.2"
});
})(jQuery);
/*
- * jQuery UI Effects 1.7.2
+ * jQuery UI Effects 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
@@ -3652,228 +3829,30 @@ $.extend($.ui.sortable, {
*/
;jQuery.effects || (function($) {
-$.effects = {
- version: "1.7.2",
+$.effects = {};
- // Saves a set of properties in a data storage
- save: function(element, set) {
- for(var i=0; i < set.length; i++) {
- if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
- }
- },
- // Restores a set of previously saved properties from a data storage
- restore: function(element, set) {
- for(var i=0; i < set.length; i++) {
- if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
- }
- },
- setMode: function(el, mode) {
- if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
- return mode;
- },
+/******************************************************************************/
+/****************************** COLOR ANIMATIONS ******************************/
+/******************************************************************************/
- getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
- // this should be a little more flexible in the future to handle a string & hash
- var y, x;
- switch (origin[0]) {
- case 'top': y = 0; break;
- case 'middle': y = 0.5; break;
- case 'bottom': y = 1; break;
- default: y = origin[0] / original.height;
- };
- switch (origin[1]) {
- case 'left': x = 0; break;
- case 'center': x = 0.5; break;
- case 'right': x = 1; break;
- default: x = origin[1] / original.width;
- };
- return {x: x, y: y};
- },
-
- // Wraps the element around a wrapper that copies position properties
- createWrapper: function(element) {
-
- //if the element is already wrapped, return it
- if (element.parent().is('.ui-effects-wrapper'))
- return element.parent();
-
- //Cache width,height and float properties of the element, and create a wrapper around it
- var props = { width: element.outerWidth(true), height: element.outerHeight(true), 'float': element.css('float') };
- element.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');
- var wrapper = element.parent();
-
- //Transfer the positioning of the element to the wrapper
- if (element.css('position') == 'static') {
- wrapper.css({ position: 'relative' });
- element.css({ position: 'relative'} );
- } else {
- var top = element.css('top'); if(isNaN(parseInt(top,10))) top = 'auto';
- var left = element.css('left'); if(isNaN(parseInt(left,10))) left = 'auto';
- wrapper.css({ position: element.css('position'), top: top, left: left, zIndex: element.css('z-index') }).show();
- element.css({position: 'relative', top: 0, left: 0 });
+// override the animation for color styles
+$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
+ 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'],
+function(i, attr) {
+ $.fx.step[attr] = function(fx) {
+ if (!fx.colorInit) {
+ fx.start = getColor(fx.elem, attr);
+ fx.end = getRGB(fx.end);
+ fx.colorInit = true;
}
- wrapper.css(props);
- return wrapper;
- },
-
- removeWrapper: function(element) {
- if (element.parent().is('.ui-effects-wrapper'))
- return element.parent().replaceWith(element);
- return element;
- },
-
- setTransition: function(element, list, factor, value) {
- value = value || {};
- $.each(list, function(i, x){
- unit = element.cssUnit(x);
- if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
- });
- return value;
- },
-
- //Base function to animate from one class to another in a seamless transition
- animateClass: function(value, duration, easing, callback) {
-
- var cb = (typeof easing == "function" ? easing : (callback ? callback : null));
- var ea = (typeof easing == "string" ? easing : null);
-
- return this.each(function() {
-
- var offset = {}; var that = $(this); var oldStyleAttr = that.attr("style") || '';
- if(typeof oldStyleAttr == 'object') oldStyleAttr = oldStyleAttr["cssText"]; /* Stupidly in IE, style is a object.. */
- if(value.toggle) { that.hasClass(value.toggle) ? value.remove = value.toggle : value.add = value.toggle; }
-
- //Let's get a style offset
- var oldStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
- if(value.add) that.addClass(value.add); if(value.remove) that.removeClass(value.remove);
- var newStyle = $.extend({}, (document.defaultView ? document.defaultView.getComputedStyle(this,null) : this.currentStyle));
- if(value.add) that.removeClass(value.add); if(value.remove) that.addClass(value.remove);
-
- // The main function to form the object for animation
- for(var n in newStyle) {
- if( typeof newStyle[n] != "function" && newStyle[n] /* No functions and null properties */
- && n.indexOf("Moz") == -1 && n.indexOf("length") == -1 /* No mozilla spezific render properties. */
- && newStyle[n] != oldStyle[n] /* Only values that have changed are used for the animation */
- && (n.match(/color/i) || (!n.match(/color/i) && !isNaN(parseInt(newStyle[n],10)))) /* Only things that can be parsed to integers or colors */
- && (oldStyle.position != "static" || (oldStyle.position == "static" && !n.match(/left|top|bottom|right/))) /* No need for positions when dealing with static positions */
- ) offset[n] = newStyle[n];
- }
-
- that.animate(offset, duration, ea, function() { // Animate the newly constructed offset object
- // Change style attribute back to original. For stupid IE, we need to clear the damn object.
- if(typeof $(this).attr("style") == 'object') { $(this).attr("style")["cssText"] = ""; $(this).attr("style")["cssText"] = oldStyleAttr; } else $(this).attr("style", oldStyleAttr);
- if(value.add) $(this).addClass(value.add); if(value.remove) $(this).removeClass(value.remove);
- if(cb) cb.apply(this, arguments);
- });
-
- });
- }
-};
-
-
-function _normalizeArguments(a, m) {
-
- var o = a[1] && a[1].constructor == Object ? a[1] : {}; if(m) o.mode = m;
- var speed = a[1] && a[1].constructor != Object ? a[1] : (o.duration ? o.duration : a[2]); //either comes from options.duration or the secon/third argument
- speed = $.fx.off ? 0 : typeof speed === "number" ? speed : $.fx.speeds[speed] || $.fx.speeds._default;
- var callback = o.callback || ( $.isFunction(a[1]) && a[1] ) || ( $.isFunction(a[2]) && a[2] ) || ( $.isFunction(a[3]) && a[3] );
-
- return [a[0], o, speed, callback];
-
-}
-
-//Extend the methods of jQuery
-$.fn.extend({
-
- //Save old methods
- _show: $.fn.show,
- _hide: $.fn.hide,
- __toggle: $.fn.toggle,
- _addClass: $.fn.addClass,
- _removeClass: $.fn.removeClass,
- _toggleClass: $.fn.toggleClass,
-
- // New effect methods
- effect: function(fx, options, speed, callback) {
- return $.effects[fx] ? $.effects[fx].call(this, {method: fx, options: options || {}, duration: speed, callback: callback }) : null;
- },
-
- show: function() {
- if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
- return this._show.apply(this, arguments);
- else {
- return this.effect.apply(this, _normalizeArguments(arguments, 'show'));
- }
- },
-
- hide: function() {
- if(!arguments[0] || (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])))
- return this._hide.apply(this, arguments);
- else {
- return this.effect.apply(this, _normalizeArguments(arguments, 'hide'));
- }
- },
-
- toggle: function(){
- if(!arguments[0] ||
- (arguments[0].constructor == Number || (/(slow|normal|fast)/).test(arguments[0])) ||
- ($.isFunction(arguments[0]) || typeof arguments[0] == 'boolean')) {
- return this.__toggle.apply(this, arguments);
- } else {
- return this.effect.apply(this, _normalizeArguments(arguments, 'toggle'));
- }
- },
-
- addClass: function(classNames, speed, easing, callback) {
- return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
- },
- removeClass: function(classNames,speed,easing,callback) {
- return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
- },
- toggleClass: function(classNames,speed,easing,callback) {
- return ( (typeof speed !== "boolean") && speed ) ? $.effects.animateClass.apply(this, [{ toggle: classNames },speed,easing,callback]) : this._toggleClass(classNames, speed);
- },
- morph: function(remove,add,speed,easing,callback) {
- return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
- },
- switchClass: function() {
- return this.morph.apply(this, arguments);
- },
-
- // helper functions
- cssUnit: function(key) {
- var style = this.css(key), val = [];
- $.each( ['em','px','%','pt'], function(i, unit){
- if(style.indexOf(unit) > 0)
- val = [parseFloat(style), unit];
- });
- return val;
- }
-});
-
-/*
- * jQuery Color Animations
- * Copyright 2007 John Resig
- * Released under the MIT and GPL licenses.
- */
-
-// We override the animation for all of these color styles
-$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){
- $.fx.step[attr] = function(fx) {
- if ( fx.state == 0 ) {
- fx.start = getColor( fx.elem, attr );
- fx.end = getRGB( fx.end );
- }
-
- fx.elem.style[attr] = "rgb(" + [
- Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0],10), 255), 0),
- Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1],10), 255), 0),
- Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2],10), 255), 0)
- ].join(",") + ")";
- };
+ fx.elem.style[attr] = 'rgb(' +
+ Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
+ Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
+ Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
+ };
});
// Color Conversion functions from highlightFade
@@ -3979,6 +3958,373 @@ var colors = {
transparent: [255,255,255]
};
+
+
+/******************************************************************************/
+/****************************** CLASS ANIMATIONS ******************************/
+/******************************************************************************/
+
+var classAnimationActions = ['add', 'remove', 'toggle'],
+ shorthandStyles = {
+ border: 1,
+ borderBottom: 1,
+ borderColor: 1,
+ borderLeft: 1,
+ borderRight: 1,
+ borderTop: 1,
+ borderWidth: 1,
+ margin: 1,
+ padding: 1
+ };
+
+function getElementStyles() {
+ var style = document.defaultView
+ ? document.defaultView.getComputedStyle(this, null)
+ : this.currentStyle,
+ newStyle = {},
+ key,
+ camelCase;
+
+ // webkit enumerates style porperties
+ if (style && style.length && style[0] && style[style[0]]) {
+ var len = style.length;
+ while (len--) {
+ key = style[len];
+ if (typeof style[key] == 'string') {
+ camelCase = key.replace(/\-(\w)/g, function(all, letter){
+ return letter.toUpperCase();
+ });
+ newStyle[camelCase] = style[key];
+ }
+ }
+ } else {
+ for (key in style) {
+ if (typeof style[key] === 'string') {
+ newStyle[key] = style[key];
+ }
+ }
+ }
+
+ return newStyle;
+}
+
+function filterStyles(styles) {
+ var name, value;
+ for (name in styles) {
+ value = styles[name];
+ if (
+ // ignore null and undefined values
+ value == null ||
+ // ignore functions (when does this occur?)
+ $.isFunction(value) ||
+ // shorthand styles that need to be expanded
+ name in shorthandStyles ||
+ // ignore scrollbars (break in IE)
+ (/scrollbar/).test(name) ||
+
+ // only colors or values that can be converted to numbers
+ (!(/color/i).test(name) && isNaN(parseFloat(value)))
+ ) {
+ delete styles[name];
+ }
+ }
+
+ return styles;
+}
+
+function styleDifference(oldStyle, newStyle) {
+ var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
+ name;
+
+ for (name in newStyle) {
+ if (oldStyle[name] != newStyle[name]) {
+ diff[name] = newStyle[name];
+ }
+ }
+
+ return diff;
+}
+
+$.effects.animateClass = function(value, duration, easing, callback) {
+ if ($.isFunction(easing)) {
+ callback = easing;
+ easing = null;
+ }
+
+ return this.each(function() {
+
+ var that = $(this),
+ originalStyleAttr = that.attr('style') || ' ',
+ originalStyle = filterStyles(getElementStyles.call(this)),
+ newStyle,
+ className = that.attr('className');
+
+ $.each(classAnimationActions, function(i, action) {
+ if (value[action]) {
+ that[action + 'Class'](value[action]);
+ }
+ });
+ newStyle = filterStyles(getElementStyles.call(this));
+ that.attr('className', className);
+
+ that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
+ $.each(classAnimationActions, function(i, action) {
+ if (value[action]) { that[action + 'Class'](value[action]); }
+ });
+ // work around bug in IE by clearing the cssText before setting it
+ if (typeof that.attr('style') == 'object') {
+ that.attr('style').cssText = '';
+ that.attr('style').cssText = originalStyleAttr;
+ } else {
+ that.attr('style', originalStyleAttr);
+ }
+ if (callback) { callback.apply(this, arguments); }
+ });
+ });
+};
+
+$.fn.extend({
+ _addClass: $.fn.addClass,
+ addClass: function(classNames, speed, easing, callback) {
+ return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
+ },
+
+ _removeClass: $.fn.removeClass,
+ removeClass: function(classNames,speed,easing,callback) {
+ return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
+ },
+
+ _toggleClass: $.fn.toggleClass,
+ toggleClass: function(classNames, force, speed, easing, callback) {
+ if ( typeof force == "boolean" || force === undefined ) {
+ if ( !speed ) {
+ // without speed parameter;
+ return this._toggleClass(classNames, force);
+ } else {
+ return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
+ }
+ } else {
+ // without switch parameter;
+ return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
+ }
+ },
+
+ switchClass: function(remove,add,speed,easing,callback) {
+ return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
+ }
+});
+
+
+
+/******************************************************************************/
+/*********************************** EFFECTS **********************************/
+/******************************************************************************/
+
+$.extend($.effects, {
+ version: "1.8.2",
+
+ // Saves a set of properties in a data storage
+ save: function(element, set) {
+ for(var i=0; i < set.length; i++) {
+ if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
+ }
+ },
+
+ // Restores a set of previously saved properties from a data storage
+ restore: function(element, set) {
+ for(var i=0; i < set.length; i++) {
+ if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
+ }
+ },
+
+ setMode: function(el, mode) {
+ if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
+ return mode;
+ },
+
+ getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
+ // this should be a little more flexible in the future to handle a string & hash
+ var y, x;
+ switch (origin[0]) {
+ case 'top': y = 0; break;
+ case 'middle': y = 0.5; break;
+ case 'bottom': y = 1; break;
+ default: y = origin[0] / original.height;
+ };
+ switch (origin[1]) {
+ case 'left': x = 0; break;
+ case 'center': x = 0.5; break;
+ case 'right': x = 1; break;
+ default: x = origin[1] / original.width;
+ };
+ return {x: x, y: y};
+ },
+
+ // Wraps the element around a wrapper that copies position properties
+ createWrapper: function(element) {
+
+ // if the element is already wrapped, return it
+ if (element.parent().is('.ui-effects-wrapper')) {
+ return element.parent();
+ }
+
+ // wrap the element
+ var props = {
+ width: element.outerWidth(true),
+ height: element.outerHeight(true),
+ 'float': element.css('float')
+ },
+ wrapper = $('<div></div>')
+ .addClass('ui-effects-wrapper')
+ .css({
+ fontSize: '100%',
+ background: 'transparent',
+ border: 'none',
+ margin: 0,
+ padding: 0
+ });
+
+ element.wrap(wrapper);
+ wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
+
+ // transfer positioning properties to the wrapper
+ if (element.css('position') == 'static') {
+ wrapper.css({ position: 'relative' });
+ element.css({ position: 'relative' });
+ } else {
+ $.extend(props, {
+ position: element.css('position'),
+ zIndex: element.css('z-index')
+ });
+ $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
+ props[pos] = element.css(pos);
+ if (isNaN(parseInt(props[pos], 10))) {
+ props[pos] = 'auto';
+ }
+ });
+ element.css({position: 'relative', top: 0, left: 0 });
+ }
+
+ return wrapper.css(props).show();
+ },
+
+ removeWrapper: function(element) {
+ if (element.parent().is('.ui-effects-wrapper'))
+ return element.parent().replaceWith(element);
+ return element;
+ },
+
+ setTransition: function(element, list, factor, value) {
+ value = value || {};
+ $.each(list, function(i, x){
+ unit = element.cssUnit(x);
+ if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
+ });
+ return value;
+ }
+});
+
+
+function _normalizeArguments(effect, options, speed, callback) {
+ // shift params for method overloading
+ if (typeof effect == 'object') {
+ callback = options;
+ speed = null;
+ options = effect;
+ effect = options.effect;
+ }
+ if ($.isFunction(options)) {
+ callback = options;
+ speed = null;
+ options = {};
+ }
+ if ($.isFunction(speed)) {
+ callback = speed;
+ speed = null;
+ }
+ if (typeof options == 'number' || $.fx.speeds[options]) {
+ callback = speed;
+ speed = options;
+ options = {};
+ }
+
+ options = options || {};
+
+ speed = speed || options.duration;
+ speed = $.fx.off ? 0 : typeof speed == 'number'
+ ? speed : $.fx.speeds[speed] || $.fx.speeds._default;
+
+ callback = callback || options.complete;
+
+ return [effect, options, speed, callback];
+}
+
+$.fn.extend({
+ effect: function(effect, options, speed, callback) {
+ var args = _normalizeArguments.apply(this, arguments),
+ // TODO: make effects takes actual parameters instead of a hash
+ args2 = {
+ options: args[1],
+ duration: args[2],
+ callback: args[3]
+ },
+ effectMethod = $.effects[effect];
+
+ return effectMethod && !$.fx.off ? effectMethod.call(this, args2) : this;
+ },
+
+ _show: $.fn.show,
+ show: function(speed) {
+ if (!speed || typeof speed == 'number' || $.fx.speeds[speed]) {
+ return this._show.apply(this, arguments);
+ } else {
+ var args = _normalizeArguments.apply(this, arguments);
+ args[1].mode = 'show';
+ return this.effect.apply(this, args);
+ }
+ },
+
+ _hide: $.fn.hide,
+ hide: function(speed) {
+ if (!speed || typeof speed == 'number' || $.fx.speeds[speed]) {
+ return this._hide.apply(this, arguments);
+ } else {
+ var args = _normalizeArguments.apply(this, arguments);
+ args[1].mode = 'hide';
+ return this.effect.apply(this, args);
+ }
+ },
+
+ // jQuery core overloads toggle and create _toggle
+ __toggle: $.fn.toggle,
+ toggle: function(speed) {
+ if (!speed || typeof speed == 'number' || $.fx.speeds[speed] ||
+ typeof speed == 'boolean' || $.isFunction(speed)) {
+ return this.__toggle.apply(this, arguments);
+ } else {
+ var args = _normalizeArguments.apply(this, arguments);
+ args[1].mode = 'toggle';
+ return this.effect.apply(this, args);
+ }
+ },
+
+ // helper functions
+ cssUnit: function(key) {
+ var style = this.css(key), val = [];
+ $.each( ['em','px','%','pt'], function(i, unit){
+ if(style.indexOf(unit) > 0)
+ val = [parseFloat(style), unit];
+ });
+ return val;
+ }
+});
+
+
+
+/******************************************************************************/
+/*********************************** EASING ***********************************/
+/******************************************************************************/
+
/*
* jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
*
@@ -4187,16 +4533,16 @@ $.extend($.easing,
})(jQuery);
/*
- * jQuery UI Effects Blind 1.7.2
+ * jQuery UI Effects Blind 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Blind
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
@@ -4236,16 +4582,16 @@ $.effects.blind = function(o) {
})(jQuery);
/*
- * jQuery UI Effects Bounce 1.7.2
+ * jQuery UI Effects Bounce 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Bounce
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
@@ -4314,16 +4660,16 @@ $.effects.bounce = function(o) {
})(jQuery);
/*
- * jQuery UI Effects Clip 1.7.2
+ * jQuery UI Effects Clip 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Clip
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
@@ -4368,16 +4714,16 @@ $.effects.clip = function(o) {
})(jQuery);
/*
- * jQuery UI Effects Drop 1.7.2
+ * jQuery UI Effects Drop 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Drop
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
@@ -4418,16 +4764,16 @@ $.effects.drop = function(o) {
})(jQuery);
/*
- * jQuery UI Effects Explode 1.7.2
+ * jQuery UI Effects Explode 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Explode
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
@@ -4497,16 +4843,48 @@ $.effects.explode = function(o) {
})(jQuery);
/*
- * jQuery UI Effects Fold 1.7.2
+ * jQuery UI Effects Fade 1.8.2
+ *
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Effects/Fade
+ *
+ * Depends:
+ * jquery.effects.core.js
+ */
+(function($) {
+
+$.effects.fade = function(o) {
+ return this.queue(function() {
+ var elem = $(this),
+ mode = $.effects.setMode(elem, o.options.mode || 'hide');
+
+ elem.animate({ opacity: mode }, {
+ queue: false,
+ duration: o.duration,
+ easing: o.options.easing,
+ complete: function() {
+ (o.callback && o.callback.apply(this, arguments));
+ elem.dequeue();
+ }
+ });
+ });
+};
+
+})(jQuery);
+/*
+ * jQuery UI Effects Fold 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Fold
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
@@ -4553,151 +4931,143 @@ $.effects.fold = function(o) {
})(jQuery);
/*
- * jQuery UI Effects Highlight 1.7.2
+ * jQuery UI Effects Highlight 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Highlight
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
$.effects.highlight = function(o) {
-
return this.queue(function() {
+ var elem = $(this),
+ props = ['backgroundImage', 'backgroundColor', 'opacity'],
+ mode = $.effects.setMode(elem, o.options.mode || 'show'),
+ animation = {
+ backgroundColor: elem.css('backgroundColor')
+ };
- // Create element
- var el = $(this), props = ['backgroundImage','backgroundColor','opacity'];
-
- // Set options
- var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
- var color = o.options.color || "#ffff99"; // Default highlight color
- var oldColor = el.css("backgroundColor");
-
- // Adjust
- $.effects.save(el, props); el.show(); // Save & Show
- el.css({backgroundImage: 'none', backgroundColor: color}); // Shift
-
- // Animation
- var animation = {backgroundColor: oldColor };
- if (mode == "hide") animation['opacity'] = 0;
-
- // Animate
- el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
- if(mode == "hide") el.hide();
- $.effects.restore(el, props);
- if (mode == "show" && $.browser.msie) this.style.removeAttribute('filter');
- if(o.callback) o.callback.apply(this, arguments);
- el.dequeue();
- }});
+ if (mode == 'hide') {
+ animation.opacity = 0;
+ }
+ $.effects.save(elem, props);
+ elem
+ .show()
+ .css({
+ backgroundImage: 'none',
+ backgroundColor: o.options.color || '#ffff99'
+ })
+ .animate(animation, {
+ queue: false,
+ duration: o.duration,
+ easing: o.options.easing,
+ complete: function() {
+ (mode == 'hide' && elem.hide());
+ $.effects.restore(elem, props);
+ (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
+ (o.callback && o.callback.apply(this, arguments));
+ elem.dequeue();
+ }
+ });
});
-
};
})(jQuery);
/*
- * jQuery UI Effects Pulsate 1.7.2
+ * jQuery UI Effects Pulsate 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Pulsate
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
$.effects.pulsate = function(o) {
-
return this.queue(function() {
+ var elem = $(this),
+ mode = $.effects.setMode(elem, o.options.mode || 'show');
+ times = ((o.options.times || 5) * 2) - 1;
+ duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
+ isVisible = elem.is(':visible'),
+ animateTo = 0;
- // Create element
- var el = $(this);
+ if (!isVisible) {
+ elem.css('opacity', 0).show();
+ animateTo = 1;
+ }
- // Set options
- var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
- var times = o.options.times || 5; // Default # of times
- var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
+ if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
+ times--;
+ }
- // Adjust
- if (mode == 'hide') times--;
- if (el.is(':hidden')) { // Show fadeIn
- el.css('opacity', 0);
- el.show(); // Show
- el.animate({opacity: 1}, duration, o.options.easing);
- times = times-2;
+ for (var i = 0; i < times; i++) {
+ elem.animate({ opacity: animateTo }, duration, o.options.easing);
+ animateTo = (animateTo + 1) % 2;
}
- // Animate
- for (var i = 0; i < times; i++) { // Pulsate
- el.animate({opacity: 0}, duration, o.options.easing).animate({opacity: 1}, duration, o.options.easing);
- };
- if (mode == 'hide') { // Last Pulse
- el.animate({opacity: 0}, duration, o.options.easing, function(){
- el.hide(); // Hide
- if(o.callback) o.callback.apply(this, arguments); // Callback
- });
- } else {
- el.animate({opacity: 0}, duration, o.options.easing).animate({opacity: 1}, duration, o.options.easing, function(){
- if(o.callback) o.callback.apply(this, arguments); // Callback
- });
- };
- el.queue('fx', function() { el.dequeue(); });
- el.dequeue();
- });
+ elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
+ if (animateTo == 0) {
+ elem.hide();
+ }
+ (o.callback && o.callback.apply(this, arguments));
+ });
+ elem
+ .queue('fx', function() { elem.dequeue(); })
+ .dequeue();
+ });
};
})(jQuery);
/*
- * jQuery UI Effects Scale 1.7.2
+ * jQuery UI Effects Scale 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Scale
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
$.effects.puff = function(o) {
-
return this.queue(function() {
+ var elem = $(this),
+ mode = $.effects.setMode(elem, o.options.mode || 'hide'),
+ percent = parseInt(o.options.percent, 10) || 150,
+ factor = percent / 100,
+ original = { height: elem.height(), width: elem.width() };
+
+ $.extend(o.options, {
+ fade: true,
+ mode: mode,
+ percent: mode == 'hide' ? percent : 100,
+ from: mode == 'hide'
+ ? original
+ : {
+ height: original.height * factor,
+ width: original.width * factor
+ }
+ });
- // Create element
- var el = $(this);
-
- // Set options
- var options = $.extend(true, {}, o.options);
- var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
- var percent = parseInt(o.options.percent,10) || 150; // Set default puff percent
- options.fade = true; // It's not a puff if it doesn't fade! :)
- var original = {height: el.height(), width: el.width()}; // Save original
-
- // Adjust
- var factor = percent / 100;
- el.from = (mode == 'hide') ? original : {height: original.height * factor, width: original.width * factor};
-
- // Animation
- options.from = el.from;
- options.percent = (mode == 'hide') ? percent : 100;
- options.mode = mode;
-
- // Animate
- el.effect('scale', options, o.duration, o.callback);
- el.dequeue();
+ elem.effect('scale', o.options, o.duration, o.callback);
+ elem.dequeue();
});
-
};
$.effects.scale = function(o) {
@@ -4825,6 +5195,9 @@ $.effects.size = function(o) {
// Animate
el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
+ if (el.to.opacity === 0) {
+ el.css('opacity', el.from.opacity);
+ }
if(mode == 'hide') el.hide(); // Hide
$.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
if(o.callback) o.callback.apply(this, arguments); // Callback
@@ -4837,16 +5210,16 @@ $.effects.size = function(o) {
})(jQuery);
/*
- * jQuery UI Effects Shake 1.7.2
+ * jQuery UI Effects Shake 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Shake
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
@@ -4894,16 +5267,16 @@ $.effects.shake = function(o) {
})(jQuery);
/*
- * jQuery UI Effects Slide 1.7.2
+ * jQuery UI Effects Slide 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Slide
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
@@ -4944,16 +5317,16 @@ $.effects.slide = function(o) {
})(jQuery);
/*
- * jQuery UI Effects Transfer 1.7.2
+ * jQuery UI Effects Transfer 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Effects/Transfer
*
* Depends:
- * effects.core.js
+ * jquery.effects.core.js
*/
(function($) {
@@ -4989,52 +5362,48 @@ $.effects.transfer = function(o) {
})(jQuery);
/*
- * jQuery UI Accordion 1.7.2
+ * jQuery UI Accordion 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Accordion
*
* Depends:
- * ui.core.js
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
*/
(function($) {
$.widget("ui.accordion", {
-
- _init: function() {
+ options: {
+ active: 0,
+ animated: 'slide',
+ autoHeight: true,
+ clearStyle: false,
+ collapsible: false,
+ event: "click",
+ fillSpace: false,
+ header: "> li > :first-child,> :not(li):even",
+ icons: {
+ header: "ui-icon-triangle-1-e",
+ headerSelected: "ui-icon-triangle-1-s"
+ },
+ navigation: false,
+ navigationFilter: function() {
+ return this.href.toLowerCase() == location.href.toLowerCase();
+ }
+ },
+ _create: function() {
var o = this.options, self = this;
this.running = 0;
- // if the user set the alwaysOpen option on init
- // then we need to set the collapsible option
- // if they set both on init, collapsible will take priority
- if (o.collapsible == $.ui.accordion.defaults.collapsible &&
- o.alwaysOpen != $.ui.accordion.defaults.alwaysOpen) {
- o.collapsible = !o.alwaysOpen;
- }
-
- if ( o.navigation ) {
- var current = this.element.find("a").filter(o.navigationFilter);
- if ( current.length ) {
- if ( current.filter(o.header).length ) {
- this.active = current;
- } else {
- this.active = current.parent().parent().prev();
- current.addClass("ui-accordion-content-active");
- }
- }
- }
-
this.element.addClass("ui-accordion ui-widget ui-helper-reset");
-
+
// in lack of child-selectors in CSS we need to mark top-LIs in a UL-accordion for some IE-fix
- if (this.element[0].nodeName == "UL") {
- this.element.children("li").addClass("ui-accordion-li-fix");
- }
+ this.element.children("li").addClass("ui-accordion-li-fix");
this.headers = this.element.find(o.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all")
.bind("mouseenter.accordion", function(){ $(this).addClass('ui-state-hover'); })
@@ -5046,17 +5415,25 @@ $.widget("ui.accordion", {
.next()
.addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
+ if ( o.navigation ) {
+ var current = this.element.find("a").filter(o.navigationFilter);
+ if ( current.length ) {
+ var header = current.closest(".ui-accordion-header");
+ if ( header.length ) {
+ // anchor within header
+ this.active = header;
+ } else {
+ // anchor within content
+ this.active = current.closest(".ui-accordion-content").prev();
+ }
+ }
+ }
+
this.active = this._findActive(this.active || o.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");
this.active.next().addClass('ui-accordion-content-active');
//Append icon elements
- $("<span/>").addClass("ui-icon " + o.icons.header).prependTo(this.headers);
- this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected);
-
- // IE7-/Win - Extra vertical space in lists fixed
- if ($.browser.msie) {
- this.element.find('a').css('zoom', '1');
- }
+ this._createIcons();
this.resize();
@@ -5090,10 +5467,27 @@ $.widget("ui.accordion", {
this.headers.find('a').attr('tabIndex','-1');
if (o.event) {
- this.headers.bind((o.event) + ".accordion", function(event) { return self._clickHandler.call(self, event, this); });
+ this.headers.bind((o.event) + ".accordion", function(event) {
+ self._clickHandler.call(self, event, this);
+ event.preventDefault();
+ });
}
},
+
+ _createIcons: function() {
+ var o = this.options;
+ if (o.icons) {
+ $("<span/>").addClass("ui-icon " + o.icons.header).prependTo(this.headers);
+ this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected);
+ this.element.addClass("ui-accordion-icons");
+ }
+ },
+
+ _destroyIcons: function() {
+ this.headers.children(".ui-icon").remove();
+ this.element.removeClass("ui-accordion-icons");
+ },
destroy: function() {
var o = this.options;
@@ -5107,19 +5501,31 @@ $.widget("ui.accordion", {
this.headers
.unbind(".accordion")
.removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top")
- .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");
+ .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabIndex");
- this.headers.find("a").removeAttr("tabindex");
- this.headers.children(".ui-icon").remove();
+ this.headers.find("a").removeAttr("tabIndex");
+ this._destroyIcons();
var contents = this.headers.next().css("display", "").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");
if (o.autoHeight || o.fillHeight) {
contents.css("height", "");
}
- },
- _setData: function(key, value) {
- if(key == 'alwaysOpen') { key = 'collapsible'; value = !value; }
- $.widget.prototype._setData.apply(this, arguments);
+ return this;
+ },
+
+ _setOption: function(key, value) {
+ $.Widget.prototype._setOption.apply(this, arguments);
+
+ if (key == "active") {
+ this.activate(value);
+ }
+ if (key == "icons") {
+ this._destroyIcons();
+ if (value) {
+ this._createIcons();
+ }
+ }
+
},
_keydown: function(event) {
@@ -5144,7 +5550,8 @@ $.widget("ui.accordion", {
break;
case keyCode.SPACE:
case keyCode.ENTER:
- return this._clickHandler({ target: event.target }, event.target);
+ this._clickHandler({ target: event.target }, event.target);
+ event.preventDefault();
}
if (toFocus) {
@@ -5163,34 +5570,37 @@ $.widget("ui.accordion", {
var o = this.options, maxHeight;
if (o.fillSpace) {
-
+
if($.browser.msie) { var defOverflow = this.element.parent().css('overflow'); this.element.parent().css('overflow', 'hidden'); }
maxHeight = this.element.parent().height();
if($.browser.msie) { this.element.parent().css('overflow', defOverflow); }
-
+
this.headers.each(function() {
- maxHeight -= $(this).outerHeight();
+ maxHeight -= $(this).outerHeight(true);
});
- var maxPadding = 0;
this.headers.next().each(function() {
- maxPadding = Math.max(maxPadding, $(this).innerHeight() - $(this).height());
- }).height(Math.max(0, maxHeight - maxPadding))
- .css('overflow', 'auto');
+ $(this).height(Math.max(0, maxHeight - $(this).innerHeight() + $(this).height()));
+ }).css('overflow', 'auto');
} else if ( o.autoHeight ) {
maxHeight = 0;
this.headers.next().each(function() {
- maxHeight = Math.max(maxHeight, $(this).outerHeight());
+ maxHeight = Math.max(maxHeight, $(this).height());
}).height(maxHeight);
}
+ return this;
},
activate: function(index) {
+ // TODO this gets called on init, changing the option without an explicit call for that
+ this.options.active = index;
// call clickHandler with custom event
var active = this._findActive(index)[0];
this._clickHandler({ target: active }, active);
+
+ return this;
},
_findActive: function(selector) {
@@ -5203,13 +5613,17 @@ $.widget("ui.accordion", {
: this.headers.filter(":eq(0)");
},
+ // TODO isn't event.target enough? why the seperate target argument?
_clickHandler: function(event, target) {
var o = this.options;
- if (o.disabled) return false;
+ if (o.disabled)
+ return;
// called only when using activate(false) to close all parts programmatically
- if (!event.target && o.collapsible) {
+ if (!event.target) {
+ if (!o.collapsible)
+ return;
this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
.find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
this.active.next().addClass('ui-accordion-content-active');
@@ -5223,22 +5637,25 @@ $.widget("ui.accordion", {
},
toShow = (this.active = $([]));
this._toggle(toShow, toHide, data);
- return false;
+ return;
}
// get the click target
var clicked = $(event.currentTarget || target);
var clickedIsActive = clicked[0] == this.active[0];
+
+ // TODO the option is changed, is that correct?
+ // TODO if it is correct, shouldn't that happen after determining that the click is valid?
+ o.active = o.collapsible && clickedIsActive ? false : $('.ui-accordion-header', this.element).index(clicked);
// if animations are still active, or the active header is the target, ignore click
if (this.running || (!o.collapsible && clickedIsActive)) {
- return false;
+ return;
}
// switch classes
this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
.find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
- this.active.next().addClass('ui-accordion-content-active');
if (!clickedIsActive) {
clicked.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top")
.find(".ui-icon").removeClass(o.icons.header).addClass(o.icons.headerSelected);
@@ -5252,15 +5669,15 @@ $.widget("ui.accordion", {
options: o,
newHeader: clickedIsActive && o.collapsible ? $([]) : clicked,
oldHeader: this.active,
- newContent: clickedIsActive && o.collapsible ? $([]) : toShow.find('> *'),
- oldContent: toHide.find('> *')
+ newContent: clickedIsActive && o.collapsible ? $([]) : toShow,
+ oldContent: toHide
},
down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
this.active = clickedIsActive ? $([]) : clicked;
this._toggle(toShow, toHide, data, clickedIsActive, down);
- return false;
+ return;
},
@@ -5320,6 +5737,9 @@ $.widget("ui.accordion", {
duration = o.duration,
easing = o.animated;
+ if (easing && !animations[easing] && !$.easing[easing]) {
+ easing = 'slide';
+ }
if (!animations[easing]) {
animations[easing] = function(options) {
this.slide(options, {
@@ -5344,6 +5764,7 @@ $.widget("ui.accordion", {
}
+ // TODO assert that the blur and focus triggers are really necessary, remove otherwise
toHide.prev().attr('aria-expanded','false').attr("tabIndex", "-1").blur();
toShow.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();
@@ -5362,6 +5783,9 @@ $.widget("ui.accordion", {
overflow: ""
});
}
+
+ // other classes are removed before the animation; this one needs to stay until completed
+ this.toHide.removeClass("ui-accordion-content-active");
this._trigger('change', null, this.data);
}
@@ -5370,26 +5794,7 @@ $.widget("ui.accordion", {
$.extend($.ui.accordion, {
- version: "1.7.2",
- defaults: {
- active: null,
- alwaysOpen: true, //deprecated, use collapsible
- animated: 'slide',
- autoHeight: true,
- clearStyle: false,
- collapsible: false,
- event: "click",
- fillSpace: false,
- header: "> li > :first-child,> :not(li):even",
- icons: {
- header: "ui-icon-triangle-1-e",
- headerSelected: "ui-icon-triangle-1-s"
- },
- navigation: false,
- navigationFilter: function() {
- return this.href.toLowerCase() == location.href.toLowerCase();
- }
- },
+ version: "1.8.2",
animations: {
slide: function(options, additions) {
options = $.extend({
@@ -5405,7 +5810,7 @@ $.extend($.ui.accordion, {
return;
}
var overflow = options.toShow.css('overflow'),
- percentDone,
+ percentDone = 0,
showProps = {},
hideProps = {},
fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
@@ -5414,10 +5819,10 @@ $.extend($.ui.accordion, {
var s = options.toShow;
originalWidth = s[0].style.width;
s.width( parseInt(s.parent().width(),10) - parseInt(s.css("paddingLeft"),10) - parseInt(s.css("paddingRight"),10) - (parseInt(s.css("borderLeftWidth"),10) || 0) - (parseInt(s.css("borderRightWidth"),10) || 0) );
-
+
$.each(fxAttrs, function(i, prop) {
hideProps[prop] = 'hide';
-
+
var parts = ('' + $.css(options.toShow[0], prop)).match(/^([\d+-.]+)(.*)$/);
showProps[prop] = {
value: parts[1],
@@ -5431,9 +5836,10 @@ $.extend($.ui.accordion, {
// IE gets very inconsistent results when animating elements
// with small values, which is common for padding
if (settings.prop == 'height') {
- percentDone = (settings.now - settings.start) / (settings.end - settings.start);
+ percentDone = ( settings.end - settings.start === 0 ) ? 0 :
+ (settings.now - settings.start) / (settings.end - settings.start);
}
-
+
options.toShow[0].style[settings.prop] =
(percentDone * showProps[settings.prop].value) + showProps[settings.prop].unit;
},
@@ -5454,35 +5860,906 @@ $.extend($.ui.accordion, {
easing: options.down ? "easeOutBounce" : "swing",
duration: options.down ? 1000 : 200
});
- },
- easeslide: function(options) {
- this.slide(options, {
- easing: "easeinout",
- duration: 700
- });
}
}
});
})(jQuery);
/*
- * jQuery UI Datepicker 1.7.2
+ * jQuery UI Autocomplete 1.8.2
+ *
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Autocomplete
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.position.js
+ */
+(function( $ ) {
+
+$.widget( "ui.autocomplete", {
+ options: {
+ minLength: 1,
+ delay: 300
+ },
+ _create: function() {
+ var self = this,
+ doc = this.element[ 0 ].ownerDocument;
+ this.element
+ .addClass( "ui-autocomplete-input" )
+ .attr( "autocomplete", "off" )
+ // TODO verify these actually work as intended
+ .attr({
+ role: "textbox",
+ "aria-autocomplete": "list",
+ "aria-haspopup": "true"
+ })
+ .bind( "keydown.autocomplete", function( event ) {
+ var keyCode = $.ui.keyCode;
+ switch( event.keyCode ) {
+ case keyCode.PAGE_UP:
+ self._move( "previousPage", event );
+ break;
+ case keyCode.PAGE_DOWN:
+ self._move( "nextPage", event );
+ break;
+ case keyCode.UP:
+ self._move( "previous", event );
+ // prevent moving cursor to beginning of text field in some browsers
+ event.preventDefault();
+ break;
+ case keyCode.DOWN:
+ self._move( "next", event );
+ // prevent moving cursor to end of text field in some browsers
+ event.preventDefault();
+ break;
+ case keyCode.ENTER:
+ case keyCode.NUMPAD_ENTER:
+ // when menu is open or has focus
+ if ( self.menu.active ) {
+ event.preventDefault();
+ }
+ //passthrough - ENTER and TAB both select the current element
+ case keyCode.TAB:
+ if ( !self.menu.active ) {
+ return;
+ }
+ self.menu.select( event );
+ break;
+ case keyCode.ESCAPE:
+ self.element.val( self.term );
+ self.close( event );
+ break;
+ case keyCode.LEFT:
+ case keyCode.RIGHT:
+ case keyCode.SHIFT:
+ case keyCode.CONTROL:
+ case keyCode.ALT:
+ case keyCode.COMMAND:
+ case keyCode.COMMAND_RIGHT:
+ case keyCode.INSERT:
+ case keyCode.CAPS_LOCK:
+ case keyCode.END:
+ case keyCode.HOME:
+ // ignore metakeys (shift, ctrl, alt)
+ break;
+ default:
+ // keypress is triggered before the input value is changed
+ clearTimeout( self.searching );
+ self.searching = setTimeout(function() {
+ self.search( null, event );
+ }, self.options.delay );
+ break;
+ }
+ })
+ .bind( "focus.autocomplete", function() {
+ self.selectedItem = null;
+ self.previous = self.element.val();
+ })
+ .bind( "blur.autocomplete", function( event ) {
+ clearTimeout( self.searching );
+ // clicks on the menu (or a button to trigger a search) will cause a blur event
+ self.closing = setTimeout(function() {
+ self.close( event );
+ self._change( event );
+ }, 150 );
+ });
+ this._initSource();
+ this.response = function() {
+ return self._response.apply( self, arguments );
+ };
+ this.menu = $( "<ul></ul>" )
+ .addClass( "ui-autocomplete" )
+ .appendTo( "body", doc )
+ // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
+ .mousedown(function() {
+ // use another timeout to make sure the blur-event-handler on the input was already triggered
+ setTimeout(function() {
+ clearTimeout( self.closing );
+ }, 13);
+ })
+ .menu({
+ focus: function( event, ui ) {
+ var item = ui.item.data( "item.autocomplete" );
+ if ( false !== self._trigger( "focus", null, { item: item } ) ) {
+ // use value to match what will end up in the input, if it was a key event
+ if ( /^key/.test(event.originalEvent.type) ) {
+ self.element.val( item.value );
+ }
+ }
+ },
+ selected: function( event, ui ) {
+ var item = ui.item.data( "item.autocomplete" );
+ if ( false !== self._trigger( "select", event, { item: item } ) ) {
+ self.element.val( item.value );
+ }
+ self.close( event );
+ // only trigger when focus was lost (click on menu)
+ var previous = self.previous;
+ if ( self.element[0] !== doc.activeElement ) {
+ self.element.focus();
+ self.previous = previous;
+ }
+ self.selectedItem = item;
+ },
+ blur: function( event, ui ) {
+ if ( self.menu.element.is(":visible") ) {
+ self.element.val( self.term );
+ }
+ }
+ })
+ .zIndex( this.element.zIndex() + 1 )
+ // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
+ .css({ top: 0, left: 0 })
+ .hide()
+ .data( "menu" );
+ if ( $.fn.bgiframe ) {
+ this.menu.element.bgiframe();
+ }
+ },
+
+ destroy: function() {
+ this.element
+ .removeClass( "ui-autocomplete-input" )
+ .removeAttr( "autocomplete" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-autocomplete" )
+ .removeAttr( "aria-haspopup" );
+ this.menu.element.remove();
+ $.Widget.prototype.destroy.call( this );
+ },
+
+ _setOption: function( key ) {
+ $.Widget.prototype._setOption.apply( this, arguments );
+ if ( key === "source" ) {
+ this._initSource();
+ }
+ },
+
+ _initSource: function() {
+ var array,
+ url;
+ if ( $.isArray(this.options.source) ) {
+ array = this.options.source;
+ this.source = function( request, response ) {
+ response( $.ui.autocomplete.filter(array, request.term) );
+ };
+ } else if ( typeof this.options.source === "string" ) {
+ url = this.options.source;
+ this.source = function( request, response ) {
+ $.getJSON( url, request, response );
+ };
+ } else {
+ this.source = this.options.source;
+ }
+ },
+
+ search: function( value, event ) {
+ value = value != null ? value : this.element.val();
+ if ( value.length < this.options.minLength ) {
+ return this.close( event );
+ }
+
+ clearTimeout( this.closing );
+ if ( this._trigger("search") === false ) {
+ return;
+ }
+
+ return this._search( value );
+ },
+
+ _search: function( value ) {
+ this.term = this.element
+ .addClass( "ui-autocomplete-loading" )
+ // always save the actual value, not the one passed as an argument
+ .val();
+
+ this.source( { term: value }, this.response );
+ },
+
+ _response: function( content ) {
+ if ( content.length ) {
+ content = this._normalize( content );
+ this._suggest( content );
+ this._trigger( "open" );
+ } else {
+ this.close();
+ }
+ this.element.removeClass( "ui-autocomplete-loading" );
+ },
+
+ close: function( event ) {
+ clearTimeout( this.closing );
+ if ( this.menu.element.is(":visible") ) {
+ this._trigger( "close", event );
+ this.menu.element.hide();
+ this.menu.deactivate();
+ }
+ },
+
+ _change: function( event ) {
+ if ( this.previous !== this.element.val() ) {
+ this._trigger( "change", event, { item: this.selectedItem } );
+ }
+ },
+
+ _normalize: function( items ) {
+ // assume all items have the right format when the first item is complete
+ if ( items.length && items[0].label && items[0].value ) {
+ return items;
+ }
+ return $.map( items, function(item) {
+ if ( typeof item === "string" ) {
+ return {
+ label: item,
+ value: item
+ };
+ }
+ return $.extend({
+ label: item.label || item.value,
+ value: item.value || item.label
+ }, item );
+ });
+ },
+
+ _suggest: function( items ) {
+ var ul = this.menu.element
+ .empty()
+ .zIndex( this.element.zIndex() + 1 ),
+ menuWidth,
+ textWidth;
+ this._renderMenu( ul, items );
+ // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
+ this.menu.deactivate();
+ this.menu.refresh();
+ this.menu.element.show().position({
+ my: "left top",
+ at: "left bottom",
+ of: this.element,
+ collision: "none"
+ });
+
+ menuWidth = ul.width( "" ).width();
+ textWidth = this.element.width();
+ ul.width( Math.max( menuWidth, textWidth ) );
+ },
+
+ _renderMenu: function( ul, items ) {
+ var self = this;
+ $.each( items, function( index, item ) {
+ self._renderItem( ul, item );
+ });
+ },
+
+ _renderItem: function( ul, item) {
+ return $( "<li></li>" )
+ .data( "item.autocomplete", item )
+ .append( "<a>" + item.label + "</a>" )
+ .appendTo( ul );
+ },
+
+ _move: function( direction, event ) {
+ if ( !this.menu.element.is(":visible") ) {
+ this.search( null, event );
+ return;
+ }
+ if ( this.menu.first() && /^previous/.test(direction) ||
+ this.menu.last() && /^next/.test(direction) ) {
+ this.element.val( this.term );
+ this.menu.deactivate();
+ return;
+ }
+ this.menu[ direction ]( event );
+ },
+
+ widget: function() {
+ return this.menu.element;
+ }
+});
+
+$.extend( $.ui.autocomplete, {
+ escapeRegex: function( value ) {
+ return value.replace( /([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1" );
+ },
+ filter: function(array, term) {
+ var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
+ return $.grep( array, function(value) {
+ return matcher.test( value.label || value.value || value );
+ });
+ }
+});
+
+}( jQuery ));
+
+/*
+ * jQuery UI Menu (not officially released)
+ *
+ * This widget isn't yet finished and the API is subject to change. We plan to finish
+ * it for the next release. You're welcome to give it a try anyway and give us feedback,
+ * as long as you're okay with migrating your code later on. We can help with that, too.
+ *
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Menu
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function($) {
+
+$.widget("ui.menu", {
+ _create: function() {
+ var self = this;
+ this.element
+ .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
+ .attr({
+ role: "listbox",
+ "aria-activedescendant": "ui-active-menuitem"
+ })
+ .click(function( event ) {
+ if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
+ return;
+ }
+ // temporary
+ event.preventDefault();
+ self.select( event );
+ });
+ this.refresh();
+ },
+
+ refresh: function() {
+ var self = this;
+
+ // don't refresh list items that are already adapted
+ var items = this.element.children("li:not(.ui-menu-item):has(a)")
+ .addClass("ui-menu-item")
+ .attr("role", "menuitem");
+
+ items.children("a")
+ .addClass("ui-corner-all")
+ .attr("tabindex", -1)
+ // mouseenter doesn't work with event delegation
+ .mouseenter(function( event ) {
+ self.activate( event, $(this).parent() );
+ })
+ .mouseleave(function() {
+ self.deactivate();
+ });
+ },
+
+ activate: function( event, item ) {
+ this.deactivate();
+ if (this.hasScroll()) {
+ var offset = item.offset().top - this.element.offset().top,
+ scroll = this.element.attr("scrollTop"),
+ elementHeight = this.element.height();
+ if (offset < 0) {
+ this.element.attr("scrollTop", scroll + offset);
+ } else if (offset > elementHeight) {
+ this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
+ }
+ }
+ this.active = item.eq(0)
+ .children("a")
+ .addClass("ui-state-hover")
+ .attr("id", "ui-active-menuitem")
+ .end();
+ this._trigger("focus", event, { item: item });
+ },
+
+ deactivate: function() {
+ if (!this.active) { return; }
+
+ this.active.children("a")
+ .removeClass("ui-state-hover")
+ .removeAttr("id");
+ this._trigger("blur");
+ this.active = null;
+ },
+
+ next: function(event) {
+ this.move("next", ".ui-menu-item:first", event);
+ },
+
+ previous: function(event) {
+ this.move("prev", ".ui-menu-item:last", event);
+ },
+
+ first: function() {
+ return this.active && !this.active.prev().length;
+ },
+
+ last: function() {
+ return this.active && !this.active.next().length;
+ },
+
+ move: function(direction, edge, event) {
+ if (!this.active) {
+ this.activate(event, this.element.children(edge));
+ return;
+ }
+ var next = this.active[direction + "All"](".ui-menu-item").eq(0);
+ if (next.length) {
+ this.activate(event, next);
+ } else {
+ this.activate(event, this.element.children(edge));
+ }
+ },
+
+ // TODO merge with previousPage
+ nextPage: function(event) {
+ if (this.hasScroll()) {
+ // TODO merge with no-scroll-else
+ if (!this.active || this.last()) {
+ this.activate(event, this.element.children(":first"));
+ return;
+ }
+ var base = this.active.offset().top,
+ height = this.element.height(),
+ result = this.element.children("li").filter(function() {
+ var close = $(this).offset().top - base - height + $(this).height();
+ // TODO improve approximation
+ return close < 10 && close > -10;
+ });
+
+ // TODO try to catch this earlier when scrollTop indicates the last page anyway
+ if (!result.length) {
+ result = this.element.children(":last");
+ }
+ this.activate(event, result);
+ } else {
+ this.activate(event, this.element.children(!this.active || this.last() ? ":first" : ":last"));
+ }
+ },
+
+ // TODO merge with nextPage
+ previousPage: function(event) {
+ if (this.hasScroll()) {
+ // TODO merge with no-scroll-else
+ if (!this.active || this.first()) {
+ this.activate(event, this.element.children(":last"));
+ return;
+ }
+
+ var base = this.active.offset().top,
+ height = this.element.height();
+ result = this.element.children("li").filter(function() {
+ var close = $(this).offset().top - base + height - $(this).height();
+ // TODO improve approximation
+ return close < 10 && close > -10;
+ });
+
+ // TODO try to catch this earlier when scrollTop indicates the last page anyway
+ if (!result.length) {
+ result = this.element.children(":first");
+ }
+ this.activate(event, result);
+ } else {
+ this.activate(event, this.element.children(!this.active || this.first() ? ":last" : ":first"));
+ }
+ },
+
+ hasScroll: function() {
+ return this.element.height() < this.element.attr("scrollHeight");
+ },
+
+ select: function( event ) {
+ this._trigger("selected", event, { item: this.active });
+ }
+});
+
+}(jQuery));
+/*
+ * jQuery UI Button 1.8.2
+ *
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Button
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function( $ ) {
+
+var lastActive,
+ baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
+ stateClasses = "ui-state-hover ui-state-active ",
+ typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon ui-button-text-only",
+ formResetHandler = function( event ) {
+ $( ":ui-button", event.target.form ).each(function() {
+ var inst = $( this ).data( "button" );
+ setTimeout(function() {
+ inst.refresh();
+ }, 1 );
+ });
+ },
+ radioGroup = function( radio ) {
+ var name = radio.name,
+ form = radio.form,
+ radios = $( [] );
+ if ( name ) {
+ if ( form ) {
+ radios = $( form ).find( "[name='" + name + "']" );
+ } else {
+ radios = $( "[name='" + name + "']", radio.ownerDocument )
+ .filter(function() {
+ return !this.form;
+ });
+ }
+ }
+ return radios;
+ };
+
+$.widget( "ui.button", {
+ options: {
+ text: true,
+ label: null,
+ icons: {
+ primary: null,
+ secondary: null
+ }
+ },
+ _create: function() {
+ this.element.closest( "form" )
+ .unbind( "reset.button" )
+ .bind( "reset.button", formResetHandler );
+
+ this._determineButtonType();
+ this.hasTitle = !!this.buttonElement.attr( "title" );
+
+ var self = this,
+ options = this.options,
+ toggleButton = this.type === "checkbox" || this.type === "radio",
+ hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
+ focusClass = "ui-state-focus";
+
+ if ( options.label === null ) {
+ options.label = this.buttonElement.html();
+ }
+
+ if ( this.element.is( ":disabled" ) ) {
+ options.disabled = true;
+ }
+
+ this.buttonElement
+ .addClass( baseClasses )
+ .attr( "role", "button" )
+ .bind( "mouseenter.button", function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).addClass( "ui-state-hover" );
+ if ( this === lastActive ) {
+ $( this ).addClass( "ui-state-active" );
+ }
+ })
+ .bind( "mouseleave.button", function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).removeClass( hoverClass );
+ })
+ .bind( "focus.button", function() {
+ // no need to check disabled, focus won't be triggered anyway
+ $( this ).addClass( focusClass );
+ })
+ .bind( "blur.button", function() {
+ $( this ).removeClass( focusClass );
+ });
+
+ if ( toggleButton ) {
+ this.element.bind( "change.button", function() {
+ self.refresh();
+ });
+ }
+
+ if ( this.type === "checkbox" ) {
+ this.buttonElement.bind( "click.button", function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).toggleClass( "ui-state-active" );
+ self.buttonElement.attr( "aria-pressed", self.element[0].checked );
+ });
+ } else if ( this.type === "radio" ) {
+ this.buttonElement.bind( "click.button", function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).addClass( "ui-state-active" );
+ self.buttonElement.attr( "aria-pressed", true );
+
+ var radio = self.element[ 0 ];
+ radioGroup( radio )
+ .not( radio )
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", false );
+ });
+ } else {
+ this.buttonElement
+ .bind( "mousedown.button", function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).addClass( "ui-state-active" );
+ lastActive = this;
+ $( document ).one( "mouseup", function() {
+ lastActive = null;
+ });
+ })
+ .bind( "mouseup.button", function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).removeClass( "ui-state-active" );
+ })
+ .bind( "keydown.button", function(event) {
+ if ( options.disabled ) {
+ return false;
+ }
+ if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
+ $( this ).addClass( "ui-state-active" );
+ }
+ })
+ .bind( "keyup.button", function() {
+ $( this ).removeClass( "ui-state-active" );
+ });
+
+ if ( this.buttonElement.is("a") ) {
+ this.buttonElement.keyup(function(event) {
+ if ( event.keyCode === $.ui.keyCode.SPACE ) {
+ // TODO pass through original event correctly (just as 2nd argument doesn't work)
+ $( this ).click();
+ }
+ });
+ }
+ }
+
+ // TODO: pull out $.Widget's handling for the disabled option into
+ // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
+ // be overridden by individual plugins
+ this._setOption( "disabled", options.disabled );
+ },
+
+ _determineButtonType: function() {
+
+ if ( this.element.is(":checkbox") ) {
+ this.type = "checkbox";
+ } else {
+ if ( this.element.is(":radio") ) {
+ this.type = "radio";
+ } else {
+ if ( this.element.is("input") ) {
+ this.type = "input";
+ } else {
+ this.type = "button";
+ }
+ }
+ }
+
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ // we don't search against the document in case the element
+ // is disconnected from the DOM
+ this.buttonElement = this.element.parents().last()
+ .find( "[for=" + this.element.attr("id") + "]" );
+ this.element.addClass( "ui-helper-hidden-accessible" );
+
+ var checked = this.element.is( ":checked" );
+ if ( checked ) {
+ this.buttonElement.addClass( "ui-state-active" );
+ }
+ this.buttonElement.attr( "aria-pressed", checked );
+ } else {
+ this.buttonElement = this.element;
+ }
+ },
+
+ widget: function() {
+ return this.buttonElement;
+ },
+
+ destroy: function() {
+ this.element
+ .removeClass( "ui-helper-hidden-accessible" );
+ this.buttonElement
+ .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
+ .removeAttr( "role" )
+ .removeAttr( "aria-pressed" )
+ .html( this.buttonElement.find(".ui-button-text").html() );
+
+ if ( !this.hasTitle ) {
+ this.buttonElement.removeAttr( "title" );
+ }
+
+ $.Widget.prototype.destroy.call( this );
+ },
+
+ _setOption: function( key, value ) {
+ $.Widget.prototype._setOption.apply( this, arguments );
+ if ( key === "disabled" ) {
+ if ( value ) {
+ this.element.attr( "disabled", true );
+ } else {
+ this.element.removeAttr( "disabled" );
+ }
+ }
+ this._resetButton();
+ },
+
+ refresh: function() {
+ var isDisabled = this.element.is( ":disabled" );
+ if ( isDisabled !== this.options.disabled ) {
+ this._setOption( "disabled", isDisabled );
+ }
+ if ( this.type === "radio" ) {
+ radioGroup( this.element[0] ).each(function() {
+ if ( $( this ).is( ":checked" ) ) {
+ $( this ).button( "widget" )
+ .addClass( "ui-state-active" )
+ .attr( "aria-pressed", true );
+ } else {
+ $( this ).button( "widget" )
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", false );
+ }
+ });
+ } else if ( this.type === "checkbox" ) {
+ if ( this.element.is( ":checked" ) ) {
+ this.buttonElement
+ .addClass( "ui-state-active" )
+ .attr( "aria-pressed", true );
+ } else {
+ this.buttonElement
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", false );
+ }
+ }
+ },
+
+ _resetButton: function() {
+ if ( this.type === "input" ) {
+ if ( this.options.label ) {
+ this.element.val( this.options.label );
+ }
+ return;
+ }
+ var buttonElement = this.buttonElement.removeClass( typeClasses ),
+ buttonText = $( "<span></span>" )
+ .addClass( "ui-button-text" )
+ .html( this.options.label )
+ .appendTo( buttonElement.empty() )
+ .text(),
+ icons = this.options.icons,
+ multipleIcons = icons.primary && icons.secondary;
+ if ( icons.primary || icons.secondary ) {
+ buttonElement.addClass( "ui-button-text-icon" +
+ ( multipleIcons ? "s" : "" ) );
+ if ( icons.primary ) {
+ buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
+ }
+ if ( icons.secondary ) {
+ buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
+ }
+ if ( !this.options.text ) {
+ buttonElement
+ .addClass( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" )
+ .removeClass( "ui-button-text-icons ui-button-text-icon" );
+ if ( !this.hasTitle ) {
+ buttonElement.attr( "title", buttonText );
+ }
+ }
+ } else {
+ buttonElement.addClass( "ui-button-text-only" );
+ }
+ }
+});
+
+$.widget( "ui.buttonset", {
+ _create: function() {
+ this.element.addClass( "ui-buttonset" );
+ this._init();
+ },
+
+ _init: function() {
+ this.refresh();
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "disabled" ) {
+ this.buttons.button( "option", key, value );
+ }
+
+ $.Widget.prototype._setOption.apply( this, arguments );
+ },
+
+ refresh: function() {
+ this.buttons = this.element.find( ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" )
+ .filter( ":ui-button" )
+ .button( "refresh" )
+ .end()
+ .not( ":ui-button" )
+ .button()
+ .end()
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
+ .filter( ":first" )
+ .addClass( "ui-corner-left" )
+ .end()
+ .filter( ":last" )
+ .addClass( "ui-corner-right" )
+ .end()
+ .end();
+ },
+
+ destroy: function() {
+ this.element.removeClass( "ui-buttonset" );
+ this.buttons
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-corner-left ui-corner-right" )
+ .end()
+ .button( "destroy" );
+
+ $.Widget.prototype.destroy.call( this );
+ }
+});
+
+}( jQuery ) );
+/*
+ * jQuery UI Datepicker 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Datepicker
*
* Depends:
- * ui.core.js
+ * jquery.ui.core.js
*/
(function($) { // hide the namespace
-$.extend($.ui, { datepicker: { version: "1.7.2" } });
+$.extend($.ui, { datepicker: { version: "1.8.2" } });
var PROP_NAME = 'datepicker';
+var dpuuid = new Date().getTime();
/* Date picker manager.
Use the singleton instance of this class, $.datepicker, to interact with the date picker.
@@ -5517,14 +6794,17 @@ function Datepicker() {
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
+ weekHeader: 'Wk', // Column header for week of the year
dateFormat: 'mm/dd/yy', // See format options on parseDate
firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
- isRTL: false // True if right-to-left language, false if left-to-right
+ isRTL: false, // True if right-to-left language, false if left-to-right
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
+ yearSuffix: '' // Additional text to append to the year in the month headers
};
this._defaults = { // Global defaults for all the date picker instances
showOn: 'focus', // 'focus' for popup on focus,
// 'button' for trigger button, or 'both' for either
- showAnim: 'show', // Name of jQuery animation for popup
+ showAnim: 'fadeIn', // Name of jQuery animation for popup
showOptions: {}, // Options for enhanced animations
defaultDate: null, // Used when field is blank: actual date,
// +/-number for offset from today, null for today
@@ -5538,10 +6818,12 @@ function Datepicker() {
gotoCurrent: false, // True if today link goes back to current selection instead
changeMonth: false, // True if month can be selected directly, false if only prev/next
changeYear: false, // True if year can be selected directly, false if only prev/next
- showMonthAfterYear: false, // True if the year select precedes month, false for month then year
- yearRange: '-10:+10', // Range of years to display in drop-down,
- // either relative to current year (-nn:+nn) or absolute (nnnn:nnnn)
+ yearRange: 'c-10:c+10', // Range of years to display in drop-down,
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
showOtherMonths: false, // True to show dates in other months, false to leave blank
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
+ showWeek: false, // True to show week of the year, false to not show it
calculateWeek: this.iso8601Week, // How to calculate the week of the year,
// takes a Date and returns the number of the week for it
shortYearCutoff: '+10', // Short year values < this are in the current century,
@@ -5549,7 +6831,7 @@ function Datepicker() {
// string value starting with '+' for current year + value
minDate: null, // The earliest selectable date, or null for no limit
maxDate: null, // The latest selectable date, or null for no limit
- duration: 'normal', // Duration of display/closure
+ duration: 'fast', // Duration of display/closure
beforeShowDay: null, // Function that takes a date and returns an array with
// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
// [2] = cell title (optional), e.g. $.datepicker.noWeekends
@@ -5565,7 +6847,8 @@ function Datepicker() {
altField: '', // Selector for an alternate field to store selected dates into
altFormat: '', // The date format to use for the alternate field
constrainInput: true, // The input is constrained by the current date format
- showButtonPanel: false // True to show button panel, false to not show it
+ showButtonPanel: false, // True to show button panel, false to not show it
+ autoSize: false // True to size the input for the date format, false to leave as is
};
$.extend(this._defaults, this.regional['']);
this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
@@ -5580,6 +6863,11 @@ $.extend(Datepicker.prototype, {
if (this.debug)
console.log.apply('', arguments);
},
+
+ // TODO rename to "widget" when switching to widget factory
+ _widgetDatepicker: function() {
+ return this.dpDiv;
+ },
/* Override the default settings for all instances of the date picker.
@param settings object - the new settings to use as defaults (anonymous object)
@@ -5608,8 +6896,10 @@ $.extend(Datepicker.prototype, {
}
var nodeName = target.nodeName.toLowerCase();
var inline = (nodeName == 'div' || nodeName == 'span');
- if (!target.id)
- target.id = 'dp' + (++this.uuid);
+ if (!target.id) {
+ this.uuid += 1;
+ target.id = 'dp' + this.uuid;
+ }
var inst = this._newInst($(target), inline);
inst.settings = $.extend({}, settings || {}, inlineSettings || {});
if (nodeName == 'input') {
@@ -5621,7 +6911,7 @@ $.extend(Datepicker.prototype, {
/* Create a new instance object. */
_newInst: function(target, inline) {
- var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars
+ var id = target[0].id.replace(/([^A-Za-z0-9_])/g, '\\\\$1'); // escape jQuery meta chars
return {id: id, input: target, // associated target
selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
drawMonth: 0, drawYear: 0, // month being drawn
@@ -5637,12 +6927,31 @@ $.extend(Datepicker.prototype, {
inst.trigger = $([]);
if (input.hasClass(this.markerClassName))
return;
+ this._attachments(input, inst);
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).
+ keypress(this._doKeyPress).keyup(this._doKeyUp).
+ bind("setData.datepicker", function(event, key, value) {
+ inst.settings[key] = value;
+ }).bind("getData.datepicker", function(event, key) {
+ return this._get(inst, key);
+ });
+ this._autoSize(inst);
+ $.data(target, PROP_NAME, inst);
+ },
+
+ /* Make attachments based on settings. */
+ _attachments: function(input, inst) {
var appendText = this._get(inst, 'appendText');
var isRTL = this._get(inst, 'isRTL');
+ if (inst.append)
+ inst.append.remove();
if (appendText) {
inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
input[isRTL ? 'before' : 'after'](inst.append);
}
+ input.unbind('focus', this._showDatepicker);
+ if (inst.trigger)
+ inst.trigger.remove();
var showOn = this._get(inst, 'showOn');
if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
input.focus(this._showDatepicker);
@@ -5657,20 +6966,39 @@ $.extend(Datepicker.prototype, {
{ src:buttonImage, alt:buttonText, title:buttonText })));
input[isRTL ? 'before' : 'after'](inst.trigger);
inst.trigger.click(function() {
- if ($.datepicker._datepickerShowing && $.datepicker._lastInput == target)
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
$.datepicker._hideDatepicker();
else
- $.datepicker._showDatepicker(target);
+ $.datepicker._showDatepicker(input[0]);
return false;
});
}
- input.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).
- bind("setData.datepicker", function(event, key, value) {
- inst.settings[key] = value;
- }).bind("getData.datepicker", function(event, key) {
- return this._get(inst, key);
- });
- $.data(target, PROP_NAME, inst);
+ },
+
+ /* Apply the maximum length for the date format. */
+ _autoSize: function(inst) {
+ if (this._get(inst, 'autoSize') && !inst.inline) {
+ var date = new Date(2009, 12 - 1, 20); // Ensure double digits
+ var dateFormat = this._get(inst, 'dateFormat');
+ if (dateFormat.match(/[DM]/)) {
+ var findMax = function(names) {
+ var max = 0;
+ var maxI = 0;
+ for (var i = 0; i < names.length; i++) {
+ if (names[i].length > max) {
+ max = names[i].length;
+ maxI = i;
+ }
+ }
+ return maxI;
+ };
+ date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
+ 'monthNames' : 'monthNamesShort'))));
+ date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
+ 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
+ }
+ inst.input.attr('size', this._formatDate(inst, date).length);
+ }
},
/* Attach an inline date picker to a div. */
@@ -5685,26 +7013,27 @@ $.extend(Datepicker.prototype, {
return this._get(inst, key);
});
$.data(target, PROP_NAME, inst);
- this._setDate(inst, this._getDefaultDate(inst));
+ this._setDate(inst, this._getDefaultDate(inst), true);
this._updateDatepicker(inst);
this._updateAlternate(inst);
},
/* Pop-up the date picker in a "dialog" box.
@param input element - ignored
- @param dateText string - the initial date to display (in the current format)
- @param onSelect function - the function(dateText) to call when a date is selected
+ @param date string or Date - the initial date to display
+ @param onSelect function - the function to call when a date is selected
@param settings object - update the dialog date picker instance's settings (anonymous object)
@param pos int[2] - coordinates for the dialog's position within the screen or
event - with x/y coordinates or
leave empty for default (screen centre)
@return the manager object */
- _dialogDatepicker: function(input, dateText, onSelect, settings, pos) {
+ _dialogDatepicker: function(input, date, onSelect, settings, pos) {
var inst = this._dialogInst; // internal instance
if (!inst) {
- var id = 'dp' + (++this.uuid);
+ this.uuid += 1;
+ var id = 'dp' + this.uuid;
this._dialogInput = $('<input type="text" id="' + id +
- '" size="1" style="position: absolute; top: -100px;"/>');
+ '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
this._dialogInput.keydown(this._doKeyDown);
$('body').append(this._dialogInput);
inst = this._dialogInst = this._newInst(this._dialogInput, false);
@@ -5712,12 +7041,13 @@ $.extend(Datepicker.prototype, {
$.data(this._dialogInput[0], PROP_NAME, inst);
}
extendRemove(inst.settings, settings || {});
- this._dialogInput.val(dateText);
+ date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
+ this._dialogInput.val(date);
this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
if (!this._pos) {
- var browserWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
- var browserHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
+ var browserWidth = document.documentElement.clientWidth;
+ var browserHeight = document.documentElement.clientHeight;
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
this._pos = // should use actual width/height below
@@ -5725,7 +7055,7 @@ $.extend(Datepicker.prototype, {
}
// move input on screen for focus, but hidden behind dialog
- this._dialogInput.css('left', this._pos[0] + 'px').css('top', this._pos[1] + 'px');
+ this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
inst.settings.onSelect = onSelect;
this._inDialog = true;
this.dpDiv.addClass(this._dialogClass);
@@ -5752,7 +7082,8 @@ $.extend(Datepicker.prototype, {
$target.removeClass(this.markerClassName).
unbind('focus', this._showDatepicker).
unbind('keydown', this._doKeyDown).
- unbind('keypress', this._doKeyPress);
+ unbind('keypress', this._doKeyPress).
+ unbind('keyup', this._doKeyUp);
} else if (nodeName == 'div' || nodeName == 'span')
$target.removeClass(this.markerClassName).empty();
},
@@ -5853,10 +7184,12 @@ $.extend(Datepicker.prototype, {
}
if (inst) {
if (this._curInst == inst) {
- this._hideDatepicker(null);
+ this._hideDatepicker();
}
- var date = this._getDateDatepicker(target);
+ var date = this._getDateDatepicker(target, true);
extendRemove(inst.settings, settings);
+ this._attachments($(target), inst);
+ this._autoSize(inst);
this._setDateDatepicker(target, date);
this._updateDatepicker(inst);
}
@@ -5878,25 +7211,24 @@ $.extend(Datepicker.prototype, {
/* Set the dates for a jQuery selection.
@param target element - the target input field or division or span
- @param date Date - the new date
- @param endDate Date - the new end date for a range (optional) */
- _setDateDatepicker: function(target, date, endDate) {
+ @param date Date - the new date */
+ _setDateDatepicker: function(target, date) {
var inst = this._getInst(target);
if (inst) {
- this._setDate(inst, date, endDate);
+ this._setDate(inst, date);
this._updateDatepicker(inst);
this._updateAlternate(inst);
}
},
/* Get the date(s) for the first entry in a jQuery selection.
- @param target element - the target input field or division or span
- @return Date - the current date or
- Date[2] - the current dates for a range */
- _getDateDatepicker: function(target) {
+ @param target element - the target input field or division or span
+ @param noDefault boolean - true if no default date is to be used
+ @return Date - the current date */
+ _getDateDatepicker: function(target, noDefault) {
var inst = this._getInst(target);
if (inst && !inst.inline)
- this._setDateFromField(inst);
+ this._setDateFromField(inst, noDefault);
return (inst ? this._getDate(inst) : null);
},
@@ -5908,17 +7240,18 @@ $.extend(Datepicker.prototype, {
inst._keyEvent = true;
if ($.datepicker._datepickerShowing)
switch (event.keyCode) {
- case 9: $.datepicker._hideDatepicker(null, '');
+ case 9: $.datepicker._hideDatepicker();
+ handled = false;
break; // hide on tab out
- case 13: var sel = $('td.' + $.datepicker._dayOverClass +
- ', td.' + $.datepicker._currentClass, inst.dpDiv);
+ case 13: var sel = $('td.' + $.datepicker._dayOverClass, inst.dpDiv).
+ add($('td.' + $.datepicker._currentClass, inst.dpDiv));
if (sel[0])
$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
else
- $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
+ $.datepicker._hideDatepicker();
return false; // don't submit the form
break; // select the value on enter
- case 27: $.datepicker._hideDatepicker(null, $.datepicker._get(inst, 'duration'));
+ case 27: $.datepicker._hideDatepicker();
break; // hide on escape
case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
-$.datepicker._get(inst, 'stepBigMonths') :
@@ -5979,6 +7312,27 @@ $.extend(Datepicker.prototype, {
}
},
+ /* Synchronise manual entry and field/alternate field. */
+ _doKeyUp: function(event) {
+ var inst = $.datepicker._getInst(event.target);
+ if (inst.input.val() != inst.lastVal) {
+ try {
+ var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
+ (inst.input ? inst.input.val() : null),
+ $.datepicker._getFormatConfig(inst));
+ if (date) { // only if valid
+ $.datepicker._setDateFromField(inst);
+ $.datepicker._updateAlternate(inst);
+ $.datepicker._updateDatepicker(inst);
+ }
+ }
+ catch (event) {
+ $.datepicker.log(event);
+ }
+ }
+ return true;
+ },
+
/* Pop-up the date picker for a given input field.
@param input element - the input field attached to the date picker or
event - if triggered by focus */
@@ -5989,9 +7343,12 @@ $.extend(Datepicker.prototype, {
if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
return;
var inst = $.datepicker._getInst(input);
+ if ($.datepicker._curInst && $.datepicker._curInst != inst) {
+ $.datepicker._curInst.dpDiv.stop(true, true);
+ }
var beforeShow = $.datepicker._get(inst, 'beforeShow');
extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
- $.datepicker._hideDatepicker(null, '');
+ inst.lastVal = null;
$.datepicker._lastInput = input;
$.datepicker._setDateFromField(inst);
if ($.datepicker._inDialog) // hide cursor
@@ -6011,7 +7368,6 @@ $.extend(Datepicker.prototype, {
}
var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
$.datepicker._pos = null;
- inst.rangeStart = null;
// determine sizing offscreen
inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
$.datepicker._updateDatepicker(inst);
@@ -6022,34 +7378,36 @@ $.extend(Datepicker.prototype, {
'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
left: offset.left + 'px', top: offset.top + 'px'});
if (!inst.inline) {
- var showAnim = $.datepicker._get(inst, 'showAnim') || 'show';
+ var showAnim = $.datepicker._get(inst, 'showAnim');
var duration = $.datepicker._get(inst, 'duration');
var postProcess = function() {
$.datepicker._datepickerShowing = true;
- if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
- $('iframe.ui-datepicker-cover').css({width: inst.dpDiv.width() + 4,
- height: inst.dpDiv.height() + 4});
+ var borders = $.datepicker._getBorders(inst.dpDiv);
+ inst.dpDiv.find('iframe.ui-datepicker-cover'). // IE6- only
+ css({left: -borders[0], top: -borders[1],
+ width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
};
+ inst.dpDiv.zIndex($(input).zIndex()+1);
if ($.effects && $.effects[showAnim])
inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
else
- inst.dpDiv[showAnim](duration, postProcess);
- if (duration == '')
+ inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
+ if (!showAnim || !duration)
postProcess();
- if (inst.input[0].type != 'hidden')
- inst.input[0].focus();
+ if (inst.input.is(':visible') && !inst.input.is(':disabled'))
+ inst.input.focus();
$.datepicker._curInst = inst;
}
},
/* Generate the date picker content. */
_updateDatepicker: function(inst) {
- var dims = {width: inst.dpDiv.width() + 4,
- height: inst.dpDiv.height() + 4};
var self = this;
+ var borders = $.datepicker._getBorders(inst.dpDiv);
inst.dpDiv.empty().append(this._generateHTML(inst))
- .find('iframe.ui-datepicker-cover').
- css({width: dims.width, height: dims.height})
+ .find('iframe.ui-datepicker-cover') // IE6- only
+ .css({left: -borders[0], top: -borders[1],
+ width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
.end()
.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
.bind('mouseout', function(){
@@ -6072,17 +7430,28 @@ $.extend(Datepicker.prototype, {
var numMonths = this._getNumberOfMonths(inst);
var cols = numMonths[1];
var width = 17;
- if (cols > 1) {
+ if (cols > 1)
inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
- } else {
+ else
inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
- }
inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
'Class']('ui-datepicker-multi');
inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
'Class']('ui-datepicker-rtl');
- if (inst.input && inst.input[0].type != 'hidden' && inst == $.datepicker._curInst)
- $(inst.input[0]).focus();
+ if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
+ inst.input.is(':visible') && !inst.input.is(':disabled'))
+ inst.input.focus();
+ },
+
+ /* Retrieve the size of left and top borders for an element.
+ @param elem (jQuery object) the element of interest
+ @return (number[2]) the left and top borders */
+ _getBorders: function(elem) {
+ var convert = function(value) {
+ return {thin: 1, medium: 2, thick: 3}[value] || value;
+ };
+ return [parseFloat(convert(elem.css('border-left-width'))),
+ parseFloat(convert(elem.css('border-top-width')))];
},
/* Check positioning to remain on screen. */
@@ -6091,54 +7460,53 @@ $.extend(Datepicker.prototype, {
var dpHeight = inst.dpDiv.outerHeight();
var inputWidth = inst.input ? inst.input.outerWidth() : 0;
var inputHeight = inst.input ? inst.input.outerHeight() : 0;
- var viewWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft();
- var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(document).scrollTop();
+ var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
+ var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
// now check if datepicker is showing outside window viewport - move to a better place if so.
- offset.left -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth) : 0;
- offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0;
+ offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
+ offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
+ Math.abs(dpHeight + inputHeight) : 0);
return offset;
},
/* Find an object's position on the screen. */
_findPos: function(obj) {
+ var inst = this._getInst(obj);
+ var isRTL = this._get(inst, 'isRTL');
while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
- obj = obj.nextSibling;
+ obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
}
var position = $(obj).offset();
return [position.left, position.top];
},
/* Hide the date picker from view.
- @param input element - the input field attached to the date picker
- @param duration string - the duration over which to close the date picker */
- _hideDatepicker: function(input, duration) {
+ @param input element - the input field attached to the date picker */
+ _hideDatepicker: function(input) {
var inst = this._curInst;
if (!inst || (input && inst != $.data(input, PROP_NAME)))
return;
- if (inst.stayOpen)
- this._selectDate('#' + inst.id, this._formatDate(inst,
- inst.currentDay, inst.currentMonth, inst.currentYear));
- inst.stayOpen = false;
if (this._datepickerShowing) {
- duration = (duration != null ? duration : this._get(inst, 'duration'));
var showAnim = this._get(inst, 'showAnim');
+ var duration = this._get(inst, 'duration');
var postProcess = function() {
$.datepicker._tidyDialog(inst);
+ this._curInst = null;
};
- if (duration != '' && $.effects && $.effects[showAnim])
- inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'),
- duration, postProcess);
+ if ($.effects && $.effects[showAnim])
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
else
- inst.dpDiv[(duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
- (showAnim == 'fadeIn' ? 'fadeOut' : 'hide')))](duration, postProcess);
- if (duration == '')
- this._tidyDialog(inst);
+ inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
+ if (!showAnim)
+ postProcess();
var onClose = this._get(inst, 'onClose');
if (onClose)
onClose.apply((inst.input ? inst.input[0] : null),
@@ -6154,7 +7522,6 @@ $.extend(Datepicker.prototype, {
}
this._inDialog = false;
}
- this._curInst = null;
},
/* Tidy up after a dialog display. */
@@ -6167,11 +7534,12 @@ $.extend(Datepicker.prototype, {
if (!$.datepicker._curInst)
return;
var $target = $(event.target);
- if (($target.parents('#' + $.datepicker._mainDivId).length == 0) &&
+ if ($target[0].id != $.datepicker._mainDivId &&
+ $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
!$target.hasClass($.datepicker.markerClassName) &&
!$target.hasClass($.datepicker._triggerClass) &&
$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
- $.datepicker._hideDatepicker(null, '');
+ $.datepicker._hideDatepicker();
},
/* Adjust one of the date sub-fields. */
@@ -6197,10 +7565,10 @@ $.extend(Datepicker.prototype, {
inst.drawYear = inst.selectedYear = inst.currentYear;
}
else {
- var date = new Date();
- inst.selectedDay = date.getDate();
- inst.drawMonth = inst.selectedMonth = date.getMonth();
- inst.drawYear = inst.selectedYear = date.getFullYear();
+ var date = new Date();
+ inst.selectedDay = date.getDate();
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
+ inst.drawYear = inst.selectedYear = date.getFullYear();
}
this._notifyChange(inst);
this._adjustDate(target);
@@ -6223,7 +7591,7 @@ $.extend(Datepicker.prototype, {
var target = $(id);
var inst = this._getInst(target[0]);
if (inst.input && inst._selectingMonthYear && !$.browser.msie)
- inst.input[0].focus();
+ inst.input.focus();
inst._selectingMonthYear = !inst._selectingMonthYear;
},
@@ -6237,24 +7605,14 @@ $.extend(Datepicker.prototype, {
inst.selectedDay = inst.currentDay = $('a', td).html();
inst.selectedMonth = inst.currentMonth = month;
inst.selectedYear = inst.currentYear = year;
- if (inst.stayOpen) {
- inst.endDay = inst.endMonth = inst.endYear = null;
- }
this._selectDate(id, this._formatDate(inst,
inst.currentDay, inst.currentMonth, inst.currentYear));
- if (inst.stayOpen) {
- inst.rangeStart = this._daylightSavingAdjust(
- new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
- this._updateDatepicker(inst);
- }
},
/* Erase the input field and hide the date picker. */
_clearDate: function(id) {
var target = $(id);
var inst = this._getInst(target[0]);
- inst.stayOpen = false;
- inst.endDay = inst.endMonth = inst.endYear = inst.rangeStart = null;
this._selectDate(target, '');
},
@@ -6273,11 +7631,11 @@ $.extend(Datepicker.prototype, {
inst.input.trigger('change'); // fire the change event
if (inst.inline)
this._updateDatepicker(inst);
- else if (!inst.stayOpen) {
- this._hideDatepicker(null, this._get(inst, 'duration'));
+ else {
+ this._hideDatepicker();
this._lastInput = inst.input[0];
if (typeof(inst.input[0]) != 'object')
- inst.input[0].focus(); // restore focus
+ inst.input.focus(); // restore focus
this._lastInput = null;
}
},
@@ -6288,7 +7646,7 @@ $.extend(Datepicker.prototype, {
if (altField) { // update alternate field too
var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
var date = this._getDate(inst);
- dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
+ var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
$(altField).each(function() { $(this).val(dateStr); });
}
},
@@ -6305,20 +7663,13 @@ $.extend(Datepicker.prototype, {
@param date Date - the date to get the week for
@return number - the number of the week within the year that contains this date */
iso8601Week: function(date) {
- var checkDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
- var firstMon = new Date(checkDate.getFullYear(), 1 - 1, 4); // First week always contains 4 Jan
- var firstDay = firstMon.getDay() || 7; // Day of week: Mon = 1, ..., Sun = 7
- firstMon.setDate(firstMon.getDate() + 1 - firstDay); // Preceding Monday
- if (firstDay < 4 && checkDate < firstMon) { // Adjust first three days in year if necessary
- checkDate.setDate(checkDate.getDate() - 3); // Generate for previous year
- return $.datepicker.iso8601Week(checkDate);
- } else if (checkDate > new Date(checkDate.getFullYear(), 12 - 1, 28)) { // Check last three days in year
- firstDay = new Date(checkDate.getFullYear() + 1, 1 - 1, 4).getDay() || 7;
- if (firstDay > 4 && (checkDate.getDay() || 7) < firstDay - 3) { // Adjust if necessary
- return 1;
- }
- }
- return Math.floor(((checkDate - firstMon) / 86400000) / 7) + 1; // Weeks to given date
+ var checkDate = new Date(date.getTime());
+ // Find Thursday of this week starting on Monday
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
+ var time = checkDate.getTime();
+ checkDate.setMonth(0); // Compare with Jan 1
+ checkDate.setDate(1);
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
},
/* Parse a string value into a date object.
@@ -6359,34 +7710,25 @@ $.extend(Datepicker.prototype, {
// Extract a number from the string value
var getNumber = function(match) {
lookAhead(match);
- var origSize = (match == '@' ? 14 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)));
- var size = origSize;
- var num = 0;
- while (size > 0 && iValue < value.length &&
- value.charAt(iValue) >= '0' && value.charAt(iValue) <= '9') {
- num = num * 10 + parseInt(value.charAt(iValue++),10);
- size--;
- }
- if (size == origSize)
+ var size = (match == '@' ? 14 : (match == '!' ? 20 :
+ (match == 'y' ? 4 : (match == 'o' ? 3 : 2))));
+ var digits = new RegExp('^\\d{1,' + size + '}');
+ var num = value.substring(iValue).match(digits);
+ if (!num)
throw 'Missing number at position ' + iValue;
- return num;
+ iValue += num[0].length;
+ return parseInt(num[0], 10);
};
// Extract a name from the string value and convert to an index
var getName = function(match, shortNames, longNames) {
var names = (lookAhead(match) ? longNames : shortNames);
- var size = 0;
- for (var j = 0; j < names.length; j++)
- size = Math.max(size, names[j].length);
- var name = '';
- var iInit = iValue;
- while (size > 0 && iValue < value.length) {
- name += value.charAt(iValue++);
- for (var i = 0; i < names.length; i++)
- if (name == names[i])
- return i + 1;
- size--;
- }
- throw 'Unknown name at position ' + iInit;
+ for (var i = 0; i < names.length; i++) {
+ if (value.substr(iValue, names[i].length) == names[i]) {
+ iValue += names[i].length;
+ return i + 1;
+ }
+ }
+ throw 'Unknown name at position ' + iValue;
};
// Confirm that a literal character matches the string value
var checkLiteral = function() {
@@ -6427,6 +7769,12 @@ $.extend(Datepicker.prototype, {
month = date.getMonth() + 1;
day = date.getDate();
break;
+ case '!':
+ var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
+ year = date.getFullYear();
+ month = date.getMonth() + 1;
+ day = date.getDate();
+ break;
case "'":
if (lookAhead("'"))
checkLiteral();
@@ -6469,9 +7817,13 @@ $.extend(Datepicker.prototype, {
RFC_1123: 'D, d M yy',
RFC_2822: 'D, d M yy',
RSS: 'D, d M y', // RFC 822
+ TICKS: '!',
TIMESTAMP: '@',
W3C: 'yy-mm-dd', // ISO 8601
+ _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
+ Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
+
/* Format a date object into a string value.
The format can be combinations of the following:
d - day of month (no leading zero)
@@ -6487,6 +7839,7 @@ $.extend(Datepicker.prototype, {
y - year (two digit)
yy - year (four digit)
@ - Unix timestamp (ms since 01/01/1970)
+ ! - Windows ticks (100ns since 01/01/0001)
'...' - literal text
'' - single quote
@@ -6542,10 +7895,8 @@ $.extend(Datepicker.prototype, {
output += formatName('D', date.getDay(), dayNamesShort, dayNames);
break;
case 'o':
- var doy = date.getDate();
- for (var m = date.getMonth() - 1; m >= 0; m--)
- doy += this._getDaysInMonth(date.getFullYear(), m);
- output += formatNumber('o', doy, 3);
+ output += formatNumber('o',
+ (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
break;
case 'm':
output += formatNumber('m', date.getMonth() + 1, 2);
@@ -6560,6 +7911,9 @@ $.extend(Datepicker.prototype, {
case '@':
output += date.getTime();
break;
+ case '!':
+ output += date.getTime() * 10000 + this._ticksTo1970;
+ break;
case "'":
if (lookAhead("'"))
output += "'";
@@ -6577,6 +7931,13 @@ $.extend(Datepicker.prototype, {
_possibleChars: function (format) {
var chars = '';
var literal = false;
+ // Check whether a format character is doubled
+ var lookAhead = function(match) {
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+ if (matches)
+ iFormat++;
+ return matches;
+ };
for (var iFormat = 0; iFormat < format.length; iFormat++)
if (literal)
if (format.charAt(iFormat) == "'" && !lookAhead("'"))
@@ -6609,17 +7970,20 @@ $.extend(Datepicker.prototype, {
},
/* Parse existing date and initialise date picker. */
- _setDateFromField: function(inst) {
+ _setDateFromField: function(inst, noDefault) {
+ if (inst.input.val() == inst.lastVal) {
+ return;
+ }
var dateFormat = this._get(inst, 'dateFormat');
- var dates = inst.input ? inst.input.val() : null;
- inst.endDay = inst.endMonth = inst.endYear = null;
- var date = defaultDate = this._getDefaultDate(inst);
+ var dates = inst.lastVal = inst.input ? inst.input.val() : null;
+ var date, defaultDate;
+ date = defaultDate = this._getDefaultDate(inst);
var settings = this._getFormatConfig(inst);
try {
date = this.parseDate(dateFormat, dates, settings) || defaultDate;
} catch (event) {
this.log(event);
- date = defaultDate;
+ dates = (noDefault ? '' : dates);
}
inst.selectedDay = date.getDate();
inst.drawMonth = inst.selectedMonth = date.getMonth();
@@ -6632,23 +7996,27 @@ $.extend(Datepicker.prototype, {
/* Retrieve the default date shown on opening. */
_getDefaultDate: function(inst) {
- var date = this._determineDate(this._get(inst, 'defaultDate'), new Date());
- var minDate = this._getMinMaxDate(inst, 'min', true);
- var maxDate = this._getMinMaxDate(inst, 'max');
- date = (minDate && date < minDate ? minDate : date);
- date = (maxDate && date > maxDate ? maxDate : date);
- return date;
+ return this._restrictMinMax(inst,
+ this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
},
/* A date may be specified as an exact value or a relative one. */
- _determineDate: function(date, defaultDate) {
+ _determineDate: function(inst, date, defaultDate) {
var offsetNumeric = function(offset) {
var date = new Date();
date.setDate(date.getDate() + offset);
return date;
};
- var offsetString = function(offset, getDaysInMonth) {
- var date = new Date();
+ var offsetString = function(offset) {
+ try {
+ return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
+ offset, $.datepicker._getFormatConfig(inst));
+ }
+ catch (e) {
+ // Ignore
+ }
+ var date = (offset.toLowerCase().match(/^c/) ?
+ $.datepicker._getDate(inst) : null) || new Date();
var year = date.getFullYear();
var month = date.getMonth();
var day = date.getDate();
@@ -6662,19 +8030,18 @@ $.extend(Datepicker.prototype, {
day += parseInt(matches[1],10) * 7; break;
case 'm' : case 'M' :
month += parseInt(matches[1],10);
- day = Math.min(day, getDaysInMonth(year, month));
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
break;
case 'y': case 'Y' :
year += parseInt(matches[1],10);
- day = Math.min(day, getDaysInMonth(year, month));
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
break;
}
matches = pattern.exec(offset);
}
return new Date(year, month, day);
};
- date = (date == null ? defaultDate :
- (typeof date == 'string' ? offsetString(date, this._getDaysInMonth) :
+ date = (date == null ? defaultDate : (typeof date == 'string' ? offsetString(date) :
(typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : date)));
date = (date && date.toString() == 'Invalid Date' ? defaultDate : date);
if (date) {
@@ -6699,15 +8066,15 @@ $.extend(Datepicker.prototype, {
},
/* Set the date(s) directly. */
- _setDate: function(inst, date, endDate) {
+ _setDate: function(inst, date, noChange) {
var clear = !(date);
var origMonth = inst.selectedMonth;
var origYear = inst.selectedYear;
- date = this._determineDate(date, new Date());
+ date = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
inst.selectedDay = inst.currentDay = date.getDate();
inst.drawMonth = inst.selectedMonth = inst.currentMonth = date.getMonth();
inst.drawYear = inst.selectedYear = inst.currentYear = date.getFullYear();
- if (origMonth != inst.selectedMonth || origYear != inst.selectedYear)
+ if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
this._notifyChange(inst);
this._adjustInstDate(inst);
if (inst.input) {
@@ -6735,11 +8102,10 @@ $.extend(Datepicker.prototype, {
var numMonths = this._getNumberOfMonths(inst);
var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
var stepMonths = this._get(inst, 'stepMonths');
- var stepBigMonths = this._get(inst, 'stepBigMonths');
var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
- var minDate = this._getMinMaxDate(inst, 'min', true);
+ var minDate = this._getMinMaxDate(inst, 'min');
var maxDate = this._getMinMaxDate(inst, 'max');
var drawMonth = inst.drawMonth - showCurrentAtPos;
var drawYear = inst.drawYear;
@@ -6749,7 +8115,7 @@ $.extend(Datepicker.prototype, {
}
if (maxDate) {
var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
- maxDate.getMonth() - numMonths[1] + 1, maxDate.getDate()));
+ maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
drawMonth--;
@@ -6766,7 +8132,8 @@ $.extend(Datepicker.prototype, {
this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
this._getFormatConfig(inst)));
var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
- '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
+ '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
+ '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
var nextText = this._get(inst, 'nextText');
@@ -6774,19 +8141,23 @@ $.extend(Datepicker.prototype, {
this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
this._getFormatConfig(inst)));
var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
- '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
+ '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
+ '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
(hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
var currentText = this._get(inst, 'currentText');
var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
currentText = (!navigationAsDateFormat ? currentText :
this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
- var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
+ var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
+ '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
- (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery.datepicker._gotoToday(\'#' + inst.id + '\');"' +
+ (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
+ '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
'>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
var firstDay = parseInt(this._get(inst, 'firstDay'),10);
firstDay = (isNaN(firstDay) ? 0 : firstDay);
+ var showWeek = this._get(inst, 'showWeek');
var dayNames = this._get(inst, 'dayNames');
var dayNamesShort = this._get(inst, 'dayNamesShort');
var dayNamesMin = this._get(inst, 'dayNamesMin');
@@ -6794,9 +8165,8 @@ $.extend(Datepicker.prototype, {
var monthNamesShort = this._get(inst, 'monthNamesShort');
var beforeShowDay = this._get(inst, 'beforeShowDay');
var showOtherMonths = this._get(inst, 'showOtherMonths');
+ var selectOtherMonths = this._get(inst, 'selectOtherMonths');
var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
- var endDate = inst.endDay ? this._daylightSavingAdjust(
- new Date(inst.endYear, inst.endMonth, inst.endDay)) : currentDate;
var defaultDate = this._getDefaultDate(inst);
var html = '';
for (var row = 0; row < numMonths[0]; row++) {
@@ -6806,22 +8176,25 @@ $.extend(Datepicker.prototype, {
var cornerClass = ' ui-corner-all';
var calender = '';
if (isMultiMonth) {
- calender += '<div class="ui-datepicker-group ui-datepicker-group-';
- switch (col) {
- case 0: calender += 'first'; cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
- case numMonths[1]-1: calender += 'last'; cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
- default: calender += 'middle'; cornerClass = ''; break;
- }
+ calender += '<div class="ui-datepicker-group';
+ if (numMonths[1] > 1)
+ switch (col) {
+ case 0: calender += ' ui-datepicker-group-first';
+ cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
+ case numMonths[1]-1: calender += ' ui-datepicker-group-last';
+ cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
+ default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
+ }
calender += '">';
}
calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
(/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
(/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
- selectedDate, row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
+ row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
'</div><table class="ui-datepicker-calendar"><thead>' +
'<tr>';
- var thead = '';
+ var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
for (var dow = 0; dow < 7; dow++) { // days of the week
var day = (dow + firstDay) % 7;
thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
@@ -6836,12 +8209,13 @@ $.extend(Datepicker.prototype, {
var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
calender += '<tr>';
- var tbody = '';
+ var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
+ this._get(inst, 'calculateWeek')(printDate) + '</td>');
for (var dow = 0; dow < 7; dow++) { // create date picker days
var daySettings = (beforeShowDay ?
beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
var otherMonth = (printDate.getMonth() != drawMonth);
- var unselectable = otherMonth || !daySettings[0] ||
+ var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
tbody += '<td class="' +
((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
@@ -6852,18 +8226,17 @@ $.extend(Datepicker.prototype, {
' ' + this._dayOverClass : '') + // highlight selected day
(unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
(otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
- (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
- ' ' + this._currentClass : '') + // highlight selected day
+ (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
(printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
- (unselectable ? '' : ' onclick="DP_jQuery.datepicker._selectDay(\'#' +
- inst.id + '\',' + drawMonth + ',' + drawYear + ', this);return false;"') + '>' + // actions
- (otherMonth ? (showOtherMonths ? printDate.getDate() : '&#xa0;') : // display for other months
+ (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
+ inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
+ (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
(unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
(printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
- (printDate.getTime() >= currentDate.getTime() && printDate.getTime() <= endDate.getTime() ? // in current range
- ' ui-state-active' : '') + // highlight selected day
- '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display for this month
+ (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
+ (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
+ '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
printDate.setDate(printDate.getDate() + 1);
printDate = this._daylightSavingAdjust(printDate);
}
@@ -6874,7 +8247,7 @@ $.extend(Datepicker.prototype, {
drawMonth = 0;
drawYear++;
}
- calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
+ calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
group += calender;
}
@@ -6888,8 +8261,7 @@ $.extend(Datepicker.prototype, {
/* Generate the month and year header. */
_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
- selectedDate, secondary, monthNames, monthNamesShort) {
- minDate = (inst.rangeStart && minDate && selectedDate < minDate ? selectedDate : minDate);
+ secondary, monthNames, monthNamesShort) {
var changeMonth = this._get(inst, 'changeMonth');
var changeYear = this._get(inst, 'changeYear');
var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
@@ -6897,13 +8269,13 @@ $.extend(Datepicker.prototype, {
var monthHtml = '';
// month selection
if (secondary || !changeMonth)
- monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span> ';
+ monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
else {
var inMinYear = (minDate && minDate.getFullYear() == drawYear);
var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
monthHtml += '<select class="ui-datepicker-month" ' +
- 'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
- 'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+ 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
+ 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
'>';
for (var month = 0; month < 12; month++) {
if ((!inMinYear || month >= minDate.getMonth()) &&
@@ -6915,30 +8287,27 @@ $.extend(Datepicker.prototype, {
monthHtml += '</select>';
}
if (!showMonthAfterYear)
- html += monthHtml + ((secondary || changeMonth || changeYear) && (!(changeMonth && changeYear)) ? '&#xa0;' : '');
+ html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
// year selection
if (secondary || !changeYear)
html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
else {
// determine range of years to display
var years = this._get(inst, 'yearRange').split(':');
- var year = 0;
- var endYear = 0;
- if (years.length != 2) {
- year = drawYear - 10;
- endYear = drawYear + 10;
- } else if (years[0].charAt(0) == '+' || years[0].charAt(0) == '-') {
- year = drawYear + parseInt(years[0], 10);
- endYear = drawYear + parseInt(years[1], 10);
- } else {
- year = parseInt(years[0], 10);
- endYear = parseInt(years[1], 10);
- }
+ var thisYear = new Date().getFullYear();
+ var determineYear = function(value) {
+ var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
+ (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
+ parseInt(value, 10)));
+ return (isNaN(year) ? thisYear : year);
+ };
+ var year = determineYear(years[0]);
+ var endYear = Math.max(year, determineYear(years[1] || ''));
year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
html += '<select class="ui-datepicker-year" ' +
- 'onchange="DP_jQuery.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
- 'onclick="DP_jQuery.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
+ 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
+ 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
'>';
for (; year <= endYear; year++) {
html += '<option value="' + year + '"' +
@@ -6947,8 +8316,9 @@ $.extend(Datepicker.prototype, {
}
html += '</select>';
}
+ html += this._get(inst, 'yearSuffix');
if (showMonthAfterYear)
- html += (secondary || changeMonth || changeYear ? '&#xa0;' : '') + monthHtml;
+ html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
html += '</div>'; // Close datepicker_header
return html;
},
@@ -6959,12 +8329,8 @@ $.extend(Datepicker.prototype, {
var month = inst.drawMonth + (period == 'M' ? offset : 0);
var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
(period == 'D' ? offset : 0);
- var date = this._daylightSavingAdjust(new Date(year, month, day));
- // ensure it is within the bounds set
- var minDate = this._getMinMaxDate(inst, 'min', true);
- var maxDate = this._getMinMaxDate(inst, 'max');
- date = (minDate && date < minDate ? minDate : date);
- date = (maxDate && date > maxDate ? maxDate : date);
+ var date = this._restrictMinMax(inst,
+ this._daylightSavingAdjust(new Date(year, month, day)));
inst.selectedDay = date.getDate();
inst.drawMonth = inst.selectedMonth = date.getMonth();
inst.drawYear = inst.selectedYear = date.getFullYear();
@@ -6972,6 +8338,15 @@ $.extend(Datepicker.prototype, {
this._notifyChange(inst);
},
+ /* Ensure a date is within any min/max bounds. */
+ _restrictMinMax: function(inst, date) {
+ var minDate = this._getMinMaxDate(inst, 'min');
+ var maxDate = this._getMinMaxDate(inst, 'max');
+ date = (minDate && date < minDate ? minDate : date);
+ date = (maxDate && date > maxDate ? maxDate : date);
+ return date;
+ },
+
/* Notify change of month/year. */
_notifyChange: function(inst) {
var onChange = this._get(inst, 'onChangeMonthYear');
@@ -6986,11 +8361,9 @@ $.extend(Datepicker.prototype, {
return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
},
- /* Determine the current maximum date - ensure no time components are set - may be overridden for a range. */
- _getMinMaxDate: function(inst, minMax, checkRange) {
- var date = this._determineDate(this._get(inst, minMax + 'Date'), null);
- return (!checkRange || !inst.rangeStart ? date :
- (!date || inst.rangeStart > date ? inst.rangeStart : date));
+ /* Determine the current maximum date - ensure no time components are set. */
+ _getMinMaxDate: function(inst, minMax) {
+ return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
},
/* Find the number of days in a given month. */
@@ -7006,8 +8379,8 @@ $.extend(Datepicker.prototype, {
/* Determines if we should allow a "next/prev" month display change. */
_canAdjustMonth: function(inst, offset, curYear, curMonth) {
var numMonths = this._getNumberOfMonths(inst);
- var date = this._daylightSavingAdjust(new Date(
- curYear, curMonth + (offset < 0 ? offset : numMonths[1]), 1));
+ var date = this._daylightSavingAdjust(new Date(curYear,
+ curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
if (offset < 0)
date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
return this._isInRange(inst, date);
@@ -7015,13 +8388,10 @@ $.extend(Datepicker.prototype, {
/* Is the given date in the accepted range? */
_isInRange: function(inst, date) {
- // during range selection, use minimum of selected date and range start
- var newMinDate = (!inst.rangeStart ? null : this._daylightSavingAdjust(
- new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay)));
- newMinDate = (newMinDate && inst.rangeStart < newMinDate ? inst.rangeStart : newMinDate);
- var minDate = newMinDate || this._getMinMaxDate(inst, 'min');
+ var minDate = this._getMinMaxDate(inst, 'min');
var maxDate = this._getMinMaxDate(inst, 'max');
- return ((!minDate || date >= minDate) && (!maxDate || date <= maxDate));
+ return ((!minDate || date.getTime() >= minDate.getTime()) &&
+ (!maxDate || date.getTime() <= maxDate.getTime()));
},
/* Provide the configuration settings for formatting/parsing. */
@@ -7077,7 +8447,7 @@ $.fn.datepicker = function(options){
}
var otherArgs = Array.prototype.slice.call(arguments, 1);
- if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate'))
+ if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
return $.datepicker['_' + options + 'Datepicker'].
apply($.datepicker, [this[0]].concat(otherArgs));
if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
@@ -7094,73 +8464,87 @@ $.fn.datepicker = function(options){
$.datepicker = new Datepicker(); // singleton instance
$.datepicker.initialized = false;
$.datepicker.uuid = new Date().getTime();
-$.datepicker.version = "1.7.2";
+$.datepicker.version = "1.8.2";
// Workaround for #4055
// Add another global to avoid noConflict issues with inline event handlers
-window.DP_jQuery = $;
+window['DP_jQuery_' + dpuuid] = $;
})(jQuery);
/*
- * jQuery UI Dialog 1.7.2
+ * jQuery UI Dialog 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Dialog
*
* Depends:
- * ui.core.js
- * ui.draggable.js
- * ui.resizable.js
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.button.js
+ * jquery.ui.draggable.js
+ * jquery.ui.mouse.js
+ * jquery.ui.position.js
+ * jquery.ui.resizable.js
*/
(function($) {
-var setDataSwitch = {
- dragStart: "start.draggable",
- drag: "drag.draggable",
- dragStop: "stop.draggable",
- maxHeight: "maxHeight.resizable",
- minHeight: "minHeight.resizable",
- maxWidth: "maxWidth.resizable",
- minWidth: "minWidth.resizable",
- resizeStart: "start.resizable",
- resize: "drag.resizable",
- resizeStop: "stop.resizable"
- },
-
- uiDialogClasses =
- 'ui-dialog ' +
- 'ui-widget ' +
- 'ui-widget-content ' +
- 'ui-corner-all ';
+var uiDialogClasses =
+ 'ui-dialog ' +
+ 'ui-widget ' +
+ 'ui-widget-content ' +
+ 'ui-corner-all ';
$.widget("ui.dialog", {
-
- _init: function() {
+ options: {
+ autoOpen: true,
+ buttons: {},
+ closeOnEscape: true,
+ closeText: 'close',
+ dialogClass: '',
+ draggable: true,
+ hide: null,
+ height: 'auto',
+ maxHeight: false,
+ maxWidth: false,
+ minHeight: 150,
+ minWidth: 150,
+ modal: false,
+ position: 'center',
+ resizable: true,
+ show: null,
+ stack: true,
+ title: '',
+ width: 300,
+ zIndex: 1000
+ },
+ _create: function() {
this.originalTitle = this.element.attr('title');
var self = this,
- options = this.options,
+ options = self.options,
- title = options.title || this.originalTitle || '&nbsp;',
- titleId = $.ui.dialog.getTitleId(this.element),
+ title = options.title || self.originalTitle || '&#160;',
+ titleId = $.ui.dialog.getTitleId(self.element),
- uiDialog = (this.uiDialog = $('<div/>'))
+ uiDialog = (self.uiDialog = $('<div></div>'))
.appendTo(document.body)
.hide()
.addClass(uiDialogClasses + options.dialogClass)
.css({
- position: 'absolute',
- overflow: 'hidden',
zIndex: options.zIndex
})
// setting tabIndex makes the div focusable
// setting outline to 0 prevents a border on focus in Mozilla
.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
- (options.closeOnEscape && event.keyCode
- && event.keyCode == $.ui.keyCode.ESCAPE && self.close(event));
+ if (options.closeOnEscape && event.keyCode &&
+ event.keyCode === $.ui.keyCode.ESCAPE) {
+
+ self.close(event);
+ event.preventDefault();
+ }
})
.attr({
role: 'dialog',
@@ -7170,7 +8554,7 @@ $.widget("ui.dialog", {
self.moveToTop(false, event);
}),
- uiDialogContent = this.element
+ uiDialogContent = self.element
.show()
.removeAttr('title')
.addClass(
@@ -7178,7 +8562,7 @@ $.widget("ui.dialog", {
'ui-widget-content')
.appendTo(uiDialog),
- uiDialogTitlebar = (this.uiDialogTitlebar = $('<div></div>'))
+ uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
.addClass(
'ui-dialog-titlebar ' +
'ui-widget-header ' +
@@ -7187,7 +8571,7 @@ $.widget("ui.dialog", {
)
.prependTo(uiDialog),
- uiDialogTitlebarClose = $('<a href="#"/>')
+ uiDialogTitlebarClose = $('<a href="#"></a>')
.addClass(
'ui-dialog-titlebar-close ' +
'ui-corner-all'
@@ -7207,16 +8591,13 @@ $.widget("ui.dialog", {
.blur(function() {
uiDialogTitlebarClose.removeClass('ui-state-focus');
})
- .mousedown(function(ev) {
- ev.stopPropagation();
- })
.click(function(event) {
self.close(event);
return false;
})
.appendTo(uiDialogTitlebar),
- uiDialogTitlebarCloseText = (this.uiDialogTitlebarCloseText = $('<span/>'))
+ uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
.addClass(
'ui-icon ' +
'ui-icon-closethick'
@@ -7224,68 +8605,104 @@ $.widget("ui.dialog", {
.text(options.closeText)
.appendTo(uiDialogTitlebarClose),
- uiDialogTitle = $('<span/>')
+ uiDialogTitle = $('<span></span>')
.addClass('ui-dialog-title')
.attr('id', titleId)
.html(title)
.prependTo(uiDialogTitlebar);
- uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
+ //handling of deprecated beforeclose (vs beforeClose) option
+ //Ticket #4669 http://dev.jqueryui.com/ticket/4669
+ //TODO: remove in 1.9pre
+ if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
+ options.beforeClose = options.beforeclose;
+ }
- (options.draggable && $.fn.draggable && this._makeDraggable());
- (options.resizable && $.fn.resizable && this._makeResizable());
+ uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
- this._createButtons(options.buttons);
- this._isOpen = false;
+ if (options.draggable && $.fn.draggable) {
+ self._makeDraggable();
+ }
+ if (options.resizable && $.fn.resizable) {
+ self._makeResizable();
+ }
- (options.bgiframe && $.fn.bgiframe && uiDialog.bgiframe());
- (options.autoOpen && this.open());
+ self._createButtons(options.buttons);
+ self._isOpen = false;
+ if ($.fn.bgiframe) {
+ uiDialog.bgiframe();
+ }
+ },
+ _init: function() {
+ if ( this.options.autoOpen ) {
+ this.open();
+ }
},
destroy: function() {
- (this.overlay && this.overlay.destroy());
- this.uiDialog.hide();
- this.element
+ var self = this;
+
+ if (self.overlay) {
+ self.overlay.destroy();
+ }
+ self.uiDialog.hide();
+ self.element
.unbind('.dialog')
.removeData('dialog')
.removeClass('ui-dialog-content ui-widget-content')
.hide().appendTo('body');
- this.uiDialog.remove();
+ self.uiDialog.remove();
+
+ if (self.originalTitle) {
+ self.element.attr('title', self.originalTitle);
+ }
- (this.originalTitle && this.element.attr('title', this.originalTitle));
+ return self;
+ },
+
+ widget: function() {
+ return this.uiDialog;
},
close: function(event) {
- var self = this;
-
- if (false === self._trigger('beforeclose', event)) {
+ var self = this,
+ maxZ;
+
+ if (false === self._trigger('beforeClose', event)) {
return;
}
- (self.overlay && self.overlay.destroy());
+ if (self.overlay) {
+ self.overlay.destroy();
+ }
self.uiDialog.unbind('keypress.ui-dialog');
- (self.options.hide
- ? self.uiDialog.hide(self.options.hide, function() {
+ self._isOpen = false;
+
+ if (self.options.hide) {
+ self.uiDialog.hide(self.options.hide, function() {
self._trigger('close', event);
- })
- : self.uiDialog.hide() && self._trigger('close', event));
+ });
+ } else {
+ self.uiDialog.hide();
+ self._trigger('close', event);
+ }
$.ui.dialog.overlay.resize();
- self._isOpen = false;
-
// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
if (self.options.modal) {
- var maxZ = 0;
+ maxZ = 0;
$('.ui-dialog').each(function() {
- if (this != self.uiDialog[0]) {
+ if (this !== self.uiDialog[0]) {
maxZ = Math.max(maxZ, $(this).css('z-index'));
}
});
$.ui.dialog.maxZ = maxZ;
}
+
+ return self;
},
isOpen: function() {
@@ -7295,58 +8712,70 @@ $.widget("ui.dialog", {
// the force parameter allows us to move modal dialogs to their correct
// position on open
moveToTop: function(force, event) {
-
- if ((this.options.modal && !force)
- || (!this.options.stack && !this.options.modal)) {
- return this._trigger('focus', event);
+ var self = this,
+ options = self.options,
+ saveScroll;
+
+ if ((options.modal && !force) ||
+ (!options.stack && !options.modal)) {
+ return self._trigger('focus', event);
}
-
- if (this.options.zIndex > $.ui.dialog.maxZ) {
- $.ui.dialog.maxZ = this.options.zIndex;
+
+ if (options.zIndex > $.ui.dialog.maxZ) {
+ $.ui.dialog.maxZ = options.zIndex;
+ }
+ if (self.overlay) {
+ $.ui.dialog.maxZ += 1;
+ self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
}
- (this.overlay && this.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = ++$.ui.dialog.maxZ));
//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
// http://ui.jquery.com/bugs/ticket/3193
- var saveScroll = { scrollTop: this.element.attr('scrollTop'), scrollLeft: this.element.attr('scrollLeft') };
- this.uiDialog.css('z-index', ++$.ui.dialog.maxZ);
- this.element.attr(saveScroll);
- this._trigger('focus', event);
+ saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
+ $.ui.dialog.maxZ += 1;
+ self.uiDialog.css('z-index', $.ui.dialog.maxZ);
+ self.element.attr(saveScroll);
+ self._trigger('focus', event);
+
+ return self;
},
open: function() {
if (this._isOpen) { return; }
- var options = this.options,
- uiDialog = this.uiDialog;
+ var self = this,
+ options = self.options,
+ uiDialog = self.uiDialog;
- this.overlay = options.modal ? new $.ui.dialog.overlay(this) : null;
- (uiDialog.next().length && uiDialog.appendTo('body'));
- this._size();
- this._position(options.position);
+ self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
+ if (uiDialog.next().length) {
+ uiDialog.appendTo('body');
+ }
+ self._size();
+ self._position(options.position);
uiDialog.show(options.show);
- this.moveToTop(true);
+ self.moveToTop(true);
// prevent tabbing out of modal dialogs
- (options.modal && uiDialog.bind('keypress.ui-dialog', function(event) {
- if (event.keyCode != $.ui.keyCode.TAB) {
- return;
- }
-
- var tabbables = $(':tabbable', this),
- first = tabbables.filter(':first')[0],
- last = tabbables.filter(':last')[0];
-
- if (event.target == last && !event.shiftKey) {
- setTimeout(function() {
- first.focus();
- }, 1);
- } else if (event.target == first && event.shiftKey) {
- setTimeout(function() {
- last.focus();
- }, 1);
- }
- }));
+ if (options.modal) {
+ uiDialog.bind('keypress.ui-dialog', function(event) {
+ if (event.keyCode !== $.ui.keyCode.TAB) {
+ return;
+ }
+
+ var tabbables = $(':tabbable', this),
+ first = tabbables.filter(':first'),
+ last = tabbables.filter(':last');
+
+ if (event.target === last[0] && !event.shiftKey) {
+ first.focus(1);
+ return false;
+ } else if (event.target === first[0] && event.shiftKey) {
+ last.focus(1);
+ return false;
+ }
+ });
+ }
// set focus to the first tabbable element in the content area or the first button
// if there are no tabbable elements, set focus on the dialog itself
@@ -7357,8 +8786,10 @@ $.widget("ui.dialog", {
.filter(':first')
.focus();
- this._trigger('open');
- this._isOpen = true;
+ self._trigger('open');
+ self._isOpen = true;
+
+ return self;
},
_createButtons: function(buttons) {
@@ -7372,59 +8803,57 @@ $.widget("ui.dialog", {
);
// if we already have a button pane, remove it
- this.uiDialog.find('.ui-dialog-buttonpane').remove();
+ self.uiDialog.find('.ui-dialog-buttonpane').remove();
- (typeof buttons == 'object' && buttons !== null &&
- $.each(buttons, function() { return !(hasButtons = true); }));
+ if (typeof buttons === 'object' && buttons !== null) {
+ $.each(buttons, function() {
+ return !(hasButtons = true);
+ });
+ }
if (hasButtons) {
$.each(buttons, function(name, fn) {
- $('<button type="button"></button>')
- .addClass(
- 'ui-state-default ' +
- 'ui-corner-all'
- )
+ var button = $('<button type="button"></button>')
.text(name)
.click(function() { fn.apply(self.element[0], arguments); })
- .hover(
- function() {
- $(this).addClass('ui-state-hover');
- },
- function() {
- $(this).removeClass('ui-state-hover');
- }
- )
- .focus(function() {
- $(this).addClass('ui-state-focus');
- })
- .blur(function() {
- $(this).removeClass('ui-state-focus');
- })
.appendTo(uiDialogButtonPane);
+ if ($.fn.button) {
+ button.button();
+ }
});
- uiDialogButtonPane.appendTo(this.uiDialog);
+ uiDialogButtonPane.appendTo(self.uiDialog);
}
},
_makeDraggable: function() {
var self = this,
- options = this.options,
+ options = self.options,
+ doc = $(document),
heightBeforeDrag;
- this.uiDialog.draggable({
- cancel: '.ui-dialog-content',
+ function filteredUi(ui) {
+ return {
+ position: ui.position,
+ offset: ui.offset
+ };
+ }
+
+ self.uiDialog.draggable({
+ cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
handle: '.ui-dialog-titlebar',
containment: 'document',
- start: function() {
- heightBeforeDrag = options.height;
+ start: function(event, ui) {
+ heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
$(this).height($(this).height()).addClass("ui-dialog-dragging");
- (options.dragStart && options.dragStart.apply(self.element[0], arguments));
+ self._trigger('dragStart', event, filteredUi(ui));
},
- drag: function() {
- (options.drag && options.drag.apply(self.element[0], arguments));
+ drag: function(event, ui) {
+ self._trigger('drag', event, filteredUi(ui));
},
- stop: function() {
+ stop: function(event, ui) {
+ options.position = [ui.position.left - doc.scrollLeft(),
+ ui.position.top - doc.scrollTop()];
$(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
- (options.dragStop && options.dragStop.apply(self.element[0], arguments));
+ self._trigger('dragStop', event, filteredUi(ui));
$.ui.dialog.overlay.resize();
}
});
@@ -7433,202 +8862,282 @@ $.widget("ui.dialog", {
_makeResizable: function(handles) {
handles = (handles === undefined ? this.options.resizable : handles);
var self = this,
- options = this.options,
- resizeHandles = typeof handles == 'string'
- ? handles
- : 'n,e,s,w,se,sw,ne,nw';
+ options = self.options,
+ // .ui-resizable has position: relative defined in the stylesheet
+ // but dialogs have to use absolute or fixed positioning
+ position = self.uiDialog.css('position'),
+ resizeHandles = (typeof handles === 'string' ?
+ handles :
+ 'n,e,s,w,se,sw,ne,nw'
+ );
+
+ function filteredUi(ui) {
+ return {
+ originalPosition: ui.originalPosition,
+ originalSize: ui.originalSize,
+ position: ui.position,
+ size: ui.size
+ };
+ }
- this.uiDialog.resizable({
+ self.uiDialog.resizable({
cancel: '.ui-dialog-content',
- alsoResize: this.element,
+ containment: 'document',
+ alsoResize: self.element,
maxWidth: options.maxWidth,
maxHeight: options.maxHeight,
minWidth: options.minWidth,
- minHeight: options.minHeight,
- start: function() {
+ minHeight: self._minHeight(),
+ handles: resizeHandles,
+ start: function(event, ui) {
$(this).addClass("ui-dialog-resizing");
- (options.resizeStart && options.resizeStart.apply(self.element[0], arguments));
+ self._trigger('resizeStart', event, filteredUi(ui));
},
- resize: function() {
- (options.resize && options.resize.apply(self.element[0], arguments));
+ resize: function(event, ui) {
+ self._trigger('resize', event, filteredUi(ui));
},
- handles: resizeHandles,
- stop: function() {
+ stop: function(event, ui) {
$(this).removeClass("ui-dialog-resizing");
options.height = $(this).height();
options.width = $(this).width();
- (options.resizeStop && options.resizeStop.apply(self.element[0], arguments));
+ self._trigger('resizeStop', event, filteredUi(ui));
$.ui.dialog.overlay.resize();
}
})
+ .css('position', position)
.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
},
- _position: function(pos) {
- var wnd = $(window), doc = $(document),
- pTop = doc.scrollTop(), pLeft = doc.scrollLeft(),
- minTop = pTop;
+ _minHeight: function() {
+ var options = this.options;
- if ($.inArray(pos, ['center','top','right','bottom','left']) >= 0) {
- pos = [
- pos == 'right' || pos == 'left' ? pos : 'center',
- pos == 'top' || pos == 'bottom' ? pos : 'middle'
- ];
- }
- if (pos.constructor != Array) {
- pos = ['center', 'middle'];
- }
- if (pos[0].constructor == Number) {
- pLeft += pos[0];
+ if (options.height === 'auto') {
+ return options.minHeight;
} else {
- switch (pos[0]) {
- case 'left':
- pLeft += 0;
- break;
- case 'right':
- pLeft += wnd.width() - this.uiDialog.outerWidth();
- break;
- default:
- case 'center':
- pLeft += (wnd.width() - this.uiDialog.outerWidth()) / 2;
- }
+ return Math.min(options.minHeight, options.height);
}
- if (pos[1].constructor == Number) {
- pTop += pos[1];
- } else {
- switch (pos[1]) {
- case 'top':
- pTop += 0;
- break;
- case 'bottom':
- pTop += wnd.height() - this.uiDialog.outerHeight();
- break;
- default:
- case 'middle':
- pTop += (wnd.height() - this.uiDialog.outerHeight()) / 2;
+ },
+
+ _position: function(position) {
+ var myAt = [],
+ offset = [0, 0],
+ isVisible;
+
+ position = position || $.ui.dialog.prototype.options.position;
+
+ // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
+// if (typeof position == 'string' || $.isArray(position)) {
+// myAt = $.isArray(position) ? position : position.split(' ');
+
+ if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
+ myAt = position.split ? position.split(' ') : [position[0], position[1]];
+ if (myAt.length === 1) {
+ myAt[1] = myAt[0];
+ }
+
+ $.each(['left', 'top'], function(i, offsetPosition) {
+ if (+myAt[i] === myAt[i]) {
+ offset[i] = myAt[i];
+ myAt[i] = offsetPosition;
+ }
+ });
+ } else if (typeof position === 'object') {
+ if ('left' in position) {
+ myAt[0] = 'left';
+ offset[0] = position.left;
+ } else if ('right' in position) {
+ myAt[0] = 'right';
+ offset[0] = -position.right;
+ }
+
+ if ('top' in position) {
+ myAt[1] = 'top';
+ offset[1] = position.top;
+ } else if ('bottom' in position) {
+ myAt[1] = 'bottom';
+ offset[1] = -position.bottom;
}
}
- // prevent the dialog from being too high (make sure the titlebar
- // is accessible)
- pTop = Math.max(pTop, minTop);
- this.uiDialog.css({top: pTop, left: pLeft});
+ // need to show the dialog to get the actual offset in the position plugin
+ isVisible = this.uiDialog.is(':visible');
+ if (!isVisible) {
+ this.uiDialog.show();
+ }
+ this.uiDialog
+ // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
+ .css({ top: 0, left: 0 })
+ .position({
+ my: myAt.join(' '),
+ at: myAt.join(' '),
+ offset: offset.join(' '),
+ of: window,
+ collision: 'fit',
+ // ensure that the titlebar is never outside the document
+ using: function(pos) {
+ var topOffset = $(this).css(pos).offset().top;
+ if (topOffset < 0) {
+ $(this).css('top', pos.top - topOffset);
+ }
+ }
+ });
+ if (!isVisible) {
+ this.uiDialog.hide();
+ }
},
- _setData: function(key, value){
- (setDataSwitch[key] && this.uiDialog.data(setDataSwitch[key], value));
+ _setOption: function(key, value){
+ var self = this,
+ uiDialog = self.uiDialog,
+ isResizable = uiDialog.is(':data(resizable)'),
+ resize = false;
+
switch (key) {
+ //handling of deprecated beforeclose (vs beforeClose) option
+ //Ticket #4669 http://dev.jqueryui.com/ticket/4669
+ //TODO: remove in 1.9pre
+ case "beforeclose":
+ key = "beforeClose";
+ break;
case "buttons":
- this._createButtons(value);
+ self._createButtons(value);
break;
case "closeText":
- this.uiDialogTitlebarCloseText.text(value);
+ // convert whatever was passed in to a string, for text() to not throw up
+ self.uiDialogTitlebarCloseText.text("" + value);
break;
case "dialogClass":
- this.uiDialog
- .removeClass(this.options.dialogClass)
+ uiDialog
+ .removeClass(self.options.dialogClass)
.addClass(uiDialogClasses + value);
break;
+ case "disabled":
+ if (value) {
+ uiDialog.addClass('ui-dialog-disabled');
+ } else {
+ uiDialog.removeClass('ui-dialog-disabled');
+ }
+ break;
case "draggable":
- (value
- ? this._makeDraggable()
- : this.uiDialog.draggable('destroy'));
+ if (value) {
+ self._makeDraggable();
+ } else {
+ uiDialog.draggable('destroy');
+ }
break;
case "height":
- this.uiDialog.height(value);
+ resize = true;
+ break;
+ case "maxHeight":
+ if (isResizable) {
+ uiDialog.resizable('option', 'maxHeight', value);
+ }
+ resize = true;
+ break;
+ case "maxWidth":
+ if (isResizable) {
+ uiDialog.resizable('option', 'maxWidth', value);
+ }
+ resize = true;
+ break;
+ case "minHeight":
+ if (isResizable) {
+ uiDialog.resizable('option', 'minHeight', value);
+ }
+ resize = true;
+ break;
+ case "minWidth":
+ if (isResizable) {
+ uiDialog.resizable('option', 'minWidth', value);
+ }
+ resize = true;
break;
case "position":
- this._position(value);
+ self._position(value);
break;
case "resizable":
- var uiDialog = this.uiDialog,
- isResizable = this.uiDialog.is(':data(resizable)');
-
// currently resizable, becoming non-resizable
- (isResizable && !value && uiDialog.resizable('destroy'));
+ if (isResizable && !value) {
+ uiDialog.resizable('destroy');
+ }
// currently resizable, changing handles
- (isResizable && typeof value == 'string' &&
- uiDialog.resizable('option', 'handles', value));
+ if (isResizable && typeof value === 'string') {
+ uiDialog.resizable('option', 'handles', value);
+ }
// currently non-resizable, becoming resizable
- (isResizable || this._makeResizable(value));
+ if (!isResizable && value !== false) {
+ self._makeResizable(value);
+ }
break;
case "title":
- $(".ui-dialog-title", this.uiDialogTitlebar).html(value || '&nbsp;');
+ // convert whatever was passed in o a string, for html() to not throw up
+ $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
break;
case "width":
- this.uiDialog.width(value);
+ resize = true;
break;
}
- $.widget.prototype._setData.apply(this, arguments);
+ $.Widget.prototype._setOption.apply(self, arguments);
+ if (resize) {
+ self._size();
+ }
},
_size: function() {
/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
* divs will both have width and height set, so we need to reset them
*/
- var options = this.options;
+ var options = this.options,
+ nonContentHeight;
// reset content sizing
+ // hide for non content measurement because height: 0 doesn't work in IE quirks mode (see #4350)
this.element.css({
- height: 0,
+ width: 'auto',
minHeight: 0,
- width: 'auto'
+ height: 0
});
// reset wrapper sizing
// determine the height of all the non-content elements
- var nonContentHeight = this.uiDialog.css({
+ nonContentHeight = this.uiDialog.css({
height: 'auto',
width: options.width
})
.height();
this.element
- .css({
- minHeight: Math.max(options.minHeight - nonContentHeight, 0),
- height: options.height == 'auto'
- ? 'auto'
- : Math.max(options.height - nonContentHeight, 0)
- });
+ .css(options.height === 'auto' ? {
+ minHeight: Math.max(options.minHeight - nonContentHeight, 0),
+ height: 'auto'
+ } : {
+ minHeight: 0,
+ height: Math.max(options.height - nonContentHeight, 0)
+ })
+ .show();
+
+ if (this.uiDialog.is(':data(resizable)')) {
+ this.uiDialog.resizable('option', 'minHeight', this._minHeight());
+ }
}
});
$.extend($.ui.dialog, {
- version: "1.7.2",
- defaults: {
- autoOpen: true,
- bgiframe: false,
- buttons: {},
- closeOnEscape: true,
- closeText: 'close',
- dialogClass: '',
- draggable: true,
- hide: null,
- height: 'auto',
- maxHeight: false,
- maxWidth: false,
- minHeight: 150,
- minWidth: 150,
- modal: false,
- position: 'center',
- resizable: true,
- show: null,
- stack: true,
- title: '',
- width: 300,
- zIndex: 1000
- },
-
- getter: 'isOpen',
+ version: "1.8.2",
uuid: 0,
maxZ: 0,
getTitleId: function($el) {
- return 'ui-dialog-title-' + ($el.attr('id') || ++this.uuid);
+ var id = $el.attr('id');
+ if (!id) {
+ this.uuid += 1;
+ id = this.uuid;
+ }
+ return 'ui-dialog-title-' + id;
},
overlay: function(dialog) {
@@ -7638,6 +9147,8 @@ $.extend($.ui.dialog, {
$.extend($.ui.dialog.overlay, {
instances: [],
+ // reuse old instances due to IE memory leak with alpha transparency (see #5185)
+ oldInstances: [],
maxZ: 0,
events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
function(event) { return event + '.dialog-overlay'; }).join(' '),
@@ -7650,43 +9161,50 @@ $.extend($.ui.dialog.overlay, {
// handle $(el).dialog().dialog('close') (see #4065)
if ($.ui.dialog.overlay.instances.length) {
$(document).bind($.ui.dialog.overlay.events, function(event) {
- var dialogZ = $(event.target).parents('.ui-dialog').css('zIndex') || 0;
- return (dialogZ > $.ui.dialog.overlay.maxZ);
+ // stop events if the z-index of the target is < the z-index of the overlay
+ return ($(event.target).zIndex() >= $.ui.dialog.overlay.maxZ);
});
}
}, 1);
// allow closing by pressing the escape key
$(document).bind('keydown.dialog-overlay', function(event) {
- (dialog.options.closeOnEscape && event.keyCode
- && event.keyCode == $.ui.keyCode.ESCAPE && dialog.close(event));
+ if (dialog.options.closeOnEscape && event.keyCode &&
+ event.keyCode === $.ui.keyCode.ESCAPE) {
+
+ dialog.close(event);
+ event.preventDefault();
+ }
});
// handle window resize
$(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
}
- var $el = $('<div></div>').appendTo(document.body)
- .addClass('ui-widget-overlay').css({
+ var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
+ .appendTo(document.body)
+ .css({
width: this.width(),
height: this.height()
});
- (dialog.options.bgiframe && $.fn.bgiframe && $el.bgiframe());
+ if ($.fn.bgiframe) {
+ $el.bgiframe();
+ }
this.instances.push($el);
return $el;
},
destroy: function($el) {
- this.instances.splice($.inArray(this.instances, $el), 1);
+ this.oldInstances.push(this.instances.splice($.inArray($el, this.instances), 1)[0]);
if (this.instances.length === 0) {
$([document, window]).unbind('.dialog-overlay');
}
$el.remove();
-
+
// adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
var maxZ = 0;
$.each(this.instances, function() {
@@ -7696,13 +9214,15 @@ $.extend($.ui.dialog.overlay, {
},
height: function() {
+ var scrollHeight,
+ offsetHeight;
// handle IE 6
if ($.browser.msie && $.browser.version < 7) {
- var scrollHeight = Math.max(
+ scrollHeight = Math.max(
document.documentElement.scrollHeight,
document.body.scrollHeight
);
- var offsetHeight = Math.max(
+ offsetHeight = Math.max(
document.documentElement.offsetHeight,
document.body.offsetHeight
);
@@ -7719,13 +9239,15 @@ $.extend($.ui.dialog.overlay, {
},
width: function() {
+ var scrollWidth,
+ offsetWidth;
// handle IE 6
if ($.browser.msie && $.browser.version < 7) {
- var scrollWidth = Math.max(
+ scrollWidth = Math.max(
document.documentElement.scrollWidth,
document.body.scrollWidth
);
- var offsetWidth = Math.max(
+ offsetWidth = Math.max(
document.documentElement.offsetWidth,
document.body.offsetWidth
);
@@ -7771,30 +9293,262 @@ $.extend($.ui.dialog.overlay.prototype, {
}
});
-})(jQuery);
+}(jQuery));
/*
- * jQuery UI Progressbar 1.7.2
+ * jQuery UI Position 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * http://docs.jquery.com/UI/Position
+ */
+(function( $ ) {
+
+$.ui = $.ui || {};
+
+var horizontalPositions = /left|center|right/,
+ horizontalDefault = "center",
+ verticalPositions = /top|center|bottom/,
+ verticalDefault = "center",
+ _position = $.fn.position,
+ _offset = $.fn.offset;
+
+$.fn.position = function( options ) {
+ if ( !options || !options.of ) {
+ return _position.apply( this, arguments );
+ }
+
+ // make a copy, we don't want to modify arguments
+ options = $.extend( {}, options );
+
+ var target = $( options.of ),
+ collision = ( options.collision || "flip" ).split( " " ),
+ offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
+ targetWidth,
+ targetHeight,
+ basePosition;
+
+ if ( options.of.nodeType === 9 ) {
+ targetWidth = target.width();
+ targetHeight = target.height();
+ basePosition = { top: 0, left: 0 };
+ } else if ( options.of.scrollTo && options.of.document ) {
+ targetWidth = target.width();
+ targetHeight = target.height();
+ basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
+ } else if ( options.of.preventDefault ) {
+ // force left top to allow flipping
+ options.at = "left top";
+ targetWidth = targetHeight = 0;
+ basePosition = { top: options.of.pageY, left: options.of.pageX };
+ } else {
+ targetWidth = target.outerWidth();
+ targetHeight = target.outerHeight();
+ basePosition = target.offset();
+ }
+
+ // force my and at to have valid horizontal and veritcal positions
+ // if a value is missing or invalid, it will be converted to center
+ $.each( [ "my", "at" ], function() {
+ var pos = ( options[this] || "" ).split( " " );
+ if ( pos.length === 1) {
+ pos = horizontalPositions.test( pos[0] ) ?
+ pos.concat( [verticalDefault] ) :
+ verticalPositions.test( pos[0] ) ?
+ [ horizontalDefault ].concat( pos ) :
+ [ horizontalDefault, verticalDefault ];
+ }
+ pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : horizontalDefault;
+ pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : verticalDefault;
+ options[ this ] = pos;
+ });
+
+ // normalize collision option
+ if ( collision.length === 1 ) {
+ collision[ 1 ] = collision[ 0 ];
+ }
+
+ // normalize offset option
+ offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
+ if ( offset.length === 1 ) {
+ offset[ 1 ] = offset[ 0 ];
+ }
+ offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
+
+ if ( options.at[0] === "right" ) {
+ basePosition.left += targetWidth;
+ } else if (options.at[0] === horizontalDefault ) {
+ basePosition.left += targetWidth / 2;
+ }
+
+ if ( options.at[1] === "bottom" ) {
+ basePosition.top += targetHeight;
+ } else if ( options.at[1] === verticalDefault ) {
+ basePosition.top += targetHeight / 2;
+ }
+
+ basePosition.left += offset[ 0 ];
+ basePosition.top += offset[ 1 ];
+
+ return this.each(function() {
+ var elem = $( this ),
+ elemWidth = elem.outerWidth(),
+ elemHeight = elem.outerHeight(),
+ position = $.extend( {}, basePosition );
+
+ if ( options.my[0] === "right" ) {
+ position.left -= elemWidth;
+ } else if ( options.my[0] === horizontalDefault ) {
+ position.left -= elemWidth / 2;
+ }
+
+ if ( options.my[1] === "bottom" ) {
+ position.top -= elemHeight;
+ } else if ( options.my[1] === verticalDefault ) {
+ position.top -= elemHeight / 2;
+ }
+
+ // prevent fractions (see #5280)
+ position.left = parseInt( position.left );
+ position.top = parseInt( position.top );
+
+ $.each( [ "left", "top" ], function( i, dir ) {
+ if ( $.ui.position[ collision[i] ] ) {
+ $.ui.position[ collision[i] ][ dir ]( position, {
+ targetWidth: targetWidth,
+ targetHeight: targetHeight,
+ elemWidth: elemWidth,
+ elemHeight: elemHeight,
+ offset: offset,
+ my: options.my,
+ at: options.at
+ });
+ }
+ });
+
+ if ( $.fn.bgiframe ) {
+ elem.bgiframe();
+ }
+ elem.offset( $.extend( position, { using: options.using } ) );
+ });
+};
+
+$.ui.position = {
+ fit: {
+ left: function( position, data ) {
+ var win = $( window ),
+ over = position.left + data.elemWidth - win.width() - win.scrollLeft();
+ position.left = over > 0 ? position.left - over : Math.max( 0, position.left );
+ },
+ top: function( position, data ) {
+ var win = $( window ),
+ over = position.top + data.elemHeight - win.height() - win.scrollTop();
+ position.top = over > 0 ? position.top - over : Math.max( 0, position.top );
+ }
+ },
+
+ flip: {
+ left: function( position, data ) {
+ if ( data.at[0] === "center" ) {
+ return;
+ }
+ var win = $( window ),
+ over = position.left + data.elemWidth - win.width() - win.scrollLeft(),
+ myOffset = data.my[ 0 ] === "left" ?
+ -data.elemWidth :
+ data.my[ 0 ] === "right" ?
+ data.elemWidth :
+ 0,
+ offset = -2 * data.offset[ 0 ];
+ position.left += position.left < 0 ?
+ myOffset + data.targetWidth + offset :
+ over > 0 ?
+ myOffset - data.targetWidth + offset :
+ 0;
+ },
+ top: function( position, data ) {
+ if ( data.at[1] === "center" ) {
+ return;
+ }
+ var win = $( window ),
+ over = position.top + data.elemHeight - win.height() - win.scrollTop(),
+ myOffset = data.my[ 1 ] === "top" ?
+ -data.elemHeight :
+ data.my[ 1 ] === "bottom" ?
+ data.elemHeight :
+ 0,
+ atOffset = data.at[ 1 ] === "top" ?
+ data.targetHeight :
+ -data.targetHeight,
+ offset = -2 * data.offset[ 1 ];
+ position.top += position.top < 0 ?
+ myOffset + data.targetHeight + offset :
+ over > 0 ?
+ myOffset + atOffset + offset :
+ 0;
+ }
+ }
+};
+
+// offset setter from jQuery 1.4
+if ( !$.offset.setOffset ) {
+ $.offset.setOffset = function( elem, options ) {
+ // set position first, in-case top/left are set even on static elem
+ if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
+ elem.style.position = "relative";
+ }
+ var curElem = $( elem ),
+ curOffset = curElem.offset(),
+ curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0,
+ curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0,
+ props = {
+ top: (options.top - curOffset.top) + curTop,
+ left: (options.left - curOffset.left) + curLeft
+ };
+
+ if ( 'using' in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ };
+
+ $.fn.offset = function( options ) {
+ var elem = this[ 0 ];
+ if ( !elem || !elem.ownerDocument ) { return null; }
+ if ( options ) {
+ return this.each(function() {
+ $.offset.setOffset( this, options );
+ });
+ }
+ return _offset.call( this );
+ };
+}
+
+}( jQuery ));
+/*
+ * jQuery UI Progressbar 1.8.2
+ *
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Progressbar
*
* Depends:
- * ui.core.js
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
*/
-(function($) {
-
-$.widget("ui.progressbar", {
-
- _init: function() {
+(function( $ ) {
+$.widget( "ui.progressbar", {
+ options: {
+ value: 0
+ },
+ _create: function() {
this.element
- .addClass("ui-progressbar"
- + " ui-widget"
- + " ui-widget-content"
- + " ui-corner-all")
+ .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
.attr({
role: "progressbar",
"aria-valuemin": this._valueMin(),
@@ -7802,294 +9556,345 @@ $.widget("ui.progressbar", {
"aria-valuenow": this._value()
});
- this.valueDiv = $('<div class="ui-progressbar-value ui-widget-header ui-corner-left"></div>').appendTo(this.element);
+ this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
+ .appendTo( this.element );
this._refreshValue();
-
},
destroy: function() {
-
this.element
- .removeClass("ui-progressbar"
- + " ui-widget"
- + " ui-widget-content"
- + " ui-corner-all")
- .removeAttr("role")
- .removeAttr("aria-valuemin")
- .removeAttr("aria-valuemax")
- .removeAttr("aria-valuenow")
- .removeData("progressbar")
- .unbind(".progressbar");
+ .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-valuemin" )
+ .removeAttr( "aria-valuemax" )
+ .removeAttr( "aria-valuenow" );
this.valueDiv.remove();
- $.widget.prototype.destroy.apply(this, arguments);
-
+ $.Widget.prototype.destroy.apply( this, arguments );
},
- value: function(newValue) {
- if (newValue === undefined) {
+ value: function( newValue ) {
+ if ( newValue === undefined ) {
return this._value();
}
- this._setData('value', newValue);
+ this._setOption( "value", newValue );
return this;
},
- _setData: function(key, value) {
-
- switch (key) {
- case 'value':
+ _setOption: function( key, value ) {
+ switch ( key ) {
+ case "value":
this.options.value = value;
this._refreshValue();
- this._trigger('change', null, {});
+ this._trigger( "change" );
break;
}
- $.widget.prototype._setData.apply(this, arguments);
-
+ $.Widget.prototype._setOption.apply( this, arguments );
},
_value: function() {
-
var val = this.options.value;
- if (val < this._valueMin()) val = this._valueMin();
- if (val > this._valueMax()) val = this._valueMax();
+ // normalize invalid value
+ if ( typeof val !== "number" ) {
+ val = 0;
+ }
+ if ( val < this._valueMin() ) {
+ val = this._valueMin();
+ }
+ if ( val > this._valueMax() ) {
+ val = this._valueMax();
+ }
return val;
-
},
_valueMin: function() {
- var valueMin = 0;
- return valueMin;
+ return 0;
},
_valueMax: function() {
- var valueMax = 100;
- return valueMax;
+ return 100;
},
_refreshValue: function() {
var value = this.value();
- this.valueDiv[value == this._valueMax() ? 'addClass' : 'removeClass']("ui-corner-right");
- this.valueDiv.width(value + '%');
- this.element.attr("aria-valuenow", value);
+ this.valueDiv
+ [ value === this._valueMax() ? "addClass" : "removeClass"]( "ui-corner-right" )
+ .width( value + "%" );
+ this.element.attr( "aria-valuenow", value );
}
-
});
-$.extend($.ui.progressbar, {
- version: "1.7.2",
- defaults: {
- value: 0
- }
+$.extend( $.ui.progressbar, {
+ version: "1.8.2"
});
-})(jQuery);
+})( jQuery );
/*
- * jQuery UI Slider 1.7.2
+ * jQuery UI Slider 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Slider
*
* Depends:
- * ui.core.js
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
*/
-(function($) {
+(function( $ ) {
-$.widget("ui.slider", $.extend({}, $.ui.mouse, {
+// number of pages in a slider
+// (how many times can you page up/down to go through the whole range)
+var numPages = 5;
- _init: function() {
+$.widget( "ui.slider", $.ui.mouse, {
+
+ widgetEventPrefix: "slide",
+
+ options: {
+ animate: false,
+ distance: 0,
+ max: 100,
+ min: 0,
+ orientation: "horizontal",
+ range: false,
+ step: 1,
+ value: 0,
+ values: null
+ },
+
+ _create: function() {
+ var self = this,
+ o = this.options;
- var self = this, o = this.options;
this._keySliding = false;
+ this._mouseSliding = false;
+ this._animateOff = true;
this._handleIndex = null;
this._detectOrientation();
this._mouseInit();
this.element
- .addClass("ui-slider"
- + " ui-slider-" + this.orientation
- + " ui-widget"
- + " ui-widget-content"
- + " ui-corner-all");
+ .addClass( "ui-slider" +
+ " ui-slider-" + this.orientation +
+ " ui-widget" +
+ " ui-widget-content" +
+ " ui-corner-all" );
+
+ if ( o.disabled ) {
+ this.element.addClass( "ui-slider-disabled ui-disabled" );
+ }
this.range = $([]);
- if (o.range) {
-
- if (o.range === true) {
- this.range = $('<div></div>');
- if (!o.values) o.values = [this._valueMin(), this._valueMin()];
- if (o.values.length && o.values.length != 2) {
- o.values = [o.values[0], o.values[0]];
+ if ( o.range ) {
+ if ( o.range === true ) {
+ this.range = $( "<div></div>" );
+ if ( !o.values ) {
+ o.values = [ this._valueMin(), this._valueMin() ];
+ }
+ if ( o.values.length && o.values.length !== 2 ) {
+ o.values = [ o.values[0], o.values[0] ];
}
} else {
- this.range = $('<div></div>');
+ this.range = $( "<div></div>" );
}
this.range
- .appendTo(this.element)
- .addClass("ui-slider-range");
+ .appendTo( this.element )
+ .addClass( "ui-slider-range" );
- if (o.range == "min" || o.range == "max") {
- this.range.addClass("ui-slider-range-" + o.range);
+ if ( o.range === "min" || o.range === "max" ) {
+ this.range.addClass( "ui-slider-range-" + o.range );
}
// note: this isn't the most fittingly semantic framework class for this element,
// but worked best visually with a variety of themes
- this.range.addClass("ui-widget-header");
-
+ this.range.addClass( "ui-widget-header" );
}
- if ($(".ui-slider-handle", this.element).length == 0)
- $('<a href="#"></a>')
- .appendTo(this.element)
- .addClass("ui-slider-handle");
+ if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
+ $( "<a href='#'></a>" )
+ .appendTo( this.element )
+ .addClass( "ui-slider-handle" );
+ }
- if (o.values && o.values.length) {
- while ($(".ui-slider-handle", this.element).length < o.values.length)
- $('<a href="#"></a>')
- .appendTo(this.element)
- .addClass("ui-slider-handle");
+ if ( o.values && o.values.length ) {
+ while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
+ $( "<a href='#'></a>" )
+ .appendTo( this.element )
+ .addClass( "ui-slider-handle" );
+ }
}
- this.handles = $(".ui-slider-handle", this.element)
- .addClass("ui-state-default"
- + " ui-corner-all");
+ this.handles = $( ".ui-slider-handle", this.element )
+ .addClass( "ui-state-default" +
+ " ui-corner-all" );
- this.handle = this.handles.eq(0);
+ this.handle = this.handles.eq( 0 );
- this.handles.add(this.range).filter("a")
- .click(function(event) {
+ this.handles.add( this.range ).filter( "a" )
+ .click(function( event ) {
event.preventDefault();
})
.hover(function() {
- if (!o.disabled) {
- $(this).addClass('ui-state-hover');
+ if ( !o.disabled ) {
+ $( this ).addClass( "ui-state-hover" );
}
}, function() {
- $(this).removeClass('ui-state-hover');
+ $( this ).removeClass( "ui-state-hover" );
})
.focus(function() {
- if (!o.disabled) {
- $(".ui-slider .ui-state-focus").removeClass('ui-state-focus'); $(this).addClass('ui-state-focus');
+ if ( !o.disabled ) {
+ $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
+ $( this ).addClass( "ui-state-focus" );
} else {
- $(this).blur();
+ $( this ).blur();
}
})
.blur(function() {
- $(this).removeClass('ui-state-focus');
+ $( this ).removeClass( "ui-state-focus" );
});
- this.handles.each(function(i) {
- $(this).data("index.ui-slider-handle", i);
+ this.handles.each(function( i ) {
+ $( this ).data( "index.ui-slider-handle", i );
});
- this.handles.keydown(function(event) {
-
- var ret = true;
-
- var index = $(this).data("index.ui-slider-handle");
-
- if (self.options.disabled)
- return;
-
- switch (event.keyCode) {
- case $.ui.keyCode.HOME:
- case $.ui.keyCode.END:
- case $.ui.keyCode.UP:
- case $.ui.keyCode.RIGHT:
- case $.ui.keyCode.DOWN:
- case $.ui.keyCode.LEFT:
- ret = false;
- if (!self._keySliding) {
- self._keySliding = true;
- $(this).addClass("ui-state-active");
- self._start(event, index);
- }
- break;
- }
-
- var curVal, newVal, step = self._step();
- if (self.options.values && self.options.values.length) {
- curVal = newVal = self.values(index);
- } else {
- curVal = newVal = self.value();
- }
-
- switch (event.keyCode) {
- case $.ui.keyCode.HOME:
- newVal = self._valueMin();
- break;
- case $.ui.keyCode.END:
- newVal = self._valueMax();
- break;
- case $.ui.keyCode.UP:
- case $.ui.keyCode.RIGHT:
- if(curVal == self._valueMax()) return;
- newVal = curVal + step;
- break;
- case $.ui.keyCode.DOWN:
- case $.ui.keyCode.LEFT:
- if(curVal == self._valueMin()) return;
- newVal = curVal - step;
- break;
- }
-
- self._slide(event, index, newVal);
-
- return ret;
-
- }).keyup(function(event) {
-
- var index = $(this).data("index.ui-slider-handle");
-
- if (self._keySliding) {
- self._stop(event, index);
- self._change(event, index);
- self._keySliding = false;
- $(this).removeClass("ui-state-active");
- }
-
- });
+ this.handles
+ .keydown(function( event ) {
+ var ret = true,
+ index = $( this ).data( "index.ui-slider-handle" ),
+ allowed,
+ curVal,
+ newVal,
+ step;
+
+ if ( self.options.disabled ) {
+ return;
+ }
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.HOME:
+ case $.ui.keyCode.END:
+ case $.ui.keyCode.PAGE_UP:
+ case $.ui.keyCode.PAGE_DOWN:
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.RIGHT:
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.LEFT:
+ ret = false;
+ if ( !self._keySliding ) {
+ self._keySliding = true;
+ $( this ).addClass( "ui-state-active" );
+ allowed = self._start( event, index );
+ if ( allowed === false ) {
+ return;
+ }
+ }
+ break;
+ }
+
+ step = self.options.step;
+ if ( self.options.values && self.options.values.length ) {
+ curVal = newVal = self.values( index );
+ } else {
+ curVal = newVal = self.value();
+ }
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.HOME:
+ newVal = self._valueMin();
+ break;
+ case $.ui.keyCode.END:
+ newVal = self._valueMax();
+ break;
+ case $.ui.keyCode.PAGE_UP:
+ newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
+ break;
+ case $.ui.keyCode.PAGE_DOWN:
+ newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
+ break;
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.RIGHT:
+ if ( curVal === self._valueMax() ) {
+ return;
+ }
+ newVal = self._trimAlignValue( curVal + step );
+ break;
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.LEFT:
+ if ( curVal === self._valueMin() ) {
+ return;
+ }
+ newVal = self._trimAlignValue( curVal - step );
+ break;
+ }
+
+ self._slide( event, index, newVal );
+
+ return ret;
+
+ })
+ .keyup(function( event ) {
+ var index = $( this ).data( "index.ui-slider-handle" );
+
+ if ( self._keySliding ) {
+ self._keySliding = false;
+ self._stop( event, index );
+ self._change( event, index );
+ $( this ).removeClass( "ui-state-active" );
+ }
+
+ });
this._refreshValue();
+ this._animateOff = false;
},
destroy: function() {
-
this.handles.remove();
this.range.remove();
this.element
- .removeClass("ui-slider"
- + " ui-slider-horizontal"
- + " ui-slider-vertical"
- + " ui-slider-disabled"
- + " ui-widget"
- + " ui-widget-content"
- + " ui-corner-all")
- .removeData("slider")
- .unbind(".slider");
+ .removeClass( "ui-slider" +
+ " ui-slider-horizontal" +
+ " ui-slider-vertical" +
+ " ui-slider-disabled" +
+ " ui-widget" +
+ " ui-widget-content" +
+ " ui-corner-all" )
+ .removeData( "slider" )
+ .unbind( ".slider" );
this._mouseDestroy();
+ return this;
},
- _mouseCapture: function(event) {
+ _mouseCapture: function( event ) {
+ var o = this.options,
+ position,
+ normValue,
+ distance,
+ closestHandle,
+ self,
+ index,
+ allowed,
+ offset,
+ mouseOverHandle;
- var o = this.options;
-
- if (o.disabled)
+ if ( o.disabled ) {
return false;
+ }
this.elementSize = {
width: this.element.outerWidth(),
@@ -8097,16 +9902,15 @@ $.widget("ui.slider", $.extend({}, $.ui.mouse, {
};
this.elementOffset = this.element.offset();
- var position = { x: event.pageX, y: event.pageY };
- var normValue = this._normValueFromMouse(position);
-
- var distance = this._valueMax() - this._valueMin() + 1, closestHandle;
- var self = this, index;
- this.handles.each(function(i) {
- var thisDistance = Math.abs(normValue - self.values(i));
- if (distance > thisDistance) {
+ position = { x: event.pageX, y: event.pageY };
+ normValue = this._normValueFromMouse( position );
+ distance = this._valueMax() - this._valueMin() + 1;
+ self = this;
+ this.handles.each(function( i ) {
+ var thisDistance = Math.abs( normValue - self.values(i) );
+ if ( distance > thisDistance ) {
distance = thisDistance;
- closestHandle = $(this);
+ closestHandle = $( this );
index = i;
}
});
@@ -8114,362 +9918,456 @@ $.widget("ui.slider", $.extend({}, $.ui.mouse, {
// workaround for bug #3736 (if both handles of a range are at 0,
// the first is always used as the one with least distance,
// and moving it is obviously prevented by preventing negative ranges)
- if(o.range == true && this.values(1) == o.min) {
- closestHandle = $(this.handles[++index]);
+ if( o.range === true && this.values(1) === o.min ) {
+ index += 1;
+ closestHandle = $( this.handles[index] );
}
- this._start(event, index);
+ allowed = this._start( event, index );
+ if ( allowed === false ) {
+ return false;
+ }
+ this._mouseSliding = true;
self._handleIndex = index;
closestHandle
- .addClass("ui-state-active")
+ .addClass( "ui-state-active" )
.focus();
-
- var offset = closestHandle.offset();
- var mouseOverHandle = !$(event.target).parents().andSelf().is('.ui-slider-handle');
+
+ offset = closestHandle.offset();
+ mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
- left: event.pageX - offset.left - (closestHandle.width() / 2),
- top: event.pageY - offset.top
- - (closestHandle.height() / 2)
- - (parseInt(closestHandle.css('borderTopWidth'),10) || 0)
- - (parseInt(closestHandle.css('borderBottomWidth'),10) || 0)
- + (parseInt(closestHandle.css('marginTop'),10) || 0)
+ left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
+ top: event.pageY - offset.top -
+ ( closestHandle.height() / 2 ) -
+ ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
+ ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
+ ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
};
- normValue = this._normValueFromMouse(position);
- this._slide(event, index, normValue);
+ normValue = this._normValueFromMouse( position );
+ this._slide( event, index, normValue );
+ this._animateOff = true;
return true;
-
},
- _mouseStart: function(event) {
+ _mouseStart: function( event ) {
return true;
},
- _mouseDrag: function(event) {
-
- var position = { x: event.pageX, y: event.pageY };
- var normValue = this._normValueFromMouse(position);
-
- this._slide(event, this._handleIndex, normValue);
+ _mouseDrag: function( event ) {
+ var position = { x: event.pageX, y: event.pageY },
+ normValue = this._normValueFromMouse( position );
+
+ this._slide( event, this._handleIndex, normValue );
return false;
-
},
- _mouseStop: function(event) {
+ _mouseStop: function( event ) {
+ this.handles.removeClass( "ui-state-active" );
+ this._mouseSliding = false;
+
+ this._stop( event, this._handleIndex );
+ this._change( event, this._handleIndex );
- this.handles.removeClass("ui-state-active");
- this._stop(event, this._handleIndex);
- this._change(event, this._handleIndex);
this._handleIndex = null;
this._clickOffset = null;
+ this._animateOff = false;
return false;
-
},
-
+
_detectOrientation: function() {
- this.orientation = this.options.orientation == 'vertical' ? 'vertical' : 'horizontal';
+ this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
},
- _normValueFromMouse: function(position) {
+ _normValueFromMouse: function( position ) {
+ var pixelTotal,
+ pixelMouse,
+ percentMouse,
+ valueTotal,
+ valueMouse;
- var pixelTotal, pixelMouse;
- if ('horizontal' == this.orientation) {
+ if ( this.orientation === "horizontal" ) {
pixelTotal = this.elementSize.width;
- pixelMouse = position.x - this.elementOffset.left - (this._clickOffset ? this._clickOffset.left : 0);
+ pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
} else {
pixelTotal = this.elementSize.height;
- pixelMouse = position.y - this.elementOffset.top - (this._clickOffset ? this._clickOffset.top : 0);
+ pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
}
- var percentMouse = (pixelMouse / pixelTotal);
- if (percentMouse > 1) percentMouse = 1;
- if (percentMouse < 0) percentMouse = 0;
- if ('vertical' == this.orientation)
+ percentMouse = ( pixelMouse / pixelTotal );
+ if ( percentMouse > 1 ) {
+ percentMouse = 1;
+ }
+ if ( percentMouse < 0 ) {
+ percentMouse = 0;
+ }
+ if ( this.orientation === "vertical" ) {
percentMouse = 1 - percentMouse;
+ }
- var valueTotal = this._valueMax() - this._valueMin(),
- valueMouse = percentMouse * valueTotal,
- valueMouseModStep = valueMouse % this.options.step,
- normValue = this._valueMin() + valueMouse - valueMouseModStep;
-
- if (valueMouseModStep > (this.options.step / 2))
- normValue += this.options.step;
-
- // Since JavaScript has problems with large floats, round
- // the final value to 5 digits after the decimal point (see #4124)
- return parseFloat(normValue.toFixed(5));
+ valueTotal = this._valueMax() - this._valueMin();
+ valueMouse = this._valueMin() + percentMouse * valueTotal;
+ return this._trimAlignValue( valueMouse );
},
- _start: function(event, index) {
+ _start: function( event, index ) {
var uiHash = {
- handle: this.handles[index],
+ handle: this.handles[ index ],
value: this.value()
};
- if (this.options.values && this.options.values.length) {
- uiHash.value = this.values(index);
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
uiHash.values = this.values();
}
- this._trigger("start", event, uiHash);
+ return this._trigger( "start", event, uiHash );
},
- _slide: function(event, index, newVal) {
+ _slide: function( event, index, newVal ) {
+ var otherVal,
+ newValues,
+ allowed;
- var handle = this.handles[index];
+ if ( this.options.values && this.options.values.length ) {
+ otherVal = this.values( index ? 0 : 1 );
- if (this.options.values && this.options.values.length) {
-
- var otherVal = this.values(index ? 0 : 1);
-
- if ((this.options.values.length == 2 && this.options.range === true) &&
- ((index == 0 && newVal > otherVal) || (index == 1 && newVal < otherVal))){
- newVal = otherVal;
+ if ( ( this.options.values.length === 2 && this.options.range === true ) &&
+ ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
+ ) {
+ newVal = otherVal;
}
- if (newVal != this.values(index)) {
- var newValues = this.values();
- newValues[index] = newVal;
+ if ( newVal !== this.values( index ) ) {
+ newValues = this.values();
+ newValues[ index ] = newVal;
// A slide can be canceled by returning false from the slide callback
- var allowed = this._trigger("slide", event, {
- handle: this.handles[index],
+ allowed = this._trigger( "slide", event, {
+ handle: this.handles[ index ],
value: newVal,
values: newValues
- });
- var otherVal = this.values(index ? 0 : 1);
- if (allowed !== false) {
- this.values(index, newVal, ( event.type == 'mousedown' && this.options.animate ), true);
+ } );
+ otherVal = this.values( index ? 0 : 1 );
+ if ( allowed !== false ) {
+ this.values( index, newVal, true );
}
}
-
} else {
-
- if (newVal != this.value()) {
+ if ( newVal !== this.value() ) {
// A slide can be canceled by returning false from the slide callback
- var allowed = this._trigger("slide", event, {
- handle: this.handles[index],
+ allowed = this._trigger( "slide", event, {
+ handle: this.handles[ index ],
value: newVal
- });
- if (allowed !== false) {
- this._setData('value', newVal, ( event.type == 'mousedown' && this.options.animate ));
+ } );
+ if ( allowed !== false ) {
+ this.value( newVal );
}
-
}
-
}
-
},
- _stop: function(event, index) {
+ _stop: function( event, index ) {
var uiHash = {
- handle: this.handles[index],
+ handle: this.handles[ index ],
value: this.value()
};
- if (this.options.values && this.options.values.length) {
- uiHash.value = this.values(index);
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
uiHash.values = this.values();
}
- this._trigger("stop", event, uiHash);
+
+ this._trigger( "stop", event, uiHash );
},
- _change: function(event, index) {
- var uiHash = {
- handle: this.handles[index],
- value: this.value()
- };
- if (this.options.values && this.options.values.length) {
- uiHash.value = this.values(index);
- uiHash.values = this.values();
+ _change: function( event, index ) {
+ if ( !this._keySliding && !this._mouseSliding ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+
+ this._trigger( "change", event, uiHash );
}
- this._trigger("change", event, uiHash);
},
- value: function(newValue) {
-
- if (arguments.length) {
- this._setData("value", newValue);
- this._change(null, 0);
+ value: function( newValue ) {
+ if ( arguments.length ) {
+ this.options.value = this._trimAlignValue( newValue );
+ this._refreshValue();
+ this._change( null, 0 );
}
return this._value();
-
},
- values: function(index, newValue, animated, noPropagation) {
+ values: function( index, newValue ) {
+ var vals,
+ newValues,
+ i;
- if (arguments.length > 1) {
- this.options.values[index] = newValue;
- this._refreshValue(animated);
- if(!noPropagation) this._change(null, index);
+ if ( arguments.length > 1 ) {
+ this.options.values[ index ] = this._trimAlignValue( newValue );
+ this._refreshValue();
+ this._change( null, index );
}
- if (arguments.length) {
- if (this.options.values && this.options.values.length) {
- return this._values(index);
+ if ( arguments.length ) {
+ if ( $.isArray( arguments[ 0 ] ) ) {
+ vals = this.options.values;
+ newValues = arguments[ 0 ];
+ for ( i = 0; i < vals.length; i += 1 ) {
+ vals[ i ] = this._trimAlignValue( newValues[ i ] );
+ this._change( null, i );
+ }
+ this._refreshValue();
} else {
- return this.value();
+ if ( this.options.values && this.options.values.length ) {
+ return this._values( index );
+ } else {
+ return this.value();
+ }
}
} else {
return this._values();
}
-
},
- _setData: function(key, value, animated) {
+ _setOption: function( key, value ) {
+ var i,
+ valsLength = 0;
- $.widget.prototype._setData.apply(this, arguments);
+ if ( $.isArray( this.options.values ) ) {
+ valsLength = this.options.values.length;
+ }
- switch (key) {
- case 'disabled':
- if (value) {
- this.handles.filter(".ui-state-focus").blur();
- this.handles.removeClass("ui-state-hover");
- this.handles.attr("disabled", "disabled");
+ $.Widget.prototype._setOption.apply( this, arguments );
+
+ switch ( key ) {
+ case "disabled":
+ if ( value ) {
+ this.handles.filter( ".ui-state-focus" ).blur();
+ this.handles.removeClass( "ui-state-hover" );
+ this.handles.attr( "disabled", "disabled" );
+ this.element.addClass( "ui-disabled" );
} else {
- this.handles.removeAttr("disabled");
+ this.handles.removeAttr( "disabled" );
+ this.element.removeClass( "ui-disabled" );
}
- case 'orientation':
-
+ break;
+ case "orientation":
this._detectOrientation();
-
this.element
- .removeClass("ui-slider-horizontal ui-slider-vertical")
- .addClass("ui-slider-" + this.orientation);
- this._refreshValue(animated);
+ .removeClass( "ui-slider-horizontal ui-slider-vertical" )
+ .addClass( "ui-slider-" + this.orientation );
+ this._refreshValue();
+ break;
+ case "value":
+ this._animateOff = true;
+ this._refreshValue();
+ this._change( null, 0 );
+ this._animateOff = false;
break;
- case 'value':
- this._refreshValue(animated);
+ case "values":
+ this._animateOff = true;
+ this._refreshValue();
+ for ( i = 0; i < valsLength; i += 1 ) {
+ this._change( null, i );
+ }
+ this._animateOff = false;
break;
}
-
- },
-
- _step: function() {
- var step = this.options.step;
- return step;
},
+ //internal value getter
+ // _value() returns value trimmed by min and max, aligned by step
_value: function() {
-
var val = this.options.value;
- if (val < this._valueMin()) val = this._valueMin();
- if (val > this._valueMax()) val = this._valueMax();
+ val = this._trimAlignValue( val );
return val;
-
},
- _values: function(index) {
+ //internal values getter
+ // _values() returns array of values trimmed by min and max, aligned by step
+ // _values( index ) returns single value trimmed by min and max, aligned by step
+ _values: function( index ) {
+ var val,
+ vals,
+ i;
- if (arguments.length) {
- var val = this.options.values[index];
- if (val < this._valueMin()) val = this._valueMin();
- if (val > this._valueMax()) val = this._valueMax();
+ if ( arguments.length ) {
+ val = this.options.values[ index ];
+ val = this._trimAlignValue( val );
return val;
} else {
- return this.options.values;
+ // .slice() creates a copy of the array
+ // this copy gets trimmed by min and max and then returned
+ vals = this.options.values.slice();
+ for ( i = 0; i < vals.length; i+= 1) {
+ vals[ i ] = this._trimAlignValue( vals[ i ] );
+ }
+
+ return vals;
+ }
+ },
+
+ // returns the step-aligned value that val is closest to, between (inclusive) min and max
+ _trimAlignValue: function( val ) {
+ if ( val < this._valueMin() ) {
+ return this._valueMin();
+ }
+ if ( val > this._valueMax() ) {
+ return this._valueMax();
+ }
+ var step = ( this.options.step > 0 ) ? this.options.step : 1,
+ valModStep = val % step,
+ alignValue = val - valModStep;
+
+ if ( Math.abs(valModStep) * 2 >= step ) {
+ alignValue += ( valModStep > 0 ) ? step : ( -step );
}
+ // Since JavaScript has problems with large floats, round
+ // the final value to 5 digits after the decimal point (see #4124)
+ return parseFloat( alignValue.toFixed(5) );
},
_valueMin: function() {
- var valueMin = this.options.min;
- return valueMin;
+ return this.options.min;
},
_valueMax: function() {
- var valueMax = this.options.max;
- return valueMax;
+ return this.options.max;
},
-
- _refreshValue: function(animate) {
-
- var oRange = this.options.range, o = this.options, self = this;
-
- if (this.options.values && this.options.values.length) {
- var vp0, vp1;
- this.handles.each(function(i, j) {
- var valPercent = (self.values(i) - self._valueMin()) / (self._valueMax() - self._valueMin()) * 100;
- var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';
- $(this).stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);
- if (self.options.range === true) {
- if (self.orientation == 'horizontal') {
- (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ left: valPercent + '%' }, o.animate);
- (i == 1) && self.range[animate ? 'animate' : 'css']({ width: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
+
+ _refreshValue: function() {
+ var oRange = this.options.range,
+ o = this.options,
+ self = this,
+ animate = ( !this._animateOff ) ? o.animate : false,
+ valPercent,
+ _set = {},
+ lastValPercent,
+ value,
+ valueMin,
+ valueMax;
+
+ if ( this.options.values && this.options.values.length ) {
+ this.handles.each(function( i, j ) {
+ valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
+ _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+ $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+ if ( self.options.range === true ) {
+ if ( self.orientation === "horizontal" ) {
+ if ( i === 0 ) {
+ self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
+ }
+ if ( i === 1 ) {
+ self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
} else {
- (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ bottom: (valPercent) + '%' }, o.animate);
- (i == 1) && self.range[animate ? 'animate' : 'css']({ height: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
+ if ( i === 0 ) {
+ self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
+ }
+ if ( i === 1 ) {
+ self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
}
}
lastValPercent = valPercent;
});
} else {
- var value = this.value(),
- valueMin = this._valueMin(),
- valueMax = this._valueMax(),
- valPercent = valueMax != valueMin
- ? (value - valueMin) / (valueMax - valueMin) * 100
- : 0;
- var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';
- this.handle.stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);
-
- (oRange == "min") && (this.orientation == "horizontal") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ width: valPercent + '%' }, o.animate);
- (oRange == "max") && (this.orientation == "horizontal") && this.range[animate ? 'animate' : 'css']({ width: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
- (oRange == "min") && (this.orientation == "vertical") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ height: valPercent + '%' }, o.animate);
- (oRange == "max") && (this.orientation == "vertical") && this.range[animate ? 'animate' : 'css']({ height: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
+ value = this.value();
+ valueMin = this._valueMin();
+ valueMax = this._valueMax();
+ valPercent = ( valueMax !== valueMin ) ?
+ ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
+ 0;
+ _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+ this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+
+ if ( oRange === "min" && this.orientation === "horizontal" ) {
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
+ }
+ if ( oRange === "max" && this.orientation === "horizontal" ) {
+ this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ if ( oRange === "min" && this.orientation === "vertical" ) {
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
+ }
+ if ( oRange === "max" && this.orientation === "vertical" ) {
+ this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
}
-
}
-}));
+});
-$.extend($.ui.slider, {
- getter: "value values",
- version: "1.7.2",
- eventPrefix: "slide",
- defaults: {
- animate: false,
- delay: 0,
- distance: 0,
- max: 100,
- min: 0,
- orientation: 'horizontal',
- range: false,
- step: 1,
- value: 0,
- values: null
- }
+$.extend( $.ui.slider, {
+ version: "1.8.2"
});
-})(jQuery);
+}(jQuery));
/*
- * jQuery UI Tabs 1.7.2
+ * jQuery UI Tabs 1.8.2
*
- * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Tabs
*
* Depends:
- * ui.core.js
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
*/
(function($) {
-$.widget("ui.tabs", {
+var tabId = 0,
+ listId = 0;
- _init: function() {
- if (this.options.deselectable !== undefined) {
- this.options.collapsible = this.options.deselectable;
- }
+function getNextTabId() {
+ return ++tabId;
+}
+
+function getNextListId() {
+ return ++listId;
+}
+
+$.widget("ui.tabs", {
+ options: {
+ add: null,
+ ajaxOptions: null,
+ cache: false,
+ cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
+ collapsible: false,
+ disable: null,
+ disabled: [],
+ enable: null,
+ event: 'click',
+ fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
+ idPrefix: 'ui-tabs-',
+ load: null,
+ panelTemplate: '<div></div>',
+ remove: null,
+ select: null,
+ show: null,
+ spinner: '<em>Loading&#8230;</em>',
+ tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
+ },
+ _create: function() {
this._tabify(true);
},
- _setData: function(key, value) {
+ _setOption: function(key, value) {
if (key == 'selected') {
if (this.options.collapsible && value == this.options.selected) {
return;
@@ -8478,16 +10376,13 @@ $.widget("ui.tabs", {
}
else {
this.options[key] = value;
- if (key == 'deselectable') {
- this.options.collapsible = value;
- }
this._tabify();
}
},
_tabId: function(a) {
return a.title && a.title.replace(/\s/g, '_').replace(/[^A-Za-z0-9\-_:\.]/g, '') ||
- this.options.idPrefix + $.data(a);
+ this.options.idPrefix + getNextTabId();
},
_sanitizeSelector: function(hash) {
@@ -8495,7 +10390,7 @@ $.widget("ui.tabs", {
},
_cookie: function() {
- var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + $.data(this.list[0]));
+ var cookie = this.cookie || (this.cookie = this.options.cookie.name || 'ui-tabs-' + getNextListId());
return $.cookie.apply(null, [cookie].concat($.makeArray(arguments)));
},
@@ -8519,7 +10414,7 @@ $.widget("ui.tabs", {
_tabify: function(init) {
- this.list = this.element.children('ul:first');
+ this.list = this.element.find('ol,ul').eq(0);
this.lis = $('li:has(a[href])', this.list);
this.anchors = this.lis.map(function() { return $('a', this)[0]; });
this.panels = $([]);
@@ -8601,7 +10496,7 @@ $.widget("ui.tabs", {
if (typeof o.selected != 'number' && this.lis.filter('.ui-tabs-selected').length) {
o.selected = this.lis.index(this.lis.filter('.ui-tabs-selected'));
}
- o.selected = o.selected || 0;
+ o.selected = o.selected || (this.lis.length ? 0 : -1);
}
else if (o.selected === null) { // usage of null is deprecated, TODO remove in next release
o.selected = -1;
@@ -8633,7 +10528,7 @@ $.widget("ui.tabs", {
self.element.queue("tabs", function() {
self._trigger('show', null, self._ui(self.anchors[o.selected], self.panels[o.selected]));
});
-
+
this.load(o.selected);
}
@@ -8710,7 +10605,7 @@ $.widget("ui.tabs", {
// and prevent IE's ClearType bug...
function resetStyle($el, fx) {
$el.css({ display: '' });
- if ($.browser.msie && fx.opacity) {
+ if (!$.support.opacity && fx.opacity) {
$el[0].style.removeAttribute('filter');
}
}
@@ -8718,7 +10613,7 @@ $.widget("ui.tabs", {
// Show a tab...
var showTab = showFx ?
function(clicked, $show) {
- $(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');
+ $(clicked).closest('li').addClass('ui-tabs-selected ui-state-active');
$show.hide().removeClass('ui-tabs-hide') // avoid flicker that way
.animate(showFx, showFx.duration || 'normal', function() {
resetStyle($show, showFx);
@@ -8726,7 +10621,7 @@ $.widget("ui.tabs", {
});
} :
function(clicked, $show) {
- $(clicked).closest('li').removeClass('ui-state-default').addClass('ui-tabs-selected ui-state-active');
+ $(clicked).closest('li').addClass('ui-tabs-selected ui-state-active');
$show.removeClass('ui-tabs-hide');
self._trigger('show', null, self._ui(clicked, $show[0]));
};
@@ -8735,14 +10630,14 @@ $.widget("ui.tabs", {
var hideTab = hideFx ?
function(clicked, $hide) {
$hide.animate(hideFx, hideFx.duration || 'normal', function() {
- self.lis.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default');
+ self.lis.removeClass('ui-tabs-selected ui-state-active');
$hide.addClass('ui-tabs-hide');
resetStyle($hide, hideFx);
self.element.dequeue("tabs");
});
} :
function(clicked, $hide, $show) {
- self.lis.removeClass('ui-tabs-selected ui-state-active').addClass('ui-state-default');
+ self.lis.removeClass('ui-tabs-selected ui-state-active');
$hide.addClass('ui-tabs-hide');
self.element.dequeue("tabs");
};
@@ -8780,7 +10675,7 @@ $.widget("ui.tabs", {
self.element.queue("tabs", function() {
hideTab(el, $hide);
}).dequeue("tabs");
-
+
this.blur();
return false;
}
@@ -8788,13 +10683,13 @@ $.widget("ui.tabs", {
if (o.cookie) {
self._cookie(o.selected, o.cookie);
}
-
+
self.element.queue("tabs", function() {
showTab(el, $show);
});
self.load(self.anchors.index(this)); // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
-
+
this.blur();
return false;
}
@@ -8814,7 +10709,7 @@ $.widget("ui.tabs", {
self.element.queue("tabs", function() {
showTab(el, $show);
});
-
+
self.load(self.anchors.index(this));
}
else {
@@ -8840,7 +10735,7 @@ $.widget("ui.tabs", {
var o = this.options;
this.abort();
-
+
this.element.unbind('.tabs')
.removeClass('ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible')
.removeData('tabs');
@@ -8882,6 +10777,8 @@ $.widget("ui.tabs", {
if (o.cookie) {
this._cookie(null, o.cookie);
}
+
+ return this;
},
add: function(url, label, index) {
@@ -8917,17 +10814,19 @@ $.widget("ui.tabs", {
this._tabify();
if (this.anchors.length == 1) { // after tabify
+ o.selected = 0;
$li.addClass('ui-tabs-selected ui-state-active');
$panel.removeClass('ui-tabs-hide');
this.element.queue("tabs", function() {
self._trigger('show', null, self._ui(self.anchors[0], self.panels[0]));
});
-
+
this.load(0);
}
// callback
this._trigger('add', null, this._ui(this.anchors[index], this.panels[index]));
+ return this;
},
remove: function(index) {
@@ -8947,6 +10846,7 @@ $.widget("ui.tabs", {
// callback
this._trigger('remove', null, this._ui($li.find('a')[0], $panel[0]));
+ return this;
},
enable: function(index) {
@@ -8960,6 +10860,7 @@ $.widget("ui.tabs", {
// callback
this._trigger('enable', null, this._ui(this.anchors[index], this.panels[index]));
+ return this;
},
disable: function(index) {
@@ -8973,6 +10874,8 @@ $.widget("ui.tabs", {
// callback
this._trigger('disable', null, this._ui(this.anchors[index], this.panels[index]));
}
+
+ return this;
},
select: function(index) {
@@ -8987,6 +10890,7 @@ $.widget("ui.tabs", {
}
this.anchors.eq(index).trigger(this.options.event + '.tabs');
+ return this;
},
load: function(index) {
@@ -9026,11 +10930,28 @@ $.widget("ui.tabs", {
o.ajaxOptions.success(r, s);
}
catch (e) {}
+ },
+ error: function(xhr, s, e) {
+ // take care of tab labels
+ self._cleanup();
- // last, so that load event is fired before show...
- self.element.dequeue("tabs");
+ // callbacks
+ self._trigger('load', null, self._ui(self.anchors[index], self.panels[index]));
+ try {
+ // Passing index avoid a race condition when this method is
+ // called after the user has selected another tab.
+ // Pass the anchor that initiated this request allows
+ // loadError to manipulate the tab content panel via $(a.hash)
+ o.ajaxOptions.error(xhr, s, index, a);
+ }
+ catch (e) {}
}
}));
+
+ // last, so that load event is fired before show...
+ self.element.dequeue("tabs");
+
+ return this;
},
abort: function() {
@@ -9038,6 +10959,10 @@ $.widget("ui.tabs", {
this.element.queue([]);
this.panels.stop(false, true);
+ // "tabs" queue must not contain more than two elements,
+ // which are the callbacks for the latest clicked tab...
+ this.element.queue("tabs", this.element.queue("tabs").splice(-2, 2));
+
// terminate pending requests from other tabs
if (this.xhr) {
this.xhr.abort();
@@ -9046,11 +10971,12 @@ $.widget("ui.tabs", {
// take care of tab labels
this._cleanup();
-
+ return this;
},
url: function(index, url) {
this.anchors.eq(index).removeData('cache.tabs').data('load.tabs', url);
+ return this;
},
length: function() {
@@ -9060,21 +10986,7 @@ $.widget("ui.tabs", {
});
$.extend($.ui.tabs, {
- version: '1.7.2',
- getter: 'length',
- defaults: {
- ajaxOptions: null,
- cache: false,
- cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
- collapsible: false,
- disabled: [],
- event: 'click',
- fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
- idPrefix: 'ui-tabs-',
- panelTemplate: '<div></div>',
- spinner: '<em>Loading&#8230;</em>',
- tabTemplate: '<li><a href="#{href}"><span>#{label}</span></a></li>'
- }
+ version: '1.8.2'
});
/*
@@ -9089,19 +11001,19 @@ $.extend($.ui.tabs.prototype, {
rotate: function(ms, continuing) {
var self = this, o = this.options;
-
+
var rotate = self._rotate || (self._rotate = function(e) {
clearTimeout(self.rotation);
self.rotation = setTimeout(function() {
var t = o.selected;
self.select( ++t < self.anchors.length ? t : 0 );
}, ms);
-
+
if (e) {
e.stopPropagation();
}
});
-
+
var stop = self._unrotate || (self._unrotate = !continuing ?
function(e) {
if (e.clientX) { // in case of a true click
@@ -9127,6 +11039,8 @@ $.extend($.ui.tabs.prototype, {
delete this._rotate;
delete this._unrotate;
}
+
+ return this;
}
});
diff --git a/libs/jquery/original lib/jquery.blockUI.js b/libs/jquery/original lib/jquery.blockUI.js
index 71fad72d1a..2349452429 100644
--- a/libs/jquery/original lib/jquery.blockUI.js
+++ b/libs/jquery/original lib/jquery.blockUI.js
@@ -1,6 +1,6 @@
-/*
+/*!
* jQuery blockUI plugin
- * Version 2.14 (18-JAN-2009)
+ * Version 2.31 (06-JAN-2010)
* @requires jQuery v1.2.3 or later
*
* Examples at: http://malsup.com/jquery/block/
@@ -8,380 +8,470 @@
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
- *
+ *
* Thanks to Amir-Hossein Sobhi for some excellent contributions!
*/
;(function($) {
if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {
- alert('blockUI requires jQuery v1.2.3 or later! You are using v' + $.fn.jquery);
- return;
+ alert('blockUI requires jQuery v1.2.3 or later! You are using v' + $.fn.jquery);
+ return;
}
+$.fn._fadeIn = $.fn.fadeIn;
+
+var noOp = function() {};
+
+// this bit is to ensure we don't call setExpression when we shouldn't (with extra muscle to handle
+// retarded userAgent strings on Vista)
+var mode = document.documentMode || 0;
+var setExpr = $.browser.msie && (($.browser.version < 8 && !mode) || mode < 8);
+var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent) && !mode;
+
// global $ methods for blocking/unblocking the entire page
$.blockUI = function(opts) { install(window, opts); };
$.unblockUI = function(opts) { remove(window, opts); };
// convenience method for quick growl-like notifications (http://www.google.com/search?q=growl)
-$.growlUI = function(title, message, timeout) {
+$.growlUI = function(title, message, timeout, onClose) {
var $m = $('<div class="growlUI"></div>');
if (title) $m.append('<h1>'+title+'</h1>');
if (message) $m.append('<h2>'+message+'</h2>');
if (timeout == undefined) timeout = 3000;
- $.blockUI({
+ $.blockUI({
message: $m, fadeIn: 700, fadeOut: 1000, centerY: false,
timeout: timeout, showOverlay: false,
+ onUnblock: onClose,
css: $.blockUI.defaults.growlCSS
- });
+ });
};
// plugin method for blocking element content
$.fn.block = function(opts) {
- return this.each(function() {
- if ($.css(this,'position') == 'static')
- this.style.position = 'relative';
- if ($.browser.msie)
- this.style.zoom = 1; // force 'hasLayout'
- install(this, opts);
- });
+ return this.unblock({ fadeOut: 0 }).each(function() {
+ if ($.css(this,'position') == 'static')
+ this.style.position = 'relative';
+ if ($.browser.msie)
+ this.style.zoom = 1; // force 'hasLayout'
+ install(this, opts);
+ });
};
// plugin method for unblocking element content
$.fn.unblock = function(opts) {
- return this.each(function() {
- remove(this, opts);
- });
+ return this.each(function() {
+ remove(this, opts);
+ });
};
-$.blockUI.version = 2.14; // 2nd generation blocking at no extra cost!
+$.blockUI.version = 2.31; // 2nd generation blocking at no extra cost!
// override these in your code to change the default behavior and style
$.blockUI.defaults = {
- // message displayed when blocking (use null for no message)
- message: '<h1>Please wait...</h1>',
-
- // styles for the message when blocking; if you wish to disable
- // these and use an external stylesheet then do this in your code:
- // $.blockUI.defaults.css = {};
- css: {
- padding: 0,
- margin: 0,
- width: '30%',
- top: '40%',
- left: '35%',
- textAlign: 'center',
- color: '#000',
- border: '3px solid #aaa',
- backgroundColor:'#fff',
- cursor: 'wait'
- },
-
- // styles for the overlay
- overlayCSS: {
- backgroundColor: '#000',
- opacity: '0.6'
- },
+ // message displayed when blocking (use null for no message)
+ message: '<h1>Please wait...</h1>',
+
+ title: null, // title string; only used when theme == true
+ draggable: true, // only used when theme == true (requires jquery-ui.js to be loaded)
+
+ theme: false, // set to true to use with jQuery UI themes
+
+ // styles for the message when blocking; if you wish to disable
+ // these and use an external stylesheet then do this in your code:
+ // $.blockUI.defaults.css = {};
+ css: {
+ padding: 0,
+ margin: 0,
+ width: '30%',
+ top: '40%',
+ left: '35%',
+ textAlign: 'center',
+ color: '#000',
+ border: '3px solid #aaa',
+ backgroundColor:'#fff',
+ cursor: 'wait'
+ },
+
+ // minimal style set used when themes are used
+ themedCSS: {
+ width: '30%',
+ top: '40%',
+ left: '35%'
+ },
+
+ // styles for the overlay
+ overlayCSS: {
+ backgroundColor: '#000',
+ opacity: 0.6,
+ cursor: 'wait'
+ },
// styles applied when using $.growlUI
- growlCSS: {
- width: '350px',
- top: '10px',
- left: '',
- right: '10px',
- border: 'none',
- padding: '5px',
- opacity: '0.6',
- cursor: null,
- color: '#fff',
- backgroundColor: '#000',
- '-webkit-border-radius': '10px',
- '-moz-border-radius': '10px'
+ growlCSS: {
+ width: '350px',
+ top: '10px',
+ left: '',
+ right: '10px',
+ border: 'none',
+ padding: '5px',
+ opacity: 0.6,
+ cursor: 'default',
+ color: '#fff',
+ backgroundColor: '#000',
+ '-webkit-border-radius': '10px',
+ '-moz-border-radius': '10px'
},
-
- // z-index for the blocking overlay
- baseZ: 1000,
-
- // set these to true to have the message automatically centered
- centerX: true, // <-- only effects element blocking (page block controlled via css above)
- centerY: true,
-
- // allow body element to be stetched in ie6; this makes blocking look better
- // on "short" pages. disable if you wish to prevent changes to the body height
- allowBodyStretch: true,
-
- // be default blockUI will supress tab navigation from leaving blocking content;
- constrainTabKey: true,
-
- // fadeIn time in millis; set to 0 to disable fadeIn on block
- fadeIn: 200,
-
- // fadeOut time in millis; set to 0 to disable fadeOut on unblock
- fadeOut: 400,
-
+
+ // IE issues: 'about:blank' fails on HTTPS and javascript:false is s-l-o-w
+ // (hat tip to Jorge H. N. de Vasconcelos)
+ iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank',
+
+ // force usage of iframe in non-IE browsers (handy for blocking applets)
+ forceIframe: false,
+
+ // z-index for the blocking overlay
+ baseZ: 1000,
+
+ // set these to true to have the message automatically centered
+ centerX: true, // <-- only effects element blocking (page block controlled via css above)
+ centerY: true,
+
+ // allow body element to be stetched in ie6; this makes blocking look better
+ // on "short" pages. disable if you wish to prevent changes to the body height
+ allowBodyStretch: true,
+
+ // enable if you want key and mouse events to be disabled for content that is blocked
+ bindEvents: true,
+
+ // be default blockUI will supress tab navigation from leaving blocking content
+ // (if bindEvents is true)
+ constrainTabKey: true,
+
+ // fadeIn time in millis; set to 0 to disable fadeIn on block
+ fadeIn: 200,
+
+ // fadeOut time in millis; set to 0 to disable fadeOut on unblock
+ fadeOut: 400,
+
// time in millis to wait before auto-unblocking; set to 0 to disable auto-unblock
timeout: 0,
// disable if you don't want to show the overlay
showOverlay: true,
- // if true, focus will be placed in the first available input field when
- // page blocking
- focusInput: true,
-
- // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
- applyPlatformOpacityRules: true,
-
- // callback method invoked when unblocking has completed; the callback is
- // passed the element that has been unblocked (which is the window object for page
- // blocks) and the options that were passed to the unblock call:
- // onUnblock(element, options)
- onUnblock: null,
-
- // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
- quirksmodeOffsetHack: 4
+ // if true, focus will be placed in the first available input field when
+ // page blocking
+ focusInput: true,
+
+ // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
+ applyPlatformOpacityRules: true,
+
+ // callback method invoked when fadeIn has completed and blocking message is visible
+ onBlock: null,
+
+ // callback method invoked when unblocking has completed; the callback is
+ // passed the element that has been unblocked (which is the window object for page
+ // blocks) and the options that were passed to the unblock call:
+ // onUnblock(element, options)
+ onUnblock: null,
+
+ // don't ask; if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493
+ quirksmodeOffsetHack: 4
};
// private data and functions follow...
-var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent);
var pageBlock = null;
var pageBlockEls = [];
function install(el, opts) {
- var full = (el == window);
- var msg = opts && opts.message !== undefined ? opts.message : undefined;
- opts = $.extend({}, $.blockUI.defaults, opts || {});
- opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
- var css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
- msg = msg === undefined ? opts.message : msg;
-
- // remove the current block (if there is one)
- if (full && pageBlock)
- remove(window, {fadeOut:0});
-
- // if an existing element is being used as the blocking content then we capture
- // its current place in the DOM (and current display style) so we can restore
- // it when we unblock
- if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
- var node = msg.jquery ? msg[0] : msg;
- var data = {};
- $(el).data('blockUI.history', data);
- data.el = node;
- data.parent = node.parentNode;
- data.display = node.style.display;
- data.position = node.style.position;
+ var full = (el == window);
+ var msg = opts && opts.message !== undefined ? opts.message : undefined;
+ opts = $.extend({}, $.blockUI.defaults, opts || {});
+ opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
+ var css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
+ var themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
+ msg = msg === undefined ? opts.message : msg;
+
+ // remove the current block (if there is one)
+ if (full && pageBlock)
+ remove(window, {fadeOut:0});
+
+ // if an existing element is being used as the blocking content then we capture
+ // its current place in the DOM (and current display style) so we can restore
+ // it when we unblock
+ if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
+ var node = msg.jquery ? msg[0] : msg;
+ var data = {};
+ $(el).data('blockUI.history', data);
+ data.el = node;
+ data.parent = node.parentNode;
+ data.display = node.style.display;
+ data.position = node.style.position;
if (data.parent)
data.parent.removeChild(node);
- }
-
- var z = opts.baseZ;
-
- // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
- // layer1 is the iframe layer which is used to supress bleed through of underlying content
- // layer2 is the overlay layer which has opacity and a wait cursor
- // layer3 is the message content that is displayed while blocking
-
- var lyr1 = ($.browser.msie) ? $('<iframe class="blockUI" style="z-index:'+ z++ +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="javascript:false;"></iframe>')
- : $('<div class="blockUI" style="display:none"></div>');
- var lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ z++ +';display:none;cursor:wait;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
- var lyr3 = full ? $('<div class="blockUI blockMsg blockPage" style="z-index:'+z+';display:none;position:fixed"></div>')
- : $('<div class="blockUI blockMsg blockElement" style="z-index:'+z+';display:none;position:absolute"></div>');
-
- // if we have a message, style it
- if (msg)
- lyr3.css(css);
-
- // style the overlay
- if (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform)))
- lyr2.css(opts.overlayCSS);
- lyr2.css('position', full ? 'fixed' : 'absolute');
-
- // make iframe layer transparent in IE
- if ($.browser.msie)
- lyr1.css('opacity','0.0');
-
- $([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
-
- // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
- var expr = $.browser.msie && (!$.boxModel || $('object,embed', full ? null : el).length > 0);
- if (ie6 || expr) {
- // give body 100% height
- if (full && opts.allowBodyStretch && $.boxModel)
- $('html,body').css('height','100%');
-
- // fix ie6 issue when blocked element has a border width
- if ((ie6 || !$.boxModel) && !full) {
- var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
- var fixT = t ? '(0 - '+t+')' : 0;
- var fixL = l ? '(0 - '+l+')' : 0;
- }
-
- // simulate fixed position
- $.each([lyr1,lyr2,lyr3], function(i,o) {
- var s = o[0].style;
- s.position = 'absolute';
- if (i < 2) {
- full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"')
- : s.setExpression('height','this.parentNode.offsetHeight + "px"');
- full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
- : s.setExpression('width','this.parentNode.offsetWidth + "px"');
- if (fixL) s.setExpression('left', fixL);
- if (fixT) s.setExpression('top', fixT);
- }
- else if (opts.centerY) {
- if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
- s.marginTop = 0;
- }
+ }
+
+ var z = opts.baseZ;
+
+ // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
+ // layer1 is the iframe layer which is used to supress bleed through of underlying content
+ // layer2 is the overlay layer which has opacity and a wait cursor (by default)
+ // layer3 is the message content that is displayed while blocking
+
+ var lyr1 = ($.browser.msie || opts.forceIframe)
+ ? $('<iframe class="blockUI" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+opts.iframeSrc+'"></iframe>')
+ : $('<div class="blockUI" style="display:none"></div>');
+ var lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ (z++) +';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
+
+ var lyr3;
+ if (opts.theme && full) {
+ var s = '<div class="blockUI blockMsg blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+z+';display:none;position:fixed">' +
+ '<div class="ui-widget-header ui-dialog-titlebar blockTitle">'+(opts.title || '&nbsp;')+'</div>' +
+ '<div class="ui-widget-content ui-dialog-content"></div>' +
+ '</div>';
+ lyr3 = $(s);
+ }
+ else {
+ lyr3 = full ? $('<div class="blockUI blockMsg blockPage" style="z-index:'+z+';display:none;position:fixed"></div>')
+ : $('<div class="blockUI blockMsg blockElement" style="z-index:'+z+';display:none;position:absolute"></div>');
+ }
+
+ // if we have a message, style it
+ if (msg) {
+ if (opts.theme) {
+ lyr3.css(themedCSS);
+ lyr3.addClass('ui-widget-content');
+ }
+ else
+ lyr3.css(css);
+ }
+
+ // style the overlay
+ if (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform)))
+ lyr2.css(opts.overlayCSS);
+ lyr2.css('position', full ? 'fixed' : 'absolute');
+
+ // make iframe layer transparent in IE
+ if ($.browser.msie || opts.forceIframe)
+ lyr1.css('opacity',0.0);
+
+ //$([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
+ var layers = [lyr1,lyr2,lyr3], $par = full ? $('body') : $(el);
+ $.each(layers, function() {
+ this.appendTo($par);
+ });
+
+ if (opts.theme && opts.draggable && $.fn.draggable) {
+ lyr3.draggable({
+ handle: '.ui-dialog-titlebar',
+ cancel: 'li'
+ });
+ }
+
+ // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
+ var expr = setExpr && (!$.boxModel || $('object,embed', full ? null : el).length > 0);
+ if (ie6 || expr) {
+ // give body 100% height
+ if (full && opts.allowBodyStretch && $.boxModel)
+ $('html,body').css('height','100%');
+
+ // fix ie6 issue when blocked element has a border width
+ if ((ie6 || !$.boxModel) && !full) {
+ var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
+ var fixT = t ? '(0 - '+t+')' : 0;
+ var fixL = l ? '(0 - '+l+')' : 0;
+ }
+
+ // simulate fixed position
+ $.each([lyr1,lyr2,lyr3], function(i,o) {
+ var s = o[0].style;
+ s.position = 'absolute';
+ if (i < 2) {
+ full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"')
+ : s.setExpression('height','this.parentNode.offsetHeight + "px"');
+ full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
+ : s.setExpression('width','this.parentNode.offsetWidth + "px"');
+ if (fixL) s.setExpression('left', fixL);
+ if (fixT) s.setExpression('top', fixT);
+ }
+ else if (opts.centerY) {
+ if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
+ s.marginTop = 0;
+ }
else if (!opts.centerY && full) {
var top = (opts.css && opts.css.top) ? parseInt(opts.css.top) : 0;
var expression = '((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + '+top+') + "px"';
- s.setExpression('top',expression);
+ s.setExpression('top',expression);
}
- });
- }
-
- // show the message
- lyr3.append(msg);//.show();
- if (msg && (msg.jquery || msg.nodeType))
- $(msg).show();
+ });
+ }
+ // show the message
+ if (msg) {
+ if (opts.theme)
+ lyr3.find('.ui-widget-content').append(msg);
+ else
+ lyr3.append(msg);
+ if (msg.jquery || msg.nodeType)
+ $(msg).show();
+ }
+
+ if (($.browser.msie || opts.forceIframe) && opts.showOverlay)
+ lyr1.show(); // opacity is zero
if (opts.fadeIn) {
- if ($.browser.msie && opts.showOverlay)
- lyr1.fadeIn(opts.fadeIn);
+ var cb = opts.onBlock ? opts.onBlock : noOp;
+ var cb1 = (opts.showOverlay && !msg) ? cb : noOp;
+ var cb2 = msg ? cb : noOp;
if (opts.showOverlay)
- lyr2.fadeIn(opts.fadeIn);
- lyr3.fadeIn(opts.fadeIn);
+ lyr2._fadeIn(opts.fadeIn, cb1);
+ if (msg)
+ lyr3._fadeIn(opts.fadeIn, cb2);
}
else {
- if ($.browser.msie && opts.showOverlay)
- lyr1.show();
if (opts.showOverlay)
lyr2.show();
- lyr3.show();
+ if (msg)
+ lyr3.show();
+ if (opts.onBlock)
+ opts.onBlock();
}
- // bind key and mouse events
- bind(1, el, opts);
-
- if (full) {
- pageBlock = lyr3[0];
- pageBlockEls = $(':input:enabled:visible',pageBlock);
- if (opts.focusInput)
- setTimeout(focus, 20);
- }
- else
- center(lyr3[0], opts.centerX, opts.centerY);
+ // bind key and mouse events
+ bind(1, el, opts);
+
+ if (full) {
+ pageBlock = lyr3[0];
+ pageBlockEls = $(':input:enabled:visible',pageBlock);
+ if (opts.focusInput)
+ setTimeout(focus, 20);
+ }
+ else
+ center(lyr3[0], opts.centerX, opts.centerY);
if (opts.timeout) {
// auto-unblock
- setTimeout(function() {
+ var to = setTimeout(function() {
full ? $.unblockUI(opts) : $(el).unblock(opts);
}, opts.timeout);
+ $(el).data('blockUI.timeout', to);
}
};
// remove the block
function remove(el, opts) {
- var full = el == window;
- var data = $(el).data('blockUI.history');
- opts = $.extend({}, $.blockUI.defaults, opts || {});
- bind(0, el, opts); // unbind events
- var els = full ? $('body').children().filter('.blockUI') : $('.blockUI', el);
-
- if (full)
- pageBlock = pageBlockEls = null;
-
- if (opts.fadeOut) {
- els.fadeOut(opts.fadeOut);
- setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
- }
- else
- reset(els, data, opts, el);
+ var full = (el == window);
+ var $el = $(el);
+ var data = $el.data('blockUI.history');
+ var to = $el.data('blockUI.timeout');
+ if (to) {
+ clearTimeout(to);
+ $el.removeData('blockUI.timeout');
+ }
+ opts = $.extend({}, $.blockUI.defaults, opts || {});
+ bind(0, el, opts); // unbind events
+
+ var els;
+ if (full) // crazy selector to handle odd field errors in ie6/7
+ els = $('body').children().filter('.blockUI').add('body > .blockUI');
+ else
+ els = $('.blockUI', el);
+
+ if (full)
+ pageBlock = pageBlockEls = null;
+
+ if (opts.fadeOut) {
+ els.fadeOut(opts.fadeOut);
+ setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
+ }
+ else
+ reset(els, data, opts, el);
};
// move blocking element back into the DOM where it started
function reset(els,data,opts,el) {
- els.each(function(i,o) {
- // remove via DOM calls so we don't lose event handlers
- if (this.parentNode)
- this.parentNode.removeChild(this);
- });
-
- if (data && data.el) {
- data.el.style.display = data.display;
- data.el.style.position = data.position;
+ els.each(function(i,o) {
+ // remove via DOM calls so we don't lose event handlers
+ if (this.parentNode)
+ this.parentNode.removeChild(this);
+ });
+
+ if (data && data.el) {
+ data.el.style.display = data.display;
+ data.el.style.position = data.position;
if (data.parent)
data.parent.appendChild(data.el);
- $(data.el).removeData('blockUI.history');
- }
+ $(el).removeData('blockUI.history');
+ }
- if (typeof opts.onUnblock == 'function')
- opts.onUnblock(el,opts);
+ if (typeof opts.onUnblock == 'function')
+ opts.onUnblock(el,opts);
};
// bind/unbind the handler
function bind(b, el, opts) {
- var full = el == window, $el = $(el);
-
- // don't bother unbinding if there is nothing to unbind
- if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
- return;
- if (!full)
- $el.data('blockUI.isBlocked', b);
-
- if (b && !opts.showOverlay) // don't prevent events when overlay not in use
+ var full = el == window, $el = $(el);
+
+ // don't bother unbinding if there is nothing to unbind
+ if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked')))
return;
+ if (!full)
+ $el.data('blockUI.isBlocked', b);
- // bind anchors and inputs for mouse and key events
- var events = 'mousedown mouseup keydown keypress';
- b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler);
+ // don't bind events when overlay is not in use or if bindEvents is false
+ if (!opts.bindEvents || (b && !opts.showOverlay))
+ return;
+
+ // bind anchors and inputs for mouse and key events
+ var events = 'mousedown mouseup keydown keypress';
+ b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler);
// former impl...
-// var $e = $('a,:input');
-// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
+// var $e = $('a,:input');
+// b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
};
// event handler to suppress keyboard/mouse events when blocking
function handler(e) {
- // allow tab navigation (conditionally)
- if (e.keyCode && e.keyCode == 9) {
- if (pageBlock && e.data.constrainTabKey) {
- var els = pageBlockEls;
- var fwd = !e.shiftKey && e.target == els[els.length-1];
- var back = e.shiftKey && e.target == els[0];
- if (fwd || back) {
- setTimeout(function(){focus(back)},10);
- return false;
- }
- }
- }
- // allow events within the message content
- if ($(e.target).parents('div.blockMsg').length > 0)
- return true;
-
- // allow events for content that is not being blocked
- return $(e.target).parents().children().filter('div.blockUI').length == 0;
+ // allow tab navigation (conditionally)
+ if (e.keyCode && e.keyCode == 9) {
+ if (pageBlock && e.data.constrainTabKey) {
+ var els = pageBlockEls;
+ var fwd = !e.shiftKey && e.target == els[els.length-1];
+ var back = e.shiftKey && e.target == els[0];
+ if (fwd || back) {
+ setTimeout(function(){focus(back)},10);
+ return false;
+ }
+ }
+ }
+ // allow events within the message content
+ if ($(e.target).parents('div.blockMsg').length > 0)
+ return true;
+
+ // allow events for content that is not being blocked
+ return $(e.target).parents().children().filter('div.blockUI').length == 0;
};
function focus(back) {
- if (!pageBlockEls)
- return;
- var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
- if (e)
- e.focus();
+ if (!pageBlockEls)
+ return;
+ var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
+ if (e)
+ e.focus();
};
function center(el, x, y) {
- var p = el.parentNode, s = el.style;
- var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
- var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
- if (x) s.left = l > 0 ? (l+'px') : '0';
- if (y) s.top = t > 0 ? (t+'px') : '0';
+ var p = el.parentNode, s = el.style;
+ var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
+ var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
+ if (x) s.left = l > 0 ? (l+'px') : '0';
+ if (y) s.top = t > 0 ? (t+'px') : '0';
};
-function sz(el, p) {
- return parseInt($.css(el,p))||0;
+function sz(el, p) {
+ return parseInt($.css(el,p))||0;
};
})(jQuery);
diff --git a/libs/jquery/original lib/jquery.js b/libs/jquery/original lib/jquery.js
index e3a442aa95..fff6776433 100644
--- a/libs/jquery/original lib/jquery.js
+++ b/libs/jquery/original lib/jquery.js
@@ -1,978 +1,1462 @@
/*!
- * jQuery JavaScript Library v1.3.2
+ * jQuery JavaScript Library v1.4.2
* http://jquery.com/
*
- * Copyright (c) 2009 John Resig
- * Dual licensed under the MIT and GPL licenses.
- * http://docs.jquery.com/License
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
*
- * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
- * Revision: 6246
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Sat Feb 13 22:33:48 2010 -0500
*/
-(function(){
+(function( window, undefined ) {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context );
+ },
-var
- // Will speed up references to window, and allows munging its name.
- window = this,
- // Will speed up references to undefined, and allows munging its name.
- undefined,
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
+
// Map over the $ in case of overwrite
_$ = window.$,
- jQuery = window.jQuery = window.$ = function( selector, context ) {
- // The jQuery object is actually just the init constructor 'enhanced'
- return new jQuery.fn.init( selector, context );
- },
+ // Use the correct document accordingly with window argument (sandbox)
+ document = window.document,
+
+ // A central reference to the root jQuery(document)
+ rootjQuery,
// A simple way to check for HTML strings or ID strings
// (both of which we optimize for)
- quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
+ quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,
+
// Is it a simple selector
- isSimple = /^.[^:#\[\.,]*$/;
+ isSimple = /^.[^:#\[\.,]*$/,
+
+ // Check if a string has a non-whitespace character in it
+ rnotwhite = /\S/,
+
+ // Used for trimming whitespace
+ rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+ // Keep a UserAgent string for use with jQuery.browser
+ userAgent = navigator.userAgent,
+
+ // For matching the engine and version of the browser
+ browserMatch,
+
+ // Has the ready events already been bound?
+ readyBound = false,
+
+ // The functions to execute on DOM ready
+ readyList = [],
+
+ // The ready event handler
+ DOMContentLoaded,
+
+ // Save a reference to some core methods
+ toString = Object.prototype.toString,
+ hasOwnProperty = Object.prototype.hasOwnProperty,
+ push = Array.prototype.push,
+ slice = Array.prototype.slice,
+ indexOf = Array.prototype.indexOf;
jQuery.fn = jQuery.prototype = {
init: function( selector, context ) {
- // Make sure that a selection was provided
- selector = selector || document;
+ var match, elem, ret, doc;
+
+ // Handle $(""), $(null), or $(undefined)
+ if ( !selector ) {
+ return this;
+ }
// Handle $(DOMElement)
if ( selector.nodeType ) {
- this[0] = selector;
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // The body element only exists once, optimize finding it
+ if ( selector === "body" && !context ) {
+ this.context = document;
+ this[0] = document.body;
+ this.selector = "body";
this.length = 1;
- this.context = selector;
return this;
}
+
// Handle HTML strings
if ( typeof selector === "string" ) {
// Are we dealing with HTML string or an ID?
- var match = quickExpr.exec( selector );
+ match = quickExpr.exec( selector );
// Verify a match, and that no context was specified for #id
if ( match && (match[1] || !context) ) {
// HANDLE: $(html) -> $(array)
- if ( match[1] )
- selector = jQuery.clean( [ match[1] ], context );
+ if ( match[1] ) {
+ doc = (context ? context.ownerDocument || context : document);
+
+ // If a single string is passed in and it's a single tag
+ // just do a createElement and skip the rest
+ ret = rsingleTag.exec( selector );
+
+ if ( ret ) {
+ if ( jQuery.isPlainObject( context ) ) {
+ selector = [ document.createElement( ret[1] ) ];
+ jQuery.fn.attr.call( selector, context, true );
+
+ } else {
+ selector = [ doc.createElement( ret[1] ) ];
+ }
+ } else {
+ ret = buildFragment( [ match[1] ], [ doc ] );
+ selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
+ }
+
+ return jQuery.merge( this, selector );
+
// HANDLE: $("#id")
- else {
- var elem = document.getElementById( match[3] );
-
- // Handle the case where IE and Opera return items
- // by name instead of ID
- if ( elem && elem.id != match[3] )
- return jQuery().find( selector );
-
- // Otherwise, we inject the element directly into the jQuery object
- var ret = jQuery( elem || [] );
- ret.context = document;
- ret.selector = selector;
- return ret;
+ } else {
+ elem = document.getElementById( match[2] );
+
+ if ( elem ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
}
- // HANDLE: $(expr, [context])
- // (which is just equivalent to: $(content).find(expr)
- } else
+ // HANDLE: $("TAG")
+ } else if ( !context && /^\w+$/.test( selector ) ) {
+ this.selector = selector;
+ this.context = document;
+ selector = document.getElementsByTagName( selector );
+ return jQuery.merge( this, selector );
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return (context || rootjQuery).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
return jQuery( context ).find( selector );
+ }
// HANDLE: $(function)
// Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) )
- return jQuery( document ).ready( selector );
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
- // Make sure that old selector state is passed along
- if ( selector.selector && selector.context ) {
+ if (selector.selector !== undefined) {
this.selector = selector.selector;
this.context = selector.context;
}
- return this.setArray(jQuery.isArray( selector ) ?
- selector :
- jQuery.makeArray(selector));
+ return jQuery.makeArray( selector, this );
},
// Start with an empty selector
selector: "",
// The current version of jQuery being used
- jquery: "1.3.2",
+ jquery: "1.4.2",
+
+ // The default length of a jQuery object is 0
+ length: 0,
// The number of elements contained in the matched element set
size: function() {
return this.length;
},
+ toArray: function() {
+ return slice.call( this, 0 );
+ },
+
// Get the Nth element in the matched element set OR
// Get the whole matched element set as a clean array
get: function( num ) {
- return num === undefined ?
+ return num == null ?
// Return a 'clean' array
- Array.prototype.slice.call( this ) :
+ this.toArray() :
// Return just the object
- this[ num ];
+ ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
},
// Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function( elems, name, selector ) {
// Build a new jQuery matched element set
- var ret = jQuery( elems );
+ var ret = jQuery();
+
+ if ( jQuery.isArray( elems ) ) {
+ push.apply( ret, elems );
+
+ } else {
+ jQuery.merge( ret, elems );
+ }
// Add the old object onto the stack (as a reference)
ret.prevObject = this;
ret.context = this.context;
- if ( name === "find" )
+ if ( name === "find" ) {
ret.selector = this.selector + (this.selector ? " " : "") + selector;
- else if ( name )
+ } else if ( name ) {
ret.selector = this.selector + "." + name + "(" + selector + ")";
+ }
// Return the newly-formed element set
return ret;
},
- // Force the current matched set of elements to become
- // the specified array of elements (destroying the stack in the process)
- // You should use pushStack() in order to do this, but maintain the stack
- setArray: function( elems ) {
- // Resetting the length to 0, then using the native Array push
- // is a super-fast way to populate an object with array-like properties
- this.length = 0;
- Array.prototype.push.apply( this, elems );
-
- return this;
- },
-
// Execute a callback for every element in the matched set.
// (You can seed the arguments with an array of args, but this is
// only used internally.)
each: function( callback, args ) {
return jQuery.each( this, callback, args );
},
+
+ ready: function( fn ) {
+ // Attach the listeners
+ jQuery.bindReady();
- // Determine the position of an element within
- // the matched set of elements
- index: function( elem ) {
- // Locate the position of the desired element
- return jQuery.inArray(
- // If it receives a jQuery object, the first element is used
- elem && elem.jquery ? elem[0] : elem
- , this );
- },
+ // If the DOM is already ready
+ if ( jQuery.isReady ) {
+ // Execute the function immediately
+ fn.call( document, jQuery );
- attr: function( name, value, type ) {
- var options = name;
+ // Otherwise, remember the function for later
+ } else if ( readyList ) {
+ // Add the function to the wait list
+ readyList.push( fn );
+ }
- // Look for the case where we're accessing a style value
- if ( typeof name === "string" )
- if ( value === undefined )
- return this[0] && jQuery[ type || "attr" ]( this[0], name );
+ return this;
+ },
+
+ eq: function( i ) {
+ return i === -1 ?
+ this.slice( i ) :
+ this.slice( i, +i + 1 );
+ },
- else {
- options = {};
- options[ name ] = value;
- }
+ first: function() {
+ return this.eq( 0 );
+ },
- // Check to see if we're setting style values
- return this.each(function(i){
- // Set all the styles
- for ( name in options )
- jQuery.attr(
- type ?
- this.style :
- this,
- name, jQuery.prop( this, options[ name ], type, i, name )
- );
- });
+ last: function() {
+ return this.eq( -1 );
},
- css: function( key, value ) {
- // ignore negative width and height values
- if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
- value = undefined;
- return this.attr( key, value, "curCSS" );
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ),
+ "slice", slice.call(arguments).join(",") );
},
- text: function( text ) {
- if ( typeof text !== "object" && text != null )
- return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || jQuery(null);
+ },
- var ret = "";
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: [].sort,
+ splice: [].splice
+};
- jQuery.each( text || this, function(){
- jQuery.each( this.childNodes, function(){
- if ( this.nodeType != 8 )
- ret += this.nodeType != 1 ?
- this.nodeValue :
- jQuery.fn.text( [ this ] );
- });
- });
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
- return ret;
- },
+jQuery.extend = jQuery.fn.extend = function() {
+ // copy reference to target object
+ var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
- wrapAll: function( html ) {
- if ( this[0] ) {
- // The elements to wrap the target around
- var wrap = jQuery( html, this[0].ownerDocument ).clone();
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
- if ( this[0].parentNode )
- wrap.insertBefore( this[0] );
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
- wrap.map(function(){
- var elem = this;
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
- while ( elem.firstChild )
- elem = elem.firstChild;
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
- return elem;
- }).append(this);
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging object literal values or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
+ var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
+ : jQuery.isArray(copy) ? [] : {};
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
}
+ }
- return this;
- },
+ // Return the modified object
+ return target;
+};
- wrapInner: function( html ) {
- return this.each(function(){
- jQuery( this ).contents().wrapAll( html );
- });
+jQuery.extend({
+ noConflict: function( deep ) {
+ window.$ = _$;
+
+ if ( deep ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
},
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // Handle when the DOM is ready
+ ready: function() {
+ // Make sure that the DOM is not already loaded
+ if ( !jQuery.isReady ) {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready, 13 );
+ }
- wrap: function( html ) {
- return this.each(function(){
- jQuery( this ).wrapAll( html );
- });
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If there are functions bound, to execute
+ if ( readyList ) {
+ // Execute all of them
+ var fn, i = 0;
+ while ( (fn = readyList[ i++ ]) ) {
+ fn.call( document, jQuery );
+ }
+
+ // Reset the list of functions
+ readyList = null;
+ }
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.triggerHandler ) {
+ jQuery( document ).triggerHandler( "ready" );
+ }
+ }
},
+
+ bindReady: function() {
+ if ( readyBound ) {
+ return;
+ }
- append: function() {
- return this.domManip(arguments, true, function(elem){
- if (this.nodeType == 1)
- this.appendChild( elem );
- });
+ readyBound = true;
+
+ // Catch cases where $(document).ready() is called after the
+ // browser event has already occurred.
+ if ( document.readyState === "complete" ) {
+ return jQuery.ready();
+ }
+
+ // Mozilla, Opera and webkit nightlies currently support this event
+ if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", jQuery.ready, false );
+
+ // If IE event model is used
+ } else if ( document.attachEvent ) {
+ // ensure firing before onload,
+ // maybe late but safe also for iframes
+ document.attachEvent("onreadystatechange", DOMContentLoaded);
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", jQuery.ready );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var toplevel = false;
+
+ try {
+ toplevel = window.frameElement == null;
+ } catch(e) {}
+
+ if ( document.documentElement.doScroll && toplevel ) {
+ doScrollCheck();
+ }
+ }
},
- prepend: function() {
- return this.domManip(arguments, true, function(elem){
- if (this.nodeType == 1)
- this.insertBefore( elem, this.firstChild );
- });
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return toString.call(obj) === "[object Function]";
},
- before: function() {
- return this.domManip(arguments, false, function(elem){
-//try{
- this.parentNode.insertBefore( elem, this );
-//}catch(e) {
-//}
- });
+ isArray: function( obj ) {
+ return toString.call(obj) === "[object Array]";
},
- after: function() {
- return this.domManip(arguments, false, function(elem){
- this.parentNode.insertBefore( elem, this.nextSibling );
- });
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
+ return false;
+ }
+
+ // Not own constructor property must be Object
+ if ( obj.constructor
+ && !hasOwnProperty.call(obj, "constructor")
+ && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwnProperty.call( obj, key );
},
- end: function() {
- return this.prevObject || jQuery( [] );
+ isEmptyObject: function( obj ) {
+ for ( var name in obj ) {
+ return false;
+ }
+ return true;
},
+
+ error: function( msg ) {
+ throw msg;
+ },
+
+ parseJSON: function( data ) {
+ if ( typeof data !== "string" || !data ) {
+ return null;
+ }
- // For internal use only.
- // Behaves like an Array's method, not like a jQuery method.
- push: [].push,
- sort: [].sort,
- splice: [].splice,
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
+ .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {
+
+ // Try to use the native JSON parser first
+ return window.JSON && window.JSON.parse ?
+ window.JSON.parse( data ) :
+ (new Function("return " + data))();
- find: function( selector ) {
- if ( this.length === 1 ) {
- var ret = this.pushStack( [], "find", selector );
- ret.length = 0;
- jQuery.find( selector, this[0], ret );
- return ret;
} else {
- return this.pushStack( jQuery.unique(jQuery.map(this, function(elem){
- return jQuery.find( selector, elem );
- })), "find", selector );
+ jQuery.error( "Invalid JSON: " + data );
}
},
- clone: function( events ) {
- // Do the clone
- var ret = this.map(function(){
- if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
- // IE copies events bound via attachEvent when
- // using cloneNode. Calling detachEvent on the
- // clone will also remove the events from the orignal
- // In order to get around this, we use innerHTML.
- // Unfortunately, this means some modifications to
- // attributes in IE that are actually only stored
- // as properties will not be copied (such as the
- // the name attribute on an input).
- var html = this.outerHTML;
- if ( !html ) {
- var div = this.ownerDocument.createElement("div");
- div.appendChild( this.cloneNode(true) );
- html = div.innerHTML;
- }
+ noop: function() {},
- return jQuery.clean([html.replace(/ jQuery\d+="(?:\d+|null)"/g, "").replace(/^\s*/, "")])[0];
- } else
- return this.cloneNode(true);
- });
+ // Evalulates a script in a global context
+ globalEval: function( data ) {
+ if ( data && rnotwhite.test(data) ) {
+ // Inspired by code by Andrea Giammarchi
+ // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
+ var head = document.getElementsByTagName("head")[0] || document.documentElement,
+ script = document.createElement("script");
- // Copy the events from the original to the clone
- if ( events === true ) {
- var orig = this.find("*").andSelf(), i = 0;
+ script.type = "text/javascript";
- ret.find("*").andSelf().each(function(){
- if ( this.nodeName !== orig[i].nodeName )
- return;
+ if ( jQuery.support.scriptEval ) {
+ script.appendChild( document.createTextNode( data ) );
+ } else {
+ script.text = data;
+ }
+
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709).
+ head.insertBefore( script, head.firstChild );
+ head.removeChild( script );
+ }
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+ },
- var events = jQuery.data( orig[i], "events" );
+ // args is for internal usage only
+ each: function( object, callback, args ) {
+ var name, i = 0,
+ length = object.length,
+ isObj = length === undefined || jQuery.isFunction(object);
- for ( var type in events ) {
- for ( var handler in events[ type ] ) {
- jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
+ if ( args ) {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.apply( object[ name ], args ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.apply( object[ i++ ], args ) === false ) {
+ break;
}
}
+ }
- i++;
- });
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( var value = object[0];
+ i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
+ }
}
- // Return the cloned set
- return ret;
+ return object;
},
- filter: function( selector ) {
- return this.pushStack(
- jQuery.isFunction( selector ) &&
- jQuery.grep(this, function(elem, i){
- return selector.call( elem, i );
- }) ||
-
- jQuery.multiFilter( selector, jQuery.grep(this, function(elem){
- return elem.nodeType === 1;
- }) ), "filter", selector );
- },
-
- closest: function( selector ) {
- var pos = jQuery.expr.match.POS.test( selector ) ? jQuery(selector) : null,
- closer = 0;
-
- return this.map(function(){
- var cur = this;
- while ( cur && cur.ownerDocument ) {
- if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selector) ) {
- jQuery.data(cur, "closest", closer);
- return cur;
- }
- cur = cur.parentNode;
- closer++;
- }
- });
+ trim: function( text ) {
+ return (text || "").replace( rtrim, "" );
},
- not: function( selector ) {
- if ( typeof selector === "string" )
- // test special case where just one selector is passed in
- if ( isSimple.test( selector ) )
- return this.pushStack( jQuery.multiFilter( selector, this, true ), "not", selector );
- else
- selector = jQuery.multiFilter( selector, this );
-
- var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
- return this.filter(function() {
- return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
- });
- },
+ // results is for internal usage only
+ makeArray: function( array, results ) {
+ var ret = results || [];
- add: function( selector ) {
- return this.pushStack( jQuery.unique( jQuery.merge(
- this.get(),
- typeof selector === "string" ?
- jQuery( selector ) :
- jQuery.makeArray( selector )
- )));
- },
+ if ( array != null ) {
+ // The window, strings (and functions) also have 'length'
+ // The extra typeof function check is to prevent crashes
+ // in Safari 2 (See: #3039)
+ if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
+ push.call( ret, array );
+ } else {
+ jQuery.merge( ret, array );
+ }
+ }
- is: function( selector ) {
- return !!selector && jQuery.multiFilter( selector, this ).length > 0;
+ return ret;
},
- hasClass: function( selector ) {
- return !!selector && this.is( "." + selector );
- },
+ inArray: function( elem, array ) {
+ if ( array.indexOf ) {
+ return array.indexOf( elem );
+ }
- val: function( value ) {
- if ( value === undefined ) {
- var elem = this[0];
+ for ( var i = 0, length = array.length; i < length; i++ ) {
+ if ( array[ i ] === elem ) {
+ return i;
+ }
+ }
- if ( elem ) {
- if( jQuery.nodeName( elem, 'option' ) )
- return (elem.attributes.value || {}).specified ? elem.value : elem.text;
+ return -1;
+ },
- // We need to handle select boxes special
- if ( jQuery.nodeName( elem, "select" ) ) {
- var index = elem.selectedIndex,
- values = [],
- options = elem.options,
- one = elem.type == "select-one";
+ merge: function( first, second ) {
+ var i = first.length, j = 0;
- // Nothing was selected
- if ( index < 0 )
- return null;
+ if ( typeof second.length === "number" ) {
+ for ( var l = second.length; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
- // Loop through all the selected options
- for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
- var option = options[ i ];
+ first.length = i;
- if ( option.selected ) {
- // Get the specifc value for the option
- value = jQuery(option).val();
+ return first;
+ },
- // We don't need an array for one selects
- if ( one )
- return value;
+ grep: function( elems, callback, inv ) {
+ var ret = [];
- // Multi-Selects return an array
- values.push( value );
- }
- }
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ if ( !inv !== !callback( elems[ i ], i ) ) {
+ ret.push( elems[ i ] );
+ }
+ }
- return values;
- }
+ return ret;
+ },
- // Everything else, we just grab the value
- return (elem.value || "").replace(/\r/g, "");
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var ret = [], value;
- }
+ // Go through the array, translating each of the items to their
+ // new value (or values).
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
- return undefined;
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
}
- if ( typeof value === "number" )
- value += '';
+ return ret.concat.apply( [], ret );
+ },
- return this.each(function(){
- if ( this.nodeType != 1 )
- return;
+ // A global GUID counter for objects
+ guid: 1,
- if ( jQuery.isArray(value) && /radio|checkbox/.test( this.type ) )
- this.checked = (jQuery.inArray(this.value, value) >= 0 ||
- jQuery.inArray(this.name, value) >= 0);
+ proxy: function( fn, proxy, thisObject ) {
+ if ( arguments.length === 2 ) {
+ if ( typeof proxy === "string" ) {
+ thisObject = fn;
+ fn = thisObject[ proxy ];
+ proxy = undefined;
- else if ( jQuery.nodeName( this, "select" ) ) {
- var values = jQuery.makeArray(value);
+ } else if ( proxy && !jQuery.isFunction( proxy ) ) {
+ thisObject = proxy;
+ proxy = undefined;
+ }
+ }
- jQuery( "option", this ).each(function(){
- this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
- jQuery.inArray( this.text, values ) >= 0);
- });
+ if ( !proxy && fn ) {
+ proxy = function() {
+ return fn.apply( thisObject || this, arguments );
+ };
+ }
- if ( !values.length )
- this.selectedIndex = -1;
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ if ( fn ) {
+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+ }
- } else
- this.value = value;
- });
+ // So proxy can be declared as an argument
+ return proxy;
},
- html: function( value ) {
- return value === undefined ?
- (this[0] ?
- this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g, "") :
- null) :
- this.empty().append( value );
- },
+ // Use of jQuery.browser is frowned upon.
+ // More details: http://docs.jquery.com/Utilities/jQuery.browser
+ uaMatch: function( ua ) {
+ ua = ua.toLowerCase();
- replaceWith: function( value ) {
- return this.after( value ).remove();
- },
+ var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
+ /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) ||
+ /(msie) ([\w.]+)/.exec( ua ) ||
+ !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) ||
+ [];
- eq: function( i ) {
- return this.slice( i, +i + 1 );
+ return { browser: match[1] || "", version: match[2] || "0" };
},
- slice: function() {
- return this.pushStack( Array.prototype.slice.apply( this, arguments ),
- "slice", Array.prototype.slice.call(arguments).join(",") );
- },
+ browser: {}
+});
- map: function( callback ) {
- return this.pushStack( jQuery.map(this, function(elem, i){
- return callback.call( elem, i, elem );
- }));
- },
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+ jQuery.browser[ browserMatch.browser ] = true;
+ jQuery.browser.version = browserMatch.version;
+}
- andSelf: function() {
- return this.add( this.prevObject );
- },
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+ jQuery.browser.safari = true;
+}
- domManip: function( args, table, callback ) {
- if ( this[0] ) {
- var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
- scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
- first = fragment.firstChild;
+if ( indexOf ) {
+ jQuery.inArray = function( elem, array ) {
+ return indexOf.call( array, elem );
+ };
+}
- if ( first )
- for ( var i = 0, l = this.length; i < l; i++ )
- callback.call( root(this[i], first), this.length > 1 || i > 0 ?
- fragment.cloneNode(true) : fragment );
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
- if ( scripts )
- jQuery.each( scripts, evalScript );
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+ DOMContentLoaded = function() {
+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+ jQuery.ready();
+ };
+
+} else if ( document.attachEvent ) {
+ DOMContentLoaded = function() {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( document.readyState === "complete" ) {
+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
+ jQuery.ready();
}
+ };
+}
- return this;
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+ if ( jQuery.isReady ) {
+ return;
+ }
- function root( elem, cur ) {
- return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
- (elem.getElementsByTagName("tbody")[0] ||
- elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
- elem;
- }
+ try {
+ // If IE is used, use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ document.documentElement.doScroll("left");
+ } catch( error ) {
+ setTimeout( doScrollCheck, 1 );
+ return;
}
-};
-// Give the init function the jQuery prototype for later instantiation
-jQuery.fn.init.prototype = jQuery.fn;
+ // and execute any waiting functions
+ jQuery.ready();
+}
function evalScript( i, elem ) {
- if ( elem.src )
+ if ( elem.src ) {
jQuery.ajax({
url: elem.src,
async: false,
dataType: "script"
});
-
- else
+ } else {
jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
+ }
- if ( elem.parentNode )
+ if ( elem.parentNode ) {
elem.parentNode.removeChild( elem );
+ }
}
-function now(){
- return +new Date;
+// Mutifunctional method to get and set values to a collection
+// The value/s can be optionally by executed if its a function
+function access( elems, key, value, exec, fn, pass ) {
+ var length = elems.length;
+
+ // Setting many attributes
+ if ( typeof key === "object" ) {
+ for ( var k in key ) {
+ access( elems, k, key[k], exec, fn, value );
+ }
+ return elems;
+ }
+
+ // Setting one attribute
+ if ( value !== undefined ) {
+ // Optionally, function values get executed if exec is true
+ exec = !pass && exec && jQuery.isFunction(value);
+
+ for ( var i = 0; i < length; i++ ) {
+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+ }
+
+ return elems;
+ }
+
+ // Getting an attribute
+ return length ? fn( elems[0], key ) : undefined;
}
-jQuery.extend = jQuery.fn.extend = function() {
- // copy reference to target object
- var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
+function now() {
+ return (new Date).getTime();
+}
+(function() {
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
- target = arguments[1] || {};
- // skip the boolean and the target
- i = 2;
+ jQuery.support = {};
+
+ var root = document.documentElement,
+ script = document.createElement("script"),
+ div = document.createElement("div"),
+ id = "script" + now();
+
+ div.style.display = "none";
+ div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+ var all = div.getElementsByTagName("*"),
+ a = div.getElementsByTagName("a")[0];
+
+ // Can't get basic test support
+ if ( !all || !all.length || !a ) {
+ return;
}
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !jQuery.isFunction(target) )
- target = {};
+ jQuery.support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: div.firstChild.nodeType === 3,
- // extend jQuery itself if only one argument is passed
- if ( length == i ) {
- target = this;
- --i;
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName("tbody").length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName("link").length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText insted)
+ style: /red/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: a.getAttribute("href") === "/a",
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.55$/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Make sure that if no value is specified for a checkbox
+ // that it defaults to "on".
+ // (WebKit defaults to "" instead)
+ checkOn: div.getElementsByTagName("input")[0].value === "on",
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected,
+
+ parentNode: div.removeChild( div.appendChild( document.createElement("div") ) ).parentNode === null,
+
+ // Will be defined later
+ deleteExpando: true,
+ checkClone: false,
+ scriptEval: false,
+ noCloneEvent: true,
+ boxModel: null
+ };
+
+ script.type = "text/javascript";
+ try {
+ script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
+ } catch(e) {}
+
+ root.insertBefore( script, root.firstChild );
+
+ // Make sure that the execution of code works by injecting a script
+ // tag with appendChild/createTextNode
+ // (IE doesn't support this, fails, and uses .text instead)
+ if ( window[ id ] ) {
+ jQuery.support.scriptEval = true;
+ delete window[ id ];
}
- for ( ; i < length; i++ )
- // Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null )
- // Extend the base object
- for ( var name in options ) {
- var src = target[ name ], copy = options[ name ];
+ // Test to see if it's possible to delete an expando from an element
+ // Fails in Internet Explorer
+ try {
+ delete script.test;
+
+ } catch(e) {
+ jQuery.support.deleteExpando = false;
+ }
- // Prevent never-ending loop
- if ( target === copy )
- continue;
+ root.removeChild( script );
- // Recurse if we're merging object values
- if ( deep && copy && typeof copy === "object" && !copy.nodeType )
- target[ name ] = jQuery.extend( deep,
- // Never move original objects, clone them
- src || ( copy.length != null ? [ ] : { } )
- , copy );
+ if ( div.attachEvent && div.fireEvent ) {
+ div.attachEvent("onclick", function click() {
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ jQuery.support.noCloneEvent = false;
+ div.detachEvent("onclick", click);
+ });
+ div.cloneNode(true).fireEvent("onclick");
+ }
- // Don't bring in undefined values
- else if ( copy !== undefined )
- target[ name ] = copy;
+ div = document.createElement("div");
+ div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
- }
+ var fragment = document.createDocumentFragment();
+ fragment.appendChild( div.firstChild );
- // Return the modified object
- return target;
-};
+ // WebKit doesn't clone checked state correctly in fragments
+ jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
-// exclude the following css properties to add px
-var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
- // cache defaultView
- defaultView = document.defaultView || {},
- toString = Object.prototype.toString;
+ // Figure out if the W3C box model works as expected
+ // document.body must exist before we can do this
+ jQuery(function() {
+ var div = document.createElement("div");
+ div.style.width = div.style.paddingLeft = "1px";
-jQuery.extend({
- noConflict: function( deep ) {
- window.$ = _$;
+ document.body.appendChild( div );
+ jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
+ document.body.removeChild( div ).style.display = 'none';
- if ( deep )
- window.jQuery = _jQuery;
+ div = null;
+ });
- return jQuery;
- },
+ // Technique from Juriy Zaytsev
+ // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
+ var eventSupported = function( eventName ) {
+ var el = document.createElement("div");
+ eventName = "on" + eventName;
- // See test/unit/core.js for details concerning isFunction.
- // Since version 1.3, DOM methods and functions like alert
- // aren't supported. They return false on IE (#2968).
- isFunction: function( obj ) {
- return toString.call(obj) === "[object Function]";
- },
+ var isSupported = (eventName in el);
+ if ( !isSupported ) {
+ el.setAttribute(eventName, "return;");
+ isSupported = typeof el[eventName] === "function";
+ }
+ el = null;
- isArray: function( obj ) {
- return toString.call(obj) === "[object Array]";
- },
+ return isSupported;
+ };
+
+ jQuery.support.submitBubbles = eventSupported("submit");
+ jQuery.support.changeBubbles = eventSupported("change");
+
+ // release memory in IE
+ root = script = div = all = a = null;
+})();
- // check if an element is in a (or is an) XML document
- isXMLDoc: function( elem ) {
- return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
- !!elem.ownerDocument && jQuery.isXMLDoc( elem.ownerDocument );
+jQuery.props = {
+ "for": "htmlFor",
+ "class": "className",
+ readonly: "readOnly",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ tabindex: "tabIndex",
+ usemap: "useMap",
+ frameborder: "frameBorder"
+};
+var expando = "jQuery" + now(), uuid = 0, windowData = {};
+
+jQuery.extend({
+ cache: {},
+
+ expando:expando,
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ "object": true,
+ "applet": true
},
- // Evalulates a script in a global context
- globalEval: function( data ) {
- if ( data && /\S/.test(data) ) {
- // Inspired by code by Andrea Giammarchi
- // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
- var head = document.getElementsByTagName("head")[0] || document.documentElement,
- script = document.createElement("script");
+ data: function( elem, name, data ) {
+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+ return;
+ }
- script.type = "text/javascript";
- if ( jQuery.support.scriptEval )
- script.appendChild( document.createTextNode( data ) );
- else
- script.text = data;
+ elem = elem == window ?
+ windowData :
+ elem;
- // Use insertBefore instead of appendChild to circumvent an IE6 bug.
- // This arises when a base node is used (#2709).
- head.insertBefore( script, head.firstChild );
- head.removeChild( script );
+ var id = elem[ expando ], cache = jQuery.cache, thisCache;
+
+ if ( !id && typeof name === "string" && data === undefined ) {
+ return null;
}
- },
- nodeName: function( elem, name ) {
- return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
- },
+ // Compute a unique ID for the element
+ if ( !id ) {
+ id = ++uuid;
+ }
- // args is for internal usage only
- each: function( object, callback, args ) {
- var name, i = 0, length = object.length;
+ // Avoid generating a new cache unless none exists and we
+ // want to manipulate it.
+ if ( typeof name === "object" ) {
+ elem[ expando ] = id;
+ thisCache = cache[ id ] = jQuery.extend(true, {}, name);
- if ( args ) {
- if ( length === undefined ) {
- for ( name in object )
- if ( callback.apply( object[ name ], args ) === false )
- break;
- } else
- for ( ; i < length; )
- if ( callback.apply( object[ i++ ], args ) === false )
- break;
+ } else if ( !cache[ id ] ) {
+ elem[ expando ] = id;
+ cache[ id ] = {};
+ }
- // A special, fast, case for the most common use of each
- } else {
- if ( length === undefined ) {
- for ( name in object )
- if ( callback.call( object[ name ], name, object[ name ] ) === false )
- break;
- } else
- for ( var value = object[0];
- i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
+ thisCache = cache[ id ];
+
+ // Prevent overriding the named cache with undefined values
+ if ( data !== undefined ) {
+ thisCache[ name ] = data;
}
- return object;
+ return typeof name === "string" ? thisCache[ name ] : thisCache;
},
- prop: function( elem, value, type, i, name ) {
- // Handle executable functions
- if ( jQuery.isFunction( value ) )
- value = value.call( elem, i );
+ removeData: function( elem, name ) {
+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+ return;
+ }
- // Handle passing in a number to a CSS property
- return typeof value === "number" && type == "curCSS" && !exclude.test( name ) ?
- value + "px" :
- value;
- },
+ elem = elem == window ?
+ windowData :
+ elem;
+
+ var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];
+
+ // If we want to remove a specific section of the element's data
+ if ( name ) {
+ if ( thisCache ) {
+ // Remove the section of cache data
+ delete thisCache[ name ];
+
+ // If we've removed all the data, remove the element's cache
+ if ( jQuery.isEmptyObject(thisCache) ) {
+ jQuery.removeData( elem );
+ }
+ }
+
+ // Otherwise, we want to remove all of the element's data
+ } else {
+ if ( jQuery.support.deleteExpando ) {
+ delete elem[ jQuery.expando ];
- className: {
- // internal only, use addClass("class")
- add: function( elem, classNames ) {
- jQuery.each((classNames || "").split(/\s+/), function(i, className){
- if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
- elem.className += (elem.className ? " " : "") + className;
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+ }
+
+ // Completely remove the data cache
+ delete cache[ id ];
+ }
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ if ( typeof key === "undefined" && this.length ) {
+ return jQuery.data( this[0] );
+
+ } else if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
});
- },
+ }
- // internal only, use removeClass("class")
- remove: function( elem, classNames ) {
- if (elem.nodeType == 1)
- elem.className = classNames !== undefined ?
- jQuery.grep(elem.className.split(/\s+/), function(className){
- return !jQuery.className.has( classNames, className );
- }).join(" ") :
- "";
- },
+ var parts = key.split(".");
+ parts[1] = parts[1] ? "." + parts[1] : "";
- // internal only, use hasClass("class")
- has: function( elem, className ) {
- return elem && jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
+ if ( value === undefined ) {
+ var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+ if ( data === undefined && this.length ) {
+ data = jQuery.data( this[0], key );
+ }
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+ } else {
+ return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() {
+ jQuery.data( this, key, value );
+ });
}
},
- // A method for quickly swapping in/out CSS properties to get correct calculations
- swap: function( elem, options, callback ) {
- var old = {};
- // Remember the old values, and insert the new ones
- for ( var name in options ) {
- old[ name ] = elem.style[ name ];
- elem.style[ name ] = options[ name ];
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+jQuery.extend({
+ queue: function( elem, type, data ) {
+ if ( !elem ) {
+ return;
}
- callback.call( elem );
+ type = (type || "fx") + "queue";
+ var q = jQuery.data( elem, type );
- // Revert the old values
- for ( var name in options )
- elem.style[ name ] = old[ name ];
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( !data ) {
+ return q || [];
+ }
+
+ if ( !q || jQuery.isArray(data) ) {
+ q = jQuery.data( elem, type, jQuery.makeArray(data) );
+
+ } else {
+ q.push( data );
+ }
+
+ return q;
},
- css: function( elem, name, force, extra ) {
- if ( name == "width" || name == "height" ) {
- var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
+ dequeue: function( elem, type ) {
+ type = type || "fx";
- function getWH() {
- val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
+ var queue = jQuery.queue( elem, type ), fn = queue.shift();
- if ( extra === "border" )
- return;
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ }
- jQuery.each( which, function() {
- if ( !extra )
- val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
- if ( extra === "margin" )
- val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
- else
- val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
- });
+ if ( fn ) {
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift("inprogress");
}
- if ( elem.offsetWidth !== 0 )
- getWH();
- else
- jQuery.swap( elem, props, getWH );
+ fn.call(elem, function() {
+ jQuery.dequeue(elem, type);
+ });
+ }
+ }
+});
- return Math.max(0, Math.round(val));
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
}
- return jQuery.curCSS( elem, name, force );
- },
+ if ( data === undefined ) {
+ return jQuery.queue( this[0], type );
+ }
+ return this.each(function( i, elem ) {
+ var queue = jQuery.queue( this, type, data );
- curCSS: function( elem, name, force ) {
- var ret, style = elem.style;
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
- // We need to handle opacity special in IE
- if ( name == "opacity" && !jQuery.support.opacity ) {
- ret = jQuery.attr( style, "opacity" );
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function() {
+ var elem = this;
+ setTimeout(function() {
+ jQuery.dequeue( elem, type );
+ }, time );
+ });
+ },
- return ret == "" ?
- "1" :
- ret;
- }
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ }
+});
+var rclass = /[\n\t]/g,
+ rspace = /\s+/,
+ rreturn = /\r/g,
+ rspecialurl = /href|src|style/,
+ rtype = /(button|input)/i,
+ rfocusable = /(button|input|object|select|textarea)/i,
+ rclickable = /^(a|area)$/i,
+ rradiocheck = /radio|checkbox/;
- // Make sure we're using the right name for getting the float value
- if ( name.match( /float/i ) )
- name = styleFloat;
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return access( this, name, value, true, jQuery.attr );
+ },
- if ( !force && style && style[ name ] )
- ret = style[ name ];
+ removeAttr: function( name, fn ) {
+ return this.each(function(){
+ jQuery.attr( this, name, "" );
+ if ( this.nodeType === 1 ) {
+ this.removeAttribute( name );
+ }
+ });
+ },
- else if ( defaultView.getComputedStyle ) {
+ addClass: function( value ) {
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ self.addClass( value.call(this, i, self.attr("class")) );
+ });
+ }
- // Only "float" is needed here
- if ( name.match( /float/i ) )
- name = "float";
+ if ( value && typeof value === "string" ) {
+ var classNames = (value || "").split( rspace );
- name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ var elem = this[i];
- var computedStyle = defaultView.getComputedStyle( elem, null );
+ if ( elem.nodeType === 1 ) {
+ if ( !elem.className ) {
+ elem.className = value;
- if ( computedStyle )
- ret = computedStyle.getPropertyValue( name );
+ } else {
+ var className = " " + elem.className + " ", setClass = elem.className;
+ for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+ if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
+ setClass += " " + classNames[c];
+ }
+ }
+ elem.className = jQuery.trim( setClass );
+ }
+ }
+ }
+ }
- // We should always get a number back from opacity
- if ( name == "opacity" && ret == "" )
- ret = "1";
+ return this;
+ },
- } else if ( elem.currentStyle ) {
- var camelCase = name.replace(/\-(\w)/g, function(all, letter){
- return letter.toUpperCase();
+ removeClass: function( value ) {
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ self.removeClass( value.call(this, i, self.attr("class")) );
});
+ }
- ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
-
- // From the awesome hack by Dean Edwards
- // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+ if ( (value && typeof value === "string") || value === undefined ) {
+ var classNames = (value || "").split(rspace);
- // If we're not dealing with a regular pixel number
- // but a number that has a weird ending, we need to convert it to pixels
- if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
- // Remember the original values
- var left = style.left, rsLeft = elem.runtimeStyle.left;
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ var elem = this[i];
- // Put in the new values to get a computed value out
- elem.runtimeStyle.left = elem.currentStyle.left;
- style.left = ret || 0;
- ret = style.pixelLeft + "px";
+ if ( elem.nodeType === 1 && elem.className ) {
+ if ( value ) {
+ var className = (" " + elem.className + " ").replace(rclass, " ");
+ for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
+ className = className.replace(" " + classNames[c] + " ", " ");
+ }
+ elem.className = jQuery.trim( className );
- // Revert the changed values
- style.left = left;
- elem.runtimeStyle.left = rsLeft;
+ } else {
+ elem.className = "";
+ }
+ }
}
}
- return ret;
+ return this;
},
- clean: function( elems, context, fragment ) {
- context = context || document;
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value, isBool = typeof stateVal === "boolean";
- // !context.createElement fails in IE with an error but returns typeof 'object'
- if ( typeof context.createElement === "undefined" )
- context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
-
- // If a single string is passed in and it's a single tag
- // just do a createElement and skip the rest
- if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
- var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);
- if ( match )
- return [ context.createElement( match[1] ) ];
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
+ });
}
- var ret = [], scripts = [], div = context.createElement("div");
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className, i = 0, self = jQuery(this),
+ state = stateVal,
+ classNames = value.split( rspace );
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space seperated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
- jQuery.each(elems, function(i, elem){
- if ( typeof elem === "number" )
- elem += '';
+ } else if ( type === "undefined" || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery.data( this, "__className__", this.className );
+ }
- if ( !elem )
- return;
+ // toggle whole className
+ this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
+ }
+ });
+ },
- // Convert html string into DOM nodes
- if ( typeof elem === "string" ) {
- // Fix "XHTML"-style tags in all browsers
- elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
- return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
- all :
- front + "></" + tag + ">";
- });
+ hasClass: function( selector ) {
+ var className = " " + selector + " ";
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+ return true;
+ }
+ }
- // Trim whitespace, otherwise indexOf won't work as expected
- var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
+ return false;
+ },
- var wrap =
- // option or optgroup
- !tags.indexOf("<opt") &&
- [ 1, "<select multiple='multiple'>", "</select>" ] ||
+ val: function( value ) {
+ if ( value === undefined ) {
+ var elem = this[0];
- !tags.indexOf("<leg") &&
- [ 1, "<fieldset>", "</fieldset>" ] ||
+ if ( elem ) {
+ if ( jQuery.nodeName( elem, "option" ) ) {
+ return (elem.attributes.value || {}).specified ? elem.value : elem.text;
+ }
- tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
- [ 1, "<table>", "</table>" ] ||
+ // We need to handle select boxes special
+ if ( jQuery.nodeName( elem, "select" ) ) {
+ var index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type === "select-one";
- !tags.indexOf("<tr") &&
- [ 2, "<table><tbody>", "</tbody></table>" ] ||
+ // Nothing was selected
+ if ( index < 0 ) {
+ return null;
+ }
- // <thead> matched above
- (!tags.indexOf("<td") || !tags.indexOf("<th")) &&
- [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
+ // Loop through all the selected options
+ for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
+ var option = options[ i ];
- !tags.indexOf("<col") &&
- [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||
+ if ( option.selected ) {
+ // Get the specifc value for the option
+ value = jQuery(option).val();
- // IE can't serialize <link> and <script> tags normally
- !jQuery.support.htmlSerialize &&
- [ 1, "div<div>", "</div>" ] ||
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
- [ 0, "", "" ];
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
- // Go to html and back, then peel off extra wrappers
- div.innerHTML = wrap[1] + elem + wrap[2];
+ return values;
+ }
- // Move to the right depth
- while ( wrap[0]-- )
- div = div.lastChild;
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+
- // Remove IE's autoinserted <tbody> from table fragments
- if ( !jQuery.support.tbody ) {
+ // Everything else, we just grab the value
+ return (elem.value || "").replace(rreturn, "");
- // String was a <table>, *may* have spurious <tbody>
- var hasBody = /<tbody/i.test(elem),
- tbody = !tags.indexOf("<table") && !hasBody ?
- div.firstChild && div.firstChild.childNodes :
+ }
- // String was a bare <thead> or <tfoot>
- wrap[1] == "<table>" && !hasBody ?
- div.childNodes :
- [];
+ return undefined;
+ }
- for ( var j = tbody.length - 1; j >= 0 ; --j )
- if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
- tbody[ j ].parentNode.removeChild( tbody[ j ] );
+ var isFunction = jQuery.isFunction(value);
- }
+ return this.each(function(i) {
+ var self = jQuery(this), val = value;
- // IE completely kills leading whitespace when innerHTML is used
- if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )
- div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
- elem = jQuery.makeArray( div.childNodes );
+ if ( isFunction ) {
+ val = value.call(this, i, self.val());
}
- if ( elem.nodeType )
- ret.push( elem );
- else
- ret = jQuery.merge( ret, elem );
+ // Typecast each time if the value is a Function and the appended
+ // value is therefore different each time.
+ if ( typeof val === "number" ) {
+ val += "";
+ }
- });
+ if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
+ this.checked = jQuery.inArray( self.val(), val ) >= 0;
- if ( fragment ) {
- for ( var i = 0; ret[i]; i++ ) {
- if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
- scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
- } else {
- if ( ret[i].nodeType === 1 )
- ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
- fragment.appendChild( ret[i] );
+ } else if ( jQuery.nodeName( this, "select" ) ) {
+ var values = jQuery.makeArray(val);
+
+ jQuery( "option", this ).each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ this.selectedIndex = -1;
}
- }
- return scripts;
- }
+ } else {
+ this.value = val;
+ }
+ });
+ }
+});
- return ret;
+jQuery.extend({
+ attrFn: {
+ val: true,
+ css: true,
+ html: true,
+ text: true,
+ data: true,
+ width: true,
+ height: true,
+ offset: true
},
-
- attr: function( elem, name, value ) {
+
+ attr: function( elem, name, value, pass ) {
// don't set attributes on text and comment nodes
- if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
return undefined;
+ }
+
+ if ( pass && name in jQuery.attrFn ) {
+ return jQuery(elem)[name](value);
+ }
- var notxml = !jQuery.isXMLDoc( elem ),
+ var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
// Whether we are setting (or getting)
set = value !== undefined;
@@ -980,472 +1464,1209 @@ jQuery.extend({
name = notxml && jQuery.props[ name ] || name;
// Only do all the following if this is a node (faster for style)
- // IE elem.getAttribute passes even for style
- if ( elem.tagName ) {
-
+ if ( elem.nodeType === 1 ) {
// These attributes require special treatment
- var special = /href|src|style/.test( name );
+ var special = rspecialurl.test( name );
- // Safari mis-reports the default selected property of a hidden option
+ // Safari mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it
- if ( name == "selected" && elem.parentNode )
- elem.parentNode.selectedIndex;
+ if ( name === "selected" && !jQuery.support.optSelected ) {
+ var parent = elem.parentNode;
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ }
// If applicable, access the attribute via the DOM 0 way
if ( name in elem && notxml && !special ) {
- if ( set ){
+ if ( set ) {
// We can't allow the type property to be changed (since it causes problems in IE)
- if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
- throw "type property can't be changed";
+ if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
+ jQuery.error( "type property can't be changed" );
+ }
elem[ name ] = value;
}
// browsers index elements by id/name on forms, give priority to attributes.
- if( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) )
+ if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
return elem.getAttributeNode( name ).nodeValue;
+ }
// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
- if ( name == "tabIndex" ) {
+ if ( name === "tabIndex" ) {
var attributeNode = elem.getAttributeNode( "tabIndex" );
- return attributeNode && attributeNode.specified
- ? attributeNode.value
- : elem.nodeName.match(/(button|input|object|select|textarea)/i)
- ? 0
- : elem.nodeName.match(/^(a|area)$/i) && elem.href
- ? 0
- : undefined;
+
+ return attributeNode && attributeNode.specified ?
+ attributeNode.value :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
}
return elem[ name ];
}
- if ( !jQuery.support.style && notxml && name == "style" )
- return jQuery.attr( elem.style, "cssText", value );
+ if ( !jQuery.support.style && notxml && name === "style" ) {
+ if ( set ) {
+ elem.style.cssText = "" + value;
+ }
+
+ return elem.style.cssText;
+ }
- if ( set )
+ if ( set ) {
// convert the value to a string (all browsers do this but IE) see #1070
elem.setAttribute( name, "" + value );
+ }
- var attr = !jQuery.support.hrefNormalized && notxml && special
+ var attr = !jQuery.support.hrefNormalized && notxml && special ?
// Some attributes require a special call on IE
- ? elem.getAttribute( name, 2 )
- : elem.getAttribute( name );
+ elem.getAttribute( name, 2 ) :
+ elem.getAttribute( name );
// Non-existent attributes return null, we normalize to undefined
return attr === null ? undefined : attr;
}
// elem is actually elem.style ... set the style
+ // Using attr for specific style information is now deprecated. Use style instead.
+ return jQuery.style( elem, name, value );
+ }
+});
+var rnamespaces = /\.(.*)$/,
+ fcleanup = function( nm ) {
+ return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
+ return "\\" + ch;
+ });
+ };
- // IE uses filters for opacity
- if ( !jQuery.support.opacity && name == "opacity" ) {
- if ( set ) {
- // IE has trouble with opacity if it does not have layout
- // Force it by setting the zoom level
- elem.zoom = 1;
+/*
+ * A number of helper functions used for managing events.
+ * Many of the ideas behind this code originated from
+ * Dean Edwards' addEvent library.
+ */
+jQuery.event = {
- // Set the alpha filter to set the opacity
- elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
- (parseInt( value ) + '' == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
- }
+ // Bind an event to an element
+ // Original by Dean Edwards
+ add: function( elem, types, handler, data ) {
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
- return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
- (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + '':
- "";
+ // For whatever reason, IE has trouble passing the window object
+ // around, causing it to be cloned in the process
+ if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
+ elem = window;
}
- name = name.replace(/-([a-z])/ig, function(all, letter){
- return letter.toUpperCase();
- });
+ var handleObjIn, handleObj;
- if ( set )
- elem[ name ] = value;
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ }
- return elem[ name ];
- },
+ // Make sure that the function being executed has a unique ID
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
- trim: function( text ) {
- return (text || "").replace( /^\s+|\s+$/g, "" );
- },
+ // Init the element's event structure
+ var elemData = jQuery.data( elem );
- makeArray: function( array ) {
- var ret = [];
+ // If no elemData is found then we must be trying to bind to one of the
+ // banned noData elements
+ if ( !elemData ) {
+ return;
+ }
- if( array != null ){
- var i = array.length;
- // The window, strings (and functions) also have 'length'
- if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
- ret[0] = array;
- else
- while( i )
- ret[--i] = array[i];
+ var events = elemData.events = elemData.events || {},
+ eventHandle = elemData.handle, eventHandle;
+
+ if ( !eventHandle ) {
+ elemData.handle = eventHandle = function() {
+ // Handle the second event of a trigger and when
+ // an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
+ jQuery.event.handle.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
}
- return ret;
- },
+ // Add elem as a property of the handle function
+ // This is to prevent a memory leak with non-native events in IE.
+ eventHandle.elem = elem;
- inArray: function( elem, array ) {
- for ( var i = 0, length = array.length; i < length; i++ )
- // Use === because on IE, window == document
- if ( array[ i ] === elem )
- return i;
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = types.split(" ");
- return -1;
+ var type, i = 0, namespaces;
+
+ while ( (type = types[ i++ ]) ) {
+ handleObj = handleObjIn ?
+ jQuery.extend({}, handleObjIn) :
+ { handler: handler, data: data };
+
+ // Namespaced event handlers
+ if ( type.indexOf(".") > -1 ) {
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ handleObj.namespace = namespaces.slice(0).sort().join(".");
+
+ } else {
+ namespaces = [];
+ handleObj.namespace = "";
+ }
+
+ handleObj.type = type;
+ handleObj.guid = handler.guid;
+
+ // Get the current list of functions bound to this event
+ var handlers = events[ type ],
+ special = jQuery.event.special[ type ] || {};
+
+ // Init the event handler queue
+ if ( !handlers ) {
+ handlers = events[ type ] = [];
+
+ // Check for a special event handler
+ // Only use addEventListener/attachEvent if the special
+ // events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add the function to the element's handler list
+ handlers.push( handleObj );
+
+ // Keep track of which events have been used, for global triggering
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
},
- merge: function( first, second ) {
- // We have to loop this way because IE & Opera overwrite the length
- // expando of getElementsByTagName
- var i = 0, elem, pos = first.length;
- // Also, we need to make sure that the correct elements are being returned
- // (IE returns comment nodes in a '*' query)
- if ( !jQuery.support.getAll ) {
- while ( (elem = second[ i++ ]) != null )
- if ( elem.nodeType != 8 )
- first[ pos++ ] = elem;
-
- } else
- while ( (elem = second[ i++ ]) != null )
- first[ pos++ ] = elem;
+ global: {},
- return first;
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, pos ) {
+ // don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
+ elemData = jQuery.data( elem ),
+ events = elemData && elemData.events;
+
+ if ( !elemData || !events ) {
+ return;
+ }
+
+ // types is actually an event object here
+ if ( types && types.type ) {
+ handler = types.handler;
+ types = types.type;
+ }
+
+ // Unbind all events for the element
+ if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
+ types = types || "";
+
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types );
+ }
+
+ return;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).unbind("mouseover mouseout", fn);
+ types = types.split(" ");
+
+ while ( (type = types[ i++ ]) ) {
+ origType = type;
+ handleObj = null;
+ all = type.indexOf(".") < 0;
+ namespaces = [];
+
+ if ( !all ) {
+ // Namespaced event handlers
+ namespaces = type.split(".");
+ type = namespaces.shift();
+
+ namespace = new RegExp("(^|\\.)" +
+ jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)")
+ }
+
+ eventType = events[ type ];
+
+ if ( !eventType ) {
+ continue;
+ }
+
+ if ( !handler ) {
+ for ( var j = 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( all || namespace.test( handleObj.namespace ) ) {
+ jQuery.event.remove( elem, origType, handleObj.handler, j );
+ eventType.splice( j--, 1 );
+ }
+ }
+
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+
+ for ( var j = pos || 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( handler.guid === handleObj.guid ) {
+ // remove the given handler for the given type
+ if ( all || namespace.test( handleObj.namespace ) ) {
+ if ( pos == null ) {
+ eventType.splice( j--, 1 );
+ }
+
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+
+ if ( pos != null ) {
+ break;
+ }
+ }
+ }
+
+ // remove generic event handler if no more handlers exist
+ if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+ removeEvent( elem, type, elemData.handle );
+ }
+
+ ret = null;
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ var handle = elemData.handle;
+ if ( handle ) {
+ handle.elem = null;
+ }
+
+ delete elemData.events;
+ delete elemData.handle;
+
+ if ( jQuery.isEmptyObject( elemData ) ) {
+ jQuery.removeData( elem );
+ }
+ }
},
- unique: function( array ) {
- var ret = [], done = {};
+ // bubbling is internal
+ trigger: function( event, data, elem /*, bubbling */ ) {
+ // Event object or event type
+ var type = event.type || event,
+ bubbling = arguments[3];
- try {
+ if ( !bubbling ) {
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[expando] ? event :
+ // Object literal
+ jQuery.extend( jQuery.Event(type), event ) :
+ // Just the event type (string)
+ jQuery.Event(type);
- for ( var i = 0, length = array.length; i < length; i++ ) {
- var id = jQuery.data( array[ i ] );
+ if ( type.indexOf("!") >= 0 ) {
+ event.type = type = type.slice(0, -1);
+ event.exclusive = true;
+ }
- if ( !done[ id ] ) {
- done[ id ] = true;
- ret.push( array[ i ] );
+ // Handle a global trigger
+ if ( !elem ) {
+ // Don't bubble custom events when global (to avoid too much overhead)
+ event.stopPropagation();
+
+ // Only trigger if we've ever bound an event for it
+ if ( jQuery.event.global[ type ] ) {
+ jQuery.each( jQuery.cache, function() {
+ if ( this.events && this.events[type] ) {
+ jQuery.event.trigger( event, data, this.handle.elem );
+ }
+ });
}
}
- } catch( e ) {
- ret = array;
+ // Handle triggering a single element
+
+ // don't do events on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return undefined;
+ }
+
+ // Clean up in case it is reused
+ event.result = undefined;
+ event.target = elem;
+
+ // Clone the incoming data, if any
+ data = jQuery.makeArray( data );
+ data.unshift( event );
+ }
+
+ event.currentTarget = elem;
+
+ // Trigger the event, it is assumed that "handle" is a function
+ var handle = jQuery.data( elem, "handle" );
+ if ( handle ) {
+ handle.apply( elem, data );
}
- return ret;
+ var parent = elem.parentNode || elem.ownerDocument;
+
+ // Trigger an inline bound script
+ try {
+ if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
+ if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
+ event.result = false;
+ }
+ }
+
+ // prevent IE from throwing an error for some elements with some event types, see #3533
+ } catch (e) {}
+
+ if ( !event.isPropagationStopped() && parent ) {
+ jQuery.event.trigger( event, data, parent, true );
+
+ } else if ( !event.isDefaultPrevented() ) {
+ var target = event.target, old,
+ isClick = jQuery.nodeName(target, "a") && type === "click",
+ special = jQuery.event.special[ type ] || {};
+
+ if ( (!special._default || special._default.call( elem, event ) === false) &&
+ !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
+
+ try {
+ if ( target[ type ] ) {
+ // Make sure that we don't accidentally re-trigger the onFOO events
+ old = target[ "on" + type ];
+
+ if ( old ) {
+ target[ "on" + type ] = null;
+ }
+
+ jQuery.event.triggered = true;
+ target[ type ]();
+ }
+
+ // prevent IE from throwing an error for some elements with some event types, see #3533
+ } catch (e) {}
+
+ if ( old ) {
+ target[ "on" + type ] = old;
+ }
+
+ jQuery.event.triggered = false;
+ }
+ }
},
- grep: function( elems, callback, inv ) {
- var ret = [];
+ handle: function( event ) {
+ var all, handlers, namespaces, namespace, events;
- // Go through the array, only saving the items
- // that pass the validator function
- for ( var i = 0, length = elems.length; i < length; i++ )
- if ( !inv != !callback( elems[ i ], i ) )
- ret.push( elems[ i ] );
+ event = arguments[0] = jQuery.event.fix( event || window.event );
+ event.currentTarget = this;
- return ret;
+ // Namespaced event handlers
+ all = event.type.indexOf(".") < 0 && !event.exclusive;
+
+ if ( !all ) {
+ namespaces = event.type.split(".");
+ event.type = namespaces.shift();
+ namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
+ }
+
+ var events = jQuery.data(this, "events"), handlers = events[ event.type ];
+
+ if ( events && handlers ) {
+ // Clone the handlers to prevent manipulation
+ handlers = handlers.slice(0);
+
+ for ( var j = 0, l = handlers.length; j < l; j++ ) {
+ var handleObj = handlers[ j ];
+
+ // Filter the functions by class
+ if ( all || namespace.test( handleObj.namespace ) ) {
+ // Pass in a reference to the handler function itself
+ // So that we can later remove it
+ event.handler = handleObj.handler;
+ event.data = handleObj.data;
+ event.handleObj = handleObj;
+
+ var ret = handleObj.handler.apply( this, arguments );
+
+ if ( ret !== undefined ) {
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+
+ if ( event.isImmediatePropagationStopped() ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return event.result;
},
- map: function( elems, callback ) {
- var ret = [];
+ props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
- // Go through the array, translating each of the items to their
- // new value (or values).
- for ( var i = 0, length = elems.length; i < length; i++ ) {
- var value = callback( elems[ i ], i );
+ fix: function( event ) {
+ if ( event[ expando ] ) {
+ return event;
+ }
- if ( value != null )
- ret[ ret.length ] = value;
+ // store a copy of the original event object
+ // and "clone" to set read-only properties
+ var originalEvent = event;
+ event = jQuery.Event( originalEvent );
+
+ for ( var i = this.props.length, prop; i; ) {
+ prop = this.props[ --i ];
+ event[ prop ] = originalEvent[ prop ];
}
- return ret.concat.apply( [], ret );
- }
-});
+ // Fix target property, if necessary
+ if ( !event.target ) {
+ event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+ }
-// Use of jQuery.browser is deprecated.
-// It's included for backwards compatibility and plugins,
-// although they should work to migrate away.
+ // check if target is a textnode (safari)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
-var userAgent = navigator.userAgent.toLowerCase();
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && event.fromElement ) {
+ event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
+ }
-// Figure out what browser is being used
-jQuery.browser = {
- version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1],
- safari: /webkit/.test( userAgent ),
- opera: /opera/.test( userAgent ),
- msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
- mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
-};
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && event.clientX != null ) {
+ var doc = document.documentElement, body = document.body;
+ event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
+ event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
+ }
-jQuery.each({
- parent: function(elem){return elem.parentNode;},
- parents: function(elem){return jQuery.dir(elem,"parentNode");},
- next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
- prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
- nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
- prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
- siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
- children: function(elem){return jQuery.sibling(elem.firstChild);},
- contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
-}, function(name, fn){
- jQuery.fn[ name ] = function( selector ) {
- var ret = jQuery.map( this, fn );
+ // Add which for key events
+ if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
+ event.which = event.charCode || event.keyCode;
+ }
- if ( selector && typeof selector == "string" )
- ret = jQuery.multiFilter( selector, ret );
+ // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
+ if ( !event.metaKey && event.ctrlKey ) {
+ event.metaKey = event.ctrlKey;
+ }
- return this.pushStack( jQuery.unique( ret ), name, selector );
- };
-});
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && event.button !== undefined ) {
+ event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+ }
-jQuery.each({
- appendTo: "append",
- prependTo: "prepend",
- insertBefore: "before",
- insertAfter: "after",
- replaceAll: "replaceWith"
-}, function(name, original){
- jQuery.fn[ name ] = function( selector ) {
- var ret = [], insert = jQuery( selector );
+ return event;
+ },
- for ( var i = 0, l = insert.length; i < l; i++ ) {
- var elems = (i > 0 ? this.clone(true) : this).get();
- jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
- ret = ret.concat( elems );
+ // Deprecated, use jQuery.guid instead
+ guid: 1E8,
+
+ // Deprecated, use jQuery.proxy instead
+ proxy: jQuery.proxy,
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: jQuery.bindReady,
+ teardown: jQuery.noop
+ },
+
+ live: {
+ add: function( handleObj ) {
+ jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) );
+ },
+
+ remove: function( handleObj ) {
+ var remove = true,
+ type = handleObj.origType.replace(rnamespaces, "");
+
+ jQuery.each( jQuery.data(this, "events").live || [], function() {
+ if ( type === this.origType.replace(rnamespaces, "") ) {
+ remove = false;
+ return false;
+ }
+ });
+
+ if ( remove ) {
+ jQuery.event.remove( this, handleObj.origType, liveHandler );
+ }
+ }
+
+ },
+
+ beforeunload: {
+ setup: function( data, namespaces, eventHandle ) {
+ // We only want to do this special case on windows
+ if ( this.setInterval ) {
+ this.onbeforeunload = eventHandle;
+ }
+
+ return false;
+ },
+ teardown: function( namespaces, eventHandle ) {
+ if ( this.onbeforeunload === eventHandle ) {
+ this.onbeforeunload = null;
+ }
+ }
}
+ }
+};
- return this.pushStack( ret, name, selector );
+var removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ elem.removeEventListener( type, handle, false );
+ } :
+ function( elem, type, handle ) {
+ elem.detachEvent( "on" + type, handle );
};
-});
-jQuery.each({
- removeAttr: function( name ) {
- jQuery.attr( this, name, "" );
- if (this.nodeType == 1)
- this.removeAttribute( name );
- },
+jQuery.Event = function( src ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !this.preventDefault ) {
+ return new jQuery.Event( src );
+ }
- addClass: function( classNames ) {
- jQuery.className.add( this, classNames );
- },
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+ // Event type
+ } else {
+ this.type = src;
+ }
- removeClass: function( classNames ) {
- jQuery.className.remove( this, classNames );
- },
+ // timeStamp is buggy for some events on Firefox(#3843)
+ // So we won't rely on the native value
+ this.timeStamp = now();
+
+ // Mark it as fixed
+ this[ expando ] = true;
+};
- toggleClass: function( classNames, state ) {
- if( typeof state !== "boolean" )
- state = !jQuery.className.has( this, classNames );
- jQuery.className[ state ? "add" : "remove" ]( this, classNames );
+function returnFalse() {
+ return false;
+}
+function returnTrue() {
+ return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+
+ // if preventDefault exists run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+ }
+ // otherwise set the returnValue property of the original event to false (IE)
+ e.returnValue = false;
},
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
- remove: function( selector ) {
- if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
- // Prevent memory leaks
- jQuery( "*", this ).add([this]).each(function(){
- jQuery.event.remove(this);
- jQuery.removeData(this);
- });
- if (this.parentNode)
- this.parentNode.removeChild( this );
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
}
+ // if stopPropagation exists run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
},
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
- empty: function() {
- // Remove element nodes and prevent memory leaks
- jQuery(this).children().remove();
+// Checks if an event happened on an element within another element
+// Used in jQuery.event.special.mouseenter and mouseleave handlers
+var withinElement = function( event ) {
+ // Check if mouse(over|out) are still within the same parent element
+ var parent = event.relatedTarget;
- // Remove any remaining nodes
- while ( this.firstChild )
- this.removeChild( this.firstChild );
- }
-}, function(name, fn){
- jQuery.fn[ name ] = function(){
- return this.each( fn, arguments );
+ // Firefox sometimes assigns relatedTarget a XUL element
+ // which we cannot access the parentNode property of
+ try {
+ // Traverse up the tree
+ while ( parent && parent !== this ) {
+ parent = parent.parentNode;
+ }
+
+ if ( parent !== this ) {
+ // set the correct event type
+ event.type = event.data;
+
+ // handle event if we actually just moused on to a non sub-element
+ jQuery.event.handle.apply( this, arguments );
+ }
+
+ // assuming we've left the element since we most likely mousedover a xul element
+ } catch(e) { }
+},
+
+// In case of event delegation, we only need to rename the event.type,
+// liveHandler will take care of the rest.
+delegate = function( event ) {
+ event.type = event.data;
+ jQuery.event.handle.apply( this, arguments );
+};
+
+// Create mouseenter and mouseleave events
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ setup: function( data ) {
+ jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
+ },
+ teardown: function( data ) {
+ jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
+ }
};
});
-// Helper function used by the dimensions and offset modules
-function num(elem, prop) {
- return elem[0] && parseInt( jQuery.curCSS(elem[0], prop, true), 10 ) || 0;
+// submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function( data, namespaces ) {
+ if ( this.nodeName.toLowerCase() !== "form" ) {
+ jQuery.event.add(this, "click.specialSubmit", function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
+ return trigger( "submit", this, arguments );
+ }
+ });
+
+ jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
+ return trigger( "submit", this, arguments );
+ }
+ });
+
+ } else {
+ return false;
+ }
+ },
+
+ teardown: function( namespaces ) {
+ jQuery.event.remove( this, ".specialSubmit" );
+ }
+ };
+
}
-var expando = "jQuery" + now(), uuid = 0, windowData = {};
-jQuery.extend({
- cache: {},
+// change delegation, happens here so we have bind.
+if ( !jQuery.support.changeBubbles ) {
- data: function( elem, name, data ) {
- elem = elem == window ?
- windowData :
- elem;
+ var formElems = /textarea|input|select/i,
- var id = elem[ expando ];
+ changeFilters,
- // Compute a unique ID for the element
- if ( !id )
- id = elem[ expando ] = ++uuid;
+ getVal = function( elem ) {
+ var type = elem.type, val = elem.value;
- // Only generate the data cache if we're
- // trying to access or manipulate it
- if ( name && !jQuery.cache[ id ] )
- jQuery.cache[ id ] = {};
+ if ( type === "radio" || type === "checkbox" ) {
+ val = elem.checked;
- // Prevent overriding the named cache with undefined values
- if ( data !== undefined )
- jQuery.cache[ id ][ name ] = data;
+ } else if ( type === "select-multiple" ) {
+ val = elem.selectedIndex > -1 ?
+ jQuery.map( elem.options, function( elem ) {
+ return elem.selected;
+ }).join("-") :
+ "";
+
+ } else if ( elem.nodeName.toLowerCase() === "select" ) {
+ val = elem.selectedIndex;
+ }
- // Return the named cache data, or the ID for the element
- return name ?
- jQuery.cache[ id ][ name ] :
- id;
+ return val;
},
- removeData: function( elem, name ) {
- elem = elem == window ?
- windowData :
- elem;
+ testChange = function testChange( e ) {
+ var elem = e.target, data, val;
- var id = elem[ expando ];
+ if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
+ return;
+ }
- // If we want to remove a specific section of the element's data
- if ( name ) {
- if ( jQuery.cache[ id ] ) {
- // Remove the section of cache data
- delete jQuery.cache[ id ][ name ];
+ data = jQuery.data( elem, "_change_data" );
+ val = getVal(elem);
- // If we've removed all the data, remove the element's cache
- name = "";
+ // the current data will be also retrieved by beforeactivate
+ if ( e.type !== "focusout" || elem.type !== "radio" ) {
+ jQuery.data( elem, "_change_data", val );
+ }
+
+ if ( data === undefined || val === data ) {
+ return;
+ }
- for ( name in jQuery.cache[ id ] )
- break;
+ if ( data != null || val ) {
+ e.type = "change";
+ return jQuery.event.trigger( e, arguments[1], elem );
+ }
+ };
- if ( !name )
- jQuery.removeData( elem );
+ jQuery.event.special.change = {
+ filters: {
+ focusout: testChange,
+
+ click: function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
+ return testChange.call( this, e );
+ }
+ },
+
+ // Change has to be called before submit
+ // Keydown will be called before keypress, which is used in submit-event delegation
+ keydown: function( e ) {
+ var elem = e.target, type = elem.type;
+
+ if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
+ (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
+ type === "select-multiple" ) {
+ return testChange.call( this, e );
+ }
+ },
+
+ // Beforeactivate happens also before the previous element is blurred
+ // with this event you can't trigger a change event, but you can store
+ // information/focus[in] is not needed anymore
+ beforeactivate: function( e ) {
+ var elem = e.target;
+ jQuery.data( elem, "_change_data", getVal(elem) );
}
+ },
- // Otherwise, we want to remove all of the element's data
- } else {
- // Clean up the element expando
- try {
- delete elem[ expando ];
- } catch(e){
- // IE has trouble directly removing the expando
- // but it's ok with using removeAttribute
- if ( elem.removeAttribute )
- elem.removeAttribute( expando );
+ setup: function( data, namespaces ) {
+ if ( this.type === "file" ) {
+ return false;
}
- // Completely remove the data cache
- delete jQuery.cache[ id ];
+ for ( var type in changeFilters ) {
+ jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
+ }
+
+ return formElems.test( this.nodeName );
+ },
+
+ teardown: function( namespaces ) {
+ jQuery.event.remove( this, ".specialChange" );
+
+ return formElems.test( this.nodeName );
}
- },
- queue: function( elem, type, data ) {
- if ( elem ){
+ };
- type = (type || "fx") + "queue";
+ changeFilters = jQuery.event.special.change.filters;
+}
- var q = jQuery.data( elem, type );
+function trigger( type, elem, args ) {
+ args[0].type = type;
+ return jQuery.event.handle.apply( elem, args );
+}
- if ( !q || jQuery.isArray(data) )
- q = jQuery.data( elem, type, jQuery.makeArray(data) );
- else if( data )
- q.push( data );
+// Create "bubbling" focus and blur events
+if ( document.addEventListener ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ this.addEventListener( orig, handler, true );
+ },
+ teardown: function() {
+ this.removeEventListener( orig, handler, true );
+ }
+ };
+ function handler( e ) {
+ e = jQuery.event.fix( e );
+ e.type = fix;
+ return jQuery.event.handle.call( this, e );
}
- return q;
- },
+ });
+}
- dequeue: function( elem, type ){
- var queue = jQuery.queue( elem, type ),
- fn = queue.shift();
+jQuery.each(["bind", "one"], function( i, name ) {
+ jQuery.fn[ name ] = function( type, data, fn ) {
+ // Handle object literals
+ if ( typeof type === "object" ) {
+ for ( var key in type ) {
+ this[ name ](key, data, type[key], fn);
+ }
+ return this;
+ }
+
+ if ( jQuery.isFunction( data ) ) {
+ fn = data;
+ data = undefined;
+ }
- if( !type || type === "fx" )
- fn = queue[0];
+ var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
+ jQuery( this ).unbind( event, handler );
+ return fn.apply( this, arguments );
+ }) : fn;
- if( fn !== undefined )
- fn.call(elem);
- }
+ if ( type === "unload" && name !== "one" ) {
+ this.one( type, data, fn );
+
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ jQuery.event.add( this[i], type, handler, data );
+ }
+ }
+
+ return this;
+ };
});
jQuery.fn.extend({
- data: function( key, value ){
- var parts = key.split(".");
- parts[1] = parts[1] ? "." + parts[1] : "";
-
- if ( value === undefined ) {
- var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+ unbind: function( type, fn ) {
+ // Handle object literals
+ if ( typeof type === "object" && !type.preventDefault ) {
+ for ( var key in type ) {
+ this.unbind(key, type[key]);
+ }
- if ( data === undefined && this.length )
- data = jQuery.data( this[0], key );
+ } else {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ jQuery.event.remove( this[i], type, fn );
+ }
+ }
- return data === undefined && parts[1] ?
- this.data( parts[0] ) :
- data;
- } else
- return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
- jQuery.data( this, key, value );
- });
+ return this;
},
-
- removeData: function( key ){
- return this.each(function(){
- jQuery.removeData( this, key );
+
+ delegate: function( selector, types, data, fn ) {
+ return this.live( types, data, fn, selector );
+ },
+
+ undelegate: function( selector, types, fn ) {
+ if ( arguments.length === 0 ) {
+ return this.unbind( "live" );
+
+ } else {
+ return this.die( types, null, fn, selector );
+ }
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
});
},
- queue: function(type, data){
- if ( typeof type !== "string" ) {
- data = type;
- type = "fx";
+
+ triggerHandler: function( type, data ) {
+ if ( this[0] ) {
+ var event = jQuery.Event( type );
+ event.preventDefault();
+ event.stopPropagation();
+ jQuery.event.trigger( event, data, this[0] );
+ return event.result;
}
+ },
- if ( data === undefined )
- return jQuery.queue( this[0], type );
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments, i = 1;
- return this.each(function(){
- var queue = jQuery.queue( this, type, data );
+ // link all the functions, so any of them can unbind this click handler
+ while ( i < args.length ) {
+ jQuery.proxy( fn, args[ i++ ] );
+ }
- if( type == "fx" && queue.length == 1 )
- queue[0].call(this);
- });
+ return this.click( jQuery.proxy( fn, function( event ) {
+ // Figure out which function to execute
+ var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ lastToggle ].apply( this, arguments ) || false;
+ }));
},
- dequeue: function(type){
- return this.each(function(){
- jQuery.dequeue( this, type );
- });
+
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
}
-});/*!
- * Sizzle CSS Selector Engine - v0.9.3
+});
+
+var liveMap = {
+ focus: "focusin",
+ blur: "focusout",
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+};
+
+jQuery.each(["live", "die"], function( i, name ) {
+ jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
+ var type, i = 0, match, namespaces, preType,
+ selector = origSelector || this.selector,
+ context = origSelector ? this : jQuery( this.context );
+
+ if ( jQuery.isFunction( data ) ) {
+ fn = data;
+ data = undefined;
+ }
+
+ types = (types || "").split(" ");
+
+ while ( (type = types[ i++ ]) != null ) {
+ match = rnamespaces.exec( type );
+ namespaces = "";
+
+ if ( match ) {
+ namespaces = match[0];
+ type = type.replace( rnamespaces, "" );
+ }
+
+ if ( type === "hover" ) {
+ types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
+ continue;
+ }
+
+ preType = type;
+
+ if ( type === "focus" || type === "blur" ) {
+ types.push( liveMap[ type ] + namespaces );
+ type = type + namespaces;
+
+ } else {
+ type = (liveMap[ type ] || type) + namespaces;
+ }
+
+ if ( name === "live" ) {
+ // bind live handler
+ context.each(function(){
+ jQuery.event.add( this, liveConvert( type, selector ),
+ { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
+ });
+
+ } else {
+ // unbind live handler
+ context.unbind( liveConvert( type, selector ), fn );
+ }
+ }
+
+ return this;
+ }
+});
+
+function liveHandler( event ) {
+ var stop, elems = [], selectors = [], args = arguments,
+ related, match, handleObj, elem, j, i, l, data,
+ events = jQuery.data( this, "events" );
+
+ // Make sure we avoid non-left-click bubbling in Firefox (#3861)
+ if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
+ return;
+ }
+
+ event.liveFired = this;
+
+ var live = events.live.slice(0);
+
+ for ( j = 0; j < live.length; j++ ) {
+ handleObj = live[j];
+
+ if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
+ selectors.push( handleObj.selector );
+
+ } else {
+ live.splice( j--, 1 );
+ }
+ }
+
+ match = jQuery( event.target ).closest( selectors, event.currentTarget );
+
+ for ( i = 0, l = match.length; i < l; i++ ) {
+ for ( j = 0; j < live.length; j++ ) {
+ handleObj = live[j];
+
+ if ( match[i].selector === handleObj.selector ) {
+ elem = match[i].elem;
+ related = null;
+
+ // Those two events require additional checking
+ if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
+ related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
+ }
+
+ if ( !related || related !== elem ) {
+ elems.push({ elem: elem, handleObj: handleObj });
+ }
+ }
+ }
+ }
+
+ for ( i = 0, l = elems.length; i < l; i++ ) {
+ match = elems[i];
+ event.currentTarget = match.elem;
+ event.data = match.handleObj.data;
+ event.handleObj = match.handleObj;
+
+ if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) {
+ stop = false;
+ break;
+ }
+ }
+
+ return stop;
+}
+
+function liveConvert( type, selector ) {
+ return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
+}
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( fn ) {
+ return fn ? this.bind( name, fn ) : this.trigger( name );
+ };
+
+ if ( jQuery.attrFn ) {
+ jQuery.attrFn[ name ] = true;
+ }
+});
+
+// Prevent memory leaks in IE
+// Window isn't included so as not to unbind existing unload events
+// More info:
+// - http://isaacschlueter.com/2006/10/msie-memory-leaks/
+if ( window.attachEvent && !window.addEventListener ) {
+ window.attachEvent("onunload", function() {
+ for ( var id in jQuery.cache ) {
+ if ( jQuery.cache[ id ].handle ) {
+ // Try/Catch is to handle iframes being unloaded, see #4280
+ try {
+ jQuery.event.remove( jQuery.cache[ id ].handle.elem );
+ } catch(e) {}
+ }
+ }
+ });
+}
+/*!
+ * Sizzle CSS Selector Engine - v1.0
* Copyright 2009, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
* More information: http://sizzlejs.com/
*/
(function(){
-var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
done = 0,
- toString = Object.prototype.toString;
+ toString = Object.prototype.toString,
+ hasDuplicate = false,
+ baseHasDuplicate = true;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+// Thus far that includes Google Chrome.
+[0, 0].sort(function(){
+ baseHasDuplicate = false;
+ return 0;
+});
var Sizzle = function(selector, context, results, seed) {
results = results || [];
- context = context || document;
+ var origContext = context = context || document;
- if ( context.nodeType !== 1 && context.nodeType !== 9 )
+ if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
return [];
-
+ }
+
if ( !selector || typeof selector !== "string" ) {
return results;
}
- var parts = [], m, set, checkSet, check, mode, extra, prune = true;
-
+ var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context),
+ soFar = selector;
+
// Reset the position of the chunker regexp (start from head)
- chunker.lastIndex = 0;
-
- while ( (m = chunker.exec(selector)) !== null ) {
+ while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
+ soFar = m[3];
+
parts.push( m[1] );
-
+
if ( m[2] ) {
- extra = RegExp.rightContext;
+ extra = m[3];
break;
}
}
@@ -1461,38 +2682,51 @@ var Sizzle = function(selector, context, results, seed) {
while ( parts.length ) {
selector = parts.shift();
- if ( Expr.relative[ selector ] )
+ if ( Expr.relative[ selector ] ) {
selector += parts.shift();
-
+ }
+
set = posProcess( selector, set );
}
}
} else {
- var ret = seed ?
- { expr: parts.pop(), set: makeArray(seed) } :
- Sizzle.find( parts.pop(), parts.length === 1 && context.parentNode ? context.parentNode : context, isXML(context) );
- set = Sizzle.filter( ret.expr, ret.set );
-
- if ( parts.length > 0 ) {
- checkSet = makeArray(set);
- } else {
- prune = false;
+ // Take a shortcut and set the context if the root selector is an ID
+ // (but not if it'll be faster if the inner selector is an ID)
+ if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+ Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+ var ret = Sizzle.find( parts.shift(), context, contextXML );
+ context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
}
- while ( parts.length ) {
- var cur = parts.pop(), pop = cur;
+ if ( context ) {
+ var ret = seed ?
+ { expr: parts.pop(), set: makeArray(seed) } :
+ Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
+ set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
- if ( !Expr.relative[ cur ] ) {
- cur = "";
+ if ( parts.length > 0 ) {
+ checkSet = makeArray(set);
} else {
- pop = parts.pop();
+ prune = false;
}
- if ( pop == null ) {
- pop = context;
- }
+ while ( parts.length ) {
+ var cur = parts.pop(), pop = cur;
+
+ if ( !Expr.relative[ cur ] ) {
+ cur = "";
+ } else {
+ pop = parts.pop();
+ }
- Expr.relative[ cur ]( checkSet, pop, isXML(context) );
+ if ( pop == null ) {
+ pop = context;
+ }
+
+ Expr.relative[ cur ]( checkSet, pop, contextXML );
+ }
+ } else {
+ checkSet = parts = [];
}
}
@@ -1501,13 +2735,13 @@ var Sizzle = function(selector, context, results, seed) {
}
if ( !checkSet ) {
- throw "Syntax error, unrecognized expression: " + (cur || selector);
+ Sizzle.error( cur || selector );
}
if ( toString.call(checkSet) === "[object Array]" ) {
if ( !prune ) {
results.push.apply( results, checkSet );
- } else if ( context.nodeType === 1 ) {
+ } else if ( context && context.nodeType === 1 ) {
for ( var i = 0; checkSet[i] != null; i++ ) {
if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
results.push( set[i] );
@@ -1525,17 +2759,22 @@ var Sizzle = function(selector, context, results, seed) {
}
if ( extra ) {
- Sizzle( extra, context, results, seed );
+ Sizzle( extra, origContext, results, seed );
+ Sizzle.uniqueSort( results );
+ }
- if ( sortOrder ) {
- hasDuplicate = false;
- results.sort(sortOrder);
+ return results;
+};
- if ( hasDuplicate ) {
- for ( var i = 1; i < results.length; i++ ) {
- if ( results[i] === results[i-1] ) {
- results.splice(i--, 1);
- }
+Sizzle.uniqueSort = function(results){
+ if ( sortOrder ) {
+ hasDuplicate = baseHasDuplicate;
+ results.sort(sortOrder);
+
+ if ( hasDuplicate ) {
+ for ( var i = 1; i < results.length; i++ ) {
+ if ( results[i] === results[i-1] ) {
+ results.splice(i--, 1);
}
}
}
@@ -1557,9 +2796,10 @@ Sizzle.find = function(expr, context, isXML){
for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
var type = Expr.order[i], match;
-
- if ( (match = Expr.match[ type ].exec( expr )) ) {
- var left = RegExp.leftContext;
+
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+ var left = match[1];
+ match.splice(1,1);
if ( left.substr( left.length - 1 ) !== "\\" ) {
match[1] = (match[1] || "").replace(/\\/g, "");
@@ -1585,11 +2825,17 @@ Sizzle.filter = function(expr, set, inplace, not){
while ( expr && set.length ) {
for ( var type in Expr.filter ) {
- if ( (match = Expr.match[ type ].exec( expr )) != null ) {
- var filter = Expr.filter[ type ], found, item;
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+ var filter = Expr.filter[ type ], found, item, left = match[1];
anyFound = false;
- if ( curLoop == result ) {
+ match.splice(1,1);
+
+ if ( left.substr( left.length - 1 ) === "\\" ) {
+ continue;
+ }
+
+ if ( curLoop === result ) {
result = [];
}
@@ -1640,9 +2886,9 @@ Sizzle.filter = function(expr, set, inplace, not){
}
// Improper expression
- if ( expr == old ) {
+ if ( expr === old ) {
if ( anyFound == null ) {
- throw "Syntax error, unrecognized expression: " + expr;
+ Sizzle.error( expr );
} else {
break;
}
@@ -1654,18 +2900,23 @@ Sizzle.filter = function(expr, set, inplace, not){
return curLoop;
};
+Sizzle.error = function( msg ) {
+ throw "Syntax error, unrecognized expression: " + msg;
+};
+
var Expr = Sizzle.selectors = {
order: [ "ID", "NAME", "TAG" ],
match: {
- ID: /#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
- CLASS: /\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,
- NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,
- ATTR: /\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
- TAG: /^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,
+ ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
+ CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
+ TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
- PSEUDO: /:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/
+ PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
},
+ leftMatch: {},
attrMap: {
"class": "className",
"for": "htmlFor"
@@ -1676,20 +2927,20 @@ var Expr = Sizzle.selectors = {
}
},
relative: {
- "+": function(checkSet, part, isXML){
+ "+": function(checkSet, part){
var isPartStr = typeof part === "string",
isTag = isPartStr && !/\W/.test(part),
isPartStrNotTag = isPartStr && !isTag;
- if ( isTag && !isXML ) {
- part = part.toUpperCase();
+ if ( isTag ) {
+ part = part.toLowerCase();
}
for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
if ( (elem = checkSet[i]) ) {
while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
- checkSet[i] = isPartStrNotTag || elem && elem.nodeName === part ?
+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
elem || false :
elem === part;
}
@@ -1699,17 +2950,17 @@ var Expr = Sizzle.selectors = {
Sizzle.filter( part, checkSet, true );
}
},
- ">": function(checkSet, part, isXML){
+ ">": function(checkSet, part){
var isPartStr = typeof part === "string";
if ( isPartStr && !/\W/.test(part) ) {
- part = isXML ? part : part.toUpperCase();
+ part = part.toLowerCase();
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
if ( elem ) {
var parent = elem.parentNode;
- checkSet[i] = parent.nodeName === part ? parent : false;
+ checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
}
}
} else {
@@ -1730,8 +2981,8 @@ var Expr = Sizzle.selectors = {
"": function(checkSet, part, isXML){
var doneName = done++, checkFn = dirCheck;
- if ( !part.match(/\W/) ) {
- var nodeCheck = part = isXML ? part : part.toUpperCase();
+ if ( typeof part === "string" && !/\W/.test(part) ) {
+ var nodeCheck = part = part.toLowerCase();
checkFn = dirNodeCheck;
}
@@ -1740,8 +2991,8 @@ var Expr = Sizzle.selectors = {
"~": function(checkSet, part, isXML){
var doneName = done++, checkFn = dirCheck;
- if ( typeof part === "string" && !part.match(/\W/) ) {
- var nodeCheck = part = isXML ? part : part.toUpperCase();
+ if ( typeof part === "string" && !/\W/.test(part) ) {
+ var nodeCheck = part = part.toLowerCase();
checkFn = dirNodeCheck;
}
@@ -1755,7 +3006,7 @@ var Expr = Sizzle.selectors = {
return m ? [m] : [];
}
},
- NAME: function(match, context, isXML){
+ NAME: function(match, context){
if ( typeof context.getElementsByName !== "undefined" ) {
var ret = [], results = context.getElementsByName(match[1]);
@@ -1782,9 +3033,10 @@ var Expr = Sizzle.selectors = {
for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
if ( elem ) {
- if ( not ^ (elem.className && (" " + elem.className + " ").indexOf(match) >= 0) ) {
- if ( !inplace )
+ if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
+ if ( !inplace ) {
result.push( elem );
+ }
} else if ( inplace ) {
curLoop[i] = false;
}
@@ -1797,14 +3049,13 @@ var Expr = Sizzle.selectors = {
return match[1].replace(/\\/g, "");
},
TAG: function(match, curLoop){
- for ( var i = 0; curLoop[i] === false; i++ ){}
- return curLoop[i] && isXML(curLoop[i]) ? match[1] : match[1].toUpperCase();
+ return match[1].toLowerCase();
},
CHILD: function(match){
- if ( match[1] == "nth" ) {
+ if ( match[1] === "nth" ) {
// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
- match[2] == "even" && "2n" || match[2] == "odd" && "2n+1" ||
+ match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
// calculate the numbers (first)n+(last) including if they are negative
@@ -1819,7 +3070,7 @@ var Expr = Sizzle.selectors = {
},
ATTR: function(match, curLoop, inplace, result, not, isXML){
var name = match[1].replace(/\\/g, "");
-
+
if ( !isXML && Expr.attrMap[name] ) {
match[1] = Expr.attrMap[name];
}
@@ -1833,7 +3084,7 @@ var Expr = Sizzle.selectors = {
PSEUDO: function(match, curLoop, inplace, result, not){
if ( match[1] === "not" ) {
// If we're dealing with a complex expression, or a simple one
- if ( match[3].match(chunker).length > 1 || /^\w/.test(match[3]) ) {
+ if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
match[3] = Sizzle(match[3], null, null, curLoop);
} else {
var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
@@ -1845,7 +3096,7 @@ var Expr = Sizzle.selectors = {
} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
return true;
}
-
+
return match;
},
POS: function(match){
@@ -1906,7 +3157,7 @@ var Expr = Sizzle.selectors = {
return "reset" === elem.type;
},
button: function(elem){
- return "button" === elem.type || elem.nodeName.toUpperCase() === "BUTTON";
+ return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
},
input: function(elem){
return /input|select|textarea|button/i.test(elem.nodeName);
@@ -1932,10 +3183,10 @@ var Expr = Sizzle.selectors = {
return i > match[3] - 0;
},
nth: function(elem, i, match){
- return match[3] - 0 == i;
+ return match[3] - 0 === i;
},
eq: function(elem, i, match){
- return match[3] - 0 == i;
+ return match[3] - 0 === i;
}
},
filter: {
@@ -1945,7 +3196,7 @@ var Expr = Sizzle.selectors = {
if ( filter ) {
return filter( elem, i, match, array );
} else if ( name === "contains" ) {
- return (elem.textContent || elem.innerText || "").indexOf(match[3]) >= 0;
+ return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
} else if ( name === "not" ) {
var not = match[3];
@@ -1956,6 +3207,8 @@ var Expr = Sizzle.selectors = {
}
return true;
+ } else {
+ Sizzle.error( "Syntax error, unrecognized expression: " + name );
}
},
CHILD: function(elem, match){
@@ -1963,41 +3216,47 @@ var Expr = Sizzle.selectors = {
switch (type) {
case 'only':
case 'first':
- while (node = node.previousSibling) {
- if ( node.nodeType === 1 ) return false;
+ while ( (node = node.previousSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ if ( type === "first" ) {
+ return true;
}
- if ( type == 'first') return true;
node = elem;
case 'last':
- while (node = node.nextSibling) {
- if ( node.nodeType === 1 ) return false;
+ while ( (node = node.nextSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
}
return true;
case 'nth':
var first = match[2], last = match[3];
- if ( first == 1 && last == 0 ) {
+ if ( first === 1 && last === 0 ) {
return true;
}
-
+
var doneName = match[0],
parent = elem.parentNode;
-
+
if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
var count = 0;
for ( node = parent.firstChild; node; node = node.nextSibling ) {
if ( node.nodeType === 1 ) {
node.nodeIndex = ++count;
}
- }
+ }
parent.sizcache = doneName;
}
-
+
var diff = elem.nodeIndex - last;
- if ( first == 0 ) {
- return diff == 0;
+ if ( first === 0 ) {
+ return diff === 0;
} else {
- return ( diff % first == 0 && diff / first >= 0 );
+ return ( diff % first === 0 && diff / first >= 0 );
}
}
},
@@ -2005,7 +3264,7 @@ var Expr = Sizzle.selectors = {
return elem.nodeType === 1 && elem.getAttribute("id") === match;
},
TAG: function(elem, match){
- return (match === "*" && elem.nodeType === 1) || elem.nodeName === match;
+ return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
},
CLASS: function(elem, match){
return (" " + (elem.className || elem.getAttribute("class")) + " ")
@@ -2033,7 +3292,7 @@ var Expr = Sizzle.selectors = {
!check ?
value && result !== false :
type === "!=" ?
- value != check :
+ value !== check :
type === "^=" ?
value.indexOf(check) === 0 :
type === "$=" ?
@@ -2055,24 +3314,29 @@ var Expr = Sizzle.selectors = {
var origPOS = Expr.match.POS;
for ( var type in Expr.match ) {
- Expr.match[ type ] = RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
+ Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
+ Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){
+ return "\\" + (num - 0 + 1);
+ }));
}
var makeArray = function(array, results) {
- array = Array.prototype.slice.call( array );
+ array = Array.prototype.slice.call( array, 0 );
if ( results ) {
results.push.apply( results, array );
return results;
}
-
+
return array;
};
// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
try {
- Array.prototype.slice.call( document.documentElement.childNodes );
+ Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
// Provide a fallback method if it does not work
} catch(e){
@@ -2101,6 +3365,13 @@ var sortOrder;
if ( document.documentElement.compareDocumentPosition ) {
sortOrder = function( a, b ) {
+ if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+ if ( a == b ) {
+ hasDuplicate = true;
+ }
+ return a.compareDocumentPosition ? -1 : 1;
+ }
+
var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
if ( ret === 0 ) {
hasDuplicate = true;
@@ -2109,6 +3380,13 @@ if ( document.documentElement.compareDocumentPosition ) {
};
} else if ( "sourceIndex" in document.documentElement ) {
sortOrder = function( a, b ) {
+ if ( !a.sourceIndex || !b.sourceIndex ) {
+ if ( a == b ) {
+ hasDuplicate = true;
+ }
+ return a.sourceIndex ? -1 : 1;
+ }
+
var ret = a.sourceIndex - b.sourceIndex;
if ( ret === 0 ) {
hasDuplicate = true;
@@ -2117,11 +3395,18 @@ if ( document.documentElement.compareDocumentPosition ) {
};
} else if ( document.createRange ) {
sortOrder = function( a, b ) {
+ if ( !a.ownerDocument || !b.ownerDocument ) {
+ if ( a == b ) {
+ hasDuplicate = true;
+ }
+ return a.ownerDocument ? -1 : 1;
+ }
+
var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
- aRange.selectNode(a);
- aRange.collapse(true);
- bRange.selectNode(b);
- bRange.collapse(true);
+ aRange.setStart(a, 0);
+ aRange.setEnd(a, 0);
+ bRange.setStart(b, 0);
+ bRange.setEnd(b, 0);
var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
if ( ret === 0 ) {
hasDuplicate = true;
@@ -2130,13 +3415,33 @@ if ( document.documentElement.compareDocumentPosition ) {
};
}
+// Utility function for retreiving the text value of an array of DOM nodes
+function getText( elems ) {
+ var ret = "", elem;
+
+ for ( var i = 0; elems[i]; i++ ) {
+ elem = elems[i];
+
+ // Get the text from text nodes and CDATA nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
+ ret += elem.nodeValue;
+
+ // Traverse everything else, except comment nodes
+ } else if ( elem.nodeType !== 8 ) {
+ ret += getText( elem.childNodes );
+ }
+ }
+
+ return ret;
+}
+
// Check to see if the browser returns elements by name when
// querying by getElementById (and provide a workaround)
(function(){
// We're going to inject a fake input element with a specified name
- var form = document.createElement("form"),
+ var form = document.createElement("div"),
id = "script" + (new Date).getTime();
- form.innerHTML = "<input name='" + id + "'/>";
+ form.innerHTML = "<a name='" + id + "'/>";
// Inject it into the root element, check its status, and remove it quickly
var root = document.documentElement;
@@ -2144,7 +3449,7 @@ if ( document.documentElement.compareDocumentPosition ) {
// The workaround has to do additional checks after a getElementById
// Which slows things down for other browsers (hence the branching)
- if ( !!document.getElementById( id ) ) {
+ if ( document.getElementById( id ) ) {
Expr.find.ID = function(match, context, isXML){
if ( typeof context.getElementById !== "undefined" && !isXML ) {
var m = context.getElementById(match[1]);
@@ -2159,6 +3464,7 @@ if ( document.documentElement.compareDocumentPosition ) {
}
root.removeChild( form );
+ root = form = null; // release memory in IE
})();
(function(){
@@ -2199,69 +3505,75 @@ if ( document.documentElement.compareDocumentPosition ) {
return elem.getAttribute("href", 2);
};
}
-})();
-
-if ( document.querySelectorAll ) (function(){
- var oldSizzle = Sizzle, div = document.createElement("div");
- div.innerHTML = "<p class='TEST'></p>";
- // Safari can't handle uppercase or unicode characters when
- // in quirks mode.
- if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
- return;
- }
+ div = null; // release memory in IE
+})();
- Sizzle = function(query, context, extra, seed){
- context = context || document;
+if ( document.querySelectorAll ) {
+ (function(){
+ var oldSizzle = Sizzle, div = document.createElement("div");
+ div.innerHTML = "<p class='TEST'></p>";
- // Only use querySelectorAll on non-XML documents
- // (ID selectors don't work in non-HTML documents)
- if ( !seed && context.nodeType === 9 && !isXML(context) ) {
- try {
- return makeArray( context.querySelectorAll(query), extra );
- } catch(e){}
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode.
+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+ return;
}
+
+ Sizzle = function(query, context, extra, seed){
+ context = context || document;
+
+ // Only use querySelectorAll on non-XML documents
+ // (ID selectors don't work in non-HTML documents)
+ if ( !seed && context.nodeType === 9 && !isXML(context) ) {
+ try {
+ return makeArray( context.querySelectorAll(query), extra );
+ } catch(e){}
+ }
+
+ return oldSizzle(query, context, extra, seed);
+ };
- return oldSizzle(query, context, extra, seed);
- };
+ for ( var prop in oldSizzle ) {
+ Sizzle[ prop ] = oldSizzle[ prop ];
+ }
- Sizzle.find = oldSizzle.find;
- Sizzle.filter = oldSizzle.filter;
- Sizzle.selectors = oldSizzle.selectors;
- Sizzle.matches = oldSizzle.matches;
-})();
+ div = null; // release memory in IE
+ })();
+}
-if ( document.getElementsByClassName && document.documentElement.getElementsByClassName ) (function(){
+(function(){
var div = document.createElement("div");
+
div.innerHTML = "<div class='test e'></div><div class='test'></div>";
// Opera can't find a second classname (in 9.6)
- if ( div.getElementsByClassName("e").length === 0 )
+ // Also, make sure that getElementsByClassName actually exists
+ if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
return;
+ }
// Safari caches class attributes, doesn't catch changes (in 3.2)
div.lastChild.className = "e";
- if ( div.getElementsByClassName("e").length === 1 )
+ if ( div.getElementsByClassName("e").length === 1 ) {
return;
-
+ }
+
Expr.order.splice(1, 0, "CLASS");
Expr.find.CLASS = function(match, context, isXML) {
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
return context.getElementsByClassName(match[1]);
}
};
+
+ div = null; // release memory in IE
})();
function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
- var sibDir = dir == "previousSibling" && !isXML;
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
if ( elem ) {
- if ( sibDir && elem.nodeType === 1 ){
- elem.sizcache = doneName;
- elem.sizset = i;
- }
elem = elem[dir];
var match = false;
@@ -2276,7 +3588,7 @@ function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
elem.sizset = i;
}
- if ( elem.nodeName === cur ) {
+ if ( elem.nodeName.toLowerCase() === cur ) {
match = elem;
break;
}
@@ -2290,14 +3602,9 @@ function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
}
function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
- var sibDir = dir == "previousSibling" && !isXML;
for ( var i = 0, l = checkSet.length; i < l; i++ ) {
var elem = checkSet[i];
if ( elem ) {
- if ( sibDir && elem.nodeType === 1 ) {
- elem.sizcache = doneName;
- elem.sizset = i;
- }
elem = elem[dir];
var match = false;
@@ -2332,15 +3639,17 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
}
}
-var contains = document.compareDocumentPosition ? function(a, b){
- return a.compareDocumentPosition(b) & 16;
+var contains = document.compareDocumentPosition ? function(a, b){
+ return !!(a.compareDocumentPosition(b) & 16);
} : function(a, b){
return a !== b && (a.contains ? a.contains(b) : true);
};
var isXML = function(elem){
- return elem.nodeType === 9 && elem.documentElement.nodeName !== "HTML" ||
- !!elem.ownerDocument && isXML( elem.ownerDocument );
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
};
var posProcess = function(selector, context){
@@ -2365,872 +3674,1122 @@ var posProcess = function(selector, context){
// EXPOSE
jQuery.find = Sizzle;
-jQuery.filter = Sizzle.filter;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = getText;
+jQuery.isXMLDoc = isXML;
+jQuery.contains = contains;
-Sizzle.selectors.filters.hidden = function(elem){
- return elem.offsetWidth === 0 || elem.offsetHeight === 0;
-};
+return;
-Sizzle.selectors.filters.visible = function(elem){
- return elem.offsetWidth > 0 || elem.offsetHeight > 0;
-};
+window.Sizzle = Sizzle;
-Sizzle.selectors.filters.animated = function(elem){
- return jQuery.grep(jQuery.timers, function(fn){
- return elem === fn.elem;
- }).length;
-};
+})();
+var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+ // Note: This RegExp should be improved, or likely pulled from Sizzle
+ rmultiselector = /,/,
+ slice = Array.prototype.slice;
+
+// Implement the identical functionality for filter and not
+var winnow = function( elements, qualifier, keep ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ return !!qualifier.call( elem, i, elem ) === keep;
+ });
-jQuery.multiFilter = function( expr, elems, not ) {
- if ( not ) {
- expr = ":not(" + expr + ")";
- }
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ return (elem === qualifier) === keep;
+ });
- return Sizzle.matches(expr, elems);
-};
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
-jQuery.dir = function( elem, dir ){
- var matched = [], cur = elem[dir];
- while ( cur && cur != document ) {
- if ( cur.nodeType == 1 )
- matched.push( cur );
- cur = cur[dir];
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
}
- return matched;
+
+ return jQuery.grep(elements, function( elem, i ) {
+ return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
+ });
};
-jQuery.nth = function(cur, result, dir, elem){
- result = result || 1;
- var num = 0;
+jQuery.fn.extend({
+ find: function( selector ) {
+ var ret = this.pushStack( "", "find", selector ), length = 0;
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ length = ret.length;
+ jQuery.find( selector, this[i], ret );
+
+ if ( i > 0 ) {
+ // Make sure that the results are unique
+ for ( var n = length; n < ret.length; n++ ) {
+ for ( var r = 0; r < length; r++ ) {
+ if ( ret[r] === ret[n] ) {
+ ret.splice(n--, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
- for ( ; cur; cur = cur[dir] )
- if ( cur.nodeType == 1 && ++num == result )
- break;
+ return ret;
+ },
- return cur;
-};
+ has: function( target ) {
+ var targets = jQuery( target );
+ return this.filter(function() {
+ for ( var i = 0, l = targets.length; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
-jQuery.sibling = function(n, elem){
- var r = [];
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false), "not", selector);
+ },
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType == 1 && n != elem )
- r.push( n );
- }
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true), "filter", selector );
+ },
+
+ is: function( selector ) {
+ return !!selector && jQuery.filter( selector, this ).length > 0;
+ },
- return r;
-};
+ closest: function( selectors, context ) {
+ if ( jQuery.isArray( selectors ) ) {
+ var ret = [], cur = this[0], match, matches = {}, selector;
-return;
+ if ( cur && selectors.length ) {
+ for ( var i = 0, l = selectors.length; i < l; i++ ) {
+ selector = selectors[i];
-window.Sizzle = Sizzle;
+ if ( !matches[selector] ) {
+ matches[selector] = jQuery.expr.match.POS.test( selector ) ?
+ jQuery( selector, context || this.context ) :
+ selector;
+ }
+ }
-})();
-/*
- * A number of helper functions used for managing events.
- * Many of the ideas behind this code originated from
- * Dean Edwards' addEvent library.
- */
-jQuery.event = {
+ while ( cur && cur.ownerDocument && cur !== context ) {
+ for ( selector in matches ) {
+ match = matches[selector];
- // Bind an event to an element
- // Original by Dean Edwards
- add: function(elem, types, handler, data) {
- if ( elem.nodeType == 3 || elem.nodeType == 8 )
- return;
+ if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
+ ret.push({ selector: selector, elem: cur });
+ delete matches[selector];
+ }
+ }
+ cur = cur.parentNode;
+ }
+ }
- // For whatever reason, IE has trouble passing the window object
- // around, causing it to be cloned in the process
- if ( elem.setInterval && elem != window )
- elem = window;
+ return ret;
+ }
- // Make sure that the function being executed has a unique ID
- if ( !handler.guid )
- handler.guid = this.guid++;
+ var pos = jQuery.expr.match.POS.test( selectors ) ?
+ jQuery( selectors, context || this.context ) : null;
- // if data is passed, bind to handler
- if ( data !== undefined ) {
- // Create temporary function pointer to original handler
- var fn = handler;
+ return this.map(function( i, cur ) {
+ while ( cur && cur.ownerDocument && cur !== context ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {
+ return cur;
+ }
+ cur = cur.parentNode;
+ }
+ return null;
+ });
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+ if ( !elem || typeof elem === "string" ) {
+ return jQuery.inArray( this[0],
+ // If it receives a string, the selector is used
+ // If it receives nothing, the siblings are used
+ elem ? jQuery( elem ) : this.parent().children() );
+ }
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context || this.context ) :
+ jQuery.makeArray( selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+ all :
+ jQuery.unique( all ) );
+ },
+
+ andSelf: function() {
+ return this.add( this.prevObject );
+ }
+});
- // Create unique handler function, wrapped around original handler
- handler = this.proxy( fn );
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
- // Store data in unique handler
- handler.data = data;
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return jQuery.nth( elem, 2, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return jQuery.nth( elem, 2, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( elem.parentNode.firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.makeArray( elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
}
- // Init the element's event structure
- var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
- handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
- // Handle the second event of a trigger and when
- // an event is called after a page has unloaded
- return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
- jQuery.event.handle.apply(arguments.callee.elem, arguments) :
- undefined;
- });
- // Add elem as a property of the handle function
- // This is to prevent a memory leak with non-native
- // event in IE.
- handle.elem = elem;
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
- // Handle multiple events separated by a space
- // jQuery(...).bind("mouseover mouseout", fn);
- jQuery.each(types.split(/\s+/), function(index, type) {
- // Namespaced event handlers
- var namespaces = type.split(".");
- type = namespaces.shift();
- handler.type = namespaces.slice().sort().join(".");
+ ret = this.length > 1 ? jQuery.unique( ret ) : ret;
- // Get the current list of functions bound to this event
- var handlers = events[type];
+ if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
- if ( jQuery.event.specialAll[type] )
- jQuery.event.specialAll[type].setup.call(elem, data, namespaces);
+ return this.pushStack( ret, name, slice.call(arguments).join(",") );
+ };
+});
- // Init the event handler queue
- if (!handlers) {
- handlers = events[type] = {};
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
- // Check for a special event handler
- // Only use addEventListener/attachEvent if the special
- // events handler returns false
- if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {
- // Bind the global event handler to the element
- if (elem.addEventListener)
- elem.addEventListener(type, handle, false);
- else if (elem.attachEvent)
- elem.attachEvent("on" + type, handle);
- }
+ return jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [], cur = elem[dir];
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
}
+ cur = cur[dir];
+ }
+ return matched;
+ },
- // Add the function to the element's handler list
- handlers[handler.guid] = handler;
+ nth: function( cur, result, dir, elem ) {
+ result = result || 1;
+ var num = 0;
- // Keep track of which events have been used, for global triggering
- jQuery.event.global[type] = true;
- });
+ for ( ; cur; cur = cur[dir] ) {
+ if ( cur.nodeType === 1 && ++num === result ) {
+ break;
+ }
+ }
- // Nullify elem to prevent memory leaks in IE
- elem = null;
+ return cur;
},
- guid: 1,
- global: {},
+ sibling: function( n, elem ) {
+ var r = [];
- // Detach an event or set of events from an element
- remove: function(elem, types, handler) {
- // don't do events on text and comment nodes
- if ( elem.nodeType == 3 || elem.nodeType == 8 )
- return;
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
- var events = jQuery.data(elem, "events"), ret, index;
+ return r;
+ }
+});
+var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g,
+ rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnocache = /<script|<object|<embed|<option|<style/i,
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, // checked="checked" or checked (html5)
+ fcloseTag = function( all, front, tag ) {
+ return rselfClosing.test( tag ) ?
+ all :
+ front + "></" + tag + ">";
+ },
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ area: [ 1, "<map>", "</map>" ],
+ _default: [ 0, "", "" ]
+ };
- if ( events ) {
- // Unbind all events for the element
- if ( types === undefined || (typeof types === "string" && types.charAt(0) == ".") )
- for ( var type in events )
- this.remove( elem, type + (types || "") );
- else {
- // types is actually an event object here
- if ( types.type ) {
- handler = types.handler;
- types = types.type;
- }
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
- // Handle multiple events seperated by a space
- // jQuery(...).unbind("mouseover mouseout", fn);
- jQuery.each(types.split(/\s+/), function(index, type){
- // Namespaced event handlers
- var namespaces = type.split(".");
- type = namespaces.shift();
- var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
-
- if ( events[type] ) {
- // remove the given handler for the given type
- if ( handler )
- delete events[type][handler.guid];
-
- // remove all handlers for the given type
- else
- for ( var handle in events[type] )
- // Handle the removal of namespaced events
- if ( namespace.test(events[type][handle].type) )
- delete events[type][handle];
-
- if ( jQuery.event.specialAll[type] )
- jQuery.event.specialAll[type].teardown.call(elem, namespaces);
-
- // remove generic event handler if no more handlers exist
- for ( ret in events[type] ) break;
- if ( !ret ) {
- if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {
- if (elem.removeEventListener)
- elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
- else if (elem.detachEvent)
- elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
- }
- ret = null;
- delete events[type];
- }
- }
- });
- }
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+ wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
- // Remove the expando if it's no longer used
- for ( ret in events ) break;
- if ( !ret ) {
- var handle = jQuery.data( elem, "handle" );
- if ( handle ) handle.elem = null;
- jQuery.removeData( elem, "events" );
- jQuery.removeData( elem, "handle" );
- }
+jQuery.fn.extend({
+ text: function( text ) {
+ if ( jQuery.isFunction(text) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ self.text( text.call(this, i, self.text()) );
+ });
}
+
+ if ( typeof text !== "object" && text !== undefined ) {
+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+ }
+
+ return jQuery.text( this );
},
- // bubbling is internal
- trigger: function( event, data, elem, bubbling ) {
- // Event object or event type
- var type = event.type || event;
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
- if( !bubbling ){
- event = typeof event === "object" ?
- // jQuery.Event object
- event[expando] ? event :
- // Object literal
- jQuery.extend( jQuery.Event(type), event ) :
- // Just the event type (string)
- jQuery.Event(type);
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
- if ( type.indexOf("!") >= 0 ) {
- event.type = type = type.slice(0, -1);
- event.exclusive = true;
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
}
- // Handle a global trigger
- if ( !elem ) {
- // Don't bubble custom events when global (to avoid too much overhead)
- event.stopPropagation();
- // Only trigger if we've ever bound an event for it
- if ( this.global[type] )
- jQuery.each( jQuery.cache, function(){
- if ( this.events && this.events[type] )
- jQuery.event.trigger( event, data, this.handle.elem );
- });
- }
+ wrap.map(function() {
+ var elem = this;
- // Handle triggering a single element
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
- // don't do events on text and comment nodes
- if ( !elem || elem.nodeType == 3 || elem.nodeType == 8 )
- return undefined;
+ return elem;
+ }).append(this);
+ }
- // Clean up in case it is reused
- event.result = undefined;
- event.target = elem;
+ return this;
+ },
- // Clone the incoming data, if any
- data = jQuery.makeArray(data);
- data.unshift( event );
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
}
- event.currentTarget = elem;
+ return this.each(function() {
+ var self = jQuery( this ), contents = self.contents();
- // Trigger the event, it is assumed that "handle" is a function
- var handle = jQuery.data(elem, "handle");
- if ( handle )
- handle.apply( elem, data );
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
- // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
- if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
- event.result = false;
+ wrap: function( html ) {
+ return this.each(function() {
+ jQuery( this ).wrapAll( html );
+ });
+ },
- // Trigger the native events (except for clicks on links)
- if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
- this.triggered = true;
- try {
- elem[ type ]();
- // prevent IE from throwing an error for some hidden elements
- } catch (e) {}
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this );
+ });
+ } else if ( arguments.length ) {
+ var set = jQuery(arguments[0]);
+ set.push.apply( set, this.toArray() );
+ return this.pushStack( set, "before", arguments );
}
+ },
- this.triggered = false;
+ after: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ } else if ( arguments.length ) {
+ var set = this.pushStack( this, "after", arguments );
+ set.push.apply( set, jQuery(arguments[0]).toArray() );
+ return set;
+ }
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ jQuery.cleanData( [ elem ] );
+ }
- if ( !event.isPropagationStopped() ) {
- var parent = elem.parentNode || elem.ownerDocument;
- if ( parent )
- jQuery.event.trigger(event, data, parent, true);
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+ }
}
+
+ return this;
},
- handle: function(event) {
- // returned undefined or false
- var all, handlers;
+ empty: function() {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ }
- event = arguments[0] = jQuery.event.fix( event || window.event );
- event.currentTarget = this;
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+ }
+
+ return this;
+ },
- // Namespaced event handlers
- var namespaces = event.type.split(".");
- event.type = namespaces.shift();
+ clone: function( events ) {
+ // Do the clone
+ var ret = this.map(function() {
+ if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
+ // IE copies events bound via attachEvent when
+ // using cloneNode. Calling detachEvent on the
+ // clone will also remove the events from the orignal
+ // In order to get around this, we use innerHTML.
+ // Unfortunately, this means some modifications to
+ // attributes in IE that are actually only stored
+ // as properties will not be copied (such as the
+ // the name attribute on an input).
+ var html = this.outerHTML, ownerDocument = this.ownerDocument;
+ if ( !html ) {
+ var div = ownerDocument.createElement("div");
+ div.appendChild( this.cloneNode(true) );
+ html = div.innerHTML;
+ }
- // Cache this now, all = true means, any handler
- all = !namespaces.length && !event.exclusive;
+ return jQuery.clean([html.replace(rinlinejQuery, "")
+ // Handle the case in IE 8 where action=/test/> self-closes a tag
+ .replace(/=([^="'>\s]+\/)>/g, '="$1">')
+ .replace(rleadingWhitespace, "")], ownerDocument)[0];
+ } else {
+ return this.cloneNode(true);
+ }
+ });
- var namespace = RegExp("(^|\\.)" + namespaces.slice().sort().join(".*\\.") + "(\\.|$)");
+ // Copy the events from the original to the clone
+ if ( events === true ) {
+ cloneCopyEvent( this, ret );
+ cloneCopyEvent( this.find("*"), ret.find("*") );
+ }
- handlers = ( jQuery.data(this, "events") || {} )[event.type];
+ // Return the cloned set
+ return ret;
+ },
- for ( var j in handlers ) {
- var handler = handlers[j];
+ html: function( value ) {
+ if ( value === undefined ) {
+ return this[0] && this[0].nodeType === 1 ?
+ this[0].innerHTML.replace(rinlinejQuery, "") :
+ null;
- // Filter the functions by class
- if ( all || namespace.test(handler.type) ) {
- // Pass in a reference to the handler function itself
- // So that we can later remove it
- event.handler = handler;
- event.data = handler.data;
+ // See if we can take a shortcut and just use innerHTML
+ } else if ( typeof value === "string" && !rnocache.test( value ) &&
+ (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
+ !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
- var ret = handler.apply(this, arguments);
+ value = value.replace(rxhtmlTag, fcloseTag);
- if( ret !== undefined ){
- event.result = ret;
- if ( ret === false ) {
- event.preventDefault();
- event.stopPropagation();
+ try {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( this[i].nodeType === 1 ) {
+ jQuery.cleanData( this[i].getElementsByTagName("*") );
+ this[i].innerHTML = value;
}
}
- if( event.isImmediatePropagationStopped() )
- break;
-
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {
+ this.empty().append( value );
}
+
+ } else if ( jQuery.isFunction( value ) ) {
+ this.each(function(i){
+ var self = jQuery(this), old = self.html();
+ self.empty().append(function(){
+ return value.call( this, i, old );
+ });
+ });
+
+ } else {
+ this.empty().append( value );
}
+
+ return this;
},
- props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+ replaceWith: function( value ) {
+ if ( this[0] && this[0].parentNode ) {
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this), old = self.html();
+ self.replaceWith( value.call( this, i, old ) );
+ });
+ }
- fix: function(event) {
- if ( event[expando] )
- return event;
+ if ( typeof value !== "string" ) {
+ value = jQuery(value).detach();
+ }
- // store a copy of the original event object
- // and "clone" to set read-only properties
- var originalEvent = event;
- event = jQuery.Event( originalEvent );
+ return this.each(function() {
+ var next = this.nextSibling, parent = this.parentNode;
- for ( var i = this.props.length, prop; i; ){
- prop = this.props[ --i ];
- event[ prop ] = originalEvent[ prop ];
- }
+ jQuery(this).remove();
- // Fix target property, if necessary
- if ( !event.target )
- event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
+ if ( next ) {
+ jQuery(next).before( value );
+ } else {
+ jQuery(parent).append( value );
+ }
+ });
+ } else {
+ return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
+ }
+ },
- // check if target is a textnode (safari)
- if ( event.target.nodeType == 3 )
- event.target = event.target.parentNode;
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
- // Add relatedTarget, if necessary
- if ( !event.relatedTarget && event.fromElement )
- event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;
+ domManip: function( args, table, callback ) {
+ var results, first, value = args[0], scripts = [], fragment, parent;
- // Calculate pageX/Y if missing and clientX/Y available
- if ( event.pageX == null && event.clientX != null ) {
- var doc = document.documentElement, body = document.body;
- event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
- event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+ return this.each(function() {
+ jQuery(this).domManip( args, table, callback, true );
+ });
}
- // Add which for key events
- if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
- event.which = event.charCode || event.keyCode;
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ args[0] = value.call(this, i, table ? self.html() : undefined);
+ self.domManip( args, table, callback );
+ });
+ }
- // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
- if ( !event.metaKey && event.ctrlKey )
- event.metaKey = event.ctrlKey;
+ if ( this[0] ) {
+ parent = value && value.parentNode;
- // Add which for click: 1 == left; 2 == middle; 3 == right
- // Note: button is not normalized, so don't use it
- if ( !event.which && event.button )
- event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
+ // If we're in a fragment, just use that instead of building a new one
+ if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+ results = { fragment: parent };
- return event;
- },
+ } else {
+ results = buildFragment( args, this, scripts );
+ }
+
+ fragment = results.fragment;
+
+ if ( fragment.childNodes.length === 1 ) {
+ first = fragment = fragment.firstChild;
+ } else {
+ first = fragment.firstChild;
+ }
- proxy: function( fn, proxy ){
- proxy = proxy || function(){ return fn.apply(this, arguments); };
- // Set the guid of unique handler to the same of original handler, so it can be removed
- proxy.guid = fn.guid = fn.guid || proxy.guid || this.guid++;
- // So proxy can be declared as an argument
- return proxy;
- },
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ callback.call(
+ table ?
+ root(this[i], first) :
+ this[i],
+ i > 0 || results.cacheable || this.length > 1 ?
+ fragment.cloneNode(true) :
+ fragment
+ );
+ }
+ }
- special: {
- ready: {
- // Make sure the ready event is setup
- setup: bindReady,
- teardown: function() {}
+ if ( scripts.length ) {
+ jQuery.each( scripts, evalScript );
+ }
}
- },
- specialAll: {
- live: {
- setup: function( selector, namespaces ){
- jQuery.event.add( this, namespaces[0], liveHandler );
- },
- teardown: function( namespaces ){
- if ( namespaces.length ) {
- var remove = 0, name = RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
-
- jQuery.each( (jQuery.data(this, "events").live || {}), function(){
- if ( name.test(this.type) )
- remove++;
- });
+ return this;
- if ( remove < 1 )
- jQuery.event.remove( this, namespaces[0], liveHandler );
- }
- }
+ function root( elem, cur ) {
+ return jQuery.nodeName(elem, "table") ?
+ (elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+ elem;
}
}
-};
+});
-jQuery.Event = function( src ){
- // Allow instantiation without the 'new' keyword
- if( !this.preventDefault )
- return new jQuery.Event(src);
+function cloneCopyEvent(orig, ret) {
+ var i = 0;
- // Event object
- if( src && src.type ){
- this.originalEvent = src;
- this.type = src.type;
- // Event type
- }else
- this.type = src;
+ ret.each(function() {
+ if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
+ return;
+ }
- // timeStamp is buggy for some events on Firefox(#3843)
- // So we won't rely on the native value
- this.timeStamp = now();
+ var oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events;
- // Mark it as fixed
- this[expando] = true;
-};
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
-function returnFalse(){
- return false;
-}
-function returnTrue(){
- return true;
+ for ( var type in events ) {
+ for ( var handler in events[ type ] ) {
+ jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
+ }
+ }
+ }
+ });
}
-// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
-// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
-jQuery.Event.prototype = {
- preventDefault: function() {
- this.isDefaultPrevented = returnTrue;
+function buildFragment( args, nodes, scripts ) {
+ var fragment, cacheable, cacheresults,
+ doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
+
+ // Only cache "small" (1/2 KB) strings that are associated with the main document
+ // Cloning options loses the selected state, so don't cache them
+ // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+ // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+ if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
+ !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
+
+ cacheable = true;
+ cacheresults = jQuery.fragments[ args[0] ];
+ if ( cacheresults ) {
+ if ( cacheresults !== 1 ) {
+ fragment = cacheresults;
+ }
+ }
+ }
- var e = this.originalEvent;
- if( !e )
- return;
- // if preventDefault exists run it on the original event
- if (e.preventDefault)
- e.preventDefault();
- // otherwise set the returnValue property of the original event to false (IE)
- e.returnValue = false;
- },
- stopPropagation: function() {
- this.isPropagationStopped = returnTrue;
+ if ( !fragment ) {
+ fragment = doc.createDocumentFragment();
+ jQuery.clean( args, doc, fragment, scripts );
+ }
- var e = this.originalEvent;
- if( !e )
- return;
- // if stopPropagation exists run it on the original event
- if (e.stopPropagation)
- e.stopPropagation();
- // otherwise set the cancelBubble property of the original event to true (IE)
- e.cancelBubble = true;
- },
- stopImmediatePropagation:function(){
- this.isImmediatePropagationStopped = returnTrue;
- this.stopPropagation();
- },
- isDefaultPrevented: returnFalse,
- isPropagationStopped: returnFalse,
- isImmediatePropagationStopped: returnFalse
-};
-// Checks if an event happened on an element within another element
-// Used in jQuery.event.special.mouseenter and mouseleave handlers
-var withinElement = function(event) {
- // Check if mouse(over|out) are still within the same parent element
- var parent = event.relatedTarget;
- // Traverse up the tree
- while ( parent && parent != this )
- try { parent = parent.parentNode; }
- catch(e) { parent = this; }
-
- if( parent != this ){
- // set the correct event type
- event.type = event.data;
- // handle event if we actually just moused on to a non sub-element
- jQuery.event.handle.apply( this, arguments );
+ if ( cacheable ) {
+ jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
}
-};
+
+ return { fragment: fragment, cacheable: cacheable };
+}
+
+jQuery.fragments = {};
jQuery.each({
- mouseover: 'mouseenter',
- mouseout: 'mouseleave'
-}, function( orig, fix ){
- jQuery.event.special[ fix ] = {
- setup: function(){
- jQuery.event.add( this, orig, withinElement, fix );
- },
- teardown: function(){
- jQuery.event.remove( this, orig, withinElement );
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = [], insert = jQuery( selector ),
+ parent = this.length === 1 && this[0].parentNode;
+
+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+ insert[ original ]( this[0] );
+ return this;
+
+ } else {
+ for ( var i = 0, l = insert.length; i < l; i++ ) {
+ var elems = (i > 0 ? this.clone(true) : this).get();
+ jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
+ ret = ret.concat( elems );
+ }
+
+ return this.pushStack( ret, name, insert.selector );
}
};
});
-jQuery.fn.extend({
- bind: function( type, data, fn ) {
- return type == "unload" ? this.one(type, data, fn) : this.each(function(){
- jQuery.event.add( this, type, fn || data, fn && data );
- });
- },
+jQuery.extend({
+ clean: function( elems, context, fragment, scripts ) {
+ context = context || document;
- one: function( type, data, fn ) {
- var one = jQuery.event.proxy( fn || data, function(event) {
- jQuery(this).unbind(event, one);
- return (fn || data).apply( this, arguments );
- });
- return this.each(function(){
- jQuery.event.add( this, type, one, fn && data);
- });
- },
+ // !context.createElement fails in IE with an error but returns typeof 'object'
+ if ( typeof context.createElement === "undefined" ) {
+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+ }
- unbind: function( type, fn ) {
- return this.each(function(){
- jQuery.event.remove( this, type, fn );
- });
- },
+ var ret = [];
- trigger: function( type, data ) {
- return this.each(function(){
- jQuery.event.trigger( type, data, this );
- });
- },
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( typeof elem === "number" ) {
+ elem += "";
+ }
- triggerHandler: function( type, data ) {
- if( this[0] ){
- var event = jQuery.Event(type);
- event.preventDefault();
- event.stopPropagation();
- jQuery.event.trigger( event, data, this[0] );
- return event.result;
- }
- },
+ if ( !elem ) {
+ continue;
+ }
- toggle: function( fn ) {
- // Save reference to arguments for access in closure
- var args = arguments, i = 1;
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" && !rhtml.test( elem ) ) {
+ elem = context.createTextNode( elem );
- // link all the functions, so any of them can unbind this click handler
- while( i < args.length )
- jQuery.event.proxy( fn, args[i++] );
+ } else if ( typeof elem === "string" ) {
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(rxhtmlTag, fcloseTag);
- return this.click( jQuery.event.proxy( fn, function(event) {
- // Figure out which function to execute
- this.lastToggle = ( this.lastToggle || 0 ) % i;
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
+ wrap = wrapMap[ tag ] || wrapMap._default,
+ depth = wrap[0],
+ div = context.createElement("div");
- // Make sure that clicks stop
- event.preventDefault();
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + elem + wrap[2];
- // and execute the function
- return args[ this.lastToggle++ ].apply( this, arguments ) || false;
- }));
- },
+ // Move to the right depth
+ while ( depth-- ) {
+ div = div.lastChild;
+ }
- hover: function(fnOver, fnOut) {
- return this.mouseenter(fnOver).mouseleave(fnOut);
- },
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
- ready: function(fn) {
- // Attach the listeners
- bindReady();
+ // String was a <table>, *may* have spurious <tbody>
+ var hasBody = rtbody.test(elem),
+ tbody = tag === "table" && !hasBody ?
+ div.firstChild && div.firstChild.childNodes :
- // If the DOM is already ready
- if ( jQuery.isReady )
- // Execute the function immediately
- fn.call( document, jQuery );
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !hasBody ?
+ div.childNodes :
+ [];
- // Otherwise, remember the function for later
- else
- // Add the function to the wait list
- jQuery.readyList.push( fn );
+ for ( var j = tbody.length - 1; j >= 0 ; --j ) {
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+ }
+ }
- return this;
- },
+ }
- live: function( type, fn ){
- var proxy = jQuery.event.proxy( fn );
- proxy.guid += this.selector + type;
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+ }
- jQuery(document).bind( liveConvert(type, this.selector), this.selector, proxy );
+ elem = div.childNodes;
+ }
- return this;
+ if ( elem.nodeType ) {
+ ret.push( elem );
+ } else {
+ ret = jQuery.merge( ret, elem );
+ }
+ }
+
+ if ( fragment ) {
+ for ( var i = 0; ret[i]; i++ ) {
+ if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+ scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+
+ } else {
+ if ( ret[i].nodeType === 1 ) {
+ ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
+ }
+ fragment.appendChild( ret[i] );
+ }
+ }
+ }
+
+ return ret;
},
+
+ cleanData: function( elems ) {
+ var data, id, cache = jQuery.cache,
+ special = jQuery.event.special,
+ deleteExpando = jQuery.support.deleteExpando;
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ id = elem[ jQuery.expando ];
+
+ if ( id ) {
+ data = cache[ id ];
+
+ if ( data.events ) {
+ for ( var type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ } else {
+ removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ if ( deleteExpando ) {
+ delete elem[ jQuery.expando ];
- die: function( type, fn ){
- jQuery(document).unbind( liveConvert(type, this.selector), fn ? { guid: fn.guid + this.selector + type } : null );
- return this;
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+ }
+
+ delete cache[ id ];
+ }
+ }
}
});
+// exclude the following css properties to add px
+var rexclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
+ ralpha = /alpha\([^)]*\)/,
+ ropacity = /opacity=([^)]*)/,
+ rfloat = /float/i,
+ rdashAlpha = /-([a-z])/ig,
+ rupper = /([A-Z])/g,
+ rnumpx = /^-?\d+(?:px)?$/i,
+ rnum = /^-?\d/,
+
+ cssShow = { position: "absolute", visibility: "hidden", display:"block" },
+ cssWidth = [ "Left", "Right" ],
+ cssHeight = [ "Top", "Bottom" ],
+
+ // cache check for defaultView.getComputedStyle
+ getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
+ // normalize float css property
+ styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat",
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ };
-function liveHandler( event ){
- var check = RegExp("(^|\\.)" + event.type + "(\\.|$)"),
- stop = true,
- elems = [];
-
- jQuery.each(jQuery.data(this, "events").live || [], function(i, fn){
- if ( check.test(fn.type) ) {
- var elem = jQuery(event.target).closest(fn.data)[0];
- if ( elem )
- elems.push({ elem: elem, fn: fn });
+jQuery.fn.css = function( name, value ) {
+ return access( this, name, value, true, function( elem, name, value ) {
+ if ( value === undefined ) {
+ return jQuery.curCSS( elem, name );
+ }
+
+ if ( typeof value === "number" && !rexclude.test(name) ) {
+ value += "px";
}
- });
-
- elems.sort(function(a,b) {
- return jQuery.data(a.elem, "closest") - jQuery.data(b.elem, "closest");
- });
- jQuery.each(elems, function(){
- if ( this.fn.call(this.elem, event, this.fn.data) === false )
- return (stop = false);
+ jQuery.style( elem, name, value );
});
+};
- return stop;
-}
+jQuery.extend({
+ style: function( elem, name, value ) {
+ // don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return undefined;
+ }
-function liveConvert(type, selector){
- return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "|")].join(".");
-}
+ // ignore negative width and height values #1599
+ if ( (name === "width" || name === "height") && parseFloat(value) < 0 ) {
+ value = undefined;
+ }
-jQuery.extend({
- isReady: false,
- readyList: [],
- // Handle when the DOM is ready
- ready: function() {
- // Make sure that the DOM is not already loaded
- if ( !jQuery.isReady ) {
- // Remember that the DOM is ready
- jQuery.isReady = true;
+ var style = elem.style || elem, set = value !== undefined;
- // If there are functions bound, to execute
- if ( jQuery.readyList ) {
- // Execute all of them
- jQuery.each( jQuery.readyList, function(){
- this.call( document, jQuery );
- });
+ // IE uses filters for opacity
+ if ( !jQuery.support.opacity && name === "opacity" ) {
+ if ( set ) {
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
- // Reset the list of functions
- jQuery.readyList = null;
+ // Set the alpha filter to set the opacity
+ var opacity = parseInt( value, 10 ) + "" === "NaN" ? "" : "alpha(opacity=" + value * 100 + ")";
+ var filter = style.filter || jQuery.curCSS( elem, "filter" ) || "";
+ style.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : opacity;
}
- // Trigger any bound ready events
- jQuery(document).triggerHandler("ready");
+ return style.filter && style.filter.indexOf("opacity=") >= 0 ?
+ (parseFloat( ropacity.exec(style.filter)[1] ) / 100) + "":
+ "";
}
- }
-});
-var readyBound = false;
+ // Make sure we're using the right name for getting the float value
+ if ( rfloat.test( name ) ) {
+ name = styleFloat;
+ }
-function bindReady(){
- if ( readyBound ) return;
- readyBound = true;
+ name = name.replace(rdashAlpha, fcamelCase);
- // Mozilla, Opera and webkit nightlies currently support this event
- if ( document.addEventListener ) {
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", function(){
- document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
- jQuery.ready();
- }, false );
+ if ( set ) {
+ style[ name ] = value;
+ }
- // If IE event model is used
- } else if ( document.attachEvent ) {
- // ensure firing before onload,
- // maybe late but safe also for iframes
- document.attachEvent("onreadystatechange", function(){
- if ( document.readyState === "complete" ) {
- document.detachEvent( "onreadystatechange", arguments.callee );
- jQuery.ready();
- }
- });
+ return style[ name ];
+ },
- // If IE and not an iframe
- // continually check to see if the document is ready
- if ( document.documentElement.doScroll && window == window.top ) (function(){
- if ( jQuery.isReady ) return;
+ css: function( elem, name, force, extra ) {
+ if ( name === "width" || name === "height" ) {
+ var val, props = cssShow, which = name === "width" ? cssWidth : cssHeight;
- try {
- // If IE is used, use the trick by Diego Perini
- // http://javascript.nwbox.com/IEContentLoaded/
- document.documentElement.doScroll("left");
- } catch( error ) {
- setTimeout( arguments.callee, 0 );
- return;
+ function getWH() {
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
+
+ if ( extra === "border" ) {
+ return;
+ }
+
+ jQuery.each( which, function() {
+ if ( !extra ) {
+ val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
+ }
+
+ if ( extra === "margin" ) {
+ val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
+ } else {
+ val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
+ }
+ });
}
- // and execute any waiting functions
- jQuery.ready();
- })();
- }
+ if ( elem.offsetWidth !== 0 ) {
+ getWH();
+ } else {
+ jQuery.swap( elem, props, getWH );
+ }
- // A fallback to window.onload, that will always work
- jQuery.event.add( window, "load", jQuery.ready );
-}
+ return Math.max(0, Math.round(val));
+ }
-jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
- "mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave," +
- "change,select,submit,keydown,keypress,keyup,error").split(","), function(i, name){
+ return jQuery.curCSS( elem, name, force );
+ },
- // Handle event binding
- jQuery.fn[name] = function(fn){
- return fn ? this.bind(name, fn) : this.trigger(name);
- };
-});
+ curCSS: function( elem, name, force ) {
+ var ret, style = elem.style, filter;
-// Prevent memory leaks in IE
-// And prevent errors on refresh with events like mouseover in other browsers
-// Window isn't included so as not to unbind existing unload events
-jQuery( window ).bind( 'unload', function(){
- for ( var id in jQuery.cache )
- // Skip the window
- if ( id != 1 && jQuery.cache[ id ].handle )
- jQuery.event.remove( jQuery.cache[ id ].handle.elem );
-});
-(function(){
+ // IE uses filters for opacity
+ if ( !jQuery.support.opacity && name === "opacity" && elem.currentStyle ) {
+ ret = ropacity.test(elem.currentStyle.filter || "") ?
+ (parseFloat(RegExp.$1) / 100) + "" :
+ "";
- jQuery.support = {};
+ return ret === "" ?
+ "1" :
+ ret;
+ }
- var root = document.documentElement,
- script = document.createElement("script"),
- div = document.createElement("div"),
- id = "script" + (new Date).getTime();
+ // Make sure we're using the right name for getting the float value
+ if ( rfloat.test( name ) ) {
+ name = styleFloat;
+ }
- div.style.display = "none";
- div.innerHTML = ' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';
+ if ( !force && style && style[ name ] ) {
+ ret = style[ name ];
- var all = div.getElementsByTagName("*"),
- a = div.getElementsByTagName("a")[0];
+ } else if ( getComputedStyle ) {
- // Can't get basic test support
- if ( !all || !all.length || !a ) {
- return;
- }
+ // Only "float" is needed here
+ if ( rfloat.test( name ) ) {
+ name = "float";
+ }
- jQuery.support = {
- // IE strips leading whitespace when .innerHTML is used
- leadingWhitespace: div.firstChild.nodeType == 3,
+ name = name.replace( rupper, "-$1" ).toLowerCase();
- // Make sure that tbody elements aren't automatically inserted
- // IE will insert them into empty tables
- tbody: !div.getElementsByTagName("tbody").length,
+ var defaultView = elem.ownerDocument.defaultView;
- // Make sure that you can get all elements in an <object> element
- // IE 7 always returns no results
- objectAll: !!div.getElementsByTagName("object")[0]
- .getElementsByTagName("*").length,
+ if ( !defaultView ) {
+ return null;
+ }
- // Make sure that link elements get serialized correctly by innerHTML
- // This requires a wrapper element in IE
- htmlSerialize: !!div.getElementsByTagName("link").length,
+ var computedStyle = defaultView.getComputedStyle( elem, null );
- // Get the style information from getAttribute
- // (IE uses .cssText insted)
- style: /red/.test( a.getAttribute("style") ),
+ if ( computedStyle ) {
+ ret = computedStyle.getPropertyValue( name );
+ }
- // Make sure that URLs aren't manipulated
- // (IE normalizes it by default)
- hrefNormalized: a.getAttribute("href") === "/a",
+ // We should always get a number back from opacity
+ if ( name === "opacity" && ret === "" ) {
+ ret = "1";
+ }
- // Make sure that element opacity exists
- // (IE uses filter instead)
- opacity: a.style.opacity === "0.5",
+ } else if ( elem.currentStyle ) {
+ var camelCase = name.replace(rdashAlpha, fcamelCase);
- // Verify style float existence
- // (IE uses styleFloat instead of cssFloat)
- cssFloat: !!a.style.cssFloat,
+ ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
- // Will be defined later
- scriptEval: false,
- noCloneEvent: true,
- boxModel: null
- };
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
- script.type = "text/javascript";
- try {
- script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
- } catch(e){}
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
+ // Remember the original values
+ var left = style.left, rsLeft = elem.runtimeStyle.left;
- root.insertBefore( script, root.firstChild );
+ // Put in the new values to get a computed value out
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ style.left = camelCase === "fontSize" ? "1em" : (ret || 0);
+ ret = style.pixelLeft + "px";
- // Make sure that the execution of code works by injecting a script
- // tag with appendChild/createTextNode
- // (IE doesn't support this, fails, and uses .text instead)
- if ( window[ id ] ) {
- jQuery.support.scriptEval = true;
- delete window[ id ];
- }
+ // Revert the changed values
+ style.left = left;
+ elem.runtimeStyle.left = rsLeft;
+ }
+ }
- root.removeChild( script );
+ return ret;
+ },
- if ( div.attachEvent && div.fireEvent ) {
- div.attachEvent("onclick", function(){
- // Cloning a node shouldn't copy over any
- // bound event handlers (IE does this)
- jQuery.support.noCloneEvent = false;
- div.detachEvent("onclick", arguments.callee);
- });
- div.cloneNode(true).fireEvent("onclick");
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( var name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ callback.call( elem );
+
+ // Revert the old values
+ for ( var name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
}
+});
- // Figure out if the W3C box model works as expected
- // document.body must exist before we can do this
- jQuery(function(){
- var div = document.createElement("div");
- div.style.width = div.style.paddingLeft = "1px";
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ var width = elem.offsetWidth, height = elem.offsetHeight,
+ skip = elem.nodeName.toLowerCase() === "tr";
- document.body.appendChild( div );
- jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
- document.body.removeChild( div ).style.display = 'none';
- });
-})();
+ return width === 0 && height === 0 && !skip ?
+ true :
+ width > 0 && height > 0 && !skip ?
+ false :
+ jQuery.curCSS(elem, "display") === "none";
+ };
-var styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat";
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+var jsc = now(),
+ rscript = /<script(.|\s)*?\/script>/gi,
+ rselectTextarea = /select|textarea/i,
+ rinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,
+ jsre = /=\?(&|$)/,
+ rquery = /\?/,
+ rts = /(\?|&)_=.*?(&|$)/,
+ rurl = /^(\w+:)?\/\/([^\/?#]+)/,
+ r20 = /%20/g,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load;
-jQuery.props = {
- "for": "htmlFor",
- "class": "className",
- "float": styleFloat,
- cssFloat: styleFloat,
- styleFloat: styleFloat,
- readonly: "readOnly",
- maxlength: "maxLength",
- cellspacing: "cellSpacing",
- rowspan: "rowSpan",
- tabindex: "tabIndex"
-};
jQuery.fn.extend({
- // Keep a copy of the old load
- _load: jQuery.fn.load,
-
load: function( url, params, callback ) {
- if ( typeof url !== "string" )
- return this._load( url );
+ if ( typeof url !== "string" ) {
+ return _load.call( this, url );
+
+ // Don't do a request if no elements are being requested
+ } else if ( !this.length ) {
+ return this;
+ }
var off = url.indexOf(" ");
if ( off >= 0 ) {
@@ -3242,7 +4801,7 @@ jQuery.fn.extend({
var type = "GET";
// If the second parameter was provided
- if ( params )
+ if ( params ) {
// If it's a function
if ( jQuery.isFunction( params ) ) {
// We assume that it's the callback
@@ -3250,10 +4809,11 @@ jQuery.fn.extend({
params = null;
// Otherwise, build a param string
- } else if( typeof params === "object" ) {
- params = jQuery.param( params );
+ } else if ( typeof params === "object" ) {
+ params = jQuery.param( params, jQuery.ajaxSettings.traditional );
type = "POST";
}
+ }
var self = this;
@@ -3263,27 +4823,30 @@ jQuery.fn.extend({
type: type,
dataType: "html",
data: params,
- complete: function(res, status){
+ complete: function( res, status ) {
// If successful, inject the HTML into all the matched elements
- if ( status == "success" || status == "notmodified" )
+ if ( status === "success" || status === "notmodified" ) {
// See if a selector was specified
self.html( selector ?
// Create a dummy div to hold the results
- jQuery("<div/>")
+ jQuery("<div />")
// inject the contents of the document in, removing the scripts
// to avoid any 'Permission Denied' errors in IE
- .append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))
+ .append(res.responseText.replace(rscript, ""))
// Locate the specified elements
.find(selector) :
// If not, just inject the full result
res.responseText );
+ }
- if( callback )
+ if ( callback ) {
self.each( callback, [res.responseText, status, res] );
+ }
}
});
+
return this;
},
@@ -3291,40 +4854,41 @@ jQuery.fn.extend({
return jQuery.param(this.serializeArray());
},
serializeArray: function() {
- return this.map(function(){
+ return this.map(function() {
return this.elements ? jQuery.makeArray(this.elements) : this;
})
- .filter(function(){
+ .filter(function() {
return this.name && !this.disabled &&
- (this.checked || /select|textarea/i.test(this.nodeName) ||
- /text|hidden|password|search/i.test(this.type));
+ (this.checked || rselectTextarea.test(this.nodeName) ||
+ rinput.test(this.type));
})
- .map(function(i, elem){
+ .map(function( i, elem ) {
var val = jQuery(this).val();
- return val == null ? null :
+
+ return val == null ?
+ null :
jQuery.isArray(val) ?
- jQuery.map( val, function(val, i){
- return {name: elem.name, value: val};
+ jQuery.map( val, function( val, i ) {
+ return { name: elem.name, value: val };
}) :
- {name: elem.name, value: val};
+ { name: elem.name, value: val };
}).get();
}
});
// Attach a bunch of functions for handling common AJAX events
-jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
- jQuery.fn[o] = function(f){
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
+ jQuery.fn[o] = function( f ) {
return this.bind(o, f);
};
});
-var jsc = now();
-
jQuery.extend({
get: function( url, data, callback, type ) {
- // shift arguments if data argument was ommited
+ // shift arguments if data argument was omited
if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
callback = data;
data = null;
}
@@ -3347,7 +4911,9 @@ jQuery.extend({
},
post: function( url, data, callback, type ) {
+ // shift arguments if data argument was omited
if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
callback = data;
data = {};
}
@@ -3377,13 +4943,21 @@ jQuery.extend({
data: null,
username: null,
password: null,
+ traditional: false,
*/
// Create the request object; Microsoft failed to properly
- // implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
+ // implement the XMLHttpRequest in IE7 (can't request local files),
+ // so we use the ActiveXObject when it is available
// This function can be overriden by calling jQuery.ajaxSetup
- xhr:function(){
- return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
- },
+ xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
+ function() {
+ return new window.XMLHttpRequest();
+ } :
+ function() {
+ try {
+ return new window.ActiveXObject("Microsoft.XMLHTTP");
+ } catch(e) {}
+ },
accepts: {
xml: "application/xml, text/xml",
html: "text/html",
@@ -3396,36 +4970,41 @@ jQuery.extend({
// Last-Modified header cache for next request
lastModified: {},
+ etag: {},
- ajax: function( s ) {
- // Extend the settings, but re-extend 's' so that it can be
- // checked again later (in the test suite, specifically)
- s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));
-
- var jsonp, jsre = /=\?(&|$)/g, status, data,
+ ajax: function( origSettings ) {
+ var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
+
+ var jsonp, status, data,
+ callbackContext = origSettings && origSettings.context || s,
type = s.type.toUpperCase();
// convert data if not already a string
- if ( s.data && s.processData && typeof s.data !== "string" )
- s.data = jQuery.param(s.data);
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
// Handle JSONP Parameter Callbacks
- if ( s.dataType == "jsonp" ) {
- if ( type == "GET" ) {
- if ( !s.url.match(jsre) )
- s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
- } else if ( !s.data || !s.data.match(jsre) )
+ if ( s.dataType === "jsonp" ) {
+ if ( type === "GET" ) {
+ if ( !jsre.test( s.url ) ) {
+ s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+ }
+ } else if ( !s.data || !jsre.test(s.data) ) {
s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+ }
s.dataType = "json";
}
// Build temporary JSONP function
- if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
- jsonp = "jsonp" + jsc++;
+ if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
+ jsonp = s.jsonpCallback || ("jsonp" + jsc++);
// Replace the =? sequence both in the query string and the data
- if ( s.data )
+ if ( s.data ) {
s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+ }
+
s.url = s.url.replace(jsre, "=" + jsonp + "$1");
// We need to make sure
@@ -3433,75 +5012,85 @@ jQuery.extend({
s.dataType = "script";
// Handle JSONP-style loading
- window[ jsonp ] = function(tmp){
+ window[ jsonp ] = window[ jsonp ] || function( tmp ) {
data = tmp;
success();
complete();
// Garbage collect
window[ jsonp ] = undefined;
- try{ delete window[ jsonp ]; } catch(e){}
- if ( head )
+
+ try {
+ delete window[ jsonp ];
+ } catch(e) {}
+
+ if ( head ) {
head.removeChild( script );
+ }
};
}
- if ( s.dataType == "script" && s.cache == null )
+ if ( s.dataType === "script" && s.cache === null ) {
s.cache = false;
+ }
- if ( s.cache === false && type == "GET" ) {
+ if ( s.cache === false && type === "GET" ) {
var ts = now();
+
// try replacing _= if it is there
- var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
+ var ret = s.url.replace(rts, "$1_=" + ts + "$2");
+
// if nothing was replaced, add timestamp to the end
- s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
+ s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
}
// If data is available, append data to url for get requests
- if ( s.data && type == "GET" ) {
- s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;
-
- // IE likes to send both get and post data, prevent this
- s.data = null;
+ if ( s.data && type === "GET" ) {
+ s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
}
// Watch for a new set of requests
- if ( s.global && ! jQuery.active++ )
+ if ( s.global && ! jQuery.active++ ) {
jQuery.event.trigger( "ajaxStart" );
+ }
// Matches an absolute URL, and saves the domain
- var parts = /^(\w+:)?\/\/([^\/?#]+)/.exec( s.url );
+ var parts = rurl.exec( s.url ),
+ remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
// If we're requesting a remote document
// and trying to load JSON or Script with a GET
- if ( s.dataType == "script" && type == "GET" && parts
- && ( parts[1] && parts[1] != location.protocol || parts[2] != location.host )){
-
- var head = document.getElementsByTagName("head")[0];
+ if ( s.dataType === "script" && type === "GET" && remote ) {
+ var head = document.getElementsByTagName("head")[0] || document.documentElement;
var script = document.createElement("script");
script.src = s.url;
- if (s.scriptCharset)
+ if ( s.scriptCharset ) {
script.charset = s.scriptCharset;
+ }
// Handle Script loading
if ( !jsonp ) {
var done = false;
// Attach handlers for all browsers
- script.onload = script.onreadystatechange = function(){
+ script.onload = script.onreadystatechange = function() {
if ( !done && (!this.readyState ||
- this.readyState == "loaded" || this.readyState == "complete") ) {
+ this.readyState === "loaded" || this.readyState === "complete") ) {
done = true;
success();
complete();
// Handle memory leak in IE
script.onload = script.onreadystatechange = null;
- head.removeChild( script );
+ if ( head && script.parentNode ) {
+ head.removeChild( script );
+ }
}
};
}
- head.appendChild(script);
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709 and #4378).
+ head.insertBefore( script, head.firstChild );
// We handle everything using the script element injection
return undefined;
@@ -3512,158 +5101,197 @@ jQuery.extend({
// Create the request object
var xhr = s.xhr();
+ if ( !xhr ) {
+ return;
+ }
+
// Open the socket
// Passing null username, generates a login popup on Opera (#2865)
- if( s.username )
+ if ( s.username ) {
xhr.open(type, s.url, s.async, s.username, s.password);
- else
+ } else {
xhr.open(type, s.url, s.async);
+ }
// Need an extra try/catch for cross domain requests in Firefox 3
try {
// Set the correct header, if data is being sent
- if ( s.data )
+ if ( s.data || origSettings && origSettings.contentType ) {
xhr.setRequestHeader("Content-Type", s.contentType);
+ }
- // Set the If-Modified-Since header, if ifModified mode.
- if ( s.ifModified )
- xhr.setRequestHeader("If-Modified-Since",
- jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[s.url] ) {
+ xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
+ }
+
+ if ( jQuery.etag[s.url] ) {
+ xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
+ }
+ }
// Set header so the called script knows that it's an XMLHttpRequest
- xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ // Only send the header if it's not a remote XHR
+ if ( !remote ) {
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ }
// Set the Accepts header for the server, depending on the dataType
xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
s.accepts[ s.dataType ] + ", */*" :
s.accepts._default );
- } catch(e){}
+ } catch(e) {}
// Allow custom headers/mimetypes and early abort
- if ( s.beforeSend && s.beforeSend(xhr, s) === false ) {
+ if ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {
// Handle the global AJAX counter
- if ( s.global && ! --jQuery.active )
+ if ( s.global && ! --jQuery.active ) {
jQuery.event.trigger( "ajaxStop" );
+ }
+
// close opended socket
xhr.abort();
return false;
}
- if ( s.global )
- jQuery.event.trigger("ajaxSend", [xhr, s]);
+ if ( s.global ) {
+ trigger("ajaxSend", [xhr, s]);
+ }
// Wait for a response to come back
- var onreadystatechange = function(isTimeout){
- // The request was aborted, clear the interval and decrement jQuery.active
- if (xhr.readyState == 0) {
- if (ival) {
- // clear poll interval
- clearInterval(ival);
- ival = null;
- // Handle the global AJAX counter
- if ( s.global && ! --jQuery.active )
- jQuery.event.trigger( "ajaxStop" );
+ var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
+ // The request was aborted
+ if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
+ // Opera doesn't call onreadystatechange before this point
+ // so we simulate the call
+ if ( !requestDone ) {
+ complete();
}
+
+ requestDone = true;
+ if ( xhr ) {
+ xhr.onreadystatechange = jQuery.noop;
+ }
+
// The transfer is complete and the data is available, or the request timed out
- } else if ( !requestDone && xhr && (xhr.readyState == 4 || isTimeout == "timeout") ) {
+ } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
requestDone = true;
+ xhr.onreadystatechange = jQuery.noop;
- // clear poll interval
- if (ival) {
- clearInterval(ival);
- ival = null;
- }
+ status = isTimeout === "timeout" ?
+ "timeout" :
+ !jQuery.httpSuccess( xhr ) ?
+ "error" :
+ s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
+ "notmodified" :
+ "success";
- status = isTimeout == "timeout" ? "timeout" :
- !jQuery.httpSuccess( xhr ) ? "error" :
- s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? "notmodified" :
- "success";
+ var errMsg;
- if ( status == "success" ) {
+ if ( status === "success" ) {
// Watch for, and catch, XML document parse errors
try {
// process the data (runs the xml through httpData regardless of callback)
data = jQuery.httpData( xhr, s.dataType, s );
- } catch(e) {
+ } catch(err) {
status = "parsererror";
+ errMsg = err;
}
}
// Make sure that the request was successful or notmodified
- if ( status == "success" ) {
- // Cache Last-Modified header, if ifModified mode.
- var modRes;
- try {
- modRes = xhr.getResponseHeader("Last-Modified");
- } catch(e) {} // swallow exception thrown by FF if header is not available
-
- if ( s.ifModified && modRes )
- jQuery.lastModified[s.url] = modRes;
-
+ if ( status === "success" || status === "notmodified" ) {
// JSONP handles its own success callback
- if ( !jsonp )
+ if ( !jsonp ) {
success();
- } else
- jQuery.handleError(s, xhr, status);
+ }
+ } else {
+ jQuery.handleError(s, xhr, status, errMsg);
+ }
// Fire the complete handlers
complete();
- if ( isTimeout )
+ if ( isTimeout === "timeout" ) {
xhr.abort();
+ }
// Stop memory leaks
- if ( s.async )
+ if ( s.async ) {
xhr = null;
+ }
}
};
- if ( s.async ) {
- // don't attach the handler to the request, just poll it instead
- var ival = setInterval(onreadystatechange, 13);
+ // Override the abort handler, if we can (IE doesn't allow it, but that's OK)
+ // Opera doesn't fire onreadystatechange at all on abort
+ try {
+ var oldAbort = xhr.abort;
+ xhr.abort = function() {
+ if ( xhr ) {
+ oldAbort.call( xhr );
+ }
- // Timeout checker
- if ( s.timeout > 0 )
- setTimeout(function(){
- // Check to see if the request is still happening
- if ( xhr && !requestDone )
- onreadystatechange( "timeout" );
- }, s.timeout);
+ onreadystatechange( "abort" );
+ };
+ } catch(e) { }
+
+ // Timeout checker
+ if ( s.async && s.timeout > 0 ) {
+ setTimeout(function() {
+ // Check to see if the request is still happening
+ if ( xhr && !requestDone ) {
+ onreadystatechange( "timeout" );
+ }
+ }, s.timeout);
}
// Send the data
try {
- xhr.send(s.data);
+ xhr.send( type === "POST" || type === "PUT" || type === "DELETE" ? s.data : null );
} catch(e) {
jQuery.handleError(s, xhr, null, e);
+ // Fire the complete handlers
+ complete();
}
// firefox 1.5 doesn't fire statechange for sync requests
- if ( !s.async )
+ if ( !s.async ) {
onreadystatechange();
+ }
- function success(){
+ function success() {
// If a local callback was specified, fire it and pass it the data
- if ( s.success )
- s.success( data, status );
+ if ( s.success ) {
+ s.success.call( callbackContext, data, status, xhr );
+ }
// Fire the global callback
- if ( s.global )
- jQuery.event.trigger( "ajaxSuccess", [xhr, s] );
+ if ( s.global ) {
+ trigger( "ajaxSuccess", [xhr, s] );
+ }
}
- function complete(){
+ function complete() {
// Process result
- if ( s.complete )
- s.complete(xhr, status);
+ if ( s.complete ) {
+ s.complete.call( callbackContext, xhr, status);
+ }
// The request was completed
- if ( s.global )
- jQuery.event.trigger( "ajaxComplete", [xhr, s] );
+ if ( s.global ) {
+ trigger( "ajaxComplete", [xhr, s] );
+ }
// Handle the global AJAX counter
- if ( s.global && ! --jQuery.active )
+ if ( s.global && ! --jQuery.active ) {
jQuery.event.trigger( "ajaxStop" );
+ }
+ }
+
+ function trigger(type, args) {
+ (s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
}
// return XMLHttpRequest to allow aborting the request etc.
@@ -3672,11 +5300,14 @@ jQuery.extend({
handleError: function( s, xhr, status, e ) {
// If a local callback was specified, fire it
- if ( s.error ) s.error( xhr, status, e );
+ if ( s.error ) {
+ s.error.call( s.context || s, xhr, status, e );
+ }
// Fire the global callback
- if ( s.global )
- jQuery.event.trigger( "ajaxError", [xhr, s, e] );
+ if ( s.global ) {
+ (s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
+ }
},
// Counter for holding the number of active queries
@@ -3686,46 +5317,57 @@ jQuery.extend({
httpSuccess: function( xhr ) {
try {
// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
- return !xhr.status && location.protocol == "file:" ||
- ( xhr.status >= 200 && xhr.status < 300 ) || xhr.status == 304 || xhr.status == 1223;
- } catch(e){}
+ return !xhr.status && location.protocol === "file:" ||
+ // Opera returns 0 when status is 304
+ ( xhr.status >= 200 && xhr.status < 300 ) ||
+ xhr.status === 304 || xhr.status === 1223 || xhr.status === 0;
+ } catch(e) {}
+
return false;
},
// Determines if an XMLHttpRequest returns NotModified
httpNotModified: function( xhr, url ) {
- try {
- var xhrRes = xhr.getResponseHeader("Last-Modified");
+ var lastModified = xhr.getResponseHeader("Last-Modified"),
+ etag = xhr.getResponseHeader("Etag");
- // Firefox always returns 200. check Last-Modified date
- return xhr.status == 304 || xhrRes == jQuery.lastModified[url];
- } catch(e){}
- return false;
+ if ( lastModified ) {
+ jQuery.lastModified[url] = lastModified;
+ }
+
+ if ( etag ) {
+ jQuery.etag[url] = etag;
+ }
+
+ // Opera returns 0 when status is 304
+ return xhr.status === 304 || xhr.status === 0;
},
httpData: function( xhr, type, s ) {
- var ct = xhr.getResponseHeader("content-type"),
- xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0,
+ var ct = xhr.getResponseHeader("content-type") || "",
+ xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
data = xml ? xhr.responseXML : xhr.responseText;
- if ( xml && data.documentElement.tagName == "parsererror" )
- throw "parsererror";
+ if ( xml && data.documentElement.nodeName === "parsererror" ) {
+ jQuery.error( "parsererror" );
+ }
// Allow a pre-filtering function to sanitize the response
- // s != null is checked to keep backwards compatibility
- if( s && s.dataFilter )
+ // s is checked to keep backwards compatibility
+ if ( s && s.dataFilter ) {
data = s.dataFilter( data, type );
+ }
// The filter can actually parse the response
- if( typeof data === "string" ){
+ if ( typeof data === "string" ) {
+ // Get the JavaScript object, if JSON is used.
+ if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
+ data = jQuery.parseJSON( data );
// If the type is "script", eval it in global context
- if ( type == "script" )
+ } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
jQuery.globalEval( data );
-
- // Get the JavaScript object, if JSON is used.
- if ( type == "json" )
- data = window["eval"]("(" + data + ")");
+ }
}
return data;
@@ -3733,39 +5375,73 @@ jQuery.extend({
// Serialize an array of form elements or a set of
// key/values into a query string
- param: function( a ) {
- var s = [ ];
-
- function add( key, value ){
- s[ s.length ] = encodeURIComponent(key) + '=' + encodeURIComponent(value);
- };
-
- // If an array was passed in, assume that it is an array
- // of form elements
- if ( jQuery.isArray(a) || a.jquery )
+ param: function( a, traditional ) {
+ var s = [];
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray(a) || a.jquery ) {
// Serialize the form elements
- jQuery.each( a, function(){
+ jQuery.each( a, function() {
add( this.name, this.value );
});
-
- // Otherwise, assume that it's an object of key/value pairs
- else
- // Serialize the key/values
- for ( var j in a )
- // If the value is an array then the key names need to be repeated
- if ( jQuery.isArray(a[j]) )
- jQuery.each( a[j], function(){
- add( j, this );
- });
- else
- add( j, jQuery.isFunction(a[j]) ? a[j]() : a[j] );
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( var prefix in a ) {
+ buildParams( prefix, a[prefix] );
+ }
+ }
// Return the resulting serialization
- return s.join("&").replace(/%20/g, "+");
- }
+ return s.join("&").replace(r20, "+");
+
+ function buildParams( prefix, obj ) {
+ if ( jQuery.isArray(obj) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || /\[\]$/.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+ } else {
+ // If array item is non-scalar (array or object), encode its
+ // numeric index to resolve deserialization ambiguity issues.
+ // Note that rack (as of 1.0.0) can't currently deserialize
+ // nested arrays properly, and attempting to do so may cause
+ // a server error. Possible fixes are to modify rack's
+ // deserialization algorithm or to provide an option or flag
+ // to force array serialization to be shallow.
+ buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v );
+ }
+ });
+
+ } else if ( !traditional && obj != null && typeof obj === "object" ) {
+ // Serialize object item.
+ jQuery.each( obj, function( k, v ) {
+ buildParams( prefix + "[" + k + "]", v );
+ });
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+ }
+ function add( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction(value) ? value() : value;
+ s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
+ }
+ }
});
var elemdisplay = {},
+ rfxtypes = /toggle|show|hide/,
+ rfxnum = /^([+-]=)?([\d+-.]+)(.*)$/,
timerId,
fxAttrs = [
// height animations
@@ -3776,39 +5452,35 @@ var elemdisplay = {},
[ "opacity" ]
];
-function genFx( type, num ){
- var obj = {};
- jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
- obj[ this ] = type;
- });
- return obj;
-}
-
jQuery.fn.extend({
- show: function(speed,callback){
- if ( speed ) {
+ show: function( speed, callback ) {
+ if ( speed || speed === 0) {
return this.animate( genFx("show", 3), speed, callback);
+
} else {
- for ( var i = 0, l = this.length; i < l; i++ ){
+ for ( var i = 0, l = this.length; i < l; i++ ) {
var old = jQuery.data(this[i], "olddisplay");
this[i].style.display = old || "";
if ( jQuery.css(this[i], "display") === "none" ) {
- var tagName = this[i].tagName, display;
+ var nodeName = this[i].nodeName, display;
+
+ if ( elemdisplay[ nodeName ] ) {
+ display = elemdisplay[ nodeName ];
- if ( elemdisplay[ tagName ] ) {
- display = elemdisplay[ tagName ];
} else {
- var elem = jQuery("<" + tagName + " />").appendTo("body");
+ var elem = jQuery("<" + nodeName + " />").appendTo("body");
display = elem.css("display");
- if ( display === "none" )
+
+ if ( display === "none" ) {
display = "block";
+ }
elem.remove();
- elemdisplay[ tagName ] = display;
+ elemdisplay[ nodeName ] = display;
}
jQuery.data(this[i], "olddisplay", display);
@@ -3817,28 +5489,30 @@ jQuery.fn.extend({
// Set the display of the elements in a second loop
// to avoid the constant reflow
- for ( var i = 0, l = this.length; i < l; i++ ){
- this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
+ for ( var j = 0, k = this.length; j < k; j++ ) {
+ this[j].style.display = jQuery.data(this[j], "olddisplay") || "";
}
return this;
}
},
- hide: function(speed,callback){
- if ( speed ) {
+ hide: function( speed, callback ) {
+ if ( speed || speed === 0 ) {
return this.animate( genFx("hide", 3), speed, callback);
+
} else {
- for ( var i = 0, l = this.length; i < l; i++ ){
+ for ( var i = 0, l = this.length; i < l; i++ ) {
var old = jQuery.data(this[i], "olddisplay");
- if ( !old && old !== "none" )
+ if ( !old && old !== "none" ) {
jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
+ }
}
// Set the display of the elements in a second loop
// to avoid the constant reflow
- for ( var i = 0, l = this.length; i < l; i++ ){
- this[i].style.display = "none";
+ for ( var j = 0, k = this.length; j < k; j++ ) {
+ this[j].style.display = "none";
}
return this;
@@ -3848,77 +5522,107 @@ jQuery.fn.extend({
// Save the old toggle function
_toggle: jQuery.fn.toggle,
- toggle: function( fn, fn2 ){
+ toggle: function( fn, fn2 ) {
var bool = typeof fn === "boolean";
- return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
- this._toggle.apply( this, arguments ) :
- fn == null || bool ?
- this.each(function(){
- var state = bool ? fn : jQuery(this).is(":hidden");
- jQuery(this)[ state ? "show" : "hide" ]();
- }) :
- this.animate(genFx("toggle", 3), fn, fn2);
+ if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+ this._toggle.apply( this, arguments );
+
+ } else if ( fn == null || bool ) {
+ this.each(function() {
+ var state = bool ? fn : jQuery(this).is(":hidden");
+ jQuery(this)[ state ? "show" : "hide" ]();
+ });
+
+ } else {
+ this.animate(genFx("toggle", 3), fn, fn2);
+ }
+
+ return this;
},
- fadeTo: function(speed,to,callback){
- return this.animate({opacity: to}, speed, callback);
+ fadeTo: function( speed, to, callback ) {
+ return this.filter(":hidden").css("opacity", 0).show().end()
+ .animate({opacity: to}, speed, callback);
},
animate: function( prop, speed, easing, callback ) {
var optall = jQuery.speed(speed, easing, callback);
- return this[ optall.queue === false ? "each" : "queue" ](function(){
+ if ( jQuery.isEmptyObject( prop ) ) {
+ return this.each( optall.complete );
+ }
+ return this[ optall.queue === false ? "each" : "queue" ](function() {
var opt = jQuery.extend({}, optall), p,
- hidden = this.nodeType == 1 && jQuery(this).is(":hidden"),
+ hidden = this.nodeType === 1 && jQuery(this).is(":hidden"),
self = this;
for ( p in prop ) {
- if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
+ var name = p.replace(rdashAlpha, fcamelCase);
+
+ if ( p !== name ) {
+ prop[ name ] = prop[ p ];
+ delete prop[ p ];
+ p = name;
+ }
+
+ if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
return opt.complete.call(this);
+ }
- if ( ( p == "height" || p == "width" ) && this.style ) {
+ if ( ( p === "height" || p === "width" ) && this.style ) {
// Store display property
opt.display = jQuery.css(this, "display");
// Make sure that nothing sneaks out
opt.overflow = this.style.overflow;
}
+
+ if ( jQuery.isArray( prop[p] ) ) {
+ // Create (if needed) and add to specialEasing
+ (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
+ prop[p] = prop[p][0];
+ }
}
- if ( opt.overflow != null )
+ if ( opt.overflow != null ) {
this.style.overflow = "hidden";
+ }
opt.curAnim = jQuery.extend({}, prop);
- jQuery.each( prop, function(name, val){
+ jQuery.each( prop, function( name, val ) {
var e = new jQuery.fx( self, opt, name );
- if ( /toggle|show|hide/.test(val) )
- e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
- else {
- var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
+ if ( rfxtypes.test(val) ) {
+ e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
+
+ } else {
+ var parts = rfxnum.exec(val),
start = e.cur(true) || 0;
if ( parts ) {
- var end = parseFloat(parts[2]),
+ var end = parseFloat( parts[2] ),
unit = parts[3] || "px";
// We need to compute starting value
- if ( unit != "px" ) {
+ if ( unit !== "px" ) {
self.style[ name ] = (end || 1) + unit;
start = ((end || 1) / e.cur(true)) * start;
self.style[ name ] = start + unit;
}
// If a +=/-= token was provided, we're doing a relative animation
- if ( parts[1] )
- end = ((parts[1] == "-=" ? -1 : 1) * end) + start;
+ if ( parts[1] ) {
+ end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
+ }
e.custom( start, end, unit );
- } else
+
+ } else {
e.custom( start, val, "" );
+ }
}
});
@@ -3927,26 +5631,31 @@ jQuery.fn.extend({
});
},
- stop: function(clearQueue, gotoEnd){
+ stop: function( clearQueue, gotoEnd ) {
var timers = jQuery.timers;
- if (clearQueue)
+ if ( clearQueue ) {
this.queue([]);
+ }
- this.each(function(){
+ this.each(function() {
// go in reverse order so anything added to the queue during the loop is ignored
- for ( var i = timers.length - 1; i >= 0; i-- )
- if ( timers[i].elem == this ) {
- if (gotoEnd)
+ for ( var i = timers.length - 1; i >= 0; i-- ) {
+ if ( timers[i].elem === this ) {
+ if (gotoEnd) {
// force the next step to be the last
timers[i](true);
+ }
+
timers.splice(i, 1);
}
+ }
});
// start the next in the queue if the last step wasn't forced
- if (!gotoEnd)
+ if ( !gotoEnd ) {
this.dequeue();
+ }
return this;
}
@@ -3960,16 +5669,15 @@ jQuery.each({
slideToggle: genFx("toggle", 1),
fadeIn: { opacity: "show" },
fadeOut: { opacity: "hide" }
-}, function( name, props ){
- jQuery.fn[ name ] = function( speed, callback ){
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, callback ) {
return this.animate( props, speed, callback );
};
});
jQuery.extend({
-
- speed: function(speed, easing, fn) {
- var opt = typeof speed === "object" ? speed : {
+ speed: function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? speed : {
complete: fn || !fn && easing ||
jQuery.isFunction( speed ) && speed,
duration: speed,
@@ -3981,11 +5689,13 @@ jQuery.extend({
// Queueing
opt.old = opt.complete;
- opt.complete = function(){
- if ( opt.queue !== false )
+ opt.complete = function() {
+ if ( opt.queue !== false ) {
jQuery(this).dequeue();
- if ( jQuery.isFunction( opt.old ) )
+ }
+ if ( jQuery.isFunction( opt.old ) ) {
opt.old.call( this );
+ }
};
return opt;
@@ -4002,42 +5712,45 @@ jQuery.extend({
timers: [],
- fx: function( elem, options, prop ){
+ fx: function( elem, options, prop ) {
this.options = options;
this.elem = elem;
this.prop = prop;
- if ( !options.orig )
+ if ( !options.orig ) {
options.orig = {};
+ }
}
});
jQuery.fx.prototype = {
-
// Simple function for setting a style value
- update: function(){
- if ( this.options.step )
+ update: function() {
+ if ( this.options.step ) {
this.options.step.call( this.elem, this.now, this );
+ }
(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
// Set display property to block for height/width animations
- if ( ( this.prop == "height" || this.prop == "width" ) && this.elem.style )
+ if ( ( this.prop === "height" || this.prop === "width" ) && this.elem.style ) {
this.elem.style.display = "block";
+ }
},
// Get the current size
- cur: function(force){
- if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) )
+ cur: function( force ) {
+ if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
return this.elem[ this.prop ];
+ }
var r = parseFloat(jQuery.css(this.elem, this.prop, force));
return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
},
// Start an animation from one number to another
- custom: function(from, to, unit){
+ custom: function( from, to, unit ) {
this.startTime = now();
this.start = from;
this.end = to;
@@ -4046,47 +5759,36 @@ jQuery.fx.prototype = {
this.pos = this.state = 0;
var self = this;
- function t(gotoEnd){
+ function t( gotoEnd ) {
return self.step(gotoEnd);
}
t.elem = this.elem;
if ( t() && jQuery.timers.push(t) && !timerId ) {
- timerId = setInterval(function(){
- var timers = jQuery.timers;
-
- for ( var i = 0; i < timers.length; i++ )
- if ( !timers[i]() )
- timers.splice(i--, 1);
-
- if ( !timers.length ) {
- clearInterval( timerId );
- timerId = undefined;
- }
- }, 13);
+ timerId = setInterval(jQuery.fx.tick, 13);
}
},
// Simple 'show' function
- show: function(){
+ show: function() {
// Remember where we started, so that we can go back to it later
- this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+ this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
this.options.show = true;
// Begin the animation
// Make sure that we start at a small width/height to avoid any
// flash of content
- this.custom(this.prop == "width" || this.prop == "height" ? 1 : 0, this.cur());
+ this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
// Start by showing the element
- jQuery(this.elem).show();
+ jQuery( this.elem ).show();
},
// Simple 'hide' function
- hide: function(){
+ hide: function() {
// Remember where we started, so that we can go back to it later
- this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
+ this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
this.options.hide = true;
// Begin the animation
@@ -4094,8 +5796,8 @@ jQuery.fx.prototype = {
},
// Each step of an animation
- step: function(gotoEnd){
- var t = now();
+ step: function( gotoEnd ) {
+ var t = now(), done = true;
if ( gotoEnd || t >= this.options.duration + this.startTime ) {
this.now = this.end;
@@ -4104,10 +5806,11 @@ jQuery.fx.prototype = {
this.options.curAnim[ this.prop ] = true;
- var done = true;
- for ( var i in this.options.curAnim )
- if ( this.options.curAnim[i] !== true )
+ for ( var i in this.options.curAnim ) {
+ if ( this.options.curAnim[i] !== true ) {
done = false;
+ }
+ }
if ( done ) {
if ( this.options.display != null ) {
@@ -4115,31 +5818,40 @@ jQuery.fx.prototype = {
this.elem.style.overflow = this.options.overflow;
// Reset the display
- this.elem.style.display = this.options.display;
- if ( jQuery.css(this.elem, "display") == "none" )
+ var old = jQuery.data(this.elem, "olddisplay");
+ this.elem.style.display = old ? old : this.options.display;
+
+ if ( jQuery.css(this.elem, "display") === "none" ) {
this.elem.style.display = "block";
+ }
}
// Hide the element if the "hide" operation was done
- if ( this.options.hide )
+ if ( this.options.hide ) {
jQuery(this.elem).hide();
+ }
// Reset the properties, if the item has been hidden or shown
- if ( this.options.hide || this.options.show )
- for ( var p in this.options.curAnim )
- jQuery.attr(this.elem.style, p, this.options.orig[p]);
+ if ( this.options.hide || this.options.show ) {
+ for ( var p in this.options.curAnim ) {
+ jQuery.style(this.elem, p, this.options.orig[p]);
+ }
+ }
// Execute the complete function
this.options.complete.call( this.elem );
}
return false;
+
} else {
var n = t - this.startTime;
this.state = n / this.options.duration;
// Perform the easing function, defaults to swing
- this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
+ var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
+ var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
+ this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
this.now = this.start + ((this.end - this.start) * this.pos);
// Perform the next step of the animation
@@ -4148,232 +5860,381 @@ jQuery.fx.prototype = {
return true;
}
-
};
jQuery.extend( jQuery.fx, {
- speeds:{
+ tick: function() {
+ var timers = jQuery.timers;
+
+ for ( var i = 0; i < timers.length; i++ ) {
+ if ( !timers[i]() ) {
+ timers.splice(i--, 1);
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ },
+
+ stop: function() {
+ clearInterval( timerId );
+ timerId = null;
+ },
+
+ speeds: {
slow: 600,
fast: 200,
// Default speed
_default: 400
},
- step: {
- opacity: function(fx){
- jQuery.attr(fx.elem.style, "opacity", fx.now);
+ step: {
+ opacity: function( fx ) {
+ jQuery.style(fx.elem, "opacity", fx.now);
},
- _default: function(fx){
- if ( fx.elem.style && fx.elem.style[ fx.prop ] != null )
- fx.elem.style[ fx.prop ] = fx.now + fx.unit;
- else
+ _default: function( fx ) {
+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+ fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
+ } else {
fx.elem[ fx.prop ] = fx.now;
+ }
}
}
});
-if ( document.documentElement["getBoundingClientRect"] )
- jQuery.fn.offset = function() {
- if ( !this[0] ) return { top: 0, left: 0 };
- if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
- var box = this[0].getBoundingClientRect(), doc = this[0].ownerDocument, body = doc.body, docElem = doc.documentElement,
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+
+function genFx( type, num ) {
+ var obj = {};
+
+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
+ obj[ this ] = type;
+ });
+
+ return obj;
+}
+if ( "getBoundingClientRect" in document.documentElement ) {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0];
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement,
clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
- top = box.top + (self.pageYOffset || jQuery.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
- left = box.left + (self.pageXOffset || jQuery.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
+ top = box.top + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
+ left = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
+
return { top: top, left: left };
};
-else
- jQuery.fn.offset = function() {
- if ( !this[0] ) return { top: 0, left: 0 };
- if ( this[0] === this[0].ownerDocument.body ) return jQuery.offset.bodyOffset( this[0] );
- jQuery.offset.initialized || jQuery.offset.initialize();
- var elem = this[0], offsetParent = elem.offsetParent, prevOffsetParent = elem,
+} else {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0];
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ jQuery.offset.initialize();
+
+ var offsetParent = elem.offsetParent, prevOffsetParent = elem,
doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
body = doc.body, defaultView = doc.defaultView,
- prevComputedStyle = defaultView.getComputedStyle(elem, null),
+ prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
top = elem.offsetTop, left = elem.offsetLeft;
while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
- computedStyle = defaultView.getComputedStyle(elem, null);
- top -= elem.scrollTop, left -= elem.scrollLeft;
+ if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+ break;
+ }
+
+ computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+ top -= elem.scrollTop;
+ left -= elem.scrollLeft;
+
if ( elem === offsetParent ) {
- top += elem.offsetTop, left += elem.offsetLeft;
- if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.tagName)) )
- top += parseInt( computedStyle.borderTopWidth, 10) || 0,
- left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+ top += elem.offsetTop;
+ left += elem.offsetLeft;
+
+ if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.nodeName)) ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
}
- if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" )
- top += parseInt( computedStyle.borderTopWidth, 10) || 0,
- left += parseInt( computedStyle.borderLeftWidth, 10) || 0;
+
+ if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
prevComputedStyle = computedStyle;
}
- if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" )
- top += body.offsetTop,
+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+ top += body.offsetTop;
left += body.offsetLeft;
+ }
- if ( prevComputedStyle.position === "fixed" )
- top += Math.max(docElem.scrollTop, body.scrollTop),
- left += Math.max(docElem.scrollLeft, body.scrollLeft);
+ if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
+ top += Math.max( docElem.scrollTop, body.scrollTop );
+ left += Math.max( docElem.scrollLeft, body.scrollLeft );
+ }
return { top: top, left: left };
};
+}
jQuery.offset = {
initialize: function() {
- if ( this.initialized ) return;
- var body = document.body, container = document.createElement('div'), innerDiv, checkDiv, table, td, rules, prop, bodyMarginTop = body.style.marginTop,
- html = '<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';
+ var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0,
+ html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
- rules = { position: 'absolute', top: 0, left: 0, margin: 0, border: 0, width: '1px', height: '1px', visibility: 'hidden' };
- for ( prop in rules ) container.style[prop] = rules[prop];
+ jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
container.innerHTML = html;
- body.insertBefore(container, body.firstChild);
- innerDiv = container.firstChild, checkDiv = innerDiv.firstChild, td = innerDiv.nextSibling.firstChild.firstChild;
+ body.insertBefore( container, body.firstChild );
+ innerDiv = container.firstChild;
+ checkDiv = innerDiv.firstChild;
+ td = innerDiv.nextSibling.firstChild.firstChild;
this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
- innerDiv.style.overflow = 'hidden', innerDiv.style.position = 'relative';
+ checkDiv.style.position = "fixed", checkDiv.style.top = "20px";
+ // safari subtracts parent border width here which is 5px
+ this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
+ checkDiv.style.position = checkDiv.style.top = "";
+
+ innerDiv.style.overflow = "hidden", innerDiv.style.position = "relative";
this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
- body.style.marginTop = '1px';
- this.doesNotIncludeMarginInBodyOffset = (body.offsetTop === 0);
- body.style.marginTop = bodyMarginTop;
+ this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
- body.removeChild(container);
- this.initialized = true;
+ body.removeChild( container );
+ body = container = innerDiv = checkDiv = table = td = null;
+ jQuery.offset.initialize = jQuery.noop;
},
- bodyOffset: function(body) {
- jQuery.offset.initialized || jQuery.offset.initialize();
+ bodyOffset: function( body ) {
var top = body.offsetTop, left = body.offsetLeft;
- if ( jQuery.offset.doesNotIncludeMarginInBodyOffset )
- top += parseInt( jQuery.curCSS(body, 'marginTop', true), 10 ) || 0,
- left += parseInt( jQuery.curCSS(body, 'marginLeft', true), 10 ) || 0;
+
+ jQuery.offset.initialize();
+
+ if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
+ top += parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0;
+ left += parseFloat( jQuery.curCSS(body, "marginLeft", true) ) || 0;
+ }
+
return { top: top, left: left };
+ },
+
+ setOffset: function( elem, options, i ) {
+ // set position first, in-case top/left are set even on static elem
+ if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) {
+ elem.style.position = "relative";
+ }
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curTop = parseInt( jQuery.curCSS( elem, "top", true ), 10 ) || 0,
+ curLeft = parseInt( jQuery.curCSS( elem, "left", true ), 10 ) || 0;
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ var props = {
+ top: (options.top - curOffset.top) + curTop,
+ left: (options.left - curOffset.left) + curLeft
+ };
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
}
};
jQuery.fn.extend({
position: function() {
- var left = 0, top = 0, results;
-
- if ( this[0] ) {
- // Get *real* offsetParent
- var offsetParent = this.offsetParent(),
-
- // Get correct offsets
- offset = this.offset(),
- parentOffset = /^body|html$/i.test(offsetParent[0].tagName) ? { top: 0, left: 0 } : offsetParent.offset();
-
- // Subtract element margins
- // note: when an element has margin: auto the offsetLeft and marginLeft
- // are the same in Safari causing offset.left to incorrectly be 0
- offset.top -= num( this, 'marginTop' );
- offset.left -= num( this, 'marginLeft' );
-
- // Add offsetParent borders
- parentOffset.top += num( offsetParent, 'borderTopWidth' );
- parentOffset.left += num( offsetParent, 'borderLeftWidth' );
-
- // Subtract the two offsets
- results = {
- top: offset.top - parentOffset.top,
- left: offset.left - parentOffset.left
- };
+ if ( !this[0] ) {
+ return null;
}
- return results;
+ var elem = this[0],
+
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent(),
+
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = /^body|html$/i.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= parseFloat( jQuery.curCSS(elem, "marginTop", true) ) || 0;
+ offset.left -= parseFloat( jQuery.curCSS(elem, "marginLeft", true) ) || 0;
+
+ // Add offsetParent borders
+ parentOffset.top += parseFloat( jQuery.curCSS(offsetParent[0], "borderTopWidth", true) ) || 0;
+ parentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], "borderLeftWidth", true) ) || 0;
+
+ // Subtract the two offsets
+ return {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ };
},
offsetParent: function() {
- var offsetParent = this[0].offsetParent || document.body;
- while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && jQuery.css(offsetParent, 'position') == 'static') )
- offsetParent = offsetParent.offsetParent;
- return jQuery(offsetParent);
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.body;
+ while ( offsetParent && (!/^body|html$/i.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent;
+ });
}
});
// Create scrollLeft and scrollTop methods
-jQuery.each( ['Left', 'Top'], function(i, name) {
- var method = 'scroll' + name;
+jQuery.each( ["Left", "Top"], function( i, name ) {
+ var method = "scroll" + name;
jQuery.fn[ method ] = function(val) {
- if (!this[0]) return null;
-
- return val !== undefined ?
+ var elem = this[0], win;
+
+ if ( !elem ) {
+ return null;
+ }
+ if ( val !== undefined ) {
// Set the scroll offset
- this.each(function() {
- this == window || this == document ?
- window.scrollTo(
- !i ? val : jQuery(window).scrollLeft(),
- i ? val : jQuery(window).scrollTop()
- ) :
+ return this.each(function() {
+ win = getWindow( this );
+
+ if ( win ) {
+ win.scrollTo(
+ !i ? val : jQuery(win).scrollLeft(),
+ i ? val : jQuery(win).scrollTop()
+ );
+
+ } else {
this[ method ] = val;
- }) :
+ }
+ });
+ } else {
+ win = getWindow( elem );
// Return the scroll offset
- this[0] == window || this[0] == document ?
- self[ i ? 'pageYOffset' : 'pageXOffset' ] ||
- jQuery.boxModel && document.documentElement[ method ] ||
- document.body[ method ] :
- this[0][ method ];
+ return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
+ jQuery.support.boxModel && win.document.documentElement[ method ] ||
+ win.document.body[ method ] :
+ elem[ method ];
+ }
};
});
+
+function getWindow( elem ) {
+ return ("scrollTo" in elem && elem.document) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
// Create innerHeight, innerWidth, outerHeight and outerWidth methods
-jQuery.each([ "Height", "Width" ], function(i, name){
+jQuery.each([ "Height", "Width" ], function( i, name ) {
- var tl = i ? "Left" : "Top", // top or left
- br = i ? "Right" : "Bottom", // bottom or right
- lower = name.toLowerCase();
+ var type = name.toLowerCase();
// innerHeight and innerWidth
- jQuery.fn["inner" + name] = function(){
+ jQuery.fn["inner" + name] = function() {
return this[0] ?
- jQuery.css( this[0], lower, false, "padding" ) :
+ jQuery.css( this[0], type, false, "padding" ) :
null;
};
// outerHeight and outerWidth
- jQuery.fn["outer" + name] = function(margin) {
+ jQuery.fn["outer" + name] = function( margin ) {
return this[0] ?
- jQuery.css( this[0], lower, false, margin ? "margin" : "border" ) :
+ jQuery.css( this[0], type, false, margin ? "margin" : "border" ) :
null;
};
- var type = name.toLowerCase();
-
jQuery.fn[ type ] = function( size ) {
// Get window width or height
- return this[0] == window ?
+ var elem = this[0];
+ if ( !elem ) {
+ return size == null ? null : this;
+ }
+
+ if ( jQuery.isFunction( size ) ) {
+ return this.each(function( i ) {
+ var self = jQuery( this );
+ self[ type ]( size.call( this, i, self[ type ]() ) );
+ });
+ }
+
+ return ("scrollTo" in elem && elem.document) ? // does it walk and quack like a window?
// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
- document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] ||
- document.body[ "client" + name ] :
+ elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
+ elem.document.body[ "client" + name ] :
// Get document width or height
- this[0] == document ?
+ (elem.nodeType === 9) ? // is it a document
// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
Math.max(
- document.documentElement["client" + name],
- document.body["scroll" + name], document.documentElement["scroll" + name],
- document.body["offset" + name], document.documentElement["offset" + name]
+ elem.documentElement["client" + name],
+ elem.body["scroll" + name], elem.documentElement["scroll" + name],
+ elem.body["offset" + name], elem.documentElement["offset" + name]
) :
// Get or set width or height on the element
size === undefined ?
// Get width or height on the element
- (this.length ? jQuery.css( this[0], type ) : null) :
+ jQuery.css( elem, type ) :
// Set the width or height on the element (default to pixels if value is unitless)
this.css( type, typeof size === "string" ? size : size + "px" );
};
});
-})();
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+
+})(window);
diff --git a/libs/jquery/stop.png b/libs/jquery/stop.png
deleted file mode 100644
index 644895c21e..0000000000
--- a/libs/jquery/stop.png
+++ /dev/null
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-anim_basic_16x16.gif b/libs/jquery/themes/base/images/ui-anim_basic_16x16.gif
new file mode 100644
index 0000000000..085ccaecaf
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-anim_basic_16x16.gif
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png b/libs/jquery/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 0000000000..5b5dab2ab7
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-bg_flat_0_aaaaaa_40x100.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-bg_flat_75_ffffff_40x100.png b/libs/jquery/themes/base/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644
index 0000000000..ac8b229af9
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-bg_flat_75_ffffff_40x100.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png b/libs/jquery/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644
index 0000000000..ad3d6346e0
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-bg_glass_55_fbf9ee_1x400.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-bg_glass_65_ffffff_1x400.png b/libs/jquery/themes/base/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 0000000000..42ccba269b
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-bg_glass_65_ffffff_1x400.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-bg_glass_75_dadada_1x400.png b/libs/jquery/themes/base/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644
index 0000000000..5a46b47cb1
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-bg_glass_75_dadada_1x400.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png b/libs/jquery/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644
index 0000000000..86c2baa655
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png b/libs/jquery/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 0000000000..4443fdc1a1
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-bg_glass_95_fef1ec_1x400.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/libs/jquery/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644
index 0000000000..7c9fa6c6ed
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-icons_222222_256x240.png b/libs/jquery/themes/base/images/ui-icons_222222_256x240.png
new file mode 100644
index 0000000000..ee039dc096
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-icons_222222_256x240.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-icons_2e83ff_256x240.png b/libs/jquery/themes/base/images/ui-icons_2e83ff_256x240.png
new file mode 100644
index 0000000000..45e8928e52
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-icons_2e83ff_256x240.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-icons_454545_256x240.png b/libs/jquery/themes/base/images/ui-icons_454545_256x240.png
new file mode 100644
index 0000000000..7ec70d11bf
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-icons_454545_256x240.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-icons_888888_256x240.png b/libs/jquery/themes/base/images/ui-icons_888888_256x240.png
new file mode 100644
index 0000000000..5ba708c391
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-icons_888888_256x240.png
Binary files differ
diff --git a/libs/jquery/themes/base/images/ui-icons_cd0a0a_256x240.png b/libs/jquery/themes/base/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 0000000000..7930a55809
--- /dev/null
+++ b/libs/jquery/themes/base/images/ui-icons_cd0a0a_256x240.png
Binary files differ
diff --git a/libs/jquery/themes/base/jquery-ui.css b/libs/jquery/themes/base/jquery-ui.css
new file mode 100644
index 0000000000..763bf311a4
--- /dev/null
+++ b/libs/jquery/themes/base/jquery-ui.css
@@ -0,0 +1,487 @@
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+*/
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
+.ui-helper-clearfix { display: inline-block; }
+/* required comment for clearfix to work in Opera \*/
+* html .ui-helper-clearfix { height:1%; }
+.ui-helper-clearfix { display:block; }
+/* end clearfix */
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
+/* Accordion
+----------------------------------*/
+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
+.ui-accordion .ui-accordion-li-fix { display: inline; }
+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
+/* IE7-/Win - Fix extra vertical space in lists */
+.ui-accordion a { zoom: 1; }
+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
+.ui-accordion .ui-accordion-content-active { display: block; }/* Autocomplete
+----------------------------------*/
+.ui-autocomplete { position: absolute; cursor: default; }
+.ui-autocomplete-loading { background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; }
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
+
+/* Menu
+----------------------------------*/
+.ui-menu {
+ list-style:none;
+ padding: 2px;
+ margin: 0;
+ display:block;
+}
+.ui-menu .ui-menu {
+ margin-top: -3px;
+}
+.ui-menu .ui-menu-item {
+ margin:0;
+ padding: 0;
+ zoom: 1;
+ float: left;
+ clear: left;
+ width: 100%;
+}
+.ui-menu .ui-menu-item a {
+ text-decoration:none;
+ display:block;
+ padding:.2em .4em;
+ line-height:1.5;
+ zoom:1;
+}
+.ui-menu .ui-menu-item a.ui-state-hover,
+.ui-menu .ui-menu-item a.ui-state-active {
+ font-weight: normal;
+ margin: -1px;
+}
+/* Button
+----------------------------------*/
+
+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
+.ui-button-icons-only { width: 3.4em; }
+button.ui-button-icons-only { width: 3.7em; }
+
+/*button text element */
+.ui-button .ui-button-text { display: block; line-height: 1.4; }
+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
+.ui-button-text-icon .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
+/* no icon support for input elements, provide padding by default */
+input.ui-button { padding: .4em 1em; }
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon, .ui-button-text-icon .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
+.ui-button-text-icon .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+
+/*button sets*/
+.ui-buttonset { margin-right: 7px; }
+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
+
+/* workarounds */
+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
+
+
+
+
+
+/* Datepicker
+----------------------------------*/
+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+ display: none; /*sorry for IE5*/
+ display/**/: block; /*sorry for IE5*/
+ position: absolute; /*must have*/
+ z-index: -1; /*must have*/
+ filter: mask(); /*must have*/
+ top: -4px; /*must have*/
+ left: -4px; /*must have*/
+ width: 200px; /*must have*/
+ height: 200px; /*must have*/
+}/* Dialog
+----------------------------------*/
+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; }
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
+/* Progressbar
+----------------------------------*/
+.ui-progressbar { height:2em; text-align: left; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable
+----------------------------------*/
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Selectable
+----------------------------------*/
+.ui-selectable-helper { border:1px dotted black }
+/* Slider
+----------------------------------*/
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
+----------------------------------*/
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
+.ui-tabs .ui-tabs-hide { display: none !important; }
+/*
+* jQuery UI CSS Framework
+* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+* To view and modify this theme, visit http://jqueryui.com/themeroller/
+*/
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1.1em/*{fsDefault}*/; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif/*{ffDefault}*/; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa/*{borderColorContent}*/; background: #ffffff/*{bgColorContent}*/ url(images/ui-bg_flat_75_ffffff_40x100.png)/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/; color: #222222/*{fcContent}*/; }
+.ui-widget-content a { color: #222222/*{fcContent}*/; }
+.ui-widget-header { border: 1px solid #aaaaaa/*{borderColorHeader}*/; background: #cccccc/*{bgColorHeader}*/ url(images/ui-bg_highlight-soft_75_cccccc_1x100.png)/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/; color: #222222/*{fcHeader}*/; font-weight: bold; }
+.ui-widget-header a { color: #222222/*{fcHeader}*/; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3/*{borderColorDefault}*/; background: #e6e6e6/*{bgColorDefault}*/ url(images/ui-bg_glass_75_e6e6e6_1x400.png)/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #555555/*{fcDefault}*/; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555/*{fcDefault}*/; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999/*{borderColorHover}*/; background: #dadada/*{bgColorHover}*/ url(images/ui-bg_glass_75_dadada_1x400.png)/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcHover}*/; }
+.ui-state-hover a, .ui-state-hover a:hover { color: #212121/*{fcHover}*/; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa/*{borderColorActive}*/; background: #ffffff/*{bgColorActive}*/ url(images/ui-bg_glass_65_ffffff_1x400.png)/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/; font-weight: normal/*{fwDefault}*/; color: #212121/*{fcActive}*/; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121/*{fcActive}*/; text-decoration: none; }
+.ui-widget :active { outline: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1/*{borderColorHighlight}*/; background: #fbf9ee/*{bgColorHighlight}*/ url(images/ui-bg_glass_55_fbf9ee_1x400.png)/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/; color: #363636/*{fcHighlight}*/; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636/*{fcHighlight}*/; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a/*{borderColorError}*/; background: #fef1ec/*{bgColorError}*/ url(images/ui-bg_glass_95_fef1ec_1x400.png)/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/; color: #cd0a0a/*{fcError}*/; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a/*{fcError}*/; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a/*{fcError}*/; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsContent}*/; }
+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png)/*{iconsHeader}*/; }
+.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png)/*{iconsDefault}*/; }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsHover}*/; }
+.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png)/*{iconsActive}*/; }
+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png)/*{iconsHighlight}*/; }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png)/*{iconsError}*/; }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-off { background-position: -96px -144px; }
+.ui-icon-radio-on { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-tl { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-tr { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-bl { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-br { -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-top { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-bottom { -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-right { -moz-border-radius-topright: 4px/*{cornerRadius}*/; -webkit-border-top-right-radius: 4px/*{cornerRadius}*/; border-top-right-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomright: 4px/*{cornerRadius}*/; -webkit-border-bottom-right-radius: 4px/*{cornerRadius}*/; border-bottom-right-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-left { -moz-border-radius-topleft: 4px/*{cornerRadius}*/; -webkit-border-top-left-radius: 4px/*{cornerRadius}*/; border-top-left-radius: 4px/*{cornerRadius}*/; -moz-border-radius-bottomleft: 4px/*{cornerRadius}*/; -webkit-border-bottom-left-radius: 4px/*{cornerRadius}*/; border-bottom-left-radius: 4px/*{cornerRadius}*/; }
+.ui-corner-all { -moz-border-radius: 4px/*{cornerRadius}*/; -webkit-border-radius: 4px/*{cornerRadius}*/; border-radius: 4px/*{cornerRadius}*/; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa/*{bgColorOverlay}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityOverlay}*/; }
+.ui-widget-shadow { margin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/; padding: 8px/*{thicknessShadow}*/; background: #aaaaaa/*{bgColorShadow}*/ url(images/ui-bg_flat_0_aaaaaa_40x100.png)/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/; opacity: .3;filter:Alpha(Opacity=30)/*{opacityShadow}*/; -moz-border-radius: 8px/*{cornerRadiusShadow}*/; -webkit-border-radius: 8px/*{cornerRadiusShadow}*/; border-radius: 8px/*{cornerRadiusShadow}*/; } \ No newline at end of file
diff --git a/libs/jquery/thickbox-loading.gif b/libs/jquery/thickbox-loading.gif
deleted file mode 100644
index 82290f4833..0000000000
--- a/libs/jquery/thickbox-loading.gif
+++ /dev/null
Binary files differ
diff --git a/libs/jquery/thickbox.css b/libs/jquery/thickbox.css
deleted file mode 100644
index 1f58bc6785..0000000000
--- a/libs/jquery/thickbox.css
+++ /dev/null
@@ -1,194 +0,0 @@
-/* ----------------------------------------------------------------------------------------------------------------*/
- /* ---------->>> global settings needed for thickbox <<<-----------------------------------------------------------*/
- /* ----------------------------------------------------------------------------------------------------------------*/
- /* ----------------------------------------------------------------------------------------------------------------*/
- /* ---------->>> thickbox specific link and font settings <<<------------------------------------------------------*/
- /* ----------------------------------------------------------------------------------------------------------------*/
-#TB_window {
- font: 12px Arial, Helvetica, sans-serif;
- color: #333333;
-}
-
-#TB_secondLine {
- font: 10px Arial, Helvetica, sans-serif;
- color: #666666;
-}
-
-#TB_window a:link {
- color: #666666;
-}
-
-#TB_window a:visited {
- color: #666666;
-}
-
-#TB_window a:hover {
- color: #000;
-}
-
-#TB_window a:active {
- color: #666666;
-}
-
-#TB_window a:focus {
- color: #666666;
-}
-
-/* ----------------------------------------------------------------------------------------------------------------*/
- /* ---------->>> thickbox settings <<<-----------------------------------------------------------------------------*/
- /* ----------------------------------------------------------------------------------------------------------------*/
-#TB_overlay {
- position: fixed;
- z-index: 100;
- top: 0px;
- left: 0px;
- height: 100%;
- width: 100%;
-}
-
-.TB_overlayMacFFBGHack {
- background: url(libs/jquery/macFFBgHack.png) repeat;
-}
-
-.TB_overlayBG {
- background-color: #000;
- filter: alpha(opacity = 75);
- -moz-opacity: 0.75;
- opacity: 0.75;
-}
-
-* html #TB_overlay { /* ie6 hack */
- position: absolute;
- height: expression(document . body . scrollHeight > document . body .
- offsetHeight ? document . body . scrollHeight : document
- . body .
- offsetHeight + 'px');
-}
-
-#TB_window {
- position: fixed;
- background: #ffffff;
- z-index: 102;
- color: #000000;
- display: none;
- border: 4px solid #525252;
- text-align: left;
- top: 50%;
- left: 50%;
-}
-
-* html #TB_window { /* ie6 hack */
- position: absolute;
- margin-top: expression(0 - parseInt(this . offsetHeight/ 2) +
- (
- TBWindowMargin = document . documentElement && document .
- documentElement . scrollTop || document . body . scrollTop
- ) +
- 'px' );
-}
-
-#TB_window img#TB_Image {
- display: block;
- margin: 15px 0 0 15px;
- border-right: 1px solid #ccc;
- border-bottom: 1px solid #ccc;
- border-top: 1px solid #666;
- border-left: 1px solid #666;
-}
-
-#TB_caption {
- height: 25px;
- padding: 7px 30px 10px 25px;
- float: left;
-}
-
-#TB_closeWindow {
- height: 25px;
- padding: 11px 25px 10px 0;
- float: right;
-}
-
-#TB_closeAjaxWindow {
- padding: 7px 10px 5px 0;
- margin-bottom: 1px;
- text-align: right;
- float: right;
-}
-
-#TB_ajaxWindowTitle {
- float: left;
- padding: 7px 0 5px 10px;
- margin-bottom: 1px;
-}
-
-#TB_title {
- background-color: #e8e8e8;
- height: 27px;
-}
-
-#TB_ajaxContent {
- clear: both;
- padding: 2px 15px 15px 15px;
- overflow: auto;
- text-align: left;
- line-height: 1.4em;
-}
-
-#TB_ajaxContent.TB_modal {
- padding: 15px;
-}
-
-#TB_ajaxContent p {
- padding: 5px 0px 5px 0px;
-}
-
-#TB_load {
- position: fixed;
- display: none;
- height: 13px;
- width: 208px;
- z-index: 103;
- top: 50%;
- left: 50%;
- margin: -6px 0 0 -104px; /* -height/2 0 0 -width/2 */
-}
-
-* html #TB_load { /* ie6 hack */
- position: absolute;
- margin-top: expression(0 - parseInt(this . offsetHeight/ 2) +
- (
- TBWindowMargin = document . documentElement && document .
- documentElement . scrollTop || document . body . scrollTop
- ) +
- 'px' );
-}
-
-#TB_HideSelect {
- z-index: 99;
- position: fixed;
- top: 0;
- left: 0;
- background-color: #fff;
- border: none;
- filter: alpha(opacity = 0);
- -moz-opacity: 0;
- opacity: 0;
- height: 100%;
- width: 100%;
-}
-
-* html #TB_HideSelect { /* ie6 hack */
- position: absolute;
- height: expression(document . body . scrollHeight > document . body .
- offsetHeight ? document . body . scrollHeight : document
- . body .
- offsetHeight + 'px');
-}
-
-#TB_iframeContent {
- clear: both;
- border: none;
- margin-bottom: -1px;
- margin-top: 1px;
- _margin-bottom: 1px;
-}
diff --git a/libs/jquery/thickbox.js b/libs/jquery/thickbox.js
deleted file mode 100644
index d2cf5404a6..0000000000
--- a/libs/jquery/thickbox.js
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Thickbox 3.1 - One Box To Rule Them All.
- * By Cody Lindley (http://www.codylindley.com)
- * Copyright (c) 2007 cody lindley
- * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
-*/
-
-var tb_pathToImage = "libs/jquery/thickbox-loading.gif";
-
-/*!!!!!!!!!!!!!!!!! edit below this line at your own risk !!!!!!!!!!!!!!!!!!!!!!!*/
-
-//on page load call tb_init
-$(document).ready(function(){
- tb_init('a.thickbox, area.thickbox, input.thickbox');//pass where to apply thickbox
- imgLoader = new Image();// preload image
- imgLoader.src = tb_pathToImage;
-});
-
-//add thickbox to href & area elements that have a class of .thickbox
-function tb_init(domChunk){
- $(domChunk).click(function(){
- var t = this.title || this.name || null;
- var a = this.href || this.alt;
- var g = this.rel || false;
- tb_show(t,a,g);
- this.blur();
- return false;
- });
-}
-
-function tb_show(caption, url, imageGroup) {//function called when the user clicks on a thickbox link
-
- try {
- if (typeof document.body.style.maxHeight === "undefined") {//if IE 6
- $("body","html").css({height: "100%", width: "100%"});
- $("html").css("overflow","hidden");
- if (document.getElementById("TB_HideSelect") === null) {//iframe to hide select elements in ie6
- $("body").append("<iframe id='TB_HideSelect'></iframe><div id='TB_overlay'></div><div id='TB_window'></div>");
- $("#TB_overlay").click(tb_remove);
- }
- }else{//all others
- if(document.getElementById("TB_overlay") === null){
- $("body").append("<div id='TB_overlay'></div><div id='TB_window'></div>");
- $("#TB_overlay").click(tb_remove);
- }
- }
-
- if(tb_detectMacXFF()){
- $("#TB_overlay").addClass("TB_overlayMacFFBGHack");//use png overlay so hide flash
- }else{
- $("#TB_overlay").addClass("TB_overlayBG");//use background and opacity
- }
-
- if(caption===null){caption="";}
- $("body").append("<div id='TB_load'><img src='"+imgLoader.src+"' /></div>");//add loader to the page
- $('#TB_load').show();//show loader
-
- var baseURL;
- if(url.indexOf("?")!==-1){ //ff there is a query string involved
- baseURL = url.substr(0, url.indexOf("?"));
- }else{
- baseURL = url;
- }
-
- var urlString = /\.jpg$|\.jpeg$|\.png$|\.gif$|\.bmp$/;
- var urlType = baseURL.toLowerCase().match(urlString);
-
- if(urlType == '.jpg' || urlType == '.jpeg' || urlType == '.png' || urlType == '.gif' || urlType == '.bmp'){//code to show images
-
- TB_PrevCaption = "";
- TB_PrevURL = "";
- TB_PrevHTML = "";
- TB_NextCaption = "";
- TB_NextURL = "";
- TB_NextHTML = "";
- TB_imageCount = "";
- TB_FoundURL = false;
- if(imageGroup){
- TB_TempArray = $("a[@rel="+imageGroup+"]").get();
- for (TB_Counter = 0; ((TB_Counter < TB_TempArray.length) && (TB_NextHTML === "")); TB_Counter++) {
- var urlTypeTemp = TB_TempArray[TB_Counter].href.toLowerCase().match(urlString);
- if (!(TB_TempArray[TB_Counter].href == url)) {
- if (TB_FoundURL) {
- TB_NextCaption = TB_TempArray[TB_Counter].title;
- TB_NextURL = TB_TempArray[TB_Counter].href;
- TB_NextHTML = "<span id='TB_next'>&nbsp;&nbsp;<a href='#'>Next &gt;</a></span>";
- } else {
- TB_PrevCaption = TB_TempArray[TB_Counter].title;
- TB_PrevURL = TB_TempArray[TB_Counter].href;
- TB_PrevHTML = "<span id='TB_prev'>&nbsp;&nbsp;<a href='#'>&lt; Prev</a></span>";
- }
- } else {
- TB_FoundURL = true;
- TB_imageCount = "Image " + (TB_Counter + 1) +" of "+ (TB_TempArray.length);
- }
- }
- }
-
- imgPreloader = new Image();
- imgPreloader.onload = function(){
- imgPreloader.onload = null;
-
- // Resizing large images - orginal by Christian Montoya edited by me.
- var pagesize = tb_getPageSize();
- var x = pagesize[0] - 150;
- var y = pagesize[1] - 150;
- var imageWidth = imgPreloader.width;
- var imageHeight = imgPreloader.height;
- if (imageWidth > x) {
- imageHeight = imageHeight * (x / imageWidth);
- imageWidth = x;
- if (imageHeight > y) {
- imageWidth = imageWidth * (y / imageHeight);
- imageHeight = y;
- }
- } else if (imageHeight > y) {
- imageWidth = imageWidth * (y / imageHeight);
- imageHeight = y;
- if (imageWidth > x) {
- imageHeight = imageHeight * (x / imageWidth);
- imageWidth = x;
- }
- }
- // End Resizing
-
- TB_WIDTH = imageWidth + 30;
- TB_HEIGHT = imageHeight + 60;
- $("#TB_window").append("<a href='' id='TB_ImageOff' title='Close'><img id='TB_Image' src='"+url+"' width='"+imageWidth+"' height='"+imageHeight+"' alt='"+caption+"'/></a>" + "<div id='TB_caption'>"+caption+"<div id='TB_secondLine'>" + TB_imageCount + TB_PrevHTML + TB_NextHTML + "</div></div><div id='TB_closeWindow'><a href='#' id='TB_closeWindowButton' title='Close'><img src='libs/jquery/stop.png' alt='close' /></a></div>");
-
- $("#TB_closeWindowButton").click(tb_remove);
-
- if (!(TB_PrevHTML === "")) {
- function goPrev(){
- if($(document).unbind("click",goPrev)){$(document).unbind("click",goPrev);}
- $("#TB_window").remove();
- $("body").append("<div id='TB_window'></div>");
- tb_show(TB_PrevCaption, TB_PrevURL, imageGroup);
- return false;
- }
- $("#TB_prev").click(goPrev);
- }
-
- if (!(TB_NextHTML === "")) {
- function goNext(){
- $("#TB_window").remove();
- $("body").append("<div id='TB_window'></div>");
- tb_show(TB_NextCaption, TB_NextURL, imageGroup);
- return false;
- }
- $("#TB_next").click(goNext);
-
- }
-
- document.onkeydown = function(e){
- if (e == null) { // ie
- keycode = event.keyCode;
- } else { // mozilla
- keycode = e.which;
- }
- if(keycode == 27){ // close
- tb_remove();
- } else if(keycode == 190){ // display previous image
- if(!(TB_NextHTML == "")){
- document.onkeydown = "";
- goNext();
- }
- } else if(keycode == 188){ // display next image
- if(!(TB_PrevHTML == "")){
- document.onkeydown = "";
- goPrev();
- }
- }
- };
-
- tb_position();
- $("#TB_load").remove();
- $("#TB_ImageOff").click(tb_remove);
- $("#TB_window").css({display:"block"}); //for safari using css instead of show
- };
-
- imgPreloader.src = url;
- }else{//code to show html
-
- var queryString = url.replace(/^[^\?]+\??/,'');
- var params = tb_parseQuery( queryString );
-
- TB_WIDTH = (params['width']*1) + 30 || 630; //defaults to 630 if no paramaters were added to URL
- TB_HEIGHT = (params['height']*1) + 40 || 440; //defaults to 440 if no paramaters were added to URL
- ajaxContentW = TB_WIDTH - 30;
- ajaxContentH = TB_HEIGHT - 45;
-
- if(url.indexOf('TB_iframe') != -1){// either iframe or ajax window
- urlNoQuery = url.split('TB_');
- $("#TB_iframeContent").remove();
- if(params['modal'] != "true"){//iframe no modal
- $("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton' title='Close'><img src='libs/jquery/stop.png' alt='close' /></a></div></div><iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW + 29)+"px;height:"+(ajaxContentH + 17)+"px;' > </iframe>");
- }else{//iframe modal
- $("#TB_overlay").unbind();
- $("#TB_window").append("<iframe frameborder='0' hspace='0' src='"+urlNoQuery[0]+"' id='TB_iframeContent' name='TB_iframeContent"+Math.round(Math.random()*1000)+"' onload='tb_showIframe()' style='width:"+(ajaxContentW + 29)+"px;height:"+(ajaxContentH + 17)+"px;'> </iframe>");
- }
- }else{// not an iframe, ajax
- if($("#TB_window").css("display") != "block"){
- if(params['modal'] != "true"){//ajax no modal
- $("#TB_window").append("<div id='TB_title'><div id='TB_ajaxWindowTitle'>"+caption+"</div><div id='TB_closeAjaxWindow'><a href='#' id='TB_closeWindowButton'><img src='libs/jquery/stop.png' alt='close' /></a></div></div><div id='TB_ajaxContent' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px'></div>");
- }else{//ajax modal
- $("#TB_overlay").unbind();
- $("#TB_window").append("<div id='TB_ajaxContent' class='TB_modal' style='width:"+ajaxContentW+"px;height:"+ajaxContentH+"px;'></div>");
- }
- }else{//this means the window is already up, we are just loading new content via ajax
- $("#TB_ajaxContent")[0].style.width = ajaxContentW +"px";
- $("#TB_ajaxContent")[0].style.height = ajaxContentH +"px";
- $("#TB_ajaxContent")[0].scrollTop = 0;
- $("#TB_ajaxWindowTitle").html(caption);
- }
- }
-
- $("#TB_closeWindowButton").click(tb_remove);
-
- if(url.indexOf('TB_inline') != -1){
- $("#TB_ajaxContent").append($('#' + params['inlineId']).children());
- $("#TB_window").unload(function () {
- $('#' + params['inlineId']).append( $("#TB_ajaxContent").children() ); // move elements back when you're finished
- });
- tb_position();
- $("#TB_load").remove();
- $("#TB_window").css({display:"block"});
- }else if(url.indexOf('TB_iframe') != -1){
- tb_position();
- if($.browser.safari){//safari needs help because it will not fire iframe onload
- $("#TB_load").remove();
- $("#TB_window").css({display:"block"});
- }
- }else{
- $("#TB_ajaxContent").load(url += "&random=" + (new Date().getTime()),function(){//to do a post change this load method
- tb_position();
- $("#TB_load").remove();
- tb_init("#TB_ajaxContent a.thickbox");
- $("#TB_window").css({display:"block"});
- });
- }
-
- }
-
- if(!params['modal']){
- document.onkeyup = function(e){
- if (e == null) { // ie
- keycode = event.keyCode;
- } else { // mozilla
- keycode = e.which;
- }
- if(keycode == 27){ // close
- tb_remove();
- }
- };
- }
-
- } catch(e) {
- //nothing here
- }
-}
-
-//helper functions below
-function tb_showIframe(){
- $("#TB_load").remove();
- $("#TB_window").css({display:"block"});
-}
-
-function tb_remove() {
- $("#TB_imageOff").unbind("click");
- $("#TB_closeWindowButton").unbind("click");
- $("#TB_window").fadeOut("fast",function(){$('#TB_window,#TB_overlay,#TB_HideSelect').trigger("unload").unbind().remove();});
- $("#TB_load").remove();
- if (typeof document.body.style.maxHeight == "undefined") {//if IE 6
- $("body","html").css({height: "auto", width: "auto"});
- $("html").css("overflow","");
- }
- document.onkeydown = "";
- document.onkeyup = "";
- return false;
-}
-
-function tb_position() {
-$("#TB_window").css({marginLeft: '-' + parseInt((TB_WIDTH / 2),10) + 'px', width: TB_WIDTH + 'px'});
- if ( !(jQuery.browser.msie && jQuery.browser.version < 7)) { // take away IE6
- $("#TB_window").css({marginTop: '-' + parseInt((TB_HEIGHT / 2),10) + 'px'});
- }
-}
-
-function tb_parseQuery ( query ) {
- var Params = {};
- if ( ! query ) {return Params;}// return empty object
- var Pairs = query.split(/[;&]/);
- for ( var i = 0; i < Pairs.length; i++ ) {
- var KeyVal = Pairs[i].split('=');
- if ( ! KeyVal || KeyVal.length != 2 ) {continue;}
- var key = unescape( KeyVal[0] );
- var val = unescape( KeyVal[1] );
- val = val.replace(/\+/g, ' ');
- Params[key] = val;
- }
- return Params;
-}
-
-function tb_getPageSize(){
- var de = document.documentElement;
- var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
- var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
- arrayPageSize = [w,h];
- return arrayPageSize;
-}
-
-function tb_detectMacXFF() {
- var userAgent = navigator.userAgent.toLowerCase();
- if (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox')!=-1) {
- return true;
- }
-}
-
-
diff --git a/libs/json/json.js b/libs/json/json.js
deleted file mode 100644
index 935bd40ce8..0000000000
--- a/libs/json/json.js
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- json.js
- 2007-08-19
-
- Public Domain
-
- This file adds these methods to JavaScript:
-
- array.toJSONString(whitelist)
- boolean.toJSONString()
- date.toJSONString()
- number.toJSONString()
- object.toJSONString(whitelist)
- string.toJSONString()
- These methods produce a JSON text from a JavaScript value.
- It must not contain any cyclical references. Illegal values
- will be excluded.
-
- The default conversion for dates is to an ISO string. You can
- add a toJSONString method to any date object to get a different
- representation.
-
- The object and array methods can take an optional whitelist
- argument. A whitelist is an array of strings. If it is provided,
- keys in objects not found in the whitelist are excluded.
-
- string.parseJSON(filter)
- This method parses a JSON text to produce an object or
- array. It can throw a SyntaxError exception.
-
- The optional filter parameter is a function which can filter and
- transform the results. It receives each of the keys and values, and
- its return value is used instead of the original value. If it
- returns what it received, then structure is not modified. If it
- returns undefined then the member is deleted.
-
- Example:
-
- // Parse the text. If a key contains the string 'date' then
- // convert the value to a date.
-
- myData = text.parseJSON(function (key, value) {
- return key.indexOf('date') >= 0 ? new Date(value) : value;
- });
-
- It is expected that these methods will formally become part of the
- JavaScript Programming Language in the Fourth Edition of the
- ECMAScript standard in 2008.
-
- This file will break programs with improper for..in loops. See
- http://yuiblog.com/blog/2006/09/26/for-in-intrigue/
-
- This is a reference implementation. You are free to copy, modify, or
- redistribute.
-
- Use your own copy. It is extremely unwise to load untrusted third party
- code into your pages.
-*/
-
-/*jslint evil: true */
-
-// Augment the basic prototypes if they have not already been augmented.
-
-if (!Object.prototype.toJSONString) {
-
- Array.prototype.toJSONString = function (w) {
- var a = [], // The array holding the partial texts.
- i, // Loop counter.
- l = this.length,
- v; // The value to be stringified.
-
-// For each value in this array...
-
- for (i = 0; i < l; i += 1) {
- v = this[i];
- switch (typeof v) {
- case 'object':
-
-// Serialize a JavaScript object value. Ignore objects thats lack the
-// toJSONString method. Due to a specification error in ECMAScript,
-// typeof null is 'object', so watch out for that case.
-
- if (v) {
- if (typeof v.toJSONString === 'function') {
- a.push(v.toJSONString(w));
- }
- } else {
- a.push('null');
- }
- break;
-
- case 'string':
- case 'number':
- case 'boolean':
- a.push(v.toJSONString());
-
-// Values without a JSON representation are ignored.
-
- }
- }
-
-// Join all of the member texts together and wrap them in brackets.
-
- return '[' + a.join(',') + ']';
- };
-
-
- Boolean.prototype.toJSONString = function () {
- return String(this);
- };
-
-
- Date.prototype.toJSONString = function () {
-
-// Eventually, this method will be based on the date.toISOString method.
-
- function f(n) {
-
-// Format integers to have at least two digits.
-
- return n < 10 ? '0' + n : n;
- }
-
- return '"' + this.getUTCFullYear() + '-' +
- f(this.getUTCMonth() + 1) + '-' +
- f(this.getUTCDate()) + 'T' +
- f(this.getUTCHours()) + ':' +
- f(this.getUTCMinutes()) + ':' +
- f(this.getUTCSeconds()) + 'Z"';
- };
-
-
- Number.prototype.toJSONString = function () {
-
-// JSON numbers must be finite. Encode non-finite numbers as null.
-
- return isFinite(this) ? String(this) : 'null';
- };
-
-
- Object.prototype.toJSONString = function (w) {
- var a = [], // The array holding the partial texts.
- k, // The current key.
- i, // The loop counter.
- v; // The current value.
-
-// If a whitelist (array of keys) is provided, use it assemble the components
-// of the object.
-
- if (w) {
- for (i = 0; i < w.length; i += 1) {
- k = w[i];
- if (typeof k === 'string') {
- v = this[k];
- switch (typeof v) {
- case 'object':
-
-// Serialize a JavaScript object value. Ignore objects that lack the
-// toJSONString method. Due to a specification error in ECMAScript,
-// typeof null is 'object', so watch out for that case.
-
- if (v) {
- if (typeof v.toJSONString === 'function') {
- a.push(k.toJSONString() + ':' +
- v.toJSONString(w));
- }
- } else {
- a.push(k.toJSONString() + ':null');
- }
- break;
-
- case 'string':
- case 'number':
- case 'boolean':
- a.push(k.toJSONString() + ':' + v.toJSONString());
-
-// Values without a JSON representation are ignored.
-
- }
- }
- }
- } else {
-
-// Iterate through all of the keys in the object, ignoring the proto chain
-// and keys that are not strings.
-
- for (k in this) {
- if (typeof k === 'string' &&
- Object.prototype.hasOwnProperty.apply(this, [k])) {
- v = this[k];
- switch (typeof v) {
- case 'object':
-
-// Serialize a JavaScript object value. Ignore objects that lack the
-// toJSONString method. Due to a specification error in ECMAScript,
-// typeof null is 'object', so watch out for that case.
-
- if (v) {
- if (typeof v.toJSONString === 'function') {
- a.push(k.toJSONString() + ':' +
- v.toJSONString());
- }
- } else {
- a.push(k.toJSONString() + ':null');
- }
- break;
-
- case 'string':
- case 'number':
- case 'boolean':
- a.push(k.toJSONString() + ':' + v.toJSONString());
-
-// Values without a JSON representation are ignored.
-
- }
- }
- }
- }
-
-// Join all of the member texts together and wrap them in braces.
-
- return '{' + a.join(',') + '}';
- };
-
-
- (function (s) {
-
-// Augment String.prototype. We do this in an immediate anonymous function to
-// avoid defining global variables.
-
-// m is a table of character substitutions.
-
- var m = {
- '\b': '\\b',
- '\t': '\\t',
- '\n': '\\n',
- '\f': '\\f',
- '\r': '\\r',
- '"' : '\\"',
- '\\': '\\\\'
- };
-
-
- s.parseJSON = function (filter) {
- var j;
-
- function walk(k, v) {
- var i;
- if (v && typeof v === 'object') {
- for (i in v) {
- if (Object.prototype.hasOwnProperty.apply(v, [i])) {
- v[i] = walk(i, v[i]);
- }
- }
- }
- return filter(k, v);
- }
-
-
-// Parsing happens in three stages. In the first stage, we run the text against
-// a regular expression which looks for non-JSON characters. We are especially
-// concerned with '()' and 'new' because they can cause invocation, and '='
-// because it can cause mutation. But just to be safe, we will reject all
-// unexpected characters.
-
-// We split the first stage into 3 regexp operations in order to work around
-// crippling deficiencies in Safari's regexp engine. First we replace all
-// backslash pairs with '@' (a non-JSON character). Second we delete all of
-// the string literals. Third, we look to see if only JSON characters
-// remain. If so, then the text is safe for eval.
-
- if (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/.test(this.
- replace(/\\./g, '@').
- replace(/"[^"\\\n\r]*"/g, ''))) {
-
-// In the second stage we use the eval function to compile the text into a
-// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
-// in JavaScript: it can begin a block or an object literal. We wrap the text
-// in parens to eliminate the ambiguity.
-
- j = eval('(' + this + ')');
-
-// In the optional third stage, we recursively walk the new structure, passing
-// each name/value pair to a filter function for possible transformation.
-
- return typeof filter === 'function' ? walk('', j) : j;
- }
-
-// If the text is not JSON parseable, then a SyntaxError is thrown.
-
- throw new SyntaxError('parseJSON');
- };
-
-
- s.toJSONString = function () {
-
-// If the string contains no control characters, no quote characters, and no
-// backslash characters, then we can simply slap some quotes around it.
-// Otherwise we must also replace the offending characters with safe
-// sequences.
-
- if (/["\\\x00-\x1f]/.test(this)) {
- return '"' + this.replace(/[\x00-\x1f\\"]/g, function (a) {
- var c = m[a];
- if (c) {
- return c;
- }
- c = a.charCodeAt();
- return '\\u00' +
- Math.floor(c / 16).toString(16) +
- (c % 16).toString(16);
- }) + '"';
- }
- return '"' + this + '"';
- };
- })(String.prototype);
-}
diff --git a/libs/open-flash-chart/php-ofc-library/ofc_bar.php b/libs/open-flash-chart/php-ofc-library/ofc_bar.php
index 6ddda42749..728420c503 100644
--- a/libs/open-flash-chart/php-ofc-library/ofc_bar.php
+++ b/libs/open-flash-chart/php-ofc-library/ofc_bar.php
@@ -1,6 +1,6 @@
<?php
-include_once 'ofc_bar_base.php';
+include_once dirname(__FILE__) . '/ofc_bar_base.php';
class bar_value
{
diff --git a/libs/open-flash-chart/php-ofc-library/ofc_bar_3d.php b/libs/open-flash-chart/php-ofc-library/ofc_bar_3d.php
index 47552184ce..9b7f697615 100644
--- a/libs/open-flash-chart/php-ofc-library/ofc_bar_3d.php
+++ b/libs/open-flash-chart/php-ofc-library/ofc_bar_3d.php
@@ -1,6 +1,6 @@
<?php
-include_once 'ofc_bar_base.php';
+include_once dirname(__FILE__) . '/ofc_bar_base.php';
class bar_3d_value
{
diff --git a/libs/open-flash-chart/php-ofc-library/ofc_bar_filled.php b/libs/open-flash-chart/php-ofc-library/ofc_bar_filled.php
index 837c1fc458..2439bd2159 100644
--- a/libs/open-flash-chart/php-ofc-library/ofc_bar_filled.php
+++ b/libs/open-flash-chart/php-ofc-library/ofc_bar_filled.php
@@ -1,6 +1,6 @@
<?php
-include_once 'ofc_bar_base.php';
+include_once dirname(__FILE__) . '/ofc_bar_base.php';
class bar_filled_value extends bar_value
{
diff --git a/libs/open-flash-chart/php-ofc-library/ofc_bar_glass.php b/libs/open-flash-chart/php-ofc-library/ofc_bar_glass.php
index e833501519..bc330d3c74 100644
--- a/libs/open-flash-chart/php-ofc-library/ofc_bar_glass.php
+++ b/libs/open-flash-chart/php-ofc-library/ofc_bar_glass.php
@@ -1,6 +1,6 @@
<?php
-include_once 'ofc_bar_base.php';
+include_once dirname(__FILE__) . '/ofc_bar_base.php';
class bar_on_show
{
@@ -128,4 +128,4 @@ class bar_3d extends bar_base
$this->type = "bar_3d";
parent::bar_base();
}
-} \ No newline at end of file
+}
diff --git a/libs/open-flash-chart/php-ofc-library/ofc_bar_sketch.php b/libs/open-flash-chart/php-ofc-library/ofc_bar_sketch.php
index ce1bcccf8a..2bad3a3b75 100644
--- a/libs/open-flash-chart/php-ofc-library/ofc_bar_sketch.php
+++ b/libs/open-flash-chart/php-ofc-library/ofc_bar_sketch.php
@@ -1,6 +1,6 @@
<?php
-include_once 'ofc_bar_base.php';
+include_once dirname(__FILE__) . '/ofc_bar_base.php';
class bar_sketch extends bar_base
{
diff --git a/libs/open-flash-chart/php-ofc-library/ofc_bar_stack.php b/libs/open-flash-chart/php-ofc-library/ofc_bar_stack.php
index 3d9f8d9f0c..5977409982 100644
--- a/libs/open-flash-chart/php-ofc-library/ofc_bar_stack.php
+++ b/libs/open-flash-chart/php-ofc-library/ofc_bar_stack.php
@@ -1,6 +1,6 @@
<?php
-include_once 'ofc_bar_base.php';
+include_once dirname(__FILE__) . '/ofc_bar_base.php';
class bar_stack extends bar_base
{
@@ -52,4 +52,4 @@ class bar_stack_key
$tmp = 'font-size';
$this->$tmp = $font_size;
}
-} \ No newline at end of file
+}
diff --git a/libs/open-flash-chart/php-ofc-library/ofc_candle.php b/libs/open-flash-chart/php-ofc-library/ofc_candle.php
index 21ad67f8d3..7ed047f843 100644
--- a/libs/open-flash-chart/php-ofc-library/ofc_candle.php
+++ b/libs/open-flash-chart/php-ofc-library/ofc_candle.php
@@ -1,6 +1,6 @@
<?php
-include_once 'ofc_bar_base.php';
+include_once dirname(__FILE__) . '/ofc_bar_base.php';
class candle_value
{
diff --git a/libs/open-flash-chart/php-ofc-library/ofc_tooltip.php b/libs/open-flash-chart/php-ofc-library/ofc_tooltip.php
index 3104ee33b9..21f8aa2ecd 100644
--- a/libs/open-flash-chart/php-ofc-library/ofc_tooltip.php
+++ b/libs/open-flash-chart/php-ofc-library/ofc_tooltip.php
@@ -1,6 +1,6 @@
<?php
-include_once 'ofc_bar_base.php';
+include_once dirname(__FILE__) . '/ofc_bar_base.php';
class tooltip
{
diff --git a/libs/open-flash-chart/php-ofc-library/ofc_y_axis_label.php b/libs/open-flash-chart/php-ofc-library/ofc_y_axis_label.php
index bded9b84e5..f2616f537e 100644
--- a/libs/open-flash-chart/php-ofc-library/ofc_y_axis_label.php
+++ b/libs/open-flash-chart/php-ofc-library/ofc_y_axis_label.php
@@ -1,38 +1,38 @@
-<?php
-
-/**
- * y_axis_label see y_axis_labels
- */
-class y_axis_label
-{
- function y_axis_label( $y, $text)
- {
- $this->y = $y;
- $this->set_text( $text );
- }
-
- function set_text( $text )
- {
- $this->text = $text;
- }
-
- function set_colour( $colour )
- {
- $this->colour = $colour;
- }
-
- function set_size( $size )
- {
- $this->size = $size;
- }
-
- function set_rotate( $rotate )
- {
- $this->rotate = $rotate;
- }
-
- function set_vertical()
- {
- $this->rotate = "vertical";
- }
+<?php
+
+/**
+ * y_axis_label see y_axis_labels
+ */
+class y_axis_label
+{
+ function y_axis_label( $y, $text)
+ {
+ $this->y = $y;
+ $this->set_text( $text );
+ }
+
+ function set_text( $text )
+ {
+ $this->text = $text;
+ }
+
+ function set_colour( $colour )
+ {
+ $this->colour = $colour;
+ }
+
+ function set_size( $size )
+ {
+ $this->size = $size;
+ }
+
+ function set_rotate( $rotate )
+ {
+ $this->rotate = $rotate;
+ }
+
+ function set_vertical()
+ {
+ $this->rotate = "vertical";
+ }
} \ No newline at end of file
diff --git a/libs/open-flash-chart/php-ofc-library/ofc_y_axis_labels.php b/libs/open-flash-chart/php-ofc-library/ofc_y_axis_labels.php
index 75f777e532..c0708ab219 100644
--- a/libs/open-flash-chart/php-ofc-library/ofc_y_axis_labels.php
+++ b/libs/open-flash-chart/php-ofc-library/ofc_y_axis_labels.php
@@ -1,57 +1,57 @@
-<?php
-
-class y_axis_labels
-{
- function y_axis_labels(){}
-
- /**
- * @param $steps which labels are generated
- */
- function set_steps( $steps )
- {
- $this->steps = $steps;
- }
-
- /**
- *
- * @param $labels as an array of [y_axis_label or string]
- */
- function set_labels( $labels )
- {
- $this->labels = $labels;
- }
-
- function set_colour( $colour )
- {
- $this->colour = $colour;
- }
-
- /**
- * font size in pixels
- */
- function set_size( $size )
- {
- $this->size = $size;
- }
-
- /**
- * rotate labels
- */
- function set_vertical()
- {
- $this->rotate = 270;
- }
-
- function rotate( $angle )
- {
- $this->rotate = $angle;
- }
-
- /**
- * @param $text default text that all labels inherit
- */
- function set_text( $text )
- {
- $this->text = $text;
- }
+<?php
+
+class y_axis_labels
+{
+ function y_axis_labels(){}
+
+ /**
+ * @param $steps which labels are generated
+ */
+ function set_steps( $steps )
+ {
+ $this->steps = $steps;
+ }
+
+ /**
+ *
+ * @param $labels as an array of [y_axis_label or string]
+ */
+ function set_labels( $labels )
+ {
+ $this->labels = $labels;
+ }
+
+ function set_colour( $colour )
+ {
+ $this->colour = $colour;
+ }
+
+ /**
+ * font size in pixels
+ */
+ function set_size( $size )
+ {
+ $this->size = $size;
+ }
+
+ /**
+ * rotate labels
+ */
+ function set_vertical()
+ {
+ $this->rotate = 270;
+ }
+
+ function rotate( $angle )
+ {
+ $this->rotate = $angle;
+ }
+
+ /**
+ * @param $text default text that all labels inherit
+ */
+ function set_text( $text )
+ {
+ $this->text = $text;
+ }
} \ No newline at end of file
diff --git a/libs/open-flash-chart/php-ofc-library/open-flash-chart.php b/libs/open-flash-chart/php-ofc-library/open-flash-chart.php
index b017097d00..9ba0db6d59 100644
--- a/libs/open-flash-chart/php-ofc-library/open-flash-chart.php
+++ b/libs/open-flash-chart/php-ofc-library/open-flash-chart.php
@@ -10,55 +10,55 @@
//
if (! function_exists('json_encode'))
{
- include_once 'JSON.php';
+ include_once dirname(__FILE__) . '/JSON.php';
}
-include_once 'json_format.php';
+include_once dirname(__FILE__) . '/json_format.php';
// ofc classes
-include_once 'ofc_title.php';
-include_once 'ofc_y_axis_base.php';
-include_once 'ofc_y_axis.php';
-include_once 'ofc_y_axis_right.php';
-include_once 'ofc_y_axis_labels.php';
-include_once 'ofc_y_axis_label.php';
-include_once 'ofc_x_axis.php';
+include_once dirname(__FILE__) . '/ofc_title.php';
+include_once dirname(__FILE__) . '/ofc_y_axis_base.php';
+include_once dirname(__FILE__) . '/ofc_y_axis.php';
+include_once dirname(__FILE__) . '/ofc_y_axis_right.php';
+include_once dirname(__FILE__) . '/ofc_y_axis_labels.php';
+include_once dirname(__FILE__) . '/ofc_y_axis_label.php';
+include_once dirname(__FILE__) . '/ofc_x_axis.php';
-include_once 'ofc_pie.php';
-//include_once 'ofc_bar.php';
-include_once 'ofc_bar_glass.php';
-include_once 'ofc_bar_filled.php';
-include_once 'ofc_bar_stack.php';
-//include_once 'ofc_bar_3d.php';
-include_once 'ofc_hbar.php';
-include_once 'ofc_line_base.php';
-include_once 'ofc_line.php';
-//include_once 'ofc_line_dot.php';
-//include_once 'ofc_line_hollow.php';
-include_once 'ofc_candle.php';
-include_once 'ofc_area_base.php';
-include_once 'ofc_tags.php';
-include_once 'ofc_arrow.php';
-//include_once 'ofc_area_hollow.php';
-//include_once 'ofc_area_line.php';
+include_once dirname(__FILE__) . '/ofc_pie.php';
+//include_once dirname(__FILE__) . '/ofc_bar.php';
+include_once dirname(__FILE__) . '/ofc_bar_glass.php';
+include_once dirname(__FILE__) . '/ofc_bar_filled.php';
+include_once dirname(__FILE__) . '/ofc_bar_stack.php';
+//include_once dirname(__FILE__) . '/ofc_bar_3d.php';
+include_once dirname(__FILE__) . '/ofc_hbar.php';
+include_once dirname(__FILE__) . '/ofc_line_base.php';
+include_once dirname(__FILE__) . '/ofc_line.php';
+//include_once dirname(__FILE__) . '/ofc_line_dot.php';
+//include_once dirname(__FILE__) . '/ofc_line_hollow.php';
+include_once dirname(__FILE__) . '/ofc_candle.php';
+include_once dirname(__FILE__) . '/ofc_area_base.php';
+include_once dirname(__FILE__) . '/ofc_tags.php';
+include_once dirname(__FILE__) . '/ofc_arrow.php';
+//include_once dirname(__FILE__) . '/ofc_area_hollow.php';
+//include_once dirname(__FILE__) . '/ofc_area_line.php';
-include_once 'ofc_x_legend.php';
-include_once 'ofc_y_legend.php';
-include_once 'ofc_bar_sketch.php';
-include_once 'ofc_scatter.php';
-include_once 'ofc_scatter_line.php';
-include_once 'ofc_x_axis_labels.php';
-include_once 'ofc_x_axis_label.php';
-include_once 'ofc_tooltip.php';
-include_once 'ofc_shape.php';
-include_once 'ofc_radar_axis.php';
-include_once 'ofc_radar_axis_labels.php';
-include_once 'ofc_radar_spoke_labels.php';
-include_once 'ofc_line_style.php';
+include_once dirname(__FILE__) . '/ofc_x_legend.php';
+include_once dirname(__FILE__) . '/ofc_y_legend.php';
+include_once dirname(__FILE__) . '/ofc_bar_sketch.php';
+include_once dirname(__FILE__) . '/ofc_scatter.php';
+include_once dirname(__FILE__) . '/ofc_scatter_line.php';
+include_once dirname(__FILE__) . '/ofc_x_axis_labels.php';
+include_once dirname(__FILE__) . '/ofc_x_axis_label.php';
+include_once dirname(__FILE__) . '/ofc_tooltip.php';
+include_once dirname(__FILE__) . '/ofc_shape.php';
+include_once dirname(__FILE__) . '/ofc_radar_axis.php';
+include_once dirname(__FILE__) . '/ofc_radar_axis_labels.php';
+include_once dirname(__FILE__) . '/ofc_radar_spoke_labels.php';
+include_once dirname(__FILE__) . '/ofc_line_style.php';
-include_once 'dot_base.php';
-include_once 'ofc_menu.php';
+include_once dirname(__FILE__) . '/dot_base.php';
+include_once dirname(__FILE__) . '/ofc_menu.php';
class open_flash_chart
{
@@ -175,4 +175,4 @@ class open_flash_chart
//
// there is no PHP end tag so we don't mess the headers up!
-// \ No newline at end of file
+//
diff --git a/libs/sparkline/LICENSE b/libs/sparkline/LICENSE-BSD.txt
index f254056552..b990fd0ae0 100644
--- a/libs/sparkline/LICENSE
+++ b/libs/sparkline/LICENSE-BSD.txt
@@ -1,4 +1,4 @@
-Copyright (c) 2004 James Byers <jbyers@users.sf.net>
+Copyright (c) 2004 James Byers <jbyers@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/libs/sparkline/LICENSE-GPL.txt b/libs/sparkline/LICENSE-GPL.txt
new file mode 100644
index 0000000000..11dddd00ef
--- /dev/null
+++ b/libs/sparkline/LICENSE-GPL.txt
@@ -0,0 +1,278 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the 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 Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/libs/sparkline/lib/Sparkline.php b/libs/sparkline/lib/Sparkline.php
index 1641d7535d..d748538c54 100644
--- a/libs/sparkline/lib/Sparkline.php
+++ b/libs/sparkline/lib/Sparkline.php
@@ -60,8 +60,8 @@ class Sparkline extends Object {
//
$this->graphAreaPx = array(array($this->graphAreaPx[0][0],
$this->graphAreaPx[0][1]),
- array($this->graphAreaPx[1][0] + $x, //FIX FROM PIWIK
- $this->graphAreaPx[1][1] + $y)); //FIX FROM PIWIK
+ array($this->graphAreaPx[1][0] + $x - 1,
+ $this->graphAreaPx[1][1] + $y - 1));
$this->imageHandle = $this->CreateImageHandle($x, $y);
@@ -356,12 +356,9 @@ class Sparkline extends Object {
}
function DrawTextRelative($string, $x, $y, $color, $position, $padding = 2, $font = FONT_1, $handle = false) {
- if(empty($string))
- {
- return;
- }
$this->Debug("Sparkline :: DrawTextRelative('$string', $x, $y, '$color', $position, $font, $padding)", DEBUG_DRAW);
- if (!$this->IsError() &&
+
+ if (!empty($string) && !$this->IsError() &&
$colorHandle = $this->GetColorHandle($color)) {
if ($handle === false) $handle = $this->imageHandle;
diff --git a/libs/sparkline/lib/Sparkline_Bar.php b/libs/sparkline/lib/Sparkline_Bar.php
index f1442a044e..ca8cca0aa3 100644
--- a/libs/sparkline/lib/Sparkline_Bar.php
+++ b/libs/sparkline/lib/Sparkline_Bar.php
@@ -67,8 +67,12 @@ class Sparkline_Bar extends Sparkline {
// data setting
//
function SetData($x, $y, $color = null, $underscore = false, $series = 1) {
- $x = trim($x);
- $y = trim($y);
+ if(!is_numeric($x)) {
+ $x = trim($x);
+ }
+ if(!is_numeric($y)) {
+ $y = trim($y);
+ }
$this->Debug("Sparkline_Bar :: SetData($x, $y, $series)", DEBUG_SET);
diff --git a/libs/sparkline/lib/Sparkline_Line.php b/libs/sparkline/lib/Sparkline_Line.php
index 16690f4803..292b3b3ed8 100644
--- a/libs/sparkline/lib/Sparkline_Line.php
+++ b/libs/sparkline/lib/Sparkline_Line.php
@@ -39,8 +39,12 @@ class Sparkline_Line extends Sparkline {
// data setting
//
function SetData($x, $y, $series = 1) {
- $x = trim($x);
- $y = trim($y);
+ if(!is_numeric($x)) {
+ $x = trim($x);
+ }
+ if(!is_numeric($y)) {
+ $y = trim($y);
+ }
$this->Debug("Sparkline_Line :: SetData($x, $y, $series)", DEBUG_SET);
@@ -95,16 +99,18 @@ class Sparkline_Line extends Sparkline {
}
if (!isset($this->yMax)) {
- $this->yMax = $this->dataSeriesStats[$series]['yMax'] + ($this->yMin * -1);
+ $this->yMax = $this->dataSeriesStats[$series]['yMax'];
}
if (!isset($this->xMax)) {
$this->xMax = $this->dataSeriesStats[$series]['xMax'];
}
+ $this->yRange = $this->yMax + ($this->yMin * -1);
+
for ($i = 0; $i < sizeof($this->dataSeries[$series]); $i++) {
- $y = round(($this->dataSeries[$series][$i] + ($this->yMin * -1)) * ($yBound / $this->yMax));
- $x = round($i * $xBound / (sizeof($this->dataSeries[$series]) ));
+ $y = round(($this->dataSeries[$series][$i] + ($this->yMin * -1)) * (($yBound-1) / $this->yRange));
+ $x = round($i * $xBound / (sizeof($this->dataSeries[$series])));
$this->dataSeriesConverted[$series][] = array($x, $y);
$this->Debug("Sparkline :: ConvertDataSeries series $series value $i ($x, $y)", DEBUG_SET);
}
@@ -167,8 +173,8 @@ class Sparkline_Line extends Sparkline {
// draw features
//
while (list(, $v) = each($this->featurePoint)) {
- $pxY = round(($v['ptY'] + ($this->yMin * -1)) * ($this->GetGraphHeight() / $this->yMax));
- $pxX = round($v['ptX'] * $this->GetGraphWidth() / $this->dataSeriesStats[1]['xMax']);
+ $pxY = round(($v['ptY'] + ($this->yMin * -1)) * ($this->GetGraphHeight() / $this->yRange));
+ $pxX = round($v['ptX'] * $this->GetGraphWidth() / sizeof($this->dataSeries[1]));
$this->DrawCircleFilled($pxX + $this->graphAreaPx[0][0],
$pxY + $this->graphAreaPx[0][1],
@@ -257,8 +263,8 @@ class Sparkline_Line extends Sparkline {
// draw features
//
while (list(, $v) = each($this->featurePoint)) {
- $pxY = round(($v['ptY'] + ($this->yMin * -1)) * ($this->GetGraphHeight() / $this->yMax));
- $pxX = round($v['ptX'] * $this->GetGraphWidth() / $this->dataSeriesStats[1]['xMax']);
+ $pxY = round(($v['ptY'] + ($this->yMin * -1)) * ($this->GetGraphHeight() / $this->yRange));
+ $pxX = round($v['ptX'] * $this->GetGraphWidth() / sizeof($this->dataSeries[1]));
$this->DrawCircleFilled($pxX + $this->graphAreaPx[0][0],
$pxY + $this->graphAreaPx[0][1],
diff --git a/libs/upgradephp/common.php b/libs/upgradephp/common.php
new file mode 100644
index 0000000000..14552fb113
--- /dev/null
+++ b/libs/upgradephp/common.php
@@ -0,0 +1,137 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @package Piwik
+ */
+
+/**
+ * Sets the default client character set.
+ *
+ * @compat
+ * Procedural style
+ * @bugs
+ * PHP documentation says this function exists in PHP 5 >= 5.0.5,
+ * but it also depends on the versions of external libraries, e.g.,
+ * php_mysqli.dll and libmysql.dll.
+ *
+ * @param $link mysqli MySQLi connection resource
+ * @param $charset string Character set
+ * @return bool TRUE on success, FALSE on failure
+ */
+if (in_array('mysqli', @get_loaded_extensions()) && !function_exists('mysqli_set_charset')) {
+ function mysqli_set_charset($link, $charset)
+ {
+ return mysqli_query($link, "SET NAMES '$charset'");
+ }
+}
+
+/**
+ * parse_ini_file() replacement.
+ * Behaves like parse_ini_file($filename, $process_sections);
+ *
+ * @author Andrew Sohn <asohn (at) aircanopy (dot) net>
+ * @author anthon (dot) pang (at) gmail (dot) com
+ *
+ * @param string $filename
+ * @param bool $process_sections (defaults to false)
+ * @return array
+ */
+if(function_exists('parse_ini_file')) {
+ function _parse_ini_file($filename, $process_sections = false) {
+ return parse_ini_file($filename, $process_sections);
+ }
+} else {
+ function _parse_ini_file($filename, $process_sections = false)
+ {
+ if(function_exists('file_get_contents')) {
+ $ini = file_get_contents($filename);
+ } else if(function_exists('file') && version_compare(phpversion(), '6') >= 0) {
+ $ini = implode(file($filename), FILE_TEXT);
+ } else if(function_exists('fopen') && function_exists('fread')) {
+ $handle = fopen($filename, 'r');
+ $ini = fread($handle, filesize($filename));
+ fclose($handle);
+ } else {
+ return false;
+ }
+
+ if(is_string($ini)) { $ini = explode("\n", str_replace("\r", "\n", $ini)); }
+ if (count($ini) == 0) { return array(); }
+
+ $sections = array();
+ $values = array();
+ $result = array();
+ $globals = array();
+ $i = 0;
+ foreach ($ini as $line) {
+ $line = trim($line);
+ $line = str_replace("\t", " ", $line);
+
+ // Comments
+ if (!preg_match('/^[a-zA-Z0-9[]/', $line)) {continue;}
+
+ // Sections
+ if ($line{0} == '[') {
+ $tmp = explode(']', $line);
+ $sections[] = trim(substr($tmp[0], 1));
+ $i++;
+ continue;
+ }
+
+ // Key-value pair
+ list($key, $value) = explode('=', $line, 2);
+ $key = trim($key);
+ $value = trim($value);
+ if (strstr($value, ";")) {
+ $tmp = explode(';', $value);
+ if (count($tmp) == 2) {
+ if ((($value{0} != '"') && ($value{0} != "'")) ||
+ preg_match('/^".*"\s*;/', $value) || preg_match('/^".*;[^"]*$/', $value) ||
+ preg_match("/^'.*'\s*;/", $value) || preg_match("/^'.*;[^']*$/", $value) ){
+ $value = $tmp[0];
+ }
+ } else {
+ if ($value{0} == '"') {
+ $value = preg_replace('/^"(.*)".*/', '$1', $value);
+ } elseif ($value{0} == "'") {
+ $value = preg_replace("/^'(.*)'.*/", '$1', $value);
+ } else {
+ $value = $tmp[0];
+ }
+ }
+ }
+
+ $value = trim($value);
+ $value = trim($value, "'\"");
+
+ if ($i == 0) {
+ if (substr($key, -2) == '[]') {
+ $globals[substr($key, 0, -2)][] = $value;
+ } else {
+ $globals[$key] = $value;
+ }
+ } else {
+ if (substr($key, -2) == '[]') {
+ $values[$i-1][substr($key, 0, -2)][] = $value;
+ } else {
+ $values[$i-1][$key] = $value;
+ }
+ }
+ }
+
+ for($j = 0; $j < $i; $j++) {
+ if ($process_sections === true) {
+ $result[$sections[$j]] = $values[$j];
+ } else {
+ $result[] = $values[$j];
+ }
+ }
+
+ return $result + $globals;
+ }
+}
diff --git a/misc/TODO b/misc/TODO
deleted file mode 100644
index a8cfe5555c..0000000000
--- a/misc/TODO
+++ /dev/null
@@ -1,7 +0,0 @@
-To fix
-======
-- ADD forward of non true show_values to forward when specified from URL to ajax
-
-CHANGES DONE TO LIBRARIES
-=========================
-- fixed PEAR so that it works under PHP5 with STRICT MODE enabled
diff --git a/misc/WebAppGallery/Manifest.xml b/misc/WebAppGallery/Manifest.xml
index 2e0b2e8490..55ad514465 100644
--- a/misc/WebAppGallery/Manifest.xml
+++ b/misc/WebAppGallery/Manifest.xml
@@ -3,16 +3,6 @@
<setAcl
path="piwik"
setAclUser="anonymousAuthenticationUser"
- setAclAccess="ReadAndExecute,ListDirectory"
- />
- <setAcl
- path="piwik/config"
- setAclUser="anonymousAuthenticationUser"
- setAclAccess="Modify"
- />
- <setAcl
- path="piwik/tmp"
- setAclUser="anonymousAuthenticationUser"
setAclAccess="Modify"
/>
</MSDeploy.iisApp>
diff --git a/misc/WebAppGallery/parameters.xml b/misc/WebAppGallery/parameters.xml
index 41f5246b90..d5edd33bf0 100644
--- a/misc/WebAppGallery/parameters.xml
+++ b/misc/WebAppGallery/parameters.xml
@@ -23,28 +23,4 @@
match="piwik"
/>
</parameter>
- <parameter
- name="SetAclParameterConfig"
- description="Sets the ACL on the configuration folder"
- defaultValue="{Application Path}/config"
- tags="Hidden"
- >
- <parameterEntry
- type="ProviderPath"
- scope="setAcl"
- match="piwik/config"
- />
- </parameter>
- <parameter
- name="SetAclParameterTmp"
- description="Sets the ACL on the tmp folder"
- defaultValue="{Application Path}/tmp"
- tags="Hidden"
- >
- <parameterEntry
- type="ProviderPath"
- scope="setAcl"
- match="piwik/tmp"
- />
- </parameter>
</parameters>
diff --git a/misc/cron/archive.sh b/misc/cron/archive.sh
index 704068864d..9b60016fc7 100644
--- a/misc/cron/archive.sh
+++ b/misc/cron/archive.sh
@@ -1,7 +1,9 @@
#!/bin/bash -e
# Description
-# This script automatically fetches the Super User token_auth
+# This cron script will automatically run Piwik archiving every hour.
+
+# It automatically fetches the Super User token_auth
# and triggers the archiving for all websites for all periods.
# This ensures that all reports are pre-computed and Piwik renders very fast.
@@ -10,25 +12,39 @@
# How to setup the crontab job?
# Add the following lines in your crontab file, eg. /etc/cron.d/piwik-archive
+#---------------START CRON TAB--
#MAILTO="youremail@example.com"
-#5 0 * * * www-data /path/to/piwik/misc/cron/archive.sh > /dev/null
-
-# Other optimization for high traffic websites
-# You may want to override the following settings in config/config.ini.php (see documentation in config/config.ini.php)
+#5 * * * * www-data /path/to/piwik/misc/cron/archive.sh > /dev/null
+#-----------------END CRON TAB--
+# When an error occurs (eg. php memory error, timeout) the error messages
+# will be sent to youremail@example.com.
+#
+# Optimization for high traffic websites
+# You may want to override the following settings in config/config.ini.php:
+# See documentation of the fields in your piwik/config/config.ini.php
+#
# [General]
# time_before_archive_considered_outdated = 3600
# enable_browser_archiving_triggering = false
+#
+#===========================================================================
-PHP_BIN=`which php5 2>/dev/null`
+for TEST_PHP_BIN in php5 php php-cli php-cgi; do
+ if which $TEST_PHP_BIN >/dev/null 2>/dev/null; then
+ PHP_BIN=`which $TEST_PHP_BIN`
+ break
+ fi
+done
if test -z $PHP_BIN; then
- PHP_BIN=`which php`
+ echo "php binary not found. Make sure php5 or php exists in PATH."
+ exit 1
fi
act_path() {
- local pathname="$1"
- readlink -f "$pathname" 2>/dev/null || \
- realpath "$pathname" 2>/dev/null || \
- type -P "$pathname" 2>/dev/null
+ local pathname="$1"
+ readlink -f "$pathname" 2>/dev/null || \
+ realpath "$pathname" 2>/dev/null || \
+ type -P "$pathname" 2>/dev/null
}
ARCHIVE=`act_path ${0}`
@@ -39,11 +55,28 @@ PIWIK_CONFIG="$PIWIK_CRON_FOLDER"/../../config/config.ini.php
PIWIK_SUPERUSER=`sed '/^\[superuser\]/,$!d;/^login[ \t]*=[ \t]*"*/!d;s///;s/"*[ \t]*$//;q' $PIWIK_CONFIG`
PIWIK_SUPERUSER_MD5_PASSWORD=`sed '/^\[superuser\]/,$!d;/^password[ \t]*=[ \t]*"*/!d;s///;s/"*[ \t]*$//;q' $PIWIK_CONFIG`
-CMD_TOKEN_AUTH="$PHP_BIN $PIWIK_PATH -- module=API&method=UsersManager.getTokenAuth&userLogin=$PIWIK_SUPERUSER&md5Password=$PIWIK_SUPERUSER_MD5_PASSWORD&format=php&serialize=0"
+CMD_TOKEN_AUTH="$PHP_BIN -q $PIWIK_PATH -- module=API&method=UsersManager.getTokenAuth&userLogin=$PIWIK_SUPERUSER&md5Password=$PIWIK_SUPERUSER_MD5_PASSWORD&format=php&serialize=0"
TOKEN_AUTH=`$CMD_TOKEN_AUTH`
-for period in day week year; do
- CMD="$PHP_BIN $PIWIK_PATH -- module=API&method=VisitsSummary.getVisits&idSite=all&period=$period&date=last52&format=xml&token_auth=$TOKEN_AUTH";
- $CMD
- echo ""
+CMD_GET_ID_SITES="$PHP_BIN -q $PIWIK_PATH -- module=API&method=SitesManager.getAllSitesId&token_auth=$TOKEN_AUTH&format=csv&convertToUnicode=0"
+ID_SITES=`$CMD_GET_ID_SITES`
+echo "Starting Piwik archiving..."
+echo ""
+for idsite in $ID_SITES; do
+ TEST_IS_NUMERIC=`echo $idsite | egrep '^[0-9]+$'`
+ if [ "$TEST_IS_NUMERIC" ]
+ then
+ for period in day week year; do
+ echo ""
+ echo "Archiving period = $period for idsite = $idsite..."
+ CMD="$PHP_BIN -q $PIWIK_PATH -- module=API&method=VisitsSummary.getVisits&idSite=$idsite&period=$period&date=last52&format=xml&token_auth=$TOKEN_AUTH";
+ $CMD
+ done
+
+ echo ""
+ echo "Archiving for idsite = $idsite done!"
+ fi
done
+
+echo "Piwik archiving finished."
+
diff --git a/misc/cron/archive.windows.ps1 b/misc/cron/archive.windows.ps1
new file mode 100644
index 0000000000..a853960e12
--- /dev/null
+++ b/misc/cron/archive.windows.ps1
@@ -0,0 +1,88 @@
+#===========================================================================
+# Description
+# This powershell script will automatically run Piwik archiving for whatever
+# frequency you set it up to run, it is recommended that is be every 1 hour
+# or 3600 seconds.
+
+# It automatically fetches the Super User token_auth
+# and triggers the archiving for all websites for all periods.
+# This ensures that all reports are pre-computed and Piwik renders very fast.
+
+# Documentation
+# Please check the documentation on http://piwik.org/docs/setup-auto-archiving/
+
+# Optimization for high traffic websites
+# You may want to override the following settings in config/config.ini.php:
+# See documentation of the fields in your piwik/config/config.ini.php
+#
+# [General]
+# time_before_archive_considered_outdated = 3600
+# enable_browser_archiving_triggering = false
+#
+#===========================================================================
+$PHP_INI = "C:\Program Files\EasyPHP-5.3.2i\apache\php.ini"
+$BINS = @("php5.exe", "php.exe")
+
+foreach($phpTestBin in $BINS)
+{
+ if(Get-Command $phpTestBin -ea SilentlyContinue)
+ {
+ $PHP_BIN = Get-Command $phpTestBin|Select-Object -ExpandProperty Definition
+ break
+ }
+}
+
+if(($PHP_BIN -eq $null) -or !(Test-Path $PHP_BIN -ea SilentlyContinue))
+{
+ Write-Host "php binary not found. Make sure php5 or php exists in PATH."
+ Exit 1
+}
+
+$PIWIK_SCRIPT_FOLDER = Split-Path -parent $MyInvocation.MyCommand.Definition
+$PIWIK_PATH="$PIWIK_SCRIPT_FOLDER\..\..\index.php"
+$PIWIK_CONFIG="$PIWIK_SCRIPT_FOLDER\..\..\config/config.ini.php"
+
+Function Parse-IniFile ($file) {
+ $ini = @{}
+ switch -regex -file $file {
+ "^\[(.+)\]$" {
+ $section = $matches[1].Trim()
+ $ini[$section] = @{}
+ }
+ "(.+)=(.+)" {
+ $name,$value = $matches[1..2]
+ $name = $name.Trim()
+ $value = $value.Trim()
+ $ini[$section][$name] = $value
+ }
+ }
+ $ini
+}
+
+$CONFIG = Parse-IniFile $PIWIK_CONFIG
+$PIWIK_SUPERUSER=$CONFIG["superuser"]["login"].Replace('"', '')
+$PIWIK_SUPERUSER_MD5_PASSWORD=$CONFIG["superuser"]["password"].Replace('"', '')
+
+$TOKEN_AUTH= & $PHP_BIN -c $PHP_INI "$PIWIK_PATH" "--" "module=API&method=UsersManager.getTokenAuth&userLogin=$PIWIK_SUPERUSER&md5Password=$PIWIK_SUPERUSER_MD5_PASSWORD&format=php&serialize=0"
+
+$ID_SITES= & $PHP_BIN -c $PHP_INI "$PIWIK_PATH" "--" "module=API&method=SitesManager.getAllSitesId&token_auth=$TOKEN_AUTH&format=csv&convertToUnicode=0"
+
+Write-Host "Starting Piwik archiving..."
+
+foreach($ID_SITE in $ID_SITES)
+{
+ if($ID_SITE -match "^\d+$")
+ {
+ foreach($period in @("day","week","year"))
+ {
+ Write-Host ""
+ Write-Host "Archiving period = $period for idsite = $ID_SITE..."
+ & $PHP_BIN -c $PHP_INI "$PIWIK_PATH" "--" "module=API&method=VisitsSummary.getVisits&idSite=$ID_SITE&period=$period&date=last52&format=xml&token_auth=$TOKEN_AUTH"
+ }
+
+ Write-Host ""
+ Write-Host "Archiving for idsite = $ID_SITE done!"
+ }
+}
+
+Write-Host "Piwik archiving finished." \ No newline at end of file
diff --git a/misc/generateVisits.php b/misc/generateVisits.php
deleted file mode 100644
index 35dec2be44..0000000000
--- a/misc/generateVisits.php
+++ /dev/null
@@ -1,118 +0,0 @@
-<?php
-/*
- * The script can be used to generate huge number of visits and actions
- * for a given number of days.
- */
-
-if(file_exists('../bootstrap.php'))
-{
- require_once '../bootstrap.php';
-}
-
-if(empty($_GET['choice']) || $_GET['choice'] != 'yes') {
- echo "<div style='color:red;font-size:large'>WARNING!</div> <br>You are about to generate fake visits which will be recorded in your Piwik database.
- <br>It will <b>not</b> be possible to easily delete these visits from the piwik logs.
- <br><br>Are you sure you want to generate fake visits?
- <br><br>
- <a href='../index.php'><b>NO</b>, I do not want to generate fake visits</a>
- <br><br>
- <a href='?choice=yes'><b>YES</b>, I want to generate fake visits</a>
- <br><br>
- Note: you can edit the source code of this file to specify how many visits to generate, how many days, etc.
- ";
- return;
-}
-
-
-// TODO - generator should generate pages with slash, then test that period archiving doesn't show the unique page view
-// TODO - should generate goals with keyword or referer that are not found for this day, to simulate a referer 5 days ago and conversion today
-$minVisitors = 20;
-$maxVisitors = 100;
-$nbActions = 10;
-$daysToCompute = 1;
-$idSite = 1;
-
-
-//-----------------------------------------------------------------------------
-error_reporting(E_ALL|E_NOTICE);
-if(!defined('PIWIK_INCLUDE_PATH'))
-{
- define('PIWIK_INCLUDE_PATH', '..');
-}
-ignore_user_abort(true);
-
-if(!defined('PIWIK_INCLUDE_SEARCH_PATH'))
-{
- define('PIWIK_INCLUDE_SEARCH_PATH', PIWIK_INCLUDE_PATH . '/core'
- . PATH_SEPARATOR . PIWIK_INCLUDE_PATH . '/libs'
- . PATH_SEPARATOR . PIWIK_INCLUDE_PATH . '/plugins');
- @ini_set('include_path', PIWIK_INCLUDE_SEARCH_PATH);
- @set_include_path(PIWIK_INCLUDE_SEARCH_PATH);
-}
-
-$GLOBALS['PIWIK_TRACKER_DEBUG'] = false;
-ob_start();
-
-// first check that user has privileges to create some random data in the DB -> he must be super user
-define('PIWIK_ENABLE_DISPATCH', false);
-require_once PIWIK_INCLUDE_PATH . "/index.php";
-require_once "FrontController.php";
-
-Piwik::setMaxExecutionTime(0);
-$idSite = Piwik_Common::getRequestVar('idSite', $idSite, 'int');
-
-try {
- Piwik_FrontController::getInstance()->init();
-} catch( Exception $e) {
- echo $e->getMessage();
- exit;
-}
-Piwik::checkUserIsSuperUser();
-
-require_once "PluginsManager.php";
-require_once "Tracker.php";
-
-//Piwik_PluginsManager::getInstance()->unloadPlugins();
-
-// we have to unload the Provider plugin otherwise it tries to lookup the IP for ahostname, and there is no dns server here
-if(Piwik_PluginsManager::getInstance()->isPluginActivated('Provider'))
-{
- Piwik_PluginsManager::getInstance()->unloadPlugin('Provider');
-}
-
-// we set the DO NOT load plugins so that the Tracker generator doesn't load the plugins we've just disabled.
-// if for some reasons you want to load the plugins, comment this line, and disable the plugin Provider in the plugins interface
-Piwik_PluginsManager::getInstance()->doNotLoadPlugins();
-
-$generator = new Piwik_Tracker_Generator;
-$generator->setMaximumUrlDepth(3);
-//$generator->disableProfiler();
-$generator->setIdSite( $idSite );
-
-$nbActionsTotal = 0;
-//$generator->emptyAllLogTables();
-$generator->init();
-
-$t = new Piwik_Timer;
-
-$startTime = time() - ($daysToCompute-1)*86400;
-while($startTime <= time())
-{
- $visitors = rand($minVisitors, $maxVisitors);
- $actions = $nbActions;
- $generator->setTimestampToUse($startTime);
-
- $nbActionsTotalThisDay = $generator->generate($visitors, $actions);
- $actionsPerVisit = round($nbActionsTotalThisDay / $visitors);
- print("Generated $visitors unique visitors and $actionsPerVisit actions per visit for the ".date("Y-m-d", $startTime)."<br>\n");
- $startTime+=86400;
- $nbActionsTotal+=$nbActionsTotalThisDay;
- sleep(1);
-}
-
-echo "<br>Total actions: $nbActionsTotal";
-echo "<br>Total requests per sec: ". round($nbActionsTotal / $t->getTime(),0);
-echo "<br>".$t;
-
-$generator->end();
-ob_end_flush();
diff --git a/misc/redirectToUrl.php b/misc/redirectToUrl.php
index c5597aa4c4..4df113fcec 100644
--- a/misc/redirectToUrl.php
+++ b/misc/redirectToUrl.php
@@ -2,7 +2,10 @@
// we redirect to the website instead of linking directly because we don't want
// to expose the referer on the piwik demo
$url = htmlentities($_GET['url']);
-if(!preg_match('~http://(forum\.)?piwik.org(/|$)~', $url)) { die; }
+if(!preg_match('~http://(dev\.|forum\.)?piwik.org(/|$)~', $url)
+&& !in_array($url, array(
+ 'http://blogvertising.pl/',
+))) { die; }
?>
<html><head>
<meta http-equiv="refresh" content="0;url=<?php echo $url; ?>"/>
diff --git a/piwik.js b/piwik.js
index 77fbaee4d1..64f07eef35 100644
--- a/piwik.js
+++ b/piwik.js
@@ -5,11 +5,11 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
*/
-var Piwik,piwik_log,piwik_track;if(!this.Piwik){Piwik=(function(){var c,i={},e=document,d=navigator,g=screen,m=window,j=m.location.hostname,f=false,o=[];function n(q){return typeof q!=="undefined"}function h(q,s,r,t){if(q.addEventListener){q.addEventListener(s,r,t);return true}else{if(q.attachEvent){return q.attachEvent("on"+s,r)}}q["on"+s]=r}function l(s,u){var t="",r,q;for(r in i){q=i[r][s];if(typeof q==="function"){t+=q(u)}}return t}function b(q){if(n(c)){var r=new Date();while(r.getTime()<c){r=new Date()}}l("unload")}function p(r){if(!f){f=true;l("load");for(var q=0;q<o.length;q++){o[q]()}}return true}function a(){if(e.addEventListener){h(e,"DOMContentLoaded",function(){e.removeEventListener("DOMContentLoaded",arguments.callee,false);p()})}else{if(e.attachEvent){e.attachEvent("onreadystatechange",function(){if(e.readyState==="complete"){e.detachEvent("onreadystatechange",arguments.callee);
-p()}});if(e.documentElement.doScroll&&m==m.top){(function(){if(f){return}try{e.documentElement.doScroll("left")}catch(q){setTimeout(arguments.callee,0);return}p()}())}}}h(m,"load",p,false)}function k(Q,C){var E=Q||"",ab=C||"",T=e.location.href,Z=e.title,L="7z|aac|arc|arj|asf|asx|avi|bin|csv|doc|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt|qtm?|ra(m|r)?|sea|sit|tar|t?bz2?|tgz|torrent|txt|wav|wma|wmv|wpd||xls|xml|z|zip",A=[j],U=[],x=[],u=[],D=500,O,R="0",w,P={pdf:["pdf","application/pdf","0"],quicktime:["qt","video/quicktime","0"],realplayer:["realp","audio/x-pn-realaudio-plugin","0"],wma:["wma","application/x-mplayer2","0"],director:["dir","application/x-director","0"],flash:["fla","application/x-shockwave-flash","0"],java:["java","application/x-java-vm","0"],gears:["gears","application/x-googlegears","0"],silverlight:["ag","application/x-silverlight","0"]},H=false,s=m.encodeURIComponent||escape,X=m.decodeURIComponent||unescape,aa=function(ae){var ah=new RegExp('[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]',"g"),af={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};
-function ac(ai){ah.lastIndex=0;return ah.test(ai)?'"'+ai.replace(ah,function(aj){var ak=af[aj];return typeof ak==="string"?ak:"\\u"+("0000"+aj.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+ai+'"'}function ad(ai){return ai<10?"0"+ai:ai}function ag(am,ak){var al,aj,ai,an,ao=ak[am];if(ao===null){return"null"}if(ao&&typeof ao==="object"&&typeof ao.toJSON==="function"){ao=ao.toJSON(am)}switch(typeof ao){case"string":return ac(ao);case"number":return isFinite(ao)?String(ao):"null";case"boolean":case"null":return String(ao);case"object":an=[];if(ao instanceof Array){for(al=0;al<ao.length;al++){an[al]=ag(al,ao)||"null"}ai=an.length===0?"[]":"["+an.join(",")+"]";return ai}if(ao instanceof Date){return ac(ao.getUTCFullYear()+"-"+ad(ao.getUTCMonth()+1)+"-"+ad(ao.getUTCDate())+"T"+ad(ao.getUTCHours())+":"+ad(ao.getUTCMinutes())+":"+ad(ao.getUTCSeconds())+"Z")}for(aj in ao){ai=ag(aj,ao);if(ai){an[an.length]=ac(aj)+":"+ai}}ai=an.length===0?"{}":"{"+an.join(",")+"}";return ai}}return ag("",{"":ae})},v={};
-function z(ah,af,ad,ag,ac,ai){var ae;if(ad){ae=new Date();ae.setTime(ae.getTime()+ad*86400000)}e.cookie=ah+"="+s(af)+(ad?";expires="+ae.toGMTString():"")+";path="+(ag?ag:"/")+(ac?";domain="+ac:"")+(ai?";secure":"")}function t(ae){var ac=new RegExp("(^|;)[ ]*"+ae+"=([^;]*)"),ad=ac.exec(e.cookie);return ad?X(ad[2]):0}function q(ae,ad){var ac=new Date(),af=new Image(1,1);c=ac.getTime()+ad;af.onLoad=function(){};af.src=ae}function y(){var ac,ad;if(typeof d.javaEnabled!=="undefined"&&d.javaEnabled()){P.java[2]="1"}if(typeof m.GearsFactory==="function"){P.gears[2]="1"}if(d.mimeTypes&&d.mimeTypes.length){for(ac in P){ad=d.mimeTypes[P[ac][1]];if(ad&&ad.enabledPlugin){P[ac][2]="1"}}}}function K(){var ac="";try{ac=top.document.referrer}catch(ae){if(parent){try{ac=parent.document.referrer}catch(ad){ac=""}}}if(ac===""){ac=e.referrer}return ac}function F(){var ac="_pk_testcookie";if(!n(d.cookieEnabled)){z(ac,"1");return t(ac)=="1"?"1":"0"}return d.cookieEnabled?"1":"0"}function J(){var ad,ac,ae;ac=new Date();
-ae="idsite="+ab+"&url="+s(T)+"&res="+g.width+"x"+g.height+"&h="+ac.getHours()+"&m="+ac.getMinutes()+"&s="+ac.getSeconds()+"&cookie="+R+"&urlref="+s(w)+"&rand="+Math.random();for(ad in P){ae+="&"+P[ad][0]+"="+P[ad][2]}ae=E+"?"+ae;return ae}function Y(){var ac=J();ac+="&action_name="+s(Z);if(n(O)){ac+="&data="+s(aa(O))}ac+=l("log");q(ac,D)}function W(ac,af,ae){var ad=J();ad+="&idgoal="+ac;if(n(af)&&af!==null){ad+="&revenue="+af}if(n(ae)){if(ae!==null){ad+="&data="+s(aa(ae))}}else{if(n(O)){ad+="&data="+s(aa(O))}}ad+=l("goal");q(ad,D)}function B(ad,ac,af){var ae;ae="idsite="+ab+"&"+ac+"="+s(ad)+"&rand="+Math.random()+"&redirect=0";if(n(af)){if(af!==null){ae+="&data="+s(aa(af))}}else{if(n(O)){ae+="&data="+s(aa(O))}}ae+=l("click");ae=E+"?"+ae;q(ae,D)}function M(ae){var ad,ac,af;for(ad=0;ad<A.length;ad++){ac=A[ad];if(ae==ac){return true}if(ac.substr(0,2)=="*."){if((ae)==ac.substr(2)){return true}af=ae.length-ac.length+1;if((af>0)&&(ae.substr(af)==ac.substr(1))){return true}}}return false}function N(ac,ae){var ad,af="(^| )(piwik_"+ae;
-if(n(ac)){for(ad=0;ad<ac.length;ad++){af+="|"+ac[ad]}}af+=")( |$)";return new RegExp(af)}function r(ae,ad,ac){if(!ac){return"link"}var af=N(x,"download"),ag=N(u,"link"),ah=new RegExp("\\.("+L+")([?&#]|$)","i");return ag.test(ae)?"link":(af.test(ae)||ah.test(ad)?"download":0)}function G(ai){var ag,aj,ak,ac;if(!n(ai)){ai=m.event}if(n(ai.target)){ag=ai.target}else{if(n(ai.srcElement)){ag=ai.srcElement}else{return}}while((aj=ag.parentNode)&&((ak=ag.tagName)!="A"&&ak!="AREA")){ag=aj}if(n(ag.href)){var ae=ag.hostname,af=ae.toLowerCase(),ah=ag.href.replace(ae,af),ad=new RegExp("^(javascript|vbscript|jscript|mocha|livescript|ecmascript): *","i");if(!ad.test(ah)){ac=r(ag.className,ah,M(af));if(ac){B(ah,ac)}}}}function V(ac){h(ac,"click",G,false)}function I(){if(!H){H=true;var ad,ac=N(U,"ignore"),ae=e.links;if(ae){for(ad=0;ad<ae.length;ad++){if(!ac.test(ae[ad].className)){V(ae[ad])}}}}}function S(ac,ae){var ad=null;if(typeof ac=="string"&&!n(v[ac])){if(typeof ae=="object"){ad=ae}else{if(typeof ae=="string"){try{eval("hookObj ="+ae)
-}catch(af){}}}v[ac]=ad}return ad}w=K();R=F();y();l("run",S);return{hook:v,getHook:function(ac){return v[ac]},setTrackerUrl:function(ac){if(n(ac)){E=ac}},setSiteId:function(ac){if(n(ac)){ab=ac}},setCustomData:function(ac){if(n(ac)){O=ac}},setLinkTrackingTimer:function(ac){if(n(ac)){D=ac}},setDownloadExtensions:function(ac){if(n(ac)){L=ac}},addDownloadExtensions:function(ac){if(n(ac)){L+="|"+ac}},setDomains:function(ac){if(typeof ac=="object"&&ac instanceof Array){A=ac;A[A.length]=j}else{if(typeof ac=="string"){A=[ac,j]}}},setIgnoreClasses:function(ac){if(typeof ac=="object"&&ac instanceof Array){U=ac}else{if(typeof ac=="string"){U=[ac]}}},setCustomUrl:function(ac){if(n(ac)){T=ac}},setDocumentTitle:function(ac){if(n(ac)){Z=ac}},setDownloadClasses:function(ac){if(typeof ac=="object"&&ac instanceof Array){x=ac}else{if(typeof ac=="string"){x=[ac]}}},setDownloadClass:function(ac){if(typeof ac=="string"){x=[ac]}},setLinkClasses:function(ac){if(typeof ac=="object"&&ac instanceof Array){u=ac}else{if(typeof ac=="string"){u=[ac]
-}}},setLinkClass:function(ac){if(typeof ac=="string"){u=[ac]}},addListener:function(ac){if(n(ac)){V(ac)}},enableLinkTracking:function(){if(f){I()}else{o[o.length]=function(){I()}}},trackGoal:function(ac,ae,ad){W(ac,ae,ad)},trackLink:function(ad,ac,ae){B(ad,ac,ae)},trackPageView:function(){Y()}}}h(m,"beforeunload",b,false);a();return{addPlugin:function(q,r){i[q]=r},getTracker:function(q,r){return new k(q,r)}}}());piwik_log=function(c,f,a,e){function b(g){try{return eval("piwik_"+g)}catch(h){}return}var d=Piwik.getTracker(a,f);d.setDocumentTitle(c);d.setCustomData(e);d.setLinkTrackingTimer(b("tracker_pause"));d.setDownloadExtensions(b("download_extensions"));d.setDomains(b("hosts_alias"));d.setIgnoreClasses(b("ignore_classes"));d.trackPageView();if(b("install_tracker")!==false){piwik_track=function(i,j,h,g){d.setSiteId(j);d.setTrackerUrl(h);d.trackLink(i,g)};d.enableLinkTracking()}}}; \ No newline at end of file
+var Piwik,piwik_log,piwik_track;if(!this.Piwik){Piwik=(function(){var b,f={},d=document,c=navigator,g=screen,l=window,i=l.location.hostname,h=false,o=[];function n(q){return typeof q!=="undefined"}function e(t,s,r,q){if(t.addEventListener){t.addEventListener(s,r,q);return true}else{if(t.attachEvent){return t.attachEvent("on"+s,r)}}t["on"+s]=r}function k(r,u){var q="",t,s;for(t in f){s=f[t][r];if(typeof s==="function"){q+=s(u)}}return q}function m(q){if(n(b)){var r;do{r=new Date()}while(r.getTime()<b)}k("unload")}function p(r){if(!h){h=true;k("load");for(var q=0;q<o.length;q++){o[q]()}}return true}function a(){if(d.addEventListener){e(d,"DOMContentLoaded",function(){d.removeEventListener("DOMContentLoaded",arguments.callee,false);p()})}else{if(d.attachEvent){d.attachEvent("onreadystatechange",function(){if(d.readyState==="complete"){d.detachEvent("onreadystatechange",arguments.callee);
+p()}});if(d.documentElement.doScroll&&l==l.top){(function(){if(h){return}try{d.documentElement.doScroll("left")}catch(q){setTimeout(arguments.callee,0);return}p()}())}}}e(l,"load",p,false)}function j(Q,P){var D=Q||"",aa=P||"",V,Z=d.title,G="7z|aac|arc|arj|asf|asx|avi|bin|csv|deb|dmg|doc|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt|qtm?|ra(m|r)?|rpm|sea|sit|tar|t?bz2?|tgz|torrent|txt|wav|wma|wmv|wpd||xls|xml|z|zip",R=[i],u=[],S=[],T=[],C=500,O,y="0",w,B={pdf:["pdf","application/pdf","0"],quicktime:["qt","video/quicktime","0"],realplayer:["realp","audio/x-pn-realaudio-plugin","0"],wma:["wma","application/x-mplayer2","0"],director:["dir","application/x-director","0"],flash:["fla","application/x-shockwave-flash","0"],java:["java","application/x-java-vm","0"],gears:["gears","application/x-googlegears","0"],silverlight:["ag","application/x-silverlight","0"]},K=false,s=l.encodeURIComponent||escape,X=l.decodeURIComponent||unescape,ab=function(ae){var ah=new RegExp('[\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]',"g"),af={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};
+function ac(ai){ah.lastIndex=0;return ah.test(ai)?'"'+ai.replace(ah,function(aj){var ak=af[aj];return typeof ak==="string"?ak:"\\u"+("0000"+aj.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+ai+'"'}function ad(ai){return ai<10?"0"+ai:ai}function ag(an,am){var al,ak,aj,ai,ao=am[an];if(ao===null){return"null"}if(ao&&typeof ao==="object"&&typeof ao.toJSON==="function"){ao=ao.toJSON(an)}switch(typeof ao){case"string":return ac(ao);case"number":return isFinite(ao)?String(ao):"null";case"boolean":case"null":return String(ao);case"object":ai=[];if(ao instanceof Array){for(al=0;al<ao.length;al++){ai[al]=ag(al,ao)||"null"}aj=ai.length===0?"[]":"["+ai.join(",")+"]";return aj}if(ao instanceof Date){return ac(ao.getUTCFullYear()+"-"+ad(ao.getUTCMonth()+1)+"-"+ad(ao.getUTCDate())+"T"+ad(ao.getUTCHours())+":"+ad(ao.getUTCMinutes())+":"+ad(ao.getUTCSeconds())+"Z")}for(ak in ao){aj=ag(ak,ao);if(aj){ai[ai.length]=ac(ak)+":"+aj}}aj=ai.length===0?"{}":"{"+ai.join(",")+"}";return aj}}return ag("",{"":ae})},v={};
+function z(ai,af,ad,ah,ae,ag){var ac;if(ad){ac=new Date();ac.setTime(ac.getTime()+ad*86400000)}d.cookie=ai+"="+s(af)+(ad?";expires="+ac.toGMTString():"")+";path="+(ah?ah:"/")+(ae?";domain="+ae:"")+(ag?";secure":"")}function t(ae){var ac=new RegExp("(^|;)[ ]*"+ae+"=([^;]*)"),ad=ac.exec(d.cookie);return ad?X(ad[2]):0}function q(ae,ad){var ac=new Date(),af=new Image(1,1);b=ac.getTime()+ad;af.onLoad=function(){};af.src=ae}function A(){var ac,ad;if(typeof c.javaEnabled!=="undefined"&&c.javaEnabled()){B.java[2]="1"}if(typeof l.GearsFactory==="function"){B.gears[2]="1"}if(c.mimeTypes&&c.mimeTypes.length){for(ac in B){ad=c.mimeTypes[B[ac][1]];if(ad&&ad.enabledPlugin){B[ac][2]="1"}}}}function I(){var ac="";try{ac=top.document.referrer}catch(ae){if(parent){try{ac=parent.document.referrer}catch(ad){ac=""}}}if(ac===""){ac=d.referrer}return ac}function N(){var ac="_pk_testcookie";if(!n(c.cookieEnabled)){z(ac,"1");return t(ac)=="1"?"1":"0"}return c.cookieEnabled?"1":"0"}function H(){var ad,ac,ae;ac=new Date();
+ae="idsite="+aa+"&rec=1&url="+s(n(V)?V:d.location.href)+"&res="+g.width+"x"+g.height+"&h="+ac.getHours()+"&m="+ac.getMinutes()+"&s="+ac.getSeconds()+"&cookie="+y+"&urlref="+s(w)+"&rand="+Math.random();for(ad in B){ae+="&"+B[ad][0]+"="+B[ad][2]}ae=D+"?"+ae;return ae}function r(ad){var ac=H();ac+="&action_name="+s(n(ad)?ad:Z);if(n(O)){ac+="&data="+s(ab(O))}ac+=k("log");q(ac,C)}function W(ac,af,ae){var ad=H();ad+="&idgoal="+ac;if(n(af)&&af!==null){ad+="&revenue="+af}if(n(ae)){if(ae!==null){ad+="&data="+s(ab(ae))}}else{if(n(O)){ad+="&data="+s(ab(O))}}ad+=k("goal");q(ad,C)}function F(ad,ac,af){var ae;ae="idsite="+aa+"&rec=1&"+ac+"="+s(ad)+"&rand="+Math.random()+"&redirect=0";if(n(af)){if(af!==null){ae+="&data="+s(ab(af))}}else{if(n(O)){ae+="&data="+s(ab(O))}}ae+=k("click");ae=D+"?"+ae;q(ae,C)}function L(af){var ad,ac,ae;for(ad=0;ad<R.length;ad++){ac=R[ad];if(af==ac){return true}if(ac.substr(0,2)=="*."){if((af)==ac.substr(2)){return true}ae=af.length-ac.length+1;if((ae>0)&&(af.substr(ae)==ac.substr(1))){return true
+}}}return false}function M(ae,ad){var af,ac="(^| )(piwik[_-]"+ad;if(n(ae)){for(af=0;af<ae.length;af++){ac+="|"+ae[af]}}ac+=")( |$)";return new RegExp(ac)}function Y(af,ac,ag){if(!ag){return"link"}var ae=M(S,"download"),ad=M(T,"link"),ah=new RegExp("\\.("+G+")([?&#]|$)","i");return ad.test(af)?"link":(ae.test(af)||ah.test(ac)?"download":0)}function E(aj){var ad,ai,ak,ac;if(!n(aj)){aj=l.event}if(n(aj.target)){ad=aj.target}else{if(n(aj.srcElement)){ad=aj.srcElement}else{return}}while((ai=ad.parentNode)&&((ak=ad.tagName)!="A"&&ak!="AREA")){ad=ai}if(n(ad.href)){var ah=ad.hostname,af=ah.toLowerCase(),ae=ad.href.replace(ah,af),ag=new RegExp("^(javascript|vbscript|jscript|mocha|livescript|ecmascript): *","i");if(!ag.test(ae)){ac=Y(ad.className,ae,L(af));if(ac){F(ae,ac)}}}}function U(ac){e(ac,"click",E,false)}function J(){if(!K){K=true;var ad,ac=M(u,"ignore"),ae=d.links;if(ae){for(ad=0;ad<ae.length;ad++){if(!ac.test(ae[ad].className)){U(ae[ad])}}}}}function x(ad,ac){var ae=null;if(typeof ad=="string"&&!n(v[ad])){if(typeof ac=="object"){ae=ac
+}else{if(typeof ac=="string"){try{eval("hookObj ="+ac)}catch(af){}}}v[ad]=ae}return ae}w=I();y=N();A();k("run",x);return{hook:v,getHook:function(ac){return v[ac]},setTrackerUrl:function(ac){if(n(ac)){D=ac}},setSiteId:function(ac){if(n(ac)){aa=ac}},setCustomData:function(ac){if(n(ac)){O=ac}},setLinkTrackingTimer:function(ac){if(n(ac)){C=ac}},setDownloadExtensions:function(ac){if(n(ac)){G=ac}},addDownloadExtensions:function(ac){if(n(ac)){G+="|"+ac}},setDomains:function(ac){if(typeof ac=="object"&&ac instanceof Array){R=ac;R[R.length]=i}else{if(typeof ac=="string"){R=[ac,i]}}},setIgnoreClasses:function(ac){if(typeof ac=="object"&&ac instanceof Array){u=ac}else{if(typeof ac=="string"){u=[ac]}}},setCustomUrl:function(ac){if(n(ac)){V=ac}},setDocumentTitle:function(ac){if(n(ac)){Z=ac}},setDownloadClasses:function(ac){if(typeof ac=="object"&&ac instanceof Array){S=ac}else{if(typeof ac=="string"){S=[ac]}}},setDownloadClass:function(ac){if(typeof ac=="string"){S=[ac]}},setLinkClasses:function(ac){if(typeof ac=="object"&&ac instanceof Array){T=ac
+}else{if(typeof ac=="string"){T=[ac]}}},setLinkClass:function(ac){if(typeof ac=="string"){T=[ac]}},addListener:function(ac){if(n(ac)){U(ac)}},enableLinkTracking:function(){if(h){J()}else{o[o.length]=function(){J()}}},trackGoal:function(ac,ae,ad){W(ac,ae,ad)},trackLink:function(ad,ac,ae){F(ad,ac,ae)},trackPageView:function(ac){r(ac)}}}e(l,"beforeunload",m,false);a();return{addPlugin:function(q,r){f[q]=r},getTracker:function(q,r){return new j(q,r)}}}());piwik_log=function(b,e,c,f){function a(g){try{return eval("piwik_"+g)}catch(h){}return}var d=Piwik.getTracker(c,e);d.setDocumentTitle(b);d.setCustomData(f);d.setLinkTrackingTimer(a("tracker_pause"));d.setDownloadExtensions(a("download_extensions"));d.setDomains(a("hosts_alias"));d.setIgnoreClasses(a("ignore_classes"));d.trackPageView();if(a("install_tracker")!==false){piwik_track=function(h,j,i,g){d.setSiteId(j);d.setTrackerUrl(i);d.trackLink(h,g)};d.enableLinkTracking()}}}; \ No newline at end of file
diff --git a/piwik.php b/piwik.php
index 3801e37c9e..0d0f108959 100644
--- a/piwik.php
+++ b/piwik.php
@@ -5,6 +5,8 @@
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
+ *
+ * @package Piwik
*/
if(file_exists('bootstrap.php'))
@@ -13,8 +15,8 @@ if(file_exists('bootstrap.php'))
}
$GLOBALS['PIWIK_TRACKER_DEBUG'] = false;
-
-define('PIWIK_TRACKER_MODE', true);
+$GLOBALS['PIWIK_TRACKER_MODE'] = true;
+define('PIWIK_ENABLE_TRACKING', true);
error_reporting(E_ALL|E_NOTICE);
define('PIWIK_DOCUMENT_ROOT', dirname(__FILE__)=='/'?'':dirname(__FILE__));
@@ -29,15 +31,7 @@ if(!defined('PIWIK_INCLUDE_PATH'))
@ignore_user_abort(true);
-if(!defined('PIWIK_INCLUDE_SEARCH_PATH'))
-{
- define('PIWIK_INCLUDE_SEARCH_PATH', PIWIK_INCLUDE_PATH . '/core'
- . PATH_SEPARATOR . PIWIK_INCLUDE_PATH . '/libs'
- . PATH_SEPARATOR . PIWIK_INCLUDE_PATH . '/plugins');
- @ini_set('include_path', PIWIK_INCLUDE_SEARCH_PATH);
- @set_include_path(PIWIK_INCLUDE_SEARCH_PATH);
-}
-
+require_once PIWIK_INCLUDE_PATH .'/libs/upgradephp/common.php';
require_once PIWIK_INCLUDE_PATH .'/libs/Event/Dispatcher.php';
require_once PIWIK_INCLUDE_PATH .'/libs/Event/Notification.php';
require_once PIWIK_INCLUDE_PATH .'/core/PluginsManager.php';
@@ -54,9 +48,9 @@ require_once PIWIK_INCLUDE_PATH .'/core/Cookie.php';
session_cache_limiter('nocache');
ob_start();
+@date_default_timezone_set('UTC');
if($GLOBALS['PIWIK_TRACKER_DEBUG'] === true)
{
- @date_default_timezone_set(date_default_timezone_get());
require_once PIWIK_INCLUDE_PATH .'/core/Loader.php';
require_once PIWIK_INCLUDE_PATH .'/core/ErrorHandler.php';
require_once PIWIK_INCLUDE_PATH .'/core/ExceptionHandler.php';
diff --git a/plugins/API/API.php b/plugins/API/API.php
index c645a91aea..8d616b153d 100644
--- a/plugins/API/API.php
+++ b/plugins/API/API.php
@@ -19,11 +19,11 @@ class Piwik_API extends Piwik_Plugin
public function getInformation()
{
return array(
- 'name' => 'API',
- 'description' => 'All the data in Piwik is available through simple APIs. This plugin is the web service entry point, that you can call to get your Web Analytics data in xml, json, php, csv, etc. Discover the <a href="http://dev.piwik.org/trac/wiki/API/Reference">Piwik APIs</a>.',
+ 'description' => Piwik_Translate('API_PluginDescription'),
+ 'homepage' => 'misc/redirectToUrl.php?url=http://dev.piwik.org/trac/wiki/API/Reference',
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
}
}
diff --git a/plugins/API/templates/listAllAPI.tpl b/plugins/API/templates/listAllAPI.tpl
index 42a1bcdfe3..68d51b6684 100644
--- a/plugins/API/templates/listAllAPI.tpl
+++ b/plugins/API/templates/listAllAPI.tpl
@@ -1,8 +1,25 @@
{assign var=showSitesSelection value=true}
{assign var=showPeriodSelection value=false}
+{assign var=showMenu value=false}
{include file="CoreAdminHome/templates/header.tpl"}
-{'API_QuickDocumentation'|translate:$token_auth}
-<span id='token_auth'>token_auth = <b>{$token_auth}</b></span>
+<style>
+{fetch file="plugins/API/templates/styles.css"}
+</style>
+<h2>{'API_QuickDocumentationTitle'|translate}</h2>
+<p>{'API_PluginDescription'|translate}</p>
+
+{if $isSuperUser}
+ <p>{'API_GenerateVisits'|translate:'VisitorGenerator':'VisitorGenerator'}</p>
+{/if}
+
+<p><b>{'API_MoreInformation'|translate:"<a target='_blank' href='misc/redirectToUrl.php?url=http://dev.piwik.org/trac/wiki/API'>":"</a>":"<a target='_blank' href='misc/redirectToUrl.php?url=http://dev.piwik.org/trac/wiki/API/Reference'>":"</a>"}</b></p>
+
+<h2>{'API_UserAuthentication'|translate}</h2>
+<p>
+{'API_UsingTokenAuth'|translate:'<b>':'</b>':"<u><code>&amp;token_auth=$token_auth</code></u>"}<br />
+<span id='token_auth'>token_auth = <b>{$token_auth}</b></span><br />
+{'API_KeepTokenSecret'|translate:'<b>':'</b>'}
<p><i>{'API_LoadedAPIs'|translate:$countLoadedAPI}</i></p>
{$list_api_methods_with_links}
+<br /> \ No newline at end of file
diff --git a/plugins/Actions/API.php b/plugins/Actions/API.php
index 658d5da13f..8b45cc989f 100644
--- a/plugins/Actions/API.php
+++ b/plugins/Actions/API.php
@@ -62,7 +62,18 @@ class Piwik_Actions_API
public function getPageUrls( $idSite, $period, $date, $expanded = false, $idSubtable = false )
{
- return $this->getDataTable('Actions_actions_url', $idSite, $period, $date, $expanded, $idSubtable );
+ $dataTable = $this->getDataTable('Actions_actions_url', $idSite, $period, $date, $expanded, $idSubtable );
+
+ // Average time on page = total time on page / number visits on that page
+ $dataTable->filter('ColumnCallbackAddColumnQuotient', array('avg_time_on_page', 'sum_time_spent', 'nb_visits', 0));
+
+ // Bounce rate = single page visits on this page / visits started on this page
+ $dataTable->filter('ColumnCallbackAddColumnPercentage', array('bounce_rate', 'entry_bounce_count', 'entry_nb_visits', 0));
+
+ // % Exit = Number of visits that finished on this page / visits on this page
+ $dataTable->filter('ColumnCallbackAddColumnPercentage', array('exit_rate', 'exit_nb_visits', 'nb_visits', 0));
+
+ return $dataTable;
}
public function getPageTitles( $idSite, $period, $date, $expanded = false, $idSubtable = false)
diff --git a/plugins/Actions/Actions.php b/plugins/Actions/Actions.php
index 199726675a..9919c02019 100644
--- a/plugins/Actions/Actions.php
+++ b/plugins/Actions/Actions.php
@@ -19,7 +19,8 @@
*/
class Piwik_Actions extends Piwik_Plugin
{
- static protected $actionCategoryDelimiter = null;
+ static protected $actionUrlCategoryDelimiter = null;
+ static protected $actionTitleCategoryDelimiter = null;
static protected $defaultActionName = null;
static protected $defaultActionNameWhenNotDefined = null;
static protected $defaultActionUrlWhenNotDefined = null;
@@ -31,11 +32,10 @@ class Piwik_Actions extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Actions',
- 'description' => 'Reports about the page views, the outlinks and downloads. Outlinks and Downloads tracking is automatic!',
+ 'description' => Piwik_Translate('Actions_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
}
@@ -53,7 +53,18 @@ class Piwik_Actions extends Piwik_Plugin
public function __construct()
{
- self::$actionCategoryDelimiter = Zend_Registry::get('config')->General->action_category_delimiter;
+ // for BC, we read the old style delimiter first (see #1067)
+ $actionDelimiter = Zend_Registry::get('config')->General->action_category_delimiter;
+ if(empty($actionDelimiter))
+ {
+ self::$actionUrlCategoryDelimiter = Zend_Registry::get('config')->General->action_url_category_delimiter;
+ self::$actionTitleCategoryDelimiter = Zend_Registry::get('config')->General->action_title_category_delimiter;
+ }
+ else
+ {
+ self::$actionUrlCategoryDelimiter = self::$actionTitleCategoryDelimiter = $actionDelimiter;
+ }
+
self::$defaultActionName = Zend_Registry::get('config')->General->action_default_name;
self::$defaultActionNameWhenNotDefined = Zend_Registry::get('config')->General->action_default_name_when_not_defined;
self::$defaultActionUrlWhenNotDefined = Zend_Registry::get('config')->General->action_default_url_when_not_defined;
@@ -64,6 +75,8 @@ class Piwik_Actions extends Piwik_Plugin
function addWidgets()
{
+ Piwik_AddWidget( 'Actions_Actions', 'Actions_SubmenuPagesEntry', 'Actions', 'getEntryPageUrls');
+ Piwik_AddWidget( 'Actions_Actions', 'Actions_SubmenuPagesExit', 'Actions', 'getExitPageUrls');
Piwik_AddWidget( 'Actions_Actions', 'Actions_SubmenuPages', 'Actions', 'getPageUrls');
Piwik_AddWidget( 'Actions_Actions', 'Actions_SubmenuPageTitles', 'Actions', 'getPageTitles');
Piwik_AddWidget( 'Actions_Actions', 'Actions_SubmenuOutlinks', 'Actions', 'getOutlinks');
@@ -73,6 +86,8 @@ class Piwik_Actions extends Piwik_Plugin
function addMenus()
{
Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuPages', array('module' => 'Actions', 'action' => 'getPageUrls'));
+ Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuPagesEntry', array('module' => 'Actions', 'action' => 'getEntryPageUrls'));
+ Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuPagesExit', array('module' => 'Actions', 'action' => 'getExitPageUrls'));
Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuPageTitles', array('module' => 'Actions', 'action' => 'getPageTitles'));
Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuOutlinks', array('module' => 'Actions', 'action' => 'getOutlinks'));
Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuDownloads', array('module' => 'Actions', 'action' => 'getDownloads'));
@@ -113,6 +128,7 @@ class Piwik_Actions extends Piwik_Plugin
public function archiveDay( $notification )
{
//TODO Actions should use integer based keys like other archive in piwik
+ /* @var $archiveProcessing Piwik_ArchiveProcessing */
$archiveProcessing = $notification->getNotificationObject();
$this->actionsTablesByType = array(
@@ -143,11 +159,12 @@ class Piwik_Actions extends Piwik_Plugin
FROM (".$archiveProcessing->logTable." as t1
LEFT JOIN ".$archiveProcessing->logVisitActionTable." as t2 USING (idvisit))
LEFT JOIN ".$archiveProcessing->logActionTable." as t3 ON (t2.idaction_url = t3.idaction)
- WHERE visit_server_date = ?
+ WHERE visit_last_action_time >= ?
+ AND visit_last_action_time <= ?
AND idsite = ?
GROUP BY t3.idaction
ORDER BY nb_hits DESC";
- $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
+ $query = $archiveProcessing->db->query($query, array( $archiveProcessing->getStartDatetimeUTC(), $archiveProcessing->getEndDatetimeUTC(), $archiveProcessing->idsite ));
$modified = $this->updateActionsTableWithRowQuery($query);
/*
@@ -161,11 +178,12 @@ class Piwik_Actions extends Piwik_Plugin
FROM (".$archiveProcessing->logTable." as t1
LEFT JOIN ".$archiveProcessing->logVisitActionTable." as t2 USING (idvisit))
LEFT JOIN ".$archiveProcessing->logActionTable." as t3 ON (t2.idaction_name = t3.idaction)
- WHERE visit_server_date = ?
+ WHERE visit_last_action_time >= ?
+ AND visit_last_action_time <= ?
AND idsite = ?
GROUP BY t3.idaction
ORDER BY nb_hits DESC";
- $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
+ $query = $archiveProcessing->db->query($query, array( $archiveProcessing->getStartDatetimeUTC(), $archiveProcessing->getEndDatetimeUTC(), $archiveProcessing->idsite ));
$modified = $this->updateActionsTableWithRowQuery($query);
/*
@@ -180,11 +198,12 @@ class Piwik_Actions extends Piwik_Plugin
sum(case visit_total_actions when 1 then 1 else 0 end) as entry_bounce_count
FROM ".$archiveProcessing->logTable."
JOIN ".$archiveProcessing->logActionTable." ON (visit_entry_idaction_url = idaction)
- WHERE visit_server_date = ?
+ WHERE visit_last_action_time >= ?
+ AND visit_last_action_time <= ?
AND idsite = ?
GROUP BY visit_entry_idaction_url
";
- $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
+ $query = $archiveProcessing->db->query($query, array( $archiveProcessing->getStartDatetimeUTC(), $archiveProcessing->getEndDatetimeUTC(), $archiveProcessing->idsite ));
$modified = $this->updateActionsTableWithRowQuery($query);
@@ -194,15 +213,15 @@ class Piwik_Actions extends Piwik_Plugin
$query = "SELECT name,
type,
count(distinct visitor_idcookie) as exit_nb_uniq_visitors,
- count(*) as exit_nb_visits,
- sum(case visit_total_actions when 1 then 1 else 0 end) as exit_bounce_count
+ count(*) as exit_nb_visits
FROM ".$archiveProcessing->logTable."
JOIN ".$archiveProcessing->logActionTable." ON (visit_exit_idaction_url = idaction)
- WHERE visit_server_date = ?
+ WHERE visit_last_action_time >= ?
+ AND visit_last_action_time <= ?
AND idsite = ?
GROUP BY visit_exit_idaction_url
";
- $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
+ $query = $archiveProcessing->db->query($query, array( $archiveProcessing->getStartDatetimeUTC(), $archiveProcessing->getEndDatetimeUTC(), $archiveProcessing->idsite ));
$modified = $this->updateActionsTableWithRowQuery($query);
/*
@@ -214,11 +233,12 @@ class Piwik_Actions extends Piwik_Plugin
FROM (".$archiveProcessing->logTable." log_visit
JOIN ".$archiveProcessing->logVisitActionTable." log_link_visit_action USING (idvisit))
JOIN ".$archiveProcessing->logActionTable." log_action ON (log_action.idaction = log_link_visit_action.idaction_url_ref)
- WHERE visit_server_date = ?
+ WHERE visit_last_action_time >= ?
+ AND visit_last_action_time <= ?
AND idsite = ?
GROUP BY idaction_url_ref
";
- $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
+ $query = $archiveProcessing->db->query($query, array( $archiveProcessing->getStartDatetimeUTC(), $archiveProcessing->getEndDatetimeUTC(), $archiveProcessing->idsite ));
$modified = $this->updateActionsTableWithRowQuery($query);
$this->archiveDayRecordInDatabase($archiveProcessing);
}
@@ -320,12 +340,21 @@ class Piwik_Actions extends Piwik_Plugin
}
}
- if(empty(self::$actionCategoryDelimiter))
+ if($type == Piwik_Tracker_Action::TYPE_ACTION_NAME)
+ {
+ $categoryDelimiter = self::$actionTitleCategoryDelimiter;
+ }
+ else
+ {
+ $categoryDelimiter = self::$actionUrlCategoryDelimiter;
+ }
+
+ if(empty($categoryDelimiter))
{
return array( trim($name) );
}
- $split = explode(self::$actionCategoryDelimiter, $name, self::$limitLevelSubCategory);
+ $split = explode($categoryDelimiter, $name, self::$limitLevelSubCategory);
// trim every category and remove empty categories
$split = array_map('trim', $split);
@@ -349,9 +378,14 @@ class Piwik_Actions extends Piwik_Plugin
$rowsProcessed = 0;
while( $row = $query->fetch() )
{
+ // in some unknown case, the type field is NULL, as reported in #1082 - we ignore this page view
+ if(empty($row['type'])) {
+ continue;
+ }
+
$actionExplodedNames = $this->getActionExplodedNames($row['name'], $row['type']);
- // we work on the root table of the given TYPE (either ACTION or DOWNLOAD or OUTLINK etc.)
+ // we work on the root table of the given TYPE (either ACTION_URL or DOWNLOAD or OUTLINK etc.)
$currentTable =& $this->actionsTablesByType[$row['type']];
// go to the level of the subcategory
@@ -370,7 +404,7 @@ class Piwik_Actions extends Piwik_Plugin
{
$actionName = '/' . $actionName;
}
- else if( $row['type'] == Piwik_Tracker_Action::TYPE_ACTION_NAME )
+ else
{
$actionName = ' ' . $actionName;
}
@@ -397,6 +431,14 @@ class Piwik_Actions extends Piwik_Plugin
}
}
+ // For pages that bounce, we don't know the time on page.
+ if($row['type'] == Piwik_Tracker_Action::TYPE_ACTION_URL
+ && isset($row['nb_visits'])
+ && !isset($row['sum_time_spent']))
+ {
+ $row['sum_time_spent'] = Zend_Registry::get('config')->Tracker->default_time_one_page_visit * $row['nb_visits'];
+ }
+
foreach($row as $name => $value)
{
// we don't add this information as itnot pertinent
diff --git a/plugins/Actions/Controller.php b/plugins/Actions/Controller.php
index 64974199b4..5e85433fbb 100644
--- a/plugins/Actions/Controller.php
+++ b/plugins/Actions/Controller.php
@@ -17,29 +17,91 @@
*/
class Piwik_Actions_Controller extends Piwik_Controller
{
- public function getPageUrls($fetch = false)
+ const ACTIONS_REPORT_ROWS_DISPLAY = 100;
+
+ protected function getPageUrlsView($currentAction, $controllerActionSubtable)
{
$view = Piwik_ViewDataTable::factory();
$view->init( $this->pluginName,
- __FUNCTION__,
+ $currentAction,
'Actions.getPageUrls',
- 'getPageUrlsSubDataTable' );
+ $controllerActionSubtable );
$view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnPageURL'));
+ return $view;
+ }
+
+ public function getPageUrls($fetch = false)
+ {
+ $view = $this->getPageUrlsView(__FUNCTION__, 'getPageUrlsSubDataTable');
+ $this->configureViewPageUrls($view);
$this->configureViewActions($view);
return $this->renderView($view, $fetch);
}
public function getPageUrlsSubDataTable($fetch = false)
{
- $view = Piwik_ViewDataTable::factory();
- $view->init( $this->pluginName,
- __FUNCTION__,
- 'Actions.getPageUrls',
- 'getActionsSubDataTable' );
+ $view = $this->getPageUrlsView(__FUNCTION__, 'getPageUrlsSubDataTable');
+ $this->configureViewPageUrls($view);
+ $this->configureViewActions($view);
+ return $this->renderView($view, $fetch);
+ }
+
+ protected function configureViewPageUrls($view)
+ {
+ $view->setColumnsToDisplay( array('label','nb_hits','nb_visits', 'bounce_rate', 'avg_time_on_page', 'exit_rate') );
+ }
+
+ public function getEntryPageUrls($fetch = false)
+ {
+ $view = $this->getPageUrlsView(__FUNCTION__, 'getEntryPageUrlsSubDataTable');
+ $this->configureViewEntryPageUrls($view);
+ $this->configureViewActions($view);
+ return $this->renderView($view, $fetch);
+ }
+
+ public function getEntryPageUrlsSubDataTable($fetch = false)
+ {
+ $view = $this->getPageUrlsView(__FUNCTION__, 'getEntryPageUrlsSubDataTable');
+ $this->configureViewEntryPageUrls($view);
$this->configureViewActions($view);
return $this->renderView($view, $fetch);
}
+
+ protected function configureViewEntryPageUrls($view)
+ {
+ $view->setSortedColumn('entry_nb_visits');
+ $view->setColumnsToDisplay( array('label','entry_nb_visits', 'entry_bounce_count', 'bounce_rate') );
+ $view->setColumnTranslation('entry_bounce_count', Piwik_Translate('General_ColumnBounces'), Piwik_Translate('General_BouncesDefinition'));
+ $view->setColumnTranslation('entry_nb_visits', Piwik_Translate('General_ColumnEntrances'), Piwik_Translate('General_EntrancesDefinition'));
+ // remove pages that are not entry pages
+ $view->queueFilter('ColumnCallbackDeleteRow', array('entry_nb_visits', 'strlen'));
+ }
+ public function getExitPageUrls($fetch = false)
+ {
+ $view = $this->getPageUrlsView(__FUNCTION__, 'getExitPageUrlsSubDataTable');
+ $this->configureViewExitPageUrls($view);
+ $this->configureViewActions($view);
+ return $this->renderView($view, $fetch);
+ }
+
+ public function getExitPageUrlsSubDataTable($fetch = false)
+ {
+ $view = $this->getPageUrlsView(__FUNCTION__, 'getExitPageUrlsSubDataTable');
+ $this->configureViewExitPageUrls($view);
+ $this->configureViewActions($view);
+ return $this->renderView($view, $fetch);
+ }
+
+ protected function configureViewExitPageUrls($view)
+ {
+ $view->setSortedColumn('exit_nb_visits');
+ $view->setColumnsToDisplay( array('label', 'exit_nb_visits', 'nb_visits', 'exit_rate') );
+ $view->setColumnTranslation('exit_nb_visits', Piwik_Translate('General_ColumnExits'), Piwik_Translate('General_ExitsDefinition'));
+ // remove pages that are not exit pages
+ $view->queueFilter('ColumnCallbackDeleteRow', array('exit_nb_visits', 'strlen'));
+ }
+
public function getPageTitles($fetch = false)
{
$view = Piwik_ViewDataTable::factory();
@@ -48,6 +110,7 @@ class Piwik_Actions_Controller extends Piwik_Controller
'Actions.getPageTitles',
'getPageTitlesSubDataTable' );
$view->setColumnTranslation('label', Piwik_Translate('Actions_ColumnPageName'));
+ $this->configureViewPageTitles($view);
$this->configureViewActions($view);
return $this->renderView($view, $fetch);
}
@@ -59,10 +122,16 @@ class Piwik_Actions_Controller extends Piwik_Controller
__FUNCTION__,
'Actions.getPageTitles',
'getPageTitlesSubDataTable' );
+ $this->configureViewPageTitles($view);
$this->configureViewActions($view);
return $this->renderView($view, $fetch);
}
+ protected function configureViewPageTitles($view)
+ {
+ $view->setColumnsToDisplay( array('label','nb_hits','nb_visits') );
+ }
+
public function getDownloads($fetch = false)
{
$view = Piwik_ViewDataTable::factory();
@@ -72,7 +141,6 @@ class Piwik_Actions_Controller extends Piwik_Controller
'getDownloadsSubDataTable' );
$this->configureViewDownloads($view);
- $view->disableShowAllColumns();
return $this->renderView($view, $fetch);
}
@@ -84,7 +152,6 @@ class Piwik_Actions_Controller extends Piwik_Controller
'Actions.getDownloads',
'getDownloadsSubDataTable');
$this->configureViewDownloads($view);
- $view->disableSearchBox();
return $this->renderView($view, $fetch);
}
@@ -96,8 +163,6 @@ class Piwik_Actions_Controller extends Piwik_Controller
'Actions.getOutlinks',
'getOutlinksSubDataTable' );
$this->configureViewOutlinks($view);
- $view->disableExcludeLowPopulation();
- $view->disableShowAllColumns();
return $this->renderView($view, $fetch);
}
@@ -109,34 +174,21 @@ class Piwik_Actions_Controller extends Piwik_Controller
'Actions.getOutlinks',
'getOutlinksSubDataTable');
$this->configureViewOutlinks($view);
- $view->disableSearchBox();
return $this->renderView($view, $fetch);
}
+ /*
+ * Page titles & Page URLs reports
+ */
protected function configureViewActions($view)
{
- $view->setTemplate('CoreHome/templates/datatable_actions.tpl');
-
- if(Piwik_Common::getRequestVar('idSubtable', -1) != -1)
- {
- $view->setTemplate('CoreHome/templates/datatable_actions_subdatable.tpl');
- }
- $currentlySearching = $view->setSearchRecursive();
-
- if($currentlySearching)
- {
- $view->setTemplate('CoreHome/templates/datatable_actions_recursive.tpl');
- }
- $view->disableSort();
- $view->disableOffsetInformation();
- $view->disableShowAllViewsIcons();
- $view->disableShowAllColumns();
-
- $view->setLimit( 100 );
- $view->setColumnsToDisplay( array('label','nb_hits','nb_visits') );
$view->setColumnTranslation('nb_hits', Piwik_Translate('General_ColumnPageviews'));
$view->setColumnTranslation('nb_visits', Piwik_Translate('General_ColumnUniquePageviews'));
-
+ $view->setColumnTranslation('avg_time_on_page', Piwik_Translate('General_ColumnAverageTimeOnPage'), Piwik_Translate('General_AverageTimeOnPageDefinition'));
+ $view->setColumnTranslation('bounce_rate', Piwik_Translate('General_ColumnBounceRate'), Piwik_Translate('General_PageBounceRateDefinition'));
+ $view->setColumnTranslation('exit_rate', Piwik_Translate('General_ColumnExitRate'), Piwik_Translate('General_PageExitRateDefinition'));
+ $view->queueFilter('ColumnCallbackReplace', array('avg_time_on_page', array('Piwik', 'getPrettyTimeFromSeconds')));
+
if(Piwik_Common::getRequestVar('enable_filter_excludelowpop', '0', 'string' ) != '0')
{
// computing minimum value to exclude
@@ -150,18 +202,14 @@ class Piwik_Actions_Controller extends Piwik_Controller
$view->setExcludeLowPopulation( 'nb_hits', $nbActionsLowPopulationThreshold );
}
-
- $view->main();
-
- // we need to rewrite the phpArray so it contains all the recursive arrays
- if($currentlySearching)
- {
- $phpArrayRecursive = $this->getArrayFromRecursiveDataTable($view->getDataTable());
- $view->getView()->arrayDataTable = $phpArrayRecursive;
- }
+
+ $this->configureGenericViewActions($view);
return $view;
}
+ /*
+ * Downloads report
+ */
protected function configureViewDownloads($view)
{
$view->setColumnsToDisplay( array('label','nb_visits','nb_hits') );
@@ -169,9 +217,12 @@ class Piwik_Actions_Controller extends Piwik_Controller
$view->setColumnTranslation('nb_hits', Piwik_Translate('Actions_ColumnDownloads'));
$view->setColumnTranslation('nb_visits', Piwik_Translate('Actions_ColumnUniqueDownloads'));
$view->disableExcludeLowPopulation();
- $view->setLimit( 15 );
+ $this->configureGenericViewActions($view);
}
+ /*
+ * Outlinks report
+ */
protected function configureViewOutlinks($view)
{
$view->setColumnsToDisplay( array('label','nb_visits','nb_hits') );
@@ -179,9 +230,38 @@ class Piwik_Actions_Controller extends Piwik_Controller
$view->setColumnTranslation('nb_hits', Piwik_Translate('Actions_ColumnClicks'));
$view->setColumnTranslation('nb_visits', Piwik_Translate('Actions_ColumnUniqueClicks'));
$view->disableExcludeLowPopulation();
- $view->setLimit( 15 );
+ $this->configureGenericViewActions($view);
}
+ /*
+ * Common to all Actions reports, how to use the custom Actions Datatable html
+ */
+ protected function configureGenericViewActions($view)
+ {
+ $view->setTemplate('CoreHome/templates/datatable_actions.tpl');
+ if(Piwik_Common::getRequestVar('idSubtable', -1) != -1)
+ {
+ $view->setTemplate('CoreHome/templates/datatable_actions_subdatable.tpl');
+ }
+ $currentlySearching = $view->setSearchRecursive();
+ if($currentlySearching)
+ {
+ $view->setTemplate('CoreHome/templates/datatable_actions_recursive.tpl');
+ }
+ // disable Footer icons
+ $view->disableShowAllViewsIcons();
+ $view->disableShowAllColumns();
+
+ $view->setLimit( self::ACTIONS_REPORT_ROWS_DISPLAY );
+ $view->main();
+ // we need to rewrite the phpArray so it contains all the recursive arrays
+ if($currentlySearching)
+ {
+ $phpArrayRecursive = $this->getArrayFromRecursiveDataTable($view->getDataTable());
+ $view->getView()->arrayDataTable = $phpArrayRecursive;
+ }
+ }
+
protected function getArrayFromRecursiveDataTable( $dataTable, $depth = 0 )
{
$table = array();
diff --git a/plugins/Actions/tests/Actions.test.php b/plugins/Actions/tests/Actions.test.php
index 08f11e81ef..a7f0197334 100644
--- a/plugins/Actions/tests/Actions.test.php
+++ b/plugins/Actions/tests/Actions.test.php
@@ -56,7 +56,11 @@ class Test_Piwik_Actions extends UnitTestCase
),
array(
'params' => array( 'name' => '', 'type' => Piwik_Tracker_Action::TYPE_ACTION_NAME),
- 'expected' => array( 'index' ),
+ 'expected' => array( Zend_Registry::get('config')->General->action_default_name_when_not_defined ),
+ ),
+ array(
+ 'params' => array( 'name' => '', 'type' => Piwik_Tracker_Action::TYPE_ACTION_URL),
+ 'expected' => array( Zend_Registry::get('config')->General->action_default_url_when_not_defined ),
),
array(
'params' => array( 'name' => 'http://example.org/download.zip', 'type' => Piwik_Tracker_Action::TYPE_DOWNLOAD),
diff --git a/plugins/AnonymizeIP/AnonymizeIP.php b/plugins/AnonymizeIP/AnonymizeIP.php
new file mode 100644
index 0000000000..e921b57e31
--- /dev/null
+++ b/plugins/AnonymizeIP/AnonymizeIP.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik_Plugins
+ * @package Piwik_AnonymizeIP
+ */
+
+/**
+ * Anonymize visitor IP addresses to comply with the privacy laws/guidelines in countries, such as Germany.
+ *
+ * @package Piwik_AnonymizeIP
+ */
+class Piwik_AnonymizeIP extends Piwik_Plugin
+{
+ /**
+ * Get plugin information
+ */
+ public function getInformation()
+ {
+ return array(
+ 'description' => Piwik_Translate('AnonymizeIP_PluginDescription'),
+ 'author' => 'Piwik',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
+ 'TrackerPlugin' => true,
+ );
+ }
+
+ /**
+ * Get list of hooks to register
+ */
+ public function getListHooksRegistered()
+ {
+ return array(
+ 'Tracker.saveVisitorInformation' => 'anonymizeVisitorIpAddress',
+ );
+ }
+
+ /**
+ * Internal function to mask portions of the visitor IP address
+ *
+ * @param $ip Unsigned long representation of IP address
+ * @param $maskLength Number of octets to reset
+ */
+ static public function applyIPMask($ip, $maskLength)
+ {
+ $maskedIP = pack('V', (float)$ip);
+
+ switch($maskLength) {
+ case 4:
+ $maskedIP[3] = "\0";
+ case 3:
+ $maskedIP[2] = "\0";
+ case 2:
+ $maskedIP[1] = "\0";
+ case 1:
+ $maskedIP[0] = "\0";
+ case 0:
+ default:
+ }
+
+ $res = unpack('V', $maskedIP);
+ return sprintf("%u", $res[1]);
+ }
+
+ /**
+ * Hook on Tracker.saveVisitorInformation to anonymize visitor IP addresses
+ */
+ function anonymizeVisitorIpAddress($notification)
+ {
+ $visitorInfo =& $notification->getNotificationObject();
+ $visitorInfo['location_ip'] = self::applyIPMask($visitorInfo['location_ip'], Piwik_Tracker_Config::getInstance()->Tracker['ip_address_mask_length']);
+ }
+}
diff --git a/plugins/AnonymizeIP/tests/AnonymizeIP.test.php b/plugins/AnonymizeIP/tests/AnonymizeIP.test.php
new file mode 100644
index 0000000000..7afd3e68bc
--- /dev/null
+++ b/plugins/AnonymizeIP/tests/AnonymizeIP.test.php
@@ -0,0 +1,46 @@
+<?php
+if(!defined("PIWIK_PATH_TEST_TO_ROOT")) {
+ define('PIWIK_PATH_TEST_TO_ROOT', getcwd().'/../../..');
+}
+if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
+{
+ require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php";
+}
+
+if(!class_exists('Piwik_AnonymizeIP', false))
+{
+ require_once dirname(__FILE__) . '/../AnonymizeIP.php';
+}
+
+class Test_Piwik_AnonymizeIP extends UnitTestCase
+{
+ // IP addresses and expected results
+ protected $ipAddresses = array(
+ // long => array( expected0, expected1, expected2, expected3, expected4 ),
+ '0' => array( 0, 0, 0, 0, 0 ), // 00 00 00 00
+ '1' => array( 1, 0, 0, 0, 0 ), // 00 00 00 01
+ '255' => array( 255, 0, 0, 0, 0 ), // 00 00 00 FF
+ '256' => array( 256, 256, 0, 0, 0 ), // 00 00 01 00
+ '257' => array( 257, 256, 0, 0, 0 ), // 00 00 01 01
+ '65535' => array( 65535, 65280, 0, 0, 0), // 00 00 FF FF
+ '65536' => array( 65536, 65536, 65536, 0, 0), // 00 01 00 00
+ '65793' => array( 65793, 65792, 65536, 0, 0), // 00 01 01 01
+ '16777215' => array( 16777215, 16776960, 16711680, 0, 0), // 00 FF FF FF
+ '16777216' => array( 16777216, 16777216, 16777216, 16777216, 0), // 01 00 00 00
+ '2147483647' => array( 2147483647, 2147483392, 2147418112, 2130706432, 0), // 7F FF FF FF
+ '2147483648' => array( '2147483648', '2147483648', '2147483648', '2147483648', 0), // 80 00 00 00
+ '4294967295' => array( '4294967295', '4294967040', '4294901760', '4278190080', 0), // FF FF FF FF
+ );
+
+ public function test_applyIPMask()
+ {
+ foreach($this->ipAddresses as $ip => $expected)
+ {
+ // each IP is tested with 0 to 4 octets masked
+ for($maskLength = 0; $maskLength <= 4; $maskLength++)
+ {
+ $this->assertTrue( Piwik_AnonymizeIP::applyIPMask($ip, $maskLength) == $expected[$maskLength] );
+ }
+ }
+ }
+}
diff --git a/plugins/CoreAdminHome/Controller.php b/plugins/CoreAdminHome/Controller.php
index 767d6ce8ca..2c63abbc7c 100644
--- a/plugins/CoreAdminHome/Controller.php
+++ b/plugins/CoreAdminHome/Controller.php
@@ -16,37 +16,38 @@
*/
class Piwik_CoreAdminHome_Controller extends Piwik_Controller
{
- function getDefaultAction()
+ public function index()
{
- return 'redirectToIndex';
- }
-
- function redirectToIndex()
- {
- if(Piwik::isUserIsSuperUser())
- {
- $module = 'CorePluginsAdmin';
- }
- else
- {
- $module = 'SitesManager';
- }
- header("Location:index.php?module=" . $module);
+ return $this->redirectToIndex('UsersManager', 'userSettings');
}
- public function index()
+ public function generalSettings()
{
- Piwik::checkUserIsSuperUser();
- $view = $this->getDefaultIndexView();
+ $view = Piwik_View::factory('generalSettings');
+ $view->enableBrowserTriggerArchiving = Piwik_ArchiveProcessing::isBrowserTriggerArchivingEnabled();
+ $view->todayArchiveTimeToLive = Piwik_ArchiveProcessing::getTodayArchiveTimeToLive();
+
+ $this->setGeneralVariablesView($view);
+ $view->menu = Piwik_GetAdminMenu();
echo $view->render();
}
- protected function getDefaultIndexView()
+ public function setGeneralSettings()
{
- $view = Piwik_View::factory('index');
- $view->content = '';
- $this->setGeneralVariablesView($view);
- $view->menu = Piwik_GetAdminMenu();
- return $view;
+ $response = new Piwik_API_ResponseBuilder(Piwik_Common::getRequestVar('format'));
+ try {
+ Piwik::checkUserIsSuperUser();
+ $this->checkTokenInUrl();
+ $enableBrowserTriggerArchiving = Piwik_Common::getRequestVar('enableBrowserTriggerArchiving');
+ $todayArchiveTimeToLive = Piwik_Common::getRequestVar('todayArchiveTimeToLive');
+
+ Piwik_ArchiveProcessing::setBrowserTriggerArchiving((bool)$enableBrowserTriggerArchiving);
+ Piwik_ArchiveProcessing::setTodayArchiveTimeToLive($todayArchiveTimeToLive);
+ $toReturn = $response->getResponse();
+ } catch(Exception $e ) {
+ $toReturn = $response->getResponseException( $e );
+ }
+ echo $toReturn;
}
+
}
diff --git a/plugins/CoreAdminHome/CoreAdminHome.php b/plugins/CoreAdminHome/CoreAdminHome.php
index c395ae00c2..8b15308f92 100644
--- a/plugins/CoreAdminHome/CoreAdminHome.php
+++ b/plugins/CoreAdminHome/CoreAdminHome.php
@@ -19,11 +19,10 @@ class Piwik_CoreAdminHome extends Piwik_Plugin
public function getInformation()
{
return array(
- 'name' => 'Administration area',
- 'description' => 'Administration area of Piwik.',
+ 'description' => Piwik_Translate('CoreAdminHome_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
}
@@ -31,6 +30,7 @@ class Piwik_CoreAdminHome extends Piwik_Plugin
{
return array(
'template_css_import' => 'css',
+ 'AdminMenu.add' => 'addMenu'
);
}
@@ -38,4 +38,12 @@ class Piwik_CoreAdminHome extends Piwik_Plugin
{
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"plugins/CoreAdminHome/templates/menu.css\" />\n";
}
+
+ function addMenu()
+ {
+ Piwik_AddAdminMenu('CoreAdminHome_MenuGeneralSettings',
+ array('module' => 'CoreAdminHome', 'action' => 'generalSettings'),
+ Piwik::isUserIsSuperUser(),
+ $order = 6);
+ }
}
diff --git a/plugins/CoreAdminHome/templates/footer.tpl b/plugins/CoreAdminHome/templates/footer.tpl
index f9ab9402da..4c988266c2 100644
--- a/plugins/CoreAdminHome/templates/footer.tpl
+++ b/plugins/CoreAdminHome/templates/footer.tpl
@@ -1,2 +1,2 @@
-
+</div>
{include file="CoreHome/templates/piwik_tag.tpl"}
diff --git a/plugins/CoreAdminHome/templates/generalSettings.js b/plugins/CoreAdminHome/templates/generalSettings.js
new file mode 100644
index 0000000000..f77a5ff9f5
--- /dev/null
+++ b/plugins/CoreAdminHome/templates/generalSettings.js
@@ -0,0 +1,30 @@
+function getGeneralSettingsAJAX()
+{
+ var ajaxRequest = piwikHelper.getStandardAjaxConf('ajaxLoading', 'ajaxError');
+ var enableBrowserTriggerArchiving = $('input[name=enableBrowserTriggerArchiving]:checked').val();
+ var todayArchiveTimeToLive = $('#todayArchiveTimeToLive').val();
+ var request = '';
+ request += 'module=CoreAdminHome';
+ request += '&action=setGeneralSettings';
+ request += '&format=json';
+ request += '&enableBrowserTriggerArchiving='+enableBrowserTriggerArchiving;
+ request += '&todayArchiveTimeToLive='+todayArchiveTimeToLive;
+ request += '&token_auth=' + piwik.token_auth;
+ ajaxRequest.data = request;
+ return ajaxRequest;
+}
+
+$(document).ready( function() {
+ $('#generalSettingsSubmit').click( function() {
+ $.ajax( getGeneralSettingsAJAX() );
+ });
+
+ $('input').keypress( function(e) {
+ var key=e.keyCode || e.which;
+ if (key==13) {
+ $('#generalSettingsSubmit').click();
+ }
+ }
+ )
+});
+
diff --git a/plugins/CoreAdminHome/templates/generalSettings.tpl b/plugins/CoreAdminHome/templates/generalSettings.tpl
new file mode 100644
index 0000000000..fa103f4347
--- /dev/null
+++ b/plugins/CoreAdminHome/templates/generalSettings.tpl
@@ -0,0 +1,53 @@
+{assign var=showSitesSelection value=false}
+{assign var=showPeriodSelection value=false}
+{include file="CoreAdminHome/templates/header.tpl"}
+{loadJavascriptTranslations plugins='UsersManager'}
+<script type="text/javascript" src="plugins/CoreAdminHome/templates/generalSettings.js"></script>
+
+<h2>{'General_GeneralSettings'|translate}</h2>
+
+{ajaxErrorDiv id=ajaxError}
+{ajaxLoadingDiv id=ajaxLoading}
+<table class="adminTable adminTableNoBorder" style='width:900px;'>
+<tr>
+ <td style='width:400px'>{'General_AllowPiwikArchivingToTriggerBrowser'|translate}</td>
+ <td style='width:220px'>
+ <fieldset>
+ <label><input type="radio" value="1" name="enableBrowserTriggerArchiving"{if $enableBrowserTriggerArchiving==1} checked="checked"{/if} />
+ {'General_Yes'|translate} <br />
+ <span class="form-description">{'General_Default'|translate}</span>
+ </label><br /><br />
+
+ <label><input type="radio" value="0" name="enableBrowserTriggerArchiving"{if $enableBrowserTriggerArchiving==0} checked="checked"{/if} />
+ {'General_No'|translate} <br />
+ <span class="form-description">{'General_ArchivingTriggerDescription'|translate:"<a href='misc/redirectToUrl.php?url=http://piwik.org/docs/setup-auto-archiving/' target='_blank'>":"</a>"}</span>
+ </label>
+ </fieldset>
+ <td>
+ {capture assign=browserArchivingHelp}
+ {'General_ArchivingInlineHelp'|translate}<br />
+ {'General_SeeTheOfficialDocumentationForMoreInformation'|translate:"<a href='misc/redirectToUrl.php?url=http://piwik.org/docs/setup-auto-archiving/' target='_blank'>":"</a>"}
+ {/capture}
+ {$browserArchivingHelp|inlineHelp} </td>
+ </td>
+</tr>
+<tr>
+ <td><label for="todayArchiveTTL">{'General_ReportsForTodayWillBeProcessedAtMostEvery'|translate}</label></td>
+ <td>
+ {'General_NSeconds'|translate:"<input size='3' value='$todayArchiveTimeToLive' id='todayArchiveTimeToLive' />"}
+ </td>
+ <td width='450px'>
+ {capture assign=archiveTodayTTLHelp}
+ {'General_SmallTrafficYouCanLeaveDefault'|translate:10}<br />
+ {'General_MediumToHighTrafficItIsRecommendedTo'|translate:1800:3600}
+ {/capture}
+ {$archiveTodayTTLHelp|inlineHelp} </td>
+ </td>
+</tr>
+
+</table>
+<input type="submit" value="{'General_Save'|translate}" id="generalSettingsSubmit" class="submit" />
+<br /><br />
+
+
+{include file="CoreAdminHome/templates/footer.tpl"}
diff --git a/plugins/CoreAdminHome/templates/header.tpl b/plugins/CoreAdminHome/templates/header.tpl
index c58df79c2b..c40295db70 100644
--- a/plugins/CoreAdminHome/templates/header.tpl
+++ b/plugins/CoreAdminHome/templates/header.tpl
@@ -2,7 +2,7 @@
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
-<title>Piwik &rsaquo; Administration</title>
+<title>Piwik &rsaquo; {'CoreAdminHome_Administration'|translate}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Piwik {$piwik_version}" />
<link rel="shortcut icon" href="plugins/CoreHome/templates/images/favicon.ico" />
@@ -10,18 +10,20 @@
{include file="CoreHome/templates/js_global_variables.tpl"}
<link rel="stylesheet" type="text/css" href="themes/default/common.css" />
-<link rel="stylesheet" type="text/css" href="libs/jquery/jquery-calendar.css" />
-<link rel="stylesheet" type="text/css" href="libs/jquery/thickbox.css" />
+<link rel="stylesheet" type="text/css" href="libs/jquery/themes/base/jquery-ui.css" class="ui-theme" />
<link rel="stylesheet" type="text/css" href="plugins/CoreAdminHome/templates/styles.css" />
{postEvent name="template_css_import"}
-<script type="text/javascript" src="themes/default/common.js"></script>
<script type="text/javascript" src="libs/jquery/jquery.js"></script>
<script type="text/javascript" src="libs/jquery/jquery-ui.js"></script>
+<script type="text/javascript" src="libs/jquery/jquery.bgiframe.js"></script>
<script type="text/javascript" src="libs/jquery/jquery.blockUI.js"></script>
-<script type="text/javascript" src="libs/jquery/thickbox.js"></script>
<script type="text/javascript" src="libs/jquery/fdd2div-modified.js"></script>
<script type="text/javascript" src="libs/javascript/sprintf.js"></script>
+<script type="text/javascript" src="themes/default/common.js"></script>
+
+<script type="text/javascript" src="libs/jquery/jquery.history.js"></script>
+<script type="text/javascript" src="plugins/CoreHome/templates/broadcast.js"></script>
{postEvent name="template_js_import"}
</head>
@@ -35,6 +37,22 @@
{include file="CoreHome/templates/js_disabled_notice.tpl"}
</div>
-<br clear="all"/>
+<br class="clearAll" />
<div id="content">
+
+{ajaxRequestErrorDiv}
+{if !isset($showMenu) || $showMenu}
+ {include file="CoreAdminHome/templates/menu.tpl"}
+{/if}
+
+{if !empty($configFileNotWritable)}
+<div class="ajaxSuccess" style="display:normal">
+ <p>{'General_ConfigFileIsNotWritable'|translate:"(config/config.ini.php)":"<br/>"}</p>
+</div>
+{elseif strpos($url, 'updated=1')}
+<div class="ajaxSuccess" style="display:normal">
+ <p>{'General_YourChangesHaveBeenSaved'|translate}</p>
+</div>
+{/if}
+
diff --git a/plugins/CoreAdminHome/templates/index.tpl b/plugins/CoreAdminHome/templates/index.tpl
deleted file mode 100644
index e207fb8be4..0000000000
--- a/plugins/CoreAdminHome/templates/index.tpl
+++ /dev/null
@@ -1,17 +0,0 @@
-{assign var=showSitesSelection value=false}
-{assign var=showPeriodSelection value=false}
-{include file="CoreAdminHome/templates/header.tpl"}
-{include file="CoreAdminHome/templates/menu.tpl"}
-
-<div style="clear:both;">
-
-<div id='content'>
-{if $content}{$content}{/if}
-</div>
-
-<div id="footer" style="border-top:1px solid gray; margin-top:20px;padding-top:10px;">
-<a href='index.php?module=CoreHome'>{'General_BackToHomepage'|translate}</a>
-
-</div>
-
-{include file="CoreAdminHome/templates/footer.tpl"}
diff --git a/plugins/CoreAdminHome/templates/menu.css b/plugins/CoreAdminHome/templates/menu.css
index 772e5d90eb..8ecc659a4c 100644
--- a/plugins/CoreAdminHome/templates/menu.css
+++ b/plugins/CoreAdminHome/templates/menu.css
@@ -1,5 +1,5 @@
#tablist {
- padding: 3px 0;
+ padding-bottom: 1px;
margin-left: 0;
margin-bottom: 0;
margin-top: 0.1em;
@@ -10,6 +10,7 @@
list-style: none;
display: inline;
margin: 0;
+ padding-bottom:3px;
}
#tablist li a {
@@ -24,9 +25,11 @@
#tablist li a:link,#tablist li a:visited {
color: black;
+ -moz-border-radius:4px 4px 0 0;
+ -webkit-border-radius:4px 4px 0 0;
}
-#tablist li a:hover {
+#tablist li a:hover, #tablist li a.active {
color: black;
background: #defdbb;
border-color: black;
diff --git a/plugins/CoreAdminHome/templates/menu.tpl b/plugins/CoreAdminHome/templates/menu.tpl
index 3dc4469aa5..9200e8160c 100644
--- a/plugins/CoreAdminHome/templates/menu.tpl
+++ b/plugins/CoreAdminHome/templates/menu.tpl
@@ -1,7 +1,9 @@
-<div id="menu">
-<ul id="tablist">
-{foreach from=$menu key=name item=url name=menu}
- <li><a href='index.php{$url|@urlRewriteWithParameters}'>{$name|translate}</a></li>
-{/foreach}
-</ul>
-</div>
+{if count($menu) > 1}
+ <div id="menu">
+ <ul id="tablist">
+ {foreach from=$menu key=name item=url name=menu}
+ <li> <a href='index.php{$url|@urlRewriteWithParameters}' {if isset($currentAdminMenuName) && $name==$currentAdminMenuName}class='active'{/if}>{$name|translate}</a></li>
+ {/foreach}
+ </ul>
+ </div>
+{/if} \ No newline at end of file
diff --git a/plugins/CoreAdminHome/templates/styles.css b/plugins/CoreAdminHome/templates/styles.css
index 04cfb8fa59..3c2bbdda7b 100644
--- a/plugins/CoreAdminHome/templates/styles.css
+++ b/plugins/CoreAdminHome/templates/styles.css
@@ -1,15 +1,9 @@
-body {
- font-family: Georgia, Trebuchet MS, arial, sans-serif;
-}
-
img {
vertical-align: baseline;
}
-
textarea {
font-size: 1em;
}
-
a {
color: black;
}
@@ -40,15 +34,13 @@ table.admin tbody tr {
table.admin tbody td {
color: #414141;
text-align: left;
+ vertical-align:top;
}
table.admin tbody th {
text-align: left;
padding: 2px;
}
-table.admin tbody td {
- vertical-align:middle;
-}
table.admin tbody td, table.admin tbody th {
color: #536C2A;
text-decoration: none;
@@ -95,20 +87,16 @@ table.admin tbody td:hover, table.admin tbody th:hover {
h2 {
border-bottom-color:#DADADA;
color:#666666;
- -x-system-font:none;
border-bottom-style:solid;
border-bottom-width:1px;
clear:both;
font-family:Georgia,"Times New Roman",Times,serif;
font-size:24px;
font-size-adjust:none;
- font-stretch:normal;
font-style:normal;
- font-variant:normal;
font-weight:normal;
- line-height:normal;
margin:5px 0pt 0pt -4px;
- padding:0pt 280px 7px 0pt;
+ padding:0pt 0px 7px 0pt;
}
p {
@@ -120,7 +108,19 @@ p {
margin:0pt 15px;
padding:0pt;
}
-
+textarea, input, select {
+ background-color:#FFFFFF;
+ border-color:#939EA5;
+ -moz-border-radius:4px;
+ -webkit-border-radius:4px;
+ border-style:solid;
+ border-width:1px;
+ margin:1px;
+ padding:3px;
+}
+input[disabled] {
+ background-color:#F7F7F7;
+}
.adminTable {
border-width: 1px;
border-style: solid;
@@ -139,8 +139,9 @@ p {
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #ccc;
- font-size: 11px;
+ font-size: 13px;
vertical-align: text-top;
+ vertical-align:top;
}
.adminTable td {
padding: 7px 15px 9px 10px;
@@ -188,3 +189,23 @@ p {
.adminTable .active {
background-color: #ECF9DD;
}
+
+.adminTable .ui-inline-help {
+ margin-top:0;
+ width:100%;
+}
+/* admin table, without borders */
+.adminTableNoBorder {
+ border:0;
+}
+.adminTableNoBorder td, .adminTableNoBorder th {
+ border:0;
+}
+
+/* other styles */
+
+.form-description {
+ color:#666666;
+ font-style:italic;
+ margin-left:10px;
+} \ No newline at end of file
diff --git a/plugins/CoreHome/Controller.php b/plugins/CoreHome/Controller.php
index 043feb8f28..853e65d4e3 100644
--- a/plugins/CoreHome/Controller.php
+++ b/plugins/CoreHome/Controller.php
@@ -23,13 +23,22 @@ class Piwik_CoreHome_Controller extends Piwik_Controller
function redirectToCoreHomeIndex()
{
- // redirect to Login only for anonymous user
- if((bool)Zend_Registry::get('config')->General->default_module_login == true
- && Piwik::getCurrentUserLogin() == 'anonymous')
+ $defaultReport = Piwik_UsersManager_API::getInstance()->getUserPreference(Piwik::getCurrentUserLogin(), Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT);
+ $module = 'CoreHome';
+ $action = 'index';
+
+ // User preference: default report to load is the All Websites dashboard
+ if($defaultReport == 'MultiSites'
+ && Piwik_PluginsManager::getInstance()->isPluginActivated('MultiSites'))
{
- return Piwik_FrontController::dispatch('Login', false);
+ $module = 'MultiSites';
}
- parent::redirectToIndex('CoreHome', 'index');
+ if($defaultReport == Piwik::getLoginPluginName())
+ {
+ $module = Piwik::getLoginPluginName();
+ }
+
+ parent::redirectToIndex($module, $action);
}
public function showInContext()
@@ -37,7 +46,6 @@ class Piwik_CoreHome_Controller extends Piwik_Controller
$controllerName = Piwik_Common::getRequestVar('moduleToLoad');
$actionName = Piwik_Common::getRequestVar('actionToLoad', 'index');
$view = $this->getDefaultIndexView();
- $view->basicHtmlView = true;
$view->content = Piwik_FrontController::getInstance()->fetchDispatch( $controllerName, $actionName );
echo $view->render();
}
@@ -51,8 +59,33 @@ class Piwik_CoreHome_Controller extends Piwik_Controller
return $view;
}
+ protected function setDateTodayIfWebsiteCreatedToday()
+ {
+ $date = Piwik_Common::getRequestVar('date', false);
+ if($date == 'today')
+ {
+ return;
+ }
+ $websiteId = Piwik_Common::getRequestVar('idSite', false);
+ if ($websiteId) {
+ $website = new Piwik_Site($websiteId);
+ $datetimeCreationDate = $this->site->getCreationDate()->getDatetime();
+ $creationDateLocalTimezone = Piwik_Date::factory($datetimeCreationDate, $website->getTimezone())->toString('Y-m-d');
+ $todayLocalTimezone = Piwik_Date::factory('now', $website->getTimezone())->toString('Y-m-d');
+ if( $creationDateLocalTimezone == $todayLocalTimezone )
+ {
+ Piwik::redirectToModule( 'CoreHome', 'index',
+ array( 'date' => 'today',
+ 'idSite' => $websiteId,
+ 'period' => Piwik_Common::getRequestVar('period'))
+ );
+ }
+ }
+ }
+
public function index()
{
+ $this->setDateTodayIfWebsiteCreatedToday();
$view = $this->getDefaultIndexView();
echo $view->render();
}
diff --git a/plugins/CoreHome/CoreHome.php b/plugins/CoreHome/CoreHome.php
index 8fd24df88e..7fb831ce9d 100644
--- a/plugins/CoreHome/CoreHome.php
+++ b/plugins/CoreHome/CoreHome.php
@@ -19,11 +19,10 @@ class Piwik_CoreHome extends Piwik_Plugin
public function getInformation()
{
return array(
- 'name' => 'Homepage',
- 'description' => 'Web Analytics Reports Structure.',
+ 'description' => Piwik_Translate('CoreHome_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
}
}
diff --git a/plugins/CoreHome/templates/broadcast.js b/plugins/CoreHome/templates/broadcast.js
index 1a2d67383c..74d1149ee3 100644
--- a/plugins/CoreHome/templates/broadcast.js
+++ b/plugins/CoreHome/templates/broadcast.js
@@ -19,6 +19,8 @@ broadcast.init = function() {
// Initialize history plugin.
// The callback is called at once by present location.hash
$.historyInit(broadcast.pageload);
+
+ piwikHelper.showAjaxLoading();
}
/************************************************
@@ -61,16 +63,23 @@ broadcast.propagateAjax = function (ajaxUrl)
// available in global scope
var currentHashStr = window.location.hash;
- // Because $.history plugin doens't care about # or ? sign infront of the query string
- // We take it out if exist;
+ // Because $.history plugin doesn't care about # or ? sign in front of the query string
+ // We take it out if it exists
currentHashStr = currentHashStr.replace(/^\?|^#/,'');
ajaxUrl = ajaxUrl.replace(/^\?|&#/,'');
var params_vals = ajaxUrl.split("&");
- for( var i=0; i<params_vals.length; i++ ) {
- currentHashStr = broadcast.updateParamValue(params_vals[i],currentHashStr);
+ for( var i=0; i<params_vals.length; i++ )
+ {
+ currentHashStr = broadcast.updateParamValue(params_vals[i],currentHashStr);
}
+ // if the module is not 'Goals', we specifically unset the 'idGoal' parameter
+ // this is to ensure that the URLs are clean (and that clicks on graphs work as expected - they are broken with the extra parameter)
+ if(broadcast.getParamValue('action', currentHashStr) != 'goalReport')
+ {
+ currentHashStr = broadcast.updateParamValue('idGoal=', currentHashStr);
+ }
// Let history know about this new Hash and load it.
$.historyLoad(currentHashStr);
};
@@ -106,7 +115,10 @@ broadcast.propagateNewPage = function (str)
for( var i=0; i<params_vals.length; i++ ) {
// update both the current search query and hash string
currentSearchStr = broadcast.updateParamValue(params_vals[i],currentSearchStr);
- currentHashStr = broadcast.updateParamValue(params_vals[i],currentHashStr);
+
+ if(currentHashStr.length != 0 ) {
+ currentHashStr = broadcast.updateParamValue(params_vals[i],currentHashStr);
+ }
}
// Now load the new page.
@@ -135,12 +147,17 @@ broadcast.updateParamValue = function(newParamValue,urlStr)
var paramName = p_v[0];
var valFromUrl = broadcast.getParamValue(paramName,urlStr);
-
+ // if set 'idGoal=' then we remove the parameter from the URL automatically (rather than passing an empty value)
+ var paramValue = p_v[1];
+ if(paramValue == '')
+ {
+ newParamValue = '';
+ }
if( valFromUrl != '') {
// replacing current param=value to newParamValue;
var regToBeReplace = new RegExp(paramName + '=' + valFromUrl, 'ig');
urlStr = urlStr.replace( regToBeReplace, newParamValue );
- } else {
+ } else if(newParamValue != '') {
urlStr += (urlStr == '') ? newParamValue : '&' + newParamValue;
}
@@ -154,8 +171,7 @@ broadcast.loadAjaxContent = function(urlAjax)
{
urlAjax = urlAjax.match(/^\?/) ? urlAjax : "?" + urlAjax;
- // showing loading...
- $('#loadingPiwik').show();
+ piwikHelper.showAjaxLoading();
$('#content').hide();
$("object").remove();
@@ -164,21 +180,21 @@ broadcast.loadAjaxContent = function(urlAjax)
function sectionLoaded(content)
{
- if(content.substring(0, 14) == '<!DOCTYPE html') {
- window.location.reload();
- return;
- }
+ if(content.substring(0, 14) == '<!DOCTYPE html') {
+ window.location.reload();
+ return;
+ }
if(urlAjax == broadcast.lastUrlRequested) {
- $('#content').html( content ).show();
- $('#loadingPiwik').hide();
- broadcast.lastUrlRequested = null;
- }
+ $('#content').html( content ).show();
+ piwikHelper.hideAjaxLoading();
+ broadcast.lastUrlRequested = null;
+ }
}
- piwikMenu.activateMenu(
- broadcast.getParamValue('module', urlAjax),
- broadcast.getParamValue('action', urlAjax),
- broadcast.getParamValue('idGoal', urlAjax)
+ piwikMenu.activateMenu(
+ broadcast.getParamValue('module', urlAjax),
+ broadcast.getParamValue('action', urlAjax),
+ broadcast.getParamValue('idGoal', urlAjax)
);
ajaxRequest = {
type: 'GET',
diff --git a/plugins/CoreHome/templates/calendar.js b/plugins/CoreHome/templates/calendar.js
index 43f35f0110..506f994e00 100644
--- a/plugins/CoreHome/templates/calendar.js
+++ b/plugins/CoreHome/templates/calendar.js
@@ -1,22 +1,20 @@
-
Date.prototype.getWeek = function() {
-var onejan = new Date(this.getFullYear(),0,1);
-return Math.ceil((((this - onejan) / 86400000) + onejan.getDay())/7);
+ var onejan = new Date(this.getFullYear(),0,1);
+ return Math.ceil((((this - onejan) / 86400000) + onejan.getDay())/7);
}
var splitDate = piwik.currentDateString.split("-");
-
var currentYear = splitDate[0];
var currentMonth = splitDate[1] - 1;
var currentDay = splitDate[2];
-
var currentDate = new Date(currentYear, currentMonth, currentDay);
+
var todayDate = new Date;
var todayMonth = todayDate.getMonth();
var todayYear = todayDate.getFullYear();
var todayDay = todayDate.getDate();
-function isDateSelected( date )
+function highlightCurrentPeriod( date )
{
var valid = false;
@@ -25,21 +23,16 @@ function isDateSelected( date )
var dateDay = date.getDate();
var style = '';
- if( date.toLocaleDateString() == todayDate.toLocaleDateString())
- {
- style = style + 'dateToday ';
- }
-
- // we dont color dates in the future
+ // we don't color dates in the future
if( dateMonth == todayMonth
&& dateYear == todayYear
&& dateDay >= todayDay
)
{
- return [true, style];
+ return [true, ''];
}
- // we dont color dates before the minimum date
+ // we don't color dates before the minimum date
if( dateYear < piwik.minDateYear
|| ( dateYear == piwik.minDateYear
&&
@@ -51,7 +44,7 @@ function isDateSelected( date )
)
)
{
- return [true, style];
+ return [true, ''];
}
// we color all day of the month for the same year for the month period
@@ -87,67 +80,85 @@ function isDateSelected( date )
if(valid)
{
- return [true, style+'dateUsedStats'];
+ return [true, 'ui-datepicker-current-period'];
}
- return [true, style];
-}
-
-function updateDate()
-{
- var date = formatDate(popUpCal.getDateFor($('#calendar')[0]));
- // Let broadcast do it job:
- // It will replace date value to both search query and hash and load the new page.
- broadcast.propagateNewPage('date='+date);
+ return [true, ''];
}
-function formatDate(date)
+function updateDate(dateText, inst)
{
- var day = date.getDate();
- var month = date.getMonth() + 1;
- return date.getFullYear() + '-'
- + (month < 10 ? '0' : '') + month + '-'
- + (day < 10 ? '0' : '') + day ;
+ var date = dateText;
+ // Let broadcast do its job:
+ // It will replace date value to both search query and hash and load the new page.
+ broadcast.propagateNewPage('date=' + date);
}
$(document).ready(function(){
-
- $("#calendar").calendar({
- onSelect: updateDate,
- showOtherMonths: true,
- dateFormat: 'DMY-',
- firstDay: 1,
- minDate: new Date(piwik.minDateYear, piwik.minDateMonth - 1, piwik.minDateDay),
- maxDate: new Date(piwik.maxDateYear, piwik.maxDateMonth - 1, piwik.maxDateDay),
- changeFirstDay: false,
- prevText: "",
- nextText: "",
- currentText: "",
- customDate: isDateSelected,
- dayNames: [
- _pk_translate('CoreHome_DaySu_js'),
- _pk_translate('CoreHome_DayMo_js'),
- _pk_translate('CoreHome_DayTu_js'),
- _pk_translate('CoreHome_DayWe_js'),
- _pk_translate('CoreHome_DayTh_js'),
- _pk_translate('CoreHome_DayFr_js'),
- _pk_translate('CoreHome_DaySa_js')],
- monthNames: [
- _pk_translate('CoreHome_MonthJanuary_js'),
- _pk_translate('CoreHome_MonthFebruary_js'),
- _pk_translate('CoreHome_MonthMarch_js'),
- _pk_translate('CoreHome_MonthApril_js'),
- _pk_translate('CoreHome_MonthMay_js'),
- _pk_translate('CoreHome_MonthJune_js'),
- _pk_translate('CoreHome_MonthJuly_js'),
- _pk_translate('CoreHome_MonthAugust_js'),
- _pk_translate('CoreHome_MonthSeptember_js'),
- _pk_translate('CoreHome_MonthOctober_js'),
- _pk_translate('CoreHome_MonthNovember_js'),
- _pk_translate('CoreHome_MonthDecember_js')]
- },
- currentDate);
-
- $("#calendar").hide();
- }
-);
+ $('#datepicker').datepicker({
+ onSelect: updateDate,
+ showOtherMonths: false,
+ dateFormat: 'yy-mm-dd',
+ firstDay: 1,
+ minDate: new Date(piwik.minDateYear, piwik.minDateMonth - 1, piwik.minDateDay),
+ maxDate: new Date(piwik.maxDateYear, piwik.maxDateMonth - 1, piwik.maxDateDay),
+ prevText: "",
+ nextText: "",
+ currentText: "",
+ beforeShowDay: highlightCurrentPeriod,
+ defaultDate: currentDate,
+ changeMonth: true,
+ changeYear: true,
+ // jquery-ui-i18n 1.7.2 lacks some translations, so we use our own
+ dayNamesMin: [
+ _pk_translate('CoreHome_DaySu_js'),
+ _pk_translate('CoreHome_DayMo_js'),
+ _pk_translate('CoreHome_DayTu_js'),
+ _pk_translate('CoreHome_DayWe_js'),
+ _pk_translate('CoreHome_DayTh_js'),
+ _pk_translate('CoreHome_DayFr_js'),
+ _pk_translate('CoreHome_DaySa_js')],
+ dayNamesShort: [
+ _pk_translate('CoreHome_ShortDay_1_js'),
+ _pk_translate('CoreHome_ShortDay_2_js'),
+ _pk_translate('CoreHome_ShortDay_3_js'),
+ _pk_translate('CoreHome_ShortDay_4_js'),
+ _pk_translate('CoreHome_ShortDay_5_js'),
+ _pk_translate('CoreHome_ShortDay_6_js'),
+ _pk_translate('CoreHome_ShortDay_7_js')],
+ dayNames: [
+ _pk_translate('CoreHome_LongDay_1_js'),
+ _pk_translate('CoreHome_LongDay_2_js'),
+ _pk_translate('CoreHome_LongDay_3_js'),
+ _pk_translate('CoreHome_LongDay_4_js'),
+ _pk_translate('CoreHome_LongDay_5_js'),
+ _pk_translate('CoreHome_LongDay_6_js'),
+ _pk_translate('CoreHome_LongDay_7_js')],
+ monthNamesShort: [
+ _pk_translate('CoreHome_ShortMonth_1_js'),
+ _pk_translate('CoreHome_ShortMonth_2_js'),
+ _pk_translate('CoreHome_ShortMonth_3_js'),
+ _pk_translate('CoreHome_ShortMonth_4_js'),
+ _pk_translate('CoreHome_ShortMonth_5_js'),
+ _pk_translate('CoreHome_ShortMonth_6_js'),
+ _pk_translate('CoreHome_ShortMonth_7_js'),
+ _pk_translate('CoreHome_ShortMonth_8_js'),
+ _pk_translate('CoreHome_ShortMonth_9_js'),
+ _pk_translate('CoreHome_ShortMonth_10_js'),
+ _pk_translate('CoreHome_ShortMonth_11_js'),
+ _pk_translate('CoreHome_ShortMonth_12_js')],
+ monthNames: [
+ _pk_translate('CoreHome_MonthJanuary_js'),
+ _pk_translate('CoreHome_MonthFebruary_js'),
+ _pk_translate('CoreHome_MonthMarch_js'),
+ _pk_translate('CoreHome_MonthApril_js'),
+ _pk_translate('CoreHome_MonthMay_js'),
+ _pk_translate('CoreHome_MonthJune_js'),
+ _pk_translate('CoreHome_MonthJuly_js'),
+ _pk_translate('CoreHome_MonthAugust_js'),
+ _pk_translate('CoreHome_MonthSeptember_js'),
+ _pk_translate('CoreHome_MonthOctober_js'),
+ _pk_translate('CoreHome_MonthNovember_js'),
+ _pk_translate('CoreHome_MonthDecember_js')]
+ });
+});
diff --git a/plugins/CoreHome/templates/cloud.tpl b/plugins/CoreHome/templates/cloud.tpl
index 18d24c1e7e..b05a8db239 100644
--- a/plugins/CoreHome/templates/cloud.tpl
+++ b/plugins/CoreHome/templates/cloud.tpl
@@ -1,12 +1,12 @@
<div id="{$properties.uniqueId}">
<div class="tagCloud">
{if count($cloudValues) == 0}
- <div id="emptyDatatable">{'General_NoDataForTagCloud'|translate}</div>
+ <div class="pk-emptyDataTable">{'General_NoDataForTagCloud'|translate}</div>
{else}
{foreach from=$cloudValues key=word item=value}
<span title="{$value.word} ({$value.value} {$columnTranslation})" class="word size{$value.size} {* we strike tags with 0 hits *} {if $value.value == 0}valueIsZero{/if}">
{if false !== $labelMetadata[$value.word].url}<a href="{$labelMetadata[$value.word].url}" target="_blank">{/if}
- {if false !== $labelMetadata[$value.word].logo}<img src="{$labelMetadata[$value.word].logo}" width="{$value.logoWidth}">{else}
+ {if false !== $labelMetadata[$value.word].logo}<img src="{$labelMetadata[$value.word].logo}" width="{$value.logoWidth}" />{else}
{$value.wordTruncated}{/if}{if false !== $labelMetadata[$value.word].url}</a>{/if}</span>
{/foreach}
{/if}
diff --git a/plugins/CoreHome/templates/datatable.css b/plugins/CoreHome/templates/datatable.css
index 48fcf6824f..47f89df30e 100644
--- a/plugins/CoreHome/templates/datatable.css
+++ b/plugins/CoreHome/templates/datatable.css
@@ -1,3 +1,4 @@
+
/*Overriding some dataTable css for better dashboard display*/
.widget .dataTableWrapper,
.widget .dataTableAllColumnsWrapper,
@@ -52,6 +53,7 @@ table.dataTable td.label,
table.subDataTable td.label,
table.dataTableActions td.label {
width: 100%;
+ white-space:nowrap;
}
table.dataTable img,
@@ -81,6 +83,15 @@ table.dataTable th {
background: #D4E3ED url(images/bg_header.jpg) repeat-x;
}
+table.dataTable th.first {
+ -moz-border-radius:6px 0 0 0;
+ -webkit-border-radius:6px 0 0 0;
+}
+
+table.dataTable th.last {
+ -moz-border-radius:0 6px 0 0;
+ -webkit-border-radius:0 6px 0 0;
+}
table.dataTable th.columnSorted {
font-weight: bold;
padding-right: 20px;
@@ -208,85 +219,86 @@ table thead div {
position: absolute;
}
-#dataTablePages {
+.dataTablePages {
color: #BFBFBF;
font-weight: bold;
margin: 10px;
font-size: 0.9em;
}
-#dataTableSearchPattern {
+.dataTableSearchPattern {
display: inline;
white-space: nowrap;
}
-#dataTableSearchPattern input {
+.dataTableSearchPattern input {
font-size: 0.7em;
padding: 2px;
border: 1px solid #B3B3B3;
color: #0C183A;
}
-#dataTableSearchPattern input:hover {
+.dataTableSearchPattern input:hover {
background: #F7F7FF none repeat scroll 0%;
}
-#dataTableSearchPattern #keyword {
+.dataTableSearchPattern #keyword {
background: transparent url(images/search.png) no-repeat scroll 4px
center;
padding: 3px 3px 3px 20px;
}
-#dataTableExcludeLowPopulation,#dataTableNext,#dataTablePrevious {
+.dataTableExcludeLowPopulation,.dataTableNext,.dataTablePrevious {
font-size: 0.9em;
color: #184A83;
text-decoration: underline;
cursor: pointer;
}
-.subDataTable#dataTableFeatures {
+/* @todo are these supposed to be together? */
+.subDataTable.dataTableFeatures {
padding-top: 0px;
padding-bottom: 5px;
width: 100%;
}
-#dataTableFeatures {
+.dataTableFeatures {
padding-top: 10px;
padding-bottom: 10px;
width: 100%;
text-align: center;
}
-#dataTableExcludeLowPopulation {
+.dataTableExcludeLowPopulation {
float: right;
font-size: 0.8em;
color: #C3C6D8;
text-align: right;
}
-#dataTableNext,#dataTablePrevious,#dataTableSearchPattern,#loadingDataTable
+.dataTableNext,.dataTablePrevious,.dataTableSearchPattern,.pk-loadingDataTable
{
display: none;
}
-.subDataTable #dataTableFooterIcons {
+.subDataTable .dataTableFooterIcons {
height: 0px;
}
-#dataTableFooterIcons {
+.dataTableFooterIcons {
float: right;
height: 18px;
}
-#exportToFormat {
+.exportToFormatIcons {
float: right;
}
-#dataTableFooterIconsShow {
+.dataTableFooterIconsShow {
float: right;
}
-#dataTableFooterIcons,#dataTableFooterIcons a {
+.dataTableFooterIcons,.dataTableFooterIcons a {
text-decoration: none;
color: #8894B1;
font-size:0.9em;
@@ -296,7 +308,7 @@ table thead div {
clear: both;
}
-#loadingDataTable {
+.pk-loadingDataTable {
float: left;
font-size: 0.9em;
color: #193B6C;
@@ -308,6 +320,7 @@ table.dataTableActions tr td.labelodd {
background-image: none;
}
+
/* levels higher than 4 have a default padding left */
tr.subActionsDataTable td.label,tr.actionsDataTable td.label {
padding-left: 7em;
@@ -318,27 +331,32 @@ tr.level0 td.label {
}
tr.level1 td.label {
- padding-left: +3.5em;
+ padding-left: +2.5em;
}
tr.level2 td.label {
- padding-left: +5.5em;
+ padding-left: +3.5em;
}
tr.level3 td.label {
- padding-left: +6.5em;
+ padding-left: +4.5em;
}
tr.level4 td.label {
- padding-left: +7em;
+ padding-left: +5em;
}
+/* less right margins for the link image in the Pa*/
+table.dataTableActions img.link {
+ margin-right: 0.3em;
+ margin-left:-0.5em;
+}
tr td.label img.plusMinus {
- margin-left: -1em;
margin-right: 0em;
+ margin-left:-1em;
}
-#emptyDatatable {
+.pk-emptyDataTable {
padding-top: 20px;
padding-bottom: 10px;
text-align: center;
diff --git a/plugins/CoreHome/templates/datatable.js b/plugins/CoreHome/templates/datatable.js
index 3de4c8fb22..75c11a62ad 100644
--- a/plugins/CoreHome/templates/datatable.js
+++ b/plugins/CoreHome/templates/datatable.js
@@ -131,7 +131,7 @@ dataTable.prototype =
// Function called to trigger the AJAX request
// The ajax request contains the function callback to trigger if the request is successful or failed
- // displayLoading = false When we don't want to display the Loading... DIV #loadingDataTable
+ // displayLoading = false When we don't want to display the Loading... DIV .pk-loadingDataTable
// for example when the script add a Loading... it self and doesn't want to display the generic Loading
reloadAjaxDataTable: function(displayLoading, callbackSuccess)
{
@@ -148,7 +148,7 @@ dataTable.prototype =
if(displayLoading)
{
- $('#'+self.workingDivId+' #loadingDataTable').css('display','block');
+ $('#'+self.workingDivId+' .pk-loadingDataTable').last().css('display','block');
}
$.ajax(self.buildAjaxRequest(callbackSuccess));
@@ -170,14 +170,15 @@ dataTable.prototype =
{
// we add class to the table so that we can give a different style to the subtable
$(content).find('table.dataTable').addClass('subDataTable');
- $(content).find('#dataTableFeatures').addClass('subDataTable');
+ $(content).find('.dataTableFeatures').addClass('subDataTable');
//we force the initialisation of subdatatables
- dataTableSel.html( $(content).html() );
+ dataTableSel.html( $(content) );
}
else
{
- dataTableSel.html( $(content).html() );
+ dataTableSel.find('object').remove();
+ dataTableSel.html( $(content) );
piwikHelper.lazyScrollTo(dataTableSel[0], 400);
}
},
@@ -204,10 +205,52 @@ dataTable.prototype =
self.handleLowPopulationLink(domElem);
self.handleOffsetInformation(domElem);
self.handleExportBox(domElem);
+ self.handleLinkedRows(domElem);
self.applyCosmetics(domElem);
self.handleSubDataTable(domElem);
},
+ handleLinkedRows: function(domElem)
+ {
+ var self = this;
+
+ var urlLinkFoundDom = $("tr td:first-child:has('.urlLink')", domElem);
+ if(urlLinkFoundDom.length == 0)
+ {
+ self.truncate( $("table tr td:first-child", domElem) );
+ }
+ else
+ {
+ urlLinkFoundDom.each( function(){
+ // we add a link based on the <span id="urlLink"> present in the column label (the first column)
+ // if this span is there, we add the link around the HTML in the TD
+ // but we add this link only for the rows that are not clickable already (subDataTable)
+ var imgToPrepend = '';
+ if( $(this).find('img').length == 0 )
+ {
+ var imageLinkWidth = 10;
+ var imageLinkHeight = 9;
+ imgToPrepend = '<img class="link" width="'+imageLinkWidth+'" height="'+imageLinkHeight+'" src="themes/default/images/link.gif" /> ';
+ }
+ var urlLinkDom = $('.urlLink',this);
+ var urlToLink = $(urlLinkDom).html();
+ $(urlLinkDom).remove();
+
+ var truncationOffsetBecauseImageIsPrepend = -2; //website subtable needs -9.
+
+ self.truncate( $(this), truncationOffsetBecauseImageIsPrepend );
+ if( urlToLink.match("javascript:") )
+ {
+ $(this).prepend(imgToPrepend).wrapInner('<a href="#" onclick="' + urlToLink.replace("javascript:","") + '"></a>');
+ }
+ else
+ {
+ $(this).prepend(imgToPrepend).wrapInner('<a target="_blank" href="' + urlToLink + '"></a>');
+ }
+ });
+ }
+ },
+
// if sorting the columns is enabled, when clicking on a column,
// - if this column was already the one used for sorting, we revert the order desc<->asc
// - we send the ajax request with the new sorting information
@@ -239,7 +282,13 @@ dataTable.prototype =
$(".sortable#"+self.param.filter_sort_column+' #thDIV', domElem).parent()
.addClass('columnSorted')
.prepend('<div id="sortIconContainer"><img id="sortIcon" width="'+imageSortWidth+'" height="'+imageSortHeight+'" src="themes/default/images/sort'+prefixSortIcon+ self.param.filter_sort_order+'.png" /></div>');
- }
+
+
+ $("th.sortable", domElem)
+ .hover( function() { $(this).css({ cursor: "pointer"}); },
+ function() { $(this).css({ cursor: "auto"});
+ });
+ }
},
// Add behaviour to the low population link
@@ -248,7 +297,7 @@ dataTable.prototype =
var self = this;
// Set the string for the DIV, either "Exclude low pop" or "Include all"
- $('#dataTableExcludeLowPopulation', domElem)
+ $('.dataTableExcludeLowPopulation', domElem)
.each(
function()
{
@@ -301,7 +350,7 @@ dataTable.prototype =
currentPattern = '';
}
- $('#dataTableSearchPattern', domElem)
+ $('.dataTableSearchPattern', domElem)
.show()
.each(function(){
// when enter is pressed in the input field we submit the form
@@ -347,7 +396,7 @@ dataTable.prototype =
{
var target = this;
var clearImg = $('<span style="position: relative;">\
- <img src="plugins/CoreHome/templates/images/reset_search.png" style="position: absolute; top: 4px; left: -15px; cursor: pointer; display: inline;" title="Clear"/>\
+ <img src="plugins/CoreHome/templates/images/reset_search.png" style="position: absolute; top: 4px; left: -15px; cursor: pointer; display: inline;" title="Clear" />\
</span>')
.click( function() {
$('#keyword', target).val('');
@@ -365,7 +414,7 @@ dataTable.prototype =
{
var self = this;
- $('#dataTablePages', domElem).each(
+ $('.dataTablePages', domElem).each(
function(){
var offset = 1+Number(self.param.filter_offset);
var offsetEnd = Number(self.param.filter_offset) + Number(self.param.filter_limit);
@@ -384,7 +433,7 @@ dataTable.prototype =
);
// Display the next link if the total Rows is greater than the current end row
- $('#dataTableNext', domElem)
+ $('.dataTableNext', domElem)
.each(function(){
var offsetEnd = Number(self.param.filter_offset)
+ Number(self.param.filter_limit);
@@ -403,7 +452,7 @@ dataTable.prototype =
;
// Display the previous link if the current offset is not zero
- $('#dataTablePrevious', domElem)
+ $('.dataTablePrevious', domElem)
.each(function(){
var offset = 1+Number(self.param.filter_offset);
if(offset != 1)
@@ -436,18 +485,18 @@ dataTable.prototype =
}
// When the (+) image is hovered, the export buttons are displayed
- $('#dataTableFooterIconsShow', domElem)
+ $('.dataTableFooterIconsShow', domElem)
.show()
.hover( function() {
$(this).fadeOut('slow');
- $('#exportToFormat', $(this).parent()).show('slow');
+ $('.exportToFormatIcons', $(this).parent()).show('slow');
}, function(){}
);
//timeout object used to hide the datatable export buttons
var timeout = null;
- $('#dataTableFooterIcons', domElem)
+ $('.dataTableFooterIcons', domElem)
.hover( function() {
//display 'hand' cursor
$(this).css({ cursor: "pointer"});
@@ -466,8 +515,8 @@ dataTable.prototype =
//set a timeout that will hide export buttons after a few moments
var dom = this;
timeout = setTimeout(function(){
- $('#exportToFormat', dom).fadeOut('fast', function(){ //queue the two actions
- $('#dataTableFooterIconsShow', dom).show('fast');});
+ $('.exportToFormatIcons', dom).fadeOut('fast', function(){ //queue the two actions
+ $('.dataTableFooterIconsShow', dom).show('fast');});
}, 1000);
}
);
@@ -481,7 +530,7 @@ dataTable.prototype =
}
);
- $('#tableGoals', domElem)
+ $('.tableGoals', domElem)
.show()
.click(
function(){
@@ -494,7 +543,7 @@ dataTable.prototype =
}
);
- $('#tableAllColumnsSwitch', domElem)
+ $('.tableAllColumnsSwitch', domElem)
.show()
.click(
function(){
@@ -511,8 +560,8 @@ dataTable.prototype =
}
);
- $('#exportToFormat img', domElem).click(function(){
- $(this).siblings('#linksExportToFormat').toggle();
+ $('.exportToFormatIcons img', domElem).click(function(){
+ $(this).siblings('.linksExportToFormat').toggle();
});
$('.exportToFormat', domElem).attr( 'href', function(){
@@ -577,42 +626,6 @@ dataTable.prototype =
applyCosmetics: function(domElem)
{
var self = this;
-
- var urlLinkFoundDom = $("tr:not('.subDataTable') td:first-child:has('#urlLink')", domElem);
- if(urlLinkFoundDom.length == 0)
- {
- self.truncate( $("table tr td:first-child", domElem) );
- }
- else
- {
- var imageLinkWidth = 10;
- var imageLinkHeight = 9;
- urlLinkFoundDom.each( function(){
- // we add a link based on the <span id="urlLink"> present in the column label (the first column)
- // if this span is there, we add the link around the HTML in the TD
- // but we add this link only for the rows that are not clickable already (subDataTable)
- var imgToPrepend = '';
- if( $(this).find('img').length == 0 )
- {
- imgToPrepend = '<img width="'+imageLinkWidth+'" height="'+imageLinkHeight+'" src="themes/default/images/link.gif" /> ';
- }
- var urlLinkDom = $('#urlLink',this);
- var urlToLink = $(urlLinkDom).html();
- $(urlLinkDom).remove();
-
- var truncationOffsetBecauseImageIsPrepend = -2; //website subtable needs -9.
- self.truncate( $(this), truncationOffsetBecauseImageIsPrepend );
-
- if( urlToLink.match("javascript:") )
- {
- $(this).prepend(imgToPrepend).wrapInner('<a href="#" onclick="' + urlToLink.replace("javascript:","") + '"></a>');
- }
- else
- {
- $(this).prepend(imgToPrepend).wrapInner('<a target="_blank" href="' + urlToLink + '"></a>');
- }
- });
- }
// Add some styles on the cells even/odd
// label (first column of a data row) or not
@@ -622,14 +635,6 @@ dataTable.prototype =
$("tr:odd td", domElem).slice(1).addClass('columnodd');
$("tr:even td", domElem).slice(1).addClass('columneven');
- // Change cursor on mouse hover if sort is enabled
- if( self.param.enable_sort )
- {
- $("th.sortable", domElem)
- .hover( function() { $(this).css({ cursor: "pointer"}); },
- function() { $(this).css({ cursor: "auto"});
- });
- }
},
//behaviour for 'nested DataTable' (DataTable loaded on a click on a row)
@@ -656,7 +661,7 @@ dataTable.prototype =
'<tr>'+
'<td colspan="'+numberOfColumns+'" class="cellSubDataTable">'+
'<div id="'+divIdToReplaceWithSubTable+'">'+
- '<span id="loadingDataTable" style="display:inline"><img src="themes/default/images/loading-blue.gif" />'+ _pk_translate('CoreHome_Loading_js') +'</span>'+
+ '<span class="pk-loadingDataTable" style="display:inline"><img src="themes/default/images/loading-blue.gif" />'+ _pk_translate('CoreHome_Loading_js') +'</span>'+
'</div>'+
'</td>'+
'</tr>'
@@ -739,6 +744,9 @@ actionDataTable.prototype =
handleExportBox: dataTable.prototype.handleExportBox,
handleSort: dataTable.prototype.handleSort,
onClickSort: dataTable.prototype.onClickSort,
+ handleLinkedRows: dataTable.prototype.handleLinkedRows,
+ truncate: dataTable.prototype.truncate,
+ handleOffsetInformation: dataTable.prototype.handleOffsetInformation,
//initialisation of the actionDataTable
init: function(workingDivId, domElem)
@@ -778,10 +786,12 @@ actionDataTable.prototype =
self.handleExportBox(domElem);
self.handleSort(domElem);
+ self.handleLinkedRows(domElem);
+ self.handleOffsetInformation(domElem);
if( self.workingDivId != undefined)
{
- self.handleSearchBox(domElem, self.actionsDataTableLoaded );
- self.handleLowPopulationLink(domElem, self.actionsDataTableLoaded );
+ self.handleSearchBox(domElem, self.dataTableLoaded );
+ self.handleLowPopulationLink(domElem, self.dataTableLoaded );
}
},
@@ -840,8 +850,8 @@ actionDataTable.prototype =
$("td:first-child:odd", this).addClass('label labeleven');
$("td:first-child:even", this).addClass('label labelodd');
// we truncate the labels columns from the second row
- $("td:first-child", this).truncate(30);
- $('.truncated', this).tooltip();
+// $("td:first-child", this).truncate(30);
+// $('.truncated', this).tooltip();
})
.removeClass('rowToProcess');
},
@@ -875,7 +885,7 @@ actionDataTable.prototype =
$(domElem).after( '\
<tr id="'+divIdToReplaceWithSubTable+'" class="cellSubDataTable">\
<td colspan="'+numberOfColumns+'">\
- <span id="loadingDataTable" style="display:inline"><img src="themes/default/images/loading-blue.gif" /> Loading...</span>\
+ <span class="pk-loadingDataTable" style="display:inline"><img src="themes/default/images/loading-blue.gif" /> Loading...</span>\
</td>\
</tr>\
');
@@ -941,7 +951,7 @@ actionDataTable.prototype =
},
//called when the full table actions is loaded
- actionsDataTableLoaded: function(response)
+ dataTableLoaded: function(response)
{
var content = $(response);
var idToReplace = $(content).attr('id');
@@ -951,7 +961,7 @@ actionDataTable.prototype =
self.parentId = '';
var dataTableSel = $('#'+idToReplace);
- dataTableSel.html($(content).html());
+ dataTableSel.html( $(content) );
piwikHelper.lazyScrollTo(dataTableSel[0], 400);
},
@@ -976,7 +986,8 @@ actionDataTable.prototype =
}
// we execute the bindDataTableEvent function for the new DIV
- self.init(self.workingDivId, $('#'+idToReplace));
+ self.init(self.workingDivId, $('#'+self.workingDivId));
+// self.init(self.workingDivId, $('#'+idToReplace));
//bind back the click event (disabled to avoid double-click problem)
self.disabledRowDom.click(
@@ -990,7 +1001,7 @@ actionDataTable.prototype =
//helper function for actionDataTable
function getLevelFromClass( style)
{
- if (typeof style == "undefined") return 0;
+ if (!style || typeof style == "undefined") return 0;
var currentLevelIndex = style.indexOf('level');
var currentLevel = 0;
@@ -1004,7 +1015,7 @@ function getLevelFromClass( style)
//helper function for actionDataTable
function getNextLevelFromClass( style )
{
- if (typeof style == "undefined") return 0;
+ if (!style || typeof style == "undefined") return 0;
currentLevel = getLevelFromClass(style);
newLevel = currentLevel;
// if this is not a row to process so
diff --git a/plugins/CoreHome/templates/datatable.tpl b/plugins/CoreHome/templates/datatable.tpl
index 7cbdc6f2cc..56c508a151 100644
--- a/plugins/CoreHome/templates/datatable.tpl
+++ b/plugins/CoreHome/templates/datatable.tpl
@@ -4,14 +4,14 @@
{$arrayDataTable.message}
{else}
{if count($arrayDataTable) == 0}
- <div id="emptyDatatable">{'CoreHome_TableNoData'|translate}</div>
+ <div class="pk-emptyDataTable">{'CoreHome_TableNoData'|translate}</div>
{else}
<a name="{$properties.uniqueId}"></a>
<table cellspacing="0" class="dataTable">
<thead>
<tr>
- {foreach from=$dataTableColumns item=column}
- <th class="sortable" id="{$column}"><div id="thDIV">{$columnTranslations[$column]}</div></th>
+ {foreach from=$dataTableColumns item=column name=head}
+ <th class="sortable {if $smarty.foreach.head.first}first{elseif $smarty.foreach.head.last}last{/if}" id="{$column}"><div id="thDIV">{$columnTranslations[$column]}</div></th>
{/foreach}
</tr>
</thead>
@@ -21,7 +21,7 @@
<tr {if $row.idsubdatatable && $javascriptVariablesToSet.controllerActionCalledWhenRequestSubTable != null}class="subDataTable" id="{$row.idsubdatatable}"{/if}>
{foreach from=$dataTableColumns item=column}
<td>
-{if !$row.idsubdatatable && $column=='label' && isset($row.metadata.url)}<span id="urlLink">{$row.metadata.url}</span>{/if}
+{if !$row.idsubdatatable && $column=='label' && !empty($row.metadata.url)}<span class="urlLink">{$row.metadata.url}</span>{/if}
{if $column=='label'}{logoHtml metadata=$row.metadata alt=$row.columns.label}{/if}
{if isset($row.columns[$column])}{$row.columns[$column]}{else}{$defaultWhenColumnValueNotDefined}{/if}
</td>
diff --git a/plugins/CoreHome/templates/datatable_actions.tpl b/plugins/CoreHome/templates/datatable_actions.tpl
index 1ffa6b99c1..44c8a16911 100644
--- a/plugins/CoreHome/templates/datatable_actions.tpl
+++ b/plugins/CoreHome/templates/datatable_actions.tpl
@@ -4,13 +4,13 @@
{$arrayDataTable.message}
{else}
{if count($arrayDataTable) == 0}
- <div id="emptyDatatable">{'CoreHome_TableNoData'|translate}</div>
+ <div class="pk-emptyDataTable">{'CoreHome_TableNoData'|translate}</div>
{else}
<table cellspacing="0" class="dataTable dataTableActions">
<thead>
<tr>
- {foreach from=$dataTableColumns item=column}
- <th class="sortable" id="{$column}">{$columnTranslations[$column]}</td>
+ {foreach from=$dataTableColumns item=column name=head}
+ <th class="sortable {if $smarty.foreach.head.first}first{elseif $smarty.foreach.head.last}last{/if}" id="{$column}"><div id="thDIV">{if !empty($columnDescriptions[$column])}<label title='{$columnDescriptions[$column]|escape:'html'}'>{/if}{$columnTranslations[$column]|escape:'html'}{if !empty($columnDescriptions[$column])}</label>{/if}</div></td>
{/foreach}
</tr>
</thead>
@@ -20,6 +20,7 @@
<tr {if $row.idsubdatatable}class="rowToProcess subActionsDataTable" id="{$row.idsubdatatable}"{else} class="actionsDataTable rowToProcess"{/if}>
{foreach from=$dataTableColumns item=column}
<td>
+ {if !$row.idsubdatatable && $column=='label' && isset($row.metadata.url)}<span class="urlLink">{$row.metadata.url}</span>{/if}
{if isset($row.columns[$column])}{$row.columns[$column]}{else}{$defaultWhenColumnValueNotDefined}{/if}
</td>
{/foreach}
diff --git a/plugins/CoreHome/templates/datatable_actions_recursive.tpl b/plugins/CoreHome/templates/datatable_actions_recursive.tpl
index d405ea3fdc..48e98197d1 100644
--- a/plugins/CoreHome/templates/datatable_actions_recursive.tpl
+++ b/plugins/CoreHome/templates/datatable_actions_recursive.tpl
@@ -4,7 +4,7 @@
{$arrayDataTable.message}
{else}
{if count($arrayDataTable) == 0}
- <div id="emptyDatatable">{'CoreHome_TableNoData'|translate}</div>
+ <div class="pk-emptyDataTable">{'CoreHome_TableNoData'|translate}</div>
{else}
<table cellspacing="0" class="dataTable dataTableActions">
<thead>
diff --git a/plugins/CoreHome/templates/datatable_actions_subdatable.tpl b/plugins/CoreHome/templates/datatable_actions_subdatable.tpl
index 0a1ec0bb0d..dbd7b903c7 100644
--- a/plugins/CoreHome/templates/datatable_actions_subdatable.tpl
+++ b/plugins/CoreHome/templates/datatable_actions_subdatable.tpl
@@ -9,6 +9,7 @@
<tr {if $row.idsubdatatable}class="subActionsDataTable" id="{$row.idsubdatatable}"{else}class="actionsDataTable"{/if}>
{foreach from=$dataTableColumns item=column}
<td>
+ {if !$row.idsubdatatable && $column=='label' && isset($row.metadata.url)}<span class="urlLink">{$row.metadata.url}</span>{/if}
{if isset($row.columns[$column])}{$row.columns[$column]}{else}{$defaultWhenColumnValueNotDefined}{/if}
</td>
{/foreach}
diff --git a/plugins/CoreHome/templates/datatable_footer.tpl b/plugins/CoreHome/templates/datatable_footer.tpl
index 1398bed288..329a2002e9 100644
--- a/plugins/CoreHome/templates/datatable_footer.tpl
+++ b/plugins/CoreHome/templates/datatable_footer.tpl
@@ -1,36 +1,40 @@
-<div id="dataTableFeatures">
+<div class="dataTableFeatures">
{if $properties.show_exclude_low_population}
- <span id="dataTableExcludeLowPopulation"></span>
+ <span class="dataTableExcludeLowPopulation"></span>
+{/if}
+
+{if $properties.show_offset_information}
+<div>
+ <span class="dataTablePages"></span>
+ <span class="dataTablePrevious">&lsaquo; {'General_Previous'|translate}</span>
+ <span class="dataTableNext">{'General_Next'|translate} &rsaquo;</span>
+</div>
{/if}
{if $properties.show_search}
-<span id="dataTableSearchPattern">
+<span class="dataTableSearchPattern">
<input id="keyword" type="text" length="15" />
<input type="submit" value="{'General_Search'|translate}" />
</span>
{/if}
-{if $properties.show_offset_information}
- <span id="dataTablePages"></span>
- <span id="dataTablePrevious">&lsaquo; {'General_Previous'|translate}</span>
- <span id="dataTableNext">{'General_Next'|translate} &rsaquo;</span>
-{/if}
{if $properties.show_footer_icons}
<div>
- <span id="dataTableFooterIcons">
- <span id="exportToFormat" style="display:none;padding-left:4px;">
+ <span class="dataTableFooterIcons">
+ <span class="exportToFormatIcons" style="display:none;padding-left:4px;">
{if $properties.show_export_as_image_icon}
<span id="dataTableFooterExportAsImageIcon">
<a href="javascript:piwikHelper.OFC.jquery.popup('{$chartDivId}');"><img title="{'General_ExportAsImage_js'|translate}" src="themes/default/images/image.png" /></a>
</span>
{/if}
<img width="16" height="16" src="themes/default/images/export.png" title="{'General_Export'|translate}" />
- <span id="linksExportToFormat" style="display:none">
+ <span class="linksExportToFormat" style="display:none">
<a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="CSV" filter_limit="100">CSV</a> |
+ <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="TSV" filter_limit="100">TSV (Excel)</a> |
<a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="XML" filter_limit="100">XML</a> |
<a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="JSON" filter_limit="100">Json</a> |
<a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="PHP" filter_limit="100">Php</a> |
- <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="RSS" filter_limit="100" date="last10"><img border="0" src="themes/default/images/feed.png"></a>
+ <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="RSS" filter_limit="100" date="last10"><img border="0" src="themes/default/images/feed.png" /></a>
</span>
{if $properties.show_all_views_icons}
<a class="viewDataTable" format="cloud"><img width="16" height="16" src="themes/default/images/tagcloud.png" title="{'General_TagCloud'|translate}" /></a>
@@ -38,12 +42,12 @@
<a class="viewDataTable" format="graphPie"><img width="16" height="16" src="themes/default/images/chart_pie.png" title="{'General_Piechart'|translate}" /></a>
{/if}
</span>
- <span id="dataTableFooterIconsShow" style="display:none;padding-left:4px;">
+ <span class="dataTableFooterIconsShow" style="display:none;padding-left:4px;">
<img src="plugins/CoreHome/templates/images/more.png" />
</span>
{if $properties.show_table}
- <span id="tableAllColumnsSwitch" style="display:none;float:right;padding-right:4px;border-right:1px solid #82A1D2;">
+ <span class="tableAllColumnsSwitch" style="display:none;float:right;padding-right:4px;border-right:1px solid #82A1D2;">
{if $javascriptVariablesToSet.viewDataTable != 'table'}
<img title="{'General_DisplayNormalTable'|translate}" src="themes/default/images/table.png" />
{elseif $properties.show_table_all_columns}
@@ -53,9 +57,9 @@
{/if}
{if $properties.show_goals}
- <span id="tableGoals" style="display:none;float:right;padding-right:4px;">
+ <span class="tableGoals" style="display:none;float:right;padding-right:4px;">
{if $javascriptVariablesToSet.viewDataTable != 'tableGoals'}
- <img title="View Goals" src="themes/default/images/goal.png" />
+ <img title="{'General_DisplayGoals'|translate}" src="themes/default/images/goal.png" />
{/if}
</span>
{/if}
@@ -63,7 +67,7 @@
</div>
{/if}
-<span id="loadingDataTable"><img src="themes/default/images/loading-blue.gif" /> {'General_LoadingData'|translate}</span>
+<span class="pk-loadingDataTable"><img src="themes/default/images/loading-blue.gif" /> {'General_LoadingData'|translate}</span>
</div>
<div class="dataTableSpacer" />
diff --git a/plugins/CoreHome/templates/date.js b/plugins/CoreHome/templates/date.js
index 7ca90166a6..4b33793a55 100644
--- a/plugins/CoreHome/templates/date.js
+++ b/plugins/CoreHome/templates/date.js
@@ -1,7 +1,7 @@
$(document).ready(function(){
$("#periodString").hide();
$("#otherPeriods").hide();
- $("#calendar").hide();
+ $("#datepicker").hide();
$("#periodString").show();
// we get the content of the div before modifying it (append image, etc.)
@@ -54,7 +54,7 @@ $(document).ready(function(){
{
$("#currentPeriod:not(.hoverPeriod)")
.addClass("hoverPeriod")
- .append('&nbsp;<img src="plugins/CoreHome/templates/images/more_period.gif" style="vertical-align:middle">');
+ .append('&nbsp;<img src="plugins/CoreHome/templates/images/more_period.gif" style="vertical-align:middle" />');
}
}, function(){
restoreCurrentPeriod();
@@ -83,6 +83,10 @@ $(document).ready(function(){
})
.click(function(){
- $("#calendar").toggle();
+ $("#datepicker").toggle();
+ if($("#datepicker").is(":visible"))
+ {
+ $("#datepicker .ui-state-highlight").removeClass('ui-state-highlight');
+ }
});
} );
diff --git a/plugins/CoreHome/templates/graph.tpl b/plugins/CoreHome/templates/graph.tpl
index ff4f282a1b..eab4ef04f5 100644
--- a/plugins/CoreHome/templates/graph.tpl
+++ b/plugins/CoreHome/templates/graph.tpl
@@ -7,6 +7,9 @@
</div></div>
<script type="text/javascript">
<!--
+ {if $flashParameters.includeData}
+ piwikHelper.OFC.set("{$chartDivId}", '{$flashParameters.data}');
+ {/if}
swfobject.embedSWF(
"{$flashParameters.ofcLibraryPath}open-flash-chart.swf?{$tag}",
"{$chartDivId}",
@@ -14,10 +17,10 @@
"{$flashParameters.requiredFlashVersion}",
"{$flashParameters.swfLibraryPath}expressInstall.swf",
{literal}{{/literal}
+ "{if $flashParameters.includeData}x-{/if}data-file":"{$urlGraphData|escape:"url"}",
{if $flashParameters.includeData}
"id":"{$chartDivId}",
{/if}
- "{if $flashParameters.includeData}x-{/if}data-file":"{$urlGraphData|escape:"url"}",
"loading":"{'General_Loading'|translate|escape:"html"}"
{literal}},
{{/literal}
@@ -28,9 +31,6 @@
"bgcolor":"#FFFFFF"
{literal}}{/literal}
);
- {if $flashParameters.includeData}
- piwikHelper.OFC.set("{$chartDivId}", '{$flashParameters.data}');
- {/if}
//-->
</script>
{else}
diff --git a/plugins/CoreHome/templates/header.tpl b/plugins/CoreHome/templates/header.tpl
index d88d17ac95..9fbb3f6a95 100644
--- a/plugins/CoreHome/templates/header.tpl
+++ b/plugins/CoreHome/templates/header.tpl
@@ -1,7 +1,15 @@
-<div id="header">
-{include file="CoreHome/templates/header_message.tpl"}
-{include file="CoreHome/templates/logo.tpl"}
-{include file="CoreHome/templates/period_select.tpl"}
-{include file="CoreHome/templates/js_disabled_notice.tpl"}
-</div>
-<br />
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Piwik &rsaquo; {'CoreHome_WebAnalyticsReports'|translate}</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Piwik {$piwik_version}" />
+<link rel="shortcut icon" href="plugins/CoreHome/templates/images/favicon.ico" />
+{loadJavascriptTranslations plugins='CoreHome'}
+{include file="CoreHome/templates/js_global_variables.tpl"}
+{include file="CoreHome/templates/js_css_includes.tpl"}
+</head>
+<body>
+{include file="CoreHome/templates/top_bar.tpl"}
+{include file="CoreHome/templates/top_screen.tpl"}
diff --git a/plugins/CoreHome/templates/header_message.tpl b/plugins/CoreHome/templates/header_message.tpl
index 2a5f3a5ee6..2fca652693 100644
--- a/plugins/CoreHome/templates/header_message.tpl
+++ b/plugins/CoreHome/templates/header_message.tpl
@@ -1,10 +1,14 @@
<span id="header_message">
-{if $piwikUrl == 'http://piwik.org/demo/'}
+{if $piwikUrl == 'http://piwik.org/demo/'}
{'General_YouAreCurrentlyViewingDemoOfPiwik'|translate:"<a target='_blank' href='http://piwik.org'>Piwik</a>":"<a href='http://piwik.org/'>":"</a>":"<a href='http://piwik.org'>piwik.org</a>"}
{elseif $latest_version_available}
- <img src='themes/default/images/warning_small.png' alt='' style="vertical-align: middle;">
- {'General_PiwikXIsAvailablePleaseUpdateNow'|translate:$latest_version_available:"<br /><a href='index.php?module=CoreUpdater&action=newVersionAvailable'>":"</a>":"<a href='misc/redirectToUrl.php?url=http://piwik.org/changelog/' target='_blank'>":"</a>"}
+ <img src='themes/default/images/warning_small.png' alt='' style="vertical-align: middle;" />
+ {if $isSuperUser}
+ {'General_PiwikXIsAvailablePleaseUpdateNow'|translate:$latest_version_available:"<br /><a href='index.php?module=CoreUpdater&action=newVersionAvailable'>":"</a>":"<a href='misc/redirectToUrl.php?url=http://piwik.org/changelog/' target='_blank'>":"</a>"}
+ {else}
+ {'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin'|translate:"<a href='misc/redirectToUrl.php?url=http://piwik.org/' target='_blank'>Piwik</a> <a href='misc/redirectToUrl.php?url=http://piwik.org/changelog/' target='_blank'>$latest_version_available</a>"}
+ {/if}
{else}
- {'General_PiwikIsACollaborativeProjectYouCanContribute'|translate:"<a href='misc/redirectToUrl.php?url=http://piwik.org'>":"$piwik_version</a>":"<br />":"<a target='_blank' href='misc/redirectToUrl.php?url=http://piwik.org/contribute/'>":"</a>"}
+ {'General_PiwikIsACollaborativeProjectYouCanContribute'|translate:"<a href='misc/redirectToUrl.php?url=http://piwik.org'>":"$piwik_version</a>":"<br />":"<a target='_blank' href='misc/redirectToUrl.php?url=http://piwik.org/contribute/'>":"</a>"}
{/if}
</span>
diff --git a/plugins/CoreHome/templates/index.tpl b/plugins/CoreHome/templates/index.tpl
index 6c34885895..cba7cbed4d 100644
--- a/plugins/CoreHome/templates/index.tpl
+++ b/plugins/CoreHome/templates/index.tpl
@@ -1,24 +1,13 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>Piwik &rsaquo; Web Analytics Reports</title>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="generator" content="Piwik {$piwik_version}" />
-<link rel="shortcut icon" href="plugins/CoreHome/templates/images/favicon.ico" />
-{loadJavascriptTranslations plugins='CoreHome'}
-{include file="CoreHome/templates/js_global_variables.tpl"}
-{include file="CoreHome/templates/js_css_includes.tpl"}
-</head>
-<body>
{assign var=showSitesSelection value=true}
-{include file="CoreHome/templates/top_bar.tpl"}
+
{include file="CoreHome/templates/header.tpl"}
-{include file="CoreHome/templates/menu.tpl"}
-<div style='clear:both'></div>
-{include file="CoreHome/templates/loading.tpl"}
-<div id='content'>
+{if isset($menu) && $menu}{include file="CoreHome/templates/menu.tpl"}{/if}
+<div style="clear:both;"></div>
+{ajaxLoadingDiv}
+{ajaxRequestErrorDiv}
+
+<div id="content">
{if $content}{$content}{/if}
</div>
diff --git a/plugins/CoreHome/templates/js_css_includes.tpl b/plugins/CoreHome/templates/js_css_includes.tpl
index d4ac685907..06311092aa 100644
--- a/plugins/CoreHome/templates/js_css_includes.tpl
+++ b/plugins/CoreHome/templates/js_css_includes.tpl
@@ -1,16 +1,14 @@
<link rel="stylesheet" type="text/css" href="themes/default/common.css" />
-<link rel="stylesheet" type="text/css" href="libs/jquery/thickbox.css" />
-<link rel="stylesheet" type="text/css" href="libs/jquery/jquery-calendar.css" />
+<link rel="stylesheet" type="text/css" href="libs/jquery/themes/base/jquery-ui.css" class="ui-theme" />
<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/styles.css" />
<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/menu.css" />
<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/datatable.css" />
<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/cloud.css" />
-<link rel="stylesheet" type="text/css" href="plugins/Dashboard/templates/dashboard.css" />
{postEvent name="template_css_import"}
-<script type="text/javascript" src="themes/default/common.js"></script>
<script type="text/javascript" src="libs/jquery/jquery.js"></script>
<script type="text/javascript" src="libs/jquery/jquery-ui.js"></script>
+<script type="text/javascript" src="libs/jquery/jquery.bgiframe.js"></script>
<script type="text/javascript" src="libs/jquery/tooltip/jquery.tooltip.js"></script>
<script type="text/javascript" src="libs/jquery/truncate/jquery.truncate.js"></script>
<script type="text/javascript" src="libs/jquery/jquery.scrollTo.js"></script>
@@ -18,9 +16,9 @@
<script type="text/javascript" src="libs/jquery/fdd2div-modified.js"></script>
<script type="text/javascript" src="libs/jquery/superfish_modified.js"></script>
<script type="text/javascript" src="libs/jquery/jquery.history.js"></script>
-<script type="text/javascript" src="libs/jquery/thickbox.js"></script>
<script type="text/javascript" src="libs/swfobject/swfobject.js"></script>
<script type="text/javascript" src="libs/javascript/sprintf.js"></script>
+<script type="text/javascript" src="themes/default/common.js"></script>
<script type="text/javascript" src="plugins/CoreHome/templates/datatable.js"></script>
<script type="text/javascript" src="plugins/CoreHome/templates/broadcast.js"></script>
<script type="text/javascript" src="plugins/CoreHome/templates/menu.js"></script>
diff --git a/plugins/CoreHome/templates/loading.tpl b/plugins/CoreHome/templates/loading.tpl
deleted file mode 100644
index 5dc8755980..0000000000
--- a/plugins/CoreHome/templates/loading.tpl
+++ /dev/null
@@ -1,4 +0,0 @@
-<div id="loadingPiwik" {if isset($basicHtmlView) && $basicHtmlView}style="display:none"{/if}>
-<img src="themes/default/images/loading-blue.gif" alt="" /> {'General_LoadingData'|translate}
-</div>
-<div id="loadingError">{'General_ErrorRequest'|translate}</div>
diff --git a/plugins/CoreHome/templates/menu.css b/plugins/CoreHome/templates/menu.css
index b95539af8c..a4d9df5ed5 100644
--- a/plugins/CoreHome/templates/menu.css
+++ b/plugins/CoreHome/templates/menu.css
@@ -27,6 +27,7 @@
float: left;
list-style: none;
z-index: 49;
+ margin-right:1px;
}
.nav li.current ul {
@@ -59,10 +60,16 @@
position: absolute;
}
+.nav li, .nav li:hover,.nav li.sfHover,.nav li.current,.nav a:focus,.nav a:hover,.nav a:active{
+ -moz-border-radius:5px 5px 0 0;
+ -webkit-border-radius:5px 5px 0 0;
+}
+
/* LEVEL1 HOVER */
-.nav li:hover,.nav li.sfHover,.nav li.current,.nav a:focus,.nav a:hover,.nav a:active
- {
+.nav li:hover,.nav li.sfHover,.nav li.current,.nav a:focus,.nav a:hover,.nav a:active {
background: #C9D5FF;
+ -moz-border-radius:5px 5px 0 0;
+ -webkit-border-radius:5px 5px 0 0;
}
.nav li {
diff --git a/plugins/CoreHome/templates/menu.js b/plugins/CoreHome/templates/menu.js
index 51139ed6b7..eef1dd5ba4 100644
--- a/plugins/CoreHome/templates/menu.js
+++ b/plugins/CoreHome/templates/menu.js
@@ -10,7 +10,7 @@ menu.prototype =
if(urlLoaded == menu.prototype.lastUrlRequested)
{
$('#content').html( content ).show();
- $('#loadingPiwik').hide();
+ piwikHelper.hideAjaxLoading();
menu.prototype.lastUrlRequested = null;
}
},
@@ -47,7 +47,7 @@ menu.prototype =
.superfish({
pathClass : 'current',
animation : {opacity:'show'},
- delay : 1000
+ delay : 2000
});
this.param.superfish.find("li")
.click( self.onClickLI )
@@ -130,8 +130,10 @@ menu.prototype =
};
$(document).ready( function(){
- piwikMenu = new menu();
- piwikMenu.init();
- piwikMenu.loadFirstSection();
- broadcast.init();
+ if($('.nav').size()) {
+ piwikMenu = new menu();
+ piwikMenu.init();
+ piwikMenu.loadFirstSection();
+ broadcast.init();
+ }
});
diff --git a/plugins/CoreHome/templates/period_select.tpl b/plugins/CoreHome/templates/period_select.tpl
index 1db1f1092b..1c704ff5b5 100644
--- a/plugins/CoreHome/templates/period_select.tpl
+++ b/plugins/CoreHome/templates/period_select.tpl
@@ -1,5 +1,4 @@
{loadJavascriptTranslations plugins='CoreHome'}
-<script type="text/javascript" src="libs/jquery/jquery-calendar.js"></script>
<script type="text/javascript" src="plugins/CoreHome/templates/calendar.js"></script>
<script type="text/javascript" src="plugins/CoreHome/templates/date.js"></script>
@@ -11,11 +10,11 @@
{foreach from=$otherPeriods item=thisPeriod} | <a href='{url period=$thisPeriod}'>{$periodsNames.$thisPeriod.singular}</a>{/foreach}
</span>
</span>
- <br/>
- <span id="calendar"></span>
+ <br />
+ <span id="datepicker"></span>
</span>
-{literal}<script language="javascript">
+{literal}<script type="text/javascript">
$(document).ready(function() {
// this will trigger to change only the period value on search query and hash string.
$("#otherPeriods a").bind('click',function(e) {
@@ -27,5 +26,4 @@ $(document).ready(function() {
});</script>
{/literal}
-<div style="clear:both"></div>
-
+<div style="clear:both;"></div>
diff --git a/plugins/CoreHome/templates/piwik_tag.tpl b/plugins/CoreHome/templates/piwik_tag.tpl
index fb4c1886fc..994388e7cf 100644
--- a/plugins/CoreHome/templates/piwik_tag.tpl
+++ b/plugins/CoreHome/templates/piwik_tag.tpl
@@ -1,8 +1,8 @@
{if $piwikUrl == 'http://piwik.org/demo/' || $debugTrackVisitsInsidePiwikUI}
-<div style="clear:both"></div>
+<div style="clear:both;"></div>
{literal}
<!-- Piwik -->
-<script language="javascript" src="piwik.js" type="text/javascript"></script>
+<script src="piwik.js" type="text/javascript"></script>
<script type="text/javascript">
try {
var piwikTracker = Piwik.getTracker("piwik.php", 1);
diff --git a/plugins/CoreHome/templates/sites_selection.tpl b/plugins/CoreHome/templates/sites_selection.tpl
index 21ed8f743b..be60868dda 100644
--- a/plugins/CoreHome/templates/sites_selection.tpl
+++ b/plugins/CoreHome/templates/sites_selection.tpl
@@ -8,11 +8,11 @@
{/foreach}
</select>
{hiddenurl idSite=null}
- <input type="submit" value="go"/>
+ <input type="submit" value="go" />
</form>
</span>
- {literal}<script language="javascript">
+ {literal}<script type="text/javascript">
$(document).ready(function() {
var extraPadding = 0;
// if there is only one website, we dont show the arrows image, so no need to add the extra padding
diff --git a/plugins/CoreHome/templates/styles.css b/plugins/CoreHome/templates/styles.css
index c3537c2cdb..850935ef0b 100644
--- a/plugins/CoreHome/templates/styles.css
+++ b/plugins/CoreHome/templates/styles.css
@@ -5,12 +5,16 @@ h1 {
}
h2 {
- font-size: 1.6em;
+ font-size: 1.3em;
color: #1D3256;
padding-bottom: 0.5em;
clear:both;
}
+h2 a {
+ text-decoration:none;
+}
+
h3 {
font-size: 1.3em;
margin-top: 2em;
@@ -20,6 +24,7 @@ h3 {
p {
padding-bottom: 1em;
margin-right: 1em;
+ margin-left:1em;
}
/* Content */
@@ -45,26 +50,14 @@ p {
padding-left:10px;
}
-#calendar {
- display: block;
-}
-
/* Calendar*/
-.calendar td.dateToday,.calendar td.dateToday a {
- font-weight: bold;
+div.ui-datepicker {
+ font-size: 62.5%;
}
-.calendar td.dateUsedStats,.calendar td.dateUsedStats a {
+.ui-datepicker-current-period a, .ui-datepicker-current-period a:link, .ui-datepicker-current-period a:visited {
+ border: 1px solid #2E85FF;
color: #2E85FF;
- border-color: #2E85FF;
-}
-
-.calendar td.calendar_unselectable {
- color: #F2F7FF;
-}
-
-.calendar {
- line-height: 1.33;
}
#otherPeriods a {
@@ -92,6 +85,7 @@ div .sparkline {
margin-top:10px;
border-bottom:1px solid white;
}
+
.sparkline img {
vertical-align: middle;
padding-right: 10px;
diff --git a/plugins/CoreHome/templates/top_bar.tpl b/plugins/CoreHome/templates/top_bar.tpl
index 7245055a2d..53957f4110 100644
--- a/plugins/CoreHome/templates/top_bar.tpl
+++ b/plugins/CoreHome/templates/top_bar.tpl
@@ -13,7 +13,7 @@
<nobr>
<small>
{'General_HelloUser'|translate:"<strong>$userLogin</strong>"}
-{if isset($userHasSomeAdminAccess) && $userHasSomeAdminAccess}| <a href='index.php?module=CoreAdminHome'>{'General_Settings'|translate}</a>{/if}
+{if $userLogin != 'anonymous'}| <a href='index.php?module=CoreAdminHome'>{'General_Settings'|translate}</a>{/if}
{if $showSitesSelection && $showWebsiteSelectorInUserInterface}| {include file=CoreHome/templates/sites_selection.tpl}{/if}
| {if $userLogin == 'anonymous'}<a href='index.php?module={$loginModule}'>{'Login_LogIn'|translate}</a>{else}<a href='index.php?module={$loginModule}&amp;action=logout'>{'Login_Logout'|translate}</a>{/if}
</small>
@@ -21,6 +21,6 @@
</nobr>
</div>
-<br clear="all" />
+<br class="clearAll" />
</div>
diff --git a/plugins/CoreHome/templates/top_screen.tpl b/plugins/CoreHome/templates/top_screen.tpl
new file mode 100644
index 0000000000..d88d17ac95
--- /dev/null
+++ b/plugins/CoreHome/templates/top_screen.tpl
@@ -0,0 +1,7 @@
+<div id="header">
+{include file="CoreHome/templates/header_message.tpl"}
+{include file="CoreHome/templates/logo.tpl"}
+{include file="CoreHome/templates/period_select.tpl"}
+{include file="CoreHome/templates/js_disabled_notice.tpl"}
+</div>
+<br />
diff --git a/plugins/CorePluginsAdmin/Controller.php b/plugins/CorePluginsAdmin/Controller.php
index b759f2b550..866ed0f8ca 100644
--- a/plugins/CorePluginsAdmin/Controller.php
+++ b/plugins/CorePluginsAdmin/Controller.php
@@ -20,38 +20,54 @@ class Piwik_CorePluginsAdmin_Controller extends Piwik_Controller
{
Piwik::checkUserIsSuperUser();
- $listPlugins = Piwik_PluginsManager::getInstance()->readPluginsDirectory();
- $loadedPlugins = Piwik_PluginsManager::getInstance()->getLoadedPlugins();
$plugins = array();
+
+ $listPlugins = Piwik_PluginsManager::getInstance()->readPluginsDirectory();
foreach($listPlugins as $pluginName)
{
$oPlugin = Piwik_PluginsManager::getInstance()->loadPlugin($pluginName);
- $plugins[$pluginName]= array( 'activated' => Piwik_PluginsManager::getInstance()->isPluginActivated($pluginName),
- 'alwaysActivated' => Piwik_PluginsManager::getInstance()->isPluginAlwaysActivated($pluginName),
- 'info' => $oPlugin->getInformation()
- );
+ $plugins[$pluginName] = array(
+ 'activated' => Piwik_PluginsManager::getInstance()->isPluginActivated($pluginName),
+ 'alwaysActivated' => Piwik_PluginsManager::getInstance()->isPluginAlwaysActivated($pluginName),
+ );
}
-
+
+ Piwik_PluginsManager::getInstance()->loadTranslations();
+
+ $loadedPlugins = Piwik_PluginsManager::getInstance()->getLoadedPlugins();
+ foreach($loadedPlugins as $oPlugin)
+ {
+ $pluginName = $oPlugin->getClassName();
+ $plugins[$pluginName]['info'] = $oPlugin->getInformation();
+ }
+
$view = Piwik_View::factory('manage');
$view->pluginsName = $plugins;
$this->setGeneralVariablesView($view);
$view->menu = Piwik_GetAdminMenu();
+ if(!Zend_Registry::get('config')->isFileWritable())
+ {
+ $view->configFileNotWritable = true;
+ }
+
echo $view->render();
}
function deactivate()
{
Piwik::checkUserIsSuperUser();
+ $this->checkTokenInUrl();
$pluginName = Piwik_Common::getRequestVar('pluginName', null, 'string');
Piwik_PluginsManager::getInstance()->deactivatePlugin($pluginName);
- Piwik_Url::redirectToUrl('index.php?module=CorePluginsAdmin');
+ Piwik_Url::redirectToUrl('index.php?module=CorePluginsAdmin&action=index');
}
function activate()
{
Piwik::checkUserIsSuperUser();
+ $this->checkTokenInUrl();
$pluginName = Piwik_Common::getRequestVar('pluginName', null, 'string');
Piwik_PluginsManager::getInstance()->activatePlugin($pluginName);
- Piwik_Url::redirectToUrl('index.php?module=CorePluginsAdmin');
+ Piwik_Url::redirectToUrl('index.php?module=CorePluginsAdmin&action=index');
}
}
diff --git a/plugins/CorePluginsAdmin/CorePluginsAdmin.php b/plugins/CorePluginsAdmin/CorePluginsAdmin.php
index dc634819a7..3680c7dd80 100644
--- a/plugins/CorePluginsAdmin/CorePluginsAdmin.php
+++ b/plugins/CorePluginsAdmin/CorePluginsAdmin.php
@@ -19,11 +19,10 @@ class Piwik_CorePluginsAdmin extends Piwik_Plugin
public function getInformation()
{
return array(
- 'name' => 'Plugins Management',
- 'description' => 'Plugins Administration Interface.',
+ 'description' => Piwik_Translate('CorePluginsAdmin_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
}
@@ -34,6 +33,9 @@ class Piwik_CorePluginsAdmin extends Piwik_Plugin
function addMenu()
{
- Piwik_AddAdminMenu('CorePluginsAdmin_MenuPlugins', array('module' => 'CorePluginsAdmin', 'action' => 'index'));
+ Piwik_AddAdminMenu('CorePluginsAdmin_MenuPlugins',
+ array('module' => 'CorePluginsAdmin', 'action' => 'index'),
+ Piwik::isUserIsSuperUser(),
+ $order = 7);
}
}
diff --git a/plugins/CorePluginsAdmin/templates/manage.tpl b/plugins/CorePluginsAdmin/templates/manage.tpl
index c77eea691e..0c83104a57 100644
--- a/plugins/CorePluginsAdmin/templates/manage.tpl
+++ b/plugins/CorePluginsAdmin/templates/manage.tpl
@@ -1,7 +1,6 @@
{assign var=showSitesSelection value=false}
{assign var=showPeriodSelection value=false}
{include file="CoreAdminHome/templates/header.tpl"}
-{include file="CoreAdminHome/templates/menu.tpl"}
<div style="max-width:980px;">
@@ -20,7 +19,7 @@
<tbody id="plugins">
{foreach from=$pluginsName key=name item=plugin}
{if !$plugin.alwaysActivated}
- <tr class={if $plugin.activated}"active"{else}class="deactivate"{/if}>
+ <tr class={if $plugin.activated}"active"{else}"deactivate"{/if}>
<td class="name">
{if isset($plugin.info.homepage)}<a title="{'CorePluginsAdmin_PluginHomepage'|translate}" href="{$plugin.info.homepage}">{/if}
{$name}
@@ -30,7 +29,7 @@
<td class="desc">
{$plugin.info.description|nl2br}
&nbsp;<cite>By
- {if isset($plugin.info.author_homepage)}<a title="Author Homepage" href="{$plugin.info.author_homepage}">{/if}
+ {if isset($plugin.info.author_homepage)}<a title="Author Homepage" href="misc/redirectToUrl.php?url={$plugin.info.author_homepage}">{/if}
{$plugin.info.author}{if isset($plugin.info.author_homepage)}</a>{/if}.</cite>
</td>
<td class="status">
@@ -41,8 +40,8 @@
<td class="togl action-links" {if $plugin.alwaysActivated}title="{'CorePluginsAdmin_ActivatedHelp'|translate}"{/if}>
{if $plugin.alwaysActivated} <center>-</center>
- {elseif $plugin.activated}<a href=index.php?module=CorePluginsAdmin&action=deactivate&pluginName={$name}>{'CorePluginsAdmin_Deactivate'|translate}</a>
- {else}<a href=index.php?module=CorePluginsAdmin&action=activate&pluginName={$name}>{'CorePluginsAdmin_Activate'|translate}</a>{/if}
+ {elseif $plugin.activated}<a href='index.php?module=CorePluginsAdmin&action=deactivate&pluginName={$name}&token_auth={$token_auth}'>{'CorePluginsAdmin_Deactivate'|translate}</a>
+ {else}<a href='index.php?module=CorePluginsAdmin&action=activate&pluginName={$name}&token_auth={$token_auth}'>{'CorePluginsAdmin_Activate'|translate}</a>{/if}
</td>
</tr>
{/if}
diff --git a/plugins/CoreUpdater/Controller.php b/plugins/CoreUpdater/Controller.php
index 824e8a73f2..266121356e 100644
--- a/plugins/CoreUpdater/Controller.php
+++ b/plugins/CoreUpdater/Controller.php
@@ -88,7 +88,7 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller
Piwik::checkDirectoriesWritableOrDie( array(self::PATH_TO_EXTRACT_LATEST_VERSION) );
// we catch exceptions in the caller (i.e., oneClickUpdate)
- $fetched = Piwik::fetchRemoteFile(self::LATEST_PIWIK_URL, $this->pathPiwikZip);
+ $fetched = Piwik_Http::fetchRemoteFile(self::LATEST_PIWIK_URL, $this->pathPiwikZip);
}
private function oneClick_Unpack()
@@ -139,6 +139,11 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller
private function oneClick_Copy()
{
/*
+ * Overwrite the downloaded robots.txt with our local copy
+ */
+ Piwik::copy(PIWIK_DOCUMENT_ROOT . '/robots.txt', $this->pathRootExtractedPiwik . '/robots.txt');
+
+ /*
* Copy all files to PIWIK_INCLUDE_PATH.
* These files are accessed through the dispatcher.
*/
@@ -185,17 +190,29 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller
{
}
- public function runUpdaterAndExit($updater, $componentsWithUpdateFile)
+ public function index()
{
- if(empty($componentsWithUpdateFile))
+ $language = Piwik_Common::getRequestVar('language', '');
+ if(!empty($language))
{
- return;
+ Piwik_LanguagesManager_API::getInstance()->setLanguageForSession($language);
}
+ $this->runUpdaterAndExit();
+ }
- if(Piwik::isPhpCliMode())
+ protected function runUpdaterAndExit()
+ {
+ $updater = new Piwik_Updater();
+ $componentsWithUpdateFile = Piwik_CoreUpdater::getComponentUpdates($updater);
+ if(empty($componentsWithUpdateFile))
+ {
+ Piwik::redirectToModule('CoreHome');
+ }
+
+ Piwik::setMaxExecutionTime(0);
+
+ if(Piwik_Common::isPhpCliMode())
{
- Piwik::setMaxExecutionTime(0);
-
$view = Piwik_View::factory('update_welcome');
$this->doWelcomeUpdates($view, $componentsWithUpdateFile);
@@ -207,12 +224,14 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller
}
else if(Piwik_Common::getRequestVar('updateCorePlugins', 0, 'integer') == 1)
{
+ $this->warningMessages = array();
$view = Piwik_View::factory('update_database_done');
$this->doExecuteUpdates($view, $updater, $componentsWithUpdateFile);
}
else
{
$view = Piwik_View::factory('update_welcome');
+ $view->queries = $updater->getSqlQueriesToExecute();
$this->doWelcomeUpdates($view, $componentsWithUpdateFile);
}
exit;
@@ -221,13 +240,12 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller
private function doWelcomeUpdates($view, $componentsWithUpdateFile)
{
$view->new_piwik_version = Piwik_Version::VERSION;
-
+ $view->commandUpgradePiwik = "<br /><code>php ".Piwik_Common::getPathToPiwikRoot()."/index.php -- \"module=CoreUpdater\" </code>";
$pluginNamesToUpdate = array();
$coreToUpdate = false;
// handle case of existing database with no tables
- $tablesInstalled = Piwik::getTablesInstalled();
- if(count($tablesInstalled) == 0)
+ if(!Piwik::isInstalled())
{
$this->errorMessages[] = Piwik_Translate('CoreUpdater_EmptyDatabaseError', Zend_Registry::get('config')->database->dbname);
$this->coreError = true;
@@ -254,7 +272,20 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller
}
}
}
+
+ // check file integrity
+ $integrityInfo = Piwik::getFileIntegrityInformation();
+ if(isset($integrityInfo[1]))
+ {
+ if($integrityInfo[0] == false)
+ {
+ $this->warningMessages[] = '<b>'.Piwik_Translate('General_FileIntegrityWarningExplanation').'</b>';
+ }
+ $this->warningMessages = array_merge($this->warningMessages, array_slice($integrityInfo, 1));
+ }
+
$view->coreError = $this->coreError;
+ $view->warningMessages = $this->warningMessages;
$view->errorMessages = $this->errorMessages;
$view->current_piwik_version = $currentVersion;
$view->pluginNamesToUpdate = $pluginNamesToUpdate;
@@ -300,11 +331,4 @@ class Piwik_CoreUpdater_Controller extends Piwik_Controller
}
}
}
-
- public function saveLanguage()
- {
- $language = Piwik_Common::getRequestVar('language');
- Piwik_LanguagesManager_API::setLanguageForSession($language);
- Piwik_Url::redirectToReferer();
- }
}
diff --git a/plugins/CoreUpdater/CoreUpdater.php b/plugins/CoreUpdater/CoreUpdater.php
index 22dc0319e8..247713f44d 100644
--- a/plugins/CoreUpdater/CoreUpdater.php
+++ b/plugins/CoreUpdater/CoreUpdater.php
@@ -19,11 +19,10 @@ class Piwik_CoreUpdater extends Piwik_Plugin
public function getInformation()
{
return array(
- 'name' => 'Updater',
- 'description' => 'Piwik updating mechanism',
+ 'description' => Piwik_Translate('CoreUpdater_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
}
@@ -36,34 +35,34 @@ class Piwik_CoreUpdater extends Piwik_Plugin
return $hooks;
}
- function dispatch()
+ public static function getComponentUpdates($updater)
{
- $language = Piwik_Common::getRequestVar('language', '', 'string');
- if($language != '')
- {
- $updaterController = new Piwik_CoreUpdater_Controller();
- $updaterController->saveLanguage();
- exit;
- }
-
- $updater = new Piwik_Updater();
$updater->addComponentToCheck('core', Piwik_Version::VERSION);
-
- $plugins = Piwik_PluginsManager::getInstance()->getInstalledPlugins();
+
+ $plugins = Piwik_PluginsManager::getInstance()->getLoadedPlugins();
foreach($plugins as $pluginName => $plugin)
{
$updater->addComponentToCheck($pluginName, $plugin->getVersion());
}
$componentsWithUpdateFile = $updater->getComponentsWithUpdateFile();
- if(count($componentsWithUpdateFile) == 0)
+ if(count($componentsWithUpdateFile) == 0 && !$updater->hasNewVersion('core'))
+ {
+ return null;
+ }
+
+ return $componentsWithUpdateFile;
+ }
+
+ function dispatch()
+ {
+ $module = Piwik_Common::getRequestVar('module', '', 'string');
+ $updater = new Piwik_Updater();
+ if(self::getComponentUpdates($updater) !== null && $module != 'CoreUpdater')
{
- return;
+ Piwik::redirectToModule('CoreUpdater');
}
-
- $updaterController = new Piwik_CoreUpdater_Controller();
- $updaterController->runUpdaterAndExit($updater, $componentsWithUpdateFile);
- }
+ }
function updateCheck()
{
diff --git a/plugins/CoreUpdater/templates/cli_update_database_done.tpl b/plugins/CoreUpdater/templates/cli_update_database_done.tpl
index 98ab7a8012..6cda000c79 100644
--- a/plugins/CoreUpdater/templates/cli_update_database_done.tpl
+++ b/plugins/CoreUpdater/templates/cli_update_database_done.tpl
@@ -54,9 +54,9 @@
{'CoreUpdater_HelpMessageIntroductionWhenWarning'|translate|unescape}
* {$helpMessage}
+ {else}
+ {'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded'|translate|unescape}
{/if}
- {'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded'|translate|unescape}
-
{/if}
{/textformat}
diff --git a/plugins/CoreUpdater/templates/cli_update_welcome.tpl b/plugins/CoreUpdater/templates/cli_update_welcome.tpl
index 3a76f18366..28d60bd955 100644
--- a/plugins/CoreUpdater/templates/cli_update_welcome.tpl
+++ b/plugins/CoreUpdater/templates/cli_update_welcome.tpl
@@ -15,20 +15,22 @@
* {$helpMessage}
{else}
- {'CoreUpdater_DatabaseUpgradeRequired'|translate|unescape}
+ {if $coreToUpdate || count($pluginNamesToUpdate) > 0}
+ {'CoreUpdater_DatabaseUpgradeRequired'|translate|unescape}
- {'CoreUpdater_YourDatabaseIsOutOfDate'|translate|unescape}
+ {'CoreUpdater_YourDatabaseIsOutOfDate'|translate|unescape}
- {if $coreToUpdate}
- {'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY'|translate:$current_piwik_version:$new_piwik_version|unescape}
+ {if $coreToUpdate}
+ {'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY'|translate:$current_piwik_version:$new_piwik_version|unescape}
- {/if}
- {if count($pluginNamesToUpdate) > 0}
- {assign var=listOfPlugins value=$pluginNamesToUpdate|@implode:', '}
- {'CoreUpdater_TheFollowingPluginsWillBeUpgradedX'|translate:$listOfPlugins|unescape}
+ {/if}
+ {if count($pluginNamesToUpdate) > 0}
+ {assign var=listOfPlugins value=$pluginNamesToUpdate|@implode:', '}
+ {'CoreUpdater_TheFollowingPluginsWillBeUpgradedX'|translate:$listOfPlugins|unescape}
- {/if}
- {'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient'|translate|unescape}
+ {/if}
+ {'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient'|translate|unescape}
+ {/if}
{/if}
{/textformat}
diff --git a/plugins/CoreUpdater/templates/header.tpl b/plugins/CoreUpdater/templates/header.tpl
index 0194dad6f4..076801771d 100644
--- a/plugins/CoreUpdater/templates/header.tpl
+++ b/plugins/CoreUpdater/templates/header.tpl
@@ -7,6 +7,20 @@
<link rel="shortcut icon" href="plugins/CoreHome/templates/images/favicon.ico" />
<link rel="stylesheet" type="text/css" href="themes/default/simple_structure.css" />
+ <link rel="stylesheet" type="text/css" href="libs/jquery/themes/base/jquery-ui.css" class="ui-theme" />
+{literal}
+<style>
+* {
+ margin: 0;
+ padding: 0;
+}
+.topBarElem {
+ font-family:arial,sans-serif !important;
+ font-size:13px;
+ line-height:1.33;
+}
+</style>
+{/literal}
{postEvent name="template_css_import"}
<script type="text/javascript" src="libs/jquery/jquery.js"></script>
diff --git a/plugins/CoreUpdater/templates/update_database_done.tpl b/plugins/CoreUpdater/templates/update_database_done.tpl
index ab2740bc7d..28b0b235d5 100644
--- a/plugins/CoreUpdater/templates/update_database_done.tpl
+++ b/plugins/CoreUpdater/templates/update_database_done.tpl
@@ -2,14 +2,14 @@
{assign var='helpMessage' value='CoreUpdater_HelpMessageContent'|translate:'<a target="_blank" href="misc/redirectToUrl.php?url=http://piwik.org/faq/">':'</a>':'</li><li>'}
{if $coreError}
- <br><br>
+ <br /><br />
<div class="error">
- <img src="themes/default/images/error_medium.png"> {'CoreUpdater_CriticalErrorDuringTheUpgradeProcess'|translate}
+ <img src="themes/default/images/error_medium.png" /> {'CoreUpdater_CriticalErrorDuringTheUpgradeProcess'|translate}
{foreach from=$errorMessages item=message}
- <pre>{$message}</pre>
+ <pre>{$message}</pre><br />
{/foreach}
</div>
- <br>
+ <br />
<p>{'CoreUpdater_HelpMessageIntroductionWhenError'|translate}
<ul><li>{$helpMessage}</li></ul></p>
@@ -23,38 +23,38 @@
{if count($warningMessages) > 0}
<div class="warning">
- <p><img src="themes/default/images/warning_medium.png"> {'CoreUpdater_WarningMessages'|translate}</p>
+ <p><img src="themes/default/images/warning_medium.png" /> {'CoreUpdater_WarningMessages'|translate}</p>
{foreach from=$warningMessages item=message}
- <pre>{$message}</pre>
+ <pre>{$message}</pre><br />
{/foreach}
</div>
{/if}
{if count($errorMessages) > 0}
<div class="warning">
- <p><img src="themes/default/images/warning_medium.png"> {'CoreUpdater_ErrorDuringPluginsUpdates'|translate}</p>
+ <p><img src="themes/default/images/warning_medium.png" /> {'CoreUpdater_ErrorDuringPluginsUpdates'|translate}</p>
{foreach from=$errorMessages item=message}
- <pre>{$message}</pre>
+ <pre>{$message}</pre><br />
{/foreach}
{if isset($deactivatedPlugins) && count($deactivatedPlugins) > 0}
{assign var=listOfDeactivatedPlugins value=$deactivatedPlugins|@implode:', '}
- <p style="color:red"><img src="themes/default/images/error_medium.png"> {'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins'|translate:$listOfDeactivatedPlugins}</p>
+ <p style="color:red"><img src="themes/default/images/error_medium.png" /> {'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins'|translate:$listOfDeactivatedPlugins}</p>
{/if}
</div>
{/if}
{if count($errorMessages) > 0 || count($warningMessages) > 0}
- <br>
+ <br />
<p>{'CoreUpdater_HelpMessageIntroductionWhenWarning'|translate}
<ul><li>{$helpMessage}</li></ul>
</p>
+ {else}
+ <p class="success">{'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded'|translate}</p>
{/if}
-
- <p class="success">{'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded'|translate}</p>
<form action="index.php">
- <input type="submit" class="submit" value="{'CoreUpdater_ContinueToPiwik'|translate}"/>
+ <input type="submit" class="submit" value="{'CoreUpdater_ContinueToPiwik'|translate}" />
</form>
{/if}
diff --git a/plugins/CoreUpdater/templates/update_new_version_available.tpl b/plugins/CoreUpdater/templates/update_new_version_available.tpl
index 7823386807..d2218175c7 100644
--- a/plugins/CoreUpdater/templates/update_new_version_available.tpl
+++ b/plugins/CoreUpdater/templates/update_new_version_available.tpl
@@ -2,14 +2,14 @@
<p><b>{'CoreUpdater_ThereIsNewVersionAvailableForUpdate'|translate}</b></p>
<p>{'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage'|translate:$piwik_new_version}</p>
-<br>
+<br />
<form action="index.php">
-<input type="hidden" name="module" value="CoreUpdater">
-<input type="hidden" name="action" value="oneClickUpdate">
-<input type="submit" class="submit" value="{'CoreUpdater_UpdateAutomatically'|translate}"/>
+<input type="hidden" name="module" value="CoreUpdater" />
+<input type="hidden" name="action" value="oneClickUpdate" />
+<input type="submit" class="submit" value="{'CoreUpdater_UpdateAutomatically'|translate}" />
<a style="margin-left:50px" class="submit button" href="http://piwik.org/latest.zip">{'CoreUpdater_DownloadX'|translate:$piwik_new_version}</a>
</form>
-
+<br />
<a href='index.php'>&laquo; {'General_BackToPiwik'|translate}</a>
{include file="CoreUpdater/templates/footer.tpl"}
diff --git a/plugins/CoreUpdater/templates/update_one_click_done.tpl b/plugins/CoreUpdater/templates/update_one_click_done.tpl
index 7f1b878f2c..f4fbde8036 100644
--- a/plugins/CoreUpdater/templates/update_one_click_done.tpl
+++ b/plugins/CoreUpdater/templates/update_one_click_done.tpl
@@ -5,14 +5,14 @@
{/foreach}
{if $coreError}
- <br/><br/>
- <div class="error"><img src="themes/default/images/error_medium.png"> {$coreError}</div>
- <br/><br/>
- <div class="warning"><img src="themes/default/images/warning_medium.png"> {'CoreUpdater_UpdateHasBeenCancelledExplanation'|translate:"<br/><br/>":"<a target='_blank' href='misc/redirectToUrl.php?url=http://piwik.org/docs/update/'>":"</a>"}</div>
- <br/><br/>
+ <br /><br />
+ <div class="error"><img src="themes/default/images/error_medium.png" /> {$coreError}</div>
+ <br /><br />
+ <div class="warning"><img src="themes/default/images/warning_medium.png" /> {'CoreUpdater_UpdateHasBeenCancelledExplanation'|translate:"<br /><br />":"<a target='_blank' href='misc/redirectToUrl.php?url=http://piwik.org/docs/update/'>":"</a>"}</div>
+ <br /><br />
{/if}
<form action="index.php">
-<input type="submit" class="submit" value="{'CoreUpdater_ContinueToPiwik'|translate}"/>
+<input type="submit" class="submit" value="{'CoreUpdater_ContinueToPiwik'|translate}" />
</form>
{include file="CoreUpdater/templates/footer.tpl"}
diff --git a/plugins/CoreUpdater/templates/update_welcome.tpl b/plugins/CoreUpdater/templates/update_welcome.tpl
index c36e5751c1..f5a8da5dbc 100644
--- a/plugins/CoreUpdater/templates/update_welcome.tpl
+++ b/plugins/CoreUpdater/templates/update_welcome.tpl
@@ -3,38 +3,97 @@
{assign var='helpMessage' value='CoreUpdater_HelpMessageContent'|translate:'<a target="_blank" href="misc/redirectToUrl.php?url=http://piwik.org/faq/">':'</a>':'</li><li>'}
{if $coreError}
- <br><br>
+ <br /><br />
<div class="error">
- <img src="themes/default/images/error_medium.png"> {'CoreUpdater_CriticalErrorDuringTheUpgradeProcess'|translate}
+ <img src="themes/default/images/error_medium.png" /> {'CoreUpdater_CriticalErrorDuringTheUpgradeProcess'|translate}
{foreach from=$errorMessages item=message}
<pre>{$message}</pre>
{/foreach}
</div>
- <br>
+ <br />
<p>{'CoreUpdater_HelpMessageIntroductionWhenError'|translate}
<ul><li>{$helpMessage}</li></ul></p>
{else}
- <p><b>{'CoreUpdater_DatabaseUpgradeRequired'|translate}</b></p>
- <p>{'CoreUpdater_YourDatabaseIsOutOfDate'|translate}</p>
+ {if $coreToUpdate || count($pluginNamesToUpdate) > 0}
+ <p style='font-size:110%;padding-top:1em;'><b>{'CoreUpdater_DatabaseUpgradeRequired'|translate}</b></p>
+ <p>{'CoreUpdater_YourDatabaseIsOutOfDate'|translate}</p>
- {if $coreToUpdate}
- <p>{'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY'|translate:$current_piwik_version:$new_piwik_version}</p>
+ {if $coreToUpdate}
+ <p>{'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY'|translate:$current_piwik_version:$new_piwik_version}</p>
+ {/if}
+
+ {if count($pluginNamesToUpdate) > 0}
+ {assign var=listOfPlugins value=$pluginNamesToUpdate|@implode:', '}
+ <p>{'CoreUpdater_TheFollowingPluginsWillBeUpgradedX'|translate:$listOfPlugins}</p>
+ {/if}
+
+ <p><strong>{'CoreUpdater_NoteForLargePiwikInstances'|translate}</strong></p>
+ <ul>
+ <li>{'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand'|translate:$commandUpgradePiwik}</li>
+ <li>{'CoreUpdater_YouCouldManuallyExecuteSqlQueries'|translate}<br />
+ <a href='#' id='showSql' style='margin-left:20px'>› {'CoreUpdater_ClickHereToViewSqlQueries'|translate}</a>
+ <div id='sqlQueries' style='display:none'>
+ <br />
+ <code>
+ # {'CoreUpdater_NoteItIsExpectedThatQueriesFail'|translate}<br /><br />
+ {foreach from=$queries item=query}&nbsp;&nbsp;&nbsp;{$query}<br />
+ {/foreach}
+ </code>
+ </div>
+ <br /><br />
+ <p><strong>{'CoreUpdater_ReadyToGo'|translate}</strong></p>
+ <p>{'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient'|translate}</p>
{/if}
- {if count($pluginNamesToUpdate) > 0}
- {assign var=listOfPlugins value=$pluginNamesToUpdate|@implode:', '}
- <p>{'CoreUpdater_TheFollowingPluginsWillBeUpgradedX'|translate:$listOfPlugins}</p>
+ {if count($warningMessages) > 0}
+ <p><i>{$warningMessages[0]}</i>
+ {if count($warningMessages) > 1}
+ <button id="more-results" class="ui-button ui-state-default ui-corner-all">{'General_Details'|translate}</button>
+ {/if}
+ </p>
{/if}
- <p>{'CoreUpdater_TheUpgradeProcessMayFail'|translate}</p>
- <p>{'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient'|translate}</p>
+ {if $coreToUpdate || count($pluginNamesToUpdate) > 0}
+ <br />
+ <form action="index.php">
+ <input type="hidden" name="updateCorePlugins" value="1" />
+ <input type="submit" class="submit" value="{'CoreUpdater_UpgradePiwik'|translate}" />
+ </form>
+ {else}
+ {if count($warningMessages) == 0}
+ <p class="success">{'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded'|translate}</p>
+ {/if}
- <br>
- <form action="index.php">
- <input type="hidden" name="updateCorePlugins" value="1">
- <input type="submit" class="submit" value="{'CoreUpdater_UpgradePiwik'|translate}"/>
- </form>
+ <br />
+ <form action="index.php">
+ <input type="submit" class="submit" value="{'CoreUpdater_ContinueToPiwik'|translate}" />
+ </form>
+ {/if}
{/if}
+{include file="Installation/templates/integrityDetails.tpl"}
+
+{literal}
+<style>
+code {
+ background-color:#F0F7FF;
+ border-color:#00008B;
+ border-style:dashed dashed dashed solid;
+ border-width:1px 1px 1px 5px;
+ direction:ltr;
+ display:block;
+ margin:2px 2px 20px;
+ padding:4px;
+ text-align:left;
+}
+</style>
+<script type="text/javascript">
+$(document).ready(function() {
+ $('#showSql').click( function () {
+ $('#sqlQueries').toggle();
+ });
+});
+</script>
+{/literal}
{include file="CoreUpdater/templates/footer.tpl"}
diff --git a/plugins/DBStats/API.php b/plugins/DBStats/API.php
index cb7618a908..4821f4e2b9 100644
--- a/plugins/DBStats/API.php
+++ b/plugins/DBStats/API.php
@@ -27,7 +27,7 @@ class Piwik_DBStats_API
return self::$instance;
}
- static public function getDBStatus()
+ public function getDBStatus()
{
Piwik::checkUserIsSuperUser();
$configDb = Zend_Registry::get('config')->database->toArray();
@@ -45,13 +45,16 @@ class Piwik_DBStats_API
return $status;
}
- static public function getTableStatus($table, $field = '')
+ public function getTableStatus($table, $field = '')
{
Piwik::checkUserIsSuperUser();
$db = Zend_Registry::get('db');
// http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html
- $tables = $db->fetchAll("SHOW TABLE STATUS LIKE ?", $table);
+ $tables = $db->fetchAll("SHOW TABLE STATUS LIKE ". $db->quote($table));
+ if(!isset($tables[0])) {
+ throw new Exception('Error, table or field not found');
+ }
if ($field == '')
{
return $tables[0];
@@ -62,7 +65,7 @@ class Piwik_DBStats_API
}
}
- static public function getAllTablesStatus()
+ public function getAllTablesStatus()
{
Piwik::checkUserIsSuperUser();
$db = Zend_Registry::get('db');
@@ -72,7 +75,7 @@ class Piwik_DBStats_API
$table = array();
foreach($tablesPiwik as $tableName)
{
- $t = self::getTableStatus($tableName);
+ $t = $this->getTableStatus($tableName);
$total['Data_length'] += $t['Data_length'];
$total['Index_length'] += $t['Index_length'];
$total['Rows'] += $t['Rows'];
diff --git a/plugins/DBStats/Controller.php b/plugins/DBStats/Controller.php
index 4896519e6e..dca55f0fe1 100644
--- a/plugins/DBStats/Controller.php
+++ b/plugins/DBStats/Controller.php
@@ -18,8 +18,9 @@ class Piwik_DBStats_Controller extends Piwik_Controller
{
function index()
{
+ Piwik::checkUserIsSuperUser();
$view = Piwik_View::factory('DBStats');
- $view->tablesStatus = Piwik_DBStats_API::getAllTablesStatus();
+ $view->tablesStatus = Piwik_DBStats_API::getInstance()->getAllTablesStatus();
$this->setGeneralVariablesView($view);
$view->menu = Piwik_GetAdminMenu();
echo $view->render();
diff --git a/plugins/DBStats/DBStats.php b/plugins/DBStats/DBStats.php
index 58c7c6b967..6e12ecf1c0 100644
--- a/plugins/DBStats/DBStats.php
+++ b/plugins/DBStats/DBStats.php
@@ -19,11 +19,10 @@ class Piwik_DBStats extends Piwik_Plugin
public function getInformation()
{
return array(
- 'name' => 'Database statistics',
- 'description' => 'This plugin reports the database usage by Piwik tables.',
+ 'description' => Piwik_Translate('DBStats_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
}
@@ -34,6 +33,9 @@ class Piwik_DBStats extends Piwik_Plugin
function addMenu()
{
- Piwik_AddAdminMenu('DBStats_DatabaseUsage', array('module' => 'DBStats', 'action' => 'index'));
+ Piwik_AddAdminMenu('DBStats_DatabaseUsage',
+ array('module' => 'DBStats', 'action' => 'index'),
+ Piwik::isUserIsSuperUser(),
+ $order = 9);
}
}
diff --git a/plugins/DBStats/templates/DBStats.tpl b/plugins/DBStats/templates/DBStats.tpl
index 2a65c22fc7..e5f054d6f0 100644
--- a/plugins/DBStats/templates/DBStats.tpl
+++ b/plugins/DBStats/templates/DBStats.tpl
@@ -1,16 +1,17 @@
{assign var=showSitesSelection value=false}
{assign var=showPeriodSelection value=false}
{include file="CoreAdminHome/templates/header.tpl"}
-{include file="CoreAdminHome/templates/menu.tpl"}
<div style="max-width:980px;">
<h2>{'DBStats_DatabaseUsage'|translate}</h2>
{assign var=totalSize value=$tablesStatus.Total.Total_length}
-<p>{'DBStats_MainDescription'|translate:$totalSize}</p>
+<p>{'DBStats_MainDescription'|translate:$totalSize}
+<br />
+{'DBStats_LearnMore'|translate:"<a href='misc/redirectToUrl.php?url=http://piwik.org/docs/setup-auto-archiving/' target='_blank'>Piwik Auto Archiving</a>"}</p>
<table class="adminTable">
<thead>
<th>{'DBStats_Table'|translate}</th>
- <th>{'DBStats_RowNumber'|translate}</th>
+ <th>{'DBStats_RowCount'|translate}</th>
<th>{'DBStats_DataSize'|translate}</th>
<th>{'DBStats_IndexSize'|translate}</th>
<th>{'DBStats_TotalSize'|translate}</th>
diff --git a/plugins/Dashboard/Controller.php b/plugins/Dashboard/Controller.php
index 863883f6be..bdfe1acf2e 100644
--- a/plugins/Dashboard/Controller.php
+++ b/plugins/Dashboard/Controller.php
@@ -21,16 +21,12 @@ class Piwik_Dashboard_Controller extends Piwik_Controller
$view = Piwik_View::factory($template);
$this->setGeneralVariablesView($view);
- // layout was JSON.stringified
- $layout = html_entity_decode($this->getLayout());
- $layout = str_replace("\\\"", "\"", $layout);
-
- if(!empty($layout)
- && strstr($layout, '[[') == false) {
- $layout = "'$layout'";
+ $view->availableWidgets = json_encode(Piwik_GetWidgetsList());
+ $layout = $this->getLayout();
+ if(empty($layout)) {
+ $layout = $this->getDefaultLayout();
}
$view->layout = $layout;
- $view->availableWidgets = json_encode(Piwik_GetWidgetsList());
return $view;
}
@@ -56,7 +52,7 @@ class Piwik_Dashboard_Controller extends Piwik_Controller
protected function saveLayoutForUser( $login, $idDashboard, $layout)
{
$paramsBind = array($login, $idDashboard, $layout, $layout);
- Piwik_Query('INSERT INTO '.Piwik::prefixTable('user_dashboard') .
+ Piwik_Query('INSERT INTO '.Piwik_Common::prefixTable('user_dashboard') .
' (login, iddashboard, layout)
VALUES (?,?,?)
ON DUPLICATE KEY UPDATE layout=?',
@@ -74,7 +70,7 @@ class Piwik_Dashboard_Controller extends Piwik_Controller
protected function getLayoutForUser( $login, $idDashboard)
{
$paramsBind = array($login, $idDashboard);
- $return = Piwik_FetchAll('SELECT layout FROM '.Piwik::prefixTable('user_dashboard') .
+ $return = Piwik_FetchAll('SELECT layout FROM '.Piwik_Common::prefixTable('user_dashboard') .
' WHERE login = ? AND iddashboard = ?', $paramsBind);
if(count($return) == 0)
{
@@ -90,14 +86,14 @@ class Piwik_Dashboard_Controller extends Piwik_Controller
*/
public function saveLayout()
{
+ $this->checkTokenInUrl();
$layout = Piwik_Common::getRequestVar('layout');
$idDashboard = Piwik_Common::getRequestVar('idDashboard', 1, 'int' );
$currentUser = Piwik::getCurrentUserLogin();
-
if($currentUser == 'anonymous')
{
$session = new Zend_Session_Namespace("Piwik_Dashboard");
- $session->idDashboard = $layout;
+ $session->dashboardLayout = $layout;
}
else
{
@@ -119,16 +115,84 @@ class Piwik_Dashboard_Controller extends Piwik_Controller
{
$session = new Zend_Session_Namespace("Piwik_Dashboard");
- if(!isset($session->idDashboard))
+ if(!isset($session->dashboardLayout))
{
return false;
}
- return $session->idDashboard;
+ $layout = $session->dashboardLayout;
}
else
{
- return $this->getLayoutForUser($currentUser,$idDashboard);
- }
+ $layout = $this->getLayoutForUser($currentUser,$idDashboard);
+ }
+
+ // layout was JSON.stringified
+ $layout = html_entity_decode($layout);
+ $layout = str_replace("\\\"", "\"", $layout);
+
+ // compatibility with the old layout format
+ if(!empty($layout)
+ && strstr($layout, '[[') == false) {
+ $layout = "'$layout'";
+ }
+ $layout = $this->removeDisabledPluginFromLayout($layout);
+ return $layout;
+ }
+
+ protected function removeDisabledPluginFromLayout($layout)
+ {
+ $layout = str_replace("\n", "", $layout);
+ // if the json decoding works (ie. new Json format)
+ // we will only return the widgets that are from enabled plugins
+ if($layoutObject = json_decode($layout, $assoc = false))
+ {
+ foreach($layoutObject as &$row)
+ {
+ if(!is_array($row))
+ {
+ $row = array();
+ continue;
+ }
+
+ foreach($row as $widgetId => $widget)
+ {
+ if(isset($widget->parameters->module)) {
+ $controllerName = $widget->parameters->module;
+ $controllerAction = $widget->parameters->action;
+ if(!Piwik_IsWidgetDefined($controllerName, $controllerAction))
+ {
+ unset($row[$widgetId]);
+ }
+ }
+ }
+ }
+ $layout = json_encode($layoutObject);
+ }
+ return $layout;
+ }
+
+ protected function getDefaultLayout()
+ {
+ $defaultLayout = '[
+ [
+ {"uniqueId":"widgetVisitsSummarygetEvolutionGraphcolumnsArray","parameters":{"module":"VisitsSummary","action":"getEvolutionGraph","columns":["nb_visits"]}},
+ {"uniqueId":"widgetVisitorInterestgetNumberOfVisitsPerVisitDuration","parameters":{"module":"VisitorInterest","action":"getNumberOfVisitsPerVisitDuration"}},
+ {"uniqueId":"widgetUserSettingsgetBrowser","parameters":{"module":"UserSettings","action":"getBrowser"}},
+ {"uniqueId":"widgetUserCountrygetCountry","parameters":{"module":"UserCountry","action":"getCountry"}},
+ {"uniqueId":"widgetExampleFeedburnerfeedburner","parameters":{"module":"ExampleFeedburner","action":"feedburner"}}
+ ],
+ [
+ {"uniqueId":"widgetReferersgetKeywords","parameters":{"module":"Referers","action":"getKeywords"}},
+ {"uniqueId":"widgetReferersgetWebsites","parameters":{"module":"Referers","action":"getWebsites"}}
+ ],
+ [
+ {"uniqueId":"widgetReferersgetSearchEngines","parameters":{"module":"Referers","action":"getSearchEngines"}},
+ {"uniqueId":"widgetVisitTimegetVisitInformationPerServerTime","parameters":{"module":"VisitTime","action":"getVisitInformationPerServerTime"}},
+ {"uniqueId":"widgetExampleRssWidgetrssPiwik","parameters":{"module":"ExampleRssWidget","action":"rssPiwik"}}
+ ]
+ ]';
+ $defaultLayout = $this->removeDisabledPluginFromLayout($defaultLayout);
+ return $defaultLayout;
}
}
diff --git a/plugins/Dashboard/Dashboard.php b/plugins/Dashboard/Dashboard.php
index 5e977160ea..cf9cacfb06 100644
--- a/plugins/Dashboard/Dashboard.php
+++ b/plugins/Dashboard/Dashboard.php
@@ -11,7 +11,6 @@
*/
/**
- *
* @package Piwik_Dashboard
*/
class Piwik_Dashboard extends Piwik_Plugin
@@ -19,11 +18,10 @@ class Piwik_Dashboard extends Piwik_Plugin
public function getInformation()
{
return array(
- 'name' => 'Dashboard',
- 'description' => 'Your Web Analytics Dashboard. You can customize Your Dashboard: add new widgets, change the order of your widgets. Each user can access his own custom Dashboard.',
+ 'description' => Piwik_Translate('Dashboard_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
}
@@ -32,6 +30,7 @@ class Piwik_Dashboard extends Piwik_Plugin
return array(
'template_js_import' => 'js',
'template_css_import' => 'css',
+ 'UsersManager.deleteUser' => 'deleteDashboardLayout',
);
}
@@ -48,19 +47,25 @@ class Piwik_Dashboard extends Piwik_Plugin
{
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"plugins/Dashboard/templates/dashboard.css\" />\n";
}
-
+
+ function deleteDashboardLayout($notification)
+ {
+ $userLogin = $notification->getNotificationObject();
+ Piwik_Query('DELETE FROM ' . Piwik_Common::prefixTable('user_dashboard') . ' WHERE login = ?', array($userLogin));
+ }
+
public function install()
{
// we catch the exception
try{
- $sql = "CREATE TABLE ". Piwik::prefixTable('user_dashboard')." (
+ $sql = "CREATE TABLE ". Piwik_Common::prefixTable('user_dashboard')." (
login VARCHAR( 100 ) NOT NULL ,
iddashboard INT NOT NULL ,
layout TEXT NOT NULL,
PRIMARY KEY ( login , iddashboard )
) DEFAULT CHARSET=utf8 " ;
Piwik_Exec($sql);
- } catch(Zend_Db_Statement_Exception $e){
+ } catch(Exception $e){
// mysql code error 1050:table already exists
// see bug #153 http://dev.piwik.org/trac/ticket/153
if(!Zend_Registry::get('db')->isErrNo($e, '1050'))
@@ -72,7 +77,7 @@ class Piwik_Dashboard extends Piwik_Plugin
public function uninstall()
{
- $sql = "DROP TABLE ". Piwik::prefixTable('user_dashboard') ;
+ $sql = "DROP TABLE ". Piwik_Common::prefixTable('user_dashboard') ;
Piwik_Exec($sql);
}
diff --git a/plugins/Dashboard/templates/Dashboard.js b/plugins/Dashboard/templates/Dashboard.js
index 73f15ecb04..74d81ec3b7 100644
--- a/plugins/Dashboard/templates/Dashboard.js
+++ b/plugins/Dashboard/templates/Dashboard.js
@@ -79,15 +79,30 @@ dashboard.prototype =
// load all widgets
$('.widget', self.dashboardElement).each( function() {
var uniqueId = $(this).attr('id');
- function onWidgetLoadedReplaceElementWithContent(loadedContent)
- {
- $('#'+uniqueId+'>.widgetContent', self.dashboardElement).html(loadedContent);
- }
- widget = widgetsHelper.getWidgetObjectFromUniqueId(uniqueId);
- widgetParameters = widget["parameters"];
- $.ajax(widgetsHelper.getLoadWidgetAjaxRequest(uniqueId, widgetParameters, onWidgetLoadedReplaceElementWithContent));
+ self.reloadWidget(uniqueId);
});
},
+
+ reloadEnclosingWidget: function(domNodeInsideWidget)
+ {
+ var uniqueId = $(domNodeInsideWidget).parents('.widget').attr('id');
+ this.reloadWidget(uniqueId);
+ },
+
+ reloadWidget: function(uniqueId)
+ {
+ function onWidgetLoadedReplaceElementWithContent(loadedContent)
+ {
+ $('#'+uniqueId+'>.widgetContent', self.dashboardElement).html(loadedContent);
+ }
+ widget = widgetsHelper.getWidgetObjectFromUniqueId(uniqueId);
+ if(widget == false)
+ {
+ return;
+ }
+ widgetParameters = widget["parameters"];
+ $.ajax(widgetsHelper.getLoadWidgetAjaxRequest(uniqueId, widgetParameters, onWidgetLoadedReplaceElementWithContent));
+ },
addDummyWidgetAtBottomOfColumn: function(columnNumber)
{
@@ -109,13 +124,14 @@ dashboard.prototype =
}
columnElement = $(self.dashboardColumnsElement[columnNumber]);
emptyWidgetContent = '<div class="sortable">'+
- widgetsHelper.getEmptyWidgetHtml(uniqueId, widgetName, _pk_translate('Dashboard_LoadingWidget_js'))+
+ widgetsHelper.getEmptyWidgetHtml(uniqueId, widgetName)+
'</div>';
if(addWidgetOnTop) {
columnElement.prepend(emptyWidgetContent);
} else {
columnElement.append(emptyWidgetContent);
}
+
widgetElement = $('#'+ uniqueId);
widgetElement
.hover( function() {
@@ -141,10 +157,14 @@ dashboard.prototype =
{
var self = this;
- function onStart() {
+ function onStart(event, ui) {
+ if(!jQuery.support.noCloneEvent) {
+ $('object', this).hide();
+ }
}
function onStop(event, ui) {
+ $('object', this).show();
$('.widgetHover', this).removeClass('widgetHover');
$('.widgetTopHover', this).removeClass('widgetTopHover');
$('.button#close', this).hide();
@@ -161,7 +181,7 @@ dashboard.prototype =
forcePlaceholderSize: true,
placeholder: 'hover',
handle: '.widgetTop',
- helper: 'original',
+ helper: 'clone',
start: onStart,
stop: onStop
});
@@ -221,7 +241,7 @@ dashboard.prototype =
var ajaxRequest =
{
type: 'POST',
- url: 'index.php?module=Dashboard&action=saveLayout',
+ url: 'index.php?module=Dashboard&action=saveLayout&token_auth='+piwik.token_auth,
dataType: 'html',
async: true,
error: piwikHelper.ajaxHandleError,
diff --git a/plugins/Dashboard/templates/dashboard.css b/plugins/Dashboard/templates/dashboard.css
index 7c78adcbcb..2551c8cff7 100644
--- a/plugins/Dashboard/templates/dashboard.css
+++ b/plugins/Dashboard/templates/dashboard.css
@@ -18,14 +18,21 @@
margin-right: 5px;
margin-left: 5px;
overflow: hidden;
+ -moz-border-radius:4px;
+ -webkit-border-radius:4px;
}
.widgetHover {
border: 1px solid #CBD3E7;
}
+.widgetContent h2 {
+ font-size:1.2em;
+}
.widgetTop {
background: #F0F0FA;
+ -moz-border-radius:4px 4px 0 0;
+ -webkit-border-radius:4px 4px 0 0;
border-bottom: 1px solid #D2D9EB;
width: 100%;
cursor: move;
diff --git a/plugins/Dashboard/templates/index.tpl b/plugins/Dashboard/templates/index.tpl
index faf0a11323..ae957e33f7 100644
--- a/plugins/Dashboard/templates/index.tpl
+++ b/plugins/Dashboard/templates/index.tpl
@@ -1,56 +1,32 @@
{loadJavascriptTranslations plugins='CoreHome Dashboard'}
<script type="text/javascript">
-{if !empty($layout) }
piwik.dashboardLayout = {$layout};
-{else}
-{literal}
- piwik.dashboardLayout =
- [
- [
- {"uniqueId":"widgetVisitsSummarygetEvolutionGraph","parameters":{"module":"VisitsSummary","action":"getEvolutionGraph","columns":["nb_visits"]}},
- {"uniqueId":"widgetVisitorInterestgetNumberOfVisitsPerVisitDuration","parameters":{"module":"VisitorInterest","action":"getNumberOfVisitsPerVisitDuration"}},
- {"uniqueId":"widgetUserSettingsgetBrowser","parameters":{"module":"UserSettings","action":"getBrowser"}},
- {"uniqueId":"widgetUserCountrygetCountry","parameters":{"module":"UserCountry","action":"getCountry"}},
- {"uniqueId":"widgetExampleFeedburnerfeedburner","parameters":{"module":"ExampleFeedburner","action":"feedburner"}}
- ],
- [
- {"uniqueId":"widgetReferersgetKeywords","parameters":{"module":"Referers","action":"getKeywords"}},
- {"uniqueId":"widgetReferersgetWebsites","parameters":{"module":"Referers","action":"getWebsites"}}
- ],
- [
- {"uniqueId":"widgetReferersgetSearchEngines","parameters":{"module":"Referers","action":"getSearchEngines"}},
- {"uniqueId":"widgetVisitTimegetVisitInformationPerServerTime","parameters":{"module":"VisitTime","action":"getVisitInformationPerServerTime"}},
- {"uniqueId":"widgetExampleRssWidgetrssPiwik","parameters":{"module":"ExampleRssWidget","action":"rssPiwik"}}
- ]
- ];
-{/literal}
{*
the old dashboard layout style is:
piwik.dashboardLayout = 'VisitsSummary.getEvolutionGraph~VisitorInterest.getNumberOfVisitsPerVisitDuration~UserSettings.getBrowser~ExampleFeedburner.feedburner|Referers.getKeywords~Referers.getWebsites|Referers.getSearchEngines~VisitTime.getVisitInformationPerServerTime~ExampleRssWidget.rssPiwik|';
*}
-{/if}
-piwik.availableWidgets = {$availableWidgets};
+ piwik.availableWidgets = {$availableWidgets};
</script>
{literal}
<script type="text/javascript">
$(document).ready( function() {
- var dashboardObject = new dashboard();
- var widgetMenuObject = new widgetMenu(dashboardObject);
- dashboardObject.init(piwik.dashboardLayout);
+ piwik.dashboardObject = new dashboard();
+ var widgetMenuObject = new widgetMenu(piwik.dashboardObject);
+ piwik.dashboardObject.init(piwik.dashboardLayout);
widgetMenuObject.init();
- $('.button#addWidget').click(function(){widgetMenuObject.show();});
+ $('#addWidget.button').click(function(){widgetMenuObject.show();});
});
</script>
{/literal}
<div id="dashboard">
<div class="dialog" id="confirm">
- <img src="themes/default/images/delete.png" style="padding: 10px; position: relative; margin-top: 10%; float: left;"/>
+ <img src="themes/default/images/delete.png" style="padding: 10px; position: relative; margin-top: 10%; float: left;" />
<p>{'Dashboard_DeleteWidgetConfirm'|translate}</p>
- <input id="yes" type="button" value="{'General_Yes'|translate}"/>
- <input id="no" type="button" value="{'General_No'|translate}"/>
+ <input id="yes" type="button" value="{'General_Yes'|translate}" />
+ <input id="no" type="button" value="{'General_No'|translate}" />
</div>
<div class="button" id="addWidget">
@@ -58,7 +34,7 @@ $(document).ready( function() {
</div>
<div class="menu" id="widgetChooser">
- <div id="closeMenuIcon"><img src="themes/default/images/close_medium.png" title="{'General_Close'|translate}"/></div>
+ <div id="closeMenuIcon"><img src="themes/default/images/close_medium.png" title="{'General_Close'|translate}" /></div>
<div id="menuTitleBar">{'Dashboard_SelectWidget'|translate}</div>
<div class="subMenu" id="sub1"></div>
diff --git a/plugins/Dashboard/templates/widgetMenu.js b/plugins/Dashboard/templates/widgetMenu.js
index 6556b9085f..997c87158f 100644
--- a/plugins/Dashboard/templates/widgetMenu.js
+++ b/plugins/Dashboard/templates/widgetMenu.js
@@ -55,7 +55,7 @@ widgetsHelper.getLoadWidgetAjaxRequest = function (widgetUniqueId, widgetParamet
return ajaxRequest;
};
-widgetsHelper.getEmptyWidgetHtml = function (uniqueId, widgetName, widgetLoadingString)
+widgetsHelper.getEmptyWidgetHtml = function (uniqueId, widgetName)
{
return '<div id="'+uniqueId+'" class="widget">'+
'<div class="widgetTop">'+
@@ -66,7 +66,7 @@ widgetsHelper.getEmptyWidgetHtml = function (uniqueId, widgetName, widgetLoading
'</div>'+
'<div class="widgetContent">'+
'<div class="widgetLoading">'+
- widgetLoadingString +
+ _pk_translate('Dashboard_LoadingWidget_js') +
'</div>'+
'</div>'+
'</div>';
@@ -194,10 +194,7 @@ widgetMenu.prototype =
widgetUniqueId,
'<div title="'+_pk_translate("Dashboard_AddPreviewedWidget_js")+'">'+
_pk_translate('Dashboard_WidgetPreview_js')+
- '</div>',
- '<span id="loadingPiwik">'+
- '<img src="themes/default/images/loading-blue.gif"> ' +_pk_translate('Dashboard_LoadingWidget_js') +
- '</span>'
+ '</div>'
);
$('#sub3').html(emptyWidgetHtml);
@@ -231,6 +228,7 @@ widgetMenu.prototype =
self.filterOutAlreadyLoadedWidget();
$.blockUI({
message: self.menuElement,
+ centerY: 0,
css: {width:'', top: '5%',left:'10%', right:'10%', margin:"0px", textAlign:'', cursor:'', border:'0px'}
});
}
@@ -309,7 +307,7 @@ widgetMenu.prototype =
);
$.extend($.blockUI.defaults.overlayCSS, { backgroundColor: '#000000', opacity: '0.4'});
$.extend($.blockUI.defaults,{ fadeIn: 0, fadeOut: 0 });
- $(window).keydown( function(e) {
+ $(document).keydown( function(e) {
var key = e.keyCode || e.which;
if(key == 27) {
self.hideMenu();
diff --git a/plugins/ExampleAPI/ExampleAPI.php b/plugins/ExampleAPI/ExampleAPI.php
index aaddcfe89b..271b58c9ab 100644
--- a/plugins/ExampleAPI/ExampleAPI.php
+++ b/plugins/ExampleAPI/ExampleAPI.php
@@ -19,15 +19,18 @@ class Piwik_ExampleAPI extends Piwik_Plugin
{
/**
* Return information about this plugin.
+ *
+ * @see Piwik_Plugin
+ *
* @return array
*/
public function getInformation()
{
return array(
- 'name' => 'Example API',
- 'description' => 'Example Plugin: How to create an API for your plugin, to export your data in multiple formats without any special coding? Visit the <a href="index.php?module=API&action=listAllAPI#ExampleAPI">ExampleAPI example methods</a>.',
+ 'description' => Piwik_Translate('ExampleAPI_PluginDescription'),
+ 'homepage' => 'index.php?module=API&action=listAllAPI#ExampleAPI',
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
+ 'author_homepage' => 'http://piwik.org/',
'version' => '0.1',
);
}
diff --git a/plugins/ExampleFeedburner/ExampleFeedburner.php b/plugins/ExampleFeedburner/ExampleFeedburner.php
index 5a1458e13f..ca7b582ce1 100644
--- a/plugins/ExampleFeedburner/ExampleFeedburner.php
+++ b/plugins/ExampleFeedburner/ExampleFeedburner.php
@@ -16,13 +16,19 @@
*/
class Piwik_ExampleFeedburner extends Piwik_Plugin
{
+ /**
+ * Return information about this plugin.
+ *
+ * @see Piwik_Plugin
+ *
+ * @return array
+ */
public function getInformation()
{
return array(
- 'name' => 'Example Feedburner',
- 'description' => 'Example Plugin: How to display your Feedburner subscriber in a Widget in the Dashboard?',
+ 'description' => Piwik_Translate('ExampleFeedburner_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
+ 'author_homepage' => 'http://piwik.org/',
'version' => '0.1',
);
}
@@ -30,8 +36,8 @@ class Piwik_ExampleFeedburner extends Piwik_Plugin
function install()
{
try{
- Piwik_Exec('ALTER TABLE '.Piwik::prefixTable('site'). " ADD `feedburnerName` VARCHAR( 100 ) DEFAULT NULL");
- } catch(Zend_Db_Statement_Exception $e){
+ Piwik_Exec('ALTER TABLE '.Piwik_Common::prefixTable('site'). " ADD `feedburnerName` VARCHAR( 100 ) DEFAULT NULL");
+ } catch(Exception $e){
// mysql code error 1060: column already exists
// if there is another error we throw the exception, otherwise it is OK as we are simply reinstalling the plugin
if(!Zend_Registry::get('db')->isErrNo($e, '1060'))
@@ -43,7 +49,7 @@ class Piwik_ExampleFeedburner extends Piwik_Plugin
function uninstall()
{
- Piwik_Query('ALTER TABLE '.Piwik::prefixTable('site'). " DROP `feedburnerName`");
+ Piwik_Query('ALTER TABLE '.Piwik_Common::prefixTable('site'). " DROP `feedburnerName`");
}
}
@@ -64,7 +70,7 @@ class Piwik_ExampleFeedburner_Controller extends Piwik_Controller
{
$view = Piwik_View::factory('feedburner');
$idSite = Piwik_Common::getRequestVar('idSite',1,'int');
- $feedburnerFeedName = Piwik_FetchOne('SELECT feedburnerName FROM '.Piwik::prefixTable('site').
+ $feedburnerFeedName = Piwik_FetchOne('SELECT feedburnerName FROM '.Piwik_Common::prefixTable('site').
' WHERE idsite = ?', $idSite );
if(empty($feedburnerFeedName))
{
@@ -72,9 +78,63 @@ class Piwik_ExampleFeedburner_Controller extends Piwik_Controller
}
$view->feedburnerFeedName = $feedburnerFeedName;
$view->idSite = $idSite;
+ $view->fbStats = $this->getFeedData($feedburnerFeedName);
echo $view->render();
}
+
+ /**
+ * Returns array of counts and images based on Feedburner URI
+ *
+ * @param string $uri
+ * @return array()
+ */
+ protected function getFeedData($uri)
+ {
+ // Awareness API only supports yesterday and back;
+ // we get stats for previous two days;
+ // @see http://code.google.com/apis/feedburner/awareness_api.html#dates
+ $yesterday = Piwik_Date::factory('-1 day', 'America/Los_Angeles');
+ $beforeYesterday = Piwik_Date::factory('-2 day', 'America/Los_Angeles');
+
+ //create url to gather XML feed from
+ $url = 'https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri='.$uri.'&dates='.$beforeYesterday->toString().','.$yesterday->toString();
+ $data = '';
+ try {
+ $data = Piwik_Http::sendHttpRequest($url, 5);
+ $xml = new SimpleXMLElement($data);
+ } catch(Exception $e) {
+ return "Error parsing the data for feed $uri. Fetched data was: \n'". $data."'";
+ }
+
+ if(count($xml->feed->entry) != 2) {
+ return "Error fetching the Feedburner stats. Expected XML, Got: \n" . strip_tags($data);
+ }
+ $data = array();
+ $i = 0;
+ foreach($xml->feed->entry as $feedDay){
+ $data[0][$i] = (int)$feedDay['circulation'];
+ $data[1][$i] = (int)$feedDay['hits'];
+ $data[2][$i] = (int)$feedDay['reach'];
+ $i++;
+ }
+
+ foreach($data as $key => $value) {
+ if( $value[0] == $value[1]) {
+ $img = 'stop.png';
+ } else if($value[0] < $value[1]) {
+ $img = 'arrow_up.png';
+ } else {
+ $img = 'arrow_down.png';
+ }
+
+ $prefixImage = '<img alt="" src="./plugins/MultiSites/images/';
+ $suffixImage = '" />';
+ $data[$key][2] = $prefixImage . $img . $suffixImage;
+ }
+ return $data;
+ }
+
/**
* Function called to save the Feedburner ID entered in the form
*
@@ -84,7 +144,7 @@ class Piwik_ExampleFeedburner_Controller extends Piwik_Controller
// we save the value in the DB for an authenticated user
if(Piwik::getCurrentUserLogin() != 'anonymous')
{
- Piwik_Query('UPDATE '.Piwik::prefixTable('site').'
+ Piwik_Query('UPDATE '.Piwik_Common::prefixTable('site').'
SET feedburnerName = ? WHERE idsite = ?',
array(Piwik_Common::getRequestVar('name','','string'), Piwik_Common::getRequestVar('idSite',1,'int'))
);
diff --git a/plugins/ExampleFeedburner/templates/feedburner.tpl b/plugins/ExampleFeedburner/templates/feedburner.tpl
index e0cb2e6747..812dcdc23e 100644
--- a/plugins/ExampleFeedburner/templates/feedburner.tpl
+++ b/plugins/ExampleFeedburner/templates/feedburner.tpl
@@ -1,37 +1,57 @@
<script type="text/javascript">
var idSite = {$idSite};
-
{literal}
$(document).ready(function(){
-
function getName()
{
return $("#feedburnerName").val();
}
- function loadIframe()
- {
- var feedburnerName = getName();
- $("#feedburnerIframe").html(
- '<iframe height=100px frameborder="0" marginheight="10" marginwidth="10" \
- src="http://www.feedburner.com/fb/ticker/api-ticker2.jsp?uris='+feedburnerName+'"></iframe>');
- }
-
$("#feedburnerSubmit").click( function(){
var feedburnerName = getName();
- $.get('index.php?module=ExampleFeedburner&action=saveFeedburnerName&idSite='+idSite+'&name='+feedburnerName);
- loadIframe();
-
+ $.get('?module=ExampleFeedburner&action=saveFeedburnerName&idSite='+idSite+'&name='+feedburnerName);
+ piwik.dashboardObject.reloadEnclosingWidget($(this));
});
-
- loadIframe();
});
</script>
-{/literal}
-<span id="feedburnerIframe"></span>
+<style>
+.metric { font-weight:bold;text-align:left; }
+.feedburner td { padding:0px 3px; }
+</style>
+{/literal}
+
+{if !is_array($fbStats)}
+ {$fbStats}
+{else}
+<table class='feedburner' align="center" cellpadding="2" style='text-align:center'>
+ <tr>
+ <td></td>
+ <td style="text-decoration:underline;">Previous</td>
+ <td style="text-decoration:underline;">Yesterday</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class='metric'>Circulation</td>
+ <td>{$fbStats[0][0]}</td>
+ <td>{$fbStats[0][1]}</td>
+ <td>{$fbStats[0][2]}</td>
+ </tr>
+ <tr>
+ <td class='metric'>Hits</td>
+ <td>{$fbStats[1][0]}</td>
+ <td>{$fbStats[1][1]}</td>
+ <td>{$fbStats[1][2]}</td>
+ </tr>
+ <tr>
+ <td class='metric'>Reach</td>
+ <td>{$fbStats[2][0]}</td>
+ <td>{$fbStats[2][1]}</td>
+ <td>{$fbStats[2][2]}</td>
+ </tr>
+</table>
+{/if}
<center>
-<input id="feedburnerName" type="text" value="{$feedburnerFeedName}">
-<input id="feedburnerSubmit" type="submit" value="ok">
+<input id="feedburnerName" type="text" value="{$feedburnerFeedName}" />
+<input id="feedburnerSubmit" type="submit" value="ok" />
</center>
-
diff --git a/plugins/ExamplePlugin/ExamplePlugin.php b/plugins/ExamplePlugin/ExamplePlugin.php
index 3891cc54fd..e0a500d617 100644
--- a/plugins/ExamplePlugin/ExamplePlugin.php
+++ b/plugins/ExamplePlugin/ExamplePlugin.php
@@ -16,13 +16,19 @@
*/
class Piwik_ExamplePlugin extends Piwik_Plugin
{
+ /**
+ * Return information about this plugin.
+ *
+ * @see Piwik_Plugin
+ *
+ * @return array
+ */
public function getInformation()
{
return array(
- 'name' => 'Example Plugin',
- 'description' => 'Example Plugin: This plugin shows how to create a very simple plugin, that exports two widgets in the Dashboard.',
+ 'description' => Piwik_Translate('ExamplePlugin_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
+ 'author_homepage' => 'http://piwik.org/',
'version' => '0.1',
'translationAvailable' => true,
);
@@ -79,9 +85,9 @@ class Piwik_ExamplePlugin_Controller extends Piwik_Controller
*/
function exampleWidget()
{
- echo "Hello world! <br> You can output whatever you want in widgets, and put them on dashboard or everywhere on the web (in your blog, website, etc.).
- <br>Widgets can include graphs, tables, flash, text, images, etc.
- <br>It's very easy to create a new plugin and widgets in Piwik. Have a look at this example file (/plugins/ExamplePlugin/ExamplePlugin.php).
+ echo "Hello world! <br /> You can output whatever you want in widgets, and put them on dashboard or everywhere on the web (in your blog, website, etc.).
+ <br />Widgets can include graphs, tables, flash, text, images, etc.
+ <br />It's very easy to create a new plugin and widgets in Piwik. Have a look at this example file (/plugins/ExamplePlugin/ExamplePlugin.php).
<div id='happycoding'><i>Happy coding!</i></div>
<div id='jsenabled'>You can easily use Jquery in widgets</div>
<script type=\"text/javascript\">$('#happycoding').hide().fadeIn(5000);$('#jsenabled').hide().css({'color':'red'}).fadeIn(10000);</script>";
@@ -97,7 +103,7 @@ class Piwik_ExamplePlugin_Controller extends Piwik_Controller
function photostreamMatt()
{
- echo '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" type="application/x-shockwave-flash" width="400px" height="343px" id="InsertWidget_35ba729b-1935-4165-a818-f17e7c9b4748" align="middle"><param name="movie" value="http://widgetserver.com/syndication/flash/wrapper/InsertWidget.swf"/><param name="quality" value="high" /><param name="wmode" value="transparent" /><param name="menu" value="false" /><param name="flashvars" value="r=2&appId=35ba729b-1935-4165-a818-f17e7c9b4748" /> <embed src="http://widgetserver.com/syndication/flash/wrapper/InsertWidget.swf" name="InsertWidget_35ba729b-1935-4165-a818-f17e7c9b4748" width="400px" height="343px" quality="high" menu="false" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" wmode="transparent" align="middle" flashvars="r=2&appId=35ba729b-1935-4165-a818-f17e7c9b4748" /></object>';
+ echo '<iframe align=center src=http://www.flickr.com/slideShow/index.gne?user_id=34965144@N00&set_id=72157602308487455 frameBorder=0 width=380 scrolling=no height=500></iframe> ';
}
/**
@@ -108,57 +114,71 @@ class Piwik_ExamplePlugin_Controller extends Piwik_Controller
function index()
{
$out = '';
- $out .= '<i>This page aims to list the different functions you can use when programming plugins for Piwik.</i><br>';
- $out .= '<b>Be careful, the following APIs may change in the near future as Piwik is still in development.</b><br>';
+ $out .= '<i>This page aims to list the different functions you can use when programming plugins for Piwik.</i><br />';
+ $out .= '<b>Be careful, the following APIs may change in the near future as Piwik is still in development.</b><br />';
$out .= '<h2>General</h2>';
$out .= '<h3>Accessible from your plugin controller</h3>';
- $out .= '<code>$this->date</code> = current selected <b>Piwik_Date</b> object (<a href="http://dev.piwik.org/trac/browser/trunk/core/Date.php">class</a>)<br/>';
- $out .= '<code>$period = Piwik_Common::getRequestVar("period");</code> - Get the current selected period<br/>';
- $out .= '<code>$idSite = Piwik_Common::getRequestVar("idSite");</code> - Get the selected idSite<br/>';
- $out .= '<code>$site = new Piwik_Site($idSite);</code> - Build the Piwik_Site object (<a href="http://dev.piwik.org/trac/browser/trunk/core/Site.php">class</a>)<br/>';
- $out .= '<code>$this->str_date</code> = current selected date in YYYY-MM-DD format<br/>';
+ $out .= '<code>$this->date</code> = current selected <b>Piwik_Date</b> object (<a href="http://dev.piwik.org/trac/browser/trunk/core/Date.php">class</a>)<br />';
+ $out .= '<code>$period = Piwik_Common::getRequestVar("period");</code> - Get the current selected period<br />';
+ $out .= '<code>$idSite = Piwik_Common::getRequestVar("idSite");</code> - Get the selected idSite<br />';
+ $out .= '<code>$site = new Piwik_Site($idSite);</code> - Build the Piwik_Site object (<a href="http://dev.piwik.org/trac/browser/trunk/core/Site.php">class</a>)<br />';
+ $out .= '<code>$this->str_date</code> = current selected date in YYYY-MM-DD format<br />';
$out .= '<h3>Misc</h3>';
- $out .= '<code>Piwik_AddMenu( $mainMenuName, $subMenuName, $url );</code> - Adds an entry to the menu in the Piwik interface (See the example in the <a href="http://dev.piwik.org/trac/browser/trunk/plugins/UserCountry/UserCountry.php#L146">UserCountry Plugin file</a>)<br/>';
- $out .= '<code>Piwik_AddWidget( $widgetCategory, $widgetName, $controllerName, $controllerAction, $customParameters = array());</code> - Adds a widget that users can add in the dashboard, or export using the Widgets link at the top of the screen. See the example in the <a href="http://dev.piwik.org/trac/browser/trunk/plugins/UserCountry/UserCountry.php#L143">UserCountry Plugin file</a> or any other plugin)<br/>';
- $out .= '<code>Piwik::prefixTable("site")</code> = <b>' . Piwik::prefixTable("site") . '</b><br/>';
+ $out .= '<code>Piwik_AddMenu( $mainMenuName, $subMenuName, $url );</code> - Adds an entry to the menu in the Piwik interface (See the example in the <a href="http://dev.piwik.org/trac/browser/trunk/plugins/UserCountry/UserCountry.php#L146">UserCountry Plugin file</a>)<br />';
+ $out .= '<code>Piwik_AddWidget( $widgetCategory, $widgetName, $controllerName, $controllerAction, $customParameters = array());</code> - Adds a widget that users can add in the dashboard, or export using the Widgets link at the top of the screen. See the example in the <a href="http://dev.piwik.org/trac/browser/trunk/plugins/UserCountry/UserCountry.php#L143">UserCountry Plugin file</a> or any other plugin)<br />';
+ $out .= '<code>Piwik_Common::prefixTable("site")</code> = <b>' . Piwik_Common::prefixTable("site") . '</b><br />';
$out .= '<h2>User access</h2>';
- $out .= '<code>Piwik::getCurrentUserLogin()</code> = <b>' . Piwik::getCurrentUserLogin() . '</b><br/>';
- $out .= '<code>Piwik::isUserHasSomeAdminAccess()</code> = <b>' . self::boolToString(Piwik::isUserHasSomeAdminAccess()) . '</b><br/>';
- $out .= '<code>Piwik::isUserHasAdminAccess( array $idSites = array(1,2) )</code> = <b>' . self::boolToString(Piwik::isUserHasAdminAccess(array(1,2) )) . '</b><br/>';
- $out .= '<code>Piwik::isUserHasViewAccess( array $idSites = array(1) ) </code> = <b>' . self::boolToString(Piwik::isUserHasViewAccess(array(1))) . '</b><br/>';
- $out .= '<code>Piwik::isUserIsSuperUser()</code> = <b>' . self::boolToString(Piwik::isUserIsSuperUser()) . '</b><br/>';
+ $out .= '<code>Piwik::getCurrentUserLogin()</code> = <b>' . Piwik::getCurrentUserLogin() . '</b><br />';
+ $out .= '<code>Piwik::isUserHasSomeAdminAccess()</code> = <b>' . self::boolToString(Piwik::isUserHasSomeAdminAccess()) . '</b><br />';
+ $out .= '<code>Piwik::isUserHasAdminAccess( array $idSites = array(1,2) )</code> = <b>' . self::boolToString(Piwik::isUserHasAdminAccess(array(1,2) )) . '</b><br />';
+ $out .= '<code>Piwik::isUserHasViewAccess( array $idSites = array(1) ) </code> = <b>' . self::boolToString(Piwik::isUserHasViewAccess(array(1))) . '</b><br />';
+ $out .= '<code>Piwik::isUserIsSuperUser()</code> = <b>' . self::boolToString(Piwik::isUserIsSuperUser()) . '</b><br />';
$out .= '<h2>Execute SQL queries</h2>';
- $txtQuery = "SELECT token_auth FROM ".Piwik::prefixTable('user')." WHERE login = ?";
+ $txtQuery = "SELECT token_auth FROM ".Piwik_Common::prefixTable('user')." WHERE login = ?";
$result = Piwik_FetchOne($txtQuery, array('anonymous'));
- $out .= '<code>Piwik_FetchOne("'.$txtQuery.'", array("anonymous"))</code> = <b>' . var_export($result,true) . '</b><br/>';
- $out .= '<br>';
+ $out .= '<code>Piwik_FetchOne("'.$txtQuery.'", array("anonymous"))</code> = <b>' . var_export($result,true) . '</b><br />';
+ $out .= '<br />';
$query = Piwik_Query($txtQuery, array('anonymous'));
$fetched = $query->fetch();
$token_auth = $fetched['token_auth'];
- $out .= '<code>$query = Piwik_Query("'.$txtQuery.'", array("anonymous"))</code><br>';
- $out .= '<code>$fetched = $query->fetch();</code><br>';
- $out .= 'At this point, we have: <code>$fetched[\'token_auth\'] == <b>'.var_export($token_auth,true) . '</b></code><br/>';
+ $out .= '<code>$query = Piwik_Query("'.$txtQuery.'", array("anonymous"))</code><br />';
+ $out .= '<code>$fetched = $query->fetch();</code><br />';
+ $out .= 'At this point, we have: <code>$fetched[\'token_auth\'] == <b>'.var_export($token_auth,true) . '</b></code><br />';
$out .= '<h2>Example Sites information API</h2>';
- $out .= '<code>Piwik_SitesManager_API::getSitesWithViewAccess()</code> = <b><pre>' .var_export(Piwik_SitesManager_API::getSitesWithViewAccess(),true) . '</pre></b><br/>';
- $out .= '<code>Piwik_SitesManager_API::getSitesWithAdminAccess()</code> = <b><pre>' .var_export(Piwik_SitesManager_API::getSitesWithAdminAccess(),true) . '</pre></b><br/>';
+ $out .= '<code>Piwik_SitesManager_API::getInstance()->getSitesWithViewAccess()</code> = <b><pre>' .var_export(Piwik_SitesManager_API::getInstance()->getSitesWithViewAccess(),true) . '</pre></b><br />';
+ $out .= '<code>Piwik_SitesManager_API::getInstance()->getSitesWithAdminAccess()</code> = <b><pre>' .var_export(Piwik_SitesManager_API::getInstance()->getSitesWithAdminAccess(),true) . '</pre></b><br />';
$out .= '<h2>Example API Users information</h2>';
- $out .= 'View the list of API methods you can call on <a href="http://dev.piwik.org/trac/wiki/API/Reference#Methods">API reference</a><br/>';
- $out .= 'For example you can try <code>Piwik_UsersManager_API::getUsersSitesFromAccess("view");</code> or <code>Piwik_UsersManager_API::deleteUser("userToDelete");</code><br/>';
+ $out .= 'View the list of API methods you can call on <a href="http://dev.piwik.org/trac/wiki/API/Reference#Methods">API reference</a><br />';
+ $out .= 'For example you can try <code>Piwik_UsersManager_API::getInstance()->getUsersSitesFromAccess("view");</code> or <code>Piwik_UsersManager_API::getInstance()->deleteUser("userToDelete");</code><br />';
+
+ $out .= '<h2>Javascript in Piwik</h2>';
+ $out .= '<h3>i18n internationalization</h3>';
+ $out .= 'In order to translate strings within Javascript code, you can use the javascript function _pk_translate( token );.
+ <ul><li>The "token" parameter is the string unique key found in the translation file. For this token string to be available in Javascript, you must
+ suffix your token by "_js" in the language file. For example, you can add <code>\'Goals_AddGoal_js\' => \'Add Goal\',</code> in the lang/en.php file</li>
+ <li>You then need to instruct Piwik to load your Javascript translations for your plugin; by default, all translation strings are not loaded in Javascript for performance reasons. This can be done by calling the Smarty modifier before any your javascript includes that would be using the translations, eg.
+ <code>{loadJavascriptTranslations plugins=\'$YOUR_PLUGIN_NAME\'}</code>. In our previous example, the $YOUR_PLUGIN_NAME being Goals, we would write <code>{loadJavascriptTranslations plugins=\'Goals\'}</code>
+ </li><li>You can then print this string from your JS code by doing <code>_pk_translate(\'Goals_AddGoal_js\');</code>.
+ </li></ul>';
+
+ $out .= '<h3>Reload a widget in the dashboard</h3>';
+ $out .= 'It is sometimes useful to reload one widget in the dashboard (for example, every 20 seconds for a real time widget, or after a setting change).
+ You can easily force your widget to reload in the dashboard by calling the helper function <code>piwik.dashboardObject.reloadEnclosingWidget($(this));</code>.';
$out .= '<h2>Smarty plugins</h2>';
- $out .= 'There are some builtin plugins for Smarty especially developped for Piwik. <br>
- You can find them on the <a href="http://dev.piwik.org/trac/browser/trunk/core/SmartyPlugins">SVN at /trunk/core/SmartyPlugins</a>. <br>
- More documentation to come about smarty plugins.<br/>';
+ $out .= 'There are some builtin plugins for Smarty especially developped for Piwik. <br />
+ You can find them on the <a href="http://dev.piwik.org/trac/browser/trunk/core/SmartyPlugins">SVN at /trunk/core/SmartyPlugins</a>. <br />
+ More documentation to come about smarty plugins.<br />';
echo $out;
}
diff --git a/plugins/ExamplePlugin/lang/en.php b/plugins/ExamplePlugin/lang/en.php
index 9fcf727fd0..9d2ee29350 100644
--- a/plugins/ExamplePlugin/lang/en.php
+++ b/plugins/ExamplePlugin/lang/en.php
@@ -11,6 +11,7 @@
*/
$translations = array(
+ 'ExamplePlugin_PluginDescription' => 'Example Plugin: This plugin shows how to create a very simple plugin, that exports two widgets in the Dashboard.',
'ExamplePlugin_exampleWidgets' => 'Example Widgets',
'ExamplePlugin_exampleWidget' => 'Example widget',
'ExamplePlugin_blogPiwikRss' => 'Blog Piwik RSS',
diff --git a/plugins/ExampleRssWidget/ExampleRssWidget.php b/plugins/ExampleRssWidget/ExampleRssWidget.php
index 7c583cefa3..f36f850e7e 100644
--- a/plugins/ExampleRssWidget/ExampleRssWidget.php
+++ b/plugins/ExampleRssWidget/ExampleRssWidget.php
@@ -16,13 +16,19 @@
*/
class Piwik_ExampleRssWidget extends Piwik_Plugin
{
+ /**
+ * Return information about this plugin.
+ *
+ * @see Piwik_Plugin
+ *
+ * @return array
+ */
public function getInformation()
{
return array(
- 'name' => 'Example Rss Widget',
- 'description' => 'Example Plugin: How to create a new widget that reads a RSS feed?',
+ 'description' => Piwik_Translate('ExampleRssWidget_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
+ 'author_homepage' => 'http://piwik.org/',
'version' => '0.1',
);
}
diff --git a/plugins/ExampleUI/API.php b/plugins/ExampleUI/API.php
index 1a606d0f16..8d741a8c2b 100644
--- a/plugins/ExampleUI/API.php
+++ b/plugins/ExampleUI/API.php
@@ -26,11 +26,11 @@ class Piwik_ExampleUI_API
return self::$instance;
}
- function getTemperaturesEvolution($date, $period)
+ public function getTemperaturesEvolution($date, $period)
{
$period = new Piwik_Period_Range($period, 'last30');
- $dateStart = $period->getDateStart()->get('Y-m-d'); // eg. "2009-04-01"
- $dateEnd = $period->getDateEnd()->get('Y-m-d'); // eg. "2009-04-30"
+ $dateStart = $period->getDateStart()->toString('Y-m-d'); // eg. "2009-04-01"
+ $dateEnd = $period->getDateEnd()->toString('Y-m-d'); // eg. "2009-04-30"
// here you could select from your custom table in the database, eg.
$query = "SELECT AVG(temperature)
@@ -56,7 +56,7 @@ class Piwik_ExampleUI_API
}
// we generate an array of random server temperatures
- function getTemperatures()
+ public function getTemperatures()
{
$xAxis = array(
'0h', '1h', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', '10h', '11h',
@@ -75,7 +75,7 @@ class Piwik_ExampleUI_API
return $dataTable;
}
- function getPlanetRatios()
+ public function getPlanetRatios()
{
$planetRatios = array(
'Mercury' => 0.382,
@@ -93,7 +93,7 @@ class Piwik_ExampleUI_API
return $dataTable;
}
- function getPlanetRatiosWithLogos()
+ public function getPlanetRatiosWithLogos()
{
$planetsDataTable = $this->getPlanetRatios();
foreach($planetsDataTable->getRows() as $row)
diff --git a/plugins/ExampleUI/Controller.php b/plugins/ExampleUI/Controller.php
index a1066a6abe..3fe44d43ef 100644
--- a/plugins/ExampleUI/Controller.php
+++ b/plugins/ExampleUI/Controller.php
@@ -77,11 +77,11 @@ class Piwik_ExampleUI_Controller extends Piwik_Controller
echo "<h2>Simple tag cloud</h2>";
$this->echoSimpleTagClouds();
- echo "<br/><br/><h2>Advanced tag cloud: with logos and links</h2>
+ echo "<br /><br /><h2>Advanced tag cloud: with logos and links</h2>
<ul style='list-style-type:disc;margin-left:50px'>
<li>The logo size is proportional to the value returned by the API</li>
<li>The logo is linked to a specific URL</li>
- </ul><br/><br/>";
+ </ul><br /><br />";
$this->echoAdvancedTagClouds();
}
function echoSimpleTagClouds()
diff --git a/plugins/ExampleUI/ExampleUI.php b/plugins/ExampleUI/ExampleUI.php
index fd5caf430f..9f365fb367 100644
--- a/plugins/ExampleUI/ExampleUI.php
+++ b/plugins/ExampleUI/ExampleUI.php
@@ -26,13 +26,19 @@
*/
class Piwik_ExampleUI extends Piwik_Plugin
{
+ /**
+ * Return information about this plugin.
+ *
+ * @see Piwik_Plugin
+ *
+ * @return array
+ */
public function getInformation()
{
return array(
- 'name' => 'Example User Interface',
- 'description' => 'Example Plugin: This plugin shows how to work with the Piwik UI: create tables, graphs, etc.',
+ 'description' => Piwik_Translate('ExampleUI_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
+ 'author_homepage' => 'http://piwik.org/',
'version' => '0.1',
);
}
diff --git a/plugins/ExampleUI/images/icons-planet/LICENSE b/plugins/ExampleUI/images/icons-planet/LICENSE
index 229295935c..cbaa1f23ed 100644
--- a/plugins/ExampleUI/images/icons-planet/LICENSE
+++ b/plugins/ExampleUI/images/icons-planet/LICENSE
@@ -1,3 +1,3 @@
-Author : Dan Wiersema
-License: Free for non-commercial use.
+Author : Dan Wiersema
+License: Free for non-commercial use.
http://www.iconspedia.com/icon/neptune-4672.html \ No newline at end of file
diff --git a/plugins/Feedback/Controller.php b/plugins/Feedback/Controller.php
index 7060f72816..a626e71989 100644
--- a/plugins/Feedback/Controller.php
+++ b/plugins/Feedback/Controller.php
@@ -1,11 +1,11 @@
<?php
/**
* Piwik - Open source web analytics
- *
+ *
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
- *
+ *
* @category Piwik_Plugins
* @package Piwik_Feedback
*/
@@ -15,10 +15,11 @@
* @package Piwik_Feedback
*/
class Piwik_Feedback_Controller extends Piwik_Controller
-{
+{
function index()
- {
+ {
$view = Piwik_View::factory('index');
+ $view->nonce = Piwik_Nonce::getNonce('Piwik_Feedback.sendFeedback', 3600);
echo $view->render();
}
@@ -27,16 +28,18 @@ class Piwik_Feedback_Controller extends Piwik_Controller
*/
function sendFeedback()
{
- $body = Piwik_Common::getRequestVar('body', '', 'string');
$email = Piwik_Common::getRequestVar('email', '', 'string');
+ $body = Piwik_Common::getRequestVar('body', '', 'string');
+ $category = Piwik_Common::getRequestVar('category', '', 'string');
+ $nonce = Piwik_Common::getRequestVar('nonce', '', 'string');
$view = Piwik_View::factory('sent');
- try
+ try
{
$minimumBodyLength = 35;
if(strlen($body) < $minimumBodyLength)
{
- throw new Exception(sprintf("Message must be at least %s characters long.", $minimumBodyLength));
+ throw new Exception(Piwik_TranslateException('Feedback_ExceptionBodyLength', array($minimumBodyLength)));
}
if(!Piwik::isValidEmailString($email))
{
@@ -44,14 +47,21 @@ class Piwik_Feedback_Controller extends Piwik_Controller
}
if(strpos($body, 'http://') !== false)
{
- throw new Exception("The message cannot contain a URL, to avoid spams messages.");
+ throw new Exception(Piwik_TranslateException('Feedback_ExceptionNoUrls'));
}
-
+ if(!Piwik_Nonce::verifyNonce('Piwik_Feedback.sendFeedback', $nonce))
+ {
+ throw new Exception(Piwik_TranslateException('General_ExceptionNonceMismatch'));
+ }
+
$mail = new Piwik_Mail();
- $mail->setFrom($email);
- $mail->addTo('hello@piwik.org','Piwik Team');
- $mail->setSubject('[ Feedback form - Piwik ]');
- $mail->setBodyText($body);
+ $mail->setFrom(Piwik_Common::unsanitizeInputValue($email));
+ $mail->addTo('hello@piwik.org', 'Piwik Team');
+ $mail->setSubject('[ Feedback form - Piwik ] ' . $category);
+ $mail->setBodyText(Piwik_Common::unsanitizeInputValue($body) . "\n"
+ . 'Piwik ' . Piwik_Version::VERSION . "\n"
+ . 'IP: ' . Piwik_Common::getIpString() . "\n"
+ . 'URL: ' . Piwik_Url::getReferer() . "\n");
@$mail->send();
}
catch(Exception $e)
@@ -59,7 +69,7 @@ class Piwik_Feedback_Controller extends Piwik_Controller
$view->ErrorString = $e->getMessage();
$view->message = $body;
}
-
+
echo $view->render();
}
}
diff --git a/plugins/Feedback/Feedback.php b/plugins/Feedback/Feedback.php
index 895d99462d..5cbd0afdf2 100644
--- a/plugins/Feedback/Feedback.php
+++ b/plugins/Feedback/Feedback.php
@@ -1,11 +1,11 @@
<?php
/**
* Piwik - Open source web analytics
- *
+ *
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
- *
+ *
* @category Piwik_Plugins
* @package Piwik_Feedback
*/
@@ -19,11 +19,28 @@ class Piwik_Feedback extends Piwik_Plugin
public function getInformation()
{
return array(
- 'name' => 'Feedback',
- 'description' => 'Send your Feedback to the Piwik Team in one click. Share your ideas and suggestions with us!',
+ 'description' => Piwik_Translate('Feedback_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
+ );
+ }
+
+ function getListHooksRegistered()
+ {
+ return array(
+ 'template_css_import' => 'css',
+ 'template_js_import' => 'js',
);
}
+
+ function css()
+ {
+ echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"plugins/Feedback/templates/styles.css\" />\n";
+ }
+
+ function js()
+ {
+ echo "<script type=\"text/javascript\" src=\"plugins/Feedback/templates/feedback.js\"></script>\n";
+ }
}
diff --git a/plugins/Feedback/images/go-previous.png b/plugins/Feedback/images/go-previous.png
new file mode 100644
index 0000000000..c37bc0414c
--- /dev/null
+++ b/plugins/Feedback/images/go-previous.png
Binary files differ
diff --git a/plugins/Feedback/templates/feedback.js b/plugins/Feedback/templates/feedback.js
new file mode 100644
index 0000000000..adaaa45448
--- /dev/null
+++ b/plugins/Feedback/templates/feedback.js
@@ -0,0 +1,28 @@
+$(function() {
+ var feedback = $('a#topbar-feedback');
+ if (feedback.size()) {
+ var fbDiv = $('<div id="feedback-dialog"></div>').appendTo('body');
+
+ $.get(feedback.attr('href'), function(data) {
+ fbDiv.html(data);
+ });
+
+ fbDiv.dialog({
+ title: feedback.html(),
+ bgiframe: true,
+ modal: true,
+ height: 480,
+ width: 500,
+ resizable: false,
+ autoOpen: false
+ });
+
+ $('#topbar-feedback').click(function() {
+ $('#feedback-faq').show();
+ $('#feedback-form').hide();
+ $('#feedback-sent').hide().empty();
+ fbDiv.dialog('open');
+ return false;
+ });
+ }
+});
diff --git a/plugins/Feedback/templates/index.tpl b/plugins/Feedback/templates/index.tpl
index aec45f58ce..02f553c177 100644
--- a/plugins/Feedback/templates/index.tpl
+++ b/plugins/Feedback/templates/index.tpl
@@ -1,24 +1,63 @@
{literal}
-<style>
-input, textarea, p {
- font-family: Georgia,"Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
- font-size:0.9em;
- padding:0.2em;
-}
-input {
- margin-top:0.8em;
-}
-</style>
-{/literal}
+<script type="text/javascript">
+$(function() {
+ $('#feedback-contact').click(function() {
+ $('#feedback-faq').hide();
+ $('#feedback-form').show();
+ return false;
+ });
-<form method="post" action="index.php?module=Feedback&action=sendFeedback">
+ $('#feedback-home').click(function() {
+ $('#feedback-form').hide();
+ $('#feedback-faq').show();
+ return false;
+ });
-<p><strong>your email :</strong>
-<br /><input type="text" name="email" size="40" /></p>
+ $('#feedback-form-submit').click(function() {
+ var feedback = $('#feedback-form form');
+ $('#feedback-form').hide();
+ $.post(feedback.attr('action'), feedback.serialize(), function (data) {
+ $('#feedback-sent').show().html(data);
+ });
+ return false;
+ });
+});
+</script>
+{/literal}
-<p><strong>your feedback:</strong><br/>
-<i>please be precise if you request for a feature or report a bug</i></p>
-<textarea name="body" cols="37" rows="10"></textarea>
-<br/>
-<input type="submit" value="Send feedback" />
-</form>
+ <div id="feedback-faq">
+ <p><strong>{'Feedback_DoYouHaveBugReportOrFeatureRequest'|translate}</strong></p>
+ <p>» {'Feedback_ViewAnswersToFAQ'|translate:"<a target='_blank' href='misc/redirectToUrl.php?url=http://piwik.org/faq/'>":"</a>"}.</p>
+ <ul>
+ <li>{'Feedback_WhyAreMyVisitsNoTracked'|translate}</li>
+ <li>{'Feedback_HowToExclude'|translate}</li>
+ <li>{'Feedback_WhyWrongCountry'|translate}</li>
+ <li>{'Feedback_HowToAnonymizeIP'|translate}</li>
+ </ul>
+ <p>» {'Feedback_VisitTheForums'|translate:"<a target='_blank' href='misc/redirectToUrl.php?url=http://forum.piwik.org/'>":"</a>"}.</p>
+ <p>» {'Feedback_LearnWaysToParticipate'|translate:"<a target='_blank' href='misc/redirectToUrl.php?url=http://piwik.org/contribute/'>":"</a>"}.</p>
+ <br />
+ <p><strong>{'Feedback_SpecialRequest'|translate}</strong></p>
+ <p>» <a target='_blank' href="#" id="feedback-contact">{'Feedback_ContactThePiwikTeam'|translate}</a></p>
+ </div>
+ <div id="feedback-form" style="display:none;">
+ <form method="post" action="index.php?module=Feedback&action=sendFeedback">
+ <p><strong>{'Feedback_IWantTo'|translate}</strong>
+ <select name="category">
+ <option value="share">{'Feedback_CategoryShareStory'|translate}</option>
+ <option value="sponsor">{'Feedback_CategorySponsor'|translate}</option>
+ <option value="hire">{'Feedback_CategoryHire'|translate}</option>
+ <option value="security">{'Feedback_CategorySecurity'|translate}</option>
+ </select>
+ </p>
+ <p><strong>{'Feedback_MyEmailAddress'|translate}</strong><br />
+ <input type="text" name="email" size="59" />
+ <input type="hidden" name="nonce" value="{$nonce}" /></p>
+ <p><strong>{'Feedback_MyMessage'|translate}</strong> {'Feedback_DetailsPlease'|translate}<br />
+ <textarea name="body" cols="57" rows="10"></textarea></p>
+ <p><input id="feedback-form-submit" type="submit" value="{'Feedback_SendFeedback'|translate}" /></p>
+ <p><a href="#" id="feedback-home"><img src="plugins/Feedback/images/go-previous.png" border="0" title="{'General_Previous'|translate}" alt="[{'General_Previous'|translate}]" /></a></p>
+ </form>
+ </div>
+ <div id="feedback-sent" style="display:none;">
+ </div>
diff --git a/plugins/Feedback/templates/sent.tpl b/plugins/Feedback/templates/sent.tpl
index 65495497bf..5ae4c1872a 100644
--- a/plugins/Feedback/templates/sent.tpl
+++ b/plugins/Feedback/templates/sent.tpl
@@ -1,33 +1,20 @@
{literal}
-<style>
-body {
- font-family: Georgia,"Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
- font-size:0.9em;
- padding:0.2em;
-}
-#error {
- color: red;
- text-align: center;
- border: 2px solid red;
- background-color:#FFFBFB;
- margin: 10px;
- padding: 10px;
-}
-#success {
- color: #38D73B;
- text-align: center;
- border: 2px solid red;
- margin: 10px;
- padding: 10px;
-}
-</style>
+<script type="text/javascript">
+ $('#feedback-retry').click(function() {
+ $('#feedback-sent').hide().empty();
+ $('#feedback-form').show();
+ return false;
+ });
+</script>
{/literal}
{if isset($ErrorString)}
- <div id="error"><strong>{'General_Error'|translate}:</strong> {$ErrorString}</div>
- <p>Please manually send your message at <a href='mailto:hello@piwik.org'>hello@piwik.org</a></p>
- <p>{$message}</p>
+ <div id="feedback-error"><strong>{'General_Error'|translate}:</strong> {$ErrorString}</div>
+ <p>{'Feedback_ManuallySendEmailTo'|translate} <a href='mailto:hello@piwik.org?subject={'[Feedback form - Piwik]'|escape:"hex"}&body={$message|stripeol|escape:"hex"}'>hello@piwik.org</a></p>
+ <textarea cols="53" rows="10" readonly="readonly">{$message}</textarea>
+ <p><a href="#" id="feedback-retry"><img src="plugins/Feedback/images/go-previous.png" border="0" title="{'General_Previous'|translate}" alt="[{'General_Previous'|translate}]" /></a></p>
{else}
- <div id="success">Your message was sent to Piwik.</div>
- <p><strong>Thank you for your helping us making Piwik better!</strong><br /> The Piwik Team</p>
+ <div id="feedback-success">{'Feedback_MessageSent'|translate}</div>
+ <p><strong>{'Feedback_ThankYou'|translate}</strong></p>
+ <p>-- {'Feedback_ThePiwikTeam'|translate}</p>
{/if}
diff --git a/plugins/Feedback/templates/styles.css b/plugins/Feedback/templates/styles.css
new file mode 100644
index 0000000000..8d95ab93db
--- /dev/null
+++ b/plugins/Feedback/templates/styles.css
@@ -0,0 +1,28 @@
+#feedback-form input, #feedback-form textarea, #feedback-sent textarea, #feedback-form select, #feedback-faq p, #feedback-form p, #feedback-sent div, #feedback-sent p, #feedback-faq li {
+ font-family: "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
+ font-size:0.9em;
+ padding:0.2em;
+}
+#feedback-faq ul {
+ list-style-type:disc;
+ list-style-position:inside;
+ padding-left:2.5em;
+}
+#feedback-faq, #feedback-form, #feedback-sent {
+ margin-right:1em;
+}
+#feedback-error {
+ color: red;
+ text-align: center;
+ border: 2px solid red;
+ background-color:#FFFBFB;
+ margin: 10px;
+ padding: 10px;
+}
+#feedback-success {
+ color: #38D73B;
+ text-align: center;
+ border: 2px solid #38D73B;
+ margin: 10px;
+ padding: 10px;
+}
diff --git a/plugins/Goals/API.php b/plugins/Goals/API.php
index 5ed95fd68b..6f00d96868 100644
--- a/plugins/Goals/API.php
+++ b/plugins/Goals/API.php
@@ -27,7 +27,7 @@ class Piwik_Goals_API
return self::$instance;
}
- static public function getGoals( $idSite )
+ public function getGoals( $idSite )
{
$goals = Piwik_FetchAll("SELECT *
FROM ".Piwik_Common::prefixTable('goal')."
@@ -53,16 +53,16 @@ class Piwik_Goals_API
// save in db
$db = Zend_Registry::get('db');
$idGoal = $db->fetchOne("SELECT max(idgoal) + 1
- FROM ".Piwik::prefixTable('goal')."
+ FROM ".Piwik_Common::prefixTable('goal')."
WHERE idsite = ?", $idSite);
if($idGoal == false)
{
$idGoal = 1;
}
- self::checkPatternIsValid($patternType, $pattern);
- $name = self::checkName($name);
- $pattern = self::checkPattern($pattern);
- $db->insert(Piwik::prefixTable('goal'),
+ $this->checkPatternIsValid($patternType, $pattern);
+ $name = $this->checkName($name);
+ $pattern = $this->checkPattern($pattern);
+ $db->insert(Piwik_Common::prefixTable('goal'),
array(
'idsite' => $idSite,
'idgoal' => $idGoal,
@@ -81,10 +81,10 @@ class Piwik_Goals_API
public function updateGoal( $idSite, $idGoal, $name, $matchAttribute, $pattern, $patternType, $caseSensitive, $revenue )
{
Piwik::checkUserHasAdminAccess($idSite);
- $name = self::checkName($name);
- $pattern = self::checkPattern($pattern);
- self::checkPatternIsValid($patternType, $pattern);
- Zend_Registry::get('db')->update( Piwik::prefixTable('goal'),
+ $name = $this->checkName($name);
+ $pattern = $this->checkPattern($pattern);
+ $this->checkPatternIsValid($patternType, $pattern);
+ Zend_Registry::get('db')->update( Piwik_Common::prefixTable('goal'),
array(
'name' => $name,
'match_attribute' => $matchAttribute,
@@ -103,8 +103,7 @@ class Piwik_Goals_API
if($patternType == 'exact'
&& substr($pattern, 0, 4) != 'http')
{
- throw new Exception("If you choose 'exact match', the matching string must be a
- URL starting with http:// or https://. For example, 'http://www.yourwebsite.com/newsletter/subscribed.html'.");
+ throw new Exception(Piwik_TranslateException('Goals_ExceptionInvalidMatchingString', array("http:// or https://", "http://www.yourwebsite.com/newsletter/subscribed.html")));
}
}
@@ -121,12 +120,12 @@ class Piwik_Goals_API
public function deleteGoal( $idSite, $idGoal )
{
Piwik::checkUserHasAdminAccess($idSite);
- Piwik_Query("UPDATE ".Piwik::prefixTable('goal')."
+ Piwik_Query("UPDATE ".Piwik_Common::prefixTable('goal')."
SET deleted = 1
WHERE idsite = ?
AND idgoal = ?",
array($idSite, $idGoal));
- Piwik_Query("DELETE FROM ".Piwik::prefixTable("log_conversion")." WHERE idgoal = ?", $idGoal);
+ Piwik_Query("DELETE FROM ".Piwik_Common::prefixTable("log_conversion")." WHERE idgoal = ?", $idGoal);
Piwik_Common::regenerateCacheWebsiteAttributes($idSite);
}
@@ -157,7 +156,7 @@ class Piwik_Goals_API
$request = new Piwik_API_Request("method=VisitFrequency.getVisitsReturning&idSite=$idSite&period=$period&date=$date&format=original");
$nbVisitsReturning = $request->process();
// echo $nbVisitsConvertedReturningVisitors;
-// echo "<br>". $nbVisitsReturning;exit;
+// echo "<br />". $nbVisitsReturning;exit;
return Piwik::getPercentageSafe($nbVisitsConvertedReturningVisitors, $nbVisitsReturning, Piwik_Goals::ROUNDING_PRECISION);
}
@@ -211,7 +210,7 @@ class Piwik_Goals_API
return $dataTable;
}
- protected static function getNumeric( $idSite, $period, $date, $toFetch )
+ protected function getNumeric( $idSite, $period, $date, $toFetch )
{
Piwik::checkUserHasViewAccess( $idSite );
$archive = Piwik_Archive::build($idSite, $period, $date );
@@ -221,16 +220,16 @@ class Piwik_Goals_API
public function getConversions( $idSite, $period, $date, $idGoal = false )
{
- return self::getNumeric( $idSite, $period, $date, Piwik_Goals::getRecordName('nb_conversions', $idGoal));
+ return $this->getNumeric( $idSite, $period, $date, Piwik_Goals::getRecordName('nb_conversions', $idGoal));
}
public function getConversionRate( $idSite, $period, $date, $idGoal = false )
{
- return self::getNumeric( $idSite, $period, $date, Piwik_Goals::getRecordName('conversion_rate', $idGoal));
+ return $this->getNumeric( $idSite, $period, $date, Piwik_Goals::getRecordName('conversion_rate', $idGoal));
}
public function getRevenue( $idSite, $period, $date, $idGoal = false )
{
- return self::getNumeric( $idSite, $period, $date, Piwik_Goals::getRecordName('revenue', $idGoal));
+ return $this->getNumeric( $idSite, $period, $date, Piwik_Goals::getRecordName('revenue', $idGoal));
}
}
diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php
index 06d16b93b0..04c54565ab 100644
--- a/plugins/Goals/Controller.php
+++ b/plugins/Goals/Controller.php
@@ -18,33 +18,54 @@ class Piwik_Goals_Controller extends Piwik_Controller
{
const CONVERSION_RATE_PRECISION = 1;
- function __construct()
+ protected $goalColumnNameToLabel = array(
+ 'nb_conversions' => 'Goals_ColumnConversions',
+ 'conversion_rate'=> 'Goals_ColumnConversionRate',
+ 'revenue' => 'Goals_ColumnRevenue',
+ );
+
+ public function __construct()
{
parent::__construct();
$this->idSite = Piwik_Common::getRequestVar('idSite');
- $this->goals = Piwik_Goals_API::getGoals($this->idSite);
+ $this->goals = Piwik_Goals_API::getInstance()->getGoals($this->idSite);
}
- function goalReport()
+ public function widgetGoalReport()
+ {
+ $view = $this->getGoalReportView();
+ $view->displayFullReport = false;
+ echo $view->render();
+ }
+
+ public function goalReport()
+ {
+ $view = $this->getGoalReportView();
+ $view->displayFullReport = true;
+ $view->goalSegments = $this->getAvailableGoalSegments();
+ echo $view->render();
+ }
+
+ protected function getGoalReportView()
{
$idGoal = Piwik_Common::getRequestVar('idGoal', null, 'int');
if(!isset($this->goals[$idGoal]))
{
- throw new Exception("idgoal $idGoal not valid.");
+ Piwik::redirectToModule('Goals', 'index', array('idGoal' => null));
}
$goalDefinition = $this->goals[$idGoal];
$view = Piwik_View::factory('single_goal');
- $view->currency = Piwik::getCurrency();
+ $this->setGeneralVariablesView($view);
$goal = $this->getMetricsForGoal($idGoal);
foreach($goal as $name => $value)
{
$view->$name = $value;
}
- $view->name = $goalDefinition['name'];
- $view->title = $goalDefinition['name'] . ' - Conversions';
+ $view->idGoal = $idGoal;
+ $view->goalName = $goalDefinition['name'];
$view->graphEvolution = $this->getEvolutionGraph(true, array(Piwik_Goals::getRecordName('nb_conversions', $idGoal)), $idGoal);
- $view->nameGraphEvolution = 'GoalsgetEvolutionGraph';
+ $view->nameGraphEvolution = 'GoalsgetEvolutionGraph'.$idGoal;
$view->topSegments = $this->getTopSegments($idGoal);
// conversion rate for new and returning visitors
@@ -52,75 +73,31 @@ class Piwik_Goals_Controller extends Piwik_Controller
$view->conversion_rate_returning = round( $request->process(), self::CONVERSION_RATE_PRECISION );
$request = new Piwik_API_Request("method=Goals.getConversionRateNewVisitors&format=original");
$view->conversion_rate_new = round( $request->process(), self::CONVERSION_RATE_PRECISION );
-
- $verticalSlider = array();
- // string label
- // array parameters to ajax call on click (module, action)
- // specific order
- // (intermediate labels)
- // automatically load the first from the list, highlights it
- $view->tableByConversion = Piwik_FrontController::getInstance()->fetchDispatch('Referers', 'getKeywords', array(false, 'tableGoals'));
- echo $view->render();
+ return $view;
}
- protected function getTopSegments($idGoal)
+ public function index()
{
- $columnNbConversions = 'goal_'.$idGoal.'_nb_conversions';
- $columnConversionRate = 'goal_'.$idGoal.'_conversion_rate';
-
- $topSegmentsToLoad = array(
- 'country' => 'UserCountry.getCountry',
- 'keyword' => 'Referers.getKeywords',
- 'website' => 'Referers.getWebsites',
- );
-
- $topSegments = array();
- foreach($topSegmentsToLoad as $segmentName => $apiMethod)
- {
- $request = new Piwik_API_Request("method=$apiMethod
- &format=original
- &filter_update_columns_when_show_all_goals=1
- &filter_sort_order=desc
- &filter_sort_column=$columnNbConversions
- &filter_limit=3");
- $datatable = $request->process();
- $topSegment = array();
- foreach($datatable->getRows() as $row)
- {
- $topSegment[] = array (
- 'name' => $row->getColumn('label'),
- 'nb_conversions' => $row->getColumn($columnNbConversions),
- 'conversion_rate' => $row->getColumn($columnConversionRate),
- 'metadata' => $row->getMetadata(),
- );
- }
- $topSegments[$segmentName] = $topSegment;
- }
- return $topSegments;
+ $view = $this->getOverviewView();
+ $view->goalsJSON = json_encode($this->goals);
+ $view->goalSegments = $this->getAvailableGoalSegments();
+ $view->userCanEditGoals = Piwik::isUserHasAdminAccess($this->idSite);
+ $view->displayFullReport = true;
+ echo $view->render();
}
- protected function getMetricsForGoal($idGoal)
+ public function widgetGoalsOverview( )
{
- $request = new Piwik_API_Request("method=Goals.get&format=original&idGoal=$idGoal");
- $datatable = $request->process();
- $dataRow = $datatable->getFirstRow();
- return array (
- 'id' => $idGoal,
- 'nb_conversions' => $dataRow->getColumn(Piwik_Goals::getRecordName('nb_conversions', $idGoal)),
- 'conversion_rate' => round($dataRow->getColumn(Piwik_Goals::getRecordName('conversion_rate', $idGoal)), 1),
- 'revenue' => $dataRow->getColumn(Piwik_Goals::getRecordName('revenue', $idGoal)),
- 'urlSparklineConversions' => $this->getUrlSparkline('getEvolutionGraph', array('columns' => array(Piwik_Goals::getRecordName('nb_conversions', $idGoal)), 'idGoal' => $idGoal)),
- 'urlSparklineConversionRate' => $this->getUrlSparkline('getEvolutionGraph', array('columns' => array(Piwik_Goals::getRecordName('conversion_rate', $idGoal)), 'idGoal' => $idGoal)),
- 'urlSparklineRevenue' => $this->getUrlSparkline('getEvolutionGraph', array('columns' => array(Piwik_Goals::getRecordName('revenue', $idGoal)), 'idGoal' => $idGoal)),
- );
+ $view = $this->getOverviewView();
+ $view->displayFullReport = false;
+ echo $view->render();
}
- function index()
+ protected function getOverviewView()
{
$view = Piwik_View::factory('overview');
- $view->currency = Piwik::getCurrency();
+ $this->setGeneralVariablesView($view);
- $view->title = 'All goals - evolution';
$view->graphEvolution = $this->getEvolutionGraph(true, array(Piwik_Goals::getRecordName('nb_conversions')));
$view->nameGraphEvolution = 'GoalsgetEvolutionGraph';
@@ -129,7 +106,7 @@ class Piwik_Goals_Controller extends Piwik_Controller
$view->urlSparklineConversionRate = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array(Piwik_Goals::getRecordName('conversion_rate'))));
$view->urlSparklineRevenue = $this->getUrlSparkline('getEvolutionGraph', array('columns' => array(Piwik_Goals::getRecordName('revenue'))));
- $request = new Piwik_API_Request("method=Goals.get&format=original");
+ $request = new Piwik_API_Request("method=Goals.get&format=original&idGoal=0");
$datatable = $request->process();
$dataRow = $datatable->getFirstRow();
$view->nb_conversions = $dataRow->getColumn('Goal_nb_conversions');
@@ -145,26 +122,36 @@ class Piwik_Goals_Controller extends Piwik_Controller
$view->goalMetrics = $goalMetrics;
$view->goals = $this->goals;
- $view->goalsJSON = json_encode($this->goals);
- $view->userCanEditGoals = Piwik::isUserHasAdminAccess($this->idSite);
- echo $view->render();
+ return $view;
+ }
+
+ public function getLastNbConversionsGraph( $fetch = false )
+ {
+ $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Goals.getConversions');
+ return $this->renderView($view, $fetch);
}
- function addNewGoal()
+ public function getLastConversionRateGraph( $fetch = false )
+ {
+ $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Goals.getConversionRate');
+ return $this->renderView($view, $fetch);
+ }
+
+ public function getLastRevenueGraph( $fetch = false )
+ {
+ $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Goals.getRevenue');
+ return $this->renderView($view, $fetch);
+ }
+
+ public function addNewGoal()
{
$view = Piwik_View::factory('add_new_goal');
+ $this->setGeneralVariablesView($view);
$view->userCanEditGoals = Piwik::isUserHasAdminAccess($this->idSite);
- $view->currency = Piwik::getCurrency();
$view->onlyShowAddNewGoal = true;
echo $view->render();
}
- protected $goalColumnNameToLabel = array(
- 'nb_conversions' => 'Goals_ColumnConversions',
- 'conversion_rate'=> 'Goals_ColumnConversionRate',
- 'revenue' => 'Goals_ColumnRevenue',
- );
-
public function getEvolutionGraph( $fetch = false, $columns = false, $idGoal = false)
{
if(empty($columns))
@@ -193,7 +180,7 @@ class Piwik_Goals_Controller extends Piwik_Controller
if(!empty($idGoal) && isset($this->goals[$idGoal]))
{
$goalName = $this->goals[$idGoal]['name'];
- $columnTranslation = "$columnTranslation (goal \"$goalName\")";
+ $columnTranslation = "$columnTranslation (".Piwik_Translate('Goals_GoalX', "$goalName").")";
}
$view->setColumnTranslation($columnName, $columnTranslation);
}
@@ -201,21 +188,74 @@ class Piwik_Goals_Controller extends Piwik_Controller
return $this->renderView($view, $fetch);
}
- function getLastNbConversionsGraph( $fetch = false )
+ protected function getAvailableGoalSegments()
{
- $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Goals.getConversions');
- return $this->renderView($view, $fetch);
+ $segments = array();
+ Piwik_PostEvent('Goals.getAvailableGoalSegments', $segments);
+ $segmentsByGroup = array();
+ foreach($segments as $segment)
+ {
+ $group = $segment['group'];
+ unset($segment['group']);
+ $segmentsByGroup[$group][] = $segment;
+ }
+ return $segmentsByGroup;
}
- function getLastConversionRateGraph( $fetch = false )
+ protected function getTopSegments($idGoal)
{
- $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Goals.getConversionRate');
- return $this->renderView($view, $fetch);
+ $columnNbConversions = 'goal_'.$idGoal.'_nb_conversions';
+ $columnConversionRate = 'goal_'.$idGoal.'_conversion_rate';
+
+ $topSegmentsToLoad = array(
+ 'country' => 'UserCountry.getCountry',
+ 'keyword' => 'Referers.getKeywords',
+ 'website' => 'Referers.getWebsites',
+ );
+
+ $topSegments = array();
+ foreach($topSegmentsToLoad as $segmentName => $apiMethod)
+ {
+ $request = new Piwik_API_Request("method=$apiMethod
+ &format=original
+ &filter_update_columns_when_show_all_goals=1
+ &filter_only_display_idgoal=". Piwik_DataTable_Filter_UpdateColumnsWhenShowAllGoals::GOALS_FULL_TABLE ."
+ &filter_sort_order=desc
+ &filter_sort_column=$columnNbConversions
+ &filter_limit=3");
+ $datatable = $request->process();
+ $topSegment = array();
+ foreach($datatable->getRows() as $row)
+ {
+ $conversions = $row->getColumn($columnNbConversions);
+ if($conversions > 0)
+ {
+ $topSegment[] = array (
+ 'name' => $row->getColumn('label'),
+ 'nb_conversions' => $conversions,
+ 'conversion_rate' => $row->getColumn($columnConversionRate),
+ 'metadata' => $row->getMetadata(),
+ );
+ }
+ }
+ $topSegments[$segmentName] = $topSegment;
+ }
+ return $topSegments;
}
-
- function getLastRevenueGraph( $fetch = false )
+
+ protected function getMetricsForGoal($idGoal)
{
- $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Goals.getRevenue');
- return $this->renderView($view, $fetch);
+ $request = new Piwik_API_Request("method=Goals.get&format=original&idGoal=$idGoal");
+ $datatable = $request->process();
+ $dataRow = $datatable->getFirstRow();
+ return array (
+ 'id' => $idGoal,
+ 'nb_conversions' => $dataRow->getColumn(Piwik_Goals::getRecordName('nb_conversions', $idGoal)),
+ 'conversion_rate' => round($dataRow->getColumn(Piwik_Goals::getRecordName('conversion_rate', $idGoal)), 1),
+ 'revenue' => $dataRow->getColumn(Piwik_Goals::getRecordName('revenue', $idGoal)),
+ 'urlSparklineConversions' => $this->getUrlSparkline('getEvolutionGraph', array('columns' => array(Piwik_Goals::getRecordName('nb_conversions', $idGoal)), 'idGoal' => $idGoal)),
+ 'urlSparklineConversionRate' => $this->getUrlSparkline('getEvolutionGraph', array('columns' => array(Piwik_Goals::getRecordName('conversion_rate', $idGoal)), 'idGoal' => $idGoal)),
+ 'urlSparklineRevenue' => $this->getUrlSparkline('getEvolutionGraph', array('columns' => array(Piwik_Goals::getRecordName('revenue', $idGoal)), 'idGoal' => $idGoal)),
+ );
}
}
diff --git a/plugins/Goals/Goals.php b/plugins/Goals/Goals.php
index 7e36b3a4d3..6ab468f09e 100644
--- a/plugins/Goals/Goals.php
+++ b/plugins/Goals/Goals.php
@@ -26,11 +26,10 @@ class Piwik_Goals extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => '(ALPHA) Goal Tracking',
- 'description' => 'Create Goals and see reports about your goal conversions: evolution over time, revenue per visit, conversions per referer, per keyword, etc.',
+ 'description' => Piwik_Translate('Goals_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
'TrackerPlugin' => true, // this plugin must be loaded during the stats logging
);
@@ -55,11 +54,20 @@ class Piwik_Goals extends Piwik_Plugin
// add the 'goal' entry in the website array
$array =& $notification->getNotificationObject();
- $array['goals'] = Piwik_Goals_API::getGoals($idsite);
+ $array['goals'] = Piwik_Goals_API::getInstance()->getGoals($idsite);
}
function addWidgets()
{
+ Piwik_AddWidget('Goals_Goals', 'Goals_GoalsOverview', 'Goals', 'widgetGoalsOverview');
+ $goals = Piwik_Tracker_GoalManager::getGoalDefinitions(Piwik_Common::getRequestVar('idSite'));
+ if(count($goals) > 0)
+ {
+ foreach($goals as $goal)
+ {
+ Piwik_AddWidget('Goals_Goals', $goal['name'], 'Goals', 'widgetGoalReport', array('idGoal' => $goal['idgoal']));
+ }
+ }
}
function addMenus()
@@ -67,14 +75,14 @@ class Piwik_Goals extends Piwik_Plugin
$goals = Piwik_Tracker_GoalManager::getGoalDefinitions(Piwik_Common::getRequestVar('idSite'));
if(count($goals)==0)
{
- Piwik_AddMenu('Goals', 'Add a new Goal', array('module' => 'Goals', 'action' => 'addNewGoal'));
+ Piwik_AddMenu('Goals_Goals', 'Goals_AddNewGoal', array('module' => 'Goals', 'action' => 'addNewGoal'));
}
else
{
- Piwik_AddMenu('Goals', 'Overview', array('module' => 'Goals'));
+ Piwik_AddMenu('Goals_Goals', 'Goals_Overview', array('module' => 'Goals', 'action' => 'index'));
foreach($goals as $goal)
{
- Piwik_AddMenu('Goals', str_replace('%', '%%', $goal['name']), array('module' => 'Goals', 'action' => 'goalReport', 'idGoal' => $goal['idgoal']));
+ Piwik_AddMenu('Goals_Goals', str_replace('%', '%%', $goal['name']), array('module' => 'Goals', 'action' => 'goalReport', 'idGoal' => $goal['idgoal']));
}
}
}
@@ -88,7 +96,7 @@ class Piwik_Goals extends Piwik_Plugin
static public function getRecordName($recordName, $idGoal = false, $visitorReturning = false)
{
$idGoalStr = $returningStr = '';
- if($idGoal !== false)
+ if(!empty($idGoal))
{
$idGoalStr = $idGoal . "_";
}
@@ -180,14 +188,14 @@ class Piwik_Goals extends Piwik_Plugin
$metricName = Piwik_Archive::$mappingFromIdToNameGoal[$metricId];
$recordName = self::getRecordName($metricName, $idgoal, $visitor_returning);
$archiveProcessing->insertNumericRecord($recordName, $value);
-// echo $record . "<br>";
+// echo $record . "<br />";
}
}
}
// Stats for all goals
$totalAllGoals = array(
- self::getRecordName('conversion_rate') => round(100 * $archiveProcessing->getNumberOfVisitsConverted() / $archiveProcessing->getNumberOfVisits(), self::ROUNDING_PRECISION),
+ self::getRecordName('conversion_rate') => $this->getConversionRate($archiveProcessing->getNumberOfVisitsConverted(), $archiveProcessing),
self::getRecordName('nb_conversions') => $nb_conversions,
self::getRecordName('revenue') => $revenue,
);
diff --git a/plugins/Goals/templates/GoalForm.js b/plugins/Goals/templates/GoalForm.js
index f3c5af4227..13ed40ba5e 100644
--- a/plugins/Goals/templates/GoalForm.js
+++ b/plugins/Goals/templates/GoalForm.js
@@ -1,20 +1,37 @@
function showAddNewGoal()
{
+ hideForms();
$("#GoalForm").show();
- $("#EditGoals").hide();
- $.scrollTo("#AddEditGoals", 400);
+ showCancel();
+ piwikHelper.lazyScrollTo("#AddEditGoals", 400);
return false;
}
function showEditGoals()
{
+ hideForms();
$("#EditGoals").show();
- $("#GoalForm").hide();
- $.scrollTo("#AddEditGoals", 400);
+ showCancel();
+ piwikHelper.lazyScrollTo("#AddEditGoals", 400);
return false;
}
+function hideForms()
+{
+ $("#GoalForm").hide();
+ $("#EditGoals").hide();
+}
+
+function showCancel()
+{
+ $("#goalsCancel").show();
+ $('#goalsCancelLink').click( function(){
+ hideForms();
+ $("#goalsCancel").hide();
+ });
+}
+
// init the goal form with existing goal value, if any
function initGoalForm(goalMethodAPI, submitText, goalName, matchAttribute, pattern, patternType, caseSensitive, revenue, goalId)
{
@@ -42,11 +59,6 @@ function initGoalForm(goalMethodAPI, submitText, goalName, matchAttribute, patte
}
}
-function initAndShowAddGoalForm()
-{
- initGoalForm('Goals.addGoal', 'Add Goal', '', 'url', '', 'contains', false, '0');
- return showAddNewGoal();
-}
function bindGoalForm()
{
@@ -78,78 +90,85 @@ function bindGoalForm()
$('a[name=linkAddNewGoal]').click( function(){
initAndShowAddGoalForm();
+ piwikHelper.lazyScrollTo('#goal_name');
} );
}
-function bindListGoalEdit()
-{
- $('a[name=linkEditGoal]').click( function() {
- var goalId = $(this).attr('id');
- var goal = piwik.goals[goalId];
- initGoalForm("Goals.updateGoal", "Update Goal", goal.name, goal.match_attribute, goal.pattern, goal.pattern_type, (goal.case_sensitive=='0' ? false : true), goal.revenue, goalId);
- showAddNewGoal();
- return false;
- });
-
- $('a[name=linkDeleteGoal]').click( function() {
- var goalId = $(this).attr('id');
- var goal = piwik.goals[goalId];
- if(confirm(sprintf("Are you sure you want to delete the Goal '%s'?", goal.name)))
- {
- $.ajax( getAjaxDeleteGoal( goalId ) );
- }
- return false;
- });
-
- $('a[name=linkEditGoals]').click( function(){
- return showEditGoals();
- } );
-}
function getAjaxDeleteGoal(idGoal)
{
- var ajaxRequest = piwikHelper.getStandardAjaxConf();
- piwikHelper.toggleAjaxLoading();
+ var ajaxRequest = piwikHelper.getStandardAjaxConf('goalAjaxLoading');
+ piwikHelper.lazyScrollTo("#AddEditGoals", 400);
var parameters = {};
parameters.idSite = piwik.idSite;
- parameters.idGoal = idGoal;
- parameters.method = 'Goals.deleteGoal';
+ parameters.idGoal = idGoal;
+ parameters.method = 'Goals.deleteGoal';
parameters.module = 'API';
parameters.format = 'json';
- parameters.token_auth = piwik.token_auth;
+ parameters.token_auth = piwik.token_auth;
ajaxRequest.data = parameters;
return ajaxRequest;
}
function getAjaxAddGoal()
{
- var ajaxRequest = piwikHelper.getStandardAjaxConf();
- piwikHelper.toggleAjaxLoading();
-
+ var ajaxRequest = piwikHelper.getStandardAjaxConf('goalAjaxLoading');
+ piwikHelper.lazyScrollTo("#AddEditGoals", 400);
var parameters = {};
parameters.idSite = piwik.idSite;
parameters.name = encodeURIComponent( $('#goal_name').val() );
-
+
if($('[name=trigger_type]').val() == 'manually') {
parameters.matchAttribute = 'manually';
parameters.patternType = 'regex';
parameters.pattern = '.*';
parameters.caseSensitive = 0;
} else {
- parameters.matchAttribute = $('input[name=match_attribute][checked]').val();
+ parameters.matchAttribute = $('input[name=match_attribute]:checked').val();
parameters.patternType = $('[name=pattern_type]').val();
parameters.pattern = encodeURIComponent( $('input[name=pattern]').val() );
parameters.caseSensitive = $('#case_sensitive').attr('checked') == true ? 1: 0;
}
parameters.revenue = $('input[name=revenue]').val();
- parameters.idGoal = $('input[name=goalIdUpdate]').val();
- parameters.method = $('input[name=methodGoalAPI]').val();
+ parameters.idGoal = $('input[name=goalIdUpdate]').val();
+ parameters.method = $('input[name=methodGoalAPI]').val();
parameters.module = 'API';
parameters.format = 'json';
- parameters.token_auth = piwik.token_auth;
+ parameters.token_auth = piwik.token_auth;
ajaxRequest.data = parameters;
return ajaxRequest;
}
+
+function bindListGoalEdit()
+{
+ $('a[name=linkEditGoal]').click( function() {
+ var goalId = $(this).attr('id');
+ var goal = piwik.goals[goalId];
+ initGoalForm("Goals.updateGoal", _pk_translate('Goals_UpdateGoal_js'), goal.name, goal.match_attribute, goal.pattern, goal.pattern_type, (goal.case_sensitive=='0' ? false : true), goal.revenue, goalId);
+ showAddNewGoal();
+ return false;
+ });
+
+ $('a[name=linkDeleteGoal]').click( function() {
+ var goalId = $(this).attr('id');
+ var goal = piwik.goals[goalId];
+ if(confirm(sprintf(_pk_translate('Goals_DeleteGoalConfirm_js'), '"'+goal.name+'"')))
+ {
+ $.ajax( getAjaxDeleteGoal( goalId ) );
+ }
+ return false;
+ });
+
+ $('a[name=linkEditGoals]').click( function(){
+ return showEditGoals();
+ } );
+}
+
+function initAndShowAddGoalForm()
+{
+ initGoalForm('Goals.addGoal', _pk_translate('Goals_AddGoal_js'), '', 'url', '', 'contains', false, '0');
+ return showAddNewGoal();
+} \ No newline at end of file
diff --git a/plugins/Goals/templates/add_edit_goal.tpl b/plugins/Goals/templates/add_edit_goal.tpl
index c09f1cdab3..e78a8eb391 100644
--- a/plugins/Goals/templates/add_edit_goal.tpl
+++ b/plugins/Goals/templates/add_edit_goal.tpl
@@ -1,44 +1,54 @@
-
-<div id="AddEditGoals">
{if isset($onlyShowAddNewGoal)}
- <h2>Add a new Goal</h2>
+ <h2>{'Goals_AddNewGoal'|translate}</h2>
+ <p>{'Goals_DescriptionGoalsManagement'|translate} </p>
+ <p>{'Goals_LearnMoreAboutGoalTrackingDocumentation'|translate:"<a href='misc/redirectToUrl.php?url=http://piwik.org/docs/tracking-goals-web-analytics/' target='_blank'>":"</a>"}
+ </p>
{else}
- <h2><a onclick='' name="linkAddNewGoal">+ Add a new Goal</a>
- or <a onclick='' name="linkEditGoals">Edit</a> existing Goals</h2>
+ <h2>{'Goals_GoalsManagement'|translate}</h2>
+ <ul class='listCircle'>
+ <li><a onclick='' name='linkAddNewGoal'><u>{'Goals_CreateNewGOal'|translate}</u></a></li>
+ <li><a onclick='' name='linkEditGoals'>{'Goals_ViewAndEditGoals'|translate}</a></li>
+ <li>{'Goals_LearnMoreAboutGoalTrackingDocumentation'|translate:"<a href='misc/redirectToUrl.php?url=http://piwik.org/docs/tracking-goals-web-analytics/' target='_blank'>":"</a>"}</li>
+ </ul>
+ <br/>
{/if}
- <div>
- <div id="ajaxError" style="display:none"></div>
- <div id="ajaxLoading" style="display:none"><div id="loadingPiwik"><img src="themes/default/images/loading-blue.gif" alt="" /> {'General_LoadingData'|translate}</div></div>
- </div>
+{ajaxErrorDiv}
+{ajaxLoadingDiv id=goalAjaxLoading}
-{if !isset($onlyShowAddNewGoal)}
- {include file="Goals/templates/list_goal_edit.tpl"}
-{/if}
+<div id="AddEditGoals">
+ {if !isset($onlyShowAddNewGoal)}
+ {include file="Goals/templates/list_goal_edit.tpl"}
+ {/if}
{include file="Goals/templates/form_add_goal.tpl"}
-
+ {if !isset($onlyShowAddNewGoal)}
+ <div id='goalsCancel'>{'General_OrCancel'|translate:"<a id='goalsCancelLink'>":"</a>"}</div>
+ {/if}
<a id='bottom'></a>
</div>
-{literal}
+{loadJavascriptTranslations plugins='Goals'}
<script type="text/javascript" src="plugins/Goals/templates/GoalForm.js"></script>
-<script language="javascript">
-
-var mappingMatchTypeName = {
- "url": "URL",
- "file": "filename",
- "external_website": "external website URL"
-};
-var mappingMatchTypeExamples = {
- "url": "eg. contains 'checkout/confirmation'<br>eg. is exactly 'http://example.com/thank-you.html'<br>eg. matches the expression '(.*)\\\/demo\\\/(.*)'",
- "file": "eg. contains 'files/brochure.pdf'<br>eg. is exactly 'http://example.com/files/brochure.pdf'<br>eg. matches the expression '(.*)\\\.zip'",
- "external_website": "eg. contains 'amazon.com'<br>eg. is exactly 'http://mypartner.com/landing.html'<br>eg. matches the expression 'http://www.amazon.com\\\/(.*)\\\/yourAffiliateId'"
-};
-
+<script type="text/javascript">
+
+var mappingMatchTypeName = {ldelim}
+ "url": "{'Goals_URL'|translate|escape}",
+ "file": "{'Goals_Filename'|translate|escape}",
+ "external_website": "{'Goals_ExternalWebsiteUrl'|translate|escape}"
+{rdelim};
+var mappingMatchTypeExamples = {ldelim}
+ "url": "{'General_ForExampleShort'|translate} {'Goals_Contains'|translate:"'checkout/confirmation'"|escape} \
+ <br />{'General_ForExampleShort'|translate|escape} {'Goals_IsExactly'|translate:"'http://example.com/thank-you.html'"|escape} \
+ <br />{'General_ForExampleShort'|translate|escape} {'Goals_MatchesExpression'|translate:"'(.*)\\\/demo\\\/(.*)'"|escape}",
+ "file": "{'General_ForExampleShort'|translate|escape} {'Goals_Contains'|translate:"'files/brochure.pdf'"|escape} \
+ <br />{'General_ForExampleShort'|translate|escape} {'Goals_IsExactly'|translate:"'http://example.com/files/brochure.pdf'"|escape} \
+ <br />{'General_ForExampleShort'|translate|escape} {'Goals_MatchesExpression'|translate:"'(.*)\\\.zip'"|escape}",
+ "external_website": "{'General_ForExampleShort'|translate|escape} {'Goals_Contains'|translate:"'amazon.com'"|escape} \
+ <br />{'General_ForExampleShort'|translate|escape} {'Goals_IsExactly'|translate:"'http://mypartner.com/landing.html'"|escape} \
+ <br />{'General_ForExampleShort'|translate|escape} {'Goals_MatchesExpression'|translate:"'http://www.amazon.com\\\/(.*)\\\/yourAffiliateId'"|escape}"
+{rdelim};
bindGoalForm();
-{/literal}
-
{if !isset($onlyShowAddNewGoal)}
piwik.goals = {$goalsJSON};
bindListGoalEdit();
diff --git a/plugins/Goals/templates/add_new_goal.tpl b/plugins/Goals/templates/add_new_goal.tpl
index 05a7f66e8d..7450bf4764 100644
--- a/plugins/Goals/templates/add_new_goal.tpl
+++ b/plugins/Goals/templates/add_new_goal.tpl
@@ -2,7 +2,5 @@
{if $userCanEditGoals}
{include file=Goals/templates/add_edit_goal.tpl}
{else}
-Only an Administrator or the Super User can add Goals for a given website.
-Please ask your Piwik administrator to set up a Goal for your website.
-<br>Tracking Goals are a great tool to help you maximize your website performance!
+{'Goals_NoGoalsNeedAccess'|translate}
{/if}
diff --git a/plugins/Goals/templates/form_add_goal.tpl b/plugins/Goals/templates/form_add_goal.tpl
index b60dbe7ad4..76350d9f40 100644
--- a/plugins/Goals/templates/form_add_goal.tpl
+++ b/plugins/Goals/templates/form_add_goal.tpl
@@ -1,85 +1,74 @@
-{literal}
-<style>
-.goalInlineHelp{
-color:#9B9B9B;
-}
-</style>
-{/literal}
<span id='GoalForm' style="display:none;">
<form>
- <table class="tableForm">
- <tbody>
- <tr>
- <td>Goal Name </td>
- <td><input type="text" name="name" value="" id="goal_name" /></td>
+<table class="tableForm tableFormGoals">
+ <tbody>
+ <tr>
+ <td>{'Goals_GoalName'|translate} </td>
+ <td><input type="text" name="name" value="" id="goal_name" /></td>
+ </tr>
+ <tr>
+ <td style='width:240px;'>{'Goals_GoalIsTriggered'|translate}
+ <select name="trigger_type">
+ <option value="visitors">{'Goals_WhenVisitors'|translate}</option>
+ <option value="manually">{'Goals_Manually'|translate}</option>
+ </select>
+ </td>
+ <td>
+ <input type="radio" id="match_attribute_url" value="url" name="match_attribute" />
+ <label for="match_attribute_url">{'Goals_VisitUrl'|translate}</label>
+ <br />
+ <input type="radio" id="match_attribute_file" value="file" name="match_attribute" />
+ <label for="match_attribute_file">{'Goals_Download'|translate}</label>
+ <br />
+ <input type="radio" id="match_attribute_external_website" value="external_website" name="match_attribute" />
+ <label for="match_attribute_external_website">{'Goals_ClickOutlink'|translate}</label>
+ </td>
</tr>
- <tr>
- <td>Goal is triggered
- <select name="trigger_type">
- <option value="visitors">when visitors</option>
- <option value="manually">manually</option>
- </select>
- </td>
- <td>
- <input type="radio" id="match_attribute_url" value="url" name="match_attribute"/>
- <label for="match_attribute_url">Visit a given URL (page or group of pages)</label>
- <br />
- <input type="radio" id="match_attribute_file" value="file" name="match_attribute"/>
- <label for="match_attribute_file">Download a file</label>
- <br />
- <input type="radio" id="match_attribute_external_website" value="external_website" name="match_attribute"/>
- <label for="match_attribute_external_website">Click on a Link to an external website </label>
- </td>
- </tr>
- </tbody>
- <tbody id="match_attribute_section">
- <tr>
- <td>where the <span id="match_attribute_name"></span></td>
- <td>
- <select name="pattern_type">
- <option value="contains">contains</option>
- <option value="exact">is exactly</option>
- <option value="regex">matches the expression</option>
- </select>
-
- <input type="text" name="pattern" value=""/>
- <br />
- <div id="examples_pattern" class="goalInlineHelp"></div>
- <br />
- <span style="float:right">
- (optional) <input type="checkbox" id="case_sensitive"/>
- <label for="case_sensitive">Case sensitive match</label>
- </span>
- </td>
- </tr>
- </tbody>
- <tbody id="manual_trigger_section" style="display:none">
- <tr>
- <td colspan="2">
- where the visited page manually calls the JavaScript piwikTracker.trackGoal() method (<a target='_blank' href='misc/redirectToUrl.php?url=http://piwik.org/docs/javascript-tracking/'>learn more</a>)
- </td>
- </tr>
- </tbody>
- <tbody>
- <tr>
- <td>(optional) Goal default value is </td>
- <td>{$currency} <input type="text" name="revenue" size="1" value="0"/>
- <div class="goalInlineHelp">
- For example, a Contact Form submitted by a visitor <br />
- may be worth $10 on average. Piwik will help you understand <br />
- how well your visitors segments are performing.</div>
- </td>
- </tr>
- <tr>
- <td colspan="2" style="border:0">
- <div class="submit">
- <input type="hidden" name="methodGoalAPI" value="">
- <input type="hidden" name="goalIdUpdate" value="">
- <input type="submit" value="Add Goal" name="submit" id="goal_submit" class="submit" />
- </div>
- </td>
- </tr>
- </tbody>
- </table>
+ </tbody>
+ <tbody id="match_attribute_section">
+ <tr>
+ <td>{'Goals_WhereThe'|translate} <span id="match_attribute_name"></span></td>
+ <td>
+ <select name="pattern_type">
+ <option value="contains">{'Goals_Contains'|translate:""}</option>
+ <option value="exact">{'Goals_IsExactly'|translate:""}</option>
+ <option value="regex">{'Goals_MatchesExpression'|translate:""}</option>
+ </select>
+
+ <input type="text" name="pattern" value="" />
+ <br />
+ <div id="examples_pattern" class="goalInlineHelp"></div>
+ <br />
+ <span style="float:right">
+ {'Goals_Optional'|translate} <input type="checkbox" id="case_sensitive" />
+ <label for="case_sensitive">{'Goals_CaseSensitive'|translate}</label>
+ </span>
+ </td>
+ </tr>
+ </tbody>
+ <tbody id="manual_trigger_section" style="display:none">
+ <tr><td colspan="2">
+ {'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore'|translate:"<a target='_blank' href='misc/redirectToUrl.php?url=http://piwik.org/docs/javascript-tracking/'>":"</a>"}
+ </td></tr>
+ </tbody>
+ <tbody>
+ <tr>
+ <td>(optional) {'Goals_DefaultRevenue'|translate}</td>
+ <td>{'<input type="text" name="revenue" size="1" value="0" />'|money:$idSite}
+ <div class="goalInlineHelp"> {'Goals_DefaultRevenueHelp'|translate} </div>
+ </td>
+ </tr>
+ <tr>
+ <tr>
+ <td colspan="2" style="border:0">
+ <input type="hidden" name="methodGoalAPI" value="" />
+ <input type="hidden" name="goalIdUpdate" value="" />
+ <center>
+ <input type="submit" value="" name="submit" id="goal_submit" class="submit" />
+ </center>
+ </td>
+ </tr>
+ </tbody>
+</table>
</form>
</span>
diff --git a/plugins/Goals/templates/goals.css b/plugins/Goals/templates/goals.css
new file mode 100644
index 0000000000..2fc9e0fbd5
--- /dev/null
+++ b/plugins/Goals/templates/goals.css
@@ -0,0 +1,40 @@
+ul.ulGoalTopElements {
+ list-style-type:circle;
+ margin-left:30px;
+}
+.ulGoalTopElements a {
+ text-decoration:none;
+ color:#0033CC;
+ border-bottom:1px dotted #0033CC;
+ line-height:2em;
+}
+.goalTopElement {
+ border-bottom:1px dotted;
+}
+.listCircle {
+ list-style:circle outside none;
+ margin-left:30px;
+}
+.segmentSelector ul li .segment{
+ cursor:pointer;
+ border-bottom:1px dotted black;
+}
+.segmentSelector ul li.activeSegment .segment {
+ font-weight: bold;
+ border:0;
+}
+
+#titleGoalsBySegment {
+ padding-top:30px;
+}
+.goalInlineHelp {
+ color:#9B9B9B;
+}
+.tableFormGoals {
+ width:700px;
+}
+#goalsCancel {
+ margin-left:550px;
+ margin-top:20px;
+ display:none;
+} \ No newline at end of file
diff --git a/plugins/Goals/templates/list_goal_edit.tpl b/plugins/Goals/templates/list_goal_edit.tpl
index 92cab34b25..805f3c2277 100644
--- a/plugins/Goals/templates/list_goal_edit.tpl
+++ b/plugins/Goals/templates/list_goal_edit.tpl
@@ -1,22 +1,41 @@
<span id='EditGoals' style="display:none;">
- <table class="tableForm">
+ <table class="tableForm tableFormGoals">
<thead style="font-weight:bold">
<td>Id</td>
- <td>Goal Name</td>
- <td>Goal is Triggered when</td>
- <td>Revenue</td>
- <td>Edit</td>
- <td>Delete</td>
+ <td>{'Goals_GoalName'|translate}</td>
+ <td>{'Goals_GoalIsTriggeredWhen'|translate}</td>
+ <td>{'Goals_ColumnRevenue'|translate}</td>
+ <td>{'General_Edit'|translate}</td>
+ <td>{'General_Delete'|translate}</td>
</thead>
{foreach from=$goals item=goal}
<tr>
<td>{$goal.idgoal}</td>
<td>{$goal.name}</td>
- <td>{$goal.match_attribute} {if isset($goal.pattern_type)}<br>Pattern {$goal.pattern_type}: {$goal.pattern}</b>{/if}</td>
- <td>{if $goal.revenue==0}-{else}{$currency}{$goal.revenue}{/if}</td>
- <td><a href='#' name="linkEditGoal" id="{$goal.idgoal}"><img src='plugins/UsersManager/images/edit.png' border=0> Edit</a></td>
- <td><a href='#' name="linkDeleteGoal" id="{$goal.idgoal}"><img src='plugins/UsersManager/images/remove.png' border=0> Delete</a></td>
+ <td><span class='matchAttribute'>{$goal.match_attribute}</span> {if isset($goal.pattern_type)}<br />{'Goals_Pattern'|translate} {$goal.pattern_type}: {$goal.pattern}</b>{/if}</td>
+ <td>{if $goal.revenue==0}-{else}{$goal.revenue|money:$idSite}{/if}</td>
+ <td><a href='#' name="linkEditGoal" id="{$goal.idgoal}"><img src='plugins/UsersManager/images/edit.png' border="0" /> {'General_Edit'|translate}</a></td>
+ <td><a href='#' name="linkDeleteGoal" id="{$goal.idgoal}"><img src='plugins/UsersManager/images/remove.png' border="0" /> {'General_Delete'|translate}</a></td>
</tr>
{/foreach}
</table>
</span>
+
+<script type="text/javascript">
+var goalTypeToTranslation = {ldelim}
+ "manually" : "{'Goals_ManuallyTriggeredUsingJavascriptFunction'|translate}",
+ "file" : "{'Goals_Download'|translate}",
+ "url" : "{'Goals_VisitUrl'|translate}",
+ "external_website" : "{'Goals_ClickOutlink'|translate}"
+{rdelim}
+{literal}
+$(document).ready( function() {
+ // translation of the goal "match attribute" to human readable description
+ $('.matchAttribute').each( function() {
+ matchAttribute = $(this).text();
+ translation = goalTypeToTranslation[matchAttribute];
+ $(this).text(translation);
+ });
+} );
+{/literal}
+</script>
diff --git a/plugins/Goals/templates/list_top_segment.tpl b/plugins/Goals/templates/list_top_segment.tpl
index 6dbe69813f..4e1ca412d3 100644
--- a/plugins/Goals/templates/list_top_segment.tpl
+++ b/plugins/Goals/templates/list_top_segment.tpl
@@ -1,5 +1,10 @@
{foreach from=$topSegment item=element name=topGoalElements}
-<span class='goalTopElement' title='<b>{$element.nb_conversions}</b> conversions, <b>{$element.conversion_rate}%</b> conversion rate'>
-{$element.name}</span>{logoHtml metadata=$element.metadata alt=$element.name}{if $smarty.foreach.topGoalElements.iteration == $smarty.foreach.topGoalElements.total-1} and {elseif $smarty.foreach.topGoalElements.iteration < $smarty.foreach.topGoalElements.total-1}, {else}{/if}
-{/foreach} {* (<a href=''>more</a>) *}
+ {assign var=goal_nb_conversion value=$element.nb_conversions}
+ {assign var=goal_conversion_rate value=$element.conversion_rate}
+ <span class='goalTopElement' title='{'Goals_Conversions'|translate:"<b>$goal_nb_conversion</b>"},
+ {'Goals_ConversionRate'|translate:"<b>$goal_conversion_rate%</b>"}'>
+ {$element.name}</span>
+ {logoHtml metadata=$element.metadata alt=$element.name}
+ {if $smarty.foreach.topGoalElements.iteration == $smarty.foreach.topGoalElements.total-1} and {elseif $smarty.foreach.topGoalElements.iteration < $smarty.foreach.topGoalElements.total-1}, {else}{/if}
+{/foreach} \ No newline at end of file
diff --git a/plugins/Goals/templates/overview.tpl b/plugins/Goals/templates/overview.tpl
index 1e342840dc..f08633c487 100644
--- a/plugins/Goals/templates/overview.tpl
+++ b/plugins/Goals/templates/overview.tpl
@@ -1,23 +1,32 @@
+<link rel="stylesheet" type="text/css" href="plugins/Goals/templates/goals.css" />
{include file="Goals/templates/title_and_evolution_graph.tpl"}
{foreach from=$goalMetrics item=goal}
-{assign var=nb_conversions value=$goal.nb_conversions}
-{assign var=conversion_rate value=$goal.conversion_rate}
-<h2 style="padding-top: 30px;">{$goal.name} (goal)</h2>
-<div id='leftcolumn'>
- <div class="sparkline">{sparkline src=$goal.urlSparklineConversions}
- {'%s conversions'|translate:"<strong>$nb_conversions</strong>"}</div>
-</div>
-<div id='rightcolumn'>
- <div class="sparkline">{sparkline src=$goal.urlSparklineConversionRate}
- {'%s conversion rate'|translate:"<strong>$conversion_rate%</strong>"}</div>
- {* (<a href=''>more</a>) *}
-</div>
+ {assign var=nb_conversions value=$goal.nb_conversions}
+ {assign var=conversion_rate value=$goal.conversion_rate}
+ {assign var=name value=$goal.name}
+
+ <h2 style="padding-top: 30px;">
+ {if $displayFullReport}<a href="javascript:broadcast.propagateAjax('module=Goals&action=goalReport&idGoal={$goal.id}')">{/if}
+ {'Goals_GoalX'|translate:"'$name'"}
+ {if $displayFullReport}</a>{/if}
+ </h2>
+ <div id='leftcolumn'>
+ <div class="sparkline">{sparkline src=$goal.urlSparklineConversions}
+ {'Goals_Conversions'|translate:"<strong>$nb_conversions</strong>"}</div>
+ </div>
+ <div id='rightcolumn'>
+ <div class="sparkline">{sparkline src=$goal.urlSparklineConversionRate}
+ {'Goals_ConversionRate'|translate:"<strong>$conversion_rate%</strong>"}</div>
+ </div>
{/foreach}
-{if $userCanEditGoals}
- {include file=Goals/templates/add_edit_goal.tpl}
-{/if}
+{if $displayFullReport}
-{include file="Goals/templates/release_notes.tpl}
+ {include file="Goals/templates/table_by_segment.tpl"}
+
+ {if $userCanEditGoals}
+ {include file=Goals/templates/add_edit_goal.tpl}
+ {/if}
+{/if} \ No newline at end of file
diff --git a/plugins/Goals/templates/release_notes.tpl b/plugins/Goals/templates/release_notes.tpl
deleted file mode 100644
index d987a7d849..0000000000
--- a/plugins/Goals/templates/release_notes.tpl
+++ /dev/null
@@ -1,36 +0,0 @@
-<div style="clear:both" />
-<br><br><hr>
-<b>About the Goal Tracking Plugin</b><br>
-<pre>
-The Goal Tracking Plugin is in alpha release. There is more coming soon!
-
-Give us Feedback!
-If you find any other bug, or if you have suggestions, please send us a message using the "Give us feedback" link at the top of the Piwik pages.
-
-Work left to do on the Goal Tracking plugin:
-- The Goal Report page will display conversion table by search engines, country, keyword, campaign, etc.
-- Contemplate adding goal conversions per landing page? If we add Goals per landing page, what page is used for goals that are triggered using piwikTracker.trackGoal in javascript?
-- The Goal Overview page will link to a Goal Report page with a "(more)" link that will ajax reload the page
-- Provide widgets for the dashboard, general goal overview, and one widget for each goal. With: graph evolution, sparklines. Widget with top segments for each goal.
-- Add visits with conversion sparkline in VisitsSummary overview
-- Add link under goal conversion to full goal reports (optional display)
-- Internationalization of all strings i18n
-- Provide documentation, screenshots, blog post + add screenshot and inline help in "Add a New Goal"
-- N/A% should be n/a
-- Way to test a URL against the regex
-- Test summary row works ok with subtables campaigns
-
-Known bugs
-- see bug described in http://forum.piwik.org/index.php?showtopic=150
-- Your top converting keyword include keyword without conversions?
-- The Goal total nb conversions should be sum of all goal conversions (wrong number when deleting a Goal)
-- After adding goal, the window should ideally refresh to the goal report page, and not to the dashboard
-- Outlink trailing slash is automatically deleted from the URL, there would be a problem when trying to exact match a URL with trailing slash
-- lines with 0 visits and no conversion should not appear
-
-Feature requests
-- need to clarify that goals are triggered once per visit max, but can be triggered multiple times by one unique visitor > need option to force only once per uniq visitor? (ie. e-commerce transaction)
-- GeoIp compatibility, archive goals by city, country? see archiveDayAggregateGoals
-- Goal conversions, revenue, etc. by hour
-- I would like to be able to plot conversions, for a given keyword/website, over the last N days/weeks/etc. See #534
-- when entering the regex to detect as a goal, we could query the piwik API for this regex and list all URLs that match the regex; allows for an easy debug/check that the regex is correct and will be triggererd when expected
diff --git a/plugins/Goals/templates/single_goal.tpl b/plugins/Goals/templates/single_goal.tpl
index 289be7b417..41968df30e 100644
--- a/plugins/Goals/templates/single_goal.tpl
+++ b/plugins/Goals/templates/single_goal.tpl
@@ -1,40 +1,28 @@
+<link rel="stylesheet" type="text/css" href="plugins/Goals/templates/goals.css" />
{include file="Goals/templates/title_and_evolution_graph.tpl"}
-<div style="clear:both"></div>
+<div style="clear:both;"></div>
{if $nb_conversions > 0}
- <h2>Conversions Overview</h2>
+ <h2>{'Goals_ConversionsOverview'|translate}</h2>
<ul class="ulGoalTopElements">
- <li>Your best converting countries are: {include file='Goals/templates/list_top_segment.tpl' topSegment=$topSegments.country}</li>
- {if count($topSegments.keyword)>0}<li>Your top converting keywords are: {include file='Goals/templates/list_top_segment.tpl' topSegment=$topSegments.keyword}</li>{/if}
- {if count($topSegments.website)>0}<li>Your best converting websites referers are: {include file='Goals/templates/list_top_segment.tpl' topSegment=$topSegments.website}</li>{/if}
- <li>Returning visitors conversion rate is <b>{$conversion_rate_returning}%</b>, New Visitors conversion rate is <b>{$conversion_rate_new}%</b></li>
+ <li>{'Goals_BestCountries'|translate} {include file='Goals/templates/list_top_segment.tpl' topSegment=$topSegments.country}</li>
+ {if count($topSegments.keyword)>0}<li>{'Goals_BestKeywords'|translate} {include file='Goals/templates/list_top_segment.tpl' topSegment=$topSegments.keyword}</li>{/if}
+ {if count($topSegments.website)>0}<li>{'Goals_BestReferers'|translate} {include file='Goals/templates/list_top_segment.tpl' topSegment=$topSegments.website}</li>{/if}
+ <li>{'Goals_ReturningVisitorsConversionRateIs'|translate:"<b>$conversion_rate_returning%</b>"}, {'Goals_NewVisitorsConversionRateIs'|translate:"<b>$conversion_rate_new%</b>"}</li>
</ul>
{/if}
-<hr>
-{$tableByConversion}
-<hr>
+
{literal}
-<style>
-ul.ulGoalTopElements {
- list-style-type:circle;
- margin-left:30px;
-}
-.ulGoalTopElements a {
- text-decoration:none;
- color:#0033CC;
- border-bottom:1px dotted #0033CC;
- line-height:2em;
-}
-.goalTopElement {
- border-bottom:1px dotted;
-}
-</style>
-<script>
+<script type="text/javascript">
$(document).ready( function() {
- $('.goalTopElement')
- .tooltip()
- ;
- });
+ $('.goalTopElement').tooltip();
+});
</script>
{/literal}
+
+{if $displayFullReport}
+ {if $nb_conversions > 0}
+ {include file="Goals/templates/table_by_segment.tpl"}
+ {/if}
+{/if} \ No newline at end of file
diff --git a/plugins/Goals/templates/table_by_segment.tpl b/plugins/Goals/templates/table_by_segment.tpl
new file mode 100644
index 0000000000..3dfa45eaa5
--- /dev/null
+++ b/plugins/Goals/templates/table_by_segment.tpl
@@ -0,0 +1,72 @@
+<h2 id='titleGoalsBySegment'>{if isset($idGoal)}
+ {'Goals_GoalConversionsBySegment'|translate:$goalName}
+ {else}{'Goals_ConversionsOverviewBySegment'|translate}{/if}</h2>
+
+<div class='segmentSelector' style='float: left;width: 220px;padding-left: 10px;height:450px'>
+ {foreach from=$goalSegments key=segmentFamilyName item=segments}
+ {'Goals_ViewGoalsBySegment'|translate:$segmentFamilyName}
+ <ul class='listCircle'>
+ {foreach from=$segments item=segment}
+ <li title='{'Goals_ViewGoalsBySegment'|translate:$segment.name}' class='goalSegment' module='{$segment.module}' action='{$segment.action}'>
+ <span class='segment'>{$segment.name}</span>
+ </li>
+ {/foreach}
+ </ul>
+ {/foreach}
+</div>
+
+<div style='float: left;'>
+ {ajaxLoadingDiv id=tableGoalsLoading}
+
+ <div id='tableGoalsBySegment'></div>
+</div>
+<div style='clear:both'></div>
+{literal}
+<script type="text/javascript">
+$(document).ready( function() {
+ var countLoaded = 0;
+ /*
+ * For each 'segment' in the list, a click will trigger an ajax request to load the datatable
+ * showing Goals metrics (conversion, conv. rates, revenue) for this segment
+ */
+ $('.goalSegment').click( function() {
+ var self = this;
+ $('.goalSegment').removeClass('activeSegment');
+ $(this).addClass('activeSegment');
+ var module = $(this).attr('module');
+ var action = $(this).attr('action');
+ widgetUniqueId = module+action;
+ self.expectedWidgetUniqueId = widgetUniqueId;
+
+ var idGoal = broadcast.getValueFromHash('idGoal');
+ var widgetParameters = {
+ 'module': module,
+ 'action': action,
+ 'viewDataTable': 'tableGoals',
+ 'filter_only_display_idgoal': idGoal.length ? idGoal : 0 // 0 is Piwik_DataTable_Filter_UpdateColumnsWhenShowAllGoals::GOALS_FULL_TABLE
+ };
+ var onWidgetLoadedCallback = function (response) {
+ if(widgetUniqueId != self.expectedWidgetUniqueId) {
+ return;
+ }
+ $('#tableGoalsBySegment').html($(response));
+ $('#tableGoalsLoading').hide();
+ $('#tableGoalsBySegment').show();
+
+ countLoaded++;
+ // only scroll down to the loaded datatable if this is not the first one
+ // otherwise, screen would jump down to the table when loading the report
+ if(countLoaded > 1)
+ {
+ piwikHelper.lazyScrollTo("#titleGoalsBySegment", 400);
+ }
+ };
+ $('#tableGoalsBySegment').hide();
+ $('#tableGoalsLoading').show();
+ ajaxRequest = widgetsHelper.getLoadWidgetAjaxRequest(widgetUniqueId, widgetParameters, onWidgetLoadedCallback);
+ $.ajax(ajaxRequest);
+ });
+ $('.goalSegment').first().click();
+});
+</script>
+{/literal}
diff --git a/plugins/Goals/templates/title_and_evolution_graph.tpl b/plugins/Goals/templates/title_and_evolution_graph.tpl
index 8a344df003..0ac5707d00 100644
--- a/plugins/Goals/templates/title_and_evolution_graph.tpl
+++ b/plugins/Goals/templates/title_and_evolution_graph.tpl
@@ -1,18 +1,22 @@
<script type="text/javascript" src="plugins/CoreHome/templates/sparkline.js"></script>
<a name="evolutionGraph" graphId="{$nameGraphEvolution}"></a>
-<h2>{$title}</h2>
+
+{if $displayFullReport}
+ <h2>{if isset($goalName)}{'Goals_GoalX'|translate:$goalName}{else}{'Goals_GoalsOverview'|translate}{/if}</h2>
+{/if}
{$graphEvolution}
<div id='leftcolumn'>
<div class="sparkline">{sparkline src=$urlSparklineConversions}
- {'%s conversions'|translate:"<strong>$nb_conversions</strong>"}</div>
+ {'Goals_Conversions'|translate:"<strong>$nb_conversions</strong>"}</div>
{if $revenue != 0 }
<div class="sparkline">{sparkline src=$urlSparklineRevenue}
- {'%s overall revenue'|translate:"<strong>$currency$revenue</strong>"}</div>
+ {assign var=revenue value=$revenue|money:$idSite}
+ {'Goals_OverallRevenue'|translate:"<strong>$revenue</strong>"}</div>
{/if}
</div>
<div id='rightcolumn'>
<div class="sparkline">{sparkline src=$urlSparklineConversionRate}
- {'%s overall conversion rate (visits with a completed goal)'|translate:"<strong>$conversion_rate%</strong>"}</div>
+ {'Goals_OverallConversionRate'|translate:"<strong>$conversion_rate%</strong>"}</div>
</div>
diff --git a/plugins/Installation/Controller.php b/plugins/Installation/Controller.php
index 022c1e4911..ef0929899e 100644
--- a/plugins/Installation/Controller.php
+++ b/plugins/Installation/Controller.php
@@ -11,6 +11,7 @@
*/
/**
+ * Installation controller
*
* @package Piwik_Installation
*/
@@ -21,6 +22,7 @@ class Piwik_Installation_Controller extends Piwik_Controller
'welcome' => 'Installation_Welcome',
'systemCheck' => 'Installation_SystemCheck',
'databaseSetup' => 'Installation_DatabaseSetup',
+ 'databaseCheck' => 'Installation_DatabaseCheck',
'tablesCreation' => 'Installation_Tables',
'generalSetup' => 'Installation_GeneralSetup',
'firstWebsiteSetup' => 'Installation_SetupWebsite',
@@ -38,35 +40,54 @@ class Piwik_Installation_Controller extends Piwik_Controller
if(!isset($this->session->currentStepDone))
{
$this->session->currentStepDone = '';
+ $this->session->skipThisStep = array();
}
Piwik_PostEvent('InstallationController.construct', $this);
}
+ /**
+ * Get installation steps
+ *
+ * @return array installation steps
+ */
public function getInstallationSteps()
{
return $this->steps;
}
+ /**
+ * Get default action (first installation step)
+ *
+ * @return string function name
+ */
function getDefaultAction()
{
$steps = array_keys($this->steps);
return $steps[0];
}
- function welcome()
+ /**
+ * Installation Step 1: Welcome
+ */
+ function welcome($message)
{
$view = new Piwik_Installation_View(
$this->pathView . 'welcome.tpl',
$this->getInstallationSteps(),
__FUNCTION__
);
+ $view->newInstall = !file_exists(Piwik_Config::getDefaultUserConfigPath());
+ $view->errorMessage = $message;
$this->skipThisStep( __FUNCTION__ );
- $view->showNextStep = true;
+ $view->showNextStep = $view->newInstall;
$this->session->currentStepDone = __FUNCTION__;
echo $view->render();
}
+ /**
+ * Installation Step 2: System Check
+ */
function systemCheck()
{
$this->checkPreviousStepIsValid( __FUNCTION__ );
@@ -80,12 +101,16 @@ class Piwik_Installation_Controller extends Piwik_Controller
$view->infos = self::getSystemInformation();
$view->helpMessages = array(
- 'zlib' => 'Installation_SystemCheckZlibHelp',
- 'SPL' => 'Installation_SystemCheckSplHelp',
- 'iconv' => 'Installation_SystemCheckIconvHelp',
- 'dom' => 'Installation_SystemCheckDomHelp',
- 'set_time_limit' => 'Installation_SystemCheckTimeLimitHelp',
- 'mail' => 'Installation_SystemCheckMailHelp',
+ 'zlib' => 'Installation_SystemCheckZlibHelp',
+ 'SPL' => 'Installation_SystemCheckSplHelp',
+ 'iconv' => 'Installation_SystemCheckIconvHelp',
+ 'dom' => 'Installation_SystemCheckDomHelp',
+ 'set_time_limit' => 'Installation_SystemCheckTimeLimitHelp',
+ 'mail' => 'Installation_SystemCheckMailHelp',
+ 'parse_ini_file' => 'Installation_SystemCheckParseIniFileHelp',
+ 'debug_backtrace' => 'Installation_SystemCheckDebugBacktraceHelp',
+ 'create_function' => 'Installation_SystemCheckCreateFunctionHelp',
+ 'eval' => 'Installation_SystemCheckEvalHelp',
);
$view->problemWithSomeDirectories = (false !== array_search(false, $view->infos['directories']));
@@ -94,6 +119,7 @@ class Piwik_Installation_Controller extends Piwik_Controller
&& $view->infos['phpVersion_ok']
&& count($view->infos['adapters'])
&& !count($view->infos['missing_extensions'])
+ && !count($view->infos['missing_functions'])
;
$this->session->currentStepDone = __FUNCTION__;
@@ -101,6 +127,9 @@ class Piwik_Installation_Controller extends Piwik_Controller
echo $view->render();
}
+ /**
+ * Installation Step 3: Database Set-up
+ */
function databaseSetup()
{
$this->checkPreviousStepIsValid( __FUNCTION__ );
@@ -125,7 +154,7 @@ class Piwik_Installation_Controller extends Piwik_Controller
if($form->validate())
{
$adapter = $form->getSubmitValue('adapter');
- $port = Piwik_Db::getDefaultPortForAdapter($adapter);
+ $port = Piwik_Db_Adapter::getDefaultPortForAdapter($adapter);
$dbInfos = array(
'host' => $form->getSubmitValue('host'),
@@ -153,9 +182,12 @@ class Piwik_Installation_Controller extends Piwik_Controller
try{
try {
Piwik::createDatabaseObject($dbInfos);
+ $this->session->databaseCreated = true;
} catch (Zend_Db_Adapter_Exception $e) {
+ $db = Piwik_Db_Adapter::factory($adapter, $dbInfos);
+
// database not found, we try to create it
- if(Zend_Registry::isRegistered('db') && Zend_Registry::get('db')->isErrNo($e, '1049'))
+ if($db->isErrNo($e, '1049'))
{
$dbInfosConnectOnly = $dbInfos;
$dbInfosConnectOnly['dbname'] = null;
@@ -165,11 +197,12 @@ class Piwik_Installation_Controller extends Piwik_Controller
}
else
{
- throw $e;
+ throw $e;
}
}
Piwik::checkDatabaseVersion();
+ $this->session->databaseVersionOk = true;
$this->session->db_infos = $dbInfos;
$this->redirectToNextStep( __FUNCTION__ );
@@ -179,11 +212,76 @@ class Piwik_Installation_Controller extends Piwik_Controller
}
$view->addForm($form);
- $view->infos = self::getSystemInformation();
+ echo $view->render();
+ }
+
+ /**
+ * Installation Step 4: Database Check
+ */
+ function databaseCheck()
+ {
+ $this->checkPreviousStepIsValid( __FUNCTION__ );
+ $view = new Piwik_Installation_View(
+ $this->pathView . 'databaseCheck.tpl',
+ $this->getInstallationSteps(),
+ __FUNCTION__
+ );
+
+ $error = false;
+ $this->skipThisStep( __FUNCTION__ );
+
+ if(isset($this->session->databaseVersionOk)
+ && $this->session->databaseVersionOk === true)
+ {
+ $view->databaseVersionOk = true;
+ }
+ else
+ {
+ $error = true;
+ }
+
+ if(isset($this->session->databaseCreated)
+ && $this->session->databaseCreated === true)
+ {
+ $dbInfos = $this->session->db_infos;
+ $view->databaseName = $dbInfos['dbname'];
+ $view->databaseCreated = true;
+ }
+ else
+ {
+ $error = true;
+ }
+
+ $this->createDbFromSessionInformation();
+ $db = Zend_Registry::get('db');
+
+ try {
+ $db->checkClientVersion();
+ } catch(Exception $e) {
+ $view->clientVersionWarning = $e->getMessage();
+ $error = true;
+ }
+
+ if(!Piwik::isDatabaseConnectionUTF8())
+ {
+ $dbInfos = $this->session->db_infos;
+ $dbInfos['charset'] = 'utf8';
+ $this->session->db_infos = $dbInfos;
+ }
+ $view->showNextStep = true;
+ $this->session->currentStepDone = __FUNCTION__;
+
+ if($error === false)
+ {
+ $this->redirectToNextStep(__FUNCTION__);
+ }
echo $view->render();
}
+ /**
+ * Installation Step 5: Table Creation
+ */
function tablesCreation()
{
$this->checkPreviousStepIsValid( __FUNCTION__ );
@@ -209,29 +307,31 @@ class Piwik_Installation_Controller extends Piwik_Controller
$this->session->skipThisStep = $tmp;
}
- if(!Piwik::isDatabaseConnectionUTF8())
- {
-// $view->charsetWarning = true;
- }
-
$tablesInstalled = Piwik::getTablesInstalled();
$tablesToInstall = Piwik::getTablesNames();
$view->tablesInstalled = '';
if(count($tablesInstalled) > 0)
{
+ // we have existing tables
$view->tablesInstalled = implode(', ', $tablesInstalled);
$view->someTablesInstalled = true;
$minimumCountPiwikTables = 12;
$baseTablesInstalled = preg_grep('/archive_numeric|archive_blob/', $tablesInstalled, PREG_GREP_INVERT);
- if(count($baseTablesInstalled) >= $minimumCountPiwikTables )
+
+ Piwik::createAccessObject();
+ Piwik::setUserIsSuperUser();
+
+ if(count($baseTablesInstalled) >= $minimumCountPiwikTables &&
+ count(Piwik_SitesManager_API::getInstance()->getAllSitesId()) > 0 &&
+ count(Piwik_UsersManager_API::getInstance()->getUsers()) > 0)
{
$view->showReuseExistingTables = true;
// when the user reuses the same tables we skip the website creation step
// workaround ZF-1743
$tmp = $this->session->skipThisStep;
$tmp['firstWebsiteSetup'] = true;
- $tmp['displayJavascriptCode'] = true;
+ $tmp['displayJavascriptCode'] = true;
$this->session->skipThisStep = $tmp;
}
}
@@ -246,18 +346,13 @@ class Piwik_Installation_Controller extends Piwik_Controller
$view->showNextStep = true;
}
- if(isset($this->session->databaseCreated)
- && $this->session->databaseCreated === true)
- {
- $view->databaseName = $this->session->db_infos['dbname'];
- $view->databaseCreated = true;
- unset($this->session->databaseCreated);
- }
-
$this->session->currentStepDone = __FUNCTION__;
echo $view->render();
}
+ /**
+ * Installation Step 6: General Set-up (superuser login/password/email and subscriptions)
+ */
function generalSetup()
{
$this->checkPreviousStepIsValid( __FUNCTION__ );
@@ -277,6 +372,7 @@ class Piwik_Installation_Controller extends Piwik_Controller
'login' => $form->getSubmitValue('login'),
'password' => md5( $form->getSubmitValue('password') ),
'email' => $form->getSubmitValue('email'),
+ 'salt' => Piwik_Common::generateUniqId(),
);
$this->session->superuser_infos = $superUserInfos;
@@ -296,7 +392,7 @@ class Piwik_Installation_Controller extends Piwik_Controller
if( !isset($params['community'])) { $params['community'] = '0'; }
$url = $host . '?' . http_build_query($params, '', '&');
try {
- Piwik::sendHttpRequest($url, $timeout = 2);
+ Piwik_Http::sendHttpRequest($url, $timeout = 2);
} catch(Exception $e) {
// e.g., disable_functions = fsockopen; allow_url_open = Off
}
@@ -308,6 +404,9 @@ class Piwik_Installation_Controller extends Piwik_Controller
echo $view->render();
}
+ /**
+ * Installation Step 7: Configure first web-site
+ */
public function firstWebsiteSetup()
{
$this->checkPreviousStepIsValid( __FUNCTION__ );
@@ -326,12 +425,12 @@ class Piwik_Installation_Controller extends Piwik_Controller
$this->session->generalSetupSuccessMessage = true;
}
+ $this->initObjectsToCallAPI();
if($form->validate())
{
$name = urlencode($form->getSubmitValue('siteName'));
$url = urlencode($form->getSubmitValue('url'));
- $this->initObjectsToCallAPI();
$request = new Piwik_API_Request("
method=SitesManager.addSite
@@ -356,6 +455,9 @@ class Piwik_Installation_Controller extends Piwik_Controller
echo $view->render();
}
+ /**
+ * Installation Step 8: Display JavaScript tracking code
+ */
public function displayJavascriptCode()
{
$this->checkPreviousStepIsValid( __FUNCTION__ );
@@ -373,7 +475,6 @@ class Piwik_Installation_Controller extends Piwik_Controller
$this->session->firstWebsiteSetupSuccessMessage = true;
}
-
$view->websiteName = urldecode($this->session->site_name);
$jsTag = Piwik::getJavascriptCode($this->session->site_idSite, Piwik_Url::getCurrentUrlWithoutFileName());
@@ -385,6 +486,9 @@ class Piwik_Installation_Controller extends Piwik_Controller
echo $view->render();
}
+ /**
+ * Installation Step 9: Finished!
+ */
public function finished()
{
$this->checkPreviousStepIsValid( __FUNCTION__ );
@@ -395,14 +499,21 @@ class Piwik_Installation_Controller extends Piwik_Controller
__FUNCTION__
);
$this->skipThisStep( __FUNCTION__ );
- $this->writeConfigFileFromSession();
- $this->session->currentStepDone = __FUNCTION__;
+ if(!file_exists(Piwik_Config::getDefaultUserConfigPath()))
+ {
+ $this->writeConfigFileFromSession();
+ }
+
$view->showNextStep = false;
+ $this->session->currentStepDone = __FUNCTION__;
echo $view->render();
}
+ /**
+ * Instantiate access and log objects
+ */
protected function initObjectsToCallAPI()
{
// connect to the database using the DB infos currently in the session
@@ -413,6 +524,20 @@ class Piwik_Installation_Controller extends Piwik_Controller
Piwik::createLogObject();
}
+ /**
+ * Create database connection from session-store
+ */
+ protected function createDbFromSessionInformation()
+ {
+ $dbInfos = $this->session->db_infos;
+ Zend_Registry::get('config')->disableSavingConfigurationFileUpdates();
+ Zend_Registry::get('config')->database = $dbInfos;
+ Piwik::createDatabaseObject($dbInfos);
+ }
+
+ /**
+ * Write configuration file from session-store
+ */
protected function writeConfigFileFromSession()
{
if(!isset($this->session->superuser_infos)
@@ -422,32 +547,50 @@ class Piwik_Installation_Controller extends Piwik_Controller
}
$config = Zend_Registry::get('config');
$config->superuser = $this->session->superuser_infos;
- $config->database = $this->session->db_infos;
+ $dbInfos = $this->session->db_infos;
+ $config->database = $dbInfos;
+
+ unset($this->session->superuser_infos);
+ unset($this->session->db_infos);
+ }
+
+ /**
+ * Save language selection in session-store
+ */
+ public function saveLanguage()
+ {
+ $language = Piwik_Common::getRequestVar('language');
+ Piwik_LanguagesManager_API::getInstance()->setLanguageForSession($language);
+ Piwik_Url::redirectToReferer();
}
/**
* The previous step is valid if it is either
* - any step before (OK to go back)
* - the current step (case when validating a form)
+ * If step is invalid, then exit.
+ *
+ * @param string $currentStep Current step
*/
protected function checkPreviousStepIsValid( $currentStep )
{
$error = false;
- // first we make sure that the config file is not present, ie. Installation state is expected
- try {
- $config = new Piwik_Config();
- $config->init();
- $error = true;
- } catch(Exception $e) {
- }
-
if(empty($this->session->currentStepDone))
{
$error = true;
}
+ else if($currentStep == 'finished' && $this->session->currentStepDone == 'finished')
+ {
+ // ok to refresh this page or use language selector
+ }
else
{
+ if(file_exists(Piwik_Config::getDefaultUserConfigPath()))
+ {
+ $error = true;
+ }
+
$steps = array_keys($this->steps);
// the currentStep
@@ -475,6 +618,12 @@ class Piwik_Installation_Controller extends Piwik_Controller
}
}
+ /**
+ * Redirect to next step
+ *
+ * @param string Current step
+ * @return none
+ */
protected function redirectToNextStep($currentStep)
{
$steps = array_keys($this->steps);
@@ -483,14 +632,23 @@ class Piwik_Installation_Controller extends Piwik_Controller
Piwik::redirectToModule('Installation' , $nextStep);
}
- protected function createDbFromSessionInformation()
+ /**
+ * Skip this step (typically to mark the current function as completed)
+ *
+ * @param string function name
+ */
+ protected function skipThisStep( $step )
{
- $dbInfos = $this->session->db_infos;
- Zend_Registry::get('config')->disableSavingConfigurationFileUpdates();
- Zend_Registry::get('config')->database = $dbInfos;
- Piwik::createDatabaseObject($dbInfos);
+ $skipThisStep = $this->session->skipThisStep;
+ if(isset($skipThisStep[$step]) && $skipThisStep[$step])
+ {
+ $this->redirectToNextStep($step);
+ }
}
+ /**
+ * Get system information
+ */
public static function getSystemInformation()
{
$minimumPhpVersion = Zend_Registry::get('config')->General->minimum_php_version;
@@ -499,6 +657,17 @@ class Piwik_Installation_Controller extends Piwik_Controller
$infos = array();
$infos['directories'] = Piwik::checkDirectoriesWritable();
+
+ $serverSoftware = $_SERVER['SERVER_SOFTWARE'];
+ if(preg_match('/^Microsoft-IIS\/(.+)/', $serverSoftware, $matches) && version_compare($matches[1], '7') >= 0)
+ {
+ Piwik::createWebConfigFiles();
+ }
+ else if(strpos($serverSoftware, 'Apache/') === 0)
+ {
+ Piwik::createHtAccessFiles();
+ }
+
$infos['phpVersion_minimum'] = $minimumPhpVersion;
$infos['phpVersion'] = phpversion();
$infos['phpVersion_ok'] = version_compare( $minimumPhpVersion, $infos['phpVersion']) === -1;
@@ -509,6 +678,7 @@ class Piwik_Installation_Controller extends Piwik_Controller
'zlib',
'SPL',
'iconv',
+ 'Reflection',
);
$infos['needed_extensions'] = $needed_extensions;
$infos['missing_extensions'] = array();
@@ -526,7 +696,7 @@ class Piwik_Installation_Controller extends Piwik_Controller
$infos['pdo_ok'] = true;
}
- $infos['adapters'] = Piwik_Db::getAdapters();
+ $infos['adapters'] = Piwik_Db_Adapter::getAdapters();
$infos['json'] = false;
if(in_array('json', $extensions))
@@ -540,36 +710,72 @@ class Piwik_Installation_Controller extends Piwik_Controller
$infos['xml'] = true;
}
- // warnings
$needed_functions = array(
- 'set_time_limit',
- 'mail',
+ 'debug_backtrace',
+ 'create_function',
+ 'eval',
);
$infos['needed_functions'] = $needed_functions;
$infos['missing_functions'] = array();
foreach($needed_functions as $needed_function)
{
- if(!function_exists($needed_function))
+ if(!self::functionExists($needed_function))
{
$infos['missing_functions'][] = $needed_function;
}
}
- $infos['openurl'] = Piwik::getTransportMethod();
+ // warnings
+ $desired_functions = array(
+ 'set_time_limit',
+ 'mail',
+ 'parse_ini_file',
+ );
+ $infos['desired_functions'] = $desired_functions;
+ $infos['missing_desired_functions'] = array();
+ foreach($desired_functions as $desired_function)
+ {
+ if(!self::functionExists($desired_function))
+ {
+ $infos['missing_desired_functions'][] = $desired_function;
+ }
+ }
+
+ $infos['openurl'] = Piwik_Http::getTransportMethod();
$infos['gd_ok'] = false;
if (in_array('gd', $extensions))
{
- $gdInfo = gd_info();
+ $gdInfo = gd_info();
$infos['gd_version'] = $gdInfo['GD Version'];
- preg_match('/([0-9]{1})/', $gdInfo['GD Version'], $gdVersion);
- if($gdVersion[0] >= 2)
- {
+ preg_match('/([0-9]{1})/', $gdInfo['GD Version'], $gdVersion);
+ if($gdVersion[0] >= 2)
+ {
$infos['gd_ok'] = true;
- }
+ }
}
- $infos['serverVersion'] = addslashes($_SERVER['SERVER_SOFTWARE']);
+ $infos['hasMbstring'] = false;
+ $infos['multibyte_ok'] = true;
+ if(function_exists('mb_internal_encoding'))
+ {
+ $infos['hasMbstring'] = true;
+ if (((int) ini_get('mbstring.func_overload')) != 0)
+ {
+ $infos['multibyte_ok'] = false;
+ }
+ }
+
+ /**
+ * @see http://php.net/ip2long
+ */
+ $infos['isIpv4'] = true;
+ if(strpos($_SERVER['REMOTE_ADDR'], ':') !== false)
+ {
+ $infos['isIpv4'] = false;
+ }
+
+ $infos['serverVersion'] = addslashes($serverSoftware);
$infos['serverOs'] = @php_uname();
$infos['serverTime'] = date('H:i:s');
@@ -577,8 +783,7 @@ class Piwik_Installation_Controller extends Piwik_Controller
$infos['memoryMinimum'] = $minimumMemoryLimit;
$infos['memory_ok'] = true;
- // on windows the ini_get is not working?
- $infos['memoryCurrent'] = '?M';
+ $infos['memoryCurrent'] = '-1';
$raised = Piwik::raiseMemoryLimitIfNecessary();
if( $memoryValue = Piwik::getMemoryLimitValue() )
@@ -587,24 +792,98 @@ class Piwik_Installation_Controller extends Piwik_Controller
$infos['memory_ok'] = $memoryValue >= $minimumMemoryLimit;
}
- $infos['isWindows'] = substr(PHP_OS, 0, 3) == 'WIN';
+ $infos['isWindows'] = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN';
+
+ $infos['protocol_ok'] = true;
+ $infos['protocol'] = self::getProtocolInformation();
+ if(Piwik_Url::getCurrentScheme() == 'http' &&
+ $infos['protocol'] !== null)
+ {
+ $infos['protocol_ok'] = false;
+ }
+
+ $integrityInfo = Piwik::getFileIntegrityInformation();
+ $infos['integrity'] = $integrityInfo[0];
+
+ $infos['integrityErrorMessages'] = array();
+ if(isset($integrityInfo[1]))
+ {
+ if($infos['integrity'] == false)
+ {
+ $infos['integrityErrorMessages'][] = '<b>'.Piwik_Translate('General_FileIntegrityWarningExplanation').'</b>';
+ }
+ $infos['integrityErrorMessages'] = array_merge($infos['integrityErrorMessages'], array_slice($integrityInfo, 1));
+ }
+ $infos['timezone'] = Piwik::isTimezoneSupportEnabled();
return $infos;
}
- protected function skipThisStep( $step )
+ /**
+ * Get protocol information, with the exception of HTTPS
+ *
+ * @return string protocol information
+ */
+ public static function getProtocolInformation()
{
- if(isset($this->session->skipThisStep[$step])
- && $this->session->skipThisStep[$step])
+ if(Piwik_Common::getRequestVar('clientProtocol', 'http', 'string') == 'https')
{
- $this->redirectToNextStep($step);
+ return 'https';
+ }
+
+ if(isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443)
+ {
+ return 'SERVER_PORT=443';
}
+
+ if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https')
+ {
+ return 'X-Forwarded-Proto';
+ }
+
+ if(isset($_SERVER['HTTP_X_FORWARDED_SCHEME']) && strtolower($_SERVER['HTTP_X_FORWARDED_SCHEME']) == 'https')
+ {
+ return 'X-Forwarded-Scheme';
+ }
+
+ if(isset($_SERVER['HTTP_X_URL_SCHEME']) && strtolower($_SERVER['HTTP_X_URL_SCHEME']) == 'https')
+ {
+ return 'X-Url-Scheme';
+ }
+
+ return null;
}
- public function saveLanguage()
+ /**
+ * Test if function exists. Also handles case where function is disabled via Suhosin.
+ *
+ * @param string $functionName Function name
+ * @return bool True if function exists (not disabled); False otherwise.
+ */
+ public static function functionExists($functionName)
{
- $language = Piwik_Common::getRequestVar('language');
- Piwik_LanguagesManager_API::setLanguageForSession($language);
- Piwik_Url::redirectToReferer();
+ // eval() is a language construct
+ if($functionName == 'eval')
+ {
+ // does not check suhosin.executor.eval.whitelist (or blacklist)
+ if(extension_loaded('suhosin'))
+ {
+ return @ini_get("suhosin.executor.disable_eval") != "1";
+ }
+ return true;
+ }
+
+ $exists = function_exists($functionName);
+ if(extension_loaded('suhosin'))
+ {
+ $blacklist = @ini_get("suhosin.executor.func.blacklist");
+ if(!empty($blacklist))
+ {
+ $blacklistFunctions = array_map('strtolower', array_map('trim', explode(',', $blacklist)));
+ return $exists && !in_array($functionName, $blacklistFunctions);
+ }
+
+ }
+ return $exists;
}
}
diff --git a/plugins/Installation/FormDatabaseSetup.php b/plugins/Installation/FormDatabaseSetup.php
index 2669cbcc5f..807cffd723 100644
--- a/plugins/Installation/FormDatabaseSetup.php
+++ b/plugins/Installation/FormDatabaseSetup.php
@@ -16,22 +16,26 @@
*/
class Piwik_Installation_FormDatabaseSetup extends Piwik_Form
{
+ function __construct()
+ {
+ parent::__construct($action = '', $attributes = 'autocomplete="off"');
+ }
function init()
{
- $infos = Piwik_Installation_Controller::getSystemInformation();
+ $availableAdapters = Piwik_Db_Adapter::getAdapters();
$adapters = array();
- foreach($infos['adapters'] as $adapter => $port)
+ foreach($availableAdapters as $adapter => $port)
{
$adapters[$adapter] = $adapter;
}
$formElements = array(
- array('text', 'host', 'mysql server', 'value='.'localhost'),
- array('text', 'username', 'login'),
- array('password', 'password', 'password'),
- array('text', 'dbname', 'database name'),
- array('text', 'tables_prefix', 'table prefix', 'value='.'piwik_'),
- array('select', 'adapter', 'adapter', $adapters),
+ array('text', 'host', Piwik_Translate('Installation_DatabaseSetupServer'), 'value='.'localhost'),
+ array('text', 'username', Piwik_Translate('Installation_DatabaseSetupLogin')),
+ array('password', 'password', Piwik_Translate('Installation_DatabaseSetupPassword')),
+ array('text', 'dbname', Piwik_Translate('Installation_DatabaseSetupDatabaseName')),
+ array('text', 'tables_prefix', Piwik_Translate('Installation_DatabaseSetupTablePrefix'), 'value='.'piwik_'),
+ array('select', 'adapter', Piwik_Translate('Installation_DatabaseSetupAdapter'), $adapters),
);
$this->addElements( $formElements );
diff --git a/plugins/Installation/FormFirstWebsiteSetup.php b/plugins/Installation/FormFirstWebsiteSetup.php
index 65f2666263..115b859a95 100644
--- a/plugins/Installation/FormFirstWebsiteSetup.php
+++ b/plugins/Installation/FormFirstWebsiteSetup.php
@@ -16,6 +16,20 @@
*/
class Piwik_Installation_FormFirstWebsiteSetup extends Piwik_Form
{
+ function validate()
+ {
+ try {
+ $timezone = $this->getSubmitValue('timezone');
+ if(!empty($timezone))
+ {
+ Piwik_SitesManager_API::getInstance()->setDefaultTimezone($timezone);
+ }
+ } catch(Exception $e) {
+ $this->_errors['timezone'] = Piwik_Translate('General_NotValid', Piwik_Translate('Installation_Timezone'));
+ }
+ return parent::validate();
+ }
+
function init()
{
$urlToGoAfter = 'index.php' . Piwik_Url::getCurrentQueryString();
@@ -23,9 +37,14 @@ class Piwik_Installation_FormFirstWebsiteSetup extends Piwik_Form
$urlExample = 'http://example.org';
$javascriptOnClickUrlExample = "\"javascript:if(this.value=='$urlExample'){this.value='http://';} this.style.color='black';\"";
+ $timezones = Piwik_SitesManager_API::getInstance()->getTimezonesList();
+ $timezones = array_merge(array('No timezone' => Piwik_Translate('SitesManager_SelectACity')), $timezones);
+
$formElements = array(
- array('text', 'siteName', 'website name'),
- array('text', 'url', 'website URL', "style='color:rgb(153, 153, 153);' value=$urlExample onfocus=".$javascriptOnClickUrlExample." onclick=".$javascriptOnClickUrlExample),
+ array('text', 'siteName', Piwik_Translate('Installation_SetupWebSiteName')),
+ array('text', 'url', Piwik_Translate('Installation_SetupWebSiteURL'), "style='color:rgb(153, 153, 153);' value=$urlExample onfocus=".$javascriptOnClickUrlExample." onclick=".$javascriptOnClickUrlExample),
+ array('select', 'timezone', Piwik_Translate('Installation_Timezone'), $timezones),
+
);
$this->addElements( $formElements );
@@ -35,6 +54,13 @@ class Piwik_Installation_FormFirstWebsiteSetup extends Piwik_Form
$formRules[] = array($row[1], Piwik_Translate('General_Required', $row[2]), 'required');
}
+
+ $submitTimezone = $this->getSubmitValue('timezone');
+ if(!$this->isSubmitted()
+ || !empty($submitTimezone))
+ {
+ $this->setSelected('timezone', $submitTimezone);
+ }
$this->addRules( $formRules );
$this->addElement('submit', 'submit', Piwik_Translate('Installation_SubmitGo'));
diff --git a/plugins/Installation/FormGeneralSetup.php b/plugins/Installation/FormGeneralSetup.php
index 0f9e8d0662..a1b62aaaf9 100644
--- a/plugins/Installation/FormGeneralSetup.php
+++ b/plugins/Installation/FormGeneralSetup.php
@@ -16,6 +16,25 @@
*/
class Piwik_Installation_FormGeneralSetup extends Piwik_Form
{
+ function __construct()
+ {
+ parent::__construct($action = '', $attributes = 'autocomplete="off"');
+ }
+
+ function validate()
+ {
+ try {
+ $login = $this->getSubmitValue('login');
+ if(!empty($login))
+ {
+ Piwik::checkValidLoginString($login);
+ }
+ } catch(Exception $e) {
+ $this->_errors['login'] = $e->getMessage();
+ }
+ return parent::validate();
+ }
+
function init()
{
$urlToGoAfter = 'index.php' . Piwik_Url::getCurrentQueryString();
diff --git a/plugins/Installation/Installation.php b/plugins/Installation/Installation.php
index 0b17c974f5..fbdd695b76 100644
--- a/plugins/Installation/Installation.php
+++ b/plugins/Installation/Installation.php
@@ -21,11 +21,10 @@ class Piwik_Installation extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Installation',
- 'description' => 'Installation process of Piwik. The Installation is usually done once only. If the configuration file config/config.inc.php is deleted, the installation will start again.',
+ 'description' => Piwik_Translate('Installation_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
@@ -35,6 +34,7 @@ class Piwik_Installation extends Piwik_Plugin
{
$hooks = array(
'FrontController.NoConfigurationFile' => 'dispatch',
+ 'FrontController.badConfigurationFile' => 'dispatch',
);
return $hooks;
}
@@ -49,8 +49,18 @@ class Piwik_Installation extends Piwik_Plugin
return new $this->installationControllerName();
}
- function dispatch()
+ function dispatch($notification = null)
{
+ if($notification)
+ {
+ $exception = $notification->getNotificationObject();
+ $message = $exception->getMessage();
+ }
+ else
+ {
+ $message = '';
+ }
+
Piwik_Translate::getInstance()->loadUserTranslation();
Piwik_PostEvent('Installation.startInstallation', $this);
@@ -59,7 +69,7 @@ class Piwik_Installation extends Piwik_Plugin
$controller = $this->getInstallationController();
if(in_array($step, array_keys($controller->getInstallationSteps())) || $step == 'saveLanguage')
{
- $controller->$step();
+ $controller->$step($message);
}
else
{
diff --git a/plugins/Installation/View.php b/plugins/Installation/View.php
index 0b5e288890..7f3ae3c197 100644
--- a/plugins/Installation/View.php
+++ b/plugins/Installation/View.php
@@ -48,6 +48,11 @@ class Piwik_Installation_View extends Piwik_View
{
$this->previousModuleName = $this->steps[$this->currentStepId - 1];
}
+ $this->previousPreviousModuleName = '';
+ if(isset($this->steps[$this->currentStepId - 2]))
+ {
+ $this->previousPreviousModuleName = $this->steps[$this->currentStepId - 2];
+ }
return parent::render();
}
diff --git a/plugins/Installation/templates/databaseCheck.tpl b/plugins/Installation/templates/databaseCheck.tpl
new file mode 100644
index 0000000000..3374582f74
--- /dev/null
+++ b/plugins/Installation/templates/databaseCheck.tpl
@@ -0,0 +1,34 @@
+{assign var=ok value="<img src='themes/default/images/ok.png' />"}
+{assign var=error value="<img src='themes/default/images/error.png' />"}
+{assign var=warning value="<img src='themes/default/images/warning.png' />"}
+{assign var=link value="<img src='themes/default/images/link.gif' />"}
+
+<h1>{'Installation_DatabaseCheck'|translate}</h1>
+
+<table class="infosServer">
+ <tr>
+ <td class="label">{'Installation_DatabaseServerVersion'|translate}</td>
+ <td>{if isset($databaseVersionOk)}{$ok}{else}{$error}{/if}</td>
+ </tr>
+ <tr>
+ <td class="label">{'Installation_DatabaseClientVersion'|translate}</td>
+ <td>{if isset($clientVersionWarning)}{$warning}{else}{$ok}{/if}</td>
+ </tr>
+{if isset($clientVersionWarning)}
+ <tr>
+ <td colspan="2">
+ <small>
+ <span style="color:#FF7F00">{$clientVersionWarning}</span>
+ </small>
+ </td>
+ </tr>
+{/if}
+ <tr>
+ <td class="label">{'Installation_DatabaseCreation'|translate}</td>
+ <td>{if isset($databaseCreated)}{$ok}{else}{$error}{/if}</td>
+ </tr>
+</table>
+
+<p>
+{$link} <a href="misc/redirectToUrl.php?url=http://piwik.org/docs/requirements/" target="_blank">{'Installation_Requirements'|translate}</a>
+</p>
diff --git a/plugins/Installation/templates/databaseSetup.tpl b/plugins/Installation/templates/databaseSetup.tpl
index 65646a7664..ff60befc62 100644
--- a/plugins/Installation/templates/databaseSetup.tpl
+++ b/plugins/Installation/templates/databaseSetup.tpl
@@ -2,7 +2,7 @@
{if isset($errorMessage)}
<div class="error">
- <img src="themes/default/images/error_medium.png">
+ <img src="themes/default/images/error_medium.png" />
{'Installation_DatabaseErrorConnect'|translate}:
<br />{$errorMessage}
diff --git a/plugins/Installation/templates/displayJavascriptCode.tpl b/plugins/Installation/templates/displayJavascriptCode.tpl
index 41f5fa6c53..4cdd03c082 100644
--- a/plugins/Installation/templates/displayJavascriptCode.tpl
+++ b/plugins/Installation/templates/displayJavascriptCode.tpl
@@ -27,7 +27,7 @@ $(document).ready( function(){
<span id="toFade" class="success">
{'Installation_SetupWebsiteSetupSuccess'|translate:$websiteName}
- <img src="themes/default/images/success_medium.png">
+ <img src="themes/default/images/success_medium.png" />
</span>
{/if}
<h1>{'Installation_JsTag'|translate}</h1>
@@ -36,9 +36,10 @@ $(document).ready( function(){
{$javascriptTag}
</code>
-<h1>{'Installation_QuickHelp'|translate}:</h1>
+<h1>{'Installation_JsTagHelpTitle'|translate}</h1>
{include file=SitesManager/templates/JavascriptTagHelp.tpl}
-<ul>
-<li>{'Installation_JsTagArchivingHelp'|translate}</li>
+
+<br />
+<h1>{'Installation_LargePiwikInstances'|translate}</h1>
+{'Installation_JsTagArchivingHelp'|translate}
<!-- <li>Link to help with the main blog engines wordpress/drupal/myspace/blogspot</li> -->
-</ul>
diff --git a/plugins/Installation/templates/firstWebsiteSetup.tpl b/plugins/Installation/templates/firstWebsiteSetup.tpl
index 2e97223be7..f8d19f70af 100644
--- a/plugins/Installation/templates/firstWebsiteSetup.tpl
+++ b/plugins/Installation/templates/firstWebsiteSetup.tpl
@@ -3,7 +3,7 @@
{if isset($displayGeneralSetupSuccess)}
<span id="toFade" class="success">
{'Installation_GeneralSetupSuccess'|translate}
- <img src="themes/default/images/success_medium.png">
+ <img src="themes/default/images/success_medium.png" />
</span>
{/if}
@@ -11,7 +11,7 @@
{if isset($errorMessage)}
<div class="error">
- <img src="themes/default/images/error_medium.png">
+ <img src="themes/default/images/error_medium.png" />
{'Installation_SetupWebsiteError'|translate}:
<br />- {$errorMessage}
diff --git a/plugins/Installation/templates/integrityDetails.tpl b/plugins/Installation/templates/integrityDetails.tpl
new file mode 100644
index 0000000000..edac941868
--- /dev/null
+++ b/plugins/Installation/templates/integrityDetails.tpl
@@ -0,0 +1,43 @@
+{if !isset($warningMessages)}
+{assign var=warningMessages value=$infos.integrityErrorMessages}
+{/if}
+<div id="integrity-results" title="{'Installation_SystemCheckFileIntegrity'|translate}" style="display:none; font-size: 62.5%;">
+ <table>
+ {foreach from=$warningMessages item=msg}
+ <tr><td>{$msg}</td></tr>
+ {/foreach}
+ </table>
+</div>
+<script type="text/javascript">
+{literal}<!--
+$(function() {
+ $("#integrity-results").dialog({
+ bgiframe: true,
+ modal: true,
+ autoOpen: false,
+ width: 600,
+ buttons: {
+ Ok: function() {
+ $(this).dialog('close');
+ }
+ }
+ });
+});
+$('#more-results').click(function() {
+ $('#integrity-results').dialog('open');
+})
+.hover(
+ function(){
+ $(this).addClass("ui-state-hover");
+ },
+ function(){
+ $(this).removeClass("ui-state-hover");
+ }
+).mousedown(function(){
+ $(this).addClass("ui-state-active");
+})
+.mouseup(function(){
+ $(this).removeClass("ui-state-active");
+});
+//-->{/literal}
+</script>
diff --git a/plugins/Installation/templates/structure.tpl b/plugins/Installation/templates/structure.tpl
index 074b13abd3..b98ca8e077 100644
--- a/plugins/Installation/templates/structure.tpl
+++ b/plugins/Installation/templates/structure.tpl
@@ -5,7 +5,9 @@
<title>Piwik &rsaquo; {'Installation_Installation'|translate}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-{postEvent name="template_css_import"}
+<link rel="stylesheet" type="text/css" href="themes/default/common.css" />
+<link rel="stylesheet" type="text/css" href="libs/jquery/themes/base/jquery-ui.css" />
+<link rel="stylesheet" type="text/css" href="themes/default/styles.css" />
<script type="text/javascript" src="libs/jquery/jquery.js"></script>
<script type="text/javascript" src="libs/jquery/jquery-ui.js"></script>
@@ -16,12 +18,17 @@
$(document).ready( function(){
$('#toFade').fadeOut(4000, function(){ $(this).css('display', 'hidden'); } );
$('input:first').focus();
+ $('#progressbar').progressbar({
+{/literal}
+ value: {$percentDone}
+{literal}
});
+});
</script>
{/literal}
{literal}
-<style>
+<style type="text/css">
div.both {
clear: both;
}
@@ -44,7 +51,7 @@ body {
}
#logo {
- padding:30;
+ padding:30px;
}
h1 {
@@ -60,6 +67,12 @@ h3 {
color:#3F5163;
}
+.topBarElem {
+ font-family:arial,sans-serif !important;
+ font-size:13px;
+ line-height:1.33;
+}
+
.error {
color:red;
font-size:100%;
@@ -80,13 +93,18 @@ h3 {
padding:10;
}
.warning {
+ margin:10px;
color:#ff5502;
font-size:130%;
font-weight:bold;
- padding:10;
+ padding:10px 20px 10px 30px;
border: 1px solid #ff5502;
}
+.warning ul {
+ list-style:disc;
+}
+
.success img, .warning img {
border:0;
vertical-align:bottom;
@@ -113,10 +131,8 @@ h3 {
margin: auto;
background: #FFFFFF;
padding: 0.2em 2em 2em 2em;
-
- -moz-border-radius: 8px;
- -khtml-border-radius: 8px;
- -webkit-border-radius: 8px;
+ -moz-border-radius: 8px;
+ -webkit-border-radius: 8px;
}
/* form errors */
#adminErrors {
@@ -130,20 +146,20 @@ h3 {
font-size:90%;
}
-#generalInstall UL {
+#generalInstall ul {
list-style-type: decimal;
}
-LI.futureStep {
+li.futureStep {
color: #d3d3d3;
}
-LI.actualStep {
+li.actualStep {
font-weight: bold;
}
-LI.pastStep {
+li.pastStep {
color: #008000;
}
-P.nextStep A {
+p.nextStep a {
font-weight: bold;
padding: 0.5em;
color: #ae0000;
@@ -153,21 +169,6 @@ P.nextStep A {
line-height:1em;
}
-#installPercent {
- width: 100%;
- height: 1.5em;
- margin: 0;
- padding: 0;
- background-color: #eee;
- border: 1px solid #ddd;
-}
-#installPercent P {
- height: 1.5em;
- background-color: #8aaecc;
- margin: 0;
- padding: 0;
-}
-
td {
border-color:#FFFFFF rgb(198, 205, 216) rgb(198, 205, 216) rgb(198, 205, 216) ;
border-style:solid;
@@ -201,11 +202,15 @@ input {
{/literal}
</head>
<body>
+
<div id="main">
<div id="content">
<div id="logo">
<span id="title">Piwik</span> &nbsp;&nbsp;&nbsp;<span id="subtitle"># {'General_OpenSourceWebAnalytics'|translate}</span>
- <span style="float:right">{postEvent name="template_topBar"}</span>
+ </div>
+ <div style="float:right" id="topRightBar">
+ <br />
+ {postEvent name="template_topBar"}
</div>
<div class="both"></div>
@@ -224,13 +229,13 @@ input {
<div class="both"></div>
+ <br />
+ <br />
<h3>{'Installation_InstallationStatus'|translate}</h3>
- <div id="installPercent">
- <p style="width: {$percentDone}%;"></p>
+ <div id="progressbar"></div>
+ {'Installation_PercentDone'|translate:$percentDone}
</div>
-
- {'Installation_PercentDone'|translate:$percentDone}
</div>
</body>
</html>
diff --git a/plugins/Installation/templates/systemCheck.tpl b/plugins/Installation/templates/systemCheck.tpl
index 75b3c6843b..b0433c96a3 100644
--- a/plugins/Installation/templates/systemCheck.tpl
+++ b/plugins/Installation/templates/systemCheck.tpl
@@ -82,7 +82,7 @@
<small>
{foreach from=$infos.missing_extensions item=missing_extension}
<p>
- {$helpMessages[$missing_extension]|translate}
+ <i>{$helpMessages[$missing_extension]|translate}</i>
</p>
{/foreach}
</small>
@@ -90,6 +90,21 @@
</tr>
{/if}
<tr>
+ <td class="label">{'Installation_SystemCheckFunctions'|translate}</td>
+ <td>{foreach from=$infos.needed_functions item=needed_function}
+ {$needed_function}
+ {if in_array($needed_function, $infos.missing_functions)}
+ {$error}
+ <p>
+ <i>{$helpMessages[$needed_function]|translate}</i>
+ </p>
+ {else}
+ {$ok}<br />
+ {/if}
+ {/foreach}
+ </td>
+ </tr>
+ <tr>
<td valign="top">
{'Installation_SystemCheckWriteDirs'|translate}
</td>
@@ -121,6 +136,23 @@
<h1>{'Optional'|translate}</h1>
<table class="infos">
<tr>
+ <td class="label">{'Installation_SystemCheckFileIntegrity'|translate}</td>
+ <td>
+ {if empty($infos.integrityErrorMessages)}
+ {$ok}
+ {else}
+ {if $infos.integrity}
+ {$warning} <i>{$infos.integrityErrorMessages[0]}</i>
+ {else}
+ {$error} <i>{$infos.integrityErrorMessages[0]}</i>
+ {/if}
+ {if count($infos.integrityErrorMessages) > 1}
+ <button id="more-results" class="ui-button ui-state-default ui-corner-all">{'General_Details'|translate}</button>
+ {/if}
+ {/if}
+ </td>
+ </tr>
+ <tr>
<td class="label">{'Installation_SystemCheckMemoryLimit'|translate}</td>
<td>
{$infos.memoryCurrent}
@@ -129,6 +161,13 @@
</td>
</tr>
<tr>
+ <td class="label">{'SitesManager_Timezone'|translate}</td>
+ <td>
+ {if $infos.timezone}{$ok}{else}{$warning}
+ <br /><i>{'SitesManager_AdvancedTimezoneSupportNotFound'|translate}</i>{/if}
+ </td>
+ </tr>
+ <tr>
<td class="label">{'Installation_SystemCheckOpenURL'|translate}</td>
<td>
{if $infos.openurl}{$infos.openurl} {$ok}{else}{$warning} <br /><i>{'Installation_SystemCheckOpenURLHelp'|translate}</i>{/if}
@@ -148,16 +187,22 @@
{if $infos.gd_ok}{$ok}{else}{$warning} <br /><i>{'Installation_SystemCheckGDHelp'|translate}</i>{/if}
</td>
</tr>
+ {if $infos.hasMbstring}
+ <tr>
+ <td class="label">{'Installation_SystemCheckMbstring'|translate}</td>
+ <td>
+ {if $infos.multibyte_ok}{$ok}{else}{$warning} <br /><i>{'Installation_SystemCheckMbstringHelp'|translate}</i>{/if}
+ </td>
+ </tr>
+ {/if}
<tr>
<td class="label">{'Installation_SystemCheckFunctions'|translate}</td>
- <td>{foreach from=$infos.needed_functions item=needed_function}
- {$needed_function}
- {if in_array($needed_function, $infos.missing_functions)}
+ <td>{foreach from=$infos.desired_functions item=desired_function}
+ {$desired_function}
+ {if in_array($desired_function, $infos.missing_desired_functions)}
{$warning}
<p>
- <small>
- {$helpMessages[$needed_function]|translate}
- </small>
+ <i>{$helpMessages[$desired_function]|translate}</i>
</p>
{else}
{$ok}<br />
@@ -165,10 +210,24 @@
{/foreach}
</td>
</tr>
+ <tr>
+ <td class="label">{'Installation_SystemCheckProtocol'|translate}</td>
+ <td>
+ {if $infos.protocol_ok}{$ok}{else}{$warning} {$infos.protocol}<br /><i>{'Installation_SystemCheckProtocolHelp'|translate}</i><br /><br /><code>[General]</code><br /><code>reverse_proxy = 1</code><br />{/if}
+ </td>
+ </tr>
+ <tr>
+ <td class="label">{'Installation_SystemCheckIpv4'|translate}</td>
+ <td>
+ {if $infos.isIpv4}{$ok}{else}{$warning}<br /><i>{'Installation_SystemCheckIpv4Help'|translate}</i>{/if}
+ </td>
+ </tr>
</table>
+{include file="Installation/templates/integrityDetails.tpl"}
+
<p>
-{$link} <a href="http://piwik.org/docs/requirements/" target="_blank">{'Installation_Requirements'|translate}</a>
+{$link} <a href="misc/redirectToUrl.php?url=http://piwik.org/docs/requirements/" target="_blank">{'Installation_Requirements'|translate}</a>
</p>
{if !$showNextStep}
diff --git a/plugins/Installation/templates/tablesCreation.tpl b/plugins/Installation/templates/tablesCreation.tpl
index 8047bef92e..028799e9fd 100644
--- a/plugins/Installation/templates/tablesCreation.tpl
+++ b/plugins/Installation/templates/tablesCreation.tpl
@@ -1,14 +1,8 @@
<h1>{'Installation_Tables'|translate}</h1>
-{if isset($charsetWarning)}
- <div class="warning">{'Installation_ConnectionCharacterSetNotUtf8'|translate}
- <img src="themes/default/images/warning_medium.png">
- </div>
-{/if}
-
{if isset($someTablesInstalled)}
<div class="warning">{'Installation_TablesWithSameNamesFound'|translate:"<span id='linkToggle'>":"</span>"}
- <img src="themes/default/images/warning_medium.png">
+ <img src="themes/default/images/warning_medium.png" />
</div>
<div id="toggle" style="display:none;color:#4F2410"><small><i>{'Installation_TablesFound'|translate}:
<br />{$tablesInstalled} </i></small></div>
@@ -17,7 +11,7 @@
<p>{'Installation_TablesWarningHelp'|translate}</p>
<p class="nextStep"><a href="{url action=$nextModuleName}">{'Installation_TablesReuse'|translate} &raquo;</a></p>
{else}
- <p class="nextStep"><a href="{url action=$previousModuleName}">&laquo; {'Installation_GoBackAndDefinePrefix'|translate}</a></p>
+ <p class="nextStep"><a href="{url action=$previousPreviousModuleName}">&laquo; {'Installation_GoBackAndDefinePrefix'|translate}</a></p>
{/if}
<p class="nextStep"><a href="{url deleteTables=1}" id="eraseAllTables">{'Installation_TablesDelete'|translate} &raquo;</a></p>
@@ -25,24 +19,19 @@
{if isset($existingTablesDeleted)}
<div class="success"> {'Installation_TablesDeletedSuccess'|translate}
- <img src="themes/default/images/success_medium.png"></div>
-{/if}
-
-{if isset($databaseCreated)}
- <div class="success"> {'Installation_DatabaseCreatedSuccess'|translate:"'$databaseName'"}
- <img src="themes/default/images/success_medium.png"></div>
+ <img src="themes/default/images/success_medium.png" /></div>
{/if}
{if isset($tablesCreated)}
<div class="success"> {'Installation_TablesCreatedSuccess'|translate}
- <img src="themes/default/images/success_medium.png"></div>
+ <img src="themes/default/images/success_medium.png" /></div>
{/if}
{literal}
<script>
$(document).ready( function(){
{/literal}
- var strConfirmEraseTables = "{'Installation_ConfirmDeleteExistingTables'|translate:"[$tablesInstalled]":"<br>"} ";
+ var strConfirmEraseTables = "{'Installation_ConfirmDeleteExistingTables'|translate:"[$tablesInstalled]":"<br />"} ";
{literal}
// toggle the display of the tables detected during the installation when clicking
diff --git a/plugins/Installation/templates/welcome.tpl b/plugins/Installation/templates/welcome.tpl
index c2985c3c36..2de55967e2 100644
--- a/plugins/Installation/templates/welcome.tpl
+++ b/plugins/Installation/templates/welcome.tpl
@@ -1,4 +1,29 @@
<h1>{'Installation_Welcome'|translate}</h1>
+{if $newInstall}
{'Installation_WelcomeHelp'|translate:$totalNumberOfSteps}
+{else}
+<p>{'Installation_ConfigurationHelp'|translate}</p>
+<br />
+<div class="error">
+{$errorMessage}
+</div>
+{/if}
+{literal}
+<script type="text/javascript">
+<!--
+$(function() {
+if (document.location.protocol === 'https:') {
+ $('p.nextStep a').attr('href', $('p.nextStep a').attr('href') + '&clientProtocol=https');
+}
+});
+//-->
+</script>
+{/literal}
+
+{if !$showNextStep}
+<p class="nextStep">
+ <a href="{url}">{'General_Refresh'|translate} &raquo;</a>
+</p>
+{/if}
diff --git a/plugins/LanguagesManager/API.php b/plugins/LanguagesManager/API.php
index 16199235a8..0e128ceb68 100644
--- a/plugins/LanguagesManager/API.php
+++ b/plugins/LanguagesManager/API.php
@@ -27,8 +27,9 @@ class Piwik_LanguagesManager_API
}
return self::$instance;
}
- static protected $availableLanguageNames = null;
- static protected $languageNames = null;
+
+ protected $availableLanguageNames = null;
+ protected $languageNames = null;
/**
* Returns true if specified language is available
@@ -36,10 +37,10 @@ class Piwik_LanguagesManager_API
* @param string $languageCode
* @return bool true if language available; false otherwise
*/
- static public function isLanguageAvailable($languageCode)
+ public function isLanguageAvailable($languageCode)
{
return $languageCode !== false
- && in_array($languageCode, self::getAvailableLanguages());
+ && in_array($languageCode, $this->getAvailableLanguages());
}
/**
@@ -47,11 +48,11 @@ class Piwik_LanguagesManager_API
*
* @return array Arry of strings, each containing its ISO language code
*/
- static public function getAvailableLanguages()
+ public function getAvailableLanguages()
{
- if(!is_null(self::$languageNames))
+ if(!is_null($this->languageNames))
{
- return self::$languageNames;
+ return $this->languageNames;
}
$path = PIWIK_INCLUDE_PATH . "/lang/";
$languages = glob($path . "*.php");
@@ -61,7 +62,7 @@ class Piwik_LanguagesManager_API
{
$languageNames[] = substr($language, $pathLength, -strlen('.php'));
}
- self::$languageNames = $languageNames;
+ $this->languageNames = $languageNames;
return $languageNames;
}
@@ -70,11 +71,11 @@ class Piwik_LanguagesManager_API
*
* @return array Array of arrays
*/
- static public function getAvailableLanguagesInfo()
+ public function getAvailableLanguagesInfo()
{
require PIWIK_INCLUDE_PATH . '/lang/en.php';
$englishTranslation = $translations;
- $filenames = self::getAvailableLanguages();
+ $filenames = $this->getAvailableLanguages();
$languagesInfo = array();
foreach($filenames as $filename)
{
@@ -99,22 +100,22 @@ class Piwik_LanguagesManager_API
*
* @return array Arry of array, each containing its ISO language code and name of the language
*/
- static public function getAvailableLanguageNames()
+ public function getAvailableLanguageNames()
{
- if(!is_null(self::$availableLanguageNames))
+ if(!is_null($this->availableLanguageNames))
{
- return self::$availableLanguageNames;
+ return $this->availableLanguageNames;
}
- $filenames = self::getAvailableLanguages();
+ $filenames = $this->getAvailableLanguages();
$languagesInfo = array();
foreach($filenames as $filename)
{
require PIWIK_INCLUDE_PATH . "/lang/$filename.php";
$languagesInfo[] = array( 'code' => $filename, 'name' => $translations['General_OriginalLanguageName']);
}
- self::$availableLanguageNames = $languagesInfo;
- return self::$availableLanguageNames;
+ $this->availableLanguageNames = $languagesInfo;
+ return $this->availableLanguageNames;
}
/**
@@ -123,9 +124,9 @@ class Piwik_LanguagesManager_API
* @param string $languageCode ISO language code
* @return array|false Array of arrays, each containing 'label' (translation index) and 'value' (translated string); false if language unavailable
*/
- static public function getTranslationsForLanguage($languageCode)
+ public function getTranslationsForLanguage($languageCode)
{
- if(!self::isLanguageAvailable($languageCode))
+ if(!$this->isLanguageAvailable($languageCode))
{
return false;
}
@@ -144,10 +145,10 @@ class Piwik_LanguagesManager_API
* @param string $login
* @param string|false $layout
*/
- static public function getLanguageForUser( $login )
+ public function getLanguageForUser( $login )
{
Piwik::checkUserIsSuperUserOrTheUser($login);
- return Piwik_FetchOne('SELECT language FROM '.Piwik::prefixTable('user_language') .
+ return Piwik_FetchOne('SELECT language FROM '.Piwik_Common::prefixTable('user_language') .
' WHERE login = ? ', array($login ));
}
@@ -157,11 +158,11 @@ class Piwik_LanguagesManager_API
* @param string $login
* @param string $languageCode
*/
- static public function setLanguageForUser($login, $languageCode)
+ public function setLanguageForUser($login, $languageCode)
{
Piwik::checkUserIsSuperUserOrTheUser($login);
$paramsBind = array($login, $languageCode, $languageCode);
- Piwik_Query('INSERT INTO '.Piwik::prefixTable('user_language') .
+ Piwik_Query('INSERT INTO '.Piwik_Common::prefixTable('user_language') .
' (login, language)
VALUES (?,?)
ON DUPLICATE KEY UPDATE language=?',
@@ -173,7 +174,7 @@ class Piwik_LanguagesManager_API
*
* @return string|null
*/
- static public function getLanguageForSession()
+ public function getLanguageForSession()
{
$session = new Zend_Session_Namespace("Piwik_LanguagesManager");
if(isset($session->language))
@@ -188,7 +189,7 @@ class Piwik_LanguagesManager_API
*
* @param string $languageCode ISO language code
*/
- static public function setLanguageForSession($languageCode)
+ public function setLanguageForSession($languageCode)
{
$session = new Zend_Session_Namespace("Piwik_LanguagesManager");
$session->language = $languageCode;
diff --git a/plugins/LanguagesManager/Controller.php b/plugins/LanguagesManager/Controller.php
index c7546540f2..f0e678125f 100644
--- a/plugins/LanguagesManager/Controller.php
+++ b/plugins/LanguagesManager/Controller.php
@@ -23,12 +23,12 @@ class Piwik_LanguagesManager_Controller extends Piwik_Controller
public function saveLanguage()
{
$language = Piwik_Common::getRequestVar('language');
- Piwik_LanguagesManager_API::setLanguageForSession($language);
+ Piwik_LanguagesManager_API::getInstance()->setLanguageForSession($language);
if(Zend_Registry::isRegistered('access')) {
$currentUser = Piwik::getCurrentUserLogin();
if($currentUser && $currentUser !== 'anonymous')
{
- Piwik_LanguagesManager_API::setLanguageForUser($currentUser, $language);
+ Piwik_LanguagesManager_API::getInstance()->setLanguageForUser($currentUser, $language);
}
}
Piwik_Url::redirectToReferer();
diff --git a/plugins/LanguagesManager/LanguagesManager.php b/plugins/LanguagesManager/LanguagesManager.php
index 8db9f2e353..6ee5178910 100644
--- a/plugins/LanguagesManager/LanguagesManager.php
+++ b/plugins/LanguagesManager/LanguagesManager.php
@@ -20,11 +20,10 @@ class Piwik_LanguagesManager extends Piwik_Plugin
public function getInformation()
{
return array(
- 'name' => 'Languages Management',
- 'description' => 'This plugin will display a list of the available languages for the Piwik interface. The language selected will be saved in the preferences for each user.',
+ 'description' => Piwik_Translate('LanguagesManager_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
}
@@ -34,6 +33,7 @@ class Piwik_LanguagesManager extends Piwik_Plugin
'template_css_import' => 'css',
'template_topBar' => 'showLanguagesSelector',
'Translate.getLanguageToLoad' => 'getLanguageToLoad',
+ 'UsersManager.deleteUser' => 'deleteUserLanguage',
);
}
@@ -49,11 +49,12 @@ class Piwik_LanguagesManager extends Piwik_Plugin
*/
function showLanguagesSelector()
{
- $view = Piwik_View::factory("languages");
- $view->languages = Piwik_LanguagesManager_API::getAvailableLanguageNames();
+ // don't use Piwik_View::factory() here
+ $view = new Piwik_View("LanguagesManager/templates/languages.tpl");
+ $view->languages = Piwik_LanguagesManager_API::getInstance()->getAvailableLanguageNames();
$view->currentLanguageCode = self::getLanguageCodeForCurrentUser();
$view->currentLanguageName = self::getLanguageNameForCurrentUser();
- echo $view ->render();
+ echo $view->render();
}
function getLanguageToLoad($notification)
@@ -61,21 +62,27 @@ class Piwik_LanguagesManager extends Piwik_Plugin
$language =& $notification->getNotificationObject();
$language = self::getLanguageCodeForCurrentUser();
}
-
+
+ function deleteUserLanguage($notification)
+ {
+ $userLogin = $notification->getNotificationObject();
+ Piwik_Query('DELETE FROM ' . Piwik_Common::prefixTable('user_language') . ' WHERE login = ?', $userLogin);
+ }
+
/**
- * @throws Zend_Db_Statement_Exception if non-recoverable error
+ * @throws Exception if non-recoverable error
*/
public function install()
{
// we catch the exception
try{
- $sql = "CREATE TABLE ". Piwik::prefixTable('user_language')." (
+ $sql = "CREATE TABLE ". Piwik_Common::prefixTable('user_language')." (
login VARCHAR( 100 ) NOT NULL ,
language VARCHAR( 10 ) NOT NULL ,
PRIMARY KEY ( login )
) DEFAULT CHARSET=utf8 " ;
Piwik_Exec($sql);
- } catch(Zend_Db_Statement_Exception $e){
+ } catch(Exception $e){
// mysql code error 1050:table already exists
// see bug #153 http://dev.piwik.org/trac/ticket/153
if(!Zend_Registry::get('db')->isErrNo($e, '1050'))
@@ -86,26 +93,25 @@ class Piwik_LanguagesManager extends Piwik_Plugin
}
/**
- * @throws Zend_Db_Statement_Exception if non-recoverable error
+ * @throws Exception if non-recoverable error
*/
public function uninstall()
{
- $sql = "DROP TABLE ". Piwik::prefixTable('user_language') ;
+ $sql = "DROP TABLE ". Piwik_Common::prefixTable('user_language') ;
Piwik_Exec($sql);
}
-
-
+
/**
* @return string Two letters language code, eg. "fr"
*/
static public function getLanguageCodeForCurrentUser()
{
$languageCode = self::getLanguageFromPreferences();
- if(!Piwik_LanguagesManager_API::isLanguageAvailable($languageCode))
+ if(!Piwik_LanguagesManager_API::getInstance()->isLanguageAvailable($languageCode))
{
- $languageCode = Piwik_Common::extractLanguageCodeFromBrowserLanguage(Piwik_Common::getBrowserLanguage(), Piwik_LanguagesManager_API::getAvailableLanguages());
+ $languageCode = Piwik_Common::extractLanguageCodeFromBrowserLanguage(Piwik_Common::getBrowserLanguage(), Piwik_LanguagesManager_API::getInstance()->getAvailableLanguages());
}
- if(!Piwik_LanguagesManager_API::isLanguageAvailable($languageCode))
+ if(!Piwik_LanguagesManager_API::getInstance()->isLanguageAvailable($languageCode))
{
$languageCode = 'en';
}
@@ -118,7 +124,7 @@ class Piwik_LanguagesManager extends Piwik_Plugin
static public function getLanguageNameForCurrentUser()
{
$languageCode = self::getLanguageCodeForCurrentUser();
- $languages = Piwik_LanguagesManager_API::getAvailableLanguageNames();
+ $languages = Piwik_LanguagesManager_API::getInstance()->getAvailableLanguageNames();
foreach($languages as $language)
{
if($language['code'] === $languageCode)
@@ -133,14 +139,14 @@ class Piwik_LanguagesManager extends Piwik_Plugin
*/
static protected function getLanguageFromPreferences()
{
- if ($language = Piwik_LanguagesManager_API::getLanguageForSession())
+ if ($language = Piwik_LanguagesManager_API::getInstance()->getLanguageForSession())
{
return $language;
}
try {
$currentUser = Piwik::getCurrentUserLogin();
- return Piwik_LanguagesManager_API::getLanguageForUser($currentUser);
+ return Piwik_LanguagesManager_API::getInstance()->getLanguageForUser($currentUser);
} catch(Exception $e) {
return false;
}
diff --git a/plugins/LanguagesManager/templates/languages.tpl b/plugins/LanguagesManager/templates/languages.tpl
index a7ebf9ff03..444caf7218 100644
--- a/plugins/LanguagesManager/templates/languages.tpl
+++ b/plugins/LanguagesManager/templates/languages.tpl
@@ -3,15 +3,16 @@
<form action="index.php?{if $currentModule != ''}module=LanguagesManager&{/if}action=saveLanguage" method="get">
<select name="language">
<option value="{$currentLanguageCode}">{$currentLanguageName}</option>
+ <option href='misc/redirectToUrl.php?url=http://piwik.org/translations/'>{'LanguagesManager_AboutPiwikTranslations'|translate}</option>
{foreach from=$languages item=language}
<option value="{$language.code}">{$language.name}</option>
{/foreach}
</select>
- <input type="submit" value="go"/>
+ <input type="submit" value="go" />
</form>
</span>
- {literal}<script language="javascript">
+ {literal}<script type="text/javascript">
$(document).ready(function() {
$("#languageSelection").fdd2div({CssClassName:"formDiv"});
$("#languageSelection").show();
diff --git a/plugins/LanguagesManager/tests/LanguagesManager.test.php b/plugins/LanguagesManager/tests/LanguagesManager.test.php
index bdd44e3c90..b7a0c84711 100644
--- a/plugins/LanguagesManager/tests/LanguagesManager.test.php
+++ b/plugins/LanguagesManager/tests/LanguagesManager.test.php
@@ -19,23 +19,62 @@ class Test_Languages_Manager extends UnitTestCase
// test all languages
function test_getTranslationsForLanguages()
{
+ $englishStrings = Piwik_LanguagesManager_API::getInstance()->getTranslationsForLanguage('en');
+ $englishStringsWithParameters = array();
+ foreach($englishStrings as $englishString)
+ {
+ $stringLabel = $englishString['label'];
+ $stringValue = $englishString['value'];
+ $count = $this->getCountParametersToReplace($stringValue);
+ if($count > 0)
+ {
+ $englishStringsWithParameters[$stringLabel] = $count;
+ }
+ }
+
// we also test that none of the language php files outputs any character on the screen (eg. space before the <?php)
- $languages = Piwik_LanguagesManager_API::getAvailableLanguages();
+ $languages = Piwik_LanguagesManager_API::getInstance()->getAvailableLanguages();
foreach($languages as $language)
{
ob_start();
- $strings = Piwik_LanguagesManager_API::getTranslationsForLanguage($language);
+ $strings = Piwik_LanguagesManager_API::getInstance()->getTranslationsForLanguage($language);
$content = ob_get_flush();
$this->assertTrue(strpos(serialize($strings), "<script") === false, " language file containing javascript");
$this->assertTrue(count($strings) > 100); // at least 100 translations in the language file
$this->assertTrue(strlen($content) == 0, "buffer was ".strlen($content)." long but should be zero. Translation file for '$language' must be buggy.");
+
+ // checking that translated strings have the same number of %s as the english source strings
+ foreach($strings as $string)
+ {
+ $stringLabel = $string['label'];
+ $stringValue = $string['value'];
+
+ if(!empty($stringValue)
+ && isset($englishStringsWithParameters[$stringLabel]))
+ {
+ $englishParametersCount = $englishStringsWithParameters[$stringLabel];
+ $countTranslation = $this->getCountParametersToReplace($stringValue);
+ //$this->assertEqual($countTranslation, $englishParametersCount,
+ // "The string $stringLabel has $englishParametersCount parameters in English, but $countTranslation in the language $language.");
+ }
+ }
}
$this->pass();
}
+ private function getCountParametersToReplace($string)
+ {
+ $sprintfParameters = array('%s', '%1$s', '%2$s', '%3$s', '%4$s', '%5$s', '%6$s');
+ $count = 0;
+ foreach($sprintfParameters as $parameter)
+ {
+ $count += substr_count($string, $parameter);
+ }
+ return $count;
+ }
//test language when it's not defined
function test_getTranslationsForLanguages_not()
{
- $this->assertFalse(Piwik_LanguagesManager_API::getTranslationsForLanguage("../no-language"));
+ $this->assertFalse(Piwik_LanguagesManager_API::getInstance()->getTranslationsForLanguage("../no-language"));
}
}
diff --git a/plugins/Live/API.php b/plugins/Live/API.php
index 8f688ff23b..b6439a143f 100644
--- a/plugins/Live/API.php
+++ b/plugins/Live/API.php
@@ -11,136 +11,277 @@
*/
/**
- *
+ * @see plugins/Referers/functions.php
+ */
+require_once PIWIK_INCLUDE_PATH . '/plugins/Live/Visitor.php';
+
+/**
* @package Piwik_Live
*/
-class Piwik_Live_API
+class Piwik_Live_API
{
static private $instance = null;
-
/*
* @return Piwik_Live_API
*/
static public function getInstance()
{
if (self::$instance == null)
- {
+ {
$c = __CLASS__;
self::$instance = new $c();
}
return self::$instance;
}
+
+ const TYPE_FETCH_VISITS = 1;
+ const TYPE_FETCH_PAGEVIEWS = 2;
/*
* @return Piwik_DataTable
*/
- public function getLastVisitForVisitor( $visitorId, $idSite = null )
+ public function getLastVisitForVisitor( $visitorId, $idSite )
{
- return $this->getLastVisitsForVisitor($visitorId, $idSite, 1);
+ return $this->getLastVisitsForVisitor($visitorId, $idSite, $limit = 1);
}
-
+
/*
* @return Piwik_DataTable
*/
public function getLastVisitsForVisitor( $visitorId, $idSite, $limit = 10 )
{
- if(is_null($idSite))
- {
- Piwik::checkUserIsSuperUser();
- }
- else
- {
- Piwik::checkUserHasViewAccess($idSite);
- }
- $visitorDetails = self::loadLastVisitorDetailsFromDatabase($visitorId, $idSite, $limit);
- $table = self::getCleanedVisitorsFromDetails($visitorDetails);
+ Piwik::checkUserHasViewAccess($idSite);
+ $visitorDetails = $this->loadLastVisitorDetailsFromDatabase($idSite, $visitorId, $limit);
+ $table = $this->getCleanedVisitorsFromDetails($visitorDetails, $idSite);
return $table;
}
/*
* @return Piwik_DataTable
*/
- public function getLastVisits( $idSite = false, $limit = 10, $minIdVisit = false )
+ public function getLastVisits( $idSite, $limit = 10, $minIdVisit = false )
{
- if(is_null($idSite))
- {
- Piwik::checkUserIsSuperUser();
- }
- else
- {
- Piwik::checkUserHasViewAccess($idSite);
- }
- $visitorDetails = self::loadLastVisitorDetailsFromDatabase(null, $idSite, $limit, $minIdVisit);
- $table = self::getCleanedVisitorsFromDetails($visitorDetails);
+ Piwik::checkUserHasViewAccess($idSite);
+ $visitorDetails = $this->loadLastVisitorDetailsFromDatabase($idSite, $visitorId = null, $limit, $minIdVisit);
+ $table = $this->getCleanedVisitorsFromDetails($visitorDetails, $idSite);
return $table;
}
+
+ /*
+ * @return Piwik_DataTable
+ */
+ public function getLastVisitsDetails( $idSite, $limit = 1000, $minIdVisit = false )
+ {
+ Piwik::checkUserHasViewAccess($idSite);
+ $visitorDetails = $this->loadLastVisitorDetailsFromDatabase($idSite, $visitorId = null, $limit, $minIdVisit);
+ $dataTable = $this->getCleanedVisitorsFromDetails($visitorDetails, $idSite);
+ return $dataTable;
+ }
+
+
+ /*
+ * @return Piwik_DataTable
+ */
+ public function getUsersInLastXMin( $idSite, $minutes = 30 )
+ {
+ Piwik::checkUserHasViewAccess($idSite);
+ $visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes, $days = 0, self::TYPE_FETCH_VISITS);
+ return $visitorData;
+ }
+
+ /*
+ * @return Piwik_DataTable
+ */
+ public function getUsersInLastXDays( $idSite, $days = 10 )
+ {
+ Piwik::checkUserHasViewAccess($idSite);
+ $visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes = 0, $days, self::TYPE_FETCH_VISITS);
+ return $visitorData;
+ }
+
+ /*
+ * @return array
+ */
+ public function getPageImpressionsInLastXDays($idSite, $days = 10)
+ {
+ Piwik::checkUserHasViewAccess($idSite);
+ $visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes = 0, $days, self::TYPE_FETCH_PAGEVIEWS);
+ return $visitorData;
+ }
+
+ /*
+ * @return array
+ */
+ public function getPageImpressionsInLastXMin($idSite, $minutes = 30)
+ {
+ Piwik::checkUserHasViewAccess($idSite);
+ $visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes, $days = 0, self::TYPE_FETCH_PAGEVIEWS);
+ return $visitorData;
+ }
/*
* @return Piwik_DataTable
*/
- static private function getCleanedVisitorsFromDetails($visitorDetails)
+ private function getCleanedVisitorsFromDetails($visitorDetails, $idSite)
{
$table = new Piwik_DataTable();
+
foreach($visitorDetails as $visitorDetail)
{
- self::cleanVisitorDetails($visitorDetail);
+ $this->cleanVisitorDetails($visitorDetail);
$visitor = new Piwik_Live_Visitor($visitorDetail);
$visitorDetailsArray = $visitor->getAllVisitorDetails();
- $dateTimeVisit = Piwik_Date::factory($visitorDetailsArray['firstActionTimestamp']);
- //TODO TO FIX
+
+ $site = new Piwik_Site($idSite);
+ $timezone = $site->getTimezone();
+ $dateTimeVisit = Piwik_Date::factory($visitorDetailsArray['firstActionTimestamp'], $timezone);
$visitorDetailsArray['serverDatePretty'] = $dateTimeVisit->getLocalized('%shortDay% %day% %shortMonth%');
$visitorDetailsArray['serverTimePretty'] = $dateTimeVisit->getLocalized('%time%');
+
+ // get Detail - 100 single SQL Statements - Performance Issue
+ $idvisit = $visitorDetailsArray['idVisit'];
+
+ $sql = "
+ SELECT DISTINCT " .Piwik_Common::prefixTable('log_action').".name AS pageUrl
+ FROM " .Piwik_Common::prefixTable('log_link_visit_action')."
+ INNER JOIN " .Piwik_Common::prefixTable('log_action')."
+ ON " .Piwik_Common::prefixTable('log_link_visit_action').".idaction_url = " .Piwik_Common::prefixTable('log_action').".idaction
+ WHERE " .Piwik_Common::prefixTable('log_link_visit_action').".idvisit = $idvisit;
+ ";
+
+ $visitorDetailsArray['actionDetails'] = Piwik_FetchAll($sql);
+
+ $sql = "
+ SELECT DISTINCT " .Piwik_Common::prefixTable('log_action').".name AS pageUrl
+ FROM " .Piwik_Common::prefixTable('log_link_visit_action')."
+ INNER JOIN " .Piwik_Common::prefixTable('log_action')."
+ ON " .Piwik_Common::prefixTable('log_link_visit_action').".idaction_name = " .Piwik_Common::prefixTable('log_action').".idaction
+ WHERE " .Piwik_Common::prefixTable('log_link_visit_action').".idvisit = $idvisit;
+ ";
+
+ $visitorDetailsArray['actionDetailsTitle'] = Piwik_FetchAll($sql);
$table->addRowFromArray( array(Piwik_DataTable_Row::COLUMNS => $visitorDetailsArray));
}
+
return $table;
}
-
+
/*
* @return array
*/
- private function loadLastVisitorDetailsFromDatabase($visitorId = null, $idSite = null, $limit = null, $minIdVisit = false )
+ private function loadLastVisitorDetailsFromDatabase($idSite, $visitorId = null, $limit = null, $minIdVisit = false )
{
$where = $whereBind = array();
-
- if(!is_null($idSite))
- {
- $where[] = " idsite = ? ";
- $whereBind[] = $idSite;
- }
-
- if(!is_null($visitorId))
+
+ $where[] = Piwik_Common::prefixTable('log_visit') . ".idsite = ? ";
+ $whereBind[] = $idSite;
+
+ if(!empty($visitorId))
{
- $where[] = " visitor_idcookie = ? ";
+ $where[] = Piwik_Common::prefixTable('log_visit') . ".visitor_idcookie = ? ";
$whereBind[] = $visitorId;
}
-
- if(!is_null($minIdVisit))
+
+ if(!empty($minIdVisit))
{
- $where[] = " idvisit > ? ";
+ $where[] = Piwik_Common::prefixTable('log_visit') . ".idvisit > ? ";
$whereBind[] = $minIdVisit;
}
-
+
$sqlWhere = "";
if(count($where) > 0)
{
$sqlWhere = " WHERE " . join(' AND ', $where);
}
-
- $sql = "SELECT *
- FROM " . Piwik::prefixTable('log_visit') . "
- $sqlWhere
- ORDER BY idvisit DESC
+
+ $sql = "SELECT " . Piwik_Common::prefixTable('log_visit') . ".* ,
+ " . Piwik_Common::prefixTable ( 'goal' ) . ".match_attribute
+ FROM " . Piwik_Common::prefixTable('log_visit') . "
+ LEFT JOIN ".Piwik_Common::prefixTable('log_conversion')."
+ ON " . Piwik_Common::prefixTable('log_visit') . ".idvisit = " . Piwik_Common::prefixTable('log_conversion') . ".idvisit
+ LEFT JOIN ".Piwik_Common::prefixTable('goal')."
+ ON (" . Piwik_Common::prefixTable('goal') . ".idsite = " . Piwik_Common::prefixTable('log_visit') . ".idsite
+ AND " . Piwik_Common::prefixTable('goal') . ".idgoal = " . Piwik_Common::prefixTable('log_conversion') . ".idgoal)
+ AND " . Piwik_Common::prefixTable('goal') . ".deleted = 0
+ $sqlWhere
+ ORDER BY idsite,idvisit DESC
LIMIT $limit";
-
+
return Piwik_FetchAll($sql, $whereBind);
}
- /*
+ /**
+ * Load last Visitors PAGES or DETAILS in MINUTES or DAYS from database
*
+ * @param int $idSite
+ * @param int $minutes
+ * @param int $days
+ * @param int $type self::TYPE_FETCH_VISITS or self::TYPE_FETCH_PAGEVIEWS
+ *
+ * @return mixed
+ */
+ private function loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes = 0, $days = 0, $type = false )
+ {
+ $where = $whereBind = array();
+
+ $where[] = " " . Piwik_Common::prefixTable('log_visit') . ".idsite = ? ";
+ $whereBind[] = $idSite;
+
+ if($minutes != 0)
+ {
+ $timeLimit = mktime(date("H"), date("i") - $minutes, 0, date("m"), date("d"), date("Y"));
+ $where[] = " visit_last_action_time > '".date('Y-m-d H:i:s',$timeLimit)."'";
+ }
+
+ if($days != 0)
+ {
+ $timeLimit = mktime(0, 0, 0, date("m"), date("d") - $days + 1, date("Y"));
+ $where[] = " visit_last_action_time > '".date('Y-m-d H:i:s', $timeLimit)."'";
+ }
+
+ $sqlWhere = "";
+ if(count($where) > 0)
+ {
+ $sqlWhere = " WHERE " . join(' AND ', $where);
+ }
+
+ // Details
+ if($type == self::TYPE_FETCH_VISITS)
+ {
+ $sql = "SELECT " . Piwik_Common::prefixTable('log_visit') . ".idvisit
+ FROM " . Piwik_Common::prefixTable('log_visit') . "
+ $sqlWhere
+ ORDER BY idsite,idvisit DESC";
+ }
+ // Pages
+ elseif($type == self::TYPE_FETCH_PAGEVIEWS)
+ {
+ $sql = "SELECT " . Piwik_Common::prefixTable('log_link_visit_action') . ".idaction_url
+ FROM " . Piwik_Common::prefixTable('log_link_visit_action') . "
+ INNER JOIN " . Piwik_Common::prefixTable('log_visit') . "
+ ON " . Piwik_Common::prefixTable('log_visit') . ".idvisit = " . Piwik_Common::prefixTable('log_link_visit_action') . ".idvisit
+ $sqlWhere";
+ }
+ else
+ {
+ // no $type is set --> ERROR
+ throw new Exception("type parameter is not properly set.");
+ }
+
+ // return $sql by fetching
+ return Piwik_FetchAll($sql, $whereBind);
+ }
+
+
+ /**
+ * Removes fields that are not meant to be displayed (md5 config hash)
+ * Or that the user should only access if he is super user (cookie, IP)
+ *
+ * @return void
*/
- static private function cleanVisitorDetails( &$visitorDetails )
+ private function cleanVisitorDetails( &$visitorDetails )
{
- $toUnset = array('config_md5config');
+ $toUnset = array('config_md5config');
if(!Piwik::isUserIsSuperUser())
{
$toUnset[] = 'visitor_idcookie';
@@ -154,4 +295,5 @@ class Piwik_Live_API
}
}
}
+
}
diff --git a/plugins/Live/Controller.php b/plugins/Live/Controller.php
index 5c60d5a6e3..c35be89d06 100644
--- a/plugins/Live/Controller.php
+++ b/plugins/Live/Controller.php
@@ -1,57 +1,184 @@
<?php
/**
* Piwik - Open source web analytics
- *
+ *
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
- *
+ *
* @category Piwik_Plugins
* @package Piwik_Live
*/
/**
- *
* @package Piwik_Live
*/
class Piwik_Live_Controller extends Piwik_Controller
{
- function widget()
+ function __construct()
+ {
+ parent::__construct();
+ $this->idSite = Piwik_Common::getRequestVar('idSite');
+ $this->minIdVisit = Piwik_Common::getRequestVar('minIdVisit', 0, 'int');
+ }
+
+ function index()
{
- $view = Piwik_View::factory('index');
- $this->setGeneralVariablesView($view);
- $view->visitors = $this->getLastVisits($fetch = true);
+ $this->widget(true);
+ }
+
+ public function widget($fetch = false)
+ {
+ $view = Piwik_View::factory('index');
+ $view->idSite = Piwik_Common::getRequestVar('idSite');
+ $view->visitorsCountHalfHour = $this->getUsersInLastXMin(30);
+ $view->visitorsCountToday = $this->getUsersInLastXDays(1);
+ $view->pisHalfhour = $this->getPageImpressionsInLastXMin(30);
+ $view->pisToday = $this->getPageImpressionsInLastXDays(1);
+ $view->visitors = $this->getLastVisitsStart($fetch = true);
+
echo $view->render();
}
-
- function getLastVisits($fetch = false)
+
+ public function getLastVisitsDetails($fetch = false)
+ {
+ $view = Piwik_ViewDataTable::factory('');
+ $view->init( $this->pluginName,
+ __FUNCTION__,
+ 'Live.getLastVisitsDetails',
+ 'getPagesFromVisitId');
+// All colomns in DB which could be shown
+//'ip', 'idVisit', 'countActions', 'isVisitorReturning', 'country', 'countryFlag', 'continent', 'provider', 'providerUrl', 'idSite',
+//'serverDate', 'visitLength', 'visitLengthPretty', 'firstActionTimestamp', 'lastActionTimestamp', 'refererType', 'refererName',
+//'keywords', 'refererUrl', 'searchEngineUrl', 'searchEngineIcon', 'operatingSystem', 'operatingSystemShortName', 'operatingSystemIcon',
+//'browserFamily', 'browserFamilyDescription', 'browser', 'browserIcon', 'screen', 'resolution', 'screenIcon', 'plugins', 'lastActionDateTime',
+//'serverDatePretty', 'serverTimePretty', 'actionDetails'
+
+ $view->setColumnsToDisplay(array(
+ 'idVisit',
+ 'serverDatePretty',
+ 'serverTimePretty',
+ 'ip',
+ 'countActions',
+ 'visitLengthPretty',
+ 'keywords',
+ 'refererUrl',
+ 'operatingSystemShortName',
+ 'browser',
+ 'screen',
+ 'resolution',
+ 'plugins',
+ ));
+
+ $view->setColumnsTranslations(array(
+ 'idVisit' => Piwik_Translate(''),
+ 'serverDatePretty' => Piwik_Translate('Live_Date'),
+ 'serverTimePretty' => Piwik_Translate('Live_Time'),
+ 'ip' => 'IP',
+ 'countActions' => Piwik_Translate('VisitorInterest_ColumnPagesPerVisit'),
+ 'visitLengthPretty' => Piwik_Translate('VisitorInterest_ColumnVisitDuration'),
+ 'keywords' => Piwik_Translate('Referers_ColumnKeyword'),
+ 'refererUrl' => Piwik_Translate('Live_Referrer_URL'),
+ 'operatingSystemShortName' => Piwik_Translate('UserSettings_ColumnOperatingSystem'),
+ 'browser' => Piwik_Translate('UserSettings_ColumnBrowser'),
+ 'screen' => Piwik_Translate('UserSettings_ColumnTypeOfScreen'),
+ 'resolution' => Piwik_Translate('UserSettings_ColumnResolution'),
+ 'plugins' => Piwik_Translate('UserSettings_ColumnPlugin'),
+ ));
+
+ $view->disableSort();
+ $view->setLimit(10);
+ $view->disableExcludeLowPopulation();
+ $view->setSortedColumn('idVisit', 'ASC');
+ $view->disableSearchBox();
+ // "Include low population" link won't be displayed under this table
+ $view->disableExcludeLowPopulation();
+ // disable the tag cloud, pie charts, bar chart icons
+ $view->disableShowAllViewsIcons();
+ // disable the button "show more datas"
+ $view->disableShowAllColumns();
+
+ return $this->renderView($view, $fetch);
+ }
+
+ function getPagesFromVisitId( $fetch = false)
+ {
+ $view = Piwik_ViewDataTable::factory('');
+ $view->init( $this->pluginName,
+ __FUNCTION__,
+ 'Live.getLastVisitsForVisitor',
+ 'getPagesFromVisitId');
+
+ return $this->renderView($view, $fetch);
+ }
+
+ public function getLastVisitsStart($fetch = false)
{
- $idSite = Piwik_Common::getRequestVar('idSite', null, 'int');
- $minIdVisit = Piwik_Common::getRequestVar('minIdVisit', 0, 'int');
- $limit = 10;
- $api = new Piwik_API_Request("method=Live.getLastVisits&idSite=$idSite&limit=$limit&minIdVisit=$minIdVisit&format=php&serialize=0&disable_generic_filters=1");
-
$view = Piwik_View::factory('lastVisits');
- $visitors = $api->process();
- if($minIdVisit == 0)
- {
- $visitors = array_slice($visitors, 3);
- }
- $view->visitors = $visitors;
- $rendered = $view->render($fetch);
+ $view->idSite = Piwik_Common::getRequestVar('idSite');
+ $view->visitors = $this->getLastVisits(10);
+
+ $rendered = $view->render($fetch);
+
if($fetch)
{
return $rendered;
}
echo $rendered;
}
-
- function index()
+
+ public function getLastVisits($limit = 10)
{
- $view = Piwik_View::factory('structure');
- $this->setGeneralVariablesView($view);
- $view->visitors = $this->getLastVisits($fetch = true);
- echo $view->render();
+ $api = new Piwik_API_Request("method=Live.getLastVisits&idSite=$this->idSite&limit=$limit&format=php&serialize=0&disable_generic_filters=1");
+ $visitors = $api->process();
+
+ return $visitors;
+ }
+
+ public function getUsersInLastXMin($minutes = 30) {
+ $api = new Piwik_API_Request("method=Live.getUsersInLastXMin&idSite=".$this->idSite."&minutes=".$minutes."&format=php&serialize=0&disable_generic_filters=1");
+ $visitors_halfhour = $api->process();
+
+ return count($visitors_halfhour);
+ }
+
+ public function getUsersInLastXDays($days = 1) {
+ $api = new Piwik_API_Request("method=Live.getUsersInLastXDays&idSite=$this->idSite&days=$days&format=php&serialize=0&disable_generic_filters=1");
+ $visitors_today = $api->process();
+
+ return count($visitors_today);
+ }
+
+ public function getPageImpressionsInLastXMin($minutes = 30) {
+ $api = new Piwik_API_Request("method=Live.getPageImpressionsInLastXMin&idSite=$this->idSite&minutes=$minutes&format=php&serialize=0&disable_generic_filters=1");
+ $pis_halfhour = $api->process();
+
+ return count($pis_halfhour);
+ }
+
+ public function getPageImpressionsInLastXDays($days = 1) {
+ $api = new Piwik_API_Request("method=Live.getPageImpressionsInLastXDays&idSite=$this->idSite&days=$days&format=php&serialize=0&disable_generic_filters=1");
+ $pis_today = $api->process();
+
+ return count($pis_today);
+ }
+
+ public function ajaxTotalVisitors($fetch = false)
+ {
+ $view = Piwik_View::factory('totalVisits');
+ $view->idSite = Piwik_Common::getRequestVar('idSite');
+ $view->visitorsCountHalfHour = $this->getUsersInLastXMin(30);
+ $view->visitorsCountToday = $this->getUsersInLastXDays(1);
+ $view->pisHalfhour = $this->getPageImpressionsInLastXMin(30);
+ $view->pisToday = $this->getPageImpressionsInLastXDays(1);
+
+ $rendered = $view->render($fetch);
+
+ if($fetch)
+ {
+ return $rendered;
+ }
+ echo $rendered;
}
}
diff --git a/plugins/Live/Live.php b/plugins/Live/Live.php
index f659a8ae0e..4fbec02c54 100644
--- a/plugins/Live/Live.php
+++ b/plugins/Live/Live.php
@@ -1,30 +1,16 @@
<?php
/**
* Piwik - Open source web analytics
- *
+ *
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
- *
+ *
* @category Piwik_Plugins
* @package Piwik_Live
*/
/**
- TODO Live! Plugin
- ====
- - api propre
- - html
- - jquery spy
- - make sure only one query is launched at once or what if requests takes more than 10s to succeed?
- - simple stats above in TEXT
- - Security review
- - blog post, push version
-
-//TODO add api to get actions name/count/first/last/etc
- */
-
-/**
*
* @package Piwik_Live
*/
@@ -33,13 +19,34 @@ class Piwik_Live extends Piwik_Plugin
public function getInformation()
{
return array(
- 'name' => 'Live Visitors',
- 'description' => 'Live Visitors!',
+ 'description' => Piwik_Translate('Live_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
}
-}
-Piwik_AddWidget('Live!', 'Live Visitors!', 'Live', 'widget');
+ function getListHooksRegistered()
+ {
+ return array(
+ 'template_css_import' => 'css',
+ 'WidgetsList.add' => 'addWidget',
+ 'Menu.add' => 'addMenu',
+ );
+ }
+
+ function css()
+ {
+ echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"themes/default/styles.css\" />\n";
+ }
+
+ function addMenu()
+ {
+ Piwik_AddMenu('General_Visitors', 'Live_VisitorLog', array('module' => 'Live', 'action' => 'getLastVisitsDetails'));
+ }
+
+ public function addWidget() {
+ Piwik_AddWidget('Live!', 'Live Visitors!', 'Live', 'widget');
+ }
+
+}
diff --git a/plugins/Live/Visitor.php b/plugins/Live/Visitor.php
index 8887566009..1ac82ebddc 100644
--- a/plugins/Live/Visitor.php
+++ b/plugins/Live/Visitor.php
@@ -1,24 +1,22 @@
<?php
/**
* Piwik - Open source web analytics
- *
+ *
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
- *
+ *
* @category Piwik_Plugins
* @package Piwik_Live
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see plugins/Referers/functions.php
* @see plugins/UserCountry/functions.php
* @see plugins/UserSettings/functions.php
* @see plugins/Provider/functions.php
*/
+
require_once PIWIK_INCLUDE_PATH . '/plugins/Referers/functions.php';
require_once PIWIK_INCLUDE_PATH . '/plugins/UserCountry/functions.php';
require_once PIWIK_INCLUDE_PATH . '/plugins/UserSettings/functions.php';
@@ -34,7 +32,7 @@ class Piwik_Live_Visitor
{
$this->details = $visitorRawData;
}
-
+
function getAllVisitorDetails()
{
return array(
@@ -53,7 +51,7 @@ class Piwik_Live_Visitor
'visitLengthPretty' => $this->getVisitLengthPretty(),
'firstActionTimestamp' => $this->getTimestampFirstAction(),
'lastActionTimestamp' => $this->getTimestampLastAction(),
-
+
'refererType' => $this->getRefererType(),
'refererName' => $this->getRefererTypeName(),
'keywords' => $this->getKeywords(),
@@ -61,7 +59,7 @@ class Piwik_Live_Visitor
'refererName' => $this->getRefererName(),
'searchEngineUrl' => $this->getSearchEngineUrl(),
'searchEngineIcon' => $this->getSearchEngineIcon(),
-
+
'operatingSystem' => $this->getOperatingSystem(),
'operatingSystemShortName' => $this->getOperatingSystemShortName(),
'operatingSystemIcon' => $this->getOperatingSystemIcon(),
@@ -73,14 +71,18 @@ class Piwik_Live_Visitor
'resolution' => $this->getResolution(),
'screenIcon' => $this->getScreenTypeIcon(),
'plugins' => $this->getPlugins(),
+ 'lastActionDateTime' => $this->getDateTimeLastAction(),
+ 'isVisitorGoalConverted' => $this->isVisitorGoalConverted(),
+ 'goalIcon' => $this->getGoalIcon(),
+ 'goalType' => $this->getGoalType(),
);
}
-
+
function getServerDate()
{
- return $this->details['visit_server_date'];
+ return date('Y-m-d', strtotime($this->details['visit_last_action_time']));
}
-
+
function getIp()
{
if(isset($this->details['location_ip']))
@@ -89,17 +91,17 @@ class Piwik_Live_Visitor
}
return false;
}
-
+
function getIdVisit()
{
return $this->details['idvisit'];
}
-
+
function getIdSite()
{
return $this->details['idsite'];
}
-
+
function getNumberOfActions()
{
return $this->details['visit_total_actions'];
@@ -109,42 +111,42 @@ class Piwik_Live_Visitor
{
return $this->details['visit_total_time'];
}
-
+
function getVisitLengthPretty()
{
return Piwik::getPrettyTimeFromSeconds($this->details['visit_total_time']);
}
-
+
function isVisitorReturning()
{
return $this->details['visitor_returning'];
}
-
+
function getTimestampFirstAction()
{
return strtotime($this->details['visit_first_action_time']);
}
-
+
function getTimestampLastAction()
{
return strtotime($this->details['visit_last_action_time']);
}
-
+
function getCountryName()
{
return Piwik_CountryTranslate($this->details['location_country']);
}
-
+
function getCountryFlag()
{
return Piwik_getFlagFromCode($this->details['location_country']);
}
-
+
function getContinent()
{
return Piwik_ContinentTranslate($this->details['location_continent']);
}
-
+
function getRefererType()
{
$map = array(
@@ -159,27 +161,27 @@ class Piwik_Live_Visitor
}
return $map[Piwik_Common::REFERER_TYPE_DIRECT_ENTRY];
}
-
+
function getRefererTypeName()
{
return Piwik_getRefererTypeLabel($this->details['referer_type']);
}
-
+
function getKeywords()
{
return $this->details['referer_keyword'];
}
-
+
function getRefererUrl()
{
- return $this->details['referer_url'];
+ return $this->details['referer_url'];
}
-
+
function getRefererName()
{
- return $this->details['referer_name'];
+ return $this->details['referer_name'];
}
-
+
function getSearchEngineUrl()
{
if($this->getRefererType() == 'searchEngine'
@@ -189,7 +191,7 @@ class Piwik_Live_Visitor
}
return null;
}
-
+
function getSearchEngineIcon()
{
$searchEngineUrl = $this->getSearchEngineUrl();
@@ -202,7 +204,7 @@ class Piwik_Live_Visitor
function getPlugins()
{
- $plugins = array(
+ $plugins = array(
'config_pdf',
'config_flash',
'config_java',
@@ -216,10 +218,10 @@ class Piwik_Live_Visitor
$return = array();
foreach($plugins as $plugin)
{
- if($this->details[$plugin] == 1)
+ if($this->details[$plugin] == 1)
{
$pluginShortName = substr($plugin, 7);
- $return[] = $pluginShortName;
+ $return[] = $pluginShortName;
}
}
return implode(", ", $return);
@@ -229,12 +231,12 @@ class Piwik_Live_Visitor
{
return Piwik_getOSLabel($this->details['config_os']);
}
-
+
function getOperatingSystemShortName()
{
return Piwik_getOSShortLabel($this->details['config_os']);
}
-
+
function getOperatingSystemIcon()
{
return Piwik_getOSLogo($this->details['config_os']);
@@ -244,44 +246,82 @@ class Piwik_Live_Visitor
{
return Piwik_getBrowserTypeLabel($this->getBrowserFamily());
}
-
+
function getBrowserFamily()
{
return Piwik_getBrowserFamily($this->details['config_browser_name']);
}
-
+
function getBrowser()
{
return Piwik_getBrowserLabel($this->details['config_browser_name'] . ";" . $this->details['config_browser_version']);
}
-
+
function getBrowserIcon()
{
return Piwik_getBrowsersLogo($this->details['config_browser_name'] . ";" . $this->details['config_browser_version']);
}
-
+
function getScreenType()
{
return Piwik_getScreenTypeFromResolution($this->details['config_resolution']);
}
-
+
function getResolution()
{
return $this->details['config_resolution'];
}
-
+
function getScreenTypeIcon()
{
return Piwik_getScreensLogo($this->getScreenType());
}
-
+
function getProvider()
{
return Piwik_getHostnameName($this->details['location_provider']);
}
-
+
function getProviderUrl()
{
return Piwik_getHostnameUrl($this->details['location_provider']);
}
+
+ function getDateTimeLastAction()
+ {
+ return date('Y-m-d H:i:s', strtotime($this->details['visit_last_action_time']));
+ }
+
+ function isVisitorGoalConverted()
+ {
+ return $this->details['visit_goal_converted'];
+ }
+
+ function getGoalType()
+ {
+ if(isset($this->details['match_attribute'])){
+ return $this->details['match_attribute'];
+ }
+ return false;
+ }
+
+ function getGoalIcon()
+ {
+ if(isset($this->details['match_attribute'])){
+ $goalicon = "";
+ switch ($this->details['match_attribute']) {
+ case "url":
+ $goalicon = "plugins/Live/templates/images/goal.png";
+ break;
+ case "file":
+ $goalicon = "plugins/Live/templates/images/download.png";
+ break;
+ case "external_website":
+ $goalicon = "plugins/Live/templates/images/outboundlink.png";
+ break;
+ }
+ return $goalicon;
+ }
+ return false;
+ }
}
diff --git a/plugins/Live/templates/images/download.png b/plugins/Live/templates/images/download.png
new file mode 100644
index 0000000000..1920b1bb22
--- /dev/null
+++ b/plugins/Live/templates/images/download.png
Binary files differ
diff --git a/plugins/Live/templates/images/file0.png b/plugins/Live/templates/images/file0.png
new file mode 100644
index 0000000000..2c6ce30fe3
--- /dev/null
+++ b/plugins/Live/templates/images/file0.png
Binary files differ
diff --git a/plugins/Live/templates/images/file1.png b/plugins/Live/templates/images/file1.png
new file mode 100644
index 0000000000..074e577058
--- /dev/null
+++ b/plugins/Live/templates/images/file1.png
Binary files differ
diff --git a/plugins/Live/templates/images/file2.png b/plugins/Live/templates/images/file2.png
new file mode 100644
index 0000000000..48aeb390f2
--- /dev/null
+++ b/plugins/Live/templates/images/file2.png
Binary files differ
diff --git a/plugins/Live/templates/images/file3.png b/plugins/Live/templates/images/file3.png
new file mode 100644
index 0000000000..0827cabe17
--- /dev/null
+++ b/plugins/Live/templates/images/file3.png
Binary files differ
diff --git a/plugins/Live/templates/images/file4.png b/plugins/Live/templates/images/file4.png
new file mode 100644
index 0000000000..a4c277981e
--- /dev/null
+++ b/plugins/Live/templates/images/file4.png
Binary files differ
diff --git a/plugins/Live/templates/images/file5.png b/plugins/Live/templates/images/file5.png
new file mode 100644
index 0000000000..5701f2b274
--- /dev/null
+++ b/plugins/Live/templates/images/file5.png
Binary files differ
diff --git a/plugins/Live/templates/images/file6.png b/plugins/Live/templates/images/file6.png
new file mode 100644
index 0000000000..5099a0222d
--- /dev/null
+++ b/plugins/Live/templates/images/file6.png
Binary files differ
diff --git a/plugins/Live/templates/images/file7.png b/plugins/Live/templates/images/file7.png
new file mode 100644
index 0000000000..8559758b56
--- /dev/null
+++ b/plugins/Live/templates/images/file7.png
Binary files differ
diff --git a/plugins/Live/templates/images/file8.png b/plugins/Live/templates/images/file8.png
new file mode 100644
index 0000000000..515bd791d7
--- /dev/null
+++ b/plugins/Live/templates/images/file8.png
Binary files differ
diff --git a/plugins/Live/templates/images/file9.png b/plugins/Live/templates/images/file9.png
new file mode 100644
index 0000000000..c06ec15bdb
--- /dev/null
+++ b/plugins/Live/templates/images/file9.png
Binary files differ
diff --git a/plugins/Live/templates/images/goal.png b/plugins/Live/templates/images/goal.png
new file mode 100644
index 0000000000..e4bc611f87
--- /dev/null
+++ b/plugins/Live/templates/images/goal.png
Binary files differ
diff --git a/plugins/Live/templates/images/outboundlink.png b/plugins/Live/templates/images/outboundlink.png
new file mode 100644
index 0000000000..0010931e2c
--- /dev/null
+++ b/plugins/Live/templates/images/outboundlink.png
Binary files differ
diff --git a/plugins/Live/templates/index.tpl b/plugins/Live/templates/index.tpl
index 5c012ea5cc..617dc91660 100644
--- a/plugins/Live/templates/index.tpl
+++ b/plugins/Live/templates/index.tpl
@@ -1,28 +1,49 @@
-<h2>Live! (alpha)</h2>
{literal}
<script type="text/javascript" src="plugins/Live/templates/scripts/spy.js"></script>
<script type="text/javascript" charset="utf-8">
- $(document).ready(function() {
- $('#visits').spy({
- limit: 10,
- ajax: 'index.php?module=Live&idSite=1&action=getLastVisits',
- timeout: 500,
- customParameterName: 'minIdVisit',
- customParameterValueCallback: lastIdVisit,
- fadeInSpeed: 1400 }
- );
+
+ $(document).ready(function() {
+ if($('#_spyTmp').size() == 0) {
+ $('#visitsLive > div:gt(2)').fadeEachDown(); // initial fade
+ $('#visitsLive').spy({
+ limit: 10,
+ ajax: 'index.php?module=Live&idSite={/literal}{$idSite}{literal}&action=getLastVisitsStart',
+ fadeLast: 2,
+ isDupe: check_for_dupe,
+ timeout: 8000,
+ customParameterName: 'minIdVisit',
+ customParameterValueCallback: lastIdVisit,
+ fadeInSpeed: 600
+ });
+ }
});
-
+
+ // first I'm ensuring that 'last' has been initialised (with last.constructor == Object),
+ // then prev.html() == last.html() will return true if the HTML is the same, or false,
+ // if I have a different entry.
+ function check_for_dupe(prev, last)
+ {
+ if (last.constructor == Object) {
+ return (prev.html() == last.html());
+ }
+ else {
+ return 0;
+ }
+ }
+
function lastIdVisit()
{
- return $('#visits > div:lt(2) .idvisit').html();
+ updateTotalVisits();
+ updateVisitBox();
+ return $('#visitsLive > div:lt(2) .idvisit').html();
}
+
var pauseImage = "plugins/Live/templates/images/pause.gif";
var pauseDisabledImage = "plugins/Live/templates/images/pause_disabled.gif";
var playImage = "plugins/Live/templates/images/play.gif";
var playDisabledImage = "plugins/Live/templates/images/play_disabled.gif";
-
+
function onClickPause()
{
$('#pauseImage').attr('src', pauseImage);
@@ -36,50 +57,127 @@
return playSpy();
}
+ // updates the numbers of total visits in startbox
+ function updateTotalVisits()
+ {
+ $("#visitsTotal").load("index.php?module=Live&idSite={/literal}{$idSite}{literal}&action=ajaxTotalVisitors");
+ }
+
+ // updates the visit table, to refresh the already presented visotors pages
+ function updateVisitBox()
+ {
+ $("#visitsLive").load("index.php?module=Live&idSite={/literal}{$idSite}{literal}&action=getLastVisitsStart");
+ }
+
+ /* TOOLTIP */
+ $('#visitsLive label').tooltip({
+ track: true,
+ delay: 0,
+ showURL: false,
+ showBody: " - ",
+ fade: 250
+ });
+
</script>
<style>
-#visits {
+#visitsLive {
text-align:left;
+ font-size:90%;
}
-#visits .datetime, #visits .country, #visits .referer, #visits .settings, #visits .returning {
- float:left;
- margin-right:10px;
- overflow:hidden;
- padding-left:1px;
- max-width:700px;
+#visitsLive .datetime, #visitsLive .country, #visitsLive .referer, #visitsLive .settings, #visitsLive .returning , #visitsLive .countActions{
+ border-bottom:1px solid #C1DAD7;
+ border-right:1px solid #C1DAD7;
+ padding:5px 5px 5px 12px;
+}
+
+#visitsLive .datetime {
+ background:#D4E3ED url(plugins/CoreHome/templates/images/bg_header.jpg) repeat-x scroll 0 0;
+ border-top:1px solid #C1DAD7;
+ color:#6D929B;
+ margin:0;
+ text-align:left;
}
-#visits .datetime {
- width:110px;
+
+#visitsLive .country {
+ color:#4F6B72;
+ background:#FFFFFF url(plugins/CoreHome/templates/images/bullet1.gif) no-repeat scroll 0 0;
}
-#visits .country {
- width:30px;
+
+#visitsLive .referer {
+ background:#F9FAFA none repeat scroll 0 0;
+ color:#797268;
}
-#visits .referer {
- width:200px;
+
+#visitsLive .pagesTitle {
+ display:block;
+ float:left;
+ padding-top: 3px;
}
-#visits .settings {
- width:100px;
+
+#visitsLive .countActions {
+ background:#FFFFFF none repeat scroll 0 0;
+ color:#4F6B72;
}
-#visits .returning {
- width:30px;
+
+#visitsLive .settings {
+ background:#FFFFFF none repeat scroll 0 0;
+ color:#4F6B72;
}
-#visits .visit {
- border-bottom:1px solid #C1DAD7;
- background-color:#F9FAFA;
- padding:10px;
- line-height:24px;
- height:40px;
+
+#visitsLive .returning {
+ background:#F9FAFA none repeat scroll 0 0;
+ color:#797268;
+}
+
+#visitsLive .visit {
+}
+
+#visitsLive .alt {
}
-#visits .alt {
- background-color:#FFFFFF;
+
+#visitsLive .actions {
+ background:#F9FAFA none repeat scroll 0 0;
+ color:#797268;
+ padding:0px 5px 0px 12px;
}
+
</style>
{/literal}
+<div id="visitsTotal">
+ <table class="dataTable" cellspacing="0">
+ <thead>
+ <tr>
+ <th id="label" class="sortable label" style="cursor: auto;">
+ <div id="thDIV">Period<div></th>
+ <th id="label" class="sortable label" style="cursor: auto;">
+ <div id="thDIV">Visits<div></th>
+ <th id="label" class="sortable label" style="cursor: auto;">
+ <div id="thDIV">PageViews<div></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <tr class="">
+ <td class="columnodd">Today</td>
+ <td class="columnodd">{$visitorsCountToday}</td>
+ <td class="columnodd">{$pisToday}</td>
+ </tr>
+ <tr class="">
+ <td class="columnodd">Last 30 minutes</td>
+ <td class="columnodd">{$visitorsCountHalfHour}</td>
+ <td class="columnodd">{$pisHalfhour}</td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+
+<div id='visitsLive'>
{$visitors}
+</div>
<div>
- <a href="#?" onclick="onClickPause();"><img id="pauseImage" border="0" src="plugins/Live/templates/images/pause_disabled.gif"></a>
- <a href="#?" onclick="onClickPlay();"><img id="playImage" border="0" src="plugins/Live/templates/images/play.gif"></a>
-</div> \ No newline at end of file
+ <a href="javascript:void(0);" onclick="onClickPause();"><img id="pauseImage" border="0" src="plugins/Live/templates/images/pause_disabled.gif" /></a>
+ <a href="javascript:void(0);" onclick="onClickPlay();"><img id="playImage" border="0" src="plugins/Live/templates/images/play.gif" /></a>
+</div>
diff --git a/plugins/Live/templates/lastVisits.tpl b/plugins/Live/templates/lastVisits.tpl
index ac515f2d63..e67ab5ec71 100644
--- a/plugins/Live/templates/lastVisits.tpl
+++ b/plugins/Live/templates/lastVisits.tpl
@@ -1,15 +1,35 @@
-<div id="visits">
{foreach from=$visitors item=visitor}
- <div class="visit{if $visitor.idVisit % 2} alt{/if}">
+ <div id="{$visitor.idVisit}" class="visit{if $visitor.idVisit % 2} alt{/if}">
<div style="display:none" class="idvisit">{$visitor.idVisit}</div>
- <div class="datetime">{$visitor.serverDatePretty}<br/>{$visitor.serverTimePretty}</div>
- <div class="country"><img src="{$visitor.countryFlag}" title="{$visitor.country}, Provider {$visitor.provider}"></div>
- <div class="referer">{if $visitor.refererType != 'directEntry'}from <a href="{$visitor.refererUrl}">{$visitor.refererName}</a> {if !empty($visitor.keywords)}"{$visitor.keywords}"{/if}{/if}</div>
- <div class="settings">
- <img src="{$visitor.browserIcon}" title="{$visitor.browser} with plugins {$visitor.plugins} enabled">
- <img src="{$visitor.operatingSystemIcon}" title="{$visitor.operatingSystem}, {$visitor.resolution}">
+ <div class="datetime">
+ {$visitor.serverDatePretty} - {$visitor.serverTimePretty}
+ &nbsp;<img src="{$visitor.countryFlag}" title="{$visitor.country}, Provider {$visitor.provider}" />
+ &nbsp;<img src="{$visitor.browserIcon}" title="{$visitor.browser} with plugins {$visitor.plugins} enabled" />
+ &nbsp;<img src="{$visitor.operatingSystemIcon}" title="{$visitor.operatingSystem}, {$visitor.resolution}" />
+ &nbsp;{if $visitor.isVisitorGoalConverted}<img src="{$visitor.goalIcon}" title="{$visitor.goalType}" />{/if}
+ {if $visitor.isVisitorReturning}&nbsp;<img src="plugins/Live/templates/images/returningVisitor.gif" title="Returning Visitor" />{/if}
+ &nbsp;<label id="" title="IP: {$visitor.ip} - Duration: {$visitor.visitLengthPretty}">more...</label>
+ </div>
+ <!--<div class="settings"></div>-->
+ <div class="referer">
+ {if $visitor.refererType != 'directEntry'}from <a href="{$visitor.refererUrl}" target="_blank">{if !empty($visitor.searchEngineIcon)}<img src="{$visitor.searchEngineIcon}" /> {/if}{$visitor.refererName}</a>
+ {if !empty($visitor.keywords)}"{$visitor.keywords}"{/if}
+ {/if}
+ {if $visitor.refererType == 'directEntry'}Direct entry{/if}
+ </div>
+ <div id="{$visitor.idVisit}_actions" class="settings">
+ <span class="pagesTitle">Pages:</span>&nbsp;
+ {php} $col = 0; {/php}
+ {foreach from=$visitor.actionDetails item=action}
+ {php}
+ $col++;
+ if ($col>=9)
+ {
+ $col=0;
+ }
+ {/php}
+ <a href="{$action.pageUrl}" target="_blank"><img align="middle" src="plugins/Live/templates/images/file{php} echo $col; {/php}.png" title="{$action.pageUrl}" /></a>
+ {/foreach}
</div>
- <div class="returning">{if $visitor.isVisitorReturning}<img src="plugins/Live/templates/images/returningVisitor.gif" title="Returning Visitor">{/if}</div>
</div>
{/foreach}
-</div>
diff --git a/plugins/Live/templates/scripts/spy.js b/plugins/Live/templates/scripts/spy.js
index c2fb38863c..27454fe029 100644
--- a/plugins/Live/templates/scripts/spy.js
+++ b/plugins/Live/templates/scripts/spy.js
@@ -12,12 +12,12 @@ $.fn.spy = function(settings) {
spy.parsing = 0;
spy.waitTimer = 0;
spy.json = null;
-
+
if (!settings.ajax) {
alert("An AJAX/AJAH URL must be set for the spy to work.");
return;
}
-
+
spy.attachHolder = function() {
// not mad on this, but the only way to parse HTML collections
if (o.method == 'html')
@@ -37,7 +37,7 @@ $.fn.spy = function(settings) {
else
return 0;
}
-
+
spy.parse = function(e, r) {
spy.parsing = 1; // flag to stop pull via ajax
if (o.method == 'html') {
@@ -45,7 +45,7 @@ $.fn.spy = function(settings) {
} else if (o.method == 'json') {
eval('spy.json = ' + r); // convert text to json
}
-
+
if ((o.method == 'json' && spy.json.constructor == Array) || o.method == 'html') {
if (spy.parseItem(e)) {
spy.waitTimer = window.setInterval(function() {
@@ -65,7 +65,7 @@ $.fn.spy = function(settings) {
spy.parsing = 0;
}
}
-
+
// returns true if there's more to parse
spy.parseItem = function(e) {
if (o.method == 'html') {
@@ -74,7 +74,7 @@ $.fn.spy = function(settings) {
if (i.size() > 0) {
i.hide();
spy.addItem(e, i);
- }
+ }
return ($('div#_spyTmp').find('div').size() != 0);
} else {
if (spy.json.length) {
@@ -85,20 +85,21 @@ $.fn.spy = function(settings) {
return (spy.json.length != 0);
}
}
-
+
spy.addItem = function(e, i) {
if (! o.isDupe.call(this, i, spy.last)) {
spy.last = i; // note i is a pointer - so when it gets modified, so does spy.last
- $('#' + e.id + ' > div:gt(' + (o.limit - 1) + ')').remove();
+ $('#' + e.id + ' > div:gt(' + (o.limit - 2) + ')').remove();
+ $('#' + e.id + ' > div:gt(' + (o.limit - o.fadeLast - 2) + ')').fadeEachDown();
o.push.call(e, i);
$('#' + e.id + ' > div:first').fadeIn(o.fadeInSpeed);
}
}
-
+
spy.push = function(r) {
$('#' + this.id).prepend(r);
}
-
+
var o = {
limit: (settings.limit || 10),
ajax: settings.ajax,
@@ -109,7 +110,7 @@ $.fn.spy = function(settings) {
fadeInSpeed: (settings.fadeInSpeed || 'slow'), // 1400 = crawl
customParameterName: settings.customParameterName,
customParameterValueCallback: settings.customParameterValueCallback,
- isDupe: (settings.isDupe || spy.isDupe),
+ isDupe: (settings.isDupe || spy.isDupe)
};
spy.attachHolder();
@@ -125,11 +126,22 @@ $.fn.spy = function(settings) {
$.get(o.ajax, parameters, function(r) {
spy.parse(e, r);
});
- }
+ }
}, o.timeout);
});
};
+$.fn.fadeEachDown = function() {
+ var s = this.size()+5;
+ return this.each(function(i) {
+ var o = 1 - (s == 1 ? 0.5 : 0.85/s*(i+1));
+ var e = this.style;
+ if (window.ActiveXObject)
+ e.filter = "alpha(opacity=" + o*100 + ")";
+ e.opacity = o;
+ });
+};
+
function pauseSpy() {
spyRunning = 0; return false;
}
@@ -137,3 +149,6 @@ function pauseSpy() {
function playSpy() {
spyRunning = 1; return false;
}
+
+
+
diff --git a/plugins/Live/templates/structure.tpl b/plugins/Live/templates/structure.tpl
deleted file mode 100644
index a3bbc0f4f6..0000000000
--- a/plugins/Live/templates/structure.tpl
+++ /dev/null
@@ -1,5 +0,0 @@
-{assign var=showSitesSelection value=true}
-{assign var=showPeriodSelection value=false}
-{include file="CoreAdminHome/templates/header.tpl"}
-{include file="Live/templates/index.tpl"}
-
diff --git a/plugins/Live/templates/totalVisits.tpl b/plugins/Live/templates/totalVisits.tpl
new file mode 100644
index 0000000000..a7294d7853
--- /dev/null
+++ b/plugins/Live/templates/totalVisits.tpl
@@ -0,0 +1,26 @@
+<div id="visitsTotal">
+ <table class="dataTable" cellspacing="0">
+ <thead>
+ <tr>
+ <th id="label" class="sortable label" style="cursor: auto;">
+ <div id="thDIV">{'Live_Date'|translate}</div></th>
+ <th id="label" class="sortable label" style="cursor: auto;">
+ <div id="thDIV">{'General_ColumnNbVisits'|translate}</div></th>
+ <th id="label" class="sortable label" style="cursor: auto;">
+ <div id="thDIV">{'General_ColumnPageviews'|translate}</div></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="">
+ <td class="columnodd">{'General_Today'|translate}</td>
+ <td class="columnodd">{$visitorsCountToday}</td>
+ <td class="columnodd">{$pisToday}</td>
+ </tr>
+ <tr class="">
+ <td class="columnodd">{'Live_Last30Minutes'|translate}</td>
+ <td class="columnodd">{$visitorsCountHalfHour}</td>
+ <td class="columnodd">{$pisHalfhour}</td>
+ </tr>
+ </tbody>
+ </table>
+</div>
diff --git a/plugins/Login/Auth.php b/plugins/Login/Auth.php
index 9bc4902831..c36254d64a 100644
--- a/plugins/Login/Auth.php
+++ b/plugins/Login/Auth.php
@@ -28,7 +28,7 @@ class Piwik_Login_Auth implements Piwik_Auth
{
$rootLogin = Zend_Registry::get('config')->superuser->login;
$rootPassword = Zend_Registry::get('config')->superuser->password;
- $rootToken = Piwik_UsersManager_API::getTokenAuth($rootLogin, $rootPassword);
+ $rootToken = Piwik_UsersManager_API::getInstance()->getTokenAuth($rootLogin, $rootPassword);
if($this->login == $rootLogin
&& $this->token_auth == $rootToken)
@@ -42,7 +42,7 @@ class Piwik_Login_Auth implements Piwik_Auth
}
$login = Piwik_FetchOne(
- 'SELECT login FROM '.Piwik::prefixTable('user').' WHERE token_auth = ?',
+ 'SELECT login FROM '.Piwik_Common::prefixTable('user').' WHERE token_auth = ?',
array($this->token_auth)
);
if($login !== false)
diff --git a/plugins/Login/Controller.php b/plugins/Login/Controller.php
index 022c47bf01..02056be0bf 100644
--- a/plugins/Login/Controller.php
+++ b/plugins/Login/Controller.php
@@ -11,13 +11,47 @@
*/
/**
+ * Login controller
*
* @package Piwik_Login
*/
class Piwik_Login_Controller extends Piwik_Controller
{
/**
+ * Get referer to redirect to upon successful login.
+ * Remembers referer URL even if navigation is: login form -> reset password -> login form
+ *
+ * @returns string
+ */
+ static public function getRefererToRedirect()
+ {
+ // retrieve any previously saved referer
+ $ns = new Zend_Session_Namespace('Piwik_Login.referer');
+ $referer = $ns->referer;
+ if(empty($referer))
+ {
+ // if the referer contains module=Login, Installation, or CoreUpdater, we instead redirect to the doc root
+ $referer = Piwik_Url::getLocalReferer();
+ if(empty($referer) || preg_match('/module=(Login|Installation|CoreUpdater)/', $referer))
+ {
+ $referer = 'index.php';
+ }
+ $ns->referer = $referer;
+ $ns->setExpirationSeconds(300, 'referer');
+ }
+ else if(!Piwik_Url::isLocalUrl($referer))
+ {
+ $referer = 'index.php';
+ }
+
+ return $referer;
+ }
+
+ /**
* Default action
+ *
+ * @param none
+ * @return void
*/
function index()
{
@@ -26,34 +60,39 @@ class Piwik_Login_Controller extends Piwik_Controller
/**
* Login form
+ *
+ * @param string $messageNoAccess Access error message
+ * @param string $currentUrl Current URL
+ * @return void
*/
- function login()
+ function login($messageNoAccess = null)
{
- $messageNoAccess = null;
- $form = new Piwik_Login_Form();
-
- $currentUrl = Piwik_Url::getReferer();
- $urlToRedirect = Piwik_Common::getRequestVar('form_url', $currentUrl, 'string');
- $urlToRedirect = htmlspecialchars_decode($urlToRedirect);
+ $urlToRedirect = self::getRefererToRedirect();
+ $form = new Piwik_Login_Form();
if($form->validate())
{
- // if the current url to redirect contains module=Login or Installation we instead redirect to the doc root
- if(preg_match('/module=(Login|Installation)/', $urlToRedirect))
+ $nonce = $form->getSubmitValue('form_nonce');
+ if(Piwik_Nonce::verifyNonce('Piwik_Login.login', $nonce))
{
- $urlToRedirect = 'index.php';
+ $login = $form->getSubmitValue('form_login');
+ $password = $form->getSubmitValue('form_password');
+ $md5Password = md5($password);
+ try {
+ $this->authenticateAndRedirect($login, $md5Password, $urlToRedirect);
+ } catch(Exception $e) {
+ $messageNoAccess = $e->getMessage();
+ }
+ }
+ else
+ {
+ $messageNoAccess = Piwik_Translate('Login_InvalidNonceOrReferer');
}
-
- $login = $form->getSubmitValue('form_login');
- $password = $form->getSubmitValue('form_password');
- $md5Password = md5($password);
- $messageNoAccess = $this->authenticateAndRedirect($login, $md5Password, $urlToRedirect);
}
$view = Piwik_View::factory('login');
- // make navigation login form -> reset password -> login form remember your first url
- $view->urlToRedirect = $urlToRedirect;
$view->AccessErrorString = $messageNoAccess;
+ $view->nonce = Piwik_Nonce::getNonce('Piwik_Login.login');
$view->linkTitle = Piwik::getRandomTitle();
$view->addForm( $form );
$view->subTemplate = 'genericForm.tpl';
@@ -62,28 +101,29 @@ class Piwik_Login_Controller extends Piwik_Controller
/**
* Form-less login
+ *
+ * @param none
+ * @return void
*/
function logme()
{
- $login = Piwik_Common::getRequestVar('login', null, 'string');
$password = Piwik_Common::getRequestVar('password', null, 'string');
- $currentUrl = 'index.php';
- $urlToRedirect = Piwik_Common::getRequestVar('url', $currentUrl, 'string');
- $urlToRedirect = htmlspecialchars_decode($urlToRedirect);
-
if(strlen($password) != 32)
{
- throw new Exception("The password parameter is expected to be a MD5 hash of the password.");
+ throw new Exception(Piwik_TranslateException('Login_ExceptionPasswordMD5HashExpected'));
}
+
+ $login = Piwik_Common::getRequestVar('login', null, 'string');
if($login == Zend_Registry::get('config')->superuser->login)
- {
- throw new Exception("The Super User cannot be authenticated using this URL.");
- }
- $authenticated = $this->authenticateAndRedirect($login, $password, $urlToRedirect);
- if($authenticated === false)
- {
- echo Piwik_Translate('Login_LoginPasswordNotCorrect');
+ {
+ throw new Exception(Piwik_TranslateException('Login_ExceptionInvalidSuperUserAuthenticationMethod', array("logme")));
}
+
+ $currentUrl = 'index.php';
+ $urlToRedirect = Piwik_Common::getRequestVar('url', $currentUrl, 'string');
+ $urlToRedirect = htmlspecialchars_decode($urlToRedirect);
+
+ $this->authenticateAndRedirect($login, $password, $urlToRedirect);
}
/**
@@ -96,51 +136,33 @@ class Piwik_Login_Controller extends Piwik_Controller
*/
protected function authenticateAndRedirect($login, $md5Password, $urlToRedirect)
{
- $tokenAuth = Piwik_UsersManager_API::getTokenAuth($login, $md5Password);
-
- $auth = Zend_Registry::get('auth');
- $auth->setLogin($login);
- $auth->setTokenAuth($tokenAuth);
-
- $authResult = $auth->authenticate();
- if(!$authResult->isValid())
- {
- return Piwik_Translate('Login_LoginPasswordNotCorrect');
- }
-
- $authCookieName = Zend_Registry::get('config')->General->login_cookie_name;
- $authCookieExpiry = time() + Zend_Registry::get('config')->General->login_cookie_expire;
- $cookie = new Piwik_Cookie($authCookieName, $authCookieExpiry);
- $cookie->set('login', $login);
- $cookie->set('token_auth', $authResult->getTokenAuth());
- $cookie->save();
-
- Zend_Session::regenerateId();
-
+ $info = array( 'login' => $login,
+ 'md5Password' => $md5Password,
+ );
+ Piwik_PostEvent('Login.initSession', $info);
Piwik_Url::redirectToUrl($urlToRedirect);
}
/**
* Lost password form. Email password reset information.
+ *
+ * @param none
+ * @return void
*/
function lostPassword()
{
$messageNoAccess = null;
- $form = new Piwik_Login_PasswordForm();
- $currentUrl = 'index.php';
- $urlToRedirect = Piwik_Common::getRequestVar('form_url', $currentUrl, 'string');
- $urlToRedirect = htmlspecialchars_decode($urlToRedirect);
+ $urlToRedirect = self::getRefererToRedirect();
+ $form = new Piwik_Login_PasswordForm();
if($form->validate())
{
$loginMail = $form->getSubmitValue('form_login');
- $messageNoAccess = $this->lostPasswordFormValidated($loginMail, $urlToRedirect);
+ $messageNoAccess = $this->lostPasswordFormValidated($loginMail);
}
$view = Piwik_View::factory('lostPassword');
$view->AccessErrorString = $messageNoAccess;
- // make navigation login form -> reset password -> login form remember your first url
- $view->urlToRedirect = $urlToRedirect;
$view->linkTitle = Piwik::getRandomTitle();
$view->addForm( $form );
$view->subTemplate = 'genericForm.tpl';
@@ -154,7 +176,7 @@ class Piwik_Login_Controller extends Piwik_Controller
* @param string $urlToRedirect (URL to redirect to, if successfully validated)
* @return string (failure message if unable to validate)
*/
- protected function lostPasswordFormValidated($loginMail, $urlToRedirect)
+ protected function lostPasswordFormValidated($loginMail)
{
$user = self::getUserInformation($loginMail);
if( $user === null )
@@ -184,7 +206,7 @@ class Piwik_Login_Controller extends Piwik_Controller
'\n',
"\n",
sprintf(Piwik_Translate('Login_MailPasswordRecoveryBody'), $login, $ip, $url, $resetToken)
- )
+ ) . "\n"
);
$piwikHost = $_SERVER['HTTP_HOST'];
@@ -205,7 +227,6 @@ class Piwik_Login_Controller extends Piwik_Controller
}
$view->linkTitle = Piwik::getRandomTitle();
- $view->urlToRedirect = $urlToRedirect;
echo $view->render();
exit;
@@ -213,28 +234,26 @@ class Piwik_Login_Controller extends Piwik_Controller
/**
* Reset password form. Enter new password here.
+ *
+ * @param none
+ * @return void
*/
function resetPassword()
{
$messageNoAccess = null;
+ $urlToRedirect = self::getRefererToRedirect();
$form = new Piwik_Login_ResetPasswordForm();
- $currentUrl = 'index.php';
- $urlToRedirect = Piwik_Common::getRequestVar('form_url', $currentUrl, 'string');
- $urlToRedirect = htmlspecialchars_decode($urlToRedirect);
-
if($form->validate())
{
$loginMail = $form->getSubmitValue('form_login');
$token = $form->getSubmitValue('form_token');
$password = $form->getSubmitValue('form_password');
- $messageNoAccess = $this->resetPasswordFormValidated($loginMail, $token, $password, $urlToRedirect);
+ $messageNoAccess = $this->resetPasswordFormValidated($loginMail, $token, $password);
}
$view = Piwik_View::factory('resetPassword');
$view->AccessErrorString = $messageNoAccess;
- // make navigation login form -> reset password -> login form remember your first url
- $view->urlToRedirect = $urlToRedirect;
$view->linkTitle = Piwik::getRandomTitle();
$view->addForm( $form );
$view->subTemplate = 'genericForm.tpl';
@@ -250,7 +269,7 @@ class Piwik_Login_Controller extends Piwik_Controller
* @param string $urlToRedirect (URL to redirect to, if successfully validated)
* @return string (failure message)
*/
- protected function resetPasswordFormValidated($loginMail, $token, $password, $urlToRedirect)
+ protected function resetPasswordFormValidated($loginMail, $token, $password)
{
$user = self::getUserInformation($loginMail);
if( $user === null )
@@ -272,7 +291,7 @@ class Piwik_Login_Controller extends Piwik_Controller
}
else
{
- Piwik_UsersManager_API::updateUser($user['login'], $password);
+ Piwik_UsersManager_API::getInstance()->updateUser($user['login'], $password);
}
}
catch(Exception $e)
@@ -282,7 +301,6 @@ class Piwik_Login_Controller extends Piwik_Controller
$view = Piwik_View::factory('passwordchanged');
$view->linkTitle = Piwik::getRandomTitle();
- $view->urlToRedirect = $urlToRedirect;
echo $view->render();
exit;
@@ -308,13 +326,13 @@ class Piwik_Login_Controller extends Piwik_Controller
'password' => Zend_Registry::get('config')->superuser->password,
);
}
- else if( Piwik_UsersManager_API::userExists($loginMail) )
+ else if( Piwik_UsersManager_API::getInstance()->userExists($loginMail) )
{
- $user = Piwik_UsersManager_API::getUser($loginMail);
+ $user = Piwik_UsersManager_API::getInstance()->getUser($loginMail);
}
- else if( Piwik_UsersManager_API::userEmailExists($loginMail) )
+ else if( Piwik_UsersManager_API::getInstance()->userEmailExists($loginMail) )
{
- $user = Piwik_UsersManager_API::getUserByEmail($loginMail);
+ $user = Piwik_UsersManager_API::getInstance()->getUserByEmail($loginMail);
}
return $user;
@@ -370,6 +388,9 @@ class Piwik_Login_Controller extends Piwik_Controller
/**
* Clear session information
+ *
+ * @param none
+ * @return void
*/
static public function clearSession()
{
@@ -382,6 +403,9 @@ class Piwik_Login_Controller extends Piwik_Controller
/**
* Logout current user
+ *
+ * @param none
+ * @return void
*/
public function logout()
{
diff --git a/plugins/Login/Form.php b/plugins/Login/Form.php
index 04176cd52d..88483c1fe6 100644
--- a/plugins/Login/Form.php
+++ b/plugins/Login/Form.php
@@ -25,20 +25,15 @@ class Piwik_Login_Form extends Piwik_Form
function init()
{
- // if form_url is not defined, go to referrer
- $currentUrl = Piwik_Url::getReferer();
- $urlToGoAfter = Piwik_Common::getRequestVar('form_url', $currentUrl, 'string');
- $urlToGoAfter = htmlspecialchars_decode($urlToGoAfter);
-
$formElements = array(
array('text', 'form_login'),
array('password', 'form_password'),
- array('hidden', 'form_url', $urlToGoAfter),
+ array('hidden', 'form_nonce'),
);
$this->addElements( $formElements );
$formRules = array(
- array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_Login')), 'required'),
+ array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('General_Username')), 'required'),
array('form_password', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_Password')), 'required'),
);
$this->addRules( $formRules );
diff --git a/plugins/Login/Login.php b/plugins/Login/Login.php
index 3866cd7ba7..0002029d82 100644
--- a/plugins/Login/Login.php
+++ b/plugins/Login/Login.php
@@ -19,11 +19,10 @@ class Piwik_Login extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Login',
- 'description' => 'Login Authentication plugin, reading the credentials from the config/config.inc.php file for the Super User, and from the Database for the other users. Can be easily replaced to introduce a new Authentication mechanism (OpenID, htaccess, custom Auth, etc.).',
+ 'description' => Piwik_Translate('Login_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
}
@@ -34,6 +33,7 @@ class Piwik_Login extends Piwik_Plugin
'FrontController.initAuthenticationObject' => 'initAuthenticationObject',
'FrontController.NoAccessException' => 'noAccess',
'API.Request.authenticate' => 'ApiRequestAuthenticate',
+ 'Login.initSession' => 'initSession',
);
return $hooks;
}
@@ -68,7 +68,8 @@ class Piwik_Login extends Piwik_Plugin
$authCookieName = Zend_Registry::get('config')->General->login_cookie_name;
$authCookieExpiry = time() + Zend_Registry::get('config')->General->login_cookie_expire;
- $authCookie = new Piwik_Cookie($authCookieName, $authCookieExpiry);
+ $authCookiePath = Zend_Registry::get('config')->General->login_cookie_path;
+ $authCookie = new Piwik_Cookie($authCookieName, $authCookieExpiry, $authCookiePath);
$defaultLogin = 'anonymous';
$defaultTokenAuth = 'anonymous';
if($authCookie->isCookieFound())
@@ -79,4 +80,36 @@ class Piwik_Login extends Piwik_Plugin
$auth->setLogin($defaultLogin);
$auth->setTokenAuth($defaultTokenAuth);
}
+
+ function initSession($notification)
+ {
+ $info = $notification->getNotificationObject();
+ $login = $info['login'];
+ $md5Password = $info['md5Password'];
+
+ $tokenAuth = Piwik_UsersManager_API::getInstance()->getTokenAuth($login, $md5Password);
+
+ $auth = Zend_Registry::get('auth');
+ $auth->setLogin($login);
+ $auth->setTokenAuth($tokenAuth);
+
+ $authResult = $auth->authenticate();
+ if(!$authResult->isValid())
+ {
+ throw new Exception(Piwik_Translate('Login_LoginPasswordNotCorrect'));
+ }
+
+ $ns = new Zend_Session_Namespace('Piwik_Login.referer');
+ unset($ns->referer);
+
+ $authCookieName = Zend_Registry::get('config')->General->login_cookie_name;
+ $authCookieExpiry = time() + Zend_Registry::get('config')->General->login_cookie_expire;
+ $authCookiePath = Zend_Registry::get('config')->General->login_cookie_path;
+ $cookie = new Piwik_Cookie($authCookieName, $authCookieExpiry, $authCookiePath);
+ $cookie->set('login', $login);
+ $cookie->set('token_auth', $authResult->getTokenAuth());
+ $cookie->save();
+
+ Zend_Session::regenerateId();
+ }
}
diff --git a/plugins/Login/PasswordForm.php b/plugins/Login/PasswordForm.php
index 7bb39d454c..dac4192c6f 100644
--- a/plugins/Login/PasswordForm.php
+++ b/plugins/Login/PasswordForm.php
@@ -25,12 +25,8 @@ class Piwik_Login_PasswordForm extends Piwik_Form
function init()
{
- $currentUrl = 'index.php';
- $urlToGoAfter = Piwik_Common::getRequestVar('form_url', $currentUrl, 'string');
-
$formElements = array(
array('text', 'form_login'),
- array('hidden', 'form_url', $urlToGoAfter),
);
$this->addElements( $formElements );
diff --git a/plugins/Login/ResetPasswordForm.php b/plugins/Login/ResetPasswordForm.php
index a62cf775d1..87470f6e18 100644
--- a/plugins/Login/ResetPasswordForm.php
+++ b/plugins/Login/ResetPasswordForm.php
@@ -25,9 +25,6 @@ class Piwik_Login_ResetPasswordForm extends Piwik_Form
function init()
{
- $currentUrl = 'index.php';
- $urlToGoAfter = Piwik_Common::getRequestVar('form_url', $currentUrl, 'string');
-
$resetToken = Piwik_Common::getRequestVar('token', '', 'string');
$formElements = array(
@@ -35,7 +32,6 @@ class Piwik_Login_ResetPasswordForm extends Piwik_Form
array('password', 'form_password'),
array('password', 'form_password_bis'),
array('text', 'form_token'),
- array('hidden', 'form_url', $urlToGoAfter),
);
$this->addElements( $formElements );
@@ -45,7 +41,7 @@ class Piwik_Login_ResetPasswordForm extends Piwik_Form
$this->setDefaults($defaults);
$formRules = array(
- array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_Login')), 'required'),
+ array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('General_Username')), 'required'),
array('form_password', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_Password')), 'required'),
array('form_password_bis', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_PasswordRepeat')), 'required'),
array('form_token', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_PasswordResetToken')), 'required'),
diff --git a/plugins/Login/templates/header.tpl b/plugins/Login/templates/header.tpl
index 5b46dd7440..b1cb4b4ae7 100644
--- a/plugins/Login/templates/header.tpl
+++ b/plugins/Login/templates/header.tpl
@@ -2,11 +2,12 @@
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
<head>
- <title>Piwik &rsaquo; Login</title>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>Piwik &rsaquo; {'Login_LogIn'|translate}</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="plugins/CoreHome/templates/images/favicon.ico" />
<link rel="stylesheet" type="text/css" href="plugins/Login/templates/login.css" media="screen" />
+ {postEvent name="template_css_import"}
{literal}
<script type="text/javascript">
@@ -20,6 +21,8 @@
window.onload = focusit;
</script>
{/literal}
+ <script type="text/javascript" src="libs/jquery/jquery.js"></script>
+ {postEvent name="template_js_import"}
</head>
<body class="login">
diff --git a/plugins/Login/templates/login.css b/plugins/Login/templates/login.css
index e80d7c4a19..af9a89aee7 100644
--- a/plugins/Login/templates/login.css
+++ b/plugins/Login/templates/login.css
@@ -14,7 +14,6 @@ form {
padding: 16px 16px 40px 16px;
font-weight: bold;
-moz-border-radius: 5px;
- -khtml-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
@@ -34,7 +33,6 @@ form .forgetmenot {
border-width: 1px;
border-style: solid;
-moz-border-radius: 3px;
- -khtml-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
cursor: default;
diff --git a/plugins/Login/templates/login.tpl b/plugins/Login/templates/login.tpl
index 16d23a0a06..f837ada5c3 100644
--- a/plugins/Login/templates/login.tpl
+++ b/plugins/Login/templates/login.tpl
@@ -16,8 +16,9 @@
<form {$form_data.attributes}>
<p>
- <label>{'Login_Login'|translate}:<br />
- <input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" /></label>
+ <label>{'General_Username'|translate}:<br />
+ <input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" />
+ <input type="hidden" name="form_nonce" id="form_nonce" value="{$nonce}" /></label>
</p>
<p>
@@ -27,14 +28,13 @@
{*
<p class="forgetmenot"><label><input name="rememberme" type="checkbox" id="rememberme" value="forever" tabindex="90" /> Remember Me</label></p>
*}
- {$form_data.form_url.html}
<p class="submit">
<input type="submit" value="{'Login_LogIn'|translate}" tabindex="100" />
</p>
</form>
<p id="nav">
-<a href="index.php?module=Login&amp;action=lostPassword&amp;form_url={$urlToRedirect|escape:url}" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a>
+<a href="index.php?module=Login&amp;action=lostPassword" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a>
</p>
</div>
diff --git a/plugins/Login/templates/lostPassword.tpl b/plugins/Login/templates/lostPassword.tpl
index 9f079f7ea4..7e3e8fbe66 100644
--- a/plugins/Login/templates/lostPassword.tpl
+++ b/plugins/Login/templates/lostPassword.tpl
@@ -23,14 +23,13 @@
<label>{'Login_LoginOrEmail'|translate}:<br />
<input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" /></label>
</p>
- {$form_data.form_url.html}
<p class="submit">
<input type="submit" value="{'Login_RemindPassword'|translate}" tabindex="100" />
</p>
</form>
<p id="nav">
-<a href="index.php?module=Login&amp;form_url={$urlToRedirect|escape:url}" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
+<a href="index.php?module=Login" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
</p>
</div>
diff --git a/plugins/Login/templates/passwordchanged.tpl b/plugins/Login/templates/passwordchanged.tpl
index 9963a060d9..5337abc2c2 100644
--- a/plugins/Login/templates/passwordchanged.tpl
+++ b/plugins/Login/templates/passwordchanged.tpl
@@ -13,7 +13,7 @@
{/if}
<p id="nav">
-<a href="index.php?module=Login&amp;form_url={$urlToRedirect|escape:url}" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
+<a href="index.php?module=Login" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
</p>
</div>
diff --git a/plugins/Login/templates/passwordsent.tpl b/plugins/Login/templates/passwordsent.tpl
index 175498c1f8..7529c57f24 100644
--- a/plugins/Login/templates/passwordsent.tpl
+++ b/plugins/Login/templates/passwordsent.tpl
@@ -13,7 +13,7 @@
{/if}
<p id="nav">
-<a href="index.php?module=Login&amp;form_url={$urlToRedirect|escape:url}" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
+<a href="index.php?module=Login" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
</p>
</div>
diff --git a/plugins/Login/templates/resetPassword.tpl b/plugins/Login/templates/resetPassword.tpl
index 2bb77b4ae9..49644b21b4 100644
--- a/plugins/Login/templates/resetPassword.tpl
+++ b/plugins/Login/templates/resetPassword.tpl
@@ -35,14 +35,13 @@
<input type="text" name="form_token" id="form_token" class="input" value="{$form_data.form_token.value}" size="20" tabindex="40" /></label>
</p>
- {$form_data.form_url.html}
<p class="submit">
<input type="submit" value="{'Login_ChangePassword'|translate}" tabindex="100" />
</p>
</form>
<p id="nav">
-<a href="index.php?module=Login&amp;action=lostPassword&amp;form_url={$urlToRedirect|escape:url}" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a>
+<a href="index.php?module=Login&amp;action=lostPassword" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a>
</p>
</div>
diff --git a/plugins/MultiSites/Controller.php b/plugins/MultiSites/Controller.php
new file mode 100644
index 0000000000..1d7b0a8280
--- /dev/null
+++ b/plugins/MultiSites/Controller.php
@@ -0,0 +1,195 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik_Plugins
+ * @package Piwik_MultiSites
+ */
+
+/**
+ *
+ * @package Piwik_MultiSites
+ */
+class Piwik_MultiSites_Controller extends Piwik_Controller
+{
+ protected $orderBy = 'names';
+ protected $order = 'desc';
+ protected $evolutionBy = 'visits';
+ protected $mySites = array();
+ protected $page = 1;
+ protected $limit = 20;
+ protected $period;
+ protected $date;
+ protected $dateToStr;
+
+
+ function index()
+ {
+ $this->getSitesInfo();
+ }
+
+
+ public function getSitesInfo()
+ {
+ Piwik::checkUserHasSomeViewAccess();
+ // overwrites the default Date set in the parent controller
+ // Instead of the default current website's local date,
+ // we set "today" or "yesterday" based on the default Piwik timezone
+ $piwikDefaultTimezone = Piwik_SitesManager_API::getInstance()->getDefaultTimezone();
+ $date = Piwik_Common::getRequestVar('date', 'today');
+ $date = $this->getDateParameterInTimezone($date, $piwikDefaultTimezone);
+ $this->setDate($date);
+
+ $mySites = Piwik_SitesManager_API::getInstance()->getSitesWithAtLeastViewAccess();
+ $params = $this->getGraphParamsModified();
+ $this->dateToStr = $params['date'];
+
+ $ids = 'all';
+ $this->period = Piwik_Common::getRequestVar('period', 'day');
+
+ $lastDate = date('Y-m-d',strtotime("-1 ".$this->period, strtotime($this->strDate)));
+
+ $visits = Piwik_VisitsSummary_API::getInstance()->getVisits($ids, $this->period, $this->strDate);
+ $lastVisits = Piwik_VisitsSummary_API::getInstance()->getVisits($ids, $this->period, $lastDate);
+
+ $actions = Piwik_VisitsSummary_API::getInstance()->getActions($ids, $this->period, $this->strDate);
+ $lastActions = Piwik_VisitsSummary_API::getInstance()->getActions($ids, $this->period, $lastDate);
+
+ $uniqueUsers = Piwik_VisitsSummary_API::getInstance()->getUniqueVisitors($ids, $this->period, $this->strDate);
+ $lastUniqueUsers = Piwik_VisitsSummary_API::getInstance()->getUniqueVisitors($ids, $this->period, $lastDate);
+
+ $visitsSummary = $this->getSummary($lastVisits, $visits, $mySites, "visits");
+ $actionsSummary = $this->getSummary($lastActions, $actions, $mySites, "actions");
+ $uniqueSummary = $this->getSummary($lastUniqueUsers, $uniqueUsers, $mySites, "unique");
+
+ $visitsArray = $visits->getArray();
+ $actionsArray = $actions->getArray();
+ $uniqueUsersArray = $uniqueUsers->getArray();
+ $lastVisitsArray = $lastVisits->getArray();
+ $lastActionsArray = $lastActions->getArray();
+ $lastUniqueUsersArray = $lastUniqueUsers->getArray();
+ foreach($mySites as &$site)
+ {
+ $idSite = $site['idsite'];
+ $site['visits'] = array_shift($visitsArray[$idSite]->getColumn(0));
+ $site['actions'] = array_shift($actionsArray[$idSite]->getColumn(0));
+ $site['unique'] = array_shift($uniqueUsersArray[$idSite]->getColumn(0));
+ $site['lastVisits'] = array_shift($lastVisitsArray[$idSite]->getColumn(0));
+ $site['lastActions'] = array_shift($lastActionsArray[$idSite]->getColumn(0));
+ $site['lastUnique'] = array_shift($lastUniqueUsersArray[$idSite]->getColumn(0));
+ $site['visitsSummaryValue'] = $visitsSummary[$idSite];
+ $site['actionsSummaryValue'] = $actionsSummary[$idSite];
+ $site['uniqueSummaryValue'] = $uniqueSummary[$idSite];
+
+ }
+
+ $view = new Piwik_View("MultiSites/templates/index.tpl");
+ $view->mySites = $mySites;
+ $view->evolutionBy = $this->evolutionBy;
+ $view->period = $this->period;
+ $view->date = $this->strDate;
+ $view->page = $this->page;
+ $view->limit = $this->limit;
+ $view->orderBy = $this->orderBy;
+ $view->order = $this->order;
+ $view->dateToStr = $this->dateToStr;
+
+ $view->autoRefreshTodayReport = false;
+ // if the current date is today, or yesterday,
+ // in case the website is set to UTC-12), or today in UTC+14, we refresh the page every 5min
+ if(in_array($this->strDate, array( 'today', date('Y-m-d'),
+ 'yesterday', Piwik_Date::factory('yesterday')->toString('Y-m-d'),
+ Piwik_Date::factory('now', 'UTC+14')->toString('Y-m-d'))))
+ {
+ $view->autoRefreshTodayReport = true;
+ }
+ $this->setGeneralVariablesView($view);
+ $this->setMinMaxDateAcrossWebsites($mySites, $view);
+
+ echo $view->render();
+ }
+
+ /**
+ * The Multisites reports displays the first calendar date as the earliest day available for all websites.
+ * Also, today is the later "today" available across all timezones.
+ * @param $mySites
+ * @param $view
+ * @return void
+ */
+ private function setMinMaxDateAcrossWebsites($mySites, $view)
+ {
+ $minDate = null;
+ $maxDate = Piwik_Date::now();
+ foreach($mySites as &$site)
+ {
+ // look for 'now' in the website's timezone
+ $timezone = $site['timezone'];
+ $date = Piwik_Date::factory('now', $timezone);
+ if($date->isLater($maxDate))
+ {
+ $maxDate = clone $date;
+ }
+
+ // look for the absolute minimum date
+ $creationDate = $site['ts_created'];
+ $date = Piwik_Date::factory($creationDate, $timezone);
+ if(is_null($minDate)
+ || $date->isEarlier($minDate))
+ {
+ $minDate = clone $date;
+ }
+ }
+ $this->setMinDateView($minDate, $view);
+ $this->setMaxDateView($maxDate, $view);
+ }
+
+ private function getSummary($lastVisits, $currentVisits, $mySites, $type)
+ {
+ $currentVisitsArray = $currentVisits->getArray();
+ $lastVisitsArray = $lastVisits->getArray();
+ $summaryArray = array();
+ foreach($mySites as $site)
+ {
+ $idSite = $site['idsite'];
+ $current = array_shift($currentVisitsArray[$idSite]->getColumn(0));
+ $last = array_shift($lastVisitsArray[$idSite]->getColumn(0));
+ $summaryArray[$idSite] = $this->fillSummary($current, $last, $this->evolutionBy);
+ }
+ return $summaryArray;
+ }
+
+ private function fillSummary($current, $last, $type)
+ {
+ if($current == 0 && $last == 0)
+ {
+ $summary = 0;
+ }
+ elseif($last == 0)
+ {
+ $summary = 100;
+ }
+ else
+ {
+ $summary = (($current - $last) / $last) * 100;
+ }
+
+ $output = round($summary,2);
+
+ return $output;
+ }
+
+ public function getEvolutionGraph( $fetch = false, $columns = false)
+ {
+ $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, "VisitsSummary.get");
+ if(empty($columns))
+ {
+ $columns = Piwik_Common::getRequestVar('columns');
+ }
+ $view->setColumnsToDisplay($columns);
+ return $this->renderView($view, $fetch);
+ }
+}
diff --git a/plugins/MultiSites/MultiSites.php b/plugins/MultiSites/MultiSites.php
new file mode 100644
index 0000000000..ccdc2169b6
--- /dev/null
+++ b/plugins/MultiSites/MultiSites.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik_Plugins
+ * @package Piwik_MultiSites
+ */
+
+/**
+ *
+ * @package Piwik_MultiSites
+ */
+class Piwik_MultiSites extends Piwik_Plugin
+{
+ public function getInformation()
+ {
+ return array(
+ 'description' => Piwik_Translate('MultiSites_PluginDescription'),
+ 'author' => 'ClearCode.cc',
+ 'author_homepage' => "http://clearcode.cc/",
+ 'version' => Piwik_Version::VERSION,
+ );
+ }
+
+ public function getListHooksRegistered()
+ {
+ return array(
+ 'template_css_import' => 'css',
+ 'template_js_import' => 'js',
+ );
+ }
+
+ public function css()
+ {
+ echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"plugins/MultiSites/templates/styles.css\" />\n";
+ }
+
+ public function js()
+ {
+ echo "<script type=\"text/javascript\" src=\"plugins/MultiSites/templates/common.js\"></script>\n";
+ }
+}
diff --git a/plugins/MultiSites/images/arrow_asc.gif b/plugins/MultiSites/images/arrow_asc.gif
new file mode 100644
index 0000000000..df463fa72f
--- /dev/null
+++ b/plugins/MultiSites/images/arrow_asc.gif
Binary files differ
diff --git a/plugins/MultiSites/images/arrow_desc.gif b/plugins/MultiSites/images/arrow_desc.gif
new file mode 100644
index 0000000000..abe79f0769
--- /dev/null
+++ b/plugins/MultiSites/images/arrow_desc.gif
Binary files differ
diff --git a/plugins/MultiSites/images/arrow_down.png b/plugins/MultiSites/images/arrow_down.png
new file mode 100644
index 0000000000..efa4624a05
--- /dev/null
+++ b/plugins/MultiSites/images/arrow_down.png
Binary files differ
diff --git a/plugins/MultiSites/images/arrow_up.png b/plugins/MultiSites/images/arrow_up.png
new file mode 100644
index 0000000000..800536e52e
--- /dev/null
+++ b/plugins/MultiSites/images/arrow_up.png
Binary files differ
diff --git a/plugins/MultiSites/images/door_in.png b/plugins/MultiSites/images/door_in.png
new file mode 100644
index 0000000000..41676a0a5b
--- /dev/null
+++ b/plugins/MultiSites/images/door_in.png
Binary files differ
diff --git a/plugins/MultiSites/images/link.gif b/plugins/MultiSites/images/link.gif
new file mode 100644
index 0000000000..e160f23b63
--- /dev/null
+++ b/plugins/MultiSites/images/link.gif
Binary files differ
diff --git a/plugins/MultiSites/images/loading-blue.gif b/plugins/MultiSites/images/loading-blue.gif
new file mode 100644
index 0000000000..8a3f8c01b6
--- /dev/null
+++ b/plugins/MultiSites/images/loading-blue.gif
Binary files differ
diff --git a/plugins/MultiSites/images/stop.png b/plugins/MultiSites/images/stop.png
new file mode 100644
index 0000000000..84d56a4532
--- /dev/null
+++ b/plugins/MultiSites/images/stop.png
Binary files differ
diff --git a/plugins/MultiSites/templates/common.js b/plugins/MultiSites/templates/common.js
new file mode 100644
index 0000000000..2fc8dc86f0
--- /dev/null
+++ b/plugins/MultiSites/templates/common.js
@@ -0,0 +1,245 @@
+function setRowData (idsite, visits, actions, unique, name, url, visitsSummaryValue, actionsSummaryValue, uniqueSummaryValue)
+{
+ this.idsite = idsite;
+ this.visits = visits;
+ this.unique = unique;
+ this.name = name;
+ this.url = url;
+ this.actions = actions;
+ this.visitsSummaryValue = parseFloat(visitsSummaryValue);
+ this.actionsSummaryValue = parseFloat(actionsSummaryValue);
+ this.uniqueSummaryValue = parseFloat(uniqueSummaryValue);
+}
+
+function setOrderBy(self, allSites, params, mOrderBy)
+{
+ if(params['mOrderBy'] == mOrderBy) {
+ if(params['order'] == 'desc') {
+ params['order'] = 'asc';
+ }
+ else {
+ params['order'] = 'desc';
+ }
+ }
+ params['mOrderBy'] = mOrderBy;
+ prepareRows(allSites, params);
+
+ $('.arrow').removeClass('multisites_desc multisites_asc');
+ if($(self).attr('class') == 'evolution')
+ {
+ mOrderBy = 'evolution';
+ }
+ $('#' + mOrderBy + ' .arrow').addClass('multisites_' + params['order']);
+
+ return params;
+}
+
+function prepareRows(allUnsortedSites, params)
+{
+ var allSites;
+ $("#tb").find("tr").remove();
+ $("#next").html('');
+ $("#prev").html('');
+ var mOrderBy = params['mOrderBy'];
+
+ allSites = orderBy(allUnsortedSites, params);
+
+ if(allSites.length > params['limit'])
+ {
+ allSites = limitBy(allSites, params);
+ }
+
+
+ displayRows(allSites, params);
+
+ showPagination(allUnsortedSites, params);
+ params['sitesVisible'] = allSites;
+}
+
+function orderBy(allSites, params)
+{
+ if(params['mOrderBy'] == 'names')
+ {
+ allSites.sort(function(a,b) {
+ if (a['name'].toLowerCase() == b['name'].toLowerCase())
+ {
+ return 0;
+ }
+ return (a['name'].toLowerCase() < b['name'].toLowerCase()) ? -1 : 1;
+ });
+ }
+ else if(params['mOrderBy'] == 'visits')
+ {
+ allSites.sort(function(a,b) {
+ if (a['visits'] == b['visits']) {
+ return 0;
+ }
+ return (a['visits'] < b['visits']) ? -1 : 1;
+ });
+ }
+ else if(params['mOrderBy'] == 'actions')
+ {
+ allSites.sort(function (a,b) {
+ if (a['actions'] == b['actions']) {
+ return 0;
+ }
+ return (a['actions'] < b['actions']) ? -1 : 1;
+ });
+ }
+ else if(params['mOrderBy'] == 'unique')
+ {
+ allSites.sort(function (a,b) {
+ if (a['unique'] == b['unique']) {
+ return 0;
+ }
+ return (a['unique'] < b['unique']) ? -1 : 1;
+ });
+ }
+ else if(params['mOrderBy'] == 'uniqueSummary')
+ {
+ allSites.sort(function (a,b) {
+ if (a['uniqueSummaryValue'] == b['uniqueSummaryValue']) {
+ return 0;
+ }
+ return (a['uniqueSummaryValue'] - b['uniqueSummaryValue'] <= 0.01) ? -1 : 1;
+ });
+ }
+ else if(params['mOrderBy'] == 'actionsSummary')
+ {
+ allSites.sort(function (a,b) {
+ if (a['actionsSummaryValue'] == b['actionsSummaryValue']) {
+ return 0;
+ }
+ return (a['actionsSummaryValue'] - b['actionsSummaryValue'] <= 0.01) ? -1 : 1;
+ });
+ }
+ else if(params['mOrderBy'] == 'visitsSummary')
+ {
+ allSites.sort(function (a,b) {
+ if (a['visitsSummaryValue'] == b['visitsSummaryValue']) {
+ return 0;
+ }
+ return (a['visitsSummaryValue'] - b['visitsSummaryValue'] <= 0.01) ? -1 : 1;
+ });
+ }
+
+ if(params['order'] == 'asc')
+ {
+ allSites.reverse();
+ }
+ return allSites;
+}
+
+function limitBy(allSites, params)
+{
+ var begin = (params['page'] - 1) * params['limit'];
+ var end = (params['page'] * params['limit']);
+ return allSites.slice(begin, end);
+}
+
+function switchEvolution(params)
+{
+ $('.actions').hide();
+ $('.unique').hide();
+ $('.visits').hide();
+ $('.' + params['evolutionBy']).show();
+ sitesVisible = params['sitesVisible'];
+ for(i = 0; i < allSites.length; i++)
+ {
+ $('#sparkline_' + allSites[i].idsite).html(getSparklineImg(allSites[i].idsite, params['evolutionBy'], params));
+ }
+}
+
+function displayRows(allSites, params)
+{
+ for(var i = 0; i < allSites.length; i++)
+ {
+ var str = params['row'];
+ str = str.replace(/%uniqueSummary%/g, getImageForSummary(allSites[i].uniqueSummaryValue));
+ str = str.replace(/%actionsSummary%/g, getImageForSummary(allSites[i].actionsSummaryValue));
+ str = str.replace(/%visitsSummary%/g, getImageForSummary(allSites[i].visitsSummaryValue));
+ str = str.replace(/%sparkline%/g, getSparklineImg(allSites[i].idsite, params['evolutionBy'], params));
+ str = str.replace(/%actions%/g, allSites[i].actions);
+ str = str.replace(/%idsite%/g, allSites[i].idsite);
+ str = str.replace(/%visits%/g, allSites[i].visits);
+ str = str.replace(/%name%/g, allSites[i].name);
+ str = str.replace(/%unique%/g, allSites[i].unique);
+ str = str.replace(/%main_url%/g, allSites[i].url);
+ str = str.replace(/%date%/g, params['date']);
+ str = str.replace(/%period%/g, params['period']);
+
+ $('#tb').append('<tr class="tables_row" id="row_'+ allSites[i].idsite+'">' + str + '</tr>');
+ }
+
+ $(".table_row").show();
+ $('.actions').hide();
+ $('.unique').hide();
+ $('.visits').hide();
+ $('#main_indicator').hide();
+ $('.' + params['evolutionBy']).show();
+ $("#main_indicator").hide();
+}
+
+function getSparklineImg(id, column, params)
+{
+ if(column == 'unique')
+ {
+ column = 'uniq_visitors';
+ }
+ return '<img class="sparkline" alt="" src="?module=MultiSites&action=getEvolutionGraph&period=' + params['period'] + '&date=' + params['dateToStr'] + '&evolutionBy=' + params['evolutionBy'] + '&columns[]=nb_' + column + '&idSite=' + id + '&idsite=' + id + '&viewDataTable=sparkline" width="100" height="25" />';
+}
+
+
+
+function showPagination(allSites, params)
+{
+ if ((params['page'] * params['limit']) < allSites.length)
+ {
+ var html = '<span style="cursor:pointer;" class="pointer" onClick="changePage(allSites, params, \'next\');">' + params['next'] + ' &#187;</span>';
+ $("#next").html(html);
+ }
+ if(params['page'] > 1)
+ {
+ html = '<span style="cursor:pointer;" onClick="changePage(allSites, params, \'prev\');">&#171; ' + params['prev'] + '</span>'
+ $("#prev").html(html);
+ }
+ var start = (params['page'] - 1) * params['limit'] + 1;
+ var count = allSites.length;
+ var end = parseInt(start) + parseInt(params['limit']) - 1;
+ if(end > count) end = count;
+ html = '<span>' + (start ) + ' - ' + end + ' of ' + count + '</span>';
+ $("#counter").html(html);
+}
+
+function changePage(allSites, params, kind)
+{
+ if(kind == 'next')
+ {
+ params['page']++;
+ }
+ else
+ {
+ params['page']--;
+ }
+ prepareRows(allSites, params);
+ return params;
+}
+
+
+function getImageForSummary(value)
+{
+ if(value > 0)
+ {
+ return '<img src="plugins/MultiSites/images/arrow_up.png" alt="" /> <b style="color: green;">' + value + ' %</b>';
+ }
+ else if(value == 0)
+ {
+ return '<img src="plugins/MultiSites/images/stop.png" alt="" /> <b>' + value + '%</b>';
+ }
+ else
+ {
+ return '<img src="plugins/MultiSites/images/arrow_down.png" alt="" /> <b style="color: red;">' + value +' %</b>';
+ }
+}
+
+
diff --git a/plugins/MultiSites/templates/index.tpl b/plugins/MultiSites/templates/index.tpl
new file mode 100644
index 0000000000..d4aa6e0097
--- /dev/null
+++ b/plugins/MultiSites/templates/index.tpl
@@ -0,0 +1,99 @@
+<img src="plugins/MultiSites/images/arrow_desc.gif" style="display: none" />
+<img src="plugins/MultiSites/images/arrow_asc.gif" style="display: none" />
+{assign var=showSitesSelection value=false}
+{assign var=showPeriodSelection value=true}
+{include file="CoreHome/templates/header.tpl"}
+
+<script type="text/javascript" src="plugins/MultiSites/templates/common.js"></script>
+<style>
+{fetch file="plugins/MultiSites/templates/styles.css"}
+</style>
+
+<div id="multisites" style="margin: auto">
+<div id="main">
+{include file="MultiSites/templates/row.tpl" assign="row"}
+<script type="text/javascript">
+ var allSites = new Array();
+ var params = new Array();
+ {foreach from=$mySites key=i item=site}
+ allSites[{$i}] = new setRowData({$site.idsite}, {$site.visits}, {$site.actions}, {$site.unique}, '{$site.name|escape:"quotes"}', '{$site.main_url}', '{$site.visitsSummaryValue|replace:",":"."}', '{$site.actionsSummaryValue|replace:",":"."}', '{$site.uniqueSummaryValue|replace:",":"."}');
+ {/foreach}
+ params['period'] = '{$period}';
+ params['date'] = '{$date}';
+ params['dateToStr'] = '{$dateToStr}';
+ params['evolutionBy'] = '{$evolutionBy}';
+ params['mOrderBy'] = '{$orderBy}';
+ params['order'] = '{$order}';
+ params['site'] = '{$site}';
+ params['limit'] = '{$limit}';
+ params['page'] = 1;
+ params['prev'] = "{'General_Previous'|translate}";
+ params['next'] = "{'General_Next'|translate}";
+ params['row'] = '{$row|escape:"javascript"}';
+</script>
+
+{postEvent name="template_headerMultiSites"}
+<div align="center">
+<table id="mt" class="dataTable" cellspacing="0" style="width:850px;">
+ <thead>
+ <th id="names" class="label" style="text-align:center">
+ <span style="cursor:pointer;" onClick="params = setOrderBy(this,allSites, params, 'names');">{'General_Website'|translate}</span>
+ <span class="arrow multisites_desc"></span>
+ </th>
+ <th id="visits" class="multisites-column" style="width: 100px">
+ <span style="cursor:pointer;" onClick="params = setOrderBy(this,allSites, params, 'visits');">{'General_ColumnNbVisits'|translate}</span>
+ <span class="arrow"></span>
+ </th>
+ <th id="actions" class="multisites-column" style="width: 110px">
+ <span style="cursor:pointer;" onClick="params = setOrderBy(this,allSites, params, 'actions');">{'General_ColumnPageviews'|translate}</span>
+ <span class="arrow"></span>
+ </th>
+ <th id="unique" class="multisites-column" style="width: 120px">
+ <span style="cursor:pointer;" onClick="params = setOrderBy(this,allSites, params, 'unique');">{'General_ColumnNbUniqVisitors'|translate}</span>
+ <span class="arrow"></span>
+ </th>
+ <th id="evolution" style="text-align:center; width:350px" colspan="2">
+ <span class="arrow "></span>
+ <span class="evolution" style="cursor:pointer;" onClick="params = setOrderBy(this,allSites, params, $('#evolution_selector').val() + 'Summary');"> {'MultiSites_Evolution'|translate}</span>
+ <select class="selector" id="evolution_selector" onchange="params['evolutionBy'] = $('#evolution_selector').val(); switchEvolution(params);">
+ <option value="visits" {if $evolutionBy eq 'visits'} selected {/if}>{'General_ColumnNbVisits'|translate}</option>
+ <option value="actions" {if $evolutionBy eq 'actions'} selected {/if}>{'General_ColumnPageviews'|translate}</option>
+ <option value="unique"{if $evolutionBy eq 'unique'} selected {/if}>{'General_ColumnNbUniqVisitors'|translate}</option>
+ </select>
+ </th>
+ </thead>
+
+ <tbody id="tb">
+ </tbody>
+
+ <tfoot>
+ <tr row_id="last" >
+ <td colspan="8" class="clean" style="padding: 20px">
+ <span id="prev" class="pager" style="padding-right: 20px;"></span>
+ <span id="dataTablePages">
+ <span id="counter">
+ </span>
+ </span>
+ <span id="next" class="clean" style="padding-left: 20px;"></span>
+ </td>
+ </tr>
+ </tfoot>
+</table>
+</div>
+<script type="text/javascript">
+prepareRows(allSites, params, '{$orderBy}');
+
+{if $autoRefreshTodayReport}
+{literal}
+function refreshAfter(timeoutPeriod) {
+ setTimeout("location.reload(true);",timeoutPeriod);
+}
+refreshAfter(5*60*1000);
+{/literal}
+{/if}
+</script>
+</div>
+</div>
+
+</body>
+</html>
diff --git a/plugins/MultiSites/templates/row.tpl b/plugins/MultiSites/templates/row.tpl
new file mode 100644
index 0000000000..c651eaed5b
--- /dev/null
+++ b/plugins/MultiSites/templates/row.tpl
@@ -0,0 +1,26 @@
+<td class="multisites-label label" >
+ <a title="View reports" href="index.php?module=CoreHome&action=index&date=%date%&period=%period%&idSite=%idsite%">%name%</a>
+
+ <span style="width: 10px; margin-left:3px">
+ <a target="_blank" title="{'General_GoTo'|translate:"%main_url%"}" href="%main_url%"><img src="plugins/MultiSites/images/link.gif" /></a>
+ </span>
+</td>
+<td class="multisites-column">
+ %visits%
+</td>
+<td class="multisites-column">
+ %actions%&nbsp;
+</td>
+<td class="multisites-column">
+ %unique%&nbsp;
+</td>
+<td style="width:170px">
+ <div class="visits" style="display:none">%visitsSummary%</div>
+ <div class="actions"style="display:none">%actionsSummary%</div>
+ <div class="unique" >%uniqueSummary%</div>
+</td>
+<td style="width:180px">
+ <div id="sparkline_%idsite%" style="width: 100px; margin: auto">
+ %sparkline%
+ </div
+</td>
diff --git a/plugins/MultiSites/templates/styles.css b/plugins/MultiSites/templates/styles.css
new file mode 100644
index 0000000000..5c8204d9d0
--- /dev/null
+++ b/plugins/MultiSites/templates/styles.css
@@ -0,0 +1,46 @@
+.indicator {
+ background-image: url("../images/loading-blue.gif");
+ background-position: center;
+ background-repeat: no-repeat;
+ height: 20px;
+ width: 60px;
+ margin: auto;
+ border: 0px !important;
+}
+.clean {
+ border: 0px !important;
+}
+#multisites td, #multisites tr, #multisites .sparkline {
+ text-align: center;
+ vertical-align: middle;
+ padding: 1px ;
+ margin: 0px ;
+}
+#multisites td.multisites-label {
+ padding-left: 15px ;
+ text-align:left;
+ width: 250px;
+}
+#multisites td.multisites-label a:hover {
+ text-decoration: underline;
+}
+#multisites td.multisites-column, #multisites th.multisites-column {
+ width:70px;
+}
+#multisites td.multisites-column-evolution, #multisites th.multisites-column-evolution {
+ width:70px;
+}
+.multisites_asc
+{
+ width: 10px;
+ height: 12px;
+ display: inline-block;
+ background-image: url('plugins/MultiSites/images/arrow_asc.gif');
+}
+.multisites_desc
+{
+ width: 10px;
+ height: 13px;
+ display: inline-block;
+ background-image: url('plugins/MultiSites/images/arrow_desc.gif');
+} \ No newline at end of file
diff --git a/plugins/Provider/API.php b/plugins/Provider/API.php
index 9f29baba58..272925dded 100644
--- a/plugins/Provider/API.php
+++ b/plugins/Provider/API.php
@@ -10,9 +10,6 @@
* @package Piwik_Provider
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see plugins/Provider/functions.php
*/
@@ -45,6 +42,7 @@ class Piwik_Provider_API
$dataTable->queueFilter('ColumnCallbackAddMetadata', array('label', 'url', 'Piwik_getHostnameUrl'));
$dataTable->queueFilter('ColumnCallbackReplace', array('label', 'Piwik_getHostnameName'));
$dataTable->queueFilter('ReplaceColumnNames');
+ $dataTable->queueFilter('ReplaceSummaryRowLabel');
return $dataTable;
}
}
diff --git a/plugins/Provider/Provider.php b/plugins/Provider/Provider.php
index a547846fc8..aec31c9f51 100644
--- a/plugins/Provider/Provider.php
+++ b/plugins/Provider/Provider.php
@@ -19,11 +19,10 @@ class Piwik_Provider extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Provider',
- 'description' => 'Reports the Provider of the visitors.',
+ 'description' => Piwik_Translate('Provider_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
'TrackerPlugin' => true, // this plugin must be loaded during the stats logging
);
@@ -45,19 +44,25 @@ class Piwik_Provider extends Piwik_Plugin
function install()
{
// add column hostname / hostname ext in the visit table
- $query = "ALTER IGNORE TABLE `".Piwik::prefixTable('log_visit')."` ADD `location_provider` VARCHAR( 100 ) NULL";
+ $query = "ALTER IGNORE TABLE `".Piwik_Common::prefixTable('log_visit')."` ADD `location_provider` VARCHAR( 100 ) NULL";
// if the column already exist do not throw error. Could be installed twice...
try {
Piwik_Exec($query);
}
- catch(Exception $e){}
+ catch(Exception $e) {
+ if(!Zend_Registry::get('db')->isErrNo($e, '1060'))
+ {
+ throw $e;
+ }
+ }
+
}
function uninstall()
{
// add column hostname / hostname ext in the visit table
- $query = "ALTER TABLE `".Piwik::prefixTable('log_visit')."` DROP `location_provider`";
+ $query = "ALTER TABLE `".Piwik_Common::prefixTable('log_visit')."` DROP `location_provider`";
Piwik_Exec($query);
}
@@ -80,9 +85,10 @@ class Piwik_Provider extends Piwik_Plugin
function archivePeriod( $notification )
{
+ $maximumRowsInDataTable = Zend_Registry::get('config')->General->datatable_archiving_maximum_rows_standard;
$archiveProcessing = $notification->getNotificationObject();
$dataTableToSum = array( 'Provider_hostnameExt' );
- $archiveProcessing->archiveDataTable($dataTableToSum);
+ $archiveProcessing->archiveDataTable($dataTableToSum, null, $maximumRowsInDataTable);
}
/**
@@ -96,7 +102,9 @@ class Piwik_Provider extends Piwik_Plugin
$labelSQL = "location_provider";
$interestByProvider = $archiveProcessing->getArrayInterestForLabel($labelSQL);
$tableProvider = $archiveProcessing->getDataTableFromArray($interestByProvider);
- $archiveProcessing->insertBlobRecord($recordName, $tableProvider->getSerialized());
+ $columnToSortByBeforeTruncation = Piwik_Archive::INDEX_NB_VISITS;
+ $maximumRowsInDataTable = Zend_Registry::get('config')->General->datatable_archiving_maximum_rows_standard;
+ $archiveProcessing->insertBlobRecord($recordName, $tableProvider->getSerialized($maximumRowsInDataTable, null, $columnToSortByBeforeTruncation));
destroy($tableProvider);
}
@@ -145,6 +153,13 @@ class Piwik_Provider extends Piwik_Plugin
}
else
{
+ $cleanHostname = null;
+ Piwik_PostEvent('Provider.getCleanHostname', $cleanHostname, $hostname);
+ if($cleanHostname !== null)
+ {
+ return $cleanHostname;
+ }
+
$e = explode('.', $hostname);
$s = sizeof($e);
@@ -173,13 +188,13 @@ class Piwik_Provider extends Piwik_Plugin
return trim(strtolower(@gethostbyaddr(long2ip($ip))));
}
- public function headerUserCountry($notification)
+ static public function headerUserCountry($notification)
{
$out =& $notification->getNotificationObject();
$out = '<div id="leftcolumn">';
}
- public function footerUserCountry($notification)
+ static public function footerUserCountry($notification)
{
$out =& $notification->getNotificationObject();
$out = '</div>
diff --git a/plugins/Provider/functions.php b/plugins/Provider/functions.php
index 4397c40867..7966fe64aa 100644
--- a/plugins/Provider/functions.php
+++ b/plugins/Provider/functions.php
@@ -20,7 +20,7 @@ function Piwik_getHostnameName($in)
{
if(empty($in))
{
- return Piwik_Translate('General_Unknown');
+ return html_entity_decode(Piwik_Translate('General_Unknown'), ENT_COMPAT, 'UTF-8');
}
if(strtolower($in) === 'ip')
{
@@ -41,6 +41,10 @@ function Piwik_getHostnameName($in)
*/
function Piwik_getHostnameUrl($in)
{
+ if($in == Piwik_DataTable::LABEL_SUMMARY_ROW)
+ {
+ return false;
+ }
if(empty($in)
|| strtolower($in) === 'ip')
{
diff --git a/plugins/Referers/API.php b/plugins/Referers/API.php
index decd1cbd2f..8153a148cb 100644
--- a/plugins/Referers/API.php
+++ b/plugins/Referers/API.php
@@ -10,9 +10,6 @@
* @package Piwik_Referers
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see plugins/Referers/functions.php
*/
@@ -57,7 +54,7 @@ class Piwik_Referers_API
return $dataTable;
}
- function getRefererType($idSite, $period, $date, $typeReferer = false)
+ public function getRefererType($idSite, $period, $date, $typeReferer = false)
{
$dataTable = $this->getDataTable('Referers_type', $idSite, $period, $date, $expanded = false);
if($typeReferer !== false)
@@ -68,13 +65,13 @@ class Piwik_Referers_API
return $dataTable;
}
- function getKeywords($idSite, $period, $date, $expanded = false)
+ public function getKeywords($idSite, $period, $date, $expanded = false)
{
$dataTable = $this->getDataTable('Referers_searchEngineByKeyword', $idSite, $period, $date, $expanded);
return $dataTable;
}
- function getSearchEnginesFromKeywordId($idSite, $period, $date, $idSubtable)
+ public function getSearchEnginesFromKeywordId($idSite, $period, $date, $idSubtable)
{
$dataTable = $this->getDataTable('Referers_searchEngineByKeyword',$idSite, $period, $date, $expanded = false, $idSubtable);
$dataTable->queueFilter('ColumnCallbackAddMetadata', array( 'label', 'url', 'Piwik_getSearchEngineUrlFromName') );
@@ -87,7 +84,7 @@ class Piwik_Referers_API
return $dataTable;
}
- function getSearchEngines($idSite, $period, $date, $expanded = false)
+ public function getSearchEngines($idSite, $period, $date, $expanded = false)
{
$dataTable = $this->getDataTable('Referers_keywordBySearchEngine',$idSite, $period, $date, $expanded);
$dataTable->queueFilter('ColumnCallbackAddMetadata', array( 'label', 'url', 'Piwik_getSearchEngineUrlFromName') );
@@ -95,7 +92,7 @@ class Piwik_Referers_API
return $dataTable;
}
- function getKeywordsFromSearchEngineId($idSite, $period, $date, $idSubtable)
+ public function getKeywordsFromSearchEngineId($idSite, $period, $date, $idSubtable)
{
$dataTable = $this->getDataTable('Referers_keywordBySearchEngine',$idSite, $period, $date, $expanded = false, $idSubtable);
@@ -107,25 +104,25 @@ class Piwik_Referers_API
return $dataTable;
}
- function getCampaigns($idSite, $period, $date, $expanded = false)
+ public function getCampaigns($idSite, $period, $date, $expanded = false)
{
$dataTable = $this->getDataTable('Referers_keywordByCampaign',$idSite, $period, $date, $expanded);
return $dataTable;
}
- function getKeywordsFromCampaignId($idSite, $period, $date, $idSubtable)
+ public function getKeywordsFromCampaignId($idSite, $period, $date, $idSubtable)
{
$dataTable = $this->getDataTable('Referers_keywordByCampaign',$idSite, $period, $date, $expanded = false, $idSubtable);
return $dataTable;
}
- function getWebsites($idSite, $period, $date, $expanded = false)
+ public function getWebsites($idSite, $period, $date, $expanded = false)
{
$dataTable = $this->getDataTable('Referers_urlByWebsite',$idSite, $period, $date, $expanded);
return $dataTable;
}
- function getUrlsFromWebsiteId($idSite, $period, $date, $idSubtable)
+ public function getUrlsFromWebsiteId($idSite, $period, $date, $idSubtable)
{
$dataTable = $this->getDataTable('Referers_urlByWebsite',$idSite, $period, $date, $expanded = false, $idSubtable);
$dataTable->queueFilter('ColumnCallbackAddMetadata', array( 'label', 'url', create_function('$label', 'return $label;')) );
@@ -133,27 +130,27 @@ class Piwik_Referers_API
return $dataTable;
}
- function getNumberOfDistinctSearchEngines($idSite, $period, $date)
+ public function getNumberOfDistinctSearchEngines($idSite, $period, $date)
{
return $this->getNumeric('Referers_distinctSearchEngines', $idSite, $period, $date);
}
- function getNumberOfDistinctKeywords($idSite, $period, $date)
+ public function getNumberOfDistinctKeywords($idSite, $period, $date)
{
return $this->getNumeric('Referers_distinctKeywords', $idSite, $period, $date);
}
- function getNumberOfDistinctCampaigns($idSite, $period, $date)
+ public function getNumberOfDistinctCampaigns($idSite, $period, $date)
{
return $this->getNumeric('Referers_distinctCampaigns', $idSite, $period, $date);
}
- function getNumberOfDistinctWebsites($idSite, $period, $date)
+ public function getNumberOfDistinctWebsites($idSite, $period, $date)
{
return $this->getNumeric('Referers_distinctWebsites', $idSite, $period, $date);
}
- function getNumberOfDistinctWebsitesUrls($idSite, $period, $date)
+ public function getNumberOfDistinctWebsitesUrls($idSite, $period, $date)
{
return $this->getNumeric('Referers_distinctWebsitesUrls', $idSite, $period, $date);
}
diff --git a/plugins/Referers/Controller.php b/plugins/Referers/Controller.php
index 658cc5ab8f..098ad12ad3 100644
--- a/plugins/Referers/Controller.php
+++ b/plugins/Referers/Controller.php
@@ -76,9 +76,9 @@ class Piwik_Referers_Controller extends Piwik_Controller
return $this->renderView($view, $fetch);
}
- function getKeywords( $fetch = false, $viewDataTable = null)
+ function getKeywords( $fetch = false)
{
- $view = Piwik_ViewDataTable::factory($viewDataTable);
+ $view = Piwik_ViewDataTable::factory();
$view->init( $this->pluginName, __FUNCTION__,
'Referers.getKeywords',
'getSearchEnginesFromKeywordId'
diff --git a/plugins/Referers/Referers.php b/plugins/Referers/Referers.php
index 3e305ba3d2..291971370c 100644
--- a/plugins/Referers/Referers.php
+++ b/plugins/Referers/Referers.php
@@ -23,11 +23,10 @@ class Piwik_Referers extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Referers',
- 'description' => 'Reports the Referers data: Search Engines, Keywords, Websites, Campaign Tracking, Direct Entry. ',
+ 'description' => Piwik_Translate('Referers_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
@@ -40,6 +39,7 @@ class Piwik_Referers extends Piwik_Plugin
'ArchiveProcessing_Period.compute' => 'archivePeriod',
'WidgetsList.add' => 'addWidgets',
'Menu.add' => 'addMenus',
+ 'Goals.getAvailableGoalSegments' => 'addGoalSegments',
);
return $hooks;
}
@@ -62,12 +62,49 @@ class Piwik_Referers extends Piwik_Plugin
function addMenus()
{
- Piwik_AddMenu('Referers_Referers', 'Referers_SubmenuEvolution', array('module' => 'Referers'));
+ Piwik_AddMenu('Referers_Referers', 'Referers_SubmenuEvolution', array('module' => 'Referers', 'action' => 'index'));
Piwik_AddMenu('Referers_Referers', 'Referers_SubmenuSearchEngines', array('module' => 'Referers', 'action' => 'getSearchEnginesAndKeywords'));
Piwik_AddMenu('Referers_Referers', 'Referers_SubmenuWebsites', array('module' => 'Referers', 'action' => 'getWebsites'));
Piwik_AddMenu('Referers_Referers', 'Referers_SubmenuCampaigns', array('module' => 'Referers', 'action' => 'getCampaigns'));
}
+ function addGoalSegments( $notification )
+ {
+ $segments =& $notification->getNotificationObject();
+ $segments = array_merge($segments, array(
+ array(
+ 'group' => Piwik_Translate('Referers_Referers'),
+ 'name' => Piwik_Translate('Referers_Keywords'),
+ 'module' => 'Referers',
+ 'action' => 'getKeywords',
+ ),
+ array(
+ 'group' => Piwik_Translate('Referers_Referers'),
+ 'name' => Piwik_Translate('Referers_SearchEngines'),
+ 'module' => 'Referers',
+ 'action' => 'getSearchEngines',
+ ),
+ array(
+ 'group' => Piwik_Translate('Referers_Referers'),
+ 'name' => Piwik_Translate('Referers_Websites'),
+ 'module' => 'Referers',
+ 'action' => 'getWebsites',
+ ),
+ array(
+ 'group' => Piwik_Translate('Referers_Referers'),
+ 'name' => Piwik_Translate('Referers_Campaigns'),
+ 'module' => 'Referers',
+ 'action' => 'getCampaigns',
+ ),
+ array(
+ 'group' => Piwik_Translate('Referers_Referers'),
+ 'name' => Piwik_Translate('Referers_Type'),
+ 'module' => 'Referers',
+ 'action' => 'getRefererType',
+ ),
+ ));
+ }
+
function archivePeriod( $notification )
{
$archiveProcessing = $notification->getNotificationObject();
@@ -150,7 +187,7 @@ class Piwik_Referers extends Piwik_Plugin
destroy($this->distinctUrls);
}
- protected function archiveDayAggregateVisits($archiveProcessing)
+ protected function archiveDayAggregateVisits(Piwik_ArchiveProcessing $archiveProcessing)
{
$query = "SELECT referer_type,
referer_name,
@@ -164,11 +201,12 @@ class Piwik_Referers extends Piwik_Plugin
sum(case visit_total_actions when 1 then 1 else 0 end) as bounce_count,
sum(case visit_goal_converted when 1 then 1 else 0 end) as nb_visits_converted
FROM ".$archiveProcessing->logTable."
- WHERE visit_server_date = ?
+ WHERE visit_last_action_time >= ?
+ AND visit_last_action_time <= ?
AND idsite = ?
GROUP BY referer_type, referer_name, referer_url, referer_keyword
ORDER BY nb_visits DESC";
- $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
+ $query = $archiveProcessing->db->query($query, array( $archiveProcessing->getStartDatetimeUTC(), $archiveProcessing->getEndDatetimeUTC(), $archiveProcessing->idsite ));
$this->interestBySearchEngine =
$this->interestByKeyword =
diff --git a/plugins/Referers/images/searchEngines/1.cz.png b/plugins/Referers/images/searchEngines/1.cz.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/1.cz.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/acont.de.png b/plugins/Referers/images/searchEngines/acont.de.png
deleted file mode 100644
index 5099e6163c..0000000000
--- a/plugins/Referers/images/searchEngines/acont.de.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/all.by.png b/plugins/Referers/images/searchEngines/all.by.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/all.by.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/apollo.lv.png b/plugins/Referers/images/searchEngines/apollo.lv.png
new file mode 100644
index 0000000000..9268827b64
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/apollo.lv.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/bg.setooz.com.png b/plugins/Referers/images/searchEngines/bg.setooz.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/bg.setooz.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/blogs.gigablast.com.png b/plugins/Referers/images/searchEngines/blogs.gigablast.com.png
new file mode 100644
index 0000000000..bcd8577d24
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/blogs.gigablast.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/blogs.seekport.de.png b/plugins/Referers/images/searchEngines/blogs.seekport.de.png
deleted file mode 100644
index d5da478ca6..0000000000
--- a/plugins/Referers/images/searchEngines/blogs.seekport.de.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/blogsearch.google.com.png b/plugins/Referers/images/searchEngines/blogsearch.google.com.png
index ac1b2d8b10..5e701b1d4e 100644
--- a/plugins/Referers/images/searchEngines/blogsearch.google.com.png
+++ b/plugins/Referers/images/searchEngines/blogsearch.google.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/cf.dir.yahoo.com.png b/plugins/Referers/images/searchEngines/cf.dir.yahoo.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/cf.dir.yahoo.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/class.hit-parade.com.png b/plugins/Referers/images/searchEngines/class.hit-parade.com.png
deleted file mode 100644
index 3525114470..0000000000
--- a/plugins/Referers/images/searchEngines/class.hit-parade.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/clusty.com.png b/plugins/Referers/images/searchEngines/clusty.com.png
new file mode 100644
index 0000000000..e34962d22d
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/clusty.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/data.quicksearches.net.png b/plugins/Referers/images/searchEngines/data.quicksearches.net.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/data.quicksearches.net.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/de.forestle.org.png b/plugins/Referers/images/searchEngines/de.forestle.org.png
new file mode 100644
index 0000000000..bacb890e10
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/de.forestle.org.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/digg.com.png b/plugins/Referers/images/searchEngines/digg.com.png
new file mode 100644
index 0000000000..1edeb3b202
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/digg.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/directory.google.com.png b/plugins/Referers/images/searchEngines/directory.google.com.png
deleted file mode 100644
index 154ecfcfe0..0000000000
--- a/plugins/Referers/images/searchEngines/directory.google.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/duckduckgo.com.png b/plugins/Referers/images/searchEngines/duckduckgo.com.png
new file mode 100644
index 0000000000..329ab66f6c
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/duckduckgo.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/ecosia.org.png b/plugins/Referers/images/searchEngines/ecosia.org.png
new file mode 100644
index 0000000000..6945878ae8
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/ecosia.org.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/find.copernic.com.png b/plugins/Referers/images/searchEngines/find.copernic.com.png
deleted file mode 100644
index d646c9fbb4..0000000000
--- a/plugins/Referers/images/searchEngines/find.copernic.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/friendfeed.com.png b/plugins/Referers/images/searchEngines/friendfeed.com.png
new file mode 100644
index 0000000000..a9bc79919e
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/friendfeed.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/froogle.google.com.png b/plugins/Referers/images/searchEngines/froogle.google.com.png
index ac1b2d8b10..5e701b1d4e 100644
--- a/plugins/Referers/images/searchEngines/froogle.google.com.png
+++ b/plugins/Referers/images/searchEngines/froogle.google.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/fulltext.centrum.cz.png b/plugins/Referers/images/searchEngines/fulltext.centrum.cz.png
deleted file mode 100644
index 0530ca5bdd..0000000000
--- a/plugins/Referers/images/searchEngines/fulltext.centrum.cz.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/g.msn.com.png b/plugins/Referers/images/searchEngines/g.msn.com.png
deleted file mode 100644
index 5ca23d7674..0000000000
--- a/plugins/Referers/images/searchEngines/g.msn.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/gais.cs.ccu.edu.tw.png b/plugins/Referers/images/searchEngines/gais.cs.ccu.edu.tw.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/gais.cs.ccu.edu.tw.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/google.canoe.com.png b/plugins/Referers/images/searchEngines/google.canoe.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/google.canoe.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/googlesyndicatedsearch.com.png b/plugins/Referers/images/searchEngines/googlesyndicatedsearch.com.png
new file mode 100644
index 0000000000..ffa48426b1
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/googlesyndicatedsearch.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/guide.opendns.com.png b/plugins/Referers/images/searchEngines/guide.opendns.com.png
deleted file mode 100644
index f227c390fe..0000000000
--- a/plugins/Referers/images/searchEngines/guide.opendns.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/hledani.tiscali.cz.png b/plugins/Referers/images/searchEngines/hledani.tiscali.cz.png
deleted file mode 100644
index e5b9a88685..0000000000
--- a/plugins/Referers/images/searchEngines/hledani.tiscali.cz.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/hotbot.lycos.com.png b/plugins/Referers/images/searchEngines/hotbot.lycos.com.png
new file mode 100644
index 0000000000..c6ed91697c
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/hotbot.lycos.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/hotbox.png b/plugins/Referers/images/searchEngines/hotbox.png
deleted file mode 100644
index ad53185532..0000000000
--- a/plugins/Referers/images/searchEngines/hotbox.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/ie4.nomade.fr.png b/plugins/Referers/images/searchEngines/ie4.nomade.fr.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/ie4.nomade.fr.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/images.google.com.png b/plugins/Referers/images/searchEngines/images.google.com.png
index 154ecfcfe0..dd52532085 100644
--- a/plugins/Referers/images/searchEngines/images.google.com.png
+++ b/plugins/Referers/images/searchEngines/images.google.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/images.search.yahoo.com.png b/plugins/Referers/images/searchEngines/images.search.yahoo.com.png
new file mode 100644
index 0000000000..91dcc48793
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/images.search.yahoo.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/ko.search.need2find.com.png b/plugins/Referers/images/searchEngines/ko.search.need2find.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/ko.search.need2find.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/lo.st.png b/plugins/Referers/images/searchEngines/lo.st.png
new file mode 100644
index 0000000000..134e0fd950
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/lo.st.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/meta.rrzn.uni-hannover.de.png b/plugins/Referers/images/searchEngines/meta.rrzn.uni-hannover.de.png
new file mode 100644
index 0000000000..b63fa1b649
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/meta.rrzn.uni-hannover.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/metaresults.copernic.com.png b/plugins/Referers/images/searchEngines/metaresults.copernic.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/metaresults.copernic.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/morfeo.centrum.cz.png b/plugins/Referers/images/searchEngines/morfeo.centrum.cz.png
deleted file mode 100644
index 0530ca5bdd..0000000000
--- a/plugins/Referers/images/searchEngines/morfeo.centrum.cz.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/mserv.rrzn.uni-hannover.de.png b/plugins/Referers/images/searchEngines/mserv.rrzn.uni-hannover.de.png
deleted file mode 100644
index 99489c9ab4..0000000000
--- a/plugins/Referers/images/searchEngines/mserv.rrzn.uni-hannover.de.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/msxml.excite.com.png b/plugins/Referers/images/searchEngines/msxml.excite.com.png
deleted file mode 100644
index 8ef8d0ba7c..0000000000
--- a/plugins/Referers/images/searchEngines/msxml.excite.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/news.google.com.png b/plugins/Referers/images/searchEngines/news.google.com.png
index 154ecfcfe0..dd52532085 100644
--- a/plugins/Referers/images/searchEngines/news.google.com.png
+++ b/plugins/Referers/images/searchEngines/news.google.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/news.openfind.com.tw.png b/plugins/Referers/images/searchEngines/news.openfind.com.tw.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/news.openfind.com.tw.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/news.seekport.de.png b/plugins/Referers/images/searchEngines/news.seekport.de.png
deleted file mode 100644
index d5da478ca6..0000000000
--- a/plugins/Referers/images/searchEngines/news.seekport.de.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/nmsearch.3721.com.png b/plugins/Referers/images/searchEngines/nmsearch.3721.com.png
deleted file mode 100644
index 6b4384e007..0000000000
--- a/plugins/Referers/images/searchEngines/nmsearch.3721.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/otsing.delfi.ee.png b/plugins/Referers/images/searchEngines/otsing.delfi.ee.png
new file mode 100644
index 0000000000..2816690eef
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/otsing.delfi.ee.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/p.zhongsou.com.png b/plugins/Referers/images/searchEngines/p.zhongsou.com.png
new file mode 100644
index 0000000000..131e9c509d
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/p.zhongsou.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/pesquisa.sapo.pt.png b/plugins/Referers/images/searchEngines/pesquisa.sapo.pt.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/pesquisa.sapo.pt.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/recherche.hit-parade.com.png b/plugins/Referers/images/searchEngines/recherche.hit-parade.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/recherche.hit-parade.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/rechercher.nomade.tiscali.fr.png b/plugins/Referers/images/searchEngines/rechercher.nomade.tiscali.fr.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/rechercher.nomade.tiscali.fr.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search-dyn.tiscali.it.png b/plugins/Referers/images/searchEngines/search-dyn.tiscali.it.png
deleted file mode 100644
index 13ef7b5474..0000000000
--- a/plugins/Referers/images/searchEngines/search-dyn.tiscali.it.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.babylon.com.png b/plugins/Referers/images/searchEngines/search.babylon.com.png
new file mode 100644
index 0000000000..02c03a13d2
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/search.babylon.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.conduit.com.png b/plugins/Referers/images/searchEngines/search.conduit.com.png
new file mode 100644
index 0000000000..fac5fe2d55
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/search.conduit.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.dogpile.com.png b/plugins/Referers/images/searchEngines/search.dogpile.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/search.dogpile.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.freecause.com.png b/plugins/Referers/images/searchEngines/search.freecause.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/search.freecause.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.iwon.com.png b/plugins/Referers/images/searchEngines/search.iwon.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/search.iwon.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.msn.com.png b/plugins/Referers/images/searchEngines/search.msn.com.png
deleted file mode 100644
index 6217b7151c..0000000000
--- a/plugins/Referers/images/searchEngines/search.msn.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.naver.com.png b/plugins/Referers/images/searchEngines/search.naver.com.png
new file mode 100644
index 0000000000..a97c282800
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/search.naver.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.netscape.com.png b/plugins/Referers/images/searchEngines/search.netscape.com.png
deleted file mode 100644
index a7dfae8e6f..0000000000
--- a/plugins/Referers/images/searchEngines/search.netscape.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.nifty.com.png b/plugins/Referers/images/searchEngines/search.nifty.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/search.nifty.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.opera.com.png b/plugins/Referers/images/searchEngines/search.opera.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/search.opera.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.rambler.ru.png b/plugins/Referers/images/searchEngines/search.rambler.ru.png
deleted file mode 100644
index d26d31ed09..0000000000
--- a/plugins/Referers/images/searchEngines/search.rambler.ru.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.supereva.com.png b/plugins/Referers/images/searchEngines/search.supereva.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/search.supereva.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.www.ee.png b/plugins/Referers/images/searchEngines/search.www.ee.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/search.www.ee.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search.yaca.yandex.ru.png b/plugins/Referers/images/searchEngines/search.yaca.yandex.ru.png
deleted file mode 100644
index bc3c364935..0000000000
--- a/plugins/Referers/images/searchEngines/search.yaca.yandex.ru.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/search1.seznam.cz.png b/plugins/Referers/images/searchEngines/search1.seznam.cz.png
deleted file mode 100644
index 49ea24c48c..0000000000
--- a/plugins/Referers/images/searchEngines/search1.seznam.cz.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/searchservice.myspace.com.png b/plugins/Referers/images/searchEngines/searchservice.myspace.com.png
new file mode 100644
index 0000000000..5c37fe2ff9
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/searchservice.myspace.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/servizi.mediaset.it.png b/plugins/Referers/images/searchEngines/servizi.mediaset.it.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/servizi.mediaset.it.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/smart.delfi.lv.png b/plugins/Referers/images/searchEngines/smart.delfi.lv.png
new file mode 100644
index 0000000000..2816690eef
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/smart.delfi.lv.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/suche.defind.de.png b/plugins/Referers/images/searchEngines/suche.defind.de.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/suche.defind.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/translate.google.com.png b/plugins/Referers/images/searchEngines/translate.google.com.png
index 154ecfcfe0..dd52532085 100644
--- a/plugins/Referers/images/searchEngines/translate.google.com.png
+++ b/plugins/Referers/images/searchEngines/translate.google.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/travel.gigablast.com.png b/plugins/Referers/images/searchEngines/travel.gigablast.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/travel.gigablast.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/vivisimo.com.png b/plugins/Referers/images/searchEngines/vivisimo.com.png
new file mode 100644
index 0000000000..1f8de0fa21
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/vivisimo.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/web.toile.com.png b/plugins/Referers/images/searchEngines/web.toile.com.png
deleted file mode 100644
index b5111f71f3..0000000000
--- a/plugins/Referers/images/searchEngines/web.toile.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/wps.openfind.com.tw.png b/plugins/Referers/images/searchEngines/wps.openfind.com.tw.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/wps.openfind.com.tw.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.123people.com.png b/plugins/Referers/images/searchEngines/www.123people.com.png
new file mode 100644
index 0000000000..205208a9d2
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.123people.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.4call.dastelefonbuch.de.png b/plugins/Referers/images/searchEngines/www.4call.dastelefonbuch.de.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.4call.dastelefonbuch.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.acoon.de.png b/plugins/Referers/images/searchEngines/www.acoon.de.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.acoon.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.caloweb.de.png b/plugins/Referers/images/searchEngines/www.caloweb.de.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.caloweb.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.crossbot.de.png b/plugins/Referers/images/searchEngines/www.crossbot.de.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.crossbot.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.cuil.com.png b/plugins/Referers/images/searchEngines/www.cuil.com.png
new file mode 100644
index 0000000000..3743b19ac5
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.cuil.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.dasoertliche.de.png b/plugins/Referers/images/searchEngines/www.dasoertliche.de.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.dasoertliche.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.deskfeeds.com.png b/plugins/Referers/images/searchEngines/www.deskfeeds.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.deskfeeds.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.dino-online.de.png b/plugins/Referers/images/searchEngines/www.dino-online.de.png
new file mode 100644
index 0000000000..e902d495e9
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.dino-online.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.eniro.se.png b/plugins/Referers/images/searchEngines/www.eniro.se.png
new file mode 100644
index 0000000000..09223f35fd
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.eniro.se.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.enrio.se.png b/plugins/Referers/images/searchEngines/www.enrio.se.png
deleted file mode 100644
index b537ac03e6..0000000000
--- a/plugins/Referers/images/searchEngines/www.enrio.se.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.eo.st.png b/plugins/Referers/images/searchEngines/www.eo.st.png
deleted file mode 100644
index 19184f55db..0000000000
--- a/plugins/Referers/images/searchEngines/www.eo.st.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.eu.ixquick.com.png b/plugins/Referers/images/searchEngines/www.eu.ixquick.com.png
deleted file mode 100644
index a688041220..0000000000
--- a/plugins/Referers/images/searchEngines/www.eu.ixquick.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.eudip.com.png b/plugins/Referers/images/searchEngines/www.eudip.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.eudip.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.eurip.com.png b/plugins/Referers/images/searchEngines/www.eurip.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.eurip.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.everyclick.com.png b/plugins/Referers/images/searchEngines/www.everyclick.com.png
new file mode 100644
index 0000000000..a86286737a
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.everyclick.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.facebook.com.png b/plugins/Referers/images/searchEngines/www.facebook.com.png
new file mode 100644
index 0000000000..50794d05c3
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.facebook.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.feedminer.com.png b/plugins/Referers/images/searchEngines/www.feedminer.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.feedminer.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.feedster.com.png b/plugins/Referers/images/searchEngines/www.feedster.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.feedster.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.firstsfind.com.png b/plugins/Referers/images/searchEngines/www.firstsfind.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.firstsfind.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.fixsuche.de.png b/plugins/Referers/images/searchEngines/www.fixsuche.de.png
new file mode 100644
index 0000000000..8f6591c35e
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.fixsuche.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.gnadenmeer.de.png b/plugins/Referers/images/searchEngines/www.gnadenmeer.de.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.gnadenmeer.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.google.com.png b/plugins/Referers/images/searchEngines/www.google.com.png
index 154ecfcfe0..dd52532085 100644
--- a/plugins/Referers/images/searchEngines/www.google.com.png
+++ b/plugins/Referers/images/searchEngines/www.google.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.google.interia.pl.png b/plugins/Referers/images/searchEngines/www.google.interia.pl.png
deleted file mode 100644
index 75a8d7c0f0..0000000000
--- a/plugins/Referers/images/searchEngines/www.google.interia.pl.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.hooseek.com.png b/plugins/Referers/images/searchEngines/www.hooseek.com.png
new file mode 100644
index 0000000000..446d33f37d
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.hooseek.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.hotbot.com.png b/plugins/Referers/images/searchEngines/www.hotbot.com.png
deleted file mode 100644
index 882c6f89bc..0000000000
--- a/plugins/Referers/images/searchEngines/www.hotbot.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.ilse.nl.png b/plugins/Referers/images/searchEngines/www.ilse.nl.png
new file mode 100644
index 0000000000..1e636956f3
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.ilse.nl.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.jungle-spider.de.png b/plugins/Referers/images/searchEngines/www.jungle-spider.de.png
new file mode 100644
index 0000000000..7827fa705a
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.jungle-spider.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.kostenlos.de.png b/plugins/Referers/images/searchEngines/www.kostenlos.de.png
new file mode 100644
index 0000000000..6efc23a5cf
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.kostenlos.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.latne.lv.png b/plugins/Referers/images/searchEngines/www.latne.lv.png
new file mode 100644
index 0000000000..e340e33092
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.latne.lv.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.maailm.com.png b/plugins/Referers/images/searchEngines/www.maailm.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.maailm.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.meceoo.fr.png b/plugins/Referers/images/searchEngines/www.meceoo.fr.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.meceoo.fr.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.meinestadt.de.png b/plugins/Referers/images/searchEngines/www.meinestadt.de.png
index c172657c4c..869889da09 100644
--- a/plugins/Referers/images/searchEngines/www.meinestadt.de.png
+++ b/plugins/Referers/images/searchEngines/www.meinestadt.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.mister-wong.com.png b/plugins/Referers/images/searchEngines/www.mister-wong.com.png
new file mode 100644
index 0000000000..af332512c3
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.mister-wong.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.monstercrawler.com.png b/plugins/Referers/images/searchEngines/www.monstercrawler.com.png
new file mode 100644
index 0000000000..0bcc37fce0
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.monstercrawler.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.mozbot.com.png b/plugins/Referers/images/searchEngines/www.mozbot.com.png
deleted file mode 100644
index 1a284a60ad..0000000000
--- a/plugins/Referers/images/searchEngines/www.mozbot.com.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.multimania.lycos.fr.png b/plugins/Referers/images/searchEngines/www.multimania.lycos.fr.png
deleted file mode 100644
index cb1478bb01..0000000000
--- a/plugins/Referers/images/searchEngines/www.multimania.lycos.fr.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.mywebsearch.com.png b/plugins/Referers/images/searchEngines/www.mysearch.com.png
index 5a437790fd..5a437790fd 100644
--- a/plugins/Referers/images/searchEngines/www.mywebsearch.com.png
+++ b/plugins/Referers/images/searchEngines/www.mysearch.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.neti.ee.png b/plugins/Referers/images/searchEngines/www.neti.ee.png
new file mode 100644
index 0000000000..650222e4b8
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.neti.ee.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.netster.com.png b/plugins/Referers/images/searchEngines/www.netster.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.netster.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.overture.com.png b/plugins/Referers/images/searchEngines/www.overture.com.png
new file mode 100644
index 0000000000..91dcc48793
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.overture.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.qualigo.at.png b/plugins/Referers/images/searchEngines/www.qualigo.at.png
new file mode 100644
index 0000000000..74658bd886
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.qualigo.at.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.qualigo.de.png b/plugins/Referers/images/searchEngines/www.qualigo.de.png
deleted file mode 100644
index b87866c2e3..0000000000
--- a/plugins/Referers/images/searchEngines/www.qualigo.de.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.rpmfind.net.png b/plugins/Referers/images/searchEngines/www.rpmfind.net.png
new file mode 100644
index 0000000000..8e196f112e
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.rpmfind.net.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.searchscout.com.png b/plugins/Referers/images/searchEngines/www.searchscout.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.searchscout.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.seekport.de.png b/plugins/Referers/images/searchEngines/www.seekport.de.png
deleted file mode 100644
index d5da478ca6..0000000000
--- a/plugins/Referers/images/searchEngines/www.seekport.de.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.sogou.com.png b/plugins/Referers/images/searchEngines/www.sogou.com.png
new file mode 100644
index 0000000000..e8561b7b22
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.sogou.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.soso.com.png b/plugins/Referers/images/searchEngines/www.soso.com.png
new file mode 100644
index 0000000000..d23736e56e
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.soso.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.start.no.png b/plugins/Referers/images/searchEngines/www.start.no.png
deleted file mode 100644
index 095f39a869..0000000000
--- a/plugins/Referers/images/searchEngines/www.start.no.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.tixuma.de.png b/plugins/Referers/images/searchEngines/www.tixuma.de.png
new file mode 100644
index 0000000000..4e516ebfb3
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.tixuma.de.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.trusted--search.com.png b/plugins/Referers/images/searchEngines/www.trusted--search.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.trusted--search.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.vindex.nl.png b/plugins/Referers/images/searchEngines/www.vindex.nl.png
new file mode 100644
index 0000000000..2e1185eb06
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.vindex.nl.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.web.nl.png b/plugins/Referers/images/searchEngines/www.web.nl.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.web.nl.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.webalta.ru.png b/plugins/Referers/images/searchEngines/www.webalta.ru.png
deleted file mode 100644
index ba7a30a043..0000000000
--- a/plugins/Referers/images/searchEngines/www.webalta.ru.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.x-recherche.com.png b/plugins/Referers/images/searchEngines/www.x-recherche.com.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/www.x-recherche.com.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.ya.ru.png b/plugins/Referers/images/searchEngines/www.ya.ru.png
deleted file mode 100644
index bc3c364935..0000000000
--- a/plugins/Referers/images/searchEngines/www.ya.ru.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/www.yandex.ru.png b/plugins/Referers/images/searchEngines/www.yandex.ru.png
deleted file mode 100644
index bc3c364935..0000000000
--- a/plugins/Referers/images/searchEngines/www.yandex.ru.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/wxsl.nl.png b/plugins/Referers/images/searchEngines/wxsl.nl.png
new file mode 100644
index 0000000000..1e660b7409
--- /dev/null
+++ b/plugins/Referers/images/searchEngines/wxsl.nl.png
Binary files differ
diff --git a/plugins/Referers/images/searchEngines/ya.ru.png b/plugins/Referers/images/searchEngines/ya.ru.png
deleted file mode 100644
index bc3c364935..0000000000
--- a/plugins/Referers/images/searchEngines/ya.ru.png
+++ /dev/null
Binary files differ
diff --git a/plugins/Referers/templates/index.tpl b/plugins/Referers/templates/index.tpl
index 0f2aff9729..bd7dfd96cf 100644
--- a/plugins/Referers/templates/index.tpl
+++ b/plugins/Referers/templates/index.tpl
@@ -4,7 +4,7 @@
<h2>{'Referers_Evolution'|translate}</h2>
{$graphEvolutionReferers}
-<br/>
+<br />
<div id='leftcolumn'>
<h2>{'Referers_Type'|translate}</h2>
<div id='leftcolumn'>
@@ -26,7 +26,7 @@
{$dataTableRefererType}
</div>
-<div style="clear:both" />
+<div style="clear:both;"></div>
<p>View
<a href="javascript:broadcast.propagateAjax('module=Referers&action=getSearchEnginesAndKeywords')">{'Referers_SubmenuSearchEngines'|translate}</a>,
diff --git a/plugins/SecurityInfo/Controller.php b/plugins/SecurityInfo/Controller.php
new file mode 100644
index 0000000000..8059d88702
--- /dev/null
+++ b/plugins/SecurityInfo/Controller.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik_Plugins
+ * @package Piwik_SecurityInfo
+ */
+
+/**
+ * @package Piwik_SecurityInfo
+ */
+class Piwik_SecurityInfo_Controller extends Piwik_Controller
+{
+ function index()
+ {
+ Piwik::checkUserIsSuperUser();
+
+ require_once(dirname(__FILE__) . '/PhpSecInfo/PhpSecInfo.php');
+
+ // instantiate the class
+ $psi = new PhpSecInfo();
+
+ // load and run all tests
+ $psi->loadAndRun();
+
+ // grab the results as a multidimensional array
+ $results = $psi->getResultsAsArray();
+
+ // suppress results
+ unset($results['test_results']['Core']['memory_limit']);
+ unset($results['test_results']['Core']['post_max_size']);
+ unset($results['test_results']['Core']['upload_max_filesize']);
+
+ $view = Piwik_View::factory('index');
+ $this->setGeneralVariablesView($view);
+ $view->menu = Piwik_GetAdminMenu();
+ $view->results = $results;
+ echo $view->render();
+ }
+}
diff --git a/plugins/SecurityInfo/LICENSE b/plugins/SecurityInfo/LICENSE
new file mode 100644
index 0000000000..26c1d76267
--- /dev/null
+++ b/plugins/SecurityInfo/LICENSE
@@ -0,0 +1,10 @@
+Copyright (C) 2006 Edward Finkler
+
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/PhpSecInfo.php b/plugins/SecurityInfo/PhpSecInfo/PhpSecInfo.php
new file mode 100644
index 0000000000..e12a057433
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/PhpSecInfo.php
@@ -0,0 +1,591 @@
+<?php
+/**
+ * Main class file
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * The default language setting if none is set/retrievable
+ *
+ */
+define ('PHPSECINFO_LANG_DEFAULT', 'en');
+
+/**
+ * a general version string to differentiate releases
+ *
+ */
+define ('PHPSECINFO_VERSION', '0.2.2');
+
+/**
+ * a YYYYMMDD date string to indicate "build" date
+ *
+ */
+define ('PHPSECINFO_BUILD', '20080723');
+
+/**
+ * Homepage for phpsecinfo project
+ *
+ */
+define ('PHPSECINFO_URL', 'http://phpsecinfo.com');
+
+/**
+ * The base folder where views are stored. Include trailing slash
+ *
+ */
+define('PHPSECINFO_VIEW_DIR_DEFAULT', 'View/');
+
+
+/**
+ * The default format, used to load the proper view.
+ */
+define('PHPSECINFO_FORMAT_DEFAULT', 'Html');
+
+
+/**
+ * The base directory, used to resolve requires and includes
+ */
+define('PHPSECINFO_BASE_DIR', dirname(__FILE__));
+
+/**
+ * This is the main class for the phpsecinfo system. It's responsible for
+ * dynamically loading tests, running those tests, and generating the results
+ * output
+ *
+ * Example:
+ * <code>
+ * <?php require_once(PHPSECINFO_BASE_DIR.'/PhpSecInfo.php'); ?>
+ * <?php phpsecinfo(); ?>
+ * </code>
+ *
+ * If you want to capture the output, or just grab the test results and display them
+ * in your own way, you'll need to do slightly more work.
+ *
+ * Example:
+ * <code>
+ * require_once(PHPSECINFO_BASE_DIR.'/PhpSecInfo.php');
+ * // instantiate the class
+ * $psi = new PhpSecInfo();
+ *
+ * // load and run all tests
+ * $psi->loadAndRun();
+ *
+ * // grab the results as a multidimensional array
+ * $results = $psi->getResultsAsArray();
+ * echo "<pre>"; echo print_r($results, true); echo "</pre>";
+ *
+ * // grab the standard results output as a string
+ * $html = $psi->getOutput();
+ *
+ * // send it to the browser
+ * echo $html;
+ * </code>
+ *
+ *
+ * The procedural function "phpsecinfo" is defined below this class.
+ * @see phpsecinfo()
+ *
+ * @author Ed Finkler <coj@funkatron.com>
+ *
+ * see CHANGELOG for changes
+ *
+ */
+class PhpSecInfo
+{
+
+ /**
+ * An array of tests to run
+ *
+ * @var array PhpSecInfo_Test
+ */
+ var $tests_to_run = array();
+
+
+ /**
+ * An array of results. Each result is an associative array:
+ * <code>
+ * $result['result'] = PHPSECINFO_TEST_RESULT_NOTICE;
+ * $result['message'] = "a string describing the test results and what they mean";
+ * </code>
+ *
+ * @var array
+ */
+ var $test_results = array();
+
+
+ /**
+ * An array of tests that were not run
+ *
+ * <code>
+ * $result['result'] = PHPSECINFO_TEST_RESULT_NOTRUN;
+ * $result['message'] = "a string explaining why the test was not run";
+ * </code>
+ *
+ * @var array
+ */
+ var $tests_not_run = array();
+
+
+ /**
+ * The language code used. Defaults to PHPSECINFO_LANG_DEFAULT, which
+ * is 'en'
+ *
+ * @var string
+ * @see PHPSECINFO_LANG_DEFAULT
+ */
+ var $language = PHPSECINFO_LANG_DEFAULT;
+
+
+ /**
+ * An array of integers recording the number of test results in each category. Categories can include
+ * some or all of the PHPSECINFO_TEST_* constants. Constants are the keys, # of results are the values.
+ *
+ * @var array
+ */
+ var $result_counts = array();
+
+
+ /**
+ * The number of tests that have been run
+ *
+ * @var integer
+ */
+ var $num_tests_run = 0;
+
+
+ /**
+ * The base directory for phpsecinfo. Set within the constructor. Paths are resolved from this.
+ * @var string
+ */
+ var $_base_dir;
+
+
+ /**
+ * The directory PHPSecInfo will look for views. It defaults to the value
+ * in PHPSECINFO_VIEW_DIR_DEFAULT, but can be changed with the setViewDirectory()
+ * method.
+ *
+ * @var string
+ */
+ var $_view_directory;
+
+
+ /**
+ * The output format, used to load the proper view
+ *
+ * @var string
+ **/
+ var $_format;
+
+ /**
+ * Constructor
+ *
+ * @return PhpSecInfo
+ */
+ function PhpSecInfo($opts = null) {
+
+ $this->_base_dir = dirname(__FILE__);
+
+ if ($opts) {
+ if (isset($opts['view_directory'])) {
+ $this->setViewDirectory($opts['view_directory']);
+ } else {
+ $this->setViewDirectory(dirname(__FILE__).DIRECTORY_SEPARATOR . PHPSECINFO_VIEW_DIR_DEFAULT);
+ }
+
+ if (isset($opts['format'])) {
+ $this->setFormat($opts['format']);
+ } else {
+ if (strtolower(php_sapi_name()) == 'cli' ) {
+ $this->setFormat('Cli');
+ } else {
+ $this->setFormat(PHPSECINFO_FORMAT_DEFAULT);
+ }
+ }
+
+ } else { /* Use defaults */
+ $this->setViewDirectory(dirname(__FILE__).DIRECTORY_SEPARATOR . PHPSECINFO_VIEW_DIR_DEFAULT);
+ if (strtolower(php_sapi_name()) == 'cli' ) {
+ $this->setFormat('Cli');
+ } else {
+ $this->setFormat(PHPSECINFO_FORMAT_DEFAULT);
+ }
+ }
+ }
+
+
+ /**
+ * recurses through the Test subdir and includes classes in each test group subdir,
+ * then builds an array of classnames for the tests that will be run
+ *
+ */
+ function loadTests() {
+
+ $test_root = dir(dirname(__FILE__).DIRECTORY_SEPARATOR.'Test');
+
+ //echo "<pre>"; echo print_r($test_root, true); echo "</pre>";
+
+ while (false !== ($entry = $test_root->read())) {
+ if ( is_dir($test_root->path.DIRECTORY_SEPARATOR.$entry) && !preg_match('|^\.(.*)$|', $entry) ) {
+ $test_dirs[] = $entry;
+ }
+ }
+ //echo "<pre>"; echo print_r($test_dirs, true); echo "</pre>";
+
+ // include_once all files in each test dir
+ foreach ($test_dirs as $test_dir) {
+ $this_dir = dir($test_root->path.DIRECTORY_SEPARATOR.$test_dir);
+
+ while (false !== ($entry = $this_dir->read())) {
+ if (!is_dir($this_dir->path.DIRECTORY_SEPARATOR.$entry)) {
+ include_once $this_dir->path.DIRECTORY_SEPARATOR.$entry;
+ $classNames[] = "PhpSecInfo_Test_".$test_dir."_".basename($entry, '.php');
+ }
+ }
+
+ }
+
+ // modded this to not throw a PHP5 STRICT notice, although I don't like passing by value here
+ $this->tests_to_run = $classNames;
+ }
+
+
+ /**
+ * This runs the tests in the tests_to_run array and
+ * places returned data in the following arrays/scalars:
+ * - $this->test_results
+ * - $this->result_counts
+ * - $this->num_tests_run
+ * - $this->tests_not_run;
+ *
+ */
+ function runTests() {
+ // initialize a bunch of arrays
+ $this->test_results = array();
+ $this->result_counts = array();
+ $this->result_counts[PHPSECINFO_TEST_RESULT_NOTRUN] = 0;
+ $this->num_tests_run = 0;
+
+ foreach ($this->tests_to_run as $testClass) {
+
+ /**
+ * @var $test PhpSecInfo_Test
+ */
+ $test = new $testClass();
+
+ if ($test->isTestable()) {
+ $test->test();
+ $rs = array( 'result' => $test->getResult(),
+ 'message' => $test->getMessage(),
+ 'value_current' => $test->getCurrentTestValue(),
+ 'value_recommended' => $test->getRecommendedTestValue(),
+ 'moreinfo_url' => $test->getMoreInfoURL(),
+ );
+ $this->test_results[$test->getTestGroup()][$test->getTestName()] = $rs;
+
+ // initialize if not yet set
+ if (!isset ($this->result_counts[$rs['result']]) ) {
+ $this->result_counts[$rs['result']] = 0;
+ }
+
+ $this->result_counts[$rs['result']]++;
+ $this->num_tests_run++;
+ } else {
+ $rs = array( 'result' => $test->getResult(),
+ 'message' => $test->getMessage(),
+ 'value_current' => NULL,
+ 'value_recommended' => NULL,
+ 'moreinfo_url' => $test->getMoreInfoURL(),
+ );
+ $this->result_counts[PHPSECINFO_TEST_RESULT_NOTRUN]++;
+ $this->tests_not_run[$test->getTestGroup()."::".$test->getTestName()] = $rs;
+ }
+ }
+ }
+
+
+ /**
+ * This is the main output method. The look and feel mimics phpinfo()
+ *
+ */
+ function renderOutput($page_title="Security Information About PHP") {
+ /**
+ * We need to use PhpSecInfo_Test::getBooleanIniValue() below
+ * @see PhpSecInfo_Test::getBooleanIniValue()
+ */
+ if (!class_exists('PhpSecInfo_Test')) {
+ include( dirname(__FILE__).DIRECTORY_SEPARATOR.'Test'.DIRECTORY_SEPARATOR.'Test.php');
+ }
+ $this->loadView($this->_format);
+ }
+
+
+ /**
+ * This is a helper method that makes it easy to output tables of test results
+ * for a given test group
+ *
+ * @param string $group_name
+ * @param array $group_results
+ */
+ function _outputRenderTable($group_name, $group_results) {
+
+ // exit out if $group_results was empty or not an array. This sorta seems a little hacky...
+ if (!is_array($group_results) || sizeof($group_results) < 1) {
+ return false;
+ }
+
+ ksort($group_results);
+
+ $this->loadView($this->_format.'/Result', array('group_name'=>$group_name, 'group_results'=>$group_results));
+
+ return true;
+ }
+
+
+
+ /**
+ * This outputs a table containing a summary of the test results (counts and % in each result type)
+ *
+ * @see PHPSecInfo::_outputRenderTable()
+ * @see PHPSecInfo::_outputGetResultTypeFromCode()
+ */
+ function _outputRenderStatsTable() {
+
+ foreach($this->result_counts as $code=>$val) {
+ if ($code != PHPSECINFO_TEST_RESULT_NOTRUN) {
+ $percentage = round($val/$this->num_tests_run * 100,2);
+ $result_type = $this->_outputGetResultTypeFromCode($code);
+ $stats[$result_type] = array( 'count' => $val,
+ 'result' => $code,
+ 'message' => "$val out of {$this->num_tests_run} ($percentage%)");
+ }
+ }
+
+ $this->_outputRenderTable('Test Results Summary', $stats);
+
+ }
+
+
+
+ /**
+ * This outputs a table containing a summary or test that were not executed, and the reasons why they were skipped
+ *
+ * @see PHPSecInfo::_outputRenderTable()
+ */
+ function _outputRenderNotRunTable() {
+
+ $this->_outputRenderTable('Tests Not Run', $this->tests_not_run);
+
+ }
+
+
+
+
+ /**
+ * This is a helper function that returns a CSS class corresponding to
+ * the result code the test returned. This allows us to color-code
+ * results
+ *
+ * @param integer $code
+ * @return string
+ */
+ function _outputGetCssClassFromResult($code) {
+
+ switch ($code) {
+ case PHPSECINFO_TEST_RESULT_OK:
+ return 'value-ok';
+ break;
+
+ case PHPSECINFO_TEST_RESULT_NOTICE:
+ return 'value-notice';
+ break;
+
+ case PHPSECINFO_TEST_RESULT_WARN:
+ return 'value-warn';
+ break;
+
+ case PHPSECINFO_TEST_RESULT_NOTRUN:
+ return 'value-notrun';
+ break;
+
+ case PHPSECINFO_TEST_RESULT_ERROR:
+ return 'value-error';
+ break;
+
+ default:
+ return 'value-notrun';
+ break;
+ }
+
+ }
+
+
+
+ /**
+ * This is a helper function that returns a label string corresponding to
+ * the result code the test returned. This is mainly used for the Test
+ * Results Summary table.
+ *
+ * @see PHPSecInfo::_outputRenderStatsTable()
+ * @param integer $code
+ * @return string
+ */
+ function _outputGetResultTypeFromCode($code) {
+
+ switch ($code) {
+ case PHPSECINFO_TEST_RESULT_OK:
+ return 'Pass';
+ break;
+
+ case PHPSECINFO_TEST_RESULT_NOTICE:
+ return 'Notice';
+ break;
+
+ case PHPSECINFO_TEST_RESULT_WARN:
+ return 'Warning';
+ break;
+
+ case PHPSECINFO_TEST_RESULT_NOTRUN:
+ return 'Not Run';
+ break;
+
+ case PHPSECINFO_TEST_RESULT_ERROR:
+ return 'Error';
+ break;
+
+ default:
+ return 'Invalid Result Code';
+ break;
+ }
+
+ }
+
+
+ /**
+ * Loads and runs all the tests
+ *
+ * As loading, then running, is a pretty common process, this saves a extra method call
+ *
+ * @since 0.1.1
+ *
+ */
+ function loadAndRun() {
+ $this->loadTests();
+ $this->runTests();
+ }
+
+
+ /**
+ * returns an associative array of test data. Four keys are set:
+ * - test_results (array)
+ * - tests_not_run (array)
+ * - result_counts (array)
+ * - num_tests_run (integer)
+ *
+ * note that this must be called after tests are loaded and run
+ *
+ * @since 0.1.1
+ * @return array
+ */
+ function getResultsAsArray() {
+ $results = array();
+
+ $results['test_results'] = $this->test_results;
+ $results['tests_not_run'] = $this->tests_not_run;
+ $results['result_counts'] = $this->result_counts;
+ $results['num_tests_run'] = $this->num_tests_run;
+
+ return $results;
+ }
+
+
+
+ /**
+ * returns the standard output as a string instead of echoing it to the browser
+ *
+ * note that this must be called after tests are loaded and run
+ *
+ * @since 0.1.1
+ *
+ * @return string
+ */
+ function getOutput() {
+ ob_start();
+ $this->renderOutput();
+ $output = ob_get_clean();
+ return $output;
+ }
+
+
+ /**
+ * A very, very simple "view" system
+ *
+ */
+ function loadView($view_name, $data=null) {
+ if ($data != null) {
+ extract($data);
+ }
+
+ $view_file = $this->getViewDirectory().$view_name.".php";
+
+ if ( file_exists($view_file) && is_readable($view_file) ) {
+ ob_start();
+ include $view_file;
+ echo ob_get_clean();
+ } else {
+ user_error("The view '{$view_file}' either does not exist or is not readable", E_USER_WARNING);
+ }
+
+
+ }
+
+
+ /**
+ * Returns the current view directory
+ *
+ * @return string
+ */
+ function getViewDirectory() {
+ return $this->_view_directory;
+ }
+
+
+ /**
+ * Sets the directory that PHPSecInfo will look in for views
+ *
+ * @param string $newdir
+ */
+ function setViewDirectory($newdir) {
+ $this->_view_directory = $newdir;
+ }
+
+
+
+
+ function getFormat() {
+ return $this->_format;
+ }
+
+
+ function setFormat($format) {
+ $this->_format = $format;
+ }
+
+}
+
+
+
+
+/**
+ * A globally-available function that runs the tests and creates the result page
+ *
+ */
+function phpsecinfo() {
+ // modded this to not throw a PHP5 STRICT notice, although I don't like passing by value here
+ $psi = new PhpSecInfo();
+ $psi->loadAndRun();
+ $psi->renderOutput();
+}
+
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Application/php.php b/plugins/SecurityInfo/PhpSecInfo/Test/Application/php.php
new file mode 100644
index 0000000000..0d86d309e9
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Application/php.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Test class for PHP Application
+ *
+ * @package PhpSecInfo
+ * @author Piwik
+ */
+
+/**
+ * require the PhpSecInfo_Test_Application class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Application.php');
+
+/**
+ * Test class for PHP application
+ *
+ * Checks PHP version
+ *
+ * @package PhpSecInfo
+ * @author Piwik
+ */
+class PhpSecInfo_Test_Application_Php extends PhpSecInfo_Test_Application
+{
+ var $test_name = "PHP";
+
+ var $recommended_value = null;
+
+ function _retrieveCurrentValue() {
+ $this->current_value = PHP_VERSION;;
+
+ $url = 'http://php.net/releases/?serialize=1&version=5';
+ $timeout = Piwik_UpdateCheck::SOCKET_TIMEOUT;
+ try {
+ $latestVersion = Piwik_Http::sendHttpRequest($url, $timeout);
+ $versionInfo = Piwik_Common::unserialize_array($latestVersion);
+ $this->recommended_value = $versionInfo['version'];
+ } catch(Exception $e) {
+ $this->recommended_value = '';
+ }
+ }
+
+ function _execTest() {
+ if (version_compare($this->current_value, '5.2.1') < 0) {
+ return PHPSECINFO_TEST_RESULT_WARN;
+ }
+
+ if (empty($this->recommended_value)) {
+ return PHPSECINFO_TEST_RESULT_ERROR;
+ }
+
+ if (version_compare($this->current_value, $this->recommended_value) >= 0 ) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', "You are running PHP ".$this->recommended_value." (the latest version).");
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', "You are running PHP ".$this->current_value.". The latest version of PHP is ".$this->recommended_value.".");
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', "You are running PHP ".$this->current_value." which is really old. We recommend running the latest (stable) version of PHP which includes numerous bug fixes and security fixes.");
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_ERROR, 'en', "Unable to determine the latest version of PHP available.");
+ }
+}
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Application/piwik.php b/plugins/SecurityInfo/PhpSecInfo/Test/Application/piwik.php
new file mode 100644
index 0000000000..5a495a352c
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Application/piwik.php
@@ -0,0 +1,58 @@
+<?php
+/**
+ * Test class for Piwik Application
+ *
+ * @package PhpSecInfo
+ * @author Piwik
+ */
+
+/**
+ * require the PhpSecInfo_Test_Application class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Application.php');
+
+/**
+ * Test class for Piwik application
+ *
+ * Checks Piwik version
+ *
+ * @package PhpSecInfo
+ * @author Piwik
+ */
+class PhpSecInfo_Test_Application_Piwik extends PhpSecInfo_Test_Application
+{
+ var $test_name = "Piwik";
+
+ var $recommended_value = null;
+
+ function _retrieveCurrentValue() {
+ $this->current_value = Piwik_Version::VERSION;
+
+ $this->recommended_value = Piwik_GetOption(Piwik_UpdateCheck::LATEST_VERSION);
+ }
+
+ function _execTest() {
+ if (version_compare($this->current_value, '0.5') < 0) {
+ return PHPSECINFO_TEST_RESULT_WARN;
+ }
+
+ if (empty($this->recommended_value)) {
+ return PHPSECINFO_TEST_RESULT_ERROR;
+ }
+
+ if (version_compare($this->current_value, $this->recommended_value) >= 0) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', "You are running Piwik ".$this->current_value." (the latest version).");
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', "You are running Piwik ".$this->current_value.". The latest version of Piwik is ".$this->recommended_value.".");
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', "You are running Piwik ".$this->current_value." which is no longer supported by the Piwik developers. We recommend running the latest (stable) version of Piwik which includes numerous enhancements, bug fixes, and security fixes.");
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_ERROR, 'en', "Unable to determine the latest version of Piwik available.");
+ }
+}
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/CGI/force_redirect.php b/plugins/SecurityInfo/PhpSecInfo/Test/CGI/force_redirect.php
new file mode 100644
index 0000000000..9822cbf394
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/CGI/force_redirect.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Test class for cgi force_redirect
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+/**
+ * require the PhpSecInfo_Test_Cgi class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Cgi.php');
+
+/**
+ * Test class for cgi force_redirect
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+class PhpSecInfo_Test_Cgi_Force_Redirect extends PhpSecInfo_Test_Cgi
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "force_redirect";
+
+ /**
+ * The recommended setting value
+ *
+ * @var mixed
+ */
+ var $recommended_value = TRUE;
+
+
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->getBooleanIniValue('cgi.force_redirect');
+ }
+
+
+ /**
+ * Checks to see if cgi.force_redirect is enabled
+ *
+ */
+ function _execTest() {
+
+ if ($this->current_value == $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_WARN;
+ }
+
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', "force_redirect is enabled, which is the recommended setting");
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', "force_redirect is disabled. In most cases, this is a <strong>serious</strong> security vulnerability. Unless you are absolutely sure this is not needed, enable this setting");
+
+ }
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/allow_url_fopen.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/allow_url_fopen.php
new file mode 100644
index 0000000000..799bb88110
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/allow_url_fopen.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Test Class for allow_url_fopen
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+/**
+ * Test Class for allow_url_fopen
+ *
+ * @package PhpSecInfo
+ *
+ *
+ */
+class PhpSecInfo_Test_Core_Allow_Url_Fopen extends PhpSecInfo_Test_Core
+{
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "allow_url_fopen";
+
+ /**
+ * The recommended setting value
+ *
+ * @var mixed
+ */
+ var $recommended_value = FALSE;
+
+
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->getBooleanIniValue('allow_url_fopen');
+ }
+
+
+ /**
+ * Checks to see if allow_url_fopen is enabled
+ *
+ */
+ function _execTest() {
+ if ( version_compare(PHP_VERSION, '5.2', '<') ) { /* this is much more severe if we're running < 5.2 */
+ if ($this->current_value == $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_WARN;
+ } else { /* In 5.2, we'll consider allow_url_fopen "safe" */
+ $this->recommended_value = TRUE;
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+ if ( version_compare(PHP_VERSION, '5.2', '<') ) { /* this is much more severe if we're running < 5.2 */
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'allow_url_fopen is disabled, which is the recommended setting');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', 'allow_url_fopen is enabled. This could be a serious security risk. You should disable allow_url_fopen and consider using the <a href="http://php.net/manual/en/ref.curl.php" target="_blank">PHP cURL functions</a> instead.');
+
+ } else {
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'You are running PHP 5.2 or greater, which makes allow_url_fopen significantly safer. Make sure allow_url_include is <em>disabled</em>, though');
+ }
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/allow_url_include.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/allow_url_include.php
new file mode 100644
index 0000000000..59bedcafc1
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/allow_url_include.php
@@ -0,0 +1,82 @@
+<?php
+/**
+ * Test Class for allow_url_include
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+/**
+ * Test Class for allow_url_include
+ *
+ * @package PhpSecInfo
+ *
+ *
+ */
+class PhpSecInfo_Test_Core_Allow_Url_Include extends PhpSecInfo_Test_Core
+{
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "allow_url_include";
+
+
+ var $recommended_value = FALSE;
+
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->getBooleanIniValue('allow_url_include');
+ }
+
+
+ /**
+ * Checks to see if allow_url_fopen is enabled
+ *
+ */
+ function _execTest() {
+ if ($this->current_value == $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_WARN;
+ }
+
+
+ /**
+ * allow_url_include is only available since PHP 5.2
+ *
+ * @return boolean
+ */
+ function isTestable() {
+
+ if ( version_compare(PHP_VERSION, '5.2', '<') ) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', 'You are running a version of PHP older than 5.2, and allow_url_include is not available');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'allow_url_include is disabled, which is the recommended setting');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', 'allow_url_include is enabled. This could be a serious security risk. You should disable allow_url_include and consider using the <a href="http://php.net/manual/en/ref.curl.php" target="_blank">PHP cURL functions</a> instead.');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/display_errors.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/display_errors.php
new file mode 100644
index 0000000000..e0e93d6748
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/display_errors.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Test class for display_errors
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+/**
+ * Test class for display_errors
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_Display_Errors extends PhpSecInfo_Test_Core
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "display_errors";
+
+ var $recommended_value = FALSE;
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->getBooleanIniValue('display_errors');
+ }
+
+
+ /**
+ * Checks to see if display_errors is enabled
+ *
+ */
+ function _execTest() {
+ if ($this->current_value == $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'display_errors is disabled, which is the recommended setting');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'display_errors is enabled. This is not recommended on "production" servers, as it could reveal sensitive information. You should consider disabling this feature');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/expose_php.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/expose_php.php
new file mode 100644
index 0000000000..3f26648193
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/expose_php.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Test class for expose_php
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+/**
+ * Test class for expose_php
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_Expose_Php extends PhpSecInfo_Test_Core
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "expose_php";
+
+ var $recommended_value = FALSE;
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->returnBytes(ini_get('expose_php'));
+ }
+
+ /**
+ * Checks to see if expose_php is enabled
+ *
+ */
+ function _execTest() {
+
+ if ($this->current_value == $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'expose_php is disabled, which is the recommended setting');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'expose_php is enabled. This adds
+ the PHP "signature" to the web server header, including the PHP version number. This
+ could attract attackers looking for vulnerable versions of PHP');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/file_uploads.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/file_uploads.php
new file mode 100644
index 0000000000..6a3c822aae
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/file_uploads.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Test Class for file_uploads
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+/**
+ * Test Class for file_uploads
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_File_Uploads extends PhpSecInfo_Test_Core
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "file_uploads";
+
+ var $recommended_value = FALSE;
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->returnBytes(ini_get('file_uploads'));
+ }
+
+ /**
+ * Checks to see if expose_php is enabled
+ *
+ */
+ function _execTest() {
+
+ if ($this->current_value == $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'file_uploads are disabled. Unless you\'re sure you need them, this is the recommended setting');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'file_uploads are enabled. If you do not require file upload capability, consider disabling them.');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/gid.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/gid.php
new file mode 100644
index 0000000000..88a6f3c6c1
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/gid.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Test class for GID
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+
+/**
+ * the minimum "safe" UID that php should be executing as. This can vary,
+ * but in general 100 seems like a good min.
+ *
+ */
+define ('PHPSECINFO_MIN_SAFE_GID', 100);
+
+/**
+ * Test class for GID
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_Gid extends PhpSecInfo_Test_Core
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "group_id";
+
+ var $recommended_value = PHPSECINFO_MIN_SAFE_GID;
+
+
+ /**
+ * This test only works under Unix OSes
+ *
+ * @return boolean
+ */
+ function isTestable() {
+ if ($this->osIsWindows()) {
+ return false;
+ } elseif ($this->getUnixId() === false) {
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', 'Functions required to retrieve group ID not available');
+ return false;
+ }
+ return true;
+ }
+
+ function _retrieveCurrentValue() {
+ $id = $this->getUnixId();
+ if (is_array($id)) {
+ $lowest_gid = key($id['groups']);
+ $this->current_value = $lowest_gid;
+ } else {
+ $this->current_value = false;
+ }
+ }
+
+ /**
+ * Checks the GID of the PHP process to make sure it is above PHPSECINFO_MIN_SAFE_GID
+ *
+ * @see PHPSECINFO_MIN_SAFE_GID
+ */
+ function _execTest() {
+ if ($this->current_value >= $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_WARN;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'PHP is executing as what is probably a non-privileged group');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', 'PHP may be executing as a "privileged" group, which could be a serious security vulnerability.');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', 'This test will not run on Windows OSes');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/magic_quotes_gpc.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/magic_quotes_gpc.php
new file mode 100644
index 0000000000..89a0ff6f0d
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/magic_quotes_gpc.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Test Class for magic_quotes_gpc
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+/**
+ * Test Class for magic_quotes_gpc
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_Magic_Quotes_GPC extends PhpSecInfo_Test_Core
+{
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "magic_quotes_gpc";
+
+
+ var $recommended_value = FALSE;
+
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->getBooleanIniValue('magic_quotes_gpc');
+ }
+
+
+ /**
+ * magic_quotes_gpc has been removed since PHP 6.0
+ *
+ * @return boolean
+ */
+ function isTestable() {
+ return version_compare(PHP_VERSION, '6', '<') ;
+ }
+
+
+ /**
+ * Checks to see if allow_url_fopen is enabled
+ *
+ */
+ function _execTest() {
+ if ($this->current_value == $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', 'You are running PHP 6 or later and magic_quotes_gpc has been removed');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'magic_quotes_gpc is disabled, which is the recommended setting');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'magic_quotes_gpc is enabled. This
+ feature is inconsistent in blocking attacks, and can in some cases cause data loss with
+ uploaded files. You should <i>not</i> rely on magic_quotes_gpc to block attacks. It is
+ recommended that magic_quotes_gpc be disabled, and input filtering be handled by your PHP
+ scripts');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/memory_limit.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/memory_limit.php
new file mode 100644
index 0000000000..82a33d8db9
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/memory_limit.php
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Test Class for memory_limit setting
+ *
+ * @package PhpSecInfo
+ * @author Paul Reinheimer
+ * @author Ed Finkler
+ * @author Mark Wallaert <mark@autumnweave.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+/**
+ * The max recommended size for the memory_limit setting, in bytes
+ *
+ */
+define ('PHPSECINFO_MEMORY_LIMIT', 8*1024*1024);
+
+/**
+ * Test Class for memory_limit setting
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_Memory_Limit extends PhpSecInfo_Test_Core
+{
+
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "memory_limit";
+
+ var $recommended_value = PHPSECINFO_MEMORY_LIMIT;
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->returnBytes(ini_get('memory_limit'));
+ }
+
+
+ /**
+ * Check to see if the memory_limit setting is enabled.
+ *
+ * Test conditions and results:
+ * OK: memory_limit enabled and set to a value of 8MB or less.
+ * NOTICE: memory_limit enabled and set to a value greater than 8MB.
+ * WARNING: memory_limit disabled (compile time option).
+ *
+ * @return integer
+ */
+ function _execTest() {
+ if (!$this->current_value) {
+ return PHPSECINFO_TEST_RESULT_WARN;
+ } else if ($this->returnBytes($this->current_value) <= PHPSECINFO_MEMORY_LIMIT) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ * @access public
+ * @return null
+ */
+ function _setMessages() {
+ parent::_setMessages();
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'memory_limit is enabled, and appears to be set
+ to a realistic value.');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'memory_limit is set to a very high value. Are
+ you sure your apps require this much memory? If not, lower the limit, as certain attacks or poor
+ programming practices can lead to exhaustion of server resources. It is recommended that you set this
+ to a realistic value (8M for example) from which it can be expanded as required.');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', 'memory_limit does not appear to be enabled. This
+ leaves the server vulnerable to attacks that attempt to exhaust resources and creates an environment
+ where poor programming practices can propagate unchecked. This must be enabled at compile time by
+ including the parameter "--enable-memory-limit" in the configure line. Once enabled "memory_limit" may
+ be set in php.ini to define the maximum amount of memory a script is allowed to allocate.');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/open_basedir.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/open_basedir.php
new file mode 100644
index 0000000000..d5b0d282f6
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/open_basedir.php
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Test Class for open_basedir
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+/**
+ * Test Class for open_basedir
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_Open_Basedir extends PhpSecInfo_Test_Core
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "open_basedir";
+
+ var $recommended_value = TRUE;
+
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->getBooleanIniValue('open_basedir');
+ }
+
+
+ /**
+ * Checks to see if allow_url_fopen is enabled
+ *
+ */
+ function _execTest() {
+ if ($this->current_value == $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'open_basedir is enabled, which is the
+ recommended setting. Keep in mind that other web applications not written in PHP will not
+ be restricted by this setting.');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'open_basedir is disabled. When
+ this is enabled, only files that are in the
+ given directory/directories and their subdirectories can be read by PHP scripts.
+ You should consider turning this on. Keep in mind that other web applications not
+ written in PHP will not be restricted by this setting.');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/post_max_size.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/post_max_size.php
new file mode 100644
index 0000000000..09bd2474ec
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/post_max_size.php
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Test Class for post_max_size
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+/**
+ * The max recommended size for the post_max_size setting, in bytes
+ *
+ */
+define ('PHPSECINFO_POST_MAXLIMIT', 1024*256);
+
+/**
+ * Test Class for post_max_size
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_Post_Max_Size extends PhpSecInfo_Test_Core
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "post_max_size";
+
+ var $recommended_value = PHPSECINFO_POST_MAXLIMIT;
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->returnBytes(ini_get('post_max_size'));
+ }
+
+ /**
+ * Check to see if the post_max_size setting is enabled.
+ */
+ function _execTest() {
+
+ if ($this->current_value
+ && $this->current_value <= $this->recommended_value
+ && $post_max_size != -1) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'post_max_size is enabled, and appears to
+ be a relatively low value');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'post_max_size is not enabled, or is set to
+ a high value. Allowing a large value may open up your server to denial-of-service attacks');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/register_globals.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/register_globals.php
new file mode 100644
index 0000000000..1caa7e8e30
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/register_globals.php
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Test Class for register_globals
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+
+/**
+ * Test Class for register_globals
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_Register_Globals extends PhpSecInfo_Test_Core
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "register_globals";
+
+
+ var $recommended_value = FALSE;
+
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->getBooleanIniValue('register_globals');
+ }
+
+
+ /**
+ * register_globals has been removed since PHP 6.0
+ *
+ * @return boolean
+ */
+ function isTestable() {
+ return version_compare(PHP_VERSION, '6', '<') ;
+ }
+
+
+
+ /**
+ * Checks to see if allow_url_fopen is enabled
+ *
+ */
+ function _execTest() {
+ if ($this->current_value == $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_WARN;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', 'You are running PHP 6 or later and register_globals has been removed');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'register_globals is disabled, which is the recommended setting');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', 'register_globals is enabled. This could be a serious security risk. You should disable register_globals immediately');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/uid.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/uid.php
new file mode 100644
index 0000000000..cbc3ae13ec
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/uid.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Test class for UID
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+
+/**
+ * the minimum "safe" UID that php should be executing as. This can vary,
+ * but in general 100 seems like a good min.
+ *
+ */
+define ('PHPSECINFO_MIN_SAFE_UID', 100);
+
+/**
+ * Test class for UID
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_Uid extends PhpSecInfo_Test_Core
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "user_id";
+
+ var $recommended_value = PHPSECINFO_MIN_SAFE_UID;
+
+ /**
+ * This test only works under Unix OSes
+ *
+ * @return boolean
+ */
+ function isTestable() {
+ if ($this->osIsWindows()) {
+ return false;
+ } elseif ($this->getUnixId() === false) {
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', 'Functions required to retrieve user ID not available');
+ return false;
+ }
+ return true;
+ }
+
+
+ function _retrieveCurrentValue() {
+ $id = $this->getUnixId();
+ if (is_array($id)) {
+ $this->current_value = $id['uid'];
+ } else {
+ $this->current_value = false;
+ }
+
+ }
+
+ /**
+ * Checks the GID of the PHP process to make sure it is above PHPSECINFO_MIN_SAFE_UID
+ *
+ * @see PHPSECINFO_MIN_SAFE_UID
+ */
+ function _execTest() {
+ if ($this->current_value >= $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_WARN;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'PHP is executing as what is probably a non-privileged user');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', 'PHP may be executing as a "privileged" user, which could be a serious security vulnerability.');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', 'This test will not run on Windows OSes');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/upload_max_filesize.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/upload_max_filesize.php
new file mode 100644
index 0000000000..bc0b66b42b
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/upload_max_filesize.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Test Class for upload_max_filesize
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+/**
+ * The max recommended size for the upload_max_filesize setting, in bytes
+ *
+ */
+define ('PHPSECINFO_UPLOAD_MAXLIMIT', 1024*256);
+
+
+/**
+ * Test Class for upload_max_filesize
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_Upload_Max_Filesize extends PhpSecInfo_Test_Core
+{
+
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "upload_max_filesize";
+
+ var $recommended_value = PHPSECINFO_UPLOAD_MAXLIMIT;
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->returnBytes(ini_get('upload_max_filesize'));
+ }
+
+ /**
+ * Check to see if the post_max_size setting is enabled.
+ */
+ function _execTest() {
+
+ if ($this->current_value
+ && $this->current_value <= $this->recommended_value
+ && $post_max_size != -1) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'upload_max_filesize is enabled, and appears to be a relatively low value.');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'upload_max_filesize is not enabled, or is set to a high value. Are you sure your apps require uploading files of this size? If not, lower the limit, as large file uploads can impact server performance');
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Core/upload_tmp_dir.php b/plugins/SecurityInfo/PhpSecInfo/Test/Core/upload_tmp_dir.php
new file mode 100644
index 0000000000..729c702daf
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Core/upload_tmp_dir.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Test Class for upload_tmp_dir
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Core.php');
+
+/**
+ * Test Class for upload_tmp_dir
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core_Upload_Tmp_Dir extends PhpSecInfo_Test_Core
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "upload_tmp_dir";
+
+ var $recommended_value = "A non-world readable/writable directory";
+
+ function _retrieveCurrentValue() {
+ $this->current_value = ini_get('upload_tmp_dir');
+
+ if( empty($this->current_value) ) {
+ if (function_exists("sys_get_temp_dir")) {
+ $this->current_value = sys_get_temp_dir();
+ } else {
+ $this->current_value = $this->sys_get_temp_dir();
+ }
+ }
+ }
+
+ /**
+ * We are disabling this function on Windows OSes right now until
+ * we can be certain of the proper way to check world-readability
+ *
+ * @return unknown
+ */
+ function isTestable() {
+ if ($this->osIsWindows()) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+
+ /**
+ * Check if upload_tmp_dir matches PHPSECINFO_TEST_COMMON_TMPDIR, or is word-writable
+ *
+ * This is still unix-specific, and it's possible that for now
+ * this test should be disabled under Windows builds.
+ *
+ * @see PHPSECINFO_TEST_COMMON_TMPDIR
+ */
+ function _execTest() {
+
+ $perms = fileperms($this->current_value);
+
+ if ($this->current_value
+ && !preg_match("|".PHPSECINFO_TEST_COMMON_TMPDIR."/?|", $this->current_value)
+ && ! ($perms & 0x0004)
+ && ! ($perms & 0x0002) ) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ // rewrite current_value to display perms
+ $this->current_value .= " (".substr(sprintf('%o', $perms), -4).")";
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', 'Test not run -- currently disabled on Windows OSes');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'upload_tmp_dir is enabled, which is the
+ recommended setting. Make sure your upload_tmp_dir path is not world-readable');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'upload_tmp_dir is disabled, or is set to a
+ common world-writable directory. This typically allows other users on this server
+ to access temporary copies of files uploaded via your PHP scripts. You should set
+ upload_tmp_dir to a non-world-readable directory');
+ }
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Curl/file_support.php b/plugins/SecurityInfo/PhpSecInfo/Test/Curl/file_support.php
new file mode 100644
index 0000000000..816d747259
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Curl/file_support.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Test class for CURL file_support
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+/**
+ * require the PhpSecInfo_Test_Curl class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Curl.php');
+
+/**
+ * Test class for CURL file_support
+ *
+ * Checks for CURL file:// support; if this is installed, it can be used to bypass
+ * safe_mode and open_basedir
+ *
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+class PhpSecInfo_Test_Curl_File_Support extends PhpSecInfo_Test_Curl
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "file_support";
+
+ var $recommended_value = '5.1.6+ or 4.4.4+';
+
+ function _retrieveCurrentValue() {
+ $this->current_value = PHP_VERSION;
+ }
+
+
+ /**
+ * Checks to see if libcurl's "file://" support is enabled by examining the "protocols" array
+ * in the info returned from curl_version()
+ * @return integer
+ *
+ */
+ function _execTest() {
+
+ $curlinfo = curl_version();
+
+ if ( version_compare($this->current_value, '5.1.6', '>=') ||
+ (version_compare($this->current_value, '4.4.4', '>=')) && ( version_compare($this->current_value, '5', '<') )
+ ) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ } else {
+ return PHPSECINFO_TEST_RESULT_WARN;
+ }
+
+ }
+
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', "You are running PHP 4.4.4 or higher, or PHP 5.1.6 or higher. These versions fix the security hole present in the cURL functions that allow it to bypass safe_mode and open_basedir restrictions.");
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', "A security hole present in your version of PHP allows the cURL functions to bypass safe_mode and open_basedir restrictions. You should upgrade to the latest version of PHP.");
+
+ }
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Session/save_path.php b/plugins/SecurityInfo/PhpSecInfo/Test/Session/save_path.php
new file mode 100644
index 0000000000..5a7ae7752e
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Session/save_path.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Test class for session save_path
+ *
+ * @package PhpSecInfo
+ * @author Thomas CORBIERE <thomas@votre-grandeur-celeste.com>
+ */
+
+/**
+ * require the PhpSecInfo_Test_Core class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Session.php');
+
+/**
+ * Test class for session save_path
+ *
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Session_Save_Path extends PhpSecInfo_Test_Session
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "save_path";
+
+ var $recommended_value = "A non-world readable/writable directory";
+
+ function _retrieveCurrentValue() {
+ $this->current_value = ini_get('session.save_path');
+
+ if( empty($this->current_value) ) {
+ if (function_exists("sys_get_temp_dir")) {
+ $this->current_value = sys_get_temp_dir();
+ } else {
+ $this->current_value = $this->sys_get_temp_dir();
+ }
+ }
+ }
+
+
+ /**
+ * We are disabling this function on Windows OSes right now until
+ * we can be certain of the proper way to check world-readability
+ *
+ * @return unknown
+ */
+ function isTestable() {
+ if ($this->osIsWindows()) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+ }
+
+
+ /**
+ * Check if session.save_path matches PHPSECINFO_TEST_COMMON_TMPDIR, or is word-writable
+ *
+ * This is still unix-specific, and it's possible that for now
+ * this test should be disabled under Windows builds.
+ *
+ * @see PHPSECINFO_TEST_COMMON_TMPDIR
+ */
+ function _execTest() {
+
+ $perms = fileperms($this->current_value);
+
+ if ($this->current_value
+ && !preg_match("|".PHPSECINFO_TEST_COMMON_TMPDIR."/?|", $this->current_value)
+ && ! ($perms & 0x0004)
+ && ! ($perms & 0x0002) ) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ // rewrite current_value to display perms
+ $this->current_value .= " (".substr(sprintf('%o', $perms), -4).")";
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', 'Test not run -- currently disabled on Windows OSes');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'save_path is enabled, which is the
+ recommended setting. Make sure your save_path path is not world-readable');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'save_path is disabled, or is set to a
+ common world-writable directory. This typically allows other users on this server
+ to access session files. You should set save_path to a non-world-readable directory');
+ }
+
+}
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Session/use_trans_sid.php b/plugins/SecurityInfo/PhpSecInfo/Test/Session/use_trans_sid.php
new file mode 100644
index 0000000000..f7f3f2e4a9
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Session/use_trans_sid.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Test class for session use_trans_sid
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the PhpSecInfo_Test_Session class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Session.php');
+
+/**
+ * Test class for session use_trans_sid
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+class PhpSecInfo_Test_Session_Use_Trans_Sid extends PhpSecInfo_Test_Session
+{
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = "use_trans_sid";
+
+
+ var $recommended_value = FALSE;
+
+
+ function _retrieveCurrentValue() {
+ $this->current_value = $this->getBooleanIniValue('session.use_trans_sid');
+ }
+
+
+ /**
+ * Checks to see if allow_url_fopen is enabled
+ *
+ */
+ function _execTest() {
+ if ($this->current_value == $this->recommended_value) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ }
+
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+
+
+ /**
+ * Set the messages specific to this test
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'use_trans_sid is disabled, which is the recommended setting');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'use_trans_sid is enabled. This makes session hijacking easier. Consider disabling this feature');
+
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Suhosin/extension.php b/plugins/SecurityInfo/PhpSecInfo/Test/Suhosin/extension.php
new file mode 100644
index 0000000000..50e4d05359
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Suhosin/extension.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Test class for Suhosin extension
+ *
+ * @package PhpSecInfo
+ * @author Piwik
+ */
+
+/**
+ * require the PhpSecInfo_Test_Suhosin class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Suhosin.php');
+
+/**
+ * Test class for Suhosin extension
+ *
+ * Checks for suhosin extension
+ *
+ * @package PhpSecInfo
+ * @author Piwik
+ */
+class PhpSecInfo_Test_Suhosin_Extension extends PhpSecInfo_Test_Suhosin
+{
+ var $test_name = "Suhosin extension";
+
+ var $recommended_value = true;
+
+ function _retrieveCurrentValue() {
+ $this->current_value = extension_loaded('suhosin');
+ }
+
+ function _execTest() {
+ if ( $this->current_value === true ) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ } else {
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+ }
+
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', "You are running PHP with the Suhosin extension loaded. This extension provides high-level runtime protections, and additional filtering and logging features.");
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', "You are not running PHP with the Suhosin extension loaded. We recommend both the patch and extension for low- and high-level protections including transparent cookie encryption and remote inclusion vulnerabilities.");
+ }
+}
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Suhosin/patch.php b/plugins/SecurityInfo/PhpSecInfo/Test/Suhosin/patch.php
new file mode 100644
index 0000000000..bd8bf5f827
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Suhosin/patch.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Test class for Suhosin patch
+ *
+ * @package PhpSecInfo
+ * @author Piwik
+ */
+
+/**
+ * require the PhpSecInfo_Test_Suhosin class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test_Suhosin.php');
+
+/**
+ * Test class for Suhosin
+ *
+ * Checks for Suhosin patch which implements low-level protections against bufferoverflows or format string vulnerabilities
+ *
+ * @package PhpSecInfo
+ * @author Piwik
+ */
+class PhpSecInfo_Test_Suhosin_Patch extends PhpSecInfo_Test_Suhosin
+{
+ var $test_name = "Suhosin patch";
+
+ var $recommended_value = true;
+
+ function _retrieveCurrentValue() {
+ if (preg_match('/Suhosin/', $_SERVER['SERVER_SOFTWARE'])) {
+ $this->current_value = true;
+ } else {
+ $this->current_value = false;
+
+ $constants = get_defined_constants(false);
+ if(isset($constants['SUHOSIN_PATCH']) && $constants['SUHOSIN_PATCH'] == 1) {
+ $this->current_value = true;
+ }
+ }
+ }
+
+ function _execTest() {
+ if ( $this->current_value === true ) {
+ return PHPSECINFO_TEST_RESULT_OK;
+ } else {
+ return PHPSECINFO_TEST_RESULT_NOTICE;
+ }
+ }
+
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', "You are running PHP with the Suhosin patch applied against the PHP core. This patch implements various low-level protections against (for example) buffer overflows and format string vulnerabilities.");
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', "You are not running PHP with the Suhosin patch applied. We recommend both the patch and extension for low- and high-level protections against (for example) buffer overflows and format string vulnerabilities.");
+ }
+}
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Test.php b/plugins/SecurityInfo/PhpSecInfo/Test/Test.php
new file mode 100644
index 0000000000..5b577dfece
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Test.php
@@ -0,0 +1,571 @@
+<?php
+/**
+ * Skeleton Test class file
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+/**
+ * require the main PhpSecInfo class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/PhpSecInfo.php');
+
+
+
+define ('PHPSECINFO_TEST_RESULT_OK', -1);
+
+define ('PHPSECINFO_TEST_RESULT_NOTICE', -2);
+
+define ('PHPSECINFO_TEST_RESULT_WARN', -4);
+
+define ('PHPSECINFO_TEST_RESULT_ERROR', -1024);
+
+define ('PHPSECINFO_TEST_RESULT_NOTRUN', -2048);
+
+define ('PHPSECINFO_TEST_COMMON_TMPDIR', '/tmp');
+
+define ('PHPSECINFO_TEST_MOREINFO_BASEURL', 'http://phpsec.org/projects/phpsecinfo/tests/');
+
+/**
+ * This is a skeleton class for PhpSecInfo tests You should extend this to make a "group" skeleton
+ * to categorize tests under, then make a subdir with your group name that contains test classes
+ * extending your group skeleton class.
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test
+{
+
+ /**
+ * This value is used to group test results together.
+ *
+ * For example, all tests related to the mysql lib should be grouped under "mysql."
+ *
+ * @var string
+ */
+ var $test_group = 'misc';
+
+
+ /**
+ * This should be a <b>unique</b>, human-readable identifier for this test
+ *
+ * @var string
+ */
+ var $test_name = 'misc_test';
+
+
+ /**
+ * This is the recommended value the test will be looking for
+ *
+ * @var mixed
+ */
+ var $recommended_value = "bar";
+
+
+ /**
+ * The result returned from the test
+ *
+ * @var integer
+ */
+ var $_result = PHPSECINFO_TEST_RESULT_NOTRUN;
+
+
+ /**
+ * The message corresponding to the result of the test
+ *
+ * @var string
+ */
+ var $_message;
+
+
+ /**
+ * the language code. Should be a pointer to the setting in the PhpSecInfo object
+ *
+ * @var string
+ */
+ var $_language = PHPSECINFO_LANG_DEFAULT;
+
+ /**
+ * Enter description here...
+ *
+ * @var mixed
+ */
+ var $current_value;
+
+ /**
+ * This is a hash of messages that correspond to various test result levels.
+ *
+ * There are five messages, each corresponding to one of the result constants
+ * (PHPSECINFO_TEST_RESULT_OK, PHPSECINFO_TEST_RESULT_NOTICE, PHPSECINFO_TEST_RESULT_WARN,
+ * PHPSECINFO_TEST_RESULT_ERROR, PHPSECINFO_TEST_RESULT_NOTRUN)
+ *
+ *
+ * @var array array
+ */
+ var $_messages = array();
+
+
+
+
+ /**
+ * Constructor for Test skeleton class
+ *
+ * @return PhpSecInfo_Test
+ */
+ function PhpSecInfo_Test() {
+ //$this->_setTestValues();
+
+ $this->_retrieveCurrentValue();
+ //$this->setRecommendedValue();
+
+ $this->_setMessages();
+ }
+
+
+ /**
+ * Determines whether or not it's appropriate to run this test (for example, if
+ * this test is for a particular library, it shouldn't be run if the lib isn't
+ * loaded).
+ *
+ * This is a terrible name, but I couldn't think of a better one atm.
+ *
+ * @return boolean
+ */
+ function isTestable() {
+
+ return true;
+ }
+
+
+ /**
+ * The "meat" of the test. This is where the real test code goes. You should override this when extending
+ *
+ * @return integer
+ */
+ function _execTest() {
+
+ return PHPSECINFO_TEST_RESULT_NOTRUN;
+ }
+
+
+ /**
+ * This function loads up result messages into the $this->_messages array.
+ *
+ * Using this method rather than setting $this->_messages directly allows result
+ * messages to be inherited. This is broken out into a separate function rather
+ * than the constructor for ease of extension purposes (php4 is whack, man).
+ *
+ */
+ function _setMessages() {
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_OK, 'en', 'This setting should be safe');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTICE, 'en', 'This could potentially be a security issue');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_WARN, 'en', 'This setting may be a serious security problem');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_ERROR, 'en', 'There was an error running this test');
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', 'This test cannot be run');
+ }
+
+
+ /**
+ * Placeholder - extend for tests
+ *
+ */
+ function _retrieveCurrentValue() {
+ $this->current_value = "foo";
+ }
+
+
+
+ /**
+ * This is the wrapper that executes the test and sets the result code and message
+ */
+ function test() {
+ $result = $this->_execTest();
+ $this->_setResult($result);
+
+ }
+
+
+
+ /**
+ * Retrieves the result
+ *
+ * @return integer
+ */
+ function getResult() {
+ return $this->_result;
+ }
+
+
+
+
+ /**
+ * Retrieves the message for the current result
+ *
+ * @return string
+ */
+ function getMessage() {
+ if (!isset($this->_message) || empty($this->_message)) {
+ $this->_setMessage($this->_result, $this->_language);
+ }
+
+ return $this->_message;
+ }
+
+
+
+ /**
+ * Sets the message for a given result code and language
+ *
+ * <code>
+ * $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', 'This test cannot be run');
+ * </code>
+ *
+ * @param integer $result_code
+ * @param string $language_code
+ * @param string $message
+ *
+ */
+ function setMessageForResult($result_code, $language_code, $message) {
+
+ if ( !isset($this->_messages[$result_code]) ) {
+ $this->_messages[$result_code] = array();
+ }
+
+ if ( !is_array($this->_messages[$result_code]) ) {
+ $this->_messages[$result_code] = array();
+ }
+
+ $this->_messages[$result_code][$language_code] = $message;
+
+ }
+
+
+
+
+ /**
+ * returns the current value. This function should be used to access the
+ * value for display. All values are cast as strings
+ *
+ * @return string
+ */
+ function getCurrentTestValue() {
+ return $this->getStringValue($this->current_value);
+ }
+
+ /**
+ * returns the recommended value. This function should be used to access the
+ * value for display. All values are cast as strings
+ *
+ * @return string
+ */
+ function getRecommendedTestValue() {
+ return $this->getStringValue($this->recommended_value);
+ }
+
+
+ /**
+ * Sets the result code
+ *
+ * @param integer $result_code
+ */
+ function _setResult($result_code) {
+ $this->_result = $result_code;
+ }
+
+
+ /**
+ * Sets the $this->_message variable based on the passed result and language codes
+ *
+ * @param integer $result_code
+ * @param string $language_code
+ */
+ function _setMessage($result_code, $language_code) {
+ $messages = $this->_messages[$result_code];
+ $message = $messages[$language_code];
+ $this->_message = $message;
+ }
+
+
+ /**
+ * Returns a link to a page with detailed information about the test
+ *
+ * URL is formatted as PHPSECINFO_TEST_MOREINFO_BASEURL + testName
+ *
+ * @see PHPSECINFO_TEST_MOREINFO_BASEURL
+ *
+ * @return string|boolean
+ */
+ function getMoreInfoURL() {
+ if ($tn = $this->getTestName()) {
+ return PHPSECINFO_TEST_MOREINFO_BASEURL.strtolower("{$tn}.html");
+ } else {
+ return false;
+ }
+ }
+
+
+
+
+ /**
+ * This retrieves the name of this test.
+ *
+ * If a name has not been set, this returns a formatted version of the class name.
+ *
+ * @return string
+ */
+ function getTestName() {
+ if (isset($this->test_name) && !empty($this->test_name)) {
+ return $this->test_name;
+ } else {
+ return ucwords(
+ str_replace('_', ' ',
+ get_class($this)
+ )
+ );
+ }
+
+ }
+
+
+ /**
+ * sets the test name
+ *
+ * @param string $test_name
+ */
+ function setTestName($test_name) {
+ $this->test_name = $test_name;
+ }
+
+
+ /**
+ * Returns the test group this test belongs to
+ *
+ * @return string
+ */
+ function getTestGroup() {
+ return $this->test_group;
+ }
+
+
+ /**
+ * sets the test group
+ *
+ * @param string $test_group
+ */
+ function setTestGroup($test_group) {
+ $this->test_group = $test_group;
+ }
+
+
+ /**
+ * This function takes the shorthand notation used in memory limit settings for PHP
+ * and returns the byte value. Totally stolen from http://us3.php.net/manual/en/function.ini-get.php
+ *
+ * <code>
+ * echo 'post_max_size in bytes = ' . $this->return_bytes(ini_get('post_max_size'));
+ * </code>
+ *
+ * @link http://php.net/manual/en/function.ini-get.php
+ * @param string $val
+ * @return integer
+ */
+ function returnBytes($val) {
+ $val = trim($val);
+
+ if ( (int)$val === 0 ) {
+ return 0;
+ }
+
+ $last = strtolower($val{strlen($val)-1});
+ switch($last) {
+ // The 'G' modifier is available since PHP 5.1.0
+ case 'g':
+ $val *= 1024;
+ case 'm':
+ $val *= 1024;
+ case 'k':
+ $val *= 1024;
+ }
+
+ return $val;
+ }
+
+
+ /**
+ * This just does the usual PHP string casting, except for
+ * the boolean FALSE value, where the string "0" is returned
+ * instead of an empty string
+ *
+ * @param mixed $val
+ * @return string
+ */
+ function getStringValue($val) {
+ if ($val === FALSE) {
+ return "0";
+ } else {
+ return (string)$val;
+ }
+ }
+
+
+ /**
+ * This method converts the several possible return values from
+ * allegedly "boolean" ini settings to proper booleans
+ *
+ * Properly converted input values are: 'off', 'on', 'false', 'true', '', '0', '1'
+ * (the last two might not be neccessary, but I'd rather be safe)
+ *
+ * If the ini_value doesn't match any of those, the value is returned as-is.
+ *
+ * @param string $ini_key the ini_key you need the value of
+ * @return boolean|mixed
+ */
+ function getBooleanIniValue($ini_key) {
+
+ $ini_val = ini_get($ini_key);
+
+ switch ( strtolower($ini_val) ) {
+
+ case 'off':
+ return false;
+ break;
+ case 'on':
+ return true;
+ break;
+ case 'false':
+ return false;
+ break;
+ case 'true':
+ return true;
+ break;
+ case '0':
+ return false;
+ break;
+ case '1':
+ return true;
+ break;
+ case '':
+ return false;
+ break;
+ default:
+ return $ini_val;
+
+ }
+
+ }
+
+ /**
+ * sys_get_temp_dir provides some temp dir detection capability
+ * that is lacking in versions of PHP that do not have the
+ * sys_get_temp_dir() function
+ *
+ * @return string|NULL
+ */
+ function sys_get_temp_dir() {
+ // Try to get from environment variable
+ if ( !empty($_ENV['TMP']) ) {
+ return realpath( $_ENV['TMP'] );
+ } else if ( !empty($_ENV['TMPDIR']) ) {
+ return realpath( $_ENV['TMPDIR'] );
+ } else if ( !empty($_ENV['TEMP']) ) {
+ return realpath( $_ENV['TEMP'] );
+ } else {
+ return NULL;
+ }
+ }
+
+
+ /**
+ * A quick function to determine whether we're running on Windows.
+ * Uses the PHP_OS constant.
+ *
+ * @return boolean
+ */
+ function osIsWindows() {
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Returns an array of data returned from the UNIX 'id' command
+ *
+ * includes uid, username, gid, groupname, and groups (if "exec"
+ * is enabled). Groups is an array of all the groups the user
+ * belongs to. Keys are the group ids, values are the group names.
+ *
+ * returns FALSE if no suitable function is available to retrieve
+ * the data
+ *
+ * @return array|boolean
+ */
+ function getUnixId() {
+
+ if ($this->osIsWindows()) {
+ return false;
+ }
+
+ $success = false;
+
+
+ if (function_exists("exec") && !PhpSecInfo_Test::getBooleanIniValue('safe_mode')) {
+ $id_raw = exec('id');
+ // uid=1000(coj) gid=1000(coj) groups=1000(coj),1001(admin)
+ preg_match( "|uid=(\d+)\((\S+)\)\s+gid=(\d+)\((\S+)\)\s+groups=(.+)|i",
+ $id_raw,
+ $matches);
+
+ if (!$matches) {
+ /**
+ * for some reason the output from 'id' wasn't as we expected.
+ * return false so the test doesn't run.
+ */
+ $success = false;
+ } else {
+ $id_data = array( 'uid'=>$matches[1],
+ 'username'=>$matches[2],
+ 'gid'=>$matches[3],
+ 'group'=>$matches[4] );
+
+ if ($matches[5]) {
+ $gs = $matches[5];
+ $gs = explode(',', $gs);
+ foreach ($gs as $groupstr) {
+ preg_match("/(\d+)\(([^\)]+)\)/", $groupstr, $subs);
+ $groups[$subs[1]] = $subs[2];
+ }
+ ksort($groups);
+ $id_data['groups'] = $groups;
+ }
+ $success = true;
+ }
+
+ }
+
+ if (!$success && function_exists("posix_getpwuid") && function_exists("posix_geteuid")
+ && function_exists('posix_getgrgid') && function_exists('posix_getgroups') ) {
+ $data = posix_getpwuid( posix_getuid() );
+ $id_data['uid'] = $data['uid'];
+ $id_data['username'] = $data['name'];
+ $id_data['gid'] = $data['gid'];
+ //$group_data = posix_getgrgid( posix_getegid() );
+ //$id_data['group'] = $group_data['name'];
+ $groups = posix_getgroups();
+ foreach ( $groups as $gid ) {
+ //$group_data = posix_getgrgid(posix_getgid());
+ $id_data['groups'][$gid] = '<unknown>';
+ }
+ $success = true;
+ }
+
+ if ($success) {
+ return $id_data;
+ } else {
+ return false;
+ }
+ }
+
+}
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Test_Application.php b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Application.php
new file mode 100644
index 0000000000..af7a2f9926
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Application.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Skeleton Test class file for Application group
+ *
+ * @package PhpSecInfo
+ * @author Anthon Pang
+ */
+
+/**
+ * require the main PhpSecInfo class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test.php');
+
+
+
+/**
+ * This is a skeleton class for PhpSecInfo "Application" tests
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Application extends PhpSecInfo_Test
+{
+
+ /**
+ * This value is used to group test results together.
+ *
+ * For example, all tests related to the mysql lib should be grouped under "mysql."
+ *
+ * @var string
+ */
+ var $test_group = 'Application';
+
+
+ /**
+ * "Application" tests should pretty much be always testable, so the default is just to return true
+ *
+ * @return boolean
+ */
+ function isTestable() {
+ return Piwik_Http::getTransportMethod() !== null;
+ }
+
+ function getMoreInfoURL() {
+ $urls = array(
+ 'Piwik' => 'http://piwik.org/changelog',
+ 'PHP' => 'http://php.net/',
+ );
+
+ if ($tn = $this->getTestName()) {
+ return $urls[$tn];
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Test_Cgi.php b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Cgi.php
new file mode 100644
index 0000000000..6843a59afa
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Cgi.php
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Skeleton Test class file for Cgi group
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+/**
+ * require the main PhpSecInfo class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test.php');
+
+
+
+/**
+ * This is a skeleton class for PhpSecInfo "CGI" tests
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Cgi extends PhpSecInfo_Test
+{
+
+ /**
+ * This value is used to group test results together.
+ *
+ * For example, all tests related to the mysql lib should be grouped under "mysql."
+ *
+ * @var string
+ */
+ var $test_group = 'CGI';
+
+
+
+ /**
+ * "CGI" tests should only be run if we're running as a CGI. The best way I could think of
+ * to test this was to preg against the php_sapi_name() return value.
+ *
+ * @return boolean
+ */
+ function isTestable() {
+ /*if ( preg_match('/^cgi.*$/', php_sapi_name()) ) {
+ return true;
+ } else {
+ return false;
+ }*/
+ return strpos(php_sapi_name(), 'cgi') === 0;
+ }
+
+
+ /**
+ * Set the messages for CGI tests
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', "You don't seem to be using the CGI SAPI");
+
+ }
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Test_Core.php b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Core.php
new file mode 100644
index 0000000000..58230794d2
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Core.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Skeleton Test class file for Core group
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+/**
+ * require the main PhpSecInfo class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test.php');
+
+
+
+/**
+ * This is a skeleton class for PhpSecInfo "Core" tests
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Core extends PhpSecInfo_Test
+{
+
+ /**
+ * This value is used to group test results together.
+ *
+ * For example, all tests related to the mysql lib should be grouped under "mysql."
+ *
+ * @var string
+ */
+ var $test_group = 'Core';
+
+
+ /**
+ * "Core" tests should pretty much be always testable, so the default is just to return true
+ *
+ * @return boolean
+ */
+ function isTestable() {
+
+ return true;
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Test_Curl.php b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Curl.php
new file mode 100644
index 0000000000..a1e7d57a6f
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Curl.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Skeleton Test class file for ` group
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+/**
+ * require the main PhpSecInfo class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test.php');
+
+
+
+/**
+ * This is a skeleton class for PhpSecInfo "Curl" tests
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Curl extends PhpSecInfo_Test
+{
+
+ /**
+ * This value is used to group test results together.
+ *
+ * For example, all tests related to the mysql lib should be grouped under "mysql."
+ *
+ * @var string
+ */
+ var $test_group = 'Curl';
+
+
+
+ /**
+ * "Curl" tests should only be run if the curl extension is installed. We can check
+ * for this by seeing if the function curl_init() is defined
+ *
+ * @return boolean
+ */
+ function isTestable() {
+/* if ( function_exists('curl_init') ) {
+ return true;
+ } else {
+ return false;
+ }
+*/
+ return extension_loaded('curl');
+ }
+
+
+ /**
+ * Set the messages for Curl tests
+ *
+ */
+ function _setMessages() {
+ parent::_setMessages();
+
+ $this->setMessageForResult(PHPSECINFO_TEST_RESULT_NOTRUN, 'en', "CURL support is not enabled in your PHP install");
+
+ }
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Test_Session.php b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Session.php
new file mode 100644
index 0000000000..5270fa62c4
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Session.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Skeleton Test class file for Session group
+ *
+ * @package PhpSecInfo
+ * @author Ed Finkler <coj@funkatron.com>
+ */
+
+
+/**
+ * require the main PhpSecInfo class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test.php');
+
+
+
+/**
+ * This is a skeleton class for PhpSecInfo "Session" tests
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Session extends PhpSecInfo_Test
+{
+
+ /**
+ * This value is used to group test results together.
+ *
+ * For example, all tests related to the mysql lib should be grouped under "mysql."
+ *
+ * @var string
+ */
+ var $test_group = 'Session';
+
+
+ /**
+ * "Session" tests should pretty much be always testable, so the default is
+ * just to return true
+ *
+ * @return boolean
+ */
+ function isTestable() {
+
+ return true;
+ }
+
+
+} \ No newline at end of file
diff --git a/plugins/SecurityInfo/PhpSecInfo/Test/Test_Suhosin.php b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Suhosin.php
new file mode 100644
index 0000000000..c9a9b3a779
--- /dev/null
+++ b/plugins/SecurityInfo/PhpSecInfo/Test/Test_Suhosin.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Skeleton Test class file for Suhosin group
+ *
+ * @package PhpSecInfo
+ * @author Anthon Pang
+ */
+
+/**
+ * require the main PhpSecInfo class
+ */
+require_once(PHPSECINFO_BASE_DIR.'/Test/Test.php');
+
+
+
+/**
+ * This is a skeleton class for PhpSecInfo "Suhosin" tests
+ * @package PhpSecInfo
+ */
+class PhpSecInfo_Test_Suhosin extends PhpSecInfo_Test
+{
+
+ /**
+ * This value is used to group test results together.
+ *
+ * For example, all tests related to the mysql lib should be grouped under "mysql."
+ *
+ * @var string
+ */
+ var $test_group = 'Suhosin';
+
+
+ /**
+ * "Suhosin" tests should pretty much be always testable, so the default is just to return true
+ *
+ * @return boolean
+ */
+ function isTestable() {
+
+ return true;
+ }
+
+ function getMoreInfoURL() {
+ if ($tn = $this->getTestName()) {
+ return 'http://www.hardened-php.net/suhosin/index.html';
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/plugins/SecurityInfo/README b/plugins/SecurityInfo/README
new file mode 100644
index 0000000000..6f6f0cd45c
--- /dev/null
+++ b/plugins/SecurityInfo/README
@@ -0,0 +1,89 @@
+## PHPSECINFO
+
+*Now on GitHub*
+
+_see LICENSE for copyright and license info_
+
+Mailing List for bug reports, feedback, etc:
+http://lists.phpsec.org/mailman/listinfo/phpsecinfo
+
+
+### WHAT IS PHPSECINFO?
+PHPSecInfo is a PHP environment security auditing tool modeled after the
+phpsecinfo() function. From a single function call, PHPSecInfo runs a
+series of tests on your PHP environment to identify potential security
+issues and offer suggestions. It can be useful as part of a multilayered
+security approach.
+
+
+#### WHAT IS PHPSECINFO NOT?
+* It is not a replacement for secure coding practices
+* It does not audit PHP code
+* It is not comprehensive test for either your hosting environment
+ or your web application
+* It is not the "final word." PHPSecInfo identifies *potential* problems
+ and offers suggestions for improvement. Your environment may _require_
+ certain settings that trigger cautions or warnings.
+
+
+### HOW DO I USE PHPSECINFO?
+
+The simplest way:
+
+* Uncompress and upload the contents of the archive to your web server's
+ document root
+* Open a browser and view the index.php file where you've uploaded the files
+ (probably something like http://www.yourdomain.com/phpsecinfo/index.php)
+
+
+### WHAT DO I DO IF I GET A NOTICE OR WARNING?
+
+Read the explanation of the result carefully. Research the issue on-line
+-- resources like the php.net official docs and the PHP Security Guide are
+very useful. Investigate why your environment is set up in such a way. If
+there's not a compelling reason to keep it as-is, you should probably
+
+A by no means comprehensive list of resources to get your started:
+
+Web Sites:
+http://www.php.net/manual/en/security.php
+http://phpsec.org/projects/guide/
+
+Books:
+http://phparch.com/pgps
+http://phpsecurity.org/
+http://apachesecurity.net/
+
+
+### HOW CAN I CUSTOMIZE THE OUTPUT OF PHPSECINFO?
+
+PHPSecInfo is intended to be used as a self-contained tool. However, you
+can obtain the test results in an array and then present this data in your
+preferred format.
+
+Example:
+<code>
+require_once('PhpSecInfo/PhpSecInfo.php');
+// instantiate the class
+$psi = new PhpSecInfo();
+
+// load and run all tests
+$psi->loadAndRun();
+
+// grab the results as a multidimensional array
+$results = $psi->getResultsAsArray();
+echo "<pre>"; echo print_r($results, true); echo "</pre>";
+
+// grab the standard results output as a string
+$html = $psi->getOutput();
+
+// send it to the browser
+echo $html;
+</code>
+
+
+### HOW CAN I OFFER FEEDBACK, REPORT BUGS, COMPLAIN, ETC.?
+
+The best way is to subscribe to and post on the PHPSecInfo Mailing List:
+
+http://lists.phpsec.org/mailman/listinfo/phpsecinfo
diff --git a/plugins/SecurityInfo/SecurityInfo.php b/plugins/SecurityInfo/SecurityInfo.php
new file mode 100644
index 0000000000..849b3992af
--- /dev/null
+++ b/plugins/SecurityInfo/SecurityInfo.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik_Plugins
+ * @package Piwik_SecurityInfo
+ */
+
+/**
+ *
+ * @package Piwik_SecurityInfo
+ */
+class Piwik_SecurityInfo extends Piwik_Plugin
+{
+ public function getInformation()
+ {
+ $info = array(
+ 'description' => Piwik_Translate('SecurityInfo_PluginDescription'),
+ 'author' => 'Piwik',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
+ );
+ return $info;
+ }
+
+ function getListHooksRegistered()
+ {
+ return array(
+ 'AdminMenu.add' => 'addMenu',
+ );
+ }
+
+ function addMenu()
+ {
+ Piwik_AddAdminMenu('SecurityInfo_Security',
+ array('module' => 'SecurityInfo', 'action' => 'index'),
+ Piwik::isUserIsSuperUser(),
+ $order = 10);
+ }
+}
diff --git a/plugins/SecurityInfo/templates/index.tpl b/plugins/SecurityInfo/templates/index.tpl
new file mode 100644
index 0000000000..0f053c1014
--- /dev/null
+++ b/plugins/SecurityInfo/templates/index.tpl
@@ -0,0 +1,31 @@
+{assign var=showSitesSelection value=false}
+{assign var=showPeriodSelection value=false}
+{include file="CoreAdminHome/templates/header.tpl"}
+{loadJavascriptTranslations plugins='SecurityInfo'}
+
+<h2>{'SecurityInfo_SecurityInformation'|translate}</h2>
+<p>{'SecurityInfo_PluginDescription'|translate}</p>
+
+<div style="max-width:980px;">
+{foreach from=$results.test_results key=i item=section}
+<h2>{$i}</h2>
+<table class="adminTable">
+ <thead>
+ <tr>
+ <th>{'SecurityInfo_Test'|translate}</th>
+ <th>{'SecurityInfo_Result'|translate}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {foreach from=$section key=j item=test}
+ <tr>
+ <td>{$j}</td>
+ <td style="{if $test.result==-1}background-color:green;color:white;{elseif $test.result==-2}background-color:yellow;color:black;{else if $test.result=--4}background-color:red;color:white;{/if}">{$test.message}</td>
+ </tr>
+ {/foreach}
+ </tbody>
+</table>
+{/foreach}
+</div>
+
+{include file="CoreAdminHome/templates/footer.tpl"}
diff --git a/plugins/SitesManager/API.php b/plugins/SitesManager/API.php
index 81c660875f..e00c159a8b 100644
--- a/plugins/SitesManager/API.php
+++ b/plugins/SitesManager/API.php
@@ -17,6 +17,10 @@
class Piwik_SitesManager_API
{
static private $instance = null;
+
+ /**
+ * @return Piwik_SitesManager_API
+ */
static public function getInstance()
{
if (self::$instance == null)
@@ -27,6 +31,11 @@ class Piwik_SitesManager_API
return self::$instance;
}
+ const OPTION_EXCLUDED_IPS_GLOBAL = 'SitesManager_ExcludedIpsGlobal';
+ const OPTION_DEFAULT_TIMEZONE = 'SitesManager_DefaultTimezone';
+ const OPTION_DEFAULT_CURRENCY = 'SitesManager_DefaultCurrency';
+ const OPTION_EXCLUDED_QUERY_PARAMETERS_GLOBAL = 'SitesManager_ExcludedQueryParameters';
+
/**
* Returns the javascript tag for the given idSite.
* This tag must be included on every page to be tracked by Piwik
@@ -34,7 +43,7 @@ class Piwik_SitesManager_API
* @param int $idSite
* @return string The Javascript tag ready to be included on the HTML pages
*/
- static public function getJavascriptTag( $idSite, $piwikUrl = '', $actionName = '')
+ public function getJavascriptTag( $idSite, $piwikUrl = '', $actionName = '')
{
Piwik::checkUserHasViewAccess($idSite);
@@ -56,10 +65,10 @@ class Piwik_SitesManager_API
* @exception if the site ID doesn't exist or the user doesn't have access to it
* @return array
*/
- static public function getSiteFromId( $idSite )
+ public function getSiteFromId( $idSite )
{
Piwik::checkUserHasViewAccess( $idSite );
- $site = Zend_Registry::get('db')->fetchRow("SELECT * FROM ".Piwik::prefixTable("site")." WHERE idsite = ?", $idSite);
+ $site = Zend_Registry::get('db')->fetchRow("SELECT * FROM ".Piwik_Common::prefixTable("site")." WHERE idsite = ?", $idSite);
return $site;
}
@@ -69,11 +78,11 @@ class Piwik_SitesManager_API
*
* @return array list of alias URLs
*/
- static private function getAliasSiteUrlsFromId( $idsite )
+ private function getAliasSiteUrlsFromId( $idsite )
{
$db = Zend_Registry::get('db');
$result = $db->fetchAll("SELECT url
- FROM ".Piwik::prefixTable("site_url"). "
+ FROM ".Piwik_Common::prefixTable("site_url"). "
WHERE idsite = ?", $idsite);
$urls = array();
foreach($result as $url)
@@ -89,11 +98,11 @@ class Piwik_SitesManager_API
* @exception if the website ID doesn't exist or the user doesn't have access to it
* @return array list of URLs
*/
- static public function getSiteUrlsFromId( $idSite )
+ public function getSiteUrlsFromId( $idSite )
{
Piwik::checkUserHasViewAccess($idSite);
- $site = self::getSiteFromId($idSite);
- $urls = self::getAliasSiteUrlsFromId($idSite);
+ $site = $this->getSiteFromId($idSite);
+ $urls = $this->getAliasSiteUrlsFromId($idSite);
return array_merge(array($site['main_url']), $urls);
}
@@ -102,10 +111,10 @@ class Piwik_SitesManager_API
*
* @return array the list of websites ID
*/
- static public function getAllSitesId()
+ public function getAllSitesId()
{
Piwik::checkUserIsSuperUser();
- $result = Piwik_FetchAll("SELECT idsite FROM ".Piwik::prefixTable('site'));
+ $result = Piwik_FetchAll("SELECT idsite FROM ".Piwik_Common::prefixTable('site'));
$idSites = array();
foreach($result as $idSite)
{
@@ -121,10 +130,10 @@ class Piwik_SitesManager_API
*
* @return array for each site, an array of information (idsite, name, main_url, etc.)
*/
- static public function getSitesWithAdminAccess()
+ public function getSitesWithAdminAccess()
{
- $sitesId = self::getSitesIdWithAdminAccess();
- return self::getSitesFromIds($sitesId);
+ $sitesId = $this->getSitesIdWithAdminAccess();
+ return $this->getSitesFromIds($sitesId);
}
/**
@@ -133,10 +142,10 @@ class Piwik_SitesManager_API
*
* @return array for each site, an array of information (idsite, name, main_url, etc.)
*/
- static public function getSitesWithViewAccess()
+ public function getSitesWithViewAccess()
{
- $sitesId = self::getSitesIdWithViewAccess();
- return self::getSitesFromIds($sitesId);
+ $sitesId = $this->getSitesIdWithViewAccess();
+ return $this->getSitesFromIds($sitesId);
}
/**
@@ -145,10 +154,10 @@ class Piwik_SitesManager_API
*
* @return array array for each site, an array of information (idsite, name, main_url, etc.)
*/
- static public function getSitesWithAtLeastViewAccess()
+ public function getSitesWithAtLeastViewAccess()
{
- $sitesId = self::getSitesIdWithAtLeastViewAccess();
- return self::getSitesFromIds($sitesId);
+ $sitesId = $this->getSitesIdWithAtLeastViewAccess();
+ return $this->getSitesFromIds($sitesId);
}
/**
@@ -157,7 +166,7 @@ class Piwik_SitesManager_API
*
* @return array list of websites ID
*/
- static public function getSitesIdWithAdminAccess()
+ public function getSitesIdWithAdminAccess()
{
$sitesId = Zend_Registry::get('access')->getSitesIdWithAdminAccess();
return $sitesId;
@@ -169,7 +178,7 @@ class Piwik_SitesManager_API
*
* @return array list of websites ID
*/
- static public function getSitesIdWithViewAccess()
+ public function getSitesIdWithViewAccess()
{
return Zend_Registry::get('access')->getSitesIdWithViewAccess();
}
@@ -180,7 +189,7 @@ class Piwik_SitesManager_API
*
* @return array list of websites ID
*/
- static public function getSitesIdWithAtLeastViewAccess()
+ public function getSitesIdWithAtLeastViewAccess()
{
return Zend_Registry::get('access')->getSitesIdWithAtLeastViewAccess();
}
@@ -191,7 +200,7 @@ class Piwik_SitesManager_API
*
* @param array list of website ID
*/
- static private function getSitesFromIds( $idSites )
+ private function getSitesFromIds( $idSites )
{
if(count($idSites) === 0)
{
@@ -199,57 +208,105 @@ class Piwik_SitesManager_API
}
$db = Zend_Registry::get('db');
$sites = $db->fetchAll("SELECT *
- FROM ".Piwik::prefixTable("site")."
+ FROM ".Piwik_Common::prefixTable("site")."
WHERE idsite IN (".implode(", ", $idSites).")
ORDER BY idsite ASC");
return $sites;
}
-
+
+ /**
+ * Returns the list of websites ID associated with a URL.
+ *
+ * @param string $url
+ * @return array list of websites ID
+ */
+ public function getSitesIdFromSiteUrl( $url )
+ {
+ $url = $this->removeTrailingSlash($url);
+
+ if(Piwik::isUserIsSuperUser())
+ {
+ $ids = Zend_Registry::get('db')->fetchAll(
+ 'SELECT idsite FROM ' . Piwik_Common::prefixTable('site') . ' WHERE main_url = ? ' .
+ 'UNION SELECT idsite FROM ' . Piwik_Common::prefixTable('site_url') . ' WHERE url = ?', array($url, $url));
+ }
+ else
+ {
+ $login = Piwik::getCurrentUserLogin();
+ $ids = Zend_Registry::get('db')->fetchAll(
+ 'SELECT idsite FROM ' . Piwik_Common::prefixTable('site') . ' WHERE main_url = ? ' .
+ 'AND idsite IN (' . Piwik_Access::getSqlAccessSite('idsite') . ') ' .
+ 'UNION SELECT idsite FROM ' . Piwik_Common::prefixTable('site_url') . ' WHERE url = ? ' .
+ 'AND idsite IN (' . Piwik_Access::getSqlAccessSite('idsite') . ')', array($url, $login, $url, $login));
+ }
+
+ return $ids;
+ }
+
/**
- * Add a website in the database.
+ * Add a website.
+ * Requires Super User access.
*
* The website is defined by a name and an array of URLs.
- * The name must not be empty.
- * The URLs array must contain at least one URL called the 'main_url' ;
- * if several URLs are provided in the array, they will be recorded as Alias URLs for
- * this website.
- *
- * Requires Super User access.
+ * @param string Site name
+ * @param array|string The URLs array must contain at least one URL called the 'main_url' ;
+ * if several URLs are provided in the array, they will be recorded
+ * as Alias URLs for this website.
+ * @param string Comma separated list of IPs to exclude from the reports (allows wildcards)
+ * @param string Timezone string, eg. 'Europe/London'
*
* @return int the website ID created
*/
- static public function addSite( $siteName, $urls )
+ public function addSite( $siteName, $urls, $excludedIps = null, $excludedQueryParameters = null, $timezone = null, $currency = null )
{
Piwik::checkUserIsSuperUser();
- self::checkName($siteName);
- $urls = self::cleanParameterUrls($urls);
- self::checkUrls($urls);
- self::checkAtLeastOneUrl($urls);
+ $this->checkName($siteName);
+ $urls = $this->cleanParameterUrls($urls);
+ $this->checkUrls($urls);
+ $this->checkAtLeastOneUrl($urls);
+ $timezone = trim($timezone);
+
+ if(empty($timezone))
+ {
+ $timezone = $this->getDefaultTimezone();
+ }
+ $this->checkValidTimezone($timezone);
+
+ if(empty($currency))
+ {
+ $currency = $this->getDefaultCurrency();
+ }
+ $this->checkValidCurrency($currency);
$db = Zend_Registry::get('db');
$url = $urls[0];
$urls = array_slice($urls, 1);
- $db->insert(Piwik::prefixTable("site"), array(
- 'name' => $siteName,
- 'main_url' => $url,
- )
- );
+ $bind = array( 'name' => $siteName,
+ 'main_url' => $url,
+ 'ts_created' => Piwik_Date::now()->getDatetime()
+ );
+
+ $bind['excluded_ips'] = $this->checkAndReturnExcludedIps($excludedIps);
+ $bind['excluded_parameters'] = $this->checkAndReturnExcludedQueryParameters($excludedQueryParameters);
+ $bind['timezone'] = $timezone;
+ $bind['currency'] = $currency;
+ $db->insert(Piwik_Common::prefixTable("site"), $bind);
$idSite = $db->lastInsertId();
- self::insertSiteUrls($idSite, $urls);
+ $this->insertSiteUrls($idSite, $urls);
// we reload the access list which doesn't yet take in consideration this new website
Zend_Registry::get('access')->reloadAccess();
- self::postUpdateWebsite($idSite);
+ $this->postUpdateWebsite($idSite);
return (int)$idSite;
}
- private static function postUpdateWebsite($idSite)
+ private function postUpdateWebsite($idSite)
{
Piwik_Common::regenerateCacheWebsiteAttributes($idSite);
}
@@ -261,11 +318,11 @@ class Piwik_SitesManager_API
*
* @param int $idSite
*/
- static public function deleteSite( $idSite )
+ public function deleteSite( $idSite )
{
Piwik::checkUserIsSuperUser();
- $idSites = Piwik_SitesManager_API::getAllSitesId();
+ $idSites = Piwik_SitesManager_API::getInstance()->getAllSitesId();
if(!in_array($idSite, $idSites))
{
throw new Exception("website id = $idSite not found");
@@ -278,13 +335,13 @@ class Piwik_SitesManager_API
$db = Zend_Registry::get('db');
- $db->query("DELETE FROM ".Piwik::prefixTable("site")."
+ $db->query("DELETE FROM ".Piwik_Common::prefixTable("site")."
WHERE idsite = ?", $idSite);
- $db->query("DELETE FROM ".Piwik::prefixTable("site_url")."
+ $db->query("DELETE FROM ".Piwik_Common::prefixTable("site_url")."
WHERE idsite = ?", $idSite);
- $db->query("DELETE FROM ".Piwik::prefixTable("access")."
+ $db->query("DELETE FROM ".Piwik_Common::prefixTable("access")."
WHERE idsite = ?", $idSite);
Piwik_Common::deleteCacheWebsiteAttributes($idSite);
@@ -296,7 +353,7 @@ class Piwik_SitesManager_API
*
* @exception if the parameter is not an array or if array empty
*/
- static private function checkAtLeastOneUrl( $urls )
+ private function checkAtLeastOneUrl( $urls )
{
if(!is_array($urls)
|| count($urls) == 0)
@@ -305,6 +362,52 @@ class Piwik_SitesManager_API
}
}
+ private function checkValidTimezone($timezone)
+ {
+ $timezones = $this->getTimezonesList();
+ foreach($timezones as $continent => $cities)
+ {
+ foreach($cities as $timezoneId => $city)
+ {
+ if($timezoneId == $timezone)
+ {
+ return true;
+ }
+ }
+ }
+ throw new Exception(Piwik_TranslateException('SitesManager_ExceptionInvalidTimezone', array($timezone)));
+ }
+
+ private function checkValidCurrency($currency)
+ {
+ if(!in_array($currency, array_keys($this->getCurrencyList())))
+ {
+ throw new Exception(Piwik_TranslateException('SitesManager_ExceptionInvalidCurrency', array($currency, "USD, EUR, etc.")));
+ }
+ }
+
+ /**
+ * Checks that the submitted IPs (comma separated list) are valid
+ * Returns the cleaned up IPs
+ * @param $excludedIps
+ *
+ * @return array of IPs
+ */
+ private function checkAndReturnExcludedIps($excludedIps)
+ {
+ $ips = explode(',', $excludedIps);
+ $ips = array_map('trim', $ips);
+ $ips = array_filter($ips, 'strlen');
+ foreach($ips as $ip)
+ {
+ if(!$this->isValidIp($ip))
+ {
+ throw new Exception(Piwik_TranslateException('SitesManager_ExceptionInvalidIPFormat', array($ip, "1.2.3.4 or 1.2.3.*")));
+ }
+ }
+ $ips = implode(',', $ips);
+ return $ips;
+ }
/**
* Add a list of alias Urls to the given idSite
*
@@ -313,22 +416,136 @@ class Piwik_SitesManager_API
*
* @return int the number of inserted URLs
*/
- static public function addSiteAliasUrls( $idSite, $urls)
+ public function addSiteAliasUrls( $idSite, $urls)
{
Piwik::checkUserHasAdminAccess( $idSite );
- $urls = self::cleanParameterUrls($urls);
- self::checkUrls($urls);
+ $urls = $this->cleanParameterUrls($urls);
+ $this->checkUrls($urls);
- $urlsInit = self::getSiteUrlsFromId($idSite);
+ $urlsInit = $this->getSiteUrlsFromId($idSite);
$toInsert = array_diff($urls, $urlsInit);
- self::insertSiteUrls($idSite, $toInsert);
- self::postUpdateWebsite($idSite);
+ $this->insertSiteUrls($idSite, $toInsert);
+ $this->postUpdateWebsite($idSite);
return count($toInsert);
}
/**
+ * Sets IPs to be excluded from all websites. IPs can contain wildcards.
+ * Will also apply to websites created in the future.
+ *
+ * @param string Comma separated list of IPs to exclude from being tracked (allows wildcards)
+ * @return bool
+ */
+ public function setGlobalExcludedIps($excludedIps)
+ {
+ Piwik::checkUserIsSuperUser();
+ $excludedIps = $this->checkAndReturnExcludedIps($excludedIps);
+ Piwik_SetOption(self::OPTION_EXCLUDED_IPS_GLOBAL, $excludedIps);
+ Piwik_Common::deleteAllCache();
+ return true;
+ }
+
+ /**
+ * Returns the list of URL query parameters that are excluded from all websites
+ *
+ * @return string Comma separated list of URL parameters
+ */
+ public function getExcludedQueryParametersGlobal()
+ {
+ Piwik::checkUserHasSomeAdminAccess();
+ return Piwik_GetOption(self::OPTION_EXCLUDED_QUERY_PARAMETERS_GLOBAL);
+ }
+
+ /**
+ * Sets list of URL query parameters to be excluded on all websites.
+ * Will also apply to websites created in the future.
+ *
+ * @param string Comma separated list of URL query parameters to exclude from URLs
+ * @return bool
+ */
+ public function setGlobalExcludedQueryParameters($excludedQueryParameters)
+ {
+ Piwik::checkUserIsSuperUser();
+ $excludedQueryParameters = $this->checkAndReturnExcludedQueryParameters($excludedQueryParameters);
+ Piwik_SetOption(self::OPTION_EXCLUDED_QUERY_PARAMETERS_GLOBAL, $excludedQueryParameters);
+ Piwik_Common::deleteAllCache();
+ return true;
+ }
+
+ /**
+ * Returns the list of IPs that are excluded from all websites
+ *
+ * @return string Comma separated list of IPs
+ */
+ public function getExcludedIpsGlobal()
+ {
+ Piwik::checkUserHasSomeAdminAccess();
+ return Piwik_GetOption(self::OPTION_EXCLUDED_IPS_GLOBAL);
+ }
+
+ /**
+ * Returns the default currency that will be set when creating a website through the API.
+ *
+ * @return string Currency ID eg. 'USD'
+ */
+ public function getDefaultCurrency()
+ {
+ Piwik::checkUserHasSomeAdminAccess();
+ $defaultCurrency = Piwik_GetOption(self::OPTION_DEFAULT_CURRENCY);
+ if($defaultCurrency)
+ {
+ return $defaultCurrency;
+ }
+ return 'USD';
+ }
+
+ /**
+ * Sets the default currency that will be used when creating websites
+ *
+ * @param $defaultCurrency string eg. 'USD'
+ * @return bool
+ */
+ public function setDefaultCurrency($defaultCurrency)
+ {
+ Piwik::checkUserIsSuperUser();
+ $this->checkValidCurrency($defaultCurrency);
+ Piwik_SetOption(self::OPTION_DEFAULT_CURRENCY, $defaultCurrency);
+ return true;
+ }
+
+ /**
+ * Returns the default timezone that will be set when creating a website through the API.
+ * Via the UI, if the default timezone is not UTC, it will be pre-selected in the drop down
+ *
+ * @return string Timezone eg. UTC+7 or Europe/Paris
+ */
+ public function getDefaultTimezone()
+ {
+ $defaultTimezone = Piwik_GetOption(self::OPTION_DEFAULT_TIMEZONE);
+ if($defaultTimezone)
+ {
+ return $defaultTimezone;
+ }
+ return 'UTC';
+ }
+
+ /**
+ * Sets the default timezone that will be used when creating websites
+ *
+ * @param $defaultTimezone string eg. Europe/Paris or UTC+8
+ * @return bool
+ */
+ public function setDefaultTimezone($defaultTimezone)
+ {
+ Piwik::checkUserIsSuperUser();
+ $this->checkValidTimezone($defaultTimezone);
+ Piwik_SetOption(self::OPTION_DEFAULT_TIMEZONE, $defaultTimezone);
+ return true;
+ }
+
+ /**
* Update an existing website.
* If only one URL is specified then only the main url will be updated.
* If several URLs are specified, both the main URL and the alias URLs will be updated.
@@ -336,59 +553,234 @@ class Piwik_SitesManager_API
* @param int website ID defining the website to edit
* @param string website name
* @param string|array the website URLs
+ * @param string Comma separated list of IPs to exclude from being tracked (allows wildcards)
+ * @param string Timezone
*
* @exception if any of the parameter is not correct
*
* @return bool true on success
*/
- static public function updateSite( $idSite, $siteName, $urls = null)
+ public function updateSite( $idSite, $siteName, $urls = null, $excludedIps = null, $excludedQueryParameters = null, $timezone = null, $currency = null)
{
Piwik::checkUserHasAdminAccess($idSite);
- self::checkName($siteName);
+ $this->checkName($siteName);
// SQL fields to update
$bind = array();
if(!is_null($urls))
{
- $urls = self::cleanParameterUrls($urls);
- self::checkUrls($urls);
- self::checkAtLeastOneUrl($urls);
+ $urls = $this->cleanParameterUrls($urls);
+ $this->checkUrls($urls);
+ $this->checkAtLeastOneUrl($urls);
$url = $urls[0];
$bind['main_url'] = $url;
}
+
+ if(!is_null($currency))
+ {
+ $currency = trim($currency);
+ $this->checkValidCurrency($currency);
+ $bind['currency'] = $currency;
+ }
+ if(!is_null($timezone))
+ {
+ $timezone = trim($timezone);
+ $this->checkValidTimezone($timezone);
+ $bind['timezone'] = $timezone;
+ }
+ $bind['excluded_ips'] = $this->checkAndReturnExcludedIps($excludedIps);
+ $bind['excluded_parameters'] = $this->checkAndReturnExcludedQueryParameters($excludedQueryParameters);
$bind['name'] = $siteName;
-
$db = Zend_Registry::get('db');
- $db->update(Piwik::prefixTable("site"),
+ $db->update(Piwik_Common::prefixTable("site"),
$bind,
"idsite = $idSite"
);
// we now update the main + alias URLs
- self::deleteSiteAliasUrls($idSite);
+ $this->deleteSiteAliasUrls($idSite);
if(count($urls) > 1)
{
- $insertedUrls = self::addSiteAliasUrls($idSite, array_slice($urls,1));
+ $insertedUrls = $this->addSiteAliasUrls($idSite, array_slice($urls,1));
+ }
+ $this->postUpdateWebsite($idSite);
+ }
+
+ private function checkAndReturnExcludedQueryParameters($parameters)
+ {
+ $parameters = trim($parameters);
+ if(empty($parameters))
+ {
+ return '';
}
- self::postUpdateWebsite($idSite);
+
+ $parameters = explode(',', $parameters);
+ $parameters = array_map('trim', $parameters);
+ $parameters = array_filter($parameters, 'strlen');
+ $parameters = array_unique($parameters);
+ return implode(',', $parameters);
+ }
+
+ /**
+ * Returns the list of supported currencies
+ * @see getCurrencySymbols()
+ * @return array ( currencyId => currencyName)
+ */
+ public function getCurrencyList()
+ {
+ return array(
+ 'USD' => 'US Dollar ($)',
+ 'EUR' => 'Euro (€)',
+ 'JPY' => 'Japanese Yen (¥)',
+ 'GBP' => 'British Pound Sterling (£)',
+ 'AUD' => 'Australian Dollar (A$)',
+ 'KRW' => 'South Korean Won (₩)',
+ 'BRL' => 'Brazilian Real (R$)',
+ 'CNY' => 'Chinese Yuan Renminbi (CN¥)',
+ 'DKK' => 'Danish Krone (Dkr)',
+ 'RUB' => 'Russian Ruble (RUB)',
+ 'SEK' => 'Swedish Krona (Skr)',
+ 'NOK' => 'Norwegian Krone (Nkr)',
+ 'PLN' => 'Polish Zloty (zł)',
+ 'TRY' => 'Turkish Lira (TL)',
+ 'TWD' => 'New Taiwan Dollar (NT$)',
+ 'HKD' => 'Hong Kong Dollar (HK$)',
+ 'THB' => 'Thai Baht (฿)',
+ 'IDR' => 'Indonesian Rupiah (Rp)',
+ 'ARS' => 'Argentine Peso (AR$)',
+ 'MXN' => 'Mexican Peso (MXN)',
+ 'VND' => 'Vietnamese Dong (₫)',
+ 'PHP' => 'Philippine Peso (Php)',
+ 'INR' => 'Indian Rupee (Rs.)',
+ 'VEF' => 'Venezuelan bolívar (Bs. F)',
+ 'CHF' => 'Swiss Franc (Fr.)',
+ );
+ }
+
+ /**
+ * Returns the list of currency symbols
+ * @see getCurrencyList()
+ * @return array( currencyId => currencySymbol )
+ */
+ public function getCurrencySymbols()
+ {
+ return array(
+ 'USD' => '$',
+ 'EUR' => '€',
+ 'JPY' => '¥',
+ 'GBP' => '£',
+ 'AUD' => 'A$',
+ 'KRW' => '₩',
+ 'BRL' => 'R$',
+ 'CNY' => 'CN¥',
+ 'DKK' => 'Dkr',
+ 'RUB' => 'RUB',
+ 'SEK' => 'Skr',
+ 'NOK' => 'Nkr',
+ 'PLN' => 'zł',
+ 'TRY' => 'TL',
+ 'TWD' => 'NT$',
+ 'HKD' => 'HK$',
+ 'THB' => '฿',
+ 'IDR' => 'Rp',
+ 'ARS' => 'AR$',
+ 'MXN' => 'MXN',
+ 'VND' => '₫',
+ 'PHP' => 'Php',
+ 'INR' => 'Rs.',
+ 'VEF' => 'Bs. F',
+ 'CHF' => 'Fr.',
+ );
+ }
+
+
+ /**
+ * Returns the list of timezones supported.
+ * Used for addSite and updateSite
+ *
+ * @TODO NOT COMPATIBLE WITH API RESPONSE AUTO BUILDER
+ *
+ * @return array of timezone strings
+ */
+ public function getTimezonesList()
+ {
+ if(!Piwik::isTimezoneSupportEnabled())
+ {
+ return array('UTC' => $this->getTimezonesListUTCOffsets());
+ }
+
+ $continents = array( 'Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
+ $timezones = timezone_identifiers_list();
+
+ $return = array();
+ foreach($timezones as $timezone)
+ {
+ $timezoneExploded = explode('/', $timezone);
+ $continent = $timezoneExploded[0];
+
+ // only display timezones that are grouped by continent
+ if(!in_array($continent, $continents))
+ {
+ continue;
+ }
+ $city = $timezoneExploded[1];
+ if(!empty($timezoneExploded[2]))
+ {
+ $city .= ' - '.$timezoneExploded[2];
+ }
+ $city = str_replace('_', ' ', $city);
+ $return[$continent][$timezone] = $city;
+ }
+
+ foreach($continents as $continent)
+ {
+ ksort($return[$continent]);
+ }
+
+ $return['UTC'] = $this->getTimezonesListUTCOffsets();
+ return $return;
+ }
+
+ private function getTimezonesListUTCOffsets()
+ {
+ // manually add the UTC offsets
+ $GmtOffsets = array (-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5,
+ 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
+
+ $return = array();
+ foreach($GmtOffsets as $offset)
+ {
+ if($offset > 0)
+ {
+ $offset = '+'.$offset;
+ }
+ elseif($offset == 0)
+ {
+ $offset = '';
+ }
+ $offset = 'UTC' . $offset;
+ $offsetName = str_replace(array('.25','.5','.75'), array(':15',':30',':45'), $offset);
+ $return[$offset] = $offsetName;
+ }
+ return $return;
}
/**
* Insert the list of alias URLs for the website.
* The URLs must not exist already for this website!
*/
- static private function insertSiteUrls($idSite, $urls)
+ private function insertSiteUrls($idSite, $urls)
{
if(count($urls) != 0)
{
$db = Zend_Registry::get('db');
foreach($urls as $url)
{
- $db->insert(Piwik::prefixTable("site_url"), array(
+ $db->insert(Piwik_Common::prefixTable("site_url"), array(
'idsite' => $idSite,
'url' => $url
)
@@ -400,10 +792,10 @@ class Piwik_SitesManager_API
/**
* Delete all the alias URLs for the given idSite.
*/
- static private function deleteSiteAliasUrls($idsite)
+ private function deleteSiteAliasUrls($idsite)
{
$db = Zend_Registry::get('db');
- $db->query("DELETE FROM ".Piwik::prefixTable("site_url") ."
+ $db->query("DELETE FROM ".Piwik_Common::prefixTable("site_url") ."
WHERE idsite = ?", $idsite);
}
@@ -412,7 +804,7 @@ class Piwik_SitesManager_API
*
* @return string the URL without the trailing slash
*/
- static private function removeTrailingSlash($url)
+ private function removeTrailingSlash($url)
{
// if there is a final slash, we take the URL without this slash (expected URL format)
if(strlen($url) > 5
@@ -428,17 +820,33 @@ class Piwik_SitesManager_API
*
* @return bool
*/
- static private function isValidUrl( $url )
+ private function isValidUrl( $url )
{
return Piwik_Common::isLookLikeUrl($url);
}
/**
+ * Tests if the IP is a valid IP, allowing wildcards, except in the first octet.
+ * Wildcards can only be used from right to left, ie. 1.1.*.* is allowed, but 1.1.*.1 is not.
+ *
+ * @param $ip
+ * @return bool
+ */
+ private function isValidIp( $ip )
+ {
+ return preg_match('~^(\d+)\.(\d+)\.(\d+)\.(\d+)$~', $ip, $matches) !== 0
+ || preg_match('~^(\d+)\.(\d+)\.(\d+)\.\*$~', $ip, $matches) !== 0
+ || preg_match('~^(\d+)\.(\d+)\.\*.\*$~', $ip, $matches) !== 0
+ || preg_match('~^(\d+)\.\*\.\*\.\*$~', $ip, $matches) !== 0
+ ;
+ }
+
+ /**
* Check that the website name has a correct format.
*
* @exception if the website name is empty
*/
- static private function checkName($siteName)
+ private function checkName($siteName)
{
if(empty($siteName))
{
@@ -452,11 +860,11 @@ class Piwik_SitesManager_API
* @exception if any of the urls is not valid
* @param array
*/
- static private function checkUrls($urls)
+ private function checkUrls($urls)
{
foreach($urls as $url)
{
- if(!self::isValidUrl($url))
+ if(!$this->isValidUrl($url))
{
throw new Exception(sprintf(Piwik_TranslateException("SitesManager_ExceptionInvalidUrl"),$url));
}
@@ -471,19 +879,20 @@ class Piwik_SitesManager_API
* @param string|array urls
* @return array the array of cleaned URLs
*/
- static private function cleanParameterUrls( $urls )
+ private function cleanParameterUrls( $urls )
{
if(!is_array($urls))
{
$urls = array($urls);
}
+
+ $urls = array_map('urldecode', $urls);
foreach($urls as &$url)
{
- $url = self::removeTrailingSlash($url);
+ $url = $this->removeTrailingSlash($url);
}
$urls = array_unique($urls);
return $urls;
}
}
-
diff --git a/plugins/SitesManager/Controller.php b/plugins/SitesManager/Controller.php
index ddf93d109b..84dc3d5a03 100644
--- a/plugins/SitesManager/Controller.php
+++ b/plugins/SitesManager/Controller.php
@@ -19,17 +19,56 @@ class Piwik_SitesManager_Controller extends Piwik_Controller
function index()
{
$view = Piwik_View::factory('SitesManager');
- $sites = Piwik_SitesManager_API::getSitesWithAdminAccess();
+ $sites = Piwik_SitesManager_API::getInstance()->getSitesWithAdminAccess();
foreach($sites as &$site)
{
- $site['alias_urls'] = Piwik_SitesManager_API::getSiteUrlsFromId($site['idsite']);
+ $site['alias_urls'] = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($site['idsite']);
+ $site['excluded_ips'] = str_replace(',','<br/>', $site['excluded_ips']);
+ $site['excluded_parameters'] = str_replace(',','<br/>', $site['excluded_parameters']);
}
$view->adminSites = $sites;
+
+ $timezones = Piwik_SitesManager_API::getInstance()->getTimezonesList();
+ $view->timezoneSupported = Piwik::isTimezoneSupportEnabled();
+ $view->timezones = json_encode($timezones);
+ $view->defaultTimezone = Piwik_SitesManager_API::getInstance()->getDefaultTimezone();
+
+ $view->currencies = json_encode(Piwik_SitesManager_API::getInstance()->getCurrencyList());
+ $view->defaultCurrency = Piwik_SitesManager_API::getInstance()->getDefaultCurrency();
+
+ $view->utcTime = Piwik_Date::now()->getDatetime();
+ $excludedIpsGlobal = Piwik_SitesManager_API::getInstance()->getExcludedIpsGlobal();
+ $view->globalExcludedIps = str_replace(',',"\n", $excludedIpsGlobal);
+ $excludedQueryParametersGlobal = Piwik_SitesManager_API::getInstance()->getExcludedQueryParametersGlobal();
+ $view->globalExcludedQueryParameters = str_replace(',',"\n", $excludedQueryParametersGlobal);
+ $view->currentIpAddress = Piwik_Common::getIpString();
+
$this->setGeneralVariablesView($view);
$view->menu = Piwik_GetAdminMenu();
echo $view->render();
}
+ function setGlobalSettings()
+ {
+ $response = new Piwik_API_ResponseBuilder(Piwik_Common::getRequestVar('format'));
+
+ try {
+ $this->checkTokenInUrl();
+ $timezone = Piwik_Common::getRequestVar('timezone', false);
+ $excludedIps = Piwik_Common::getRequestVar('excludedIps', false);
+ $excludedQueryParameters = Piwik_Common::getRequestVar('excludedQueryParameters', false);
+ $currency = Piwik_Common::getRequestVar('currency', false);
+ Piwik_SitesManager_API::getInstance()->setDefaultTimezone($timezone);
+ Piwik_SitesManager_API::getInstance()->setDefaultCurrency($currency);
+ Piwik_SitesManager_API::getInstance()->setGlobalExcludedQueryParameters($excludedQueryParameters);
+ Piwik_SitesManager_API::getInstance()->setGlobalExcludedIps($excludedIps);
+ $toReturn = $response->getResponse();
+ } catch(Exception $e ) {
+ $toReturn = $response->getResponseException( $e );
+ }
+ echo $toReturn;
+ }
+
function displayJavascriptCode()
{
$idSite = Piwik_Common::getRequestVar('idsite', 1);
@@ -38,6 +77,8 @@ class Piwik_SitesManager_Controller extends Piwik_Controller
$view = Piwik_View::factory('DisplayJavascriptCode');
$this->setGeneralVariablesView($view);
$view->menu = Piwik_GetAdminMenu();
+ $site = new Piwik_Site($idSite);
+ $view->displaySiteName = $site->getName();
$view->jsTag = $jsTag;
echo $view->render();
}
diff --git a/plugins/SitesManager/SitesManager.php b/plugins/SitesManager/SitesManager.php
index b2542e966c..dfca3e2c6f 100644
--- a/plugins/SitesManager/SitesManager.php
+++ b/plugins/SitesManager/SitesManager.php
@@ -19,11 +19,10 @@ class Piwik_SitesManager extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Sites Management',
- 'description' => 'Websites Management in Piwik: Add a new Website, Edit an existing one, Show the Javascript code to include on your pages. All the actions are also available through the API.',
+ 'description' => Piwik_Translate('SitesManager_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
}
@@ -33,21 +32,105 @@ class Piwik_SitesManager extends Piwik_Plugin
return array(
'template_css_import' => 'css',
'AdminMenu.add' => 'addMenu',
- 'Common.fetchWebsiteAttributes' => 'recordWebsiteHostsInCache',
+ 'Common.fetchWebsiteAttributes' => 'recordWebsiteDataInCache',
);
}
+ function addMenu()
+ {
+ Piwik_AddAdminMenu('SitesManager_MenuSites',
+ array('module' => 'SitesManager', 'action' => 'index'),
+ Piwik::isUserHasSomeAdminAccess(),
+ $order = 5);
+ }
+
function css()
{
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"themes/default/styles.css\" />\n";
}
- function recordWebsiteHostsInCache($notification)
+ /**
+ * Hooks when a website tracker cache is flushed (website updated, cache deleted, or empty cache)
+ * Will record in the tracker config file all data needed for this website in Tracker.
+ *
+ * @param $notification
+ * @return void
+ */
+ function recordWebsiteDataInCache($notification)
{
- $idsite = $notification->getNotificationInfo();
+ $idSite = $notification->getNotificationInfo();
// add the 'hosts' entry in the website array
$array =& $notification->getNotificationObject();
- $urls = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $array['hosts'] = $this->getTrackerHosts($idSite);
+ $array['excluded_ips'] = $this->getTrackerExcludedIps($idSite);
+ $array['excluded_parameters'] = $this->getTrackerExcludedQueryParameters($idSite);
+ }
+
+ /**
+ * Returns the array of excluded IPs to save in the config file
+ * @param $idSite
+ * @return array
+ */
+ private function getTrackerExcludedIps($idSite)
+ {
+ $website = Piwik_SitesManager_API::getInstance()->getSiteFromId($idSite);
+ $excludedIps = $website['excluded_ips'];
+ $globalExcludedIps = Piwik_SitesManager_API::getInstance()->getExcludedIpsGlobal();
+
+ $excludedIps .= ',' . $globalExcludedIps;
+
+ $ipRanges = array();
+ foreach(explode(',', $excludedIps) as $ip)
+ {
+ $ipMin = $ipMax = $ip;
+ if(substr_count($ip, '*') > 0)
+ {
+ $ipMin = str_replace('*', '0', $ip);
+ $ipMax = str_replace('*', '255', $ip);
+ }
+ $ipRange = array( ip2long($ipMin), ip2long($ipMax));
+
+ // we can still get invalid IPs at this stage (eg. ip2long(555.1.1.1) would return false)
+ if($ipRange[0] === false || $ipRange[1] === false)
+ {
+ continue;
+ }
+
+ // long data type is signed; convert to stringified unsigned number
+ $ipRange[0] = sprintf("%u", $ipRange[0]);
+ $ipRange[1] = sprintf("%u", $ipRange[1]);
+
+ $ipRanges[] = $ipRange;
+ }
+ return $ipRanges;
+ }
+
+ /**
+ * Returns the array of URL query parameters to exclude from URLs
+ * @param $idSite
+ * @return array
+ */
+ private function getTrackerExcludedQueryParameters($idSite)
+ {
+ $website = Piwik_SitesManager_API::getInstance()->getSiteFromId($idSite);
+ $excludedQueryParameters = $website['excluded_parameters'];
+ $globalExcludedQueryParameters = Piwik_SitesManager_API::getInstance()->getExcludedQueryParametersGlobal();
+
+ $excludedQueryParameters .= ',' . $globalExcludedQueryParameters;
+ $parameters = explode(',', $excludedQueryParameters);
+ $parameters = array_filter($parameters, 'strlen');
+ $parameters = array_unique($parameters);
+ return $parameters;
+ }
+
+ /**
+ * Returns the hosts alias URLs
+ * @param $idSite
+ * @return array
+ */
+ private function getTrackerHosts($idSite)
+ {
+ $urls = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idSite);
$hosts = array();
foreach($urls as $url)
{
@@ -57,12 +140,7 @@ class Piwik_SitesManager extends Piwik_Plugin
$hosts[] = $url['host'];
}
}
- $array['hosts'] = $hosts;
+ return $hosts;
}
- function addMenu()
- {
- Piwik_AddAdminMenu('SitesManager_MenuSites', array('module' => 'SitesManager', 'action' => 'index'));
- }
}
-
diff --git a/plugins/SitesManager/templates/DisplayJavascriptCode.tpl b/plugins/SitesManager/templates/DisplayJavascriptCode.tpl
index 9fa7c7f617..29a1e53170 100644
--- a/plugins/SitesManager/templates/DisplayJavascriptCode.tpl
+++ b/plugins/SitesManager/templates/DisplayJavascriptCode.tpl
@@ -2,7 +2,6 @@
{assign var=showPeriodSelection value=false}
{include file="CoreAdminHome/templates/header.tpl"}
{loadJavascriptTranslations plugins='SitesManager'}
-{include file="CoreAdminHome/templates/menu.tpl"}
{literal}
<style>
@@ -13,7 +12,7 @@ code {
border-width:1px 1px 1px 5px;
direction:ltr;
display:block;
- font-size:80%;
+ font-size:90%;
margin:2px 2px 20px;
padding:4px;
text-align:left;
@@ -22,7 +21,7 @@ code {
</style>
{/literal}
-<h2>{$siteName}</h2>
+<h2>{$displaySiteName}</h2>
<p>{'SitesManager_JsTrackingTagHelp'|translate}:</p>
<code>{$jsTag}</code>
diff --git a/plugins/SitesManager/templates/SitesManager.js b/plugins/SitesManager/templates/SitesManager.js
index 7b523b98a4..cf14893c8c 100644
--- a/plugins/SitesManager/templates/SitesManager.js
+++ b/plugins/SitesManager/templates/SitesManager.js
@@ -1,8 +1,7 @@
function getDeleteSiteAJAX( idSite )
{
var ajaxRequest = piwikHelper.getStandardAjaxConf();
- piwikHelper.toggleAjaxLoading();
-
+
var parameters = {};
parameters.module = 'API';
parameters.format = 'json';
@@ -18,19 +17,28 @@ function getDeleteSiteAJAX( idSite )
function getAddSiteAJAX( row )
{
var ajaxRequest = piwikHelper.getStandardAjaxConf();
- piwikHelper.toggleAjaxLoading();
var parameters = {};
- var siteName = $(row).find('input#siteadd_name').val();
- var urls = $(row).find('textarea#siteadd_urls').val();
- var urls = urls.trim().split("\n");
-
+ var siteName = $(row).find('input#name').val();
+ var urls = $(row).find('textarea#urls').val();
+ urls = getApiFormatUrls(urls);
+ var excludedIps = $(row).find('textarea#excludedIps').val();
+ excludedIps = getApiFormatTextarea(excludedIps);
+ var timezone = encodeURIComponent($(row).find('#timezones option:selected').val());
+ var currency = encodeURIComponent($(row).find('#currencies option:selected').val());
+ var excludedQueryParameters = $(row).find('textarea#excludedQueryParameters').val();
+ excludedQueryParameters = getApiFormatTextarea(excludedQueryParameters);
+
var request = '';
request += '&module=API';
request += '&format=json';
request += '&method=SitesManager.addSite';
siteName = encodeURIComponent(siteName);
request += '&siteName='+siteName;
+ request += '&timezone='+timezone;
+ request += '&currency='+currency;
+ request += '&excludedIps='+excludedIps;
+ request += '&excludedQueryParameters='+excludedQueryParameters;
$.each(urls, function (key,value){ request+= '&urls[]='+escape(value);} );
request += '&token_auth=' + piwik.token_auth;
@@ -39,15 +47,33 @@ function getAddSiteAJAX( row )
return ajaxRequest;
}
+function getApiFormatUrls(urls)
+{
+ var aUrls = urls.trim().split("\n");
+ for(var i=0; i < aUrls.length; i++) {
+ aUrls[i] = encodeURIComponent(aUrls[i]);
+ }
+ return aUrls;
+}
+function getApiFormatTextarea(textareaContent)
+{
+ return textareaContent.trim().split("\n").join(',');
+}
+
function getUpdateSiteAJAX( row )
{
var ajaxRequest = piwikHelper.getStandardAjaxConf();
- piwikHelper.toggleAjaxLoading();
var siteName = $(row).find('input#siteName').val();
var idSite = $(row).children('#idSite').html();
- var urls = $(row).find('textarea#urls').val().trim().split("\n");
-
+ var urls = $(row).find('textarea#urls').val();
+ urls = getApiFormatUrls(urls);
+ var excludedIps = $(row).find('textarea#excludedIps').val();
+ excludedIps = getApiFormatTextarea(excludedIps);
+ var excludedQueryParameters = $(row).find('textarea#excludedQueryParameters').val();
+ excludedQueryParameters = getApiFormatTextarea(excludedQueryParameters);
+ var timezone = encodeURIComponent($(row).find('#timezones option:selected').val());
+ var currency = encodeURIComponent($(row).find('#currencies option:selected').val());
var request = '';
request += '&module=API';
request += '&format=json';
@@ -55,6 +81,10 @@ function getUpdateSiteAJAX( row )
siteName = encodeURIComponent(siteName);
request += '&siteName='+siteName;
request += '&idSite='+idSite;
+ request += '&timezone='+timezone;
+ request += '&currency='+currency;
+ request += '&excludedIps='+excludedIps;
+ request += '&excludedQueryParameters='+excludedQueryParameters;
$.each(urls, function (key,value){ if(value.length>1) request+= '&urls[]='+value;} );
request += '&token_auth=' + piwik.token_auth;
@@ -63,9 +93,31 @@ function getUpdateSiteAJAX( row )
return ajaxRequest;
}
+function getGlobalSettingsAJAX()
+{
+ var ajaxRequest = piwikHelper.getStandardAjaxConf('ajaxLoadingGlobalSettings', 'ajaxErrorGlobalSettings');
+ var timezone = encodeURIComponent($('#defaultTimezone option:selected').val());
+ var currency = encodeURIComponent($('#defaultCurrency option:selected').val());
+ var excludedIps = $('textarea#globalExcludedIps').val();
+ excludedIps = getApiFormatTextarea(excludedIps);
+ var excludedQueryParameters = $('textarea#globalExcludedQueryParameters').val();
+ excludedQueryParameters = getApiFormatTextarea(excludedQueryParameters);
+ var request = '';
+ request += 'module=SitesManager';
+ request += '&action=setGlobalSettings';
+ request += '&format=json';
+ request += '&timezone='+timezone;
+ request += '&currency='+currency;
+ request += '&excludedIps='+excludedIps;
+ request += '&excludedQueryParameters='+excludedQueryParameters;
+ request += '&token_auth=' + piwik.token_auth;
+ ajaxRequest.data = request;
+ return ajaxRequest;
+}
+
$(document).ready( function() {
$('.addRowSite').click( function() {
- piwikHelper.ajaxHideError();
+ piwikHelper.hideAjaxError();
$(this).toggle();
var numberOfRows = $('table#editSites')[0].rows.length;
@@ -73,22 +125,25 @@ $(document).ready( function() {
$(' <tr id="'+newRowId+'">\
<td>&nbsp;</td>\
- <td><input id="siteadd_name" value="Name" size=25></td>\
- <td><textarea cols=30 rows=3 id="siteadd_urls">http://siteUrl.com/\nhttp://siteUrl2.com/</textarea></td>\
- <td><img src="plugins/UsersManager/images/ok.png" class="addsite" href="#"></td>\
- <td><img src="plugins/UsersManager/images/remove.png" class="cancel"></td>\
+ <td><input id="name" value="Name" size="15" /></td>\
+ <td><textarea cols="25" rows="3" id="urls">http://siteUrl.com/\nhttp://siteUrl2.com/</textarea><br />'+aliasUrlsHelp+'</td>\
+ <td><textarea cols="20" rows="4" id="excludedIps"></textarea><br />'+excludedIpHelp+'</td>\
+ <td><textarea cols="20" rows="4" id="excludedQueryParameters"></textarea><br />'+excludedQueryParametersHelp+'</td>\
+ <td>'+getTimezoneSelector(defaultTimezone)+'<br />' + timezoneHelp + '</td>\
+ <td>'+getCurrencySelector(defaultCurrency)+'<br />' + currencyHelp + '</td>\
+ <td><img src="plugins/UsersManager/images/ok.png" class="addsite" href="#" title="' + _pk_translate('SitesManager_Save_js') + '" /></td>\
+ <td><img src="plugins/UsersManager/images/remove.png" class="cancel" title="' + _pk_translate('SitesManager_Cancel_js') +'" /></td>\
</tr>')
.appendTo('#editSites')
;
- $('#'+newRowId).keypress( submitSiteOnEnter );
$('.addsite').click( function(){ $.ajax( getAddSiteAJAX($('tr#'+newRowId)) ); } );
- $('.cancel').click(function() { piwikHelper.ajaxHideError(); $(this).parents('tr').remove(); $('.addRowSite').toggle(); });
-
+ $('.cancel').click(function() { piwikHelper.hideAjaxError(); $(this).parents('tr').remove(); $('.addRowSite').toggle(); });
+ return false;
} );
// when click on deleteuser, the we ask for confirmation and then delete the user
$('.deleteSite').click( function() {
- piwikHelper.ajaxHideError();
+ piwikHelper.hideAjaxError();
var idRow = $(this).attr('id');
var nameToDelete = $(this).parent().parent().find('input#siteName').val() || $(this).parent().parent().find('td#siteName').html();
var idsiteToDelete = $(this).parent().parent().find('#idSite').html();
@@ -101,7 +156,7 @@ $(document).ready( function() {
var alreadyEdited = new Array;
$('.editSite')
.click( function() {
- piwikHelper.ajaxHideError();
+ piwikHelper.hideAjaxError();
var idRow = $(this).attr('id');
if(alreadyEdited[idRow]==1) return;
alreadyEdited[idRow] = 1;
@@ -113,14 +168,39 @@ $(document).ready( function() {
var idName = $(n).attr('id');
if(idName == 'siteName')
{
- var contentAfter = '<input id="'+idName+'" value="'+contentBefore+'" size="25">';
+ var contentAfter = '<input id="'+idName+'" value="'+contentBefore+'" size="15" />';
$(n)
.html(contentAfter)
.keypress( submitSiteOnEnter );
}
if(idName == 'urls')
{
- var contentAfter = '<textarea cols=30 rows=3 id="urls">'+contentBefore.replace(/<br *\/? *>/gi,"\n")+'</textarea>';
+ var contentAfter = '<textarea cols="25" rows="3" id="urls">'+contentBefore.replace(/<br *\/? *>/gi,"\n")+'</textarea>';
+ contentAfter += '<br />'+aliasUrlsHelp;
+ $(n).html(contentAfter);
+ }
+ if(idName == 'excludedIps')
+ {
+ var contentAfter = '<textarea cols="20" rows="4" id="excludedIps">'+contentBefore.replace(/<br *\/? *>/gi,"\n")+'</textarea>';
+ contentAfter += '<br />'+excludedIpHelp;
+ $(n).html(contentAfter);
+ }
+ if(idName == 'excludedQueryParameters')
+ {
+ var contentAfter = '<textarea cols="20" rows="4" id="excludedQueryParameters">'+contentBefore.replace(/<br *\/? *>/gi,"\n")+'</textarea>';
+ contentAfter += '<br />'+excludedQueryParametersHelp;
+ $(n).html(contentAfter);
+ }
+ if(idName == 'timezone')
+ {
+ var contentAfter = getTimezoneSelector(contentBefore);
+ contentAfter += '<br />' + timezoneHelp;
+ $(n).html(contentAfter);
+ }
+ if(idName == 'currency')
+ {
+ var contentAfter = getCurrencySelector(contentBefore);
+ contentAfter += '<br />' + currencyHelp;
$(n).html(contentAfter);
}
}
@@ -128,15 +208,55 @@ $(document).ready( function() {
$(this)
.toggle()
.parent()
- .prepend( $('<img src="plugins/UsersManager/images/ok.png" class="updateSite">')
+ .prepend( $('<img src="plugins/UsersManager/images/ok.png" class="updateSite" title="' + _pk_translate('SitesManager_Save_js') + '" />')
.click( function(){ $.ajax( getUpdateSiteAJAX( $('tr#'+idRow) ) ); } )
);
}
);
+ $('#globalSettingsSubmit').click( function() {
+ $.ajax( getGlobalSettingsAJAX() );
+ });
+
+ $('#defaultTimezone').html( getTimezoneSelector(defaultTimezone));
+ $('#defaultCurrency').html( getCurrencySelector(defaultCurrency));
+
$('td.editableSite').click( function(){ $(this).parent().find('.editSite').click(); } );
});
-
+
+function getTimezoneSelector(selectedTimezone)
+{
+ var html = '<select id="timezones">';
+ for(var continent in timezones) {
+ html += '<optgroup label="' + continent + '">';
+ for(var timezoneId in timezones[continent]) {
+ var selected = '';
+ if(timezoneId == selectedTimezone) {
+ selected = ' selected="selected" ';
+ }
+ html += '<option ' + selected + ' value="'+ timezoneId + '">' + timezones[continent][timezoneId] + '</option>';
+ }
+ html += "</optgroup>\n";
+ }
+ html += '</select>';
+ return html;
+}
+
+
+function getCurrencySelector(selectedCurrency)
+{
+ var html = '<select id="currencies">';
+ for(var currency in currencies) {
+ var selected = '';
+ if(currency == selectedCurrency) {
+ selected = ' selected="selected" ';
+ }
+ html += '<option ' + selected + ' value="'+ currency + '">' + currencies[currency] + '</option>';
+ }
+ html += '</select>';
+ return html;
+}
+
function submitSiteOnEnter(e)
{
var key=e.keyCode || e.which;
diff --git a/plugins/SitesManager/templates/SitesManager.tpl b/plugins/SitesManager/templates/SitesManager.tpl
index 39d7f9261a..b61a3eaea2 100644
--- a/plugins/SitesManager/templates/SitesManager.tpl
+++ b/plugins/SitesManager/templates/SitesManager.tpl
@@ -2,9 +2,47 @@
{assign var=showPeriodSelection value=false}
{include file="CoreAdminHome/templates/header.tpl"}
{loadJavascriptTranslations plugins='SitesManager'}
-{include file="CoreAdminHome/templates/menu.tpl"}
+
+<script type="text/javascript">
+{capture assign=excludedIpHelpPlain}{'SitesManager_HelpExcludedIps'|translate:"1.2.3.*":"1.2.*.*"}<br /><br /> {'SitesManager_YourCurrentIpAddressIs'|translate:"<i>$currentIpAddress</i>"}{/capture}
+{assign var=excludedIpHelp value=$excludedIpHelpPlain|inlineHelp}
+var excludedIpHelp = '{$excludedIpHelp|escape:javascript}';
+var aliasUrlsHelp = '{'SitesManager_AliasUrlHelp'|translate|inlineHelp|escape:javascript}';
+{capture assign=defaultTimezoneHelpPlain}
+ {if $timezoneSupported}
+ {'SitesManager_ChooseCityInSameTimezoneAsYou'|translate}
+ {else}
+ {'SitesManager_AdvancedTimezoneSupportNotFound'|translate}
+ {/if} <br /><br />{'SitesManager_UTCTimeIs'|translate:$utcTime}
+{/capture}
+
+{capture assign=timezoneHelpPlain}
+ {$defaultTimezoneHelpPlain}
+ <br /><br />{'SitesManager_ChangingYourTimezoneWillOnlyAffectDataForward'|translate}
+{/capture}
+
+{capture assign=currencyHelpPlain}
+ {'SitesManager_CurrencySymbolWillBeUsedForGoals'|translate|inlineHelp}
+{/capture}
+
+{capture assign=excludedQueryParametersHelp}
+ {'SitesManager_ListOfQueryParametersToExclude'|translate}
+ <br /><br />
+ {'SitesManager_PiwikWillAutomaticallyExcludeCommonSessionParameters'|translate:"phpsessid, sessionid, etc."}
+{/capture}
+{assign var=excludedQueryParametersHelp value=$excludedQueryParametersHelp|inlineHelp}
+var excludedQueryParametersHelp = '{$excludedQueryParametersHelp|escape:javascript}';
+var timezoneHelp = '{$timezoneHelpPlain|inlineHelp|escape:javascript}';
+var currencyHelp = '{$currencyHelpPlain|escape:javascript}';
+{assign var=defaultTimezoneHelp value=$defaultTimezoneHelpPlain|inlineHelp};
+var timezones = {$timezones};
+var currencies = {$currencies};
+var defaultTimezone = '{$defaultTimezone}';
+var defaultCurrency = '{$defaultCurrency}';
+</script>
<script type="text/javascript" src="plugins/SitesManager/templates/SitesManager.js"></script>
+
{literal}
<style>
.addRowSite:hover, .editableSite:hover, .addsite:hover, .cancel:hover, .deleteSite:hover, .editSite:hover, .updateSite:hover{
@@ -22,13 +60,27 @@
#editSites {
valign: top;
}
+option, select {
+ font-size:11px;
+}
+textarea {
+font-size:9pt;
+}
+.admin thead th {
+vertical-align:middle;
+}
</style>
{/literal}
+
<h2>{'SitesManager_WebsitesManagement'|translate}</h2>
-<p>{'SitesManager_MainDescription'|translate}</p>
+<p>{'SitesManager_MainDescription'|translate}
+{if $isSuperUser}
+<br />{'SitesManager_SuperUserCan'|translate:"<a href='#globalSettings'>":"</a>"}
+{/if}
+</p>
+{ajaxErrorDiv}
+{ajaxLoadingDiv}
-<div id="ajaxError" style="display:none"></div>
-<div id="ajaxLoading" style="display:none"><div id="loadingPiwik"><img src="themes/default/images/loading-blue.gif" alt="" /> {'General_LoadingData'|translate} </div></div>
{if $adminSites|@count == 0}
{'SitesManager_NoWebsites'|translate}
@@ -39,6 +91,10 @@
<th>{'SitesManager_Id'|translate}</th>
<th>{'SitesManager_Name'|translate}</th>
<th>{'SitesManager_Urls'|translate}</th>
+ <th>{'SitesManager_ExcludedIps'|translate}</th>
+ <th>{'SitesManager_ExcludedParameters'|translate|replace:" ":"<br />"}</th>
+ <th>{'SitesManager_Timezone'|translate}</th>
+ <th>{'SitesManager_Currency'|translate}</th>
<th> </th>
<th> </th>
<th> {'SitesManager_JsTrackingTag'|translate} </th>
@@ -50,15 +106,75 @@
<td id="idSite">{$site.idsite}</td>
<td id="siteName" class="editableSite">{$site.name}</td>
<td id="urls" class="editableSite">{foreach from=$site.alias_urls item=url}{$url}<br />{/foreach}</td>
- <td><img src='plugins/UsersManager/images/edit.png' class="editSite" id="row{$i}" href='#' alt="" /></td>
- <td><img src='plugins/UsersManager/images/remove.png' class="deleteSite" id="row{$i}" value="{'General_Delete'|translate}" alt="" /></td>
+ <td id="excludedIps" class="editableSite">{foreach from=$site.excluded_ips item=ip}{$ip}<br />{/foreach}</td>
+ <td id="excludedQueryParameters" class="editableSite">{foreach from=$site.excluded_parameters item=parameter}{$parameter}<br />{/foreach}</td>
+ <td id="timezone" class="editableSite">{$site.timezone}</td>
+ <td id="currency" class="editableSite">{$site.currency}</td>
+ <td><img src='plugins/UsersManager/images/edit.png' class="editSite" id="row{$i}" href='#' title="{'General_Edit'|translate}" /></td>
+ <td><img src='plugins/UsersManager/images/remove.png' class="deleteSite" id="row{$i}" title="{'General_Delete'|translate}" value="{'General_Delete'|translate}" /></td>
<td><a href='{url action=displayJavascriptCode idsite=$site.idsite}'>{'SitesManager_ShowTrackingTag'|translate}</a></td>
</tr>
{/foreach}
-
</tbody>
</table>
- <div class="addRowSite"><a href="#"><img src='plugins/UsersManager/images/add.png' alt="" /> {'SitesManager_AddSite'|translate}</a></div>
+ {if $isSuperUser}
+ <div class="addRowSite"><a href=""><img src='plugins/UsersManager/images/add.png' alt="" /> {'SitesManager_AddSite'|translate}</a></div>
+ {/if}
+{/if}
+
+{if $isSuperUser}
+<br />
+ <a name='globalSettings'></a>
+ <h2>{'SitesManager_GlobalWebsitesSettings'|translate}</h2>
+ <br />
+ <table style='width:600px' class="adminTable adminTableNoBorder" >
+
+ <tr><td colspan="2">
+ <b>{'SitesManager_GlobalListExcludedIps'|translate}</b>
+ <p>{'SitesManager_ListOfIpsToBeExcludedOnAllWebsites'|translate} </p>
+ </td></tr>
+ <tr><td>
+ <textarea cols="30" rows="3" id="globalExcludedIps">{$globalExcludedIps}
+</textarea>
+ </td><td>
+ {$excludedIpHelp}
+ </td></tr>
+
+ <tr><td colspan="2">
+ <b>{'SitesManager_GlobalListExcludedQueryParameters'|translate}</b>
+ <p>{'SitesManager_ListOfQueryParametersToBeExcludedOnAllWebsites'|translate} </p>
+ </td></tr>
+ <tr><td>
+ <textarea cols="30" rows="3" id="globalExcludedQueryParameters">{$globalExcludedQueryParameters}
+</textarea>
+ </td><td>
+ {$excludedQueryParametersHelp}
+ </td></tr>
+
+ <tr><td colspan="2">
+ <b>{'SitesManager_DefaultTimezoneForNewWebsites'|translate}</b>
+ <p>{'SitesManager_SelectDefaultTimezone'|translate} </p>
+ </td></tr>
+ <tr><td>
+ <div id='defaultTimezone'></div>
+ </td><td>
+ {$defaultTimezoneHelp}
+ </td></tr>
+
+ <tr><td colspan="2">
+ <b>{'SitesManager_DefaultCurrencyForNewWebsites'|translate}</b>
+ <p>{'SitesManager_SelectDefaultCurrency'|translate} </p>
+ </td></tr>
+ <tr><td>
+ <div id='defaultCurrency'></div>
+ </td><td>
+ {$currencyHelpPlain}
+ </td></tr>
+ </table>
+ <span style='margin-left:20px'><input type="submit" class="submit" id='globalSettingsSubmit' value="{'General_Save'|translate}" /></span>
+ {ajaxErrorDiv id=ajaxErrorGlobalSettings}
+ {ajaxLoadingDiv id=ajaxLoadingGlobalSettings}
{/if}
+<br /><br /><br /><br />
{include file="CoreAdminHome/templates/footer.tpl"}
diff --git a/plugins/SitesManager/tests/SitesManager.test.php b/plugins/SitesManager/tests/SitesManager.test.php
index db4c765812..fbaf8c7adf 100644
--- a/plugins/SitesManager/tests/SitesManager.test.php
+++ b/plugins/SitesManager/tests/SitesManager.test.php
@@ -7,10 +7,15 @@ if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php";
}
-require_once "Database.test.php";
+require_once PIWIK_PATH_TEST_TO_ROOT . '/tests/core/Database.test.php';
class Test_Piwik_SitesManager extends Test_Database
{
+ public function __construct()
+ {
+ Piwik_PluginsManager::getInstance()->unloadPlugin('ExampleFeedburner');
+ parent::__construct();
+ }
public function setUp()
{
parent::setUp();
@@ -19,6 +24,9 @@ class Test_Piwik_SitesManager extends Test_Database
$pseudoMockAccess = new FakeAccess;
FakeAccess::$superUser = true;
Zend_Registry::set('access', $pseudoMockAccess);
+
+ // clear static Site cache
+ Piwik_Site::clearCache();
}
/**
@@ -27,7 +35,7 @@ class Test_Piwik_SitesManager extends Test_Database
public function test_addSite_emptyName()
{
try {
- Piwik_SitesManager_API::addSite("",array("http://piwik.net"));
+ Piwik_SitesManager_API::getInstance()->addSite("",array("http://piwik.net"));
}
catch (Exception $expected) {
return;
@@ -41,7 +49,7 @@ class Test_Piwik_SitesManager extends Test_Database
public function test_addSite_noUrls()
{
try {
- Piwik_SitesManager_API::addSite("name",array());
+ Piwik_SitesManager_API::getInstance()->addSite("name",array());
}
catch (Exception $expected) {
return;
@@ -55,7 +63,7 @@ class Test_Piwik_SitesManager extends Test_Database
public function test_addSite_wrongUrls1()
{
try {
- Piwik_SitesManager_API::addSite("name",array(""));
+ Piwik_SitesManager_API::getInstance()->addSite("name",array(""));
}
catch (Exception $expected) {
return;
@@ -68,7 +76,7 @@ class Test_Piwik_SitesManager extends Test_Database
public function test_addSite_wrongUrls2()
{
try {
- Piwik_SitesManager_API::addSite("name","");
+ Piwik_SitesManager_API::getInstance()->addSite("name","");
}
catch (Exception $expected) {
return;
@@ -82,7 +90,7 @@ class Test_Piwik_SitesManager extends Test_Database
public function test_addSite_wrongUrls3()
{
try {
- Piwik_SitesManager_API::addSite("name","httpww://piwik.net");
+ Piwik_SitesManager_API::getInstance()->addSite("name","httpww://piwik.net");
}
catch (Exception $expected) {
return;
@@ -96,7 +104,7 @@ class Test_Piwik_SitesManager extends Test_Database
public function test_addSite_wrongUrls4()
{
try {
- Piwik_SitesManager_API::addSite("name","httpww://piwik.net/gqg~#");
+ Piwik_SitesManager_API::getInstance()->addSite("name","httpww://piwik.net/gqg~#");
}
catch (Exception $expected) {
return;
@@ -105,19 +113,68 @@ class Test_Piwik_SitesManager extends Test_Database
}
/**
+ * Test with valid IPs
+ */
+ public function test_addSite_excludedIpsAndtimezoneAndCurrencyAndExcludedQueryParameters_valid()
+ {
+ $ips = '1.2.3.4,1.1.1.*,1.2.*.*,1.*.*.*';
+ $timezone = 'Europe/Paris';
+ $currency = 'EUR';
+ $excludedQueryParameters = 'p1,P2, P33333';
+ $expectedExcludedQueryParameters = 'p1,P2,P33333';
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("name","http://piwik.net/", $ips, $excludedQueryParameters,$timezone, $currency);
+ $siteInfo = Piwik_SitesManager_API::getInstance()->getSiteFromId($idsite);
+ $this->assertEqual($siteInfo['excluded_ips'], $ips);
+ $this->assertEqual($siteInfo['timezone'], $timezone);
+ $this->assertEqual($siteInfo['currency'], $currency);
+ $this->assertEqual($siteInfo['excluded_parameters'], $expectedExcludedQueryParameters);
+ }
+
+ /**
+ * Test with invalid IPs
+ */
+ public function test_addSite_excludedIps_notValid()
+ {
+ $invalidIps = array(
+ '35817587341',
+ 'ieagieha',
+ '1.2.3',
+ '*.1.1.1',
+ '*.*.1.1',
+ '*.*.*.1',
+ '*.*.*.*',
+ '1.1.1.1.1',
+ );
+ foreach($invalidIps as $ip)
+ {
+ $raised = false;
+ try {
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("name","http://piwik.net/", $ip);
+ } catch(Exception $e) {
+ $raised = true;
+ }
+ if(!$raised)
+ {
+ $this->fail('was expecting invalid IP exception to raise');
+ }
+ }
+ $this->pass();
+ }
+
+ /**
* one url -> one main_url and nothing inserted as alias urls
*/
public function test_addSite_oneUrl()
{
$url = "http://piwik.net/";
$urlOK = "http://piwik.net";
- $idsite = Piwik_SitesManager_API::addSite("name",$url);
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("name",$url);
$this->assertIsA( $idsite,'int');
- $siteInfo = Piwik_SitesManager_API::getSiteFromId($idsite);
+ $siteInfo = Piwik_SitesManager_API::getInstance()->getSiteFromId($idsite);
$this->assertEqual($siteInfo['main_url'], $urlOK);
- $siteUrls = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $siteUrls = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$this->assertTrue(count($siteUrls)===1);
}
@@ -128,13 +185,13 @@ class Test_Piwik_SitesManager extends Test_Database
{
$urls = array("http://piwik.net/","http://piwik.com","https://piwik.net/test/");
$urlsOK = array("http://piwik.net","http://piwik.com","https://piwik.net/test");
- $idsite = Piwik_SitesManager_API::addSite("super website",$urls);
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("super website",$urls);
$this->assertIsA( $idsite,'int');
- $siteInfo = Piwik_SitesManager_API::getSiteFromId($idsite);
+ $siteInfo = Piwik_SitesManager_API::getInstance()->getSiteFromId($idsite);
$this->assertEqual($siteInfo['main_url'], $urlsOK[0]);
- $siteUrls = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $siteUrls = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$this->assertEqual($siteUrls, $urlsOK);
}
@@ -144,10 +201,10 @@ class Test_Piwik_SitesManager extends Test_Database
public function test_addSite_strangeName()
{
$name = "supertest(); ~@@()''!£\$'%%^'!£";
- $idsite = Piwik_SitesManager_API::addSite($name,"http://piwik.net");
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite($name,"http://piwik.net");
$this->assertIsA( $idsite,'int');
- $siteInfo = Piwik_SitesManager_API::getSiteFromId($idsite);
+ $siteInfo = Piwik_SitesManager_API::getInstance()->getSiteFromId($idsite);
$this->assertEqual($siteInfo['name'], $name);
}
@@ -157,14 +214,14 @@ class Test_Piwik_SitesManager extends Test_Database
public function test_addSite()
{
$name = "website ";
- $idsite = Piwik_SitesManager_API::addSite($name,array("http://piwik.net","http://piwik.com/test/"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite($name,array("http://piwik.net","http://piwik.com/test/"));
$this->assertIsA( $idsite,'int');
- $siteInfo = Piwik_SitesManager_API::getSiteFromId($idsite);
+ $siteInfo = Piwik_SitesManager_API::getInstance()->getSiteFromId($idsite);
$this->assertEqual($siteInfo['name'], $name);
$this->assertEqual($siteInfo['main_url'], "http://piwik.net");
- $siteUrls = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $siteUrls = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$this->assertEqual($siteUrls, array("http://piwik.net","http://piwik.com/test"));
return $idsite;
@@ -177,7 +234,7 @@ class Test_Piwik_SitesManager extends Test_Database
{
$idsite = $this->test_addSite();
- $siteUrlsBefore = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $siteUrlsBefore = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$toAdd = array( "http://piwik1.net",
"http://piwik2.net",
@@ -195,10 +252,10 @@ class Test_Piwik_SitesManager extends Test_Database
"http://l42578gqege.f4",
"http://super.com/test/test/atqata675675/te");
- $insertedUrls = Piwik_SitesManager_API::addSiteAliasUrls($idsite, $toAdd);
+ $insertedUrls = Piwik_SitesManager_API::getInstance()->addSiteAliasUrls($idsite, $toAdd);
$this->assertEqual($insertedUrls, count($toAdd));
- $siteUrlsAfter = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $siteUrlsAfter = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$shouldHave = array_merge($siteUrlsBefore, $toAddValid);
sort($shouldHave);
@@ -215,14 +272,14 @@ class Test_Piwik_SitesManager extends Test_Database
{
$idsite = $this->test_addSite();
- $siteUrlsBefore = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $siteUrlsBefore = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$toAdd = array_merge($siteUrlsBefore, array("http://piwik1.net","http://piwik2.net"));
- $insertedUrls = Piwik_SitesManager_API::addSiteAliasUrls($idsite, $toAdd);
+ $insertedUrls = Piwik_SitesManager_API::getInstance()->addSiteAliasUrls($idsite, $toAdd);
$this->assertEqual($insertedUrls, count($toAdd) - count($siteUrlsBefore));
- $siteUrlsAfter = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $siteUrlsAfter = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$shouldHave = $toAdd;
sort($shouldHave);
@@ -239,14 +296,14 @@ class Test_Piwik_SitesManager extends Test_Database
{
$idsite = $this->test_addSite();
- $siteUrlsBefore = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $siteUrlsBefore = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$toAdd = array();
- $insertedUrls = Piwik_SitesManager_API::addSiteAliasUrls($idsite, $toAdd);
+ $insertedUrls = Piwik_SitesManager_API::getInstance()->addSiteAliasUrls($idsite, $toAdd);
$this->assertEqual($insertedUrls, count($toAdd));
- $siteUrlsAfter = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $siteUrlsAfter = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$shouldHave = $siteUrlsBefore;
sort($shouldHave);
@@ -263,14 +320,14 @@ class Test_Piwik_SitesManager extends Test_Database
{
$idsite = $this->test_addSite();
- $siteUrlsBefore = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $siteUrlsBefore = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$toAdd = $siteUrlsBefore;
- $insertedUrls = Piwik_SitesManager_API::addSiteAliasUrls($idsite, $toAdd);
+ $insertedUrls = Piwik_SitesManager_API::getInstance()->addSiteAliasUrls($idsite, $toAdd);
$this->assertEqual($insertedUrls, 0);
- $siteUrlsAfter = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $siteUrlsAfter = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$shouldHave = $siteUrlsBefore;
sort($shouldHave);
@@ -287,7 +344,7 @@ class Test_Piwik_SitesManager extends Test_Database
$idsite = $this->test_addSite();
$toAdd = array("htt{}p://pigeq.com/test");
try {
- $insertedUrls = Piwik_SitesManager_API::addSiteAliasUrls($idsite, $toAdd);
+ $insertedUrls = Piwik_SitesManager_API::getInstance()->addSiteAliasUrls($idsite, $toAdd);
}
catch (Exception $expected) {
return;
@@ -302,7 +359,7 @@ class Test_Piwik_SitesManager extends Test_Database
{
$toAdd = array("http://pigeq.com/test");
try {
- $insertedUrls = Piwik_SitesManager_API::addSiteAliasUrls(-1, $toAdd);
+ $insertedUrls = Piwik_SitesManager_API::getInstance()->addSiteAliasUrls(-1, $toAdd);
}
catch (Exception $expected) {
return;
@@ -318,7 +375,7 @@ class Test_Piwik_SitesManager extends Test_Database
$toAdd = array("http://pigeq.com/test");
try {
- $insertedUrls = Piwik_SitesManager_API::addSiteAliasUrls(155, $toAdd);
+ $insertedUrls = Piwik_SitesManager_API::getInstance()->addSiteAliasUrls(155, $toAdd);
}
catch (Exception $expected) {
return;
@@ -331,7 +388,7 @@ class Test_Piwik_SitesManager extends Test_Database
*/
function test_getAllSitesId_noId()
{
- $ids = Piwik_SitesManager_API::getAllSitesId();
+ $ids = Piwik_SitesManager_API::getInstance()->getAllSitesId();
$this->assertEqual(array(),$ids);
}
@@ -342,14 +399,14 @@ class Test_Piwik_SitesManager extends Test_Database
{
$name="tetq";
$idsites = array(
- Piwik_SitesManager_API::addSite($name,array("http://piwik.net","http://piwik.com/test/")),
- Piwik_SitesManager_API::addSite($name,array("http://piwik.net","http://piwik.com/test/")),
- Piwik_SitesManager_API::addSite($name,array("http://piwik.net","http://piwik.com/test/")),
- Piwik_SitesManager_API::addSite($name,array("http://piwik.net","http://piwik.com/test/")),
- Piwik_SitesManager_API::addSite($name,array("http://piwik.net","http://piwik.com/test/")),
+ Piwik_SitesManager_API::getInstance()->addSite($name,array("http://piwik.net","http://piwik.com/test/")),
+ Piwik_SitesManager_API::getInstance()->addSite($name,array("http://piwik.net","http://piwik.com/test/")),
+ Piwik_SitesManager_API::getInstance()->addSite($name,array("http://piwik.net","http://piwik.com/test/")),
+ Piwik_SitesManager_API::getInstance()->addSite($name,array("http://piwik.net","http://piwik.com/test/")),
+ Piwik_SitesManager_API::getInstance()->addSite($name,array("http://piwik.net","http://piwik.com/test/")),
);
- $ids = Piwik_SitesManager_API::getAllSitesId();
+ $ids = Piwik_SitesManager_API::getInstance()->getAllSitesId();
$this->assertEqual($idsites,$ids);
}
@@ -360,7 +417,7 @@ class Test_Piwik_SitesManager extends Test_Database
{
try {
- $siteInfo = Piwik_SitesManager_API::getSiteFromId(0);
+ $siteInfo = Piwik_SitesManager_API::getInstance()->getSiteFromId(0);
}
catch (Exception $expected) {
return;
@@ -375,7 +432,7 @@ class Test_Piwik_SitesManager extends Test_Database
{
try {
- $siteInfo = Piwik_SitesManager_API::getSiteFromId("x1");
+ $siteInfo = Piwik_SitesManager_API::getInstance()->getSiteFromId("x1");
}
catch (Exception $expected) {
return;
@@ -388,7 +445,7 @@ class Test_Piwik_SitesManager extends Test_Database
*/
function test_getSiteFromId_wrongId3()
{
- $idsite = Piwik_SitesManager_API::addSite("site",array("http://piwik.net","http://piwik.com/test/"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site",array("http://piwik.net","http://piwik.com/test/"));
$this->assertEqual($idsite,1);
// set noaccess to site 1
@@ -396,7 +453,7 @@ class Test_Piwik_SitesManager extends Test_Database
FakeAccess::setIdSitesAdmin (array());
try {
- $siteInfo = Piwik_SitesManager_API::getSiteFromId(1);
+ $siteInfo = Piwik_SitesManager_API::getInstance()->getSiteFromId(1);
}
catch (Exception $expected) {
return;
@@ -410,10 +467,10 @@ class Test_Piwik_SitesManager extends Test_Database
function test_getSiteFromId_normalId()
{
$name = "website ''";
- $idsite = Piwik_SitesManager_API::addSite($name,array("http://piwik.net","http://piwik.com/test/"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite($name,array("http://piwik.net","http://piwik.com/test/"));
$this->assertIsA( $idsite,'int');
- $siteInfo = Piwik_SitesManager_API::getSiteFromId($idsite);
+ $siteInfo = Piwik_SitesManager_API::getInstance()->getSiteFromId($idsite);
$this->assertEqual($siteInfo['name'], $name);
$this->assertEqual($siteInfo['main_url'], "http://piwik.net");
}
@@ -426,7 +483,7 @@ class Test_Piwik_SitesManager extends Test_Database
{
FakeAccess::setIdSitesAdmin (array());
- $sites = Piwik_SitesManager_API::getSitesWithAdminAccess();
+ $sites = Piwik_SitesManager_API::getInstance()->getSitesWithAdminAccess();
$this->assertEqual($sites, array());
}
@@ -435,18 +492,18 @@ class Test_Piwik_SitesManager extends Test_Database
*/
function test_getSitesWithAdminAccess()
{
- $idsite = Piwik_SitesManager_API::addSite("site1",array("http://piwik.net","http://piwik.com/test/"));
- $idsite = Piwik_SitesManager_API::addSite("site2",array("http://piwik.com/test/"));
- $idsite = Piwik_SitesManager_API::addSite("site3",array("http://piwik.org"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array("http://piwik.net","http://piwik.com/test/"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site2",array("http://piwik.com/test/"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site3",array("http://piwik.org"));
$resultWanted = array(
- 0 => array("idsite" => 1, "name" => "site1", "main_url" =>"http://piwik.net"),
- 1 => array("idsite" => 3, "name" => "site3", "main_url" =>"http://piwik.org"),
+ 0 => array("idsite" => 1, "name" => "site1", "main_url" =>"http://piwik.net", "excluded_ips" => "", 'excluded_parameters' => '', 'timezone' => 'UTC', 'currency' => 'USD'),
+ 1 => array("idsite" => 3, "name" => "site3", "main_url" =>"http://piwik.org", "excluded_ips" => "", 'excluded_parameters' => '', 'timezone' => 'UTC', 'currency' => 'USD'),
);
FakeAccess::setIdSitesAdmin (array(1,3));
- $sites = Piwik_SitesManager_API::getSitesWithAdminAccess();
+ $sites = Piwik_SitesManager_API::getInstance()->getSitesWithAdminAccess();
// we dont test the ts_created
unset($sites[0]['ts_created']);
@@ -462,7 +519,7 @@ class Test_Piwik_SitesManager extends Test_Database
FakeAccess::setIdSitesView (array());
FakeAccess::setIdSitesAdmin (array());
- $sites = Piwik_SitesManager_API::getSitesWithViewAccess();
+ $sites = Piwik_SitesManager_API::getInstance()->getSitesWithViewAccess();
$this->assertEqual($sites, array());
}
@@ -471,19 +528,19 @@ class Test_Piwik_SitesManager extends Test_Database
*/
function test_getSitesWithViewAccess()
{
- $idsite = Piwik_SitesManager_API::addSite("site1",array("http://piwik.net","http://piwik.com/test/"));
- $idsite = Piwik_SitesManager_API::addSite("site2",array("http://piwik.com/test/"));
- $idsite = Piwik_SitesManager_API::addSite("site3",array("http://piwik.org"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array("http://piwik.net","http://piwik.com/test/"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site2",array("http://piwik.com/test/"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site3",array("http://piwik.org"));
$resultWanted = array(
- 0 => array("idsite" => 1, "name" => "site1", "main_url" =>"http://piwik.net"),
- 1 => array("idsite" => 3, "name" => "site3", "main_url" =>"http://piwik.org"),
+ 0 => array("idsite" => 1, "name" => "site1", "main_url" =>"http://piwik.net", "excluded_ips" => "", 'excluded_parameters' => '', 'timezone' => 'UTC', 'currency' => 'USD'),
+ 1 => array("idsite" => 3, "name" => "site3", "main_url" =>"http://piwik.org", "excluded_ips" => "", 'excluded_parameters' => '', 'timezone' => 'UTC', 'currency' => 'USD'),
);
FakeAccess::setIdSitesView (array(1,3));
FakeAccess::setIdSitesAdmin (array());
- $sites = Piwik_SitesManager_API::getSitesWithViewAccess();
+ $sites = Piwik_SitesManager_API::getInstance()->getSitesWithViewAccess();
// we dont test the ts_created
unset($sites[0]['ts_created']);
unset($sites[1]['ts_created']);
@@ -498,7 +555,7 @@ class Test_Piwik_SitesManager extends Test_Database
FakeAccess::setIdSitesView (array());
FakeAccess::setIdSitesAdmin (array());
- $sites = Piwik_SitesManager_API::getSitesWithAtLeastViewAccess();
+ $sites = Piwik_SitesManager_API::getInstance()->getSitesWithAtLeastViewAccess();
$this->assertEqual($sites, array());
}
@@ -507,19 +564,19 @@ class Test_Piwik_SitesManager extends Test_Database
*/
function test_getSitesWithAtLeastViewAccess()
{
- $idsite = Piwik_SitesManager_API::addSite("site1",array("http://piwik.net","http://piwik.com/test/"));
- $idsite = Piwik_SitesManager_API::addSite("site2",array("http://piwik.com/test/"));
- $idsite = Piwik_SitesManager_API::addSite("site3",array("http://piwik.org"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array("http://piwik.net","http://piwik.com/test/"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site2",array("http://piwik.com/test/"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site3",array("http://piwik.org"));
$resultWanted = array(
- 0 => array("idsite" => 1, "name" => "site1", "main_url" =>"http://piwik.net"),
- 1 => array("idsite" => 3, "name" => "site3", "main_url" =>"http://piwik.org"),
+ 0 => array("idsite" => 1, "name" => "site1", "main_url" =>"http://piwik.net", "excluded_ips" => "", 'excluded_parameters' => '', 'timezone' => 'UTC', 'currency' => 'USD'),
+ 1 => array("idsite" => 3, "name" => "site3", "main_url" =>"http://piwik.org", "excluded_ips" => "", 'excluded_parameters' => '', 'timezone' => 'UTC', 'currency' => 'USD'),
);
FakeAccess::setIdSitesView (array(1,3));
FakeAccess::setIdSitesAdmin (array());
- $sites = Piwik_SitesManager_API::getSitesWithAtLeastViewAccess();
+ $sites = Piwik_SitesManager_API::getInstance()->getSitesWithAtLeastViewAccess();
// we dont test the ts_created
unset($sites[0]['ts_created']);
unset($sites[1]['ts_created']);
@@ -532,9 +589,9 @@ class Test_Piwik_SitesManager extends Test_Database
*/
function test_getSiteUrlsFromId_noUrls()
{
- $idsite = Piwik_SitesManager_API::addSite("site1",array("http://piwik.net"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array("http://piwik.net"));
- $urls = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $urls = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$this->assertEqual(array("http://piwik.net"),$urls);
}
@@ -549,14 +606,14 @@ class Test_Piwik_SitesManager extends Test_Database
"http://piwik.com");
sort($site);
- $idsite = Piwik_SitesManager_API::addSite("site1",$site);
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",$site);
$siteWanted = array("http://piwik.net",
"http://piwik.org",
"http://piwik.com");
sort($siteWanted);
- $urls = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $urls = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$this->assertEqual($siteWanted, $urls);
@@ -571,7 +628,7 @@ class Test_Piwik_SitesManager extends Test_Database
FakeAccess::setIdSitesAdmin (array());
try {
- Piwik_SitesManager_API::getSiteUrlsFromId(1);
+ Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId(1);
}
catch (Exception $expected) {
return;
@@ -588,12 +645,12 @@ class Test_Piwik_SitesManager extends Test_Database
"http://piwiknew.net",
"http://piwiknew.org",
"http://piwiknew.fr");
- $idsite = Piwik_SitesManager_API::addSite("site1",$urls);
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",$urls);
$newMainUrl = "http://main.url";
- Piwik_SitesManager_API::updateSite($idsite, "test toto@{}", $newMainUrl );
+ Piwik_SitesManager_API::getInstance()->updateSite($idsite, "test toto@{}", $newMainUrl );
- $allUrls = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $allUrls = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
$this->assertEqual($allUrls[0], $newMainUrl);
$aliasUrls = array_slice($allUrls,1);
@@ -605,12 +662,12 @@ class Test_Piwik_SitesManager extends Test_Database
*/
function test_updateSite_strangeNameNoUrl()
{
- $idsite = Piwik_SitesManager_API::addSite("site1","http://main.url");
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1","http://main.url");
$newName ="test toto@{'786'}";
- Piwik_SitesManager_API::updateSite($idsite, $newName );
+ Piwik_SitesManager_API::getInstance()->updateSite($idsite, $newName );
- $site = Piwik_SitesManager_API::getSiteFromId($idsite);
+ $site = Piwik_SitesManager_API::getInstance()->getSiteFromId($idsite);
$this->assertEqual($site['name'],$newName);
// url didn't change because parameter url NULL in updateSite
@@ -629,20 +686,168 @@ class Test_Piwik_SitesManager extends Test_Database
"http://piwiknew.net",
"http://piwiknew.org",
"http://piwiknew.fr");
- $idsite = Piwik_SitesManager_API::addSite("site1",$urls);
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",$urls);
$newurls = array("http://piwiknew2.com",
"http://piwiknew2.net",
"http://piwiknew2.org",
"http://piwiknew2.fr");
- Piwik_SitesManager_API::updateSite($idsite, "test toto@{}",$newurls );
+ Piwik_SitesManager_API::getInstance()->updateSite($idsite, "test toto@{}",$newurls );
- $allUrls = Piwik_SitesManager_API::getSiteUrlsFromId($idsite);
+ $allUrls = Piwik_SitesManager_API::getInstance()->getSiteUrlsFromId($idsite);
sort($allUrls);
sort($newurls);
$this->assertEqual($allUrls,$newurls);
}
-}
+ function test_addSites_invalidTimezone()
+ {
+ // trying invalid timezones
+ try {
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array('http://example.org'), '', '', 'UTC+15');
+ $this->fail('invalid timezone should raise an exception');
+ } catch(Exception $e) {
+ }
+ try {
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array('http://example.org'), '', '', 'Paris');
+ $this->fail('invalid timezone should raise an exception');
+ } catch(Exception $e) {
+ }
+ $this->pass();
+ }
+
+ function test_addSites_invalidCurrency()
+ {
+ $invalidCurrency = '€';
+ try {
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array('http://example.org'), '', 'UTC', $invalidCurrency);
+ $this->fail('invalid currency should raise an exception');
+ } catch(Exception $e) {
+ }
+ $this->pass();
+ }
+
+ function test_setDefaultTimezoneAndCurrencyAndExcludedQueryParametersAndExcludedIps()
+ {
+ // test that they return default values
+ $defaultTimezone = Piwik_SitesManager_API::getInstance()->getDefaultTimezone();
+ $this->assertEqual($defaultTimezone, 'UTC');
+ $defaultCurrency = Piwik_SitesManager_API::getInstance()->getDefaultCurrency();
+ $this->assertEqual($defaultCurrency, 'USD');
+ $excludedIps = Piwik_SitesManager_API::getInstance()->getExcludedIpsGlobal();
+ $this->assertEqual($excludedIps, '');
+ $excludedQueryParameters = Piwik_SitesManager_API::getInstance()->getExcludedQueryParametersGlobal();
+ $this->assertEqual($excludedQueryParameters, '');
+
+ // test that when not specified, defaults are set as expected
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array('http://example.org'));
+ $site = new Piwik_Site($idsite);
+ $this->assertEqual($site->getTimezone(), 'UTC');
+ $this->assertEqual($site->getCurrency(), 'USD');
+ $this->assertEqual($site->getExcludedQueryParameters(), '');
+ $this->assertEqual($site->getExcludedIps(), '');
+
+ // set the global timezone and get it
+ $newDefaultTimezone = 'UTC+5.5';
+ Piwik_SitesManager_API::getInstance()->setDefaultTimezone($newDefaultTimezone);
+ $defaultTimezone = Piwik_SitesManager_API::getInstance()->getDefaultTimezone();
+ $this->assertEqual($defaultTimezone, $newDefaultTimezone);
+
+ // set the default currency and get it
+ $newDefaultCurrency = 'EUR';
+ Piwik_SitesManager_API::getInstance()->setDefaultCurrency($newDefaultCurrency);
+ $defaultCurrency = Piwik_SitesManager_API::getInstance()->getDefaultCurrency();
+ $this->assertEqual($defaultCurrency, $newDefaultCurrency);
+
+ // set the global IPs to exclude and get it
+ $newGlobalExcludedIps = '1.1.1.*,1.1.*.*,150.1.1.1';
+ Piwik_SitesManager_API::getInstance()->setGlobalExcludedIps($newGlobalExcludedIps);
+ $globalExcludedIps = Piwik_SitesManager_API::getInstance()->getExcludedIpsGlobal();
+ $this->assertEqual($globalExcludedIps, $newGlobalExcludedIps);
+
+ // set the global URL query params to exclude and get it
+ $newGlobalExcludedQueryParameters = 'PHPSESSID,blabla, TesT';
+ // removed the space
+ $expectedGlobalExcludedQueryParameters = 'PHPSESSID,blabla,TesT';
+ Piwik_SitesManager_API::getInstance()->setGlobalExcludedQueryParameters($newGlobalExcludedQueryParameters);
+ $globalExcludedQueryParameters = Piwik_SitesManager_API::getInstance()->getExcludedQueryParametersGlobal();
+ $this->assertEqual($globalExcludedQueryParameters, $expectedGlobalExcludedQueryParameters);
+
+ // create a website and check that default currency and default timezone are set
+ // however, excluded IPs and excluded query Params are not returned
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array('http://example.org'), '', '', $newDefaultTimezone);
+ $site = new Piwik_Site($idsite);
+ $this->assertEqual($site->getTimezone(), $newDefaultTimezone);
+ $this->assertEqual($site->getCreationDate()->toString(), date('Y-m-d'));
+ $this->assertEqual($site->getCurrency(), $newDefaultCurrency);
+ $this->assertEqual($site->getExcludedIps(), '');
+ $this->assertEqual($site->getExcludedQueryParameters(), '');
+ }
+
+ function test_getSitesIdFromSiteUrl_SuperUser()
+ {
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array("http://piwik.net","http://piwik.com"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site2",array("http://piwik.com","http://piwik.net"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site3",array("http://piwik.com","http://piwik.org"));
+
+ $idsites = Piwik_SitesManager_API::getInstance()->getSitesIdFromSiteUrl('http://piwik.org');
+ $this->assertTrue(count($idsites) == 1);
+
+ $idsites = Piwik_SitesManager_API::getInstance()->getSitesIdFromSiteUrl('http://piwik.net');
+ $this->assertTrue(count($idsites) == 2);
+
+ $idsites = Piwik_SitesManager_API::getInstance()->getSitesIdFromSiteUrl('http://piwik.com');
+ $this->assertTrue(count($idsites) == 3);
+ }
+
+ function test_getSitesIdFromSiteUrl_User()
+ {
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array("http://piwik.net","http://piwik.com"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site2",array("http://piwik.com","http://piwik.net"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site3",array("http://piwik.com","http://piwik.org"));
+
+ $saveAccess = Zend_Registry::get('access');
+
+ Piwik_UsersManager_API::getInstance()->addUser("user1", "geqgegagae", "tegst@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->setUserAccess("user1", "view", array(1));
+
+ Piwik_UsersManager_API::getInstance()->addUser("user2", "geqgegagae", "tegst2@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->setUserAccess("user2", "view", array(1));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("user2", "admin", array(3));
+
+ Piwik_UsersManager_API::getInstance()->addUser("user3", "geqgegagae", "tegst3@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->setUserAccess("user3", "view", array(1,2));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("user3", "admin", array(3));
+
+ $pseudoMockAccess = new FakeAccess;
+ FakeAccess::$superUser = false;
+ FakeAccess::$identity = 'user1';
+ FakeAccess::setIdSitesView (array(1));
+ FakeAccess::setIdSitesAdmin (array());
+ Zend_Registry::set('access', $pseudoMockAccess);
+ $idsites = Piwik_SitesManager_API::getInstance()->getSitesIdFromSiteUrl('http://piwik.com');
+ $this->assertTrue(count($idsites) == 1);
+
+ $pseudoMockAccess = new FakeAccess;
+ FakeAccess::$superUser = false;
+ FakeAccess::$identity = 'user2';
+ FakeAccess::setIdSitesView (array(1));
+ FakeAccess::setIdSitesAdmin (array(3));
+ Zend_Registry::set('access', $pseudoMockAccess);
+ $idsites = Piwik_SitesManager_API::getInstance()->getSitesIdFromSiteUrl('http://piwik.com');
+ $this->assertTrue(count($idsites) == 2);
+
+ $pseudoMockAccess = new FakeAccess;
+ FakeAccess::$superUser = false;
+ FakeAccess::$identity = 'user3';
+ FakeAccess::setIdSitesView (array(1,2));
+ FakeAccess::setIdSitesAdmin (array(3));
+ Zend_Registry::set('access', $pseudoMockAccess);
+ $idsites = Piwik_SitesManager_API::getInstance()->getSitesIdFromSiteUrl('http://piwik.com');
+ $this->assertTrue(count($idsites) == 3);
+
+ Zend_Registry::set('access', $saveAccess);
+ }
+}
diff --git a/plugins/UserCountry/API.php b/plugins/UserCountry/API.php
index 3b83786e9a..107c072b3d 100644
--- a/plugins/UserCountry/API.php
+++ b/plugins/UserCountry/API.php
@@ -10,9 +10,6 @@
* @package Piwik_UserCountry
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see core/DataFiles/Countries.php
* @see plugins/UserCountry/functions.php
diff --git a/plugins/UserCountry/UserCountry.php b/plugins/UserCountry/UserCountry.php
index 5c502d872d..f397b0a379 100644
--- a/plugins/UserCountry/UserCountry.php
+++ b/plugins/UserCountry/UserCountry.php
@@ -19,11 +19,10 @@ class Piwik_UserCountry extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Visitors Country',
- 'description' => 'Reports the Country of the visitors.',
+ 'description' => Piwik_Translate('UserCountry_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
}
@@ -35,6 +34,7 @@ class Piwik_UserCountry extends Piwik_Plugin
'ArchiveProcessing_Period.compute' => 'archivePeriod',
'WidgetsList.add' => 'addWidgets',
'Menu.add' => 'addMenu',
+ 'Goals.getAvailableGoalSegments' => 'addGoalSegments',
);
return $hooks;
}
@@ -47,7 +47,26 @@ class Piwik_UserCountry extends Piwik_Plugin
function addMenu()
{
- Piwik_AddMenu('General_Visitors', 'UserCountry_SubmenuLocations', array('module' => 'UserCountry'));
+ Piwik_AddMenu('General_Visitors', 'UserCountry_SubmenuLocations', array('module' => 'UserCountry', 'action' => 'index'));
+ }
+
+ function addGoalSegments( $notification )
+ {
+ $segments =& $notification->getNotificationObject();
+ $segments = array_merge($segments, array(
+ array(
+ 'group' => Piwik_Translate('UserCountry_Location'),
+ 'name' => Piwik_Translate('UserCountry_Country'),
+ 'module' => 'UserCountry',
+ 'action' => 'getCountry',
+ ),
+ array(
+ 'group' => Piwik_Translate('UserCountry_Location'),
+ 'name' => Piwik_Translate('UserCountry_Continent'),
+ 'module' => 'UserCountry',
+ 'action' => 'getContinent',
+ ),
+ ));
}
function archivePeriod( $notification )
diff --git a/plugins/UserSettings/API.php b/plugins/UserSettings/API.php
index 8e3b65c734..aab8f3416a 100644
--- a/plugins/UserSettings/API.php
+++ b/plugins/UserSettings/API.php
@@ -10,9 +10,6 @@
* @package Piwik_UserSettings
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see plugins/UserSettings/functions.php
*/
@@ -42,8 +39,10 @@ class Piwik_UserSettings_API
$dataTable = $archive->getDataTable($name);
$dataTable->filter('Sort', array(Piwik_Archive::INDEX_NB_VISITS));
$dataTable->queueFilter('ReplaceColumnNames');
+ $dataTable->queueFilter('ReplaceSummaryRowLabel');
return $dataTable;
}
+
public function getResolution( $idSite, $period, $date )
{
$dataTable = $this->getDataTable('UserSettings_resolution', $idSite, $period, $date);
diff --git a/plugins/UserSettings/Controller.php b/plugins/UserSettings/Controller.php
index 367ef275d2..ac3a72291e 100644
--- a/plugins/UserSettings/Controller.php
+++ b/plugins/UserSettings/Controller.php
@@ -58,7 +58,7 @@ class Piwik_UserSettings_Controller extends Piwik_Controller
__FUNCTION__,
'UserSettings.getOS'
);
- $view->setColumnTranslation('label', Piwik_Translate('UserSettings_ColumnOperatinsSystem'));
+ $view->setColumnTranslation('label', Piwik_Translate('UserSettings_ColumnOperatingSystem'));
return $this->renderView($view, $fetch);
}
diff --git a/plugins/UserSettings/UserSettings.php b/plugins/UserSettings/UserSettings.php
index 66243c7ce6..bb0c10dddf 100644
--- a/plugins/UserSettings/UserSettings.php
+++ b/plugins/UserSettings/UserSettings.php
@@ -19,29 +19,21 @@ class Piwik_UserSettings extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Visitors Settings',
- 'description' => 'Reports various User Settings: Browser, Browser Family, Operating System, Plugins, Resolution, Global Settings.',
+ 'description' => Piwik_Translate('UserSettings_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
}
- // source: http://en.wikipedia.org/wiki/List_of_web_browsers
- static public $browserType = array(
- "ie" => array("IE"),
- "gecko" => array("NS", "PX", "FF", "FB", "CA", "GA", "KM", "MO", "SM"),
- "khtml" => array("SF", "KO", "OW", "CH", "AR"),
- "opera" => array("OP")
- );
-
static public $browserType_display = array(
- 'ie' => 'Internet Explorer',
- 'gecko' => 'Gecko (Mozilla, Netscape)',
- 'khtml' => 'KHTML (Safari, Chrome)',
- 'opera' => 'Opera',
+ 'ie' => 'Trident (IE)',
+ 'gecko' => 'Gecko (Firefox)',
+ 'khtml' => 'KHTML (Konqueror)',
+ 'webkit' => 'WebKit (Safari)',
+ 'opera' => 'Presto (Opera)',
);
function getListHooksRegistered()
@@ -68,12 +60,14 @@ class Piwik_UserSettings extends Piwik_Plugin
function addMenu()
{
- Piwik_AddMenu('General_Visitors', 'UserSettings_SubmenuSettings', array('module' => 'UserSettings'));
+ Piwik_AddMenu('General_Visitors', 'UserSettings_SubmenuSettings', array('module' => 'UserSettings', 'action' => 'index'));
}
function archiveDay( $notification )
{
require_once PIWIK_INCLUDE_PATH . '/plugins/UserSettings/functions.php';
+ $maximumRowsInDataTable = Zend_Registry::get('config')->General->datatable_archiving_maximum_rows_standard;
+ $columnToSortByBeforeTruncation = Piwik_Archive::INDEX_NB_VISITS;
$archiveProcessing = $notification->getNotificationObject();
$this->archiveProcessing = $archiveProcessing;
@@ -82,21 +76,21 @@ class Piwik_UserSettings extends Piwik_Plugin
$labelSQL = "CONCAT(config_os, ';', config_browser_name, ';', config_resolution)";
$interestByConfiguration = $archiveProcessing->getArrayInterestForLabel($labelSQL);
$tableConfiguration = $archiveProcessing->getDataTableFromArray($interestByConfiguration);
- $archiveProcessing->insertBlobRecord($recordName, $tableConfiguration->getSerialized());
+ $archiveProcessing->insertBlobRecord($recordName, $tableConfiguration->getSerialized($maximumRowsInDataTable, null, $columnToSortByBeforeTruncation));
destroy($tableConfiguration);
$recordName = 'UserSettings_os';
$labelSQL = "config_os";
$interestByOs = $archiveProcessing->getArrayInterestForLabel($labelSQL);
$tableOs = $archiveProcessing->getDataTableFromArray($interestByOs);
- $archiveProcessing->insertBlobRecord($recordName, $tableOs->getSerialized());
+ $archiveProcessing->insertBlobRecord($recordName, $tableOs->getSerialized($maximumRowsInDataTable, null, $columnToSortByBeforeTruncation));
destroy($tableOs);
$recordName = 'UserSettings_browser';
$labelSQL = "CONCAT(config_browser_name, ';', config_browser_version)";
$interestByBrowser = $archiveProcessing->getArrayInterestForLabel($labelSQL);
$tableBrowser = $archiveProcessing->getDataTableFromArray($interestByBrowser);
- $archiveProcessing->insertBlobRecord($recordName, $tableBrowser->getSerialized());
+ $archiveProcessing->insertBlobRecord($recordName, $tableBrowser->getSerialized($maximumRowsInDataTable, null, $columnToSortByBeforeTruncation));
$recordName = 'UserSettings_browserType';
$tableBrowserType = $this->getTableBrowserByType($tableBrowser);
@@ -109,7 +103,7 @@ class Piwik_UserSettings extends Piwik_Plugin
$interestByResolution = $archiveProcessing->getArrayInterestForLabel($labelSQL);
$tableResolution = $archiveProcessing->getDataTableFromArray($interestByResolution);
$tableResolution->filter('ColumnCallbackDeleteRow', array('label', 'Piwik_UserSettings_keepStrlenGreater'));
- $archiveProcessing->insertBlobRecord($recordName, $tableResolution->getSerialized());
+ $archiveProcessing->insertBlobRecord($recordName, $tableResolution->getSerialized($maximumRowsInDataTable, null, $columnToSortByBeforeTruncation));
$recordName = 'UserSettings_wideScreen';
$tableWideScreen = $this->getTableWideScreen($tableResolution);
@@ -126,6 +120,7 @@ class Piwik_UserSettings extends Piwik_Plugin
function archivePeriod( $notification )
{
$archiveProcessing = $notification->getNotificationObject();
+ $maximumRowsInDataTable = Zend_Registry::get('config')->General->datatable_archiving_maximum_rows_standard;
$dataTableToSum = array(
'UserSettings_configuration',
@@ -137,7 +132,7 @@ class Piwik_UserSettings extends Piwik_Plugin
'UserSettings_plugin',
);
- $archiveProcessing->archiveDataTable($dataTableToSum);
+ $archiveProcessing->archiveDataTable($dataTableToSum, null, $maximumRowsInDataTable);
}
protected function getTableWideScreen($tableResolution)
diff --git a/plugins/UserSettings/functions.php b/plugins/UserSettings/functions.php
index 95d19e4817..c2aebe7b64 100644
--- a/plugins/UserSettings/functions.php
+++ b/plugins/UserSettings/functions.php
@@ -10,9 +10,6 @@
* @package Piwik_UserSettings
*/
-// no direct access
-defined('PIWIK_INCLUDE_PATH') or die;
-
/**
* @see libs/UserAgentParser/UserAgentParser.php
*/
@@ -32,7 +29,7 @@ function Piwik_getOSLabel($osId)
}
if( $osId == 'UNK')
{
- return Piwik_Translate('General_Unknown');
+ return html_entity_decode(Piwik_Translate('General_Unknown'), ENT_COMPAT, 'UTF-8');
}
return $osId;
}
@@ -46,7 +43,7 @@ function Piwik_getOSShortLabel($osId)
}
if( $osId == 'UNK')
{
- return Piwik_Translate('General_Unknown');
+ return html_entity_decode(Piwik_Translate('General_Unknown'), ENT_COMPAT, 'UTF-8');
}
return $osId;
}
@@ -59,7 +56,7 @@ function Piwik_getBrowserTypeLabel($oldLabel)
}
if($oldLabel == 'unknown')
{
- return Piwik_Translate('General_Unknown');
+ return html_entity_decode(Piwik_Translate('General_Unknown'), ENT_COMPAT, 'UTF-8');
}
return $oldLabel;
}
@@ -78,7 +75,7 @@ function Piwik_getConfigurationLabel($str)
$browser = UserAgentParser::getBrowserNameFromId($name);
if($browser === false)
{
- $browser = Piwik_Translate('General_Unknown');
+ $browser = html_entity_decode(Piwik_Translate('General_Unknown'), ENT_COMPAT, 'UTF-8');
}
$resolution = $values[2];
return $os . " / " . $browser . " / " . $resolution;
@@ -95,7 +92,7 @@ function Piwik_getBrowserLabel($oldLabel)
}
if( $browserId == 'UNK')
{
- return Piwik_Translate('General_Unknown');
+ return html_entity_decode(Piwik_Translate('General_Unknown'), ENT_COMPAT, 'UTF-8');
}
return $oldLabel;
}
@@ -111,7 +108,7 @@ function Piwik_getBrowserShortLabel($oldLabel)
}
if( $browserId == 'UNK')
{
- return Piwik_Translate('General_Unknown');
+ return html_entity_decode(Piwik_Translate('General_Unknown'), ENT_COMPAT, 'UTF-8');
}
return $oldLabel;
}
@@ -129,11 +126,19 @@ function Piwik_getBrowserVersion($str)
function Piwik_getBrowsersLogo($label)
{
$id = Piwik_getBrowserId($label);
+ // For aggregated row 'Others'
+ if(empty($id)) {
+ $id = 'UNK';
+ }
return 'plugins/UserSettings/images/browsers/'. $id . '.gif';
}
function Piwik_getOSLogo($label)
{
+ // For aggregated row 'Others'
+ if(empty($label)) {
+ $label = 'UNK';
+ }
$path = 'plugins/UserSettings/images/os/'. $label . '.gif';
return $path;
}
@@ -171,14 +176,6 @@ function Piwik_getScreenTypeFromResolution($resolution)
function Piwik_getBrowserFamily($browserLabel)
{
- $familyNameToUse = 'unknown';
- foreach(Piwik_UserSettings::$browserType as $familyName => $aBrowsers)
- {
- if(in_array(substr($browserLabel, 0, 2), $aBrowsers))
- {
- $familyNameToUse = $familyName;
- break;
- }
- }
+ $familyNameToUse = UserAgentParser::getBrowserFamilyFromId(substr($browserLabel, 0, 2));
return $familyNameToUse;
-}
+}
diff --git a/plugins/UserSettings/images/browsers/AB.gif b/plugins/UserSettings/images/browsers/AB.gif
new file mode 100644
index 0000000000..cd651565b1
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/AB.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/AN.gif b/plugins/UserSettings/images/browsers/AN.gif
new file mode 100644
index 0000000000..9c69167f2f
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/AN.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/BE.gif b/plugins/UserSettings/images/browsers/BE.gif
new file mode 100644
index 0000000000..2e952f5c2c
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/BE.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/BX.gif b/plugins/UserSettings/images/browsers/BX.gif
index 73053607b7..a34ba48408 100644
--- a/plugins/UserSettings/images/browsers/BX.gif
+++ b/plugins/UserSettings/images/browsers/BX.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/CO.gif b/plugins/UserSettings/images/browsers/CO.gif
new file mode 100644
index 0000000000..462c7f6e6c
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/CO.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/CS.gif b/plugins/UserSettings/images/browsers/CS.gif
new file mode 100644
index 0000000000..9078936525
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/CS.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/DI.gif b/plugins/UserSettings/images/browsers/DI.gif
index 73053607b7..0ae8bbcdb0 100644
--- a/plugins/UserSettings/images/browsers/DI.gif
+++ b/plugins/UserSettings/images/browsers/DI.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/EL.gif b/plugins/UserSettings/images/browsers/EL.gif
new file mode 100644
index 0000000000..92de33e4ab
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/EL.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/EP.gif b/plugins/UserSettings/images/browsers/EP.gif
new file mode 100644
index 0000000000..647095ec78
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/EP.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/FD.gif b/plugins/UserSettings/images/browsers/FD.gif
new file mode 100644
index 0000000000..e39e41ca22
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/FD.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/FE.gif b/plugins/UserSettings/images/browsers/FE.gif
new file mode 100644
index 0000000000..d9c6c9edac
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/FE.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/FL.gif b/plugins/UserSettings/images/browsers/FL.gif
new file mode 100644
index 0000000000..c52999e4ac
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/FL.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/GE.gif b/plugins/UserSettings/images/browsers/GE.gif
new file mode 100644
index 0000000000..3401b729d3
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/GE.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/HA.gif b/plugins/UserSettings/images/browsers/HA.gif
new file mode 100644
index 0000000000..7c87ca4f36
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/HA.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/KP.gif b/plugins/UserSettings/images/browsers/KP.gif
new file mode 100644
index 0000000000..58258f12fc
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/KP.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/KZ.gif b/plugins/UserSettings/images/browsers/KZ.gif
new file mode 100644
index 0000000000..3042cc80f5
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/KZ.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/MI.gif b/plugins/UserSettings/images/browsers/MI.gif
new file mode 100644
index 0000000000..0688fffc23
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/MI.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/WO.gif b/plugins/UserSettings/images/browsers/WO.gif
new file mode 100644
index 0000000000..fd0debbd8c
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/WO.gif
Binary files differ
diff --git a/plugins/UserSettings/images/browsers/WP.gif b/plugins/UserSettings/images/browsers/WP.gif
new file mode 100644
index 0000000000..22cd2a5adf
--- /dev/null
+++ b/plugins/UserSettings/images/browsers/WP.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/AIX.gif b/plugins/UserSettings/images/os/AIX.gif
index 90581d1377..9a663f2be6 100644
--- a/plugins/UserSettings/images/os/AIX.gif
+++ b/plugins/UserSettings/images/os/AIX.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/AMI.gif b/plugins/UserSettings/images/os/AMI.gif
new file mode 100644
index 0000000000..2b28a93a64
--- /dev/null
+++ b/plugins/UserSettings/images/os/AMI.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/BEO.gif b/plugins/UserSettings/images/os/BEO.gif
new file mode 100644
index 0000000000..f38d8b90e3
--- /dev/null
+++ b/plugins/UserSettings/images/os/BEO.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/BSD.gif b/plugins/UserSettings/images/os/BSD.gif
index c09e375398..326d33d8de 100644
--- a/plugins/UserSettings/images/os/BSD.gif
+++ b/plugins/UserSettings/images/os/BSD.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/DFB.gif b/plugins/UserSettings/images/os/DFB.gif
new file mode 100644
index 0000000000..6935e91a80
--- /dev/null
+++ b/plugins/UserSettings/images/os/DFB.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/DSI.gif b/plugins/UserSettings/images/os/DSI.gif
new file mode 100644
index 0000000000..6fb563dfa5
--- /dev/null
+++ b/plugins/UserSettings/images/os/DSI.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/HPX.gif b/plugins/UserSettings/images/os/HPX.gif
index 37a836180b..062ec181a9 100644
--- a/plugins/UserSettings/images/os/HPX.gif
+++ b/plugins/UserSettings/images/os/HPX.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/IPA.gif b/plugins/UserSettings/images/os/IPA.gif
new file mode 100644
index 0000000000..4e9113fac4
--- /dev/null
+++ b/plugins/UserSettings/images/os/IPA.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/IPH.gif b/plugins/UserSettings/images/os/IPH.gif
index dae428be44..82e583558d 100644
--- a/plugins/UserSettings/images/os/IPH.gif
+++ b/plugins/UserSettings/images/os/IPH.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/IRI.gif b/plugins/UserSettings/images/os/IRI.gif
index f615f25cf0..65dd44a9aa 100644
--- a/plugins/UserSettings/images/os/IRI.gif
+++ b/plugins/UserSettings/images/os/IRI.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/LIN.gif b/plugins/UserSettings/images/os/LIN.gif
index 2ef898de04..12e3888175 100644
--- a/plugins/UserSettings/images/os/LIN.gif
+++ b/plugins/UserSettings/images/os/LIN.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/MAC.gif b/plugins/UserSettings/images/os/MAC.gif
index d6af9e1d57..73b2d9cac5 100644
--- a/plugins/UserSettings/images/os/MAC.gif
+++ b/plugins/UserSettings/images/os/MAC.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/NBS.gif b/plugins/UserSettings/images/os/NBS.gif
index c09e375398..33e6749cf0 100644
--- a/plugins/UserSettings/images/os/NBS.gif
+++ b/plugins/UserSettings/images/os/NBS.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/NDS.gif b/plugins/UserSettings/images/os/NDS.gif
new file mode 100644
index 0000000000..fe731351e4
--- /dev/null
+++ b/plugins/UserSettings/images/os/NDS.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/OBS.gif b/plugins/UserSettings/images/os/OBS.gif
new file mode 100644
index 0000000000..01c1b07a98
--- /dev/null
+++ b/plugins/UserSettings/images/os/OBS.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/OS2.gif b/plugins/UserSettings/images/os/OS2.gif
index 90fbdab26c..4ec088d1b9 100644
--- a/plugins/UserSettings/images/os/OS2.gif
+++ b/plugins/UserSettings/images/os/OS2.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/POS.gif b/plugins/UserSettings/images/os/POS.gif
new file mode 100644
index 0000000000..49e089ef24
--- /dev/null
+++ b/plugins/UserSettings/images/os/POS.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/SOS.gif b/plugins/UserSettings/images/os/SOS.gif
index f4a97e87f2..9d17c20246 100644
--- a/plugins/UserSettings/images/os/SOS.gif
+++ b/plugins/UserSettings/images/os/SOS.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/SYL.gif b/plugins/UserSettings/images/os/SYL.gif
new file mode 100644
index 0000000000..c6e1f25687
--- /dev/null
+++ b/plugins/UserSettings/images/os/SYL.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/T64.gif b/plugins/UserSettings/images/os/T64.gif
new file mode 100644
index 0000000000..3255046dc6
--- /dev/null
+++ b/plugins/UserSettings/images/os/T64.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/UNK.gif b/plugins/UserSettings/images/os/UNK.gif
index 6de56a753a..ec7aa05e07 100644
--- a/plugins/UserSettings/images/os/UNK.gif
+++ b/plugins/UserSettings/images/os/UNK.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/W2K.gif b/plugins/UserSettings/images/os/W2K.gif
index 19d75be8c8..404eeabc72 100644
--- a/plugins/UserSettings/images/os/W2K.gif
+++ b/plugins/UserSettings/images/os/W2K.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/W95.gif b/plugins/UserSettings/images/os/W95.gif
index 19d75be8c8..404eeabc72 100644
--- a/plugins/UserSettings/images/os/W95.gif
+++ b/plugins/UserSettings/images/os/W95.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/W98.gif b/plugins/UserSettings/images/os/W98.gif
index 19d75be8c8..404eeabc72 100644
--- a/plugins/UserSettings/images/os/W98.gif
+++ b/plugins/UserSettings/images/os/W98.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/WI7.gif b/plugins/UserSettings/images/os/WI7.gif
index a91e528b5c..d782a6d42d 100644
--- a/plugins/UserSettings/images/os/WI7.gif
+++ b/plugins/UserSettings/images/os/WI7.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/WME.gif b/plugins/UserSettings/images/os/WME.gif
index 19d75be8c8..404eeabc72 100644
--- a/plugins/UserSettings/images/os/WME.gif
+++ b/plugins/UserSettings/images/os/WME.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/WNT.gif b/plugins/UserSettings/images/os/WNT.gif
index 19d75be8c8..404eeabc72 100644
--- a/plugins/UserSettings/images/os/WNT.gif
+++ b/plugins/UserSettings/images/os/WNT.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/WOS.gif b/plugins/UserSettings/images/os/WOS.gif
new file mode 100644
index 0000000000..60dcc17d6a
--- /dev/null
+++ b/plugins/UserSettings/images/os/WOS.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/WS3.gif b/plugins/UserSettings/images/os/WS3.gif
index a91e528b5c..d782a6d42d 100644
--- a/plugins/UserSettings/images/os/WS3.gif
+++ b/plugins/UserSettings/images/os/WS3.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/WVI.gif b/plugins/UserSettings/images/os/WVI.gif
index a91e528b5c..d782a6d42d 100644
--- a/plugins/UserSettings/images/os/WVI.gif
+++ b/plugins/UserSettings/images/os/WVI.gif
Binary files differ
diff --git a/plugins/UserSettings/images/os/WXP.gif b/plugins/UserSettings/images/os/WXP.gif
index a91e528b5c..d782a6d42d 100644
--- a/plugins/UserSettings/images/os/WXP.gif
+++ b/plugins/UserSettings/images/os/WXP.gif
Binary files differ
diff --git a/plugins/UserSettings/images/plugins/cookie.gif b/plugins/UserSettings/images/plugins/cookie.gif
index 1a518e122c..7e5f561527 100644
--- a/plugins/UserSettings/images/plugins/cookie.gif
+++ b/plugins/UserSettings/images/plugins/cookie.gif
Binary files differ
diff --git a/plugins/UserSettings/images/plugins/director.gif b/plugins/UserSettings/images/plugins/director.gif
index 4d6de84f5e..d40a752044 100644
--- a/plugins/UserSettings/images/plugins/director.gif
+++ b/plugins/UserSettings/images/plugins/director.gif
Binary files differ
diff --git a/plugins/UserSettings/images/plugins/flash.gif b/plugins/UserSettings/images/plugins/flash.gif
index 1388f67da0..d144c55b8d 100644
--- a/plugins/UserSettings/images/plugins/flash.gif
+++ b/plugins/UserSettings/images/plugins/flash.gif
Binary files differ
diff --git a/plugins/UserSettings/images/plugins/gears.gif b/plugins/UserSettings/images/plugins/gears.gif
index d721ed7840..ea5f0dd3f8 100644
--- a/plugins/UserSettings/images/plugins/gears.gif
+++ b/plugins/UserSettings/images/plugins/gears.gif
Binary files differ
diff --git a/plugins/UserSettings/images/plugins/java.gif b/plugins/UserSettings/images/plugins/java.gif
index 2525255334..0aae25f993 100644
--- a/plugins/UserSettings/images/plugins/java.gif
+++ b/plugins/UserSettings/images/plugins/java.gif
Binary files differ
diff --git a/plugins/UserSettings/images/plugins/pdf.gif b/plugins/UserSettings/images/plugins/pdf.gif
index 41ae83e801..ac908f408f 100644
--- a/plugins/UserSettings/images/plugins/pdf.gif
+++ b/plugins/UserSettings/images/plugins/pdf.gif
Binary files differ
diff --git a/plugins/UserSettings/images/plugins/quicktime.gif b/plugins/UserSettings/images/plugins/quicktime.gif
index 144f9f60a3..4822161249 100644
--- a/plugins/UserSettings/images/plugins/quicktime.gif
+++ b/plugins/UserSettings/images/plugins/quicktime.gif
Binary files differ
diff --git a/plugins/UserSettings/images/plugins/realplayer.gif b/plugins/UserSettings/images/plugins/realplayer.gif
index 1e32d9632f..6078f1a427 100644
--- a/plugins/UserSettings/images/plugins/realplayer.gif
+++ b/plugins/UserSettings/images/plugins/realplayer.gif
Binary files differ
diff --git a/plugins/UserSettings/images/plugins/silverlight.gif b/plugins/UserSettings/images/plugins/silverlight.gif
index d25ee0a23c..227f132254 100644
--- a/plugins/UserSettings/images/plugins/silverlight.gif
+++ b/plugins/UserSettings/images/plugins/silverlight.gif
Binary files differ
diff --git a/plugins/UserSettings/images/plugins/windowsmedia.gif b/plugins/UserSettings/images/plugins/windowsmedia.gif
index 99a4318f29..04f816250d 100644
--- a/plugins/UserSettings/images/plugins/windowsmedia.gif
+++ b/plugins/UserSettings/images/plugins/windowsmedia.gif
Binary files differ
diff --git a/plugins/UserSettings/images/screens/dual.gif b/plugins/UserSettings/images/screens/dual.gif
index c54b5473c1..5cdbbae22e 100644
--- a/plugins/UserSettings/images/screens/dual.gif
+++ b/plugins/UserSettings/images/screens/dual.gif
Binary files differ
diff --git a/plugins/UserSettings/images/screens/normal.gif b/plugins/UserSettings/images/screens/normal.gif
index 7ffecc304c..1c5c39976e 100644
--- a/plugins/UserSettings/images/screens/normal.gif
+++ b/plugins/UserSettings/images/screens/normal.gif
Binary files differ
diff --git a/plugins/UserSettings/images/screens/wide.gif b/plugins/UserSettings/images/screens/wide.gif
index 36ff560b50..6b726d55c1 100644
--- a/plugins/UserSettings/images/screens/wide.gif
+++ b/plugins/UserSettings/images/screens/wide.gif
Binary files differ
diff --git a/plugins/UserSettings/templates/index.tpl b/plugins/UserSettings/templates/index.tpl
index 91400a6e7c..35c0e4b51a 100644
--- a/plugins/UserSettings/templates/index.tpl
+++ b/plugins/UserSettings/templates/index.tpl
@@ -13,7 +13,7 @@
<h2>{'UserSettings_Configurations'|translate}</h2>
{$dataTableConfiguration}
- <h2>{'UserSettings_OperatinsSystems'|translate}</h2>
+ <h2>{'UserSettings_OperatingSystems'|translate}</h2>
{$dataTableOS}
<h2>{'UserSettings_Resolutions'|translate}</h2>
diff --git a/plugins/UserSettings/tests/UserSettings.test.php b/plugins/UserSettings/tests/UserSettings.test.php
new file mode 100644
index 0000000000..e9e8f00378
--- /dev/null
+++ b/plugins/UserSettings/tests/UserSettings.test.php
@@ -0,0 +1,800 @@
+<?php
+if(!defined("PIWIK_PATH_TEST_TO_ROOT")) {
+ define('PIWIK_PATH_TEST_TO_ROOT', getcwd().'/../../..');
+}
+if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
+{
+ require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php";
+}
+
+if(!class_exists('Piwik_UserSettings', false))
+{
+ require_once 'UserSettings/UserSettings.php';
+}
+require 'UserSettings/functions.php';
+
+class Test_Piwik_UserSettings extends UnitTestCase
+{
+ // User agent strings and expected parser results
+ protected $userAgents = array(
+ // 'User Agent String' => array(
+ // array( browser_id, name, short_name, version, major_number, minor_number, family ),
+ // array( os_id, name, short_name )),
+
+ // ABrowse
+ 'Mozilla/5.0 (compatible; U; ABrowse 0.6; Syllable) AppleWebKit/420+ (KHTML, like Gecko)' => array(
+ array('AB', 'ABrowse', 'ABrowse', '0.6', '0', '6', 'webkit'),
+ array('SYL', 'Syllable', 'Syllable')),
+ 'Mozilla/5.0 (compatible; ABrowse 0.4; Syllable)' => array(
+ array('AB', 'ABrowse', 'ABrowse', '0.4', '0', '4', 'webkit'),
+ array('SYL', 'Syllable', 'Syllable')),
+
+ // Acoo Browser (treat as IE)
+ 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6; Acoo Browser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)' => array(
+ array('IE', 'Internet Explorer', 'IE', '8.0', '8', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Acoo Browser; .NET CLR 2.0.50727; .NET CLR 1.1.4322)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Acoo Browser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)' => array(
+ array('IE', 'Internet Explorer', 'IE', '6.0', '6', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // Amaya
+ 'amaya/9.52 libwww/5.4.0' => array(
+ array('AM', 'Amaya', 'Amaya', '9.52', '9', '52', 'unknown'),
+ false),
+
+ // AmigaVoyager
+ 'AmigaVoyager/3.2 (AmigaOS/MC680x0)' => array(
+ array('AV', 'AmigaVoyager', 'AmigaVoyager', '3.2', '3', '2', 'unknown'),
+ array('AMI', 'AmigaOS', 'AmigaOS')),
+ 'AmigaVoyager/2.95 (compatible; MC680x0; AmigaOS; SV1)' => array(
+ array('AV', 'AmigaVoyager', 'AmigaVoyager', '2.95', '2', '95', 'unknown'),
+ array('AMI', 'AmigaOS', 'AmigaOS')),
+ 'AmigaVoyager/2.95 (compatible; MC680x0; AmigaOS)' => array(
+ array('AV', 'AmigaVoyager', 'AmigaVoyager', '2.95', '2', '95', 'unknown'),
+ array('AMI', 'AmigaOS', 'AmigaOS')),
+
+ // Android
+ 'Mozilla/5.0 (Linux; U; Android 1.1; en-us; dream) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2' => array(
+ array('AN', 'Android', 'Android', '3.0', '3', '0', 'webkit'),
+ array('AND', 'Android', 'Android')),
+
+ // AOL / America Online Browser (treat as IE)
+ 'Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.43; Windows NT 5.1; .NET CLR 1.1.4322)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.1; AOLBuild 4334.5009; Windows NT 5.1; GTB5; .NET CLR 1.1.4322)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.0; Windows NT 5.1; InfoPath.1)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 6.0; AOL 8.0; Windows NT 5.1; SV1)' => array(
+ array('IE', 'Internet Explorer', 'IE', '6.0', '6', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 7.0; AOL 7.0; Windows NT 5.1)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 5.5; AOL 6.0; Windows 98; Win 9x 4.90)' => array(
+ array('IE', 'Internet Explorer', 'IE', '5.5', '5', '5', 'ie'),
+ array('WME', 'Windows Me', 'Win Me')),
+ 'Mozilla/4.0 (compatible; MSIE 5.5; AOL 5.0; Windows NT 5.0)' => array(
+ array('IE', 'Internet Explorer', 'IE', '5.5', '5', '5', 'ie'),
+ array('W2K', 'Windows 2000', 'Win 2000')),
+ 'Mozilla/4.0 (compatible; MSIE 4.01; AOL 4.0; Windows 95)' => array(
+ array('IE', 'Internet Explorer', 'IE', '4.01', '4', '01', 'ie'),
+ array('W95', 'Windows 95', 'Win 95')),
+ 'Mozilla/4.0 (compatible; MSIE 7.0; America Online Browser 1.1; Windows NT 5.1; (R1 1.5); .NET CLR 2.0.50727; InfoPath.1)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 6.0; America Online Browser 1.1; Windows 98)' => array(
+ array('IE', 'Internet Explorer', 'IE', '6.0', '6', '0', 'ie'),
+ array('W98', 'Windows 98', 'Win 98')),
+
+ // Arora
+ 'Mozilla/5.0 (X11; U; Linux; de-DE) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.8.0' => array(
+ array('AR', 'Arora', 'Arora', '0.8', '0', '8', 'webkit'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6' => array(
+ array('AR', 'Arora', 'Arora', '0.6', '0', '6', 'webkit'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.2; pt-BR) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.4 (Change: )' => array(
+ array('AR', 'Arora', 'Arora', '0.4', '0', '4', 'webkit'),
+ array('WS3', 'Windows Server 2003 / XP x64', 'Win S2003')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)' => array(
+ array('AR', 'Arora', 'Arora', '0.3', '0', '3', 'webkit'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.2 (Change: 189 35c14e0)' => array(
+ array('AR', 'Arora', 'Arora', '0.2', '0', '2', 'webkit'),
+ array('LIN', 'Linux', 'Linux')),
+
+ // Avant (treat as IE)
+ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser; .NET CLR 2.0.50727; MAXTHON 2.0)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; Avant Browser; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)' => array(
+ array('IE', 'Internet Explorer', 'IE', '8.0', '8', '0', 'ie'),
+ array('WI7', 'Windows 7', 'Win 7')),
+
+ // AWeb
+ 'Amiga-AWeb/3.5.07 beta' => array(
+ array('AW', 'Amiga AWeb', 'AWeb', '3.5', '3', '5', 'unknown'),
+ array('AMI', 'AmigaOS', 'AmigaOS')),
+ 'Mozilla/6.0; (Spoofed by Amiga-AWeb/3.5.07 beta)' => array(
+ array('AW', 'Amiga AWeb', 'AWeb', '3.5', '3', '5', 'unknown'),
+ array('AMI', 'AmigaOS', 'AmigaOS')),
+ 'MSIE/6.0; (Spoofed by Amiga-AWeb/3.4APL)' => array(
+ array('AW', 'Amiga AWeb', 'AWeb', '3.4', '3', '4', 'unknown'),
+ array('AMI', 'AmigaOS', 'AmigaOS')),
+
+ // Beonex
+ 'Mozilla/5.0 (Windows; U; WinNT; en; rv:1.0.2) Gecko/20030311 Beonex/0.8.2-stable' => array(
+ array('BE', 'Beonex', 'Beonex', '0.8', '0', '8', 'unknown'),
+ array('WNT', 'Windows NT', 'Win NT')),
+ 'Mozilla/5.0 (Windows; U; WinNT; en; Preview) Gecko/20020603 Beonex/0.8-stable' => array(
+ array('BE', 'Beonex', 'Beonex', '0.8', '0', '8', 'unknown'),
+ array('WNT', 'Windows NT', 'Win NT')),
+
+ // BlackBerry
+ 'BlackBerry8700/4.1.0 Profile/MIDP-2.0 Configuration/CLDC-1.1' => array(
+ array('BB', 'BlackBerry', 'BlackBerry', '8700.0', '8700', '0', 'unknown'),
+ array('BLB', 'BlackBerry', 'BlackBerry')),
+
+ // BrowseX
+ 'Mozilla/4.61 [en] (X11; U; ) - BrowseX (2.0.0 Windows)' => array(
+ array('BX', 'BrowseX', 'BrowseX', '2.0', '2', '0', 'unknown'),
+ false),
+
+ // Camino (formerly known as Chimera; not to be confused with another browser also named Chimera)
+ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.8pre) Gecko/2009022800 Camino/2.0b3pre' => array(
+ array('CA', 'Camino', 'Camino', '2.0', '2', '0', 'gecko'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en; rv:1.9.0.10pre) Gecko/2009041800 Camino/2.0b3pre (like Firefox/3.0.10pre)' => array(
+ array('CA', 'Camino', 'Camino', '2.0', '2', '0', 'gecko'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en; rv:1.8.1.4pre) Gecko/20070511 Camino/1.6pre' => array(
+ array('CA', 'Camino', 'Camino', '1.6', '1', '6', 'gecko'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en; rv:1.8.1.6) Gecko/20070809 Firefox/2.0.0.6 Camino/1.5.1' => array(
+ array('CA', 'Camino', 'Camino', '1.5', '1', '5', 'gecko'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.0.1) Gecko/20030306 Camino/0.7' => array(
+ array('CA', 'Camino', 'Camino', '0.7', '0', '7', 'gecko'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; pl-PL; rv:1.0.1) Gecko/20021111 Chimera/0.6' => array(
+ array('CA', 'Camino', 'Camino', '0.6', '0', '6', 'gecko'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+
+ // Cheshire
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko, Safari) Cheshire/1.0.UNOFFICIAL' => array(
+ array('CS', 'Cheshire', 'Cheshire', '1.0', '1', '0', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/419 (KHTML, like Gecko, Safari/419.3) Cheshire/1.0.ALPHA' => array(
+ array('CS', 'Cheshire', 'Cheshire', '1.0', '1', '0', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.9 (KHTML, like Safari) Cheshire/1.0.ALPHA' => array(
+ array('CS', 'Cheshire', 'Cheshire', '1.0', '1', '0', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+
+ // Chrome / Chromium
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US) AppleWebKit/532.9 (KHTML, like Gecko) Chrome/5.0.310.0 Safari/532.9' => array(
+ array('CH', 'Chrome', 'Chrome', '5.0', '5', '0', 'webkit'),
+ array('WS3', 'Windows Server 2003 / XP x64', 'Win S2003')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/1.0.154.48 Safari/525.19' => array(
+ array('CH', 'Chrome', 'Chrome', '1.0', '1', '0', 'webkit'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (Linux; U; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13' => array(
+ array('CH', 'Chrome', 'Chrome', '0.2', '0', '2', 'webkit'),
+ array('LIN', 'Linux', 'Linux')),
+
+ // ChromePlus (treat as Chrome)
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.2 (KHTML, like Gecko) ChromePlus/4.0.222.3 Chrome/4.0.222.3 Safari/532.2' => array(
+ array('CH', 'Chrome', 'Chrome', '4.0', '4', '0', 'webkit'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.28.3 (KHTML, like Gecko) Version/3.2.3 ChromePlus/4.0.222.3 Chrome/4.0.222.3 Safari/525.28.3' => array(
+ array('CH', 'Chrome', 'Chrome', '3.2', '3', '2', 'webkit'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // CometBird
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.5) Gecko/2009011615 Firefox/3.0.5 CometBird/3.0.5' => array(
+ array('CO', 'CometBird', 'CometBird', '3.0', '3', '0', 'gecko'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // Crazy Browser (treat as IE)
+ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; InfoPath.2; .NET CLR 2.0.50727; .NET CLR 1.1.4322; Crazy Browser 3.0.0 Beta2)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser; .NET CLR 2.0.50727; .NET CLR 3.0.04506.590; .NET CLR 3.5.20706; Crazy Browser 2.0.1)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // Dillo
+ 'Dillo/2.0' => array(
+ array('DI', 'Dillo', 'Dillo', '2.0', '2', '0', 'unknown'),
+ false),
+ 'Dillo/0.6.4' => array(
+ array('DI', 'Dillo', 'Dillo', '0.6', '0', '6', 'unknown'),
+ false),
+
+ // ELinks
+ 'ELinks/0.12~pre2.dfsg0-1ubuntu1-lite (textmode; Debian; Linux 2.6.32-4-jolicloud i686; 143x37-2)' => array(
+ array('EL', 'ELinks', 'ELinks', '0.12', '0', '12', 'unknown'),
+ array('LIN', 'Linux', 'Linux')),
+ 'ELinks/0.12pre5.GIT (textmode; CYGWIN_NT-6.1 1.7.1(0.218/5/3) i686; 80x24-2)' => array(
+ array('EL', 'ELinks', 'ELinks', '0.12', '0', '12', 'unknown'),
+ array('WI7', 'Windows 7', 'Win 7')),
+ 'ELinks (0.4.3; NetBSD 3.0.2_PATCH sparc64; 141x19)' => array(
+ array('EL', 'ELinks', 'ELinks', '0.4', '0', '4', 'unknown'),
+ array('NBS', 'NetBSD', 'NetBSD')),
+
+ // Epiphany
+ 'Mozilla/5.0 (X11; U; Linux i686; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Safari/531.2+ Epiphany/2.29.5' => array(
+ array('EP', 'Epiphany', 'Epiphany', '2.29', '2', '29', 'webkit'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en; rv:1.9.0.11) Gecko/20080528 Epiphany/2.22 Firefox/3.0' => array(
+ // technically, this should be 'gecko' but UserAgentParser only supports one browserType (family) per browser
+ array('EP', 'Epiphany', 'Epiphany', '2.22', '2', '22', 'webkit'),
+ array('LIN', 'Linux', 'Linux')),
+
+ // Fennec
+ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2a1pre) Gecko/20090626 Fennec/1.0b2' => array(
+ array('FE', 'Fennec', 'Fennec', '1.0', '1', '0', 'gecko'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (X11; U; Linux armv6l; en-US; rv:1.9.1b1pre) Gecko/20081005220218 Gecko/2008052201 Fennec/0.9pre' => array(
+ array('FE', 'Fennec', 'Fennec', '0.9', '0', '9', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; Linux armv6l; en-US; rv:1.9.1a1pre) Gecko/2008071707 Fennec/0.5' => array(
+ array('FE', 'Fennec', 'Fennec', '0.5', '0', '5', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+
+ // Firefox (formerly Firebird, formerly Phoenix; and rebranded versions)
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:2.0a1pre) Gecko/2008060602 Minefield/4.0a1pre' => array(
+ array('FF', 'Firefox', 'Firefox', '4.0', '4', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:2.0a1pre) Gecko/2008060602 Minefield/4.0a1p' => array(
+ array('FF', 'Firefox', 'Firefox', '4.0', '4', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2a2pre) Gecko/20090826 Namoroka/3.6a2pre' => array(
+ array('FF', 'Firefox', 'Firefox', '3.6', '3', '6', 'gecko'),
+ array('WVI', 'Windows Vista', 'Win Vista')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2) Gecko/20100119 Namoroka/3.6' => array(
+ array('FF', 'Firefox', 'Firefox', '3.6', '3', '6', 'gecko'),
+ array('WI7', 'Windows 7', 'Win 7')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1b4pre) Gecko/20090420 Shiretoko/3.5b4pre (.NET CLR 3.5.30729)' => array(
+ array('FF', 'Firefox', 'Firefox', '3.5', '3', '5', 'gecko'),
+ array('WI7', 'Windows 7', 'Win 7')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.2) Gecko/20090803 Ubuntu/9.04 (jaunty) Shiretoko/3.5.2' => array(
+ array('FF', 'Firefox', 'Firefox', '3.5', '3', '5', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6' => array(
+ array('FF', 'Firefox', 'Firefox', '3.0', '3', '0', 'gecko'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9a7) Gecko/2007080210 GranParadiso/3.0a7' => array(
+ array('FF', 'Firefox', 'Firefox', '3.0', '3', '0', 'gecko'),
+ array('WVI', 'Windows Vista', 'Win Vista')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008072716 IceCat/3.0.1-g1' => array(
+ array('FF', 'Firefox', 'Firefox', '3.0', '3', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.0.1) Gecko/2008071420 Iceweasel/3.0.1 (Debian-3.0.1-1)' => array(
+ array('FF', 'Firefox', 'Firefox', '3.0', '3', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1b2) Gecko/20060821 BonEcho/2.0b2' => array(
+ array('FF', 'Firefox', 'Firefox', '2.0', '2', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; Darwin Power Macintosh; en-US; rv:1.8.0.12) Gecko/20070803 Firefox/1.5.0.12 Fink Community Edition' => array(
+ array('FF', 'Firefox', 'Firefox', '1.5', '1', '5', 'gecko'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6b) Gecko/20031212 Firebird/0.7+' => array(
+ array('FB', 'Firebird', 'Firebird', '0.7', '0', '7', 'gecko'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (Windows; U; Win98; de-DE; rv:1.4b) Gecko/20030516 Mozilla Firebird/0.6' => array(
+ array('FB', 'Firebird', 'Firebird', '0.6', '0', '6', 'gecko'),
+ array('W98', 'Windows 98', 'Win 98')),
+ 'Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.3a) Gecko/20021207 Phoenix/0.5' => array(
+ array('PX', 'Phoenix', 'Phoenix', '0.5', '0', '5', 'gecko'),
+ array('WNT', 'Windows NT', 'Win NT')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.2b) Gecko/20020923 Phoenix/0.1' => array(
+ array('PX', 'Phoenix', 'Phoenix', '0.1', '0', '1', 'gecko'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (Nintendo DS v4; U; M3 Adapter CF + PassMe2; en-US; rv:1.8.0.6 ) Gecko/20060728 Firefox/1.5.0.6 (firefox.gba.ds)' => array(
+ array('FF', 'Firefox', 'Firefox', '1.5', '1', '5', 'gecko'),
+ array('NDS', 'Nintendo DS', 'DS')),
+
+ // Flock
+ 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Flock/3.0.0.3737 Chrome/4.1.249.1071 Safari/532.5' => array(
+ array('FL', 'Flock', 'Flock', '3.0', '3', '0', 'webkit'),
+ array('WI7', 'Windows 7', 'Win 7')),
+ // pre-3.0 is actually gecko
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 Flock/2.5.6 (.NET CLR 3.5.30729)' => array(
+ array('FL', 'Flock', 'Flock', '2.5', '2', '5', 'webkit'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 AppleWebKit/531.21.8 KHTML/4.3.5 (like Gecko) Firefox/3.5.7 Flock/2.5.6 (.NET CLR 3.5.30729)' => array(
+ array('FL', 'Flock', 'Flock', '2.5', '2', '5', 'webkit'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 AppleWebKit/531.21.8 (KHTML, like Gecko) Firefox/3.5.7 Flock/2.5.6 (.NET CLR 3.5.30729)' => array(
+ array('FL', 'Flock', 'Flock', '2.5', '2', '5', 'webkit'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.9) Gecko/20071106 Firefox/2.0.0.9 Flock/1.0.1' => array(
+ array('FL', 'Flock', 'Flock', '1.0', '1', '0', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1.8) Gecko/20071101 Firefox/2.0.0.8 Flock/1.0' => array(
+ array('FL', 'Flock', 'Flock', '1.0', '1', '0', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8b5) Gecko/20051021 Flock/0.4 Firefox/1.0+' => array(
+ array('FL', 'Flock', 'Flock', '0.4', '0', '4', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+
+ // Fluid
+ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_1; nl-nl) AppleWebKit/532.3+ (KHTML, like Gecko) Fluid/0.9.6 Safari/532.3+' => array(
+ array('FD', 'Fluid', 'Fluid', '0.9', '0', '9', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Fluid/0.9.4 Safari/525.13' => array(
+ array('FD', 'Fluid', 'Fluid', '0.9', '0', '9', 'webkit'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // Galeon
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko/20090327 Galeon/2.0.7' => array(
+ array('GA', 'Galeon', 'Galeon', '2.0', '2', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; OpenBSD i386; en-US; rv:1.8.1.19) Gecko/20090701 Galeon/2.0.7' => array(
+ array('GA', 'Galeon', 'Galeon', '2.0', '2', '0', 'gecko'),
+ array('OBS', 'OpenBSD', 'OpenBSD')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.19) Gecko/20081216 Galeon/2.0.4 Firefox/2.0.0.19' => array(
+ array('GA', 'Galeon', 'Galeon', '2.0', '2', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.13pre) Gecko/20080207 Galeon/2.0.1 (Ubuntu package 2.0.1-1ubuntu2) Firefox/1.5.0.13pre' => array(
+ array('GA', 'Galeon', 'Galeon', '2.0', '2', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.6) Gecko/20040406 Galeon/1.3.15' => array(
+ array('GA', 'Galeon', 'Galeon', '1.3', '1', '3', 'gecko'),
+ array('BSD', 'FreeBSD', 'FreeBSD')),
+ 'Mozilla/5.0 Galeon/1.2.9 (X11; Linux i686; U;) Gecko/20021213 Debian/1.2.9-0.bunk' => array(
+ array('GA', 'Galeon', 'Galeon', '1.2', '1', '2', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 Galeon/1.0.3 (X11; Linux i686; U;) Gecko/0' => array(
+ array('GA', 'Galeon', 'Galeon', '1.0', '1', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+
+ // Google Earth embedded browser
+ 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.4 (KHTML, like Gecko) Google Earth/5.2.1.1329 Safari/532.4' => array(
+ array('GE', 'Google Earth', 'Google Earth', '5.2', '5', '2', 'webkit'),
+ array('WI7', 'Windows 7', 'Win 7')),
+
+ // GreenBrowser (treat as IE)
+ 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; Media Center PC 5.0; .NET CLR 3.5.21022; GreenBrowser)' => array(
+ array('IE', 'Internet Explorer', 'IE', '6.0', '6', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; InfoPath.2; .NET CLR 3.0.30729; GreenBrowser)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WVI', 'Windows Vista', 'Win Vista')),
+
+ // Hana
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.9 (KHTML, like Gecko) Hana/1.1' => array(
+ array('HA', 'Hana', 'Hana', '1.1', '1', '1', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/417.9 (KHTML, like Gecko) Hana/1.0' => array(
+ array('HA', 'Hana', 'Hana', '1.0', '1', '0', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+
+ // HotJava
+ 'HotJava/1.1.2 FCS' => array(
+ array('HJ', 'HotJava', 'HotJava', '1.1', '1', '1', 'unknown'),
+ false),
+ 'HotJava/1.0.1/JRE1.1.x' => array(
+ array('HJ', 'HotJava', 'HotJava', '1.0', '1', '0', 'unknown'),
+ false),
+
+ // iBrowse
+ 'Mozilla/5.0 (compatible; IBrowse 3.0; AmigaOS4.0)' => array(
+ array('IB', 'IBrowse', 'IBrowse', '3.0', '3', '0', 'unknown'),
+ array('AMI', 'AmigaOS', 'AmigaOS')),
+ 'Mozilla/4.0 (compatible; IBrowse 2.3; AmigaOS4.0)' => array(
+ array('IB', 'IBrowse', 'IBrowse', '2.3', '2', '3', 'unknown'),
+ array('AMI', 'AmigaOS', 'AmigaOS')),
+ 'IBrowse/2.4 (AmigaOS 3.9; 68K)' => array(
+ array('IB', 'IBrowse', 'IBrowse', '2.4', '2', '4', 'unknown'),
+ array('AMI', 'AmigaOS', 'AmigaOS')),
+ 'IBrowse/2.3 (AmigaOS V51)' => array(
+ array('IB', 'IBrowse', 'IBrowse', '2.3', '2', '3', 'unknown'),
+ array('AMI', 'AmigaOS', 'AmigaOS')),
+ 'IBrowse/2.3 (AmigaOS 4.0)' => array(
+ array('IB', 'IBrowse', 'IBrowse', '2.3', '2', '3', 'unknown'),
+ array('AMI', 'AmigaOS', 'AmigaOS')),
+
+ // iCab
+ 'iCab/4.5 (Macintosh; U; PPC Mac OS X)' => array(
+ array('IC', 'iCab', 'iCab', '4.5', '4', '5', 'unknown'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'iCab/4.5 (Macintosh; U; Mac OS X Leopard 10.5.7)' => array(
+ array('IC', 'iCab', 'iCab', '4.5', '4', '5', 'unknown'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (compatible; iCab 3.0.5; Macintosh; U; PPC Mac OS)' => array(
+ array('IC', 'iCab', 'iCab', '3.0', '3', '0', 'unknown'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (compatible; iCab 3.0.5; Macintosh; U; PPC Mac OS X)' => array(
+ array('IC', 'iCab', 'iCab', '3.0', '3', '0', 'unknown'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS; en) iCab 3' => array(
+ array('IC', 'iCab', 'iCab', '3.0', '3', '0', 'unknown'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/4.5 (compatible; iCab 2.7.1; Macintosh; I; PPC)' => array(
+ array('IC', 'iCab', 'iCab', '2.7', '2', '7', 'unknown'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'iCab/2.9.8 (Macintosh; U; 68K)' => array(
+ array('IC', 'iCab', 'iCab', '2.9', '2', '9', 'unknown'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Lynx/2.8 (compatible; iCab 2.9.8; Macintosh; U; 68K)' => array(
+ array('IC', 'iCab', 'iCab', '2.9', '2', '9', 'unknown'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/4/5 (compatible; iCab 2.9.8; Macintosh; U; 68K)' => array(
+ array('IC', 'iCab', 'iCab', '2.9', '2', '9', 'unknown'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/4.0 (compatible; MSIE 5.0; Mac_PowerPC)' => array(
+ array('IE', 'Internet Explorer', 'IE', '5.0', '5', '0', 'ie'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/4.76 (Macintosh; I; PPC)' => array(
+ array('NS', 'Netscape', 'Netscape', '4.76', '4', '76', 'gecko'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+
+ // Internet Explorer
+ 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' => array(
+ array('IE', 'Internet Explorer', 'IE', '9.0', '9', '0', 'ie'),
+ array('WI7', 'Windows 7', 'Win 7')),
+ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/5.0)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WVI', 'Windows Vista', 'Win Vista')),
+ 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET CLR 3.0.04506; .NET CLR 3.5.21022; InfoPath.2; SLCC1; Zune 3.0)' => array(
+ array('IE', 'Internet Explorer', 'IE', '8.0', '8', '0', 'ie'),
+ array('WI7', 'Windows 7', 'Win 7')),
+ 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)' => array(
+ array('IE', 'Internet Explorer', 'IE', '8.0', '8', '0', 'ie'),
+ array('WVI', 'Windows Vista', 'Win Vista')),
+ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WVI', 'Windows Vista', 'Win Vista')),
+ 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)' => array(
+ array('IE', 'Internet Explorer', 'IE', '8.0', '8', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)' => array(
+ array('IE', 'Internet Explorer', 'IE', '6.0', '6', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)' => array(
+ array('IE', 'Internet Explorer', 'IE', '6.0', '6', '0', 'ie'),
+ array('WS3', 'Windows Server 2003 / XP x64', 'Win S2003')),
+ 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; WOW64; SV1; .NET CLR 2.0.50727)' => array(
+ array('IE', 'Internet Explorer', 'IE', '6.0', '6', '0', 'ie'),
+ array('WS3', 'Windows Server 2003 / XP x64', 'Win S2003')),
+ 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Win64; x64; SV1; .NET CLR 2.0.50727)' => array(
+ array('IE', 'Internet Explorer', 'IE', '6.0', '6', '0', 'ie'),
+ array('WS3', 'Windows Server 2003 / XP x64', 'Win S2003')),
+
+ // Internet Explorer with misbehaving Google Tool Bar
+ 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6.5; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)' => array(
+ array('IE', 'Internet Explorer', 'IE', '8.0', '8', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB0.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)' => array(
+ array('IE', 'Internet Explorer', 'IE', '8.0', '8', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // Iron
+ 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/531.0 (KHTML, like Gecko) Iron/3.0.189.0 Safari/531.0' => array(
+ array('IR', 'Iron', 'Iron', '3.0', '3', '0', 'webkit'),
+ array('WI7', 'Windows 7', 'Win 7')),
+
+ // K-Meleon
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.21) Gecko/20090331 K-Meleon/1.5.3' => array(
+ array('KM', 'K-Meleon', 'K-Meleon', '1.5', '1', '5', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (Darwin; FreeBSD 5.6; en-GB; rv:1.8.1.17pre) Gecko/20080716 K-Meleon/1.5.0' => array(
+ array('KM', 'K-Meleon', 'K-Meleon', '1.5', '1', '5', 'gecko'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Windows; U; WinNT4.0; en-US; rv:1.2b) Gecko/20021016 K-Meleon 0.7' => array(
+ array('KM', 'K-Meleon', 'K-Meleon', '0.7', '0', '7', 'gecko'),
+ array('WNT', 'Windows NT', 'Win NT')),
+
+ // Kapiko
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.1) Gecko/20080722 Firefox/3.0.1 Kapiko/3.0' => array(
+ array('KP', 'Kapiko', 'Kapiko', '3.0', '3', '0', 'gecko'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // Kazehakase
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.11) Gecko Kazehakase/0.5.4 Debian/0.5.4-2.1ubuntu3' => array(
+ array('KZ', 'Kazehakase', 'Kazehakase', '0.5', '0', '5', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.13) Gecko/20080311 (Debian-1.8.1.13+nobinonly-0ubuntu1) Kazehakase/0.5.2' => array(
+ array('KZ', 'Kazehakase', 'Kazehakase', '0.5', '0', '5', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; Linux x86_64; U;) Gecko/20060207 Kazehakase/0.3.5 Debian/0.3.5-1' => array(
+ array('KZ', 'Kazehakase', 'Kazehakase', '0.3', '0', '3', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+
+ // KKMAN (treat as IE)
+ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; KKMAN3.2)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // Konqueror
+ 'Mozilla/5.0 (compatible; Konqueror/4.0; Linux) KHTML/4.0.5 (like Gecko)' => array(
+ array('KO', 'Konqueror', 'Konqueror', '4.0', '4', '0', 'khtml'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (compatible; Konqueror/4.0; Microsoft Windows) KHTML/4.0.80 (like Gecko)' => array(
+ array('KO', 'Konqueror', 'Konqueror', '4.0', '4', '0', 'khtml'),
+ false),
+ 'Mozilla/5.0 (compatible; Konqueror/3.5; GNU/kFreeBSD) KHTML/3.5.9 (like Gecko) (Debian)' => array(
+ array('KO', 'Konqueror', 'Konqueror', '3.5', '3', '5', 'khtml'),
+ array('BSD', 'FreeBSD', 'FreeBSD')),
+ 'Mozilla/5.0 (compatible; Konqueror/2.1.1; X11)' => array(
+ array('KO', 'Konqueror', 'Konqueror', '2.1', '2', '1', 'khtml'),
+ false),
+
+ // Links
+ 'Links' => array(
+ false,
+ false),
+ 'Links (2.1pre31; Linux 2.6.21-omap1 armv6l; x)' => array(
+ array('LI', 'Links', 'Links', '2.1', '2', '1', 'unknown'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Links (0.99; OS/2 1 i386; 80x33)' => array(
+ array('LI', 'Links', 'Links', '0.99', '0', '99', 'unknown'),
+ array('OS2', 'OS/2', 'OS/2')),
+
+ // Lunascape (identity crisis)
+ 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1) Gecko/20090701 Firefox/3.5 Lunascape/5.1.2.3' => array(
+ array('FF', 'Firefox', 'Firefox', '3.5', '3', '5', 'gecko'),
+ array('WVI', 'Windows Vista', 'Win Vista')),
+ 'Mozilla/5.0 (Windows; U; ; cs-CZ) AppleWebKit/532+ (KHTML, like Gecko, Safari/532.0) Lunascape/5.1.2.3' => array(
+ array('SF', 'Safari', 'Safari', '4.0', '4', '0', 'webkit'),
+ false),
+ 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; InfoPath.1; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Lunascape 5.1.2.3)' => array(
+ array('IE', 'Internet Explorer', 'IE', '6.0', '6', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // Lynx
+ 'Lynx (textmode)' => array(
+ false,
+ false),
+ 'Lynx/2.8.7dev.9 libwww-FM/2.14' => array(
+ array('LX', 'Lynx', 'Lynx', '2.8', '2', '8', 'unknown'),
+ false),
+
+ // Maxathon (treat as IE)
+ 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)' => array(
+ array('IE', 'Internet Explorer', 'IE', '7.0', '7', '0', 'ie'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // Midori
+ 'Midori/0.1.9 (X11; Linux i686; U; fr-fr) WebKit/532+' => array(
+ array('MI', 'Midori', 'Midori', '0.1', '0', '1', 'webkit'),
+ array('LIN', 'Linux', 'Linux')),
+
+ // Mozilla Suite
+ 'Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.7) Gecko/20070606' => array(
+ array('MO', 'Mozilla', 'Mozilla', '1.7', '1', '7', 'gecko'),
+ array('SOS', 'SunOS', 'SunOS')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.8) Gecko/20050927 Debian/1.7.8-1sarge3' => array(
+ array('MO', 'Mozilla', 'Mozilla', '1.7', '1', '7', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+
+ // NCSA Mosaic
+ 'PATHWORKS Mosaic/1.0 libwww/2.15_Spyglass' => array(
+ array('MC', 'NCSA Mosaic', 'Mosaic', '1.0', '1', '0', 'unknown'),
+ false),
+ 'WinMosaic/Version 2.0 (ALPHA 2)' => array(
+ array('MC', 'NCSA Mosaic', 'Mosaic', '2.0', '2', '0', 'unknown'),
+ false),
+ 'VMS_Mosaic/3.8-1 (Motif;OpenVMS V7.3-2 DEC 3000 - M700) libwww/2.12_Mosaic' => array(
+ array('MC', 'NCSA Mosaic', 'Mosaic', '3.8', '3', '8', 'unknown'),
+ false),
+ 'Mosaic from Digital/1.02_Win32' => array(
+ array('MC', 'NCSA Mosaic', 'Mosaic', '1.02', '1', '02', 'unknown'),
+ array('W95', 'Windows 95', 'Win 95')),
+ 'NCSA Mosaic/2.0.0b4 (Windows AXP)' => array(
+ array('MC', 'NCSA Mosaic', 'Mosaic', '2.0', '2', '0', 'unknown'),
+ false),
+ 'NCSA_Mosaic/2.7b5 (X11;Linux 2.6.7 i686) libwww/2.12 modified' => array(
+ array('MC', 'NCSA Mosaic', 'Mosaic', '2.7', '2', '7', 'unknown'),
+ array('LIN', 'Linux', 'Linux')),
+ 'mMosaic/3.6.6 (X11;SunOS 5.8 sun4m)' => array(
+ array('MC', 'NCSA Mosaic', 'Mosaic', '3.6', '3', '6', 'unknown'),
+ array('SOS', 'SunOS', 'SunOS')),
+
+ // Netscape Navigator (9.x)
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.8pre) Gecko/20071015 Firefox/2.0.0.7 Navigator/9.0' => array(
+ array('NS', 'Netscape', 'Netscape', '9.0', '9', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20070321 Netscape/9.0' => array(
+ array('NS', 'Netscape', 'Netscape', '9.0', '9', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+
+ // Netscape (6.x - 8.x)
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20070321 Netscape/8.1.3' => array(
+ array('NS', 'Netscape', 'Netscape', '8.1', '8', '1', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)' => array(
+ array('NS', 'Netscape', 'Netscape', '7.2', '7', '2', 'gecko'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (X11; U; OSF1 alpha; en-US; rv:0.9.4.1) Gecko/20020517 Netscape6/6.2.3' => array(
+ array('NS', 'Netscape', 'Netscape', '6.2', '6', '2', 'gecko'),
+ array('T64', 'Tru64', 'Tru64')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1' => array(
+ array('NS', 'Netscape', 'Netscape', '6.1', '6', '1', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+
+ // Netscape Communicator (4.x)
+ 'Mozilla/4.76C-SGI [en] (X11; I; IRIX64 6.5 IP30)' => array(
+ array('NS', 'Netscape', 'Netscape', '4.76', '4', '76', 'gecko'),
+ array('IRI', 'IRIX', 'IRIX')),
+ 'Mozilla/4.72 [en] (X11; I; HP-UX B.11.00 9000/800)' => array(
+ array('NS', 'Netscape', 'Netscape', '4.72', '4', '72', 'gecko'),
+ array('HPX', 'HP-UX', 'HP-UX')),
+ 'Mozilla/4.41 (BEOS; U ;Nav)' => array(
+ array('NS', 'Netscape', 'Netscape', '4.41', '4', '41', 'gecko'),
+ array('BEO', 'BeOS', 'BeOS')),
+ 'Mozilla/4.0 (compatible; Windows NT 5.1; U; en)' => array(
+ array('NS', 'Netscape', 'Netscape', '4.0', '4', '0', 'gecko'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // Netscape Navigator (up to 3.x)
+ 'Mozilla/3.0 (X11; I; AIX 2)' => array(
+ array('NS', 'Netscape', 'Netscape', '3.0', '3', '0', 'gecko'),
+ array('AIX', 'AIX', 'AIX')),
+ 'Mozilla/2.02 [fr] (WinNT; I)' => array(
+ array('NS', 'Netscape', 'Netscape', '2.02', '2', '02', 'gecko'),
+ array('WNT', 'Windows NT', 'Win NT')),
+
+ // Omniweb
+ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US) AppleWebKit/525.18 (KHTML, like Gecko, Safari/525.20) OmniWeb/v622.3.0.105198' => array(
+ array('OW', 'OmniWeb', 'OmniWeb', '5.8', '5', '8', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/522+ (KHTML, like Gecko, Safari/522) OmniWeb/v613' => array(
+ array('OW', 'OmniWeb', 'OmniWeb', '5.6', '5', '6', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/420+ (KHTML, like Gecko, Safari/420) OmniWeb/v607' => array(
+ array('OW', 'OmniWeb', 'OmniWeb', '5.5', '5', '5', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/125.4 (KHTML, like Gecko, Safari) OmniWeb/v563.34' => array(
+ array('OW', 'OmniWeb', 'OmniWeb', '5.1', '5', '1', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/85 (KHTML, like Gecko) OmniWeb/v558.36' => array(
+ array('OW', 'OmniWeb', 'OmniWeb', '5.0', '5', '0', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-US) AppleWebKit/85 (KHTML, like Gecko) OmniWeb/v496' => array(
+ array('OW', 'OmniWeb', 'OmniWeb', '4.5', '4', '5', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+
+ // Opera
+ 'Opera/9.63 (Windows NT 5.1; U; en) Presto/2.1.1' => array(
+ array('OP', 'Opera', 'Opera', '9.63', '9', '63', 'opera'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Opera/9.30 (Nintendo Wii; U; ; 2047-7; en)' => array(
+ array('OP', 'Opera', 'Opera', '9.30', '9', '30', 'opera'),
+ array('WII', 'Nintendo Wii', 'Wii')),
+ 'Opera/9.64 (Windows ME; U; en) Presto/2.1.1' => array(
+ array('OP', 'Opera', 'Opera', '9.64', '9', '64', 'opera'),
+ array('WME', 'Windows Me', 'Win Me')),
+ 'Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.00' => array(
+ array('OP', 'Opera', 'Opera', '10.00', '10', '0', 'opera'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/4.0 (compatible; MSIE 6.0; Nitro) Opera 8.50 [en Mozilla/4.0 (compatible; MSIE 6.0; Nitro) Opera 8.50 [ja]' => array(
+ array('OP', 'Opera', 'Opera', '8.50', '8', '50', 'opera'),
+ array('NDS', 'Nintendo DS', 'DS')),
+ 'Opera/9.00 (Nintendo DS U; ; 1309-9; de)' => array(
+ array('OP', 'Opera', 'Opera', '9.00', '9', '00', 'opera'),
+ array('NDS', 'Nintendo DS', 'DS')),
+ 'Opera/9.50 (Nintendo DSi; Opera/507; U; en-US) ' => array(
+ array('OP', 'Opera', 'Opera', '9.50', '9', '50', 'opera'),
+ array('DSI', 'Nintendo DSi', 'DSi')),
+
+ // PSP
+ 'PSP (PlayStation Portable); 2.00' => array(
+ false,
+ array('PSP', 'PlayStation Portable', 'PSP')),
+ 'Mozilla/4.0 (PSP (PlayStation Portable); 2.00)' => array(
+ false,
+ array('PSP', 'PlayStation Portable', 'PSP')),
+
+ // Safari
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Version/3.1.2 Safari/525.21' => array(
+ array('SF', 'Safari', 'Safari', '3.1', '3', '1', 'webkit'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_2 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5G77 Safari/525.20' => array(
+ array('SF', 'Safari', 'Safari', '3.1', '3', '1', 'webkit'),
+ array('IPH', 'iPhone', 'iPhone')),
+ 'Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A100a Safari/419.3' => array(
+ array('SF', 'Safari', 'Safari', '3.0', '3', '0', 'webkit'),
+ array('IPD', 'iPod', 'iPod')),
+ 'Mozilla/5.0 (iPod; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11a Safari/525.20' => array(
+ array('SF', 'Safari', 'Safari', '3.1', '3', '1', 'webkit'),
+ array('IPD', 'iPod', 'iPod')),
+ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/527.3+ (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1' => array(
+ array('SF', 'Safari', 'Safari', '3.1', '3', '1', 'webkit'),
+ array('MAC', 'Mac OS', 'Mac OS')),
+ 'Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10' => array(
+ array('SF', 'Safari', 'Safari', '4.0', '4', '0', 'webkit'),
+ array('IPA', 'iPad', 'iPad')),
+
+ // SeaMonkey (formerly Mozilla Suite and rebranded versions)
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.8) Gecko/20071008 Iceape/1.1.5 (Ubuntu-1.1.5-1ubuntu0.7.10)' => array(
+ array('SM', 'SeaMonkey', 'SeaMonkey', '1.1', '1', '1', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1b4pre) Gecko/20090405 SeaMonkey/2.0b1pre' => array(
+ array('SM', 'SeaMonkey', 'SeaMonkey', '2.0', '2', '0', 'gecko'),
+ array('LIN', 'Linux', 'Linux')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9) Gecko' => array(
+ // this pre-2.0 UA is missing the SeaMonkey/X.Y
+ array('SM', 'SeaMonkey', 'SeaMonkey', '1.9', '1', '9', 'gecko'),
+ array('WXP', 'Windows XP', 'Win XP')),
+ 'Mozilla/5.0 (Windows; U; Windows NT 5.1; cs; rv:1.9) Gecko/2008052906' => array(
+ // this pre-2.0 UA is missing the SeaMonkey/X.Y
+ array('SM', 'SeaMonkey', 'SeaMonkey', '1.9', '1', '9', 'gecko'),
+ array('WXP', 'Windows XP', 'Win XP')),
+
+ // Palm webOS
+ 'Mozilla/5.0 (webOS/1.0; U; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pre/1.0' => array(
+ array('WO', 'Palm webOS', 'webOS', '1.0', '1', '0', 'webkit'),
+ array('WOS', 'Palm webOS', 'webOS')),
+ 'Mozilla/5.0 (webOS/Palm webOS 1.2.9; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pixi/1.0' => array(
+ array('WO', 'Palm webOS', 'webOS', '1.0', '1', '0', 'webkit'),
+ array('WOS', 'Palm webOS', 'webOS')),
+ 'Mozilla/5.0 [en] (PalmOS; U; WebPro/3.5; Palm-Zi72)' => array(
+ array('WP', 'WebPro', 'WebPro', '3.5', '3', '5', 'unknown'),
+ array('POS', 'Palm OS', 'Palm OS')),
+
+ // Palm WebPro
+ 'Mozilla/4.76 [en] (PalmOS; U; WebPro/3.0.1a; Palm-Cct1)' => array(
+ array('WP', 'WebPro', 'WebPro', '3.0', '3', '0', 'unknown'),
+ array('POS', 'Palm OS', 'Palm OS')),
+ 'Mozilla/4.76 [en] (PalmOS; U; WebPro/3.0; Palm-Arz1)' => array(
+ array('WP', 'WebPro', 'WebPro', '3.0', '3', '0', 'unknown'),
+ array('POS', 'Palm OS', 'Palm OS')),
+ );
+
+ public function test_getBrowser()
+ {
+ foreach($this->userAgents as $userAgent => $expected)
+ {
+ $res = UserAgentParser::getBrowser($userAgent);
+ $family = false;
+
+ if($res === false)
+ $ok = $res === $expected[0];
+ else
+ {
+ $family = Piwik_getBrowserFamily($res['id']);
+ $ok = $expected[0][0] == $res['id'] &&
+ $expected[0][1] == $res['name'] &&
+ $expected[0][2] == $res['short_name'] &&
+ $expected[0][3] == $res['version'] &&
+ $expected[0][4] == $res['major_number'] &&
+ $expected[0][5] == $res['minor_number'] &&
+ $expected[0][6] == $family;
+ }
+
+ $this->assertTrue($ok);
+ if(!$ok)
+ {
+ var_dump(array($userAgent, $res, $family));
+ }
+ }
+ }
+
+ public function test_getOperatingSystem()
+ {
+ foreach($this->userAgents as $userAgent => $expected)
+ {
+ $res = UserAgentParser::getOperatingSystem($userAgent);
+
+ $ok = $expected[1][0] == $res['id'] &&
+ $expected[1][1] == $res['name'] &&
+ $expected[1][2] == $res['short_name'];
+
+ $this->assertTrue($ok);
+ if(!$ok)
+ {
+ var_dump(array($userAgent, $res));
+ }
+ }
+ }
+}
diff --git a/plugins/UsersManager/API.php b/plugins/UsersManager/API.php
index fda72c78c3..8ab60fb252 100644
--- a/plugins/UsersManager/API.php
+++ b/plugins/UsersManager/API.php
@@ -17,6 +17,10 @@
class Piwik_UsersManager_API
{
static private $instance = null;
+
+ /**
+ * @return Piwik_UsersManager_API
+ */
static public function getInstance()
{
if (self::$instance == null)
@@ -27,17 +31,51 @@ class Piwik_UsersManager_API
return self::$instance;
}
+ const PREFERENCE_DEFAULT_REPORT = 'defaultReport';
+ const PREFERENCE_DEFAULT_REPORT_DATE = 'defaultReportDate';
+
+ /**
+ * Sets a user preference
+ * @param $userLogin
+ * @param $preferenceName
+ * @param $preferenceValue
+ * @return void
+ */
+ public function setUserPreference($userLogin, $preferenceName, $preferenceValue)
+ {
+ Piwik::checkUserIsSuperUserOrTheUser($userLogin);
+ Piwik_SetOption($this->getPreferenceId($userLogin, $preferenceName), $preferenceValue);
+ }
+
+ /**
+ * Gets a user preference
+ * @param $userLogin
+ * @param $preferenceName
+ * @param $preferenceValue
+ * @return void
+ */
+ public function getUserPreference($userLogin, $preferenceName)
+ {
+ Piwik::checkUserIsSuperUserOrTheUser($userLogin);
+ return Piwik_GetOption($this->getPreferenceId($userLogin, $preferenceName));
+ }
+
+ private function getPreferenceId($login, $preference)
+ {
+ return $login . '_' . $preference;
+ }
+
/**
* Returns the list of all the users
*
* @return array the list of all the users
*/
- static public function getUsers()
+ public function getUsers()
{
Piwik::checkUserIsSuperUser();
$db = Zend_Registry::get('db');
- $users = $db->fetchAll("SELECT * FROM ".Piwik::prefixTable("user")." ORDER BY login ASC");
+ $users = $db->fetchAll("SELECT * FROM ".Piwik_Common::prefixTable("user")." ORDER BY login ASC");
return $users;
}
@@ -46,12 +84,12 @@ class Piwik_UsersManager_API
*
* @return array the list of all the users login
*/
- static public function getUsersLogin()
+ public function getUsersLogin()
{
Piwik::checkUserHasSomeAdminAccess();
$db = Zend_Registry::get('db');
- $users = $db->fetchAll("SELECT login FROM ".Piwik::prefixTable("user")." ORDER BY login ASC");
+ $users = $db->fetchAll("SELECT login FROM ".Piwik_Common::prefixTable("user")." ORDER BY login ASC");
$return = array();
foreach($users as $login)
{
@@ -75,15 +113,15 @@ class Piwik_UsersManager_API
* )
*
*/
- static public function getUsersSitesFromAccess( $access )
+ public function getUsersSitesFromAccess( $access )
{
Piwik::checkUserIsSuperUser();
- self::checkAccessType($access);
+ $this->checkAccessType($access);
$db = Zend_Registry::get('db');
$users = $db->fetchAll("SELECT login,idsite
- FROM ".Piwik::prefixTable("access")
+ FROM ".Piwik_Common::prefixTable("access")
." WHERE access = ?", $access);
$return = array();
foreach($users as $user)
@@ -109,13 +147,13 @@ class Piwik_UsersManager_API
* ...
* )
*/
- static public function getUsersAccessFromSite( $idSite )
+ public function getUsersAccessFromSite( $idSite )
{
Piwik::checkUserHasAdminAccess( $idSite );
$db = Zend_Registry::get('db');
$users = $db->fetchAll("SELECT login,access
- FROM ".Piwik::prefixTable("access")
+ FROM ".Piwik_Common::prefixTable("access")
." WHERE idsite = ?", $idSite);
$return = array();
foreach($users as $user)
@@ -142,15 +180,15 @@ class Piwik_UsersManager_API
* ...
* )
*/
- static public function getSitesAccessFromUser( $userLogin )
+ public function getSitesAccessFromUser( $userLogin )
{
Piwik::checkUserIsSuperUser();
- self::checkUserExists($userLogin);
- self::checkUserIsNotSuperUser($userLogin);
+ $this->checkUserExists($userLogin);
+ $this->checkUserIsNotSuperUser($userLogin);
$db = Zend_Registry::get('db');
$users = $db->fetchAll("SELECT idsite,access
- FROM ".Piwik::prefixTable("access")
+ FROM ".Piwik_Common::prefixTable("access")
." WHERE login = ?", $userLogin);
$return = array();
foreach($users as $user)
@@ -170,15 +208,15 @@ class Piwik_UsersManager_API
*
* @return array the user information
*/
- static public function getUser( $userLogin )
+ public function getUser( $userLogin )
{
- Piwik::checkUserIsSuperUser();
- self::checkUserExists($userLogin);
- self::checkUserIsNotSuperUser($userLogin);
+ Piwik::checkUserIsSuperUserOrTheUser($userLogin);
+ $this->checkUserExists($userLogin);
+ $this->checkUserIsNotSuperUser($userLogin);
$db = Zend_Registry::get('db');
$user = $db->fetchRow("SELECT *
- FROM ".Piwik::prefixTable("user")
+ FROM ".Piwik_Common::prefixTable("user")
." WHERE login = ?", $userLogin);
return $user;
}
@@ -190,48 +228,39 @@ class Piwik_UsersManager_API
*
* @return array the user information
*/
- static public function getUserByEmail( $userEmail )
+ public function getUserByEmail( $userEmail )
{
Piwik::checkUserIsSuperUser();
- self::checkUserEmailExists($userEmail);
+ $this->checkUserEmailExists($userEmail);
$db = Zend_Registry::get('db');
$user = $db->fetchRow("SELECT *
- FROM ".Piwik::prefixTable("user")
+ FROM ".Piwik_Common::prefixTable("user")
." WHERE email = ?", $userEmail);
return $user;
}
- static private function checkLogin($userLogin)
+ private function checkLogin($userLogin)
{
- if(self::userExists($userLogin))
+ if($this->userExists($userLogin))
{
throw new Exception(Piwik_TranslateException('UsersManager_ExceptionLoginExists', $userLogin));
}
- $loginMinimumLength = 3;
- $loginMaximumLength = 100;
- $l = strlen($userLogin);
- if(!($l >= $loginMinimumLength
- && $l <= $loginMaximumLength
- && (preg_match('/^[A-Za-z0-9_.-]*$/', $userLogin) > 0))
- )
- {
- throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidLoginFormat', array($loginMinimumLength, $loginMaximumLength)));
- }
+ Piwik::checkValidLoginString($userLogin);
}
- static private function checkPassword($password)
+ private function checkPassword($password)
{
- if(!self::isValidPasswordString($password))
+ if(!$this->isValidPasswordString($password))
{
throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidPassword'));
}
}
- static private function checkEmail($email)
+ private function checkEmail($email)
{
- if(self::userEmailExists($email))
+ if($this->userEmailExists($email))
{
throw new Exception(Piwik_TranslateException('UsersManager_ExceptionEmailExists', $email));
}
@@ -242,7 +271,7 @@ class Piwik_UsersManager_API
}
}
- static private function getCleanAlias($alias,$userLogin)
+ private function getCleanAlias($alias,$userLogin)
{
if(empty($alias))
{
@@ -251,7 +280,7 @@ class Piwik_UsersManager_API
return $alias;
}
- static private function getCleanPassword($password)
+ private function getCleanPassword($password)
{
// if change here, should also edit the installation process
// to change how the root pwd is saved in the config file
@@ -273,29 +302,30 @@ class Piwik_UsersManager_API
*
* @exception in case of an invalid parameter
*/
- static public function addUser( $userLogin, $password, $email, $alias = false )
+ public function addUser( $userLogin, $password, $email, $alias = false )
{
Piwik::checkUserIsSuperUser();
- self::checkLogin($userLogin);
- self::checkUserIsNotSuperUser($userLogin);
- self::checkPassword($password);
- self::checkEmail($email);
+ $this->checkLogin($userLogin);
+ $this->checkUserIsNotSuperUser($userLogin);
+ $this->checkPassword($password);
+ $this->checkEmail($email);
- $alias = self::getCleanAlias($alias,$userLogin);
- $passwordTransformed = self::getCleanPassword($password);
+ $alias = $this->getCleanAlias($alias,$userLogin);
+ $passwordTransformed = $this->getCleanPassword($password);
- $token_auth = self::getTokenAuth($userLogin, $passwordTransformed);
+ $token_auth = $this->getTokenAuth($userLogin, $passwordTransformed);
$db = Zend_Registry::get('db');
- $db->insert( Piwik::prefixTable("user"), array(
+ $db->insert( Piwik_Common::prefixTable("user"), array(
'login' => $userLogin,
'password' => $passwordTransformed,
'alias' => $alias,
'email' => $email,
'token_auth' => $token_auth,
- )
+ 'date_registered' => Piwik_Date::now()->getDatetime()
+ )
);
// we reload the access list which doesn't yet take in consideration this new user
@@ -311,12 +341,12 @@ class Piwik_UsersManager_API
*
* @see addUser() for all the parameters
*/
- static public function updateUser( $userLogin, $password = false, $email = false, $alias = false )
+ public function updateUser( $userLogin, $password = false, $email = false, $alias = false )
{
Piwik::checkUserIsSuperUserOrTheUser($userLogin);
- self::checkUserIsNotAnonymous( $userLogin );
- self::checkUserIsNotSuperUser($userLogin);
- $userInfo = self::getUser($userLogin);
+ $this->checkUserIsNotAnonymous( $userLogin );
+ $this->checkUserIsNotSuperUser($userLogin);
+ $userInfo = $this->getUser($userLogin);
if(empty($password))
{
@@ -324,8 +354,8 @@ class Piwik_UsersManager_API
}
else
{
- self::checkPassword($password);
- $password = self::getCleanPassword($password);
+ $this->checkPassword($password);
+ $password = $this->getCleanPassword($password);
}
if(empty($alias))
@@ -340,15 +370,15 @@ class Piwik_UsersManager_API
if($email != $userInfo['email'])
{
- self::checkEmail($email);
+ $this->checkEmail($email);
}
- $alias = self::getCleanAlias($alias,$userLogin);
- $token_auth = self::getTokenAuth($userLogin,$password);
+ $alias = $this->getCleanAlias($alias,$userLogin);
+ $token_auth = $this->getTokenAuth($userLogin,$password);
$db = Zend_Registry::get('db');
- $db->update( Piwik::prefixTable("user"),
+ $db->update( Piwik_Common::prefixTable("user"),
array(
'password' => $password,
'alias' => $alias,
@@ -368,19 +398,18 @@ class Piwik_UsersManager_API
*
* @return bool true on success
*/
- static public function deleteUser( $userLogin )
+ public function deleteUser( $userLogin )
{
Piwik::checkUserIsSuperUser();
- self::checkUserIsNotAnonymous( $userLogin );
- self::checkUserIsNotSuperUser($userLogin);
- if(!self::userExists($userLogin))
+ $this->checkUserIsNotAnonymous( $userLogin );
+ $this->checkUserIsNotSuperUser($userLogin);
+ if(!$this->userExists($userLogin))
{
throw new Exception(Piwik_TranslateException("UsersManager_ExceptionDeleteDoesNotExist", $userLogin));
}
-
- self::deleteUserOnly( $userLogin );
- self::deleteUserAccess( $userLogin );
+ $this->deleteUserOnly( $userLogin );
+ $this->deleteUserAccess( $userLogin );
}
/**
@@ -388,11 +417,10 @@ class Piwik_UsersManager_API
*
* @return bool true if the user is known
*/
- static public function userExists( $userLogin )
+ public function userExists( $userLogin )
{
- Piwik::checkUserHasSomeAdminAccess();
$count = Piwik_FetchOne("SELECT count(*)
- FROM ".Piwik::prefixTable("user"). "
+ FROM ".Piwik_Common::prefixTable("user"). "
WHERE login = ?", $userLogin);
return $count != 0;
}
@@ -402,11 +430,11 @@ class Piwik_UsersManager_API
*
* @return bool true if the user is known
*/
- static public function userEmailExists( $userEmail )
+ public function userEmailExists( $userEmail )
{
Piwik::checkUserHasSomeAdminAccess();
$count = Piwik_FetchOne("SELECT count(*)
- FROM ".Piwik::prefixTable("user"). "
+ FROM ".Piwik_Common::prefixTable("user"). "
WHERE email = ?", $userEmail);
return $count != 0;
}
@@ -428,11 +456,11 @@ class Piwik_UsersManager_API
*
* @return bool true on success
*/
- static public function setUserAccess( $userLogin, $access, $idSites)
+ public function setUserAccess( $userLogin, $access, $idSites)
{
- self::checkAccessType( $access );
- self::checkUserExists( $userLogin);
- self::checkUserIsNotSuperUser($userLogin);
+ $this->checkAccessType( $access );
+ $this->checkUserExists( $userLogin);
+ $this->checkUserIsNotSuperUser($userLogin);
if($userLogin == 'anonymous'
&& $access == 'admin')
@@ -444,7 +472,7 @@ class Piwik_UsersManager_API
// has an 'admin' access
if($idSites === 'all')
{
- $idSites = Piwik_SitesManager_API::getSitesIdWithAdminAccess();
+ $idSites = Piwik_SitesManager_API::getInstance()->getSitesIdWithAdminAccess();
}
// in case the idSites is an integer we build an array
elseif(!is_array($idSites))
@@ -456,7 +484,7 @@ class Piwik_UsersManager_API
// basically an admin can give the view or the admin access to any user for the websites he manages
Piwik::checkUserHasAdminAccess( $idSites );
- self::deleteUserAccess( $userLogin, $idSites);
+ $this->deleteUserAccess( $userLogin, $idSites);
// delete UserAccess
$db = Zend_Registry::get('db');
@@ -467,7 +495,7 @@ class Piwik_UsersManager_API
{
foreach($idSites as $idsite)
{
- $db->insert( Piwik::prefixTable("access"),
+ $db->insert( Piwik_Common::prefixTable("access"),
array( "idsite" => $idsite,
"login" => $userLogin,
"access" => $access)
@@ -485,9 +513,9 @@ class Piwik_UsersManager_API
* @param string user login
* @exception if the user doesn't exist
*/
- static private function checkUserExists( $userLogin )
+ private function checkUserExists( $userLogin )
{
- if(!self::userExists($userLogin))
+ if(!$this->userExists($userLogin))
{
throw new Exception(Piwik_TranslateException("UsersManager_ExceptionUserDoesNotExist", $userLogin));
}
@@ -499,22 +527,22 @@ class Piwik_UsersManager_API
* @param string user email
* @exception if the user doesn't exist
*/
- static private function checkUserEmailExists( $userEmail )
+ private function checkUserEmailExists( $userEmail )
{
- if(!self::userEmailExists($userEmail))
+ if(!$this->userEmailExists($userEmail))
{
throw new Exception(Piwik_TranslateException("UsersManager_ExceptionUserDoesNotExist", $userEmail));
}
}
- static private function checkUserIsNotAnonymous( $userLogin )
+ private function checkUserIsNotAnonymous( $userLogin )
{
if($userLogin == 'anonymous')
{
throw new Exception(Piwik_TranslateException("UsersManager_ExceptionEditAnonymous"));
}
}
- static private function checkUserIsNotSuperUser( $userLogin )
+ private function checkUserIsNotSuperUser( $userLogin )
{
if($userLogin == Zend_Registry::get('config')->superuser->login)
{
@@ -522,7 +550,7 @@ class Piwik_UsersManager_API
}
}
- static private function checkAccessType($access)
+ private function checkAccessType($access)
{
$accessList = Piwik_Access::getListAccess();
@@ -542,10 +570,12 @@ class Piwik_UsersManager_API
* @param string the user login.
*
*/
- static private function deleteUserOnly( $userLogin )
+ private function deleteUserOnly( $userLogin )
{
$db = Zend_Registry::get('db');
- $db->query("DELETE FROM ".Piwik::prefixTable("user")." WHERE login = ?", $userLogin);
+ $db->query("DELETE FROM ".Piwik_Common::prefixTable("user")." WHERE login = ?", $userLogin);
+
+ Piwik_PostEvent('UsersManager.deleteUser', $userLogin);
}
@@ -558,13 +588,13 @@ class Piwik_UsersManager_API
*
* @return bool true on success
*/
- static private function deleteUserAccess( $userLogin, $idSites = null )
+ private function deleteUserAccess( $userLogin, $idSites = null )
{
$db = Zend_Registry::get('db');
if(is_null($idSites))
{
- $db->query( "DELETE FROM ".Piwik::prefixTable("access").
+ $db->query( "DELETE FROM ".Piwik_Common::prefixTable("access").
" WHERE login = ?",
array( $userLogin) );
}
@@ -572,7 +602,7 @@ class Piwik_UsersManager_API
{
foreach($idSites as $idsite)
{
- $db->query( "DELETE FROM ".Piwik::prefixTable("access").
+ $db->query( "DELETE FROM ".Piwik_Common::prefixTable("access").
" WHERE idsite = ? AND login = ?",
array($idsite, $userLogin)
);
@@ -586,12 +616,11 @@ class Piwik_UsersManager_API
* @param string Login
* @param string MD5ied string of the password
*/
- static public function getTokenAuth($userLogin, $md5Password)
+ public function getTokenAuth($userLogin, $md5Password)
{
if(strlen($md5Password) != 32)
{
- throw new Exception("UsersManager.getTokenAuth is expecting a MD5-hashed password (32 chars long string).
- Please call the md5() function on the password before calling this method.");
+ throw new Exception(Piwik_TranslateException('UsersManager_ExceptionPasswordMD5HashExpected'));
}
return md5($userLogin . $md5Password );
}
@@ -602,7 +631,7 @@ class Piwik_UsersManager_API
* @param string email
* @return bool
*/
- static private function isValidPasswordString( $input )
+ private function isValidPasswordString( $input )
{
$l = strlen($input);
return $l >= 6 && $l <= 26;
diff --git a/plugins/UsersManager/Controller.php b/plugins/UsersManager/Controller.php
index 630efcefb9..4ac8dca17f 100644
--- a/plugins/UsersManager/Controller.php
+++ b/plugins/UsersManager/Controller.php
@@ -17,11 +17,14 @@
*/
class Piwik_UsersManager_Controller extends Piwik_Controller
{
+ /**
+ * The "Manage Users and Permissions" Admin UI screen
+ */
function index()
{
$view = Piwik_View::factory('UsersManager');
- $IdSitesAdmin = Piwik_SitesManager_API::getSitesIdWithAdminAccess();
+ $IdSitesAdmin = Piwik_SitesManager_API::getInstance()->getSitesIdWithAdminAccess();
$idSiteSelected = 1;
if(count($IdSitesAdmin) > 0)
@@ -36,38 +39,272 @@ class Piwik_UsersManager_Controller extends Piwik_Controller
}
else
{
- $usersAccessByWebsite = Piwik_UsersManager_API::getUsersAccessFromSite( $idSiteSelected );
+ $usersAccessByWebsite = Piwik_UsersManager_API::getInstance()->getUsersAccessFromSite( $idSiteSelected );
}
// requires super user access
- $usersLogin = Piwik_UsersManager_API::getUsersLogin();
+ $usersLogin = Piwik_UsersManager_API::getInstance()->getUsersLogin();
// we dont want to display the user currently logged so that the user can't change his settings from admin to view...
$currentlyLogged = Piwik::getCurrentUserLogin();
-
foreach($usersLogin as $login)
{
- if( $login != $currentlyLogged
- && !isset($usersAccessByWebsite[$login]))
+ if(!isset($usersAccessByWebsite[$login]))
{
$usersAccessByWebsite[$login] = 'noaccess';
}
}
+ unset($usersAccessByWebsite[$currentlyLogged]);
+
ksort($usersAccessByWebsite);
$users = array();
if(Zend_Registry::get('access')->isSuperUser())
{
- $users = Piwik_UsersManager_API::getUsers();
+ $users = Piwik_UsersManager_API::getInstance()->getUsers();
}
$view->idSiteSelected = $idSiteSelected;
$view->users = $users;
$view->usersAccessByWebsite = $usersAccessByWebsite;
$view->formUrl = Piwik_Url::getCurrentUrl();
- $view->websites = Piwik_SitesManager_API::getSitesWithAdminAccess();
+ $view->websites = Piwik_SitesManager_API::getInstance()->getSitesWithAdminAccess();
+ $this->setGeneralVariablesView($view);
+ $view->menu = Piwik_GetAdminMenu();
+ echo $view->render();
+ }
+
+ const DEFAULT_DATE = 'today';
+
+ /**
+ * The "User Settings" admin UI screen view
+ */
+ public function userSettings()
+ {
+ $view = Piwik_View::factory('userSettings');
+
+ $userLogin = Piwik::getCurrentUserLogin();
+ if(Piwik::isUserIsSuperUser())
+ {
+ $view->userAlias = $userLogin;
+ $view->userEmail = Zend_Registry::get('config')->superuser->email;
+ if(!Zend_Registry::get('config')->isFileWritable())
+ {
+ $view->configFileNotWritable = true;
+ }
+ }
+ else
+ {
+ $user = Piwik_UsersManager_API::getInstance()->getUser($userLogin);
+ $view->userAlias = $user['alias'];
+ $view->userEmail = $user['email'];
+ }
+
+ $defaultReport = Piwik_UsersManager_API::getInstance()->getUserPreference($userLogin, Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT);
+ if($defaultReport === false)
+ {
+ $defaultReport = $this->getDefaultWebsiteId();
+ }
+ $view->defaultReport = $defaultReport;
+
+ $defaultDate = Piwik_UsersManager_API::getInstance()->getUserPreference($userLogin, Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT_DATE);
+ if($defaultDate === false)
+ {
+ $defaultDate = self::DEFAULT_DATE;
+ }
+ $view->defaultDate = $defaultDate;
+ $view->availableDefaultDates = array(
+ 'today' => Piwik_Translate('General_Today'),
+ 'yesterday' => Piwik_Translate('General_Yesterday'),
+ 'week' => Piwik_Translate('General_CurrentWeek'),
+ 'month' => Piwik_Translate('General_CurrentMonth'),
+ 'year' => Piwik_Translate('General_CurrentYear'),
+ );
+
+ $view->ignoreCookieSet = $this->isIgnoreCookieFound();
+ $this->initViewAnonymousUserSettings($view);
+ $view->piwikHost = Piwik_Url::getCurrentHost();
$this->setGeneralVariablesView($view);
$view->menu = Piwik_GetAdminMenu();
echo $view->render();
}
+
+ public function setIgnoreCookie()
+ {
+ Piwik::checkUserHasSomeViewAccess();
+ $this->checkTokenInUrl();
+ $cookie = $this->getIgnoreCookie();
+ if($cookie->isCookieFound())
+ {
+ $cookie->delete();
+ }
+ else
+ {
+ $cookie->save();
+ }
+ Piwik::redirectToModule('UsersManager', 'userSettings');
+ }
+
+ protected function getIgnoreCookie()
+ {
+ $cookie_name = Zend_Registry::get('config')->Tracker->ignore_visits_cookie_name;
+ $cookie_path = Zend_Registry::get('config')->Tracker->cookie_path;
+ return new Piwik_Cookie($cookie_name, null, $cookie_path);
+ }
+
+ protected function isIgnoreCookieFound()
+ {
+ $cookie = $this->getIgnoreCookie();
+ return $cookie->isCookieFound();
+ }
+
+ /**
+ * The Super User can modify Anonymous user settings
+ * @param $view
+ */
+ protected function initViewAnonymousUserSettings($view)
+ {
+ if(!Piwik::isUserIsSuperUser())
+ {
+ return;
+ }
+ $userLogin = 'anonymous';
+
+ // Which websites are available to the anonymous users?
+ $anonymousSitesAccess = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser($userLogin);
+ $anonymousSites = array();
+ foreach($anonymousSitesAccess as $info)
+ {
+ $idSite = $info['site'];
+ $anonymousSites[$idSite] = Piwik_SitesManager_API::getInstance()->getSiteFromId($idSite);
+ }
+ $view->anonymousSites = $anonymousSites;
+
+ // Which report is displayed by default to the anonymous user?
+ $anonymousDefaultReport = Piwik_UsersManager_API::getInstance()->getUserPreference($userLogin, Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT);
+ if($anonymousDefaultReport === false)
+ {
+ if(empty($anonymousSites))
+ {
+ $anonymousDefaultReport = Piwik::getLoginPluginName();
+ }
+ else
+ {
+ // we manually imitate what would happen, in case the anonymous user logs in
+ // and is redirected to the first website available to him in the list
+ // @see getDefaultWebsiteId()
+ reset($anonymousSites);
+ $anonymousDefaultReport = key($anonymousSites);
+ }
+ }
+ $view->anonymousDefaultReport = $anonymousDefaultReport;
+
+ $anonymousDefaultDate = Piwik_UsersManager_API::getInstance()->getUserPreference($userLogin, Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT_DATE);
+ if($anonymousDefaultDate === false)
+ {
+ $anonymousDefaultDate = self::DEFAULT_DATE;
+ }
+ $view->anonymousDefaultDate = $anonymousDefaultDate;
+ }
+
+ /**
+ * Records settings for the anonymous users (default report, default date)
+ */
+ public function recordAnonymousUserSettings()
+ {
+ $response = new Piwik_API_ResponseBuilder(Piwik_Common::getRequestVar('format'));
+ try {
+ Piwik::checkUserIsSuperUser();
+ $this->checkTokenInUrl();
+ $anonymousDefaultReport = Piwik_Common::getRequestVar('anonymousDefaultReport');
+ $anonymousDefaultDate = Piwik_Common::getRequestVar('anonymousDefaultDate');
+ $userLogin = 'anonymous';
+ Piwik_UsersManager_API::getInstance()->setUserPreference($userLogin,
+ Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT,
+ $anonymousDefaultReport);
+ Piwik_UsersManager_API::getInstance()->setUserPreference($userLogin,
+ Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT_DATE,
+ $anonymousDefaultDate);
+ $toReturn = $response->getResponse();
+ } catch(Exception $e ) {
+ $toReturn = $response->getResponseException( $e );
+ }
+ echo $toReturn;
+ }
+
+ /**
+ * Records settings from the "User Settings" page
+ */
+ public function recordUserSettings()
+ {
+ $response = new Piwik_API_ResponseBuilder(Piwik_Common::getRequestVar('format'));
+ try {
+ $this->checkTokenInUrl();
+ $alias = Piwik_Common::getRequestVar('alias');
+ $email = Piwik_Common::getRequestVar('email');
+ $defaultReport = Piwik_Common::getRequestVar('defaultReport');
+ $defaultDate = Piwik_Common::getRequestVar('defaultDate');
+
+ $newPassword = false;
+ $password = Piwik_Common::getRequestvar('password', false);
+ $passwordBis = Piwik_Common::getRequestvar('passwordBis', false);
+ if(!empty($password)
+ || !empty($passwordBis))
+ {
+ if($password != $passwordBis)
+ {
+ throw new Exception(Piwik_Translate('Login_PasswordsDoNotMatch'));
+ }
+ $newPassword = $password;
+ }
+
+ $userLogin = Piwik::getCurrentUserLogin();
+ if(Piwik::isUserIsSuperUser())
+ {
+ $superUser = Zend_Registry::get('config')->superuser;
+ $updatedSuperUser = false;
+ if($newPassword !== false)
+ {
+ $md5PasswordSuperUser = md5($newPassword);
+ $superUser->password = $md5PasswordSuperUser;
+ $updatedSuperUser = true;
+ }
+ if($superUser->email != $email)
+ {
+ $superUser->email = $email;
+ $updatedSuperUser = true;
+ }
+ if($updatedSuperUser)
+ {
+ Zend_Registry::get('config')->superuser = $superUser->toArray();
+ }
+ }
+ else
+ {
+ Piwik_UsersManager_API::getInstance()->updateUser($userLogin, $newPassword, $email, $alias);
+ }
+
+ // logs the user in with the new password
+ if($newPassword !== false)
+ {
+ $info = array( 'login' => $userLogin,
+ 'md5Password' => md5($newPassword),
+ );
+ Piwik_PostEvent('Login.initSession', $info);
+ }
+
+ Piwik_UsersManager_API::getInstance()->setUserPreference($userLogin,
+ Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT,
+ $defaultReport);
+ Piwik_UsersManager_API::getInstance()->setUserPreference($userLogin,
+ Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT_DATE,
+ $defaultDate);
+
+ $toReturn = $response->getResponse();
+ } catch(Exception $e ) {
+ $toReturn = $response->getResponseException( $e );
+ }
+ echo $toReturn;
+ }
+
}
diff --git a/plugins/UsersManager/UsersManager.php b/plugins/UsersManager/UsersManager.php
index 10fe88a003..5471a75658 100644
--- a/plugins/UsersManager/UsersManager.php
+++ b/plugins/UsersManager/UsersManager.php
@@ -19,11 +19,10 @@ class Piwik_UsersManager extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Users Management',
- 'description' => 'Users Management in Piwik: add a new User, edit an existing one, update the permissions. All the actions are also available through the API.',
+ 'description' => Piwik_Translate('UsersManager_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
@@ -36,7 +35,14 @@ class Piwik_UsersManager extends Piwik_Plugin
function addMenu()
{
- Piwik_AddAdminMenu('UsersManager_MenuUsers', array('module' => 'UsersManager', 'action' => 'index'));
+ Piwik_AddAdminMenu('UsersManager_MenuUsers',
+ array('module' => 'UsersManager', 'action' => 'index'),
+ Piwik::isUserHasSomeAdminAccess(),
+ $order = 3);
+ Piwik_AddAdminMenu('UsersManager_MenuUserSettings',
+ array('module' => 'UsersManager', 'action' => 'userSettings'),
+ Piwik::isUserHasSomeViewAccess(),
+ $order = 1);
}
}
diff --git a/plugins/UsersManager/templates/UsersManager.js b/plugins/UsersManager/templates/UsersManager.js
index dd08e2ae90..068b56785e 100644
--- a/plugins/UsersManager/templates/UsersManager.js
+++ b/plugins/UsersManager/templates/UsersManager.js
@@ -1,7 +1,17 @@
+function changeSite()
+{
+ var action = $('form#accessSites').attr('action');
+ var idsite = getIdSites();
+
+ action = action + '&idsite=' + idsite;
+
+ window.location = action;
+ return false;
+}
+
function getUpdateUserAJAX( row )
{
- var ajaxRequest = piwikHelper.getStandardAjaxConf();
- piwikHelper.toggleAjaxLoading();
+ var ajaxRequest = piwikHelper.getStandardAjaxConf('ajaxLoadingUsersManagement', 'ajaxErrorUsersManagement');
var parameters = {};
parameters.module = 'API';
@@ -21,8 +31,7 @@ function getUpdateUserAJAX( row )
function getDeleteUserAJAX( login )
{
- var ajaxRequest = piwikHelper.getStandardAjaxConf();
- piwikHelper.toggleAjaxLoading();
+ var ajaxRequest = piwikHelper.getStandardAjaxConf('ajaxLoadingUsersManagement', 'ajaxErrorUsersManagement');
var parameters = {};
parameters.module = 'API';
@@ -38,8 +47,7 @@ function getDeleteUserAJAX( login )
function getAddUserAJAX( row )
{
- var ajaxRequest = piwikHelper.getStandardAjaxConf();
- piwikHelper.toggleAjaxLoading();
+ var ajaxRequest = piwikHelper.getStandardAjaxConf('ajaxLoadingUsersManagement', 'ajaxErrorUsersManagement');
var parameters = {};
parameters.module = 'API';
@@ -110,15 +118,16 @@ function bindUpdateAccess()
// callback called when the ajax request Update the user permissions is successful
function successCallback (response)
{
+ piwikHelper.hideAjaxLoading();
// if the permission couldn't be granted
if(response.result == "error")
{
- piwikHelper.ajaxShowError(response.message);
+ piwikHelper.showAjaxError(response.message);
}
// if the permission change was successful
else
{
- piwikHelper.ajaxHideError();
+ piwikHelper.hideAjaxError();
$(self).parent().parent().find('.accessGranted')
.attr("src","plugins/UsersManager/images/no-access.png" )
@@ -163,7 +172,7 @@ $(document).ready( function() {
// when click on edituser, the cells become editable
$('.edituser')
.click( function() {
- piwikHelper.ajaxHideError();
+ piwikHelper.hideAjaxError();
var idRow = $(this).attr('id');
if(alreadyEdited[idRow]==1) return;
alreadyEdited[idRow] = 1;
@@ -175,7 +184,7 @@ $(document).ready( function() {
var idName = $(n).attr('id');
if(idName != 'userLogin')
{
- var contentAfter = '<input id="'+idName+'" value="'+contentBefore+'" size="25">';
+ var contentAfter = '<input id="'+idName+'" value="'+contentBefore+'" size="25" />';
$(n).html(contentAfter);
}
}
@@ -184,7 +193,7 @@ $(document).ready( function() {
$(this)
.toggle()
.parent()
- .prepend( $('<img src="plugins/UsersManager/images/ok.png" class="updateuser">')
+ .prepend( $('<img src="plugins/UsersManager/images/ok.png" class="updateuser" />')
.click( function(){ $.ajax( getUpdateUserAJAX( $('tr#'+idRow) ) ); } )
);
});
@@ -197,7 +206,7 @@ $(document).ready( function() {
// when click on deleteuser, the we ask for confirmation and then delete the user
$('.deleteuser')
.click( function() {
- piwikHelper.ajaxHideError();
+ piwikHelper.hideAjaxError();
var idRow = $(this).attr('id');
var loginToDelete = $(this).parent().parent().find('#userLogin').html();
if( confirm(sprintf(_pk_translate('UsersManager_DeleteConfirm_js'),'"'+loginToDelete+'"')) )
@@ -208,7 +217,7 @@ $(document).ready( function() {
);
$('.addrow').click( function() {
- piwikHelper.ajaxHideError();
+ piwikHelper.hideAjaxError();
$(this).toggle();
var numberOfRows = $('table#users')[0].rows.length;
@@ -216,21 +225,22 @@ $(document).ready( function() {
var newRowId = 'row' + newRowId;
$(' <tr id="'+newRowId+'">\
- <td><input id="useradd_login" value="login?" size=10></td>\
- <td><input id="useradd_password" value="password" size=10></td>\
- <td><input id="useradd_email" value="email@domain.com" size=15></td>\
- <td><input id="useradd_alias" value="alias" size=15></td>\
+ <td><input id="useradd_login" value="login?" size="10" /></td>\
+ <td><input id="useradd_password" value="password" size="10" /></td>\
+ <td><input id="useradd_email" value="email@domain.com" size="15" /></td>\
+ <td><input id="useradd_alias" value="alias" size="15" /></td>\
<td>-</td>\
- <td><img src="plugins/UsersManager/images/ok.png" class="adduser"></td>\
- <td><img src="plugins/UsersManager/images/remove.png" class="cancel"></td>\
+ <td><img src="plugins/UsersManager/images/ok.png" class="adduser" /></td>\
+ <td><img src="plugins/UsersManager/images/remove.png" class="cancel" /></td>\
</tr>')
.appendTo('#users')
;
$('#'+newRowId).keypress( submitOnEnter );
$('.adduser').click( function(){ $.ajax( getAddUserAJAX($('tr#'+newRowId)) ); } );
- $('.cancel').click(function() { piwikHelper.ajaxHideError(); $(this).parents('tr').remove(); $('.addrow').toggle(); });
+ $('.cancel').click(function() { piwikHelper.hideAjaxError(); $(this).parents('tr').remove(); $('.addrow').toggle(); });
});
$('.updateAccess')
.click( bindUpdateAccess );
+ $('#accessUpdated').hide();
});
diff --git a/plugins/UsersManager/templates/UsersManager.tpl b/plugins/UsersManager/templates/UsersManager.tpl
index be8b398c82..ecd42dcd30 100644
--- a/plugins/UsersManager/templates/UsersManager.tpl
+++ b/plugins/UsersManager/templates/UsersManager.tpl
@@ -2,7 +2,6 @@
{assign var=showPeriodSelection value=false}
{include file="CoreAdminHome/templates/header.tpl"}
{loadJavascriptTranslations plugins='UsersManager'}
-{include file="CoreAdminHome/templates/menu.tpl"}
{literal}
<style>
@@ -16,17 +15,6 @@
text-align:center;
}
-#accessUpdated {
- color: red;
- text-align: center;
- font-weight: bold;
- width: 350px;
- margin: 10px;
- padding: 10px;
- display: none;
- border: 3px solid green;
- color: green;
-}
#access td, #users td {
spacing: 0px;
padding: 2px 5px 5px 4px;
@@ -56,7 +44,7 @@
<p>{'UsersManager_MainDescription'|translate}</p>
<div id="sites">
<form method="post" action="{url action=index}" id="accessSites">
- <p>{'UsersManager_Sites'|translate}: <select id="selectIdsite" name="idsite" onchange="this.form.submit()">
+ <p>{'UsersManager_Sites'|translate}: <select id="selectIdsite" name="idsite" onchange="changeSite()">
<optgroup label="{'UsersManager_AllWebsites'|translate}">
<option label="{'UsersManager_AllWebsites'|translate}" value="all" {if $idSiteSelected=='all'} selected="selected"{/if}>{'UsersManager_ApplyToAllWebsites'|translate}</option>
@@ -72,6 +60,10 @@
</form>
</div>
+{ajaxErrorDiv}
+{ajaxLoadingDiv}
+<div id="accessUpdated" class="ajaxSuccess"><p>{'General_Done'|translate}!</p></div>
+
<table class="admin" id="access">
<thead>
<tr>
@@ -83,9 +75,9 @@
</thead>
<tbody>
+{assign var=accesValid value="<img src='plugins/UsersManager/images/ok.png' class='accessGranted' />"}
+{assign var=accesInvalid value="<img src='plugins/UsersManager/images/no-access.png' class='updateAccess' />"}
{foreach from=$usersAccessByWebsite key=login item=access}
-{assign var=accesValid value="<img src='plugins/UsersManager/images/ok.png' class='accessGranted'>"}
-{assign var=accesInvalid value="<img src='plugins/UsersManager/images/no-access.png' class='updateAccess'>"}
<tr>
<td id='login'>{$login}</td>
<td id='noaccess'>{if $access=='noaccess' and $idSiteSelected!='all'}{$accesValid}{else}{$accesInvalid}{/if}&nbsp;</td>
@@ -96,24 +88,24 @@
</tbody>
</table>
-<div id="accessUpdated">{'General_Done'|translate}!</div>
-
<div class="dialog" id="confirm">
<p>{'UsersManager_ChangeAllConfirm'|translate:"<span id='login'></span>"}</p>
- <input id="yes" type="button" value="{'General_Yes'|translate}"/>
- <input id="no" type="button" value="{'General_No'|translate}"/>
+ <input id="yes" type="button" value="{'General_Yes'|translate}" />
+ <input id="no" type="button" value="{'General_No'|translate}" />
</div>
{if $userIsSuperUser}
- <br/>
+ <br />
<h2>{'UsersManager_UsersManagement'|translate}</h2>
<p>{'UsersManager_UsersManagementMainDescription'|translate}</p>
- <div id="ajaxError" style="display:none"></div>
- <div id="ajaxLoading" style="display:none"><div id="loadingPiwik"><img src="themes/default/images/loading-blue.gif" alt="" /> {'General_LoadingData'|translate}</div></div>
+
+ {ajaxErrorDiv id=ajaxErrorUsersManagement}
+ {ajaxLoadingDiv id=ajaxLoadingUsersManagement}
+
<table class="admin" id="users">
<thead>
<tr>
- <th>{'UsersManager_Login'|translate}</th>
+ <th>{'General_Username'|translate}</th>
<th>{'UsersManager_Password'|translate}</th>
<th>{'UsersManager_Email'|translate}</th>
<th>{'UsersManager_Alias'|translate}</th>
@@ -132,15 +124,15 @@
<td id="email" class="editable">{$user.email}</td>
<td id="alias" class="editable">{$user.alias}</td>
<td id="alias">{$user.token_auth}</td>
- <td><img src='plugins/UsersManager/images/edit.png' class="edituser" id="row{$i}" href='#'></td>
- <td><img src='plugins/UsersManager/images/remove.png' class="deleteuser" id="row{$i}" value="Delete"></td>
+ <td><img src='plugins/UsersManager/images/edit.png' class="edituser" id="row{$i}" href='#' /></td>
+ <td><img src='plugins/UsersManager/images/remove.png' class="deleteuser" id="row{$i}" value="Delete" /></td>
</tr>
{/if}
{/foreach}
</tbody>
</table>
- <div class="addrow"><a href="#"><img src='plugins/UsersManager/images/add.png'> {'UsersManager_AddUser'|translate}</a></div>
+ <div class="addrow"><a href="#"><img src='plugins/UsersManager/images/add.png' /> {'UsersManager_AddUser'|translate}</a></div>
{/if}
{include file="CoreAdminHome/templates/footer.tpl"}
diff --git a/plugins/UsersManager/templates/userSettings.js b/plugins/UsersManager/templates/userSettings.js
new file mode 100644
index 0000000000..87ac2877ea
--- /dev/null
+++ b/plugins/UsersManager/templates/userSettings.js
@@ -0,0 +1,60 @@
+function getUserSettingsAJAX()
+{
+ var ajaxRequest = piwikHelper.getStandardAjaxConf('ajaxLoadingUserSettings', 'ajaxErrorUserSettings');
+ var alias = $('#alias').val();
+ var email = $('#email').val();
+ var password = $('#password').val();
+ var passwordBis = $('#passwordBis').val();
+ var defaultReport = $('input[name=defaultReport]:checked').val();
+ if(defaultReport == 1) {
+ defaultReport = $('#defaultReportWebsite option:selected').val();
+ }
+ var defaultDate = $('input[name=defaultDate]:checked').val();
+ var request = '';
+ request += 'module=UsersManager';
+ request += '&action=recordUserSettings';
+ request += '&format=json';
+ request += '&alias='+alias;
+ request += '&email='+email;
+ request += '&password='+password;
+ request += '&passwordBis='+passwordBis;
+ request += '&defaultReport='+defaultReport;
+ request += '&defaultDate='+defaultDate;
+ request += '&token_auth=' + piwik.token_auth;
+ ajaxRequest.data = request;
+ return ajaxRequest;
+}
+function getAnonymousUserSettingsAJAX()
+{
+ var ajaxRequest = piwikHelper.getStandardAjaxConf('ajaxLoadingAnonymousUserSettings', 'ajaxErrorAnonymousUserSettings');
+ var anonymousDefaultReport = $('input[name=anonymousDefaultReport]:checked').val();
+ if(anonymousDefaultReport == 1) {
+ anonymousDefaultReport = $('#anonymousDefaultReportWebsite option:selected').val();
+ }
+ var anonymousDefaultDate = $('input[name=anonymousDefaultDate]:checked').val();
+ var request = '';
+ request += 'module=UsersManager';
+ request += '&action=recordAnonymousUserSettings';
+ request += '&format=json';
+ request += '&anonymousDefaultReport='+anonymousDefaultReport;
+ request += '&anonymousDefaultDate='+anonymousDefaultDate;
+ request += '&token_auth=' + piwik.token_auth;
+ ajaxRequest.data = request;
+ return ajaxRequest;
+}
+
+$(document).ready( function() {
+ $('#userSettingsSubmit').click( function() {
+ $.ajax( getUserSettingsAJAX() );
+ });
+ $('#userSettingsTable input').keypress( function(e) {
+ var key=e.keyCode || e.which;
+ if (key==13) {
+ $('#userSettingsSubmit').click();
+ }});
+
+ $('#anonymousUserSettingsSubmit').click( function() {
+ $.ajax( getAnonymousUserSettingsAJAX() );
+ });
+});
+
diff --git a/plugins/UsersManager/templates/userSettings.tpl b/plugins/UsersManager/templates/userSettings.tpl
new file mode 100644
index 0000000000..c4b18b2cbd
--- /dev/null
+++ b/plugins/UsersManager/templates/userSettings.tpl
@@ -0,0 +1,130 @@
+{assign var=showSitesSelection value=false}
+{assign var=showPeriodSelection value=false}
+{include file="CoreAdminHome/templates/header.tpl"}
+{loadJavascriptTranslations plugins='UsersManager'}
+<script type="text/javascript" src="plugins/UsersManager/templates/userSettings.js"></script>
+<h2>{'UsersManager_MenuUserSettings'|translate}</h2>
+
+<br />
+<table id='userSettingsTable' class="adminTable adminTableNoBorder" style='width:1000px'>
+<tr>
+ <td><label for="username">{'General_Username'|translate} </label></td>
+ <td>
+ <input size="25" value="{$userLogin}" id="username" disabled="disabled" />
+ <span class='form-description'>{'UsersManager_YourUsernameCannotBeChanged'|translate}</span>
+ </td>
+</tr>
+
+<tr>
+ <td><label for="alias">{'UsersManager_Alias'|translate} </label></td>
+ <td><input size="25" value="{$userAlias}" id="alias"{if $isSuperUser} disabled="disabled"{/if} />
+ {if $isSuperUser}
+ <span class='form-description'>
+ {'UsersManager_TheSuperUserAliasCannotBeChanged'|translate}
+ </span>
+ {/if}
+ </td>
+</td>
+</tr>
+<tr>
+ <td><label for="email">{'UsersManager_Email'|translate} </label></td>
+ <td><input size="25" value="{$userEmail}" id="email" /></td>
+</tr>
+<tr>
+ <td>{'UsersManager_ReportToLoadByDefault'|translate}</td>
+ <td>
+ <fieldset>
+ <label><input type="radio" value="MultiSites" name="defaultReport"{if $defaultReport=='MultiSites'} checked="checked"{/if} /> {'General_AllWebsitesDashboard'|translate}</label><br />
+ <label><input type="radio" value="1" name="defaultReport"{if $defaultReport!='MultiSites'} checked="checked"{/if} /> {'General_DashboardForASpecificWebsite'|translate}</label>
+ <select id="defaultReportWebsite">
+ {if isset($sites)}{foreach from=$sites item=info}
+ <option value="{$info.idsite}" {if $defaultReport==$info.idsite} selected="selected"{/if}>{$info.name}</option>
+ {/foreach}{/if}
+ </select>
+ </fieldset>
+ </td>
+</tr>
+<tr>
+ <td>{'UsersManager_ReportDateToLoadByDefault'|translate}</td>
+ <td>
+ <fieldset>
+ {foreach from=$availableDefaultDates key=value item=description}
+ <label><input type="radio"{if $defaultDate==$value} checked="checked"{/if} value="{$value}" name="defaultDate" /> {$description}</label><br />
+ {/foreach}
+ </fieldset>
+ </td>
+</tr>
+
+<tr>
+ <td><label for="email">{'UsersManager_ChangePassword'|translate} </label></td>
+ <td><input size="25" value="" autocomplete="off" id="password" type="password" />
+ <span class='form-description'>{'UsersManager_IfYouWouldLikeToChangeThePasswordTypeANewOne'|translate}</span>
+ <br /><input size="25" value="" autocomplete="off" id="passwordBis" type="password" />
+ <span class='form-description'> {'UsersManager_TypeYourPasswordAgain'|translate}</span>
+ </td>
+</tr>
+</table>
+
+{ajaxErrorDiv id=ajaxErrorUserSettings}
+{ajaxLoadingDiv id=ajaxLoadingUserSettings}
+<input type="submit" value="{'General_Save'|translate}" id="userSettingsSubmit" class="submit" />
+
+<br/><br/>
+<a name='excludeCookie'></a><h2>{'UsersManager_ExcludeVisitsViaCookie'|translate}</h2>
+<p>{if $ignoreCookieSet}{'UsersManager_YourVisitsAreIgnoredOnDomain'|translate:"<strong>":$piwikHost:"</strong>"}
+{else}{'UsersManager_YourVisitsAreNotIgnored'|translate:"<strong>":"</strong>"}{/if}</p>
+<span style='margin-left:20px'>
+<a href='{url token_auth=$token_auth action=setIgnoreCookie}#excludeCookie'>&rsaquo; {if $ignoreCookieSet}{'UsersManager_ClickHereToDeleteTheCookie'|translate}
+{else}{'UsersManager_ClickHereToSetTheCookieOnDomain'|translate:$piwikHost}{/if}
+<br />
+</a></span>
+
+<br/><br/>
+{if $isSuperUser}
+ <h2>{'UsersManager_MenuAnonymousUserSettings'|translate}</h2>
+ {if count($anonymousSites) == 0}
+ <br /><span class='form-description'><b>{'UsersManager_NoteNoAnonymousUserAccessSettingsWontBeUsed'|translate}</b></span><br />
+ {/if}
+ <br />
+
+ {ajaxErrorDiv id=ajaxErrorAnonymousUserSettings}
+ {ajaxLoadingDiv id=ajaxLoadingAnonymousUserSettings}
+
+ <table id='anonymousUserSettingsTable' class="adminTable adminTableNoBorder" style='width:800px'>
+ <tr>
+ <td style='width:400px'>{'UsersManager_WhenUsersAreNotLoggedInAndVisitPiwikTheyShouldAccess'|translate}</td>
+ <td>
+ <fieldset>
+ <label><input type="radio" value="Login" name="anonymousDefaultReport"{if $anonymousDefaultReport==$loginModule} checked="checked"{/if} /> {'UsersManager_TheLoginScreen'|translate}</label><br />
+ <label><input {if empty($anonymousSites)}disabled="disabled" {/if}type="radio" value="MultiSites" name="anonymousDefaultReport"{if $anonymousDefaultReport=='MultiSites'} checked="checked"{/if} /> {'General_AllWebsitesDashboard'|translate}</label><br />
+
+ <label><input {if empty($anonymousSites)}disabled="disabled" {/if}type="radio" value="1" name="anonymousDefaultReport"{if $anonymousDefaultReport>0} checked="checked"{/if} /> {'General_DashboardForASpecificWebsite'|translate}</label>
+ {if !empty($anonymousSites)}
+ <select id="anonymousDefaultReportWebsite">
+ {foreach from=$anonymousSites item=info}
+ <option value="{$info.idsite}" {if $anonymousDefaultReport==$info.idsite} selected="selected"{/if}>{$info.name}</option>
+ {/foreach}
+ </select>
+ {/if}
+ </fieldset>
+ </td>
+ </tr>
+ <tr>
+ <td>{'UsersManager_ForAnonymousUsersReportDateToLoadByDefault'|translate}</td>
+ <td>
+ <fieldset>
+ {foreach from=$availableDefaultDates key=value item=description}
+ <label><input type="radio" {if $anonymousDefaultDate==$value}checked="checked" {/if}value="{$value}" name="anonymousDefaultDate" /> {$description}</label><br />
+ {/foreach}
+ </fieldset>
+ </td>
+ </tr>
+
+ </table>
+
+<input type="submit" value="{'General_Save'|translate}" id="anonymousUserSettingsSubmit" class="submit" />
+
+{/if}
+
+
+{include file="CoreAdminHome/templates/footer.tpl"}
diff --git a/plugins/UsersManager/tests/UsersManager.test.php b/plugins/UsersManager/tests/UsersManager.test.php
index a76251d639..6b8d8b6407 100644
--- a/plugins/UsersManager/tests/UsersManager.test.php
+++ b/plugins/UsersManager/tests/UsersManager.test.php
@@ -7,7 +7,7 @@ if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php";
}
-require_once "Database.test.php";
+require_once PIWIK_PATH_TEST_TO_ROOT . '/tests/core/Database.test.php';
class Test_Piwik_UsersManager extends Test_Database
{
@@ -53,12 +53,12 @@ class Test_Piwik_UsersManager extends Test_Database
{
$newAlias = $user['alias'];
}
- $userAfter = Piwik_UsersManager_API::getUser($user["login"]);
+ $userAfter = Piwik_UsersManager_API::getInstance()->getUser($user["login"]);
unset($userAfter['date_registered']);
// we now compute what the token auth should be, it should always be a hash of the login and the current password
// if the password has changed then the token_auth has changed!
- $user['token_auth']= Piwik_UsersManager_API::getTokenAuth($user["login"], md5($newPassword) );
+ $user['token_auth']= Piwik_UsersManager_API::getInstance()->getTokenAuth($user["login"], md5($newPassword) );
$user['password']=md5($newPassword);
$user['email']=$newEmail;
@@ -78,28 +78,28 @@ class Test_Piwik_UsersManager extends Test_Database
'password'=>"geqgeagae",
'email'=>"test@test.com",
'alias'=>"alias");
- Piwik_UsersManager_API::addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
+ Piwik_UsersManager_API::getInstance()->addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
try {
- Piwik_UsersManager_API::addUser('superusertest','te','fake@fale.co','ega');
+ Piwik_UsersManager_API::getInstance()->addUser('superusertest','te','fake@fale.co','ega');
$this->fail();
} catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionSuperUser)", $expected->getMessage());
}
try {
- Piwik_UsersManager_API::updateUser('superusertest','te','fake@fale.co','ega');
+ Piwik_UsersManager_API::getInstance()->updateUser('superusertest','te','fake@fale.co','ega');
$this->fail();
} catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionSuperUser)", $expected->getMessage());
}
try {
- Piwik_UsersManager_API::deleteUser('superusertest','te','fake@fale.co','ega');
+ Piwik_UsersManager_API::getInstance()->deleteUser('superusertest','te','fake@fale.co','ega');
$this->fail();
} catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionSuperUser)", $expected->getMessage());
}
try {
- Piwik_UsersManager_API::deleteUser('superusertest','te','fake@fale.co','ega');
+ Piwik_UsersManager_API::getInstance()->deleteUser('superusertest','te','fake@fale.co','ega');
$this->fail();
} catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionSuperUser)", $expected->getMessage());
@@ -117,11 +117,11 @@ class Test_Piwik_UsersManager extends Test_Database
'email'=>"test@test.com",
'alias'=>"alias");
- Piwik_UsersManager_API::addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
+ Piwik_UsersManager_API::getInstance()->addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
try {
- Piwik_UsersManager_API::updateUser( $login, "pas");
+ Piwik_UsersManager_API::getInstance()->updateUser( $login, "pas");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionInvalidPassword)", $expected->getMessage());
@@ -140,7 +140,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_wrongLogin1()
{
try {
- Piwik_UsersManager_API::addUser(12, "password", "email@email.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser(12, "password", "email@email.com", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionInvalidLogin)", $expected->getMessage());
@@ -155,7 +155,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_wrongLogin2()
{
try {
- Piwik_UsersManager_API::addUser("gegag'ggea'", "password", "email@email.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("gegag'ggea'", "password", "email@email.com", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionInvalidLogin)", $expected->getMessage());
@@ -169,7 +169,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_wrongLogin3()
{
try {
- Piwik_UsersManager_API::addUser("gegag11gge@", "password", "email@email.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("gegag11gge@", "password", "email@email.com", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionInvalidLogin)", $expected->getMessage());
@@ -184,7 +184,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_wrongLogin4()
{
try {
- Piwik_UsersManager_API::addUser("geg'ag11gge@", "password", "email@email.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geg'ag11gge@", "password", "email@email.com", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionInvalidLogin)", $expected->getMessage());
@@ -199,8 +199,8 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_existingLogin()
{
try {
- Piwik_UsersManager_API::addUser("test", "password", "email@email.com", "alias");
- Piwik_UsersManager_API::addUser("test", "password2", "em2ail@email.com", "al2ias");
+ Piwik_UsersManager_API::getInstance()->addUser("test", "password", "email@email.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("test", "password2", "em2ail@email.com", "al2ias");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionLoginExists)", $expected->getMessage());
@@ -216,7 +216,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_wrongPassword1()
{
try {
- Piwik_UsersManager_API::addUser("geggeqgeqag", "pas", "email@email.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqag", "pas", "email@email.com", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionInvalidPassword)", $expected->getMessage());
@@ -230,7 +230,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_wrongPassword2()
{
try {
- Piwik_UsersManager_API::addUser("ghqgeggg", "gegageqqqqqqqgeqgqeg84897897897897g122", "email@email.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("ghqgeggg", "gegageqqqqqqqgeqgqeg84897897897897g122", "email@email.com", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionInvalidPassword)", $expected->getMessage());
@@ -245,7 +245,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_wrongPassword3()
{
try {
- Piwik_UsersManager_API::addUser("geggeqgeqag", "", "email@email.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqag", "", "email@email.com", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionInvalidPassword)", $expected->getMessage());
@@ -259,7 +259,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_wrongEmail1()
{
try {
- Piwik_UsersManager_API::addUser("geggeqgeqag", "geqgeagae", "ema'il@email.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqag", "geqgeagae", "ema'il@email.com", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(mail)", $expected->getMessage());
@@ -274,7 +274,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_wrongEmail2()
{
try {
- Piwik_UsersManager_API::addUser("geggeqgeqag", "geqgeagae", "@email.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqag", "geqgeagae", "@email.com", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(mail)", $expected->getMessage());
@@ -288,7 +288,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_wrongEmail3()
{
try {
- Piwik_UsersManager_API::addUser("geggeqgeqag", "geqgeagae", "email@.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqag", "geqgeagae", "email@.com", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(mail)", $expected->getMessage());
@@ -303,7 +303,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_wrongEmail4()
{
try {
- Piwik_UsersManager_API::addUser("geggeqgeqag", "geqgeagae", "email@4.", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqag", "geqgeagae", "email@4.", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(mail)", $expected->getMessage());
@@ -319,7 +319,7 @@ class Test_Piwik_UsersManager extends Test_Database
{
try {
- Piwik_UsersManager_API::addUser("geggeqgeqag", "geqgeagae", "", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqag", "geqgeagae", "", "alias");
}
catch (Exception $expected) {
$this->assertPattern("(mail)", $expected->getMessage());
@@ -334,8 +334,8 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_emptyAlias()
{
$login ="geggeqgeqag";
- Piwik_UsersManager_API::addUser($login, "geqgeagae", "mgeagi@geq.com", "");
- $user = Piwik_UsersManager_API::getUser($login);
+ Piwik_UsersManager_API::getInstance()->addUser($login, "geqgeagae", "mgeagi@geq.com", "");
+ $user = Piwik_UsersManager_API::getInstance()->getUser($login);
$this->assertEqual($user['alias'], $login);
$this->assertEqual($user['login'], $login);
@@ -346,8 +346,8 @@ class Test_Piwik_UsersManager extends Test_Database
function test_addUser_noAliasSpecified()
{
$login ="geggeqg455eqag";
- Piwik_UsersManager_API::addUser($login, "geqgeagae", "mgeagi@geq.com");
- $user = Piwik_UsersManager_API::getUser($login);
+ Piwik_UsersManager_API::getInstance()->addUser($login, "geqgeagae", "mgeagi@geq.com");
+ $user = Piwik_UsersManager_API::getInstance()->getUser($login);
$this->assertEqual($user['alias'], $login);
$this->assertEqual($user['login'], $login);
@@ -364,11 +364,12 @@ class Test_Piwik_UsersManager extends Test_Database
$email = "mgeag4544i@geq.com";
$alias = "her is my alias )(&|\" '£%*(&%+))";
- Piwik_UsersManager_API::addUser($login, $password, $email, $alias);
- $user = Piwik_UsersManager_API::getUser($login);
+ $time = time();
+ Piwik_UsersManager_API::getInstance()->addUser($login, $password, $email, $alias);
+ $user = Piwik_UsersManager_API::getInstance()->getUser($login);
// check that the date registered is correct
- $this->assertTrue( strtotime($user['date_registered']) >= time() - 1 ,
+ $this->assertTrue( strtotime($user['date_registered']) == $time ,
"the date_registered ".strtotime($user['date_registered'])." is different from the time() ". time());
$this->assertTrue($user['date_registered'] <= time() );
@@ -391,10 +392,10 @@ class Test_Piwik_UsersManager extends Test_Database
*/
function test_deleteUser_doesntExist()
{
- Piwik_UsersManager_API::addUser("geggeqgeqag", "geqgeagae", "test@test.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqag", "geqgeagae", "test@test.com", "alias");
try {
- Piwik_UsersManager_API::deleteUser("geggeqggnew");
+ Piwik_UsersManager_API::getInstance()->deleteUser("geggeqggnew");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionDeleteDoesNotExist)", $expected->getMessage());
@@ -409,7 +410,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_deleteUser_emptyUser()
{
try {
- Piwik_UsersManager_API::deleteUser("");
+ Piwik_UsersManager_API::getInstance()->deleteUser("");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionDeleteDoesNotExist)", $expected->getMessage());
@@ -424,7 +425,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_deleteUser_nullUser()
{
try {
- Piwik_UsersManager_API::deleteUser(null);
+ Piwik_UsersManager_API::getInstance()->deleteUser(null);
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionDeleteDoesNotExist)", $expected->getMessage());
@@ -440,35 +441,35 @@ class Test_Piwik_UsersManager extends Test_Database
{
//create the 3 websites
- $idsite = Piwik_SitesManager_API::addSite("site1",array("http://piwik.net","http://piwik.com/test/"));
- $idsite = Piwik_SitesManager_API::addSite("site2",array("http://piwik.com/test/"));
- $idsite = Piwik_SitesManager_API::addSite("site3",array("http://piwik.org"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array("http://piwik.net","http://piwik.com/test/"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site2",array("http://piwik.com/test/"));
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site3",array("http://piwik.org"));
//add user and set some rights
- Piwik_UsersManager_API::addUser("geggeqgeqag", "geqgeagae", "test@test.com", "alias");
- Piwik_UsersManager_API::setUserAccess("geggeqgeqag", "view", array(1,2));
- Piwik_UsersManager_API::setUserAccess("geggeqgeqag", "admin", array(1,3));
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqag", "geqgeagae", "test@test.com", "alias");
+ Piwik_UsersManager_API::getInstance()->setUserAccess("geggeqgeqag", "view", array(1,2));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("geggeqgeqag", "admin", array(1,3));
// check rights are set
- $this->assertNotEqual(Piwik_UsersManager_API::getSitesAccessFromUser("geggeqgeqag"), array());
+ $this->assertNotEqual(Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("geggeqgeqag"), array());
// delete the user
- Piwik_UsersManager_API::deleteUser("geggeqgeqag");
+ Piwik_UsersManager_API::getInstance()->deleteUser("geggeqgeqag");
// try to get it, it should raise an exception
try {
- $user = Piwik_UsersManager_API::getUser("geggeqgeqag");
+ $user = Piwik_UsersManager_API::getInstance()->getUser("geggeqgeqag");
$this->fail("Exception not raised.");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionUserDoesNotExist)", $expected->getMessage());
}
// add the same user
- Piwik_UsersManager_API::addUser("geggeqgeqag", "geqgeagae", "test@test.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqag", "geqgeagae", "test@test.com", "alias");
//checks access have been deleted
//to do so we recreate the same user login and check if the rights are still there
- $this->assertEqual(Piwik_UsersManager_API::getSitesAccessFromUser("geggeqgeqag"), array());
+ $this->assertEqual(Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("geggeqgeqag"), array());
}
@@ -480,7 +481,7 @@ class Test_Piwik_UsersManager extends Test_Database
{
// try to get it, it should raise an exception
try {
- $user = Piwik_UsersManager_API::getUser("geggeqgeqag");
+ $user = Piwik_UsersManager_API::getInstance()->getUser("geggeqgeqag");
$this->fail("Exception not raised.");
}
catch (Exception $expected) {
@@ -498,8 +499,8 @@ class Test_Piwik_UsersManager extends Test_Database
$email = "mgeag4544i@geq.com";
$alias = "";
- Piwik_UsersManager_API::addUser($login, $password, $email, $alias);
- $user = Piwik_UsersManager_API::getUser($login);
+ Piwik_UsersManager_API::getInstance()->addUser($login, $password, $email, $alias);
+ $user = Piwik_UsersManager_API::getInstance()->getUser($login);
// check that all fields are the same
$this->assertEqual($user['login'], $login);
@@ -517,7 +518,7 @@ class Test_Piwik_UsersManager extends Test_Database
*/
function test_getUsers_noUser()
{
- $this->assertEqual(Piwik_UsersManager_API::getUsers(), array());
+ $this->assertEqual(Piwik_UsersManager_API::getInstance()->getUsers(), array());
}
/**
@@ -526,11 +527,11 @@ class Test_Piwik_UsersManager extends Test_Database
function test_getUsers()
{
- Piwik_UsersManager_API::addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
- Piwik_UsersManager_API::addUser("geggeqge632ge56a4qag", "geqgegeagae", "tesggt@tesgt.com", "alias");
- Piwik_UsersManager_API::addUser("geggeqgeqagqegg", "geqgeaggggae", "tesgggt@tesgt.com");
+ Piwik_UsersManager_API::getInstance()->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqge632ge56a4qag", "geqgegeagae", "tesggt@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqagqegg", "geqgeaggggae", "tesgggt@tesgt.com");
- $users = Piwik_UsersManager_API::getUsers();
+ $users = Piwik_UsersManager_API::getInstance()->getUsers();
foreach($users as &$user)
{
unset($user['token_auth']);
@@ -552,11 +553,11 @@ class Test_Piwik_UsersManager extends Test_Database
function test_getUsersLogin()
{
- Piwik_UsersManager_API::addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
- Piwik_UsersManager_API::addUser("geggeqge632ge56a4qag", "geqgegeagae", "tesggt@tesgt.com", "alias");
- Piwik_UsersManager_API::addUser("geggeqgeqagqegg", "geqgeaggggae", "tesgggt@tesgt.com");
+ Piwik_UsersManager_API::getInstance()->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqge632ge56a4qag", "geqgegeagae", "tesggt@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("geggeqgeqagqegg", "geqgeaggggae", "tesgggt@tesgt.com");
- $logins = Piwik_UsersManager_API::getUsersLogin();
+ $logins = Piwik_UsersManager_API::getInstance()->getUsersLogin();
$this->assertEqual($logins,
array( "gegg4564eqgeqag", "geggeqge632ge56a4qag", "geggeqgeqagqegg")
@@ -571,7 +572,7 @@ class Test_Piwik_UsersManager extends Test_Database
{
// try to get it, it should raise an exception
try {
- Piwik_UsersManager_API::setUserAccess("nologin", "view", 1);
+ Piwik_UsersManager_API::getInstance()->setUserAccess("nologin", "view", 1);
$this->fail("Exception not raised.");
}
catch (Exception $expected) {
@@ -585,11 +586,11 @@ class Test_Piwik_UsersManager extends Test_Database
*/
function test_setUserAccess_wrongAccess()
{
- Piwik_UsersManager_API::addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
// try to get it, it should raise an exception
try {
- Piwik_UsersManager_API::setUserAccess("gegg4564eqgeqag", "viewnotknown", 1);
+ Piwik_UsersManager_API::getInstance()->setUserAccess("gegg4564eqgeqag", "viewnotknown", 1);
$this->fail("Exception not raised.");
}
catch (Exception $expected) {
@@ -602,14 +603,14 @@ class Test_Piwik_UsersManager extends Test_Database
*/
function test_setUserAccess_idsitesIsAll()
{
- Piwik_UsersManager_API::addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
FakeAccess::$superUser = false;
- Piwik_UsersManager_API::setUserAccess("gegg4564eqgeqag", "view", "all");
+ Piwik_UsersManager_API::getInstance()->setUserAccess("gegg4564eqgeqag", "view", "all");
FakeAccess::$superUser = true;
- $access = Piwik_UsersManager_API::getSitesAccessFromUser("gegg4564eqgeqag");
+ $access = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->_flatten($access);
FakeAccess::$superUser = false;
@@ -628,16 +629,16 @@ class Test_Piwik_UsersManager extends Test_Database
{
FakeAccess::$superUser = true;
- $id1=Piwik_SitesManager_API::addSite("test",array("http://piwik.net","http://piwik.com/test/"));
- $id2=Piwik_SitesManager_API::addSite("test2",array("http://piwik.net","http://piwik.com/test/"));
- $id3=Piwik_SitesManager_API::addSite("test3",array("http://piwik.net","http://piwik.com/test/"));
- $id4=Piwik_SitesManager_API::addSite("test4",array("http://piwik.net","http://piwik.com/test/"));
- $id5=Piwik_SitesManager_API::addSite("test5",array("http://piwik.net","http://piwik.com/test/"));
+ $id1=Piwik_SitesManager_API::getInstance()->addSite("test",array("http://piwik.net","http://piwik.com/test/"));
+ $id2=Piwik_SitesManager_API::getInstance()->addSite("test2",array("http://piwik.net","http://piwik.com/test/"));
+ $id3=Piwik_SitesManager_API::getInstance()->addSite("test3",array("http://piwik.net","http://piwik.com/test/"));
+ $id4=Piwik_SitesManager_API::getInstance()->addSite("test4",array("http://piwik.net","http://piwik.com/test/"));
+ $id5=Piwik_SitesManager_API::getInstance()->addSite("test5",array("http://piwik.net","http://piwik.com/test/"));
- Piwik_UsersManager_API::addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
- Piwik_UsersManager_API::setUserAccess("gegg4564eqgeqag", "view", "all");
+ Piwik_UsersManager_API::getInstance()->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->setUserAccess("gegg4564eqgeqag", "view", "all");
- $access = Piwik_UsersManager_API::getSitesAccessFromUser("gegg4564eqgeqag");
+ $access = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->_flatten($access);
$this->assertEqual( array($id1,$id2,$id3,$id4,$id5), array_keys($access));
@@ -648,11 +649,11 @@ class Test_Piwik_UsersManager extends Test_Database
*/
function test_setUserAccess_idsitesEmpty()
{
- Piwik_UsersManager_API::addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
- Piwik_UsersManager_API::setUserAccess("gegg4564eqgeqag", "view", array());
+ Piwik_UsersManager_API::getInstance()->setUserAccess("gegg4564eqgeqag", "view", array());
- $access = Piwik_UsersManager_API::getSitesAccessFromUser("gegg4564eqgeqag");
+ $access = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->_flatten($access);
$this->assertEqual( array(), $access);
@@ -663,12 +664,12 @@ class Test_Piwik_UsersManager extends Test_Database
*/
function test_setUserAccess_idsitesOneSite()
{
- Piwik_UsersManager_API::addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
- $id1=Piwik_SitesManager_API::addSite("test",array("http://piwik.net","http://piwik.com/test/"));
+ Piwik_UsersManager_API::getInstance()->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
+ $id1=Piwik_SitesManager_API::getInstance()->addSite("test",array("http://piwik.net","http://piwik.com/test/"));
- Piwik_UsersManager_API::setUserAccess("gegg4564eqgeqag", "view", array(1));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("gegg4564eqgeqag", "view", array(1));
- $access = Piwik_UsersManager_API::getSitesAccessFromUser("gegg4564eqgeqag");
+ $access = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->_flatten($access);
$this->assertEqual( array(1), array_keys($access));
}
@@ -679,14 +680,14 @@ class Test_Piwik_UsersManager extends Test_Database
function test_setUserAccess_idsitesMultipleSites()
{
- Piwik_UsersManager_API::addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
- $id1=Piwik_SitesManager_API::addSite("test",array("http://piwik.net","http://piwik.com/test/"));
- $id2=Piwik_SitesManager_API::addSite("test",array("http://piwik.net","http://piwik.com/test/"));
- $id3=Piwik_SitesManager_API::addSite("test",array("http://piwik.net","http://piwik.com/test/"));
+ Piwik_UsersManager_API::getInstance()->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
+ $id1=Piwik_SitesManager_API::getInstance()->addSite("test",array("http://piwik.net","http://piwik.com/test/"));
+ $id2=Piwik_SitesManager_API::getInstance()->addSite("test",array("http://piwik.net","http://piwik.com/test/"));
+ $id3=Piwik_SitesManager_API::getInstance()->addSite("test",array("http://piwik.net","http://piwik.com/test/"));
- Piwik_UsersManager_API::setUserAccess("gegg4564eqgeqag", "view", array($id1,$id3));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("gegg4564eqgeqag", "view", array($id1,$id3));
- $access = Piwik_UsersManager_API::getSitesAccessFromUser("gegg4564eqgeqag");
+ $access = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->_flatten($access);
$this->assertEqual( array($id1,$id3), array_keys($access));
}
@@ -696,14 +697,14 @@ class Test_Piwik_UsersManager extends Test_Database
function test_setUserAccess_withIdSitesIsStringCommaSeparated()
{
- Piwik_UsersManager_API::addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
- $id1=Piwik_SitesManager_API::addSite("test",array("http://piwik.net","http://piwik.com/test/"));
- $id2=Piwik_SitesManager_API::addSite("test",array("http://piwik.net","http://piwik.com/test/"));
- $id3=Piwik_SitesManager_API::addSite("test",array("http://piwik.net","http://piwik.com/test/"));
+ Piwik_UsersManager_API::getInstance()->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
+ $id1=Piwik_SitesManager_API::getInstance()->addSite("test",array("http://piwik.net","http://piwik.com/test/"));
+ $id2=Piwik_SitesManager_API::getInstance()->addSite("test",array("http://piwik.net","http://piwik.com/test/"));
+ $id3=Piwik_SitesManager_API::getInstance()->addSite("test",array("http://piwik.net","http://piwik.com/test/"));
- Piwik_UsersManager_API::setUserAccess("gegg4564eqgeqag", "view", "1,3");
+ Piwik_UsersManager_API::getInstance()->setUserAccess("gegg4564eqgeqag", "view", "1,3");
- $access = Piwik_UsersManager_API::getSitesAccessFromUser("gegg4564eqgeqag");
+ $access = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->_flatten($access);
$this->assertEqual( array($id1,$id3), array_keys($access));
}
@@ -714,14 +715,14 @@ class Test_Piwik_UsersManager extends Test_Database
*/
function test_setUserAccess_multipleCallDistinctAccessSameUser()
{
- Piwik_UsersManager_API::addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
- $id1=Piwik_SitesManager_API::addSite("test",array("http://piwik.net","http://piwik.com/test/"));
- $id2=Piwik_SitesManager_API::addSite("test",array("http://piwik.net","http://piwik.com/test/"));
+ Piwik_UsersManager_API::getInstance()->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com", "alias");
+ $id1=Piwik_SitesManager_API::getInstance()->addSite("test",array("http://piwik.net","http://piwik.com/test/"));
+ $id2=Piwik_SitesManager_API::getInstance()->addSite("test",array("http://piwik.net","http://piwik.com/test/"));
- Piwik_UsersManager_API::setUserAccess("gegg4564eqgeqag", "view", array($id1));
- Piwik_UsersManager_API::setUserAccess("gegg4564eqgeqag", "admin", array($id2));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("gegg4564eqgeqag", "view", array($id1));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("gegg4564eqgeqag", "admin", array($id2));
- $access = Piwik_UsersManager_API::getSitesAccessFromUser("gegg4564eqgeqag");
+ $access = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->_flatten($access);
$this->assertEqual( array($id1=>'view',$id2=>'admin'), $access);
}
@@ -731,19 +732,19 @@ class Test_Piwik_UsersManager extends Test_Database
*/
function test_setUserAccess_multipleCallDistinctAccessMultipleUser()
{
- Piwik_UsersManager_API::addUser("user1", "geqgegagae", "tegst@tesgt.com", "alias");
- Piwik_UsersManager_API::addUser("user2", "geqgegagae", "tegst2@tesgt.com", "alias");
- $id1=Piwik_SitesManager_API::addSite("test1",array("http://piwik.net","http://piwik.com/test/"));
- $id2=Piwik_SitesManager_API::addSite("test2",array("http://piwik.net","http://piwik.com/test/"));
- $id3=Piwik_SitesManager_API::addSite("test2",array("http://piwik.net","http://piwik.com/test/"));
+ Piwik_UsersManager_API::getInstance()->addUser("user1", "geqgegagae", "tegst@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("user2", "geqgegagae", "tegst2@tesgt.com", "alias");
+ $id1=Piwik_SitesManager_API::getInstance()->addSite("test1",array("http://piwik.net","http://piwik.com/test/"));
+ $id2=Piwik_SitesManager_API::getInstance()->addSite("test2",array("http://piwik.net","http://piwik.com/test/"));
+ $id3=Piwik_SitesManager_API::getInstance()->addSite("test2",array("http://piwik.net","http://piwik.com/test/"));
- Piwik_UsersManager_API::setUserAccess("user1", "view", array($id1,$id2));
- Piwik_UsersManager_API::setUserAccess("user2", "admin", array($id1));
- Piwik_UsersManager_API::setUserAccess("user2", "view", array($id3));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("user1", "view", array($id1,$id2));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("user2", "admin", array($id1));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("user2", "view", array($id3));
- $access1 = Piwik_UsersManager_API::getSitesAccessFromUser("user1");
+ $access1 = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("user1");
$access1 = $this->_flatten($access1);
- $access2 = Piwik_UsersManager_API::getSitesAccessFromUser("user2");
+ $access2 = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("user2");
$access2 = $this->_flatten($access2);
$wanted1 = array( $id1 => 'view', $id2 => 'view', );
$wanted2 = array( $id1 => 'admin', $id3 => 'view' );
@@ -752,9 +753,9 @@ class Test_Piwik_UsersManager extends Test_Database
$this->assertEqual($access2, $wanted2);
- $access1 = Piwik_UsersManager_API::getUsersAccessFromSite($id1);
- $access2 = Piwik_UsersManager_API::getUsersAccessFromSite($id2);
- $access3 = Piwik_UsersManager_API::getUsersAccessFromSite($id3);
+ $access1 = Piwik_UsersManager_API::getInstance()->getUsersAccessFromSite($id1);
+ $access2 = Piwik_UsersManager_API::getInstance()->getUsersAccessFromSite($id2);
+ $access3 = Piwik_UsersManager_API::getInstance()->getUsersAccessFromSite($id3);
$wanted1 = array( 'user1' => 'view', 'user2' => 'admin', );
$wanted2 = array( 'user1' => 'view' );
$wanted3 = array( 'user2' => 'view' );
@@ -763,8 +764,8 @@ class Test_Piwik_UsersManager extends Test_Database
$this->assertEqual($access2, $wanted2);
$this->assertEqual($access3, $wanted3);
- $access1 = Piwik_UsersManager_API::getUsersSitesFromAccess('view');
- $access2 = Piwik_UsersManager_API::getUsersSitesFromAccess('admin');
+ $access1 = Piwik_UsersManager_API::getInstance()->getUsersSitesFromAccess('view');
+ $access2 = Piwik_UsersManager_API::getInstance()->getUsersSitesFromAccess('admin');
$wanted1 = array( 'user1' => array($id1,$id2), 'user2' => array($id3) );
$wanted2 = array( 'user2' => array($id1) );
@@ -778,15 +779,15 @@ class Test_Piwik_UsersManager extends Test_Database
*/
function test_setUserAccess_multipleCallOverwriteSingleUserOneSite()
{
- Piwik_UsersManager_API::addUser("user1", "geqgegagae", "tegst@tesgt.com", "alias");
+ Piwik_UsersManager_API::getInstance()->addUser("user1", "geqgegagae", "tegst@tesgt.com", "alias");
- $id1=Piwik_SitesManager_API::addSite("test1",array("http://piwik.net","http://piwik.com/test/"));
- $id2=Piwik_SitesManager_API::addSite("test2",array("http://piwik.net","http://piwik.com/test/"));
+ $id1=Piwik_SitesManager_API::getInstance()->addSite("test1",array("http://piwik.net","http://piwik.com/test/"));
+ $id2=Piwik_SitesManager_API::getInstance()->addSite("test2",array("http://piwik.net","http://piwik.com/test/"));
- Piwik_UsersManager_API::setUserAccess("user1", "view", array($id1,$id2));
- Piwik_UsersManager_API::setUserAccess("user1", "admin", array($id1));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("user1", "view", array($id1,$id2));
+ Piwik_UsersManager_API::getInstance()->setUserAccess("user1", "admin", array($id1));
- $access1 = Piwik_UsersManager_API::getSitesAccessFromUser("user1");
+ $access1 = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("user1");
$access1 = $this->_flatten($access1);
$wanted1 = array( $id1 => 'admin', $id2 => 'view', );
@@ -801,7 +802,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_getSitesAccessFromUser_wrongUser()
{
try {
- $access1 = Piwik_UsersManager_API::getSitesAccessFromUser("user1");
+ $access1 = Piwik_UsersManager_API::getInstance()->getSitesAccessFromUser("user1");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionUserDoesNotExist)", $expected->getMessage());
@@ -816,7 +817,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_getUsersAccessFromSite_wrongSite()
{
try {
- $access1 = Piwik_UsersManager_API::getUsersAccessFromSite(1);
+ $access1 = Piwik_UsersManager_API::getInstance()->getUsersAccessFromSite(1);
}
catch (Exception $expected) {
return;
@@ -830,7 +831,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_getUsersSitesFromAccess_wrongSite()
{
try {
- $access1 = Piwik_UsersManager_API::getUsersSitesFromAccess('unknown');
+ $access1 = Piwik_UsersManager_API::getInstance()->getUsersSitesFromAccess('unknown');
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionAccessValues)", $expected->getMessage());
@@ -846,7 +847,7 @@ class Test_Piwik_UsersManager extends Test_Database
function test_updateUser_wrongLogin()
{
try {
- Piwik_UsersManager_API::updateUser( "lolgin", "password");
+ Piwik_UsersManager_API::getInstance()->updateUser( "lolgin", "password");
}
catch (Exception $expected) {
$this->assertPattern("(UsersManager_ExceptionUserDoesNotExist)", $expected->getMessage());
@@ -867,9 +868,9 @@ class Test_Piwik_UsersManager extends Test_Database
'email'=>"test@test.com",
'alias'=>"alias");
- Piwik_UsersManager_API::addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
+ Piwik_UsersManager_API::getInstance()->addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
- Piwik_UsersManager_API::updateUser( $login, "passowordOK");
+ Piwik_UsersManager_API::getInstance()->updateUser( $login, "passowordOK");
$this->_checkUserHasNotChanged($user, "passowordOK");
}
@@ -886,9 +887,9 @@ class Test_Piwik_UsersManager extends Test_Database
'email'=>"test@test.com",
'alias'=>"alias");
- Piwik_UsersManager_API::addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
+ Piwik_UsersManager_API::getInstance()->addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
- Piwik_UsersManager_API::updateUser( $login, "passowordOK", null, "newalias");
+ Piwik_UsersManager_API::getInstance()->updateUser( $login, "passowordOK", null, "newalias");
$this->_checkUserHasNotChanged($user, "passowordOK", null, "newalias");
}
@@ -905,9 +906,9 @@ class Test_Piwik_UsersManager extends Test_Database
'email'=>"test@test.com",
'alias'=>"alias");
- Piwik_UsersManager_API::addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
+ Piwik_UsersManager_API::getInstance()->addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
- Piwik_UsersManager_API::updateUser( $login, "passowordOK", "email@geaga.com");
+ Piwik_UsersManager_API::getInstance()->updateUser( $login, "passowordOK", "email@geaga.com");
$this->_checkUserHasNotChanged($user, "passowordOK", "email@geaga.com");
}
@@ -950,9 +951,9 @@ class Test_Piwik_UsersManager extends Test_Database
'email'=>"test@test.com",
'alias'=>"alias");
- Piwik_UsersManager_API::addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
+ Piwik_UsersManager_API::getInstance()->addUser($user['login'],$user['password'] ,$user['email'] ,$user['alias'] );
- Piwik_UsersManager_API::updateUser( $login, "passowordOK", "email@geaga.com", "NEW ALIAS");
+ Piwik_UsersManager_API::getInstance()->updateUser( $login, "passowordOK", "email@geaga.com", "NEW ALIAS");
$this->_checkUserHasNotChanged($user, "passowordOK", "email@geaga.com", "NEW ALIAS");
}
diff --git a/plugins/VisitFrequency/API.php b/plugins/VisitFrequency/API.php
index 8e770d9007..1b7e43d4a9 100644
--- a/plugins/VisitFrequency/API.php
+++ b/plugins/VisitFrequency/API.php
@@ -54,7 +54,7 @@ class Piwik_VisitFrequency_API
$dataTable = $archive->getDataTableFromNumeric($toFetch);
if($bounceRateReturningRequested !== false)
{
- $dataTable->filter('ColumnCallbackAddColumnPercentage', array('bounce_count_returning', 'bounce_rate_returning', 'nb_visits_returning', 0));
+ $dataTable->filter('ColumnCallbackAddColumnPercentage', array('bounce_rate_returning', 'bounce_count_returning', 'nb_visits_returning', 0));
$dataTable->deleteColumns($toFetch);
}
return $dataTable;
diff --git a/plugins/VisitFrequency/VisitFrequency.php b/plugins/VisitFrequency/VisitFrequency.php
index ccd83d0662..5dcdfeb581 100644
--- a/plugins/VisitFrequency/VisitFrequency.php
+++ b/plugins/VisitFrequency/VisitFrequency.php
@@ -19,11 +19,10 @@ class Piwik_VisitFrequency extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Visits Frequency',
- 'description' => 'Reports various statistics about the Returning Visitor versus the First time visitor.',
+ 'description' => Piwik_Translate('VisitFrequency_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
}
@@ -47,7 +46,7 @@ class Piwik_VisitFrequency extends Piwik_Plugin
function addMenu()
{
- Piwik_AddMenu('General_Visitors', 'VisitFrequency_SubmenuFrequency', array('module' => 'VisitFrequency'));
+ Piwik_AddMenu('General_Visitors', 'VisitFrequency_SubmenuFrequency', array('module' => 'VisitFrequency', 'action' => 'index'));
}
function archivePeriod( $notification )
@@ -67,6 +66,7 @@ class Piwik_VisitFrequency extends Piwik_Plugin
function archiveDay($notification)
{
+ /* @var $archiveProcessing Piwik_ArchiveProcessing */
$archiveProcessing = $notification->getNotificationObject();
$query = "SELECT count(distinct visitor_idcookie) as nb_uniq_visitors_returning,
@@ -77,11 +77,11 @@ class Piwik_VisitFrequency extends Piwik_Plugin
sum(case visit_total_actions when 1 then 1 else 0 end) as bounce_count_returning,
sum(case visit_goal_converted when 1 then 1 else 0 end) as nb_visits_converted_returning
FROM ".$archiveProcessing->logTable."
- WHERE visit_server_date = ?
+ WHERE visit_last_action_time >= ?
+ AND visit_last_action_time <= ?
AND idsite = ?
- AND visitor_returning = 1
- GROUP BY visitor_returning";
- $row = $archiveProcessing->db->fetchRow($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ) );
+ AND visitor_returning = 1";
+ $row = $archiveProcessing->db->fetchRow($query, array( $archiveProcessing->getStartDatetimeUTC(), $archiveProcessing->getEndDatetimeUTC(), $archiveProcessing->idsite ) );
if($row === false || $row === null)
{
diff --git a/plugins/VisitFrequency/templates/index.tpl b/plugins/VisitFrequency/templates/index.tpl
index ec4664d310..1d7e483157 100644
--- a/plugins/VisitFrequency/templates/index.tpl
+++ b/plugins/VisitFrequency/templates/index.tpl
@@ -2,7 +2,7 @@
<script type="text/javascript" src="plugins/CoreHome/templates/sparkline.js"></script>
<a name="evolutionGraph" graphId="VisitFrequencygetEvolutionGraph"></a>
-<h2>{'VisitFrequency_Evolution'|translate}</h2>
+<h2>{'VisitFrequency_ColumnReturningVisits'|translate}</h2>
{$graphEvolutionVisitFrequency}
<br />
diff --git a/plugins/VisitTime/Controller.php b/plugins/VisitTime/Controller.php
index 7053c9d545..b49f35452f 100644
--- a/plugins/VisitTime/Controller.php
+++ b/plugins/VisitTime/Controller.php
@@ -16,7 +16,7 @@
*/
class Piwik_VisitTime_Controller extends Piwik_Controller
{
- function index()
+ public function index()
{
$view = Piwik_View::factory('index');
$view->dataTableVisitInformationPerLocalTime = $this->getVisitInformationPerLocalTime(true);
@@ -24,7 +24,7 @@ class Piwik_VisitTime_Controller extends Piwik_Controller
echo $view->render();
}
- function getVisitInformationPerServerTime( $fetch = false)
+ public function getVisitInformationPerServerTime( $fetch = false)
{
$view = Piwik_ViewDataTable::factory( 'graphVerticalBar');
$view->init( $this->pluginName, __FUNCTION__, "VisitTime.getVisitInformationPerServerTime" );
@@ -42,7 +42,7 @@ class Piwik_VisitTime_Controller extends Piwik_Controller
return $this->renderView($view, $fetch);
}
- function getVisitInformationPerLocalTime( $fetch = false)
+ public function getVisitInformationPerLocalTime( $fetch = false)
{
$view = Piwik_ViewDataTable::factory( 'graphVerticalBar');
$view->init( $this->pluginName, __FUNCTION__, "VisitTime.getVisitInformationPerLocalTime" );
diff --git a/plugins/VisitTime/VisitTime.php b/plugins/VisitTime/VisitTime.php
index d565a3fb91..510a7f7ffd 100644
--- a/plugins/VisitTime/VisitTime.php
+++ b/plugins/VisitTime/VisitTime.php
@@ -19,11 +19,10 @@ class Piwik_VisitTime extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Visits Time',
- 'description' => 'Reports the Local and Server time. Server time information can be useful to schedule a maintenance on the Website.',
+ 'description' => Piwik_Translate('VisitTime_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
}
@@ -35,6 +34,7 @@ class Piwik_VisitTime extends Piwik_Plugin
'ArchiveProcessing_Period.compute' => 'archivePeriod',
'WidgetsList.add' => 'addWidgets',
'Menu.add' => 'addMenu',
+ 'Goals.getAvailableGoalSegments' => 'addGoalSegments',
);
return $hooks;
}
@@ -47,9 +47,20 @@ class Piwik_VisitTime extends Piwik_Plugin
function addMenu()
{
- Piwik_AddMenu('General_Visitors', 'VisitTime_SubmenuTimes', array('module' => 'VisitTime'));
+ Piwik_AddMenu('General_Visitors', 'VisitTime_SubmenuTimes', array('module' => 'VisitTime', 'action' => 'index'));
}
+ function addGoalSegments( $notification )
+ {
+ $segments =& $notification->getNotificationObject();
+ $segments[] = array(
+ 'group' => Piwik_Translate('VisitTime_ColumnServerTime'),
+ 'name' => Piwik_Translate('VisitTime_ColumnServerTime'),
+ 'module' => 'VisitTime',
+ 'action' => 'getVisitInformationPerServerTime',
+ );
+ }
+
function archivePeriod( $notification )
{
$archiveProcessing = $notification->getNotificationObject();
@@ -73,16 +84,37 @@ class Piwik_VisitTime extends Piwik_Plugin
$labelSQL = "HOUR(visitor_localtime)";
$this->interestByLocalTime = $archiveProcessing->getArrayInterestForLabel($labelSQL);
- $labelSQL = "HOUR(visit_first_action_time)";
+ $labelSQL = "HOUR(visit_last_action_time)";
$this->interestByServerTime = $archiveProcessing->getArrayInterestForLabel($labelSQL);
+ $this->interestByServerTime = $this->convertServerTimeToLocalTimezone($this->interestByServerTime, $archiveProcessing);
+ }
+
+ protected function convertServerTimeToLocalTimezone($interestByServerTime, $archiveProcessing)
+ {
+ $date = Piwik_Date::factory($archiveProcessing->getStartDatetimeUTC())->toString();
+ $timezone = $archiveProcessing->site->getTimezone();
+ $visitsByHourTz = array();
+ foreach($interestByServerTime as $hour => $stats)
+ {
+ $datetime = $date . ' '.$hour.':00:00';
+ $hourInTz = (int)Piwik_Date::factory($datetime, $timezone)->toString('H');
+ $visitsByHourTz[$hourInTz] = $stats;
+ }
+ return $visitsByHourTz;
}
protected function archiveDayAggregateGoals($archiveProcessing)
{
$query = $archiveProcessing->queryConversionsBySingleSegment("HOUR(server_time)");
+ $goalByServerTime = array();
while($row = $query->fetch())
{
- $this->interestByServerTime[$row['label']][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getGoalRowFromQueryRow($row);
+ $goalByServerTime[$row['label']][$row['idgoal']] = $archiveProcessing->getGoalRowFromQueryRow($row);
+ }
+ $goalByServerTime = $this->convertServerTimeToLocalTimezone($goalByServerTime, $archiveProcessing);
+ foreach($goalByServerTime as $hour => $goals)
+ {
+ $this->interestByServerTime[$hour][Piwik_Archive::INDEX_GOALS] = $goals;
}
$archiveProcessing->enrichConversionsByLabelArray($this->interestByServerTime);
}
diff --git a/plugins/VisitorGenerator/Controller.php b/plugins/VisitorGenerator/Controller.php
new file mode 100644
index 0000000000..cac81633d3
--- /dev/null
+++ b/plugins/VisitorGenerator/Controller.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik_Plugin
+ * @package Piwik_VisitorGenerator
+ */
+
+/**
+ *
+ * @package Piwik_VisitorGenerator
+ */
+class Piwik_VisitorGenerator_Controller extends Piwik_Controller {
+
+ public function index() {
+ Piwik::checkUserIsSuperUser();
+
+ $sitesList = Piwik_SitesManager_API::getInstance()->getSitesWithAdminAccess();
+
+ $view = Piwik_View::factory('index');
+ $this->setGeneralVariablesView($view);
+ $view->assign('sitesList', $sitesList);
+
+ $view->menu = Piwik_GetAdminMenu();
+ echo $view->render();
+ }
+
+ public function generate() {
+ // Only admin is allowed to do this!
+ Piwik::checkUserIsSuperUser();
+ $this->checkTokenInUrl();
+
+ $GET = $_GET;
+ $POST = $_POST;
+ $COOKIE = $_COOKIE;
+ $REQUEST = $_REQUEST;
+
+ if(Piwik_Common::getRequestVar('choice', 'no') != 'yes') {
+ Piwik::redirectToModule('VisitorGenerator', 'index');
+ }
+
+ $minVisitors = Piwik_Common::getRequestVar('minVisitors', 20, 'int');
+ $maxVisitors = Piwik_Common::getRequestVar('maxVisitors', 100, 'int');
+ $nbActions = Piwik_Common::getRequestVar('nbActions', 10, 'int');
+ $daysToCompute = Piwik_Common::getRequestVar('daysToCompute', 1, 'int');
+ $idSite = Piwik_Common::getRequestVar('idSite');
+ Piwik::setMaxExecutionTime(0);
+
+ $loadedPlugins = Piwik_PluginsManager::getInstance()->getLoadedPlugins();
+ $loadedPlugins = array_keys($loadedPlugins);
+ // we have to unload the Provider plugin otherwise it tries to lookup the IP for a hostname, and there is no dns server here
+ if(Piwik_PluginsManager::getInstance()->isPluginActivated('Provider')) {
+ Piwik_PluginsManager::getInstance()->unloadPlugin('Provider');
+ }
+
+ // we set the DO NOT load plugins so that the Tracker generator doesn't load the plugins we've just disabled.
+ // if for some reasons you want to load the plugins, comment this line, and disable the plugin Provider in the plugins interface
+ Piwik_PluginsManager::getInstance()->doNotLoadPlugins();
+
+ $generator = new Piwik_VisitorGenerator_Generator();
+ $generator->setMaximumUrlDepth(3);
+
+ //$generator->disableProfiler();
+ $generator->setIdSite( $idSite );
+
+ $nbActionsTotal = 0;
+ //$generator->emptyAllLogTables();
+ $generator->init();
+
+ $timer = new Piwik_Timer;
+
+ $startTime = time() - ($daysToCompute-1)*86400;
+ $dates = array();
+ while($startTime <= time()) {
+ $visitors = rand($minVisitors, $maxVisitors);
+ $actions = $nbActions;
+ $generator->setTimestampToUse($startTime);
+
+ $nbActionsTotalThisDay = $generator->generate($visitors, $actions);
+ $actionsPerVisit = round($nbActionsTotalThisDay / $visitors);
+
+ $date = array();
+ $date['visitors'] = $visitors;
+ $date['actionsPerVisit'] = $actionsPerVisit;
+ $date['startTime'] = $startTime;
+ $dates[] = $date;
+
+ $startTime += 86400;
+ $nbActionsTotal += $nbActionsTotalThisDay;
+ //sleep(1);
+ }
+
+ $generator->end();
+
+ // Recover all super globals
+ $_GET = $GET;
+ $_POST = $POST;
+ $_COOKIE = $COOKIE;
+ $_REQUEST = $REQUEST;
+
+ // Reload plugins
+ Piwik_PluginsManager::getInstance()->loadPlugins($loadedPlugins);
+
+ // Init view
+ $view = Piwik_View::factory('generate');
+ $view->menu = Piwik_GetAdminMenu();
+ $this->setGeneralVariablesView($view);
+ $view->assign('dates', $dates);
+ $view->assign('timer', $timer);
+ $view->assign('nbActionsTotal', $nbActionsTotal);
+ $view->assign('nbRequestsPerSec', round($nbActionsTotal / $timer->getTime(),0));
+ echo $view->render();
+ }
+}
diff --git a/core/Tracker/Generator.php b/plugins/VisitorGenerator/Generator.php
index 7a6dfdfe21..9b32a83799 100644
--- a/core/Tracker/Generator.php
+++ b/plugins/VisitorGenerator/Generator.php
@@ -6,8 +6,8 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
*
- * @category Piwik
- * @package Piwik
+ * @category Piwik_Plugin
+ * @package Piwik_VisitorGenerator
*/
/**
@@ -31,13 +31,12 @@
* - action_name
* - HTML title
*
- * @package Piwik
- * @subpackage Piwik_Tracker
+ * @package Piwik_VisitorGenerator
*
- * "Le Generator, il est trop Fort!"
- * - Random fan
+ * "Le Generator, il est trop Fort!"
+ * - Random fan
*/
-class Piwik_Tracker_Generator
+class Piwik_VisitorGenerator_Generator
{
/**
* GET parameters array of values to be used for the current visit
@@ -200,9 +199,9 @@ class Piwik_Tracker_Generator
public function emptyAllLogTables()
{
$db = Zend_Registry::get('db');
- $db->query('TRUNCATE TABLE '.Piwik::prefixTable('log_action'));
- $db->query('TRUNCATE TABLE '.Piwik::prefixTable('log_visit'));
- $db->query('TRUNCATE TABLE '.Piwik::prefixTable('log_link_visit_action'));
+ $db->query('TRUNCATE TABLE '.Piwik_Common::prefixTable('log_action'));
+ $db->query('TRUNCATE TABLE '.Piwik_Common::prefixTable('log_visit'));
+ $db->query('TRUNCATE TABLE '.Piwik_Common::prefixTable('log_link_visit_action'));
}
/**
@@ -252,6 +251,9 @@ class Piwik_Tracker_Generator
}
mt_srand(make_seed());
+ // set rec=1 parameter, required as of 0.5.5 in order to force the request to be recorded
+ $this->setCurrentRequest('rec', 1);
+
/*
* Sets values for: resolutions, colors, idSite, times
*/
@@ -293,7 +295,7 @@ class Piwik_Tracker_Generator
*/
// we load some real referers to be used by the generator
$referers = array();
- require_once PIWIK_INCLUDE_PATH . '/misc/generateVisitsData/Referers.php';
+ require_once PIWIK_INCLUDE_PATH . '/plugins/VisitorGenerator/data/Referers.php';
$this->addParam('urlref',$referers);
@@ -302,8 +304,8 @@ class Piwik_Tracker_Generator
// load some user agent and accept language
$userAgent = $acceptLanguages = array();
- require_once PIWIK_INCLUDE_PATH . '/misc/generateVisitsData/UserAgent.php';
- require_once PIWIK_INCLUDE_PATH . '/misc/generateVisitsData/AcceptLanguage.php';
+ require_once PIWIK_INCLUDE_PATH . '/plugins/VisitorGenerator/data/UserAgent.php';
+ require_once PIWIK_INCLUDE_PATH . '/plugins/VisitorGenerator/data/AcceptLanguage.php';
$this->userAgents=$userAgent;
$this->acceptLanguage=$acceptLanguages;
}
@@ -321,7 +323,7 @@ class Piwik_Tracker_Generator
{
if($this->reinitProfilingAtEveryRequest)
{
- $all = Piwik_Query('TRUNCATE TABLE '.Piwik::prefixTable('log_profiling').'' );
+ $all = Piwik_Query('TRUNCATE TABLE '.Piwik_Common::prefixTable('log_profiling').'' );
}
}
}
@@ -342,7 +344,7 @@ class Piwik_Tracker_Generator
for($i = 0; $i < $nbVisitors; $i++)
{
$nbActions = mt_rand(1, $nbActionsMaxPerVisit);
- Piwik_Tracker_Generator_Visit::setTimestampToUse($this->getTimestampToUse());
+ Piwik_VisitorGenerator_Visit::setTimestampToUse($this->getTimestampToUse());
$this->generateNewVisit();
for($j = 1; $j <= $nbActions; $j++)
@@ -614,7 +616,7 @@ class Piwik_Tracker_Generator
protected function saveVisit()
{
$this->setFakeRequest();
- $process = new Piwik_Tracker_Generator_Tracker();
+ $process = new Piwik_VisitorGenerator_Tracker();
$process->main();
unset($process);
}
diff --git a/core/Tracker/Generator/Tracker.php b/plugins/VisitorGenerator/Tracker.php
index 92bd002d59..0bc70796a9 100644
--- a/core/Tracker/Generator/Tracker.php
+++ b/plugins/VisitorGenerator/Tracker.php
@@ -6,8 +6,8 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
*
- * @category Piwik
- * @package Piwik
+ * @category Piwik_Plugin
+ * @package Piwik_VisitorGenerator
*/
/**
@@ -16,10 +16,9 @@
* - doesn't print the 1pixel transparent GIF at the end of the visit process
* - overwrite the Tracker Visit object to use so we use our own Tracker_visit @see Piwik_Tracker_Generator_Visit
*
- * @package Piwik
- * @subpackage Piwik_Tracker
+ * @package Piwik_VisitorGenerator
*/
-class Piwik_Tracker_Generator_Tracker extends Piwik_Tracker
+class Piwik_VisitorGenerator_Tracker extends Piwik_Tracker
{
/**
* Does nothing instead of sending headers
@@ -36,13 +35,14 @@ class Piwik_Tracker_Generator_Tracker extends Piwik_Tracker
}
/**
- * Returns our 'generator home made' Piwik_Tracker_Generator_Visit object.
+ * Returns our 'generator home made' Piwik_VisitorGenerator_Visit object.
*
- * @return Piwik_Tracker_Generator_Visit
+ * @return Piwik_VisitorGenerator_Visit
*/
protected function getNewVisitObject()
{
- $visit = new Piwik_Tracker_Generator_Visit();
+ $visit = new Piwik_VisitorGenerator_Visit();
+ $visit->generateTimestamp();
return $visit;
}
diff --git a/core/Tracker/Generator/Visit.php b/plugins/VisitorGenerator/Visit.php
index 2937ebfe0d..4aa41adcd0 100644
--- a/core/Tracker/Generator/Visit.php
+++ b/plugins/VisitorGenerator/Visit.php
@@ -6,18 +6,17 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id$
*
- * @category Piwik
- * @package Piwik
+ * @category Piwik_Plugin
+ * @package Piwik_VisitorGenerator
*/
/**
* Fake Piwik_Tracker_Visit class that overwrite all the Time related method to be able
* to setup a given timestamp for the generated visitor and actions.
*
- * @package Piwik
- * @subpackage Piwik_Tracker
+ * @package Piwik_VisitorGenerator
*/
-class Piwik_Tracker_Generator_Visit extends Piwik_Tracker_Visit
+class Piwik_VisitorGenerator_Visit extends Piwik_Tracker_Visit
{
static protected $timestampToUse;
@@ -32,11 +31,15 @@ class Piwik_Tracker_Generator_Visit extends Piwik_Tracker_Visit
protected function getCurrentTimestamp()
{
- self::$timestampToUse = max(@$this->visitorInfo['visit_last_action_time'],self::$timestampToUse);
- self::$timestampToUse += mt_rand(4,1840);
return self::$timestampToUse;
}
+ public function generateTimestamp()
+ {
+ self::$timestampToUse = max(@$this->visitorInfo['visit_last_action_time'],self::$timestampToUse);
+ self::$timestampToUse += mt_rand(4,1840);
+ }
+
protected function updateCookie()
{
@parent::updateCookie();
diff --git a/plugins/VisitorGenerator/VisitorGenerator.php b/plugins/VisitorGenerator/VisitorGenerator.php
new file mode 100644
index 0000000000..ee13df4b32
--- /dev/null
+++ b/plugins/VisitorGenerator/VisitorGenerator.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik_Plugin
+ * @package Piwik_VisitorGenerator
+ */
+
+/**
+ *
+ * @package Piwik_VisitorGenerator
+ */
+class Piwik_VisitorGenerator extends Piwik_Plugin {
+
+ public function getInformation() {
+ $info = array(
+ 'description' => Piwik_Translate('VisitorGenerator_PluginDescription'),
+ 'author' => 'Piwik',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
+ );
+ return $info;
+ }
+
+ public function getListHooksRegistered() {
+ return array(
+ 'AdminMenu.add' => 'addMenu',
+ );
+ }
+
+ public function addMenu() {
+ Piwik_AddAdminMenu(
+ 'VisitorGenerator_VisitorGenerator',
+ array('module' => 'VisitorGenerator', 'action' => 'index'),
+ Piwik::isUserIsSuperUser(),
+ $order = 10
+ );
+ }
+}
+?>
diff --git a/misc/generateVisitsData/AcceptLanguage.php b/plugins/VisitorGenerator/data/AcceptLanguage.php
index 4994eee82b..49dde7c841 100644
--- a/misc/generateVisitsData/AcceptLanguage.php
+++ b/plugins/VisitorGenerator/data/AcceptLanguage.php
@@ -1,4 +1,20 @@
<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik_Plugin
+ * @package Piwik_VisitorGenerator
+ */
+
+/**
+ * Accept-Language: strings
+ *
+ * @package Piwik_VisitorGenerator
+ */
$acceptLanguages = array(
"fr",
"fr,fr-fr;q=0.8,en-us",
diff --git a/misc/generateVisitsData/Referers.php b/plugins/VisitorGenerator/data/Referers.php
index 8a1a4c60b7..3d0086d850 100644
--- a/misc/generateVisitsData/Referers.php
+++ b/plugins/VisitorGenerator/data/Referers.php
@@ -1,4 +1,20 @@
<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik_Plugin
+ * @package Piwik_VisitorGenerator
+ */
+
+/**
+ * Referer: strings
+ *
+ * @package Piwik_VisitorGenerator
+ */
$referers = array(
"http://www.google.fr/search?hl=fr&q=statistique langues internet&btnG=Recherche Google&meta=",
"http://annusiteperso.free.fr/",
diff --git a/misc/generateVisitsData/UserAgent.php b/plugins/VisitorGenerator/data/UserAgent.php
index 433e74bcf3..b5f019a482 100644
--- a/misc/generateVisitsData/UserAgent.php
+++ b/plugins/VisitorGenerator/data/UserAgent.php
@@ -1,4 +1,20 @@
<?php
+/**
+ * Piwik - Open source web analytics
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
+ * @version $Id$
+ *
+ * @category Piwik_Plugin
+ * @package Piwik_VisitorGenerator
+ */
+
+/**
+ * User-Agent: strings
+ *
+ * @package Piwik_VisitorGenerator
+ */
$userAgent = array(
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
"Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0 )",
diff --git a/plugins/VisitorGenerator/templates/generate.tpl b/plugins/VisitorGenerator/templates/generate.tpl
new file mode 100644
index 0000000000..a4063f25b9
--- /dev/null
+++ b/plugins/VisitorGenerator/templates/generate.tpl
@@ -0,0 +1,30 @@
+{assign var=showSitesSelection value=false}
+{assign var=showPeriodSelection value=false}
+{include file="CoreAdminHome/templates/header.tpl"}
+
+<h2>{'VisitorGenerator_VisitorGenerator'|translate}</h2>
+
+<table class="adminTable adminTableNoBorder" style="width: 600px;">
+<thead>
+ <tr>
+ <th>{'VisitorGenerator_Visitors'|translate}</th>
+ <th>{'VisitorGenerator_ActionsPerVisit'|translate}</th>
+ <th>{'VisitorGenerator_Date'|translate}</th>
+ </tr>
+</thead>
+<tbody>
+{foreach from=$dates item=date}
+ <tr>
+ <td>{$date.visitors}</td>
+ <td>{$date.actionsPerVisit}</td>
+ <td>{$date.startTime|date_format:"%Y-%m-%d"}</td>
+ </tr>
+{/foreach}
+</tbody>
+</table>
+
+<p>{'VisitorGenerator_NbActions'|translate}: {$nbActionsTotal}<br />
+{'VisitorGenerator_NbRequestsPerSec'|translate}: {$nbRequestsPerSec}<br />
+{$timer}</p>
+
+{include file="CoreAdminHome/templates/footer.tpl"} \ No newline at end of file
diff --git a/plugins/VisitorGenerator/templates/index.tpl b/plugins/VisitorGenerator/templates/index.tpl
new file mode 100644
index 0000000000..f54349b472
--- /dev/null
+++ b/plugins/VisitorGenerator/templates/index.tpl
@@ -0,0 +1,45 @@
+{assign var=showSitesSelection value=false}
+{assign var=showPeriodSelection value=false}
+{include file="CoreAdminHome/templates/header.tpl"}
+
+<h2>{'VisitorGenerator_VisitorGenerator'|translate}</h2>
+<p>{'VisitorGenerator_PluginDescription'|translate}</p>
+
+<form method="POST" action="{url module=VisitorGenerator action=generate}">
+<table class="adminTable adminTableNoBorder" style="width: 600px;">
+<tr>
+ <td><label for="idSite">{'VisitorGenerator_SelectWebsite'|translate}</label></td>
+ <td><select name="idSite">
+ {foreach from=$sitesList item=site}
+ <option value="{$site.idsite}">{$site.name}</option>
+ {/foreach}
+ </select></td>
+</tr>
+<tr>
+ <td><label for="minVisitors">{'VisitorGenerator_MinVisitors'|translate}</label></td>
+ <td><input type="text" value="20" name="minVisitors" /></td>
+</tr>
+<tr>
+ <td><label for="maxVisitors">{'VisitorGenerator_MaxVisitors'|translate}</label></td>
+ <td><input type="text" value="100" name="maxVisitors" /></td>
+</tr>
+<tr>
+ <td><label for="nbActions">{'VisitorGenerator_NbActions'|translate}</label></td>
+ <td><input type="text" value="10" name="nbActions" /></td>
+</tr>
+<tr>
+ <td><label for="daysToCompute">{'VisitorGenerator_DaysToCompute'|translate}</label></td>
+ <td><input type="text" value="1" name="daysToCompute" /></td>
+</tr>
+</table>
+<p>{'VisitorGenerator_Warning'|translate}<br />
+{'VisitorGenerator_NotReversible'|translate:'<b>':'</b>'}<br /><br />
+{'VisitorGenerator_AreYouSure'|translate}<br />
+</p>
+<input type="checkbox" name="choice" id="choice" value="yes" /> <label for="choice">{'VisitorGenerator_ChoiceYes'|translate}</label>
+<br />
+<input type="hidden" value="{$token_auth}" name="token_auth" />
+<input type="submit" value="{'VisitorGenerator_Submit'|translate}" name="submit" class="submit" />
+</form>
+
+{include file="CoreAdminHome/templates/footer.tpl"} \ No newline at end of file
diff --git a/plugins/VisitorInterest/VisitorInterest.php b/plugins/VisitorInterest/VisitorInterest.php
index 2379972407..ee4fdbd3f2 100644
--- a/plugins/VisitorInterest/VisitorInterest.php
+++ b/plugins/VisitorInterest/VisitorInterest.php
@@ -19,11 +19,10 @@ class Piwik_VisitorInterest extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Visitors Interest',
- 'description' => 'Reports about the Visitor Interest: number of pages viewed, time spent on the Website.',
+ 'description' => Piwik_Translate('VisitorInterest_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
@@ -74,7 +73,7 @@ class Piwik_VisitorInterest extends Piwik_Plugin
function addMenu()
{
Piwik_RenameMenuEntry('General_Visitors', 'VisitFrequency_SubmenuFrequency',
- 'General_Visitors', 'VisitorInterest_SubmenuFrequencyLoyalty' );
+ 'General_Visitors', 'VisitorInterest_Engagement' );
}
function postLoad()
@@ -159,13 +158,13 @@ class Piwik_VisitorInterest extends Piwik_Plugin
return $table;
}
- public function headerVisitsFrequency($notification)
+ static public function headerVisitsFrequency($notification)
{
$out =& $notification->getNotificationObject();
$out = '<div id="leftcolumn">';
}
- public function footerVisitsFrequency($notification)
+ static public function footerVisitsFrequency($notification)
{
$out =& $notification->getNotificationObject();
$out = '</div>
diff --git a/plugins/VisitsSummary/API.php b/plugins/VisitsSummary/API.php
index 1bf80f2e50..e3ea62e02c 100644
--- a/plugins/VisitsSummary/API.php
+++ b/plugins/VisitsSummary/API.php
@@ -55,13 +55,13 @@ class Piwik_VisitsSummary_API
$dataTable = $archive->getDataTableFromNumeric($toFetch);
if($bounceRateRequested !== false)
{
- $dataTable->filter('ColumnCallbackAddColumnPercentage', array('bounce_count', 'bounce_rate', 'nb_visits', 0));
+ $dataTable->filter('ColumnCallbackAddColumnPercentage', array('bounce_rate', 'bounce_count', 'nb_visits', 0));
$dataTable->deleteColumns($toFetch);
}
return $dataTable;
}
- protected static function getNumeric( $idSite, $period, $date, $toFetch )
+ protected function getNumeric( $idSite, $period, $date, $toFetch )
{
Piwik::checkUserHasViewAccess( $idSite );
$archive = Piwik_Archive::build($idSite, $period, $date );
@@ -71,41 +71,41 @@ class Piwik_VisitsSummary_API
public function getVisits( $idSite, $period, $date )
{
- return self::getNumeric( $idSite, $period, $date, 'nb_visits');
+ return $this->getNumeric( $idSite, $period, $date, 'nb_visits');
}
public function getUniqueVisitors( $idSite, $period, $date )
{
- return self::getNumeric( $idSite, $period, $date, 'nb_uniq_visitors');
+ return $this->getNumeric( $idSite, $period, $date, 'nb_uniq_visitors');
}
public function getActions( $idSite, $period, $date )
{
- return self::getNumeric( $idSite, $period, $date, 'nb_actions');
+ return $this->getNumeric( $idSite, $period, $date, 'nb_actions');
}
public function getMaxActions( $idSite, $period, $date )
{
- return self::getNumeric( $idSite, $period, $date, 'max_actions');
+ return $this->getNumeric( $idSite, $period, $date, 'max_actions');
}
public function getBounceCount( $idSite, $period, $date )
{
- return self::getNumeric( $idSite, $period, $date, 'bounce_count');
+ return $this->getNumeric( $idSite, $period, $date, 'bounce_count');
}
public function getVisitsConverted( $idSite, $period, $date )
{
- return self::getNumeric( $idSite, $period, $date, 'nb_visits_converted');
+ return $this->getNumeric( $idSite, $period, $date, 'nb_visits_converted');
}
public function getSumVisitsLength( $idSite, $period, $date )
{
- return self::getNumeric( $idSite, $period, $date, 'sum_visit_length');
+ return $this->getNumeric( $idSite, $period, $date, 'sum_visit_length');
}
public function getSumVisitsLengthPretty( $idSite, $period, $date )
{
- return Piwik::getPrettyTimeFromSeconds(self::getSumVisitsLength( $idSite, $period, $date ));
+ return Piwik::getPrettyTimeFromSeconds($this->getSumVisitsLength( $idSite, $period, $date ));
}
}
diff --git a/plugins/VisitsSummary/VisitsSummary.php b/plugins/VisitsSummary/VisitsSummary.php
index 6ae9228c1c..77273376ea 100644
--- a/plugins/VisitsSummary/VisitsSummary.php
+++ b/plugins/VisitsSummary/VisitsSummary.php
@@ -19,11 +19,10 @@ class Piwik_VisitsSummary extends Piwik_Plugin
public function getInformation()
{
$info = array(
- 'name' => 'Visits Summary',
- 'description' => 'Reports the general Analytics numbers: visits, unique visitors, number of actions, Bounce Rate, etc.',
+ 'description' => Piwik_Translate('VisitsSummary_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
return $info;
}
@@ -45,7 +44,7 @@ class Piwik_VisitsSummary extends Piwik_Plugin
function addMenu()
{
- Piwik_AddMenu('General_Visitors', 'VisitsSummary_SubmenuOverview', array('module' => 'VisitsSummary'), true);
+ Piwik_AddMenu('General_Visitors', 'VisitsSummary_SubmenuOverview', array('module' => 'VisitsSummary', 'action' => 'index'), true);
}
}
diff --git a/plugins/VisitsSummary/templates/sparklines.tpl b/plugins/VisitsSummary/templates/sparklines.tpl
index f8ce97cc29..8dfc316160 100644
--- a/plugins/VisitsSummary/templates/sparklines.tpl
+++ b/plugins/VisitsSummary/templates/sparklines.tpl
@@ -3,11 +3,11 @@
{if isset($urlSparklineNbUniqVisitors)}
<div class="sparkline">{sparkline src=$urlSparklineNbUniqVisitors} {'VisitsSummary_NbUniqueVisitors'|translate:"<strong>$nbUniqVisitors</strong>"}</div>
{/if}
- <div class="sparkline">{sparkline src=$urlSparklineNbActions} {'VisitsSummary_NbActions'|translate:"<strong>$nbActions</strong>"}</div>
+ <div class="sparkline">{sparkline src=$urlSparklineNbActions} {'VisitsSummary_NbActionsDescription'|translate:"<strong>$nbActions</strong>"}</div>
</div>
<div id='rightcolumn'>
<div class="sparkline">{sparkline src=$urlSparklineSumVisitLength} {assign var=sumtimeVisitLength value=$sumVisitLength|sumtime} {'VisitsSummary_TotalTime'|translate:"<strong>$sumtimeVisitLength</strong>"}</div>
<div class="sparkline">{sparkline src=$urlSparklineMaxActions} {'VisitsSummary_MaxNbActions'|translate:"<strong>$maxActions</strong>"}</div>
<div class="sparkline">{sparkline src=$urlSparklineBounceRate} {'VisitsSummary_NbVisitsBounced'|translate:"<strong>$bounceRate%</strong>"}</div>
</div>
-<div style="clear:both" /> \ No newline at end of file
+<div style="clear:both;"></div>
diff --git a/plugins/Widgetize/Controller.php b/plugins/Widgetize/Controller.php
index 8cd3b7c902..700c9885f7 100644
--- a/plugins/Widgetize/Controller.php
+++ b/plugins/Widgetize/Controller.php
@@ -41,17 +41,9 @@ class Piwik_Widgetize_Controller extends Piwik_Controller
echo $view->render();
}
- function testClearspring()
- {
- $view = Piwik_View::factory('test_widget');
- $view->url1 = Piwik_Url::getCurrentUrlWithoutQueryString().'?module=Widgetize&action=iframe&moduleToWidgetize=Referers&actionToWidgetize=getKeywords&idSite=1&period=day&date=yesterday&filter_limit=5&token_auth='.Piwik::getCurrentUserTokenAuth();
- $view->url2 = Piwik_Url::getCurrentUrlWithoutQueryString().'?module=Widgetize&action=iframe&moduleToWidgetize=VisitTime&actionToWidgetize=getVisitInformationPerServerTime&idSite=1&period=day&date=yesterday&viewDataTable=graphVerticalBar&show_footer=0&token_auth='.Piwik::getCurrentUserTokenAuth();
- $view->url3 = Piwik_Url::getCurrentUrlWithoutQueryString().'?module=Widgetize&action=iframe&moduleToWidgetize=Referers&actionToWidgetize=getKeywords&idSite=1&period=day&date=yesterday&viewDataTable=cloud&show_footer=1&filter_limit=15&show_search=false&token_auth='.Piwik::getCurrentUserTokenAuth();
- echo $view->render();
- }
-
function js()
{
+ Piwik_API_Request::reloadAuthUsingTokenAuth();
$controllerName = Piwik_Common::getRequestVar('moduleToWidgetize');
$actionName = Piwik_Common::getRequestVar('actionToWidgetize');
$parameters = array ( $fetch = true );
@@ -65,6 +57,7 @@ class Piwik_Widgetize_Controller extends Piwik_Controller
function iframe()
{
+ Piwik_API_Request::reloadAuthUsingTokenAuth();
$controllerName = Piwik_Common::getRequestVar('moduleToWidgetize');
$actionName = Piwik_Common::getRequestVar('actionToWidgetize');
$parameters = array ( $fetch = true );
diff --git a/plugins/Widgetize/Widgetize.php b/plugins/Widgetize/Widgetize.php
index 9e60096a01..cfe98e3aa1 100644
--- a/plugins/Widgetize/Widgetize.php
+++ b/plugins/Widgetize/Widgetize.php
@@ -19,11 +19,10 @@ class Piwik_Widgetize extends Piwik_Plugin
public function getInformation()
{
return array(
- 'name' => 'Widgetize your data!',
- 'description' => 'The plugin makes it very easy to export any Piwik Widget in your Blog, Website or on Igoogle and Netvibes!',
+ 'description' => Piwik_Translate('Widgetize_PluginDescription'),
'author' => 'Piwik',
- 'homepage' => 'http://piwik.org/',
- 'version' => '0.1',
+ 'author_homepage' => 'http://piwik.org/',
+ 'version' => Piwik_Version::VERSION,
);
}
}
diff --git a/plugins/Widgetize/templates/index.tpl b/plugins/Widgetize/templates/index.tpl
index f2f3573019..3e705fb001 100644
--- a/plugins/Widgetize/templates/index.tpl
+++ b/plugins/Widgetize/templates/index.tpl
@@ -1,6 +1,6 @@
{assign var=showSitesSelection value=true}
{assign var=showPeriodSelection value=true}
-{include file="CoreAdminHome/templates/header.tpl"}
+{include file="CoreHome/templates/header.tpl"}
{loadJavascriptTranslations plugins='Dashboard'}
<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/styles.css" />
@@ -8,16 +8,16 @@
<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/cloud.css" />
<link rel="stylesheet" type="text/css" href="plugins/Dashboard/templates/dashboard.css" />
-<script type="text/javascript" src="themes/default/common.js"></script>
<script type="text/javascript" src="libs/swfobject/swfobject.js"></script>
<script type="text/javascript" src="libs/jquery/tooltip/jquery.tooltip.js"></script>
<script type="text/javascript" src="libs/jquery/truncate/jquery.truncate.js"></script>
<script type="text/javascript" src="libs/jquery/jquery.scrollTo.js"></script>
+<script type="text/javascript" src="themes/default/common.js"></script>
<script type="text/javascript" src="plugins/CoreHome/templates/datatable.js"></script>
<script type="text/javascript" src="plugins/Dashboard/templates/widgetMenu.js"></script>
<script type="text/javascript" src="plugins/Widgetize/templates/widgetize.js"></script>
-<script src="http://cdn.clearspring.com/launchpad/v2/standalone.js" type="text/javascript"></script>
+
{literal}
<style>
.menu {
@@ -64,9 +64,11 @@ $(document).ready( function() {
menu.registerCallbackOnWidgetLoad( widgetized.callbackAddExportButtonsUnderWidget );
menu.registerCallbackOnMenuHover( widgetized.deleteEmbedElements );
menu.show();
+ var dashboardUrl = document.location.protocol + '//' + document.location.hostname + document.location.pathname + '?module=Widgetize&action=iframe&moduleToWidgetize=Dashboard&actionToWidgetize=index&idSite=1&period=week&date=yesterday';
$('#exportFullDashboard').html(
- widgetized.getInputFormWithHtml( 'dashboardEmbed', '<iframe src="'+document.location.protocol + '//' + document.location.hostname + document.location.pathname + '?'+'module=Widgetize&action=iframe&moduleToWidgetize=Dashboard&actionToWidgetize=index&idSite=1&period=week&date=yesterday" frameborder="0" marginheight="0" marginwidth="0" width="100%" height="100%"></iframe>')
+ widgetized.getInputFormWithHtml( 'dashboardEmbed', '<iframe src="'+ dashboardUrl +'" frameborder="0" marginheight="0" marginwidth="0" width="100%" height="100%"></iframe>')
);
+ $('#linkDashboardUrl').attr('href',dashboardUrl);
});
{/literal}
@@ -74,13 +76,18 @@ $(document).ready( function() {
<div style="max-width:980px;">
<p>With Piwik, you can export your Web Analytics reports on your blog, website, or intranet dashboard... in one click.
- If you want your widgets to be viewable by everybody, you first have to set the 'view' permissions
- to the anonymous user in the <a href='index.php?module=UsersManager'>Users Management section</a>.
- <br>Note: You can also display the full Piwik dashboard in your application or website in an Iframe.
+ <p><b>&rsaquo; Widget authentication:</b> If you want your widgets to be viewable by everybody, you first have to set the 'view' permissions
+ to the anonymous user in the <a href='index.php?module=UsersManager'>Users Management section</a>.
+ <br />Alternatively, if you are publishing widgets on a password protected or private page,
+ you don't necessarily have to allow 'anonymous' to view your reports. In this case, you can add the secret token_auth parameter (found in the <a href='{url module=API action=listAllAPI}' target='_blank'>API page</a>) in the widget URL.
+ </p>
+ <p><b>&rsaquo; Widgetize the full dashboard:</b> You can also display the full Piwik dashboard in your application or website in an IFRAME (<a href='' target='_blank' id='linkDashboardUrl'>see example</a>).
+ The date parameter can be set to a specific calendar date, "today", or "yesterday". The period parameter can be set to "day", "week", "month", or "year".
+ The language parameter can be set to the language code of a translation, such as language=fr.
For example, for idSite=1 and date=yesterday, you can write: <span id='exportFullDashboard'></span>
</p>
-
- <div id="widgetChooser">
+ <p> <b>&rsaquo; Select a report, and copy paste in your page the embed code below the widget:</b>
+ <div id="widgetChooser" style='height:600px'>
<div class="subMenu" id="sub1"></div>
<div class="subMenu" id="sub2"></div>
<div class="subMenu" id="sub3"></div>
diff --git a/plugins/Widgetize/templates/js.tpl b/plugins/Widgetize/templates/js.tpl
index 18ea5d877b..a92c76e6fc 100644
--- a/plugins/Widgetize/templates/js.tpl
+++ b/plugins/Widgetize/templates/js.tpl
@@ -1,19 +1,19 @@
{loadJavascriptTranslations disableOutputScriptTag=1 plugins='CoreHome'}
-document.write('<link rel="stylesheet" href="{$piwikUrl}themes/default/common.css">');
-document.write('<link rel="stylesheet" href="{$piwikUrl}plugins/CoreHome/templates/styles.css">');
-document.write('<link rel="stylesheet" href="{$piwikUrl}plugins/CoreHome/templates/datatable.css">');
-document.write('<link rel="stylesheet" href="{$piwikUrl}plugins/CoreHome/templates/cloud.css">');
+document.write('<link rel="stylesheet" type="text/css" href="{$piwikUrl}themes/default/common.css" />');
+document.write('<link rel="stylesheet" type="text/css" href="{$piwikUrl}plugins/CoreHome/templates/styles.css" />');
+document.write('<link rel="stylesheet" type="text/css" href="{$piwikUrl}plugins/CoreHome/templates/datatable.css" />');
+document.write('<link rel="stylesheet" type="text/css" href="{$piwikUrl}plugins/CoreHome/templates/cloud.css" />');
-document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}themes/default/common.js"></scr'+'ipt>');
-document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/swfobject/swfobject.js"></scr'+'ipt>');
-document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/jquery/jquery.js"></scr'+'ipt>');
-document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/jquery/jquery-ui.js"></scr'+'ipt>');
-document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/jquery/tooltip/jquery.tooltip.js"></scr'+'ipt>');
-document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/jquery/truncate/jquery.truncate.js"></scr'+'ipt>');
-document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}libs/javascript/sprintf.js"></scr'+'ipt>');
-document.write('<scr'+'ipt language="javascript" src="{$piwikUrl}plugins/CoreHome/templates/datatable.js"></scr'+'ipt>');
+document.write('<scr'+'ipt type="text/javascript" src="{$piwikUrl}libs/swfobject/swfobject.js"></scr'+'ipt>');
+document.write('<scr'+'ipt type="text/javascript" src="{$piwikUrl}libs/jquery/jquery.js"></scr'+'ipt>');
+document.write('<scr'+'ipt type="text/javascript" src="{$piwikUrl}libs/jquery/jquery-ui.js"></scr'+'ipt>');
+document.write('<scr'+'ipt type="text/javascript" src="{$piwikUrl}libs/jquery/tooltip/jquery.tooltip.js"></scr'+'ipt>');
+document.write('<scr'+'ipt type="text/javascript" src="{$piwikUrl}libs/jquery/truncate/jquery.truncate.js"></scr'+'ipt>');
+document.write('<scr'+'ipt type="text/javascript" src="{$piwikUrl}libs/javascript/sprintf.js"></scr'+'ipt>');
+document.write('<scr'+'ipt type="text/javascript" src="{$piwikUrl}themes/default/common.js"></scr'+'ipt>');
+document.write('<scr'+'ipt type="text/javascript" src="{$piwikUrl}plugins/CoreHome/templates/datatable.js"></scr'+'ipt>');
var content = '{$content|escape:'javascript'}';
-document.write('<scr'+'ipt language="javascript">document.write(content)</scr'+'ipt>');
+document.write('<scr'+'ipt type="text/javascript">document.write(content)</scr'+'ipt>');
diff --git a/plugins/Widgetize/templates/widgetize.js b/plugins/Widgetize/templates/widgetize.js
index e509a63cdd..5f8a3c368d 100644
--- a/plugins/Widgetize/templates/widgetize.js
+++ b/plugins/Widgetize/templates/widgetize.js
@@ -4,7 +4,7 @@ function widgetize()
this.getInputFormWithHtml = function(inputId, htmlEmbed)
{
- return '<input class="formEmbedCode" id="'+inputId+'" value="'+ htmlEmbed.replace(/"/g, '&quot;') +'" onclick="javascript:document.getElementById(\''+inputId+'\').focus();document.getElementById(\''+inputId+'\').select();" readonly="true" type="text">';
+ return '<input class="formEmbedCode" id="'+inputId+'" value="'+ htmlEmbed.replace(/"/g, '&quot;') +'" onclick="javascript:document.getElementById(\''+inputId+'\').focus();document.getElementById(\''+inputId+'\').select();" readonly="true" type="text" />';
}
this.getEmbedUrl = function( parameters, exportFormat )
@@ -84,21 +84,9 @@ function widgetize()
'</span>'+
'</div>'
);
- });
-
- // Add the Clearspring Export
- $(exportButtonsElement).append(
- '<div id="embedThisWidgetEverywhere">'+
- '<div id="exportThisWidget">'+
- '<label for="flashEmbed">&rsaquo; Export anywhere!</label>'+
- '<img src="http://cdn.clearspring.com/launchpad/static/cs_button_share1.gif">'+
- '</div>'+
- '<div id="exportThisWidgetMenu"></div>'+
- '</div>'
- );
-
+ });
+
// We then replace the div iframeDivToExport with the actual Iframe html
- // Clearspring will then build a widget that has the same html as this div
$('#iframeDivToExport')
.html(widgetIframeHtml);
@@ -107,17 +95,8 @@ function widgetize()
.parent()
.append(exportButtonsElement);
- // Call clearspring
- $Launchpad.ShowButton({
- actionElement : "exportThisWidget",
- targetElement : "exportThisWidgetMenu",
- userId : "4797da88692e4fe9",
- widgetName : widgetName + " - Piwik",
- source : "iframeDivToExport"
- });
-
// JS is buggy at least on IE
//var widgetJS = '<script type="text/javascript" src="'+ getEmbedUrl(pluginId, actionId, "js") +'"></scr'+'ipt>';
- //divEmbedThisWidget.append('<br/>Embed JS: '+ getInputFormWithHtml('javascriptEmbed', widgetJS));
+ //divEmbedThisWidget.append('<br />Embed JS: '+ getInputFormWithHtml('javascriptEmbed', widgetJS));
}
}
diff --git a/tests/all_tests.php b/tests/all_tests.php
index d16d71450f..4eaafa1a91 100644
--- a/tests/all_tests.php
+++ b/tests/all_tests.php
@@ -5,6 +5,7 @@ require_once "config_test.php";
Piwik::createConfigObject();
$databaseTestName = Zend_Registry::get('config')->database_tests->dbname;
Zend_Registry::get('config')->disableSavingConfigurationFileUpdates();
+Piwik::setMaxExecutionTime(300);
?>
<h2>Piwik unit tests</h2>
diff --git a/tests/build.xml b/tests/build.xml
index 034641e18a..df3a8939dc 100644
--- a/tests/build.xml
+++ b/tests/build.xml
@@ -2,7 +2,7 @@
<property file="build.properties" />
<property file="defaults.properties" />
-
+
<target name="chmod">
<condition property="chmodcondition">
<and>
@@ -12,26 +12,26 @@
</condition>
<antcall target="chmod-inner"/>
</target>
-
+
<target name="chmod-inner" if="chmodcondition">
-
+
<property file="${basedir}/webtest/config/webtest.properties" />
-
+
<copy file="${basedir}/webtest/chmod.php" tofile="${basedir}/../build/chmod.php" overwrite="true">
<filterset>
<filter token="PATH" value="${basedir}/../build"/>
</filterset>
</copy>
-
+
<!-- <get src="${wt.config.protocol}://${wt.config.host}:${wt.config.port}/${wt.config.basepath}/chmod.php" dest="/dev/null" ignoreerrors="true"/> -->
-
+
<exec executable="wget">
<arg value="${wt.config.protocol}://${wt.config.host}:${wt.config.port}/${wt.config.basepath}/chmod.php"/>
<arg value="--output-document=/dev/null" />
<arg value="--no-check-certificate" />
</exec>
</target>
-
+
<target name="clean">
<delete dir="${basedir}/../build" />
<delete dir="${basedir}/results" />
@@ -43,6 +43,7 @@
<fileset dir="${basedir}/..">
<include name="config/**" />
<include name="core/**" />
+ <include name="js/**" />
<include name="lang/**" />
<include name="libs/**" />
<include name="misc/**" />
@@ -56,33 +57,62 @@
</copy>
<mkdir dir="${basedir}/../build/tmp/templates_c"/>
<mkdir dir="${basedir}/../build/tmp/cache"/>
+ <mkdir dir="${basedir}/../build/tmp/latest"/>
<chmod perm="a+rw">
<dirset dir="${basedir}/../build">
<include name="config" />
<include name="tmp" />
<include name="tmp/templates_c" />
<include name="tmp/cache" />
+ <include name="tmp/latest" />
</dirset>
</chmod>
</target>
-
- <target name="process-build-resources" depends="prepare-build-filesystem">
- <copy file="${basedir}/config.ini.template.php" tofile="${basedir}/../build/config/config.ini.php" overwrite="true">
+
+ <target name="process-build-resources-pdo-mysql" depends="prepare-build-filesystem">
+ <copy file="${basedir}/config/pdo_mysql.template.php" tofile="${basedir}/../build/config/config.ini.php" overwrite="true">
<filterset>
<filtersfile file="${basedir}/build.properties"/>
</filterset>
</copy>
</target>
-
- <target name="test" depends="process-build-resources">
+
+ <target name="test-pdo-mysql" depends="process-build-resources-pdo-mysql">
+
+ <echo>PDO_MYSQL unit tests started</echo>
+
<mkdir dir="${basedir}/../build/test-results"/>
<exec executable="${php.executable}" dir="${basedir}/../build/tests" failonerror="true" failifexecutionfails="true">
<arg value="all_tests.php" />
</exec>
+
+ <echo>PDO_MYSQL unit tests finished</echo>
+
+ </target>
+
+ <target name="process-build-resources-mysqli" depends="prepare-build-filesystem">
+ <copy file="${basedir}/config/mysqli.template.php" tofile="${basedir}/../build/config/config.ini.php" overwrite="true">
+ <filterset>
+ <filtersfile file="${basedir}/build.properties"/>
+ </filterset>
+ </copy>
</target>
-
+
+ <target name="test-mysqli" depends="process-build-resources-mysqli">
+
+ <echo>MYSQLI unit tests started</echo>
+
+ <mkdir dir="${basedir}/../build/test-results"/>
+ <exec executable="${php.executable}" dir="${basedir}/../build/tests" failonerror="true" failifexecutionfails="true">
+ <arg value="all_tests.php" />
+ </exec>
+
+ <echo>MYSQLI unit tests finished</echo>
+
+ </target>
+
<target name="phpdoc">
-
+
<echo>phpDocumentor started</echo>
<delete dir="${basedir}/build/phpdocumentor-report"/>
@@ -92,27 +122,27 @@
<arg value="--useconfig"/>
<arg path="${basedir}/../misc/phpdoc-config.ini"/>
</exec>
-
+
<copy todir="${phpdocumentor.report.dir}" overwrite="true" failonerror="true" verbose="true">
<fileset dir="${basedir}/../build/documentation"/>
</copy>
-
+
<echo>phpDocumentor finished</echo>
</target>
-
+
<target name="webtest">
<delete file="${basedir}/../build/config/config.ini.php"/>
<ant antfile="${basedir}/build-canoo.xml"/>
</target>
-
+
<target name="schemaspy">
-
+
<echo>SchemaSpy started</echo>
-
+
<delete dir="${basedir}/build/schemaspy-report"/>
<mkdir dir="${basedir}/build/schemaspy-report"/>
-
+
<echo message="Generating schema for MySql" />
<java jar="${basedir}/lib/java/schemaSpy_3.1.1.jar" fork="true" failonerror="true" maxmemory="256m" dir="${basedir}">
<arg value="-t"/>
@@ -130,23 +160,23 @@
<arg value="-p"/>
<arg value="${database.main.password}"/>
</java>
-
+
<copy todir="${schemaspy.report.dir}" overwrite="true" failonerror="true" verbose="true">
<fileset dir="${basedir}/build/schemaspy-report"/>
</copy>
-
+
<echo>SchemaSpy finished</echo>
</target>
-
<target name="all">
<antcall target="chmod"/>
- <antcall target="test"/>
+ <antcall target="test-pdo-mysql"/>
+ <!-- antcall target="test-mysqli"/ -->
<antcall target="webtest"/>
<antcall target="chmod"/>
<antcall target="phpdoc"/>
<antcall target="schemaspy"/>
</target>
-
+
</project>
diff --git a/tests/config/mysqli.template.php b/tests/config/mysqli.template.php
new file mode 100644
index 0000000000..ca05bb6c93
--- /dev/null
+++ b/tests/config/mysqli.template.php
@@ -0,0 +1,30 @@
+; <?php exit; ?> DO NOT REMOVE THIS LINE
+; this file is just here for documentation purpose
+; the config.ini.php is normally created during the installation process
+; when this file is absent it triggers the Installation process
+; the config.ini.php file contains information about the super user and the database access
+
+[superuser]
+login= @superuser.loging@
+password= @superuser.password@
+email= @superuser.email@
+
+[database]
+host= @database.main.host@
+port= @database.main.port@
+username= @database.main.username@
+password= @database.main.password@
+dbname= @database.main.name@
+adapter= MYSQLI
+tables_prefix= piwik_
+schema= Myisam
+
+[database_tests]
+host= @database.test.host@
+port= @database.test.port@
+username= @database.test.username@
+password= @database.test.password@
+dbname= @database.test.name@
+adapter= MYSQLI
+tables_prefix= piwiktests_
+schema= Myisam
diff --git a/tests/config.ini.template.php b/tests/config/pdo_mysql.template.php
index 4fbbcb8cf8..96397b6393 100644
--- a/tests/config.ini.template.php
+++ b/tests/config/pdo_mysql.template.php
@@ -17,6 +17,7 @@ password= @database.main.password@
dbname= @database.main.name@
adapter= PDO_MYSQL
tables_prefix= piwik_
+schema= Myisam
[database_tests]
host= @database.test.host@
@@ -26,3 +27,4 @@ password= @database.test.password@
dbname= @database.test.name@
adapter= PDO_MYSQL
tables_prefix= piwiktests_
+schema= Myisam
diff --git a/tests/config_test.php b/tests/config_test.php
index 1251637339..c6269e344c 100644
--- a/tests/config_test.php
+++ b/tests/config_test.php
@@ -20,16 +20,16 @@ if(!defined('PIWIK_INCLUDE_SEARCH_PATH'))
}
@ini_set('include_path', PIWIK_INCLUDE_SEARCH_PATH);
@set_include_path(PIWIK_INCLUDE_SEARCH_PATH);
-
+@ini_set('memory_limit', -1);
+require_once PIWIK_INCLUDE_PATH .'/libs/upgradephp/upgrade.php';
require_once PIWIK_INCLUDE_PATH .'/core/Loader.php';
require_once 'simpletest/autorun.php';
require_once 'simpletest/mock_objects.php';
-SimpleTest :: prefer(new HtmlReporter());
+SimpleTest::prefer(new HtmlReporter());
error_reporting(E_ALL|E_NOTICE);
-//@date_default_timezone_set('Europe/London');
-@date_default_timezone_set('America/Toronto');
+@date_default_timezone_set('UTC');
require_once PIWIK_INCLUDE_PATH .'/libs/Zend/Exception.php';
require_once PIWIK_INCLUDE_PATH .'/libs/Zend/Loader.php';
@@ -43,6 +43,11 @@ function dump($var)
print("</pre>");
}
+function printDebug($text)
+{
+ return;
+}
+
require_once PIWIK_INCLUDE_PATH .'/libs/Zend/Registry.php';
require_once PIWIK_INCLUDE_PATH .'/libs/Zend/Config/Ini.php';
require_once PIWIK_INCLUDE_PATH .'/libs/Zend/Config.php';
diff --git a/tests/core/API/DocumentationGenerator.test.php b/tests/core/API/DocumentationGenerator.test.php
index 1846be3bc1..48105112f5 100644
--- a/tests/core/API/DocumentationGenerator.test.php
+++ b/tests/core/API/DocumentationGenerator.test.php
@@ -15,13 +15,12 @@ class Test_Piwik_API_DocumentationGenerator extends UnitTestCase
{
Piwik::createConfigObject();
Zend_Registry::get('config')->setTestEnvironment();
- Zend_Registry::get('config')->disableSavingConfigurationFileUpdates();
Piwik::createLogObject();
Piwik::createAccessObject();
Piwik::createDatabaseObject();
Piwik::setUserIsSuperUser();
$pluginsManager = Piwik_PluginsManager::getInstance();
- $pluginsManager->setPluginsToLoad( Zend_Registry::get('config')->Plugins->Plugins->toArray() );
+ $pluginsManager->loadPlugins( Zend_Registry::get('config')->Plugins->Plugins->toArray() );
$apiGenerator = new Piwik_API_DocumentationGenerator_CallAllMethods();
$requestUrls = $apiGenerator->getAllRequestsWithParameters();
diff --git a/tests/core/ArchiveProcessing.test.php b/tests/core/ArchiveProcessing.test.php
new file mode 100644
index 0000000000..db91b6e8df
--- /dev/null
+++ b/tests/core/ArchiveProcessing.test.php
@@ -0,0 +1,121 @@
+<?php
+if(!defined("PIWIK_PATH_TEST_TO_ROOT")) {
+ define('PIWIK_PATH_TEST_TO_ROOT', getcwd().'/../..');
+}
+if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
+{
+ require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php";
+}
+
+require_once "Database.test.php";
+class Test_Piwik_ArchiveProcessing extends Test_Database
+{
+ public function setUp()
+ {
+ parent::setUp();
+
+ // setup the access layer
+ $pseudoMockAccess = new FakeAccess;
+ FakeAccess::$superUser = true;
+ Zend_Registry::set('access', $pseudoMockAccess);
+ }
+
+
+ public function tearDown()
+ {
+ }
+
+ private function createWebsite($timezone = 'UTC')
+ {
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite(
+ "site1",
+ array("http://piwik.net"),
+ $excludedIps = "",
+ $excludedQueryParameters = "",
+ $timezone);
+ return new Piwik_Site($idsite);
+ }
+
+ private function createArchiveProcessing($periodLabel, $dateLabel, $siteTimezone)
+ {
+ $site = $this->createWebsite($siteTimezone);
+ $date = Piwik_Date::factory($dateLabel);
+ $period = Piwik_Period::factory($periodLabel, $date);
+
+ $archiveProcessing = Piwik_ArchiveProcessing::factory($periodLabel);
+ $archiveProcessing->setSite($site);
+ $archiveProcessing->setPeriod($period);
+ $archiveProcessing->init();
+ return $archiveProcessing;
+ }
+
+ // test of validity of an archive, for a month not finished
+ public function test_init_currentMonth()
+ {
+ $archiveProcessing = $this->createArchiveProcessing('month', date('Y-m-d'), 'UTC+10');
+
+ // min finished timestamp considered when looking at archive timestamp
+ $dateMinArchived = Piwik_Date::today()->setTimezone('UTC+10')->getTimestamp();
+ $this->assertEqual($archiveProcessing->getMinTimeArchivedProcessed(), $dateMinArchived);
+ $this->assertTrue($archiveProcessing->isArchiveTemporary());
+ }
+
+ // test of validity of an archive, for a month in the past
+ public function test_init_dayInPast()
+ {
+ $archiveProcessing = $this->createArchiveProcessing('day', '2010-01-01', 'UTC');
+
+ // min finished timestamp considered when looking at archive timestamp
+ $dateMinArchived = Piwik_Date::factory('2010-01-02')->getTimestamp();
+ $this->assertEqual($archiveProcessing->getMinTimeArchivedProcessed(), $dateMinArchived);
+
+ $this->assertEqual($archiveProcessing->getStartDatetimeUTC(), '2010-01-01 00:00:00');
+ $this->assertEqual($archiveProcessing->getEndDatetimeUTC(), '2010-01-01 23:59:59');
+ $this->assertFalse($archiveProcessing->isArchiveTemporary());
+ }
+
+ // test of validity of an archive, for a non UTC date in the past
+ public function test_init_dayInPast_NonUTCWebsite()
+ {
+ $timezone = 'UTC+5.5';
+ $archiveProcessing = $this->createArchiveProcessing('day', '2010-01-01', 'UTC+5.5');
+ // min finished timestamp considered when looking at archive timestamp
+ $dateMinArchived = Piwik_Date::factory('2010-01-01 18:30:00');
+ $this->assertEqual($archiveProcessing->getMinTimeArchivedProcessed(), $dateMinArchived->getTimestamp());
+
+ $this->assertEqual($archiveProcessing->getStartDatetimeUTC(), '2009-12-31 18:30:00');
+ $this->assertEqual($archiveProcessing->getEndDatetimeUTC(), '2010-01-01 18:29:59');
+ $this->assertFalse($archiveProcessing->isArchiveTemporary());
+ }
+
+ // test of validity of an archive, for today's archive
+ public function test_init_today()
+ {
+ Piwik_ArchiveProcessing::setBrowserTriggerArchiving(true);
+
+ $archiveProcessing = $this->createArchiveProcessing('day', 'today', 'UTC-1');
+
+ // we look at anything processed within the time to live range
+ $dateMinArchived = time() - Piwik_ArchiveProcessing::getTodayArchiveTimeToLive();
+ $this->assertEqual($archiveProcessing->getMinTimeArchivedProcessed(), $dateMinArchived);
+ $this->assertTrue($archiveProcessing->isArchiveTemporary());
+
+ // when browsers don't trigger archives, we force ArchiveProcessing
+ // to fetch any of the most recent archive
+ Piwik_ArchiveProcessing::setBrowserTriggerArchiving(false);
+ // see isArchivingDisabled()
+ // Running in CLI doesn't impact the time to live today's archive we are loading
+ // From CLI, we will not return data that is 'stale'
+ if(!Piwik_Common::isPhpCliMode())
+ {
+ $dateMinArchived = 0;
+ }
+ $this->assertEqual($archiveProcessing->getMinTimeArchivedProcessed(), $dateMinArchived);
+
+ $this->assertEqual($archiveProcessing->getStartDatetimeUTC(), date('Y-m-d').' 01:00:00');
+ $this->assertEqual($archiveProcessing->getEndDatetimeUTC(), date('Y-m-d', time()+86400).' 00:59:59');
+ $this->assertTrue($archiveProcessing->isArchiveTemporary());
+ }
+
+}
+
diff --git a/tests/core/Common.test.php b/tests/core/Common.test.php
index ba15c77fe3..f1526910e0 100644
--- a/tests/core/Common.test.php
+++ b/tests/core/Common.test.php
@@ -7,6 +7,9 @@ if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php";
}
+class Test_Piwik_Cookie_Mock_Class {
+}
+
require_once 'Common.php';
class Test_Piwik_Common extends UnitTestCase
{
@@ -590,7 +593,7 @@ class Test_Piwik_Common extends UnitTestCase
{
if(isset($info[2]) && $info[2] !== false)
{
- $this->assertTrue(strrpos($info[2], "{k}") !== false, "$host search URL is not defined correctly, found {$info[2]} but must contain the macro {k}");
+ $this->assertTrue(strrpos($info[2], "{k}") !== false, $host . " search URL is not defined correctly, must contain the macro {k}");
}
}
}
@@ -649,7 +652,24 @@ class Test_Piwik_Common extends UnitTestCase
// new google url formats
'http://www.google.com/url?sa=t&source=web&ct=res&cd=7&url=http%3A%2F%2Fwww.example.com%2Fmypage.htm&ei=0SjdSa-1N5O8M_qW8dQN&rct=j&q=flowers&usg=AFQjCNHJXSUh7Vw7oubPaO3tZOzz-F-u_w&sig2=X8uCFh6IoPtnwmvGMULQfw'
- => array('name' => 'Google', 'keywords' => 'flowers')
+ => array('name' => 'Google', 'keywords' => 'flowers'),
+ 'http://www.google.com/webhp?tab=mw#hl=en&source=hp&q=test+hash&btnG=Google+Search&aq=f&aqi=&aql=&oq=&fp=22b4dcbb1403dc0f'
+ => false,
+ 'http://www.google.com/#hl=en&source=hp&q=test+hash&aq=f&aqi=n1g5g-s1g1g-s1g2&aql=&oq=&fp=22b4dcbb1403dc0f'
+ => false,
+
+ // new google image format
+ 'http://www.google.com/imgres?imgurl=http://www.imagedomain.com/zoom/34782_ZOOM.jpg&imgrefurl=http://www.mydomain.com/product/Omala-Govindra-Tank-XS-Brown-and-Chile.html&usg=__BD6z_JrJRAFjScDRhj4Tp8Vm_Zo=&h=610&w=465&sz=248&hl=en&start=3&itbs=1&tbnid=aiNVNce9-ZYAPM:&tbnh=136&tbnw=104&prev=/images%3Fq%3DFull%2BSupport%2BTummy%26hl%3Den%26safe%3Doff%26sa%3DG%26gbv%3D2%26tbs%3Disch:1'
+ => array('name' => 'Google Images', 'keywords' => 'full support tummy'),
+
+ // Google CSE is not standard google
+ 'http://www.google.com/cse?cx=006944612449134755049%3Ahq5up-97k4u&cof=FORID%3A10&q=piwik&ad=w9&num=10&rurl=http%3A%2F%2Fwww.homepagle.com%2Fsearch.php%3Fcx%3D006944612449134755049%253Ahq5up-97k4u%26cof%3DFORID%253A10%26q%3D89'
+ => array('name' => 'Google Custom Search', 'keywords' => 'piwik'),
+
+ // bing image search has a special URL
+ 'http://www.bing.com/images/search?q=piwik&go=&form=QBIL'
+ => array('name' => 'Bing Images', 'keywords' => 'piwik'),
+
);
foreach($urls as $refererUrl => $expectedReturnedValue) {
@@ -658,9 +678,102 @@ class Test_Piwik_Common extends UnitTestCase
$result = $expectedReturnedValue === $returnedValue;
$this->assertTrue($result);
if(!$result) {
- echo "error in extracting from $refererUrl got ".$exported."<br>";
+ $this->fail("error in extracting from $refererUrl got ".$exported."<br>");
}
}
}
+
+ public function testUnserializeArray()
+ {
+ $a = array('value1', 'value2');
+ $as = serialize($a);
+ $expected = 'a:2:{i:0;s:6:"value1";i:1;s:6:"value2";}';
+ $this->assertEqual( $as, $expected );
+
+ $ua = Piwik_Common::unserialize_array($as);
+ $this->assertTrue( is_array($ua) && count($ua) == 2 && $ua[0] === 'value1' && $ua[1] === 'value2' );
+
+ $a = 'O:31:"Test_Piwik_Cookie_Phantom_Class":0:{}';
+ try {
+ unserialize($a);
+ $this->fail("Expected exception not raised");
+ } catch(Exception $expected) {
+ $this->pass("test: unserializing an object where class not (yet) defined<br>\n");
+ }
+
+ $ua = Piwik_Common::unserialize_array($a);
+ $this->assertEqual( $a, $ua );
+
+ $a = 'O:28:"Test_Piwik_Cookie_Mock_Class":0:{}';
+ try {
+ unserialize($a);
+ $this->pass("test: unserializing an object where class is defined<br>\n");
+ } catch(Exception $unexpected) {
+ $this->fail("Unexpected exception raised");
+ }
+
+ $ua = Piwik_Common::unserialize_array($a);
+ $this->assertEqual( $a, $ua );
+
+ $a = 'a:1:{i:0;O:28:"Test_Piwik_Cookie_Mock_Class":0:{}}';
+ try {
+ unserialize($a);
+ $this->pass("test: unserializing nested object where class is defined<br>\n");
+ } catch(Exception $unexpected) {
+ $this->fail("Unexpected exception raised");
+ }
+
+ $ua = Piwik_Common::unserialize_array($a);
+ $this->assertEqual( $a, $ua );
+
+ $a = 'a:2:{i:0;s:4:"test";i:1;O:28:"Test_Piwik_Cookie_Mock_Class":0:{}}';
+ try {
+ unserialize($a);
+ $this->pass("test: unserializing another nested object where class is defined<br>\n");
+ } catch(Exception $unexpected) {
+ $this->fail("Unexpected exception raised");
+ }
+
+ $ua = Piwik_Common::unserialize_array($a);
+ $this->assertEqual( $a, $ua );
+
+ $a = 'O:28:"Test_Piwik_Cookie_Mock_Class":1:{s:34:"'."\0".'Test_Piwik_Cookie_Mock_Class'."\0".'name";s:4:"test";}';
+ try {
+ unserialize($a);
+ $this->pass("test: unserializing object with member where class is defined<br>\n");
+ } catch(Exception $unexpected) {
+ $this->fail("Unexpected exception raised");
+ }
+
+ $ua = Piwik_Common::unserialize_array($a);
+ $this->assertEqual( $a, $ua );
+
+ $a = 'a:1:{s:4:"test";s:1:"'."\0".'";}';
+ try {
+ unserialize($a);
+ $this->pass("test: unserializing with leading null byte<br>\n");
+ } catch(Exception $unexpected) {
+ $this->fail("Unexpected exception raised");
+ }
+
+ $ua = Piwik_Common::unserialize_array($a);
+ $this->assertEqual( $a, $ua );
+
+ $a = 'a:1:{s:4:"test";s:3:"'."a\0b".'";}';
+ try {
+ unserialize($a);
+ $this->pass("test: unserializing with leading intervening byte<br>\n");
+ } catch(Exception $unexpected) {
+ $this->fail("Unexpected exception raised");
+ }
+
+ $ua = Piwik_Common::unserialize_array($a);
+ $this->assertEqual( $a, $ua );
+
+ // arrays and objects cannot be used as keys, i.e., generates "Warning: Illegal offset type ..."
+ $a = 'a:2:{i:0;a:0:{}O:28:"Test_Piwik_Cookie_Mock_Class":0:{}s:4:"test";';
+ $ua = Piwik_Common::unserialize_array($a);
+ $this->assertEqual( $a, $ua );
+ }
}
diff --git a/tests/core/DataTable.test.php b/tests/core/DataTable.test.php
index 878ca2e5ef..271535b354 100644
--- a/tests/core/DataTable.test.php
+++ b/tests/core/DataTable.test.php
@@ -70,10 +70,10 @@ class Test_Piwik_DataTable extends UnitTestCase
$table = $this->getSimpleTestDataTable();
$rowsCount = $table->getRowsCount();
- $this->assertTrue($table->getLastRow(), $table->getRowFromId(Piwik_DataTable::ID_SUMMARY_ROW));
+ $this->assertEqual($table->getLastRow(), $table->getRowFromId(Piwik_DataTable::ID_SUMMARY_ROW));
$table->deleteRow(Piwik_DataTable::ID_SUMMARY_ROW);
- $this->assertTrue($table->getLastRow(), $table->getRowFromId($rowsCount-2));
+ $this->assertEqual($table->getLastRow(), $table->getRowFromId($rowsCount-2));
}
public function test_getRowFromIdSubDataTable()
diff --git a/tests/core/DataTable/Renderer.test.php b/tests/core/DataTable/Renderer.test.php
index a170ca784b..2b84325945 100644
--- a/tests/core/DataTable/Renderer.test.php
+++ b/tests/core/DataTable/Renderer.test.php
@@ -48,7 +48,7 @@ class Test_Piwik_DataTable_Renderer extends UnitTestCase
array ( Piwik_DataTable_Row::COLUMNS => array( 'label' => 'Google&copy;', 'bool' => false, 'goals' => array('idgoal=1' => array('revenue'=> 5.5, 'nb_conversions' => 10)), 'nb_uniq_visitors' => 11, 'nb_visits' => 11, 'nb_actions' => 17, 'max_actions' => '5', 'sum_visit_length' => 517, 'bounce_count' => 9),
Piwik_DataTable_Row::METADATA => array('url' => 'http://www.google.com/display"and,properly', 'logo' => './plugins/Referers/images/searchEngines/www.google.com.png'),
),
- array ( Piwik_DataTable_Row::COLUMNS => array( 'label' => 'Yahoo!', 'bool' => true, 'nb_uniq_visitors' => 15, 'nb_visits' => 151, 'nb_actions' => 147, 'max_actions' => '50', 'sum_visit_length' => 517, 'bounce_count' => 90),
+ array ( Piwik_DataTable_Row::COLUMNS => array( 'label' => 'Yahoo!', 'nb_uniq_visitors' => 15, 'bool' => true, 'nb_visits' => 151, 'nb_actions' => 147, 'max_actions' => '50', 'sum_visit_length' => 517, 'bounce_count' => 90),
Piwik_DataTable_Row::METADATA => array('url' => 'http://www.yahoo.com', 'logo' => './plugins/Referers/images/searchEngines/www.yahoo.com.png'),
Piwik_DataTable_Row::DATATABLE_ASSOCIATED => $subDataTableForRow2,
)
@@ -127,8 +127,8 @@ class Test_Piwik_DataTable_Renderer extends UnitTestCase
</row>
<row>
<label>Yahoo!</label>
- <bool>1</bool>
<nb_uniq_visitors>15</nb_uniq_visitors>
+ <bool>1</bool>
<nb_visits>151</nb_visits>
<nb_actions>147</nb_actions>
<max_actions>50</max_actions>
@@ -215,6 +215,7 @@ class Test_Piwik_DataTable_Renderer extends UnitTestCase
function test_CSV_test1()
{
$dataTable = $this->getDataTableTest();
+
$render = new Piwik_DataTable_Renderer_Csv();
$render->setTable($dataTable);
$render->convertToUnicode = false;
@@ -286,7 +287,7 @@ Yahoo!,1,,,15,151,147,50,517,90,http://www.yahoo.com,./plugins/Referers/images/s
$render = new Piwik_DataTable_Renderer_Json();
$render->setTable($dataTable);
$render->setRenderSubTables(true);
- $expected = '[{"label":"Google&copy;","bool":false,"goals":{"idgoal=1":{"revenue":5.5,"nb_conversions":10}},"nb_uniq_visitors":11,"nb_visits":11,"nb_actions":17,"max_actions":"5","sum_visit_length":517,"bounce_count":9,"url":"http:\/\/www.google.com\/display\"and,properly","logo":".\/plugins\/Referers\/images\/searchEngines\/www.google.com.png"},{"label":"Yahoo!","bool":true,"nb_uniq_visitors":15,"nb_visits":151,"nb_actions":147,"max_actions":"50","sum_visit_length":517,"bounce_count":90,"url":"http:\/\/www.yahoo.com","logo":".\/plugins\/Referers\/images\/searchEngines\/www.yahoo.com.png","idsubdatatable":1,"subtable":[{"label":"sub1","count":1,"bool":false},{"label":"sub2","count":2,"bool":true}]}]';
+ $expected = '[{"label":"Google&copy;","bool":false,"goals":{"idgoal=1":{"revenue":5.5,"nb_conversions":10}},"nb_uniq_visitors":11,"nb_visits":11,"nb_actions":17,"max_actions":"5","sum_visit_length":517,"bounce_count":9,"url":"http:\/\/www.google.com\/display\"and,properly","logo":".\/plugins\/Referers\/images\/searchEngines\/www.google.com.png"},{"label":"Yahoo!","nb_uniq_visitors":15,"bool":true,"nb_visits":151,"nb_actions":147,"max_actions":"50","sum_visit_length":517,"bounce_count":90,"url":"http:\/\/www.yahoo.com","logo":".\/plugins\/Referers\/images\/searchEngines\/www.yahoo.com.png","idsubdatatable":1,"subtable":[{"label":"sub1","count":1,"bool":false},{"label":"sub2","count":2,"bool":true}]}]';
$rendered = $render->render();
$this->assertEqual( $expected,$rendered);
@@ -366,8 +367,8 @@ Yahoo!,1,,,15,151,147,50,517,90,http://www.yahoo.com,./plugins/Referers/images/s
1 =>
array (
'label' => 'Yahoo!',
- 'bool' => true,
'nb_uniq_visitors' => 15,
+ 'bool' => true,
'nb_visits' => 151,
'nb_actions' => 147,
'max_actions' => '50',
@@ -1120,7 +1121,7 @@ idSite,row2,15";
$expected=
-"- 1 ['visits' => 245, 'visitors' => 245] ['logo' => 'test.png'] [idsubtable = ]<br>\n- 2 ['visits' => 3] [] [idsubtable = $idsubtable1]<br>\n*- 1 ['visits' => 1] [] [idsubtable = $idsubsubtable]<br>\n**- 1 ['visits' => 2] [] [idsubtable = ]<br>\n- 3 ['visits' => 9] [] [idsubtable = $idsubtable2]<br>\n*- 1 ['visits' => 5] [] [idsubtable = ]<br>\n";
+"- 1 ['visits' => 245, 'visitors' => 245] ['logo' => 'test.png'] [idsubtable = ]<br />\n- 2 ['visits' => 3] [] [idsubtable = $idsubtable1]<br />\n*- 1 ['visits' => 1] [] [idsubtable = $idsubsubtable]<br />\n**- 1 ['visits' => 2] [] [idsubtable = ]<br />\n- 3 ['visits' => 9] [] [idsubtable = $idsubtable2]<br />\n*- 1 ['visits' => 5] [] [idsubtable = ]<br />\n";
/*
* RENDER
*/
@@ -1147,7 +1148,7 @@ idSite,row2,15";
);
- $expected="- 1 ['visits' => 245, 'visitors' => 245] ['logo' => 'test.png'] [idsubtable = ]<br>\n";
+ $expected="- 1 ['visits' => 245, 'visitors' => 245] ['logo' => 'test.png'] [idsubtable = ]<br />\n";
/*
* RENDER
diff --git a/tests/core/Database.test.php b/tests/core/Database.test.php
index 9b0e37b284..050bc8507d 100644
--- a/tests/core/Database.test.php
+++ b/tests/core/Database.test.php
@@ -14,18 +14,24 @@ class Test_Database extends UnitTestCase
{
parent::__construct( $title );
print("The test class extends Test_Database: the test Piwik database is created once in the constructor, and all tables are truncated at the end of EACH unit test method.<br>");
-
- Piwik::createConfigObject();
- Zend_Registry::get('config')->setTestEnvironment();
- Zend_Registry::get('config')->disableSavingConfigurationFileUpdates();
- Piwik::createDatabaseObject();
- Piwik::createLogObject();
-
- Piwik::dropDatabase();
- Piwik::createDatabase();
- Piwik::disconnectDatabase();
- Piwik::createDatabaseObject();
- Piwik::createTables();
+ try {
+ Piwik::createConfigObject();
+ Zend_Registry::get('config')->setTestEnvironment();
+ Piwik_Tracker_Config::getInstance()->setTestEnvironment();
+ Piwik::createDatabaseObject();
+ Piwik::createLogObject();
+
+ Piwik::dropDatabase();
+ Piwik::createDatabase();
+ Piwik::disconnectDatabase();
+ Piwik::createDatabaseObject();
+ Piwik::createTables();
+ Piwik_PluginsManager::getInstance()->installLoadedPlugins();
+ } catch(Exception $e) {
+ echo $e->getMessage();
+ echo "<br/><b>TEST INITIALIZATION FAILED!";
+ throw $e;
+ }
}
public function __destruct()
{
@@ -36,6 +42,8 @@ class Test_Database extends UnitTestCase
public function tearDown()
{
+ Piwik_Option::getInstance()->clearCache();
+ Piwik_Common::deleteAllCache();
Piwik::truncateAllTables();
}
@@ -78,9 +86,9 @@ class FakeAccess
}
}
- static public function setSuperUser()
+ static public function setSuperUser($bool = true)
{
- self::$superUser = true;
+ self::$superUser = $bool;
}
static public function reloadAccess()
@@ -94,7 +102,7 @@ class FakeAccess
}
else
{
- $websitesAccess=Piwik_SitesManager_API::getAllSitesId();
+ $websitesAccess=Piwik_SitesManager_API::getInstance()->getAllSitesId();
}
if(!is_array($idSites))
@@ -119,7 +127,7 @@ class FakeAccess
}
else
{
- $websitesAccess=Piwik_SitesManager_API::getAllSitesId();
+ $websitesAccess=Piwik_SitesManager_API::getInstance()->getAllSitesId();
}
if(!is_array($idSites))
@@ -175,7 +183,7 @@ class FakeAccess
{
if(self::$superUser)
{
- return Piwik_SitesManager_API::getAllSitesId();
+ return Piwik_SitesManager_API::getInstance()->getAllSitesId();
}
return self::$idSitesAdmin;
}
@@ -184,7 +192,7 @@ class FakeAccess
{
if(self::$superUser)
{
- return Piwik_SitesManager_API::getAllSitesId();
+ return Piwik_SitesManager_API::getInstance()->getAllSitesId();
}
return self::$idSitesView;
}
@@ -192,7 +200,7 @@ class FakeAccess
{
if(self::$superUser)
{
- return Piwik_SitesManager_API::getAllSitesId();
+ return Piwik_SitesManager_API::getInstance()->getAllSitesId();
}
return array_merge(self::$idSitesView,self::$idSitesAdmin);
}
diff --git a/tests/core/Date.test.php b/tests/core/Date.test.php
index 07983e8868..56a1f30a8f 100644
--- a/tests/core/Date.test.php
+++ b/tests/core/Date.test.php
@@ -28,13 +28,114 @@ class Test_Piwik_Date extends UnitTestCase
function test_today()
{
$date = Piwik_Date::today();
- $this->assertEqual( strtotime(date("Y-m-d "). " 00:00:00"), $date->get());
+ $this->assertEqual( strtotime(date("Y-m-d "). " 00:00:00"), $date->getTimestamp());
+
+ // test getDatetime()
+ $this->assertEqual( $date->getDatetime(), $date->getDateStartUTC());
+ $date = $date->setTime('12:00:00');
+ $this->assertEqual( $date->getDatetime(), date('Y-m-d') . ' 12:00:00');
}
+
//create today object check that timestamp is correct (midnight)
function test_yesterday()
{
$date = Piwik_Date::yesterday();
- $this->assertEqual( strtotime(date("Y-m-d",time()-86400). " 00:00:00"), $date->get());
+ $this->assertEqual( strtotime(date("Y-m-d",strtotime('-1day')). " 00:00:00"), $date->getTimestamp());
+ }
+
+ function test_factoryTimezone()
+ {
+ // now in UTC converted to UTC+10 means adding 10 hours
+ $date = Piwik_Date::factory('now', 'UTC+10');
+ $dateExpected = Piwik_Date::now()->addHour(10);
+ $this->assertEqual($date->getDatetime(), $dateExpected->getDatetime());
+
+ // Congo is in UTC+1 all year long (no DST)
+ $date = Piwik_Date::factory('now', 'Africa/Brazzaville');
+ $dateExpected = Piwik_Date::factory('now')->addHour(1);
+ $this->assertEqual($date->getDatetime(), $dateExpected->getDatetime());
+
+ // yesterday same time in Congo is the same as today in Congo - 24 hours
+ $date = Piwik_Date::factory('yesterdaySameTime', 'Africa/Brazzaville');
+ $dateExpected = Piwik_Date::factory('now', 'Africa/Brazzaville')->subHour(24);
+ $this->assertEqual($date->getDatetime(), $dateExpected->getDatetime());
+ }
+
+ function test_setTimezone_dayInUTC()
+ {
+ $date = Piwik_Date::factory('2010-01-01');
+
+ $dayStart = '2010-01-01 00:00:00';
+ $dayEnd = '2010-01-01 23:59:59';
+ $this->assertEqual($date->getDateStartUTC(), $dayStart);
+ $this->assertEqual($date->getDateEndUTC(), $dayEnd);
+
+ $date = $date->setTimezone('UTC');
+ $this->assertEqual($date->getDateStartUTC(), $dayStart);
+ $this->assertEqual($date->getDateEndUTC(), $dayEnd);
+
+ $date = $date->setTimezone('Europe/Paris');
+ $utcDayStart = '2009-12-31 23:00:00';
+ $utcDayEnd = '2010-01-01 22:59:59';
+ $this->assertEqual($date->getDateStartUTC(), $utcDayStart);
+ $this->assertEqual($date->getDateEndUTC(), $utcDayEnd);
+
+ $date = $date->setTimezone('UTC+1');
+ $utcDayStart = '2009-12-31 23:00:00';
+ $utcDayEnd = '2010-01-01 22:59:59';
+ $this->assertEqual($date->getDateStartUTC(), $utcDayStart);
+ $this->assertEqual($date->getDateEndUTC(), $utcDayEnd);
+
+ $date = $date->setTimezone('UTC-1');
+ $utcDayStart = '2010-01-01 01:00:00';
+ $utcDayEnd = '2010-01-02 00:59:59';
+ $this->assertEqual($date->getDateStartUTC(), $utcDayStart);
+ $this->assertEqual($date->getDateEndUTC(), $utcDayEnd);
+ }
+
+ function test_modifyDate_withTimezone()
+ {
+ $date = Piwik_Date::factory('2010-01-01');
+ $date = $date->setTimezone('UTC-1');
+
+ $timestamp = $date->getTimestamp();
+ $date = $date->addHour(0)->addHour(0)->addHour(0);
+ $this->assertEqual($timestamp, $date->getTimestamp());
+
+
+ $date = Piwik_Date::factory('2010-01-01')->setTimezone('Europe/Paris');
+ $dateExpected = clone $date;
+ $date = $date->addHour(2);
+ $dateExpected = $dateExpected->addHour(1)->addHour(1)->addHour(1)->subHour(1);
+ $this->assertEqual($date->getTimestamp(), $dateExpected->getTimestamp());
+ }
+
+ function test_getDateStartUTCEnd_DuringDstTimezone()
+ {
+ $date = Piwik_Date::factory('2010-03-28');
+ $parisDayStart = '2010-03-28 00:00:00';
+ $parisDayEnd = '2010-03-28 23:59:59';
+
+ $date = $date->setTimezone('Europe/Paris');
+ $utcDayStart = '2010-03-27 23:00:00';
+ $utcDayEnd = '2010-03-28 21:59:59';
+
+ $this->assertEqual($date->getDateStartUTC(), $utcDayStart);
+ $this->assertEqual($date->getDateEndUTC(), $utcDayEnd);
+ }
+
+ function test_addHour()
+ {
+ // add partial hours
+ $dayStart = '2010-03-28 00:00:00';
+ $dayExpected = '2010-03-28 05:45:00';
+ $date = Piwik_Date::factory($dayStart)->addHour(5.75);
+ $this->assertEqual($date->getDatetime(), $dayExpected);
+
+ // remove partial hours
+ $dayExpected = '2010-03-27 18:15:00';
+ $date = Piwik_Date::factory($dayStart)->subHour(5.75);
+ $this->assertEqual($date->getDatetime(), $dayExpected);
}
}
diff --git a/tests/core/Http.test.php b/tests/core/Http.test.php
new file mode 100644
index 0000000000..9ac7daabfd
--- /dev/null
+++ b/tests/core/Http.test.php
@@ -0,0 +1,52 @@
+<?php
+if(!defined("PIWIK_PATH_TEST_TO_ROOT")) {
+ define('PIWIK_PATH_TEST_TO_ROOT', getcwd().'/../..');
+}
+if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
+{
+ require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php";
+}
+class Test_Piwik_Http extends UnitTestCase
+{
+ public function test_fetchRemoteFile()
+ {
+ $methods = array(
+ 'curl', 'stream', 'socket'
+ );
+
+ $this->assertTrue( in_array(Piwik_Http::getTransportMethod(), $methods) );
+
+ foreach($methods as $method)
+ {
+ $version = '';
+ try {
+ $version = Piwik_Http::sendHttpRequestBy($method, 'http://api.piwik.org/1.0/getLatestVersion/', 5);
+ }
+ catch(Exception $e) {
+ var_dump($e->getMessage());
+ }
+
+ $this->assertTrue( preg_match('/^([0-9.]+)$/', $version) );
+ }
+
+ $destinationPath = PIWIK_USER_PATH . '/tmp/latest/LATEST';
+ try {
+ Piwik_Http::fetchRemoteFile('http://api.piwik.org/1.0/getLatestVersion/', $destinationPath, 3);
+ }
+ catch(Exception $e) {
+ var_dump($e->getMessage());
+ }
+
+ $this->assertTrue( filesize($destinationPath) > 0 );
+
+ $destinationPath = PIWIK_USER_PATH . '/tmp/latest/latest.zip';
+ try {
+ Piwik_Http::fetchRemoteFile('http://piwik.org/latest.zip', $destinationPath, 3);
+ }
+ catch(Exception $e) {
+ var_dump($e->getMessage());
+ }
+
+ $this->assertTrue( filesize($destinationPath) > 0 );
+ }
+}
diff --git a/tests/core/Period.test.php b/tests/core/Period.test.php
index 6f51fb7900..b1eabafed6 100644
--- a/tests/core/Period.test.php
+++ b/tests/core/Period.test.php
@@ -55,7 +55,6 @@ class Test_Piwik_Period extends UnitTestCase
function test_day_isFinished_today()
{
$period = new Piwik_Period_Day( Piwik_Date::today());
- $this->assertEqual( $period->isFinished(), false);
$this->assertEqual( $period->toString(), date("Y-m-d"));
$this->assertEqual( $period->getSubperiods(), array());
$this->assertEqual( $period->getNumberOfSubperiods(), 0);
@@ -65,7 +64,6 @@ class Test_Piwik_Period extends UnitTestCase
{
$period = new Piwik_Period_Day( Piwik_Date::yesterday());
- $this->assertEqual( $period->isFinished(), true);
$this->assertEqual( $period->toString(), date("Y-m-d", time()-86400));
$this->assertEqual( $period->getSubperiods(), array());
$this->assertEqual( $period->getNumberOfSubperiods(), 0);
@@ -75,7 +73,6 @@ class Test_Piwik_Period extends UnitTestCase
function test_day_isFinished_tomorrow()
{
$period = new Piwik_Period_Day( Piwik_Date::factory(date("Y-m-d",time()+86400)));
- $this->assertEqual( $period->isFinished(), false);
$this->assertEqual( $period->toString(), date("Y-m-d", time()+86400));
$this->assertEqual( $period->getSubperiods(), array());
$this->assertEqual( $period->getNumberOfSubperiods(), 0);
@@ -85,7 +82,6 @@ class Test_Piwik_Period extends UnitTestCase
function test_day_isFinished_31stfeb()
{
$period = new Piwik_Period_Day( Piwik_Date::factory("2007-02-31"));
- $this->assertEqual( $period->isFinished(), true);
$this->assertEqual( $period->toString(), "2007-03-03");
$this->assertEqual( $period->getSubperiods(), array());
$this->assertEqual( $period->getNumberOfSubperiods(), 0);
@@ -224,7 +220,6 @@ class Test_Piwik_Period extends UnitTestCase
"2006-12-31",);
$this->assertEqual( $month->toString(), $correct);
$this->assertEqual( $month->getNumberOfSubperiods(), 31);
- $this->assertEqual( $month->isFinished(), true);
}
// testing month feb leap year
function test_month_FebLeap()
@@ -262,7 +257,6 @@ class Test_Piwik_Period extends UnitTestCase
"2024-02-29",);
$this->assertEqual( $month->toString(), $correct);
$this->assertEqual( $month->getNumberOfSubperiods(), 29);
- $this->assertEqual( $month->isFinished(), false);
}
// testing month feb non-leap year
function test_month_FebNonLeap()
@@ -299,7 +293,6 @@ class Test_Piwik_Period extends UnitTestCase
"2023-02-28",);
$this->assertEqual( $month->toString(), $correct);
$this->assertEqual( $month->getNumberOfSubperiods(), 28);
- $this->assertEqual( $month->isFinished(), false);
}
// testing jan
function test_month_Jan()
@@ -339,7 +332,6 @@ class Test_Piwik_Period extends UnitTestCase
"2007-01-31",);
$this->assertEqual( $month->toString(), $correct);
$this->assertEqual( $month->getNumberOfSubperiods(), 31);
- $this->assertEqual( $month->isFinished(), true);
}
// testing month containing a time change (DST)
@@ -380,7 +372,6 @@ class Test_Piwik_Period extends UnitTestCase
"2007-03-31",);
$this->assertEqual( $month->toString(), $correct);
$this->assertEqual( $month->getNumberOfSubperiods(), 31);
- $this->assertEqual( $month->isFinished(), true);
}
function test_month_DSTChangeOct()
{
@@ -419,7 +410,6 @@ class Test_Piwik_Period extends UnitTestCase
"2017-10-31",);
$this->assertEqual( $month->toString(), $correct);
$this->assertEqual( $month->getNumberOfSubperiods(), 31);
- $this->assertEqual( $month->isFinished(), false);
}
/**
* Testing Period_Week
@@ -446,7 +436,6 @@ class Test_Piwik_Period extends UnitTestCase
"2006-01-01",);
$this->assertEqual( $week->toString(), $correct);
$this->assertEqual( $week->getNumberOfSubperiods(), 7);
- $this->assertEqual( $week->isFinished(), true);
}
// test week between 2 months Week Mai 29 To Mai 31 2006
function test_week_Between2month()
@@ -462,7 +451,6 @@ class Test_Piwik_Period extends UnitTestCase
"2006-06-04",);
$this->assertEqual( $week->toString(), $correct);
$this->assertEqual( $week->getNumberOfSubperiods(), 7);
- $this->assertEqual( $week->isFinished(), true);
}
// test week between feb and march for leap year
function test_week_febLeapyear()
@@ -479,11 +467,9 @@ class Test_Piwik_Period extends UnitTestCase
$week = new Piwik_Period_Week( Piwik_Date::factory('2023-02-27'));
$this->assertEqual( $week->toString(), $correct);
$this->assertEqual( $week->getNumberOfSubperiods(), 7);
- $this->assertEqual( $week->isFinished(), false);
$week = new Piwik_Period_Week( Piwik_Date::factory('2023-03-01'));
$this->assertEqual( $week->toString(), $correct);
$this->assertEqual( $week->getNumberOfSubperiods(), 7);
- $this->assertEqual( $week->isFinished(), false);
}
// test week between feb and march for no leap year
function test_week_febnonLeapyear()
@@ -500,11 +486,9 @@ class Test_Piwik_Period extends UnitTestCase
$week = new Piwik_Period_Week( Piwik_Date::factory('2024-02-27'));
$this->assertEqual( $week->toString(), $correct);
$this->assertEqual( $week->getNumberOfSubperiods(), 7);
- $this->assertEqual( $week->isFinished(), false);
$week = new Piwik_Period_Week( Piwik_Date::factory('2024-03-01'));
$this->assertEqual( $week->toString(), $correct);
$this->assertEqual( $week->getNumberOfSubperiods(), 7);
- $this->assertEqual( $week->isFinished(), false);
}
// test week normal middle of the month
function test_week_middleofmonth()
@@ -521,7 +505,6 @@ class Test_Piwik_Period extends UnitTestCase
$week = new Piwik_Period_Week( Piwik_Date::factory('2024-10-09'));
$this->assertEqual( $week->toString(), $correct);
$this->assertEqual( $week->getNumberOfSubperiods(), 7);
- $this->assertEqual( $week->isFinished(), false);
}
/**
@@ -548,9 +531,7 @@ class Test_Piwik_Period extends UnitTestCase
$year = new Piwik_Period_Year( Piwik_Date::factory('2024-10-09'));
$this->assertEqual( $year->getNumberOfSubperiods(), 12);
- $this->assertEqual( $year->isFinished(), false);
$this->assertEqual( $year->toString(), $correct);
-
}
// test past
@@ -573,7 +554,6 @@ class Test_Piwik_Period extends UnitTestCase
$week = new Piwik_Period_Year( Piwik_Date::factory('2000-02-15'));
$this->assertEqual( $week->getNumberOfSubperiods(), 12);
- $this->assertEqual( $week->isFinished(), true);
$this->assertEqual( $week->toString(), $correct);
}
@@ -581,7 +561,6 @@ class Test_Piwik_Period extends UnitTestCase
// test range 1
function test_range_today()
{
-
$range = new Piwik_Period_Range( 'day', 'last1' );
$today = Piwik_Date::today();
@@ -591,7 +570,21 @@ class Test_Piwik_Period extends UnitTestCase
$correct = array_reverse($correct);
$this->assertEqual( $range->getNumberOfSubperiods(), 1);
- $this->assertEqual( $range->isFinished(), false);
+ $this->assertEqual( $range->toString(), $correct);
+ }
+
+ function test_range_today_UtcPlus12()
+ {
+ // rather ugly test, UTC+23 doesn't exist, but it's a way to test that last1 in UTC+23 will be "our" UTC tomorrow
+ $range = new Piwik_Period_Range( 'day', 'last1', 'UTC+23' );
+ $today = Piwik_Date::now()->addHour(23);
+
+ $correct=array(
+ $today->toString(),
+ );
+ $correct = array_reverse($correct);
+
+ $this->assertEqual( $range->getNumberOfSubperiods(), 1);
$this->assertEqual( $range->toString(), $correct);
}
@@ -609,7 +602,6 @@ class Test_Piwik_Period extends UnitTestCase
$correct = array_reverse($correct);
$this->assertEqual( $range->getNumberOfSubperiods(), 2);
- $this->assertEqual( $range->isFinished(), false);
$this->assertEqual( $range->toString(), $correct);
}
// test range 3
@@ -627,7 +619,6 @@ class Test_Piwik_Period extends UnitTestCase
$correct = array_reverse($correct);
$this->assertEqual( $range->getNumberOfSubperiods(), 50);
- $this->assertEqual( $range->isFinished(), false);
$this->assertEqual( $range->toString(), $correct);
}
// test range 4
@@ -645,7 +636,6 @@ class Test_Piwik_Period extends UnitTestCase
$correct = array_reverse($correct);
$this->assertEqual( $range->getNumberOfSubperiods(), 3);
- $this->assertEqual( $range->isFinished(), true);
$this->assertEqual( $range->toString(), $correct);
}
@@ -662,7 +652,6 @@ class Test_Piwik_Period extends UnitTestCase
);
$this->assertEqual( $range->getNumberOfSubperiods(), count($correct));
- $this->assertEqual( $range->isFinished(), true);
$this->assertEqual( $range->toString(), $correct);
}
@@ -689,7 +678,6 @@ class Test_Piwik_Period extends UnitTestCase
);
$this->assertEqual( $range->getNumberOfSubperiods(), count($correct));
- $this->assertEqual( $range->isFinished(), true);
$this->assertEqual( $range->toString(), $correct);
}
// test range date1,date2
@@ -730,7 +718,6 @@ class Test_Piwik_Period extends UnitTestCase
);
$this->assertEqual( $range->getNumberOfSubperiods(), count($correct));
- $this->assertEqual( $range->isFinished(), true);
$this->assertEqual( $range->toString(), $correct);
}
// test range date1,date2
@@ -771,7 +758,6 @@ class Test_Piwik_Period extends UnitTestCase
),
);
$this->assertEqual( $range->getNumberOfSubperiods(), count($correct));
- $this->assertEqual( $range->isFinished(), true);
$this->assertEqual( $range->toString(), $correct);
}
// test range date1,date2
@@ -851,7 +837,6 @@ class Test_Piwik_Period extends UnitTestCase
);
$this->assertEqual( $range->getNumberOfSubperiods(), count($correct));
- $this->assertEqual( $range->isFinished(), true);
$this->assertEqual( $range->toString(), $correct);
}
@@ -874,7 +859,6 @@ class Test_Piwik_Period extends UnitTestCase
$this->assertEqual( $range->getNumberOfSubperiods(), 50);
- $this->assertEqual( $range->isFinished(), false);
$this->assertEqual( $range->toString(), $correct);
}
@@ -884,7 +868,6 @@ class Test_Piwik_Period extends UnitTestCase
$range = new Piwik_Period_Range( 'week', 'last1' );
$currentWeek = new Piwik_Period_Week(Piwik_Date::today());
$this->assertEqual( $range->getNumberOfSubperiods(), 1);
- $this->assertEqual( $range->isFinished(), false);
$this->assertEqual( $range->toString(), array($currentWeek->toString()));
}
@@ -906,7 +889,6 @@ class Test_Piwik_Period extends UnitTestCase
$correct = array_reverse($correct);
$this->assertEqual( $range->getNumberOfSubperiods(), 20);
- $this->assertEqual( $range->isFinished(), false);
$this->assertEqual( $range->toString(), $correct);
}
@@ -916,7 +898,6 @@ class Test_Piwik_Period extends UnitTestCase
$range = new Piwik_Period_Range( 'month', 'last1' );
$month = new Piwik_Period_Month(Piwik_Date::today());
$this->assertEqual( $range->getNumberOfSubperiods(), 1);
- $this->assertEqual( $range->isFinished(), false);
$this->assertEqual( $range->toString(), array($month->toString()));
}
@@ -940,7 +921,6 @@ class Test_Piwik_Period extends UnitTestCase
$this->assertEqual( $range->getNumberOfSubperiods(), 10);
- $this->assertEqual( $range->isFinished(), true);
$this->assertEqual( $range->toString(), $correct);
}
@@ -962,7 +942,6 @@ class Test_Piwik_Period extends UnitTestCase
$correct = array_reverse($correct);
$this->assertEqual( $range->getNumberOfSubperiods(), 10);
- $this->assertEqual( $range->isFinished(), false);
$this->assertEqual( $range->toString(), $correct);
}
@@ -973,7 +952,6 @@ class Test_Piwik_Period extends UnitTestCase
$range = new Piwik_Period_Range( 'year', 'last1' );
$currentYear = new Piwik_Period_Year(Piwik_Date::today());
$this->assertEqual( $range->getNumberOfSubperiods(), 1);
- $this->assertEqual( $range->isFinished(), false);
$this->assertEqual( $range->toString(), array($currentYear->toString()));
}
}
diff --git a/tests/core/Piwik.test.php b/tests/core/Piwik.test.php
index bd3431111a..3b60a6d291 100644
--- a/tests/core/Piwik.test.php
+++ b/tests/core/Piwik.test.php
@@ -45,4 +45,3 @@ class Test_Piwik extends UnitTestCase
}
}
-
diff --git a/tests/core/ReleaseCheckList.test.php b/tests/core/ReleaseCheckList.test.php
index 0ad5f8d9ab..80321507e2 100644
--- a/tests/core/ReleaseCheckList.test.php
+++ b/tests/core/ReleaseCheckList.test.php
@@ -11,6 +11,14 @@ if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
class Test_Piwik_ReleaseCheckList extends UnitTestCase
{
+ public function test_checkPatchedQuickform()
+ {
+ // we patched quickform so that it supports SELECT optgroup html tags
+ // see patch: http://pear.php.net/bugs/bug.php?id=1283&edit=12&patch=add-optgroup-support&revision=latest
+ $this->assertTrue(method_exists('HTML_QuickForm_select', '_optionToHtml'));
+ $this->assertTrue(method_exists('HTML_QuickForm_select', '_isInOptGroup'));
+ }
+
public function test_checkThatConfigurationValuesAreProductionValues()
{
$this->globalConfig = parse_ini_file(PIWIK_PATH_TEST_TO_ROOT . '/config/global.ini.php', true);
@@ -24,11 +32,24 @@ class Test_Piwik_ReleaseCheckList extends UnitTestCase
$this->checkEqual(array('Tracker' => 'record_statistics'), '1');
$this->checkEqual(array('Tracker' => 'visit_standard_length'), '1800');
$this->checkEqual(array('Tracker' => 'enable_detect_unique_visitor_using_settings'), '1');
- $this->checkEqual(array('log' => 'logger_message'), array('screen'));
+ // logging messages are disabled
+ $this->checkEqual(array('log' => 'logger_message'), '');
$this->checkEqual(array('log' => 'logger_exception'), array('screen'));
$this->checkEqual(array('log' => 'logger_error'), array('screen'));
$this->checkEqual(array('log' => 'logger_api_call'), null);
}
+
+ public function test_templatesDontContainDebug()
+ {
+ $patternFailIfFound = '{debug}';
+ $files = Piwik::globr(PIWIK_INCLUDE_PATH . '/plugins', '*.tpl');
+ foreach($files as $file)
+ {
+ $content = file_get_contents($file);
+ $this->assertFalse(strpos($content, $patternFailIfFound), 'found in '.$file);
+ }
+ }
+
private function checkEqual($key, $valueExpected)
{
$section = key($key);
@@ -70,7 +91,6 @@ class Test_Piwik_ReleaseCheckList extends UnitTestCase
function test_piwikTrackerDebugIsOff()
{
$this->assertTrue(!isset($GLOBALS['PIWIK_TRACKER_DEBUG']));
- define('PIWIK_ENABLE_TRACKING', false);
include PIWIK_PATH_TEST_TO_ROOT . "/piwik.php";
$this->assertTrue($GLOBALS['PIWIK_TRACKER_DEBUG'] === false);
}
@@ -79,7 +99,6 @@ class Test_Piwik_ReleaseCheckList extends UnitTestCase
{
Piwik::createConfigObject();
Zend_Registry::get('config')->setTestEnvironment();
- Zend_Registry::get('config')->disableSavingConfigurationFileUpdates();
$jqueryJs = file_get_contents( PIWIK_DOCUMENT_ROOT . '/libs/jquery/jquery.js', false, NULL, 0, 512 );
$this->assertTrue( preg_match('/jQuery (?:JavaScript Library )?v?([0-9.]+)/', $jqueryJs, $matches) );
diff --git a/tests/core/TablePartitioning.test.php b/tests/core/TablePartitioning.test.php
index 0c312cd8ee..f28dbc09ea 100644
--- a/tests/core/TablePartitioning.test.php
+++ b/tests/core/TablePartitioning.test.php
@@ -48,7 +48,7 @@ class Test_Piwik_TablePartitioning extends Test_Database
$this->assertTrue( in_array($tablename, $allTablesInstalled), "$tablename !==".var_export($allTablesInstalled,true));
$this->assertTrue( $tablename, $p->getTableName());
- $this->assertEqual( $tablename, (string)$p);
+ $this->assertEqual( $tablename, (string)$p->__toString());
}
// test monthly
@@ -68,7 +68,7 @@ class Test_Piwik_TablePartitioning extends Test_Database
$allTablesInstalled = Piwik::getTablesInstalled( $forceReload = true );
$this->assertTrue( in_array($tablename, $allTablesInstalled));
$this->assertTrue( $tablename, $p->getTableName());
- $this->assertEqual( $tablename, (string)$p);
+ $this->assertEqual( $tablename, (string)$p->__toString());
}
// test daily
@@ -88,7 +88,7 @@ class Test_Piwik_TablePartitioning extends Test_Database
$allTablesInstalled = Piwik::getTablesInstalled();
$this->assertTrue( in_array($tablename, $allTablesInstalled));
$this->assertTrue( $tablename, $p->getTableName());
- $this->assertEqual( $tablename, (string)$p);
+ $this->assertEqual( $tablename, (string)$p->__toString());
}
}
diff --git a/tests/core/Tracker/Action.test.php b/tests/core/Tracker/Action.test.php
index 2cc1fba216..bc2492d6b3 100644
--- a/tests/core/Tracker/Action.test.php
+++ b/tests/core/Tracker/Action.test.php
@@ -9,14 +9,133 @@ if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
require_once 'Tracker/Action.php';
require_once 'Tracker/Config.php';
-class Test_Piwik_TrackerAction extends UnitTestCase
+require_once "Database.test.php";
+
+class Test_Piwik_TrackerAction extends Test_Database
{
+ function setUp()
+ {
+ $GLOBALS['PIWIK_TRACKER_MODE'] = true;
+ parent::setUp();
+ $userFile = PIWIK_PATH_TEST_TO_ROOT . '/tests/resources/Tracker/Action.config.ini.php';
+ $config = Piwik_Tracker_Config::getInstance();
+ $config->init($userFile);
+ }
+
+ function tearDown()
+ {
+ $GLOBALS['PIWIK_TRACKER_MODE'] = false;
+ }
+
+ protected function setUpRootAccess()
+ {
+ $pseudoMockAccess = new FakeAccess;
+ FakeAccess::$superUser = true;
+ Zend_Registry::set('access', $pseudoMockAccess);
+ }
+
+ protected function getTestUrls()
+ {
+ $urls = array(
+ // a wrongly formatted url (parse_url returns false)
+ 'http:////wrongurl',
+
+ // a URL with all components
+ 'http://username:password@hostname:80/path?phpSESSID=value#anchor',
+
+ // a standard url
+ 'http://a.com/index?p1=v1',
+
+ // testing with capital parameter
+ 'http://a.com/index?p1=v1&P2=v2&p3=v3',
+
+ // testing with extra &&
+ 'http://a.com/index?p1=v1&&p2=v2&p3=v3&p4=v4&&',
+ );
+
+ return $urls;
+ }
+
+ /*
+ * No excluded query parameters specified, appart from the standard "session" parameters, always excluded
+ */
+ function test_excludeQueryParameters_none()
+ {
+ $excludedQueryParameters = '';
+ $this->setUpRootAccess();
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array('http://example.org'), $excludedIps = '', $excludedQueryParameters);
+ $urls = $this->getTestUrls();
+ foreach($urls as $url)
+ {
+ $expectedUrl = $url;
+ if($url=='http://username:password@hostname:80/path?phpSESSID=value#anchor')
+ {
+ $expectedUrl = 'http://username:password@hostname:80/path#anchor';
+ }
+
+ // the extra & are automatically cleaned up
+ if($url=='http://a.com/index?p1=v1&&p2=v2&p3=v3&p4=v4&&')
+ {
+ $expectedUrl = 'http://a.com/index?p1=v1&p2=v2&p3=v3&p4=v4';
+ }
+ $this->assertEqual($expectedUrl, Piwik_Tracker_Action::excludeQueryParametersFromUrl($url, $idsite));
+ }
+ }
+
+ /*
+ * Testing with some website specific parameters excluded
+ */
+ function test_excludeQueryParameters_siteExcluded()
+ {
+ $excludedQueryParameters = 'p4, p2';
+ $expectedUrls = array(
+ 'http:////wrongurl',
+ 'http://username:password@hostname:80/path#anchor',
+ 'http://a.com/index?p1=v1',
+ 'http://a.com/index?p1=v1&p3=v3',
+ 'http://a.com/index?p1=v1&p3=v3',
+ );
+ $this->setUpRootAccess();
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array('http://example.org'), $excludedIps = '', $excludedQueryParameters);
+ $urls = $this->getTestUrls();
+ $filteredUrls = array();
+ foreach($urls as $url)
+ {
+ $filteredUrls[] = Piwik_Tracker_Action::excludeQueryParametersFromUrl($url, $idsite);
+ }
+ $this->assertEqual($expectedUrls, $filteredUrls);
+ }
+
+ /*
+ * Testing with some website specific and some global excluded query parameters
+ */
+ function test_excludeQueryParameters_siteAndGlobalExcluded()
+ {
+ // testing also that query parameters are case insensitive
+ $excludedQueryParameters = 'P2';
+ $excludedGlobalParameters = 'blabla, P4';
+ $expectedUrls = array(
+ 'http:////wrongurl',
+ 'http://username:password@hostname:80/path#anchor',
+ 'http://a.com/index?p1=v1',
+ 'http://a.com/index?p1=v1&p3=v3',
+ 'http://a.com/index?p1=v1&p3=v3',
+ );
+ $this->setUpRootAccess();
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("site1",array('http://example.org'), $excludedIps = '', $excludedQueryParameters);
+ Piwik_SitesManager_API::getInstance()->setGlobalExcludedQueryParameters($excludedGlobalParameters);
+ $urls = $this->getTestUrls();
+ $filteredUrls = array();
+ foreach($urls as $url)
+ {
+ $filteredUrls[] = Piwik_Tracker_Action::excludeQueryParametersFromUrl($url, $idsite);
+ }
+ $this->assertEqual($expectedUrls, $filteredUrls);
+ }
+
+
function test_extractUrlAndActionNameFromRequest()
{
- $userFile = PIWIK_PATH_TEST_TO_ROOT . '/tests/resources/Tracker/Action.config.ini.php';
- $config = Piwik_Tracker_Config::getInstance();
- $config->init($userFile);
-
$action = new Test_Piwik_TrackerAction_extractUrlAndActionNameFromRequest();
$tests = array(
@@ -103,7 +222,7 @@ class Test_Piwik_TrackerAction extends UnitTestCase
// empty request
array(
'request' => array(),
- 'expected' => array( 'name' => null, 'url' => '/',
+ 'expected' => array( 'name' => null, 'url' => '',
'type' => Piwik_Tracker_Action::TYPE_ACTION_URL),
),
array(
diff --git a/tests/core/Tracker/Visit.test.php b/tests/core/Tracker/Visit.test.php
new file mode 100644
index 0000000000..4aff75d73f
--- /dev/null
+++ b/tests/core/Tracker/Visit.test.php
@@ -0,0 +1,108 @@
+<?php
+if(!defined("PIWIK_PATH_TEST_TO_ROOT")) {
+ define('PIWIK_PATH_TEST_TO_ROOT', getcwd().'/../../..');
+}
+if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
+{
+ require_once PIWIK_PATH_TEST_TO_ROOT . "/tests/config_test.php";
+}
+
+require_once 'Tracker/Visit.php';
+
+
+require_once "Database.test.php";
+class Test_Piwik_TrackerVisit extends Test_Database
+{
+ public function setUp()
+ {
+ $GLOBALS['PIWIK_TRACKER_MODE'] = true;
+ parent::setUp();
+
+ // setup the access layer
+ $pseudoMockAccess = new FakeAccess;
+ FakeAccess::$superUser = true;
+ Zend_Registry::set('access', $pseudoMockAccess);
+ }
+
+ public function tearDown()
+ {
+ $GLOBALS['PIWIK_TRACKER_MODE'] = false;
+ }
+
+ function test_isVisitorIpExcluded()
+ {
+ $excludedIps = array(
+ '12.12.12.12',
+ '13.13.13.*',
+ '14.14.*.*',
+ '15.*.*.*',
+ '255.1.1.1',
+ '255.150.150.150',
+ '155.*.*.*',
+ '255.255.100.*'
+ );
+ $visit = new Test_Piwik_TrackerVisit_public();
+ foreach($excludedIps as $idExcludedId => $excludedIp)
+ {
+ $idsite = Piwik_SitesManager_API::getInstance()->addSite("name","http://piwik.net/", $excludedIp);
+ $visit->setRequest(array('idsite' => $idsite));
+
+ // test that IPs within the range, or the given IP, are excluded
+ $ips = $this->getIpsFromWildcardIp($excludedIp);
+ foreach($ips as $testIpIsExcluded)
+ {
+ $testIpIsExcluded = ip2long($testIpIsExcluded);
+ $this->assertTrue($testIpIsExcluded !== false);
+ $testIpIsExcluded = sprintf("%u", $testIpIsExcluded);
+ $this->assertTrue($visit->public_isVisitorIpExcluded($testIpIsExcluded), long2ip($testIpIsExcluded) . " is not excluded");
+ }
+
+ // test that all other IPs (set as being exclusively out of any other IP ranges)
+ // are included in the tracking
+ foreach($excludedIps as $idIncludedIp => $includedIp)
+ {
+ if($idIncludedIp == $idExcludedId)
+ {
+ continue;
+ }
+ $ips = $this->getIpsFromWildcardIp($includedIp);
+ foreach($ips as $testIpIsIncluded)
+ {
+ $testIpIsIncluded = ip2long($testIpIsIncluded);
+ $this->assertTrue($testIpIsIncluded !== false);
+ $testIpIsIncluded = sprintf("%u", $testIpIsIncluded);
+ $this->assertFalse($visit->public_isVisitorIpExcluded($testIpIsIncluded), long2ip($testIpIsIncluded) . " is excluded by the rule ". $excludedIp);
+ }
+ }
+ }
+ }
+
+ /**
+ * Given an IP (containing wildcards or not), returns IP within the range (replacing wildcards with proper values)
+ * @param $wildcardIp 145.65.*.*
+ * @return array (145.65.1.1, 145.65.255.255, etc.)
+ */
+ private function getIpsFromWildcardIp($wildcardIp)
+ {
+ if(substr_count($wildcardIp, '*') === 0 )
+ {
+ return array($wildcardIp);
+ }
+
+ $ips = array();
+ foreach(array(1,50,100,255) as $byte)
+ {
+ $ips[] = str_replace('*', $byte, $wildcardIp);
+ }
+ return $ips;
+ }
+}
+
+
+
+class Test_Piwik_TrackerVisit_public extends Piwik_Tracker_Visit {
+ public function public_isVisitorIpExcluded( $ip )
+ {
+ return $this->isVisitorIpExcluded($ip);
+ }
+}
diff --git a/tests/core/Url.test.php b/tests/core/Url.test.php
index 06643761fc..61f32f14f7 100644
--- a/tests/core/Url.test.php
+++ b/tests/core/Url.test.php
@@ -18,7 +18,7 @@ class Test_Piwik_Url extends UnitTestCase
{
$this->assertEqual(Piwik_Url::getCurrentQueryStringWithParametersModified(array()),Piwik_Url::getCurrentQueryString() );
$this->assertEqual(Piwik_Url::getCurrentUrl(), Piwik_Url::getCurrentUrlWithoutQueryString());
- $this->assertEqual(Piwik_Url::getCurrentUrl(), Piwik_Url::getCurrentHost() . Piwik_Url::getCurrentScriptName() );
+ $this->assertEqual(Piwik_Url::getCurrentUrl(), Piwik_Url::getCurrentScheme() . '://' . Piwik_Url::getCurrentHost() . Piwik_Url::getCurrentScriptName() );
print("<br>\nPiwik_Url::getCurrentQueryStringWithParametersModified() "
. Piwik_Url::getCurrentQueryStringWithParametersModified(array()));
diff --git a/tests/javascript/assets/qunit.css b/tests/javascript/assets/qunit.css
index 4542933c55..5714bf4a59 100644
--- a/tests/javascript/assets/qunit.css
+++ b/tests/javascript/assets/qunit.css
@@ -1,17 +1,119 @@
-h1#qunit-header { padding: 15px; font-size: large; background-color: #06b; color: white; font-family: 'trebuchet ms', verdana, arial; margin: 0; }
-h1#qunit-header a { color: white; }
-h2#qunit-banner { height: 2em; border-bottom: 1px solid white; background-color: #eee; margin: 0; font-family: 'trebuchet ms', verdana, arial; }
-h2#qunit-banner.pass { background-color: green; }
-h2#qunit-banner.fail { background-color: red; }
+ol#qunit-tests {
+ font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
+ margin:0;
+ padding:0;
+ list-style-position:inside;
-h2#qunit-userAgent { padding: 10px; background-color: #eee; color: black; margin: 0; font-size: small; font-weight: normal; font-family: 'trebuchet ms', verdana, arial; font-size: 10pt; }
+ font-size: smaller;
+}
+ol#qunit-tests li{
+ padding:0.4em 0.5em 0.4em 2.5em;
+ border-bottom:1px solid #fff;
+ font-size:small;
+ list-style-position:inside;
+}
+ol#qunit-tests li ol{
+ box-shadow: inset 0px 2px 13px #999;
+ -moz-box-shadow: inset 0px 2px 13px #999;
+ -webkit-box-shadow: inset 0px 2px 13px #999;
+ margin-top:0.5em;
+ margin-left:0;
+ padding:0.5em;
+ background-color:#fff;
+ border-radius:15px;
+ -moz-border-radius: 15px;
+ -webkit-border-radius: 15px;
+}
+ol#qunit-tests li li{
+ border-bottom:none;
+ margin:0.5em;
+ background-color:#fff;
+ list-style-position: inside;
+ padding:0.4em 0.5em 0.4em 0.5em;
+}
-div#qunit-testrunner-toolbar { background: #eee; border-top: 1px solid black; padding: 10px; font-family: 'trebuchet ms', verdana, arial; margin: 0; font-size: 10pt; }
-
-ol#qunit-tests { font-family: 'trebuchet ms', verdana, arial; font-size: 10pt; }
-ol#qunit-tests li strong { cursor:pointer; }
-ol#qunit-tests .pass { color: green; }
-ol#qunit-tests .fail { color: red; }
-
-p#qunit-testresult { margin-left: 1em; font-size: 10pt; font-family: 'trebuchet ms', verdana, arial; }
+ol#qunit-tests li li.pass{
+ border-left:26px solid #C6E746;
+ background-color:#fff;
+ color:#5E740B;
+ }
+ol#qunit-tests li li.fail{
+ border-left:26px solid #EE5757;
+ background-color:#fff;
+ color:#710909;
+}
+ol#qunit-tests li.pass{
+ background-color:#D2E0E6;
+ color:#528CE0;
+}
+ol#qunit-tests li.fail{
+ background-color:#EE5757;
+ color:#000;
+}
+ol#qunit-tests li strong {
+ cursor:pointer;
+}
+h1#qunit-header{
+ background-color:#0d3349;
+ margin:0;
+ padding:0.5em 0 0.5em 1em;
+ color:#fff;
+ font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
+ border-top-right-radius:15px;
+ border-top-left-radius:15px;
+ -moz-border-radius-topright:15px;
+ -moz-border-radius-topleft:15px;
+ -webkit-border-top-right-radius:15px;
+ -webkit-border-top-left-radius:15px;
+ text-shadow: rgba(0, 0, 0, 0.5) 4px 4px 1px;
+}
+h2#qunit-banner{
+ font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
+ height:5px;
+ margin:0;
+ padding:0;
+}
+h2#qunit-banner.qunit-pass{
+ background-color:#C6E746;
+}
+h2#qunit-banner.qunit-fail, #qunit-testrunner-toolbar {
+ background-color:#EE5757;
+}
+#qunit-testrunner-toolbar {
+ font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
+ padding:0;
+ /*width:80%;*/
+ padding:0em 0 0.5em 2em;
+ font-size: small;
+}
+h2#qunit-userAgent {
+ font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
+ background-color:#2b81af;
+ margin:0;
+ padding:0;
+ color:#fff;
+ font-size: small;
+ padding:0.5em 0 0.5em 2.5em;
+ text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
+}
+p#qunit-testresult{
+ font-family:"Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial;
+ margin:0;
+ font-size: small;
+ color:#2b81af;
+ border-bottom-right-radius:15px;
+ border-bottom-left-radius:15px;
+ -moz-border-radius-bottomright:15px;
+ -moz-border-radius-bottomleft:15px;
+ -webkit-border-bottom-right-radius:15px;
+ -webkit-border-bottom-left-radius:15px;
+ background-color:#D2E0E6;
+ padding:0.5em 0.5em 0.5em 2.5em;
+}
+strong b.fail{
+ color:#710909;
+ }
+strong b.pass{
+ color:#5E740B;
+ }
diff --git a/tests/javascript/assets/qunit.js b/tests/javascript/assets/qunit.js
index 510b4cde59..8bef026151 100644
--- a/tests/javascript/assets/qunit.js
+++ b/tests/javascript/assets/qunit.js
@@ -6,59 +6,120 @@
* Copyright (c) 2009 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
- *
- * $Id$
*/
(function(window) {
var QUnit = {
+
+ // Initialize the configuration options
+ init: function() {
+ config = {
+ stats: { all: 0, bad: 0 },
+ moduleStats: { all: 0, bad: 0 },
+ started: +new Date,
+ blocking: false,
+ autorun: false,
+ assertions: [],
+ filters: [],
+ queue: []
+ };
+
+ var tests = id("qunit-tests"),
+ banner = id("qunit-banner"),
+ result = id("qunit-testresult");
+
+ if ( tests ) {
+ tests.innerHTML = "";
+ }
+
+ if ( banner ) {
+ banner.className = "";
+ }
+
+ if ( result ) {
+ result.parentNode.removeChild( result );
+ }
+ },
// call on start of module test to prepend name to all tests
- module: function module(name, lifecycle) {
+ module: function(name, testEnvironment) {
config.currentModule = name;
- config.moduleLifecycle = lifecycle;
synchronize(function() {
- QUnit.moduleLog( name );
+ if ( config.currentModule ) {
+ QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
+ }
+
+ config.currentModule = name;
+ config.moduleTestEnvironment = testEnvironment;
+ config.moduleStats = { all: 0, bad: 0 };
+
+ QUnit.moduleStart( name, testEnvironment );
});
},
+
+ asyncTest: function(testName, expected, callback) {
+ if ( arguments.length === 2 ) {
+ callback = expected;
+ expected = 0;
+ }
+
+ QUnit.test(testName, expected, callback, true);
+ },
- test: function test(testName, callback) {
- var name = testName;
+ test: function(testName, expected, callback, async) {
+ var name = testName, testEnvironment, testEnvironmentArg;
+
+ if ( arguments.length === 2 ) {
+ callback = expected;
+ expected = null;
+ }
+ // is 2nd argument a testEnvironment?
+ if ( expected && typeof expected === 'object') {
+ testEnvironmentArg = expected;
+ expected = null;
+ }
if ( config.currentModule ) {
name = config.currentModule + " module: " + name;
}
- var lifecycle = extend({
- setup: function() {},
- teardown: function() {}
- }, config.moduleLifecycle);
-
if ( !validTest(name) ) {
return;
}
- var testEnvironment = {};
-
synchronize(function() {
- QUnit.testLog( testName );
+ QUnit.testStart( testName );
+
+ testEnvironment = extend({
+ setup: function() {},
+ teardown: function() {}
+ }, config.moduleTestEnvironment);
+ if (testEnvironmentArg) {
+ extend(testEnvironment,testEnvironmentArg);
+ }
+ // allow utility functions to access the current test environment
+ QUnit.current_testEnvironment = testEnvironment;
+
config.assertions = [];
- config.expected = null;
+ config.expected = expected;
+
try {
if ( !config.pollution ) {
saveGlobal();
}
- lifecycle.setup.call(testEnvironment);
+ testEnvironment.setup.call(testEnvironment);
} catch(e) {
QUnit.ok( false, "Setup failed on " + name + ": " + e.message );
}
- });
- synchronize(function() {
+ if ( async ) {
+ QUnit.stop();
+ }
+
try {
callback.call(testEnvironment);
} catch(e) {
@@ -66,21 +127,24 @@ var QUnit = {
QUnit.ok( false, "Died on test #" + (config.assertions.length + 1) + ": " + e.message );
// else next test will carry the responsibility
saveGlobal();
+
+ // Restart the tests if they're blocking
+ if ( config.blocking ) {
+ start();
+ }
}
});
synchronize(function() {
try {
checkPollution();
- lifecycle.teardown.call(testEnvironment);
+ testEnvironment.teardown.call(testEnvironment);
} catch(e) {
QUnit.ok( false, "Teardown failed on " + name + ": " + e.message );
}
- });
- synchronize(function() {
try {
- reset();
+ QUnit.reset();
} catch(e) {
fail("reset() failed, following Test " + name + ", exception and reset fn follows", e, reset);
}
@@ -93,6 +157,7 @@ var QUnit = {
tests = id("qunit-tests");
config.stats.all += config.assertions.length;
+ config.moduleStats.all += config.assertions.length;
if ( tests ) {
var ol = document.createElement("ol");
@@ -103,7 +168,7 @@ var QUnit = {
var li = document.createElement("li");
li.className = assertion.result ? "pass" : "fail";
- li.innerHTML = assertion.message || "(no message)";
+ li.appendChild(document.createTextNode(assertion.message || "(no message)"));
ol.appendChild( li );
if ( assertion.result ) {
@@ -111,6 +176,7 @@ var QUnit = {
} else {
bad++;
config.stats.bad++;
+ config.moduleStats.bad++;
}
}
@@ -123,7 +189,7 @@ var QUnit = {
});
addEvent(b, "dblclick", function(e) {
- var target = (e || window.event).target;
+ var target = e && e.target ? e.target : window.event.srcElement;
if ( target.nodeName.toLowerCase() === "strong" ) {
var text = "", node = target.firstChild;
@@ -158,17 +224,35 @@ var QUnit = {
} else {
for ( var i = 0; i < config.assertions.length; i++ ) {
if ( !config.assertions[i].result ) {
+ bad++;
config.stats.bad++;
+ config.moduleStats.bad++;
}
}
}
+
+ QUnit.testDone( testName, bad, config.assertions.length );
+
+ if ( !window.setTimeout && !config.queue.length ) {
+ done();
+ }
});
+
+ if ( window.setTimeout && !config.doneTimer ) {
+ config.doneTimer = window.setTimeout(function(){
+ if ( !config.queue.length ) {
+ done();
+ } else {
+ synchronize( done );
+ }
+ }, 13);
+ }
},
/**
* Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through.
*/
- expect: function expect(asserts) {
+ expect: function(asserts) {
config.expected = asserts;
},
@@ -176,7 +260,7 @@ var QUnit = {
* Asserts true.
* @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
*/
- ok: function ok(a, msg) {
+ ok: function(a, msg) {
QUnit.log(a, msg);
config.assertions.push({
@@ -191,21 +275,37 @@ var QUnit = {
*
* Prefered to ok( actual == expected, message )
*
- * @example equals( format("Received {0} bytes.", 2), "Received 2 bytes." );
+ * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." );
*
* @param Object actual
* @param Object expected
* @param String message (optional)
*/
- equals: function equals(actual, expected, message) {
+ equal: function(actual, expected, message) {
push(expected == actual, actual, expected, message);
},
+
+ notEqual: function(actual, expected, message) {
+ push(expected != actual, actual, expected, message);
+ },
- same: function(a, b, message) {
+ deepEqual: function(a, b, message) {
push(QUnit.equiv(a, b), a, b, message);
},
+
+ notDeepEqual: function(a, b, message) {
+ push(!QUnit.equiv(a, b), a, b, message);
+ },
+
+ strictEqual: function(actual, expected, message) {
+ push(expected === actual, actual, expected, message);
+ },
+
+ notStrictEqual: function(actual, expected, message) {
+ push(expected !== actual, actual, expected, message);
+ },
- start: function start() {
+ start: function() {
// A slight delay, to avoid any current callbacks
if ( window.setTimeout ) {
window.setTimeout(function() {
@@ -222,13 +322,13 @@ var QUnit = {
}
},
- stop: function stop(timeout) {
+ stop: function(timeout) {
config.blocking = true;
if ( timeout && window.setTimeout ) {
config.timeout = window.setTimeout(function() {
QUnit.ok( false, "Test timed out" );
- start();
+ QUnit.start();
}, timeout);
}
},
@@ -236,7 +336,7 @@ var QUnit = {
/**
* Resets the test setup. Useful for tests that modify the DOM.
*/
- reset: function reset() {
+ reset: function() {
if ( window.jQuery ) {
jQuery("#main").html( config.fixture );
jQuery.event.global = {};
@@ -252,7 +352,7 @@ var QUnit = {
* @param DOMElement elem
* @param String type
*/
- triggerEvent: function triggerEvent( elem, type, event ) {
+ triggerEvent: function( elem, type, event ) {
if ( document.createEvent ) {
event = document.createEvent("MouseEvents");
event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView,
@@ -264,29 +364,28 @@ var QUnit = {
}
},
+ // Safe object type checking
+ is: function( type, obj ) {
+ return Object.prototype.toString.call( obj ) === "[object "+ type +"]";
+ },
+
// Logging callbacks
- done: function done(failures, total) {},
- log: function log(result, message) {},
- testLog: function testLog(name) {},
- moduleLog: function moduleLog(name) {}
+ done: function(failures, total) {},
+ log: function(result, message) {},
+ testStart: function(name) {},
+ testDone: function(name, failures, total) {},
+ moduleStart: function(name, testEnvironment) {},
+ moduleDone: function(name, failures, total) {}
};
+// Backwards compatibility, deprecated
+QUnit.equals = QUnit.equal;
+QUnit.same = QUnit.deepEqual;
+
// Maintain internal state
var config = {
- // Logging the passes and failures
- stats: {
- all: 0,
- bad: 0
- },
-
// The queue of tests to run
queue: [],
-
- // The log of global variables to check against
- pollution: [],
-
- // queue of test assertions
- assertions: [],
// block until document ready
blocking: true
@@ -303,6 +402,9 @@ var config = {
GETParams.splice( i, 1 );
i--;
config.noglobals = true;
+ } else if ( GETParams[i].search('=') > -1 ) {
+ GETParams.splice( i, 1 );
+ i--;
}
}
@@ -313,11 +415,28 @@ var config = {
QUnit.isLocal = !!(location.protocol === 'file:');
})();
-// public API as global methods
-extend(window, QUnit);
-window.QUnit = QUnit;
+// Expose the API as global variables, unless an 'exports'
+// object exists, in that case we assume we're in CommonJS
+if ( typeof exports === "undefined" || typeof require === "undefined" ) {
+ extend(window, QUnit);
+ window.QUnit = QUnit;
+} else {
+ extend(exports, QUnit);
+ exports.QUnit = QUnit;
+}
+
+if ( typeof document === "undefined" || document.readyState === "complete" ) {
+ config.autorun = true;
+}
addEvent(window, "load", function() {
+ // Initialize the config, saving the execution queue
+ var oldconfig = extend({}, config);
+ QUnit.init();
+ extend(config, oldconfig);
+
+ config.blocking = false;
+
var userAgent = id("qunit-userAgent");
if ( userAgent ) {
userAgent.innerHTML = navigator.userAgent;
@@ -335,14 +454,14 @@ addEvent(window, "load", function() {
var li = document.getElementsByTagName("li");
for ( var i = 0; i < li.length; i++ ) {
if ( li[i].className.indexOf("pass") > -1 ) {
- li[i].style.display = filter.checked ? "none" : "block";
+ li[i].style.display = filter.checked ? "none" : "";
}
}
});
toolbar.appendChild( filter );
var label = document.createElement("label");
- label.setAttribute("for", "filter-pass");
+ label.setAttribute("for", "qunit-filter-pass");
label.innerHTML = "Hide passed tests";
toolbar.appendChild( label );
@@ -361,16 +480,12 @@ addEvent(window, "load", function() {
toolbar.appendChild( missing );
label = document.createElement("label");
- label.setAttribute("for", "filter-missing");
+ label.setAttribute("for", "qunit-filter-missing");
label.innerHTML = "Hide missing tests (untested code is broken code)";
toolbar.appendChild( label );
}
- var started = +new Date,
- main = id('main');
-
- config.blocking = false;
-
+ var main = id('main');
if ( main ) {
config.fixture = main.innerHTML;
}
@@ -379,26 +494,59 @@ addEvent(window, "load", function() {
config.ajaxSettings = window.jQuery.ajaxSettings;
}
- synchronize(function() {
- var banner = id("qunit-banner"),
- html = ['Tests completed in ',
- +new Date - started, ' milliseconds.<br/>',
- '<span class="bad">', config.stats.all - config.stats.bad, '</span> tests of <span class="all">', config.stats.all, '</span> passed, ', config.stats.bad,' failed.'].join('');
+ QUnit.start();
+});
- if ( banner ) {
- var result = document.createElement("p");
+function done() {
+ if ( config.doneTimer && window.clearTimeout ) {
+ window.clearTimeout( config.doneTimer );
+ config.doneTimer = null;
+ }
+
+ if ( config.queue.length ) {
+ config.doneTimer = window.setTimeout(function(){
+ if ( !config.queue.length ) {
+ done();
+ } else {
+ synchronize( done );
+ }
+ }, 13);
+
+ return;
+ }
+
+ config.autorun = true;
+
+ // Log the last module results
+ if ( config.currentModule ) {
+ QUnit.moduleDone( config.currentModule, config.moduleStats.bad, config.moduleStats.all );
+ }
+
+ var banner = id("qunit-banner"),
+ tests = id("qunit-tests"),
+ html = ['Tests completed in ',
+ +new Date - config.started, ' milliseconds.<br/>',
+ '<span class="passed">', config.stats.all - config.stats.bad, '</span> tests of <span class="total">', config.stats.all, '</span> passed, <span class="failed">', config.stats.bad,'</span> failed.'].join('');
+
+ if ( banner ) {
+ banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass");
+ }
+
+ if ( tests ) {
+ var result = id("qunit-testresult");
+
+ if ( !result ) {
+ result = document.createElement("p");
result.id = "qunit-testresult";
result.className = "result";
- result.innerHTML = html;
- document.body.appendChild( result );
-
- banner.className +=
- " " + (config.stats.bad ? "fail" : "pass");
+ tests.parentNode.insertBefore( result, tests.nextSibling );
}
- QUnit.done( config.stats.bad, config.stats.all );
- });
-});
+ result.innerHTML = html;
+ }
+
+ QUnit.done( config.stats.bad, config.stats.all );
+}
function validTest( name ) {
var i = config.filters.length,
@@ -436,7 +584,7 @@ function push(result, actual, expected, message) {
function synchronize( callback ) {
config.queue.push( callback );
- if ( !config.blocking ) {
+ if ( config.autorun && !config.blocking ) {
process();
}
}
@@ -452,7 +600,7 @@ function saveGlobal() {
if ( config.noglobals ) {
for ( var key in window ) {
- config.pollution.push(key);
+ config.pollution.push( key );
}
}
}
@@ -461,24 +609,32 @@ function checkPollution( name ) {
var old = config.pollution;
saveGlobal();
- if ( config.pollution.length > old.length ) {
- ok( false, "Introduced global variable(s): " + diff(old, config.pollution).join(", ") );
+ var newGlobals = diff( old, config.pollution );
+ if ( newGlobals.length > 0 ) {
+ ok( false, "Introduced global variable(s): " + newGlobals.join(", ") );
config.expected++;
}
-}
-function diff( clean, dirty ) {
- var results = [];
+ var deletedGlobals = diff( config.pollution, old );
+ if ( deletedGlobals.length > 0 ) {
+ ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") );
+ config.expected++;
+ }
+}
- for ( var i = 0; i < dirty.length; i++ ) {
- for ( var c = 0; c < clean.length; c++ ) {
- if ( clean[c] === dirty[i] ) {
- results.push( clean[c] );
+// returns a new Array with the elements that are in a but not in b
+function diff( a, b ) {
+ var result = a.slice();
+ for ( var i = 0; i < result.length; i++ ) {
+ for ( var j = 0; j < b.length; j++ ) {
+ if ( result[i] === b[j] ) {
+ result.splice(i, 1);
+ i--;
+ break;
}
}
}
-
- return results;
+ return result;
}
function fail(message, exception, callback) {
@@ -527,13 +683,13 @@ QUnit.equiv = function () {
// Determine what is o.
function hoozit(o) {
- if (o.constructor === String) {
+ if (QUnit.is("String", o)) {
return "string";
- } else if (o.constructor === Boolean) {
+ } else if (QUnit.is("Boolean", o)) {
return "boolean";
- } else if (o.constructor === Number) {
+ } else if (QUnit.is("Number", o)) {
if (isNaN(o)) {
return "nan";
@@ -549,24 +705,24 @@ QUnit.equiv = function () {
return "null";
// consider: typeof [] === object
- } else if (o instanceof Array) {
+ } else if (QUnit.is( "Array", o)) {
return "array";
// consider: typeof new Date() === object
- } else if (o instanceof Date) {
+ } else if (QUnit.is( "Date", o)) {
return "date";
// consider: /./ instanceof Object;
// /./ instanceof RegExp;
// typeof /./ === "function"; // => false in IE and Opera,
// true in FF and Safari
- } else if (o instanceof RegExp) {
+ } else if (QUnit.is( "RegExp", o)) {
return "regexp";
} else if (typeof o === "object") {
return "object";
- } else if (o instanceof Function) {
+ } else if (QUnit.is( "Function", o)) {
return "function";
} else {
return undefined;
@@ -757,21 +913,31 @@ QUnit.jsDump = (function() {
this.parsers.error;
},
typeOf:function( obj ) {
- var type = typeof obj,
- f = 'function';//we'll use it 3 times, save it
- return type != 'object' && type != f ? type :
- !obj ? 'null' :
- obj.exec ? 'regexp' :// some browsers (FF) consider regexps functions
- obj.getHours ? 'date' :
- obj.scrollBy ? 'window' :
- obj.nodeName == '#document' ? 'document' :
- obj.nodeName ? 'node' :
- obj.item ? 'nodelist' : // Safari reports nodelists as functions
- obj.callee ? 'arguments' :
- obj.call || obj.constructor != Array && //an array would also fall on this hack
- (obj+'').indexOf(f) != -1 ? f : //IE reports functions like alert, as objects
- 'length' in obj ? 'array' :
- type;
+ var type;
+ if ( obj === null ) {
+ type = "null";
+ } else if (typeof obj === "undefined") {
+ type = "undefined";
+ } else if (QUnit.is("RegExp", obj)) {
+ type = "regexp";
+ } else if (QUnit.is("Date", obj)) {
+ type = "date";
+ } else if (QUnit.is("Function", obj)) {
+ type = "function";
+ } else if (QUnit.is("Array", obj)) {
+ type = "array";
+ } else if (QUnit.is("Window", obj) || QUnit.is("global", obj)) {
+ type = "window";
+ } else if (QUnit.is("HTMLDocument", obj)) {
+ type = "document";
+ } else if (QUnit.is("HTMLCollection", obj) || QUnit.is("NodeList", obj)) {
+ type = "nodelist";
+ } else if (/^\[object HTML/.test(Object.prototype.toString.call( obj ))) {
+ type = "node";
+ } else {
+ type = typeof obj;
+ }
+ return type;
},
separator:function() {
return this.multiline ? this.HTML ? '<br />' : '\n' : this.HTML ? '&nbsp;' : ' ';
diff --git a/tests/javascript/index.php b/tests/javascript/index.php
index becba7bb63..d8c7ae33e5 100644
--- a/tests/javascript/index.php
+++ b/tests/javascript/index.php
@@ -265,7 +265,7 @@ $(document).ready(function () {
});
test("Tracking", function() {
- expect(<?php echo $sqlite ? 12 : 3; ?>);
+ expect(<?php echo $sqlite ? 14 : 3; ?>);
var tracker = Piwik.getTracker();
@@ -296,6 +296,8 @@ if ($sqlite) {
tracker.trackPageView();
+ tracker.trackPageView("CustomTitleTest");
+
tracker.trackLink("http://example.ca", "link", { "token" : "'. $token .'" });
var buttons = new Array("click1", "click2", "click3", "click4", "click5", "click6", "click7");
@@ -305,14 +307,17 @@ if ($sqlite) {
tracker.trackGoal(42, 69, { "boy" : "Michael", "girl" : "Mandy" });
+ piwik_log("CompatibilityLayer", 1, "piwik.php", {"token":"'. $token .'"});
+
stop();
setTimeout(function() {
jQuery.ajax({
url: url("piwik.php?results='. $token .'"),
success: function(results) {
//alert(results);
- ok( /\<span\>7\<\/span\>/.test( results ), "count tracking events" );
+ ok( /\<span\>9\<\/span\>/.test( results ), "count tracking events" );
ok( /PiwikTest/.test( results ), "trackPageView()" );
+ ok( /CustomTitleTest/.test( results ), "trackPageView(customTitle)" );
ok( /example.ca/.test( results ), "trackLink()" );
ok( /example.net/.test( results ), "click: implicit outlink (by outbound URL)" );
ok( /example.html/.test( results ), "click: explicit outlink" );
@@ -320,6 +325,7 @@ if ($sqlite) {
ok( /example.word/.test( results ), "click: explicit download" );
ok( ! /example.(org|php)/.test( results ), "click: ignored" );
ok( /idgoal=42.*?revenue=69.*?Michael.*?Mandy/.test( results ), "trackGoal()" );
+ ok( /CompatibilityLayer/.test( results ), "piwik_log(): compatibility layer" );
start();
}
diff --git a/tests/simpletest/expectation.php b/tests/simpletest/expectation.php
index 83f763d270..eb435dd900 100644
--- a/tests/simpletest/expectation.php
+++ b/tests/simpletest/expectation.php
@@ -441,6 +441,8 @@ class OutsideMarginExpectation extends WithinMarginExpectation {
}
}
+// test() method is incompatible with SimpleExpectation (php 5.3.1)
+if(0){
/**
* Test for reference.
* @package SimpleTest
@@ -491,6 +493,7 @@ class ReferenceExpectation extends SimpleExpectation {
return $this->_value;
}
}
+}
/**
* Test for identity.
diff --git a/tests/simpletest/simpletest.php b/tests/simpletest/simpletest.php
index 642f75fd7c..907c54e427 100644
--- a/tests/simpletest/simpletest.php
+++ b/tests/simpletest/simpletest.php
@@ -87,7 +87,7 @@ class SimpleTest {
* @access public
* @see preferred()
*/
- function prefer(&$object) {
+ public static function prefer(&$object) {
$registry = &SimpleTest::_getRegistry();
$registry['Preferred'][] = &$object;
}
@@ -202,7 +202,7 @@ class SimpleTest {
* @access private
* @static
*/
- function &_getRegistry() {
+ public static function &_getRegistry() {
static $registry = false;
if (! $registry) {
$registry = SimpleTest::_getDefaults();
@@ -231,7 +231,7 @@ class SimpleTest {
* @access private
* @static
*/
- function _getDefaults() {
+ private static function _getDefaults() {
return array(
'StubBaseClass' => 'SimpleStub',
'MockBaseClass' => 'SimpleMock',
diff --git a/tests/webtest/testcases/level0/test.piwik.index.xml b/tests/webtest/testcases/level0/test.piwik.index.xml
index d2e6130a21..e2b3e4e8ec 100644
--- a/tests/webtest/testcases/level0/test.piwik.index.xml
+++ b/tests/webtest/testcases/level0/test.piwik.index.xml
@@ -39,7 +39,8 @@
<verifyTitle description="check the title is parsed correctly" text="Piwik &rsaquo; Installation" />
<verifyText description="check page text" text="Piwik" />
<verifyText description="check page text" text="Welcome!" />
- <verifyText description="check page text" text="This process is split up into 8 easy steps and will take around 5 minutes" />
+ <verifyText description="check page text" text="This process is split up into 9 easy steps and will take around 5 minutes" />
+
&checkForErrors;
&verifyLinksAndImages;
@@ -80,7 +81,19 @@
<clickButton description="click 'Go!' button" label="Go!"/>
- <!-- 4. tablesCreation -->
+ <!-- 4. databaseCheck -->
+<!--
+ <verifyTitle description="check the title is parsed correctly" text="Piwik &rsaquo; Installation" />
+ <verifyText description="check page text" text="Piwik" />
+ <verifyText description="check page text" text="Database check" />
+
+ &checkForErrors;
+ &verifyLinksAndImages;
+
+ <clickLink description="click 'Next'" label="Next &raquo;" />
+-->
+
+ <!-- 5. tablesCreation -->
<not description="check if no error">
<verifyXPath description="looking for error image" xpath="//img[@src='themes/default/images/error_medium.png']"/>
@@ -100,7 +113,7 @@
<clickLink description="click 'Next'" label="Next &raquo;" />
- <!-- 5. generalSetup -->
+ <!-- 6. generalSetup -->
<verifyTitle description="check the title is parsed correctly" text="Piwik &rsaquo; Installation" />
<verifyText description="check page text" text="Piwik" />
@@ -116,7 +129,7 @@
<clickButton description="click 'Go!' button" label="Go!"/>
- <!-- 6. firstWebsiteSetup -->
+ <!-- 7. firstWebsiteSetup -->
<not description="check if no error">
<verifyXPath description="looking for error image" xpath="//img[@src='themes/default/images/error_medium.png']"/>
@@ -135,10 +148,11 @@
<setInputField description="set Piwik site name" name="siteName" value="Dummy Site Name" />
<setInputField description="set Piwik URL" name="url" value="${wt.config.protocol}://${wt.config.host}:${wt.config.port}${wt.config.basepath}" />
+ <setSelectField description="set Piwik timezone" name="timezone" value="UTC" />
<clickButton description="click 'Go!' button" label="Go!"/>
- <!-- 7. displayJavascriptCode -->
+ <!-- 8. displayJavascriptCode -->
<not description="check if no error">
<verifyXPath description="looking for error image" xpath="//img[@src='themes/default/images/error_medium.png']"/>
@@ -157,7 +171,7 @@
<clickLink description="click 'Next'" label="Next &raquo;" />
- <!-- 8. finished -->
+ <!-- 9. finished -->
<verifyTitle description="check the title is parsed correctly" text="Piwik &rsaquo; Installation" />
<verifyText description="check page text" text="Piwik" />
@@ -170,7 +184,7 @@
<!-- logging in -->
- <verifyTitle description="check the title is parsed correctly" text="Piwik &rsaquo; Login" />
+ <verifyTitle description="check the title is parsed correctly" text="Piwik &rsaquo; Sign in" />
<verifyText description="check page text" text="Piwik" />
<verifyText description="check page text" text="Lost your password?" />
@@ -179,13 +193,14 @@
<setInputField description="set Piwik login" htmlId="form_login" value="piwik_login" />
<setInputField description="set Piwik password" htmlId="form_password" value="piwik_password" />
+
<clickButton description="click 'Sign in' button" label="Sign in"/>
<!-- logged in -->
<verifyTitle description="check the title is parsed correctly" text="Piwik &rsaquo; Web Analytics Reports" />
<verifyText description="check page text" text="Piwik" />
- <verifyText description="check page text" text="Your Dashboard" />
+ <verifyText description="check page text" text="Dashboard" />
<verifyText description="check page text" text="Hello" />
</steps>
diff --git a/themes/default/common.css b/themes/default/common.css
index b5dcc24084..904da21c95 100644
--- a/themes/default/common.css
+++ b/themes/default/common.css
@@ -22,6 +22,9 @@ ol,ul {
blockquote,q {
quotes: none;
}
+label {
+ cursor:pointer;
+}
/* remember to define focus styles! */
:focus {
outline: 0;
@@ -33,6 +36,13 @@ ins {
del {
text-decoration: line-through;
}
+/* br clear="all" deprecated */
+br.clearAll {
+ clear: both;
+ height: 0;
+ line-height: 0;
+ font-size: px; /*for IE*/
+}
/* start piwik styles */
body {
font-family: Georgia, "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
@@ -85,6 +95,8 @@ a {
padding:5px;
font-weight:bold;
right:10px;
+ -moz-border-radius:4px;
+ -webkit-border-radius:4px;
}
#header_message, #header_message a {
color:#FF7F00;
@@ -98,7 +110,7 @@ a {
float: left;
height: 22px;
padding-left: 10px;
- width:550px; /* when this is not set, wrong display in safari/chrome? */
+ width:620px; /* when this is not set, wrong display in safari/chrome? */
}
#topLeftBar, #topRightBar {
font-family: arial, sans-serif !important;
@@ -162,7 +174,7 @@ a {
.tableForm .submit {
text-align:center;
}
-.submit input{
+input.submit {
margin-top:15px;
background:transparent url(./images/background-submit.png) repeat scroll 0%;
font-size:1.4em;
@@ -171,8 +183,9 @@ a {
border-width:3px;
color:#333;
padding:0.15em;
+ align:center;
}
-#ajaxError {
+.ajaxError {
color: red;
text-align: center;
font-weight: bold;
@@ -180,4 +193,29 @@ a {
border: 3px solid red;
margin: 10px;
padding: 10px;
+ -moz-border-radius:9px;
+ -webkit-border-radius:9px;
+}
+.ajaxSuccess {
+ padding: 20px;
+ margin:10px;
+ display: block;
+ color:#301901;
+ border: 1px solid #e6db55;
+ -moz-border-radius:3px;
+ -webkit-border-radius:3px;
+ background-color: #ffffe0;
+ padding:0 0.6em;
+ display:inline-block;
+}
+/* extending the jquery UI css for inline help */
+.ui-widget {
+ text-align:justify;
+}
+
+.ui-inline-help {
+ width:170px;
+ margin-top:20px;
+ padding:0 0.7em;
}
+
diff --git a/themes/default/common.js b/themes/default/common.js
index 95a3cb82ff..ccb28b4ffe 100644
--- a/themes/default/common.js
+++ b/themes/default/common.js
@@ -47,6 +47,42 @@ piwikHelper.findSWFGraph = function(name) {
return null;
}
+piwikHelper.showAjaxError = function( string, errorDivID )
+{
+ errorDivID = errorDivID || 'ajaxError';
+ $('#'+errorDivID).html(string).show();
+}
+
+piwikHelper.hideAjaxError = function(errorDivID)
+{
+ errorDivID = errorDivID || 'ajaxError';
+ $('#'+errorDivID).hide();
+}
+
+piwikHelper.showAjaxLoading = function(loadingDivID)
+{
+ loadingDivID = loadingDivID || 'ajaxLoading';
+ $('#'+loadingDivID).show();
+}
+piwikHelper.hideAjaxLoading = function(loadingDivID)
+{
+ loadingDivID = loadingDivID || 'ajaxLoading';
+ $('#'+loadingDivID).hide();
+}
+
+piwikHelper.getStandardAjaxConf = function(loadingDivID, errorDivID)
+{
+ piwikHelper.showAjaxLoading(loadingDivID);
+ piwikHelper.hideAjaxError(errorDivID);
+ var ajaxRequest = {};
+ ajaxRequest.type = 'GET';
+ ajaxRequest.url = 'index.php';
+ ajaxRequest.dataType = 'json';
+ ajaxRequest.error = piwikHelper.ajaxHandleError;
+ ajaxRequest.success = function(response) { piwikHelper.ajaxHandleResponse(response, loadingDivID, errorDivID); };
+ return ajaxRequest;
+}
+
piwikHelper.redirectToUrl = function(url) {
window.location = url;
}
@@ -59,55 +95,44 @@ piwikHelper.ajaxHandleError = function()
}, 2000);
}
-piwikHelper.ajaxShowError = function( string )
-{
- $('#ajaxError').html(string).show();
-}
-
-piwikHelper.ajaxHideError = function()
-{
- $('#ajaxError').hide();
-}
-
-piwikHelper.ajaxHandleResponse = function(response)
+piwikHelper.ajaxHandleResponse = function(response, loadingDivID, errorDivID)
{
if(response.result == "error")
{
- piwikHelper.ajaxShowError(response.message);
+ piwikHelper.hideAjaxLoading(loadingDivID);
+ piwikHelper.showAjaxError(response.message, errorDivID);
}
else
{
- window.location.reload();
+ // add updated=1 to the URL so that a "Your changes have been saved" message is displayed
+ var urlToRedirect = String(window.location.pathname) + String(window.location.search);
+ updatedUrl = 'updated=1';
+ if(urlToRedirect.search(new RegExp(updatedUrl)) == -1)
+ {
+ urlToRedirect += '&' + updatedUrl;
+ }
+ var currentHashStr = window.location.hash;
+ if(currentHashStr.length > 0) {
+ urlToRedirect += currentHashStr;
+ }
+ piwikHelper.redirectToUrl(urlToRedirect);
}
- piwikHelper.toggleAjaxLoading();
-}
-
-piwikHelper.toggleAjaxLoading = function()
-{
- $('#ajaxLoading').toggle();
}
-piwikHelper.getStandardAjaxConf = function()
-{
- var ajaxRequest = {};
- ajaxRequest.type = 'GET';
- ajaxRequest.url = 'index.php';
- ajaxRequest.dataType = 'json';
- ajaxRequest.error = piwikHelper.ajaxHandleError;
- ajaxRequest.success = piwikHelper.ajaxHandleResponse;
- return ajaxRequest;
-}
-
-// Scrolls the window to the jquery element 'elem' if necessary.
-// "time" specifies the duration of the animation in ms
+/**
+ * Scrolls the window to the jquery element 'elem'
+ * if the top of the element is not currently visible on screen
+ * @param elem Selector for the DOM node to scroll to, eg. '#myDiv'
+ * @param time Specifies the duration of the animation in ms
+ */
piwikHelper.lazyScrollTo = function(elem, time)
{
var elemTop = $(elem).offset().top;
- //only scroll the page if the graph is not visible
+ // only scroll the page if the graph is not visible
if(elemTop < $(window).scrollTop()
|| elemTop > $(window).scrollTop()+$(window).height())
{
- //scroll the page smoothly to the graph
+ // scroll the page smoothly to the graph
$.scrollTo(elem, time);
}
}
diff --git a/themes/default/genericForm.tpl b/themes/default/genericForm.tpl
index f8f00d39cb..fccbc45d60 100644
--- a/themes/default/genericForm.tpl
+++ b/themes/default/genericForm.tpl
@@ -2,7 +2,7 @@
{if $form_data.errors}
<div class="warning">
<img src="themes/default/images/warning_medium.png">
- <strong>Please fix the following errors:</strong>
+ <strong>{'Installation_PleaseFixTheFollowingErrors'|translate}:</strong>
<ul>
{foreach from=$form_data.errors item=data}
<li>{$data}</li>
diff --git a/themes/default/simple_structure.css b/themes/default/simple_structure.css
index c3dca9ea4e..1fdca428f6 100644
--- a/themes/default/simple_structure.css
+++ b/themes/default/simple_structure.css
@@ -8,7 +8,6 @@ html { background: #eee; }
margin:auto;
margin-top: 30px;
-moz-border-radius: 12px;
- -khtml-border-radius: 12px;
-webkit-border-radius: 12px;
}
#h1 {
@@ -27,7 +26,7 @@ html { background: #eee; }
}
p, dt {
line-height: 120%;
- padding-bottom: 2px;
+ padding-bottom: 1em;
margin:10;
}
a { color: #006; }
@@ -37,7 +36,6 @@ a { color: #006; }
padding: 5px 7px 7px;
border: 1px solid #a3a3a3;
-moz-border-radius: 3px;
- -khtml-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
color: #246;
@@ -75,3 +73,7 @@ a { color: #006; }
border:0;
vertical-align:bottom;
}
+.warning, .error {
+ -moz-border-radius:4px;
+ -webkit-border-radius:4px;
+} \ No newline at end of file
diff --git a/web.config b/web.config
deleted file mode 100644
index 2981ea21bf..0000000000
--- a/web.config
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<configuration>
- <system.webServer>
- <security>
- <requestFiltering>
- <hiddenSegments>
- <add segment="config" />
- <add segment="tmp" />
- </hiddenSegments>
- </requestFiltering>
- </security>
- <directoryBrowse enabled="false" />
- <defaultDocument>
- <files>
- <remove value="index.php" />
- <add value="index.php" />
- </files>
- </defaultDocument>
- </system.webServer>
-</configuration>