Upgrade to Bugzilla 5.0.3.
authorddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Mar 2017 16:27:49 +0000 (16:27 +0000)
committerddkilzer@apple.com <ddkilzer@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Mar 2017 16:27:49 +0000 (16:27 +0000)
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@214224 268f45cc-cd09-0410-ab3c-d52691b4dbfc

811 files changed:
Websites/bugs.webkit.org/.bzrignore
Websites/bugs.webkit.org/.gitignore
Websites/bugs.webkit.org/.htaccess
Websites/bugs.webkit.org/.travis.yml [deleted file]
Websites/bugs.webkit.org/Bugzilla.pm
Websites/bugs.webkit.org/Bugzilla/.htaccess
Websites/bugs.webkit.org/Bugzilla/Attachment.pm
Websites/bugs.webkit.org/Bugzilla/Attachment/PatchReader.pm
Websites/bugs.webkit.org/Bugzilla/Auth.pm
Websites/bugs.webkit.org/Bugzilla/Auth/Login.pm
Websites/bugs.webkit.org/Bugzilla/Auth/Login/APIKey.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/Auth/Login/CGI.pm
Websites/bugs.webkit.org/Bugzilla/Auth/Login/Cookie.pm
Websites/bugs.webkit.org/Bugzilla/Auth/Login/Env.pm
Websites/bugs.webkit.org/Bugzilla/Auth/Login/Stack.pm
Websites/bugs.webkit.org/Bugzilla/Auth/Persist/Cookie.pm
Websites/bugs.webkit.org/Bugzilla/Auth/Verify.pm
Websites/bugs.webkit.org/Bugzilla/Auth/Verify/DB.pm
Websites/bugs.webkit.org/Bugzilla/Auth/Verify/LDAP.pm
Websites/bugs.webkit.org/Bugzilla/Auth/Verify/RADIUS.pm
Websites/bugs.webkit.org/Bugzilla/Auth/Verify/Stack.pm
Websites/bugs.webkit.org/Bugzilla/Bug.pm
Websites/bugs.webkit.org/Bugzilla/BugMail.pm
Websites/bugs.webkit.org/Bugzilla/BugUrl.pm
Websites/bugs.webkit.org/Bugzilla/BugUrl/Bugzilla.pm
Websites/bugs.webkit.org/Bugzilla/BugUrl/Bugzilla/Local.pm
Websites/bugs.webkit.org/Bugzilla/BugUrl/Debian.pm
Websites/bugs.webkit.org/Bugzilla/BugUrl/GitHub.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/BugUrl/Google.pm
Websites/bugs.webkit.org/Bugzilla/BugUrl/JIRA.pm
Websites/bugs.webkit.org/Bugzilla/BugUrl/Launchpad.pm
Websites/bugs.webkit.org/Bugzilla/BugUrl/MantisBT.pm
Websites/bugs.webkit.org/Bugzilla/BugUrl/SourceForge.pm
Websites/bugs.webkit.org/Bugzilla/BugUrl/Trac.pm
Websites/bugs.webkit.org/Bugzilla/BugUserLastVisit.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/CGI.pm
Websites/bugs.webkit.org/Bugzilla/Chart.pm
Websites/bugs.webkit.org/Bugzilla/Classification.pm
Websites/bugs.webkit.org/Bugzilla/Comment.pm
Websites/bugs.webkit.org/Bugzilla/Comment/TagWeights.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/Component.pm
Websites/bugs.webkit.org/Bugzilla/Config.pm
Websites/bugs.webkit.org/Bugzilla/Config/Admin.pm
Websites/bugs.webkit.org/Bugzilla/Config/Advanced.pm
Websites/bugs.webkit.org/Bugzilla/Config/Attachment.pm
Websites/bugs.webkit.org/Bugzilla/Config/Auth.pm
Websites/bugs.webkit.org/Bugzilla/Config/BugChange.pm
Websites/bugs.webkit.org/Bugzilla/Config/BugFields.pm
Websites/bugs.webkit.org/Bugzilla/Config/Common.pm
Websites/bugs.webkit.org/Bugzilla/Config/Core.pm
Websites/bugs.webkit.org/Bugzilla/Config/DependencyGraph.pm
Websites/bugs.webkit.org/Bugzilla/Config/General.pm
Websites/bugs.webkit.org/Bugzilla/Config/GroupSecurity.pm
Websites/bugs.webkit.org/Bugzilla/Config/LDAP.pm
Websites/bugs.webkit.org/Bugzilla/Config/MTA.pm
Websites/bugs.webkit.org/Bugzilla/Config/Memcached.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/Config/PatchViewer.pm [deleted file]
Websites/bugs.webkit.org/Bugzilla/Config/Query.pm
Websites/bugs.webkit.org/Bugzilla/Config/RADIUS.pm
Websites/bugs.webkit.org/Bugzilla/Config/ShadowDB.pm
Websites/bugs.webkit.org/Bugzilla/Config/UserMatch.pm
Websites/bugs.webkit.org/Bugzilla/Constants.pm
Websites/bugs.webkit.org/Bugzilla/DB.pm
Websites/bugs.webkit.org/Bugzilla/DB/Mysql.pm
Websites/bugs.webkit.org/Bugzilla/DB/Oracle.pm
Websites/bugs.webkit.org/Bugzilla/DB/Pg.pm
Websites/bugs.webkit.org/Bugzilla/DB/Schema.pm
Websites/bugs.webkit.org/Bugzilla/DB/Schema/Mysql.pm
Websites/bugs.webkit.org/Bugzilla/DB/Schema/Oracle.pm
Websites/bugs.webkit.org/Bugzilla/DB/Schema/Pg.pm
Websites/bugs.webkit.org/Bugzilla/DB/Schema/Sqlite.pm
Websites/bugs.webkit.org/Bugzilla/DB/Sqlite.pm
Websites/bugs.webkit.org/Bugzilla/Error.pm
Websites/bugs.webkit.org/Bugzilla/Extension.pm
Websites/bugs.webkit.org/Bugzilla/Field.pm
Websites/bugs.webkit.org/Bugzilla/Field/Choice.pm
Websites/bugs.webkit.org/Bugzilla/Field/ChoiceInterface.pm
Websites/bugs.webkit.org/Bugzilla/Flag.pm
Websites/bugs.webkit.org/Bugzilla/FlagType.pm
Websites/bugs.webkit.org/Bugzilla/Group.pm
Websites/bugs.webkit.org/Bugzilla/Hook.pm
Websites/bugs.webkit.org/Bugzilla/Install.pm
Websites/bugs.webkit.org/Bugzilla/Install/CPAN.pm
Websites/bugs.webkit.org/Bugzilla/Install/DB.pm
Websites/bugs.webkit.org/Bugzilla/Install/Filesystem.pm
Websites/bugs.webkit.org/Bugzilla/Install/Localconfig.pm
Websites/bugs.webkit.org/Bugzilla/Install/Requirements.pm
Websites/bugs.webkit.org/Bugzilla/Install/Util.pm
Websites/bugs.webkit.org/Bugzilla/Job/BugMail.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/Job/Mailer.pm
Websites/bugs.webkit.org/Bugzilla/JobQueue.pm
Websites/bugs.webkit.org/Bugzilla/JobQueue/Runner.pm
Websites/bugs.webkit.org/Bugzilla/Keyword.pm
Websites/bugs.webkit.org/Bugzilla/MIME.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/Mailer.pm
Websites/bugs.webkit.org/Bugzilla/Memcached.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/Migrate.pm
Websites/bugs.webkit.org/Bugzilla/Migrate/Gnats.pm
Websites/bugs.webkit.org/Bugzilla/Milestone.pm
Websites/bugs.webkit.org/Bugzilla/Object.pm
Websites/bugs.webkit.org/Bugzilla/Product.pm
Websites/bugs.webkit.org/Bugzilla/RNG.pm
Websites/bugs.webkit.org/Bugzilla/Report.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/Search.pm
Websites/bugs.webkit.org/Bugzilla/Search/Clause.pm
Websites/bugs.webkit.org/Bugzilla/Search/ClauseGroup.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/Search/Condition.pm
Websites/bugs.webkit.org/Bugzilla/Search/Quicksearch.pm
Websites/bugs.webkit.org/Bugzilla/Search/Recent.pm
Websites/bugs.webkit.org/Bugzilla/Search/Saved.pm
Websites/bugs.webkit.org/Bugzilla/Sender/Transport/Sendmail.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/Series.pm
Websites/bugs.webkit.org/Bugzilla/Status.pm
Websites/bugs.webkit.org/Bugzilla/Template.pm
Websites/bugs.webkit.org/Bugzilla/Template/Context.pm
Websites/bugs.webkit.org/Bugzilla/Template/Plugin/Bugzilla.pm
Websites/bugs.webkit.org/Bugzilla/Template/Plugin/Hook.pm
Websites/bugs.webkit.org/Bugzilla/Template/Plugin/User.pm [deleted file]
Websites/bugs.webkit.org/Bugzilla/Token.pm
Websites/bugs.webkit.org/Bugzilla/Update.pm
Websites/bugs.webkit.org/Bugzilla/User.pm
Websites/bugs.webkit.org/Bugzilla/User/APIKey.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/User/Setting.pm
Websites/bugs.webkit.org/Bugzilla/User/Setting/Lang.pm
Websites/bugs.webkit.org/Bugzilla/User/Setting/Skin.pm
Websites/bugs.webkit.org/Bugzilla/User/Setting/Timezone.pm
Websites/bugs.webkit.org/Bugzilla/UserAgent.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/Util.pm
Websites/bugs.webkit.org/Bugzilla/Version.pm
Websites/bugs.webkit.org/Bugzilla/WebService.pm
Websites/bugs.webkit.org/Bugzilla/WebService/Bug.pm
Websites/bugs.webkit.org/Bugzilla/WebService/BugUserLastVisit.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Bugzilla.pm
Websites/bugs.webkit.org/Bugzilla/WebService/Classification.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Component.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Constants.pm
Websites/bugs.webkit.org/Bugzilla/WebService/FlagType.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Group.pm
Websites/bugs.webkit.org/Bugzilla/WebService/Product.pm
Websites/bugs.webkit.org/Bugzilla/WebService/README
Websites/bugs.webkit.org/Bugzilla/WebService/Server.pm
Websites/bugs.webkit.org/Bugzilla/WebService/Server/JSONRPC.pm
Websites/bugs.webkit.org/Bugzilla/WebService/Server/REST.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Server/REST/Resources/Bug.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Server/REST/Resources/BugUserLastVisit.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Server/REST/Resources/Bugzilla.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Server/REST/Resources/Classification.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Server/REST/Resources/Component.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Server/REST/Resources/FlagType.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Server/REST/Resources/Group.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Server/REST/Resources/Product.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Server/REST/Resources/User.pm [new file with mode: 0644]
Websites/bugs.webkit.org/Bugzilla/WebService/Server/XMLRPC.pm
Websites/bugs.webkit.org/Bugzilla/WebService/User.pm
Websites/bugs.webkit.org/Bugzilla/WebService/Util.pm
Websites/bugs.webkit.org/Bugzilla/Whine.pm
Websites/bugs.webkit.org/Bugzilla/Whine/Query.pm
Websites/bugs.webkit.org/Bugzilla/Whine/Schedule.pm
Websites/bugs.webkit.org/ChangeLog
Websites/bugs.webkit.org/LICENSE [new file with mode: 0644]
Websites/bugs.webkit.org/README
Websites/bugs.webkit.org/admin.cgi
Websites/bugs.webkit.org/attachment.cgi
Websites/bugs.webkit.org/buglist.cgi
Websites/bugs.webkit.org/chart.cgi
Websites/bugs.webkit.org/checksetup.pl
Websites/bugs.webkit.org/clean-bug-user-last-visit.pl [new file with mode: 0755]
Websites/bugs.webkit.org/colchange.cgi
Websites/bugs.webkit.org/collectstats.pl
Websites/bugs.webkit.org/config.cgi
Websites/bugs.webkit.org/contrib/.htaccess
Websites/bugs.webkit.org/contrib/Bugzilla.pm [new file with mode: 0644]
Websites/bugs.webkit.org/contrib/README
Websites/bugs.webkit.org/contrib/bugzilla-queue.rhel
Websites/bugs.webkit.org/contrib/bugzilla-queue.suse
Websites/bugs.webkit.org/contrib/bugzilla-submit/bugzilla-submit
Websites/bugs.webkit.org/contrib/bugzilla-submit/bugzilla-submit.xml
Websites/bugs.webkit.org/contrib/bz_webservice_demo.pl
Websites/bugs.webkit.org/contrib/bzdbcopy.pl
Websites/bugs.webkit.org/contrib/cmdline/bugcount
Websites/bugs.webkit.org/contrib/cmdline/bugids
Websites/bugs.webkit.org/contrib/cmdline/buglist
Websites/bugs.webkit.org/contrib/cmdline/bugs
Websites/bugs.webkit.org/contrib/cmdline/bugslink
Websites/bugs.webkit.org/contrib/cmdline/makequery
Websites/bugs.webkit.org/contrib/cmdline/query.conf
Websites/bugs.webkit.org/contrib/console.pl
Websites/bugs.webkit.org/contrib/convert-workflow.pl
Websites/bugs.webkit.org/contrib/cvs-update.pl [deleted file]
Websites/bugs.webkit.org/contrib/extension-convert.pl
Websites/bugs.webkit.org/contrib/fixperms.pl
Websites/bugs.webkit.org/contrib/jb2bz.py
Websites/bugs.webkit.org/contrib/merge-users.pl
Websites/bugs.webkit.org/contrib/mysqld-watcher.pl
Websites/bugs.webkit.org/contrib/new-yui.sh
Websites/bugs.webkit.org/contrib/recode.pl
Websites/bugs.webkit.org/contrib/sendbugmail.pl
Websites/bugs.webkit.org/contrib/sendunsentbugmail.pl
Websites/bugs.webkit.org/contrib/syncLDAP.pl
Websites/bugs.webkit.org/createaccount.cgi
Websites/bugs.webkit.org/data/.htaccess
Websites/bugs.webkit.org/data/params [deleted file]
Websites/bugs.webkit.org/data/params.json [new file with mode: 0644]
Websites/bugs.webkit.org/describecomponents.cgi
Websites/bugs.webkit.org/describekeywords.cgi
Websites/bugs.webkit.org/docs/TODO [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/Makefile [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/README.docs [deleted file]
Websites/bugs.webkit.org/docs/en/images/bugzilla.png [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/images/bzLifecycle.xml
Websites/bugs.webkit.org/docs/en/images/callouts/1.gif [deleted file]
Websites/bugs.webkit.org/docs/en/images/callouts/2.gif [deleted file]
Websites/bugs.webkit.org/docs/en/images/callouts/3.gif [deleted file]
Websites/bugs.webkit.org/docs/en/images/caution.gif [deleted file]
Websites/bugs.webkit.org/docs/en/images/note.gif [deleted file]
Websites/bugs.webkit.org/docs/en/images/tip.gif [deleted file]
Websites/bugs.webkit.org/docs/en/images/warning.gif [deleted file]
Websites/bugs.webkit.org/docs/en/make.bat [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rel_notes.txt [deleted file]
Websites/bugs.webkit.org/docs/en/rst/_static/bugzilla.css [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/about/index.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/categorization.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/custom-fields.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/extensions.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/field-values.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/flags.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/groups.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/index.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/keywords.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/parameters.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/preferences.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/quips.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/users.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/whining.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/administering/workflow.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/attachment.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/bug-user-last-visit.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/bug.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/bugzilla.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/classification.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/comment.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/component.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/field.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/flagtype.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/general.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/group.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/index.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/product.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/core/v1/user.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/api/index.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/conf.py [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/index.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/apache-windows.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/apache.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/backups.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/db_server.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/essential-post-install-config.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/iis.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/index.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/installing-end.inc.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/linux.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/mac-os-x.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/merging-accounts.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/migrating-from-1.inc.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/migrating-from-2.inc.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/migrating-from-a-tarball.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/migrating-from-bzr.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/migrating-from-cvs.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/migrating.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/moving.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/multiple-bugzillas.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/mysql.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/optional-post-install-config.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/oracle.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/postgresql.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/quick-start.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/sanity-check.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/sqlite.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/upgrading-customizations.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/upgrading-with-1.inc.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/upgrading-with-2.inc.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/upgrading-with-a-tarball.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/upgrading-with-git.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/upgrading.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/web_server.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/installing/windows.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/integrating/apis.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/integrating/extensions.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/integrating/faq.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/integrating/index.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/integrating/languages.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/integrating/skins.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/integrating/templates.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/style.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/using/creating-an-account.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/using/editing.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/using/extensions.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/using/filing.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/using/finding.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/using/index.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/using/preferences.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/using/reports-and-charts.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/using/tips.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/rst/using/understanding.rst [new file with mode: 0644]
Websites/bugs.webkit.org/docs/en/xml/Bugzilla-Guide.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/about.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/administration.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/conventions.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/customization.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/gfdl.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/glossary.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/index.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/installation.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/modules.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/patches.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/security.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/troubleshooting.xml [deleted file]
Websites/bugs.webkit.org/docs/en/xml/using.xml [deleted file]
Websites/bugs.webkit.org/docs/lib/Pod/Simple/HTML/Bugzilla.pm
Websites/bugs.webkit.org/docs/lib/Pod/Simple/HTMLBatch/Bugzilla.pm
Websites/bugs.webkit.org/docs/makedocs.pl
Websites/bugs.webkit.org/docs/style.css
Websites/bugs.webkit.org/duplicates.cgi
Websites/bugs.webkit.org/editclassifications.cgi
Websites/bugs.webkit.org/editcomponents.cgi
Websites/bugs.webkit.org/editfields.cgi
Websites/bugs.webkit.org/editflagtypes.cgi
Websites/bugs.webkit.org/editgroups.cgi
Websites/bugs.webkit.org/editkeywords.cgi
Websites/bugs.webkit.org/editmilestones.cgi
Websites/bugs.webkit.org/editparams.cgi
Websites/bugs.webkit.org/editproducts.cgi
Websites/bugs.webkit.org/editsettings.cgi
Websites/bugs.webkit.org/editusers.cgi
Websites/bugs.webkit.org/editvalues.cgi
Websites/bugs.webkit.org/editversions.cgi
Websites/bugs.webkit.org/editwhines.cgi
Websites/bugs.webkit.org/editworkflow.cgi
Websites/bugs.webkit.org/email_in.pl
Websites/bugs.webkit.org/enter_bug.cgi
Websites/bugs.webkit.org/extensions/BmpConvert/Config.pm
Websites/bugs.webkit.org/extensions/BmpConvert/Extension.pm
Websites/bugs.webkit.org/extensions/Example/Config.pm
Websites/bugs.webkit.org/extensions/Example/Extension.pm
Websites/bugs.webkit.org/extensions/Example/docs/en/rst/api/v1/index.rst [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/Example/docs/en/rst/index-admin.rst [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/Example/docs/en/rst/index-user.rst [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/Example/lib/Auth/Login.pm
Websites/bugs.webkit.org/extensions/Example/lib/Auth/Verify.pm
Websites/bugs.webkit.org/extensions/Example/lib/Config.pm
Websites/bugs.webkit.org/extensions/Example/lib/Util.pm
Websites/bugs.webkit.org/extensions/Example/lib/WebService.pm
Websites/bugs.webkit.org/extensions/Example/template/en/default/account/prefs/my_tab.html.tmpl
Websites/bugs.webkit.org/extensions/Example/template/en/default/admin/params/example.html.tmpl
Websites/bugs.webkit.org/extensions/Example/template/en/default/hook/account/prefs/prefs-tabs.html.tmpl
Websites/bugs.webkit.org/extensions/Example/template/en/default/hook/admin/params/editparams-current_panel.html.tmpl
Websites/bugs.webkit.org/extensions/Example/template/en/default/hook/admin/sanitycheck/messages-statuses.html.tmpl
Websites/bugs.webkit.org/extensions/Example/template/en/default/hook/global/footer-end.html.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/Example/template/en/default/hook/global/setting-descs-settings.none.tmpl
Websites/bugs.webkit.org/extensions/Example/template/en/default/hook/global/user-error-errors.html.tmpl
Websites/bugs.webkit.org/extensions/Example/template/en/default/hook/search/tabs-search_tabs.html.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/Example/template/en/default/pages/example.html.tmpl
Websites/bugs.webkit.org/extensions/Example/template/en/default/setup/strings.txt.pl
Websites/bugs.webkit.org/extensions/MoreBugUrl/Config.pm [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/MoreBugUrl/Extension.pm [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/MoreBugUrl/disabled [moved from Websites/bugs.webkit.org/data/mail with 100% similarity]
Websites/bugs.webkit.org/extensions/MoreBugUrl/lib/BitBucket.pm [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/MoreBugUrl/lib/GetSatisfaction.pm [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/MoreBugUrl/lib/PHP.pm [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/MoreBugUrl/lib/RT.pm [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/MoreBugUrl/lib/Redmine.pm [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/MoreBugUrl/lib/ReviewBoard.pm [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/MoreBugUrl/lib/Rietveld.pm [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/MoreBugUrl/lib/Savane.pm [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/MoreBugUrl/template/en/default/hook/global/user-error-bug_url_invalid_tracker.html.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/OldBugMove/Config.pm
Websites/bugs.webkit.org/extensions/OldBugMove/Extension.pm
Websites/bugs.webkit.org/extensions/OldBugMove/lib/Params.pm
Websites/bugs.webkit.org/extensions/OldBugMove/template/en/default/admin/params/oldbugmove.html.tmpl
Websites/bugs.webkit.org/extensions/OldBugMove/template/en/default/hook/bug/edit-after_comment_textarea.html.tmpl
Websites/bugs.webkit.org/extensions/OldBugMove/template/en/default/hook/bug/format_comment-type.txt.tmpl
Websites/bugs.webkit.org/extensions/OldBugMove/template/en/default/hook/global/user-error-auth_failure_action.html.tmpl
Websites/bugs.webkit.org/extensions/OldBugMove/template/en/default/hook/global/user-error-errors.html.tmpl
Websites/bugs.webkit.org/extensions/OldBugMove/template/en/default/hook/list/edit-multiple-after_groups.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/Config.pm
Websites/bugs.webkit.org/extensions/Voting/Extension.pm
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/account/prefs/email-relationships.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/admin/products/edit-common-rows.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/admin/products/updated-changes.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/admin/sanitycheck/messages-statuses.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/admin/users/confirm-delete-warn_safe.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/bug/edit-after_importance.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/bug/format_comment-type.txt.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/bug/process/header-title.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/bug/process/results-title.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/bug/show-header-end.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/global/code-error-errors.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/global/field-descs-end.none.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/global/messages-messages.html.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/global/reason-descs-end.none.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/global/user-error-errors.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/search/form-after_freetext_fields.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/hook/search/search-report-select-rep_fields.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/pages/voting.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/pages/voting/bug.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/pages/voting/user.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/voting/delete-all.html.tmpl
Websites/bugs.webkit.org/extensions/Voting/template/en/default/voting/votes-removed.txt.tmpl
Websites/bugs.webkit.org/extensions/Voting/web/style.css
Websites/bugs.webkit.org/extensions/create.pl
Websites/bugs.webkit.org/images/csv.png [new file with mode: 0644]
Websites/bugs.webkit.org/images/ical.png [new file with mode: 0644]
Websites/bugs.webkit.org/images/rss.png [new file with mode: 0644]
Websites/bugs.webkit.org/images/rss_small.png [new file with mode: 0644]
Websites/bugs.webkit.org/images/xml.png [new file with mode: 0644]
Websites/bugs.webkit.org/importxml.pl
Websites/bugs.webkit.org/index.cgi
Websites/bugs.webkit.org/install-module.pl
Websites/bugs.webkit.org/jobqueue.pl
Websites/bugs.webkit.org/js/TUI.js
Websites/bugs.webkit.org/js/attachment.js
Websites/bugs.webkit.org/js/bug.js
Websites/bugs.webkit.org/js/change-columns.js
Websites/bugs.webkit.org/js/comment-tagging.js [new file with mode: 0644]
Websites/bugs.webkit.org/js/comments.js
Websites/bugs.webkit.org/js/custom-search.js
Websites/bugs.webkit.org/js/expanding-tree.js
Websites/bugs.webkit.org/js/field.js
Websites/bugs.webkit.org/js/flag.js
Websites/bugs.webkit.org/js/global.js
Websites/bugs.webkit.org/js/params.js
Websites/bugs.webkit.org/js/productform.js
Websites/bugs.webkit.org/js/util.js
Websites/bugs.webkit.org/jsonrpc.cgi
Websites/bugs.webkit.org/lib/.htaccess
Websites/bugs.webkit.org/migrate.pl
Websites/bugs.webkit.org/mod_perl.pl
Websites/bugs.webkit.org/page.cgi
Websites/bugs.webkit.org/post_bug.cgi
Websites/bugs.webkit.org/process_bug.cgi
Websites/bugs.webkit.org/query.cgi
Websites/bugs.webkit.org/quips.cgi
Websites/bugs.webkit.org/relogin.cgi
Websites/bugs.webkit.org/report.cgi
Websites/bugs.webkit.org/reports.cgi
Websites/bugs.webkit.org/request.cgi
Websites/bugs.webkit.org/rest.cgi [new file with mode: 0755]
Websites/bugs.webkit.org/runtests.pl
Websites/bugs.webkit.org/sanitycheck.cgi
Websites/bugs.webkit.org/sanitycheck.pl
Websites/bugs.webkit.org/search_plugin.cgi
Websites/bugs.webkit.org/show_activity.cgi
Websites/bugs.webkit.org/show_bug.cgi
Websites/bugs.webkit.org/showdependencygraph.cgi
Websites/bugs.webkit.org/showdependencytree.cgi
Websites/bugs.webkit.org/skins/README
Websites/bugs.webkit.org/skins/contrib/Dusk/buglist.css
Websites/bugs.webkit.org/skins/contrib/Dusk/global.css
Websites/bugs.webkit.org/skins/contrib/Dusk/index.css [deleted file]
Websites/bugs.webkit.org/skins/standard/IE-fixes.css [deleted file]
Websites/bugs.webkit.org/skins/standard/admin.css
Websites/bugs.webkit.org/skins/standard/attachment.css [deleted file]
Websites/bugs.webkit.org/skins/standard/bug.css [new file with mode: 0644]
Websites/bugs.webkit.org/skins/standard/buglist.css
Websites/bugs.webkit.org/skins/standard/dependency-tree.css [deleted file]
Websites/bugs.webkit.org/skins/standard/duplicates.css [deleted file]
Websites/bugs.webkit.org/skins/standard/editusers.css [deleted file]
Websites/bugs.webkit.org/skins/standard/enter_bug.css [deleted file]
Websites/bugs.webkit.org/skins/standard/global.css
Websites/bugs.webkit.org/skins/standard/index.css [deleted file]
Websites/bugs.webkit.org/skins/standard/page.css [deleted file]
Websites/bugs.webkit.org/skins/standard/params.css [deleted file]
Websites/bugs.webkit.org/skins/standard/reports.css [deleted file]
Websites/bugs.webkit.org/skins/standard/search_form.css [deleted file]
Websites/bugs.webkit.org/skins/standard/show_bug.css [deleted file]
Websites/bugs.webkit.org/skins/standard/show_multiple.css [deleted file]
Websites/bugs.webkit.org/skins/standard/summarize-time.css [deleted file]
Websites/bugs.webkit.org/summarize_time.cgi
Websites/bugs.webkit.org/t/.htaccess
Websites/bugs.webkit.org/t/001compile.t
Websites/bugs.webkit.org/t/002goodperl.t
Websites/bugs.webkit.org/t/003safesys.t
Websites/bugs.webkit.org/t/004template.t
Websites/bugs.webkit.org/t/005whitespace.t
Websites/bugs.webkit.org/t/006spellcheck.t
Websites/bugs.webkit.org/t/007util.t
Websites/bugs.webkit.org/t/008filter.t
Websites/bugs.webkit.org/t/009bugwords.t
Websites/bugs.webkit.org/t/010dependencies.t
Websites/bugs.webkit.org/t/011pod.t
Websites/bugs.webkit.org/t/012throwables.t
Websites/bugs.webkit.org/t/013dbschema.t [new file with mode: 0644]
Websites/bugs.webkit.org/t/Support/Files.pm
Websites/bugs.webkit.org/t/Support/Systemexec.pm
Websites/bugs.webkit.org/t/Support/Templates.pm
Websites/bugs.webkit.org/taskgraph.json [new file with mode: 0644]
Websites/bugs.webkit.org/template/.htaccess
Websites/bugs.webkit.org/template/en/default/account/auth/login-small.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/auth/login.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/cancel-token.txt.tmpl
Websites/bugs.webkit.org/template/en/default/account/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/created.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/email/change-new.txt.tmpl
Websites/bugs.webkit.org/template/en/default/account/email/change-old.txt.tmpl
Websites/bugs.webkit.org/template/en/default/account/email/confirm-new.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/email/confirm.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/email/request-new.txt.tmpl
Websites/bugs.webkit.org/template/en/default/account/password/forgotten-password.txt.tmpl
Websites/bugs.webkit.org/template/en/default/account/password/set-forgotten-password.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/prefs/account.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/prefs/apikey.html.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/account/prefs/email.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/prefs/permissions.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/prefs/prefs.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/prefs/saved-searches.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/prefs/settings.html.tmpl
Websites/bugs.webkit.org/template/en/default/account/profile-activity.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/admin.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/classifications/add.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/classifications/del.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/classifications/edit-common.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/classifications/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/classifications/footer.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/classifications/reclassify.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/classifications/select.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/components/confirm-delete.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/components/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/components/edit-common.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/components/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/components/footer.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/components/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/components/select-product.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/confirm-action.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/custom_fields/cf-js.js.tmpl
Websites/bugs.webkit.org/template/en/default/admin/custom_fields/confirm-delete.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/custom_fields/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/custom_fields/edit-common.html.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/admin/custom_fields/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/custom_fields/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/fieldvalues/confirm-delete.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/fieldvalues/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/fieldvalues/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/fieldvalues/footer.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/fieldvalues/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/fieldvalues/select-field.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/flag-type/confirm-delete.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/flag-type/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/flag-type/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/groups/confirm-remove.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/groups/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/groups/delete.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/groups/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/groups/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/keywords/confirm-delete.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/keywords/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/keywords/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/keywords/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/milestones/confirm-delete.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/milestones/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/milestones/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/milestones/footer.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/milestones/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/milestones/select-product.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/admin.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/advanced.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/attachment.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/auth.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/bugchange.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/bugfields.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/common.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/core.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/dependencygraph.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/editparams.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/general.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/groupsecurity.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/index.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/ldap.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/memcached.html.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/admin/params/mta.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/patchviewer.html.tmpl [deleted file]
Websites/bugs.webkit.org/template/en/default/admin/params/query.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/radius.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/shadowdb.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/params/usermatch.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/products/confirm-delete.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/products/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/products/edit-common.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/products/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/products/footer.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/products/groupcontrol/confirm-edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/products/groupcontrol/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/products/groupcontrol/updated.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/products/list-classifications.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/products/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/products/updated.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/sanitycheck/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/sanitycheck/messages.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/settings/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/sudo.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/table.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/users/confirm-delete.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/users/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/users/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/users/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/users/listselectvars.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/users/responsibilities.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/users/search.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/users/userdata.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/versions/confirm-delete.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/versions/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/versions/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/versions/footer.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/versions/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/versions/select-product.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/workflow/comment.html.tmpl
Websites/bugs.webkit.org/template/en/default/admin/workflow/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/choose.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/confirm-delete.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/created.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/createformcontents.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/delete_reason.txt.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/diff-file.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/diff-footer.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/diff-header.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/midair.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/show-multiple.html.tmpl
Websites/bugs.webkit.org/template/en/default/attachment/updated.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/activity/show.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/activity/table.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/choose.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/comment.html.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/bug/comments.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/create/comment-guided.txt.tmpl
Websites/bugs.webkit.org/template/en/default/bug/create/comment.txt.tmpl
Websites/bugs.webkit.org/template/en/default/bug/create/create-guided.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/create/create.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/create/created.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/create/make-template.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/create/user-message.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/dependency-graph.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/dependency-tree.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/edit.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/field-events.js.tmpl
Websites/bugs.webkit.org/template/en/default/bug/field-help.none.tmpl
Websites/bugs.webkit.org/template/en/default/bug/field-label.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/field.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/format_comment.txt.tmpl
Websites/bugs.webkit.org/template/en/default/bug/knob.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/link.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/navigate.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/process/bugmail.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/process/confirm-duplicate.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/process/header.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/process/midair.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/process/results.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/process/verify-new-product.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/show-header.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/show-multiple.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/show.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/show.xml.tmpl
Websites/bugs.webkit.org/template/en/default/bug/summarize-time.html.tmpl
Websites/bugs.webkit.org/template/en/default/bug/time.html.tmpl
Websites/bugs.webkit.org/template/en/default/config.js.tmpl
Websites/bugs.webkit.org/template/en/default/config.rdf.tmpl
Websites/bugs.webkit.org/template/en/default/email/bugmail-common.txt.tmpl
Websites/bugs.webkit.org/template/en/default/email/bugmail-header.txt.tmpl
Websites/bugs.webkit.org/template/en/default/email/bugmail.html.tmpl
Websites/bugs.webkit.org/template/en/default/email/bugmail.txt.tmpl
Websites/bugs.webkit.org/template/en/default/email/flagmail.txt.tmpl [moved from Websites/bugs.webkit.org/template/en/default/request/email.txt.tmpl with 67% similarity]
Websites/bugs.webkit.org/template/en/default/email/header-common.txt.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/email/lockout.txt.tmpl
Websites/bugs.webkit.org/template/en/default/email/new-api-key.txt.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/email/new-user-details.txt.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/email/sanitycheck.txt.tmpl
Websites/bugs.webkit.org/template/en/default/email/sudo.txt.tmpl
Websites/bugs.webkit.org/template/en/default/email/whine.txt.tmpl
Websites/bugs.webkit.org/template/en/default/extensions/config.pm.tmpl
Websites/bugs.webkit.org/template/en/default/extensions/extension.pm.tmpl
Websites/bugs.webkit.org/template/en/default/extensions/hook-readme.txt.tmpl
Websites/bugs.webkit.org/template/en/default/extensions/index-admin.rst.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/extensions/index-user.rst.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/extensions/license.txt.tmpl
Websites/bugs.webkit.org/template/en/default/extensions/name-readme.txt.tmpl
Websites/bugs.webkit.org/template/en/default/extensions/util.pm.tmpl
Websites/bugs.webkit.org/template/en/default/extensions/web-readme.txt.tmpl
Websites/bugs.webkit.org/template/en/default/filterexceptions.pl
Websites/bugs.webkit.org/template/en/default/flag/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/banner.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/calendar.js.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/global/choose-classification.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/choose-product.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/code-error.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/common-links.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/confirm-action.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/confirm-user-match.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/docslinks.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/field-descs.none.tmpl
Websites/bugs.webkit.org/template/en/default/global/footer.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/header.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/help.html.tmpl [deleted file]
Websites/bugs.webkit.org/template/en/default/global/hidden-fields.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/initialize.none.tmpl [deleted file]
Websites/bugs.webkit.org/template/en/default/global/js-products.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/message.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/message.txt.tmpl
Websites/bugs.webkit.org/template/en/default/global/messages.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/per-bug-queries.html.tmpl [deleted file]
Websites/bugs.webkit.org/template/en/default/global/product-select.html.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/global/reason-descs.none.tmpl
Websites/bugs.webkit.org/template/en/default/global/select-menu.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/setting-descs.none.tmpl
Websites/bugs.webkit.org/template/en/default/global/site-navigation.html.tmpl [deleted file]
Websites/bugs.webkit.org/template/en/default/global/tabs.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/textarea.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/useful-links.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/user-error.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/user.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/userselect.html.tmpl
Websites/bugs.webkit.org/template/en/default/global/value-descs.js.tmpl
Websites/bugs.webkit.org/template/en/default/global/value-descs.none.tmpl
Websites/bugs.webkit.org/template/en/default/global/variables.none.tmpl
Websites/bugs.webkit.org/template/en/default/index.html.tmpl
Websites/bugs.webkit.org/template/en/default/list/change-columns.html.tmpl
Websites/bugs.webkit.org/template/en/default/list/edit-multiple.html.tmpl
Websites/bugs.webkit.org/template/en/default/list/list-simple.html.tmpl
Websites/bugs.webkit.org/template/en/default/list/list.atom.tmpl
Websites/bugs.webkit.org/template/en/default/list/list.csv.tmpl
Websites/bugs.webkit.org/template/en/default/list/list.html.tmpl
Websites/bugs.webkit.org/template/en/default/list/list.ics.tmpl
Websites/bugs.webkit.org/template/en/default/list/list.rdf.tmpl
Websites/bugs.webkit.org/template/en/default/list/quips.html.tmpl
Websites/bugs.webkit.org/template/en/default/list/server-push.html.tmpl
Websites/bugs.webkit.org/template/en/default/list/table.html.tmpl
Websites/bugs.webkit.org/template/en/default/pages/bug-writing.html.tmpl
Websites/bugs.webkit.org/template/en/default/pages/bugzilla.dtd.tmpl [moved from Websites/bugs.webkit.org/bugzilla.dtd with 55% similarity]
Websites/bugs.webkit.org/template/en/default/pages/fields.html.tmpl
Websites/bugs.webkit.org/template/en/default/pages/linked.html.tmpl
Websites/bugs.webkit.org/template/en/default/pages/linkify.html.tmpl
Websites/bugs.webkit.org/template/en/default/pages/quicksearch.html.tmpl
Websites/bugs.webkit.org/template/en/default/pages/release-notes.html.tmpl
Websites/bugs.webkit.org/template/en/default/pages/release-notes3.html.tmpl [deleted file]
Websites/bugs.webkit.org/template/en/default/pages/sudo.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/chart.csv.tmpl
Websites/bugs.webkit.org/template/en/default/reports/chart.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/chart.png.tmpl
Websites/bugs.webkit.org/template/en/default/reports/components.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/create-chart.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/delete-series.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/duplicates-simple.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/duplicates-table.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/duplicates.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/edit-series.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/keywords.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/menu.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/old-charts.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/report-bar.png.tmpl
Websites/bugs.webkit.org/template/en/default/reports/report-line.png.tmpl
Websites/bugs.webkit.org/template/en/default/reports/report-pie.png.tmpl
Websites/bugs.webkit.org/template/en/default/reports/report-simple.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/report-table.csv.tmpl
Websites/bugs.webkit.org/template/en/default/reports/report-table.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/report.csv.tmpl
Websites/bugs.webkit.org/template/en/default/reports/report.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/series-common.html.tmpl
Websites/bugs.webkit.org/template/en/default/reports/series.html.tmpl
Websites/bugs.webkit.org/template/en/default/request/queue.csv.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/request/queue.html.tmpl
Websites/bugs.webkit.org/template/en/default/rest.html.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/search/boolean-charts.html.tmpl
Websites/bugs.webkit.org/template/en/default/search/field.html.tmpl
Websites/bugs.webkit.org/template/en/default/search/form.html.tmpl
Websites/bugs.webkit.org/template/en/default/search/knob.html.tmpl
Websites/bugs.webkit.org/template/en/default/search/search-advanced.html.tmpl
Websites/bugs.webkit.org/template/en/default/search/search-create-series.html.tmpl
Websites/bugs.webkit.org/template/en/default/search/search-plugin.xml.tmpl
Websites/bugs.webkit.org/template/en/default/search/search-report-graph.html.tmpl
Websites/bugs.webkit.org/template/en/default/search/search-report-select.html.tmpl
Websites/bugs.webkit.org/template/en/default/search/search-report-table.html.tmpl
Websites/bugs.webkit.org/template/en/default/search/search-specific.html.tmpl
Websites/bugs.webkit.org/template/en/default/search/tabs.html.tmpl
Websites/bugs.webkit.org/template/en/default/search/type-select.html.tmpl
Websites/bugs.webkit.org/template/en/default/setup/strings.txt.pl
Websites/bugs.webkit.org/template/en/default/welcome-admin.html.tmpl
Websites/bugs.webkit.org/template/en/default/whine/header.txt.tmpl [new file with mode: 0644]
Websites/bugs.webkit.org/template/en/default/whine/mail.html.tmpl
Websites/bugs.webkit.org/template/en/default/whine/mail.txt.tmpl
Websites/bugs.webkit.org/template/en/default/whine/multipart-mime.txt.tmpl [deleted file]
Websites/bugs.webkit.org/template/en/default/whine/schedule.html.tmpl
Websites/bugs.webkit.org/testagent.cgi
Websites/bugs.webkit.org/testserver.pl
Websites/bugs.webkit.org/token.cgi
Websites/bugs.webkit.org/userprefs.cgi
Websites/bugs.webkit.org/votes.cgi
Websites/bugs.webkit.org/whine.pl
Websites/bugs.webkit.org/whineatnews.pl
Websites/bugs.webkit.org/xmlrpc.cgi
Websites/bugs.webkit.org/xt/.htaccess
Websites/bugs.webkit.org/xt/lib/Bugzilla/Test/Search.pm
Websites/bugs.webkit.org/xt/lib/Bugzilla/Test/Search/AndTest.pm
Websites/bugs.webkit.org/xt/lib/Bugzilla/Test/Search/Constants.pm
Websites/bugs.webkit.org/xt/lib/Bugzilla/Test/Search/CustomTest.pm
Websites/bugs.webkit.org/xt/lib/Bugzilla/Test/Search/FieldTest.pm
Websites/bugs.webkit.org/xt/lib/Bugzilla/Test/Search/FieldTestNormal.pm
Websites/bugs.webkit.org/xt/lib/Bugzilla/Test/Search/InjectionTest.pm
Websites/bugs.webkit.org/xt/lib/Bugzilla/Test/Search/NotTest.pm
Websites/bugs.webkit.org/xt/lib/Bugzilla/Test/Search/OperatorTest.pm
Websites/bugs.webkit.org/xt/lib/Bugzilla/Test/Search/OrTest.pm
Websites/bugs.webkit.org/xt/search.t

index 7ab83e7..4b27e57 100644 (file)
@@ -1,10 +1,7 @@
-.htaccess
 /lib/*
 /template/en/custom
-/docs/bugzilla.ent
-/docs/en/xml/bugzilla.ent
-/docs/en/txt
 /docs/en/html
+/docs/en/txt
 /docs/en/pdf
 /skins/custom
 /graphs
@@ -12,21 +9,5 @@
 /localconfig
 /index.html
 
-/skins/contrib/Dusk/IE-fixes.css
 /skins/contrib/Dusk/admin.css
-/skins/contrib/Dusk/attachment.css
-/skins/contrib/Dusk/create_attachment.css
-/skins/contrib/Dusk/dependency-tree.css
-/skins/contrib/Dusk/duplicates.css
-/skins/contrib/Dusk/editusers.css
-/skins/contrib/Dusk/enter_bug.css
-/skins/contrib/Dusk/help.css
-/skins/contrib/Dusk/panel.css
-/skins/contrib/Dusk/page.css
-/skins/contrib/Dusk/params.css
-/skins/contrib/Dusk/reports.css
-/skins/contrib/Dusk/show_bug.css
-/skins/contrib/Dusk/search_form.css
-/skins/contrib/Dusk/show_multiple.css
-/skins/contrib/Dusk/summarize-time.css
-.DS_Store
+/skins/contrib/Dusk/bug.css
index 7ab83e7..ba98f70 100644 (file)
@@ -1,10 +1,8 @@
-.htaccess
+/**/.htaccess
 /lib/*
 /template/en/custom
-/docs/bugzilla.ent
-/docs/en/xml/bugzilla.ent
-/docs/en/txt
 /docs/en/html
+/docs/en/txt
 /docs/en/pdf
 /skins/custom
 /graphs
 /localconfig
 /index.html
 
-/skins/contrib/Dusk/IE-fixes.css
 /skins/contrib/Dusk/admin.css
-/skins/contrib/Dusk/attachment.css
-/skins/contrib/Dusk/create_attachment.css
-/skins/contrib/Dusk/dependency-tree.css
-/skins/contrib/Dusk/duplicates.css
-/skins/contrib/Dusk/editusers.css
-/skins/contrib/Dusk/enter_bug.css
-/skins/contrib/Dusk/help.css
-/skins/contrib/Dusk/panel.css
-/skins/contrib/Dusk/page.css
-/skins/contrib/Dusk/params.css
-/skins/contrib/Dusk/reports.css
-/skins/contrib/Dusk/show_bug.css
-/skins/contrib/Dusk/search_form.css
-/skins/contrib/Dusk/show_multiple.css
-/skins/contrib/Dusk/summarize-time.css
-.DS_Store
+/skins/contrib/Dusk/bug.css
index e9d88de..e2746f6 100644 (file)
@@ -1,7 +1,20 @@
 # Don't allow people to retrieve non-cgi executable files or our private data
-<FilesMatch ^(lib|.*\.pm|.*\.pl|.*localconfig.*)$>
-  deny from all
+<FilesMatch (\.pm|\.pl|\.tmpl|localconfig.*)$>
+  <IfModule mod_version.c>
+    <IfVersion < 2.4>
+      Deny from all
+    </IfVersion>
+    <IfVersion >= 2.4>
+      Require all denied
+    </IfVersion>
+  </IfModule>
+  <IfModule !mod_version.c>
+    Deny from all
+  </IfModule>
 </FilesMatch>
+
+Options -Indexes
+
 <IfModule mod_expires.c>
 <IfModule mod_headers.c>
 <IfModule mod_env.c>
 </IfModule>
 </IfModule>
 
+<IfModule mod_rewrite.c>
+  RewriteEngine On
+  RewriteOptions inherit
+  RewriteRule ^rest/(.*)$ rest.cgi/$1 [NE]
+</IfModule>
+
 # Force all connections to HTTPS for 90 days at a time.
 <IfModule mod_headers.c>
   Header set Strict-Transport-Security "max-age=7776000"
diff --git a/Websites/bugs.webkit.org/.travis.yml b/Websites/bugs.webkit.org/.travis.yml
deleted file mode 100644 (file)
index 68e2b47..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-language: perl
-perl:
-  - 5.10
-  - 5.12
-
-env:
-  - TEST_SUITE=sanity
-  - TEST_SUITE=docs
-  - TEST_SUITE=webservices DB=mysql
-  - TEST_SUITE=selenium DB=mysql
-  - TEST_SUITE=webservices DB=pg
-  - TEST_SUITE=selenium DB=pg
-
-matrix:
-  exclude:
-    - perl: 5.12
-      env: TEST_SUITE=docs
-    - perl: 5.10
-      env: TEST_SUITE=webservices DB=mysql
-    - perl: 5.12
-      env: TEST_SUITE=selenium DB=mysql
-    - perl: 5.10
-      env: TEST_SUITE=webservices DB=pg
-    - perl: 5.12
-      env: TEST_SUITE=selenium DB=pg
-
-before_install:
-  - git clone https://github.com/bugzilla/qa.git -b 4.2 qa
-
-install: true
-
-script: ./qa/travis.sh
-
-after_failure:
-  - sudo cat /var/log/apache2/error.log
-
-notifications:
-  irc:
-    channels:
-      - "irc.mozilla.org#qa-bugzilla"
-      - "irc.mozilla.org#bugzilla"
-    template:
-      - "Bugzilla %{branch} : %{author} : %{message}"
-      - "Commit Message : %{commit_message}"
-      - "Commit Link : %{compare_url}"
-      - "Build Link : %{build_url}"
-  on_success: change
-  on_failure: always
index 5b39e4c..e4772e0 100644 (file)
@@ -1,30 +1,15 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# The Initial Developer of the Original Code is Netscape Communications
-# Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All
-# Rights Reserved.
-#
-# Contributor(s): Bradley Baetz <bbaetz@student.usyd.edu.au>
-#                 Erik Stambaugh <erik@dasbistro.com>
-#                 A. Karl Kornel <karl@kornel.name>
-#                 Marc Schumann <wurblzap@gmail.com>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla;
 
+use 5.10.1;
 use strict;
+use warnings;
 
 # We want any compile errors to get to the browser, if possible.
 BEGIN {
@@ -35,23 +20,24 @@ BEGIN {
     }
 }
 
-use Bugzilla::Config;
-use Bugzilla::Constants;
 use Bugzilla::Auth;
 use Bugzilla::Auth::Persist::Cookie;
 use Bugzilla::CGI;
-use Bugzilla::Extension;
+use Bugzilla::Config;
+use Bugzilla::Constants;
 use Bugzilla::DB;
-use Bugzilla::Install::Localconfig qw(read_localconfig);
-use Bugzilla::Install::Requirements qw(OPTIONAL_MODULES);
-use Bugzilla::Install::Util qw(init_console);
-use Bugzilla::Template;
-use Bugzilla::User;
 use Bugzilla::Error;
-use Bugzilla::Util;
+use Bugzilla::Extension;
 use Bugzilla::Field;
 use Bugzilla::Flag;
+use Bugzilla::Install::Localconfig qw(read_localconfig);
+use Bugzilla::Install::Requirements qw(OPTIONAL_MODULES have_vers);
+use Bugzilla::Install::Util qw(init_console include_languages);
+use Bugzilla::Memcached;
+use Bugzilla::Template;
 use Bugzilla::Token;
+use Bugzilla::User;
+use Bugzilla::Util;
 
 use File::Basename;
 use File::Spec::Functions;
@@ -84,7 +70,7 @@ use constant SHUTDOWNHTML_RETRY_AFTER => 3600;
 # Global Code
 #####################################################################
 
-# $::SIG{__DIE__} = i_am_cgi() ? \&CGI::Carp::confess : \&Carp::confess;
+#$::SIG{__DIE__} = i_am_cgi() ? \&CGI::Carp::confess : \&Carp::confess;
 
 # Note that this is a raw subroutine, not a method, so $class isn't available.
 sub init_page {
@@ -96,11 +82,28 @@ sub init_page {
     }
 
     if (${^TAINT}) {
+        my $path = '';
+        if (ON_WINDOWS) {
+            # On Windows, these paths are tainted, preventing
+            # File::Spec::Win32->tmpdir from using them. But we need
+            # a place to temporary store attachments which are uploaded.
+            foreach my $temp (qw(TMPDIR TMP TEMP WINDIR)) {
+                trick_taint($ENV{$temp}) if $ENV{$temp};
+            }
+            # Some DLLs used by Strawberry Perl are also in c\bin,
+            # see https://rt.cpan.org/Public/Bug/Display.html?id=99104
+            if (!ON_ACTIVESTATE) {
+                my $c_path = $path = dirname($^X);
+                $c_path =~ s/\bperl\b(?=\\bin)/c/;
+                $path .= ";$c_path";
+                trick_taint($path);
+            }
+        }
         # Some environment variables are not taint safe
         delete @::ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
         # Some modules throw undefined errors (notably File::Spec::Win32) if
         # PATH is undefined.
-        $ENV{'PATH'} = '';
+        $ENV{'PATH'} = $path;
     }
 
     # Because this function is run live from perl "use" commands of
@@ -136,8 +139,8 @@ sub init_page {
     #
     # This code must go here. It cannot go anywhere in Bugzilla::CGI, because
     # it uses Template, and that causes various dependency loops.
-    if (Bugzilla->params->{"shutdownhtml"}
-        && !grep { $_ eq $script } SHUTDOWNHTML_EXEMPT)
+    if (!grep { $_ eq $script } SHUTDOWNHTML_EXEMPT
+        and Bugzilla->params->{'shutdownhtml'})
     {
         # Allow non-cgi scripts to exit silently (without displaying any
         # message), if desired. At this point, no DBI call has been made
@@ -180,10 +183,8 @@ sub init_page {
             print Bugzilla->cgi->header(-status => 503, 
                 -retry_after => SHUTDOWNHTML_RETRY_AFTER);
         }
-        my $t_output;
-        $template->process("global/message.$extension.tmpl", $vars, \$t_output)
+        $template->process("global/message.$extension.tmpl", $vars)
             || ThrowTemplateError($template->error);
-        print $t_output . "\n";
         exit;
     }
 }
@@ -193,9 +194,7 @@ sub init_page {
 #####################################################################
 
 sub template {
-    my $class = shift;
-    $class->request_cache->{template} ||= Bugzilla::Template->create();
-    return $class->request_cache->{template};
+    return $_[0]->request_cache->{template} ||= Bugzilla::Template->create();
 }
 
 sub template_inner {
@@ -203,9 +202,7 @@ sub template_inner {
     my $cache = $class->request_cache;
     my $current_lang = $cache->{template_current_lang}->[0];
     $lang ||= $current_lang || '';
-    $class->request_cache->{"template_inner_$lang"}
-        ||= Bugzilla::Template->create(language => $lang);
-    return $class->request_cache->{"template_inner_$lang"};
+    return $cache->{"template_inner_$lang"} ||= Bugzilla::Template->create(language => $lang);
 }
 
 our $extension_packages;
@@ -240,7 +237,7 @@ sub feature {
         foreach my $package (@{ OPTIONAL_MODULES() }) {
             foreach my $f (@{ $package->{feature} }) {
                 $feature_map->{$f} ||= [];
-                push(@{ $feature_map->{$f} }, $package->{module});
+                push(@{ $feature_map->{$f} }, $package);
             }
         }
         $cache->{feature_map} = $feature_map;
@@ -251,22 +248,15 @@ sub feature {
     }
 
     my $success = 1;
-    foreach my $module (@{ $feature_map->{$feature} }) {
-        # We can't use a string eval and "use" here (it kills Template-Toolkit,
-        # see https://rt.cpan.org/Public/Bug/Display.html?id=47929), so we have
-        # to do a block eval.
-        $module =~ s{::}{/}g;
-        $module .= ".pm";
-        eval { require $module; 1; } or $success = 0;
+    foreach my $package (@{ $feature_map->{$feature} }) {
+        have_vers($package) or $success = 0;
     }
     $cache->{feature}->{$feature} = $success;
     return $success;
 }
 
 sub cgi {
-    my $class = shift;
-    $class->request_cache->{cgi} ||= new Bugzilla::CGI();
-    return $class->request_cache->{cgi};
+    return $_[0]->request_cache->{cgi} ||= new Bugzilla::CGI();
 }
 
 sub input_params {
@@ -286,21 +276,15 @@ sub input_params {
 }
 
 sub localconfig {
-    my $class = shift;
-    $class->request_cache->{localconfig} ||= read_localconfig();
-    return $class->request_cache->{localconfig};
+    return $_[0]->process_cache->{localconfig} ||= read_localconfig();
 }
 
 sub params {
-    my $class = shift;
-    $class->request_cache->{params} ||= Bugzilla::Config::read_param_file();
-    return $class->request_cache->{params};
+    return $_[0]->request_cache->{params} ||= Bugzilla::Config::read_param_file();
 }
 
 sub user {
-    my $class = shift;
-    $class->request_cache->{user} ||= new Bugzilla::User;
-    return $class->request_cache->{user};
+    return $_[0]->request_cache->{user} ||= new Bugzilla::User;
 }
 
 sub set_user {
@@ -309,8 +293,7 @@ sub set_user {
 }
 
 sub sudoer {
-    my $class = shift;    
-    return $class->request_cache->{sudoer};
+    return $_[0]->request_cache->{sudoer};
 }
 
 sub sudo_request {
@@ -388,6 +371,12 @@ sub login {
         $class->set_user($authenticated_user);
     }
 
+    if ($class->sudoer) {
+        $class->sudoer->update_last_seen_date();
+    } else {
+        $class->user->update_last_seen_date();
+    }
+
     return $class->user;
 }
 
@@ -426,38 +415,40 @@ sub logout_request {
 }
 
 sub job_queue {
-    my $class = shift;
     require Bugzilla::JobQueue;
-    $class->request_cache->{job_queue} ||= Bugzilla::JobQueue->new();
-    return $class->request_cache->{job_queue};
+    return $_[0]->request_cache->{job_queue} ||= Bugzilla::JobQueue->new();
 }
 
 sub dbh {
-    my $class = shift;
     # If we're not connected, then we must want the main db
-    $class->request_cache->{dbh} ||= $class->dbh_main;
-
-    return $class->request_cache->{dbh};
+    return $_[0]->request_cache->{dbh} ||= $_[0]->dbh_main;
 }
 
 sub dbh_main {
-    my $class = shift;
-    $class->request_cache->{dbh_main} ||= Bugzilla::DB::connect_main();
-    return $class->request_cache->{dbh_main};
+    return $_[0]->request_cache->{dbh_main} ||= Bugzilla::DB::connect_main();
 }
 
 sub languages {
-    my $class = shift;
     return Bugzilla::Install::Util::supported_languages();
 }
 
+sub current_language {
+    return $_[0]->request_cache->{current_language} ||= (include_languages())[0];
+}
+
 sub error_mode {
     my ($class, $newval) = @_;
     if (defined $newval) {
         $class->request_cache->{error_mode} = $newval;
     }
-    return $class->request_cache->{error_mode}
-        || (i_am_cgi() ? ERROR_MODE_WEBPAGE : ERROR_MODE_DIE);
+
+    # XXX - Once we require Perl 5.10.1, this test can be replaced by //.
+    if (exists $class->request_cache->{error_mode}) {
+        return $class->request_cache->{error_mode};
+    }
+    else {
+        return (i_am_cgi() ? ERROR_MODE_WEBPAGE : ERROR_MODE_DIE);
+    }
 }
 
 # This is used only by Bugzilla::Error to throw errors.
@@ -490,14 +481,23 @@ sub usage_mode {
         elsif ($newval == USAGE_MODE_TEST) {
             $class->error_mode(ERROR_MODE_TEST);
         }
+        elsif ($newval == USAGE_MODE_REST) {
+            $class->error_mode(ERROR_MODE_REST);
+        }
         else {
             ThrowCodeError('usage_mode_invalid',
                            {'invalid_usage_mode', $newval});
         }
         $class->request_cache->{usage_mode} = $newval;
     }
-    return $class->request_cache->{usage_mode}
-        || (i_am_cgi()? USAGE_MODE_BROWSER : USAGE_MODE_CMDLINE);
+
+    # XXX - Once we require Perl 5.10.1, this test can be replaced by //.
+    if (exists $class->request_cache->{usage_mode}) {
+        return $class->request_cache->{usage_mode};
+    }
+    else {
+        return (i_am_cgi()? USAGE_MODE_BROWSER : USAGE_MODE_CMDLINE);
+    }
 }
 
 sub installation_mode {
@@ -547,6 +547,11 @@ sub switch_to_main_db {
     return $class->dbh_main;
 }
 
+sub is_shadow_db {
+    my $class = shift;
+    return $class->request_cache->{dbh} != $class->dbh_main;
+}
+
 sub fields {
     my ($class, $criteria) = @_;
     $criteria ||= {};
@@ -615,13 +620,8 @@ sub has_flags {
 }
 
 sub local_timezone {
-    my $class = shift;
-
-    if (!defined $class->request_cache->{local_timezone}) {
-        $class->request_cache->{local_timezone} =
-          DateTime::TimeZone->new(name => 'local');
-    }
-    return $class->request_cache->{local_timezone};
+    return $_[0]->process_cache->{local_timezone}
+             ||= DateTime::TimeZone->new(name => 'local');
 }
 
 # This creates the request cache for non-mod_perl installations.
@@ -642,19 +642,49 @@ sub request_cache {
     return $_request_cache;
 }
 
+sub clear_request_cache {
+    $_request_cache = {};
+    if ($ENV{MOD_PERL}) {
+        require Apache2::RequestUtil;
+        my $request = eval { Apache2::RequestUtil->request };
+        if ($request) {
+            my $pnotes = $request->pnotes;
+            delete @$pnotes{(keys %$pnotes)};
+        }
+    }
+}
+
+# This is a per-process cache.  Under mod_cgi it's identical to the
+# request_cache.  When using mod_perl, items in this cache live until the
+# worker process is terminated.
+our $_process_cache = {};
+
+sub process_cache {
+    return $_process_cache;
+}
+
+# This is a memcached wrapper, which provides cross-process and cross-system
+# caching.
+sub memcached {
+    return $_[0]->process_cache->{memcached} ||= Bugzilla::Memcached->_new();
+}
+
 # Private methods
 
 # Per-process cleanup. Note that this is a plain subroutine, not a method,
 # so we don't have $class available.
 sub _cleanup {
-    my $main   = Bugzilla->request_cache->{dbh_main};
-    my $shadow = Bugzilla->request_cache->{dbh_shadow};
+    my $cache = Bugzilla->request_cache;
+    my $main = $cache->{dbh_main};
+    my $shadow = $cache->{dbh_shadow};
     foreach my $dbh ($main, $shadow) {
         next if !$dbh;
         $dbh->bz_rollback_transaction() if $dbh->bz_in_transaction;
         $dbh->disconnect;
     }
-    undef $_request_cache;
+    my $smtp = $cache->{smtp};
+    $smtp->disconnect if $smtp;
+    clear_request_cache();
 
     # These are both set by CGI.pm but need to be undone so that
     # Apache can actually shut down its children if it needs to.
@@ -745,7 +775,7 @@ If you ever need a L<Bugzilla::Template> object while you're already
 processing a template, use this. Also use it if you want to specify
 the language to use. If no argument is passed, it uses the last
 language set. If the argument is "" (empty string), the language is
-reset to the current one (the one used by Bugzilla->template).
+reset to the current one (the one used by C<Bugzilla-E<gt>template>).
 
 =item C<cgi>
 
@@ -775,10 +805,10 @@ not an arrayref.
 
 =item C<user>
 
-C<undef> if there is no currently logged in user or if the login code has not
-yet been run.  If an sudo session is in progress, the C<Bugzilla::User>
-corresponding to the person who is being impersonated.  If no session is in
-progress, the current C<Bugzilla::User>.
+Default C<Bugzilla::User> object if there is no currently logged in user or
+if the login code has not yet been run.  If an sudo session is in progress,
+the C<Bugzilla::User> corresponding to the person who is being impersonated.
+If no session is in progress, the current C<Bugzilla::User>.
 
 =item C<set_user>
 
@@ -822,7 +852,7 @@ default), LOGOUT_ALL or LOGOUT_KEEP_CURRENT.
 
 =item C<logout_user($user)>
 
-Logs out the specified user (invalidating all his sessions), taking a
+Logs out the specified user (invalidating all their sessions), taking a
 Bugzilla::User instance.
 
 =item C<logout_by_id($id)>
@@ -863,8 +893,8 @@ specify this argument, all fields will be returned.
 
 =item C<error_mode>
 
-Call either C<Bugzilla->error_mode(Bugzilla::Constants::ERROR_MODE_DIE)>
-or C<Bugzilla->error_mode(Bugzilla::Constants::ERROR_MODE_DIE_SOAP_FAULT)> to
+Call either C<Bugzilla-E<gt>error_mode(Bugzilla::Constants::ERROR_MODE_DIE)>
+or C<Bugzilla-E<gt>error_mode(Bugzilla::Constants::ERROR_MODE_DIE_SOAP_FAULT)> to
 change this flag's default of C<Bugzilla::Constants::ERROR_MODE_WEBPAGE> and to
 indicate that errors should be passed to error mode specific error handlers
 rather than being sent to a browser and finished with an exit().
@@ -873,24 +903,24 @@ This is useful, for example, to keep C<eval> blocks from producing wild HTML
 on errors, making it easier for you to catch them.
 (Remember to reset the error mode to its previous value afterwards, though.)
 
-C<Bugzilla->error_mode> will return the current state of this flag.
+C<Bugzilla-E<gt>error_mode> will return the current state of this flag.
 
-Note that C<Bugzilla->error_mode> is being called by C<Bugzilla->usage_mode> on
+Note that C<Bugzilla-E<gt>error_mode> is being called by C<Bugzilla-E<gt>usage_mode> on
 usage mode changes.
 
 =item C<usage_mode>
 
-Call either C<Bugzilla->usage_mode(Bugzilla::Constants::USAGE_MODE_CMDLINE)>
-or C<Bugzilla->usage_mode(Bugzilla::Constants::USAGE_MODE_XMLRPC)> near the
+Call either C<Bugzilla-E<gt>usage_mode(Bugzilla::Constants::USAGE_MODE_CMDLINE)>
+or C<Bugzilla-E<gt>usage_mode(Bugzilla::Constants::USAGE_MODE_XMLRPC)> near the
 beginning of your script to change this flag's default of
 C<Bugzilla::Constants::USAGE_MODE_BROWSER> and to indicate that Bugzilla is
 being called in a non-interactive manner.
 
 This influences error handling because on usage mode changes, C<usage_mode>
-calls C<Bugzilla->error_mode> to set an error mode which makes sense for the
+calls C<Bugzilla-E<gt>error_mode> to set an error mode which makes sense for the
 usage mode.
 
-C<Bugzilla->usage_mode> will return the current state of this flag.
+C<Bugzilla-E<gt>usage_mode> will return the current state of this flag.
 
 =item C<installation_mode>
 
@@ -915,6 +945,10 @@ The main database handle. See L<DBI>.
 Currently installed languages.
 Returns a reference to a list of RFC 1766 language tags of installed languages.
 
+=item C<current_language>
+
+The currently active language.
+
 =item C<switch_to_shadow_db>
 
 Switch from using the main database to using the shadow database.
@@ -923,11 +957,17 @@ Switch from using the main database to using the shadow database.
 
 Change the database object to refer to the main database.
 
+=item C<is_shadow_db>
+
+Returns true if the currently active database is the shadow database.
+Returns false if a the currently active database is the man database, or if a
+shadow database is not configured or enabled.
+
 =item C<params>
 
-The current Parameters of Bugzilla, as a hashref. If C<data/params>
-does not exist, then we return an empty hashref. If C<data/params>
-is unreadable or is not valid perl, we C<die>.
+The current Parameters of Bugzilla, as a hashref. If C<data/params.json>
+does not exist, then we return an empty hashref. If C<data/params.json>
+is unreadable or is not valid, we C<die>.
 
 =item C<local_timezone>
 
@@ -947,3 +987,99 @@ Tells you whether or not a specific feature is enabled. For names
 of features, see C<OPTIONAL_MODULES> in C<Bugzilla::Install::Requirements>.
 
 =back
+
+=head1 B<CACHING>
+
+Bugzilla has several different caches available which provide different
+capabilities and lifetimes.
+
+The keys of all caches are unregulated; use of prefixes is suggested to avoid
+collisions.
+
+=over
+
+=item B<Request Cache>
+
+The request cache is a hashref which supports caching any perl variable for the
+duration of the current request. At the end of the current request the contents
+of this cache are cleared.
+
+Examples of its use include caching objects to avoid re-fetching the same data
+from the database, and passing data between otherwise unconnected parts of
+Bugzilla.
+
+=over
+
+=item C<request_cache>
+
+Returns a hashref which can be checked and modified to store any perl variable
+for the duration of the current request.
+
+=item C<clear_request_cache>
+
+Removes all entries from the C<request_cache>.
+
+=back
+
+=item B<Process Cache>
+
+The process cache is a hashref which support caching of any perl variable. If
+Bugzilla is configured to run using Apache mod_perl, the contents of this cache
+are persisted across requests for the lifetime of the Apache worker process
+(which varies depending on the SizeLimit configuration in mod_perl.pl).
+
+If Bugzilla isn't running under mod_perl, the process cache's contents are
+cleared at the end of the request.
+
+The process cache is only suitable for items which never change while Bugzilla
+is running (for example the path where Bugzilla is installed).
+
+=over
+
+=item C<process_cache>
+
+Returns a hashref which can be checked and modified to store any perl variable
+for the duration of the current process (mod_perl) or request (mod_cgi).
+
+=back
+
+=item B<Memcached>
+
+If Memcached is installed and configured, Bugzilla can use it to cache data
+across requests and between webheads. Unlike the request and process caches,
+only scalars, hashrefs, and arrayrefs can be stored in Memcached.
+
+Memcached integration is only required for large installations of Bugzilla -- if
+you have multiple webheads then configuring Memcached is recommended.
+
+=over
+
+=item C<memcached>
+
+Returns a C<Bugzilla::Memcached> object. An object is always returned even if
+Memcached is not available.
+
+See the documentation for the C<Bugzilla::Memcached> module for more
+information.
+
+=back
+
+=back
+
+=head1 B<Methods in need of POD>
+
+=over
+
+=item init_page
+
+=item extensions
+
+=item logout_user_by_id
+
+=item localconfig
+
+=item active_custom_fields
+
+=item has_flags
+
+=back
index 62adb57..dfd9cd5 100644 (file)
@@ -1,3 +1,13 @@
 # nothing in this directory is retrievable unless overridden by an .htaccess
 # in a subdirectory
-deny from all
+<IfModule mod_version.c>
+  <IfVersion < 2.4>
+    Deny from all
+  </IfVersion>
+  <IfVersion >= 2.4>
+    Require all denied
+  </IfVersion>
+</IfModule>
+<IfModule !mod_version.c>
+  Deny from all
+</IfModule>
index fa88453..3318379 100644 (file)
@@ -1,31 +1,16 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# The Initial Developer of the Original Code is Netscape Communications
-# Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All
-# Rights Reserved.
-#
-# Contributor(s): Terry Weissman <terry@mozilla.org>
-#                 Myk Melez <myk@mozilla.org>
-#                 Marc Schumann <wurblzap@gmail.com>
-#                 Frédéric Buclin <LpSolit@gmail.com>
-
-use strict;
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Attachment;
 
+use 5.10.1;
+use strict;
+use warnings;
+
 =head1 NAME
 
 Bugzilla::Attachment - Bugzilla attachment class.
@@ -61,8 +46,9 @@ use Bugzilla::Hook;
 
 use File::Copy;
 use List::Util qw(max);
+use Storable qw(dclone);
 
-use base qw(Bugzilla::Object);
+use parent qw(Bugzilla::Object);
 
 ###############################
 ####    Initialization     ####
@@ -75,22 +61,19 @@ use constant LIST_ORDER => ID_FIELD;
 use constant AUDIT_CREATES => 0;
 use constant AUDIT_UPDATES => 0;
 
-sub DB_COLUMNS {
-    my $dbh = Bugzilla->dbh;
-
-    return qw(
-        attach_id
-        bug_id
-        description
-        filename
-        isobsolete
-        ispatch
-        isprivate
-        mimetype
-        modification_time
-        submitter_id),
-        $dbh->sql_date_format('attachments.creation_ts', '%Y.%m.%d %H:%i') . ' AS creation_ts';
-}
+use constant DB_COLUMNS => qw(
+    attach_id
+    bug_id
+    creation_ts
+    description
+    filename
+    isobsolete
+    ispatch
+    isprivate
+    mimetype
+    modification_time
+    submitter_id
+);
 
 use constant REQUIRED_FIELD_MAP => {
     bug_id => 'bug',
@@ -116,7 +99,8 @@ use constant VALIDATORS => {
 };
 
 use constant VALIDATOR_DEPENDENCIES => {
-    mimetype => ['ispatch'],
+    content_type => ['ispatch'],
+    mimetype     => ['ispatch'],
 };
 
 use constant UPDATE_VALIDATORS => {
@@ -142,8 +126,7 @@ the ID of the bug to which the attachment is attached
 =cut
 
 sub bug_id {
-    my $self = shift;
-    return $self->{bug_id};
+    return $_[0]->{bug_id};
 }
 
 =over
@@ -157,11 +140,8 @@ the bug object to which the attachment is attached
 =cut
 
 sub bug {
-    my $self = shift;
-
     require Bugzilla::Bug;
-    $self->{bug} ||= Bugzilla::Bug->new($self->bug_id);
-    return $self->{bug};
+    return $_[0]->{bug} //= Bugzilla::Bug->new({ id => $_[0]->bug_id, cache => 1 });
 }
 
 =over
@@ -175,8 +155,7 @@ user-provided text describing the attachment
 =cut
 
 sub description {
-    my $self = shift;
-    return $self->{description};
+    return $_[0]->{description};
 }
 
 =over
@@ -190,8 +169,7 @@ the attachment's MIME media type
 =cut
 
 sub contenttype {
-    my $self = shift;
-    return $self->{mimetype};
+    return $_[0]->{mimetype};
 }
 
 =over
@@ -205,10 +183,8 @@ the user who attached the attachment
 =cut
 
 sub attacher {
-    my $self = shift;
-    return $self->{attacher} if exists $self->{attacher};
-    $self->{attacher} = new Bugzilla::User($self->{submitter_id});
-    return $self->{attacher};
+    return $_[0]->{attacher}
+      //= new Bugzilla::User({ id => $_[0]->{submitter_id}, cache => 1 });
 }
 
 =over
@@ -222,8 +198,7 @@ the date and time on which the attacher attached the attachment
 =cut
 
 sub attached {
-    my $self = shift;
-    return $self->{creation_ts};
+    return $_[0]->{creation_ts};
 }
 
 =over
@@ -237,8 +212,7 @@ the date and time on which the attachment was last modified.
 =cut
 
 sub modification_time {
-    my $self = shift;
-    return $self->{modification_time};
+    return $_[0]->{modification_time};
 }
 
 =over
@@ -252,8 +226,7 @@ the name of the file the attacher attached
 =cut
 
 sub filename {
-    my $self = shift;
-    return $self->{filename};
+    return $_[0]->{filename};
 }
 
 =over
@@ -267,8 +240,7 @@ whether or not the attachment is a patch
 =cut
 
 sub ispatch {
-    my $self = shift;
-    return $self->{ispatch};
+    return $_[0]->{ispatch};
 }
 
 =over
@@ -282,8 +254,7 @@ whether or not the attachment is obsolete
 =cut
 
 sub isobsolete {
-    my $self = shift;
-    return $self->{isobsolete};
+    return $_[0]->{isobsolete};
 }
 
 =over
@@ -297,8 +268,7 @@ whether or not the attachment is private
 =cut
 
 sub isprivate {
-    my $self = shift;
-    return $self->{isprivate};
+    return $_[0]->{isprivate};
 }
 
 =over
@@ -315,8 +285,7 @@ matches, because this will return a value even if it's matched by the generic
 =cut
 
 sub is_viewable {
-    my $self = shift;
-    my $contenttype = $self->contenttype;
+    my $contenttype = $_[0]->contenttype;
     my $cgi = Bugzilla->cgi;
 
     # We assume we can view all text and image types.
@@ -359,7 +328,7 @@ sub data {
     # If there's no attachment data in the database, the attachment is stored
     # in a local file, so retrieve it from there.
     if (length($self->{data}) == 0) {
-        if (open(AH, $self->_get_local_filename())) {
+        if (open(AH, '<', $self->_get_local_filename())) {
             local $/;
             binmode AH;
             $self->{data} = <AH>;
@@ -374,7 +343,7 @@ sub data {
 
 =item C<datasize>
 
-the length (in characters) of the attachment content
+the length (in bytes) of the attachment content
 
 =back
 
@@ -390,7 +359,7 @@ the length (in characters) of the attachment content
 
 sub datasize {
     my $self = shift;
-    return $self->{datasize} if exists $self->{datasize};
+    return $self->{datasize} if defined $self->{datasize};
 
     # If we have already retrieved the data, return its size.
     return length($self->{data}) if exists $self->{data};
@@ -405,7 +374,7 @@ sub datasize {
     # is stored in a local file, and so retrieve its size from the file,
     # or the attachment has been deleted.
     unless ($self->{datasize}) {
-        if (open(AH, $self->_get_local_filename())) {
+        if (open(AH, '<', $self->_get_local_filename())) {
             binmode AH;
             $self->{datasize} = (stat(AH))[7];
             close(AH);
@@ -433,11 +402,8 @@ flags that have been set on the attachment
 =cut
 
 sub flags {
-    my $self = shift;
-
     # Don't cache it as it must be in sync with ->flag_types.
-    $self->{flags} = [map { @{$_->{flags}} } @{$self->flag_types}];
-    return $self->{flags};
+    return $_[0]->{flags} = [map { @{$_->{flags}} } @{$_[0]->flag_types}];
 }
 
 =over
@@ -460,8 +426,7 @@ sub flag_types {
                  component_id => $self->bug->component_id,
                  attach_id    => $self->id };
 
-    $self->{flag_types} = Bugzilla::Flag->_flag_types($vars);
-    return $self->{flag_types};
+    return $self->{flag_types} = Bugzilla::Flag->_flag_types($vars);
 }
 
 ###############################
@@ -530,6 +495,53 @@ sub _check_content_type {
     }
     trick_taint($content_type);
 
+    # $ENV{HOME} must be defined when using File::MimeInfo::Magic,
+    # see https://rt.cpan.org/Public/Bug/Display.html?id=41744.
+    local $ENV{HOME} = $ENV{HOME} || File::Spec->rootdir();
+
+    # If we have autodetected application/octet-stream from the Content-Type
+    # header, let's have a better go using a sniffer if available.
+    if (defined Bugzilla->input_params->{contenttypemethod}
+        && Bugzilla->input_params->{contenttypemethod} eq 'autodetect'
+        && $content_type eq 'application/octet-stream'
+        && Bugzilla->feature('typesniffer'))
+    {
+        import File::MimeInfo::Magic qw(mimetype);
+        require IO::Scalar;
+
+        # data is either a filehandle, or the data itself.
+        my $fh = $params->{data};
+        if (!ref($fh)) {
+            $fh = new IO::Scalar \$fh;
+        }
+        elsif (!$fh->isa('IO::Handle')) {
+            # CGI.pm sends us an Fh that isn't actually an IO::Handle, but
+            # has a method for getting an actual handle out of it.
+            $fh = $fh->handle;
+            # ->handle returns an literal IO::Handle, even though the
+            # underlying object is a file. So we rebless it to be a proper
+            # IO::File object so that we can call ->seek on it and so on.
+            # Just in case CGI.pm fixes this some day, we check ->isa first.
+            if (!$fh->isa('IO::File')) {
+                bless $fh, 'IO::File';
+            }
+        }
+
+        my $mimetype = mimetype($fh);
+        $fh->seek(0, 0);
+        $content_type = $mimetype if $mimetype;
+    }
+
+    # Make sure patches are viewable in the browser
+    if (!ref($invocant)
+        && defined Bugzilla->input_params->{contenttypemethod}
+        && Bugzilla->input_params->{contenttypemethod} eq 'autodetect'
+        && $content_type =~ m{text/x-(?:diff|patch)})
+    {
+        $params->{ispatch} = 1;
+        $content_type = 'text/plain';
+    }
+
     return $content_type;
 }
 
@@ -582,9 +594,11 @@ sub _check_filename {
     # a big deal if it munges incorrectly occasionally.
     $filename =~ s/^.*[\/\\]//;
 
-    # Truncate the filename to 100 characters, counting from the end of the
-    # string to make sure we keep the filename extension.
-    $filename = substr($filename, -100, 100);
+    # Truncate the filename to MAX_ATTACH_FILENAME_LENGTH characters, counting 
+    # from the end of the string to make sure we keep the filename extension.
+    $filename = substr($filename, 
+                       -&MAX_ATTACH_FILENAME_LENGTH, 
+                       MAX_ATTACH_FILENAME_LENGTH);
     trick_taint($filename);
 
     return $filename;
@@ -608,12 +622,12 @@ sub _check_is_private {
 
 =over
 
-=item C<get_attachments_by_bug($bug_id)>
+=item C<get_attachments_by_bug($bug)>
 
 Description: retrieves and returns the attachments the currently logged in
              user can view for the given bug.
 
-Params:     C<$bug_id> - integer - the ID of the bug for which
+Params:     C<$bug> - Bugzilla::Bug object - the bug for which
             to retrieve and return attachments.
 
 Returns:    a reference to an array of attachment objects.
@@ -621,14 +635,14 @@ Returns:    a reference to an array of attachment objects.
 =cut
 
 sub get_attachments_by_bug {
-    my ($class, $bug_id, $vars) = @_;
+    my ($class, $bug, $vars) = @_;
     my $user = Bugzilla->user;
     my $dbh = Bugzilla->dbh;
 
     # By default, private attachments are not accessible, unless the user
     # is in the insider group or submitted the attachment.
     my $and_restriction = '';
-    my @values = ($bug_id);
+    my @values = ($bug->id);
 
     unless ($user->is_insider) {
         $and_restriction = 'AND (isprivate = 0 OR submitter_id = ?)';
@@ -640,50 +654,75 @@ sub get_attachments_by_bug {
                                                undef, @values);
 
     my $attachments = Bugzilla::Attachment->new_from_list($attach_ids);
+    $_->{bug} = $bug foreach @$attachments;
 
-    # To avoid $attachment->flags to run SQL queries itself for each
-    # attachment listed here, we collect all the data at once and
-    # populate $attachment->{flags} ourselves.
+    # To avoid $attachment->flags and $attachment->flag_types running SQL queries
+    # themselves for each attachment listed here, we collect all the data at once and
+    # populate $attachment->{flag_types} ourselves. We also load all attachers and
+    # datasizes at once for the same reason.
     if ($vars->{preload}) {
-        $_->{flags} = [] foreach @$attachments;
-        my %att = map { $_->id => $_ } @$attachments;
+        # Preload flag types and flags
+        my $vars = { target_type  => 'attachment',
+                     product_id   => $bug->product_id,
+                     component_id => $bug->component_id,
+                     attach_id    => $attach_ids };
+        my $flag_types = Bugzilla::Flag->_flag_types($vars);
+
+        foreach my $attachment (@$attachments) {
+            $attachment->{flag_types} = [];
+            my $new_types = dclone($flag_types);
+            foreach my $new_type (@$new_types) {
+                $new_type->{flags} = [ grep($_->attach_id == $attachment->id,
+                                            @{ $new_type->{flags} }) ];
+                push(@{ $attachment->{flag_types} }, $new_type);
+            }
+        }
 
-        my $flags = Bugzilla::Flag->match({ bug_id      => $bug_id,
-                                            target_type => 'attachment' });
+        # Preload attachers.
+        my %user_ids = map { $_->{submitter_id} => 1 } @$attachments;
+        my $users = Bugzilla::User->new_from_list([keys %user_ids]);
+        my %user_map = map { $_->id => $_ } @$users;
+        foreach my $attachment (@$attachments) {
+            $attachment->{attacher} = $user_map{$attachment->{submitter_id}};
+        }
 
-        # Exclude flags for private attachments you cannot see.
-        @$flags = grep {exists $att{$_->attach_id}} @$flags;
+        # Preload datasizes.
+        my $sizes =
+          $dbh->selectall_hashref('SELECT attach_id, LENGTH(thedata) AS datasize
+                                   FROM attachments LEFT JOIN attach_data ON attach_id = id
+                                   WHERE bug_id = ?',
+                                   'attach_id', undef, $bug->id);
 
-        push(@{$att{$_->attach_id}->{flags}}, $_) foreach @$flags;
-        $attachments = [sort {$a->id <=> $b->id} values %att];
+        # Force the size of attachments not in the DB to be recalculated.
+        $_->{datasize} = $sizes->{$_->id}->{datasize} || undef foreach @$attachments;
     }
+
     return $attachments;
 }
 
 =pod
 
-=item C<validate_can_edit($attachment, $product_id)>
+=item C<validate_can_edit>
 
 Description: validates if the user is allowed to view and edit the attachment.
              Only the submitter or someone with editbugs privs can edit it.
              Only the submitter and users in the insider group can view
              private attachments.
 
-Params:      $attachment - the attachment object being edited.
-             $product_id - the product ID the attachment belongs to.
+Params:      none
 
 Returns:     1 on success, 0 otherwise.
 
 =cut
 
 sub validate_can_edit {
-    my ($attachment, $product_id) = @_;
+    my $attachment = shift;
     my $user = Bugzilla->user;
 
     # The submitter can edit their attachments.
     return ($attachment->attacher->id == $user->id
             || ((!$attachment->isprivate || $user->is_insider)
-                 && $user->in_group('editbugs', $product_id))) ? 1 : 0;
+                 && $user->in_group('editbugs', $attachment->bug->product_id))) ? 1 : 0;
 }
 
 =item C<validate_obsolete($bug, $attach_ids)>
@@ -691,7 +730,7 @@ sub validate_can_edit {
 Description: validates if attachments the user wants to mark as obsolete
              really belong to the given bug and are not already obsolete.
              Moreover, a user cannot mark an attachment as obsolete if
-             he cannot view it (due to restrictions on it).
+             they cannot view it (due to restrictions on it).
 
 Params:      $bug - The bug object obsolete attachments should belong to.
              $attach_ids - The list of attachments to mark as obsolete.
@@ -713,19 +752,19 @@ sub validate_obsolete {
         $vars->{'attach_id'} = $attachid;
 
         detaint_natural($attachid)
-          || ThrowCodeError('invalid_attach_id_to_obsolete', $vars);
+          || ThrowUserError('invalid_attach_id', $vars);
 
         # Make sure the attachment exists in the database.
         my $attachment = new Bugzilla::Attachment($attachid)
           || ThrowUserError('invalid_attach_id', $vars);
 
         # Check that the user can view and edit this attachment.
-        $attachment->validate_can_edit($bug->product_id)
+        $attachment->validate_can_edit
           || ThrowUserError('illegal_attachment_edit', { attach_id => $attachment->id });
 
         if ($attachment->bug_id != $bug->bug_id) {
             $vars->{'my_bug_id'} = $bug->bug_id;
-            ThrowCodeError('mismatched_bug_ids_on_obsolete', $vars);
+            ThrowUserError('mismatched_bug_ids_on_obsolete', $vars);
         }
 
         next if $attachment->isobsolete;
@@ -826,6 +865,8 @@ sub create {
 sub run_create_validators {
     my ($class, $params) = @_;
 
+    $params->{submitter_id} = Bugzilla->user->id || ThrowUserError('invalid_user');
+
     # Let's validate the attachment content first as it may
     # alter some other attachment attributes.
     $params->{data} = $class->_check_data($params);
@@ -833,7 +874,6 @@ sub run_create_validators {
 
     $params->{creation_ts} ||= Bugzilla->dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
     $params->{modification_time} = $params->{creation_ts};
-    $params->{submitter_id} = Bugzilla->user->id || ThrowCodeError('invalid_user');
 
     return $params;
 }
@@ -852,23 +892,23 @@ sub update {
     }
 
     # Record changes in the activity table.
-    my $sth = $dbh->prepare('INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when,
-                                                        fieldid, removed, added)
-                             VALUES (?, ?, ?, ?, ?, ?, ?)');
-
+    require Bugzilla::Bug;
     foreach my $field (keys %$changes) {
         my $change = $changes->{$field};
         $field = "attachments.$field" unless $field eq "flagtypes.name";
-        my $fieldid = get_field_id($field);
-        $sth->execute($self->bug_id, $self->id, $user->id, $timestamp,
-                      $fieldid, $change->[0], $change->[1]);
+        Bugzilla::Bug::LogActivityEntry($self->bug_id, $field, $change->[0],
+            $change->[1], $user->id, $timestamp, undef, $self->id);
     }
 
     if (scalar(keys %$changes)) {
-      $dbh->do('UPDATE attachments SET modification_time = ? WHERE attach_id = ?',
-               undef, ($timestamp, $self->id));
-      $dbh->do('UPDATE bugs SET delta_ts = ? WHERE bug_id = ?',
-               undef, ($timestamp, $self->bug_id));
+        $dbh->do('UPDATE attachments SET modification_time = ? WHERE attach_id = ?',
+                 undef, ($timestamp, $self->id));
+        $dbh->do('UPDATE bugs SET delta_ts = ? WHERE bug_id = ?',
+                 undef, ($timestamp, $self->bug_id));
+        $self->{modification_time} = $timestamp;
+        # because we updated the attachments table after SUPER::update(), we
+        # need to ensure the cache is flushed.
+        Bugzilla->memcached->clear({ table => 'attachments', id => $self->id });
     }
 
     return $changes;
@@ -893,11 +933,26 @@ sub remove_from_db {
     my $dbh = Bugzilla->dbh;
 
     $dbh->bz_start_transaction();
-    $dbh->do('DELETE FROM flags WHERE attach_id = ?', undef, $self->id);
+    my $flag_ids = $dbh->selectcol_arrayref(
+        'SELECT id FROM flags WHERE attach_id = ?', undef, $self->id);
+    $dbh->do('DELETE FROM flags WHERE ' . $dbh->sql_in('id', $flag_ids))
+        if @$flag_ids;
     $dbh->do('DELETE FROM attach_data WHERE id = ?', undef, $self->id);
     $dbh->do('UPDATE attachments SET mimetype = ?, ispatch = ?, isobsolete = ?
               WHERE attach_id = ?', undef, ('text/plain', 0, 1, $self->id));
     $dbh->bz_commit_transaction();
+
+    my $filename = $self->_get_local_filename;
+    if (-e $filename) {
+        unlink $filename or warn "Couldn't unlink $filename: $!";
+    }
+
+    # As we don't call SUPER->remove_from_db we need to manually clear
+    # memcached here.
+    Bugzilla->memcached->clear({ table => 'attachments', id => $self->id });
+    foreach my $flag_id (@$flag_ids) {
+        Bugzilla->memcached->clear({ table => 'flags', id => $flag_id });
+    }
 }
 
 ###############################
@@ -911,12 +966,18 @@ sub get_content_type {
     return 'text/plain' if ($cgi->param('ispatch') || $cgi->param('attach_text'));
 
     my $content_type;
-    my $method = $cgi->param('contenttypemethod');
+    my $method = $cgi->param('contenttypemethod') || '';
 
-    if (!defined $method) {
-        ThrowUserError("missing_content_type_method");
+    if ($method eq 'list') {
+        # The user selected a content type from the list, so use their
+        # selection.
+        $content_type = $cgi->param('contenttypeselection');
+    }
+    elsif ($method eq 'manual') {
+        # The user entered a content type manually, so use their entry.
+        $content_type = $cgi->param('contenttypeentry');
     }
-    elsif ($method eq 'autodetect') {
+    else {
         defined $cgi->upload('data') || ThrowUserError('file_not_specified');
         # The user asked us to auto-detect the content type, so use the type
         # specified in the HTTP request headers.
@@ -924,33 +985,40 @@ sub get_content_type {
             $cgi->uploadInfo($cgi->param('data'))->{'Content-Type'};
         $content_type || ThrowUserError("missing_content_type");
 
-        # Set the ispatch flag to 1 if the content type
-        # is text/x-diff or text/x-patch
-        if ($content_type =~ m{text/x-(?:diff|patch)}) {
-            $cgi->param('ispatch', 1);
-            $content_type = 'text/plain';
-        }
-
         # Internet Explorer sends image/x-png for PNG images,
         # so convert that to image/png to match other browsers.
         if ($content_type eq 'image/x-png') {
             $content_type = 'image/png';
         }
     }
-    elsif ($method eq 'list') {
-        # The user selected a content type from the list, so use their
-        # selection.
-        $content_type = $cgi->param('contenttypeselection');
-    }
-    elsif ($method eq 'manual') {
-        # The user entered a content type manually, so use their entry.
-        $content_type = $cgi->param('contenttypeentry');
-    }
-    else {
-        ThrowCodeError("illegal_content_type_method", { contenttypemethod => $method });
-    }
     return $content_type;
 }
 
 
 1;
+
+=head1 B<Methods in need of POD>
+
+=over
+
+=item set_filename
+
+=item set_is_obsolete
+
+=item DB_COLUMNS
+
+=item set_is_private
+
+=item set_content_type
+
+=item set_description
+
+=item get_content_type
+
+=item set_flags
+
+=item set_is_patch
+
+=item update
+
+=back
index cfc7610..d0e2212 100644 (file)
@@ -1,43 +1,42 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# Contributor(s): John Keiser <john@johnkeiser.com>
-#                 Frédéric Buclin <LpSolit@gmail.com>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
+package Bugzilla::Attachment::PatchReader;
+
+use 5.10.1;
 use strict;
+use warnings;
 
-package Bugzilla::Attachment::PatchReader;
+use Config;
+use IO::Select;
+use IPC::Open3;
+use Symbol 'gensym';
 
 use Bugzilla::Error;
 use Bugzilla::Attachment;
 use Bugzilla::Util;
 
+use constant PERLIO_IS_ENABLED => $Config{useperlio};
+
 sub process_diff {
-    my ($attachment, $format, $context) = @_;
+    my ($attachment, $format) = @_;
     my $dbh = Bugzilla->dbh;
     my $cgi = Bugzilla->cgi;
     my $lc  = Bugzilla->localconfig;
     my $vars = {};
 
-    my ($reader, $last_reader) = setup_patch_readers(undef, $context);
+    require PatchReader::Raw;
+    my $reader = new PatchReader::Raw;
 
     if ($format eq 'raw') {
         require PatchReader::DiffPrinter::raw;
-        $last_reader->sends_data_to(new PatchReader::DiffPrinter::raw());
+        $reader->sends_data_to(new PatchReader::DiffPrinter::raw());
         # Actually print out the patch.
-        print $cgi->header(-type => 'text/plain',
-                           -expires => '+3M');
+        print $cgi->header(-type => 'text/plain');
         disable_utf8();
         $reader->iterate_string('Attachment ' . $attachment->id, $attachment->data);
     }
@@ -46,7 +45,7 @@ sub process_diff {
         if ($lc->{interdiffbin} && $lc->{diffpath}) {
             # Get the list of attachments that the user can view in this bug.
             my @attachments =
-                @{Bugzilla::Attachment->get_attachments_by_bug($attachment->bug_id)};
+                @{Bugzilla::Attachment->get_attachments_by_bug($attachment->bug)};
             # Extract patches only.
             @attachments = grep {$_->ispatch == 1} @attachments;
             # We want them sorted from newer to older.
@@ -73,7 +72,7 @@ sub process_diff {
         $vars->{'description'} = $attachment->description;
         $vars->{'other_patches'} = \@other_patches;
 
-        setup_template_patch_reader($last_reader, $format, $context, $vars);
+        setup_template_patch_reader($reader, $vars);
         # The patch is going to be displayed in a HTML page and if the utf8
         # param is enabled, we have to encode attachment data as utf8.
         if (Bugzilla->params->{'utf8'}) {
@@ -85,11 +84,13 @@ sub process_diff {
 }
 
 sub process_interdiff {
-    my ($old_attachment, $new_attachment, $format, $context) = @_;
+    my ($old_attachment, $new_attachment, $format) = @_;
     my $cgi = Bugzilla->cgi;
     my $lc  = Bugzilla->localconfig;
     my $vars = {};
 
+    require PatchReader::Raw;
+
     # Encode attachment data as utf8 if it's going to be displayed in a HTML
     # page using the UTF-8 encoding.
     if ($format ne 'raw' && Bugzilla->params->{'utf8'}) {
@@ -108,23 +109,87 @@ sub process_interdiff {
 
     # Send through interdiff, send output directly to template.
     # Must hack path so that interdiff will work.
-    $ENV{'PATH'} = $lc->{diffpath};
-    open my $interdiff_fh, "$lc->{interdiffbin} $old_filename $new_filename|";
-    binmode $interdiff_fh;
-    my ($reader, $last_reader) = setup_patch_readers("", $context);
+    local $ENV{'PATH'} = $lc->{diffpath};
+
+    # Open the interdiff pipe, reading from both STDOUT and STDERR
+    # To avoid deadlocks, we have to read the entire output from all handles
+    my ($stdout, $stderr) = ('', '');
+    my ($pid, $interdiff_stdout, $interdiff_stderr, $use_select);
+    if ($ENV{MOD_PERL}) {
+        require Apache2::RequestUtil;
+        require Apache2::SubProcess;
+        my $request = Apache2::RequestUtil->request;
+        (undef, $interdiff_stdout, $interdiff_stderr) = $request->spawn_proc_prog(
+            $lc->{interdiffbin}, [$old_filename, $new_filename]
+        );
+        $use_select = !PERLIO_IS_ENABLED;
+    } else {
+        $interdiff_stderr = gensym;
+        $pid = open3(gensym, $interdiff_stdout, $interdiff_stderr,
+                        $lc->{interdiffbin}, $old_filename, $new_filename);
+        $use_select = 1;
+    }
+
+    if ($format ne 'raw' && Bugzilla->params->{'utf8'}) {
+        binmode $interdiff_stdout, ':utf8';
+        binmode $interdiff_stderr, ':utf8';
+    } else {
+        binmode $interdiff_stdout;
+        binmode $interdiff_stderr;
+    }
+
+    if ($use_select) {
+        my $select = IO::Select->new();
+        $select->add($interdiff_stdout, $interdiff_stderr);
+        while (my @handles = $select->can_read) {
+            foreach my $handle (@handles) {
+                my $line = <$handle>;
+                if (!defined $line) {
+                    $select->remove($handle);
+                    next;
+                }
+                if ($handle == $interdiff_stdout) {
+                    $stdout .= $line;
+                } else {
+                    $stderr .= $line;
+                }
+            }
+        }
+        waitpid($pid, 0) if $pid;
+
+    } else {
+        local $/ = undef;
+        $stdout = <$interdiff_stdout>;
+        $stdout //= '';
+        $stderr = <$interdiff_stderr>;
+        $stderr //= '';
+    }
+
+    close($interdiff_stdout),
+    close($interdiff_stderr);
+
+    # Tidy up
+    unlink($old_filename) or warn "Could not unlink $old_filename: $!";
+    unlink($new_filename) or warn "Could not unlink $new_filename: $!";
+
+    # Any output on STDERR means interdiff failed to full process the patches.
+    # Interdiff's error messages are generic and not useful to end users, so we
+    # show a generic failure message.
+    if ($stderr) {
+        warn($stderr);
+        $warning = 'interdiff3';
+    }
+
+    my $reader = new PatchReader::Raw;
 
     if ($format eq 'raw') {
         require PatchReader::DiffPrinter::raw;
-        $last_reader->sends_data_to(new PatchReader::DiffPrinter::raw());
+        $reader->sends_data_to(new PatchReader::DiffPrinter::raw());
         # Actually print out the patch.
-        print $cgi->header(-type => 'text/plain',
-                           -expires => '+3M');
+        print $cgi->header(-type => 'text/plain');
         disable_utf8();
     }
     else {
-        # In case the HTML page is displayed with the UTF-8 encoding.
-        binmode $interdiff_fh, ':utf8' if Bugzilla->params->{'utf8'};
-
         $vars->{'warning'} = $warning if $warning;
         $vars->{'bugid'} = $new_attachment->bug_id;
         $vars->{'oldid'} = $old_attachment->id;
@@ -132,16 +197,10 @@ sub process_interdiff {
         $vars->{'newid'} = $new_attachment->id;
         $vars->{'new_desc'} = $new_attachment->description;
 
-        setup_template_patch_reader($last_reader, $format, $context, $vars);
+        setup_template_patch_reader($reader, $vars);
     }
-    $reader->iterate_fh($interdiff_fh, 'interdiff #' . $old_attachment->id .
-                        ' #' . $new_attachment->id);
-    close $interdiff_fh;
-    $ENV{'PATH'} = '';
-
-    # Delete temporary files.
-    unlink($old_filename) or warn "Could not unlink $old_filename: $!";
-    unlink($new_filename) or warn "Could not unlink $new_filename: $!";
+    $reader->iterate_string('interdiff #' . $old_attachment->id .
+                            ' #' . $new_attachment->id, $stdout);
 }
 
 ######################
@@ -153,7 +212,6 @@ sub get_unified_diff {
 
     # Bring in the modules we need.
     require PatchReader::Raw;
-    require PatchReader::FixPatchRoot;
     require PatchReader::DiffPrinter::raw;
     require PatchReader::PatchInfoGrabber;
     require File::Temp;
@@ -165,14 +223,6 @@ sub get_unified_diff {
     my $reader = new PatchReader::Raw;
     my $last_reader = $reader;
 
-    # Fixes patch root (makes canonical if possible).
-    if (Bugzilla->params->{'cvsroot'}) {
-        my $fix_patch_root =
-            new PatchReader::FixPatchRoot(Bugzilla->params->{'cvsroot'});
-        $last_reader->sends_data_to($fix_patch_root);
-        $last_reader = $fix_patch_root;
-    }
-
     # Grabs the patch file info.
     my $patch_info_grabber = new PatchReader::PatchInfoGrabber();
     $last_reader->sends_data_to($patch_info_grabber);
@@ -208,7 +258,9 @@ sub warn_if_interdiff_might_fail {
 
     # Verify that the revisions in the files are the same.
     foreach my $file (keys %{$old_file_list}) {
-        if ($old_file_list->{$file}{old_revision} ne
+        if (exists $old_file_list->{$file}{old_revision}
+            && exists $new_file_list->{$file}{old_revision}
+            && $old_file_list->{$file}{old_revision} ne
             $new_file_list->{$file}{old_revision})
         {
             return 'interdiff2';
@@ -217,46 +269,8 @@ sub warn_if_interdiff_might_fail {
     return undef;
 }
 
-sub setup_patch_readers {
-    my ($diff_root, $context) = @_;
-
-    # Parameters:
-    # format=raw|html
-    # context=patch|file|0-n
-    # collapsed=0|1
-    # headers=0|1
-
-    # Define the patch readers.
-    # The reader that reads the patch in (whatever its format).
-    require PatchReader::Raw;
-    my $reader = new PatchReader::Raw;
-    my $last_reader = $reader;
-    # Fix the patch root if we have a cvs root.
-    if (Bugzilla->params->{'cvsroot'}) {
-        require PatchReader::FixPatchRoot;
-        $last_reader->sends_data_to(new PatchReader::FixPatchRoot(Bugzilla->params->{'cvsroot'}));
-        $last_reader->sends_data_to->diff_root($diff_root) if defined($diff_root);
-        $last_reader = $last_reader->sends_data_to;
-    }
-
-    # Add in cvs context if we have the necessary info to do it
-    if ($context ne 'patch' && Bugzilla->localconfig->{cvsbin} 
-        && Bugzilla->params->{'cvsroot_get'}) 
-    {
-        require PatchReader::AddCVSContext;
-        # We need to set $cvsbin as global, because PatchReader::CVSClient
-        # needs it in order to find 'cvs'.
-        $main::cvsbin = Bugzilla->localconfig->{cvsbin};
-        $last_reader->sends_data_to(
-          new PatchReader::AddCVSContext($context, Bugzilla->params->{'cvsroot_get'}));
-        $last_reader = $last_reader->sends_data_to;
-    }
-
-    return ($reader, $last_reader);
-}
-
 sub setup_template_patch_reader {
-    my ($last_reader, $format, $context, $vars) = @_;
+    my ($last_reader, $vars) = @_;
     my $cgi = Bugzilla->cgi;
     my $template = Bugzilla->template;
 
@@ -271,25 +285,33 @@ sub setup_template_patch_reader {
     }
 
     $vars->{'collapsed'} = $cgi->param('collapsed');
-    $vars->{'context'} = $context;
-    $vars->{'do_context'} = Bugzilla->localconfig->{cvsbin} 
-                            && Bugzilla->params->{'cvsroot_get'} && !$vars->{'newid'};
 
     # Print everything out.
-    print $cgi->header(-type => 'text/html',
-                       -expires => '+3M');
+    print $cgi->header(-type => 'text/html');
 
     $last_reader->sends_data_to(new PatchReader::DiffPrinter::template($template,
-                                "attachment/diff-header.$format.tmpl",
-                                "attachment/diff-file.$format.tmpl",
-                                "attachment/diff-footer.$format.tmpl",
-                                { %{$vars},
-                                  bonsai_url => Bugzilla->params->{'bonsai_url'},
-                                  lxr_url => Bugzilla->params->{'lxr_url'},
-                                  lxr_root => Bugzilla->params->{'lxr_root'},
-                                }));
+                                'attachment/diff-header.html.tmpl',
+                                'attachment/diff-file.html.tmpl',
+                                'attachment/diff-footer.html.tmpl',
+                                $vars));
 }
 
 1;
 
 __END__
+
+=head1 B<Methods in need of POD>
+
+=over
+
+=item get_unified_diff
+
+=item process_diff
+
+=item warn_if_interdiff_might_fail
+
+=item setup_template_patch_reader
+
+=item process_interdiff
+
+=back
index 45034e1..c830f05 100644 (file)
@@ -1,29 +1,16 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# The Initial Developer of the Original Code is Netscape Communications
-# Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All
-# Rights Reserved.
-#
-# Contributor(s): Bradley Baetz <bbaetz@acm.org>
-#                 Erik Stambaugh <erik@dasbistro.com>
-#                 Max Kanat-Alexander <mkanat@bugzilla.org>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth;
 
+use 5.10.1;
 use strict;
+use warnings;
+
 use fields qw(
     _info_getter
     _verifier
@@ -38,13 +25,14 @@ use Bugzilla::User::Setting ();
 use Bugzilla::Auth::Login::Stack;
 use Bugzilla::Auth::Verify::Stack;
 use Bugzilla::Auth::Persist::Cookie;
+use Socket;
 
 sub new {
     my ($class, $params) = @_;
     my $self = fields::new($class);
 
     $params            ||= {};
-    $params->{Login}   ||= Bugzilla->params->{'user_info_class'} . ',Cookie';
+    $params->{Login}   ||= Bugzilla->params->{'user_info_class'} . ',Cookie,APIKey';
     $params->{Verify}  ||= Bugzilla->params->{'user_verify_class'};
 
     $self->{_info_getter} = new Bugzilla::Auth::Login::Stack($params->{Login});
@@ -58,7 +46,6 @@ sub new {
 
 sub login {
     my ($self, $type) = @_;
-    my $dbh = Bugzilla->dbh;
 
     # Get login info from the cookie, form, environment variables, etc.
     my $login_info = $self->{_info_getter}->get_login_info();
@@ -67,7 +54,7 @@ sub login {
         return $self->_handle_login_result($login_info, $type);
     }
 
-    # Now verify his username and password against the DB, LDAP, etc.
+    # Now verify their username and password against the DB, LDAP, etc.
     if ($self->{_info_getter}->{successful}->requires_verification) {
         $login_info = $self->{_verifier}->check_credentials($login_info);
         if ($login_info->{failure}) {
@@ -123,6 +110,15 @@ sub can_logout {
     return $getter->can_logout;
 }
 
+sub login_token {
+    my ($self) = @_;
+    my $getter = $self->{_info_getter}->{successful};
+    if ($getter && $getter->isa('Bugzilla::Auth::Login::Cookie')) {
+        return $getter->login_token;
+    }
+    return undef;
+}
+
 sub user_can_create_account {
     my ($self) = @_;
     my $verifier = $self->{_verifier}->{successful};
@@ -158,7 +154,7 @@ sub _handle_login_result {
         if ($self->{_info_getter}->{successful}->requires_persistence
             and !Bugzilla->request_cache->{auth_no_automatic_login}) 
         {
-            $self->{_persister}->persist_login($user);
+            $user->{_login_token} = $self->{_persister}->persist_login($user);
         }
     }
     elsif ($fail_code == AUTH_ERROR) {
@@ -183,7 +179,7 @@ sub _handle_login_result {
     elsif ($fail_code == AUTH_LOGINFAILED or $fail_code == AUTH_NO_SUCH_USER) {
         my $remaining_attempts = MAX_LOGIN_ATTEMPTS 
                                  - ($result->{failure_count} || 0);
-        ThrowUserError("invalid_username_or_password", 
+        ThrowUserError("invalid_login_or_password", 
                        { remaining => $remaining_attempts });
     }
     # The account may be disabled
@@ -215,10 +211,18 @@ sub _handle_login_result {
             my $default_settings = Bugzilla::User::Setting::get_defaults();
             my $template = Bugzilla->template_inner(
                                $default_settings->{lang}->{default_value});
+            my $address = $attempts->[0]->{ip_addr};
+            # Note: inet_aton will only resolve IPv4 addresses.
+            # For IPv6 we'll need to use inet_pton which requires Perl 5.12.
+            my $n = inet_aton($address);
+            if ($n) {
+                $address = gethostbyaddr($n, AF_INET) . " ($address)"
+            }
             my $vars = {
                 locked_user => $user,
                 attempts    => $attempts,
                 unlock_at   => $unlock_at,
+                address     => $address,
             };
             my $message;
             $template->process('email/lockout.txt.tmpl', $vars, \$message)
@@ -294,7 +298,7 @@ An incorrect username or password was given.
 The hashref may also contain a C<failure_count> element, which specifies
 how many times the account has failed to log in within the lockout
 period (see L</AUTH_LOCKOUT>). This is used to warn the user when
-he is getting close to being locked out.
+they are getting close to being locked out.
 
 =head2 C<AUTH_NO_SUCH_USER>
 
@@ -416,6 +420,14 @@ Params:      None
 Returns:     C<true> if users can change their own email address,
              C<false> otherwise.
 
+=item C<login_token>
+
+Description: If a login token was used instead of a cookie then this
+             will return the current login token data such as user id
+             and the token itself.
+Params:      None
+Returns:     A hash containing C<login_token> and C<user_id>.
+
 =back
 
 =head1 STRUCTURE
@@ -531,5 +543,3 @@ A L<Bugzilla::User> object representing the authenticated user.
 Note that C<Bugzilla::Auth::login> may modify this object at various points.
 
 =back
-
-
index 42ce51c..a5f0897 100644 (file)
@@ -1,22 +1,16 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth::Login;
 
+use 5.10.1;
 use strict;
+use warnings;
+
 use fields qw();
 
 # Determines whether or not a user can logout. It's really a subroutine,
diff --git a/Websites/bugs.webkit.org/Bugzilla/Auth/Login/APIKey.pm b/Websites/bugs.webkit.org/Bugzilla/Auth/Login/APIKey.pm
new file mode 100644 (file)
index 0000000..63e3557
--- /dev/null
@@ -0,0 +1,53 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+
+package Bugzilla::Auth::Login::APIKey;
+
+use 5.10.1;
+use strict;
+use warnings;
+
+use base qw(Bugzilla::Auth::Login);
+
+use Bugzilla::Constants;
+use Bugzilla::User::APIKey;
+use Bugzilla::Util;
+use Bugzilla::Error;
+
+use constant requires_persistence  => 0;
+use constant requires_verification => 0;
+use constant can_login             => 0;
+use constant can_logout            => 0;
+
+# This method is only available to web services. An API key can never
+# be used to authenticate a Web request.
+sub get_login_info {
+    my ($self) = @_;
+    my $params = Bugzilla->input_params;
+    my ($user_id, $login_cookie);
+
+    my $api_key_text = trim(delete $params->{'Bugzilla_api_key'});
+    if (!i_am_webservice() || !$api_key_text) {
+        return { failure => AUTH_NODATA };
+    }
+
+    my $api_key = Bugzilla::User::APIKey->new({ name => $api_key_text });
+
+    if (!$api_key or $api_key->api_key ne $api_key_text) {
+        # The second part checks the correct capitalisation. Silly MySQL
+        ThrowUserError("api_key_not_valid");
+    }
+    elsif ($api_key->revoked) {
+        ThrowUserError('api_key_revoked');
+    }
+
+    $api_key->update_last_used();
+
+    return { user_id => $api_key->user_id };
+}
+
+1;
index 8e877b9..6003d62 100644 (file)
@@ -1,55 +1,69 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# The Initial Developer of the Original Code is Netscape Communications
-# Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All
-# Rights Reserved.
-#
-# Contributor(s): Terry Weissman <terry@mozilla.org>
-#                 Dan Mosedale <dmose@mozilla.org>
-#                 Joe Robins <jmrobins@tgix.com>
-#                 Dave Miller <justdave@syndicomm.com>
-#                 Christopher Aillon <christopher@aillon.com>
-#                 Gervase Markham <gerv@gerv.net>
-#                 Christian Reis <kiko@async.com.br>
-#                 Bradley Baetz <bbaetz@acm.org>
-#                 Erik Stambaugh <erik@dasbistro.com>
-#                 Max Kanat-Alexander <mkanat@bugzilla.org>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth::Login::CGI;
+
+use 5.10.1;
 use strict;
-use base qw(Bugzilla::Auth::Login);
+use warnings;
+
+use parent qw(Bugzilla::Auth::Login);
 use constant user_can_create_account => 1;
 
 use Bugzilla::Constants;
 use Bugzilla::WebService::Constants;
 use Bugzilla::Util;
 use Bugzilla::Error;
+use Bugzilla::Token;
 
 sub get_login_info {
     my ($self) = @_;
     my $params = Bugzilla->input_params;
+    my $cgi = Bugzilla->cgi;
+
+    my $login = trim(delete $params->{'Bugzilla_login'});
+    my $password = delete $params->{'Bugzilla_password'};
+    # The token must match the cookie to authenticate the request.
+    my $login_token = delete $params->{'Bugzilla_login_token'};
+    my $login_cookie = $cgi->cookie('Bugzilla_login_request_cookie');
 
-    my $username = trim(delete $params->{"Bugzilla_login"});
-    my $password = delete $params->{"Bugzilla_password"};
+    my $valid = 0;
+    # If the web browser accepts cookies, use them.
+    if ($login_token && $login_cookie) {
+        my ($time, undef) = split(/-/, $login_token);
+        # Regenerate the token based on the information we have.
+        my $expected_token = issue_hash_token(['login_request', $login_cookie], $time);
+        $valid = 1 if $expected_token eq $login_token;
+        $cgi->remove_cookie('Bugzilla_login_request_cookie');
+    }
+    # WebServices and other local scripts can bypass this check.
+    # This is safe because we won't store a login cookie in this case.
+    elsif (Bugzilla->usage_mode != USAGE_MODE_BROWSER) {
+        $valid = 1;
+    }
+    # Else falls back to the Referer header and accept local URLs.
+    # Attachments are served from a separate host (ideally), and so
+    # an evil attachment cannot abuse this check with a redirect.
+    elsif (my $referer = $cgi->referer) {
+        my $urlbase = correct_urlbase();
+        $valid = 1 if $referer =~ /^\Q$urlbase\E/;
+    }
+    # If the web browser doesn't accept cookies and the Referer header
+    # is missing, we have no way to make sure that the authentication
+    # request comes from the user.
+    elsif ($login && $password) {
+        ThrowUserError('auth_untrusted_request', { login => $login });
+    }
 
-    if (!defined $username || !defined $password) {
+    if (!defined($login) || !defined($password) || !$valid) {
         return { failure => AUTH_NODATA };
     }
 
-    return { username => $username, password => $password };
+    return { username => $login, password => $password };
 }
 
 sub fail_nodata {
index de9188c..c09f08d 100644 (file)
@@ -1,25 +1,22 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# Contributor(s): Bradley Baetz <bbaetz@acm.org>
-#                 Max Kanat-Alexander <mkanat@bugzilla.org>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth::Login::Cookie;
+
+use 5.10.1;
 use strict;
+use warnings;
+
 use base qw(Bugzilla::Auth::Login);
+use fields qw(_login_token);
 
 use Bugzilla::Constants;
+use Bugzilla::Error;
+use Bugzilla::Token;
 use Bugzilla::Util;
 
 use List::Util qw(first);
@@ -27,7 +24,8 @@ use List::Util qw(first);
 use constant requires_persistence  => 0;
 use constant requires_verification => 0;
 use constant can_login => 0;
-use constant is_automatic => 1;
+
+sub is_automatic { return $_[0]->login_token ? 0 : 1; }
 
 # Note that Cookie never consults the Verifier, it always assumes
 # it has a valid DB account or it fails.
@@ -35,24 +33,49 @@ sub get_login_info {
     my ($self) = @_;
     my $cgi = Bugzilla->cgi;
     my $dbh = Bugzilla->dbh;
+    my ($user_id, $login_cookie);
 
-    my $ip_addr      = remote_ip();
-    my $login_cookie = $cgi->cookie("Bugzilla_logincookie");
-    my $user_id      = $cgi->cookie("Bugzilla_login");
+    if (!Bugzilla->request_cache->{auth_no_automatic_login}) {
+        $login_cookie = $cgi->cookie("Bugzilla_logincookie");
+        $user_id      = $cgi->cookie("Bugzilla_login");
 
-    # If cookies cannot be found, this could mean that they haven't
-    # been made available yet. In this case, look at Bugzilla_cookie_list.
-    unless ($login_cookie) {
-        my $cookie = first {$_->name eq 'Bugzilla_logincookie'}
-                            @{$cgi->{'Bugzilla_cookie_list'}};
-        $login_cookie = $cookie->value if $cookie;
+        # If cookies cannot be found, this could mean that they haven't
+        # been made available yet. In this case, look at Bugzilla_cookie_list.
+        unless ($login_cookie) {
+            my $cookie = first {$_->name eq 'Bugzilla_logincookie'}
+                                @{$cgi->{'Bugzilla_cookie_list'}};
+            $login_cookie = $cookie->value if $cookie;
+        }
+        unless ($user_id) {
+            my $cookie = first {$_->name eq 'Bugzilla_login'}
+                                @{$cgi->{'Bugzilla_cookie_list'}};
+            $user_id = $cookie->value if $cookie;
+        }
+
+        # If the call is for a web service, and an api token is provided, check
+        # it is valid.
+        if (i_am_webservice() && Bugzilla->input_params->{Bugzilla_api_token}) {
+            my $api_token = Bugzilla->input_params->{Bugzilla_api_token};
+            my ($token_user_id, undef, undef, $token_type)
+                = Bugzilla::Token::GetTokenData($api_token);
+            if (!defined $token_type
+                || $token_type ne 'api_token'
+                || $user_id != $token_user_id)
+            {
+                ThrowUserError('auth_invalid_token', { token => $api_token });
+            }
+        }
     }
-    unless ($user_id) {
-        my $cookie = first {$_->name eq 'Bugzilla_login'}
-                            @{$cgi->{'Bugzilla_cookie_list'}};
-        $user_id = $cookie->value if $cookie;
+
+    # If no cookies were provided, we also look for a login token
+    # passed in the parameters of a webservice
+    my $token = $self->login_token;
+    if ($token && (!$login_cookie || !$user_id)) {
+        ($user_id, $login_cookie) = ($token->{'user_id'}, $token->{'login_token'});
     }
 
+    my $ip_addr = remote_ip();
+
     if ($login_cookie && $user_id) {
         # Anything goes for these params - they're just strings which
         # we're going to verify against the db
@@ -68,7 +91,9 @@ sub get_login_info {
                                         AND (ipaddr = ? OR ipaddr IS NULL)',
                                  undef, ($login_cookie, $user_id, $ip_addr));
 
-        # If the cookie is valid, return a valid username.
+        # If the cookie or token is valid, return a valid username.
+        # If they were not valid and we are using a webservice, then
+        # throw an error notifying the client.
         if (defined $db_cookie && $login_cookie eq $db_cookie) {
             # If we logged in successfully, then update the lastused 
             # time on the login cookie
@@ -76,13 +101,43 @@ sub get_login_info {
                        WHERE cookie = ?", undef, $login_cookie);
             return { user_id => $user_id };
         }
+        elsif (i_am_webservice()) {
+            ThrowUserError('invalid_cookies_or_token');
+        }
     }
 
-    # Either the he cookie is invalid, or we got no cookie. We don't want 
-    # to ever return AUTH_LOGINFAILED, because we don't want Bugzilla to 
-    # actually throw an error when it gets a bad cookie. It should just 
-    # look like there was no cookie to begin with.
+    # Either the cookie or token is invalid and we are not authenticating
+    # via a webservice, or we did not receive a cookie or token. We don't
+    # want to ever return AUTH_LOGINFAILED, because we don't want Bugzilla to
+    # actually throw an error when it gets a bad cookie or token. It should just
+    # look like there was no cookie or token to begin with.
     return { failure => AUTH_NODATA };
 }
 
+sub login_token {
+    my ($self) = @_;
+    my $input      = Bugzilla->input_params;
+    my $usage_mode = Bugzilla->usage_mode;
+
+    return $self->{'_login_token'} if exists $self->{'_login_token'};
+
+    if (!i_am_webservice()) {
+        return $self->{'_login_token'} = undef;
+    }
+
+    # Check if a token was passed in via requests for WebServices
+    my $token = trim(delete $input->{'Bugzilla_token'});
+    return $self->{'_login_token'} = undef if !$token;
+
+    my ($user_id, $login_token) = split('-', $token, 2);
+    if (!detaint_natural($user_id) || !$login_token) {
+        return $self->{'_login_token'} = undef;
+    }
+
+    return $self->{'_login_token'} = {
+        user_id     => $user_id,
+        login_token => $login_token
+    };
+}
+
 1;
index 76227f1..653df2b 100644 (file)
@@ -1,28 +1,17 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# The Initial Developer of the Original Code is Netscape Communications
-# Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All
-# Rights Reserved.
-#
-# Contributor(s): Erik Stambaugh <erik@dasbistro.com>
-#                 Max Kanat-Alexander <mkanat@bugzilla.org>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth::Login::Env;
+
+use 5.10.1;
 use strict;
-use base qw(Bugzilla::Auth::Login);
+use warnings;
+
+use parent qw(Bugzilla::Auth::Login);
 
 use Bugzilla::Constants;
 use Bugzilla::Error;
@@ -36,7 +25,6 @@ use constant extern_id_used => 1;
 
 sub get_login_info {
     my ($self) = @_;
-    my $dbh = Bugzilla->dbh;
 
     my $env_id       = $ENV{Bugzilla->params->{"auth_env_id"}} || '';
     my $env_email    = $ENV{Bugzilla->params->{"auth_env_email"}} || '';
index e8d9c46..dc35998 100644 (file)
@@ -1,26 +1,16 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# The Initial Developer of the Original Code is Netscape Communications
-# Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All
-# Rights Reserved.
-#
-# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth::Login::Stack;
+
+use 5.10.1;
 use strict;
+use warnings;
+
 use base qw(Bugzilla::Auth::Login);
 use fields qw(
     _stack
index ace4746..2d1291f 100644 (file)
@@ -1,35 +1,16 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# The Initial Developer of the Original Code is Netscape Communications
-# Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All
-# Rights Reserved.
-#
-# Contributor(s): Terry Weissman <terry@mozilla.org>
-#                 Dan Mosedale <dmose@mozilla.org>
-#                 Joe Robins <jmrobins@tgix.com>
-#                 Dave Miller <justdave@syndicomm.com>
-#                 Christopher Aillon <christopher@aillon.com>
-#                 Gervase Markham <gerv@gerv.net>
-#                 Christian Reis <kiko@async.com.br>
-#                 Bradley Baetz <bbaetz@acm.org>
-#                 Erik Stambaugh <erik@dasbistro.com>
-#                 Max Kanat-Alexander <mkanat@bugzilla.org>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth::Persist::Cookie;
+
+use 5.10.1;
 use strict;
+use warnings;
+
 use fields qw();
 
 use Bugzilla::Constants;
@@ -75,6 +56,10 @@ sub persist_login {
 
     $dbh->bz_commit_transaction();
 
+    # We do not want WebServices to generate login cookies.
+    # All we need is the login token for User.login.
+    return $login_cookie if i_am_webservice();
+
     # Prevent JavaScript from accessing login cookies.
     my %cookieargs = ('-httponly' => 1);
 
@@ -107,6 +92,7 @@ sub logout {
 
     my $dbh = Bugzilla->dbh;
     my $cgi = Bugzilla->cgi;
+    my $input = Bugzilla->input_params;
     $param = {} unless $param;
     my $user = $param->{user} || Bugzilla->user;
     my $type = $param->{type} || LOGOUT_ALL;
@@ -120,16 +106,24 @@ sub logout {
     # The LOGOUT_*_CURRENT options require the current login cookie.
     # If a new cookie has been issued during this run, that's the current one.
     # If not, it's the one we've received.
+    my @login_cookies;
     my $cookie = first {$_->name eq 'Bugzilla_logincookie'}
                        @{$cgi->{'Bugzilla_cookie_list'}};
-    my $login_cookie;
     if ($cookie) {
-        $login_cookie = $cookie->value;
+        push(@login_cookies, $cookie->value);
+    }
+    elsif ($cookie = $cgi->cookie('Bugzilla_logincookie')) {
+        push(@login_cookies, $cookie);
     }
-    else {
-        $login_cookie = $cgi->cookie("Bugzilla_logincookie") || '';
+
+    # If we are a webservice using a token instead of cookie
+    # then add that as well to the login cookies to delete
+    if (my $login_token = $user->authorizer->login_token) {
+        push(@login_cookies, $login_token->{'login_token'});
     }
-    trick_taint($login_cookie);
+
+    # Make sure that @login_cookies is not empty to not break SQL statements.
+    push(@login_cookies, '') unless @login_cookies;
 
     # These queries use both the cookie ID and the user ID as keys. Even
     # though we know the userid must match, we still check it in the SQL
@@ -138,12 +132,18 @@ sub logout {
     # logged in and got the same cookie, we could be logging the other
     # user out here. Yes, this is very very very unlikely, but why take
     # chances? - bbaetz
+    map { trick_taint($_) } @login_cookies;
+    @login_cookies = map { $dbh->quote($_) } @login_cookies;
     if ($type == LOGOUT_KEEP_CURRENT) {
-        $dbh->do("DELETE FROM logincookies WHERE cookie != ? AND userid = ?",
-                 undef, $login_cookie, $user->id);
+        $dbh->do("DELETE FROM logincookies WHERE " .
+                 $dbh->sql_in('cookie', \@login_cookies, 1) .
+                 " AND userid = ?",
+                 undef, $user->id);
     } elsif ($type == LOGOUT_CURRENT) {
-        $dbh->do("DELETE FROM logincookies WHERE cookie = ? AND userid = ?",
-                 undef, $login_cookie, $user->id);
+        $dbh->do("DELETE FROM logincookies WHERE " .
+                 $dbh->sql_in('cookie', \@login_cookies) .
+                 " AND userid = ?",
+                 undef, $user->id);
     } else {
         die("Invalid type $type supplied to logout()");
     }
index a8cd0af..9dc8327 100644 (file)
@@ -1,22 +1,16 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth::Verify;
 
+use 5.10.1;
 use strict;
+use warnings;
+
 use fields qw();
 
 use Bugzilla::Constants;
@@ -97,6 +91,7 @@ sub create_or_update_user {
         if ($extern_id && $username_user_id && !$extern_user_id) {
             $dbh->do('UPDATE profiles SET extern_id = ? WHERE userid = ?',
                      undef, $extern_id, $username_user_id);
+            Bugzilla->memcached->clear({ table => 'profiles', id => $username_user_id });
         }
 
         # Finally, at this point, one of these will give us a valid user id.
@@ -111,21 +106,24 @@ sub create_or_update_user {
 
     my $user = new Bugzilla::User($user_id);
 
-    # Now that we have a valid User, we need to see if any data has to be
-    # updated.
+    # Now that we have a valid User, we need to see if any data has to be updated.
+    my $changed = 0;
+
     if ($username && lc($user->login) ne lc($username)) {
         validate_email_syntax($username)
           || return { failure => AUTH_ERROR, error => 'auth_invalid_email',
                       details => {addr => $username} };
         $user->set_login($username);
+        $changed = 1;
     }
     if ($real_name && $user->name ne $real_name) {
         # $real_name is more than likely tainted, but we only use it
         # in a placeholder and we never use it after this.
         trick_taint($real_name);
         $user->set_name($real_name);
+        $changed = 1;
     }
-    $user->update();
+    $user->update() if $changed;
 
     return { user => $user };
 }
@@ -242,3 +240,11 @@ edit the extern_id for all users.
 The default value is C<false>.
 
 =back
+
+=head1 B<Methods in need of POD>
+
+=over
+
+=item can_change_password
+
+=back
index 2fcfd40..28a9310 100644 (file)
@@ -1,35 +1,17 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# The Initial Developer of the Original Code is Netscape Communications
-# Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All
-# Rights Reserved.
-#
-# Contributor(s): Terry Weissman <terry@mozilla.org>
-#                 Dan Mosedale <dmose@mozilla.org>
-#                 Joe Robins <jmrobins@tgix.com>
-#                 Dave Miller <justdave@syndicomm.com>
-#                 Christopher Aillon <christopher@aillon.com>
-#                 Gervase Markham <gerv@gerv.net>
-#                 Christian Reis <kiko@async.com.br>
-#                 Bradley Baetz <bbaetz@acm.org>
-#                 Erik Stambaugh <erik@dasbistro.com>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth::Verify::DB;
+
+use 5.10.1;
 use strict;
-use base qw(Bugzilla::Auth::Verify);
+use warnings;
+
+use parent qw(Bugzilla::Auth::Verify);
 
 use Bugzilla::Constants;
 use Bugzilla::Token;
@@ -74,10 +56,19 @@ sub check_credentials {
                };
     } 
 
-    # Force the user to type a longer password if it's too short.
-    if (length($password) < USER_PASSWORD_MIN_LENGTH) {
-        return { failure => AUTH_ERROR, user_error => 'password_current_too_short',
-                 details => { locked_user => $user } };
+    # Force the user to change their password if it does not meet the current
+    # criteria. This should usually only happen if the criteria has changed.
+    if (Bugzilla->usage_mode == USAGE_MODE_BROWSER &&
+        Bugzilla->params->{password_check_on_login})
+    {
+        my $check = validate_password_check($password);
+        if ($check) {
+            return {
+                failure => AUTH_ERROR,
+                user_error => $check,
+                details => { locked_user => $user }
+            }
+        }
     }
 
     # The user's credentials are okay, so delete any outstanding
@@ -85,12 +76,25 @@ sub check_credentials {
     Bugzilla::Token::DeletePasswordTokens($user->id, "user_logged_in");
     $user->clear_login_failures();
 
+    my $update_password = 0;
+
     # If their old password was using crypt() or some different hash
     # than we're using now, convert the stored password to using
     # whatever hashing system we're using now.
     my $current_algorithm = PASSWORD_DIGEST_ALGORITHM;
-    if ($real_password_crypted !~ /{\Q$current_algorithm\E}$/) {
-        $user->set_password($password);
+    $update_password = 1 if ($real_password_crypted !~ /{\Q$current_algorithm\E}$/);
+
+    # If their old password was using a different length salt than what
+    # we're using now, update the password to use the new salt length.
+    if ($real_password_crypted =~ /^([^,]+),/) {
+        $update_password = 1 if (length($1) != PASSWORD_SALT_LENGTH);
+    }
+
+    # If needed, update the user's password.
+    if ($update_password) {
+        # We can't call $user->set_password because we don't want the password
+        # complexity rules to apply here.
+        $user->{cryptpassword} = bz_crypt($password);
         $user->update();
     }
 
@@ -103,6 +107,7 @@ sub change_password {
     my $cryptpassword = bz_crypt($password);
     $dbh->do("UPDATE profiles SET cryptpassword = ? WHERE userid = ?",
              undef, $cryptpassword, $user->id);
+    Bugzilla->memcached->clear({ table => 'profiles', id => $user->id });
 }
 
 1;
index 0f10f9f..e37f557 100644 (file)
@@ -1,35 +1,16 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# The Initial Developer of the Original Code is Netscape Communications
-# Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All
-# Rights Reserved.
-#
-# Contributor(s): Terry Weissman <terry@mozilla.org>
-#                 Dan Mosedale <dmose@mozilla.org>
-#                 Joe Robins <jmrobins@tgix.com>
-#                 Dave Miller <justdave@syndicomm.com>
-#                 Christopher Aillon <christopher@aillon.com>
-#                 Gervase Markham <gerv@gerv.net>
-#                 Christian Reis <kiko@async.com.br>
-#                 Bradley Baetz <bbaetz@acm.org>
-#                 Erik Stambaugh <erik@dasbistro.com>
-#                 Max Kanat-Alexander <mkanat@bugzilla.org>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth::Verify::LDAP;
+
+use 5.10.1;
 use strict;
+use warnings;
+
 use base qw(Bugzilla::Auth::Verify);
 use fields qw(
     ldap
@@ -172,7 +153,7 @@ sub _bind_ldap_for_search {
 # We can't just do this in new(), because we're not allowed to throw any
 # error from anywhere under Bugzilla::Auth::new -- otherwise we
 # could create a situation where the admin couldn't get to editparams
-# to fix his mistake. (Because Bugzilla->login always calls 
+# to fix their mistake. (Because Bugzilla->login always calls
 # Bugzilla::Auth->new, and almost every page calls Bugzilla->login.)
 sub ldap {
     my ($self) = @_;
index da36c3b..283d9b4 100644 (file)
@@ -1,26 +1,17 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# The Initial Developer of the Original Code is Marc Schumann.
-# Portions created by Marc Schumann are Copyright (c) 2007 Marc Schumann.
-# All rights reserved.
-#
-# Contributor(s): Marc Schumann <wurblzap@gmail.com>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth::Verify::RADIUS;
+
+use 5.10.1;
 use strict;
-use base qw(Bugzilla::Auth::Verify);
+use warnings;
+
+use parent qw(Bugzilla::Auth::Verify);
 
 use Bugzilla::Constants;
 use Bugzilla::Error;
index e1a0119..3e5db3c 100644 (file)
@@ -1,21 +1,16 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Auth::Verify::Stack;
+
+use 5.10.1;
 use strict;
+use warnings;
+
 use base qw(Bugzilla::Auth::Verify);
 use fields qw(
     _stack
index 90bd8b6..8b4493f 100644 (file)
@@ -1,36 +1,15 @@
-# -*- Mode: perl; indent-tabs-mode: nil -*-
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
 #
-# The contents of this file are subject to the Mozilla Public
-# License Version 1.1 (the "License"); you may not use this file
-# except in compliance with the License. You may obtain a copy of
-# the License at http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS
-# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
-# implied. See the License for the specific language governing
-# rights and limitations under the License.
-#
-# The Original Code is the Bugzilla Bug Tracking System.
-#
-# The Initial Developer of the Original Code is Netscape Communications
-# Corporation. Portions created by Netscape are
-# Copyright (C) 1998 Netscape Communications Corporation. All
-# Rights Reserved.
-#
-# Contributor(s): Dawn Endico    <endico@mozilla.org>
-#                 Terry Weissman <terry@mozilla.org>
-#                 Chris Yeh      <cyeh@bluemartini.com>
-#                 Bradley Baetz  <bbaetz@acm.org>
-#                 Dave Miller    <justdave@bugzilla.org>
-#                 Max Kanat-Alexander <mkanat@bugzilla.org>
-#                 Frédéric Buclin <LpSolit@gmail.com>
-#                 Lance Larsh <lance.larsh@oracle.com>
-#                 Elliotte Martin <elliotte_martin@yahoo.com>
-#                 Christian Legnitto <clegnitto@mozilla.com>
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
 
 package Bugzilla::Bug;
 
+use 5.10.1;
 use strict;
+use warnings;
 
 use Bugzilla::Attachment;
 use Bugzilla::Constants;
@@ -50,15 +29,14 @@ use Bugzilla::Group;
 use Bugzilla::Status;
 use Bugzilla::Comment;
 use Bugzilla::BugUrl;
+use Bugzilla::BugUserLastVisit;
 
 use List::MoreUtils qw(firstidx uniq part);
 use List::Util qw(min max first);
 use Storable qw(dclone);
-use URI;
-use URI::QueryParam;
 use Scalar::Util qw(blessed);
 
-use base qw(Bugzilla::Object Exporter);
+use parent qw(Bugzilla::Object Exporter);
 @Bugzilla::Bug::EXPORT = qw(
     bug_alias_to_id
     LogActivityEntry
@@ -71,11 +49,13 @@ use base qw(Bugzilla::Object Exporter);
 
 use constant DB_TABLE   => 'bugs';
 use constant ID_FIELD   => 'bug_id';
-use constant NAME_FIELD => 'alias';
+use constant NAME_FIELD => 'bug_id';
 use constant LIST_ORDER => ID_FIELD;
 # Bugs have their own auditing table, bugs_activity.
 use constant AUDIT_CREATES => 0;
 use constant AUDIT_UPDATES => 0;
+# This will be enabled later
+use constant USE_MEMCACHED => 0;
 
 # This is a sub because it needs to call other subroutines.
 sub DB_COLUMNS {
@@ -85,7 +65,6 @@ sub DB_COLUMNS {
     my @custom_names = map {$_->name} @custom;
 
     my @columns = (qw(
-        alias
         assigned_to
         bug_file_loc
         bug_id
@@ -93,6 +72,7 @@ sub DB_COLUMNS {
         bug_status
         cclist_accessible
         component_id
+        creation_ts
         delta_ts
         estimated_time
         everconfirmed
@@ -111,7 +91,6 @@ sub DB_COLUMNS {
         version
     ),
     'reporter    AS reporter_id',
-    $dbh->sql_date_format('creation_ts', '%Y.%m.%d %H:%i') . ' AS creation_ts',
     $dbh->sql_date_format('deadline', '%Y-%m-%d') . ' AS deadline',
     @custom_names);
     
@@ -125,6 +104,7 @@ sub VALIDATORS {
     my $validators = {
         alias          => \&_check_alias,
         assigned_to    => \&_check_assigned_to,
+        blocked        => \&_check_dependencies,
         bug_file_loc   => \&_check_bug_file_loc,
         bug_severity   => \&_check_select_field,
         bug_status     => \&_check_bug_status,
@@ -133,6 +113,7 @@ sub VALIDATORS {
         component      => \&_check_component,
         creation_ts    => \&_check_creation_ts,
         deadline       => \&_check_deadline,
+        dependson      => \&_check_dependencies,
         dup_id         => \&_check_dup_id,
         estimated_time => \&_check_time_field,
         everconfirmed  => \&Bugzilla::Object::check_boolean,
@@ -166,12 +147,21 @@ sub VALIDATORS {
         elsif ($field->type == FIELD_TYPE_DATETIME) {
             $validator = \&_check_datetime_field;
         }
+        elsif ($field->type == FIELD_TYPE_DATE) {
+            $validator = \&_check_date_field;
+        }
         elsif ($field->type == FIELD_TYPE_FREETEXT) {
             $validator = \&_check_freetext_field;
         }
         elsif ($field->type == FIELD_TYPE_BUG_ID) {
             $validator = \&_check_bugid_field;
         }
+        elsif ($field->type == FIELD_TYPE_TEXTAREA) {
+            $validator = \&_check_textarea_field;
+        }
+        elsif ($field->type == FIELD_TYPE_INTEGER) {
+            $validator = \&_check_integer_field;
+        }
         else {
             $validator = \&_check_default_field;
         }
@@ -188,14 +178,16 @@ sub VALIDATOR_DEPENDENCIES {
 
     my %deps = (
         assigned_to      => ['component'],
+        blocked          => ['product'],
         bug_status       => ['product', 'comment', 'target_milestone'],
         cc               => ['component'],
         comment          => ['creation_ts'],
         component        => ['product'],
+        dependson        => ['product'],
         dup_id           => ['bug_status', 'resolution'],
         groups           => ['product'],
         keywords         => ['product'],
-        resolution       => ['bug_status'],
+        resolution       => ['bug_status', 'dependson'],
         qa_contact       => ['component'],
         target_milestone => ['product'],
         version          => ['product'],
@@ -215,7 +207,6 @@ sub UPDATE_COLUMNS {
                       Bugzilla->active_custom_fields;
     my @custom_names = map {$_->name} @custom;
     my @columns = qw(
-        alias
         assigned_to
         bug_file_loc
         bug_severity
@@ -248,7 +239,9 @@ use constant NUMERIC_COLUMNS => qw(
 );
 
 sub DATE_COLUMNS {
-    my @fields = @{ Bugzilla->fields({ type => FIELD_TYPE_DATETIME }) };
+    my @fields = (@{ Bugzilla->fields({ type => [FIELD_TYPE_DATETIME,
+                                                 FIELD_TYPE_DATE] })
+                   });
     return map { $_->name } @fields;
 }
 
@@ -262,7 +255,6 @@ use constant MAX_LINE_LENGTH => 254;
 # use.)
 use constant FIELD_MAP => {
     blocks           => 'blocked',
-    cc_accessible    => 'cclist_accessible',
     commentprivacy   => 'comment_is_private',
     creation_time    => 'creation_ts',
     creator          => 'reporter',
@@ -280,10 +272,6 @@ use constant FIELD_MAP => {
     summary          => 'short_desc',
     url              => 'bug_file_loc',
     whiteboard       => 'status_whiteboard',
-
-    # These are special values for the WebService Bug.search method.
-    limit            => 'LIMIT',
-    offset           => 'OFFSET',
 };
 
 use constant REQUIRED_FIELD_MAP => {
@@ -311,35 +299,37 @@ use constant EXTRA_REQUIRED_FIELDS => qw(creation_ts target_milestone cc qa_cont
 
 #####################################################################
 
-# This and "new" catch every single way of creating a bug, so that we
-# can call _create_cf_accessors.
-sub _do_list_select {
-    my $invocant = shift;
-    $invocant->_create_cf_accessors();
-    return $invocant->SUPER::_do_list_select(@_);
-}
-
 sub new {
     my $invocant = shift;
     my $class = ref($invocant) || $invocant;
     my $param = shift;
 
-    $class->_create_cf_accessors();
-
     # Remove leading "#" mark if we've just been passed an id.
-    if (!ref $param && $param =~ /^#(\d+)$/) {
+    if (!ref $param && $param =~ /^#([0-9]+)$/) {
         $param = $1;
     }
 
     # If we get something that looks like a word (not a number),
     # make it the "name" param.
-    if (!defined $param || (!ref($param) && $param !~ /^\d+$/)) {
-        # But only if aliases are enabled.
-        if (Bugzilla->params->{'usebugaliases'} && $param) {
-            $param = { name => $param };
+    if (!defined $param
+        || (!ref($param) && $param !~ /^[0-9]+$/)
+        || (ref($param) && $param->{id} !~ /^[0-9]+$/))
+    {
+        if ($param) {
+            my $alias = ref($param) ? $param->{id} : $param;
+            my $bug_id = bug_alias_to_id($alias);
+            if (! $bug_id) {
+                my $error_self = {};
+                bless $error_self, $class;
+                $error_self->{'bug_id'} = $alias;
+                $error_self->{'error'}  = 'InvalidBugId';
+                return $error_self;
+            }
+            $param = { id => $bug_id,
+                       cache => ref($param) ? $param->{cache} : 0 };
         }
         else {
-            # Aliases are off, and we got something that's not a number.
+            # We got something that's not a number.
             my $error_self = {};
             bless $error_self, $class;
             $error_self->{'bug_id'} = $param;
@@ -370,20 +360,35 @@ sub new {
     return $self;
 }
 
-sub check {
+sub initialize {
+    $_[0]->_create_cf_accessors();
+}
+
+sub object_cache_key {
     my $class = shift;
-    my ($id, $field) = @_;
+    my $key = $class->SUPER::object_cache_key(@_)
+      || return;
+    return $key . ',' . Bugzilla->user->id;
+}
 
-    ThrowUserError('improper_bug_id_field_value', { field => $field }) unless defined $id;
+sub check {
+    my $class = shift;
+    my ($param, $field) = @_;
 
     # Bugzilla::Bug throws lots of special errors, so we don't call
     # SUPER::check, we just call our new and do our own checks.
-    my $self = $class->new(trim($id));
-    # For error messages, use the id that was returned by new(), because
-    # it's cleaned up.
-    $id = $self->id;
+    my $id = ref($param)
+        ? ($param->{id} = trim($param->{id}))
+        : ($param = trim($param));
+    ThrowUserError('improper_bug_id_field_value', { field => $field }) unless defined $id;
+
+    my $self = $class->new($param);
 
     if ($self->{error}) {
+        # For error messages, use the id that was returned by new(), because
+        # it's cleaned up.
+        $id = $self->id;
+
         if ($self->{error} eq 'NotFound') {
              ThrowUserError("bug_id_does_not_exist", { bug_id => $id });
         }
@@ -395,22 +400,35 @@ sub check {
     }
 
     unless ($field && $field =~ /^(dependson|blocked|dup_id)$/) {
-        $self->check_is_visible;
+        $self->check_is_visible($id);
     }
     return $self;
 }
 
+sub check_for_edit {
+    my $class = shift;
+    my $bug = $class->check(@_);
+
+    Bugzilla->user->can_edit_product($bug->product_id)
+        || ThrowUserError("product_edit_denied", { product => $bug->product });
+
+    return $bug;
+}
+
 sub check_is_visible {
-    my $self = shift;
+    my ($self, $input_id) = @_;
+    $input_id ||= $self->id;
     my $user = Bugzilla->user;
 
     if (!$user->can_see_bug($self->id)) {
         # The error the user sees depends on whether or not they are
         # logged in (i.e. $user->id contains the user's positive integer ID).
+        # If we are validating an alias, then use it in the error message
+        # instead of its corresponding bug ID, to not disclose it.
         if ($user->id) {
-            ThrowUserError("bug_access_denied", { bug_id => $self->id });
+            ThrowUserError("bug_access_denied", { bug_id => $input_id });
         } else {
-            ThrowUserError("bug_access_query", { bug_id => $self->id });
+            ThrowUserError("bug_access_query", { bug_id => $input_id });
         }
     }
 }
@@ -487,14 +505,72 @@ sub preload {
     # to the more complex method.
     my @all_dep_ids;
     foreach my $bug (@$bugs) {
-        push(@all_dep_ids, @{ $bug->blocked }, @{ $bug->dependson });
+        push @all_dep_ids, @{ $bug->blocked }, @{ $bug->dependson };
+        push @all_dep_ids, @{ $bug->duplicate_ids };
+        push @all_dep_ids, @{ $bug->_preload_referenced_bugs };
     }
     @all_dep_ids = uniq @all_dep_ids;
     # If we don't do this, can_see_bug will do one call per bug in
-    # the dependency lists, during get_bug_link in Bugzilla::Template.
+    # the dependency and duplicate lists, in Bugzilla::Template::get_bug_link.
     $user->visible_bugs(\@all_dep_ids);
 }
 
+# Helps load up bugs referenced in comments by retrieving them with a single
+# query from the database and injecting bug objects into the object-cache.
+sub _preload_referenced_bugs {
+    my $self = shift;
+
+    # inject current duplicates into the object-cache first
+    foreach my $bug (@{ $self->duplicates }) {
+        $bug->object_cache_set() unless Bugzilla::Bug->object_cache_get($bug->id);
+    }
+
+    # preload bugs from comments
+    my $referenced_bug_ids = _extract_bug_ids($self->comments);
+    my @ref_bug_ids = grep { !Bugzilla::Bug->object_cache_get($_) } @$referenced_bug_ids;
+
+    # inject into object-cache
+    my $referenced_bugs = Bugzilla::Bug->new_from_list(\@ref_bug_ids);
+    $_->object_cache_set() foreach @$referenced_bugs;
+
+    return $referenced_bug_ids;
+}
+
+# Extract bug IDs mentioned in comments. This is much faster than calling quoteUrls().
+sub _extract_bug_ids {
+    my $comments = shift;
+    my @bug_ids;
+
+    my $params = Bugzilla->params;
+    my @urlbases = ($params->{'urlbase'});
+    push(@urlbases, $params->{'sslbase'}) if $params->{'sslbase'};
+    my $urlbase_re = '(?:' . join('|', map { qr/$_/ } @urlbases) . ')';
+    my $bug_word = template_var('terms')->{bug};
+    my $bugs_word = template_var('terms')->{bugs};
+
+    foreach my $comment (@$comments) {
+        if ($comment->type == CMT_HAS_DUPE || $comment->type == CMT_DUPE_OF) {
+            push @bug_ids, $comment->extra_data;
+            next;
+        }
+        my $s = $comment->already_wrapped ? qr/\s/ : qr/\h/;
+        my $text = $comment->body;
+        # Full bug links
+        push @bug_ids, $text =~ /\b$urlbase_re\Qshow_bug.cgi?id=\E([0-9]+)(?:\#c[0-9]+)?/g;
+        # bug X
+        my $bug_re = qr/\Q$bug_word\E$s*\#?$s*([0-9]+)/i;
+        push @bug_ids, $text =~ /\b$bug_re/g;
+        # bugs X, Y, Z
+        my $bugs_re = qr/\Q$bugs_word\E$s*\#?$s*([0-9]+)(?:$s*,$s*\#?$s*([0-9]+))+/i;
+        push @bug_ids, $text =~ /\b$bugs_re/g;
+        # Old duplicate markers
+        push @bug_ids, $text =~ /(?<=^\*\*\*\ This\ bug\ has\ been\ marked\ as\ a\ duplicate\ of\ )([0-9]+)(?=\ \*\*\*\Z)/;
+    }
+    # Make sure to filter invalid bug IDs.
+    @bug_ids = grep { $_ < MAX_INT_32 } @bug_ids;
+    return [uniq @bug_ids];
+}
+
 sub possible_duplicates {
     my ($class, $params) = @_;
     my $short_desc = $params->{summary};
@@ -512,8 +588,10 @@ sub possible_duplicates {
     my $dbh = Bugzilla->dbh;
     my $user = Bugzilla->user;
     my @words = split(/[\b\s]+/, $short_desc || '');
-    # Exclude punctuation from the array.
-    @words = map { /(\w+)/; $1 } @words;
+    # Remove leading/trailing punctuation from words
+    foreach my $word (@words) {
+        $word =~ s/(?:^\W+|\W+$)//g;
+    }
     # And make sure that each word is longer than 2 characters.
     @words = grep { defined $_ and length($_) > 2 } @words;
 
@@ -594,8 +672,7 @@ sub possible_duplicates {
 # C<rep_platform> - B<Required> The platform the bug was found against.
 # C<version>      - B<Required> The version of the product the bug was found in.
 #
-# C<alias>        - An alias for this bug. Will be ignored if C<usebugaliases>
-#                   is off.
+# C<alias>        - An alias for this bug.
 # C<target_milestone> - When this bug is expected to be fixed.
 # C<status_whiteboard> - A string.
 # C<bug_status>   - The initial status of the bug, a string.
@@ -634,12 +711,14 @@ sub create {
 
     # These are not a fields in the bugs table, so we don't pass them to
     # insert_create_data.
+    my $bug_aliases      = delete $params->{alias};
     my $cc_ids           = delete $params->{cc};
     my $groups           = delete $params->{groups};
     my $depends_on       = delete $params->{dependson};
     my $blocked          = delete $params->{blocked};
     my $keywords         = delete $params->{keywords};
     my $creation_comment = delete $params->{comment};
+&nb